From 52e7e6e3e47c66b362d62d8e277e85f65714285a Mon Sep 17 00:00:00 2001 From: Takashi NATSUME Date: Fri, 20 Oct 2017 23:13:28 +0900 Subject: [PATCH] Add a warning in 'nova-manage cell_v2 delete_cell' When deleting a cell, if there are instance mappings to the cell, the command fails with the following message. * There are existing instances mapped to cell with uuid UUID. But even if all instances have been deleted in the cell, the same message is shown. So in that case, add a warning that the instance mappings have to be deleted by 'nova-manage db archive_deleted_rows' before deleting the cell. Change-Id: I2a163fb50a7e71ce9f463bc9ddeffe2ea47d1588 Closes-Bug: #1725331 --- doc/source/cli/nova-manage.rst | 4 ++- nova/cmd/manage.py | 18 +++++++++-- nova/tests/unit/test_nova_manage.py | 31 ++++++++++++++++++- .../notes/bug-1725331-fcf93514045a557a.yaml | 6 ++++ 4 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 releasenotes/notes/bug-1725331-fcf93514045a557a.yaml diff --git a/doc/source/cli/nova-manage.rst b/doc/source/cli/nova-manage.rst index 8ef9c56979..3601d55cac 100644 --- a/doc/source/cli/nova-manage.rst +++ b/doc/source/cli/nova-manage.rst @@ -213,7 +213,9 @@ Nova Cells v2 the cell and the hosts are deleted successfully with ``--force`` option, 1 if a cell with that uuid could not be found, 2 if host mappings were found for the cell (cell not empty) without ``--force`` option, and 3 - if there are instances mapped to the cell (cell not empty). + if there are instances mapped to the cell (cell not empty), 4 if there are + instance mappings to the cell but all instances have been deleted + in the cell. ``nova-manage cell_v2 list_hosts [--cell_uuid ]`` diff --git a/nova/cmd/manage.py b/nova/cmd/manage.py index 3f59f89d12..7653ab09ae 100644 --- a/nova/cmd/manage.py +++ b/nova/cmd/manage.py @@ -1393,9 +1393,21 @@ class CellV2Commands(object): instance_mappings = objects.InstanceMappingList.get_by_cell_id( ctxt, cell_mapping.id) if instance_mappings: - print(_('There are existing instances mapped to cell with ' - 'uuid %s.') % cell_uuid) - return 3 + with context.target_cell(ctxt, cell_mapping) as cctxt: + instances = objects.InstanceList.get_all(cctxt) + if instances: + # There are instances in the cell. + print(_('There are existing instances mapped to cell with ' + 'uuid %s.') % cell_uuid) + return 3 + # There are no instances in the cell but the records remains + # in the 'instance_mappings' table. + print(_("There are instance mappings to cell with uuid %s, " + "but all instances have been deleted " + "in the cell.") % cell_uuid) + print(_("So execute 'nova-manage db archive_deleted_rows' to " + "delete the instance mappings.")) + return 4 # Delete hosts mapped to the cell. for host_mapping in host_mappings: diff --git a/nova/tests/unit/test_nova_manage.py b/nova/tests/unit/test_nova_manage.py index f1ed36b1bc..54734f237f 100644 --- a/nova/tests/unit/test_nova_manage.py +++ b/nova/tests/unit/test_nova_manage.py @@ -1691,10 +1691,14 @@ class CellV2CommandsTestCase(test.NoDBTestCase): output = self.output.getvalue().strip() self.assertIn('There are existing hosts mapped to cell', output) - def test_delete_cell_instance_mappings_exist(self): + @mock.patch.object(objects.InstanceList, 'get_all') + def test_delete_cell_instance_mappings_exist_with_instances( + self, mock_get_all): """Tests trying to delete a cell which has instance mappings.""" cell_uuid = uuidutils.generate_uuid() ctxt = context.get_admin_context() + mock_get_all.return_value = [objects.Instance( + ctxt, uuid=uuidsentinel.instance)] # create the cell mapping cm = objects.CellMapping( context=ctxt, uuid=cell_uuid, database_connection='fake:///db', @@ -1709,6 +1713,31 @@ class CellV2CommandsTestCase(test.NoDBTestCase): output = self.output.getvalue().strip() self.assertIn('There are existing instances mapped to cell', output) + @mock.patch.object(objects.InstanceList, 'get_all', + return_value=[]) + def test_delete_cell_instance_mappings_exist_without_instances( + self, mock_get_all): + """Tests trying to delete a cell which has instance mappings.""" + cell_uuid = uuidutils.generate_uuid() + ctxt = context.get_admin_context() + # create the cell mapping + cm = objects.CellMapping( + context=ctxt, uuid=cell_uuid, database_connection='fake:///db', + transport_url='fake:///mq') + cm.create() + # create an instance mapping in this cell + im = objects.InstanceMapping( + context=ctxt, instance_uuid=uuidutils.generate_uuid(), + cell_mapping=cm, project_id=uuidutils.generate_uuid()) + im.create() + self.assertEqual(4, self.commands.delete_cell(cell_uuid)) + output = self.output.getvalue().strip() + self.assertIn('There are instance mappings to cell with uuid', output) + self.assertIn('but all instances have been deleted in the cell.', + output) + self.assertIn("So execute 'nova-manage db archive_deleted_rows' to " + "delete the instance mappings.", output) + def test_delete_cell_success_without_host_mappings(self): """Tests trying to delete an empty cell.""" cell_uuid = uuidutils.generate_uuid() diff --git a/releasenotes/notes/bug-1725331-fcf93514045a557a.yaml b/releasenotes/notes/bug-1725331-fcf93514045a557a.yaml new file mode 100644 index 0000000000..edd9fc9001 --- /dev/null +++ b/releasenotes/notes/bug-1725331-fcf93514045a557a.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + The ``nova-manage cell_v2 delete_cell`` command returns an exit code 4 + when there are instance mappings to a cell to delete but all instances + have been deleted in the cell.