Merge "Don't use OVO with ResourceProvider and ResourceProviderList"

This commit is contained in:
Zuul 2019-02-26 03:52:02 +00:00 committed by Gerrit Code Review
commit 872ed53616
9 changed files with 78 additions and 132 deletions

@ -1,26 +1,20 @@
alembic==0.9.8
amqp==2.2.2
appdirs==1.4.3
attrs==17.4.0
Babel==2.3.4
bandit==1.1.0
cachetools==2.0.1
colorama==0.3.9
contextlib2==0.5.5
coverage==4.0
debtcollector==1.19.0
decorator==3.4.0
eventlet==0.18.2
extras==1.0.0
fasteners==0.14.1
fixtures==3.0.0
flake8==2.5.5
future==0.16.0
futurist==1.6.0
gabbi==1.35.0
gitdb2==2.0.3
GitPython==2.1.8
greenlet==0.4.10
hacking==0.12.0
iso8601==0.1.11
Jinja2==2.10
@ -29,7 +23,6 @@ jsonpath-rw-ext==1.1.3
jsonschema==2.6.0
keystoneauth1==3.9.0
keystonemiddleware==4.18.0
kombu==4.1.0
linecache2==1.0.0
Mako==1.0.7
MarkupSafe==1.0
@ -41,8 +34,8 @@ mox3==0.20.0
msgpack-python==0.5.6
netaddr==0.7.18
netifaces==0.10.4
os-resource-classes==0.2.0
os-client-config==1.29.0
os-resource-classes==0.2.0
os-service-types==1.2.0
os-traits==0.4.0
oslo.concurrency==3.26.0
@ -51,17 +44,12 @@ oslo.context==2.19.2
oslo.db==4.40.0
oslo.i18n==3.15.3
oslo.log==3.36.0
oslo.messaging==6.3.0
oslo.middleware==3.31.0
oslo.policy==1.35.0
oslo.serialization==2.18.0
oslo.service==1.24.0
oslo.upgradecheck==0.2.0
oslo.utils==3.37.0
oslo.versionedobjects==1.31.2
oslotest==3.4.0
Paste==2.0.2
PasteDeploy==1.5.2
pbr==2.0.0
pep8==1.5.7
pluggy==0.6.0
@ -71,7 +59,6 @@ psycopg2==2.7
py==1.5.2
pycadf==2.7.0
pyflakes==0.8.1
pyinotify==0.9.6
PyMySQL==0.7.6
pyparsing==2.2.0
pytest==3.4.2
@ -95,7 +82,6 @@ statsd==3.2.2
stestr==1.0.0
stevedore==1.20.0
Tempita==0.5.2
tenacity==4.9.0
testrepository==0.0.20
testresources==2.0.0
testscenarios==0.4
@ -103,7 +89,6 @@ testtools==2.2.0
traceback2==1.4.0
unittest2==1.1.0
urllib3==1.22
vine==1.1.4
WebOb==1.8.2
wrapt==1.10.11
wsgi-intercept==1.7.0

