From 2398b78df5c30ccb71ea22821a40ad2a793a6a1a Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Tue, 16 Apr 2019 10:52:52 +0100 Subject: [PATCH] Remove nova-consoleauth Obliterate all references to the aforementioned service. This mostly consists of removing the core service and any references to the now removed '[workarounds] enable_consoleauth' configuration option. Part of blueprint remove-consoleauth Change-Id: I0498599fd636aa9e30df932f0d893db5efa23260 Signed-off-by: Stephen Finucane Depends-On: Icfc175c49a1fc650d1c9ad06b77209a70c6386db --- .../openstack/compute/console_auth_tokens.py | 32 +-- nova/api/openstack/compute/hosts.py | 3 - nova/cmd/consoleauth.py | 50 ---- nova/compute/api.py | 73 ------ nova/conf/compute.py | 2 +- nova/conf/consoleauth.py | 4 - nova/conf/upgrade_levels.py | 18 -- nova/conf/workarounds.py | 32 --- nova/console/websocketproxy.py | 30 +-- nova/consoleauth/__init__.py | 17 -- nova/consoleauth/manager.py | 136 ---------- nova/consoleauth/rpcapi.py | 103 -------- nova/objects/fields.py | 2 + nova/service.py | 1 - .../compute/test_console_auth_tokens.py | 103 ++------ nova/tests/unit/compute/test_compute.py | 91 +------ nova/tests/unit/compute/test_compute_api.py | 26 +- .../tests/unit/console/test_websocketproxy.py | 77 +----- nova/tests/unit/consoleauth/__init__.py | 0 .../unit/consoleauth/test_consoleauth.py | 240 ------------------ nova/tests/unit/consoleauth/test_rpcapi.py | 90 ------- nova/tests/unit/test_profiler.py | 2 - ...ove-nova-consoleauth-b7c61e50649206ea.yaml | 9 + setup.cfg | 1 - 24 files changed, 61 insertions(+), 1081 deletions(-) delete mode 100644 nova/cmd/consoleauth.py delete mode 100644 nova/consoleauth/__init__.py delete mode 100644 nova/consoleauth/manager.py delete mode 100644 nova/consoleauth/rpcapi.py delete mode 100644 nova/tests/unit/consoleauth/__init__.py delete mode 100644 nova/tests/unit/consoleauth/test_consoleauth.py delete mode 100644 nova/tests/unit/consoleauth/test_rpcapi.py create mode 100644 releasenotes/notes/remove-nova-consoleauth-b7c61e50649206ea.yaml diff --git a/nova/api/openstack/compute/console_auth_tokens.py b/nova/api/openstack/compute/console_auth_tokens.py index e8066b1f8d57..b295ac05aa77 100644 --- a/nova/api/openstack/compute/console_auth_tokens.py +++ b/nova/api/openstack/compute/console_auth_tokens.py @@ -17,7 +17,6 @@ import webob from nova.api.openstack import wsgi import nova.conf -from nova.consoleauth import rpcapi as consoleauth_rpcapi from nova import context as nova_context from nova.i18n import _ from nova import objects @@ -27,9 +26,6 @@ CONF = nova.conf.CONF class ConsoleAuthTokensController(wsgi.Controller): - def __init__(self): - super(ConsoleAuthTokensController, self).__init__() - self._consoleauth_rpcapi = consoleauth_rpcapi.ConsoleAuthAPI() def _show(self, req, id, rdp_only): """Checks a console auth token and returns the related connect info.""" @@ -42,21 +38,19 @@ class ConsoleAuthTokensController(wsgi.Controller): raise webob.exc.HTTPBadRequest(explanation=msg) connect_info = None - if CONF.workarounds.enable_consoleauth: - connect_info = self._consoleauth_rpcapi.check_token(context, token) - else: - results = nova_context.scatter_gather_skip_cell0( - context, objects.ConsoleAuthToken.validate, token) - # NOTE(melwitt): Console token auths are stored in cell databases, - # but with only the token as a request param, we can't know which - # cell database contains the token's corresponding connection info. - # So, we must query all cells for the info and we can break the - # loop as soon as we find a result because the token is associated - # with one instance, which can only be in one cell. - for result in results.values(): - if not nova_context.is_cell_failure_sentinel(result): - connect_info = result.to_dict() - break + + results = nova_context.scatter_gather_skip_cell0( + context, objects.ConsoleAuthToken.validate, token) + # NOTE(melwitt): Console token auths are stored in cell databases, + # but with only the token as a request param, we can't know which + # cell database contains the token's corresponding connection info. + # So, we must query all cells for the info and we can break the + # loop as soon as we find a result because the token is associated + # with one instance, which can only be in one cell. + for result in results.values(): + if not nova_context.is_cell_failure_sentinel(result): + connect_info = result.to_dict() + break if not connect_info: raise webob.exc.HTTPNotFound(explanation=_("Token not found")) diff --git a/nova/api/openstack/compute/hosts.py b/nova/api/openstack/compute/hosts.py index 31424b24b08a..bf87439e89e5 100644 --- a/nova/api/openstack/compute/hosts.py +++ b/nova/api/openstack/compute/hosts.py @@ -53,9 +53,6 @@ class HostController(wsgi.Controller): | {'host_name': 'some.celly.host.name', | 'service': 'cells', | 'zone': 'internal'}, - | {'host_name': 'console1.host.com', - | 'service': 'consoleauth', - | 'zone': 'internal'}, | {'host_name': 'network1.host.com', | 'service': 'network', | 'zone': 'internal'}, diff --git a/nova/cmd/consoleauth.py b/nova/cmd/consoleauth.py deleted file mode 100644 index e28d56a10b05..000000000000 --- a/nova/cmd/consoleauth.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (c) 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""VNC Console Proxy Server.""" - -import sys - -from oslo_log import log as logging -from oslo_reports import guru_meditation_report as gmr -from oslo_reports import opts as gmr_opts - -import nova.conf -from nova import config -from nova.consoleauth import rpcapi -from nova import objects -from nova import service -from nova import version - -CONF = nova.conf.CONF -LOG = logging.getLogger('nova.consoleauth') - - -def main(): - config.parse_args(sys.argv) - logging.setup(CONF, "nova") - objects.register_all() - gmr_opts.set_defaults(CONF) - - gmr.TextGuruMeditation.setup_autorun(version, conf=CONF) - - LOG.warning('The nova-consoleauth service is deprecated as console token ' - 'authorization storage has moved from the nova-consoleauth ' - 'service backend to the database backend.') - - server = service.Service.create(binary='nova-consoleauth', - topic=rpcapi.RPC_TOPIC) - service.serve(server) - service.wait() diff --git a/nova/compute/api.py b/nova/compute/api.py index dd32e589ed34..878c982ea2c5 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -51,7 +51,6 @@ from nova.compute.utils import wrap_instance_event from nova.compute import vm_states from nova import conductor import nova.conf -from nova.consoleauth import rpcapi as consoleauth_rpcapi from nova import context as nova_context from nova import crypto from nova.db import base @@ -259,7 +258,6 @@ class API(base.Base): self._placementclient = None # Lazy-load on first access. self.security_group_api = (security_group_api or openstack_driver.get_openstack_security_group_driver()) - self.consoleauth_rpcapi = consoleauth_rpcapi.ConsoleAuthAPI() self.compute_rpcapi = compute_rpcapi.ComputeAPI() self.compute_task_api = conductor.ComputeTaskAPI() self.servicegroup_api = servicegroup.API() @@ -2066,13 +2064,6 @@ class API(base.Base): instance.progress = 0 instance.save() - if CONF.workarounds.enable_consoleauth: - # TODO(melwitt): Remove the conditions for running this line - # with cells v2, when consoleauth is no longer being used by - # cells v2, in Stein. - self.consoleauth_rpcapi.delete_tokens_for_instance( - context, instance.uuid) - if not instance.host and not may_have_ports_or_volumes: try: with compute_utils.notify_about_instance_delete( @@ -3803,18 +3794,6 @@ class API(base.Base): """Get a url to an instance Console.""" connect_info = self.compute_rpcapi.get_vnc_console(context, instance=instance, console_type=console_type) - - # TODO(melwitt): In Rocky, the compute manager puts the - # console authorization in the database in the above method. - # The following will be removed when everything has been - # converted to use the database, in Stein. - if CONF.workarounds.enable_consoleauth: - self.consoleauth_rpcapi.authorize_console(context, - connect_info['token'], console_type, - connect_info['host'], connect_info['port'], - connect_info['internal_access_path'], instance.uuid, - access_url=connect_info['access_url']) - return {'url': connect_info['access_url']} @check_instance_host @@ -3824,17 +3803,6 @@ class API(base.Base): """Get a url to an instance Console.""" connect_info = self.compute_rpcapi.get_spice_console(context, instance=instance, console_type=console_type) - # TODO(melwitt): In Rocky, the compute manager puts the - # console authorization in the database in the above method. - # The following will be removed when everything has been - # converted to use the database, in Stein. - if CONF.workarounds.enable_consoleauth: - self.consoleauth_rpcapi.authorize_console(context, - connect_info['token'], console_type, - connect_info['host'], connect_info['port'], - connect_info['internal_access_path'], instance.uuid, - access_url=connect_info['access_url']) - return {'url': connect_info['access_url']} @check_instance_host @@ -3844,17 +3812,6 @@ class API(base.Base): """Get a url to an instance Console.""" connect_info = self.compute_rpcapi.get_rdp_console(context, instance=instance, console_type=console_type) - # TODO(melwitt): In Rocky, the compute manager puts the - # console authorization in the database in the above method. - # The following will be removed when everything has been - # converted to use the database, in Stein. - if CONF.workarounds.enable_consoleauth: - self.consoleauth_rpcapi.authorize_console(context, - connect_info['token'], console_type, - connect_info['host'], connect_info['port'], - connect_info['internal_access_path'], instance.uuid, - access_url=connect_info['access_url']) - return {'url': connect_info['access_url']} @check_instance_host @@ -3864,17 +3821,6 @@ class API(base.Base): """Get a url to a serial console.""" connect_info = self.compute_rpcapi.get_serial_console(context, instance=instance, console_type=console_type) - - # TODO(melwitt): In Rocky, the compute manager puts the - # console authorization in the database in the above method. - # The following will be removed when everything has been - # converted to use the database, in Stein. - if CONF.workarounds.enable_consoleauth: - self.consoleauth_rpcapi.authorize_console(context, - connect_info['token'], console_type, - connect_info['host'], connect_info['port'], - connect_info['internal_access_path'], instance.uuid, - access_url=connect_info['access_url']) return {'url': connect_info['access_url']} @check_instance_host @@ -3884,16 +3830,6 @@ class API(base.Base): """Get a url to a MKS console.""" connect_info = self.compute_rpcapi.get_mks_console(context, instance=instance, console_type=console_type) - # TODO(melwitt): In Rocky, the compute manager puts the - # console authorization in the database in the above method. - # The following will be removed when everything has been - # converted to use the database, in Stein. - if CONF.workarounds.enable_consoleauth: - self.consoleauth_rpcapi.authorize_console(context, - connect_info['token'], console_type, - connect_info['host'], connect_info['port'], - connect_info['internal_access_path'], instance.uuid, - access_url=connect_info['access_url']) return {'url': connect_info['access_url']} @check_instance_host @@ -4493,15 +4429,6 @@ class API(base.Base): self._record_action_start(context, instance, instance_actions.LIVE_MIGRATION) - # TODO(melwitt): In Rocky, we optionally store console authorizations - # in both the consoleauth service and the database while - # we convert to using the database. Remove the condition for running - # this line with cells v2, when consoleauth is no longer being used by - # cells v2, in Stein. - if CONF.workarounds.enable_consoleauth: - self.consoleauth_rpcapi.delete_tokens_for_instance( - context, instance.uuid) - # NOTE(sbauza): Force is a boolean by the new related API version if force is False and host_name: # Unset the host to make sure we call the scheduler diff --git a/nova/conf/compute.py b/nova/conf/compute.py index f5c5a7f8c024..5af2b4f76e9b 100644 --- a/nova/conf/compute.py +++ b/nova/conf/compute.py @@ -1289,7 +1289,7 @@ registered in the database as an enabled service. Sometimes it can be useful to register new compute services in disabled state and then enabled them at a later point in time. This option only sets this behavior for nova-compute services, it does not auto-disable other services like nova-conductor, -nova-scheduler, nova-consoleauth, or nova-osapi_compute. +nova-scheduler, or nova-osapi_compute. Possible values: diff --git a/nova/conf/consoleauth.py b/nova/conf/consoleauth.py index 3f4480ee380f..0ebadbb2415f 100644 --- a/nova/conf/consoleauth.py +++ b/nova/conf/consoleauth.py @@ -32,10 +32,6 @@ The lifetime of a console auth token (in seconds). A console auth token is used in authorizing console access for a user. Once the auth token time to live count has elapsed, the token is considered expired. Expired tokens are then deleted. - -Related options: - -* ``[workarounds]/enable_consoleauth`` """) ] diff --git a/nova/conf/upgrade_levels.py b/nova/conf/upgrade_levels.py index b22a7cd0f17d..07dc5fe84a02 100644 --- a/nova/conf/upgrade_levels.py +++ b/nova/conf/upgrade_levels.py @@ -108,24 +108,6 @@ Console RPC API version cap. Possible values: -* By default send the latest version the client knows about -* A string representing a version number in the format 'N.N'; - for example, possible values might be '1.12' or '2.0'. -* An OpenStack release name, in lower case, such as 'mitaka' or - 'liberty'. -"""), - cfg.StrOpt('consoleauth', - deprecated_for_removal=True, - deprecated_since='18.0.0', - deprecated_reason=""" -The nova-consoleauth service was deprecated in 18.0.0 (Rocky) and will be -removed in an upcoming release. -""", - help=""" -Consoleauth RPC API version cap. - -Possible values: - * By default send the latest version the client knows about * A string representing a version number in the format 'N.N'; for example, possible values might be '1.12' or '2.0'. diff --git a/nova/conf/workarounds.py b/nova/conf/workarounds.py index 0831c7a2841e..88624468aed2 100644 --- a/nova/conf/workarounds.py +++ b/nova/conf/workarounds.py @@ -154,38 +154,6 @@ Related options: compute service to the scheduler service. """), - cfg.BoolOpt( - 'enable_consoleauth', - default=False, - deprecated_for_removal=True, - deprecated_since="18.0.0", - deprecated_reason=""" -This option has been added as deprecated originally because it is used -for avoiding a upgrade issue and it will not be used in the future. -See the help text for more details. -""", - help=""" -Enable the consoleauth service to avoid resetting unexpired consoles. - -Console token authorizations have moved from the ``nova-consoleauth`` service -to the database, so all new consoles will be supported by the database backend. -With this, consoles that existed before database backend support will be reset. -For most operators, this should be a minimal disruption as the default TTL of a -console token is 10 minutes. - -Operators that have much longer token TTL configured or otherwise wish to avoid -immediately resetting all existing consoles can enable this flag to continue -using the ``nova-consoleauth`` service in addition to the database backend. -Once all of the old ``nova-consoleauth`` supported console tokens have expired, -this flag should be disabled. For example, if a deployment has configured a -token TTL of one hour, the operator may disable the flag, one hour after -deploying the new code during an upgrade. - -Related options: - -* ``[consoleauth]/token_ttl`` -"""), - cfg.BoolOpt( 'enable_numa_live_migration', default=False, diff --git a/nova/console/websocketproxy.py b/nova/console/websocketproxy.py index f9415c60f548..448bdba92bae 100644 --- a/nova/console/websocketproxy.py +++ b/nova/console/websocketproxy.py @@ -30,7 +30,6 @@ import websockify from nova.compute import rpcapi as compute_rpcapi import nova.conf -from nova.consoleauth import rpcapi as consoleauth_rpcapi from nova import context from nova import exception from nova.i18n import _ @@ -125,14 +124,8 @@ class NovaProxyRequestHandlerBase(object): str(port), console_type) - def _get_connect_info_consoleauth(self, ctxt, token): - # NOTE(PaulMurray) consoleauth check_token() validates the token - # and does an rpc to compute manager to check the console port - # is correct. - rpcapi = consoleauth_rpcapi.ConsoleAuthAPI() - return rpcapi.check_token(ctxt, token=token) - - def _get_connect_info_database(self, ctxt, token): + def _get_connect_info(self, ctxt, token): + """Validate the token and get the connect info.""" # NOTE(PaulMurray) ConsoleAuthToken.validate validates the token. # We call the compute manager directly to check the console port # is correct. @@ -147,25 +140,6 @@ class NovaProxyRequestHandlerBase(object): return connect_info - def _get_connect_info(self, ctxt, token): - """Validate the token and get the connect info.""" - connect_info = None - - # NOTE(melwitt): If consoleauth is enabled to aid in transitioning - # to the database backend, check it first before falling back to - # the database. Tokens that existed pre-database-backend will - # reside in the consoleauth service storage. - if CONF.workarounds.enable_consoleauth: - connect_info = self._get_connect_info_consoleauth(ctxt, token) - # If consoleauth is enabled to aid in transitioning to the database - # backend and we didn't find a token in the consoleauth service - # storage, check the database for a token because it's probably a - # post-database-backend token, which are stored in the database. - if not connect_info: - connect_info = self._get_connect_info_database(ctxt, token) - - return connect_info - def new_websocket_client(self): """Called after a new WebSocket connection has been established.""" # Reopen the eventlet hub to make sure we don't share an epoll diff --git a/nova/consoleauth/__init__.py b/nova/consoleauth/__init__.py deleted file mode 100644 index c2f4ca5b73ea..000000000000 --- a/nova/consoleauth/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Module to authenticate Consoles.""" diff --git a/nova/consoleauth/manager.py b/nova/consoleauth/manager.py deleted file mode 100644 index afcc968953f5..000000000000 --- a/nova/consoleauth/manager.py +++ /dev/null @@ -1,136 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Auth Components for Consoles.""" - -import time - -from oslo_log import log as logging -import oslo_messaging as messaging -from oslo_serialization import jsonutils - -from nova import cache_utils -from nova.compute import rpcapi as compute_rpcapi -import nova.conf -from nova import context as nova_context -from nova import manager -from nova import objects - - -LOG = logging.getLogger(__name__) - -CONF = nova.conf.CONF - - -class ConsoleAuthManager(manager.Manager): - """Manages token based authentication.""" - - target = messaging.Target(version='2.1') - - def __init__(self, scheduler_driver=None, *args, **kwargs): - super(ConsoleAuthManager, self).__init__(service_name='consoleauth', - *args, **kwargs) - self._mc = None - self._mc_instance = None - self.compute_rpcapi = compute_rpcapi.ComputeAPI() - - @property - def mc(self): - if self._mc is None: - self._mc = cache_utils.get_client(CONF.consoleauth.token_ttl) - return self._mc - - @property - def mc_instance(self): - if self._mc_instance is None: - self._mc_instance = cache_utils.get_client() - return self._mc_instance - - def reset(self): - LOG.info('Reloading compute RPC API') - compute_rpcapi.LAST_VERSION = None - self.compute_rpcapi = compute_rpcapi.ComputeAPI() - - def _get_tokens_for_instance(self, instance_uuid): - tokens_str = self.mc_instance.get(instance_uuid.encode('UTF-8')) - if not tokens_str: - tokens = [] - else: - tokens = jsonutils.loads(tokens_str) - return tokens - - def authorize_console(self, context, token, console_type, host, port, - internal_access_path, instance_uuid, - access_url=None): - - token_dict = {'token': token, - 'instance_uuid': instance_uuid, - 'console_type': console_type, - 'host': host, - 'port': port, - 'internal_access_path': internal_access_path, - 'access_url': access_url, - 'last_activity_at': time.time()} - data = jsonutils.dumps(token_dict) - - self.mc.set(token.encode('UTF-8'), data) - tokens = self._get_tokens_for_instance(instance_uuid) - - # Remove the expired tokens from cache. - token_values = self.mc.get_multi( - [tok.encode('UTF-8') for tok in tokens]) - tokens = [name for name, value in zip(tokens, token_values) - if value is not None] - tokens.append(token) - - self.mc_instance.set(instance_uuid.encode('UTF-8'), - jsonutils.dumps(tokens)) - - LOG.info("Received Token: %(token)s, %(token_dict)s", - {'token': token, 'token_dict': token_dict}) - - def _validate_token(self, context, token): - instance_uuid = token['instance_uuid'] - if instance_uuid is None: - return False - - mapping = objects.InstanceMapping.get_by_instance_uuid(context, - instance_uuid) - with nova_context.target_cell(context, mapping.cell_mapping) as cctxt: - instance = objects.Instance.get_by_uuid(cctxt, instance_uuid) - - return self.compute_rpcapi.validate_console_port( - cctxt, - instance, - token['port'], - token['console_type']) - - def check_token(self, context, token): - token_str = self.mc.get(token.encode('UTF-8')) - token_valid = (token_str is not None) - LOG.info("Checking Token: %(token)s, %(token_valid)s", - {'token': token, 'token_valid': token_valid}) - if token_valid: - token = jsonutils.loads(token_str) - if self._validate_token(context, token): - return token - - def delete_tokens_for_instance(self, context, instance_uuid): - tokens = self._get_tokens_for_instance(instance_uuid) - if tokens: - self.mc.delete_multi( - [tok.encode('UTF-8') for tok in tokens]) - self.mc_instance.delete(instance_uuid.encode('UTF-8')) diff --git a/nova/consoleauth/rpcapi.py b/nova/consoleauth/rpcapi.py deleted file mode 100644 index d9b424deebd5..000000000000 --- a/nova/consoleauth/rpcapi.py +++ /dev/null @@ -1,103 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Client side of the consoleauth RPC API. -""" - -import oslo_messaging as messaging - -import nova.conf -from nova import profiler -from nova import rpc - -CONF = nova.conf.CONF -RPC_TOPIC = 'consoleauth' - - -@profiler.trace_cls("rpc") -class ConsoleAuthAPI(object): - '''Client side of the consoleauth rpc API. - - API version history: - - * 1.0 - Initial version. - * 1.1 - Added get_backdoor_port() - * 1.2 - Added instance_uuid to authorize_console, and - delete_tokens_for_instance - - ... Grizzly and Havana support message version 1.2. 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 1.2. - - * 2.0 - Major API rev for Icehouse - - ... 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 - - ... Kilo, Liberty, Mitaka, Newton, and Ocata support message version - 2.1. 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.1. - - ''' - - VERSION_ALIASES = { - 'grizzly': '1.2', - 'havana': '1.2', - 'icehouse': '2.0', - 'juno': '2.0', - 'kilo': '2.1', - 'liberty': '2.1', - 'mitaka': '2.1', - 'newton': '2.1', - 'ocata': '2.1', - } - - def __init__(self): - super(ConsoleAuthAPI, self).__init__() - target = messaging.Target(topic=RPC_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, - access_url): - # The remote side doesn't return anything, but we want to block - # until it completes.' - 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() - return cctxt.call(ctxt, 'check_token', token=token) - - def delete_tokens_for_instance(self, ctxt, instance_uuid): - cctxt = self.client.prepare() - return cctxt.cast(ctxt, - 'delete_tokens_for_instance', - instance_uuid=instance_uuid) diff --git a/nova/objects/fields.py b/nova/objects/fields.py index 041ba64fef19..c543026f2b15 100644 --- a/nova/objects/fields.py +++ b/nova/objects/fields.py @@ -765,6 +765,8 @@ class NotificationSource(BaseNovaEnum): CONDUCTOR = 'nova-conductor' SCHEDULER = 'nova-scheduler' NETWORK = 'nova-network' + # TODO(stephenfin): Remove 'CONSOLEAUTH' when 'NotificationPublisher' is + # updated to version 3.0 CONSOLEAUTH = 'nova-consoleauth' # TODO(stephenfin): Remove when 'NotificationPublisher' object version is # bumped to 3.0 diff --git a/nova/service.py b/nova/service.py index 3fbdc0f90bc5..7aa62b3ead97 100644 --- a/nova/service.py +++ b/nova/service.py @@ -55,7 +55,6 @@ CONF = nova.conf.CONF SERVICE_MANAGERS = { 'nova-compute': 'nova.compute.manager.ComputeManager', 'nova-console': 'nova.console.manager.ConsoleProxyManager', - 'nova-consoleauth': 'nova.consoleauth.manager.ConsoleAuthManager', 'nova-conductor': 'nova.conductor.manager.ConductorManager', 'nova-metadata': 'nova.api.manager.MetadataManager', 'nova-scheduler': 'nova.scheduler.manager.SchedulerManager', diff --git a/nova/tests/unit/api/openstack/compute/test_console_auth_tokens.py b/nova/tests/unit/api/openstack/compute/test_console_auth_tokens.py index f68f588c71cd..429096d51d97 100644 --- a/nova/tests/unit/api/openstack/compute/test_console_auth_tokens.py +++ b/nova/tests/unit/api/openstack/compute/test_console_auth_tokens.py @@ -15,21 +15,18 @@ import copy -import ddt import mock import webob from nova.api.openstack import api_version_request from nova.api.openstack.compute import console_auth_tokens \ as console_auth_tokens_v21 -from nova.consoleauth import rpcapi as consoleauth_rpcapi from nova import exception from nova import objects from nova import test from nova.tests.unit.api.openstack import fakes -@ddt.ddt class ConsoleAuthTokensExtensionTestV21(test.NoDBTestCase): controller_class = console_auth_tokens_v21 @@ -52,86 +49,35 @@ class ConsoleAuthTokensExtensionTestV21(test.NoDBTestCase): self.req = fakes.HTTPRequest.blank('', use_admin_context=True) self.context = self.req.environ['nova.context'] - @ddt.data(True, False) @mock.patch('nova.objects.ConsoleAuthToken.validate', return_value=objects.ConsoleAuthToken( instance_uuid=fakes.FAKE_UUID, host='fake_host', port='1234', internal_access_path='fake_access_path', console_type='rdp-html5', token=fakes.FAKE_UUID)) - @mock.patch.object(consoleauth_rpcapi.ConsoleAuthAPI, 'check_token', - return_value={ - 'instance_uuid': fakes.FAKE_UUID, - 'host': 'fake_host', - 'port': '1234', - 'internal_access_path': 'fake_access_path', - 'console_type': 'rdp-html5'}) - def test_get_console_connect_info(self, enable_consoleauth, - mock_check_token, mock_validate): - self.flags(enable_consoleauth=enable_consoleauth, group='workarounds') + def test_get_console_connect_info(self, mock_validate): output = self.controller.show(self.req, fakes.FAKE_UUID) - if enable_consoleauth: - self.assertEqual(self._EXPECTED_OUTPUT, output) - mock_check_token.assert_called_once_with(self.context, - fakes.FAKE_UUID) - mock_validate.assert_not_called() - else: - self.assertEqual(self._EXPECTED_OUTPUT_DB, output) - mock_validate.assert_called_once_with(self.context, - fakes.FAKE_UUID) - mock_check_token.assert_not_called() + self.assertEqual(self._EXPECTED_OUTPUT_DB, output) + mock_validate.assert_called_once_with(self.context, fakes.FAKE_UUID) - @ddt.data(True, False) @mock.patch('nova.objects.ConsoleAuthToken.validate', side_effect=exception.InvalidToken(token='***')) - @mock.patch.object(consoleauth_rpcapi.ConsoleAuthAPI, 'check_token', - return_value=None) - def test_get_console_connect_info_token_not_found(self, enable_consoleauth, - mock_check_token, - mock_validate): - self.flags(enable_consoleauth=enable_consoleauth, group='workarounds') + def test_get_console_connect_info_token_not_found(self, mock_validate): self.assertRaises(webob.exc.HTTPNotFound, self.controller.show, self.req, fakes.FAKE_UUID) - if enable_consoleauth: - mock_check_token.assert_called_once_with(self.context, - fakes.FAKE_UUID) - mock_validate.assert_not_called() - else: - mock_validate.assert_called_once_with(self.context, - fakes.FAKE_UUID) - mock_check_token.assert_not_called() + mock_validate.assert_called_once_with(self.context, fakes.FAKE_UUID) - @ddt.data(True, False) @mock.patch('nova.objects.ConsoleAuthToken.validate', return_value=objects.ConsoleAuthToken( instance_uuid=fakes.FAKE_UUID, host='fake_host', port='1234', internal_access_path='fake_access_path', console_type='unauthorized_console_type', token=fakes.FAKE_UUID)) - @mock.patch.object(consoleauth_rpcapi.ConsoleAuthAPI, 'check_token', - return_value={ - 'instance_uuid': fakes.FAKE_UUID, - 'host': 'fake_host', - 'port': '1234', - 'internal_access_path': 'fake_access_path', - 'console_type': 'unauthorized_console_type'}) - def test_get_console_connect_info_nonrdp_console_type(self, - enable_consoleauth, - mock_check_token, - mock_validate): - self.flags(enable_consoleauth=enable_consoleauth, group='workarounds') + def test_get_console_connect_info_nonrdp_console_type(self, mock_validate): self.assertRaises(webob.exc.HTTPUnauthorized, self.controller.show, self.req, fakes.FAKE_UUID) - if enable_consoleauth: - mock_check_token.assert_called_once_with(self.context, - fakes.FAKE_UUID) - mock_validate.assert_not_called() - else: - mock_validate.assert_called_once_with(self.context, - fakes.FAKE_UUID) - mock_check_token.assert_not_called() + mock_validate.assert_called_once_with(self.context, fakes.FAKE_UUID) -@ddt.ddt class ConsoleAuthTokensExtensionTestV231(ConsoleAuthTokensExtensionTestV21): def setUp(self): @@ -139,30 +85,13 @@ class ConsoleAuthTokensExtensionTestV231(ConsoleAuthTokensExtensionTestV21): self.req.api_version_request = api_version_request.APIVersionRequest( '2.31') - @ddt.data(True, False) - @mock.patch('nova.objects.ConsoleAuthToken.validate') - @mock.patch.object(consoleauth_rpcapi.ConsoleAuthAPI, 'check_token') - def test_get_console_connect_info_nonrdp_console_type(self, - enable_consoleauth, - mock_check, - mock_validate): - self.flags(enable_consoleauth=enable_consoleauth, group='workarounds') - mock_validate.return_value = objects.ConsoleAuthToken( - instance_uuid=fakes.FAKE_UUID, host='fake_host', port='1234', - internal_access_path='fake_access_path', console_type='webmks', - token=fakes.FAKE_UUID) - mock_check.return_value = {'instance_uuid': fakes.FAKE_UUID, - 'host': 'fake_host', - 'port': '1234', - 'internal_access_path': 'fake_access_path', - 'console_type': 'webmks'} + @mock.patch('nova.objects.ConsoleAuthToken.validate', + return_value = objects.ConsoleAuthToken( + instance_uuid=fakes.FAKE_UUID, host='fake_host', + port='1234', internal_access_path='fake_access_path', + console_type='webmks', + token=fakes.FAKE_UUID)) + def test_get_console_connect_info_nonrdp_console_type(self, mock_validate): output = self.controller.show(self.req, fakes.FAKE_UUID) - if enable_consoleauth: - self.assertEqual(self._EXPECTED_OUTPUT, output) - mock_check.assert_called_once_with(self.context, fakes.FAKE_UUID) - mock_validate.assert_not_called() - else: - self.assertEqual(self._EXPECTED_OUTPUT_DB, output) - mock_validate.assert_called_once_with(self.context, - fakes.FAKE_UUID) - mock_check.assert_not_called() + self.assertEqual(self._EXPECTED_OUTPUT_DB, output) + mock_validate.assert_called_once_with(self.context, fakes.FAKE_UUID) diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py index a86b7f7e2d5a..5768c081b9f5 100644 --- a/nova/tests/unit/compute/test_compute.py +++ b/nova/tests/unit/compute/test_compute.py @@ -10157,12 +10157,8 @@ class ComputeAPITestCase(BaseTestCase): self.assertRaises(exception.InvalidVolume, self.compute_api.rescue, self.context, instance) - @ddt.data(True, False) @mock.patch.object(compute_rpcapi.ComputeAPI, 'get_vnc_console') - @mock.patch.object(compute.consoleauth_rpcapi.ConsoleAuthAPI, - 'authorize_console') - def test_vnc_console(self, enable_consoleauth, mock_auth, mock_get): - self.flags(enable_consoleauth=enable_consoleauth, group='workarounds') + def test_vnc_console(self, mock_get): # Make sure we can a vnc console for an instance. fake_instance = self._fake_instance( @@ -10185,14 +10181,6 @@ class ComputeAPITestCase(BaseTestCase): mock_get.assert_called_once_with( self.context, instance=fake_instance, console_type=fake_console_type) - if enable_consoleauth: - mock_auth.assert_called_once_with( - self.context, 'fake_token', fake_console_type, - 'fake_console_host', 'fake_console_port', 'fake_access_path', - 'f3000000-0000-0000-0000-000000000000', - access_url='fake_console_url') - else: - mock_auth.assert_not_called() def test_get_vnc_console_no_host(self): instance = self._create_fake_instance_obj(params={'host': ''}) @@ -10201,12 +10189,8 @@ class ComputeAPITestCase(BaseTestCase): self.compute_api.get_vnc_console, self.context, instance, 'novnc') - @ddt.data(True, False) - @mock.patch.object(compute.consoleauth_rpcapi.ConsoleAuthAPI, - 'authorize_console') @mock.patch.object(compute_rpcapi.ComputeAPI, 'get_spice_console') - def test_spice_console(self, enable_consoleauth, mock_spice, mock_auth): - self.flags(enable_consoleauth=enable_consoleauth, group='workarounds') + def test_spice_console(self, mock_spice): # Make sure we can a spice console for an instance. fake_instance = self._fake_instance( @@ -10229,14 +10213,6 @@ class ComputeAPITestCase(BaseTestCase): mock_spice.assert_called_once_with(self.context, instance=fake_instance, console_type=fake_console_type) - if enable_consoleauth: - mock_auth.assert_called_once_with( - self.context, 'fake_token', fake_console_type, - 'fake_console_host', 'fake_console_port', 'fake_access_path', - 'f3000000-0000-0000-0000-000000000000', - access_url='fake_console_url') - else: - mock_auth.assert_not_called() def test_get_spice_console_no_host(self): instance = self._create_fake_instance_obj(params={'host': ''}) @@ -10264,12 +10240,8 @@ class ComputeAPITestCase(BaseTestCase): getattr(self.compute_api, 'get_%s_console' % console_type), self.context, instance, console_type) - @ddt.data(True, False) - @mock.patch.object(compute.consoleauth_rpcapi.ConsoleAuthAPI, - 'authorize_console') @mock.patch.object(compute_rpcapi.ComputeAPI, 'get_rdp_console') - def test_rdp_console(self, enable_consoleauth, mock_rdp, mock_auth): - self.flags(enable_consoleauth=enable_consoleauth, group='workarounds') + def test_rdp_console(self, mock_rdp): # Make sure we can a rdp console for an instance. fake_instance = self._fake_instance({ 'uuid': 'f3000000-0000-0000-0000-000000000000', @@ -10290,14 +10262,6 @@ class ComputeAPITestCase(BaseTestCase): self.assertEqual(console, {'url': 'fake_console_url'}) mock_rdp.assert_called_once_with(self.context, instance=fake_instance, console_type=fake_console_type) - if enable_consoleauth: - mock_auth.assert_called_once_with( - self.context, 'fake_token', fake_console_type, - 'fake_console_host', 'fake_console_port', 'fake_access_path', - 'f3000000-0000-0000-0000-000000000000', - access_url='fake_console_url') - else: - mock_auth.assert_not_called() def test_get_rdp_console_no_host(self): instance = self._create_fake_instance_obj(params={'host': ''}) @@ -10321,21 +10285,8 @@ class ComputeAPITestCase(BaseTestCase): 'instance_uuid': fake_instance.uuid, 'access_url': 'fake_access_url'} - rpcapi = compute_rpcapi.ComputeAPI - - with test.nested( - mock.patch.object(rpcapi, 'get_serial_console', - return_value=fake_connect_info), - mock.patch.object(self.compute_api.consoleauth_rpcapi, - 'authorize_console') - ) as (mock_get_serial_console, mock_authorize_console): - self.compute_api.consoleauth_rpcapi.authorize_console( - self.context, 'fake_token', fake_console_type, - 'fake_serial_host', 'fake_tcp_port', - 'fake_access_path', - 'f3000000-0000-0000-0000-000000000000', - access_url='fake_access_url') - + with mock.patch.object(self.compute_api.compute_rpcapi, + 'get_serial_console', return_value=fake_connect_info): console = self.compute_api.get_serial_console(self.context, fake_instance, fake_console_type) @@ -10362,13 +10313,8 @@ class ComputeAPITestCase(BaseTestCase): 'instance_uuid': fake_instance.uuid, 'access_url': 'fake_access_url'} - with test.nested( - mock.patch.object(self.compute_api.compute_rpcapi, - 'get_mks_console', - return_value=fake_connect_info), - mock.patch.object(self.compute_api.consoleauth_rpcapi, - 'authorize_console') - ) as (mock_get_mks_console, mock_authorize_console): + with mock.patch.object(self.compute_api.compute_rpcapi, + 'get_mks_console', return_value=fake_connect_info): console = self.compute_api.get_mks_console(self.context, fake_instance, fake_console_type) @@ -11433,17 +11379,14 @@ class ComputeAPITestCase(BaseTestCase): instance, instance_uuid = self._run_instance() rpcapi = self.compute_api.compute_task_api - consoleauth_rpcapi = self.compute_api.consoleauth_rpcapi fake_spec = objects.RequestSpec() - @mock.patch.object(consoleauth_rpcapi, 'delete_tokens_for_instance') @mock.patch.object(rpcapi, 'live_migrate_instance') @mock.patch.object(objects.ComputeNodeList, 'get_all_by_host') @mock.patch.object(objects.RequestSpec, 'get_by_instance_uuid') @mock.patch.object(self.compute_api, '_record_action_start') def do_test(record_action_start, get_by_instance_uuid, - get_all_by_host, live_migrate_instance, - delete_tokens_for_instance): + get_all_by_host, live_migrate_instance): get_by_instance_uuid.return_value = fake_spec get_all_by_host.return_value = objects.ComputeNodeList( objects=[objects.ComputeNode( @@ -11468,12 +11411,6 @@ class ComputeAPITestCase(BaseTestCase): disk_over_commit=True, request_spec=fake_spec, async_=False) - if CONF.workarounds.enable_consoleauth: - delete_tokens_for_instance.assert_called_once_with( - self.context, instance.uuid) - else: - delete_tokens_for_instance.assert_not_called() - do_test() instance.refresh() self.assertEqual(instance['task_state'], task_states.MIGRATING) @@ -11484,19 +11421,13 @@ class ComputeAPITestCase(BaseTestCase): self.assertEqual('fake_dest_host', req_dest.host) self.assertEqual('fake_dest_node', req_dest.node) - @ddt.data(True, False) - def test_live_migrate(self, enable_consoleauth): - self.flags(enable_consoleauth=enable_consoleauth, group='workarounds') + def test_live_migrate(self): self._test_live_migrate() - @ddt.data(True, False) - def test_live_migrate_with_not_forced_host(self, enable_consoleauth): - self.flags(enable_consoleauth=enable_consoleauth, group='workarounds') + def test_live_migrate_with_not_forced_host(self): self._test_live_migrate(force=False) - @ddt.data(True, False) - def test_live_migrate_with_forced_host(self, enable_consoleauth): - self.flags(enable_consoleauth=enable_consoleauth, group='workarounds') + def test_live_migrate_with_forced_host(self): self._test_live_migrate(force=True) def test_fail_live_migrate_with_non_existing_destination(self): diff --git a/nova/tests/unit/compute/test_compute_api.py b/nova/tests/unit/compute/test_compute_api.py index 6c3ad5e544c4..215f86abc4c9 100644 --- a/nova/tests/unit/compute/test_compute_api.py +++ b/nova/tests/unit/compute/test_compute_api.py @@ -37,7 +37,6 @@ from nova.compute import utils as compute_utils from nova.compute import vm_states from nova import conductor import nova.conf -from nova.consoleauth import rpcapi as consoleauth_rpcapi from nova import context from nova.db import api as db from nova import exception @@ -992,8 +991,6 @@ class _ComputeAPIUnitTestMixIn(object): @mock.patch.object(image_api.API, 'delete') @mock.patch.object(objects.InstanceMapping, 'save') @mock.patch.object(objects.InstanceMapping, 'get_by_instance_uuid') - @mock.patch.object(consoleauth_rpcapi.ConsoleAuthAPI, - 'delete_tokens_for_instance') @mock.patch.object(compute_utils, 'notify_about_instance_usage') @mock.patch.object(db, 'instance_destroy') @@ -1010,7 +1007,7 @@ class _ComputeAPIUnitTestMixIn(object): def _test_delete(self, delete_type, mock_save, mock_bdm_get, mock_elevated, mock_get_cn, mock_up, mock_record, mock_inst_update, mock_deallocate, mock_inst_meta, mock_inst_destroy, - mock_notify_legacy, mock_del_token, mock_get_inst, + mock_notify_legacy, mock_get_inst, mock_save_im, mock_image_delete, mock_mig_get, mock_notify, **attrs): expected_save_calls = [mock.call()] @@ -1175,11 +1172,6 @@ class _ComputeAPIUnitTestMixIn(object): mock_terminate.assert_called_once_with( self.context, inst, []) - if CONF.workarounds.enable_consoleauth: - mock_del_token.assert_called_once_with(self.context, instance_uuid) - else: - mock_del_token.assert_not_called() - if is_shelved: mock_image_delete.assert_called_once_with(self.context, snapshot_id) @@ -1204,9 +1196,7 @@ class _ComputeAPIUnitTestMixIn(object): task_state=task_states.RESIZE_FINISH, old_flavor=old_flavor) - @ddt.data(True, False) - def test_delete_in_resized(self, enable_consoleauth): - self.flags(enable_consoleauth=enable_consoleauth, group='workarounds') + def test_delete_in_resized(self): self._test_delete('delete', vm_state=vm_states.RESIZED) def test_delete_shelved(self): @@ -1215,9 +1205,7 @@ class _ComputeAPIUnitTestMixIn(object): vm_state=vm_states.SHELVED, system_metadata=fake_sys_meta) - @ddt.data(True, False) - def test_delete_shelved_offloaded(self, enable_consoleauth): - self.flags(enable_consoleauth=enable_consoleauth, group='workarounds') + def test_delete_shelved_offloaded(self): fake_sys_meta = {'shelved_image_id': SHELVED_IMAGE} self._test_delete('delete', vm_state=vm_states.SHELVED_OFFLOADED, @@ -1235,9 +1223,7 @@ class _ComputeAPIUnitTestMixIn(object): vm_state=vm_states.SHELVED_OFFLOADED, system_metadata=fake_sys_meta) - @ddt.data(True, False) - def test_delete_shelved_exception(self, enable_consoleauth): - self.flags(enable_consoleauth=enable_consoleauth, group='workarounds') + def test_delete_shelved_exception(self): fake_sys_meta = {'shelved_image_id': SHELVED_IMAGE_EXCEPTION} self._test_delete('delete', vm_state=vm_states.SHELVED, @@ -1252,9 +1238,7 @@ class _ComputeAPIUnitTestMixIn(object): def test_delete_soft_in_resized(self): self._test_delete('soft_delete', vm_state=vm_states.RESIZED) - @ddt.data(True, False) - def test_delete_soft(self, enable_consoleauth): - self.flags(enable_consoleauth=enable_consoleauth, group='workarounds') + def test_delete_soft(self): self._test_delete('soft_delete') def test_delete_forced(self): diff --git a/nova/tests/unit/console/test_websocketproxy.py b/nova/tests/unit/console/test_websocketproxy.py index 9faa5e02291c..e2f1fd8eef4d 100644 --- a/nova/tests/unit/console/test_websocketproxy.py +++ b/nova/tests/unit/console/test_websocketproxy.py @@ -66,10 +66,9 @@ class NovaProxyRequestHandlerDBTestCase(test.TestCase): @mock.patch('nova.objects.ConsoleAuthToken.validate') @mock.patch('nova.objects.Instance.get_by_uuid') @mock.patch('nova.compute.rpcapi.ComputeAPI.validate_console_port') - @mock.patch('nova.consoleauth.rpcapi.ConsoleAuthAPI.check_token') def test_new_websocket_client_db( - self, mock_ca_check, mock_validate_port, mock_inst_get, - mock_validate, internal_access_path=None, + self, mock_validate_port, mock_inst_get, mock_validate, + internal_access_path=None, instance_not_found=False): db_obj = self._fake_console_db( @@ -113,7 +112,6 @@ class NovaProxyRequestHandlerDBTestCase(test.TestCase): mock_validate_port.assert_called_once_with( ctxt, mock_inst_get.return_value, str(db_obj['port']), db_obj['console_type']) - mock_ca_check.assert_not_called() self.wh.socket.assert_called_with('node1', 10000, connect=True) @@ -201,60 +199,6 @@ class NovaProxyRequestHandlerBaseTestCase(test.NoDBTestCase): 'Host': 'example.net:6080', } - @mock.patch('nova.consoleauth.rpcapi.ConsoleAuthAPI.check_token') - def test_new_websocket_client_enable_consoleauth(self, check_token): - self.flags(enable_consoleauth=True, group='workarounds') - - check_token.return_value = { - 'host': 'node1', - 'port': '10000', - 'console_type': 'novnc', - 'access_url': 'https://example.net:6080' - } - self.wh.socket.return_value = '' - self.wh.path = "http://127.0.0.1/?%s" % self.path - self.wh.headers = self.fake_header - - self.wh.new_websocket_client() - - check_token.assert_called_with(mock.ANY, token="123-456-789") - self.wh.socket.assert_called_with('node1', 10000, connect=True) - self.wh.do_proxy.assert_called_with('') - - @mock.patch('nova.consoleauth.rpcapi.ConsoleAuthAPI.check_token', - return_value=None) - @mock.patch('nova.console.websocketproxy.NovaProxyRequestHandlerBase.' - '_check_console_port') - @mock.patch('nova.objects.ConsoleAuthToken.validate') - def test_new_websocket_client_enable_consoleauth_fallback(self, validate, - check_port, - check_token): - # Since consoleauth is enabled, it should be called first before - # falling back to the database. - self.flags(enable_consoleauth=True, group='workarounds') - - params = { - 'id': 1, - 'token': '123-456-789', - 'instance_uuid': uuids.instance, - 'host': 'node1', - 'port': '10000', - 'console_type': 'novnc', - 'access_url_base': 'https://example.net:6080' - } - validate.return_value = objects.ConsoleAuthToken(**params) - - self.wh.socket.return_value = '' - self.wh.path = "http://127.0.0.1/?%s" % self.path - self.wh.headers = self.fake_header - - self.wh.new_websocket_client() - - check_token.assert_called_with(mock.ANY, token="123-456-789") - validate.assert_called_with(mock.ANY, "123-456-789") - self.wh.socket.assert_called_with('node1', 10000, connect=True) - self.wh.do_proxy.assert_called_with('') - @mock.patch('nova.console.websocketproxy.NovaProxyRequestHandlerBase.' '_check_console_port') @mock.patch('nova.objects.ConsoleAuthToken.validate') @@ -441,23 +385,6 @@ class NovaProxyRequestHandlerBaseTestCase(test.NoDBTestCase): self.wh.socket.assert_called_with('node1', 10000, connect=True) self.wh.do_proxy.assert_called_with('') - @mock.patch.object(websocketproxy, 'sys') - @mock.patch('nova.consoleauth.rpcapi.ConsoleAuthAPI.check_token') - def test_new_websocket_client_py273_special_scheme( - self, check_token, mock_sys): - mock_sys.version_info = (2, 7, 3) - check_token.return_value = { - 'host': 'node1', - 'port': '10000', - 'console_type': 'novnc' - } - self.wh.socket.return_value = '' - self.wh.path = "ws://127.0.0.1/?%s" % self.path - self.wh.headers = self.fake_header - - self.assertRaises(exception.NovaException, - self.wh.new_websocket_client) - @mock.patch('socket.getfqdn') def test_address_string_doesnt_do_reverse_dns_lookup(self, getfqdn): request_mock = mock.MagicMock() diff --git a/nova/tests/unit/consoleauth/__init__.py b/nova/tests/unit/consoleauth/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/nova/tests/unit/consoleauth/test_consoleauth.py b/nova/tests/unit/consoleauth/test_consoleauth.py deleted file mode 100644 index 911ba1f747bc..000000000000 --- a/nova/tests/unit/consoleauth/test_consoleauth.py +++ /dev/null @@ -1,240 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -""" -Tests for Consoleauth Code. - -""" - -import mock -from oslo_utils.fixture import uuidsentinel as uuids -from oslo_utils import timeutils -import six - -from nova.consoleauth import manager -from nova import context -from nova import objects -from nova import test - - -class ConsoleauthTestCase(test.NoDBTestCase): - """Test Case for consoleauth.""" - - rpcapi = 'nova.compute.rpcapi.ComputeAPI.' - - def setUp(self): - super(ConsoleauthTestCase, self).setUp() - self.manager_api = self.manager = manager.ConsoleAuthManager() - self.context = context.get_admin_context() - self.instance_uuid = '00000000-0000-0000-0000-000000000000' - self.is_cells = False - - def test_reset(self): - with mock.patch('nova.compute.rpcapi.ComputeAPI') as mock_rpc: - old_rpcapi = self.manager_api.compute_rpcapi - self.manager_api.reset() - mock_rpc.assert_called_once_with() - self.assertNotEqual(old_rpcapi, - self.manager_api.compute_rpcapi) - - @mock.patch('nova.objects.instance.Instance.get_by_uuid') - def test_tokens_expire(self, mock_get): - mock_get.return_value = None - # NOTE(danms): Get the faked InstanceMapping from the SingleCellSimple - # fixture so we can return it from our own mock to verify - # that it was called - fake_im = objects.InstanceMapping.get_by_instance_uuid(self.context, - uuids.instance) - - # Test that tokens expire correctly. - self.useFixture(test.TimeOverride()) - token = u'mytok' - self.flags(token_ttl=1, group='consoleauth') - - self._stub_validate_console_port(True) - - self.manager_api.authorize_console(self.context, token, 'novnc', - '127.0.0.1', '8080', 'host', - self.instance_uuid) - with mock.patch('nova.objects.InstanceMapping.' - 'get_by_instance_uuid') as mock_get: - mock_get.return_value = fake_im - self.assertIsNotNone(self.manager_api.check_token(self.context, - token)) - timeutils.advance_time_seconds(1) - self.assertIsNone(self.manager_api.check_token(self.context, - token)) - if not self.is_cells: - mock_get.assert_called_once_with(self.context, - self.instance_uuid) - - def _stub_validate_console_port(self, result): - def fake_validate_console_port(self, ctxt, instance, - port, console_type): - return result - - self.stub_out(self.rpcapi + 'validate_console_port', - fake_validate_console_port) - - @mock.patch('nova.objects.instance.Instance.get_by_uuid') - def test_multiple_tokens_for_instance(self, mock_get): - mock_get.return_value = None - - tokens = [u"token" + str(i) for i in range(10)] - - self._stub_validate_console_port(True) - - for token in tokens: - self.manager_api.authorize_console(self.context, token, 'novnc', - '127.0.0.1', '8080', 'host', - self.instance_uuid) - - for token in tokens: - self.assertIsNotNone( - self.manager_api.check_token(self.context, token)) - - def test_delete_tokens_for_instance(self): - tokens = [u"token" + str(i) for i in range(10)] - for token in tokens: - self.manager_api.authorize_console(self.context, token, 'novnc', - '127.0.0.1', '8080', 'host', - self.instance_uuid) - self.manager_api.delete_tokens_for_instance(self.context, - self.instance_uuid) - stored_tokens = self.manager._get_tokens_for_instance( - self.instance_uuid) - - self.assertEqual(len(stored_tokens), 0) - - for token in tokens: - self.assertIsNone( - self.manager_api.check_token(self.context, token)) - - def test_delete_tokens_for_instance_no_tokens(self): - with test.nested( - mock.patch.object(self.manager, '_get_tokens_for_instance', - return_value=[]), - mock.patch.object(self.manager.mc, 'delete_multi'), - mock.patch.object(self.manager.mc_instance, 'delete') - ) as ( - mock_get_tokens, mock_delete_multi, mock_delete - ): - self.manager.delete_tokens_for_instance( - self.context, self.instance_uuid) - # Since here were no tokens, we didn't try to clear anything - # from the cache. - mock_delete_multi.assert_not_called() - mock_delete.assert_called_once_with( - self.instance_uuid.encode('UTF-8')) - - @mock.patch('nova.objects.instance.Instance.get_by_uuid') - def test_wrong_token_has_port(self, mock_get): - mock_get.return_value = None - - token = u'mytok' - - self._stub_validate_console_port(False) - - self.manager_api.authorize_console(self.context, token, 'novnc', - '127.0.0.1', '8080', 'host', - instance_uuid=self.instance_uuid) - self.assertIsNone(self.manager_api.check_token(self.context, token)) - - def test_delete_expired_tokens(self): - self.useFixture(test.TimeOverride()) - token = u'mytok' - self.flags(token_ttl=1, group='consoleauth') - - self._stub_validate_console_port(True) - - self.manager_api.authorize_console(self.context, token, 'novnc', - '127.0.0.1', '8080', 'host', - self.instance_uuid) - timeutils.advance_time_seconds(1) - self.assertIsNone(self.manager_api.check_token(self.context, token)) - - token1 = u'mytok2' - self.manager_api.authorize_console(self.context, token1, 'novnc', - '127.0.0.1', '8080', 'host', - self.instance_uuid) - stored_tokens = self.manager._get_tokens_for_instance( - self.instance_uuid) - # when trying to store token1, expired token is removed fist. - self.assertEqual(len(stored_tokens), 1) - self.assertEqual(stored_tokens[0], token1) - - -class ControlauthMemcacheEncodingTestCase(test.NoDBTestCase): - def setUp(self): - super(ControlauthMemcacheEncodingTestCase, self).setUp() - self.manager = manager.ConsoleAuthManager() - self.context = context.get_admin_context() - self.u_token = u"token" - self.u_instance = u"instance" - - def test_authorize_console_encoding(self): - with test.nested( - mock.patch.object(self.manager.mc_instance, - 'set', return_value=None), - mock.patch.object(self.manager.mc_instance, - 'get', return_value='["token"]'), - mock.patch.object(self.manager.mc, - 'set', return_value=None), - mock.patch.object(self.manager.mc, - 'get', return_value=None), - mock.patch.object(self.manager.mc, - 'get_multi', return_value=["token1"]), - ) as ( - mock_instance_set, - mock_instance_get, - mock_set, - mock_get, - mock_get_multi): - self.manager.authorize_console(self.context, self.u_token, - 'novnc', '127.0.0.1', '8080', - 'host', self.u_instance) - mock_set.assert_has_calls([mock.call(b'token', mock.ANY)]) - mock_instance_get.assert_has_calls([mock.call(b'instance')]) - mock_get_multi.assert_has_calls([mock.call([b'token'])]) - mock_instance_set.assert_has_calls( - [mock.call(b'instance', mock.ANY)]) - - def test_check_token_encoding(self): - with mock.patch.object(self.manager.mc, - "get", - return_value=None) as mock_get: - self.manager.check_token(self.context, self.u_token) - mock_get.assert_called_once_with(test.MatchType(six.binary_type)) - - def test_delete_tokens_for_instance_encoding(self): - with test.nested( - mock.patch.object(self.manager.mc_instance, - 'get', return_value='["token"]'), - mock.patch.object(self.manager.mc_instance, - 'delete', return_value=True), - mock.patch.object(self.manager.mc, - 'get'), - mock.patch.object(self.manager.mc, - 'delete_multi', return_value=True), - ) as ( - mock_instance_get, - mock_instance_delete, - mock_get, - mock_delete_multi): - self.manager.delete_tokens_for_instance(self.context, - self.u_instance) - mock_instance_get.assert_has_calls([mock.call(b'instance')]) - mock_instance_delete.assert_has_calls([mock.call(b'instance')]) - mock_delete_multi.assert_has_calls([mock.call([b'token'])]) diff --git a/nova/tests/unit/consoleauth/test_rpcapi.py b/nova/tests/unit/consoleauth/test_rpcapi.py deleted file mode 100644 index 759c2b4e9d16..000000000000 --- a/nova/tests/unit/consoleauth/test_rpcapi.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Unit Tests for nova.consoleauth.rpcapi -""" - -import mock - -from nova.consoleauth import rpcapi as consoleauth_rpcapi -from nova import context -from nova import test - - -class ConsoleAuthRpcAPITestCase(test.NoDBTestCase): - DROPPED_ARG = object() - - def _test_consoleauth_api(self, method, **kwargs): - do_cast = kwargs.pop('_do_cast', False) - - ctxt = context.RequestContext('fake_user', 'fake_project') - - rpcapi = consoleauth_rpcapi.ConsoleAuthAPI() - self.assertIsNotNone(rpcapi.client) - self.assertEqual(rpcapi.client.target.topic, - consoleauth_rpcapi.RPC_TOPIC) - - orig_prepare = rpcapi.client.prepare - - version = kwargs.pop('version', None) - rpc_kwargs = {k: v for k, v in kwargs.items() - if v is not self.DROPPED_ARG} - - with test.nested( - mock.patch.object(rpcapi.client, 'cast' if do_cast else 'call'), - mock.patch.object(rpcapi.client, 'prepare'), - mock.patch.object(rpcapi.client, 'can_send_version'), - ) as ( - rpc_mock, prepare_mock, csv_mock - ): - prepare_mock.return_value = rpcapi.client - rpc_mock.return_value = None if do_cast else 'foo' - - 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) - - 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", - 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') - - def test_delete_tokens_for_instnace(self): - self._test_consoleauth_api('delete_tokens_for_instance', - _do_cast=True, - instance_uuid="instance") diff --git a/nova/tests/unit/test_profiler.py b/nova/tests/unit/test_profiler.py index b93e1c02c061..8550010e0e12 100644 --- a/nova/tests/unit/test_profiler.py +++ b/nova/tests/unit/test_profiler.py @@ -57,8 +57,6 @@ class TestProfiler(test.NoDBTestCase): 'nova.conductor.rpcapi.ConductorAPI', 'nova.console.manager.ConsoleProxyManager', 'nova.console.rpcapi.ConsoleAPI', - 'nova.consoleauth.manager.ConsoleAuthManager', - 'nova.consoleauth.rpcapi.ConsoleAuthAPI', 'nova.image.api.API', 'nova.network.api.API', 'nova.network.manager.FlatDHCPManager', diff --git a/releasenotes/notes/remove-nova-consoleauth-b7c61e50649206ea.yaml b/releasenotes/notes/remove-nova-consoleauth-b7c61e50649206ea.yaml new file mode 100644 index 000000000000..ba60f7ffa39f --- /dev/null +++ b/releasenotes/notes/remove-nova-consoleauth-b7c61e50649206ea.yaml @@ -0,0 +1,9 @@ +--- +upgrade: + - | + The ``nova-consoleauth`` service has been deprecated since the 18.0.0 + Rocky release and has now been removed. The following configuration + options have been removed: + + * ``[upgrade_levels] consoleauth`` + * ``[workarounds] enable_consoleauth`` diff --git a/setup.cfg b/setup.cfg index 0cac6300af1e..ff4549fefce7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -59,7 +59,6 @@ console_scripts = nova-compute = nova.cmd.compute:main nova-conductor = nova.cmd.conductor:main nova-console = nova.cmd.console:main - nova-consoleauth = nova.cmd.consoleauth:main nova-dhcpbridge = nova.cmd.dhcpbridge:main nova-manage = nova.cmd.manage:main nova-network = nova.cmd.network:main