summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorgtt116 <gtt116@126.com>2012-11-28 11:11:26 +0800
committergtt116 <gtt116@126.com>2013-02-03 08:57:20 +0000
commit0d813e44ff126640ffbc4f915be5b2fa203c7811 (patch)
tree2e5a8be0ce9d24d6a4fe1d5476d1cdde153ac4b8 /nova
parent3793b061df30e1f56094d7e579bca59b9c20de98 (diff)
downloadnova-0d813e44ff126640ffbc4f915be5b2fa203c7811.tar.gz
nova-0d813e44ff126640ffbc4f915be5b2fa203c7811.tar.xz
nova-0d813e44ff126640ffbc4f915be5b2fa203c7811.zip
Add REST API to show availability_zone of instance.
Implement one workitem for bp:show-availability-zone This show the availability zone and availability zone of its host in API: GET /servers/details, GET /server/{uuid}. When create instance if "availability_zone" doesn't specified, the "availability_zone" of the instance will be None. But actually the instance is in a zone which its host is in. So I think show both of them will be fine. Change-Id: I2d742ee2d291b514bf783fa79293785cca8ea2a5
Diffstat (limited to 'nova')
-rw-r--r--nova/api/openstack/compute/contrib/extended_availability_zone.py106
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_extended_availability_zone.py118
-rw-r--r--nova/tests/api/openstack/compute/test_extensions.py1
-rw-r--r--nova/tests/fake_policy.py1
-rw-r--r--nova/tests/integrated/api_samples/OS-EXT-AZ/server-get-resp.json.tpl56
-rw-r--r--nova/tests/integrated/api_samples/OS-EXT-AZ/server-get-resp.xml.tpl19
-rw-r--r--nova/tests/integrated/api_samples/OS-EXT-AZ/server-post-req.json.tpl16
-rw-r--r--nova/tests/integrated/api_samples/OS-EXT-AZ/server-post-req.xml.tpl19
-rw-r--r--nova/tests/integrated/api_samples/OS-EXT-AZ/server-post-resp.json.tpl16
-rw-r--r--nova/tests/integrated/api_samples/OS-EXT-AZ/server-post-resp.xml.tpl6
-rw-r--r--nova/tests/integrated/api_samples/OS-EXT-AZ/servers-detail-resp.json.tpl58
-rw-r--r--nova/tests/integrated/api_samples/OS-EXT-AZ/servers-detail-resp.xml.tpl20
-rw-r--r--nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl8
-rw-r--r--nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl3
-rw-r--r--nova/tests/integrated/api_samples/all_extensions/server-get-resp.json.tpl2
-rw-r--r--nova/tests/integrated/api_samples/all_extensions/server-get-resp.xml.tpl2
-rw-r--r--nova/tests/integrated/api_samples/all_extensions/servers-details-resp.json.tpl2
-rw-r--r--nova/tests/integrated/api_samples/all_extensions/servers-details-resp.xml.tpl4
-rw-r--r--nova/tests/integrated/test_api_samples.py26
19 files changed, 480 insertions, 3 deletions
diff --git a/nova/api/openstack/compute/contrib/extended_availability_zone.py b/nova/api/openstack/compute/contrib/extended_availability_zone.py
new file mode 100644
index 000000000..b7451cb6a
--- /dev/null
+++ b/nova/api/openstack/compute/contrib/extended_availability_zone.py
@@ -0,0 +1,106 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 Netease, LLC.
+# 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.
+
+"""The Extended Availability Zone Status API extension."""
+
+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.openstack.common import log as logging
+
+LOG = logging.getLogger(__name__)
+authorize = extensions.soft_extension_authorizer('compute',
+ 'extended_availability_zone')
+
+
+class ExtendedAZController(wsgi.Controller):
+
+ def _get_host_az(self, context, instance):
+ admin_context = context.elevated()
+ if instance['host']:
+ return availability_zones.get_host_availability_zone(
+ admin_context, instance['host'])
+
+ def _extend_server(self, context, server, instance):
+ key = "%s:availability_zone" % Extended_availability_zone.alias
+ server[key] = instance.get('availability_zone', None)
+
+ key = "%s:host_availability_zone" % Extended_availability_zone.alias
+ server[key] = self._get_host_az(context, instance)
+
+ @wsgi.extends
+ def show(self, req, resp_obj, id):
+ context = req.environ['nova.context']
+ if authorize(context):
+ resp_obj.attach(xml=ExtendedAZTemplate())
+ server = resp_obj.obj['server']
+ db_instance = req.get_db_instance(server['id'])
+ self._extend_server(context, server, db_instance)
+
+ @wsgi.extends
+ def detail(self, req, resp_obj):
+ context = req.environ['nova.context']
+ if authorize(context):
+ resp_obj.attach(xml=ExtendedAZsTemplate())
+ servers = list(resp_obj.obj['servers'])
+ for server in servers:
+ db_instance = req.get_db_instance(server['id'])
+ self._extend_server(context, server, db_instance)
+
+
+class Extended_availability_zone(extensions.ExtensionDescriptor):
+ """Extended Server Attributes support."""
+
+ name = "ExtendedAvailabilityZone"
+ alias = "OS-EXT-AZ"
+ namespace = ("http://docs.openstack.org/compute/ext/"
+ "extended_availability_zone/api/v2")
+ updated = "2013-01-30T00:00:00+00:00"
+
+ def get_controller_extensions(self):
+ controller = ExtendedAZController()
+ extension = extensions.ControllerExtension(self, 'servers', controller)
+ return [extension]
+
+
+def make_server(elem):
+ elem.set('{%s}availability_zone' % Extended_availability_zone.namespace,
+ '%s:availability_zone' % Extended_availability_zone.alias)
+ elem.set('{%s}host_availability_zone' %
+ Extended_availability_zone.namespace,
+ '%s:host_availability_zone' %
+ Extended_availability_zone.alias)
+
+
+class ExtendedAZTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('server', selector='server')
+ make_server(root)
+ alias = Extended_availability_zone.alias
+ namespace = Extended_availability_zone.namespace
+ return xmlutil.SlaveTemplate(root, 1, nsmap={alias: namespace})
+
+
+class ExtendedAZsTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('servers')
+ elem = xmlutil.SubTemplateElement(root, 'server', selector='servers')
+ make_server(elem)
+ alias = Extended_availability_zone.alias
+ namespace = Extended_availability_zone.namespace
+ return xmlutil.SlaveTemplate(root, 1, nsmap={alias: namespace})
diff --git a/nova/tests/api/openstack/compute/contrib/test_extended_availability_zone.py b/nova/tests/api/openstack/compute/contrib/test_extended_availability_zone.py
new file mode 100644
index 000000000..8ebd810ac
--- /dev/null
+++ b/nova/tests/api/openstack/compute/contrib/test_extended_availability_zone.py
@@ -0,0 +1,118 @@
+# Copyright 2011 OpenStack LLC.
+# 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 lxml import etree
+import webob
+
+from nova.api.openstack.compute.contrib import extended_availability_zone
+from nova import compute
+from nova import exception
+from nova.openstack.common import jsonutils
+from nova import test
+from nova.tests.api.openstack import fakes
+
+UUID1 = '00000000-0000-0000-0000-000000000001'
+UUID2 = '00000000-0000-0000-0000-000000000002'
+UUID3 = '00000000-0000-0000-0000-000000000003'
+
+
+def fake_compute_get(*args, **kwargs):
+ inst = fakes.stub_instance(1, uuid=UUID3, host="host-fake")
+ inst['availability_zone'] = 'az-i'
+ return inst
+
+
+def fake_compute_get_all(*args, **kwargs):
+ inst1 = fakes.stub_instance(1, uuid=UUID1, host="host-1")
+ inst2 = fakes.stub_instance(2, uuid=UUID2, host="host-2")
+ inst1['availability_zone'] = 'az-i'
+ inst2['availability_zone'] = 'az-i'
+ return [inst1, inst2]
+
+
+class ExtendedServerAttributesTest(test.TestCase):
+ content_type = 'application/json'
+ prefix = 'OS-EXT-AZ:'
+
+ def setUp(self):
+ super(ExtendedServerAttributesTest, self).setUp()
+ fakes.stub_out_nw_api(self.stubs)
+ self.stubs.Set(compute.api.API, 'get', fake_compute_get)
+ self.stubs.Set(compute.api.API, 'get_all', fake_compute_get_all)
+
+ self.flags(
+ osapi_compute_extension=[
+ 'nova.api.openstack.compute.contrib.select_extensions'],
+ osapi_compute_ext_list=['Extended_availability_zone'])
+
+ def _make_request(self, url):
+ req = webob.Request.blank(url)
+ req.headers['Accept'] = self.content_type
+ res = req.get_response(fakes.wsgi_app(init_only=('servers',)))
+ return res
+
+ def _get_server(self, body):
+ return jsonutils.loads(body).get('server')
+
+ def _get_servers(self, body):
+ return jsonutils.loads(body).get('servers')
+
+ def assertServerAttributes(self, server, az_instance, az_host):
+ self.assertEqual(server.get('%savailability_zone' % self.prefix),
+ az_instance)
+ self.assertEqual(server.get('%shost_availability_zone' % self.prefix),
+ az_host)
+
+ def test_show(self):
+ url = '/v2/fake/servers/%s' % UUID3
+ res = self._make_request(url)
+
+ self.assertEqual(res.status_int, 200)
+ self.assertServerAttributes(self._get_server(res.body),
+ az_instance='az-i',
+ az_host='nova')
+
+ def test_detail(self):
+ url = '/v2/fake/servers/detail'
+ res = self._make_request(url)
+
+ self.assertEqual(res.status_int, 200)
+ for i, server in enumerate(self._get_servers(res.body)):
+ self.assertServerAttributes(server,
+ az_instance='az-i',
+ az_host='nova')
+
+ def test_no_instance_passthrough_404(self):
+
+ def fake_compute_get(*args, **kwargs):
+ raise exception.InstanceNotFound(instance_id='fake')
+
+ self.stubs.Set(compute.api.API, 'get', fake_compute_get)
+ url = '/v2/fake/servers/70f6db34-de8d-4fbd-aafb-4065bdfa6115'
+ res = self._make_request(url)
+
+ self.assertEqual(res.status_int, 404)
+
+
+class ExtendedServerAttributesXmlTest(ExtendedServerAttributesTest):
+ content_type = 'application/xml'
+ prefix = '{%s}' % extended_availability_zone.\
+ Extended_availability_zone.namespace
+
+ def _get_server(self, body):
+ return etree.XML(body)
+
+ def _get_servers(self, body):
+ return etree.XML(body).getchildren()
diff --git a/nova/tests/api/openstack/compute/test_extensions.py b/nova/tests/api/openstack/compute/test_extensions.py
index 485968209..52798b9aa 100644
--- a/nova/tests/api/openstack/compute/test_extensions.py
+++ b/nova/tests/api/openstack/compute/test_extensions.py
@@ -166,6 +166,7 @@ class ExtensionControllerTest(ExtensionTestCase):
"Createserverext",
"DeferredDelete",
"DiskConfig",
+ "ExtendedAvailabilityZone",
"ExtendedStatus",
"ExtendedServerAttributes",
"FixedIPs",
diff --git a/nova/tests/fake_policy.py b/nova/tests/fake_policy.py
index ead43adea..43d9e72b3 100644
--- a/nova/tests/fake_policy.py
+++ b/nova/tests/fake_policy.py
@@ -119,6 +119,7 @@ policy_data = """
"compute_extension:disk_config": "",
"compute_extension:extended_server_attributes": "",
"compute_extension:extended_status": "",
+ "compute_extension:extended_availability_zone": "",
"compute_extension:fixed_ips": "",
"compute_extension:flavor_access": "",
"compute_extension:flavor_disabled": "",
diff --git a/nova/tests/integrated/api_samples/OS-EXT-AZ/server-get-resp.json.tpl b/nova/tests/integrated/api_samples/OS-EXT-AZ/server-get-resp.json.tpl
new file mode 100644
index 000000000..25915610d
--- /dev/null
+++ b/nova/tests/integrated/api_samples/OS-EXT-AZ/server-get-resp.json.tpl
@@ -0,0 +1,56 @@
+{
+ "server": {
+ "updated": "%(timestamp)s",
+ "created": "%(timestamp)s",
+ "OS-EXT-AZ:availability_zone": null,
+ "OS-EXT-AZ:host_availability_zone": "nova",
+ "accessIPv4": "",
+ "accessIPv6": "",
+ "addresses": {
+ "private": [
+ {
+ "addr": "%(ip)s",
+ "version": 4
+ }
+ ]
+ },
+ "flavor": {
+ "id": "1",
+ "links": [
+ {
+ "href": "%(host)s/openstack/flavors/1",
+ "rel": "bookmark"
+ }
+ ]
+ },
+ "hostId": "%(hostid)s",
+ "id": "%(uuid)s",
+ "image": {
+ "id": "%(uuid)s",
+ "links": [
+ {
+ "href": "%(host)s/openstack/images/%(uuid)s",
+ "rel": "bookmark"
+ }
+ ]
+ },
+ "links": [
+ {
+ "href": "%(host)s/v2/openstack/servers/%(uuid)s",
+ "rel": "self"
+ },
+ {
+ "href": "%(host)s/openstack/servers/%(uuid)s",
+ "rel": "bookmark"
+ }
+ ],
+ "metadata": {
+ "My Server Name": "Apache1"
+ },
+ "name": "new-server-test",
+ "progress": 0,
+ "status": "ACTIVE",
+ "tenant_id": "openstack",
+ "user_id": "fake"
+ }
+}
diff --git a/nova/tests/integrated/api_samples/OS-EXT-AZ/server-get-resp.xml.tpl b/nova/tests/integrated/api_samples/OS-EXT-AZ/server-get-resp.xml.tpl
new file mode 100644
index 000000000..1cdbd2012
--- /dev/null
+++ b/nova/tests/integrated/api_samples/OS-EXT-AZ/server-get-resp.xml.tpl
@@ -0,0 +1,19 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<server xmlns:OS-EXT-AZ="http://docs.openstack.org/compute/ext/extended_availability_zone/api/v2" xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" status="ACTIVE" updated="%(timestamp)s" hostId="%(hostid)s" name="new-server-test" created="%(timestamp)s" userId="fake" tenantId="openstack" accessIPv4="" accessIPv6="" progress="0" id="%(uuid)s" OS-EXT-AZ:availability_zone="None" OS-EXT-AZ:host_availability_zone="nova">
+ <image id="%(uuid)s">
+ <atom:link href="%(host)s/openstack/images/%(uuid)s" rel="bookmark"/>
+ </image>
+ <flavor id="1">
+ <atom:link href="%(host)s/openstack/flavors/1" rel="bookmark"/>
+ </flavor>
+ <metadata>
+ <meta key="My Server Name">Apache1</meta>
+ </metadata>
+ <addresses>
+ <network id="private">
+ <ip version="4" addr="%(ip)s"/>
+ </network>
+ </addresses>
+ <atom:link href="%(host)s/v2/openstack/servers/%(uuid)s" rel="self"/>
+ <atom:link href="%(host)s/openstack/servers/%(uuid)s" rel="bookmark"/>
+</server>
diff --git a/nova/tests/integrated/api_samples/OS-EXT-AZ/server-post-req.json.tpl b/nova/tests/integrated/api_samples/OS-EXT-AZ/server-post-req.json.tpl
new file mode 100644
index 000000000..d3916d1aa
--- /dev/null
+++ b/nova/tests/integrated/api_samples/OS-EXT-AZ/server-post-req.json.tpl
@@ -0,0 +1,16 @@
+{
+ "server" : {
+ "name" : "new-server-test",
+ "imageRef" : "%(host)s/openstack/images/%(image_id)s",
+ "flavorRef" : "%(host)s/openstack/flavors/1",
+ "metadata" : {
+ "My Server Name" : "Apache1"
+ },
+ "personality" : [
+ {
+ "path" : "/etc/banner.txt",
+ "contents" : "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA=="
+ }
+ ]
+ }
+}
diff --git a/nova/tests/integrated/api_samples/OS-EXT-AZ/server-post-req.xml.tpl b/nova/tests/integrated/api_samples/OS-EXT-AZ/server-post-req.xml.tpl
new file mode 100644
index 000000000..f92614984
--- /dev/null
+++ b/nova/tests/integrated/api_samples/OS-EXT-AZ/server-post-req.xml.tpl
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<server xmlns="http://docs.openstack.org/compute/api/v1.1" imageRef="%(host)s/openstack/images/%(image_id)s" flavorRef="%(host)s/openstack/flavors/1" name="new-server-test">
+ <metadata>
+ <meta key="My Server Name">Apache1</meta>
+ </metadata>
+ <personality>
+ <file path="/etc/banner.txt">
+ ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp
+ dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k
+ IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs
+ c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g
+ QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo
+ ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv
+ dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy
+ c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6
+ b25zLiINCg0KLVJpY2hhcmQgQmFjaA==
+ </file>
+ </personality>
+</server>
diff --git a/nova/tests/integrated/api_samples/OS-EXT-AZ/server-post-resp.json.tpl b/nova/tests/integrated/api_samples/OS-EXT-AZ/server-post-resp.json.tpl
new file mode 100644
index 000000000..d5f030c87
--- /dev/null
+++ b/nova/tests/integrated/api_samples/OS-EXT-AZ/server-post-resp.json.tpl
@@ -0,0 +1,16 @@
+{
+ "server": {
+ "adminPass": "%(password)s",
+ "id": "%(id)s",
+ "links": [
+ {
+ "href": "%(host)s/v2/openstack/servers/%(uuid)s",
+ "rel": "self"
+ },
+ {
+ "href": "%(host)s/openstack/servers/%(uuid)s",
+ "rel": "bookmark"
+ }
+ ]
+ }
+}
diff --git a/nova/tests/integrated/api_samples/OS-EXT-AZ/server-post-resp.xml.tpl b/nova/tests/integrated/api_samples/OS-EXT-AZ/server-post-resp.xml.tpl
new file mode 100644
index 000000000..3bb13e69b
--- /dev/null
+++ b/nova/tests/integrated/api_samples/OS-EXT-AZ/server-post-resp.xml.tpl
@@ -0,0 +1,6 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<server xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" id="%(id)s" adminPass="%(password)s">
+ <metadata/>
+ <atom:link href="%(host)s/v2/openstack/servers/%(uuid)s" rel="self"/>
+ <atom:link href="%(host)s/openstack/servers/%(uuid)s" rel="bookmark"/>
+</server>
diff --git a/nova/tests/integrated/api_samples/OS-EXT-AZ/servers-detail-resp.json.tpl b/nova/tests/integrated/api_samples/OS-EXT-AZ/servers-detail-resp.json.tpl
new file mode 100644
index 000000000..895f0a514
--- /dev/null
+++ b/nova/tests/integrated/api_samples/OS-EXT-AZ/servers-detail-resp.json.tpl
@@ -0,0 +1,58 @@
+{
+ "servers": [
+ {
+ "updated": "%(timestamp)s",
+ "created": "%(timestamp)s",
+ "OS-EXT-AZ:availability_zone": null,
+ "OS-EXT-AZ:host_availability_zone": "nova",
+ "accessIPv4": "",
+ "accessIPv6": "",
+ "addresses": {
+ "private": [
+ {
+ "addr": "%(ip)s",
+ "version": 4
+ }
+ ]
+ },
+ "flavor": {
+ "id": "1",
+ "links": [
+ {
+ "href": "%(host)s/openstack/flavors/1",
+ "rel": "bookmark"
+ }
+ ]
+ },
+ "hostId": "%(hostid)s",
+ "id": "%(uuid)s",
+ "image": {
+ "id": "%(uuid)s",
+ "links": [
+ {
+ "href": "%(host)s/openstack/images/%(uuid)s",
+ "rel": "bookmark"
+ }
+ ]
+ },
+ "links": [
+ {
+ "href": "%(host)s/v2/openstack/servers/%(id)s",
+ "rel": "self"
+ },
+ {
+ "href": "%(host)s/openstack/servers/%(id)s",
+ "rel": "bookmark"
+ }
+ ],
+ "metadata": {
+ "My Server Name": "Apache1"
+ },
+ "name": "new-server-test",
+ "progress": 0,
+ "status": "ACTIVE",
+ "tenant_id": "openstack",
+ "user_id": "fake"
+ }
+ ]
+}
diff --git a/nova/tests/integrated/api_samples/OS-EXT-AZ/servers-detail-resp.xml.tpl b/nova/tests/integrated/api_samples/OS-EXT-AZ/servers-detail-resp.xml.tpl
new file mode 100644
index 000000000..15cd9b1e1
--- /dev/null
+++ b/nova/tests/integrated/api_samples/OS-EXT-AZ/servers-detail-resp.xml.tpl
@@ -0,0 +1,20 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<servers xmlns:OS-EXT-AZ="http://docs.openstack.org/compute/ext/extended_availability_zone/api/v2" xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1"> <server status="ACTIVE" updated="%(timestamp)s" hostId="%(hostid)s" name="new-server-test" created="%(timestamp)s" userId="fake" tenantId="openstack" accessIPv4="" accessIPv6="" progress="0" id="%(id)s" OS-EXT-AZ:availability_zone="None" OS-EXT-AZ:host_availability_zone="nova">
+ <image id="%(uuid)s">
+ <atom:link href="%(host)s/openstack/images/%(uuid)s" rel="bookmark"/>
+ </image>
+ <flavor id="1">
+ <atom:link href="%(host)s/openstack/flavors/1" rel="bookmark"/>
+ </flavor>
+ <metadata>
+ <meta key="My Server Name">Apache1</meta>
+ </metadata>
+ <addresses>
+ <network id="private">
+ <ip version="4" addr="%(ip)s"/>
+ </network>
+ </addresses>
+ <atom:link href="%(host)s/v2/openstack/servers/%(uuid)s" rel="self"/>
+ <atom:link href="%(host)s/openstack/servers/%(uuid)s" rel="bookmark"/>
+ </server>
+</servers>
diff --git a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl
index be2fabec4..50415fef3 100644
--- a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl
+++ b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl
@@ -17,6 +17,14 @@
"updated": "%(timestamp)s"
},
{
+ "alias": "OS-EXT-AZ",
+ "description": "%(text)s",
+ "links": [],
+ "name": "ExtendedAvailabilityZone",
+ "namespace": "http://docs.openstack.org/compute/ext/extended_availability_zone/api/v2",
+ "updated": "%(timestamp)s"
+ },
+ {
"alias": "OS-EXT-SRV-ATTR",
"description": "%(text)s",
"links": [],
diff --git a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl
index ae2e9ff9e..f7251d13b 100644
--- a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl
+++ b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl
@@ -6,6 +6,9 @@
<extension alias="OS-DCF" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/disk_config/api/v1.1" name="DiskConfig">
<description>%(text)s</description>
</extension>
+ <extension alias="OS-EXT-AZ" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/extended_availability_zone/api/v2" name="ExtendedAvailabilityZone">
+ <description>%(text)s</description>
+ </extension>
<extension alias="OS-EXT-SRV-ATTR" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" name="ExtendedServerAttributes">
<description>%(text)s</description>
</extension>
diff --git a/nova/tests/integrated/api_samples/all_extensions/server-get-resp.json.tpl b/nova/tests/integrated/api_samples/all_extensions/server-get-resp.json.tpl
index 92e626293..85fc6f605 100644
--- a/nova/tests/integrated/api_samples/all_extensions/server-get-resp.json.tpl
+++ b/nova/tests/integrated/api_samples/all_extensions/server-get-resp.json.tpl
@@ -1,6 +1,8 @@
{
"server": {
"OS-DCF:diskConfig": "AUTO",
+ "OS-EXT-AZ:availability_zone": null,
+ "OS-EXT-AZ:host_availability_zone": "nova",
"OS-EXT-SRV-ATTR:host": "%(compute_host)s",
"OS-EXT-SRV-ATTR:hypervisor_hostname": "%(hypervisor_hostname)s",
"OS-EXT-SRV-ATTR:instance_name": "instance-00000001",
diff --git a/nova/tests/integrated/api_samples/all_extensions/server-get-resp.xml.tpl b/nova/tests/integrated/api_samples/all_extensions/server-get-resp.xml.tpl
index 137e59686..bd73accda 100644
--- a/nova/tests/integrated/api_samples/all_extensions/server-get-resp.xml.tpl
+++ b/nova/tests/integrated/api_samples/all_extensions/server-get-resp.xml.tpl
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='UTF-8'?>
-<server xmlns:OS-DCF="http://docs.openstack.org/compute/ext/disk_config/api/v1.1" xmlns:OS-EXT-SRV-ATTR="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" xmlns:OS-EXT-STS="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" status="ACTIVE" updated="%(timestamp)s" hostId="%(hostid)s" name="new-server-test" created="%(timestamp)s" userId="fake" tenantId="openstack" accessIPv4="" accessIPv6="" progress="0" id="%(id)s" key_name="None" config_drive="" OS-EXT-SRV-ATTR:vm_state="active" OS-EXT-SRV-ATTR:task_state="None" OS-EXT-SRV-ATTR:power_state="1" OS-EXT-SRV-ATTR:instance_name="instance-00000001" OS-EXT-SRV-ATTR:host="%(compute_host)s" OS-EXT-SRV-ATTR:hypervisor_hostname="%(hypervisor_hostname)s" OS-DCF:diskConfig="AUTO">
+<server xmlns:OS-DCF="http://docs.openstack.org/compute/ext/disk_config/api/v1.1" xmlns:OS-EXT-AZ="http://docs.openstack.org/compute/ext/extended_availability_zone/api/v2" xmlns:OS-EXT-SRV-ATTR="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" xmlns:OS-EXT-STS="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" status="ACTIVE" updated="%(timestamp)s" hostId="%(hostid)s" name="new-server-test" created="%(timestamp)s" userId="fake" tenantId="openstack" accessIPv4="" accessIPv6="" progress="0" id="%(id)s" key_name="None" config_drive="" OS-EXT-SRV-ATTR:vm_state="active" OS-EXT-SRV-ATTR:task_state="None" OS-EXT-SRV-ATTR:power_state="1" OS-EXT-SRV-ATTR:instance_name="instance-00000001" OS-EXT-SRV-ATTR:host="%(compute_host)s" OS-EXT-SRV-ATTR:hypervisor_hostname="%(hypervisor_hostname)s" OS-EXT-AZ:availability_zone="None" OS-EXT-AZ:host_availability_zone="nova" OS-DCF:diskConfig="AUTO">
<image id="%(uuid)s">
<atom:link href="%(host)s/openstack/images/%(uuid)s" rel="bookmark"/>
</image>
diff --git a/nova/tests/integrated/api_samples/all_extensions/servers-details-resp.json.tpl b/nova/tests/integrated/api_samples/all_extensions/servers-details-resp.json.tpl
index 8f1583baf..a4918203b 100644
--- a/nova/tests/integrated/api_samples/all_extensions/servers-details-resp.json.tpl
+++ b/nova/tests/integrated/api_samples/all_extensions/servers-details-resp.json.tpl
@@ -2,6 +2,8 @@
"servers": [
{
"OS-DCF:diskConfig": "AUTO",
+ "OS-EXT-AZ:availability_zone": null,
+ "OS-EXT-AZ:host_availability_zone": "nova",
"OS-EXT-SRV-ATTR:host": "%(compute_host)s",
"OS-EXT-SRV-ATTR:hypervisor_hostname": "%(hypervisor_hostname)s",
"OS-EXT-SRV-ATTR:instance_name": "instance-00000001",
diff --git a/nova/tests/integrated/api_samples/all_extensions/servers-details-resp.xml.tpl b/nova/tests/integrated/api_samples/all_extensions/servers-details-resp.xml.tpl
index 344686e66..d26eb38ef 100644
--- a/nova/tests/integrated/api_samples/all_extensions/servers-details-resp.xml.tpl
+++ b/nova/tests/integrated/api_samples/all_extensions/servers-details-resp.xml.tpl
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='UTF-8'?>
-<servers xmlns:OS-DCF="http://docs.openstack.org/compute/ext/disk_config/api/v1.1" xmlns:OS-EXT-SRV-ATTR="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" xmlns:OS-EXT-STS="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1">
- <server xmlns:OS-DCF="http://docs.openstack.org/compute/ext/disk_config/api/v1.1" xmlns:OS-EXT-SRV-ATTR="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" xmlns:OS-EXT-STS="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" status="ACTIVE" updated="%(timestamp)s" hostId="%(hostid)s" name="new-server-test" created="%(timestamp)s" userId="fake" tenantId="openstack" accessIPv4="" accessIPv6="" progress="0" id="%(id)s" key_name="None" config_drive="" OS-EXT-SRV-ATTR:vm_state="active" OS-EXT-SRV-ATTR:task_state="None" OS-EXT-SRV-ATTR:power_state="1" OS-EXT-SRV-ATTR:instance_name="instance-00000001" OS-EXT-SRV-ATTR:host="%(compute_host)s" OS-EXT-SRV-ATTR:hypervisor_hostname="%(hypervisor_hostname)s" OS-DCF:diskConfig="AUTO">
+<servers xmlns:OS-DCF="http://docs.openstack.org/compute/ext/disk_config/api/v1.1" xmlns:OS-EXT-AZ="http://docs.openstack.org/compute/ext/extended_availability_zone/api/v2" xmlns:OS-EXT-SRV-ATTR="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" xmlns:OS-EXT-STS="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <server xmlns:OS-DCF="http://docs.openstack.org/compute/ext/disk_config/api/v1.1" xmlns:OS-EXT-AZ="http://docs.openstack.org/compute/ext/extended_availability_zone/api/v2" xmlns:OS-EXT-SRV-ATTR="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" xmlns:OS-EXT-STS="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" status="ACTIVE" updated="%(timestamp)s" hostId="%(hostid)s" name="new-server-test" created="%(timestamp)s" userId="fake" tenantId="openstack" accessIPv4="" accessIPv6="" progress="0" id="%(id)s" key_name="None" config_drive="" OS-EXT-SRV-ATTR:vm_state="active" OS-EXT-SRV-ATTR:task_state="None" OS-EXT-SRV-ATTR:power_state="1" OS-EXT-SRV-ATTR:instance_name="instance-00000001" OS-EXT-SRV-ATTR:host="%(compute_host)s" OS-EXT-SRV-ATTR:hypervisor_hostname="%(hypervisor_hostname)s" OS-EXT-AZ:availability_zone="None" OS-EXT-AZ:host_availability_zone="nova" OS-DCF:diskConfig="AUTO">
<image id="%(uuid)s">
<atom:link href="%(host)s/openstack/images/%(uuid)s" rel="bookmark"/>
</image>
diff --git a/nova/tests/integrated/test_api_samples.py b/nova/tests/integrated/test_api_samples.py
index a53279e47..f1f86d21b 100644
--- a/nova/tests/integrated/test_api_samples.py
+++ b/nova/tests/integrated/test_api_samples.py
@@ -2799,3 +2799,29 @@ class FpingSampleJsonTests(ServersSampleBase):
class FpingSampleXmlTests(FpingSampleJsonTests):
ctype = 'xml'
+
+
+class ExtendedAvailabilityZoneJsonTests(ServersSampleBase):
+ extension_name = ("nova.api.openstack.compute.contrib"
+ ".extended_availability_zone"
+ ".Extended_availability_zone")
+
+ def test_get(self):
+ uuid = self._post_server()
+ response = self._do_get('servers/%s' % uuid)
+ self.assertEqual(response.status, 200)
+ subs = self._get_regexes()
+ subs['hostid'] = '[a-f0-9]+'
+ return self._verify_response('server-get-resp', subs, response)
+
+ def test_detail(self):
+ uuid = self._post_server()
+ response = self._do_get('servers/detail')
+ self.assertEqual(response.status, 200)
+ subs = self._get_regexes()
+ subs['hostid'] = '[a-f0-9]+'
+ return self._verify_response('servers-detail-resp', subs, response)
+
+
+class ExtendedAvailabilityZoneXmlTests(ExtendedAvailabilityZoneJsonTests):
+ ctype = 'xml'