From 1102441a4259fe155eb2a61cd16c6e015787472c Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Tue, 7 Feb 2017 08:43:42 -0800 Subject: [PATCH] Add an update_cell command to nova-manage In case a cell record was incorrectly created, or needs to be updated to point to a new database or mq endpoint, we need a way for users to be able to update a CellMapping record. Since deleting and re-creating is definitely not an option, this patch adds an update_cell which allows updating the mutable fields if necessary. Change-Id: I75ddfa458a6fb650f1098505193398984f2be596 --- doc/source/man/nova-manage.rst | 11 ++++++++ nova/cmd/manage.py | 43 +++++++++++++++++++++++++++++ nova/tests/unit/test_nova_manage.py | 32 +++++++++++++++++++++ 3 files changed, 86 insertions(+) diff --git a/doc/source/man/nova-manage.rst b/doc/source/man/nova-manage.rst index 4170b3004390..67797f23b407 100644 --- a/doc/source/man/nova-manage.rst +++ b/doc/source/man/nova-manage.rst @@ -163,6 +163,17 @@ Nova Cells v2 found, 2 if host mappings were found for the cell (cell not empty), and 3 if there are instances mapped to the cell (cell not empty). +``nova-manage cell_v2 update_cell --cell_uuid [--name ] [--transport-url ] [--database_connection ]`` + + Updates the properties of a cell by the given uuid. If the cell is not + found by uuid, this command will return an exit code of 1. If the + properties cannot be set, this will return 2. Otherwise, the exit code + will be 0. + + NOTE: Updating the transport_url or database_connection fields on + a running system will NOT result in all nodes immediately using the + new values. Use caution when changing these values. + Nova Logs ~~~~~~~~~ diff --git a/nova/cmd/manage.py b/nova/cmd/manage.py index 5399747fbf31..3954a2594b03 100644 --- a/nova/cmd/manage.py +++ b/nova/cmd/manage.py @@ -1496,6 +1496,49 @@ class CellV2Commands(object): cell_mapping.destroy() return 0 + @args('--cell_uuid', metavar='', dest='cell_uuid', + required=True, help=_('The uuid of the cell to update.')) + @args('--name', metavar='', dest='name', + help=_('Set the cell name.')) + @args('--transport-url', metavar='', dest='transport_url', + help=_('Set the cell transport_url. NOTE that running nodes ' + 'will not see the change until restart!')) + @args('--database_connection', metavar='', dest='db_connection', + help=_('Set the cell database_connection. NOTE that running nodes ' + 'will not see the change until restart!')) + def update_cell(self, cell_uuid, name, transport_url, db_connection): + """Updates the properties of a cell by the given uuid. + + If the cell is not found by uuid, this command will return an exit + code of 1. If the properties cannot be set, this will return 2. + Otherwise, the exit code will be 0. + + NOTE: Updating the transport_url or database_connection fields on + a running system will NOT result in all nodes immediately using the + new values. Use caution when changing these values. + """ + ctxt = context.get_admin_context() + try: + cell_mapping = objects.CellMapping.get_by_uuid(ctxt, cell_uuid) + except exception.CellMappingNotFound: + print(_('Cell with uuid %s was not found.') % cell_uuid) + return 1 + + if name: + cell_mapping.name = name + if transport_url: + cell_mapping.transport_url = transport_url + if db_connection: + cell_mapping.database_connection = db_connection + + try: + cell_mapping.save() + except Exception as e: + print(_('Unable to update CellMapping: %s') % e) + return 2 + + return 0 + CATEGORIES = { 'account': AccountCommands, diff --git a/nova/tests/unit/test_nova_manage.py b/nova/tests/unit/test_nova_manage.py index 640397837e2c..a6f6cd83f559 100644 --- a/nova/tests/unit/test_nova_manage.py +++ b/nova/tests/unit/test_nova_manage.py @@ -1532,6 +1532,38 @@ class CellV2CommandsTestCase(test.NoDBTestCase): output = self.output.getvalue().strip() self.assertEqual('', output) + def test_update_cell_not_found(self): + self.assertEqual(1, self.commands.update_cell( + uuidsentinel.cell1, 'foo', 'fake://new', 'fake:///new')) + self.assertIn('not found', self.output.getvalue()) + + def test_update_cell_failed(self): + ctxt = context.get_admin_context() + objects.CellMapping(context=ctxt, uuid=uuidsentinel.cell1, + name='cell1', + transport_url='fake://mq', + database_connection='fake:///db').create() + with mock.patch('nova.objects.CellMapping.save') as mock_save: + mock_save.side_effect = Exception + self.assertEqual(2, self.commands.update_cell( + uuidsentinel.cell1, 'foo', 'fake://new', 'fake:///new')) + self.assertIn('Unable to update', self.output.getvalue()) + + def test_update_cell_success(self): + ctxt = context.get_admin_context() + objects.CellMapping(context=ctxt, uuid=uuidsentinel.cell1, + name='cell1', + transport_url='fake://mq', + database_connection='fake:///db').create() + self.assertEqual(0, self.commands.update_cell( + uuidsentinel.cell1, 'foo', 'fake://new', 'fake:///new')) + cm = objects.CellMapping.get_by_uuid(ctxt, uuidsentinel.cell1) + self.assertEqual('foo', cm.name) + self.assertEqual('fake://new', cm.transport_url) + self.assertEqual('fake:///new', cm.database_connection) + output = self.output.getvalue().strip() + self.assertEqual('', output) + class TestNovaManageMain(test.NoDBTestCase): """Tests the nova-manage:main() setup code."""