diff --git a/doc/api_samples/OS-EXT-VIF-NET/server-post-req.json b/doc/api_samples/OS-EXT-VIF-NET/server-post-req.json new file mode 100644 index 000000000000..d88eb4122223 --- /dev/null +++ b/doc/api_samples/OS-EXT-VIF-NET/server-post-req.json @@ -0,0 +1,16 @@ +{ + "server" : { + "name" : "new-server-test", + "imageRef" : "http://openstack.example.com/openstack/images/70a599e0-31e7-49b7-b260-868f441e862b", + "flavorRef" : "http://openstack.example.com/openstack/flavors/1", + "metadata" : { + "My Server Name" : "Apache1" + }, + "personality" : [ + { + "path" : "/etc/banner.txt", + "contents" : "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA==" + } + ] + } +} \ No newline at end of file diff --git a/doc/api_samples/OS-EXT-VIF-NET/server-post-req.xml b/doc/api_samples/OS-EXT-VIF-NET/server-post-req.xml new file mode 100644 index 000000000000..0a3c8bb5303d --- /dev/null +++ b/doc/api_samples/OS-EXT-VIF-NET/server-post-req.xml @@ -0,0 +1,19 @@ + + + + Apache1 + + + + ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp + dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k + IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs + c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g + QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo + ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv + dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy + c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6 + b25zLiINCg0KLVJpY2hhcmQgQmFjaA== + + + \ No newline at end of file diff --git a/doc/api_samples/OS-EXT-VIF-NET/server-post-resp.json b/doc/api_samples/OS-EXT-VIF-NET/server-post-resp.json new file mode 100644 index 000000000000..f8379cbb3f5e --- /dev/null +++ b/doc/api_samples/OS-EXT-VIF-NET/server-post-resp.json @@ -0,0 +1,16 @@ +{ + "server": { + "adminPass": "m62Pu3gkXXV2", + "id": "a98dd3ae-5feb-4b4b-afa4-25e830ad3305", + "links": [ + { + "href": "http://openstack.example.com/v2/openstack/servers/a98dd3ae-5feb-4b4b-afa4-25e830ad3305", + "rel": "self" + }, + { + "href": "http://openstack.example.com/openstack/servers/a98dd3ae-5feb-4b4b-afa4-25e830ad3305", + "rel": "bookmark" + } + ] + } +} \ No newline at end of file diff --git a/doc/api_samples/OS-EXT-VIF-NET/server-post-resp.xml b/doc/api_samples/OS-EXT-VIF-NET/server-post-resp.xml new file mode 100644 index 000000000000..d620ed00b066 --- /dev/null +++ b/doc/api_samples/OS-EXT-VIF-NET/server-post-resp.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/doc/api_samples/OS-EXT-VIF-NET/vifs-list-resp.json b/doc/api_samples/OS-EXT-VIF-NET/vifs-list-resp.json new file mode 100644 index 000000000000..57ff0d0c96df --- /dev/null +++ b/doc/api_samples/OS-EXT-VIF-NET/vifs-list-resp.json @@ -0,0 +1,9 @@ +{ + "virtual_interfaces": [ + { + "id": "cec8b9bb-5d22-4104-b3c8-4c35db3210a6", + "mac_address": "fa:16:3e:3c:ce:6f", + "OS-EXT-VIF-NET:net_id": "cec8b9bb-5d22-4104-b3c8-4c35db3210a7" + } + ] +} diff --git a/doc/api_samples/OS-EXT-VIF-NET/vifs-list-resp.xml b/doc/api_samples/OS-EXT-VIF-NET/vifs-list-resp.xml new file mode 100644 index 000000000000..d5a587d5504a --- /dev/null +++ b/doc/api_samples/OS-EXT-VIF-NET/vifs-list-resp.xml @@ -0,0 +1,8 @@ + + + + diff --git a/doc/api_samples/all_extensions/extensions-get-resp.json b/doc/api_samples/all_extensions/extensions-get-resp.json index 0ad7a6498409..4fcf47fe55b5 100644 --- a/doc/api_samples/all_extensions/extensions-get-resp.json +++ b/doc/api_samples/all_extensions/extensions-get-resp.json @@ -56,6 +56,14 @@ "namespace": "http://docs.openstack.org/compute/ext/extended_status/api/v1.1", "updated": "2011-11-03T00:00:00+00:00" }, + { + "alias": "OS-EXT-VIF-NET", + "description": "Adds network id parameter to the virtual interface list.", + "links": [], + "name": "ExtendedVIFNet", + "namespace": "http://docs.openstack.org/compute/ext/extended-virtual-interfaces-net/api/v1.1", + "updated": "2013-03-07T00:00:00+00:00" + }, { "alias": "OS-FLV-DISABLED", "description": "Support to show the disabled status of a flavor.", diff --git a/doc/api_samples/all_extensions/extensions-get-resp.xml b/doc/api_samples/all_extensions/extensions-get-resp.xml index da20e0b6169b..179a05363530 100644 --- a/doc/api_samples/all_extensions/extensions-get-resp.xml +++ b/doc/api_samples/all_extensions/extensions-get-resp.xml @@ -21,6 +21,9 @@ Extended Status support. + + Adds network id parameter to the virtual interface list. + Support to show the disabled status of a flavor. diff --git a/etc/nova/policy.json b/etc/nova/policy.json index 5a6800f94264..1213f3fb58b9 100644 --- a/etc/nova/policy.json +++ b/etc/nova/policy.json @@ -46,6 +46,7 @@ "compute_extension:extended_status": "", "compute_extension:extended_availability_zone": "", "compute_extension:extended_ips": "", + "compute_extension:extended_vif_net": "", "compute_extension:fixed_ips": "rule:admin_api", "compute_extension:flavor_access": "", "compute_extension:flavor_disabled": "", diff --git a/nova/api/openstack/compute/contrib/extended_virtual_interfaces_net.py b/nova/api/openstack/compute/contrib/extended_virtual_interfaces_net.py new file mode 100644 index 000000000000..d087472bbcf8 --- /dev/null +++ b/nova/api/openstack/compute/contrib/extended_virtual_interfaces_net.py @@ -0,0 +1,77 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 IBM Corp. +# +# 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 nova.api.openstack import extensions +from nova.api.openstack import wsgi +from nova.api.openstack import xmlutil +from nova import network +from nova.openstack.common import log as logging + +LOG = logging.getLogger(__name__) +authorize = extensions.soft_extension_authorizer('compute', 'extended_vif_net') + + +def make_vif(elem): + elem.set('{%s}net_id' % Extended_virtual_interfaces_net.namespace, + '%s:net_id' % Extended_virtual_interfaces_net.alias) + + +class ExtendedVirtualInterfaceNetTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('virtual_interfaces', + selector='virtual_interfaces') + elem = xmlutil.SubTemplateElement(root, 'virtual_interface', + selector='virtual_interfaces') + make_vif(elem) + return xmlutil.SlaveTemplate(root, 1, + nsmap={Extended_virtual_interfaces_net.alias: + Extended_virtual_interfaces_net.namespace}) + + +class ExtendedServerVIFNetController(wsgi.Controller): + def __init__(self): + super(ExtendedServerVIFNetController, self).__init__() + self.network_api = network.API() + + @wsgi.extends + def index(self, req, resp_obj, server_id): + key = "%s:net_id" % Extended_virtual_interfaces_net.alias + context = req.environ['nova.context'] + if authorize(context): + # Attach our slave template to the response object + resp_obj.attach(xml=ExtendedVirtualInterfaceNetTemplate()) + for vif in resp_obj.obj['virtual_interfaces']: + vif1 = self.network_api.get_vif_by_mac_address(context, + vif['mac_address']) + vif[key] = vif1['net_uuid'] + + +class Extended_virtual_interfaces_net(extensions.ExtensionDescriptor): + """Adds network id parameter to the virtual interface list.""" + + name = "ExtendedVIFNet" + alias = "OS-EXT-VIF-NET" + namespace = ("http://docs.openstack.org/compute/ext/" + "extended-virtual-interfaces-net/api/v1.1") + updated = "2013-03-07T00:00:00+00:00" + + def get_controller_extensions(self): + controller = ExtendedServerVIFNetController() + extension = extensions.ControllerExtension(self, + 'os-virtual-interfaces', + controller) + return [extension] diff --git a/nova/network/api.py b/nova/network/api.py index 21d071357992..4d1c145f89b4 100644 --- a/nova/network/api.py +++ b/nova/network/api.py @@ -3,6 +3,7 @@ # Copyright (c) 2011 X.commerce, a business unit of eBay Inc. # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. +# Copyright 2013 IBM Corp. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -185,13 +186,24 @@ class API(base.Base): @wrap_check_policy def get_vifs_by_instance(self, context, instance): - return self.db.virtual_interface_get_by_instance(context, + vifs = self.db.virtual_interface_get_by_instance(context, instance['uuid']) + for vif in vifs: + if vif.get('network_id') is not None: + network = self.db.network_get(context, vif['network_id'], + project_only="allow_none") + vif['net_uuid'] = network['uuid'] + return vifs @wrap_check_policy def get_vif_by_mac_address(self, context, mac_address): - return self.db.virtual_interface_get_by_address(context, - mac_address) + vif = self.db.virtual_interface_get_by_address(context, + mac_address) + if vif.get('network_id') is not None: + network = self.db.network_get(context, vif['network_id'], + project_only="allow_none") + vif['net_uuid'] = network['uuid'] + return vif @wrap_check_policy def allocate_floating_ip(self, context, pool=None): diff --git a/nova/network/manager.py b/nova/network/manager.py index ac413135acb7..0e668a164f74 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -4,6 +4,7 @@ # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. +# Copyright 2013 IBM Corp. # # 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 @@ -1343,6 +1344,10 @@ class NetworkManager(manager.Manager): instance = self.db.instance_get(context, instance_id) vifs = self.db.virtual_interface_get_by_instance(context, instance['uuid']) + for vif in vifs: + if vif.get('network_id') is not None: + network = self._get_network_by_id(context, vif['network_id']) + vif['net_uuid'] = network['uuid'] return [dict(vif.iteritems()) for vif in vifs] def get_instance_id_by_floating_address(self, context, address): @@ -1393,8 +1398,12 @@ class NetworkManager(manager.Manager): """Returns the vifs record for the mac_address.""" # NOTE(vish): This is no longer used but can't be removed until # we major version the network_rpcapi to 2.0. - return self.db.virtual_interface_get_by_address(context, + vif = self.db.virtual_interface_get_by_address(context, mac_address) + if vif.get('network_id') is not None: + network = self._get_network_by_id(context, vif['network_id']) + vif['net_uuid'] = network['uuid'] + return vif @manager.periodic_task( spacing=CONF.dns_update_periodic_interval) diff --git a/nova/tests/api/openstack/compute/contrib/test_extended_virtual_interfaces_net.py b/nova/tests/api/openstack/compute/contrib/test_extended_virtual_interfaces_net.py new file mode 100644 index 000000000000..35717b985d56 --- /dev/null +++ b/nova/tests/api/openstack/compute/contrib/test_extended_virtual_interfaces_net.py @@ -0,0 +1,124 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 IBM Corp. +# 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_virtual_interfaces_net +from nova.api.openstack import wsgi +from nova import compute +from nova import network +from nova.openstack.common import jsonutils +from nova import test +from nova.tests.api.openstack import fakes + + +FAKE_UUID = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' + + +FAKE_VIFS = [{'uuid': '00000000-0000-0000-0000-00000000000000000', + 'address': '00-00-00-00-00-00', + 'net_uuid': '00000000-0000-0000-0000-00000000000000001'}, + {'uuid': '11111111-1111-1111-1111-11111111111111111', + 'address': '11-11-11-11-11-11', + 'net_uuid': '11111111-1111-1111-1111-11111111111111112'}] + +EXPECTED_NET_UUIDS = ['00000000-0000-0000-0000-00000000000000001', + '11111111-1111-1111-1111-11111111111111112'] + + +def compute_api_get(self, context, instance_id): + return dict(uuid=FAKE_UUID, id=instance_id, instance_type_id=1, host='bob') + + +def get_vifs_by_instance(self, context, instance_id): + return FAKE_VIFS + + +def get_vif_by_mac_address(self, context, mac_address): + if mac_address == "00-00-00-00-00-00": + return {'net_uuid': '00000000-0000-0000-0000-00000000000000001'} + else: + return {'net_uuid': '11111111-1111-1111-1111-11111111111111112'} + + +class ExtendedServerVIFNetTest(test.TestCase): + content_type = 'application/json' + prefix = "%s:" % extended_virtual_interfaces_net. \ + Extended_virtual_interfaces_net.alias + + def setUp(self): + super(ExtendedServerVIFNetTest, self).setUp() + self.stubs.Set(compute.api.API, "get", + compute_api_get) + self.stubs.Set(network.api.API, "get_vifs_by_instance", + get_vifs_by_instance) + self.stubs.Set(network.api.API, "get_vif_by_mac_address", + get_vif_by_mac_address) + self.flags( + osapi_compute_extension=[ + 'nova.api.openstack.compute.contrib.select_extensions'], + osapi_compute_ext_list=['Virtual_interfaces', + 'Extended_virtual_interfaces_net']) + + 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=( + 'os-virtual-interfaces', 'OS-EXT-VIF-NET'))) + return res + + def _get_vifs(self, body): + return jsonutils.loads(body).get('virtual_interfaces') + + def _get_net_id(self, vifs): + for vif in vifs: + yield vif['%snet_id' % self.prefix] + + def assertVIFs(self, vifs): + result = [] + for net_id in self._get_net_id(vifs): + result.append(net_id) + sorted(result) + + for i, net_uuid in enumerate(result): + self.assertEqual(net_uuid, EXPECTED_NET_UUIDS[i]) + + def test_get_extend_virtual_interfaces_list(self): + res = self._make_request('/v2/fake/servers/abcd/os-virtual-interfaces') + + self.assertEqual(res.status_int, 200) + self.assertVIFs(self._get_vifs(res.body)) + + +class ExtendedServerVIFNetSerializerTest(ExtendedServerVIFNetTest): + content_type = 'application/xml' + prefix = "{%s}" % extended_virtual_interfaces_net. \ + Extended_virtual_interfaces_net.namespace + + def setUp(self): + super(ExtendedServerVIFNetSerializerTest, self).setUp() + self.namespace = wsgi.XMLNS_V11 + self.serializer = extended_virtual_interfaces_net. \ + ExtendedVirtualInterfaceNetTemplate() + + def _get_vifs(self, body): + return etree.XML(body).getchildren() + + def _get_net_id(self, vifs): + for vif in vifs: + yield vif.attrib['%snet_id' % self.prefix] diff --git a/nova/tests/api/openstack/compute/test_extensions.py b/nova/tests/api/openstack/compute/test_extensions.py index dcc2c9b3de70..e73d42ad73b0 100644 --- a/nova/tests/api/openstack/compute/test_extensions.py +++ b/nova/tests/api/openstack/compute/test_extensions.py @@ -168,6 +168,7 @@ class ExtensionControllerTest(ExtensionTestCase): "DiskConfig", "ExtendedAvailabilityZone", "ExtendedIps", + "ExtendedVIFNet", "Evacuate", "ExtendedStatus", "ExtendedServerAttributes", diff --git a/nova/tests/fake_policy.py b/nova/tests/fake_policy.py index d47ff629ad5d..c0bbe9467845 100644 --- a/nova/tests/fake_policy.py +++ b/nova/tests/fake_policy.py @@ -124,6 +124,7 @@ policy_data = """ "compute_extension:extended_status": "", "compute_extension:extended_availability_zone": "", "compute_extension:extended_ips": "", + "compute_extension:extended_vif_net": "", "compute_extension:fixed_ips": "", "compute_extension:flavor_access": "", "compute_extension:flavor_disabled": "", @@ -219,6 +220,7 @@ policy_data = """ "network:associate": "", "network:disassociate": "", "network:get_vifs_by_instance": "", + "network:get_vif_by_mac_address": "", "network:allocate_for_instance": "", "network:deallocate_for_instance": "", "network:validate_networks": "", diff --git a/nova/tests/integrated/api_samples/OS-EXT-VIF-NET/server-post-req.json.tpl b/nova/tests/integrated/api_samples/OS-EXT-VIF-NET/server-post-req.json.tpl new file mode 100644 index 000000000000..d3916d1aa68a --- /dev/null +++ b/nova/tests/integrated/api_samples/OS-EXT-VIF-NET/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-VIF-NET/server-post-req.xml.tpl b/nova/tests/integrated/api_samples/OS-EXT-VIF-NET/server-post-req.xml.tpl new file mode 100644 index 000000000000..f92614984242 --- /dev/null +++ b/nova/tests/integrated/api_samples/OS-EXT-VIF-NET/server-post-req.xml.tpl @@ -0,0 +1,19 @@ + + + + Apache1 + + + + ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp + dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k + IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs + c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g + QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo + ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv + dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy + c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6 + b25zLiINCg0KLVJpY2hhcmQgQmFjaA== + + + diff --git a/nova/tests/integrated/api_samples/OS-EXT-VIF-NET/server-post-resp.json.tpl b/nova/tests/integrated/api_samples/OS-EXT-VIF-NET/server-post-resp.json.tpl new file mode 100644 index 000000000000..d5f030c8730b --- /dev/null +++ b/nova/tests/integrated/api_samples/OS-EXT-VIF-NET/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-VIF-NET/server-post-resp.xml.tpl b/nova/tests/integrated/api_samples/OS-EXT-VIF-NET/server-post-resp.xml.tpl new file mode 100644 index 000000000000..3bb13e69bd6d --- /dev/null +++ b/nova/tests/integrated/api_samples/OS-EXT-VIF-NET/server-post-resp.xml.tpl @@ -0,0 +1,6 @@ + + + + + + diff --git a/nova/tests/integrated/api_samples/OS-EXT-VIF-NET/vifs-list-resp.json.tpl b/nova/tests/integrated/api_samples/OS-EXT-VIF-NET/vifs-list-resp.json.tpl new file mode 100644 index 000000000000..684b93448d27 --- /dev/null +++ b/nova/tests/integrated/api_samples/OS-EXT-VIF-NET/vifs-list-resp.json.tpl @@ -0,0 +1,9 @@ +{ + "virtual_interfaces": [ + { + "id": "%(id)s", + "mac_address": "%(mac_addr)s", + "OS-EXT-VIF-NET:net_id": "%(id)s" + } + ] +} diff --git a/nova/tests/integrated/api_samples/OS-EXT-VIF-NET/vifs-list-resp.xml.tpl b/nova/tests/integrated/api_samples/OS-EXT-VIF-NET/vifs-list-resp.xml.tpl new file mode 100644 index 000000000000..adf7d7baa39f --- /dev/null +++ b/nova/tests/integrated/api_samples/OS-EXT-VIF-NET/vifs-list-resp.xml.tpl @@ -0,0 +1,8 @@ + + + + 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 1faf7f480321..05273245c3e3 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 @@ -56,6 +56,14 @@ "namespace": "http://docs.openstack.org/compute/ext/extended_status/api/v1.1", "updated": "%(timestamp)s" }, + { + "alias": "OS-EXT-VIF-NET", + "description": "%(text)s", + "links": [], + "name": "ExtendedVIFNet", + "namespace": "http://docs.openstack.org/compute/ext/extended-virtual-interfaces-net/api/v1.1", + "updated": "%(timestamp)s" + }, { "alias": "OS-FLV-DISABLED", "description": "%(text)s", 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 0aefc123f512..9bb85f5bd8af 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 @@ -21,6 +21,9 @@ %(text)s + + %(text)s + %(text)s diff --git a/nova/tests/integrated/test_api_samples.py b/nova/tests/integrated/test_api_samples.py index 9d907347eca0..c0c908e077c6 100644 --- a/nova/tests/integrated/test_api_samples.py +++ b/nova/tests/integrated/test_api_samples.py @@ -2356,6 +2356,36 @@ class ExtendedStatusSampleXmlTests(ExtendedStatusSampleJsonTests): ctype = 'xml' +class ExtendedVIFNetSampleJsonTests(ServersSampleBase): + extension_name = ("nova.api.openstack.compute.contrib" + ".extended_virtual_interfaces_net.Extended_virtual_interfaces_net") + + def _get_flags(self): + f = super(ExtendedVIFNetSampleJsonTests, self)._get_flags() + f['osapi_compute_extension'] = CONF.osapi_compute_extension[:] + # extended_virtual_interfaces_net_update also + # needs virtual_interfaces to be loaded + f['osapi_compute_extension'].append( + ('nova.api.openstack.compute.contrib' + '.virtual_interfaces.Virtual_interfaces')) + return f + + def test_vifs_list(self): + uuid = self._post_server() + + response = self._do_get('servers/%s/os-virtual-interfaces' % uuid) + self.assertEqual(response.status, 200) + + subs = self._get_regexes() + subs['mac_addr'] = '(?:[a-f0-9]{2}:){5}[a-f0-9]{2}' + + self._verify_response('vifs-list-resp', subs, response, 200) + + +class ExtendedVIFNetSampleXmlTests(ExtendedIpsSampleJsonTests): + ctype = 'xml' + + class FlavorManageSampleJsonTests(ApiSampleTestBase): extension_name = ("nova.api.openstack.compute.contrib.flavormanage." "Flavormanage")