From 69df608fbe1a58c21944188c2584e474de886f28 Mon Sep 17 00:00:00 2001 From: He Jie Xu Date: Mon, 11 Aug 2014 14:18:18 +0800 Subject: [PATCH] Change v3 attach_interface to v2.1 This patch changes v3 attach_interface API to v2.1 and makes v2 unit tests share between v2 and v2.1. The differences between v2 and v3 are described on the wiki page https://wiki.openstack.org/wiki/NovaAPIv2tov3. Partially implements blueprint v2-on-v3-api Change-Id: If18676604edc8fea41d7888eb6546245163e91c2 --- .../attach-interfaces-create-req.json | 2 +- .../attach-interfaces-create-resp.json | 2 +- .../attach-interfaces-list-resp.json | 2 +- .../attach-interfaces-show-resp.json | 2 +- .../compute/plugins/v3/attach_interfaces.py | 6 +- .../compute/schemas/v3/attach_interfaces.py | 2 +- .../compute/contrib/test_attach_interfaces.py | 162 ++++--- .../plugins/v3/test_attach_interfaces.py | 450 ------------------ .../attach-interfaces-create-req.json.tpl | 2 +- .../attach-interfaces-create-resp.json.tpl | 2 +- .../attach-interfaces-list-resp.json.tpl | 2 +- .../attach-interfaces-show-resp.json.tpl | 2 +- 12 files changed, 110 insertions(+), 526 deletions(-) delete mode 100644 nova/tests/api/openstack/compute/plugins/v3/test_attach_interfaces.py diff --git a/doc/v3/api_samples/os-attach-interfaces/attach-interfaces-create-req.json b/doc/v3/api_samples/os-attach-interfaces/attach-interfaces-create-req.json index af7bdd7af466..d14e7914041b 100644 --- a/doc/v3/api_samples/os-attach-interfaces/attach-interfaces-create-req.json +++ b/doc/v3/api_samples/os-attach-interfaces/attach-interfaces-create-req.json @@ -1,5 +1,5 @@ { - "interface_attachment": { + "interfaceAttachment": { "port_id": "ce531f90-199f-48c0-816c-13e38010b442" } } \ No newline at end of file diff --git a/doc/v3/api_samples/os-attach-interfaces/attach-interfaces-create-resp.json b/doc/v3/api_samples/os-attach-interfaces/attach-interfaces-create-resp.json index 93b68d9c694d..9dff234366fa 100644 --- a/doc/v3/api_samples/os-attach-interfaces/attach-interfaces-create-resp.json +++ b/doc/v3/api_samples/os-attach-interfaces/attach-interfaces-create-resp.json @@ -1,5 +1,5 @@ { - "interface_attachment": { + "interfaceAttachment": { "fixed_ips": [ { "ip_address": "192.168.1.3", diff --git a/doc/v3/api_samples/os-attach-interfaces/attach-interfaces-list-resp.json b/doc/v3/api_samples/os-attach-interfaces/attach-interfaces-list-resp.json index 9d977378b779..192f9a648733 100644 --- a/doc/v3/api_samples/os-attach-interfaces/attach-interfaces-list-resp.json +++ b/doc/v3/api_samples/os-attach-interfaces/attach-interfaces-list-resp.json @@ -1,5 +1,5 @@ { - "interface_attachments": [ + "interfaceAttachments": [ { "fixed_ips": [ { diff --git a/doc/v3/api_samples/os-attach-interfaces/attach-interfaces-show-resp.json b/doc/v3/api_samples/os-attach-interfaces/attach-interfaces-show-resp.json index 93b68d9c694d..9dff234366fa 100644 --- a/doc/v3/api_samples/os-attach-interfaces/attach-interfaces-show-resp.json +++ b/doc/v3/api_samples/os-attach-interfaces/attach-interfaces-show-resp.json @@ -1,5 +1,5 @@ { - "interface_attachment": { + "interfaceAttachment": { "fixed_ips": [ { "ip_address": "192.168.1.3", diff --git a/nova/api/openstack/compute/plugins/v3/attach_interfaces.py b/nova/api/openstack/compute/plugins/v3/attach_interfaces.py index 92eadd381cdc..cb414d78ca03 100644 --- a/nova/api/openstack/compute/plugins/v3/attach_interfaces.py +++ b/nova/api/openstack/compute/plugins/v3/attach_interfaces.py @@ -77,7 +77,7 @@ class InterfaceAttachmentController(object): if port_info['port']['device_id'] != server_id: raise exc.HTTPNotFound() - return {'interface_attachment': _translate_interface_attachment_view( + return {'interfaceAttachment': _translate_interface_attachment_view( port_info['port'])} @extensions.expected_errors((400, 404, 409, 500, 501)) @@ -91,7 +91,7 @@ class InterfaceAttachmentController(object): port_id = None req_ip = None if body: - attachment = body['interface_attachment'] + attachment = body['interfaceAttachment'] network_id = attachment.get('net_id', None) port_id = attachment.get('port_id', None) try: @@ -177,7 +177,7 @@ class InterfaceAttachmentController(object): ports = data.get('ports', []) results = [entity_maker(port) for port in ports] - return {'interface_attachments': results} + return {'interfaceAttachments': results} class AttachInterfaces(extensions.V3APIExtensionBase): diff --git a/nova/api/openstack/compute/schemas/v3/attach_interfaces.py b/nova/api/openstack/compute/schemas/v3/attach_interfaces.py index 471275a02f05..921ebc12fcf2 100644 --- a/nova/api/openstack/compute/schemas/v3/attach_interfaces.py +++ b/nova/api/openstack/compute/schemas/v3/attach_interfaces.py @@ -15,7 +15,7 @@ create = { 'type': 'object', 'properties': { - 'interface_attachment': { + 'interfaceAttachment': { 'type': 'object', 'properties': { 'net_id': { diff --git a/nova/tests/api/openstack/compute/contrib/test_attach_interfaces.py b/nova/tests/api/openstack/compute/contrib/test_attach_interfaces.py index ce3a7eb3555c..ee411d389620 100644 --- a/nova/tests/api/openstack/compute/contrib/test_attach_interfaces.py +++ b/nova/tests/api/openstack/compute/contrib/test_attach_interfaces.py @@ -16,7 +16,10 @@ import mock from oslo.config import cfg -from nova.api.openstack.compute.contrib import attach_interfaces +from nova.api.openstack.compute.contrib import attach_interfaces \ + as attach_interfaces_v2 +from nova.api.openstack.compute.plugins.v3 import attach_interfaces \ + as attach_interfaces_v3 from nova.compute import api as compute_api from nova import context from nova import exception @@ -41,6 +44,7 @@ FAKE_PORT_ID3 = '33333333-3333-3333-3333-333333333333' FAKE_NET_ID1 = '44444444-4444-4444-4444-444444444444' FAKE_NET_ID2 = '55555555-5555-5555-5555-555555555555' FAKE_NET_ID3 = '66666666-6666-6666-6666-666666666666' +FAKE_BAD_NET_ID = '00000000-0000-0000-0000-000000000000' port_data1 = { "id": FAKE_PORT_ID1, @@ -96,7 +100,7 @@ def fake_attach_interface(self, context, instance, network_id, port_id, # if no network_id is given when add a port to an instance, use the # first default network. network_id = fake_networks[0] - if network_id == 'bad_id': + if network_id == FAKE_BAD_NET_ID: raise exception.NetworkNotFound(network_id=network_id) if not port_id: port_id = ports[fake_networks.index(network_id)]['id'] @@ -118,9 +122,12 @@ def fake_get_instance(self, *args, **kwargs): return {} -class InterfaceAttachTests(test.NoDBTestCase): +class InterfaceAttachTestsV21(test.NoDBTestCase): + url = '/v3/os-interfaces' + controller_cls = attach_interfaces_v3.InterfaceAttachmentController + def setUp(self): - super(InterfaceAttachTests, self).setUp() + super(InterfaceAttachTestsV21, self).setUp() self.flags(auth_strategy=None, group='neutron') self.flags(url='http://anyhost/', group='neutron') self.flags(url_timeout=30, group='neutron') @@ -135,73 +142,69 @@ class InterfaceAttachTests(test.NoDBTestCase): 'port_state': port_data1['status'], 'fixed_ips': port_data1['fixed_ips'], }} + self.attachments = self.controller_cls() @mock.patch.object(compute_api.API, 'get', side_effect=exception.InstanceNotFound(instance_id='')) - def _test_instance_not_found(self, url, func, params, mock_get, + def _test_instance_not_found(self, url, func, args, mock_get, kwargs=None, method='GET'): req = webob.Request.blank(url) req.method = method req.headers['content-type'] = 'application/json' req.environ['nova.context'] = self.context - self.assertRaises(exc.HTTPNotFound, func, req, *params) + if not kwargs: + kwargs = {} + self.assertRaises(exc.HTTPNotFound, func, req, *args, **kwargs) def test_show_instance_not_found(self): - attachments = attach_interfaces.InterfaceAttachmentController() - self._test_instance_not_found('/v2/fake/os-interfaces/fake', - attachments.show, ('fake', 'fake')) + self._test_instance_not_found(self.url + 'fake', + self.attachments.show, ('fake', 'fake')) def test_index_instance_not_found(self): - attachments = attach_interfaces.InterfaceAttachmentController() - self._test_instance_not_found('/v2/fake/os-interfaces', - attachments.index, ('fake', )) + self._test_instance_not_found(self.url, + self.attachments.index, ('fake', )) - def test_delete_instance_not_found(self): - attachments = attach_interfaces.InterfaceAttachmentController() - self._test_instance_not_found('/v2/fake/os-interfaces/fake', - attachments.delete, ('fake', 'fake'), - method='DELETE') + def test_detach_interface_instance_not_found(self): + self._test_instance_not_found(self.url + '/fake', + self.attachments.delete, + ('fake', 'fake'), method='DELETE') - def test_create_instance_not_found(self): - attachments = attach_interfaces.InterfaceAttachmentController() - self._test_instance_not_found('/v2/fake/os-interfaces', - attachments.create, - ('fake', {'interfaceAttachment': {}}), - 'POST') + def test_attach_interface_instance_not_found(self): + self._test_instance_not_found( + '/v2/fake/os-interfaces', self.attachments.create, ('fake', ), + kwargs={'body': {'interfaceAttachment': {}}}, method='POST') def test_show(self): - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank('/v2/fake/os-interfaces/show') + req = webob.Request.blank(self.url + '/show') req.method = 'POST' req.body = jsonutils.dumps({}) req.headers['content-type'] = 'application/json' req.environ['nova.context'] = self.context - result = attachments.show(req, FAKE_UUID1, FAKE_PORT_ID1) + result = self.attachments.show(req, FAKE_UUID1, FAKE_PORT_ID1) self.assertEqual(self.expected_show, result) def test_show_invalid(self): - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank('/v2/fake/os-interfaces/show') + req = webob.Request.blank(self.url + '/show') req.method = 'POST' req.body = jsonutils.dumps({}) req.headers['content-type'] = 'application/json' req.environ['nova.context'] = self.context self.assertRaises(exc.HTTPNotFound, - attachments.show, req, FAKE_UUID2, FAKE_PORT_ID1) + self.attachments.show, req, FAKE_UUID2, + FAKE_PORT_ID1) def test_delete(self): self.stubs.Set(compute_api.API, 'detach_interface', fake_detach_interface) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank('/v2/fake/os-interfaces/delete') + req = webob.Request.blank(self.url + '/delete') req.method = 'DELETE' req.body = jsonutils.dumps({}) req.headers['content-type'] = 'application/json' req.environ['nova.context'] = self.context - result = attachments.delete(req, FAKE_UUID1, FAKE_PORT_ID1) + result = self.attachments.delete(req, FAKE_UUID1, FAKE_PORT_ID1) self.assertEqual('202 Accepted', result.status) def test_detach_interface_instance_locked(self): @@ -212,15 +215,14 @@ class InterfaceAttachTests(test.NoDBTestCase): self.stubs.Set(compute_api.API, 'detach_interface', fake_detach_interface_from_locked_server) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank('/v2/fake/os-interfaces/delete') + req = webob.Request.blank(self.url + '/delete') req.method = 'POST' req.body = jsonutils.dumps({}) req.headers['content-type'] = 'application/json' req.environ['nova.context'] = self.context self.assertRaises(exc.HTTPConflict, - attachments.delete, + self.attachments.delete, req, FAKE_UUID1, FAKE_PORT_ID1) @@ -228,15 +230,14 @@ class InterfaceAttachTests(test.NoDBTestCase): def test_delete_interface_not_found(self): self.stubs.Set(compute_api.API, 'detach_interface', fake_detach_interface) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank('/v2/fake/os-interfaces/delete') + req = webob.Request.blank(self.url + '/delete') req.method = 'DELETE' req.body = jsonutils.dumps({}) req.headers['content-type'] = 'application/json' req.environ['nova.context'] = self.context self.assertRaises(exc.HTTPNotFound, - attachments.delete, + self.attachments.delete, req, FAKE_UUID1, 'invaid-port-id') @@ -249,55 +250,53 @@ class InterfaceAttachTests(test.NoDBTestCase): self.stubs.Set(compute_api.API, 'attach_interface', fake_attach_interface_to_locked_server) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank('/v2/fake/os-interfaces/attach') + req = webob.Request.blank(self.url + '/attach') req.method = 'POST' req.body = jsonutils.dumps({}) req.headers['content-type'] = 'application/json' req.environ['nova.context'] = self.context self.assertRaises(exc.HTTPConflict, - attachments.create, req, FAKE_UUID1, - jsonutils.loads(req.body)) + self.attachments.create, req, FAKE_UUID1, + body=jsonutils.loads(req.body)) def test_attach_interface_without_network_id(self): self.stubs.Set(compute_api.API, 'attach_interface', fake_attach_interface) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank('/v2/fake/os-interfaces/attach') + req = webob.Request.blank(self.url + '/attach') req.method = 'POST' req.body = jsonutils.dumps({}) req.headers['content-type'] = 'application/json' req.environ['nova.context'] = self.context - result = attachments.create(req, FAKE_UUID1, jsonutils.loads(req.body)) + result = self.attachments.create(req, FAKE_UUID1, + body=jsonutils.loads(req.body)) self.assertEqual(result['interfaceAttachment']['net_id'], FAKE_NET_ID1) def test_attach_interface_with_network_id(self): self.stubs.Set(compute_api.API, 'attach_interface', fake_attach_interface) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank('/v2/fake/os-interfaces/attach') + req = webob.Request.blank(self.url + '/attach') req.method = 'POST' req.body = jsonutils.dumps({'interfaceAttachment': {'net_id': FAKE_NET_ID2}}) req.headers['content-type'] = 'application/json' req.environ['nova.context'] = self.context - result = attachments.create(req, FAKE_UUID1, jsonutils.loads(req.body)) + result = self.attachments.create(req, FAKE_UUID1, + body=jsonutils.loads(req.body)) self.assertEqual(result['interfaceAttachment']['net_id'], FAKE_NET_ID2) def _attach_interface_bad_request_case(self, body): self.stubs.Set(compute_api.API, 'attach_interface', fake_attach_interface) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank('/v2/fake/os-interfaces/attach') + req = webob.Request.blank(self.url + '/attach') req.method = 'POST' req.body = jsonutils.dumps(body) req.headers['content-type'] = 'application/json' req.environ['nova.context'] = self.context self.assertRaises(exc.HTTPBadRequest, - attachments.create, req, FAKE_UUID1, - jsonutils.loads(req.body)) + self.attachments.create, req, FAKE_UUID1, + body=jsonutils.loads(req.body)) def test_attach_interface_with_port_and_network_id(self): body = { @@ -311,7 +310,7 @@ class InterfaceAttachTests(test.NoDBTestCase): def test_attach_interface_with_invalid_data(self): body = { 'interfaceAttachment': { - 'net_id': 'bad_id' + 'net_id': FAKE_BAD_NET_ID } } self._attach_interface_bad_request_case(body) @@ -324,16 +323,15 @@ class InterfaceAttachTests(test.NoDBTestCase): self.stubs.Set(compute_api.API, 'attach_interface', fake_attach_interface_invalid_state) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank('/v2/fake/os-interfaces/attach') + req = webob.Request.blank(self.url + '/attach') req.method = 'POST' req.body = jsonutils.dumps({'interfaceAttachment': {'net_id': FAKE_NET_ID1}}) req.headers['content-type'] = 'application/json' req.environ['nova.context'] = self.context self.assertRaises(exc.HTTPConflict, - attachments.create, req, FAKE_UUID1, - jsonutils.loads(req.body)) + self.attachments.create, req, FAKE_UUID1, + body=jsonutils.loads(req.body)) def test_detach_interface_with_invalid_state(self): def fake_detach_interface_invalid_state(*args, **kwargs): @@ -343,14 +341,13 @@ class InterfaceAttachTests(test.NoDBTestCase): self.stubs.Set(compute_api.API, 'detach_interface', fake_detach_interface_invalid_state) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank('/v2/fake/os-interfaces/attach') + req = webob.Request.blank(self.url + '/attach') req.method = 'DELETE' req.body = jsonutils.dumps({}) req.headers['content-type'] = 'application/json' req.environ['nova.context'] = self.context self.assertRaises(exc.HTTPConflict, - attachments.delete, + self.attachments.delete, req, FAKE_UUID1, FAKE_NET_ID1) @@ -363,16 +360,53 @@ class InterfaceAttachTests(test.NoDBTestCase): get_mock.side_effect = fake_get_instance attach_mock.side_effect = exception.FixedIpAlreadyInUse( address='10.0.2.2', instance_uuid=FAKE_UUID1) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank('/v2/fake/os-interfaces/attach') + req = webob.Request.blank(self.url + '/attach') req.method = 'POST' req.body = jsonutils.dumps({}) req.headers['content-type'] = 'application/json' req.environ['nova.context'] = self.context self.assertRaises(exc.HTTPBadRequest, - attachments.create, req, FAKE_UUID1, - jsonutils.loads(req.body)) + self.attachments.create, req, FAKE_UUID1, + body=jsonutils.loads(req.body)) attach_mock.assert_called_once_with(self.context, {}, None, None, None) get_mock.assert_called_once_with(self.context, FAKE_UUID1, want_objects=True, expected_attrs=None) + + def _test_attach_interface_with_invalid_parameter(self, param): + self.stubs.Set(compute_api.API, 'attach_interface', + fake_attach_interface) + req = webob.Request.blank(self.url + '/attach') + req.method = 'POST' + req.body = jsonutils.dumps({'interface_attachment': param}) + req.headers['content-type'] = 'application/json' + req.environ['nova.context'] = self.context + self.assertRaises(exception.ValidationError, + self.attachments.create, req, FAKE_UUID1, + body=jsonutils.loads(req.body)) + + def test_attach_interface_instance_with_non_uuid_net_id(self): + param = {'net_id': 'non_uuid'} + self._test_attach_interface_with_invalid_parameter(param) + + def test_attach_interface_instance_with_non_uuid_port_id(self): + param = {'port_id': 'non_uuid'} + self._test_attach_interface_with_invalid_parameter(param) + + def test_attach_interface_instance_with_non_array_fixed_ips(self): + param = {'fixed_ips': 'non_array'} + self._test_attach_interface_with_invalid_parameter(param) + + +class InterfaceAttachTestsV2(InterfaceAttachTestsV21): + url = '/v2/fake/os-interfaces' + controller_cls = attach_interfaces_v2.InterfaceAttachmentController + + def test_attach_interface_instance_with_non_uuid_net_id(self): + pass + + def test_attach_interface_instance_with_non_uuid_port_id(self): + pass + + def test_attach_interface_instance_with_non_array_fixed_ips(self): + pass diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_attach_interfaces.py b/nova/tests/api/openstack/compute/plugins/v3/test_attach_interfaces.py deleted file mode 100644 index f0ed6e45a6ef..000000000000 --- a/nova/tests/api/openstack/compute/plugins/v3/test_attach_interfaces.py +++ /dev/null @@ -1,450 +0,0 @@ -# Copyright 2012 SINA Inc. -# 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. - -import mock -from oslo.config import cfg - -from nova.api.openstack.compute.plugins.v3 import attach_interfaces -from nova.compute import api as compute_api -from nova import context -from nova import exception -from nova.network import api as network_api -from nova.openstack.common import jsonutils -from nova import test -from nova.tests import fake_network_cache_model - -import webob -from webob import exc - - -CONF = cfg.CONF - -FAKE_UUID1 = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' -FAKE_UUID2 = 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb' - -FAKE_PORT_ID1 = '11111111-1111-1111-1111-111111111111' -FAKE_PORT_ID2 = '22222222-2222-2222-2222-222222222222' -FAKE_PORT_ID3 = '33333333-3333-3333-3333-333333333333' - -FAKE_NET_ID1 = '44444444-4444-4444-4444-444444444444' -FAKE_NET_ID2 = '55555555-5555-5555-5555-555555555555' -FAKE_NET_ID3 = '66666666-6666-6666-6666-666666666666' - -port_data1 = { - "id": FAKE_PORT_ID1, - "network_id": FAKE_NET_ID1, - "admin_state_up": True, - "status": "ACTIVE", - "mac_address": "aa:aa:aa:aa:aa:aa", - "fixed_ips": ["10.0.1.2"], - "device_id": FAKE_UUID1, -} - -port_data2 = { - "id": FAKE_PORT_ID2, - "network_id": FAKE_NET_ID2, - "admin_state_up": True, - "status": "ACTIVE", - "mac_address": "bb:bb:bb:bb:bb:bb", - "fixed_ips": ["10.0.2.2"], - "device_id": FAKE_UUID1, -} - -port_data3 = { - "id": FAKE_PORT_ID3, - "network_id": FAKE_NET_ID3, - "admin_state_up": True, - "status": "ACTIVE", - "mac_address": "bb:bb:bb:bb:bb:bb", - "fixed_ips": ["10.0.2.2"], - "device_id": '', -} - -fake_networks = [FAKE_NET_ID1, FAKE_NET_ID2] -ports = [port_data1, port_data2, port_data3] - - -def fake_list_ports(self, *args, **kwargs): - result = [] - for port in ports: - if port['device_id'] == kwargs['device_id']: - result.append(port) - return {'ports': result} - - -def fake_show_port(self, context, port_id, **kwargs): - for port in ports: - if port['id'] == port_id: - return {'port': port} - - -def fake_attach_interface(self, context, instance, network_id, port_id, - requested_ip='192.168.1.3'): - if not network_id: - # if no network_id is given when add a port to an instance, use the - # first default network. - network_id = fake_networks[0] - if network_id == 'bad_id': - raise exception.NetworkNotFound(network_id=network_id) - if not port_id: - port_id = ports[fake_networks.index(network_id)]['id'] - vif = fake_network_cache_model.new_vif() - vif['id'] = port_id - vif['network']['id'] = network_id - vif['network']['subnets'][0]['ips'][0]['address'] = requested_ip - return vif - - -def fake_detach_interface(self, context, instance, port_id): - for port in ports: - if port['id'] == port_id: - return - raise exception.PortNotFound(port_id=port_id) - - -def fake_get_instance(self, *args, **kwargs): - return {} - - -class InterfaceAttachTests(test.NoDBTestCase): - def setUp(self): - super(InterfaceAttachTests, self).setUp() - self.flags(auth_strategy=None, group='neutron') - self.flags(url='http://anyhost/', group='neutron') - self.flags(url_timeout=30, group='neutron') - self.stubs.Set(network_api.API, 'show_port', fake_show_port) - self.stubs.Set(network_api.API, 'list_ports', fake_list_ports) - self.stubs.Set(compute_api.API, 'get', fake_get_instance) - self.context = context.get_admin_context() - self.expected_show = {'interface_attachment': - {'net_id': FAKE_NET_ID1, - 'port_id': FAKE_PORT_ID1, - 'mac_addr': port_data1['mac_address'], - 'port_state': port_data1['status'], - 'fixed_ips': port_data1['fixed_ips'], - }} - - def test_item_instance_not_found(self): - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank('/v3/servers/fake/os-attach-interfaces/') - req.method = 'GET' - req.body = jsonutils.dumps({}) - req.headers['content-type'] = 'application/json' - req.environ['nova.context'] = self.context - - def fake_get_instance_exception(self, context, instance_uuid, - **kwargs): - raise exception.InstanceNotFound(instance_id=instance_uuid) - - self.stubs.Set(compute_api.API, 'get', fake_get_instance_exception) - self.assertRaises(exc.HTTPNotFound, attachments.index, - req, 'fake') - - def test_show(self): - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank('/v3/servers/fake/os-attach-interfaces/show') - req.method = 'POST' - req.body = jsonutils.dumps({}) - req.headers['content-type'] = 'application/json' - req.environ['nova.context'] = self.context - - result = attachments.show(req, FAKE_UUID1, FAKE_PORT_ID1) - self.assertEqual(self.expected_show, result) - - def test_show_instance_not_found(self): - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank('/v3/servers/fake/os-attach-interfaces/show') - req.method = 'POST' - req.body = jsonutils.dumps({}) - req.headers['content-type'] = 'application/json' - req.environ['nova.context'] = self.context - - def fake_get_instance_exception(self, context, instance_uuid, - **kwargs): - raise exception.InstanceNotFound(instance_id=instance_uuid) - - self.stubs.Set(compute_api.API, 'get', fake_get_instance_exception) - self.assertRaises(exc.HTTPNotFound, attachments.show, - req, 'fake', FAKE_PORT_ID1) - - def test_show_invalid(self): - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank('/v3/servers/fake/os-attach-interfaces/show') - req.method = 'POST' - req.body = jsonutils.dumps({}) - req.headers['content-type'] = 'application/json' - req.environ['nova.context'] = self.context - - self.assertRaises(exc.HTTPNotFound, - attachments.show, req, FAKE_UUID2, FAKE_PORT_ID1) - - def test_delete(self): - self.stubs.Set(compute_api.API, 'detach_interface', - fake_detach_interface) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank( - '/v3/servers/fake/os-attach-interfaces/delete') - req.method = 'DELETE' - req.body = jsonutils.dumps({}) - req.headers['content-type'] = 'application/json' - req.environ['nova.context'] = self.context - - result = attachments.delete(req, FAKE_UUID1, FAKE_PORT_ID1) - self.assertEqual('202 Accepted', result.status) - - def test_detach_interface_instance_locked(self): - def fake_detach_interface_from_locked_server(self, context, - instance, port_id): - raise exception.InstanceIsLocked(instance_uuid=FAKE_UUID1) - - self.stubs.Set(compute_api.API, - 'detach_interface', - fake_detach_interface_from_locked_server) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank( - '/v3/servers/fake/os-attach-interfaces/delete') - req.method = 'POST' - req.body = jsonutils.dumps({}) - req.headers['content-type'] = 'application/json' - req.environ['nova.context'] = self.context - - self.assertRaises(exc.HTTPConflict, - attachments.delete, - req, - FAKE_UUID1, - FAKE_PORT_ID1) - - def test_delete_interface_not_found(self): - self.stubs.Set(compute_api.API, 'detach_interface', - fake_detach_interface) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank( - '/v3/servers/fake/os-attach-interfaces/delete') - req.method = 'DELETE' - req.body = jsonutils.dumps({}) - req.headers['content-type'] = 'application/json' - req.environ['nova.context'] = self.context - - self.assertRaises(exc.HTTPNotFound, - attachments.delete, - req, - FAKE_UUID1, - 'invaid-port-id') - - def test_delete_instance_not_found(self): - self.stubs.Set(compute_api.API, 'detach_interface', - fake_detach_interface) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank( - '/v3/servers/fake/os-attach-interfaces/delete') - req.method = 'DELETE' - req.body = jsonutils.dumps({}) - req.headers['content-type'] = 'application/json' - req.environ['nova.context'] = self.context - - def fake_get_instance_exception(self, context, instance_uuid, - **kwargs): - raise exception.InstanceNotFound(instance_id=instance_uuid) - - self.stubs.Set(compute_api.API, 'get', fake_get_instance_exception) - self.assertRaises(exc.HTTPNotFound, - attachments.delete, - req, - 'fake', - 'invaid-port-id') - - def test_attach_interface_instance_locked(self): - def fake_attach_interface_to_locked_server(self, context, - instance, network_id, port_id, requested_ip): - raise exception.InstanceIsLocked(instance_uuid=FAKE_UUID1) - - self.stubs.Set(compute_api.API, - 'attach_interface', - fake_attach_interface_to_locked_server) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank( - '/v3/servers/fake/os-attach-interfaces/attach') - req.method = 'POST' - req.body = jsonutils.dumps({}) - req.headers['content-type'] = 'application/json' - req.environ['nova.context'] = self.context - self.assertRaises(exc.HTTPConflict, - attachments.create, req, FAKE_UUID1, - body=jsonutils.loads(req.body)) - - def test_attach_interface_without_network_id(self): - self.stubs.Set(compute_api.API, 'attach_interface', - fake_attach_interface) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank( - '/v3/servers/fake/os-attach-interfaces/attach') - req.method = 'POST' - req.body = jsonutils.dumps({}) - req.headers['content-type'] = 'application/json' - req.environ['nova.context'] = self.context - result = attachments.create(req, FAKE_UUID1, - body=jsonutils.loads(req.body)) - self.assertEqual(result['interface_attachment']['net_id'], - FAKE_NET_ID1) - - def test_attach_interface_with_network_id(self): - self.stubs.Set(compute_api.API, 'attach_interface', - fake_attach_interface) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank( - '/v3/servers/fake/os-attach-interfaces/attach') - req.method = 'POST' - req.body = jsonutils.dumps({'interface_attachment': - {'net_id': FAKE_NET_ID2}}) - req.headers['content-type'] = 'application/json' - req.environ['nova.context'] = self.context - result = attachments.create(req, - FAKE_UUID1, body=jsonutils.loads(req.body)) - self.assertEqual(result['interface_attachment']['net_id'], - FAKE_NET_ID2) - - def test_attach_interface_with_port_and_network_id(self): - self.stubs.Set(compute_api.API, 'attach_interface', - fake_attach_interface) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank( - '/v3/servers/fake/os-attach-interfaces/attach') - req.method = 'POST' - req.body = jsonutils.dumps({'interface_attachment': - {'port_id': FAKE_PORT_ID1, - 'net_id': FAKE_NET_ID2}}) - req.headers['content-type'] = 'application/json' - req.environ['nova.context'] = self.context - self.assertRaises(exc.HTTPBadRequest, - attachments.create, req, FAKE_UUID1, - body=jsonutils.loads(req.body)) - - def test_attach_interface_instance_not_found(self): - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank( - '/v3/servers/fake/os-attach-interfaces/attach') - req.method = 'POST' - req.body = jsonutils.dumps({'interface_attachment': - {'net_id': FAKE_NET_ID2}}) - req.headers['content-type'] = 'application/json' - req.environ['nova.context'] = self.context - - def fake_get_instance_exception(self, context, instance_uuid, - **kwargs): - raise exception.InstanceNotFound(instance_id=instance_uuid) - - self.stubs.Set(compute_api.API, 'get', fake_get_instance_exception) - self.assertRaises(exc.HTTPNotFound, - attachments.create, req, 'fake', - body=jsonutils.loads(req.body)) - - def _test_attach_interface_with_invalid_parameter(self, param): - self.stubs.Set(compute_api.API, 'attach_interface', - fake_attach_interface) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank( - '/v3/servers/fake/os-attach-interfaces/attach') - req.method = 'POST' - req.body = jsonutils.dumps({'interface_attachment': param}) - req.headers['content-type'] = 'application/json' - req.environ['nova.context'] = self.context - self.assertRaises(exception.ValidationError, - attachments.create, req, FAKE_UUID1, - body=jsonutils.loads(req.body)) - - def test_attach_interface_instance_with_non_uuid_net_id(self): - param = {'net_id': 'non_uuid'} - self._test_attach_interface_with_invalid_parameter(param) - - def test_attach_interface_instance_with_non_uuid_port_id(self): - param = {'port_id': 'non_uuid'} - self._test_attach_interface_with_invalid_parameter(param) - - def test_attach_interface_instance_with_non_array_fixed_ips(self): - param = {'fixed_ips': 'non_array'} - self._test_attach_interface_with_invalid_parameter(param) - - def test_attach_interface_with_invalid_state(self): - def fake_attach_interface_invalid_state(*args, **kwargs): - raise exception.InstanceInvalidState( - instance_uuid='', attr='', state='', - method='attach_interface') - - self.stubs.Set(compute_api.API, 'attach_interface', - fake_attach_interface_invalid_state) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank( - '/v3/servers/fake/os-attach-interfaces/attach') - req.method = 'POST' - req.body = jsonutils.dumps({'interface_attachment': - {'net_id': FAKE_NET_ID1}}) - req.headers['content-type'] = 'application/json' - req.environ['nova.context'] = self.context - self.assertRaises(exc.HTTPConflict, - attachments.create, req, FAKE_UUID1, - body=jsonutils.loads(req.body)) - - def test_detach_interface_with_invalid_state(self): - def fake_detach_interface_invalid_state(*args, **kwargs): - raise exception.InstanceInvalidState( - instance_uuid='', attr='', state='', - method='detach_interface') - - self.stubs.Set(compute_api.API, 'detach_interface', - fake_detach_interface_invalid_state) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank( - '/v3/servers/fake/os-attach-interfaces/delete') - req.method = 'DELETE' - req.body = jsonutils.dumps({}) - req.headers['content-type'] = 'application/json' - req.environ['nova.context'] = self.context - self.assertRaises(exc.HTTPConflict, - attachments.delete, - req, - FAKE_UUID1, - FAKE_NET_ID1) - - -class InterfaceAttachTestsWithMock(test.NoDBTestCase): - def setUp(self): - super(InterfaceAttachTestsWithMock, self).setUp() - self.flags(auth_strategy=None, group='neutron') - self.flags(url='http://anyhost/', group='neutron') - self.flags(url_timeout=30, group='neutron') - self.context = context.get_admin_context() - - @mock.patch.object(compute_api.API, 'get') - @mock.patch.object(compute_api.API, 'attach_interface') - def test_attach_interface_fixed_ip_already_in_use(self, - attach_mock, - get_mock): - get_mock.side_effect = fake_get_instance - attach_mock.side_effect = exception.FixedIpAlreadyInUse( - address='10.0.3.2', instance_uuid=FAKE_UUID1) - attachments = attach_interfaces.InterfaceAttachmentController() - req = webob.Request.blank( - '/v3/servers/fake/os-attach-interfaces/attach') - req.method = 'POST' - req.body = jsonutils.dumps({}) - req.headers['content-type'] = 'application/json' - req.environ['nova.context'] = self.context - self.assertRaises(exc.HTTPBadRequest, - attachments.create, req, FAKE_UUID1, - body=jsonutils.loads(req.body)) - attach_mock.assert_called_once_with(self.context, {}, None, None, None) - get_mock.assert_called_once_with(self.context, FAKE_UUID1, - want_objects=True, - expected_attrs=None) diff --git a/nova/tests/integrated/v3/api_samples/os-attach-interfaces/attach-interfaces-create-req.json.tpl b/nova/tests/integrated/v3/api_samples/os-attach-interfaces/attach-interfaces-create-req.json.tpl index e0fcbe86a03d..11dcf64373a0 100644 --- a/nova/tests/integrated/v3/api_samples/os-attach-interfaces/attach-interfaces-create-req.json.tpl +++ b/nova/tests/integrated/v3/api_samples/os-attach-interfaces/attach-interfaces-create-req.json.tpl @@ -1,5 +1,5 @@ { - "interface_attachment": { + "interfaceAttachment": { "port_id": "ce531f90-199f-48c0-816c-13e38010b442" } } diff --git a/nova/tests/integrated/v3/api_samples/os-attach-interfaces/attach-interfaces-create-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-attach-interfaces/attach-interfaces-create-resp.json.tpl index 93b68d9c694d..9dff234366fa 100644 --- a/nova/tests/integrated/v3/api_samples/os-attach-interfaces/attach-interfaces-create-resp.json.tpl +++ b/nova/tests/integrated/v3/api_samples/os-attach-interfaces/attach-interfaces-create-resp.json.tpl @@ -1,5 +1,5 @@ { - "interface_attachment": { + "interfaceAttachment": { "fixed_ips": [ { "ip_address": "192.168.1.3", diff --git a/nova/tests/integrated/v3/api_samples/os-attach-interfaces/attach-interfaces-list-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-attach-interfaces/attach-interfaces-list-resp.json.tpl index 9d977378b779..192f9a648733 100644 --- a/nova/tests/integrated/v3/api_samples/os-attach-interfaces/attach-interfaces-list-resp.json.tpl +++ b/nova/tests/integrated/v3/api_samples/os-attach-interfaces/attach-interfaces-list-resp.json.tpl @@ -1,5 +1,5 @@ { - "interface_attachments": [ + "interfaceAttachments": [ { "fixed_ips": [ { diff --git a/nova/tests/integrated/v3/api_samples/os-attach-interfaces/attach-interfaces-show-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-attach-interfaces/attach-interfaces-show-resp.json.tpl index 93b68d9c694d..9dff234366fa 100644 --- a/nova/tests/integrated/v3/api_samples/os-attach-interfaces/attach-interfaces-show-resp.json.tpl +++ b/nova/tests/integrated/v3/api_samples/os-attach-interfaces/attach-interfaces-show-resp.json.tpl @@ -1,5 +1,5 @@ { - "interface_attachment": { + "interfaceAttachment": { "fixed_ips": [ { "ip_address": "192.168.1.3",