From 063b5e4d9e169eec8eb216f44e53b1952c73120b Mon Sep 17 00:00:00 2001 From: Chris Dent Date: Fri, 20 May 2016 16:24:14 +0000 Subject: [PATCH] Add name and generation to ResourceProvider object Add 'name' and 'generation' to the ResourceProvider object so that the humane name and generation counter associated with the provider can be persisted and used in display. Change-Id: I5bc19065fdd2bbbeec67908f3feabbd43a492c89 Partially-Implements: blueprint generic-resource-pools --- nova/objects/compute_node.py | 25 ++++++++++++++-- nova/objects/resource_provider.py | 5 ++++ nova/tests/functional/db/test_compute_node.py | 8 ++++- .../functional/db/test_resource_provider.py | 14 +++++++-- .../unit/compute/test_resource_tracker.py | 2 +- nova/tests/unit/objects/test_objects.py | 2 +- .../unit/objects/test_resource_provider.py | 29 +++++++++++++------ 7 files changed, 68 insertions(+), 17 deletions(-) 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')