@ -28,8 +28,6 @@ from oslo_db import api as oslo_db_api
from oslo_db import exception as db_exc
from oslo_log import log as logging
from oslo_utils import encodeutils
from oslo_versionedobjects import base
from oslo_versionedobjects import fields
import six
import sqlalchemy as sa
from sqlalchemy import exc as sqla_exc
@ -975,15 +973,17 @@ def _delete_rp_record(context, _id):
delete(synchronize_session=False)
@base.VersionedObjectRegistry.register_if(False)
class ResourceProvider(base.VersionedObject, base.TimestampedObject):
class ResourceProvider(object):
SETTABLE_FIELDS = ('name', 'parent_provider_uuid')
fields = {
'id': fields.IntegerField(read_only=True),
'uuid': fields.UUIDField(nullable=False),
'name': fields.StringField(nullable=False),
'generation': fields.IntegerField(nullable=False),
def __init__(self, context, id=None, uuid=None, name=None,
generation=None, parent_provider_uuid=None,
root_provider_uuid=None, updated_at=None, created_at=None):
self._context = context
self.id = id
self.uuid = uuid
self.name = name
self.generation = generation
# UUID of the root provider in a hierarchy of providers. Will be equal
# to the uuid field if this provider is the root provider of a
# hierarchy. This field is never manually set by the user. Instead, it
@ -992,44 +992,44 @@ class ResourceProvider(base.VersionedObject, base.TimestampedObject):
# is an optimization field that allows us to very quickly query for all
# providers within a particular tree without doing any recursive
# querying.
'root_provider_uuid': fields.UUIDField(nullable=False),
self.root_provider_uuid = root_provider_uuid
# UUID of the direct parent provider, or None if this provider is a
# "root" provider.
'parent_provider_uuid': fields.UUIDField(nullable=True, default=None),
}
self.parent_provider_uuid = parent_provider_uuid
self.updated_at = updated_at
self.created_at = created_at
def create(self):
if 'id' in self:
if self.id is not None:
raise exception.ObjectActionError(action='create',
reason='already created')
if 'uuid' not in self:
if self.uuid is None:
raise exception.ObjectActionError(action='create',
reason='uuid is required')
if 'name' not in self:
if not self.name:
raise exception.ObjectActionError(action='create',
reason='name is required')
if 'root_provider_uuid' in self:
raise exception.ObjectActionError(
action='create',
reason=_('root provider UUID cannot be manually set.'))
self.obj_set_defaults()
updates = self.obj_get_changes()
# These are the only fields we are willing to create with.
# If there are others, ignore them.
updates = {
'name': self.name,
'uuid': self.uuid,
'parent_provider_uuid': self.parent_provider_uuid,
}
self._create_in_db(self._context, updates)
self.obj_reset_changes()
def destroy(self):
self._delete(self._context, self.id)
def save(self):
updates = self.obj_get_changes()
if updates and any(k not in self.SETTABLE_FIELDS
for k in updates.keys()):
raise exception.ObjectActionError(
action='save',
reason='Immutable fields changed')
# These are the only fields we are willing to save with.
# If there are others, ignore them.
updates = {
'name': self.name,
'parent_provider_uuid': self.parent_provider_uuid,
}
self._update_in_db(self._context, self.id, updates)
self.obj_reset_changes()
@classmethod
def get_by_uuid(cls, context, uuid):
@ -1039,7 +1039,7 @@ class ResourceProvider(base.VersionedObject, base.TimestampedObject):
:param uuid: UUID of the provider to search for
"""
rp_rec = _get_provider_by_uuid(context, uuid)
return cls._from_db_object(context, cls(), rp_rec)
return cls._from_db_object(context, cls(context), rp_rec)
def add_inventory(self, inventory):
"""Add one new Inventory to the resource provider.
@ -1048,12 +1048,10 @@ class ResourceProvider(base.VersionedObject, base.TimestampedObject):
already present.
"""
_add_inventory(self._context, self, inventory)
self.obj_reset_changes()
def delete_inventory(self, resource_class):
"""Delete Inventory of provided resource_class."""
_delete_inventory(self._context, self, resource_class)
self.obj_reset_changes()
def set_inventory(self, inv_list):
"""Set all resource provider Inventory to be the provided list."""
@ -1062,7 +1060,6 @@ class ResourceProvider(base.VersionedObject, base.TimestampedObject):
LOG.warning('Resource provider %(uuid)s is now over-'
'capacity for %(resource)s',
{'uuid': uuid, 'resource': rclass})
self.obj_reset_changes()
def update_inventory(self, inventory):
"""Update one existing Inventory of the same resource class.
@ -1074,7 +1071,6 @@ class ResourceProvider(base.VersionedObject, base.TimestampedObject):
LOG.warning('Resource provider %(uuid)s is now over-'
'capacity for %(resource)s',
{'uuid': uuid, 'resource': rclass})
self.obj_reset_changes()
def get_aggregates(self):
"""Get the aggregate uuids associated with this resource provider."""
@ -1101,7 +1097,6 @@ class ResourceProvider(base.VersionedObject, base.TimestampedObject):
associate with the provider.
"""
_set_traits(self._context, self, traits)
self.obj_reset_changes()
@db_api.placement_context_manager.writer
def _create_in_db(self, context, updates):
@ -1291,10 +1286,10 @@ class ResourceProvider(base.VersionedObject, base.TimestampedObject):
uuid = db_resource_provider['uuid']
db_resource_provider['root_provider_uuid'] = uuid
_set_root_provider_id(context, rp_id, rp_id)
for field in resource_provider.fields:
for field in ['id', 'uuid', 'name', 'generation',
'root_provider_uuid', 'parent_provider_uuid',
'updated_at', 'created_at']:
setattr(resource_provider, field, db_resource_provider[field])
resource_provider._context = context
resource_provider.obj_reset_changes()
return resource_provider
@ -1425,12 +1420,25 @@ def _get_providers_with_shared_capacity(ctx, rc_id, amount, member_of=None):
return [r[0] for r in ctx.session.execute(sel)]
@base.VersionedObjectRegistry.register_if(False)
class ResourceProviderList(base.ObjectListBase, base.VersionedObject):
class ResourceProviderList(object):
fields = {
'objects': fields.ListOfObjectsField('ResourceProvider'),
}
def __init__(self, objects=None):
self.objects = objects or []
def __len__(self):
"""List length is a proxy for truthiness."""
return len(self.objects)
def __getitem__(self, index):
return self.objects[index]
# FIXME(cdent): There are versions of this that need context
# and versions that don't. Unify into a super class.
@staticmethod
def _set_objects(context, list_obj, item_cls, db_list):
for db_item in db_list:
list_obj.objects.append(item_cls(context, **db_item))
return list_obj
@staticmethod
@db_api.placement_context_manager.reader
@ -1623,8 +1631,8 @@ class ResourceProviderList(base.ObjectListBase, base.VersionedObject):
:type filters: dict
"""
resource_providers = cls._get_all_by_filters_from_db(context, filters)
return base.obj_make_list(context, cls(context),
ResourceProvider, resource_providers)
return cls._set_objects(context, cls(), ResourceProvider,
resource_providers)
class Inventory(object):
@ -3680,7 +3688,7 @@ def _alloc_candidates_single_provider(ctx, requested_resources, rp_tuples):
# We already added self
if anchor == rp_summary.resource_provider.root_provider_uuid:
continue
req_obj = copy.deepcopy(req_obj)
req_obj = copy.copy(req_obj)
req_obj.anchor_root_provider_uuid = anchor
alloc_requests.append(req_obj)
return alloc_requests, list(summaries.values())
@ -3882,7 +3890,7 @@ def _consolidate_allocation_requests(areqs):
for arr in areq.resource_requests:
key = _rp_rc_key(arr.resource_provider, arr.resource_class)
if key not in arrs_by_rp_rc:
arrs_by_rp_rc[key] = copy.deepcopy(arr)
arrs_by_rp_rc[key] = copy.copy(arr)
else:
arrs_by_rp_rc[key].amount += arr.amount
return AllocationRequest(

@ -26,13 +26,10 @@ from placement.tests.functional import base
def create_provider(context, name, *aggs, **kwargs):
parent = kwargs.get('parent')
root = kwargs.get('root')
uuid = kwargs.get('uuid', getattr(uuids, name))
rp = rp_obj.ResourceProvider(context, name=name, uuid=uuid)
if parent:
rp.parent_provider_uuid = parent
if root:
rp.root_provider_uuid = root
rp.create()
if aggs:
rp.set_aggregates(aggs)

@ -240,15 +240,6 @@ class ResourceProviderTestCase(tb.PlacementDbBaseTestCase):
self.assertEqual(uuidsentinel.parent, rp1.root_provider_uuid)
def test_save_root_provider_failed(self):
"""Test that if we provide a root_provider_uuid value that points to
a resource provider that doesn't exist, we get an ObjectActionError if
we save the object.
"""
self.assertRaises(
exception.ObjectActionError,
self._create_provider, 'rp1', root=uuidsentinel.noexists)
def test_save_unknown_parent_provider(self):
"""Test that if we provide a parent_provider_uuid value that points to
a resource provider that doesn't exist, that we get an

@ -16,6 +16,7 @@ import six
import testtools
import webob
from placement import context
from placement import exception
from placement.handlers import aggregate
from placement.objects import resource_provider
@ -27,7 +28,9 @@ class TestAggregateHandlerErrors(testtools.TestCase):
"""
def test_concurrent_exception_causes_409(self):
rp = resource_provider.ResourceProvider()
fake_context = context.RequestContext(
user_id='fake', project_id='fake')
rp = resource_provider.ResourceProvider(fake_context)
expected_message = ('Update conflict: Another thread concurrently '
'updated the data')
with mock.patch.object(rp, "set_aggregates",

@ -147,29 +147,6 @@ class TestResourceProviderNoDB(_TestCase):
self.assertRaises(exception.ObjectActionError,
obj.create)
def test_create_with_root_provider_uuid_fail(self):
obj = resource_provider.ResourceProvider(
context=self.context,
uuid=_RESOURCE_PROVIDER_UUID,
name=_RESOURCE_PROVIDER_NAME,
root_provider_uuid=_RESOURCE_PROVIDER_UUID,
)
exc = self.assertRaises(exception.ObjectActionError, obj.create)
self.assertIn('root provider UUID cannot be manually set', str(exc))
def test_save_immutable(self):
fields = {
'id': 1,
'uuid': _RESOURCE_PROVIDER_UUID,
'generation': 1,
'root_provider_uuid': _RESOURCE_PROVIDER_UUID,
}
for field in fields:
rp = resource_provider.ResourceProvider(context=self.context)
setattr(rp, field, fields[field])
self.assertRaises(exception.ObjectActionError, rp.save)
class TestProviderSummaryNoDB(_TestCase):
@ -198,7 +175,8 @@ class TestInventoryNoDB(_TestCase):
id=_INVENTORY_DB['id'] + 1,
resource_provider_id=_RESOURCE_PROVIDER_ID)]
mock_get.return_value = expected
rp = resource_provider.ResourceProvider(id=_RESOURCE_PROVIDER_ID,
rp = resource_provider.ResourceProvider(self.context,
id=_RESOURCE_PROVIDER_ID,
uuid=_RESOURCE_PROVIDER_UUID)
objs = resource_provider.InventoryList.get_all_by_resource_provider(
self.context, rp)
@ -208,7 +186,8 @@ class TestInventoryNoDB(_TestCase):
self.assertEqual(_RESOURCE_PROVIDER_ID, objs[0].resource_provider.id)
def test_set_defaults(self):
rp = resource_provider.ResourceProvider(id=_RESOURCE_PROVIDER_ID,
rp = resource_provider.ResourceProvider(self.context,
id=_RESOURCE_PROVIDER_ID,
uuid=_RESOURCE_PROVIDER_UUID)
kwargs = dict(resource_provider=rp,
resource_class=_RESOURCE_CLASS_NAME,
@ -222,7 +201,8 @@ class TestInventoryNoDB(_TestCase):
self.assertEqual(1.0, inv.allocation_ratio)
def test_capacity(self):
rp = resource_provider.ResourceProvider(id=_RESOURCE_PROVIDER_ID,
rp = resource_provider.ResourceProvider(self.context,
id=_RESOURCE_PROVIDER_ID,
uuid=_RESOURCE_PROVIDER_UUID)
kwargs = dict(resource_provider=rp,
resource_class=_RESOURCE_CLASS_NAME,
@ -240,7 +220,8 @@ class TestInventoryNoDB(_TestCase):
class TestInventoryList(_TestCase):
def test_find(self):
rp = resource_provider.ResourceProvider(uuid=uuids.rp_uuid)
rp = resource_provider.ResourceProvider(
self.context, uuid=uuids.rp_uuid)
inv_list = resource_provider.InventoryList(objects=[
resource_provider.Inventory(
resource_provider=rp,
@ -283,7 +264,8 @@ class TestAllocationListNoDB(_TestCase):
return_value=[_ALLOCATION_DB])
def test_get_all_by_resource_provider(self, mock_get_allocations_from_db,
mock_create_consumers):
rp = resource_provider.ResourceProvider(id=_RESOURCE_PROVIDER_ID,
rp = resource_provider.ResourceProvider(self.context,
id=_RESOURCE_PROVIDER_ID,
uuid=uuids.resource_provider)
rp_alloc_list = resource_provider.AllocationList
allocations = rp_alloc_list.get_all_by_resource_provider(
@ -350,20 +332,6 @@ class TestTraits(_TestCase):
synced = resource_provider._TRAITS_SYNCED
self.assertTrue(synced)
@mock.patch('placement.objects.resource_provider.'
'ResourceProvider.obj_reset_changes')
@mock.patch('placement.objects.resource_provider.'
'_set_traits')
def test_set_traits_resets_changes(self, mock_set_traits, mock_reset):
trait = resource_provider.Trait(self.context, name="HW_CPU_X86_AVX2")
traits = resource_provider.TraitList(objects=[trait])
rp = resource_provider.ResourceProvider(self.context, name='cn1',
uuid=uuids.cn1)
rp.set_traits(traits)
mock_set_traits.assert_called_once_with(self.context, rp, traits)
mock_reset.assert_called_once_with()
class TestAllocationCandidatesNoDB(_TestCase):
def test_limit_results(self):

@ -286,11 +286,12 @@ class TestPlacementURLs(testtools.TestCase):
def setUp(self):
super(TestPlacementURLs, self).setUp()
self.resource_provider = rp_obj.ResourceProvider(
name=uuidsentinel.rp_name,
uuid=uuidsentinel.rp_uuid)
fake_context = context.RequestContext(
user_id='fake', project_id='fake')
self.resource_provider = rp_obj.ResourceProvider(
fake_context,
name=uuidsentinel.rp_name,
uuid=uuidsentinel.rp_uuid)
self.resource_class = rp_obj.ResourceClass(
fake_context,
name='CUSTOM_BAREMETAL_GOLD',
@ -824,8 +825,10 @@ class TestPickLastModified(testtools.TestCase):
def setUp(self):
super(TestPickLastModified, self).setUp()
fake_context = context.RequestContext(
user_id='fake', project_id='fake')
self.resource_provider = rp_obj.ResourceProvider(
name=uuidsentinel.rp_name, uuid=uuidsentinel.rp_uuid)
fake_context, name=uuidsentinel.rp_name, uuid=uuidsentinel.rp_uuid)
def test_updated_versus_none(self):
now = timeutils.utcnow(with_timezone=True)

@ -138,15 +138,7 @@ def pick_last_modified(last_modified, obj):
If updated_at is not implemented in `obj` use the current time in UTC.
"""
try:
current_modified = (obj.updated_at or obj.created_at)
# TODO(cdent): NotImplementedError catching can go away when all of
# OVO is gone.
except NotImplementedError:
# If updated_at is not implemented, we are looking at objects that
# have not come from the database, so "now" is the right modified
# time.
current_modified = timeutils.utcnow(with_timezone=True)
current_modified = (obj.updated_at or obj.created_at)
if current_modified is None:
# The object was not loaded from the DB, it was created in
# the current context.

@ -22,7 +22,6 @@ oslo.policy>=1.35.0 # Apache-2.0
oslo.i18n>=3.15.3 # Apache-2.0
oslo.middleware>=3.31.0 # Apache-2.0
oslo.upgradecheck>=0.2.0 # Apache-2.0
oslo.versionedobjects>=1.31.2 # Apache-2.0
os-resource-classes>=0.2.0 # Apache-2.0
os-traits>=0.4.0 # Apache-2.0
microversion-parse>=0.2.1 # Apache-2.0