Add an extension to show the network id of a virtual interface
This extension adds the OS-EXT-VIF-NET:net_id param so that users can determine vif plunged into which network now. DocImpact Change-Id: I56bef5c45f7f545aa5e9b13760dff1c802da0f8f Signed-off-by: Zhi Yan Liu <zhiyanl@cn.ibm.com>
This commit is contained in:
		
							
								
								
									
										16
									
								
								doc/api_samples/OS-EXT-VIF-NET/server-post-req.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								doc/api_samples/OS-EXT-VIF-NET/server-post-req.json
									
									
									
									
									
										Normal file
									
								
							| @@ -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==" | ||||||
|  |             } | ||||||
|  |         ] | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								doc/api_samples/OS-EXT-VIF-NET/server-post-req.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								doc/api_samples/OS-EXT-VIF-NET/server-post-req.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <server xmlns="http://docs.openstack.org/compute/api/v1.1" imageRef="http://openstack.example.com/openstack/images/70a599e0-31e7-49b7-b260-868f441e862b" flavorRef="http://openstack.example.com/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> | ||||||
							
								
								
									
										16
									
								
								doc/api_samples/OS-EXT-VIF-NET/server-post-resp.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								doc/api_samples/OS-EXT-VIF-NET/server-post-resp.json
									
									
									
									
									
										Normal file
									
								
							| @@ -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" | ||||||
|  |             } | ||||||
|  |         ] | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										6
									
								
								doc/api_samples/OS-EXT-VIF-NET/server-post-resp.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								doc/api_samples/OS-EXT-VIF-NET/server-post-resp.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -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="37443b33-eb80-4eea-90d8-f90778f53dea" adminPass="ffV6E5gsNPpi"> | ||||||
|  |   <metadata/> | ||||||
|  |   <atom:link href="http://openstack.example.com/v2/openstack/servers/37443b33-eb80-4eea-90d8-f90778f53dea" rel="self"/> | ||||||
|  |   <atom:link href="http://openstack.example.com/openstack/servers/37443b33-eb80-4eea-90d8-f90778f53dea" rel="bookmark"/> | ||||||
|  | </server> | ||||||
							
								
								
									
										9
									
								
								doc/api_samples/OS-EXT-VIF-NET/vifs-list-resp.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								doc/api_samples/OS-EXT-VIF-NET/vifs-list-resp.json
									
									
									
									
									
										Normal file
									
								
							| @@ -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" | ||||||
|  |         } | ||||||
|  |     ] | ||||||
|  | } | ||||||
							
								
								
									
										8
									
								
								doc/api_samples/OS-EXT-VIF-NET/vifs-list-resp.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								doc/api_samples/OS-EXT-VIF-NET/vifs-list-resp.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | <?xml version='1.0' encoding='UTF-8'?> | ||||||
