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 <sfinucan@redhat.com>
This commit is contained in:
parent
3062a1199d
commit
6537a537f9
@ -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
|
||||
|
@ -87,5 +87,4 @@ deployments, but are documented for existing ones.
|
||||
|
||||
nova-dhcpbridge
|
||||
nova-network
|
||||
nova-console
|
||||
nova-xvpvncproxy
|
||||
|
@ -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 <https://bugs.launchpad.net/nova>`__
|
@ -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'),
|
||||
|
@ -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
|
||||
|
@ -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()
|
@ -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):
|
||||
|
@ -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(
|
||||
|
@ -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'.
|
||||
|
@ -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)
|
@ -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
|
@ -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)
|
@ -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)
|
||||
|
||||
##################
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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'
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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')
|
@ -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')
|
@ -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()
|
||||
|
@ -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',
|
||||
|
@ -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``
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user