diff --git a/nova/objects/compute_node.py b/nova/objects/compute_node.py index 8142e9bdbd..bf51100ef3 100644 --- a/nova/objects/compute_node.py +++ b/nova/objects/compute_node.py @@ -13,6 +13,7 @@ # under the License. +from oslo_db import exception as db_exc from oslo_log import log as logging from oslo_serialization import jsonutils from oslo_utils import uuidutils @@ -314,6 +315,27 @@ class ComputeNode(base.NovaPersistentObject, base.NovaObject): return True + def _ensure_resource_provider(self): + shortname = self.host.split('.')[0] + rp_name = 'compute-%s-%s' % (shortname, self.uuid) + rp = objects.ResourceProvider( + context=self._context, uuid=self.uuid, + name=rp_name) + try: + rp.create() + except db_exc.DBDuplicateEntry: + rp = objects.ResourceProvider.get_by_uuid(self._context, self.uuid) + if rp.name != rp_name: + # FIXME(danms): We probably need a .save() operation on RP + # so that we can update this + LOG.warning(_LW('Compute node %(uuid)s changed name ' + 'from %(old)s to %(new)s'), + {'uuid': self.uuid, + 'old': rp.name, + 'new': rp_name}) + + return rp + def create_inventory(self): """Create the initial inventory objects for this compute node. @@ -321,8 +343,7 @@ class ComputeNode(base.NovaPersistentObject, base.NovaObject): is created, or after an upgrade where the required services have reached the required version. """ - rp = objects.ResourceProvider(context=self._context, uuid=self.uuid) - rp.create() + rp = self._ensure_resource_provider() cpu = objects.Inventory(context=self._context, resource_provider=rp, diff --git a/nova/objects/resource_provider.py b/nova/objects/resource_provider.py index 3932b6f72e..ece8e925ac 100644 --- a/nova/objects/resource_provider.py +++ b/nova/objects/resource_provider.py @@ -45,6 +45,8 @@ class ResourceProvider(base.NovaObject): fields = { 'id': fields.IntegerField(read_only=True), 'uuid': fields.UUIDField(nullable=False), + 'name': fields.StringField(nullable=False), + 'generation': fields.IntegerField(nullable=False), } @base.remotable @@ -55,6 +57,9 @@ class ResourceProvider(base.NovaObject): if 'uuid' not in self: raise exception.ObjectActionError(action='create', reason='uuid is required') + if 'name' not in self: + raise exception.ObjectActionError(action='create', + reason='name is required') updates = self.obj_get_changes() db_rp = self._create_in_db(self._context, updates) self._from_db_object(self._context, self, db_rp) diff --git a/nova/tests/functional/db/test_compute_node.py b/nova/tests/functional/db/test_compute_node.py index 2eb37656c7..27bee00fae 100644 --- a/nova/tests/functional/db/test_compute_node.py +++ b/nova/tests/functional/db/test_compute_node.py @@ -28,7 +28,7 @@ class ComputeNodeTestCase(test.TestCase): memory_mb_used=0, free_ram_mb=0, free_disk_gb=0, hypervisor_type='danvm', hypervisor_version=1, cpu_info='barf', - cpu_allocation_ratio=1.0, + cpu_allocation_ratio=1.0, host='foo', ram_allocation_ratio=1.0, disk_allocation_ratio=1.0) @@ -59,3 +59,9 @@ class ComputeNodeTestCase(test.TestCase): self.assertEqual(1024, obj.total) elif obj.resource_class == fields.ResourceClass.DISK_GB: self.assertEqual(2000, obj.total) + + def test_recreate_rp(self): + self.cn.create_inventory() + rp = self.cn._ensure_resource_provider() + self.assertEqual('compute-%s-%s' % ('foo', self.cn.uuid), + rp.name) diff --git a/nova/tests/functional/db/test_resource_provider.py b/nova/tests/functional/db/test_resource_provider.py index 89ec789d52..01b068bee9 100644 --- a/nova/tests/functional/db/test_resource_provider.py +++ b/nova/tests/functional/db/test_resource_provider.py @@ -48,7 +48,8 @@ class ResourceProviderTestCase(test.NoDBTestCase): def test_create_resource_provider(self): created_resource_provider = objects.ResourceProvider( context=self.context, - uuid=uuidsentinel.fake_resource_provider + uuid=uuidsentinel.fake_resource_provider, + name=uuidsentinel.fake_resource_name, ) created_resource_provider.create() self.assertIsInstance(created_resource_provider.id, int) @@ -58,7 +59,13 @@ class ResourceProviderTestCase(test.NoDBTestCase): uuidsentinel.fake_resource_provider ) self.assertEqual(retrieved_resource_provider.id, - created_resource_provider.id) + created_resource_provider.id) + self.assertEqual(retrieved_resource_provider.uuid, + created_resource_provider.uuid) + self.assertEqual(retrieved_resource_provider.name, + created_resource_provider.name) + self.assertEqual(0, created_resource_provider.generation) + self.assertEqual(0, retrieved_resource_provider.generation) def test_create_inventory_with_uncreated_provider(self): resource_provider = objects.ResourceProvider( @@ -78,7 +85,8 @@ class ResourceProviderTestCase(test.NoDBTestCase): def test_create_and_update_inventory(self): resource_provider = objects.ResourceProvider( context=self.context, - uuid=uuidsentinel.inventory_resource_provider + uuid=uuidsentinel.inventory_resource_provider, + name='foo', ) resource_provider.create() resource_class = fields.ResourceClass.DISK_GB diff --git a/nova/tests/unit/compute/test_resource_tracker.py b/nova/tests/unit/compute/test_resource_tracker.py index e45cef6793..19a1f68217 100644 --- a/nova/tests/unit/compute/test_resource_tracker.py +++ b/nova/tests/unit/compute/test_resource_tracker.py @@ -456,7 +456,7 @@ class BaseTrackerTestCase(BaseTestCase): return updates def _fake_rp_create(self, context, updates): - return dict(updates, id=1) + return dict(updates, id=1, name='foo', generation=1) def _fake_migration_get_in_progress_by_host_and_node(self, ctxt, host, node): diff --git a/nova/tests/unit/objects/test_objects.py b/nova/tests/unit/objects/test_objects.py index 9f1935dae9..101c5b0ca2 100644 --- a/nova/tests/unit/objects/test_objects.py +++ b/nova/tests/unit/objects/test_objects.py @@ -1180,7 +1180,7 @@ object_data = { 'Quotas': '1.2-1fe4cd50593aaf5d36a6dc5ab3f98fb3', 'QuotasNoOp': '1.2-e041ddeb7dc8188ca71706f78aad41c1', 'RequestSpec': '1.6-c1cb516acdf120d367a42d343ed695b5', - 'ResourceProvider': '1.0-57a9a344b0faed9cf6d6811835b6deb6', + 'ResourceProvider': '1.0-a1ae70ee9f95344276e349565219d2d2', 'S3ImageMapping': '1.0-7dd7366a890d82660ed121de9092276e', 'SchedulerLimits': '1.0-249c4bd8e62a9b327b7026b7f19cc641', 'SchedulerRetries': '1.1-3c9c8b16143ebbb6ad7030e999d14cc0', diff --git a/nova/tests/unit/objects/test_resource_provider.py b/nova/tests/unit/objects/test_resource_provider.py index c918fada80..da62bfa06b 100644 --- a/nova/tests/unit/objects/test_resource_provider.py +++ b/nova/tests/unit/objects/test_resource_provider.py @@ -22,9 +22,12 @@ _RESOURCE_CLASS_NAME = 'DISK_GB' _RESOURCE_CLASS_ID = 2 _RESOURCE_PROVIDER_ID = 1 _RESOURCE_PROVIDER_UUID = uuids.resource_provider +_RESOURCE_PROVIDER_NAME = uuids.resource_name _RESOURCE_PROVIDER_DB = { 'id': _RESOURCE_PROVIDER_ID, 'uuid': _RESOURCE_PROVIDER_UUID, + 'name': _RESOURCE_PROVIDER_NAME, + 'generation': 0, } _INVENTORY_ID = 2 _INVENTORY_DB = { @@ -55,12 +58,14 @@ class _TestResourceProviderNoDB(object): return_value=_RESOURCE_PROVIDER_DB) def test_create(self, mock_db_create): obj = objects.ResourceProvider(context=self.context, - uuid=_RESOURCE_PROVIDER_UUID) + uuid=_RESOURCE_PROVIDER_UUID, + name=_RESOURCE_PROVIDER_NAME) obj.create() self.assertEqual(_RESOURCE_PROVIDER_UUID, obj.uuid) self.assertIsInstance(obj.id, int) mock_db_create.assert_called_once_with( - self.context, {'uuid': _RESOURCE_PROVIDER_UUID}) + self.context, {'uuid': _RESOURCE_PROVIDER_UUID, + 'name': _RESOURCE_PROVIDER_NAME}) def test_create_id_fail(self): obj = objects.ResourceProvider(context=self.context, @@ -88,24 +93,28 @@ class TestRemoteResourceProviderNoDB(test_objects._RemoteTest, class TestResourceProvider(test_objects._LocalTest): def test_create_in_db(self): - updates = {'uuid': _RESOURCE_PROVIDER_UUID} + updates = {'uuid': _RESOURCE_PROVIDER_UUID, + 'name': _RESOURCE_PROVIDER_NAME} db_rp = objects.ResourceProvider._create_in_db( self.context, updates) self.assertIsInstance(db_rp.id, int) self.assertEqual(_RESOURCE_PROVIDER_UUID, db_rp.uuid) + self.assertEqual(_RESOURCE_PROVIDER_NAME, db_rp.name) def test_get_by_uuid_from_db(self): rp = objects.ResourceProvider(context=self.context, - uuid=_RESOURCE_PROVIDER_UUID) + uuid=_RESOURCE_PROVIDER_UUID, + name=_RESOURCE_PROVIDER_NAME) rp.create() retrieved_rp = objects.ResourceProvider._get_by_uuid_from_db( self.context, _RESOURCE_PROVIDER_UUID) self.assertEqual(rp.uuid, retrieved_rp.uuid) + self.assertEqual(rp.name, retrieved_rp.name) + def test_get_by_uuid_from_db_missing(self): self.assertRaises(exception.NotFound, - objects.ResourceProvider._get_by_uuid_from_db, - self.context, - uuids.missing) + objects.ResourceProvider.get_by_uuid, + self.context, uuids.missing) class _TestInventoryNoDB(object): @@ -169,7 +178,8 @@ class TestInventory(test_objects._LocalTest): def _make_inventory(self): db_rp = objects.ResourceProvider( - context=self.context, uuid=uuids.inventory_resource_provider) + context=self.context, uuid=uuids.inventory_resource_provider, + name=_RESOURCE_PROVIDER_NAME) db_rp.create() updates = dict(_INVENTORY_DB, resource_provider_id=db_rp.id) @@ -246,7 +256,8 @@ class TestInventory(test_objects._LocalTest): def test_create_requires_resource_class(self): rp = objects.ResourceProvider( - context=self.context, uuid=uuids.inventory_resource_provider) + context=self.context, uuid=uuids.inventory_resource_provider, + name=_RESOURCE_PROVIDER_NAME) rp.create() inventory_dict = dict(_INVENTORY_DB) inventory_dict.pop('id')