|  | <virtual_interfaces | ||||||
|  | 	xmlns:OS-EXT-VIF-NET="http://docs.openstack.org/compute/ext/extended-virtual-interfaces-net/api/v1.1" | ||||||
|  | 	xmlns="http://docs.openstack.org/compute/api/v1.1"> | ||||||
|  |   <virtual_interface id="94edf7aa-565a-469a-8f45-656b4acf8229" | ||||||
|  |                      mac_address="fa:16:3e:7d:31:9a" | ||||||
|  |                      OS-EXT-VIF-NET:net_id="94edf7aa-565a-469a-8f45-656b4acf8230"/> | ||||||
|  | </virtual_interfaces> | ||||||
| @@ -56,6 +56,14 @@ | |||||||
|             "namespace": "http://docs.openstack.org/compute/ext/extended_status/api/v1.1", |             "namespace": "http://docs.openstack.org/compute/ext/extended_status/api/v1.1", | ||||||
|             "updated": "2011-11-03T00:00:00+00:00" |             "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", |             "alias": "OS-FLV-DISABLED", | ||||||
|             "description": "Support to show the disabled status of a flavor.", |             "description": "Support to show the disabled status of a flavor.", | ||||||
|   | |||||||
| @@ -21,6 +21,9 @@ | |||||||
|   <extension alias="OS-EXT-STS" updated="2011-11-03T00:00:00+00:00" namespace="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" name="ExtendedStatus"> |   <extension alias="OS-EXT-STS" updated="2011-11-03T00:00:00+00:00" namespace="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" name="ExtendedStatus"> | ||||||
|     <description>Extended Status support.</description> |     <description>Extended Status support.</description> | ||||||
|   </extension> |   </extension> | ||||||
|  |   <extension alias="OS-EXT-VIF-NET" updated="2013-03-07T00:00:00+00:00" namespace="http://docs.openstack.org/compute/ext/extended-virtual-interfaces-net/api/v1.1" name="ExtendedVIFNet"> | ||||||
|  |     <description>Adds network id parameter to the virtual interface list.</description> | ||||||
|  |   </extension> | ||||||
|   <extension alias="OS-FLV-DISABLED" updated="2012-08-29T00:00:00+00:00" namespace="http://docs.openstack.org/compute/ext/flavor_disabled/api/v1.1" name="FlavorDisabled"> |   <extension alias="OS-FLV-DISABLED" updated="2012-08-29T00:00:00+00:00" namespace="http://docs.openstack.org/compute/ext/flavor_disabled/api/v1.1" name="FlavorDisabled"> | ||||||
|     <description>Support to show the disabled status of a flavor.</description> |     <description>Support to show the disabled status of a flavor.</description> | ||||||
|   </extension> |   </extension> | ||||||
|   | |||||||
| @@ -46,6 +46,7 @@ | |||||||
|     "compute_extension:extended_status": "", |     "compute_extension:extended_status": "", | ||||||
|     "compute_extension:extended_availability_zone": "", |     "compute_extension:extended_availability_zone": "", | ||||||
|     "compute_extension:extended_ips": "", |     "compute_extension:extended_ips": "", | ||||||
|  |     "compute_extension:extended_vif_net": "", | ||||||
|     "compute_extension:fixed_ips": "rule:admin_api", |     "compute_extension:fixed_ips": "rule:admin_api", | ||||||
|     "compute_extension:flavor_access": "", |     "compute_extension:flavor_access": "", | ||||||
|     "compute_extension:flavor_disabled": "", |     "compute_extension:flavor_disabled": "", | ||||||
|   | |||||||
| @@ -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] | ||||||
| @@ -3,6 +3,7 @@ | |||||||
| # Copyright (c) 2011 X.commerce, a business unit of eBay Inc. | # Copyright (c) 2011 X.commerce, a business unit of eBay Inc. | ||||||
| # Copyright 2010 United States Government as represented by the | # Copyright 2010 United States Government as represented by the | ||||||
| # Administrator of the National Aeronautics and Space Administration. | # Administrator of the National Aeronautics and Space Administration. | ||||||
|  | # Copyright 2013 IBM Corp. | ||||||
| # All Rights Reserved. | # All Rights Reserved. | ||||||
| # | # | ||||||
| #    Licensed under the Apache License, Version 2.0 (the "License"); you may | #    Licensed under the Apache License, Version 2.0 (the "License"); you may | ||||||
| @@ -185,13 +186,24 @@ class API(base.Base): | |||||||
|  |  | ||||||
|     @wrap_check_policy |     @wrap_check_policy | ||||||
|     def get_vifs_by_instance(self, context, instance): |     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']) |                                                          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 |     @wrap_check_policy | ||||||
|     def get_vif_by_mac_address(self, context, mac_address): |     def get_vif_by_mac_address(self, context, mac_address): | ||||||
|         return self.db.virtual_interface_get_by_address(context, |         vif = self.db.virtual_interface_get_by_address(context, | ||||||
|                                                         mac_address) |                                                        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 |     @wrap_check_policy | ||||||
|     def allocate_floating_ip(self, context, pool=None): |     def allocate_floating_ip(self, context, pool=None): | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
| # Copyright 2010 United States Government as represented by the | # Copyright 2010 United States Government as represented by the | ||||||
| # Administrator of the National Aeronautics and Space Administration. | # Administrator of the National Aeronautics and Space Administration. | ||||||
| # All Rights Reserved. | # All Rights Reserved. | ||||||
|  | # Copyright 2013 IBM Corp. | ||||||
| # | # | ||||||
| #    Licensed under the Apache License, Version 2.0 (the "License"); you may | #    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 | #    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) |         instance = self.db.instance_get(context, instance_id) | ||||||
|         vifs = self.db.virtual_interface_get_by_instance(context, |         vifs = self.db.virtual_interface_get_by_instance(context, | ||||||
|                                                          instance['uuid']) |                                                          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] |         return [dict(vif.iteritems()) for vif in vifs] | ||||||
|  |  | ||||||
|     def get_instance_id_by_floating_address(self, context, address): |     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.""" |         """Returns the vifs record for the mac_address.""" | ||||||
|         # NOTE(vish): This is no longer used but can't be removed until |         # NOTE(vish): This is no longer used but can't be removed until | ||||||
|         #             we major version the network_rpcapi to 2.0. |         #             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) |                                                         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( |     @manager.periodic_task( | ||||||
|         spacing=CONF.dns_update_periodic_interval) |         spacing=CONF.dns_update_periodic_interval) | ||||||
|   | |||||||
| @@ -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] | ||||||
| @@ -168,6 +168,7 @@ class ExtensionControllerTest(ExtensionTestCase): | |||||||
|             "DiskConfig", |             "DiskConfig", | ||||||
|             "ExtendedAvailabilityZone", |             "ExtendedAvailabilityZone", | ||||||
|             "ExtendedIps", |             "ExtendedIps", | ||||||
|  |             "ExtendedVIFNet", | ||||||
|             "Evacuate", |             "Evacuate", | ||||||
|             "ExtendedStatus", |             "ExtendedStatus", | ||||||
|             "ExtendedServerAttributes", |             "ExtendedServerAttributes", | ||||||
|   | |||||||
| @@ -124,6 +124,7 @@ policy_data = """ | |||||||
|     "compute_extension:extended_status": "", |     "compute_extension:extended_status": "", | ||||||
|     "compute_extension:extended_availability_zone": "", |     "compute_extension:extended_availability_zone": "", | ||||||
|     "compute_extension:extended_ips": "", |     "compute_extension:extended_ips": "", | ||||||
|  |     "compute_extension:extended_vif_net": "", | ||||||
|     "compute_extension:fixed_ips": "", |     "compute_extension:fixed_ips": "", | ||||||
|     "compute_extension:flavor_access": "", |     "compute_extension:flavor_access": "", | ||||||
|     "compute_extension:flavor_disabled": "", |     "compute_extension:flavor_disabled": "", | ||||||
| @@ -219,6 +220,7 @@ policy_data = """ | |||||||
|     "network:associate": "", |     "network:associate": "", | ||||||
|     "network:disassociate": "", |     "network:disassociate": "", | ||||||
|     "network:get_vifs_by_instance": "", |     "network:get_vifs_by_instance": "", | ||||||
|  |     "network:get_vif_by_mac_address": "", | ||||||
|     "network:allocate_for_instance": "", |     "network:allocate_for_instance": "", | ||||||
|     "network:deallocate_for_instance": "", |     "network:deallocate_for_instance": "", | ||||||
|     "network:validate_networks": "", |     "network:validate_networks": "", | ||||||
|   | |||||||
| @@ -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==" | ||||||
|  |             } | ||||||
|  |         ] | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -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> | ||||||
| @@ -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" | ||||||
|  |             } | ||||||
|  |         ] | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -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> | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | { | ||||||
|  |     "virtual_interfaces": [ | ||||||
|  |         { | ||||||
|  |             "id": "%(id)s", | ||||||
|  |             "mac_address": "%(mac_addr)s", | ||||||
|  |             "OS-EXT-VIF-NET:net_id": "%(id)s" | ||||||
|  |         } | ||||||
|  |     ] | ||||||
|  | } | ||||||
| @@ -0,0 +1,8 @@ | |||||||
|  | <?xml version='1.0' encoding='UTF-8'?> | ||||||
|  | <virtual_interfaces | ||||||
|  |         xmlns:OS-EXT-VIF-NET="http://docs.openstack.org/compute/ext/extended-virtual-interfaces-net/api/v1.1" | ||||||
|  |         xmlns="http://docs.openstack.org/compute/api/v1.1"> | ||||||
|  |   <virtual_interface id="%(id)s" | ||||||
|  |                      mac_address="%(mac_addr)s" | ||||||
|  |                      OS-EXT-VIF-NET:net_id="%(id)s"/> | ||||||
|  | </virtual_interfaces> | ||||||
| @@ -56,6 +56,14 @@ | |||||||
|             "namespace": "http://docs.openstack.org/compute/ext/extended_status/api/v1.1", |             "namespace": "http://docs.openstack.org/compute/ext/extended_status/api/v1.1", | ||||||
|             "updated": "%(timestamp)s" |             "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", |             "alias": "OS-FLV-DISABLED", | ||||||
|             "description": "%(text)s", |             "description": "%(text)s", | ||||||
|   | |||||||
| @@ -21,6 +21,9 @@ | |||||||
|   <extension alias="OS-EXT-STS" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" name="ExtendedStatus"> |   <extension alias="OS-EXT-STS" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" name="ExtendedStatus"> | ||||||
|     <description>%(text)s</description> |     <description>%(text)s</description> | ||||||
|   </extension> |   </extension> | ||||||
|  |   <extension alias="OS-EXT-VIF-NET" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/extended-virtual-interfaces-net/api/v1.1" name="ExtendedVIFNet"> | ||||||
|  |     <description>%(text)s</description> | ||||||
|  |   </extension> | ||||||
|   <extension alias="OS-FLV-DISABLED" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/flavor_disabled/api/v1.1" name="FlavorDisabled"> |   <extension alias="OS-FLV-DISABLED" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/flavor_disabled/api/v1.1" name="FlavorDisabled"> | ||||||
|     <description>%(text)s</description> |     <description>%(text)s</description> | ||||||
|   </extension> |   </extension> | ||||||
|   | |||||||
| @@ -2356,6 +2356,36 @@ class ExtendedStatusSampleXmlTests(ExtendedStatusSampleJsonTests): | |||||||
|         ctype = 'xml' |         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): | class FlavorManageSampleJsonTests(ApiSampleTestBase): | ||||||
|     extension_name = ("nova.api.openstack.compute.contrib.flavormanage." |     extension_name = ("nova.api.openstack.compute.contrib.flavormanage." | ||||||
|                       "Flavormanage") |                       "Flavormanage") | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Zhi Yan Liu
					Zhi Yan Liu