Add nova-manage cell_v2 create_cell command

Currently, all of the commands that create a new cell require the
presence of compute hosts, else they won't create a cell mapping.
In the use case of a fresh install, it's reasonable that compute
host records may not yet exist at the time of cells v2 setup.

This provides a way for operators to create a new empty cell at
setup time and defer adding hosts to the cell until they have
started their compute hosts later (via the 'discover_hosts'
command).

The command optionally accepts a database connection url and
message queue transport url, else it will take the values from
the nova.conf. It returns the uuid of the newly created cell.

Change-Id: I2fd7d854ffa579e550f6002cfb7223d7f40acac6
Related-Bug: #1656276
This commit is contained in:
Andrey Volkov 2016-08-16 11:25:54 +03:00 committed by Matt Riedemann
parent 9008f6d561
commit f7e9f312a0
2 changed files with 100 additions and 0 deletions

View File

@ -103,6 +103,7 @@ _EXTRA_DEFAULT_LOG_LEVELS = ['oslo_db=INFO', 'oslo_policy=INFO']
# Decorators for actions
args = cmd_common.args
action_description = cmd_common.action_description
def param2id(object_id):
@ -1397,6 +1398,49 @@ class CellV2Commands(object):
cell_mapping=cell_mapping)
host_mapping.create()
@action_description(
_("Add a new cell to nova API database. "
"DB and MQ urls can be provided directly "
"or can be taken from config. The result is cell uuid."))
@args('--name', metavar='<name>', help=_('The name of the cell'))
@args('--database_connection', metavar='<database url>',
dest='database_connection',
help=_('The database url for the cell database'))
@args('--transport-url', metavar='<transport url>', dest='transport_url',
help=_('The transport url for the cell message queue'))
@args('--verbose', action='store_true',
help=_('Output the uuid of the created cell'))
def create_cell(self, name=None, database_connection=None,
transport_url=None, verbose=False):
ctxt = context.get_context()
transport_url = transport_url or CONF.transport_url
if not transport_url:
print(_('Must specify --transport-url if [DEFAULT]/transport_url '
'is not set in the configuration file.'))
return 1
database_connection = database_connection or CONF.database.connection
if not database_connection:
print(_('Must specify --database_connection '
'if [database]/connection is not set '
'in the configuration file.'))
return 1
if any(cell.database_connection == database_connection
and cell.transport_url == transport_url
for cell in objects.CellMappingList.get_all(ctxt)):
print(_('Cell with the specified transport_url '
'and database_connection combination already exists'))
return 2
cell_mapping_uuid = uuidutils.generate_uuid()
cell_mapping = objects.CellMapping(
ctxt,
uuid=cell_mapping_uuid, name=name,
transport_url=transport_url,
database_connection=database_connection)
cell_mapping.create()
if verbose:
print(cell_mapping_uuid)
return 0
CATEGORIES = {
'account': AccountCommands,

View File

@ -1370,6 +1370,62 @@ class CellV2CommandsTestCase(test.NoDBTestCase):
self.assertEqual(from_cli,
self.commands._validate_transport_url(from_cli))
def test_create_cell_use_params(self):
ctxt = context.get_context()
kwargs = dict(
name='fake-name',
transport_url='fake-transport-url',
database_connection='fake-db-connection')
status = self.commands.create_cell(verbose=True, **kwargs)
self.assertEqual(0, status)
cell2_uuid = self.output.getvalue().strip()
self.commands.create_cell(**kwargs)
cell2 = objects.CellMapping.get_by_uuid(ctxt, cell2_uuid)
self.assertEqual(kwargs['name'], cell2.name)
self.assertEqual(kwargs['database_connection'],
cell2.database_connection)
self.assertEqual(kwargs['transport_url'], cell2.transport_url)
def test_create_cell_use_config_values(self):
settings = dict(
transport_url='fake-conf-transport-url',
database_connection='fake-conf-db-connection')
self.flags(connection=settings['database_connection'],
group='database')
self.flags(transport_url=settings['transport_url'])
ctxt = context.get_context()
status = self.commands.create_cell(verbose=True)
self.assertEqual(0, status)
cell1_uuid = self.output.getvalue().strip()
cell1 = objects.CellMapping.get_by_uuid(ctxt, cell1_uuid)
self.assertIsNone(cell1.name)
self.assertEqual(settings['database_connection'],
cell1.database_connection)
self.assertEqual(settings['transport_url'], cell1.transport_url)
def test_create_cell_failed_if_non_unique(self):
kwargs = dict(
name='fake-name',
transport_url='fake-transport-url',
database_connection='fake-db-connection')
status1 = self.commands.create_cell(verbose=True, **kwargs)
status2 = self.commands.create_cell(verbose=True, **kwargs)
self.assertEqual(0, status1)
self.assertEqual(2, status2)
self.assertIn('exists', self.output.getvalue())
def test_create_cell_failed_if_no_transport_url(self):
status = self.commands.create_cell()
self.assertEqual(1, status)
self.assertIn('--transport-url', self.output.getvalue())
def test_create_cell_failed_if_no_database_connection(self):
self.flags(connection=None, group='database')
status = self.commands.create_cell(transport_url='fake-transport-url')
self.assertEqual(1, status)
self.assertIn('--database_connection', self.output.getvalue())
class TestNovaManageMain(test.NoDBTestCase):
"""Tests the nova-manage:main() setup code."""