diff --git a/doc/source/configuration/settings.rst b/doc/source/configuration/settings.rst index 7ef538f3df..d5dee1bf54 100644 --- a/doc/source/configuration/settings.rst +++ b/doc/source/configuration/settings.rst @@ -1888,11 +1888,15 @@ CONSOLE_TYPE Added the ``SERIAL`` option +.. versionchanged:: 2017.11(Queens) + + Added the ``MKS`` option + Default: ``"AUTO"`` This setting specifies the type of in-browser console used to access the VMs. Valid values are ``"AUTO"``, ``"VNC"``, ``"SPICE"``, ``"RDP"``, -``"SERIAL"``, and ``None``. +``"SERIAL"``, ``"MKS"``, and ``None``. ENABLE_FLAVOR_EDIT ~~~~~~~~~~~~~~~~~~ diff --git a/openstack_dashboard/api/microversions.py b/openstack_dashboard/api/microversions.py index 58af79a56d..ea744d508a 100644 --- a/openstack_dashboard/api/microversions.py +++ b/openstack_dashboard/api/microversions.py @@ -30,6 +30,7 @@ MICROVERSION_FEATURES = { "nova": { "locked_attribute": ["2.9", "2.42"], "instance_description": ["2.19", "2.42"], + "remote_console_mks": ["2.8", "2.53"] }, "cinder": { "consistency_groups": ["2.0", "3.10"], diff --git a/openstack_dashboard/api/nova.py b/openstack_dashboard/api/nova.py index 16c40445e9..dc6fa0ad57 100644 --- a/openstack_dashboard/api/nova.py +++ b/openstack_dashboard/api/nova.py @@ -101,6 +101,14 @@ class SerialConsole(base.APIDictWrapper): _attrs = ['url', 'type'] +class MKSConsole(base.APIDictWrapper): + """Wrapper for the "console" dictionary. + + Returned by the novaclient.servers.get_mks_console method. + """ + _attrs = ['url', 'type'] + + class Server(base.APIResourceWrapper): """Simple wrapper around novaclient.server.Server. @@ -280,25 +288,32 @@ def upgrade_api(request, client, version): @profiler.trace def server_vnc_console(request, instance_id, console_type='novnc'): return VNCConsole(novaclient(request).servers.get_vnc_console( - instance_id, console_type)['console']) + instance_id, console_type)['remote_console']) @profiler.trace def server_spice_console(request, instance_id, console_type='spice-html5'): return SPICEConsole(novaclient(request).servers.get_spice_console( - instance_id, console_type)['console']) + instance_id, console_type)['remote_console']) @profiler.trace def server_rdp_console(request, instance_id, console_type='rdp-html5'): return RDPConsole(novaclient(request).servers.get_rdp_console( - instance_id, console_type)['console']) + instance_id, console_type)['remote_console']) @profiler.trace def server_serial_console(request, instance_id, console_type='serial'): return SerialConsole(novaclient(request).servers.get_serial_console( - instance_id, console_type)['console']) + instance_id, console_type)['remote_console']) + + +@profiler.trace +def server_mks_console(request, instance_id, console_type='mks'): + microver = get_microversion(request, "remote_console_mks") + return MKSConsole(novaclient(request, microver).servers.get_mks_console( + instance_id, console_type)['remote_console']) @profiler.trace diff --git a/openstack_dashboard/api/rest/nova.py b/openstack_dashboard/api/rest/nova.py index 1fb111a4b8..5f370cfef7 100644 --- a/openstack_dashboard/api/rest/nova.py +++ b/openstack_dashboard/api/rest/nova.py @@ -242,7 +242,8 @@ class RemoteConsoleInfo(generic.View): CONSOLES = OrderedDict([('VNC', api.nova.server_vnc_console), ('SPICE', api.nova.server_spice_console), ('RDP', api.nova.server_rdp_console), - ('SERIAL', api.nova.server_serial_console)]) + ('SERIAL', api.nova.server_serial_console), + ('MKS', api.nova.server_mks_console)]) """Get a tuple of console url and console type.""" if console_type == 'AUTO': diff --git a/openstack_dashboard/dashboards/admin/instances/urls.py b/openstack_dashboard/dashboards/admin/instances/urls.py index 455942cee8..e33ae4cfd2 100644 --- a/openstack_dashboard/dashboards/admin/instances/urls.py +++ b/openstack_dashboard/dashboards/admin/instances/urls.py @@ -30,6 +30,7 @@ urlpatterns = [ url(INSTANCES % 'detail', views.DetailView.as_view(), name='detail'), url(INSTANCES % 'console', views.console, name='console'), url(INSTANCES % 'vnc', views.vnc, name='vnc'), + url(INSTANCES % 'mks', views.mks, name='mks'), url(INSTANCES % 'spice', views.spice, name='spice'), url(INSTANCES % 'rdp', views.rdp, name='rdp'), url(INSTANCES % 'live_migrate', views.LiveMigrateView.as_view(), diff --git a/openstack_dashboard/dashboards/admin/instances/views.py b/openstack_dashboard/dashboards/admin/instances/views.py index c23ef2c4db..2d3e53c08b 100644 --- a/openstack_dashboard/dashboards/admin/instances/views.py +++ b/openstack_dashboard/dashboards/admin/instances/views.py @@ -61,6 +61,11 @@ def rdp(args, **kvargs): return views.rdp(args, **kvargs) +# re-use mks from project.instances.views to make reflection work +def mks(args, **kvargs): + return views.mks(args, **kvargs) + + # re-use get_resource_id_by_name from project.instances.views def swap_filter(resources, filters, fake_field, real_field): return views.swap_filter(resources, filters, fake_field, real_field) diff --git a/openstack_dashboard/dashboards/project/instances/console.py b/openstack_dashboard/dashboards/project/instances/console.py index 9380889256..3ecc603bd3 100644 --- a/openstack_dashboard/dashboards/project/instances/console.py +++ b/openstack_dashboard/dashboards/project/instances/console.py @@ -27,7 +27,8 @@ LOG = logging.getLogger(__name__) CONSOLES = OrderedDict([('VNC', api.nova.server_vnc_console), ('SPICE', api.nova.server_spice_console), ('RDP', api.nova.server_rdp_console), - ('SERIAL', api.nova.server_serial_console)]) + ('SERIAL', api.nova.server_serial_console), + ('MKS', api.nova.server_mks_console)]) def get_console(request, console_type, instance): diff --git a/openstack_dashboard/dashboards/project/instances/views.py b/openstack_dashboard/dashboards/project/instances/views.py index 01242ca3c6..39a7b401aa 100644 --- a/openstack_dashboard/dashboards/project/instances/views.py +++ b/openstack_dashboard/dashboards/project/instances/views.py @@ -209,6 +209,17 @@ def vnc(request, instance_id): exceptions.handle(request, msg, redirect=redirect) +def mks(request, instance_id): + try: + instance = api.nova.server_get(request, instance_id) + console_url = project_console.get_console(request, 'MKS', instance)[1] + return shortcuts.redirect(console_url) + except Exception: + redirect = reverse("horizon:project:instances:index") + msg = _('Unable to get MKS console for instance "%s".') % instance_id + exceptions.handle(request, msg, redirect=redirect) + + def spice(request, instance_id): try: instance = api.nova.server_get(request, instance_id) diff --git a/openstack_dashboard/local/local_settings.py.example b/openstack_dashboard/local/local_settings.py.example index a4e34b9d54..8f63dbe8bf 100644 --- a/openstack_dashboard/local/local_settings.py.example +++ b/openstack_dashboard/local/local_settings.py.example @@ -104,8 +104,8 @@ WEBROOT = '/' #OPENSTACK_KEYSTONE_FEDERATION_MANAGEMENT = False # Set Console type: -# valid options are "AUTO"(default), "VNC", "SPICE", "RDP", "SERIAL" or None -# Set to None explicitly if you want to deactivate the console. +# valid options are "AUTO"(default), "VNC", "SPICE", "RDP", "SERIAL", "MKS" +# or None. Set to None explicitly if you want to deactivate the console. #CONSOLE_TYPE = "AUTO" # If provided, a "Report Bug" link will be displayed in the site header diff --git a/openstack_dashboard/test/api_tests/nova_tests.py b/openstack_dashboard/test/api_tests/nova_tests.py index 6043dae03e..dddff5b5ea 100644 --- a/openstack_dashboard/test/api_tests/nova_tests.py +++ b/openstack_dashboard/test/api_tests/nova_tests.py @@ -91,7 +91,7 @@ class ComputeApiTests(test.APITestCase): def test_server_vnc_console(self): server = self.servers.first() console = self.servers.vnc_console_data - console_type = console["console"]["type"] + console_type = console["remote_console"]["type"] novaclient = self.stub_novaclient() novaclient.servers = self.mox.CreateMockAnything() @@ -107,7 +107,7 @@ class ComputeApiTests(test.APITestCase): def test_server_spice_console(self): server = self.servers.first() console = self.servers.spice_console_data - console_type = console["console"]["type"] + console_type = console["remote_console"]["type"] novaclient = self.stub_novaclient() novaclient.servers = self.mox.CreateMockAnything() @@ -123,7 +123,7 @@ class ComputeApiTests(test.APITestCase): def test_server_rdp_console(self): server = self.servers.first() console = self.servers.rdp_console_data - console_type = console["console"]["type"] + console_type = console["remote_console"]["type"] novaclient = self.stub_novaclient() novaclient.servers = self.mox.CreateMockAnything() @@ -136,6 +136,25 @@ class ComputeApiTests(test.APITestCase): console_type) self.assertIsInstance(ret_val, api.nova.RDPConsole) + def test_server_mks_console(self): + server = self.servers.first() + console = self.servers.mks_console_data + console_type = console["remote_console"]["type"] + + return_value = {"version": {"min_version": "2.1", "version": "2.53"}} + novaclient = self.stub_novaclient() + novaclient.versions = self.mox.CreateMockAnything() + novaclient.versions.get_current().AndReturn(return_value) + novaclient.servers = self.mox.CreateMockAnything() + novaclient.servers.get_mks_console(server.id, + console_type).AndReturn(console) + self.mox.ReplayAll() + + ret_val = api.nova.server_mks_console(self.request, + server.id, + console_type) + self.assertIsInstance(ret_val, api.nova.MKSConsole) + def test_server_list(self): servers = self.servers.list() diff --git a/openstack_dashboard/test/test_data/nova_data.py b/openstack_dashboard/test/test_data/nova_data.py index de4aa1023b..0b0d7c82fa 100644 --- a/openstack_dashboard/test/test_data/nova_data.py +++ b/openstack_dashboard/test/test_data/nova_data.py @@ -392,17 +392,37 @@ def data(TEST): TEST.servers.add(server_1, server_2, server_3, server_4) # VNC Console Data - console = {u'console': {u'url': u'http://example.com:6080/vnc_auto.html', - u'type': u'novnc'}} + console = { + u'remote_console': { + u'url': u'http://example.com:6080/vnc_auto.html', + u'type': u'novnc' + } + } TEST.servers.vnc_console_data = console # SPICE Console Data - console = {u'console': {u'url': u'http://example.com:6080/spice_auto.html', - u'type': u'spice'}} + console = { + u'remote_console': { + u'url': u'http://example.com:6080/spice_auto.html', + u'type': u'spice' + } + } TEST.servers.spice_console_data = console # RDP Console Data - console = {u'console': {u'url': u'http://example.com:6080/rdp_auto.html', - u'type': u'rdp'}} + console = { + u'remote_console': { + u'url': u'http://example.com:6080/rdp_auto.html', + u'type': u'rdp' + } + } TEST.servers.rdp_console_data = console + # MKS Console Data + console = { + u'remote_console': { + u'url': u'http://example.com:6080/mks_auto.html', + u'type': u'mks' + } + } + TEST.servers.mks_console_data = console # Usage usage_vals = {"tenant_id": TEST.tenant.id, diff --git a/releasenotes/notes/bp-mks-console-support-a943797a8bad14ca.yaml b/releasenotes/notes/bp-mks-console-support-a943797a8bad14ca.yaml new file mode 100644 index 0000000000..02afe87bf9 --- /dev/null +++ b/releasenotes/notes/bp-mks-console-support-a943797a8bad14ca.yaml @@ -0,0 +1,4 @@ +--- +features: + - Add MKS console support. + Blueprint can be found at [``_]