From 6537a537f9efccf078783a0c9646d9e36fd30d65 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 10 Oct 2019 12:55:11 +0100 Subject: [PATCH] Remove 'nova-console' service, 'console' RPC API This legacy service was only compatible with the XenServer driver and has effectively been replaced by the noVNC console proxy service. Remove the service. The API that provided remote access to this service, 'os-consoles', was removed in a previous change. Note that 'os-remote-consoles' is unrelated and therefore is not removed, though it will now reject requests for XVP VNC consoles. This was previously discussed and agreed on openstack-dev [1] and openstack-discuss [1]. Part of blueprint remove-xvpvncproxy [1] http://lists.openstack.org/pipermail/openstack-dev/2018-October/135413.html [2] http://lists.openstack.org/pipermail/openstack-discuss/2019-April/005369.html Change-Id: Ib1ff32f04b16af7981471f67c8e0bf04e6ecb6be Signed-off-by: Stephen Finucane --- doc/source/_extra/.htaccess | 1 - doc/source/cli/index.rst | 1 - doc/source/cli/nova-console.rst | 54 ---- doc/source/conf.py | 1 - doc/test/redirect-tests.txt | 1 - nova/cmd/console.py | 51 ---- nova/compute/manager.py | 4 +- nova/compute/rpcapi.py | 1 + nova/conf/upgrade_levels.py | 12 - nova/console/api.py | 56 ---- nova/console/manager.py | 115 -------- nova/console/rpcapi.py | 77 ----- nova/db/api.py | 41 +-- nova/db/sqlalchemy/api.py | 99 ------- nova/db/sqlalchemy/models.py | 1 + nova/exception.py | 25 -- nova/objects/fields.py | 2 + nova/service.py | 1 - nova/tests/unit/console/test_console.py | 199 ------------- nova/tests/unit/console/test_rpcapi.py | 61 ---- nova/tests/unit/db/test_db_api.py | 263 +----------------- nova/tests/unit/test_profiler.py | 2 - .../remove-nova-console-5a2b86210a43e7c8.yaml | 10 +- setup.cfg | 1 - 24 files changed, 16 insertions(+), 1063 deletions(-) delete mode 100644 doc/source/cli/nova-console.rst delete mode 100644 nova/cmd/console.py delete mode 100644 nova/console/api.py delete mode 100644 nova/console/manager.py delete mode 100644 nova/console/rpcapi.py delete mode 100644 nova/tests/unit/console/test_console.py delete mode 100644 nova/tests/unit/console/test_rpcapi.py diff --git a/doc/source/_extra/.htaccess b/doc/source/_extra/.htaccess index de6f615321..02f6eb3730 100644 --- a/doc/source/_extra/.htaccess +++ b/doc/source/_extra/.htaccess @@ -31,7 +31,6 @@ redirectmatch 301 ^/nova/([^/]+)/man/nova-cells.html$ /nova/$1/cli/nova-cells.ht # this is gone and never coming back, indicate that to the end users redirectmatch 301 ^/nova/([^/]+)/man/nova-compute.html$ /nova/$1/cli/nova-compute.html redirectmatch 301 ^/nova/([^/]+)/man/nova-conductor.html$ /nova/$1/cli/nova-conductor.html -redirectmatch 301 ^/nova/([^/]+)/man/nova-console.html$ /nova/$1/cli/nova-console.html redirectmatch 301 ^/nova/([^/]+)/man/nova-dhcpbridge.html$ /nova/$1/cli/nova-dhcpbridge.html redirectmatch 301 ^/nova/([^/]+)/man/nova-manage.html$ /nova/$1/cli/nova-manage.html redirectmatch 301 ^/nova/([^/]+)/man/nova-network.html$ /nova/$1/cli/nova-network.html diff --git a/doc/source/cli/index.rst b/doc/source/cli/index.rst index 7aae96aae5..1ce869fb22 100644 --- a/doc/source/cli/index.rst +++ b/doc/source/cli/index.rst @@ -87,5 +87,4 @@ deployments, but are documented for existing ones. nova-dhcpbridge nova-network - nova-console nova-xvpvncproxy diff --git a/doc/source/cli/nova-console.rst b/doc/source/cli/nova-console.rst deleted file mode 100644 index e7e752ad39..0000000000 --- a/doc/source/cli/nova-console.rst +++ /dev/null @@ -1,54 +0,0 @@ -============ -nova-console -============ - -------------------- -Nova Console Server -------------------- - -:Author: openstack@lists.openstack.org -:Copyright: OpenStack Foundation -:Manual section: 1 -:Manual group: cloud computing - -Synopsis -======== - -:: - - nova-console [options] - -Description -=========== - -:program:`nova-console` is a server daemon that serves the Nova Console -service, which is a console proxy to set up multi-tenant VM console access, -e.g. with *XVP*. - -.. deprecated:: 19.0.0 - - :program:`nova-console` is deprecated since 19.0.0 (Stein) and will be - removed in an upcoming release. - -Options -======= - -**General options** - -Files -===== - -* ``/etc/nova/nova.conf`` -* ``/etc/nova/policy.json`` -* ``/etc/nova/rootwrap.conf`` -* ``/etc/nova/rootwrap.d/`` - -See Also -======== - -* :nova-doc:`OpenStack Nova <>` - -Bugs -==== - -* Nova bugs are managed at `Launchpad `__ diff --git a/doc/source/conf.py b/doc/source/conf.py index cd96c37cb2..775509aa6b 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -86,7 +86,6 @@ _man_pages = [ ('nova-api-os-compute', u'Cloud controller fabric'), ('nova-compute', u'Cloud controller fabric'), ('nova-conductor', u'Cloud controller fabric'), - ('nova-console', u'Cloud controller fabric'), ('nova-dhcpbridge', u'Cloud controller fabric'), ('nova-manage', u'Cloud controller fabric'), ('nova-network', u'Cloud controller fabric'), diff --git a/doc/test/redirect-tests.txt b/doc/test/redirect-tests.txt index 71c51ff43c..c1d706d1a8 100644 --- a/doc/test/redirect-tests.txt +++ b/doc/test/redirect-tests.txt @@ -31,7 +31,6 @@ /nova/latest/man/nova-cells.html 301 /nova/latest/cli/nova-cells.html /nova/latest/man/nova-compute.html 301 /nova/latest/cli/nova-compute.html /nova/latest/man/nova-conductor.html 301 /nova/latest/cli/nova-conductor.html -/nova/latest/man/nova-console.html 301 /nova/latest/cli/nova-console.html /nova/latest/man/nova-dhcpbridge.html 301 /nova/latest/cli/nova-dhcpbridge.html /nova/latest/man/nova-manage.html 301 /nova/latest/cli/nova-manage.html /nova/latest/man/nova-network.html 301 /nova/latest/cli/nova-network.html diff --git a/nova/cmd/console.py b/nova/cmd/console.py deleted file mode 100644 index b5736b83d1..0000000000 --- a/nova/cmd/console.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (c) 2010 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. - -"""Starter script for Nova Console Proxy.""" - -import sys - -from oslo_config import cfg -from oslo_log import log as logging -from oslo_reports import guru_meditation_report as gmr -from oslo_reports import opts as gmr_opts - -from nova import config -from nova.console import rpcapi as console_rpcapi -from nova import objects -from nova import service -from nova import version - -CONF = cfg.CONF -LOG = logging.getLogger('nova.console') - - -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-console service is deprecated as it is Xen ' - 'specific, does not function properly in a multi-cell ' - 'environment, and has effectively been replaced by noVNC ' - 'and the nova-novncproxy service.') - - server = service.Service.create(binary='nova-console', - topic=console_rpcapi.RPC_TOPIC) - service.serve(server) - service.wait() diff --git a/nova/compute/manager.py b/nova/compute/manager.py index a7b2f483cd..1b65cbb0bd 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -69,7 +69,6 @@ from nova.compute.utils import wrap_instance_event from nova.compute import vm_states from nova import conductor import nova.conf -from nova.console import rpcapi as console_rpcapi import nova.context from nova import exception from nova import exception_wrapper @@ -1504,6 +1503,7 @@ class ComputeManager(manager.Manager): except exception.InstanceNotFound: return power_state.NOSTATE + # TODO(stephenfin): Remove this once we bump the compute API to v6.0 def get_console_topic(self, context): """Retrieves the console host for a project on this host. @@ -1511,7 +1511,7 @@ class ComputeManager(manager.Manager): """ # TODO(mdragon): perhaps make this variable by console_type? - return '%s.%s' % (console_rpcapi.RPC_TOPIC, CONF.console_host) + return 'console.%s' % CONF.console_host @wrap_exception() def get_console_pool_info(self, context, console_type): diff --git a/nova/compute/rpcapi.py b/nova/compute/rpcapi.py index b2445daa44..75c3b804e6 100644 --- a/nova/compute/rpcapi.py +++ b/nova/compute/rpcapi.py @@ -709,6 +709,7 @@ class ComputeAPI(object): return cctxt.call(ctxt, 'get_console_pool_info', console_type=console_type) + # TODO(stephenfin): This is no longer used and can be removed in v6.0 def get_console_topic(self, ctxt, host): version = '5.0' cctxt = self.router.client(ctxt).prepare( diff --git a/nova/conf/upgrade_levels.py b/nova/conf/upgrade_levels.py index 07dc5fe84a..19cc5e23b3 100644 --- a/nova/conf/upgrade_levels.py +++ b/nova/conf/upgrade_levels.py @@ -96,18 +96,6 @@ Conductor 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('console', - help=""" -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'. diff --git a/nova/console/api.py b/nova/console/api.py deleted file mode 100644 index e5204d9bb4..0000000000 --- a/nova/console/api.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (c) 2010 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. - -"""Handles ConsoleProxy API requests.""" - - -from nova.compute import rpcapi as compute_rpcapi -from nova.console import rpcapi as console_rpcapi -from nova.db import base -from nova import objects - - -class API(base.Base): - """API for spinning up or down console proxy connections.""" - def get_consoles(self, context, instance_uuid): - return self.db.console_get_all_by_instance(context, instance_uuid, - columns_to_join=['pool']) - - def get_console(self, context, instance_uuid, console_uuid): - return self.db.console_get(context, console_uuid, instance_uuid) - - def delete_console(self, context, instance_uuid, console_uuid): - console = self.db.console_get(context, console_uuid, instance_uuid) - rpcapi = console_rpcapi.ConsoleAPI(topic=console_rpcapi.RPC_TOPIC, - server=console['pool']['host']) - rpcapi.remove_console(context, console['id']) - - def create_console(self, context, instance_uuid): - # NOTE(mdragon): If we wanted to return this the console info - # here, as we would need to do a call. - # They can just do an index later to fetch - # console info. I am not sure which is better - # here. - instance = objects.Instance.get_by_uuid(context, instance_uuid) - topic = self._get_console_topic(context, instance.host) - server = None - if '.' in topic: - topic, server = topic.split('.', 1) - rpcapi = console_rpcapi.ConsoleAPI(topic=topic, server=server) - rpcapi.add_console(context, instance.id) - - def _get_console_topic(self, context, instance_host): - rpcapi = compute_rpcapi.ComputeAPI() - return rpcapi.get_console_topic(context, instance_host) diff --git a/nova/console/manager.py b/nova/console/manager.py deleted file mode 100644 index a67abf4c88..0000000000 --- a/nova/console/manager.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright (c) 2010 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. - -"""Console Proxy Service.""" - -from oslo_log import log as logging -import oslo_messaging as messaging - -from nova.compute import rpcapi as compute_rpcapi -import nova.conf -from nova.console import xvp -from nova import exception -from nova import manager -from nova import objects -from nova import utils - - -CONF = nova.conf.CONF -LOG = logging.getLogger(__name__) - - -class ConsoleProxyManager(manager.Manager): - """Sets up and tears down any console proxy connections. - - Needed for accessing instance consoles securely. - - """ - - target = messaging.Target(version='2.0') - - def __init__(self, *args, **kwargs): - self.driver = xvp.XVPConsoleProxy() - super(ConsoleProxyManager, self).__init__(service_name='console', - *args, **kwargs) - self.driver.host = self.host - self.compute_rpcapi = compute_rpcapi.ComputeAPI() - - def reset(self): - LOG.info('Reloading compute RPC API') - compute_rpcapi.LAST_VERSION = None - self.compute_rpcapi = compute_rpcapi.ComputeAPI() - - def init_host(self): - self.driver.init_host() - - def add_console(self, context, instance_id): - instance = objects.Instance.get_by_id(context, instance_id) - host = instance.host - name = instance.name - pool = self._get_pool_for_instance_host(context, host) - try: - console = self.db.console_get_by_pool_instance(context, - pool['id'], - instance.uuid) - except exception.NotFound: - LOG.debug('Adding console', instance=instance) - password = utils.generate_password(8) - port = self.driver.get_port(context) - console_data = {'instance_name': name, - 'instance_uuid': instance.uuid, - 'password': password, - 'pool_id': pool['id']} - if port: - console_data['port'] = port - console = self.db.console_create(context, console_data) - self.driver.setup_console(context, console) - - return console['id'] - - def remove_console(self, context, console_id): - try: - console = self.db.console_get(context, console_id) - except exception.NotFound: - LOG.debug('Tried to remove non-existent console ' - '%(console_id)s.', - {'console_id': console_id}) - return - self.db.console_delete(context, console_id) - self.driver.teardown_console(context, console) - - def _get_pool_for_instance_host(self, context, instance_host): - context = context.elevated() - console_type = self.driver.console_type - try: - pool = self.db.console_pool_get_by_host_type(context, - instance_host, - self.host, - console_type) - except exception.NotFound: - # NOTE(mdragon): Right now, the only place this info exists is the - # compute worker's flagfile, at least for - # xenserver. Thus we need to ask. - pool_info = self.compute_rpcapi.get_console_pool_info(context, - instance_host, console_type) - pool_info['password'] = self.driver.fix_pool_password( - pool_info['password']) - pool_info['host'] = self.host - pool_info['public_hostname'] = \ - CONF.xenserver.console_public_hostname - pool_info['console_type'] = self.driver.console_type - pool_info['compute_host'] = instance_host - pool = self.db.console_pool_create(context, pool_info) - return pool diff --git a/nova/console/rpcapi.py b/nova/console/rpcapi.py deleted file mode 100644 index e1765561f3..0000000000 --- a/nova/console/rpcapi.py +++ /dev/null @@ -1,77 +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 console RPC API. -""" - -import oslo_messaging as messaging - -import nova.conf -from nova import profiler -from nova import rpc - -CONF = nova.conf.CONF -RPC_TOPIC = "console" - - -@profiler.trace_cls("rpc") -class ConsoleAPI(object): - '''Client side of the console rpc API. - - API version history: - - 1.0 - Initial version. - 1.1 - Added get_backdoor_port() - - ... Grizzly and Havana support message version 1.1. So, any changes to - existing methods in 1.x after that point should be done such that they - can handle the version_cap being set to 1.1. - - 2.0 - Major API rev for Icehouse - - ... Icehouse, Juno, Kilo, Liberty, Mitaka, Newton, and Ocata 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. - - ''' - - VERSION_ALIASES = { - 'grizzly': '1.1', - 'havana': '1.1', - 'icehouse': '2.0', - 'juno': '2.0', - 'kilo': '2.0', - 'liberty': '2.0', - 'mitaka': '2.0', - 'newton': '2.0', - 'ocata': '2.0', - } - - def __init__(self, topic=None, server=None): - super(ConsoleAPI, self).__init__() - topic = topic if topic else RPC_TOPIC - target = messaging.Target(topic=topic, server=server, version='2.0') - version_cap = self.VERSION_ALIASES.get(CONF.upgrade_levels.console, - CONF.upgrade_levels.console) - self.client = rpc.get_client(target, version_cap=version_cap) - - def add_console(self, ctxt, instance_id): - cctxt = self.client.prepare() - cctxt.cast(ctxt, 'add_console', instance_id=instance_id) - - def remove_console(self, ctxt, console_id): - cctxt = self.client.prepare() - cctxt.cast(ctxt, 'remove_console', console_id=console_id) diff --git a/nova/db/api.py b/nova/db/api.py index 5828970b49..c9b6da6bdf 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -1413,21 +1413,7 @@ def project_get_networks(context, project_id, associate=True): return IMPL.project_get_networks(context, project_id, associate) -################### - - -def console_pool_create(context, values): - """Create console pool.""" - return IMPL.console_pool_create(context, values) - - -def console_pool_get_by_host_type(context, compute_host, proxy_host, - console_type): - """Fetch a console pool for a given proxy host, compute host, and type.""" - return IMPL.console_pool_get_by_host_type(context, - compute_host, - proxy_host, - console_type) +################## def console_pool_get_all_by_host_type(context, host, console_type): @@ -1437,31 +1423,6 @@ def console_pool_get_all_by_host_type(context, host, console_type): console_type) -def console_create(context, values): - """Create a console.""" - return IMPL.console_create(context, values) - - -def console_delete(context, console_id): - """Delete a console.""" - return IMPL.console_delete(context, console_id) - - -def console_get_by_pool_instance(context, pool_id, instance_uuid): - """Get console entry for a given instance and pool.""" - return IMPL.console_get_by_pool_instance(context, pool_id, instance_uuid) - - -def console_get_all_by_instance(context, instance_uuid, columns_to_join=None): - """Get consoles for a given instance.""" - return IMPL.console_get_all_by_instance(context, instance_uuid, - columns_to_join) - - -def console_get(context, console_id, instance_uuid=None): - """Get a specific console (possibly on a given instance).""" - return IMPL.console_get(context, console_id, instance_uuid) - ################## diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index af39e9e234..1191f2e5e2 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -4487,40 +4487,6 @@ def migration_migrate_to_uuid(context, count): ################## -@pick_context_manager_writer -def console_pool_create(context, values): - pool = models.ConsolePool() - pool.update(values) - try: - pool.save(context.session) - except db_exc.DBDuplicateEntry: - raise exception.ConsolePoolExists( - host=values["host"], - console_type=values["console_type"], - compute_host=values["compute_host"], - ) - return pool - - -@pick_context_manager_reader -def console_pool_get_by_host_type(context, compute_host, host, - console_type): - - result = model_query(context, models.ConsolePool, read_deleted="no").\ - filter_by(host=host).\ - filter_by(console_type=console_type).\ - filter_by(compute_host=compute_host).\ - options(joinedload('consoles')).\ - first() - - if not result: - raise exception.ConsolePoolNotFoundForHostType( - host=host, console_type=console_type, - compute_host=compute_host) - - return result - - @pick_context_manager_reader def console_pool_get_all_by_host_type(context, host, console_type): return model_query(context, models.ConsolePool, read_deleted="no").\ @@ -4530,71 +4496,6 @@ def console_pool_get_all_by_host_type(context, host, console_type): all() -################## - - -@pick_context_manager_writer -def console_create(context, values): - console = models.Console() - console.update(values) - console.save(context.session) - return console - - -@pick_context_manager_writer -def console_delete(context, console_id): - # NOTE(mdragon): consoles are meant to be transient. - context.session.query(models.Console).\ - filter_by(id=console_id).\ - delete() - - -@pick_context_manager_reader -def console_get_by_pool_instance(context, pool_id, instance_uuid): - result = model_query(context, models.Console, read_deleted="yes").\ - filter_by(pool_id=pool_id).\ - filter_by(instance_uuid=instance_uuid).\ - options(joinedload('pool')).\ - first() - - if not result: - raise exception.ConsoleNotFoundInPoolForInstance( - pool_id=pool_id, instance_uuid=instance_uuid) - - return result - - -@pick_context_manager_reader -def console_get_all_by_instance(context, instance_uuid, columns_to_join=None): - query = model_query(context, models.Console, read_deleted="yes").\ - filter_by(instance_uuid=instance_uuid) - if columns_to_join: - for column in columns_to_join: - query = query.options(joinedload(column)) - return query.all() - - -@pick_context_manager_reader -def console_get(context, console_id, instance_uuid=None): - query = model_query(context, models.Console, read_deleted="yes").\ - filter_by(id=console_id).\ - options(joinedload('pool')) - - if instance_uuid is not None: - query = query.filter_by(instance_uuid=instance_uuid) - - result = query.first() - - if not result: - if instance_uuid: - raise exception.ConsoleNotFoundForInstance( - instance_uuid=instance_uuid) - else: - raise exception.ConsoleNotFound(console_id=console_id) - - return result - - ######################## # User-provided metadata diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index fcfad5d7a3..5fef1a8372 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -1001,6 +1001,7 @@ class ConsolePool(BASE, NovaBase, models.SoftDeleteMixin): compute_host = Column(String(255)) +# TODO(stephenfin): Remove in V or later class Console(BASE, NovaBase, models.SoftDeleteMixin): """Represents a console session for an instance.""" __tablename__ = 'consoles' diff --git a/nova/exception.py b/nova/exception.py index 11fca3f285..6da5c0544d 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -1203,35 +1203,10 @@ class ConsoleLogOutputException(NovaException): "%(instance_id)s. Reason: %(reason)s") -class ConsolePoolExists(NovaException): - msg_fmt = _("Console pool with host %(host)s, console_type " - "%(console_type)s and compute_host %(compute_host)s " - "already exists.") - - -class ConsolePoolNotFoundForHostType(NotFound): - msg_fmt = _("Console pool of type %(console_type)s " - "for compute host %(compute_host)s " - "on proxy host %(host)s not found.") - - -class ConsoleNotFound(NotFound): - msg_fmt = _("Console %(console_id)s could not be found.") - - -class ConsoleNotFoundForInstance(ConsoleNotFound): - msg_fmt = _("Console for instance %(instance_uuid)s could not be found.") - - class ConsoleNotAvailable(NotFound): msg_fmt = _("Guest does not have a console available.") -class ConsoleNotFoundInPoolForInstance(ConsoleNotFound): - msg_fmt = _("Console for instance %(instance_uuid)s " - "in pool %(pool_id)s could not be found.") - - class ConsoleTypeInvalid(Invalid): msg_fmt = _("Invalid console type %(console_type)s") diff --git a/nova/objects/fields.py b/nova/objects/fields.py index 9a44dd42f9..05074bad8c 100644 --- a/nova/objects/fields.py +++ b/nova/objects/fields.py @@ -796,6 +796,8 @@ class NotificationSource(BaseNovaEnum): # TODO(stephenfin): Remove when 'NotificationPublisher' object version is # bumped to 3.0 CELLS = 'nova-cells' + # TODO(stephenfin): Remove when 'NotificationPublisher' object version is + # bumped to 3.0 CONSOLE = 'nova-console' METADATA = 'nova-metadata' diff --git a/nova/service.py b/nova/service.py index 7aa62b3ead..24aa733289 100644 --- a/nova/service.py +++ b/nova/service.py @@ -54,7 +54,6 @@ CONF = nova.conf.CONF SERVICE_MANAGERS = { 'nova-compute': 'nova.compute.manager.ComputeManager', - 'nova-console': 'nova.console.manager.ConsoleProxyManager', 'nova-conductor': 'nova.conductor.manager.ConductorManager', 'nova-metadata': 'nova.api.manager.MetadataManager', 'nova-scheduler': 'nova.scheduler.manager.SchedulerManager', diff --git a/nova/tests/unit/console/test_console.py b/nova/tests/unit/console/test_console.py deleted file mode 100644 index c9496e0618..0000000000 --- a/nova/tests/unit/console/test_console.py +++ /dev/null @@ -1,199 +0,0 @@ -# Copyright (c) 2010 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 Console proxy.""" - -import fixtures -import mock - -from nova.compute import rpcapi as compute_rpcapi -from nova.console import api as console_api -from nova.console import manager as console_manager -from nova import context -from nova.db import api as db -from nova import exception -from nova import objects -from nova import test -from nova.tests.unit import fake_instance -from nova.tests.unit import fake_xvp_console_proxy - - -class ConsoleTestCase(test.TestCase): - """Test case for console proxy manager.""" - def setUp(self): - super(ConsoleTestCase, self).setUp() - self.useFixture(fixtures.MonkeyPatch( - 'nova.console.manager.xvp.XVPConsoleProxy', - fake_xvp_console_proxy.FakeConsoleProxy)) - self.console = console_manager.ConsoleProxyManager() - self.user_id = 'fake' - self.project_id = 'fake' - self.context = context.RequestContext(self.user_id, self.project_id) - self.host = 'test_compute_host' - self.pool_info = {'address': '127.0.0.1', - 'username': 'test', - 'password': '1234pass'} - - def test_reset(self): - with mock.patch('nova.compute.rpcapi.ComputeAPI') as mock_rpc: - old_rpcapi = self.console.compute_rpcapi - self.console.reset() - mock_rpc.assert_called_once_with() - self.assertNotEqual(old_rpcapi, - self.console.compute_rpcapi) - - def _create_instance(self): - """Create a test instance.""" - inst = {} - inst['image_id'] = 1 - inst['reservation_id'] = 'r-fakeres' - inst['user_id'] = self.user_id - inst['project_id'] = self.project_id - inst['instance_type_id'] = 1 - inst['ami_launch_index'] = 0 - return fake_instance.fake_instance_obj(self.context, **inst) - - @mock.patch.object(compute_rpcapi.ComputeAPI, 'get_console_pool_info') - def test_get_pool_for_instance_host(self, mock_get): - mock_get.return_value = self.pool_info - pool = self.console._get_pool_for_instance_host(self.context, - self.host) - self.assertEqual(pool['compute_host'], self.host) - - @mock.patch.object(compute_rpcapi.ComputeAPI, 'get_console_pool_info') - def test_get_pool_creates_new_pool_if_needed(self, mock_get): - mock_get.return_value = self.pool_info - self.assertRaises(exception.NotFound, - db.console_pool_get_by_host_type, - self.context, - self.host, - self.console.host, - self.console.driver.console_type) - pool = self.console._get_pool_for_instance_host(self.context, - self.host) - pool2 = db.console_pool_get_by_host_type(self.context, - self.host, - self.console.host, - self.console.driver.console_type) - self.assertEqual(pool['id'], pool2['id']) - - def test_get_pool_does_not_create_new_pool_if_exists(self): - pool_info = {'address': '127.0.0.1', - 'username': 'test', - 'password': '1234pass', - 'host': self.console.host, - 'console_type': self.console.driver.console_type, - 'compute_host': 'sometesthostname'} - new_pool = db.console_pool_create(self.context, pool_info) - pool = self.console._get_pool_for_instance_host(self.context, - 'sometesthostname') - self.assertEqual(pool['id'], new_pool['id']) - - @mock.patch.object(compute_rpcapi.ComputeAPI, 'get_console_pool_info') - @mock.patch('nova.objects.instance.Instance.get_by_id') - def test_add_console(self, mock_id, mock_get): - mock_get.return_value = self.pool_info - - instance = self._create_instance() - mock_id.return_value = instance - self.console.add_console(self.context, instance.id) - pool = db.console_pool_get_by_host_type(self.context, - instance.host, self.console.host, - self.console.driver.console_type) - - console_instances = [con['instance_uuid'] for con in pool['consoles']] - self.assertIn(instance.uuid, console_instances) - - @mock.patch.object(compute_rpcapi.ComputeAPI, 'get_console_pool_info') - @mock.patch('nova.objects.instance.Instance.get_by_id') - def test_add_console_does_not_duplicate(self, mock_id, mock_get): - mock_get.return_value = self.pool_info - - instance = self._create_instance() - mock_id.return_value = instance - cons1 = self.console.add_console(self.context, instance.id) - cons2 = self.console.add_console(self.context, instance.id) - self.assertEqual(cons1, cons2) - - @mock.patch.object(compute_rpcapi.ComputeAPI, 'get_console_pool_info') - @mock.patch('nova.objects.instance.Instance.get_by_id') - def test_remove_console(self, mock_id, mock_get): - mock_get.return_value = self.pool_info - - instance = self._create_instance() - mock_id.return_value = instance - console_id = self.console.add_console(self.context, instance.id) - self.console.remove_console(self.context, console_id) - - self.assertRaises(exception.NotFound, - db.console_get, - self.context, - console_id) - - -class ConsoleAPITestCase(test.NoDBTestCase): - """Test case for console API.""" - def setUp(self): - super(ConsoleAPITestCase, self).setUp() - - self.context = context.RequestContext('fake', 'fake') - self.console_api = console_api.API() - self.fake_uuid = '00000000-aaaa-bbbb-cccc-000000000000' - self.fake_instance = { - 'id': 1, - 'uuid': self.fake_uuid, - 'host': 'fake_host' - } - self.fake_console = { - 'pool': {'host': 'fake_host'}, - 'id': 'fake_id' - } - - def _fake_db_console_get(_ctxt, _console_uuid, _instance_uuid): - return self.fake_console - self.stub_out('nova.db.api.console_get', _fake_db_console_get) - - def _fake_db_console_get_all_by_instance(_ctxt, _instance_uuid, - columns_to_join): - return [self.fake_console] - self.stub_out('nova.db.api.console_get_all_by_instance', - _fake_db_console_get_all_by_instance) - - def test_get_consoles(self): - console = self.console_api.get_consoles(self.context, self.fake_uuid) - self.assertEqual(console, [self.fake_console]) - - def test_get_console(self): - console = self.console_api.get_console(self.context, self.fake_uuid, - 'fake_id') - self.assertEqual(console, self.fake_console) - - @mock.patch('nova.console.rpcapi.ConsoleAPI.remove_console') - def test_delete_console(self, mock_remove): - self.console_api.delete_console(self.context, self.fake_uuid, - 'fake_id') - mock_remove.assert_called_once_with(self.context, 'fake_id') - - @mock.patch.object(compute_rpcapi.ComputeAPI, 'get_console_topic', - return_value='compute.fake_host') - @mock.patch.object(objects.Instance, 'get_by_uuid') - def test_create_console(self, mock_get_instance_by_uuid, - mock_get_console_topic): - mock_get_instance_by_uuid.return_value = objects.Instance( - **self.fake_instance) - self.console_api.create_console(self.context, self.fake_uuid) - mock_get_console_topic.assert_called_once_with(self.context, - 'fake_host') diff --git a/nova/tests/unit/console/test_rpcapi.py b/nova/tests/unit/console/test_rpcapi.py deleted file mode 100644 index 34650a4795..0000000000 --- a/nova/tests/unit/console/test_rpcapi.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2012, 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.console.rpcapi -""" - -import mock - -from nova.console import rpcapi as console_rpcapi -from nova import context -from nova import test - - -class ConsoleRpcAPITestCase(test.NoDBTestCase): - def _test_console_api(self, method, rpc_method, **kwargs): - ctxt = context.RequestContext('fake_user', 'fake_project') - - rpcapi = console_rpcapi.ConsoleAPI() - self.assertIsNotNone(rpcapi.client) - self.assertEqual(rpcapi.client.target.topic, - console_rpcapi.RPC_TOPIC) - - orig_prepare = rpcapi.client.prepare - - with test.nested( - mock.patch.object(rpcapi.client, rpc_method), - 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 = 'foo' if rpc_method == 'call' else None - csv_mock.side_effect = ( - lambda v: orig_prepare().can_send_version()) - - 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) - - def test_add_console(self): - self._test_console_api('add_console', instance_id='i', - rpc_method='cast') - - def test_remove_console(self): - self._test_console_api('remove_console', console_id='i', - rpc_method='cast') diff --git a/nova/tests/unit/db/test_db_api.py b/nova/tests/unit/db/test_db_api.py index 3ae6b6c832..bd5e2825a6 100644 --- a/nova/tests/unit/db/test_db_api.py +++ b/nova/tests/unit/db/test_db_api.py @@ -3210,25 +3210,6 @@ class InstanceTestCase(test.TestCase, ModelsObjectComparatorMixin): db.virtual_interface_create(ctxt, {'instance_uuid': uuid}) - pool_values = { - 'address': '192.168.10.10', - 'username': 'user1', - 'password': 'passwd1', - 'console_type': 'type1', - 'public_hostname': 'public_host1', - 'host': 'host1', - 'compute_host': 'compute_host1', - } - console_pool = db.console_pool_create(ctxt, pool_values) - console_values = { - 'instance_name': instance['name'], - 'instance_uuid': uuid, - 'password': 'pass', - 'port': 7878, - 'pool_id': console_pool['id'] - } - db.console_create(self.ctxt, console_values) - # Hard delete the instance db.instance_destroy(ctxt, uuid, hard_delete=True) @@ -3260,10 +3241,7 @@ class InstanceTestCase(test.TestCase, ModelsObjectComparatorMixin): _assert_instance_id_mapping(ctxt, self, uuid) self.assertRaises(exception.InstanceNotFound, db.instance_destroy, ctxt, uuid) - # NOTE(ttsiouts): Should these also be valid? - # instance_consoles = db.console_get_all_by_instance(ctxt, uuid) - # self.assertEqual(0, len(instance_consoles)) - # Also FixedIp has the instance_uuid as a foreign key + # NOTE(ttsiouts): FixedIp has the instance_uuid as a foreign key def test_check_instance_exists(self): instance = self.create_instance_with_args() @@ -7916,207 +7894,6 @@ class CertificateTestCase(test.TestCase, ModelsObjectComparatorMixin): self._assertEqualObjects(self.created[1], cert[0]) -class ConsoleTestCase(test.TestCase, ModelsObjectComparatorMixin): - - def setUp(self): - super(ConsoleTestCase, self).setUp() - self.ctxt = context.get_admin_context() - pools_data = [ - {'address': '192.168.10.10', - 'username': 'user1', - 'password': 'passwd1', - 'console_type': 'type1', - 'public_hostname': 'public_host1', - 'host': 'host1', - 'compute_host': 'compute_host1', - }, - {'address': '192.168.10.11', - 'username': 'user2', - 'password': 'passwd2', - 'console_type': 'type2', - 'public_hostname': 'public_host2', - 'host': 'host2', - 'compute_host': 'compute_host2', - }, - ] - self.console_pools = [db.console_pool_create(self.ctxt, val) - for val in pools_data] - instance_uuid = uuidsentinel.uuid1 - db.instance_create(self.ctxt, {'uuid': instance_uuid}) - self.console_data = [{'instance_name': 'name' + str(x), - 'instance_uuid': instance_uuid, - 'password': 'pass' + str(x), - 'port': 7878 + x, - 'pool_id': self.console_pools[x]['id']} - for x in range(len(pools_data))] - self.consoles = [db.console_create(self.ctxt, val) - for val in self.console_data] - - def test_console_create(self): - ignored_keys = ['id', 'deleted', 'deleted_at', 'created_at', - 'updated_at'] - for console in self.consoles: - self.assertIsNotNone(console['id']) - self._assertEqualListsOfObjects(self.console_data, self.consoles, - ignored_keys=ignored_keys) - - def test_console_get_by_id(self): - console = self.consoles[0] - console_get = db.console_get(self.ctxt, console['id']) - self._assertEqualObjects(console, console_get, - ignored_keys=['pool']) - - def test_console_get_by_id_uuid(self): - console = self.consoles[0] - console_get = db.console_get(self.ctxt, console['id'], - console['instance_uuid']) - self._assertEqualObjects(console, console_get, - ignored_keys=['pool']) - - def test_console_get_by_pool_instance(self): - console = self.consoles[0] - console_get = db.console_get_by_pool_instance(self.ctxt, - console['pool_id'], console['instance_uuid']) - self._assertEqualObjects(console, console_get, - ignored_keys=['pool']) - - def test_console_get_all_by_instance(self): - instance_uuid = self.consoles[0]['instance_uuid'] - consoles_get = db.console_get_all_by_instance(self.ctxt, instance_uuid) - self._assertEqualListsOfObjects(self.consoles, consoles_get) - - def test_console_get_all_by_instance_with_pool(self): - instance_uuid = self.consoles[0]['instance_uuid'] - consoles_get = db.console_get_all_by_instance(self.ctxt, instance_uuid, - columns_to_join=['pool']) - self._assertEqualListsOfObjects(self.consoles, consoles_get, - ignored_keys=['pool']) - self._assertEqualListsOfObjects([pool for pool in self.console_pools], - [c['pool'] for c in consoles_get]) - - def test_console_get_all_by_instance_empty(self): - consoles_get = db.console_get_all_by_instance(self.ctxt, - uuidsentinel.uuid2) - self.assertEqual(consoles_get, []) - - def test_console_delete(self): - console_id = self.consoles[0]['id'] - db.console_delete(self.ctxt, console_id) - self.assertRaises(exception.ConsoleNotFound, db.console_get, - self.ctxt, console_id) - - def test_console_get_by_pool_instance_not_found(self): - self.assertRaises(exception.ConsoleNotFoundInPoolForInstance, - db.console_get_by_pool_instance, self.ctxt, - self.consoles[0]['pool_id'], - uuidsentinel.uuid2) - - def test_console_get_not_found(self): - self.assertRaises(exception.ConsoleNotFound, db.console_get, - self.ctxt, 100500) - - def test_console_get_not_found_instance(self): - self.assertRaises(exception.ConsoleNotFoundForInstance, db.console_get, - self.ctxt, self.consoles[0]['id'], - uuidsentinel.uuid2) - - -class ConsolePoolTestCase(test.TestCase, ModelsObjectComparatorMixin): - def setUp(self): - super(ConsolePoolTestCase, self).setUp() - - self.ctxt = context.get_admin_context() - self.test_console_pool_1 = { - 'address': '192.168.2.10', - 'username': 'user_1', - 'password': 'secret_123', - 'console_type': 'type_1', - 'public_hostname': 'public_hostname_123', - 'host': 'localhost', - 'compute_host': '127.0.0.1', - } - self.test_console_pool_2 = { - 'address': '192.168.2.11', - 'username': 'user_2', - 'password': 'secret_1234', - 'console_type': 'type_2', - 'public_hostname': 'public_hostname_1234', - 'host': '127.0.0.1', - 'compute_host': 'localhost', - } - self.test_console_pool_3 = { - 'address': '192.168.2.12', - 'username': 'user_3', - 'password': 'secret_12345', - 'console_type': 'type_2', - 'public_hostname': 'public_hostname_12345', - 'host': '127.0.0.1', - 'compute_host': '192.168.1.1', - } - - def test_console_pool_create(self): - console_pool = db.console_pool_create( - self.ctxt, self.test_console_pool_1) - self.assertIsNotNone(console_pool.get('id')) - ignored_keys = ['deleted', 'created_at', 'updated_at', - 'deleted_at', 'id'] - self._assertEqualObjects( - console_pool, self.test_console_pool_1, ignored_keys) - - def test_console_pool_create_duplicate(self): - db.console_pool_create(self.ctxt, self.test_console_pool_1) - self.assertRaises(exception.ConsolePoolExists, db.console_pool_create, - self.ctxt, self.test_console_pool_1) - - def test_console_pool_get_by_host_type(self): - params = [ - self.test_console_pool_1, - self.test_console_pool_2, - ] - - for p in params: - db.console_pool_create(self.ctxt, p) - - ignored_keys = ['deleted', 'created_at', 'updated_at', - 'deleted_at', 'id', 'consoles'] - - cp = self.test_console_pool_1 - db_cp = db.console_pool_get_by_host_type( - self.ctxt, cp['compute_host'], cp['host'], cp['console_type'] - ) - self._assertEqualObjects(cp, db_cp, ignored_keys) - - def test_console_pool_get_by_host_type_no_resuls(self): - self.assertRaises( - exception.ConsolePoolNotFoundForHostType, - db.console_pool_get_by_host_type, self.ctxt, 'compute_host', - 'host', 'console_type') - - def test_console_pool_get_all_by_host_type(self): - params = [ - self.test_console_pool_1, - self.test_console_pool_2, - self.test_console_pool_3, - ] - for p in params: - db.console_pool_create(self.ctxt, p) - ignored_keys = ['deleted', 'created_at', 'updated_at', - 'deleted_at', 'id', 'consoles'] - - cp = self.test_console_pool_2 - db_cp = db.console_pool_get_all_by_host_type( - self.ctxt, cp['host'], cp['console_type']) - - self._assertEqualListsOfObjects( - db_cp, [self.test_console_pool_2, self.test_console_pool_3], - ignored_keys) - - def test_console_pool_get_all_by_host_type_no_results(self): - res = db.console_pool_get_all_by_host_type( - self.ctxt, 'cp_host', 'cp_console_type') - self.assertEqual([], res) - - class DnsdomainTestCase(test.TestCase): def setUp(self): @@ -8455,9 +8232,6 @@ class ArchiveTestCase(test.TestCase, ModelsObjectComparatorMixin): self.dns_domains = models.DNSDomain.__table__ self.shadow_dns_domains = sqlalchemyutils.get_table( self.engine, "shadow_dns_domains") - self.consoles = models.Console.__table__ - self.shadow_consoles = sqlalchemyutils.get_table( - self.engine, "shadow_consoles") self.console_pools = models.ConsolePool.__table__ self.shadow_console_pools = sqlalchemyutils.get_table( self.engine, "shadow_console_pools") @@ -8813,41 +8587,6 @@ class ArchiveTestCase(test.TestCase, ModelsObjectComparatorMixin): 'sqlite version too old for reliable SQLA foreign_keys') self.conn.execute("PRAGMA foreign_keys = ON") - def test_archive_deleted_rows_fk_constraint(self): - # consoles.pool_id depends on console_pools.id - self._check_sqlite_version_less_than_3_7() - ins_stmt = self.console_pools.insert().values(deleted=1, - deleted_at=timeutils.utcnow()) - result = self.conn.execute(ins_stmt) - id1 = result.inserted_primary_key[0] - ins_stmt = self.consoles.insert().values(deleted=1, - deleted_at=timeutils.utcnow(), - pool_id=id1) - result = self.conn.execute(ins_stmt) - result.inserted_primary_key[0] - # The first try to archive console_pools should fail, due to FK. - num = sqlalchemy_api._archive_deleted_rows_for_table(self.metadata, - "console_pools", - max_rows=None, - before=None) - self.assertEqual(num[0], 0) - # Then archiving consoles should work. - num = sqlalchemy_api._archive_deleted_rows_for_table(self.metadata, - "consoles", - max_rows=None, - before=None) - self.assertEqual(num[0], 1) - # Then archiving console_pools should work. - num = sqlalchemy_api._archive_deleted_rows_for_table(self.metadata, - "console_pools", - max_rows=None, - before=None) - self.assertEqual(num[0], 1) - self._assert_shadow_tables_empty_except( - 'shadow_console_pools', - 'shadow_consoles' - ) - def test_archive_deleted_rows_for_migrations(self): # migrations.instance_uuid depends on instances.uuid self._check_sqlite_version_less_than_3_7() diff --git a/nova/tests/unit/test_profiler.py b/nova/tests/unit/test_profiler.py index 8550010e0e..2cef753b7c 100644 --- a/nova/tests/unit/test_profiler.py +++ b/nova/tests/unit/test_profiler.py @@ -55,8 +55,6 @@ class TestProfiler(test.NoDBTestCase): 'nova.conductor.manager.ConductorManager', 'nova.conductor.rpcapi.ComputeTaskAPI', 'nova.conductor.rpcapi.ConductorAPI', - 'nova.console.manager.ConsoleProxyManager', - 'nova.console.rpcapi.ConsoleAPI', 'nova.image.api.API', 'nova.network.api.API', 'nova.network.manager.FlatDHCPManager', diff --git a/releasenotes/notes/remove-nova-console-5a2b86210a43e7c8.yaml b/releasenotes/notes/remove-nova-console-5a2b86210a43e7c8.yaml index 2249def097..8a31b98a5a 100644 --- a/releasenotes/notes/remove-nova-console-5a2b86210a43e7c8.yaml +++ b/releasenotes/notes/remove-nova-console-5a2b86210a43e7c8.yaml @@ -1,7 +1,13 @@ --- upgrade: - | - The following APIs have been removed. Calling these APIs will + The ``nova-console`` service has been deprecated since the 19.0.0 Stein + release and has now been removed. The following configuration options are + therefore removed. + + * ``[upgrade_levels] console`` + + In addition, the following APIs have been removed. Calling these APIs will now result in a ``410 HTTPGone`` error response: * ``POST /servers/{server_id}/consoles`` @@ -9,7 +15,7 @@ upgrade: * ``GET /servers/{server_id}/consoles/{console_id}`` * ``DELETE /servers/{server_id}/consoles/{console_id}`` - In addition, the following policies are removed. These were related to the + Finally, the following policies are removed. These were related to the removed APIs listed above and no longer had any effect: * ``os_compute_api:os-consoles:index`` diff --git a/setup.cfg b/setup.cfg index 2ec22861e0..db858c746f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -66,7 +66,6 @@ console_scripts = nova-api-os-compute = nova.cmd.api_os_compute:main nova-compute = nova.cmd.compute:main nova-conductor = nova.cmd.conductor:main - nova-console = nova.cmd.console:main nova-dhcpbridge = nova.cmd.dhcpbridge:main nova-manage = nova.cmd.manage:main nova-network = nova.cmd.network:main