object-ify availability_zones

This change converts availability_zones to use the Aggregate and
Service objects instead of direct database access.

Related to blueprint compute-manager-objects-juno

Change-Id: I2ec7373f063ed728dde2af3b7c8259f4391885bc
This commit is contained in:
melanie witt 2014-06-25 04:33:40 +00:00
parent a167654eb3
commit a15fa17efc
3 changed files with 52 additions and 18 deletions

View File

@ -15,9 +15,11 @@
"""Availability zone helper functions."""
import collections
from oslo.config import cfg
from nova import db
from nova import objects
from nova.openstack.common import memorycache
# NOTE(vish): azs don't change that often, so cache them for an hour to
@ -61,11 +63,34 @@ def _make_cache_key(host):
return "azcache-%s" % host.encode('utf-8')
def _build_metadata_by_host(aggregates, hosts=None):
if hosts and not isinstance(hosts, set):
hosts = set(hosts)
metadata = collections.defaultdict(set)
for aggregate in aggregates:
for host in aggregate.hosts:
if hosts and host not in hosts:
continue
metadata[host].add(aggregate.metadata.values()[0])
return metadata
def _build_metadata_by_key(aggregates):
metadata = collections.defaultdict(set)
for aggregate in aggregates:
for key, value in aggregate.metadata.iteritems():
metadata[key].add(value)
return metadata
def set_availability_zones(context, services):
# Makes sure services isn't a sqlalchemy object
services = [dict(service.iteritems()) for service in services]
metadata = db.aggregate_host_get_by_metadata_key(context,
key='availability_zone')
hosts = set([service['host'] for service in services])
aggregates = objects.AggregateList.get_by_metadata_key(context,
'availability_zone', hosts=hosts)
metadata = _build_metadata_by_host(aggregates, hosts=hosts)
# gather all of the availability zones associated with a service host
for service in services:
az = CONF.internal_service_availability_zone
if service['topic'] == "compute":
@ -85,8 +110,9 @@ def get_host_availability_zone(context, host, conductor_api=None):
metadata = conductor_api.aggregate_metadata_get_by_host(
context, host, key='availability_zone')
else:
metadata = db.aggregate_metadata_get_by_host(
context, host, key='availability_zone')
aggregates = objects.AggregateList.get_by_host(context, host,
key='availability_zone')
metadata = _build_metadata_by_key(aggregates)
if 'availability_zone' in metadata:
az = list(metadata['availability_zone'])[0]
else:
@ -114,7 +140,7 @@ def get_availability_zones(context, get_only_available=False,
:param with_hosts: whether to return hosts part of the AZs
:type with_hosts: bool
"""
enabled_services = db.service_get_all(context, False)
enabled_services = objects.ServiceList.get_all(context, disabled=False)
enabled_services = set_availability_zones(context, enabled_services)
available_zones = []
@ -130,7 +156,7 @@ def get_availability_zones(context, get_only_available=False,
available_zones = list(_available_zones.items())
if not get_only_available:
disabled_services = db.service_get_all(context, True)
disabled_services = objects.ServiceList.get_all(context, disabled=True)
disabled_services = set_availability_zones(context, disabled_services)
not_available_zones = []
azs = available_zones if not with_hosts else dict(available_zones)

View File

@ -25,18 +25,20 @@ from nova import servicegroup
from nova import test
from nova.tests.api.openstack import fakes
from nova.tests import matchers
from nova.tests.objects import test_service
def fake_service_get_all(context, disabled=None):
def __fake_service(binary, availability_zone,
created_at, updated_at, host, disabled):
return {'binary': binary,
'availability_zone': availability_zone,
'available_zones': availability_zone,
'created_at': created_at,
'updated_at': updated_at,
'host': host,
'disabled': disabled}
return dict(test_service.fake_service,
binary=binary,
availability_zone=availability_zone,
available_zones=availability_zone,
created_at=created_at,
updated_at=updated_at,
host=host,
disabled=disabled)
if disabled:
return [__fake_service("nova-compute", "zone-2",

View File

@ -16,6 +16,7 @@ import mock
from nova import db
from nova import exception
from nova.objects import aggregate
from nova.objects import service
from nova.openstack.common import timeutils
from nova.tests.objects import test_compute_node
@ -163,12 +164,17 @@ class _TestServiceObject(object):
def test_get_all_with_az(self):
self.mox.StubOutWithMock(db, 'service_get_all')
self.mox.StubOutWithMock(db, 'aggregate_host_get_by_metadata_key')
self.mox.StubOutWithMock(aggregate.AggregateList,
'get_by_metadata_key')
db.service_get_all(self.context, disabled=None).AndReturn(
[dict(fake_service, topic='compute')])
db.aggregate_host_get_by_metadata_key(
self.context, key='availability_zone').AndReturn(
{fake_service['host']: ['test-az']})
agg = aggregate.Aggregate()
agg.name = 'foo'
agg.metadata = {'availability_zone': 'test-az'}
agg.create(self.context)
agg.hosts = [fake_service['host']]
aggregate.AggregateList.get_by_metadata_key(self.context,
'availability_zone', hosts=set(agg.hosts)).AndReturn([agg])
self.mox.ReplayAll()
services = service.ServiceList.get_all(self.context, set_zones=True)
self.assertEqual(1, len(services))