summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nova/compute/manager.py14
-rw-r--r--nova/test.py9
-rw-r--r--nova/tests/fixtures/nova.py4
-rw-r--r--nova/tests/unit/compute/test_compute_mgr.py23
4 files changed, 42 insertions, 8 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index f59fd82d10..2aad5c77fb 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -1509,15 +1509,21 @@ class ComputeManager(manager.Manager):
to write our node identity uuid (if not already done) based on
nodes assigned to us in the database.
"""
- if service_ref.version >= service_obj.NODE_IDENTITY_VERSION:
- # Already new enough, nothing to do here
- return
-
if 'ironic' in CONF.compute_driver.lower():
# We do not persist a single local node identity for
# ironic
return
+ if service_ref.version >= service_obj.NODE_IDENTITY_VERSION:
+ # Already new enough, nothing to do here, but make sure that we
+ # have a UUID file already, as this is not our first time starting.
+ if nova.virt.node.read_local_node_uuid() is None:
+ raise exception.InvalidConfiguration(
+ ('No local node identity found, but this is not our '
+ 'first startup on this host. Refusing to start after '
+ 'potentially having lost that state!'))
+ return
+
if nova.virt.node.read_local_node_uuid():
# We already have a local node identity, no migration needed
return
diff --git a/nova/test.py b/nova/test.py
index 562bd2516e..0f7965ea33 100644
--- a/nova/test.py
+++ b/nova/test.py
@@ -171,6 +171,12 @@ class TestCase(base.BaseTestCase):
# base class when USES_DB is True.
NUMBER_OF_CELLS = 1
+ # The stable compute id stuff is intentionally singleton-ish, which makes
+ # it a nightmare for testing multiple host/node combinations in tests like
+ # we do. So, mock it out by default, unless the test is specifically
+ # designed to handle it.
+ STUB_COMPUTE_ID = True
+
def setUp(self):
"""Run before each test method to initialize test environment."""
# Ensure BaseTestCase's ConfigureLogging fixture is disabled since
@@ -301,7 +307,8 @@ class TestCase(base.BaseTestCase):
# Reset our local node uuid cache (and avoid writing to the
# local filesystem when we generate a new one).
- self.useFixture(nova_fixtures.ComputeNodeIdFixture())
+ if self.STUB_COMPUTE_ID:
+ self.useFixture(nova_fixtures.ComputeNodeIdFixture())
def _setup_cells(self):
"""Setup a normal cellsv2 environment.
diff --git a/nova/tests/fixtures/nova.py b/nova/tests/fixtures/nova.py
index 76dc63755d..5fd893e7dc 100644
--- a/nova/tests/fixtures/nova.py
+++ b/nova/tests/fixtures/nova.py
@@ -1863,3 +1863,7 @@ class ComputeNodeIdFixture(fixtures.Fixture):
self.useFixture(fixtures.MockPatch(
'nova.virt.node.write_local_node_uuid',
lambda uuid: None))
+ self.useFixture(fixtures.MockPatch(
+ 'nova.compute.manager.ComputeManager.'
+ '_ensure_existing_node_identity',
+ mock.DEFAULT))
diff --git a/nova/tests/unit/compute/test_compute_mgr.py b/nova/tests/unit/compute/test_compute_mgr.py
index c5fed20377..16de724a42 100644
--- a/nova/tests/unit/compute/test_compute_mgr.py
+++ b/nova/tests/unit/compute/test_compute_mgr.py
@@ -91,6 +91,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
# os-brick>=5.1 now uses external file system locks instead of internal
# locks so we need to set up locking
REQUIRES_LOCKING = True
+ STUB_COMPUTE_ID = False
def setUp(self):
super(ComputeManagerUnitTestCase, self).setUp()
@@ -6361,13 +6362,15 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
'two-image': 'existing'}, r)
@mock.patch.object(virt_node, 'write_local_node_uuid')
- def test_ensure_node_uuid_not_needed_version(self, mock_node):
+ @mock.patch.object(virt_node, 'read_local_node_uuid')
+ def test_ensure_node_uuid_not_needed_version(self, mock_read, mock_write):
# Make sure an up-to-date service bypasses the persistence
service_ref = service_obj.Service()
self.assertEqual(service_obj.SERVICE_VERSION, service_ref.version)
- mock_node.assert_not_called()
+ mock_read.return_value = 'not none'
+ mock_write.assert_not_called()
self.compute._ensure_existing_node_identity(service_ref)
- mock_node.assert_not_called()
+ mock_write.assert_not_called()
@mock.patch.object(virt_node, 'write_local_node_uuid')
def test_ensure_node_uuid_not_needed_ironic(self, mock_node):
@@ -6452,6 +6455,20 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
mock_get_cn.assert_called_once_with(mock.ANY, self.compute.host)
mock_write_node.assert_called_once_with(str(uuids.compute))
+ @mock.patch.object(virt_node, 'read_local_node_uuid')
+ def test_ensure_node_uuid_missing_file_ironic(self, mock_read):
+ mock_service = mock.MagicMock(
+ version=service_obj.NODE_IDENTITY_VERSION)
+ mock_read.return_value = None
+ self.assertRaises(exception.InvalidConfiguration,
+ self.compute._ensure_existing_node_identity,
+ mock_service)
+ mock_read.assert_called_once_with()
+
+ # Now make sure that ironic causes this exact configuration to pass
+ self.flags(compute_driver='ironic')
+ self.compute._ensure_existing_node_identity(mock_service)
+
def test_ensure_node_uuid_called_by_init_host(self):
# test_init_host() above ensures that we do not call
# _ensure_existing_node_identity() in the service_ref=None case.