Remove 'nova-manage cell' commands
These are no longer necessary with the removal of cells v1. A check for cells v1 in 'nova-manage cell_v2 simple_cell_setup' is also removed, meaning this can no longer return the '2' exit code. Part of blueprint remove-cells-v1 Change-Id: I8c2bfb31224300bc639d5089c4dfb62143d04b7f Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
This commit is contained in:
@@ -184,13 +184,11 @@ Nova Cells v2
|
|||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
``nova-manage cell_v2 simple_cell_setup [--transport-url <transport_url>]``
|
``nova-manage cell_v2 simple_cell_setup [--transport-url <transport_url>]``
|
||||||
Setup a fresh cells v2 environment; this should not be used if you
|
Setup a fresh cells v2 environment. If a ``transport_url`` is not
|
||||||
currently have a cells v1 environment. If a transport_url is not
|
|
||||||
specified, it will use the one defined by ``[DEFAULT]/transport_url``
|
specified, it will use the one defined by ``[DEFAULT]/transport_url``
|
||||||
in the configuration file. Returns 0 if setup is completed
|
in the configuration file. Returns 0 if setup is completed
|
||||||
(or has already been done), 1 if no hosts are reporting (and cannot be
|
(or has already been done), 1 if no hosts are reporting (and cannot be
|
||||||
mapped), 1 if the transport url is missing or invalid, and 2 if run in a
|
mapped) and 1 if the transport url is missing or invalid.
|
||||||
cells v1 environment.
|
|
||||||
|
|
||||||
``nova-manage cell_v2 map_cell0 [--database_connection <database_connection>]``
|
``nova-manage cell_v2 map_cell0 [--database_connection <database_connection>]``
|
||||||
Create a cell mapping to the database connection for the cell0 database.
|
Create a cell mapping to the database connection for the cell0 database.
|
||||||
|
@@ -891,159 +891,6 @@ class ApiDbCommands(object):
|
|||||||
print(migration.db_version(database='api'))
|
print(migration.db_version(database='api'))
|
||||||
|
|
||||||
|
|
||||||
class CellCommands(object):
|
|
||||||
"""Commands for managing cells v1 functionality."""
|
|
||||||
|
|
||||||
# TODO(stephenfin): Remove this when cells v1 is removed
|
|
||||||
description = ('DEPRECATED: The cell commands, which configure cells v1 '
|
|
||||||
'functionality, are deprecated as Cells v1 itself has '
|
|
||||||
'been deprecated. They will be removed in an upcoming '
|
|
||||||
'release.')
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _parse_server_string(server_str):
|
|
||||||
"""Parses the given server_string and returns a tuple of host and port.
|
|
||||||
If it's not a combination of host part and port, the port element is an
|
|
||||||
empty string. If the input is invalid expression, return a tuple of two
|
|
||||||
empty strings.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
# First of all, exclude pure IPv6 address (w/o port).
|
|
||||||
if netaddr.valid_ipv6(server_str):
|
|
||||||
return (server_str, '')
|
|
||||||
|
|
||||||
# Next, check if this is IPv6 address with a port number
|
|
||||||
# combination.
|
|
||||||
if server_str.find("]:") != -1:
|
|
||||||
(address, port) = server_str.replace('[', '', 1).split(']:')
|
|
||||||
return (address, port)
|
|
||||||
|
|
||||||
# Third, check if this is a combination of an address and a port
|
|
||||||
if server_str.find(':') == -1:
|
|
||||||
return (server_str, '')
|
|
||||||
|
|
||||||
# This must be a combination of an address and a port
|
|
||||||
(address, port) = server_str.split(':')
|
|
||||||
return (address, port)
|
|
||||||
|
|
||||||
except (ValueError, netaddr.AddrFormatError):
|
|
||||||
print('Invalid server_string: %s' % server_str)
|
|
||||||
return ('', '')
|
|
||||||
|
|
||||||
def _create_transport_hosts(self, username, password,
|
|
||||||
broker_hosts=None, hostname=None, port=None):
|
|
||||||
"""Returns a list of oslo.messaging.TransportHost objects."""
|
|
||||||
transport_hosts = []
|
|
||||||
# Either broker-hosts or hostname should be set
|
|
||||||
if broker_hosts:
|
|
||||||
hosts = broker_hosts.split(',')
|
|
||||||
for host in hosts:
|
|
||||||
host = host.strip()
|
|
||||||
broker_hostname, broker_port = self._parse_server_string(host)
|
|
||||||
if not broker_port:
|
|
||||||
msg = _('Invalid broker_hosts value: %s. It should be'
|
|
||||||
' in hostname:port format') % host
|
|
||||||
raise ValueError(msg)
|
|
||||||
try:
|
|
||||||
broker_port = int(broker_port)
|
|
||||||
except ValueError:
|
|
||||||
msg = _('Invalid port value: %s. It should be '
|
|
||||||
'an integer') % broker_port
|
|
||||||
raise ValueError(msg)
|
|
||||||
transport_hosts.append(
|
|
||||||
messaging.TransportHost(
|
|
||||||
hostname=broker_hostname,
|
|
||||||
port=broker_port,
|
|
||||||
username=username,
|
|
||||||
password=password))
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
port = int(port)
|
|
||||||
except ValueError:
|
|
||||||
msg = _("Invalid port value: %s. Should be an integer") % port
|
|
||||||
raise ValueError(msg)
|
|
||||||
transport_hosts.append(
|
|
||||||
messaging.TransportHost(
|
|
||||||
hostname=hostname,
|
|
||||||
port=port,
|
|
||||||
username=username,
|
|
||||||
password=password))
|
|
||||||
return transport_hosts
|
|
||||||
|
|
||||||
@args('--name', metavar='<name>', help='Name for the new cell')
|
|
||||||
@args('--cell_type', metavar='<parent|api|child|compute>',
|
|
||||||
help='Whether the cell is parent/api or child/compute')
|
|
||||||
@args('--username', metavar='<username>',
|
|
||||||
help='Username for the message broker in this cell')
|
|
||||||
@args('--password', metavar='<password>',
|
|
||||||
help='Password for the message broker in this cell')
|
|
||||||
@args('--broker_hosts', metavar='<broker_hosts>',
|
|
||||||
help='Comma separated list of message brokers in this cell. '
|
|
||||||
'Each Broker is specified as hostname:port with both '
|
|
||||||
'mandatory. This option overrides the --hostname '
|
|
||||||
'and --port options (if provided). ')
|
|
||||||
@args('--hostname', metavar='<hostname>',
|
|
||||||
help='Address of the message broker in this cell')
|
|
||||||
@args('--port', metavar='<number>',
|
|
||||||
help='Port number of the message broker in this cell')
|
|
||||||
@args('--virtual_host', metavar='<virtual_host>',
|
|
||||||
help='The virtual host of the message broker in this cell')
|
|
||||||
@args('--woffset', metavar='<float>')
|
|
||||||
@args('--wscale', metavar='<float>')
|
|
||||||
def create(self, name, cell_type='child', username=None, broker_hosts=None,
|
|
||||||
password=None, hostname=None, port=None, virtual_host=None,
|
|
||||||
woffset=None, wscale=None):
|
|
||||||
|
|
||||||
if cell_type not in ['parent', 'child', 'api', 'compute']:
|
|
||||||
print("Error: cell type must be 'parent'/'api' or "
|
|
||||||
"'child'/'compute'")
|
|
||||||
return 2
|
|
||||||
|
|
||||||
# Set up the transport URL
|
|
||||||
transport_hosts = self._create_transport_hosts(
|
|
||||||
username, password,
|
|
||||||
broker_hosts, hostname,
|
|
||||||
port)
|
|
||||||
transport_url = rpc.get_transport_url()
|
|
||||||
transport_url.hosts.extend(transport_hosts)
|
|
||||||
transport_url.virtual_host = virtual_host
|
|
||||||
|
|
||||||
is_parent = False
|
|
||||||
if cell_type in ['api', 'parent']:
|
|
||||||
is_parent = True
|
|
||||||
values = {'name': name,
|
|
||||||
'is_parent': is_parent,
|
|
||||||
'transport_url': urlparse.unquote(str(transport_url)),
|
|
||||||
'weight_offset': float(woffset),
|
|
||||||
'weight_scale': float(wscale)}
|
|
||||||
ctxt = context.get_admin_context()
|
|
||||||
db.cell_create(ctxt, values)
|
|
||||||
|
|
||||||
@args('--cell_name', metavar='<cell_name>',
|
|
||||||
help='Name of the cell to delete')
|
|
||||||
def delete(self, cell_name):
|
|
||||||
ctxt = context.get_admin_context()
|
|
||||||
db.cell_delete(ctxt, cell_name)
|
|
||||||
|
|
||||||
def list(self):
|
|
||||||
ctxt = context.get_admin_context()
|
|
||||||
cells = db.cell_get_all(ctxt)
|
|
||||||
fmt = "%3s %-10s %-6s %-10s %-15s %-5s %-10s"
|
|
||||||
print(fmt % ('Id', 'Name', 'Type', 'Username', 'Hostname',
|
|
||||||
'Port', 'VHost'))
|
|
||||||
print(fmt % ('-' * 3, '-' * 10, '-' * 6, '-' * 10, '-' * 15,
|
|
||||||
'-' * 5, '-' * 10))
|
|
||||||
for cell in cells:
|
|
||||||
url = rpc.get_transport_url(cell.transport_url)
|
|
||||||
host = url.hosts[0] if url.hosts else messaging.TransportHost()
|
|
||||||
print(fmt % (cell.id, cell.name,
|
|
||||||
'parent' if cell.is_parent else 'child',
|
|
||||||
host.username, host.hostname,
|
|
||||||
host.port, url.virtual_host))
|
|
||||||
print(fmt % ('-' * 3, '-' * 10, '-' * 6, '-' * 10, '-' * 15,
|
|
||||||
'-' * 5, '-' * 10))
|
|
||||||
|
|
||||||
|
|
||||||
class CellV2Commands(object):
|
class CellV2Commands(object):
|
||||||
"""Commands for managing cells v2."""
|
"""Commands for managing cells v2."""
|
||||||
|
|
||||||
@@ -1085,14 +932,10 @@ class CellV2Commands(object):
|
|||||||
"""Simple cellsv2 setup.
|
"""Simple cellsv2 setup.
|
||||||
|
|
||||||
This simplified command is for use by existing non-cells users to
|
This simplified command is for use by existing non-cells users to
|
||||||
configure the default environment. If you are using CellsV1, this
|
configure the default environment. Returns 0 if setup is completed (or
|
||||||
will not work for you. Returns 0 if setup is completed (or has
|
has already been done) and 1 if no hosts are reporting (and this cannot
|
||||||
already been done), 1 if no hosts are reporting (and this cannot
|
be mapped).
|
||||||
be mapped) and 2 if run in a CellsV1 environment.
|
|
||||||
"""
|
"""
|
||||||
if CONF.cells.enable:
|
|
||||||
print('CellsV1 users cannot use this simplified setup command')
|
|
||||||
return 2
|
|
||||||
transport_url = self._validate_transport_url(transport_url)
|
transport_url = self._validate_transport_url(transport_url)
|
||||||
if not transport_url:
|
if not transport_url:
|
||||||
return 1
|
return 1
|
||||||
@@ -2332,7 +2175,6 @@ class PlacementCommands(object):
|
|||||||
|
|
||||||
CATEGORIES = {
|
CATEGORIES = {
|
||||||
'api_db': ApiDbCommands,
|
'api_db': ApiDbCommands,
|
||||||
'cell': CellCommands,
|
|
||||||
'cell_v2': CellV2Commands,
|
'cell_v2': CellV2Commands,
|
||||||
'db': DbCommands,
|
'db': DbCommands,
|
||||||
'floating': FloatingIpCommands,
|
'floating': FloatingIpCommands,
|
||||||
|
@@ -879,149 +879,6 @@ class ApiDbCommandsTestCase(test.NoDBTestCase):
|
|||||||
version=4, database='api')
|
version=4, database='api')
|
||||||
|
|
||||||
|
|
||||||
class CellCommandsTestCase(test.NoDBTestCase):
|
|
||||||
def setUp(self):
|
|
||||||
super(CellCommandsTestCase, self).setUp()
|
|
||||||
self.output = StringIO()
|
|
||||||
self.useFixture(fixtures.MonkeyPatch('sys.stdout', self.output))
|
|
||||||
self.commands = manage.CellCommands()
|
|
||||||
|
|
||||||
def test_create_transport_hosts_multiple(self):
|
|
||||||
"""Test the _create_transport_hosts method
|
|
||||||
when broker_hosts is set.
|
|
||||||
"""
|
|
||||||
brokers = "127.0.0.1:5672,127.0.0.2:5671"
|
|
||||||
thosts = self.commands._create_transport_hosts(
|
|
||||||
'guest', 'devstack',
|
|
||||||
broker_hosts=brokers)
|
|
||||||
self.assertEqual(2, len(thosts))
|
|
||||||
self.assertEqual('127.0.0.1', thosts[0].hostname)
|
|
||||||
self.assertEqual(5672, thosts[0].port)
|
|
||||||
self.assertEqual('127.0.0.2', thosts[1].hostname)
|
|
||||||
self.assertEqual(5671, thosts[1].port)
|
|
||||||
|
|
||||||
def test_create_transport_hosts_single(self):
|
|
||||||
"""Test the _create_transport_hosts method when hostname is passed."""
|
|
||||||
thosts = self.commands._create_transport_hosts('guest', 'devstack',
|
|
||||||
hostname='127.0.0.1',
|
|
||||||
port=80)
|
|
||||||
self.assertEqual(1, len(thosts))
|
|
||||||
self.assertEqual('127.0.0.1', thosts[0].hostname)
|
|
||||||
self.assertEqual(80, thosts[0].port)
|
|
||||||
|
|
||||||
def test_create_transport_hosts_single_broker(self):
|
|
||||||
"""Test the _create_transport_hosts method for single broker_hosts."""
|
|
||||||
thosts = self.commands._create_transport_hosts(
|
|
||||||
'guest', 'devstack',
|
|
||||||
broker_hosts='127.0.0.1:5672')
|
|
||||||
self.assertEqual(1, len(thosts))
|
|
||||||
self.assertEqual('127.0.0.1', thosts[0].hostname)
|
|
||||||
self.assertEqual(5672, thosts[0].port)
|
|
||||||
|
|
||||||
def test_create_transport_hosts_both(self):
|
|
||||||
"""Test the _create_transport_hosts method when both broker_hosts
|
|
||||||
and hostname/port are passed.
|
|
||||||
"""
|
|
||||||
thosts = self.commands._create_transport_hosts(
|
|
||||||
'guest', 'devstack',
|
|
||||||
broker_hosts='127.0.0.1:5672',
|
|
||||||
hostname='127.0.0.2', port=80)
|
|
||||||
self.assertEqual(1, len(thosts))
|
|
||||||
self.assertEqual('127.0.0.1', thosts[0].hostname)
|
|
||||||
self.assertEqual(5672, thosts[0].port)
|
|
||||||
|
|
||||||
def test_create_transport_hosts_wrong_val(self):
|
|
||||||
"""Test the _create_transport_hosts method when broker_hosts
|
|
||||||
is wrongly specified
|
|
||||||
"""
|
|
||||||
self.assertRaises(ValueError,
|
|
||||||
self.commands._create_transport_hosts,
|
|
||||||
'guest', 'devstack',
|
|
||||||
broker_hosts='127.0.0.1:5672,127.0.0.1')
|
|
||||||
|
|
||||||
def test_create_transport_hosts_wrong_port_val(self):
|
|
||||||
"""Test the _create_transport_hosts method when port in
|
|
||||||
broker_hosts is wrongly specified
|
|
||||||
"""
|
|
||||||
self.assertRaises(ValueError,
|
|
||||||
self.commands._create_transport_hosts,
|
|
||||||
'guest', 'devstack',
|
|
||||||
broker_hosts='127.0.0.1:')
|
|
||||||
|
|
||||||
def test_create_transport_hosts_wrong_port_arg(self):
|
|
||||||
"""Test the _create_transport_hosts method when port
|
|
||||||
argument is wrongly specified
|
|
||||||
"""
|
|
||||||
self.assertRaises(ValueError,
|
|
||||||
self.commands._create_transport_hosts,
|
|
||||||
'guest', 'devstack',
|
|
||||||
hostname='127.0.0.1', port='ab')
|
|
||||||
|
|
||||||
@mock.patch.object(context, 'get_admin_context')
|
|
||||||
@mock.patch.object(db, 'cell_create')
|
|
||||||
def test_create_broker_hosts(self, mock_db_cell_create, mock_ctxt):
|
|
||||||
"""Test the create function when broker_hosts is
|
|
||||||
passed
|
|
||||||
"""
|
|
||||||
cell_tp_url = "fake://guest:devstack@127.0.0.1:5432"
|
|
||||||
cell_tp_url += ",guest:devstack@127.0.0.2:9999/"
|
|
||||||
ctxt = mock.sentinel
|
|
||||||
mock_ctxt.return_value = mock.sentinel
|
|
||||||
self.commands.create("test",
|
|
||||||
broker_hosts='127.0.0.1:5432,127.0.0.2:9999',
|
|
||||||
woffset=0, wscale=0,
|
|
||||||
username="guest", password="devstack")
|
|
||||||
exp_values = {'name': "test",
|
|
||||||
'is_parent': False,
|
|
||||||
'transport_url': cell_tp_url,
|
|
||||||
'weight_offset': 0.0,
|
|
||||||
'weight_scale': 0.0}
|
|
||||||
mock_db_cell_create.assert_called_once_with(ctxt, exp_values)
|
|
||||||
|
|
||||||
@mock.patch.object(context, 'get_admin_context')
|
|
||||||
@mock.patch.object(db, 'cell_create')
|
|
||||||
def test_create_broker_hosts_with_url_decoding_fix(self,
|
|
||||||
mock_db_cell_create,
|
|
||||||
mock_ctxt):
|
|
||||||
"""Test the create function when broker_hosts is
|
|
||||||
passed
|
|
||||||
"""
|
|
||||||
cell_tp_url = "fake://the=user:the=password@127.0.0.1:5432/"
|
|
||||||
ctxt = mock.sentinel
|
|
||||||
mock_ctxt.return_value = mock.sentinel
|
|
||||||
self.commands.create("test",
|
|
||||||
broker_hosts='127.0.0.1:5432',
|
|
||||||
woffset=0, wscale=0,
|
|
||||||
username="the=user",
|
|
||||||
password="the=password")
|
|
||||||
exp_values = {'name': "test",
|
|
||||||
'is_parent': False,
|
|
||||||
'transport_url': cell_tp_url,
|
|
||||||
'weight_offset': 0.0,
|
|
||||||
'weight_scale': 0.0}
|
|
||||||
mock_db_cell_create.assert_called_once_with(ctxt, exp_values)
|
|
||||||
|
|
||||||
@mock.patch.object(context, 'get_admin_context')
|
|
||||||
@mock.patch.object(db, 'cell_create')
|
|
||||||
def test_create_hostname(self, mock_db_cell_create, mock_ctxt):
|
|
||||||
"""Test the create function when hostname and port is
|
|
||||||
passed
|
|
||||||
"""
|
|
||||||
cell_tp_url = "fake://guest:devstack@127.0.0.1:9999/"
|
|
||||||
ctxt = mock.sentinel
|
|
||||||
mock_ctxt.return_value = mock.sentinel
|
|
||||||
self.commands.create("test",
|
|
||||||
hostname='127.0.0.1', port="9999",
|
|
||||||
woffset=0, wscale=0,
|
|
||||||
username="guest", password="devstack")
|
|
||||||
exp_values = {'name': "test",
|
|
||||||
'is_parent': False,
|
|
||||||
'transport_url': cell_tp_url,
|
|
||||||
'weight_offset': 0.0,
|
|
||||||
'weight_scale': 0.0}
|
|
||||||
mock_db_cell_create.assert_called_once_with(ctxt, exp_values)
|
|
||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class CellV2CommandsTestCase(test.NoDBTestCase):
|
class CellV2CommandsTestCase(test.NoDBTestCase):
|
||||||
USES_DB_SELF = True
|
USES_DB_SELF = True
|
||||||
@@ -1560,10 +1417,6 @@ class CellV2CommandsTestCase(test.NoDBTestCase):
|
|||||||
self._test_migrate_simple_command()
|
self._test_migrate_simple_command()
|
||||||
self._test_migrate_simple_command()
|
self._test_migrate_simple_command()
|
||||||
|
|
||||||
def test_simple_command_cellsv1(self):
|
|
||||||
self.flags(enable=True, group='cells')
|
|
||||||
self.assertEqual(2, self.commands.simple_cell_setup('foo'))
|
|
||||||
|
|
||||||
def test_instance_verify_no_mapping(self):
|
def test_instance_verify_no_mapping(self):
|
||||||
r = self.commands.verify_instance(uuidsentinel.instance)
|
r = self.commands.verify_instance(uuidsentinel.instance)
|
||||||
self.assertEqual(1, r)
|
self.assertEqual(1, r)
|
||||||
|
@@ -2,10 +2,14 @@
|
|||||||
upgrade:
|
upgrade:
|
||||||
- |
|
- |
|
||||||
The *cells v1* feature has been deprecated since the 16.0.0 Pike release
|
The *cells v1* feature has been deprecated since the 16.0.0 Pike release
|
||||||
and has now been removed. The ``nova-cells`` service has been removed. The
|
and has now been removed. The ``nova-cells`` service and ``nova-manage
|
||||||
*cells v1* specific REST APIs have been removed along with their related
|
cells`` commands have been removed, while the ``nova-manage cell_v2
|
||||||
policy rules. Calling these APIs will now result in a ``410 (Gone)`` error
|
simple_cell_setup`` command will no longer check if cells v1 is enabled and
|
||||||
response.
|
therefore can no longer exit with ``2``.
|
||||||
|
|
||||||
|
The *cells v1* specific REST APIs have
|
||||||
|
been removed along with their related policy rules. Calling these APIs will
|
||||||
|
now result in a ``410 (Gone)`` error response.
|
||||||
|
|
||||||
* ``GET /os-cells``
|
* ``GET /os-cells``
|
||||||
* ``POST /os-cells``
|
* ``POST /os-cells``
|
||||||
|
Reference in New Issue
Block a user