api: Address issues with remote consoles APIs

* Add a note explaining presence of xvpvnc console type
* Make 'url' mandatory in create response
* Remove unnecessary description fields: we will populate these later
* De-deuplcate request body schemas
* Re-add references to the rdp console to the api-ref

Change-Id: I5555b8cf7a83fad689e98522850b5550b49566ed
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane
2025-06-10 10:46:58 +01:00
parent 485ee768d6
commit c4f81a54d5
5 changed files with 73 additions and 122 deletions

View File

@@ -5986,17 +5986,20 @@ remote_console:
remote_console_protocol: remote_console_protocol:
description: | description: |
The protocol of remote console. The valid values are ``vnc``, ``spice``, The protocol of remote console. The valid values are ``vnc``, ``spice``,
``serial`` and ``mks``. The protocol ``mks`` is added since Microversion ``rdp``, ``serial`` and ``mks``. The protocol ``mks`` is added since
``2.8``. Microversion ``2.8``. The protocol ``rdp`` requires the Hyper-V driver
which was removed in the 29.0.0 (Caracal) release.
in: body in: body
required: true required: true
type: string type: string
remote_console_type: remote_console_type:
description: | description: |
The type of remote console. The valid values are ``novnc``, The type of remote console. The valid values are ``novnc``,
``spice-html5``, ``spice-direct``, ``serial``, and ``webmks``. The type ``rdp-html5``, ``spice-html5``, ``spice-direct``, ``serial``, and
``webmks`` was added in Microversion ``2.8``, and the type ``webmks``. The type ``webmks`` was added in Microversion ``2.8`` and the
``spice-direct`` was added in Microversion ``2.99``. 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 in: body
required: true required: true
type: string type: string

View File

@@ -8,20 +8,22 @@
Enables all users to perform an action on a server. Specify the action Enables all users to perform an action on a server. Specify the action
in the request body. in the request body.
You can associate a fixed or floating IP address with a server, There are many actions available for a server:
or disassociate a fixed or floating IP address from a server.
You can create an image from a server, create a backup of a server, * You can associate and disassociate a fixed or floating IP address with
and force-delete a server before deferred cleanup. or from a server
You can lock, pause, reboot, rebuild, rescue, resize, resume, confirm * You can create an image from a server
the resize of, revert a pending resize for, shelve, shelf-offload, * You can create a backup of a server
unshelve, start, stop, unlock, unpause, and unrescue a server. You can * You can force-delete a server before deferred cleanup
also change the password of the server and add a security group to or * You can lock, pause, reboot, rebuild, rescue, resize, resume, confirm
remove a security group from a server. You can also trigger a crash dump the resize of, revert a pending resize for, shelve, shelf-offload,
into a server since Mitaka release. unshelve, start, stop, unlock, unpause, and unrescue a server
* You can change the password of the server
You can get an serial, SPICE, or VNC console for a 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) Add (Associate) Floating Ip (addFloatingIp Action) (DEPRECATED)
================================================================ ================================================================

View File

@@ -157,13 +157,21 @@ class RemoteConsolesController(wsgi.Controller):
target={'project_id': instance.project_id}) target={'project_id': instance.project_id})
protocol = body['remote_console']['protocol'] protocol = body['remote_console']['protocol']
console_type = body['remote_console']['type'] console_type = body['remote_console']['type']
# handle removed console types
if protocol in ('rdp',):
raise webob.exc.HTTPBadRequest(
'Unavailable console type %s.' % protocol
)
try: 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) output = handler(context, instance, console_type)
return {'remote_console': {'protocol': protocol, return {'remote_console': {'protocol': protocol,
'type': console_type, 'type': console_type,
'url': output['url']}} 'url': output['url']}}
except exception.InstanceNotFound as e: except exception.InstanceNotFound as e:
raise webob.exc.HTTPNotFound(explanation=e.format_message()) raise webob.exc.HTTPNotFound(explanation=e.format_message())
except exception.InstanceNotReady as e: except exception.InstanceNotReady as e:
@@ -174,5 +182,5 @@ class RemoteConsolesController(wsgi.Controller):
exception.ImageSerialPortNumberExceedFlavorValue, exception.ImageSerialPortNumberExceedFlavorValue,
exception.SocketPortRangeExhaustedException) as e: exception.SocketPortRangeExhaustedException) as e:
raise webob.exc.HTTPBadRequest(explanation=e.format_message()) raise webob.exc.HTTPBadRequest(explanation=e.format_message())
except NotImplementedError: except (NotImplementedError, KeyError):
common.raise_feature_not_supported() common.raise_feature_not_supported()

View File

