Merge "Add API schema for v2.1 networks API"

This commit is contained in:
Jenkins 2015-02-10 14:20:14 +00:00 committed by Gerrit Code Review
commit 5c2c5eb122
5 changed files with 132 additions and 37 deletions

View File

@ -17,8 +17,10 @@
import netaddr
from webob import exc
from nova.api.openstack.compute.schemas.v3 import networks as schema
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
from nova.api import validation
from nova import exception
from nova.i18n import _
from nova import network
@ -133,33 +135,17 @@ class NetworkController(wsgi.Controller):
raise exc.HTTPNotFound(explanation=msg)
@extensions.expected_errors((400, 409, 501))
@validation.schema(schema.create)
def create(self, req, body):
context = req.environ['nova.context']
authorize(context)
def bad(e):
return exc.HTTPBadRequest(explanation=e)
if not (body and body.get("network")):
raise bad(_("Missing network in body"))
params = body["network"]
if not params.get("label"):
raise bad(_("Network label is required"))
cidr = params.get("cidr") or params.get("cidr_v6")
if not cidr:
raise bad(_("Network cidr or cidr_v6 is required"))
if params.get("project_id") == "":
params["project_id"] = None
params["num_networks"] = 1
try:
params["network_size"] = netaddr.IPNetwork(cidr).size
except netaddr.AddrFormatError:
msg = _('%s is not a valid ip network') % cidr
raise exc.HTTPBadRequest(explanation=msg)
params["network_size"] = netaddr.IPNetwork(cidr).size
try:
network = self.network_api.create(context, **params)[0]

View File

@ -0,0 +1,68 @@
# Copyright 2015 NEC Corporation. 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 nova.api.validation import parameter_types
create = {
'type': 'object',
'properties': {
'network': {
'type': 'object',
'properties': {
'label': {
'type': 'string', 'maxLength': 255
},
'ipam': parameter_types.boolean,
'cidr': parameter_types.cidr,
'cidr_v6': parameter_types.cidr,
'project_id': parameter_types.project_id,
'multi_host': parameter_types.boolean,
'gateway': parameter_types.ipv4,
'gateway_v6': parameter_types.ipv6,
'bridge': {
'type': 'string',
},
'bridge_interface': {
'type': 'string',
},
# NOTE: In _extract_subnets(), dns1, dns2 dhcp_server are
# used only for IPv4, not IPv6.
'dns1': parameter_types.ipv4,
'dns2': parameter_types.ipv4,
'dhcp_server': parameter_types.ipv4,
'fixed_cidr': parameter_types.cidr,
'allowed_start': parameter_types.ip_address,
'allowed_end': parameter_types.ip_address,
'enable_dhcp': parameter_types.boolean,
'share_address': parameter_types.boolean,
'mtu': parameter_types.positive_integer,
'vlan': parameter_types.positive_integer,
'vlan_start': parameter_types.positive_integer,
'vpn_start': {
'type': 'string',
},
},
'required': ['label'],
'oneOf': [
{'required': ['cidr']},
{'required': ['cidr_v6']}
],
'additionalProperties': False,
},
},
'required': ['network'],
'additionalProperties': False,
}

View File

@ -189,3 +189,18 @@ ip_address = {
{'format': 'ipv6'}
]
}
ipv4 = {
'type': 'string', 'format': 'ipv4'
}
ipv6 = {
'type': 'string', 'format': 'ipv6'
}
cidr = {
'type': 'string', 'format': 'cidr'
}

View File

@ -1135,14 +1135,20 @@ class NetworkManager(manager.Manager):
self._convert_int_args(kwargs)
# check for certain required inputs
# NOTE: We can remove this check after v2.0 API code is removed because
# jsonschema has checked already before this.
label = kwargs["label"]
if not label:
raise exception.NetworkNotCreated(req="label")
# Size of "label" column in nova.networks is 255, hence the restriction
# NOTE: We can remove this check after v2.0 API code is removed because
# jsonschema has checked already before this.
if len(label) > 255:
raise exception.LabelTooLong()
# NOTE: We can remove this check after v2.0 API code is removed because
# jsonschema has checked already before this.
if not (kwargs["cidr"] or kwargs["cidr_v6"]):
raise exception.NetworkNotCreated(req="cidr or cidr_v6")

View File

