Skip to content

Commit 4f11257

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Abort startup if nodename conflict is detected"
2 parents 7ea9aac + cf33be6 commit 4f11257

File tree

6 files changed

+49
-2
lines changed

6 files changed

+49
-2
lines changed

nova/compute/manager.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10480,6 +10480,14 @@ def _update_available_resource_for_node(self, context, nodename,
1048010480
LOG.exception(
1048110481
"Error updating PCI resources for node %(node)s.",
1048210482
{'node': nodename})
10483+
except exception.InvalidConfiguration as e:
10484+
if startup:
10485+
# If this happens during startup, we need to let it raise to
10486+
# abort our service startup.
10487+
raise
10488+
else:
10489+
LOG.error("Error updating resources for node %s: %s",
10490+
nodename, e)
1048310491
except Exception:
1048410492
LOG.exception("Error updating resources for node %(node)s.",
1048510493
{'node': nodename})

nova/compute/resource_tracker.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,13 @@ def _init_compute_node(self, context, resources):
728728
cn = objects.ComputeNode(context)
729729
cn.host = self.host
730730
self._copy_resources(cn, resources, initial=True)
731-
cn.create()
731+
try:
732+
cn.create()
733+
except exception.DuplicateRecord:
734+
raise exception.InvalidConfiguration(
735+
'Duplicate compute node record found for host %s node %s' % (
736+
cn.host, cn.hypervisor_hostname))
737+
732738
# Only map the ComputeNode into compute_nodes if create() was OK
733739
# because if create() fails, on the next run through here nodename
734740
# would be in compute_nodes and we won't try to create again (because

nova/exception.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2512,6 +2512,10 @@ class InvalidNodeConfiguration(NovaException):
25122512
msg_fmt = _('Invalid node identity configuration: %(reason)s')
25132513

25142514

2515+
class DuplicateRecord(NovaException):
2516+
msg_fmt = _('Unable to create duplicate record for %(target)s')
2517+
2518+
25152519
class NotSupportedComputeForEvacuateV295(NotSupported):
25162520
msg_fmt = _("Starting to microversion 2.95, evacuate API will stop "
25172521
"instance on destination. To evacuate before upgrades are "

nova/objects/compute_node.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# License for the specific language governing permissions and limitations
1313
# under the License.
1414

15+
from oslo_db import exception as db_exc
1516
from oslo_serialization import jsonutils
1617
from oslo_utils import uuidutils
1718
from oslo_utils import versionutils
@@ -339,7 +340,12 @@ def create(self):
339340
self._convert_supported_instances_to_db_format(updates)
340341
self._convert_pci_stats_to_db_format(updates)
341342

342-
db_compute = db.compute_node_create(self._context, updates)
343+
try:
344+
db_compute = db.compute_node_create(self._context, updates)
345+
except db_exc.DBDuplicateEntry:
346+
target = 'compute node %s:%s' % (updates['hypervisor_hostname'],
347+
updates['uuid'])
348+
raise exception.DuplicateRecord(target=target)
343349
self._from_db_object(self._context, self, db_compute)
344350

345351
@base.remotable

nova/tests/unit/compute/test_resource_tracker.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1552,6 +1552,20 @@ def test_undelete_node_move_host(self, mock_pci, mock_update):
15521552
self.assertEqual('fake-host', node.host)
15531553
mock_update.assert_called()
15541554

1555+
@mock.patch.object(resource_tracker.ResourceTracker,
1556+
'_get_compute_node',
1557+
return_value=None)
1558+
@mock.patch('nova.objects.compute_node.ComputeNode.create')
1559+
def test_create_failed_conflict(self, mock_create, mock_getcn):
1560+
self._setup_rt()
1561+
resources = {'hypervisor_hostname': 'node1',
1562+
'uuid': uuids.node1}
1563+
mock_create.side_effect = exc.DuplicateRecord(target='foo')
1564+
self.assertRaises(exc.InvalidConfiguration,
1565+
self.rt._init_compute_node,
1566+
mock.MagicMock,
1567+
resources)
1568+
15551569

15561570
@ddt.ddt
15571571
class TestUpdateComputeNode(BaseTestCase):

nova/tests/unit/objects/test_compute_node.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from unittest import mock
1717

1818
import netaddr
19+
from oslo_db import exception as db_exc
1920
from oslo_serialization import jsonutils
2021
from oslo_utils.fixture import uuidsentinel
2122
from oslo_utils import timeutils
@@ -341,6 +342,14 @@ def test_recreate_fails(self, mock_get, mock_create):
341342
'uuid': uuidsentinel.fake_compute_node}
342343
mock_create.assert_called_once_with(self.context, param_dict)
343344

345+
@mock.patch('nova.db.main.api.compute_node_create')
346+
def test_create_duplicate(self, mock_create):
347+
mock_create.side_effect = db_exc.DBDuplicateEntry
348+
compute = compute_node.ComputeNode(context=self.context)
349+
compute.service_id = 456
350+
compute.hypervisor_hostname = 'node1'
351+
self.assertRaises(exception.DuplicateRecord, compute.create)
352+
344353
@mock.patch.object(db, 'compute_node_update')
345354
@mock.patch(
346355
'nova.db.main.api.compute_node_get', return_value=fake_compute_node)

0 commit comments

Comments
 (0)