Merge "rp: Remove RP.get_traits() method"

This commit is contained in:
Zuul 2017-10-27 14:48:58 +00:00 committed by Gerrit Code Review
commit 4c123db903
3 changed files with 57 additions and 31 deletions

View File

@ -198,12 +198,21 @@ def list_traits_for_resource_provider(req):
context = req.environ['placement.context']
uuid = util.wsgi_path_item(req.environ, 'uuid')
resource_provider = rp_obj.ResourceProvider.get_by_uuid(
context, uuid)
# Resource provider object is needed for two things: If it is
# NotFound we'll get a 404 here, which needs to happen because
# get_all_by_resource_provider can return an empty list.
# It is also needed for the generation, used in the outgoing
# representation.
try:
rp = rp_obj.ResourceProvider.get_by_uuid(context, uuid)
except exception.NotFound as exc:
raise webob.exc.HTTPNotFound(
_("No resource provider with uuid %(uuid)s found: %(error)s") %
{'uuid': uuid, 'error': exc})
response_body = _serialize_traits(resource_provider.get_traits())
response_body[
"resource_provider_generation"] = resource_provider.generation
traits = rp_obj.TraitList.get_all_by_resource_provider(context, rp)
response_body = _serialize_traits(traits)
response_body["resource_provider_generation"] = rp.generation
req.response.status = 200
req.response.body = encodeutils.to_utf8(jsonutils.dumps(response_body))

View File

@ -482,6 +482,19 @@ def _set_aggregates(context, rp_id, provided_aggregates):
conn.execute(insert_aggregates)
@db_api.api_context_manager.reader
def _get_traits_by_provider_id(context, rp_id):
t = sa.alias(_TRAIT_TBL, name='t')
rpt = sa.alias(_RP_TRAIT_TBL, name='rpt')
conn = context.session.connection()
join_cond = sa.and_(t.c.id == rpt.c.trait_id,
rpt.c.resource_provider_id == rp_id)
join = sa.join(t, rpt, join_cond)
sel = sa.select([t.c.id, t.c.name]).select_from(join)
return [dict(r) for r in conn.execute(sel).fetchall()]
@base.NovaObjectRegistry.register_if(False)
class ResourceProvider(base.NovaObject):
@ -620,35 +633,20 @@ class ResourceProvider(base.NovaObject):
resource_provider.obj_reset_changes()
return resource_provider
@staticmethod
@db_api.api_context_manager.reader
def _get_traits_from_db(context, _id):
db_traits = context.session.query(models.Trait).join(
models.ResourceProviderTrait,
sa.and_(
models.Trait.id == models.ResourceProviderTrait.trait_id,
models.ResourceProviderTrait.resource_provider_id == _id
)).all()
return db_traits
@base.remotable
def get_traits(self):
db_traits = self._get_traits_from_db(self._context, self.id)
return base.obj_make_list(self._context, TraitList(self._context),
Trait, db_traits)
@staticmethod
@db_api.api_context_manager.writer
def _set_traits_to_db(context, rp, _id, traits):
existing_traits = ResourceProvider._get_traits_from_db(context, _id)
existing_traits = _get_traits_by_provider_id(context, _id)
traits_dict = {trait.name: trait for trait in traits}
existing_traits_dict = {trait.name: trait for trait in existing_traits}
existing_traits_dict = {
trait['name']: trait for trait in existing_traits
}
to_add_names = (set(traits_dict.keys()) -
set(existing_traits_dict.keys()))
to_delete_names = (set(existing_traits_dict.keys()) -
set(traits_dict.keys()))
to_delete_ids = [existing_traits_dict[name].id
to_delete_ids = [existing_traits_dict[name]['id']
for name in to_delete_names]
conn = context.session.connection()
@ -2287,6 +2285,14 @@ class TraitList(base.ObjectListBase, base.NovaObject):
db_traits = cls._get_all_from_db(context, filters)
return base.obj_make_list(context, cls(context), Trait, db_traits)
@classmethod
def get_all_by_resource_provider(cls, context, rp):
"""Returns a TraitList containing Trait objects for any trait
associated with the supplied resource provider.
"""
db_traits = _get_traits_by_provider_id(context, rp.id)
return base.obj_make_list(context, cls(context), Trait, db_traits)
@base.NovaObjectRegistry.register_if(False)
class AllocationRequestResource(base.NovaObject):

View File

@ -1782,7 +1782,9 @@ class ResourceProviderTraitTestCase(ResourceProviderBaseCase):
trait_objs.append(t)
rp.set_traits(trait_objs)
self._assert_traits(trait_names, rp.get_traits())
rp_traits = rp_obj.TraitList.get_all_by_resource_provider(self.ctx, rp)
self._assert_traits(trait_names, rp_traits)
self.assertEqual(rp.generation, generation + 1)
generation = rp.generation
@ -1791,7 +1793,8 @@ class ResourceProviderTraitTestCase(ResourceProviderBaseCase):
filters={'name_in': trait_names})
self._assert_traits(trait_names, updated_traits)
rp.set_traits(updated_traits)
self._assert_traits(trait_names, rp.get_traits())
rp_traits = rp_obj.TraitList.get_all_by_resource_provider(self.ctx, rp)
self._assert_traits(trait_names, rp_traits)
self.assertEqual(rp.generation, generation + 1)
def test_set_traits_for_correct_resource_provider(self):
@ -1823,14 +1826,22 @@ class ResourceProviderTraitTestCase(ResourceProviderBaseCase):
rp2.set_traits([t])
# Ensure the association
self._assert_traits(['CUSTOM_TRAIT_A'], rp1.get_traits())
self._assert_traits(['CUSTOM_TRAIT_A'], rp2.get_traits())
rp1_traits = rp_obj.TraitList.get_all_by_resource_provider(
self.ctx, rp1)
rp2_traits = rp_obj.TraitList.get_all_by_resource_provider(
self.ctx, rp2)
self._assert_traits(['CUSTOM_TRAIT_A'], rp1_traits)
self._assert_traits(['CUSTOM_TRAIT_A'], rp2_traits)
# Detach the trait from one of ResourceProvider, and ensure the
# trait association with another ResourceProvider still exists.
rp1.set_traits([])
self._assert_traits([], rp1.get_traits())
self._assert_traits(['CUSTOM_TRAIT_A'], rp2.get_traits())
rp1_traits = rp_obj.TraitList.get_all_by_resource_provider(
self.ctx, rp1)
rp2_traits = rp_obj.TraitList.get_all_by_resource_provider(
self.ctx, rp2)
self._assert_traits([], rp1_traits)
self._assert_traits(['CUSTOM_TRAIT_A'], rp2_traits)
def test_trait_delete_in_use(self):
rp = rp_obj.ResourceProvider(