Merge "Improve performance for checking hosts AZs"

This commit is contained in:
Jenkins 2014-06-20 18:57:10 +00:00 committed by Gerrit Code Review
commit 9d88e2a568
4 changed files with 62 additions and 16 deletions

View File

@ -103,32 +103,50 @@ def update_host_availability_zone_cache(context, host, availability_zone=None):
cache.set(cache_key, availability_zone, AZ_CACHE_SECONDS)
def get_availability_zones(context, get_only_available=False):
def get_availability_zones(context, get_only_available=False,
with_hosts=False):
"""Return available and unavailable zones on demand.
:param get_only_available: flag to determine whether to return
available zones only, default False indicates return both
available zones and not available zones, True indicates return
available zones only
:param get_only_available: flag to determine whether to return
available zones only, default False indicates return both
available zones and not available zones, True indicates return
available zones only
: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 = set_availability_zones(context, enabled_services)
available_zones = []
for zone in [service['availability_zone'] for service
in enabled_services]:
if zone not in available_zones:
for (zone, host) in [(service['availability_zone'], service['host'])
for service in enabled_services]:
if not with_hosts and zone not in available_zones:
available_zones.append(zone)
elif with_hosts:
_available_zones = dict(available_zones)
zone_hosts = _available_zones.setdefault(zone, set())
zone_hosts.add(host)
# .items() returns a view in Py3, casting it to list for Py2 compat
available_zones = list(_available_zones.items())
if not get_only_available:
disabled_services = db.service_get_all(context, True)
disabled_services = set_availability_zones(context, disabled_services)
not_available_zones = []
zones = [service['availability_zone'] for service in disabled_services
if service['availability_zone'] not in available_zones]
for zone in zones:
if zone not in not_available_zones:
azs = available_zones if not with_hosts else dict(available_zones)
zones = [(service['availability_zone'], service['host'])
for service in disabled_services
if service['availability_zone'] not in azs]
for (zone, host) in zones:
if not with_hosts and zone not in not_available_zones:
not_available_zones.append(zone)
elif with_hosts:
_not_available_zones = dict(not_available_zones)
zone_hosts = _not_available_zones.setdefault(zone, set())
zone_hosts.add(host)
# .items() returns a view in Py3, casting it to list for Py2
# compat
not_available_zones = list(_not_available_zones.items())
return (available_zones, not_available_zones)
else:
return available_zones

View File

@ -3359,9 +3359,17 @@ class AggregateAPI(base.Base):
"""
if 'availability_zone' in metadata:
_hosts = hosts or aggregate.hosts
zones, not_zones = availability_zones.get_availability_zones(
context, with_hosts=True)
for host in _hosts:
host_az = availability_zones.get_host_availability_zone(
context, host)
# NOTE(sbauza): Host can only be in one AZ, so let's take only
# the first element
host_azs = [az for (az, az_hosts) in zones
if host in az_hosts
and az != CONF.internal_service_availability_zone]
host_az = host_azs.pop()
if host_azs:
LOG.warning(_("More than 1 AZ for host %s"), host)
if host_az == CONF.default_availability_zone:
# NOTE(sbauza): Aggregate with AZ set to default AZ can
# exist, we need to check

View File

@ -9568,8 +9568,20 @@ class ComputeAPIAggrTestCase(BaseTestCase):
self.mox.StubOutWithMock(availability_zones,
'update_host_availability_zone_cache')
availability_zones.update_host_availability_zone_cache(self.context,
fake_host)
def _stub_update_host_avail_zone_cache(host, az=None):
if az is not None:
availability_zones.update_host_availability_zone_cache(
self.context, host, az)
else:
availability_zones.update_host_availability_zone_cache(
self.context, host)
for avail_zone, hosts in six.iteritems(values):
for host in hosts:
_stub_update_host_avail_zone_cache(
host, CONF.default_availability_zone)
_stub_update_host_avail_zone_cache(fake_host)
self.mox.ReplayAll()
fake_notifier.NOTIFICATIONS = []

View File

@ -226,6 +226,14 @@ class AvailabilityZoneTestCases(test.TestCase):
self.assertEqual(zones, ['nova-test', 'nova-test2'])
zones, not_zones = az.get_availability_zones(self.context,
with_hosts=True)
self.assertEqual(zones, [(u'nova-test2', set([u'host3'])),
(u'nova-test', set([u'host1']))])
self.assertEqual(not_zones, [(u'nova-test3', set([u'host4'])),
(u'nova', set([u'host5']))])
def test_get_instance_availability_zone_default_value(self):
"""Test get right availability zone by given an instance."""
fake_inst_id = 162