add get_by_metadata_key to AggregateList object

This change adds the get_by_metadata_key function to the AggregateList object
and the aggregate_get_by_metadata_key function to the DB API.

Previously, the only DB API function available for finding aggregates matching
a metadata key returned a dictionary of aggregated metadata. The
aggregate_get_by_metadata_key function returns all rows matching the specified
metadata key, and is called by the existing aggregate_host_get_by_metadata_key
DB API function.

The get_by_metadata_key function returns a list of Aggregate objects matching
the specified metadata key.

Related to blueprint compute-manager-objects-juno

Change-Id: If50c9f613dd192ab44577f26a81dd5b40e3a7af7
This commit is contained in:
melanie witt 2014-06-24 23:08:20 +00:00
parent b8e3902881
commit a167654eb3
5 changed files with 67 additions and 9 deletions

View File

@ -1769,6 +1769,10 @@ def aggregate_host_get_by_metadata_key(context, key):
return IMPL.aggregate_host_get_by_metadata_key(context, key)
def aggregate_get_by_metadata_key(context, key):
return IMPL.aggregate_get_by_metadata_key(context, key)
def aggregate_update(context, aggregate_id, values):
"""Update the attributes of an aggregates.

View File

@ -5094,13 +5094,7 @@ def aggregate_metadata_get_by_metadata_key(context, aggregate_id, key):
def aggregate_host_get_by_metadata_key(context, key):
query = model_query(context, models.Aggregate)
query = query.join("_metadata")
query = query.filter(models.AggregateMetadata.key == key)
query = query.options(contains_eager("_metadata"))
query = query.options(joinedload("_hosts"))
rows = query.all()
rows = aggregate_get_by_metadata_key(context, key)
metadata = collections.defaultdict(set)
for agg in rows:
for agghost in agg._hosts:
@ -5108,6 +5102,19 @@ def aggregate_host_get_by_metadata_key(context, key):
return dict(metadata)
def aggregate_get_by_metadata_key(context, key):
"""Return rows that match metadata key.
:param key Matches metadata key.
"""
query = model_query(context, models.Aggregate)
query = query.join("_metadata")
query = query.filter(models.AggregateMetadata.key == key)
query = query.options(contains_eager("_metadata"))
query = query.options(joinedload("_hosts"))
return query.all()
def aggregate_update(context, aggregate_id, values):
session = get_session()

View File

@ -151,7 +151,8 @@ class AggregateList(base.ObjectListBase, base.NovaObject):
# Version 1.0: Initial version
# Version 1.1: Added key argument to get_by_host()
# Aggregate <= version 1.1
VERSION = '1.1'
# Version 1.2: Added get_by_metadata_key
VERSION = '1.2'
fields = {
'objects': fields.ListOfObjectsField('Aggregate'),
@ -160,8 +161,21 @@ class AggregateList(base.ObjectListBase, base.NovaObject):
'1.0': '1.1',
'1.1': '1.1',
# NOTE(danms): Aggregate was at 1.1 before we added this
'1.2': '1.1',
}
@classmethod
def _filter_db_aggregates(cls, db_aggregates, hosts):
if not isinstance(hosts, set):
hosts = set(hosts)
filtered_aggregates = []
for db_aggregate in db_aggregates:
for host in db_aggregate['hosts']:
if host in hosts:
filtered_aggregates.append(db_aggregate)
break
return filtered_aggregates
@base.remotable_classmethod
def get_all(cls, context):
db_aggregates = db.aggregate_get_all(context)
@ -173,3 +187,11 @@ class AggregateList(base.ObjectListBase, base.NovaObject):
db_aggregates = db.aggregate_get_by_host(context, host, key=key)
return base.obj_make_list(context, cls(context), objects.Aggregate,
db_aggregates)
@base.remotable_classmethod
def get_by_metadata_key(cls, context, key, hosts=None):
db_aggregates = db.aggregate_get_by_metadata_key(context, key=key)
if hosts:
db_aggregates = cls._filter_db_aggregates(db_aggregates, hosts)
return base.obj_make_list(context, cls(context), objects.Aggregate,
db_aggregates)

View File

@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import mock
from nova import db
from nova import exception
from nova.objects import aggregate
@ -163,6 +165,29 @@ class _TestAggregateObject(object):
self.assertEqual(1, len(aggs))
self.compare_obj(aggs[0], fake_aggregate, subs=SUBS)
@mock.patch('nova.db.aggregate_get_by_metadata_key')
def test_get_by_metadata_key(self, get_by_metadata_key):
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.db.aggregate_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]
aggs = aggregate.AggregateList.get_by_metadata_key(
self.context, 'this', hosts=['baz'])
self.assertEqual(0, len(aggs))
@mock.patch('nova.db.aggregate_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]
aggs = aggregate.AggregateList.get_by_metadata_key(
self.context, 'this', hosts=['foo', 'bar'])
self.assertEqual(1, len(aggs))
self.compare_obj(aggs[0], fake_aggregate, subs=SUBS)
class TestAggregateObject(test_objects._LocalTest,
_TestAggregateObject):

View File

@ -895,7 +895,7 @@ object_data = {
'Agent': '1.0-c4ff8a833aee8ae44ab8aed1a171273d',
'AgentList': '1.0-f8b860e1f2ce80e676ba1a37ddf86e4f',
'Aggregate': '1.1-f5d477be06150529a9b2d27cc49030b5',
'AggregateList': '1.1-3e67b6a4840b19c797504cc6056b27ff',
'AggregateList': '1.2-504137b7ec3855b00d01f165dcebc23e',
'BlockDeviceMapping': '1.1-9968ffe513e7672484b0f528b034cd0f',
'BlockDeviceMappingList': '1.2-d6d7df540ca149dda78b22b4b10bdef3',
'ComputeNode': '1.3-b3b8935a99ca48621dc9ba271d5ed668',