@ -106,9 +106,7 @@ NEW_NETWORK = {
"cidr": "10.20.105.0/24",
"label": "new net 111",
"vlan_start": 111,
"injected": False,
"multi_host": False,
'mtu': None,
'dhcp_server': '10.0.0.1',
'enable_dhcp': True,
'share_address': False,
@ -194,6 +192,14 @@ class FakeNetworkAPI(object):
def get(self, context, network_id):
for network in self.networks:
if network.get('uuid') == network_id:
if 'injected' in network and network['injected'] is None:
# NOTE: This is a workaround for passing unit tests.
# When using nova-network, 'injected' value should be
# boolean because of the definition of objects.Network().
# However, 'injected' value can be None if neutron.
# So here changes the value to False just for passing
# following _from_db_object().
network['injected'] = False
return objects.Network._from_db_object(context,
objects.Network(),
network)
@ -229,6 +235,7 @@ class FakeNetworkAPI(object):
# NOTE(vish): tests that network create Exceptions actually return
# the proper error responses
class NetworkCreateExceptionsTestV21(test.TestCase):
validation_error = exception.ValidationError
class PassthroughAPI(object):
def __init__(self):
@ -252,28 +259,39 @@ class NetworkCreateExceptionsTestV21(test.TestCase):
def test_network_create_bad_vlan(self):
self.new_network['network']['vlan_start'] = 'foo'
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create, self.req, self.new_network)
self.assertRaises(self.validation_error,
self.controller.create, self.req,
body=self.new_network)
def test_network_create_no_cidr(self):
self.new_network['network']['cidr'] = ''
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create, self.req, self.new_network)
self.assertRaises(self.validation_error,
self.controller.create, self.req,
body=self.new_network)
def test_network_create_invalid_fixed_cidr(self):
self.new_network['network']['fixed_cidr'] = 'foo'
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create, self.req, self.new_network)
self.assertRaises(self.validation_error,
self.controller.create, self.req,
body=self.new_network)
def test_network_create_invalid_start(self):
self.new_network['network']['allowed_start'] = 'foo'
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create, self.req, self.new_network)
self.assertRaises(self.validation_error,
self.controller.create, self.req,
body=self.new_network)
def test_network_create_bad_cidr(self):
self.new_network['network']['cidr'] = '128.0.0.0/900'
self.assertRaises(self.validation_error,
self.controller.create, self.req,
body=self.new_network)
def test_network_create_handle_network_not_created(self):
self.new_network['network']['label'] = 'fail_NetworkNotCreated'
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create, self.req, self.new_network)
self.controller.create, self.req,
body=self.new_network)
def test_network_create_cidr_conflict(self):
@ -288,10 +306,12 @@ class NetworkCreateExceptionsTestV21(test.TestCase):
self.new_network['network']['cidr'] = '10.0.0.0/24'
self.assertRaises(webob.exc.HTTPConflict,
self.controller.create, self.req, self.new_network)
self.controller.create, self.req,
body=self.new_network)
class NetworkCreateExceptionsTestV2(NetworkCreateExceptionsTestV21):
validation_error = webob.exc.HTTPBadRequest
def _setup(self):
ext_mgr = extensions.ExtensionManager()
@ -300,6 +320,11 @@ class NetworkCreateExceptionsTestV2(NetworkCreateExceptionsTestV21):
self.controller = networks.NetworkController(
self.PassthroughAPI(), ext_mgr)
def test_network_create_with_both_cidr_and_cidr_v6(self):
# NOTE: v2.0 API cannot handle this case, so we need to just
# skip it on the API.
pass
class NetworksTestV21(test.NoDBTestCase):
@ -428,15 +453,10 @@ class NetworksTestV21(test.NoDBTestCase):
def test_network_create_large(self):
self.new_network['network']['cidr'] = '128.0.0.0/4'
res_dict = self.controller.create(self.req, self.new_network)
res_dict = self.controller.create(self.req, body=self.new_network)
self.assertEqual(res_dict['network']['cidr'],
self.new_network['network']['cidr'])
def test_network_create_bad_cidr(self):
self.new_network['network']['cidr'] = '128.0.0.0/900'
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create, self.req, self.new_network)
def test_network_neutron_disassociate_not_implemented(self):
uuid = FAKE_NETWORKS[1]['uuid']
self.flags(network_api_class='nova.network.neutronv2.api.API')
@ -469,7 +489,7 @@ class NetworksTestV2(NetworksTestV21):
self.stubs.Set(self.controller.network_api, 'create', no_mtu)
self.new_network['network']['mtu'] = 9000
self.controller.create(self.req, self.new_network)
self.controller.create(self.req, body=self.new_network)
class NetworksAssociateTestV21(test.NoDBTestCase):