@@ -20,6 +20,11 @@ get_vnc_console = {
'os-getVNCConsole': { 'os-getVNCConsole': {
'type': 'object', 'type': 'object',
'properties': { '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': {
'type': 'string', 'type': 'string',
'enum': ['novnc', 'xvpvnc'], 'enum': ['novnc', 'xvpvnc'],
@@ -63,8 +68,7 @@ get_serial_console = {
'type': 'object', 'type': 'object',
'properties': { 'properties': {
'type': { 'type': {
'type': 'string', 'type': 'string', 'enum': ['serial'],
'enum': ['serial'],
}, },
}, },
'required': ['type'], 'required': ['type'],
@@ -83,11 +87,16 @@ create_v26 = {
'properties': { 'properties': {
'protocol': { 'protocol': {
'type': 'string', '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': {
'type': 'string', 'type': 'string',
'enum': ['novnc', 'xvpvnc', 'spice-html5', 'serial'], 'enum': [
'novnc', 'xvpvnc', 'spice-html5', 'serial', 'rdp-html5'
],
}, },
}, },
'required': ['protocol', 'type'], 'required': ['protocol', 'type'],
@@ -98,53 +107,18 @@ create_v26 = {
'additionalProperties': False, 'additionalProperties': False,
} }
create_v28 = { create_v28 = copy.deepcopy(create_v26)
'type': 'object', create_v28['properties']['remote_console']['properties']['protocol'][
'properties': { 'enum'
'remote_console': { ].append('mks')
'type': 'object', create_v28['properties']['remote_console']['properties']['type'][
'properties': { 'enum'
'protocol': { ].append('webmks')
'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_v299 = { create_v299 = copy.deepcopy(create_v28)
'type': 'object', create_v299['properties']['remote_console']['properties']['type'][
'properties': { 'enum'
'remote_console': { ].append('spice-direct')
'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,
}
get_vnc_console_response = { get_vnc_console_response = {
'type': 'object', 'type': 'object',
@@ -152,16 +126,8 @@ get_vnc_console_response = {
'console': { 'console': {
'type': 'object', 'type': 'object',
'properties': { 'properties': {
'type': { 'type': {'type': 'string', 'enum': ['novnc', 'xvpvnc']},
'type': 'string', 'url': {'type': 'string', 'format': 'uri'},
'enum': ['novnc', 'xvpvnc'],
'description': '',
},
'url': {
'type': 'string',
'format': 'uri',
'description': '',
},
}, },
'required': ['type', 'url'], 'required': ['type', 'url'],
'additionalProperties': False, 'additionalProperties': False,
@@ -177,16 +143,8 @@ get_spice_console_response = {
'console': { 'console': {
'type': 'object', 'type': 'object',
'properties': { 'properties': {
'type': { 'type': {'type': 'string', 'const': 'spice-html5'},
'type': 'string', 'url': {'type': 'string', 'format': 'uri'},
'const': 'spice-html5',
'description': '',
},
'url': {
'type': 'string',
'format': 'uri',
'description': '',
},
}, },
'required': ['type', 'url'], 'required': ['type', 'url'],
'additionalProperties': False, 'additionalProperties': False,
@@ -201,16 +159,8 @@ get_rdp_console_response = {
'console': { 'console': {
'type': 'object', 'type': 'object',
'properties': { 'properties': {
'type': { 'type': {'type': 'string', 'const': 'rdp-html5'},
'type': 'string', 'url': {'type': 'string', 'format': 'uri'},
'const': 'rdp',
'description': '',
},
'url': {
'type': 'string',
'format': 'uri',
'description': '',
},
}, },
'required': ['type', 'url'], 'required': ['type', 'url'],
'additionalProperties': False, 'additionalProperties': False,
@@ -226,16 +176,8 @@ get_serial_console_response = {
'console': { 'console': {
'type': 'object', 'type': 'object',
'properties': { 'properties': {
'type': { 'type': {'type': 'string', 'const': 'serial'},
'type': 'string', 'url': {'type': 'string', 'format': 'uri'},
'const': 'serial',
'description': '',
},
'url': {
'type': 'string',
'format': 'uri',
'description': '',
},
}, },
'required': ['type', 'url'], 'required': ['type', 'url'],
'additionalProperties': False, 'additionalProperties': False,
@@ -253,18 +195,17 @@ create_response = {
'properties': { 'properties': {
'protocol': { 'protocol': {
'type': 'string', 'type': 'string',
'enum': ['vnc', 'spice', 'serial'], 'enum': ['vnc', 'spice', 'serial', 'rdp'],
}, },
'type': { 'type': {
'type': 'string', 'type': 'string',
'enum': ['novnc', 'xvpvnc', 'spice-html5', 'serial'], 'enum': [
}, 'novnc', 'xvpvnc', 'spice-html5', 'serial', 'rdp-html5'
'url': { ],
'type': 'string',
'format': 'uri',
}, },
'url': {'type': 'string', 'format': 'uri'},
}, },
'required': ['protocol', 'type'], 'required': ['protocol', 'type', 'url'],
'additionalProperties': False, 'additionalProperties': False,
}, },
}, },

View File

@@ -16,6 +16,7 @@
from unittest import mock from unittest import mock
import webob import webob
import webob.exc
from nova.api.openstack import api_version_request from nova.api.openstack import api_version_request
from nova.api.openstack.compute import remote_consoles \ from nova.api.openstack.compute import remote_consoles \
@@ -352,12 +353,8 @@ class ConsolesExtensionTestV26(test.NoDBTestCase):
'spice-html5') 'spice-html5')
def test_create_rdp_console_bad_request(self): 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'}} 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) self.req, fakes.FAKE_UUID, body=body)
def test_create_serial_console(self): def test_create_serial_console(self):