Add MKS console support

Co-Authored-By: jinke <jin.ke@99cloud.net>
Co-Authored-By: yong sheng gong <gong.yongsheng@99cloud.net>

Change-Id: Id8ee4a28a09eb3d7f7598c507c0a4320a97cd01c
implements: bp support-mks-console-type
This commit is contained in:
yong sheng gong 2017-10-16 23:09:53 +08:00 committed by jinke
parent c1a45f5677
commit 1f41f29f0b
12 changed files with 100 additions and 18 deletions

View File

@ -1888,11 +1888,15 @@ CONSOLE_TYPE
Added the ``SERIAL`` option Added the ``SERIAL`` option
.. versionchanged:: 2017.11(Queens)
Added the ``MKS`` option
Default: ``"AUTO"`` Default: ``"AUTO"``
This setting specifies the type of in-browser console used to access the VMs. This setting specifies the type of in-browser console used to access the VMs.
Valid values are ``"AUTO"``, ``"VNC"``, ``"SPICE"``, ``"RDP"``, Valid values are ``"AUTO"``, ``"VNC"``, ``"SPICE"``, ``"RDP"``,
``"SERIAL"``, and ``None``. ``"SERIAL"``, ``"MKS"``, and ``None``.
ENABLE_FLAVOR_EDIT ENABLE_FLAVOR_EDIT
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~

View File

