diff --git a/nova/compute/api.py b/nova/compute/api.py index 09565bcb87db..81340906e8de 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -2858,7 +2858,8 @@ class API(base.Base): self.consoleauth_rpcapi.authorize_console(context, connect_info['token'], console_type, connect_info['host'], connect_info['port'], - connect_info['internal_access_path'], instance.uuid) + connect_info['internal_access_path'], instance.uuid, + access_url=connect_info['access_url']) return {'url': connect_info['access_url']} @@ -2878,7 +2879,8 @@ class API(base.Base): self.consoleauth_rpcapi.authorize_console(context, connect_info['token'], console_type, connect_info['host'], connect_info['port'], - connect_info['internal_access_path'], instance.uuid) + connect_info['internal_access_path'], instance.uuid, + access_url=connect_info['access_url']) return {'url': connect_info['access_url']} @@ -2898,7 +2900,8 @@ class API(base.Base): self.consoleauth_rpcapi.authorize_console(context, connect_info['token'], console_type, connect_info['host'], connect_info['port'], - connect_info['internal_access_path'], instance.uuid) + connect_info['internal_access_path'], instance.uuid, + access_url=connect_info['access_url']) return {'url': connect_info['access_url']} @@ -2919,7 +2922,8 @@ class API(base.Base): self.consoleauth_rpcapi.authorize_console(context, connect_info['token'], console_type, connect_info['host'], connect_info['port'], - connect_info['internal_access_path'], instance.uuid) + connect_info['internal_access_path'], instance.uuid, + access_url=connect_info['access_url']) return {'url': connect_info['access_url']} @check_instance_host diff --git a/nova/compute/cells_api.py b/nova/compute/cells_api.py index 03e7e3cc8e15..cf1aa8956b50 100644 --- a/nova/compute/cells_api.py +++ b/nova/compute/cells_api.py @@ -337,7 +337,7 @@ class ComputeCellsAPI(compute_api.API): self.consoleauth_rpcapi.authorize_console(context, connect_info['token'], console_type, connect_info['host'], connect_info['port'], connect_info['internal_access_path'], - instance.uuid) + instance.uuid, access_url=connect_info['access_url']) return {'url': connect_info['access_url']} @wrap_check_policy @@ -353,7 +353,7 @@ class ComputeCellsAPI(compute_api.API): self.consoleauth_rpcapi.authorize_console(context, connect_info['token'], console_type, connect_info['host'], connect_info['port'], connect_info['internal_access_path'], - instance.uuid) + instance.uuid, access_url=connect_info['access_url']) return {'url': connect_info['access_url']} @wrap_check_policy @@ -369,7 +369,7 @@ class ComputeCellsAPI(compute_api.API): self.consoleauth_rpcapi.authorize_console(context, connect_info['token'], console_type, connect_info['host'], connect_info['port'], connect_info['internal_access_path'], - instance.uuid) + instance.uuid, access_url=connect_info['access_url']) return {'url': connect_info['access_url']} @wrap_check_policy @@ -385,7 +385,7 @@ class ComputeCellsAPI(compute_api.API): self.consoleauth_rpcapi.authorize_console(context, connect_info['token'], console_type, connect_info['host'], connect_info['port'], connect_info['internal_access_path'], - instance.uuid) + instance.uuid, access_url=connect_info['access_url']) return {'url': connect_info['access_url']} @check_instance_cell diff --git a/nova/consoleauth/manager.py b/nova/consoleauth/manager.py index 9555404f5963..3ad341bb1289 100644 --- a/nova/consoleauth/manager.py +++ b/nova/consoleauth/manager.py @@ -47,7 +47,7 @@ CONF.import_opt('enable', 'nova.cells.opts', group='cells') class ConsoleAuthManager(manager.Manager): """Manages token based authentication.""" - target = messaging.Target(version='2.0') + target = messaging.Target(version='2.1') def __init__(self, scheduler_driver=None, *args, **kwargs): super(ConsoleAuthManager, self).__init__(service_name='consoleauth', @@ -65,7 +65,8 @@ class ConsoleAuthManager(manager.Manager): return tokens def authorize_console(self, context, token, console_type, host, port, - internal_access_path, instance_uuid): + internal_access_path, instance_uuid, + access_url=None): token_dict = {'token': token, 'instance_uuid': instance_uuid, @@ -73,6 +74,7 @@ class ConsoleAuthManager(manager.Manager): 'host': host, 'port': port, 'internal_access_path': internal_access_path, + 'access_url': access_url, 'last_activity_at': time.time()} data = jsonutils.dumps(token_dict) diff --git a/nova/consoleauth/rpcapi.py b/nova/consoleauth/rpcapi.py index 7273c5d3eefe..c005c8b633ed 100644 --- a/nova/consoleauth/rpcapi.py +++ b/nova/consoleauth/rpcapi.py @@ -47,6 +47,8 @@ class ConsoleAuthAPI(object): ... Icehouse and Juno support message version 2.0. So, any changes to existing methods in 2.x after that point should be done such that they can handle the version_cap being set to 2.0. + + * 2.1 - Added access_url to authorize_console ''' VERSION_ALIASES = { @@ -58,22 +60,28 @@ class ConsoleAuthAPI(object): def __init__(self): super(ConsoleAuthAPI, self).__init__() - target = messaging.Target(topic=CONF.consoleauth_topic, version='2.0') + target = messaging.Target(topic=CONF.consoleauth_topic, version='2.1') version_cap = self.VERSION_ALIASES.get(CONF.upgrade_levels.consoleauth, CONF.upgrade_levels.consoleauth) self.client = rpc.get_client(target, version_cap=version_cap) def authorize_console(self, ctxt, token, console_type, host, port, - internal_access_path, instance_uuid): + internal_access_path, instance_uuid, + access_url): # The remote side doesn't return anything, but we want to block # until it completes.' - cctxt = self.client.prepare() - return cctxt.call(ctxt, - 'authorize_console', - token=token, console_type=console_type, - host=host, port=port, - internal_access_path=internal_access_path, - instance_uuid=instance_uuid) + msg_args = dict(token=token, console_type=console_type, + host=host, port=port, + internal_access_path=internal_access_path, + instance_uuid=instance_uuid, + access_url=access_url) + version = '2.1' + if not self.client.can_send_version('2.1'): + version = '2.0' + del msg_args['access_url'] + + cctxt = self.client.prepare(version=version) + return cctxt.call(ctxt, 'authorize_console', **msg_args) def check_token(self, ctxt, token): cctxt = self.client.prepare() diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py index f2b6de82906a..3fe262959aa5 100644 --- a/nova/tests/unit/compute/test_compute.py +++ b/nova/tests/unit/compute/test_compute.py @@ -8979,7 +8979,8 @@ class ComputeAPITestCase(BaseTestCase): 'authorize_console') self.compute_api.consoleauth_rpcapi.authorize_console( self.context, 'fake_token', fake_console_type, 'fake_console_host', - 'fake_console_port', 'fake_access_path', 'fake_uuid') + 'fake_console_port', 'fake_access_path', 'fake_uuid', + access_url='fake_console_url') self.mox.ReplayAll() @@ -9018,7 +9019,8 @@ class ComputeAPITestCase(BaseTestCase): 'authorize_console') self.compute_api.consoleauth_rpcapi.authorize_console( self.context, 'fake_token', fake_console_type, 'fake_console_host', - 'fake_console_port', 'fake_access_path', 'fake_uuid') + 'fake_console_port', 'fake_access_path', 'fake_uuid', + access_url='fake_console_url') self.mox.ReplayAll() @@ -9057,7 +9059,8 @@ class ComputeAPITestCase(BaseTestCase): 'authorize_console') self.compute_api.consoleauth_rpcapi.authorize_console( self.context, 'fake_token', fake_console_type, 'fake_console_host', - 'fake_console_port', 'fake_access_path', 'fake_uuid') + 'fake_console_port', 'fake_access_path', 'fake_uuid', + access_url='fake_console_url') self.mox.ReplayAll() @@ -9097,7 +9100,8 @@ class ComputeAPITestCase(BaseTestCase): self.compute_api.consoleauth_rpcapi.authorize_console( self.context, 'fake_token', fake_console_type, 'fake_serial_host', 'fake_tcp_port', - 'fake_access_path', 'fake_uuid') + 'fake_access_path', 'fake_uuid', + access_url='fake_access_url') console = self.compute_api.get_serial_console(self.context, fake_instance, diff --git a/nova/tests/unit/consoleauth/test_rpcapi.py b/nova/tests/unit/consoleauth/test_rpcapi.py index 8731782a671b..bff7a28eda3c 100644 --- a/nova/tests/unit/consoleauth/test_rpcapi.py +++ b/nova/tests/unit/consoleauth/test_rpcapi.py @@ -20,6 +20,7 @@ import contextlib import mock from oslo_config import cfg +import six from nova.consoleauth import rpcapi as consoleauth_rpcapi from nova import context @@ -29,6 +30,8 @@ CONF = cfg.CONF class ConsoleAuthRpcAPITestCase(test.NoDBTestCase): + DROPPED_ARG = object() + def _test_consoleauth_api(self, method, **kwargs): do_cast = kwargs.pop('_do_cast', False) @@ -40,6 +43,10 @@ class ConsoleAuthRpcAPITestCase(test.NoDBTestCase): orig_prepare = rpcapi.client.prepare + version = kwargs.pop('version', None) + rpc_kwargs = {k: v for k, v in six.iteritems(kwargs) + if v is not self.DROPPED_ARG} + with contextlib.nested( mock.patch.object(rpcapi.client, 'cast' if do_cast else 'call'), mock.patch.object(rpcapi.client, 'prepare'), @@ -49,19 +56,35 @@ class ConsoleAuthRpcAPITestCase(test.NoDBTestCase): ): prepare_mock.return_value = rpcapi.client rpc_mock.return_value = None if do_cast else 'foo' - csv_mock.side_effect = ( - lambda v: orig_prepare().can_send_version()) + + def fake_csv(v): + if version: + return orig_prepare( + version_cap=version).can_send_version(version=v) + else: + return orig_prepare().can_send_version() + csv_mock.side_effect = fake_csv retval = getattr(rpcapi, method)(ctxt, **kwargs) self.assertEqual(retval, rpc_mock.return_value) - prepare_mock.assert_called_once_with() - rpc_mock.assert_called_once_with(ctxt, method, **kwargs) + if version: + prepare_mock.assert_called_once_with(version=version) + else: + prepare_mock.assert_called_once_with() + rpc_mock.assert_called_once_with(ctxt, method, **rpc_kwargs) def test_authorize_console(self): self._test_consoleauth_api('authorize_console', token='token', console_type='ctype', host='h', port='p', - internal_access_path='iap', instance_uuid="instance") + internal_access_path='iap', instance_uuid="instance", + access_url=self.DROPPED_ARG, version='2.0') + + def test_authorize_console_access_url(self): + self._test_consoleauth_api('authorize_console', token='token', + console_type='ctype', host='h', port='p', + internal_access_path='iap', instance_uuid="instance", + access_url="fake_access_url", version='2.1') def test_check_token(self): self._test_consoleauth_api('check_token', token='t')