Add AggregateList.get_by_metadata() query method
This query method lets us pull aggregates by key, value, or key and value. Change-Id: I1425005f94e2ac22e7e07bc09c7305900a25ca4a
This commit is contained in:
@@ -417,10 +417,14 @@ def _get_by_host_from_db(context, host, key=None):
|
|||||||
|
|
||||||
|
|
||||||
@db_api.api_context_manager.reader
|
@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 = context.session.query(api_models.Aggregate)
|
||||||
query = query.join("_metadata")
|
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(contains_eager("_metadata"))
|
||||||
query = query.options(joinedload("_hosts"))
|
query = query.options(joinedload("_hosts"))
|
||||||
|
|
||||||
@@ -433,7 +437,8 @@ class AggregateList(base.ObjectListBase, base.NovaObject):
|
|||||||
# Version 1.1: Added key argument to get_by_host()
|
# Version 1.1: Added key argument to get_by_host()
|
||||||
# Aggregate <= version 1.1
|
# Aggregate <= version 1.1
|
||||||
# Version 1.2: Added get_by_metadata_key
|
# Version 1.2: Added get_by_metadata_key
|
||||||
VERSION = '1.2'
|
# Version 1.3: Added get_by_metadata
|
||||||
|
VERSION = '1.3'
|
||||||
|
|
||||||
fields = {
|
fields = {
|
||||||
'objects': fields.ListOfObjectsField('Aggregate'),
|
'objects': fields.ListOfObjectsField('Aggregate'),
|
||||||
@@ -465,8 +470,20 @@ class AggregateList(base.ObjectListBase, base.NovaObject):
|
|||||||
|
|
||||||
@base.remotable_classmethod
|
@base.remotable_classmethod
|
||||||
def get_by_metadata_key(cls, context, key, hosts=None):
|
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:
|
if hosts is not None:
|
||||||
db_aggregates = cls._filter_db_aggregates(db_aggregates, hosts)
|
db_aggregates = cls._filter_db_aggregates(db_aggregates, hosts)
|
||||||
return base.obj_make_list(context, cls(context), objects.Aggregate,
|
return base.obj_make_list(context, cls(context), objects.Aggregate,
|
||||||
db_aggregates)
|
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)
|
||||||
|
@@ -181,7 +181,7 @@ class AggregateObjectDbTestCase(test.TestCase):
|
|||||||
_create_aggregate(self.context,
|
_create_aggregate(self.context,
|
||||||
values={'name': 'aggregate_3'},
|
values={'name': 'aggregate_3'},
|
||||||
metadata={'badkey': 'good'})
|
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')
|
key='goodkey')
|
||||||
self.assertEqual(2, len(rl1))
|
self.assertEqual(2, len(rl1))
|
||||||
|
|
||||||
@@ -204,8 +204,8 @@ class AggregateObjectDbTestCase(test.TestCase):
|
|||||||
metadata={'goodkey': 'good'})
|
metadata={'goodkey': 'good'})
|
||||||
result = aggregate_obj._aggregate_get_from_db(self.context,
|
result = aggregate_obj._aggregate_get_from_db(self.context,
|
||||||
agg.id)
|
agg.id)
|
||||||
md = aggregate_obj._get_by_metadata_key_from_db(self.context,
|
md = aggregate_obj._get_by_metadata_from_db(self.context,
|
||||||
key='goodkey')
|
key='goodkey')
|
||||||
self.assertEqual(len(md), 1)
|
self.assertEqual(len(md), 1)
|
||||||
self.assertEqual(md[0]['id'], agg.id)
|
self.assertEqual(md[0]['id'], agg.id)
|
||||||
self.assertEqual(result.name, fake_create_aggregate['name'])
|
self.assertEqual(result.name, fake_create_aggregate['name'])
|
||||||
@@ -538,3 +538,26 @@ class AggregateObjectTestCase(test.TestCase):
|
|||||||
result = aggregate_obj.Aggregate.get_by_id(self.context, i)
|
result = aggregate_obj.Aggregate.get_by_id(self.context, i)
|
||||||
compare_obj(self, agg, fake_agg)
|
compare_obj(self, agg, fake_agg)
|
||||||
compare_obj(self, result, 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)
|
||||||
|
@@ -192,7 +192,7 @@ class _TestAggregateObject(object):
|
|||||||
self.assertEqual(1, len(aggs))
|
self.assertEqual(1, len(aggs))
|
||||||
self.compare_obj(aggs[0], fake_aggregate, subs=SUBS)
|
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):
|
def test_get_by_metadata_key(self, mock_api_get_by_metadata_key):
|
||||||
mock_api_get_by_metadata_key.return_value = [fake_aggregate]
|
mock_api_get_by_metadata_key.return_value = [fake_aggregate]
|
||||||
aggs = aggregate.AggregateList.get_by_metadata_key(
|
aggs = aggregate.AggregateList.get_by_metadata_key(
|
||||||
@@ -200,14 +200,14 @@ class _TestAggregateObject(object):
|
|||||||
self.assertEqual(1, len(aggs))
|
self.assertEqual(1, len(aggs))
|
||||||
self.compare_obj(aggs[0], fake_aggregate, subs=SUBS)
|
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):
|
def test_get_by_metadata_key_and_hosts_no_match(self, get_by_metadata_key):
|
||||||
get_by_metadata_key.return_value = [fake_aggregate]
|
get_by_metadata_key.return_value = [fake_aggregate]
|
||||||
aggs = aggregate.AggregateList.get_by_metadata_key(
|
aggs = aggregate.AggregateList.get_by_metadata_key(
|
||||||
self.context, 'this', hosts=['baz'])
|
self.context, 'this', hosts=['baz'])
|
||||||
self.assertEqual(0, len(aggs))
|
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):
|
def test_get_by_metadata_key_and_hosts_match(self, get_by_metadata_key):
|
||||||
get_by_metadata_key.return_value = [fake_aggregate]
|
get_by_metadata_key.return_value = [fake_aggregate]
|
||||||
aggs = aggregate.AggregateList.get_by_metadata_key(
|
aggs = aggregate.AggregateList.get_by_metadata_key(
|
||||||
|
@@ -1057,7 +1057,7 @@ object_data = {
|
|||||||
'Agent': '1.0-c0c092abaceb6f51efe5d82175f15eba',
|
'Agent': '1.0-c0c092abaceb6f51efe5d82175f15eba',
|
||||||
'AgentList': '1.0-5a7380d02c3aaf2a32fc8115ae7ca98c',
|
'AgentList': '1.0-5a7380d02c3aaf2a32fc8115ae7ca98c',
|
||||||
'Aggregate': '1.3-f315cb68906307ca2d1cca84d4753585',
|
'Aggregate': '1.3-f315cb68906307ca2d1cca84d4753585',
|
||||||
'AggregateList': '1.2-fb6e19f3c3a3186b04eceb98b5dadbfa',
|
'AggregateList': '1.3-3ea55a050354e72ef3306adefa553957',
|
||||||
'BandwidthUsage': '1.2-c6e4c779c7f40f2407e3d70022e3cd1c',
|
'BandwidthUsage': '1.2-c6e4c779c7f40f2407e3d70022e3cd1c',
|
||||||
'BandwidthUsageList': '1.2-5fe7475ada6fe62413cbfcc06ec70746',
|
'BandwidthUsageList': '1.2-5fe7475ada6fe62413cbfcc06ec70746',
|
||||||
'BlockDeviceMapping': '1.19-407e75274f48e60a76e56283333c9dbc',
|
'BlockDeviceMapping': '1.19-407e75274f48e60a76e56283333c9dbc',
|
||||||
|
Reference in New Issue
Block a user