@ -30,6 +30,7 @@ MICROVERSION_FEATURES = {
"nova": { "nova": {
"locked_attribute": ["2.9", "2.42"], "locked_attribute": ["2.9", "2.42"],
"instance_description": ["2.19", "2.42"], "instance_description": ["2.19", "2.42"],
"remote_console_mks": ["2.8", "2.53"]
}, },
"cinder": { "cinder": {
"consistency_groups": ["2.0", "3.10"], "consistency_groups": ["2.0", "3.10"],

View File

@ -101,6 +101,14 @@ class SerialConsole(base.APIDictWrapper):
_attrs = ['url', 'type'] _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): class Server(base.APIResourceWrapper):
"""Simple wrapper around novaclient.server.Server. """Simple wrapper around novaclient.server.Server.
@ -280,25 +288,32 @@ def upgrade_api(request, client, version):
@profiler.trace @profiler.trace
def server_vnc_console(request, instance_id, console_type='novnc'): def server_vnc_console(request, instance_id, console_type='novnc'):
return VNCConsole(novaclient(request).servers.get_vnc_console( return VNCConsole(novaclient(request).servers.get_vnc_console(
instance_id, console_type)['console']) instance_id, console_type)['remote_console'])
@profiler.trace @profiler.trace
def server_spice_console(request, instance_id, console_type='spice-html5'): def server_spice_console(request, instance_id, console_type='spice-html5'):
return SPICEConsole(novaclient(request).servers.get_spice_console( return SPICEConsole(novaclient(request).servers.get_spice_console(
instance_id, console_type)['console']) instance_id, console_type)['remote_console'])
@profiler.trace @profiler.trace
def server_rdp_console(request, instance_id, console_type='rdp-html5'): def server_rdp_console(request, instance_id, console_type='rdp-html5'):
return RDPConsole(novaclient(request).servers.get_rdp_console( return RDPConsole(novaclient(request).servers.get_rdp_console(
instance_id, console_type)['console']) instance_id, console_type)['remote_console'])
@profiler.trace @profiler.trace
def server_serial_console(request, instance_id, console_type='serial'): def server_serial_console(request, instance_id, console_type='serial'):
return SerialConsole(novaclient(request).servers.get_serial_console( 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 @profiler.trace

View File

@ -242,7 +242,8 @@ class RemoteConsoleInfo(generic.View):
CONSOLES = OrderedDict([('VNC', api.nova.server_vnc_console), CONSOLES = OrderedDict([('VNC', api.nova.server_vnc_console),
('SPICE', api.nova.server_spice_console), ('SPICE', api.nova.server_spice_console),
('RDP', api.nova.server_rdp_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.""" """Get a tuple of console url and console type."""
if console_type == 'AUTO': if console_type == 'AUTO':

View File

@ -30,6 +30,7 @@ urlpatterns = [
url(INSTANCES % 'detail', views.DetailView.as_view(), name='detail'), url(INSTANCES % 'detail', views.DetailView.as_view(), name='detail'),
url(INSTANCES % 'console', views.console, name='console'), url(INSTANCES % 'console', views.console, name='console'),
url(INSTANCES % 'vnc', views.vnc, name='vnc'), url(INSTANCES % 'vnc', views.vnc, name='vnc'),
url(INSTANCES % 'mks', views.mks, name='mks'),
url(INSTANCES % 'spice', views.spice, name='spice'), url(INSTANCES % 'spice', views.spice, name='spice'),
url(INSTANCES % 'rdp', views.rdp, name='rdp'), url(INSTANCES % 'rdp', views.rdp, name='rdp'),
url(INSTANCES % 'live_migrate', views.LiveMigrateView.as_view(), url(INSTANCES % 'live_migrate', views.LiveMigrateView.as_view(),

View File

@ -61,6 +61,11 @@ def rdp(args, **kvargs):
return views.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 # re-use get_resource_id_by_name from project.instances.views
def swap_filter(resources, filters, fake_field, real_field): def swap_filter(resources, filters, fake_field, real_field):
return views.swap_filter(resources, filters, fake_field, real_field) return views.swap_filter(resources, filters, fake_field, real_field)

View File

@ -27,7 +27,8 @@ LOG = logging.getLogger(__name__)
CONSOLES = OrderedDict([('VNC', api.nova.server_vnc_console), CONSOLES = OrderedDict([('VNC', api.nova.server_vnc_console),
('SPICE', api.nova.server_spice_console), ('SPICE', api.nova.server_spice_console),
('RDP', api.nova.server_rdp_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): def get_console(request, console_type, instance):

View File

@ -209,6 +209,17 @@ def vnc(request, instance_id):
exceptions.handle(request, msg, redirect=redirect) 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): def spice(request, instance_id):
try: try:
instance = api.nova.server_get(request, instance_id) instance = api.nova.server_get(request, instance_id)

View File

@ -104,8 +104,8 @@ WEBROOT = '/'
#OPENSTACK_KEYSTONE_FEDERATION_MANAGEMENT = False #OPENSTACK_KEYSTONE_FEDERATION_MANAGEMENT = False
# Set Console type: # Set Console type:
# valid options are "AUTO"(default), "VNC", "SPICE", "RDP", "SERIAL" or None # valid options are "AUTO"(default), "VNC", "SPICE", "RDP", "SERIAL", "MKS"
# Set to None explicitly if you want to deactivate the console. # or None. Set to None explicitly if you want to deactivate the console.
#CONSOLE_TYPE = "AUTO" #CONSOLE_TYPE = "AUTO"
# If provided, a "Report Bug" link will be displayed in the site header # If provided, a "Report Bug" link will be displayed in the site header

View File

@ -91,7 +91,7 @@ class ComputeApiTests(test.APITestCase):
def test_server_vnc_console(self): def test_server_vnc_console(self):
server = self.servers.first() server = self.servers.first()
console = self.servers.vnc_console_data console = self.servers.vnc_console_data
console_type = console["console"]["type"] console_type = console["remote_console"]["type"]
novaclient = self.stub_novaclient() novaclient = self.stub_novaclient()
novaclient.servers = self.mox.CreateMockAnything() novaclient.servers = self.mox.CreateMockAnything()
@ -107,7 +107,7 @@ class ComputeApiTests(test.APITestCase):
def test_server_spice_console(self): def test_server_spice_console(self):
server = self.servers.first() server = self.servers.first()
console = self.servers.spice_console_data console = self.servers.spice_console_data
console_type = console["console"]["type"] console_type = console["remote_console"]["type"]
novaclient = self.stub_novaclient() novaclient = self.stub_novaclient()
novaclient.servers = self.mox.CreateMockAnything() novaclient.servers = self.mox.CreateMockAnything()
@ -123,7 +123,7 @@ class ComputeApiTests(test.APITestCase):
def test_server_rdp_console(self): def test_server_rdp_console(self):
server = self.servers.first() server = self.servers.first()
console = self.servers.rdp_console_data console = self.servers.rdp_console_data
console_type = console["console"]["type"] console_type = console["remote_console"]["type"]
novaclient = self.stub_novaclient() novaclient = self.stub_novaclient()
novaclient.servers = self.mox.CreateMockAnything() novaclient.servers = self.mox.CreateMockAnything()
@ -136,6 +136,25 @@ class ComputeApiTests(test.APITestCase):
console_type) console_type)
self.assertIsInstance(ret_val, api.nova.RDPConsole) 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): def test_server_list(self):
servers = self.servers.list() servers = self.servers.list()

View File

@ -392,17 +392,37 @@ def data(TEST):
TEST.servers.add(server_1, server_2, server_3, server_4) TEST.servers.add(server_1, server_2, server_3, server_4)
# VNC Console Data # VNC Console Data
console = {u'console': {u'url': u'http://example.com:6080/vnc_auto.html', console = {
u'type': u'novnc'}} u'remote_console': {
u'url': u'http://example.com:6080/vnc_auto.html',
u'type': u'novnc'
}
}
TEST.servers.vnc_console_data = console TEST.servers.vnc_console_data = console
# SPICE Console Data # SPICE Console Data
console = {u'console': {u'url': u'http://example.com:6080/spice_auto.html', console = {
u'type': u'spice'}} u'remote_console': {
u'url': u'http://example.com:6080/spice_auto.html',
u'type': u'spice'
}
}
TEST.servers.spice_console_data = console TEST.servers.spice_console_data = console
# RDP Console Data # RDP Console Data
console = {u'console': {u'url': u'http://example.com:6080/rdp_auto.html', console = {
u'type': u'rdp'}} u'remote_console': {
u'url': u'http://example.com:6080/rdp_auto.html',
u'type': u'rdp'
}
}
TEST.servers.rdp_console_data = console 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
usage_vals = {"tenant_id": TEST.tenant.id, usage_vals = {"tenant_id": TEST.tenant.id,

View File

@ -0,0 +1,4 @@
---
features:
- Add MKS console support.
Blueprint can be found at [`<https://blueprints.launchpad.net/horizon/+spec/support-mks-console-type>`_]