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.