Merge "Adding REST API to show all availability zones of an region"
This commit is contained in:
commit
4220e0110e
@ -83,6 +83,8 @@
|
||||
"compute_extension:virtual_storage_arrays": "",
|
||||
"compute_extension:volumes": "",
|
||||
"compute_extension:volumetypes": "",
|
||||
"compute_extension:availability_zone:list": "",
|
||||
"compute_extension:availability_zone:detail": "rule:admin_api",
|
||||
|
||||
|
||||
"volume:create": "",
|
||||
|
@ -250,32 +250,10 @@ class CloudController(object):
|
||||
else:
|
||||
return self._describe_availability_zones(context, **kwargs)
|
||||
|
||||
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)
|
||||
enabled_services = availability_zones.set_availability_zones(context,
|
||||
enabled_services)
|
||||
disabled_services = availability_zones.set_availability_zones(context,
|
||||
disabled_services)
|
||||
|
||||
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 = []
|
||||
zones = [service['available_zones'] for service in disabled_services
|
||||
if service['available_zones'] not in available_zones]
|
||||
for zone in zones:
|
||||
if zone not 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)
|
||||
available_zones, not_available_zones = \
|
||||
availability_zones.get_availability_zones(ctxt)
|
||||
|
||||
result = []
|
||||
for zone in available_zones:
|
||||
@ -291,7 +269,8 @@ class CloudController(object):
|
||||
|
||||
def _describe_availability_zones_verbose(self, context, **kwargs):
|
||||
ctxt = context.elevated()
|
||||
available_zones, not_available_zones = self._get_zones(ctxt)
|
||||
available_zones, not_available_zones = \
|
||||
availability_zones.get_availability_zones(ctxt)
|
||||
|
||||
# Available services
|
||||
enabled_services = db.service_get_all(context, False)
|
||||
|
@ -14,14 +14,165 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License
|
||||
|
||||
from nova.api.openstack import common
|
||||
from nova.api.openstack import extensions
|
||||
from nova.api.openstack import wsgi
|
||||
from nova.api.openstack import xmlutil
|
||||
from nova import availability_zones
|
||||
from nova import db
|
||||
from nova.openstack.common import cfg
|
||||
from nova.openstack.common import log as logging
|
||||
from nova import servicegroup
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
|
||||
authorize_list = extensions.extension_authorizer('compute',
|
||||
'availability_zone:list')
|
||||
authorize_detail = extensions.extension_authorizer('compute',
|
||||
'availability_zone:detail')
|
||||
|
||||
|
||||
def make_availability_zone(elem):
|
||||
elem.set('name', 'zoneName')
|
||||
|
||||
zoneStateElem = xmlutil.SubTemplateElement(elem, 'zoneState',
|
||||
selector='zoneState')
|
||||
zoneStateElem.set('available')
|
||||
|
||||
hostsElem = xmlutil.SubTemplateElement(elem, 'hosts', selector='hosts')
|
||||
hostElem = xmlutil.SubTemplateElement(hostsElem, 'host',
|
||||
selector=xmlutil.get_items)
|
||||
hostElem.set('name', 0)
|
||||
|
||||
svcsElem = xmlutil.SubTemplateElement(hostElem, 'services', selector=1)
|
||||
svcElem = xmlutil.SubTemplateElement(svcsElem, 'service',
|
||||
selector=xmlutil.get_items)
|
||||
svcElem.set('name', 0)
|
||||
|
||||
svcStateElem = xmlutil.SubTemplateElement(svcElem, 'serviceState',
|
||||
selector=1)
|
||||
svcStateElem.set('available')
|
||||
svcStateElem.set('active')
|
||||
svcStateElem.set('updated_at')
|
||||
|
||||
# Attach metadata node
|
||||
elem.append(common.MetadataTemplate())
|
||||
|
||||
|
||||
class AvailabilityZonesTemplate(xmlutil.TemplateBuilder):
|
||||
def construct(self):
|
||||
root = xmlutil.TemplateElement('availabilityZones')
|
||||
zoneElem = xmlutil.SubTemplateElement(root, 'availabilityZone',
|
||||
selector='availabilityZoneInfo')
|
||||
make_availability_zone(zoneElem)
|
||||
return xmlutil.MasterTemplate(root, 1, nsmap={
|
||||
Availability_zone.alias: Availability_zone.namespace})
|
||||
|
||||
|
||||
class AvailabilityZoneController(wsgi.Controller):
|
||||
"""The Availability Zone API controller for the OpenStack API."""
|
||||
|
||||
def __init__(self):
|
||||
super(AvailabilityZoneController, self).__init__()
|
||||
self.servicegroup_api = servicegroup.API()
|
||||
|
||||
def _describe_availability_zones(self, context, **kwargs):
|
||||
ctxt = context.elevated()
|
||||
available_zones, not_available_zones = \
|
||||
availability_zones.get_availability_zones(ctxt)
|
||||
|
||||
result = []
|
||||
for zone in available_zones:
|
||||
# Hide internal_service_availability_zone
|
||||
if zone == CONF.internal_service_availability_zone:
|
||||
continue
|
||||
result.append({'zoneName': zone,
|
||||
'zoneState': {'available': True},
|
||||
"hosts": None})
|
||||
for zone in not_available_zones:
|
||||
result.append({'zoneName': zone,
|
||||
'zoneState': {'available': False},
|
||||
"hosts": None})
|
||||
return {'availabilityZoneInfo': result}
|
||||
|
||||
def _describe_availability_zones_verbose(self, context, **kwargs):
|
||||
ctxt = context.elevated()
|
||||
available_zones, not_available_zones = \
|
||||
availability_zones.get_availability_zones(ctxt)
|
||||
|
||||
# Available services
|
||||
enabled_services = db.service_get_all(context, False)
|
||||
enabled_services = availability_zones.set_availability_zones(context,
|
||||
enabled_services)
|
||||
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['availability_zone'] +
|
||||
service['host'], [])
|
||||
host_services[service['availability_zone'] + service['host']].\
|
||||
append(service)
|
||||
|
||||
result = []
|
||||
for zone in available_zones:
|
||||
hosts = {}
|
||||
for host in zone_hosts[zone]:
|
||||
hosts[host] = {}
|
||||
for service in host_services[zone + host]:
|
||||
alive = self.servicegroup_api.service_is_up(service)
|
||||
hosts[host][service['binary']] = {'available': alive,
|
||||
'active': True != service['disabled'],
|
||||
'updated_at': service['updated_at']}
|
||||
result.append({'zoneName': zone,
|
||||
'zoneState': {'available': True},
|
||||
"hosts": hosts})
|
||||
|
||||
for zone in not_available_zones:
|
||||
result.append({'zoneName': zone,
|
||||
'zoneState': {'available': False},
|
||||
"hosts": None})
|
||||
return {'availabilityZoneInfo': result}
|
||||
|
||||
@wsgi.serializers(xml=AvailabilityZonesTemplate)
|
||||
def index(self, req):
|
||||
"""Returns a summary list of availability zone."""
|
||||
context = req.environ['nova.context']
|
||||
authorize_list(context)
|
||||
|
||||
return self._describe_availability_zones(context)
|
||||
|
||||
@wsgi.serializers(xml=AvailabilityZonesTemplate)
|
||||
def detail(self, req):
|
||||
"""Returns a detailed list of availability zone."""
|
||||
context = req.environ['nova.context']
|
||||
authorize_detail(context)
|
||||
|
||||
return self._describe_availability_zones_verbose(context)
|
||||
|
||||
|
||||
class Availability_zone(extensions.ExtensionDescriptor):
|
||||
"""Add availability_zone to the Create Server v1.1 API."""
|
||||
"""1. Add availability_zone to the Create Server v1.1 API.
|
||||
2. Add availability zones describing.
|
||||
"""
|
||||
|
||||
name = "AvailabilityZone"
|
||||
alias = "os-availability-zone"
|
||||
namespace = ("http://docs.openstack.org/compute/ext/"
|
||||
"availabilityzone/api/v1.1")
|
||||
updated = "2012-08-09T00:00:00+00:00"
|
||||
updated = "2012-12-21T00:00:00+00:00"
|
||||
|
||||
def get_resources(self):
|
||||
resources = []
|
||||
|
||||
res = extensions.ResourceExtension('os-availability-zone',
|
||||
AvailabilityZoneController(),
|
||||
collection_actions={'detail': 'GET'})
|
||||
resources.append(res)
|
||||
|
||||
return resources
|
||||
|
@ -60,3 +60,25 @@ def get_host_availability_zone(context, host):
|
||||
return list(metadata['availability_zone'])[0]
|
||||
else:
|
||||
return CONF.default_availability_zone
|
||||
|
||||
|
||||
def get_availability_zones(context):
|
||||
"""Return available and unavailable zones."""
|
||||
enabled_services = db.service_get_all(context, False)
|
||||
disabled_services = db.service_get_all(context, True)
|
||||
enabled_services = set_availability_zones(context, enabled_services)
|
||||
disabled_services = set_availability_zones(context, disabled_services)
|
||||
|
||||
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 = []
|
||||
zones = [service['available_zones'] for service in disabled_services
|
||||
if service['available_zones'] not in available_zones]
|
||||
for zone in zones:
|
||||
if zone not in not_available_zones:
|
||||
not_available_zones.append(zone)
|
||||
return (available_zones, not_available_zones)
|
||||
|
@ -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)
|
@ -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": "",
|
||||
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
@ -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>
|
@ -0,0 +1,18 @@
|
||||
{
|
||||
"availabilityZoneInfo": [
|
||||
{
|
||||
"zoneName": "zone-1",
|
||||
"zoneState": {
|
||||
"available": true
|
||||
},
|
||||
"hosts": null
|
||||
},
|
||||
{
|
||||
"zoneName": "zone-2",
|
||||
"zoneState": {
|
||||
"available": false
|
||||
},
|
||||
"hosts": null
|
||||
}
|
||||
]
|
||||
}
|
@ -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>
|
Loading…
Reference in New Issue
Block a user