Merge "Fix logic for checking if az can be updated"

This commit is contained in:
Jenkins 2015-04-28 21:31:39 +00:00 committed by Gerrit Code Review
commit 9d77ab1290
3 changed files with 16 additions and 67 deletions

View File

@ -3578,34 +3578,17 @@ class AggregateAPI(base.Base):
""" """
if 'availability_zone' in metadata: if 'availability_zone' in metadata:
_hosts = hosts or aggregate.hosts _hosts = hosts or aggregate.hosts
zones, not_zones = availability_zones.get_availability_zones( host_aggregates = objects.AggregateList.get_by_metadata_key(
context, with_hosts=True) context, 'availability_zone', hosts=_hosts)
for host in _hosts: conflicting_azs = [
# NOTE(sbauza): Host can only be in one AZ, so let's take only agg.availability_zone for agg in host_aggregates
# the first element if agg.availability_zone != metadata['availability_zone']
host_azs = [az for (az, az_hosts) in zones and agg.id != aggregate.id]
if host in az_hosts if conflicting_azs:
and az != CONF.internal_service_availability_zone] msg = _("One or more hosts already in availability zone(s) "
host_az = host_azs.pop() "%s") % conflicting_azs
if host_azs: self._raise_invalid_aggregate_exc(action_name, aggregate.id,
LOG.warning(_LW("More than 1 AZ for host %s"), host) msg)
if host_az == CONF.default_availability_zone:
# NOTE(sbauza): Aggregate with AZ set to default AZ can
# exist, we need to check
host_aggs = objects.AggregateList.get_by_host(
context, host, key='availability_zone')
default_aggs = [agg for agg in host_aggs
if agg['metadata'].get(
'availability_zone'
) == CONF.default_availability_zone]
else:
default_aggs = []
if (host_az != aggregate.metadata.get('availability_zone') and
(host_az != CONF.default_availability_zone or
len(default_aggs) != 0)):
self._check_az_for_host(
metadata, host_az, aggregate.id,
action_name=action_name)
def _raise_invalid_aggregate_exc(self, action_name, aggregate_id, reason): def _raise_invalid_aggregate_exc(self, action_name, aggregate_id, reason):
if action_name == AGGREGATE_ACTION_ADD: if action_name == AGGREGATE_ACTION_ADD:
@ -3624,27 +3607,6 @@ class AggregateAPI(base.Base):
raise exception.NovaException( raise exception.NovaException(
_("Unexpected aggregate action %s") % action_name) _("Unexpected aggregate action %s") % action_name)
def _check_az_for_host(self, aggregate_meta, host_az, aggregate_id,
action_name=AGGREGATE_ACTION_ADD):
# NOTE(mtreinish) The availability_zone key returns a set of
# zones so loop over each zone. However there should only
# ever be one zone in the set because an aggregate can only
# have a single availability zone set at one time.
if isinstance(aggregate_meta["availability_zone"], six.string_types):
azs = set([aggregate_meta["availability_zone"]])
else:
azs = aggregate_meta["availability_zone"]
for aggregate_az in azs:
# NOTE(mtreinish) Ensure that the aggregate_az is not none
# if it is none then that is just a regular aggregate and
# it is valid to have a host in multiple aggregates.
if aggregate_az and aggregate_az != host_az:
msg = _("Host already in availability zone "
"%s") % host_az
self._raise_invalid_aggregate_exc(action_name,
aggregate_id, msg)
def _update_az_cache_for_host(self, context, host_name, aggregate_meta): def _update_az_cache_for_host(self, context, host_name, aggregate_meta):
# Update the availability_zone cache to avoid getting wrong # Update the availability_zone cache to avoid getting wrong
# availability_zone in cache retention time when add/remove # availability_zone in cache retention time when add/remove
@ -3664,11 +3626,9 @@ class AggregateAPI(base.Base):
# validates the host; ComputeHostNotFound is raised if invalid # validates the host; ComputeHostNotFound is raised if invalid
objects.Service.get_by_compute_host(context, host_name) objects.Service.get_by_compute_host(context, host_name)
metadata = self.db.aggregate_metadata_get_by_metadata_key(
context, aggregate_id, 'availability_zone')
aggregate = objects.Aggregate.get_by_id(context, aggregate_id) aggregate = objects.Aggregate.get_by_id(context, aggregate_id)
self.is_safe_to_update_az(context, metadata, hosts=[host_name], self.is_safe_to_update_az(context, aggregate.metadata,
aggregate=aggregate) hosts=[host_name], aggregate=aggregate)
aggregate.add_host(host_name) aggregate.add_host(host_name)
self.scheduler_client.update_aggregates(context, [aggregate]) self.scheduler_client.update_aggregates(context, [aggregate])

View File

@ -194,7 +194,7 @@ 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 = db.aggregate_get_by_metadata_key(context, key=key) db_aggregates = db.aggregate_get_by_metadata_key(context, key=key)
if hosts: 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)

View File

@ -10319,19 +10319,8 @@ class ComputeAPIAggrTestCase(BaseTestCase):
self.mox.StubOutWithMock(availability_zones, self.mox.StubOutWithMock(availability_zones,
'update_host_availability_zone_cache') 'update_host_availability_zone_cache')
def _stub_update_host_avail_zone_cache(host, az=None): availability_zones.update_host_availability_zone_cache(self.context,
if az is not None: fake_host)
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 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() self.mox.ReplayAll()
fake_notifier.NOTIFICATIONS = [] fake_notifier.NOTIFICATIONS = []