Convert multinic v3 plugin to v2.1

Changes required to have v3 plugin natively support
the v2.1 API.

add_fixed_ip -> addFixedIp
remove_fixed_ip -> removeFixedIp

Removes v3 version of the multinic test and changes to
share use of the v2 unittests code. Backports a v2.1 specific
test.

Partially implements blueprint v2-on-v3-api

Change-Id: Ie01eddf1e772092c291b1475404f87e6e6f47c71
This commit is contained in:
Chris Yeoh 2014-08-20 14:34:15 +09:30
parent 6e55c1f507
commit 07ad7689ee
8 changed files with 71 additions and 186 deletions

View File

@ -1,5 +1,5 @@
{
"add_fixed_ip":{
"addFixedIp":{
"network_id": 1
}
}
}

View File

@ -1,5 +1,5 @@
{
"remove_fixed_ip":{
"removeFixedIp":{
"address": "10.0.0.4"
}
}
}

View File

@ -36,8 +36,8 @@ class MultinicController(wsgi.Controller):
super(MultinicController, self).__init__(*args, **kwargs)
self.compute_api = compute.API()
@wsgi.action('add_fixed_ip')
@extensions.expected_errors(404)
@wsgi.action('addFixedIp')
@extensions.expected_errors((400, 404))
@validation.schema(multinic.add_fixed_ip)
def _add_fixed_ip(self, req, id, body):
"""Adds an IP on a given network to an instance."""
@ -46,7 +46,7 @@ class MultinicController(wsgi.Controller):
instance = common.get_instance(self.compute_api, context, id,
want_objects=True)
network_id = body['add_fixed_ip']['network_id']
network_id = body['addFixedIp']['networkId']
try:
self.compute_api.add_fixed_ip(context, instance, network_id)
except exception.NoMoreFixedIps as e:
@ -54,7 +54,7 @@ class MultinicController(wsgi.Controller):
return webob.Response(status_int=202)
@wsgi.action('remove_fixed_ip')
@wsgi.action('removeFixedIp')
@extensions.expected_errors((400, 404))
@validation.schema(multinic.remove_fixed_ip)
def _remove_fixed_ip(self, req, id, body):
@ -64,7 +64,7 @@ class MultinicController(wsgi.Controller):
instance = common.get_instance(self.compute_api, context, id,
want_objects=True)
address = body['remove_fixed_ip']['address']
address = body['removeFixedIp']['address']
try:
self.compute_api.remove_fixed_ip(context, instance, address)

View File

