diff --git a/doc/source/man/nova-manage.rst b/doc/source/man/nova-manage.rst index 109bad2a57e8..b1db93789234 100644 --- a/doc/source/man/nova-manage.rst +++ b/doc/source/man/nova-manage.rst @@ -143,14 +143,17 @@ Nova Cells v2 transport url or database connection was missing, and 2 if a cell is already using that transport url and database connection combination. -``nova-manage cell_v2 discover_hosts [--cell_uuid ] [--verbose]`` +``nova-manage cell_v2 discover_hosts [--cell_uuid ] [--verbose] [--strict]`` Searches cells, or a single cell, and maps found hosts. This command will check the database for each cell (or a single one if passed in) and map any hosts which are not currently mapped. If a host is already mapped nothing will be done. You need to re-run this command each time you add more compute hosts to a cell (otherwise the scheduler will never place - instances there and the API will not list the new hosts). + instances there and the API will not list the new hosts). If the strict + option is provided the command will only be considered successful if an + unmapped host is discovered (exit code 0). Any other case is considered a + failure (exit code 1). ``nova-manage cell_v2 list_cells [--verbose]`` diff --git a/nova/cmd/manage.py b/nova/cmd/manage.py index d9ce9ae01d1c..40c3884c69e7 100644 --- a/nova/cmd/manage.py +++ b/nova/cmd/manage.py @@ -1448,7 +1448,11 @@ class CellV2Commands(object): 'map.') @args('--verbose', action='store_true', help=_('Provide detailed output when discovering hosts.')) - def discover_hosts(self, cell_uuid=None, verbose=False): + @args('--strict', action='store_true', + help=_('Considered successful (exit code 0) only when an unmapped ' + 'host is discovered. Any other outcome will be considered a ' + 'failure (exit code 1).')) + def discover_hosts(self, cell_uuid=None, verbose=False, strict=False): """Searches cells, or a single cell, and maps found hosts. When a new host is added to a deployment it will add a service entry @@ -1461,7 +1465,10 @@ class CellV2Commands(object): print(msg) ctxt = context.RequestContext() - host_mapping_obj.discover_hosts(ctxt, cell_uuid, status_fn) + hosts = host_mapping_obj.discover_hosts(ctxt, cell_uuid, status_fn) + # discover_hosts will return an empty list if no hosts are discovered + if strict: + return int(not hosts) @action_description( _("Add a new cell to nova API database. " diff --git a/nova/tests/unit/test_nova_manage.py b/nova/tests/unit/test_nova_manage.py index c7e2916f8b19..287e83f2d9cb 100644 --- a/nova/tests/unit/test_nova_manage.py +++ b/nova/tests/unit/test_nova_manage.py @@ -1390,6 +1390,19 @@ class CellV2CommandsTestCase(test.NoDBTestCase): mock_cell_mapping_get_by_uuid.assert_not_called() + @mock.patch('nova.objects.host_mapping.discover_hosts') + def test_discover_hosts_strict(self, mock_discover_hosts): + # Check for exit code 0 if unmapped hosts found + mock_discover_hosts.return_value = ['fake'] + self.assertEqual(self.commands.discover_hosts(strict=True), 0) + + # Check for exit code 1 if no unmapped hosts are found + mock_discover_hosts.return_value = [] + self.assertEqual(self.commands.discover_hosts(strict=True), 1) + + # Check the return when strict=False + self.assertIsNone(self.commands.discover_hosts()) + def test_validate_transport_url_in_conf(self): from_conf = 'fake://user:pass@host:port/' self.flags(transport_url=from_conf)