diff --git a/api-ref/source/parameters.yaml b/api-ref/source/parameters.yaml index f644c84f9ea2..5c608fef829d 100644 --- a/api-ref/source/parameters.yaml +++ b/api-ref/source/parameters.yaml @@ -5986,17 +5986,20 @@ remote_console: remote_console_protocol: description: | The protocol of remote console. The valid values are ``vnc``, ``spice``, - ``serial`` and ``mks``. The protocol ``mks`` is added since Microversion - ``2.8``. + ``rdp``, ``serial`` and ``mks``. The protocol ``mks`` is added since + Microversion ``2.8``. The protocol ``rdp`` requires the Hyper-V driver + which was removed in the 29.0.0 (Caracal) release. in: body required: true type: string remote_console_type: description: | The type of remote console. The valid values are ``novnc``, - ``spice-html5``, ``spice-direct``, ``serial``, and ``webmks``. The type - ``webmks`` was added in Microversion ``2.8``, and the type - ``spice-direct`` was added in Microversion ``2.99``. + ``rdp-html5``, ``spice-html5``, ``spice-direct``, ``serial``, and + ``webmks``. The type ``webmks`` was added in Microversion ``2.8`` and the + type ``spice-direct`` was added in Microversion ``2.99``. The type + ``rdp-html5`` requires the Hyper-V driver which was removed in the 29.0.0 + (Caracal) release. in: body required: true type: string diff --git a/api-ref/source/servers-actions.inc b/api-ref/source/servers-actions.inc index e36c4a16802f..c000a148fdbf 100644 --- a/api-ref/source/servers-actions.inc +++ b/api-ref/source/servers-actions.inc @@ -8,20 +8,22 @@ Enables all users to perform an action on a server. Specify the action in the request body. -You can associate a fixed or floating IP address with a server, -or disassociate a fixed or floating IP address from a server. +There are many actions available for a server: -You can create an image from a server, create a backup of a server, -and force-delete a server before deferred cleanup. -You can lock, pause, reboot, rebuild, rescue, resize, resume, confirm -the resize of, revert a pending resize for, shelve, shelf-offload, -unshelve, start, stop, unlock, unpause, and unrescue a server. You can -also change the password of the server and add a security group to or -remove a security group from a server. You can also trigger a crash dump -into a server since Mitaka release. - -You can get an serial, SPICE, or VNC console for a server. +* You can associate and disassociate a fixed or floating IP address with + or from a server +* You can create an image from a server +* You can create a backup of a server +* You can force-delete a server before deferred cleanup +* You can lock, pause, reboot, rebuild, rescue, resize, resume, confirm + the resize of, revert a pending resize for, shelve, shelf-offload, + unshelve, start, stop, unlock, unpause, and unrescue a server +* You can change the password of the server +* You can add a security group to or remove a security group from a server +* You can trigger a crash dump into a server +* You can get a graphical or serial console for a server +...among others. Add (Associate) Floating Ip (addFloatingIp Action) (DEPRECATED) ================================================================ diff --git a/nova/api/openstack/compute/remote_consoles.py b/nova/api/openstack/compute/remote_consoles.py index 52d8dcc8c94d..0f6d728369ae 100644 --- a/nova/api/openstack/compute/remote_consoles.py +++ b/nova/api/openstack/compute/remote_consoles.py @@ -157,13 +157,21 @@ class RemoteConsolesController(wsgi.Controller): target={'project_id': instance.project_id}) protocol = body['remote_console']['protocol'] console_type = body['remote_console']['type'] + + # handle removed console types + if protocol in ('rdp',): + raise webob.exc.HTTPBadRequest( + 'Unavailable console type %s.' % protocol + ) + try: - handler = self.handlers.get(protocol) + # this should never fail in the real world since our schema + # prevents unsupported types getting through + handler = self.handlers[protocol] output = handler(context, instance, console_type) return {'remote_console': {'protocol': protocol, 'type': console_type, 'url': output['url']}} - except exception.InstanceNotFound as e: raise webob.exc.HTTPNotFound(explanation=e.format_message()) except exception.InstanceNotReady as e: @@ -174,5 +182,5 @@ class RemoteConsolesController(wsgi.Controller): exception.ImageSerialPortNumberExceedFlavorValue, exception.SocketPortRangeExhaustedException) as e: raise webob.exc.HTTPBadRequest(explanation=e.format_message()) - except NotImplementedError: + except (NotImplementedError, KeyError): common.raise_feature_not_supported() diff --git a/nova/api/openstack/compute/schemas/remote_consoles.py b/nova/api/openstack/compute/schemas/remote_consoles.py index b563fbf9f5fd..e4b6bf3a1491 100644 --- a/nova/api/openstack/compute/schemas/remote_consoles.py +++ b/nova/api/openstack/compute/schemas/remote_consoles.py @@ -20,6 +20,11 @@ get_vnc_console = { 'os-getVNCConsole': { 'type': 'object', 'properties': { + # NOTE(stephenfin): While we only support novnc nowadays, we + # previously supported xvpvnc for the XenServer driver. Since + # our generated schemas are unversioned, we need to accept + # these old values here and reject them lower down the stack. + # Ditto for other schemas in this file. 'type': { 'type': 'string', 'enum': ['novnc', 'xvpvnc'], @@ -63,8 +68,7 @@ get_serial_console = { 'type': 'object', 'properties': { 'type': { - 'type': 'string', - 'enum': ['serial'], + 'type': 'string', 'enum': ['serial'], }, }, 'required': ['type'], @@ -83,11 +87,16 @@ create_v26 = { 'properties': { 'protocol': { 'type': 'string', - 'enum': ['vnc', 'spice', 'serial'], + # While we no longer support the rdp console type, we still + # list it here for documentation purposes. It is rejected + # at the controller level. + 'enum': ['vnc', 'spice', 'serial', 'rdp'], }, 'type': { 'type': 'string', - 'enum': ['novnc', 'xvpvnc', 'spice-html5', 'serial'], + 'enum': [ + 'novnc', 'xvpvnc', 'spice-html5', 'serial', 'rdp-html5' + ], }, }, 'required': ['protocol', 'type'], @@ -98,53 +107,18 @@ create_v26 = { 'additionalProperties': False, } -create_v28 = { - 'type': 'object', - 'properties': { - 'remote_console': { - 'type': 'object', - 'properties': { - 'protocol': { - 'type': 'string', - 'enum': ['vnc', 'spice', 'serial', 'mks'], - }, - 'type': { - 'type': 'string', - 'enum': ['novnc', 'xvpvnc', 'spice-html5', 'serial', - 'webmks'], - }, - }, - 'required': ['protocol', 'type'], - 'additionalProperties': False, - }, - }, - 'required': ['remote_console'], - 'additionalProperties': False, -} +create_v28 = copy.deepcopy(create_v26) +create_v28['properties']['remote_console']['properties']['protocol'][ + 'enum' +].append('mks') +create_v28['properties']['remote_console']['properties']['type'][ + 'enum' +].append('webmks') -create_v299 = { - 'type': 'object', - 'properties': { - 'remote_console': { - 'type': 'object', - 'properties': { - 'protocol': { - 'type': 'string', - 'enum': ['vnc', 'spice', 'rdp', 'serial', 'mks'], - }, - 'type': { - 'type': 'string', - 'enum': ['novnc', 'xvpvnc', 'spice-html5', 'spice-direct', - 'serial', 'webmks'], - }, - }, - 'required': ['protocol', 'type'], - 'additionalProperties': False, - }, - }, - 'required': ['remote_console'], - 'additionalProperties': False, -} +create_v299 = copy.deepcopy(create_v28) +create_v299['properties']['remote_console']['properties']['type'][ + 'enum' +].append('spice-direct') get_vnc_console_response = { 'type': 'object', @@ -152,16 +126,8 @@ get_vnc_console_response = { 'console': { 'type': 'object', 'properties': { - 'type': { - 'type': 'string', - 'enum': ['novnc', 'xvpvnc'], - 'description': '', - }, - 'url': { - 'type': 'string', - 'format': 'uri', - 'description': '', - }, + 'type': {'type': 'string', 'enum': ['novnc', 'xvpvnc']}, + 'url': {'type': 'string', 'format': 'uri'}, }, 'required': ['type', 'url'], 'additionalProperties': False, @@ -177,16 +143,8 @@ get_spice_console_response = { 'console': { 'type': 'object', 'properties': { - 'type': { - 'type': 'string', - 'const': 'spice-html5', - 'description': '', - }, - 'url': { - 'type': 'string', - 'format': 'uri', - 'description': '', - }, + 'type': {'type': 'string', 'const': 'spice-html5'}, + 'url': {'type': 'string', 'format': 'uri'}, }, 'required': ['type', 'url'], 'additionalProperties': False, @@ -201,16 +159,8 @@ get_rdp_console_response = { 'console': { 'type': 'object', 'properties': { - 'type': { - 'type': 'string', - 'const': 'rdp', - 'description': '', - }, - 'url': { - 'type': 'string', - 'format': 'uri', - 'description': '', - }, + 'type': {'type': 'string', 'const': 'rdp-html5'}, + 'url': {'type': 'string', 'format': 'uri'}, }, 'required': ['type', 'url'], 'additionalProperties': False, @@ -226,16 +176,8 @@ get_serial_console_response = { 'console': { 'type': 'object', 'properties': { - 'type': { - 'type': 'string', - 'const': 'serial', - 'description': '', - }, - 'url': { - 'type': 'string', - 'format': 'uri', - 'description': '', - }, + 'type': {'type': 'string', 'const': 'serial'}, + 'url': {'type': 'string', 'format': 'uri'}, }, 'required': ['type', 'url'], 'additionalProperties': False, @@ -253,18 +195,17 @@ create_response = { 'properties': { 'protocol': { 'type': 'string', - 'enum': ['vnc', 'spice', 'serial'], + 'enum': ['vnc', 'spice', 'serial', 'rdp'], }, 'type': { 'type': 'string', - 'enum': ['novnc', 'xvpvnc', 'spice-html5', 'serial'], - }, - 'url': { - 'type': 'string', - 'format': 'uri', + 'enum': [ + 'novnc', 'xvpvnc', 'spice-html5', 'serial', 'rdp-html5' + ], }, + 'url': {'type': 'string', 'format': 'uri'}, }, - 'required': ['protocol', 'type'], + 'required': ['protocol', 'type', 'url'], 'additionalProperties': False, }, }, diff --git a/nova/tests/unit/api/openstack/compute/test_remote_consoles.py b/nova/tests/unit/api/openstack/compute/test_remote_consoles.py index 4b53d76b3a26..3616953dda96 100644 --- a/nova/tests/unit/api/openstack/compute/test_remote_consoles.py +++ b/nova/tests/unit/api/openstack/compute/test_remote_consoles.py @@ -16,6 +16,7 @@ from unittest import mock import webob +import webob.exc from nova.api.openstack import api_version_request from nova.api.openstack.compute import remote_consoles \ @@ -352,12 +353,8 @@ class ConsolesExtensionTestV26(test.NoDBTestCase): 'spice-html5') def test_create_rdp_console_bad_request(self): - mock_handler = mock.MagicMock() - mock_handler.return_value = {'url': "http://fake"} - self.controller.handlers['rdp'] = mock_handler - body = {'remote_console': {'protocol': 'rdp', 'type': 'rdp-html5'}} - self.assertRaises(exception.ValidationError, self.controller.create, + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, self.req, fakes.FAKE_UUID, body=body) def test_create_serial_console(self):