diff options
-rw-r--r-- | nova/api/ec2/cloud.py | 80 | ||||
-rw-r--r-- | nova/tests/api/ec2/test_cloud.py | 21 |
2 files changed, 73 insertions, 28 deletions
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index c252684a3..76528d6ec 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -208,20 +208,29 @@ class CloudController(object): else: return self._describe_availability_zones(context, **kwargs) - def _describe_availability_zones(self, context, **kwargs): - ctxt = context.elevated() - enabled_services = db.service_get_all(ctxt, False) - disabled_services = db.service_get_all(ctxt, True) + def _get_zones(self, context): + """Return available and unavailable zones.""" + enabled_services = db.service_get_all(context, False) + disabled_services = db.service_get_all(context, True) + available_zones = [] for zone in [service.availability_zone for service in enabled_services]: if not zone in available_zones: available_zones.append(zone) + not_available_zones = [] for zone in [service.availability_zone for service in disabled_services if not service['availability_zone'] in available_zones]: if not zone in not_available_zones: not_available_zones.append(zone) + + return (available_zones, not_available_zones) + + def _describe_availability_zones(self, context, **kwargs): + ctxt = context.elevated() + available_zones, not_available_zones = self._get_zones(ctxt) + result = [] for zone in available_zones: result.append({'zoneName': zone, @@ -232,30 +241,45 @@ class CloudController(object): return {'availabilityZoneInfo': result} def _describe_availability_zones_verbose(self, context, **kwargs): - rv = {'availabilityZoneInfo': [{'zoneName': 'nova', - 'zoneState': 'available'}]} - - services = db.service_get_all(context, False) - hosts = [] - for host in [service['host'] for service in services]: - if not host in hosts: - hosts.append(host) - for host in hosts: - rv['availabilityZoneInfo'].append({'zoneName': '|- %s' % host, - 'zoneState': ''}) - hsvcs = [service for service in services - if service['host'] == host] - for svc in hsvcs: - alive = utils.service_is_up(svc) - art = (alive and ":-)") or "XXX" - active = 'enabled' - if svc['disabled']: - active = 'disabled' - rv['availabilityZoneInfo'].append({ - 'zoneName': '| |- %s' % svc['binary'], - 'zoneState': '%s %s %s' % (active, art, - svc['updated_at'])}) - return rv + ctxt = context.elevated() + available_zones, not_available_zones = self._get_zones(ctxt) + + # Available services + enabled_services = db.service_get_all(context, False) + zone_hosts = {} + host_services = {} + for service in enabled_services: + zone_hosts.setdefault(service.availability_zone, []) + if not service.host in zone_hosts[service.availability_zone]: + zone_hosts[service.availability_zone].append(service.host) + + host_services.setdefault(service.host, []) + host_services[service.host].append(service) + + result = [] + for zone in available_zones: + result.append({'zoneName': zone, + 'zoneState': "available"}) + for host in zone_hosts[zone]: + result.append({'zoneName': '|- %s' % host, + 'zoneState': ''}) + + for service in host_services[host]: + alive = utils.service_is_up(service) + art = (alive and ":-)") or "XXX" + active = 'enabled' + if service['disabled']: + active = 'disabled' + result.append({'zoneName': '| |- %s' % service['binary'], + 'zoneState': ('%s %s %s' + % (active, art, + service['updated_at']))}) + + for zone in not_available_zones: + result.append({'zoneName': zone, + 'zoneState': "not available"}) + + return {'availabilityZoneInfo': result} def describe_regions(self, context, region_name=None, **kwargs): if FLAGS.region_list: diff --git a/nova/tests/api/ec2/test_cloud.py b/nova/tests/api/ec2/test_cloud.py index af78d823b..b085b9ab1 100644 --- a/nova/tests/api/ec2/test_cloud.py +++ b/nova/tests/api/ec2/test_cloud.py @@ -690,6 +690,27 @@ class CloudTestCase(test.TestCase): db.service_destroy(self.context, service1['id']) db.service_destroy(self.context, service2['id']) + def test_describe_availability_zones_verbose(self): + """Makes sure describe_availability_zones works and filters results.""" + service1 = db.service_create(self.context, {'host': 'host1_zones', + 'binary': "nova-compute", + 'topic': 'compute', + 'report_count': 0, + 'availability_zone': "zone1"}) + service2 = db.service_create(self.context, {'host': 'host2_zones', + 'binary': "nova-compute", + 'topic': 'compute', + 'report_count': 0, + 'availability_zone': "zone2"}) + + admin_ctxt = context.get_admin_context(read_deleted="no") + result = self.cloud.describe_availability_zones(admin_ctxt, + zone_name='verbose') + + self.assertEqual(len(result['availabilityZoneInfo']), 15) + db.service_destroy(self.context, service1['id']) + db.service_destroy(self.context, service2['id']) + def test_describe_snapshots(self): """Makes sure describe_snapshots works and filters results.""" vol = db.volume_create(self.context, {}) |