@ -13,21 +13,21 @@
add_fixed_ip = {
'type': 'object',
'properties': {
'add_fixed_ip': {
'addFixedIp': {
'type': 'object',
'properties': {
# The maxLength is from the column 'uuid' of the
# table 'networks'
'network_id': {
'networkId': {
'type': ['string', 'number'],
'minLength': 1, 'maxLength': 36,
},
},
'required': ['network_id'],
'required': ['networkId'],
'additionalProperties': False,
},
},
'required': ['add_fixed_ip'],
'required': ['addFixedIp'],
'additionalProperties': False,
}
@ -35,7 +35,7 @@ add_fixed_ip = {
remove_fixed_ip = {
'type': 'object',
'properties': {
'remove_fixed_ip': {
'removeFixedIp': {
'type': 'object',
'properties': {
'address': {
@ -50,6 +50,6 @@ remove_fixed_ip = {
'additionalProperties': False,
},
},
'required': ['remove_fixed_ip'],
'required': ['removeFixedIp'],
'additionalProperties': False,
}

View File

@ -41,7 +41,8 @@ def compute_api_remove_fixed_ip(self, context, instance, address):
last_remove_fixed_ip = (instance['uuid'], address)
def compute_api_get(self, context, instance_id, want_objects=False):
def compute_api_get(self, context, instance_id, want_objects=False,
expected_attrs=None):
instance = objects.Instance()
instance.uuid = instance_id
instance.id = 1
@ -51,9 +52,9 @@ def compute_api_get(self, context, instance_id, want_objects=False):
return instance
class FixedIpTest(test.NoDBTestCase):
class FixedIpTestV21(test.NoDBTestCase):
def setUp(self):
super(FixedIpTest, self).setUp()
super(FixedIpTestV21, self).setUp()
fakes.stub_out_networking(self.stubs)
fakes.stub_out_rate_limiting(self.stubs)
self.stubs.Set(compute.api.API, "add_fixed_ip",
@ -61,18 +62,21 @@ class FixedIpTest(test.NoDBTestCase):
self.stubs.Set(compute.api.API, "remove_fixed_ip",
compute_api_remove_fixed_ip)
self.stubs.Set(compute.api.API, 'get', compute_api_get)
self.flags(
osapi_compute_extension=[
'nova.api.openstack.compute.contrib.select_extensions'],
osapi_compute_ext_list=['Multinic'])
self.app = fakes.wsgi_app(init_only=('servers',))
self.app = self._get_app()
def _get_app(self):
return fakes.wsgi_app_v3(init_only=('servers', 'os-multinic'))
def _get_url(self):
return '/v3'
def test_add_fixed_ip(self):
global last_add_fixed_ip
last_add_fixed_ip = (None, None)
body = dict(addFixedIp=dict(networkId='test_net'))
req = webob.Request.blank('/v2/fake/servers/%s/action' % UUID)
req = webob.Request.blank(
self._get_url() + '/servers/%s/action' % UUID)
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = 'application/json'
@ -82,7 +86,8 @@ class FixedIpTest(test.NoDBTestCase):
self.assertEqual(last_add_fixed_ip, (UUID, 'test_net'))
def _test_add_fixed_ip_bad_request(self, body):
req = webob.Request.blank('/v2/fake/servers/%s/action' % UUID)
req = webob.Request.blank(
self._get_url() + '/servers/%s/action' % UUID)
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = 'application/json'
@ -102,7 +107,8 @@ class FixedIpTest(test.NoDBTestCase):
last_add_fixed_ip = (None, None)
body = dict(addFixedIp=dict())
req = webob.Request.blank('/v2/fake/servers/%s/action' % UUID)
req = webob.Request.blank(
self._get_url() + '/servers/%s/action' % UUID)
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = 'application/json'
@ -116,7 +122,8 @@ class FixedIpTest(test.NoDBTestCase):
mock_add_fixed_ip.side_effect = exception.NoMoreFixedIps
body = dict(addFixedIp=dict(networkId='test_net'))
req = webob.Request.blank('/v2/fake/servers/%s/action' % UUID)
req = webob.Request.blank(
self._get_url() + '/servers/%s/action' % UUID)
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = 'application/json'
@ -129,7 +136,8 @@ class FixedIpTest(test.NoDBTestCase):
last_remove_fixed_ip = (None, None)
body = dict(removeFixedIp=dict(address='10.10.10.1'))
req = webob.Request.blank('/v2/fake/servers/%s/action' % UUID)
req = webob.Request.blank(
self._get_url() + '/servers/%s/action' % UUID)
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = 'application/json'
@ -143,7 +151,8 @@ class FixedIpTest(test.NoDBTestCase):
last_remove_fixed_ip = (None, None)
body = dict(removeFixedIp=dict())
req = webob.Request.blank('/v2/fake/servers/%s/action' % UUID)
req = webob.Request.blank(
self._get_url() + '/servers/%s/action' % UUID)
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = 'application/json'
@ -151,3 +160,33 @@ class FixedIpTest(test.NoDBTestCase):
resp = req.get_response(self.app)
self.assertEqual(resp.status_int, 400)
self.assertEqual(last_remove_fixed_ip, (None, None))
def test_remove_fixed_ip_invalid_address(self):
body = {'remove_fixed_ip': {'address': ''}}
req = webob.Request.blank(
self._get_url() + '/servers/%s/action' % UUID)
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = 'application/json'
resp = req.get_response(self.app)
self.assertEqual(400, resp.status_int)
class FixedIpTestV2(FixedIpTestV21):
def setUp(self):
super(FixedIpTestV2, self).setUp()
self.flags(
osapi_compute_extension=[
'nova.api.openstack.compute.contrib.select_extensions'],
osapi_compute_ext_list=['Multinic'])
def _get_app(self):
return fakes.wsgi_app(init_only=('servers',))
def _get_url(self):
return '/v2/fake'
def test_remove_fixed_ip_invalid_address(self):
# NOTE(cyeoh): This test is disabled for the V2 API because it is
# has poorer input validation.
pass

View File

@ -1,154 +0,0 @@
# Copyright 2011 OpenStack Foundation
# 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
import webob
from nova import compute
from nova import exception
from nova.openstack.common import jsonutils
from nova import test
from nova.tests.api.openstack import fakes
UUID = '70f6db34-de8d-4fbd-aafb-4065bdfa6114'
last_add_fixed_ip = (None, None)
last_remove_fixed_ip = (None, None)
def compute_api_add_fixed_ip(self, context, instance, network_id):
global last_add_fixed_ip
last_add_fixed_ip = (instance['uuid'], network_id)
def compute_api_remove_fixed_ip(self, context, instance, address):
global last_remove_fixed_ip
last_remove_fixed_ip = (instance['uuid'], address)
def compute_api_get(self, context, instance_id, expected_attrs=None,
want_objects=False):
return {'id': 1, 'uuid': instance_id}
class FixedIpTest(test.NoDBTestCase):
def setUp(self):
super(FixedIpTest, self).setUp()
fakes.stub_out_networking(self.stubs)
fakes.stub_out_rate_limiting(self.stubs)
self.stubs.Set(compute.api.API, "add_fixed_ip",
compute_api_add_fixed_ip)
self.stubs.Set(compute.api.API, "remove_fixed_ip",
compute_api_remove_fixed_ip)
self.stubs.Set(compute.api.API, 'get', compute_api_get)
self.app = fakes.wsgi_app_v3(init_only=('servers', 'os-multinic'))
def test_add_fixed_ip(self):
global last_add_fixed_ip
last_add_fixed_ip = (None, None)
body = dict(add_fixed_ip=dict(network_id='test_net'))
req = webob.Request.blank('/v3/servers/%s/action' % UUID)
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = 'application/json'
resp = req.get_response(self.app)
self.assertEqual(resp.status_int, 202)
self.assertEqual(last_add_fixed_ip, (UUID, 'test_net'))
def test_add_fixed_ip_empty_network_id(self):
body = {'add_fixed_ip': {'network_id': ''}}
req = webob.Request.blank('/v3/servers/%s/action' % UUID)
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = 'application/json'
resp = req.get_response(self.app)
self.assertEqual(400, resp.status_int)
def test_add_fixed_ip_network_id_bigger_than_36(self):
body = {'add_fixed_ip': {'network_id': 'a' * 37}}
req = webob.Request.blank('/v3/servers/%s/action' % UUID)
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = 'application/json'
resp = req.get_response(self.app)
self.assertEqual(400, resp.status_int)
def test_add_fixed_ip_no_network(self):
global last_add_fixed_ip
last_add_fixed_ip = (None, None)
body = dict(add_fixed_ip=dict())
req = webob.Request.blank('/v3/servers/%s/action' % UUID)
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = 'application/json'
resp = req.get_response(self.app)
self.assertEqual(resp.status_int, 400)
self.assertEqual(last_add_fixed_ip, (None, None))
@mock.patch.object(compute.api.API, 'add_fixed_ip')
def test_add_fixed_ip_no_more_ips_available(self, mock_add_fixed_ip):
mock_add_fixed_ip.side_effect = exception.NoMoreFixedIps
body = dict(add_fixed_ip=dict())
req = webob.Request.blank('/v3/servers/%s/action' % UUID)
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = 'application/json'
resp = req.get_response(self.app)
self.assertEqual(resp.status_int, 400)
def test_remove_fixed_ip(self):
global last_remove_fixed_ip
last_remove_fixed_ip = (None, None)
body = dict(remove_fixed_ip=dict(address='10.10.10.1'))
req = webob.Request.blank('/v3/servers/%s/action' % UUID)
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = 'application/json'
resp = req.get_response(self.app)
self.assertEqual(resp.status_int, 202)
self.assertEqual(last_remove_fixed_ip, (UUID, '10.10.10.1'))
def test_remove_fixed_ip_invalid_address(self):
body = {'remove_fixed_ip': {'address': ''}}
req = webob.Request.blank('/v3/servers/%s/action' % UUID)
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = 'application/json'
resp = req.get_response(self.app)
self.assertEqual(400, resp.status_int)
def test_remove_fixed_ip_no_address(self):
global last_remove_fixed_ip
last_remove_fixed_ip = (None, None)
body = dict(remove_fixed_ip=dict())
req = webob.Request.blank('/v3/servers/%s/action' % UUID)
req.method = 'POST'
req.body = jsonutils.dumps(body)
req.headers['content-type'] = 'application/json'
resp = req.get_response(self.app)
self.assertEqual(resp.status_int, 400)
self.assertEqual(last_remove_fixed_ip, (None, None))

View File

@ -1,5 +1,5 @@
{
"add_fixed_ip":{
"network_id": %(networkId)s
"addFixedIp":{
"networkId": %(networkId)s
}
}

View File

@ -1,5 +1,5 @@
{
"remove_fixed_ip":{
"removeFixedIp":{
"address": "%(ip)s"
}
}