From 446c47ad747ede4bf8dece84391f38ab646533a1 Mon Sep 17 00:00:00 2001 From: Michael Still Date: Thu, 3 Apr 2025 20:25:05 +1100 Subject: [PATCH] Add support for spice-direct console types. This patch adds support for Nova microversion 2.99 which exposes the new spice-direct console type and the pre-existing /os-console-auth-token/ API. +----------+----------------------------------------------------------+ | Field | Value | +----------+----------------------------------------------------------+ | protocol | spice | | type | spice-direct | | url | http://127.0.0.1:13002/nova?token=f78009fb-41ad-... | +----------+----------------------------------------------------------+ +----------------------+--------------------------------------+ | Field | Value | +----------------------+--------------------------------------+ | host | 127.0.0.1 | | instance_uuid | f2477018-aa93-... | | internal_access_path | None | | port | 5900 | | tls_port | 5901 | +----------------------+--------------------------------------+ Change-Id: I97e3415ec3110374cf95d244cd75bcdf6c5e7871 --- doc/source/user/proxies/compute.rst | 11 +++++- .../compute/v2/console_auth_token.rst | 13 +++++++ openstack/compute/v2/_proxy.py | 15 +++++++- openstack/compute/v2/console_auth_token.py | 35 +++++++++++++++++++ openstack/compute/v2/server.py | 4 ++- openstack/compute/v2/server_remote_console.py | 10 +++++- openstack/tests/unit/compute/v2/test_proxy.py | 9 +++++ .../tests/unit/compute/v2/test_server.py | 8 +++++ ...e-console-auth-token-999b790aec83de85.yaml | 13 +++++++ 9 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 doc/source/user/resources/compute/v2/console_auth_token.rst create mode 100644 openstack/compute/v2/console_auth_token.py create mode 100644 releasenotes/notes/compute-add-validate-console-auth-token-999b790aec83de85.yaml diff --git a/doc/source/user/proxies/compute.rst b/doc/source/user/proxies/compute.rst index eec5c8f2a..c82a990e2 100644 --- a/doc/source/user/proxies/compute.rst +++ b/doc/source/user/proxies/compute.rst @@ -42,7 +42,7 @@ Starting, Stopping, etc. reboot_server, restore_server, shelve_server, unshelve_server, lock_server, unlock_server, pause_server, unpause_server, rescue_server, unrescue_server, evacuate_server, migrate_server, - get_server_console_output, live_migrate_server + live_migrate_server Modifying a Server ****************** @@ -187,6 +187,15 @@ Migration Operations :noindex: :members: migrations +Interactive Consoles +^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: openstack.compute.v2._proxy.Proxy + :noindex: + :members: create_server_remote_console, get_server_console_url, + validate_console_auth_token, get_server_console_output, + create_console + Helpers ^^^^^^^ diff --git a/doc/source/user/resources/compute/v2/console_auth_token.rst b/doc/source/user/resources/compute/v2/console_auth_token.rst new file mode 100644 index 000000000..86b0718fd --- /dev/null +++ b/doc/source/user/resources/compute/v2/console_auth_token.rst @@ -0,0 +1,13 @@ +openstack.compute.v2.console_auth_token +======================================= + +.. automodule:: openstack.compute.v2.console_auth_token + +The ServerRemoteConsole Class +----------------------------- + +The ``ConsoleAuthToken`` class inherits from +:class:`~openstack.resource.Resource`. + +.. autoclass:: openstack.compute.v2.console_auth_token.ConsoleAuthToken + :members: diff --git a/openstack/compute/v2/_proxy.py b/openstack/compute/v2/_proxy.py index f48e1f684..63e67277a 100644 --- a/openstack/compute/v2/_proxy.py +++ b/openstack/compute/v2/_proxy.py @@ -16,6 +16,7 @@ import warnings from openstack.block_storage.v3 import volume as _volume from openstack.compute.v2 import aggregate as _aggregate from openstack.compute.v2 import availability_zone +from openstack.compute.v2 import console_auth_token as _console_auth_token from openstack.compute.v2 import extension from openstack.compute.v2 import flavor as _flavor from openstack.compute.v2 import hypervisor as _hypervisor @@ -57,6 +58,7 @@ class Proxy(proxy.Proxy): "keypair": _keypair.Keypair, "limits": limits.Limits, "migration": _migration.Migration, + "os_console_auth_token": _console_auth_token.ConsoleAuthToken, "quota_class_set": _quota_class_set.QuotaClassSet, "quota_set": _quota_set.QuotaSet, "server": _server.Server, @@ -2384,6 +2386,15 @@ class Proxy(proxy.Proxy): server = self._get_resource(_server.Server, server) return server.get_console_url(self, console_type) + def validate_console_auth_token(self, console_token): + """Lookup console connection information for a console auth token. + + :param console_token: The console auth token as returned in the URL + from get_server_console_url. + :returns: Dictionary with connection details, varying by console type. + """ + return self._get(_console_auth_token.ConsoleAuthToken, console_token) + def get_server_console_output(self, server, length=None): """Return the console output for a server. @@ -2411,10 +2422,12 @@ class Proxy(proxy.Proxy): * rdp-html5 * serial * webmks (supported after 2.8) + * spice-direct (supported after 2.99) :param console_protocol: Optional console protocol (is respected only after microversion 2.6). - :returns: Dictionary with console type, url and optionally protocol. + :returns: Dictionary with console type, connection details (a url), and + optionally protocol. """ server = self._get_resource(_server.Server, server) # NOTE: novaclient supports undocumented type xcpvnc also supported diff --git a/openstack/compute/v2/console_auth_token.py b/openstack/compute/v2/console_auth_token.py new file mode 100644 index 000000000..c6aa5ac95 --- /dev/null +++ b/openstack/compute/v2/console_auth_token.py @@ -0,0 +1,35 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from openstack import resource + + +class ConsoleAuthToken(resource.Resource): + resource_key = 'console' + base_path = '/os-console-auth-tokens' + + # capabilities + allow_fetch = True + + _max_microversion = '2.99' + + # Properties + #: Instance UUID + instance_uuid = resource.Body('instance_uuid') + #: Hypervisor host + host = resource.Body('host') + #: Hypervisor port + port = resource.Body('port') + #: Hypervisor TLS port + tls_port = resource.Body('tls_port') + #: Internal access path + internal_access_path = resource.Body('internal_access_path') diff --git a/openstack/compute/v2/server.py b/openstack/compute/v2/server.py index 069caacd1..f4cdc6443 100644 --- a/openstack/compute/v2/server.py +++ b/openstack/compute/v2/server.py @@ -35,6 +35,7 @@ CONSOLE_TYPE_ACTION_MAPPING = { 'novnc': 'os-getVNCConsole', 'xvpvnc': 'os-getVNCConsole', 'spice-html5': 'os-getSPICEConsole', + 'spice-direct': 'os-getSPICEConsole', 'rdp-html5': 'os-getRDPConsole', 'serial': 'os-getSerialConsole', } @@ -889,7 +890,8 @@ class Server(resource.Resource, metadata.MetadataMixin, tag.TagMixin): :param session: The session to use for making this request. :param console_type: The type of console to return. This is cloud-specific. One of: ``novnc``, ``xvpvnc``, ``spice-html5``, - ``rdp-html5``, ``serial``. + ``spice-direct`` (after Nova microversion 2.99), ``rdp-html5``, + or ``serial``. :returns: None """ action = CONSOLE_TYPE_ACTION_MAPPING.get(console_type) diff --git a/openstack/compute/v2/server_remote_console.py b/openstack/compute/v2/server_remote_console.py index 7a845b6ab..7d62ea6dd 100644 --- a/openstack/compute/v2/server_remote_console.py +++ b/openstack/compute/v2/server_remote_console.py @@ -17,6 +17,7 @@ CONSOLE_TYPE_PROTOCOL_MAPPING = { 'novnc': 'vnc', 'xvpvnc': 'vnc', 'spice-html5': 'spice', + 'spice-direct': 'spice', 'rdp-html5': 'rdp', 'serial': 'serial', 'webmks': 'mks', @@ -34,7 +35,7 @@ class ServerRemoteConsole(resource.Resource): allow_delete = False allow_list = False - _max_microversion = '2.8' + _max_microversion = '2.99' #: Protocol of the remote console. protocol = resource.Body('protocol') @@ -55,6 +56,13 @@ class ServerRemoteConsole(resource.Resource): raise ValueError( 'Console type webmks is not supported on server side' ) + if ( + not utils.supports_microversion(session, '2.99') + and self.type == 'spice-direct' + ): + raise ValueError( + 'Console type spice-direct is not supported on server side' + ) return super().create( session, prepend_key=prepend_key, base_path=base_path, **params ) diff --git a/openstack/tests/unit/compute/v2/test_proxy.py b/openstack/tests/unit/compute/v2/test_proxy.py index 0e9cd9843..c579f1c10 100644 --- a/openstack/tests/unit/compute/v2/test_proxy.py +++ b/openstack/tests/unit/compute/v2/test_proxy.py @@ -21,6 +21,7 @@ from openstack.block_storage.v3 import volume from openstack.compute.v2 import _proxy from openstack.compute.v2 import aggregate from openstack.compute.v2 import availability_zone as az +from openstack.compute.v2 import console_auth_token from openstack.compute.v2 import extension from openstack.compute.v2 import flavor from openstack.compute.v2 import hypervisor @@ -1885,3 +1886,11 @@ class TestServerAction(TestComputeProxy): method_kwargs={'server': 'server_a'}, expected_kwargs={'server_id': 'server_a'}, ) + + +class TestValidateConsoleAuthToken(TestComputeProxy): + def test_validate_console_auth_token(self): + self.verify_get( + self.proxy.validate_console_auth_token, + console_auth_token.ConsoleAuthToken, + ) diff --git a/openstack/tests/unit/compute/v2/test_server.py b/openstack/tests/unit/compute/v2/test_server.py index 2c9e59c5c..f2cdc7e3d 100644 --- a/openstack/tests/unit/compute/v2/test_server.py +++ b/openstack/tests/unit/compute/v2/test_server.py @@ -1256,6 +1256,14 @@ class TestServer(base.TestCase): microversion=self.sess.default_microversion, ) + sot.get_console_url(self.sess, 'spice-direct') + self.sess.post.assert_called_with( + 'servers/IDENTIFIER/action', + json={'os-getSPICEConsole': {'type': 'spice-direct'}}, + headers={'Accept': ''}, + microversion=self.sess.default_microversion, + ) + sot.get_console_url(self.sess, 'rdp-html5') self.sess.post.assert_called_with( 'servers/IDENTIFIER/action', diff --git a/releasenotes/notes/compute-add-validate-console-auth-token-999b790aec83de85.yaml b/releasenotes/notes/compute-add-validate-console-auth-token-999b790aec83de85.yaml new file mode 100644 index 000000000..474e42c1e --- /dev/null +++ b/releasenotes/notes/compute-add-validate-console-auth-token-999b790aec83de85.yaml @@ -0,0 +1,13 @@ +--- +features: + - | + Add the ``validate_console_auth_token`` method to the Compute proxy. This + method uses the pre-existing ``os-console-auth-tokens`` OpenStack Compute + API to validate a console access token as produced by + ``get_console_url``. In addition, the method returns hypervisor connection + information for the console (hypervisor IP and port numbers), as this call + is generally used by the console proxies which users connect to. + + By default, callers of this method must have ``admin`` access to the + OpenStack Compute API due to the privileged nature of the hypervisor + connection information returned.