Skip to content

Commit

Permalink
Add AggregateList.get_by_metadata() query method
Browse files Browse the repository at this point in the history
This query method lets us pull aggregates by key, value,
or key and value.

Change-Id: I1425005f94e2ac22e7e07bc09c7305900a25ca4a
  • Loading branch information
kk7ds committed Mar 28, 2018
1 parent f6ea6e6 commit 9522794
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 11 deletions.
25 changes: 21 additions & 4 deletions nova/objects/aggregate.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,10 +417,14 @@ def _get_by_host_from_db(context, host, key=None):


@db_api.api_context_manager.reader
def _get_by_metadata_key_from_db(context, key):
def _get_by_metadata_from_db(context, key=None, value=None):
assert(key is not None or value is not None)
query = context.session.query(api_models.Aggregate)
query = query.join("_metadata")
query = query.filter(api_models.AggregateMetadata.key == key)
if key is not None:
query = query.filter(api_models.AggregateMetadata.key == key)
if value is not None:
query = query.filter(api_models.AggregateMetadata.value == value)
query = query.options(contains_eager("_metadata"))
query = query.options(joinedload("_hosts"))

Expand All @@ -433,7 +437,8 @@ class AggregateList(base.ObjectListBase, base.NovaObject):
# Version 1.1: Added key argument to get_by_host()
# Aggregate <= version 1.1
# Version 1.2: Added get_by_metadata_key
VERSION = '1.2'
# Version 1.3: Added get_by_metadata
VERSION = '1.3'

fields = {
'objects': fields.ListOfObjectsField('Aggregate'),
Expand Down Expand Up @@ -465,8 +470,20 @@ def get_by_host(cls, context, host, key=None):

@base.remotable_classmethod
def get_by_metadata_key(cls, context, key, hosts=None):
db_aggregates = _get_by_metadata_key_from_db(context, key=key)
db_aggregates = _get_by_metadata_from_db(context, key=key)
if hosts is not None:
db_aggregates = cls._filter_db_aggregates(db_aggregates, hosts)
return base.obj_make_list(context, cls(context), objects.Aggregate,
db_aggregates)

@base.remotable_classmethod
def get_by_metadata(cls, context, key=None, value=None):
"""Return aggregates with a metadata key set to value.
This returns a list of all aggregates that have a metadata key
set to some value. If key is specified, then only values for
that key will qualify.
"""
db_aggregates = _get_by_metadata_from_db(context, key=key, value=value)
return base.obj_make_list(context, cls(context), objects.Aggregate,
db_aggregates)
29 changes: 26 additions & 3 deletions nova/tests/functional/db/test_aggregate.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ def test_aggregate_get_by_metadata_key_from_db(self):
_create_aggregate(self.context,
values={'name': 'aggregate_3'},
metadata={'badkey': 'good'})
rl1 = aggregate_obj._get_by_metadata_key_from_db(self.context,
rl1 = aggregate_obj._get_by_metadata_from_db(self.context,
key='goodkey')
self.assertEqual(2, len(rl1))

Expand All @@ -204,8 +204,8 @@ def test_aggregate_create_in_db_with_metadata(self):
metadata={'goodkey': 'good'})
result = aggregate_obj._aggregate_get_from_db(self.context,
agg.id)
md = aggregate_obj._get_by_metadata_key_from_db(self.context,
key='goodkey')
md = aggregate_obj._get_by_metadata_from_db(self.context,
key='goodkey')
self.assertEqual(len(md), 1)
self.assertEqual(md[0]['id'], agg.id)
self.assertEqual(result.name, fake_create_aggregate['name'])
Expand Down Expand Up @@ -538,3 +538,26 @@ def test_delete_host(self):
result = aggregate_obj.Aggregate.get_by_id(self.context, i)
compare_obj(self, agg, fake_agg)
compare_obj(self, result, fake_agg)

def test_get_by_metadata(self):
agg = aggregate_obj.Aggregate.get_by_id(self.context, 1)
agg.update_metadata({'foo': 'bar'})

agg = aggregate_obj.Aggregate.get_by_id(self.context, 2)
agg.update_metadata({'foo': 'baz',
'fu': 'bar'})

aggs = aggregate_obj.AggregateList.get_by_metadata(
self.context, key='foo', value='bar')
self.assertEqual(1, len(aggs))
self.assertEqual(1, aggs[0].id)

aggs = aggregate_obj.AggregateList.get_by_metadata(
self.context, value='bar')
self.assertEqual(2, len(aggs))
self.assertEqual(set([1, 2]), set([a.id for a in aggs]))

def test_get_by_metadata_from_db_assertion(self):
self.assertRaises(AssertionError,
aggregate_obj._get_by_metadata_from_db,
self.context)
6 changes: 3 additions & 3 deletions nova/tests/unit/objects/test_aggregate.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,22 +192,22 @@ def test_by_host(self, mock_api_get_by_host):
self.assertEqual(1, len(aggs))
self.compare_obj(aggs[0], fake_aggregate, subs=SUBS)

@mock.patch('nova.objects.aggregate._get_by_metadata_key_from_db')
@mock.patch('nova.objects.aggregate._get_by_metadata_from_db')
def test_get_by_metadata_key(self, mock_api_get_by_metadata_key):
mock_api_get_by_metadata_key.return_value = [fake_aggregate]
aggs = aggregate.AggregateList.get_by_metadata_key(
self.context, 'this')
self.assertEqual(1, len(aggs))
self.compare_obj(aggs[0], fake_aggregate, subs=SUBS)

@mock.patch('nova.objects.aggregate._get_by_metadata_key_from_db')
@mock.patch('nova.objects.aggregate._get_by_metadata_from_db')
def test_get_by_metadata_key_and_hosts_no_match(self, get_by_metadata_key):
get_by_metadata_key.return_value = [fake_aggregate]
aggs = aggregate.AggregateList.get_by_metadata_key(
self.context, 'this', hosts=['baz'])
self.assertEqual(0, len(aggs))

@mock.patch('nova.objects.aggregate._get_by_metadata_key_from_db')
@mock.patch('nova.objects.aggregate._get_by_metadata_from_db')
def test_get_by_metadata_key_and_hosts_match(self, get_by_metadata_key):
get_by_metadata_key.return_value = [fake_aggregate]
aggs = aggregate.AggregateList.get_by_metadata_key(
Expand Down
2 changes: 1 addition & 1 deletion nova/tests/unit/objects/test_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -1057,7 +1057,7 @@ def obj_name(cls):
'Agent': '1.0-c0c092abaceb6f51efe5d82175f15eba',
'AgentList': '1.0-5a7380d02c3aaf2a32fc8115ae7ca98c',
'Aggregate': '1.3-f315cb68906307ca2d1cca84d4753585',
'AggregateList': '1.2-fb6e19f3c3a3186b04eceb98b5dadbfa',
'AggregateList': '1.3-3ea55a050354e72ef3306adefa553957',
'BandwidthUsage': '1.2-c6e4c779c7f40f2407e3d70022e3cd1c',
'BandwidthUsageList': '1.2-5fe7475ada6fe62413cbfcc06ec70746',
'BlockDeviceMapping': '1.19-407e75274f48e60a76e56283333c9dbc',
Expand Down

0 comments on commit 9522794

Please sign in to comment.