diff options
| author | zhiyanliu <zhiyanl@cn.ibm.com> | 2013-01-23 15:56:05 +0800 |
|---|---|---|
| committer | zhiyanliu <lzy.dev@gmail.com> | 2013-01-23 15:57:01 +0800 |
| commit | 3272809735685e1cdabfd9cf7d87a7287c4209e8 (patch) | |
| tree | 93870b3d078b0356b57c3745f1f35d2def2144d8 /nova/tests | |
| parent | a1c1e1bac155666d93f4003841132e66b3599ca8 (diff) | |
Adding REST API to show all availability zones of an region
Returns a summary or detailed list of availability zone to client.
To keep consistent result with EC2 API and de-duplicate, I have
refactored EC2 cloud controllor code.
Implement one workitem for bp:show-availability-zone
Change-Id: I6c9c673c757c6c319a1cdd94d7420b8983f92bbb
Signed-off-by: zhiyanliu <zhiyanl@cn.ibm.com>
Diffstat (limited to 'nova/tests')
6 files changed, 368 insertions, 0 deletions
diff --git a/nova/tests/api/openstack/compute/contrib/test_availability_zone.py b/nova/tests/api/openstack/compute/contrib/test_availability_zone.py new file mode 100644 index 000000000..8abe7f388 --- /dev/null +++ b/nova/tests/api/openstack/compute/contrib/test_availability_zone.py @@ -0,0 +1,244 @@ +# Copyright 2012 IBM +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from datetime import datetime +from lxml import etree +import webob + +from nova.api.openstack.compute.contrib import availability_zone +from nova import availability_zones +from nova import context +from nova import db +from nova.openstack.common import jsonutils +from nova import servicegroup +from nova import test +from nova.tests.api.openstack import fakes + + +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} + + if disabled: + return [__fake_service("nova-compute", "zone-2", + datetime(2012, 11, 14, 9, 53, 25, 0), + datetime(2012, 12, 26, 14, 45, 25, 0), + "fake_host-1", True), + __fake_service("nova-scheduler", "internal", + datetime(2012, 11, 14, 9, 57, 3, 0), + datetime(2012, 12, 26, 14, 45, 25, 0), + "fake_host-1", True), + __fake_service("nova-network", "internal", + datetime(2012, 11, 16, 7, 25, 46, 0), + datetime(2012, 12, 26, 14, 45, 24, 0), + "fake_host-2", True)] + else: + return [__fake_service("nova-compute", "zone-1", + datetime(2012, 11, 14, 9, 53, 25, 0), + datetime(2012, 12, 26, 14, 45, 25, 0), + "fake_host-1", False), + __fake_service("nova-sched", "internal", + datetime(2012, 11, 14, 9, 57, 03, 0), + datetime(2012, 12, 26, 14, 45, 25, 0), + "fake_host-1", False), + __fake_service("nova-network", "internal", + datetime(2012, 11, 16, 7, 25, 46, 0), + datetime(2012, 12, 26, 14, 45, 24, 0), + "fake_host-2", False)] + + +def fake_service_is_up(self, service): + return service['binary'] != u"nova-network" + + +def fake_set_availability_zones(context, services): + return services + + +class AvailabilityZoneApiTest(test.TestCase): + def setUp(self): + super(AvailabilityZoneApiTest, self).setUp() + self.stubs.Set(db, 'service_get_all', fake_service_get_all) + self.stubs.Set(availability_zones, 'set_availability_zones', + fake_set_availability_zones) + self.stubs.Set(servicegroup.API, 'service_is_up', fake_service_is_up) + + def test_availability_zone_index(self): + req = webob.Request.blank('/v2/fake/os-availability-zone') + resp = req.get_response(fakes.wsgi_app()) + self.assertEqual(resp.status_int, 200) + resp_dict = jsonutils.loads(resp.body) + + self.assertTrue('availabilityZoneInfo' in resp_dict) + zones = resp_dict['availabilityZoneInfo'] + self.assertEqual(len(zones), 2) + self.assertEqual(zones[0]['zoneName'], u'zone-1') + self.assertTrue(zones[0]['zoneState']['available']) + self.assertIsNone(zones[0]['hosts']) + self.assertEqual(zones[1]['zoneName'], u'zone-2') + self.assertFalse(zones[1]['zoneState']['available']) + self.assertIsNone(zones[1]['hosts']) + + def test_availability_zone_detail(self): + def _formatZone(zone_dict): + result = [] + + # Zone tree view item + result.append({'zoneName': zone_dict['zoneName'], + 'zoneState': u'available' + if zone_dict['zoneState']['available'] else + u'not available'}) + + if zone_dict['hosts'] is not None: + for (host, services) in zone_dict['hosts'].items(): + # Host tree view item + result.append({'zoneName': u'|- %s' % host, + 'zoneState': u''}) + for (svc, state) in services.items(): + # Service tree view item + result.append({'zoneName': u'| |- %s' % svc, + 'zoneState': u'%s %s %s' % ( + 'enabled' if state['active'] else + 'disabled', + ':-)' if state['available'] else + 'XXX', + jsonutils.to_primitive( + state['updated_at']))}) + return result + + def _assertZone(zone, name, status): + self.assertEqual(zone['zoneName'], name) + self.assertEqual(zone['zoneState'], status) + + availabilityZone = availability_zone.AvailabilityZoneController() + + req = webob.Request.blank('/v2/fake/os-availability-zone/detail') + req.method = 'GET' + req.environ['nova.context'] = context.get_admin_context() + resp_dict = availabilityZone.detail(req) + + self.assertTrue('availabilityZoneInfo' in resp_dict) + zones = resp_dict['availabilityZoneInfo'] + self.assertEqual(len(zones), 3) + + ''' availabilityZoneInfo field content in response body: + [{'zoneName': 'zone-1', + 'zoneState': {'available': True}, + 'hosts': {'fake_host-1': { + 'nova-compute': {'active': True, 'available': True, + 'updated_at': datetime(2012, 12, 26, 14, 45, 25)}}}}, + {'zoneName': 'internal', + 'zoneState': {'available': True}, + 'hosts': {'fake_host-1': { + 'nova-sched': {'active': True, 'available': True, + 'updated_at': datetime(2012, 12, 26, 14, 45, 25)}}, + 'fake_host-2': { + 'nova-network': {'active': True, 'available': False, + 'updated_at': datetime(2012, 12, 26, 14, 45, 24)}}}}, + {'zoneName': 'zone-2', + 'zoneState': {'available': False}, + 'hosts': None}] + ''' + + l0 = [u'zone-1', u'available'] + l1 = [u'|- fake_host-1', u''] + l2 = [u'| |- nova-compute', u'enabled :-) 2012-12-26T14:45:25.000000'] + l3 = [u'internal', u'available'] + l4 = [u'|- fake_host-1', u''] + l5 = [u'| |- nova-sched', u'enabled :-) 2012-12-26T14:45:25.000000'] + l6 = [u'|- fake_host-2', u''] + l7 = [u'| |- nova-network', u'enabled XXX 2012-12-26T14:45:24.000000'] + l8 = [u'zone-2', u'not available'] + + z0 = _formatZone(zones[0]) + z1 = _formatZone(zones[1]) + z2 = _formatZone(zones[2]) + + self.assertEqual(len(z0), 3) + self.assertEqual(len(z1), 5) + self.assertEqual(len(z2), 1) + + _assertZone(z0[0], l0[0], l0[1]) + _assertZone(z0[1], l1[0], l1[1]) + _assertZone(z0[2], l2[0], l2[1]) + _assertZone(z1[0], l3[0], l3[1]) + _assertZone(z1[1], l4[0], l4[1]) + _assertZone(z1[2], l5[0], l5[1]) + _assertZone(z1[3], l6[0], l6[1]) + _assertZone(z1[4], l7[0], l7[1]) + _assertZone(z2[0], l8[0], l8[1]) + + +class AvailabilityZoneSerializerTest(test.TestCase): + def test_availability_zone_index_detail_serializer(self): + def _verify_zone(zone_dict, tree): + self.assertEqual(tree.tag, 'availabilityZone') + self.assertEqual(zone_dict['zoneName'], tree.get('name')) + self.assertEqual(str(zone_dict['zoneState']['available']), + tree[0].get('available')) + + for _idx, host_child in enumerate(tree[1]): + self.assertTrue(host_child.get('name') in zone_dict['hosts']) + svcs = zone_dict['hosts'][host_child.get('name')] + for _idx, svc_child in enumerate(host_child[0]): + self.assertTrue(svc_child.get('name') in svcs) + svc = svcs[svc_child.get('name')] + self.assertEqual(len(svc_child), 1) + + self.assertEqual(str(svc['available']), + svc_child[0].get('available')) + self.assertEqual(str(svc['active']), + svc_child[0].get('active')) + self.assertEqual(str(svc['updated_at']), + svc_child[0].get('updated_at')) + + serializer = availability_zone.AvailabilityZonesTemplate() + raw_availability_zones = \ + [{'zoneName': 'zone-1', + 'zoneState': {'available': True}, + 'hosts': {'fake_host-1': { + 'nova-compute': {'active': True, 'available': True, + 'updated_at': + datetime(2012, 12, 26, 14, 45, 25)}}}}, + {'zoneName': 'internal', + 'zoneState': {'available': True}, + 'hosts': {'fake_host-1': { + 'nova-sched': {'active': True, 'available': True, + 'updated_at': + datetime(2012, 12, 26, 14, 45, 25)}}, + 'fake_host-2': { + 'nova-network': {'active': True, + 'available': False, + 'updated_at': + datetime(2012, 12, 26, 14, 45, 24)}}}}, + {'zoneName': 'zone-2', + 'zoneState': {'available': False}, + 'hosts': None}] + + text = serializer.serialize( + dict(availabilityZoneInfo=raw_availability_zones)) + tree = etree.fromstring(text) + + self.assertEqual('availabilityZones', tree.tag) + self.assertEqual(len(raw_availability_zones), len(tree)) + for idx, child in enumerate(tree): + _verify_zone(raw_availability_zones[idx], child) diff --git a/nova/tests/fake_policy.py b/nova/tests/fake_policy.py index acefa856c..04e4adbbd 100644 --- a/nova/tests/fake_policy.py +++ b/nova/tests/fake_policy.py @@ -158,6 +158,8 @@ policy_data = """ "compute_extension:volumes": "", "compute_extension:volumetypes": "", "compute_extension:zones": "", + "compute_extension:availability_zone:list": "", + "compute_extension:availability_zone:detail": "is_admin:True", "volume:create": "", diff --git a/nova/tests/integrated/api_samples/os-availability-zone/availability-zone-details-resp.json.tpl b/nova/tests/integrated/api_samples/os-availability-zone/availability-zone-details-resp.json.tpl new file mode 100644 index 000000000..6d44692e1 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-availability-zone/availability-zone-details-resp.json.tpl @@ -0,0 +1,48 @@ +{ + "availabilityZoneInfo": [ + { + "zoneName": "zone-1", + "zoneState": { + "available": true + }, + "hosts": { + "fake_host-1": { + "nova-compute": { + "active": true, + "available": true, + "updated_at": "2012-12-26T14:45:25.000000" + } + } + } + }, + { + "zoneName": "internal", + "zoneState": { + "available": true + }, + "hosts": { + "fake_host-1": { + "nova-sched": { + "active": true, + "available": true, + "updated_at": "2012-12-26T14:45:25.000000" + } + }, + "fake_host-2": { + "nova-network": { + "active": true, + "available": false, + "updated_at": "2012-12-26T14:45:24.000000" + } + } + } + }, + { + "zoneName": "zone-2", + "zoneState": { + "available": false + }, + "hosts": null + } + ] +}
\ No newline at end of file diff --git a/nova/tests/integrated/api_samples/os-availability-zone/availability-zone-details-resp.xml.tpl b/nova/tests/integrated/api_samples/os-availability-zone/availability-zone-details-resp.xml.tpl new file mode 100644 index 000000000..856a64957 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-availability-zone/availability-zone-details-resp.xml.tpl @@ -0,0 +1,44 @@ +<?xml version='1.0' encoding='UTF-8'?> +<availabilityZones + xmlns:os-availability-zone="http://docs.openstack.org/compute/ext/availabilityzone/api/v1.1"> + <availabilityZone name="zone-1"> + <zoneState available="True" /> + <hosts> + <host name="fake_host-1"> + <services> + <service name="nova-compute"> + <serviceState available="True" active="True" + updated_at="2012-12-26 14:45:25" /> + </service> + </services> + </host> + </hosts> + <metadata /> + </availabilityZone> + <availabilityZone name="internal"> + <zoneState available="True" /> + <hosts> + <host name="fake_host-1"> + <services> + <service name="nova-sched"> + <serviceState available="True" active="True" + updated_at="2012-12-26 14:45:25" /> + </service> + </services> + </host> + <host name="fake_host-2"> + <services> + <service name="nova-network"> + <serviceState available="False" active="True" + updated_at="2012-12-26 14:45:24" /> + </service> + </services> + </host> + </hosts> + <metadata /> + </availabilityZone> + <availabilityZone name="zone-2"> + <zoneState available="False" /> + <metadata /> + </availabilityZone> +</availabilityZones>
\ No newline at end of file diff --git a/nova/tests/integrated/api_samples/os-availability-zone/availability-zone-get-resp.json.tpl b/nova/tests/integrated/api_samples/os-availability-zone/availability-zone-get-resp.json.tpl new file mode 100644 index 000000000..381708aaf --- /dev/null +++ b/nova/tests/integrated/api_samples/os-availability-zone/availability-zone-get-resp.json.tpl @@ -0,0 +1,18 @@ +{ + "availabilityZoneInfo": [ + { + "zoneName": "zone-1", + "zoneState": { + "available": true + }, + "hosts": null + }, + { + "zoneName": "zone-2", + "zoneState": { + "available": false + }, + "hosts": null + } + ] +}
\ No newline at end of file diff --git a/nova/tests/integrated/api_samples/os-availability-zone/availability-zone-get-resp.xml.tpl b/nova/tests/integrated/api_samples/os-availability-zone/availability-zone-get-resp.xml.tpl new file mode 100644 index 000000000..1eff177de --- /dev/null +++ b/nova/tests/integrated/api_samples/os-availability-zone/availability-zone-get-resp.xml.tpl @@ -0,0 +1,12 @@ +<?xml version='1.0' encoding='UTF-8'?> +<availabilityZones + xmlns:os-availability-zone="http://docs.openstack.org/compute/ext/availabilityzone/api/v1.1"> + <availabilityZone name="zone-1"> + <zoneState available="True" /> + <metadata /> + </availabilityZone> + <availabilityZone name="zone-2"> + <zoneState available="False" /> + <metadata /> + </availabilityZone> +</availabilityZones>
\ No newline at end of file |
