summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/nova-manage96
-rw-r--r--nova/api/openstack/compute/contrib/networks.py29
-rw-r--r--nova/network/manager.py90
-rw-r--r--nova/network/quantum/nova_ipam_lib.py2
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_networks.py62
-rw-r--r--nova/tests/fake_flags.py1
-rw-r--r--nova/tests/network/test_linux_net.py1
-rw-r--r--nova/tests/test_nova_manage.py4
8 files changed, 195 insertions, 90 deletions
diff --git a/bin/nova-manage b/bin/nova-manage
index 9a09a8b5a..01b27ef2d 100755
--- a/bin/nova-manage
+++ b/bin/nova-manage
@@ -83,6 +83,7 @@ from nova import db
from nova.db import migration
from nova import exception
from nova import flags
+from nova.api.openstack.compute.contrib import networks
from nova.openstack.common import cfg
from nova.openstack.common import importutils
from nova.openstack.common import log as logging
@@ -94,6 +95,8 @@ from nova import utils
from nova import version
from nova.volume import volume_types
+from webob import exc
+
FLAGS = flags.FLAGS
flags.DECLARE('flat_network_bridge', 'nova.network.manager')
flags.DECLARE('num_networks', 'nova.network.manager')
@@ -434,7 +437,7 @@ class NetworkCommands(object):
@args('--label', dest="label", metavar='<label>',
help='Label for network (ex: public)')
- @args('--fixed_range_v4', dest="fixed_range_v4", metavar='<x.x.x.x/yy>',
+ @args('--fixed_range_v4', dest="cidr", metavar='<x.x.x.x/yy>',
help='IPv4 subnet (ex: 10.0.0.0/8)')
@args('--num_networks', dest="num_networks", metavar='<number>',
help='Number of networks to create')
@@ -442,7 +445,7 @@ class NetworkCommands(object):
help='Number of IPs per network')
@args('--vlan', dest="vlan_start", metavar='<vlan id>', help='vlan id')
@args('--vpn', dest="vpn_start", help='vpn start')
- @args('--fixed_range_v6', dest="fixed_range_v6",
+ @args('--fixed_range_v6', dest="cidr_v6",
help='IPv6 subnet (ex: fe80::/64')
@args('--gateway', dest="gateway", help='gateway')
@args('--gateway_v6', dest="gateway_v6", help='ipv6 gateway')
@@ -464,91 +467,22 @@ class NetworkCommands(object):
help='Project id')
@args('--priority', dest="priority", metavar="<number>",
help='Network interface priority')
- def create(self, label=None, fixed_range_v4=None, num_networks=None,
+ def create(self, label=None, cidr=None, num_networks=None,
network_size=None, multi_host=None, vlan_start=None,
- vpn_start=None, fixed_range_v6=None, gateway=None,
+ vpn_start=None, cidr_v6=None, gateway=None,
gateway_v6=None, bridge=None, bridge_interface=None,
dns1=None, dns2=None, project_id=None, priority=None,
uuid=None, fixed_cidr=None):
"""Creates fixed ips for host by range"""
-
- # check for certain required inputs
- if not label:
- raise exception.NetworkNotCreated(req='--label')
- # Size of "label" column in nova.networks is 255, hence the restriction
- if len(label) > 255:
- reason = _("Maximum allowed length for 'label' is 255.")
- raise exception.InvalidInput(reason=reason)
- if not (fixed_range_v4 or fixed_range_v6):
- req = '--fixed_range_v4 or --fixed_range_v6'
- raise exception.NetworkNotCreated(req=req)
-
- bridge = bridge or FLAGS.flat_network_bridge
- if not bridge:
- bridge_required = ['nova.network.manager.FlatManager',
- 'nova.network.manager.FlatDHCPManager']
- if FLAGS.network_manager in bridge_required:
- raise exception.NetworkNotCreated(req='--bridge')
-
- bridge_interface = (bridge_interface or FLAGS.flat_interface or
- FLAGS.vlan_interface)
- if not bridge_interface:
- interface_required = ['nova.network.manager.VlanManager']
- if FLAGS.network_manager in interface_required:
- raise exception.NetworkNotCreated(req='--bridge_interface')
-
- # sanitize other input using FLAGS if necessary
- if not num_networks:
- num_networks = FLAGS.num_networks
- if not network_size and fixed_range_v4:
- fixnet = netaddr.IPNetwork(fixed_range_v4)
- each_subnet_size = fixnet.size / int(num_networks)
- if each_subnet_size > FLAGS.network_size:
- network_size = FLAGS.network_size
- subnet = 32 - int(math.log(network_size, 2))
- oversize_msg = _('Subnet(s) too large, defaulting to /%s.'
- ' To override, specify network_size flag.') % subnet
- print oversize_msg
- else:
- network_size = fixnet.size
- if not multi_host:
- multi_host = FLAGS.multi_host
- else:
- multi_host = multi_host == 'T'
- if not vlan_start:
- vlan_start = FLAGS.vlan_start
- if not vpn_start:
- vpn_start = FLAGS.vpn_start
- if not dns1 and FLAGS.flat_network_dns:
- dns1 = FLAGS.flat_network_dns
-
- if not network_size:
- network_size = FLAGS.network_size
-
- if fixed_cidr:
- fixed_cidr = netaddr.IPNetwork(fixed_cidr)
-
- # create the network
+ kwargs = dict(((k, v) for k, v in locals().iteritems()
+ if v and k != "self"))
+ if multi_host is not None:
+ kwargs['multi_host'] = multi_host == 'T'
net_manager = importutils.import_object(FLAGS.network_manager)
- net_manager.create_networks(context.get_admin_context(),
- label=label,
- cidr=fixed_range_v4,
- multi_host=multi_host,
- num_networks=int(num_networks),
- network_size=int(network_size),
- vlan_start=int(vlan_start),
- vpn_start=int(vpn_start),
- cidr_v6=fixed_range_v6,
- gateway=gateway,
- gateway_v6=gateway_v6,
- bridge=bridge,
- bridge_interface=bridge_interface,
- dns1=dns1,
- dns2=dns2,
- project_id=project_id,
- priority=priority,
- uuid=uuid,
- fixed_cidr=fixed_cidr)
+ try:
+ net_manager.create_networks(context.get_admin_context(), **kwargs)
+ except exc.HTTPBadRequest as ex:
+ print ex
def list(self):
"""List all created networks"""
diff --git a/nova/api/openstack/compute/contrib/networks.py b/nova/api/openstack/compute/contrib/networks.py
index fb1d3d77e..f673bf43a 100644
--- a/nova/api/openstack/compute/contrib/networks.py
+++ b/nova/api/openstack/compute/contrib/networks.py
@@ -16,7 +16,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-
+import netaddr
import webob
from webob import exc
@@ -111,8 +111,31 @@ class NetworkController(object):
raise exc.HTTPNotFound(_("Network not found"))
return exc.HTTPAccepted()
- def create(self, req, id, body=None):
- raise exc.HTTPNotImplemented()
+ def create(self, req, body):
+ context = req.environ['nova.context']
+ authorize(context)
+
+ def bad(e):
+ return exc.HTTPUnprocessableEntity(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"))
+
+ LOG.debug(_("Creating network with label %s") % params["label"])
+
+ params["num_networks"] = 1
+ params["network_size"] = netaddr.IPNetwork(cidr).size
+
+ network = self.network_api.create(context, **params)[0]
+ return {"network": network_dict(context, network)}
def add(self, req, body):
context = req.environ['nova.context']
diff --git a/nova/network/manager.py b/nova/network/manager.py
index c1f3a6418..862fb6f78 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -769,6 +769,8 @@ class NetworkManager(manager.SchedulerDependentManager):
timeout_fixed_ips = True
+ required_create_args = []
+
def __init__(self, network_driver=None, *args, **kwargs):
if not network_driver:
network_driver = FLAGS.network_driver
@@ -1348,10 +1350,86 @@ class NetworkManager(manager.SchedulerDependentManager):
if not fixed_ip['allocated']:
self.db.fixed_ip_disassociate(context, address)
- def create_networks(self, context, label, cidr, multi_host, num_networks,
- network_size, cidr_v6, gateway, gateway_v6, bridge,
- bridge_interface, dns1=None, dns2=None,
+ def create_networks(self, context,
+ label, cidr=None, multi_host=None, num_networks=None,
+ network_size=None, cidr_v6=None,
+ gateway=None, gateway_v6=None, bridge=None,
+ bridge_interface=None, dns1=None, dns2=None,
fixed_cidr=None, **kwargs):
+ arg_names = ("label", "cidr", "multi_host", "num_networks",
+ "network_size", "cidr_v6",
+ "gateway", "gateway_v6", "bridge",
+ "bridge_interface", "dns1", "dns2",
+ "fixed_cidr")
+ for name in arg_names:
+ kwargs[name] = locals()[name]
+ int_args = ("network_size", "num_networks",
+ "vlan_start", "vpn_start")
+ for key in int_args:
+ try:
+ kwargs[key] = int(kwargs[key])
+ except ValueError:
+ raise ValueError(_("%s must be an integer") % key)
+ except KeyError:
+ pass
+
+ # check for certain required inputs
+ label = kwargs["label"]
+ if not label:
+ raise exception.NetworkNotCreated(req="label")
+
+ # Size of "label" column in nova.networks is 255, hence the restriction
+ if len(label) > 255:
+ raise ValueError(_("Maximum allowed length for 'label' is 255."))
+
+ if not (kwargs["cidr"] or kwargs["cidr_v6"]):
+ raise exception.NetworkNotCreated(req="cidr or cidr_v6")
+
+ kwargs["bridge"] = kwargs["bridge"] or FLAGS.flat_network_bridge
+ kwargs["bridge_interface"] = (kwargs["bridge_interface"] or
+ FLAGS.flat_interface)
+
+ for fld in self.required_create_args:
+ if not kwargs[fld]:
+ raise exception.NetworkNotCreated(req=fld)
+
+ num_networks = kwargs["num_networks"] or FLAGS.num_networks
+ network_size = kwargs["network_size"]
+ cidr = kwargs["cidr"]
+ if not network_size and cidr:
+ fixnet = netaddr.IPNetwork(cidr)
+ each_subnet_size = fixnet.size / num_networks
+ if each_subnet_size > FLAGS.network_size:
+ network_size = FLAGS.network_size
+ subnet = 32 - int(math.log(network_size, 2))
+ oversize_msg = _(
+ 'Subnet(s) too large, defaulting to /%s.'
+ ' To override, specify network_size flag.') % subnet
+ LOG.warn(oversize_msg)
+ else:
+ network_size = fixnet.size
+ kwargs["num_networks"] = num_networks
+ kwargs["network_size"] = network_size
+
+ kwargs["multi_host"] = (FLAGS.multi_host
+ if kwargs["multi_host"] is None
+ else
+ utils.bool_from_str(kwargs["multi_host"]))
+ kwargs["vlan_start"] = kwargs.get("vlan_start") or FLAGS.vlan_start
+ kwargs["vpn_start"] = kwargs.get("vpn_start") or FLAGS.vpn_start
+ kwargs["dns1"] = kwargs["dns1"] or FLAGS.flat_network_dns
+ kwargs["network_size"] = kwargs["network_size"] or FLAGS.network_size
+
+ if kwargs["fixed_cidr"]:
+ kwargs["fixed_cidr"] = netaddr.IPNetwork(kwargs["fixed_cidr"])
+
+ return self._do_create_networks(context, **kwargs)
+
+ def _do_create_networks(self, context,
+ label, cidr, multi_host, num_networks,
+ network_size, cidr_v6, gateway, gateway_v6, bridge,
+ bridge_interface, dns1=None, dns2=None,
+ fixed_cidr=None, **kwargs):
"""Create networks based on parameters."""
# NOTE(jkoelker): these are dummy values to make sure iter works
# TODO(tr3buchet): disallow carving up networks
@@ -1719,6 +1797,8 @@ class FlatManager(NetworkManager):
timeout_fixed_ips = False
+ required_create_args = ['bridge']
+
def _allocate_fixed_ips(self, context, instance_id, host, networks,
**kwargs):
"""Calls allocate_fixed_ip once for each network."""
@@ -1793,6 +1873,7 @@ class FlatDHCPManager(RPCAllocateFixedIP, FloatingIP, NetworkManager):
SHOULD_CREATE_BRIDGE = True
DHCP = True
+ required_create_args = ['bridge']
def init_host(self):
"""Do any initialization that needs to be run if this is a
@@ -1862,6 +1943,7 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager):
SHOULD_CREATE_BRIDGE = True
SHOULD_CREATE_VLAN = True
DHCP = True
+ required_create_args = ['bridge_interface']
def init_host(self):
"""Do any initialization that needs to be run if this is a
@@ -1941,6 +2023,8 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager):
'%(num_networks)s. Network size is %(network_size)s') %
kwargs)
+ kwargs['bridge_interface'] = (kwargs.get('bridge_interface') or
+ FLAGS.vlan_interface)
return NetworkManager.create_networks(
self, context, vpn=True, **kwargs)
diff --git a/nova/network/quantum/nova_ipam_lib.py b/nova/network/quantum/nova_ipam_lib.py
index f398815e5..02157bf7c 100644
--- a/nova/network/quantum/nova_ipam_lib.py
+++ b/nova/network/quantum/nova_ipam_lib.py
@@ -59,7 +59,7 @@ class QuantumNovaIPAMLib(object):
"""
admin_context = context.elevated()
subnet_size = len(netaddr.IPNetwork(cidr))
- networks = manager.FlatManager.create_networks(self.net_manager,
+ networks = manager.FlatManager._do_create_networks(self.net_manager,
admin_context, label, cidr,
False, 1, subnet_size, cidr_v6, gateway,
gateway_v6, quantum_net_id, None, dns1, dns2,
diff --git a/nova/tests/api/openstack/compute/contrib/test_networks.py b/nova/tests/api/openstack/compute/contrib/test_networks.py
index efbb7ceba..808493f1b 100644
--- a/nova/tests/api/openstack/compute/contrib/test_networks.py
+++ b/nova/tests/api/openstack/compute/contrib/test_networks.py
@@ -15,6 +15,10 @@
# under the License.
import copy
+import itertools
+import math
+import netaddr
+import uuid
import webob
@@ -23,6 +27,11 @@ from nova import exception
from nova import test
from nova.tests.api.openstack import fakes
+from nova import flags
+
+
+FLAGS = flags.FLAGS
+
FAKE_NETWORKS = [
{
@@ -75,6 +84,15 @@ FAKE_USER_NETWORKS = [
},
]
+NEW_NETWORK = {
+ "network": {
+ "bridge_interface": "eth0",
+ "cidr": "10.20.105.0/24",
+ "label": "new net 111",
+ "vlan_start": 111,
+ }
+}
+
class FakeNetworkAPI(object):
@@ -117,6 +135,32 @@ class FakeNetworkAPI(object):
return network
raise exception.NetworkNotFound()
+ def create(self, context, **kwargs):
+ subnet_bits = int(math.ceil(math.log(kwargs.get(
+ 'network_size', FLAGS.network_size), 2)))
+ fixed_net_v4 = netaddr.IPNetwork(kwargs['cidr'])
+ prefixlen_v4 = 32 - subnet_bits
+ subnets_v4 = list(fixed_net_v4.subnet(
+ prefixlen_v4,
+ count=kwargs.get('num_networks', FLAGS.num_networks)))
+ new_networks = []
+ new_id = max((net['id'] for net in self.networks))
+ for index, subnet_v4 in enumerate(subnets_v4):
+ new_id += 1
+ net = {'id': new_id, 'uuid': str(uuid.uuid4())}
+
+ net['cidr'] = str(subnet_v4)
+ net['netmask'] = str(subnet_v4.netmask)
+ net['gateway'] = kwargs.get('gateway') or str(subnet_v4[1])
+ net['broadcast'] = str(subnet_v4.broadcast)
+ net['dhcp_start'] = str(subnet_v4[2])
+
+ for key in FAKE_NETWORKS[0].iterkeys():
+ net.setdefault(key, kwargs.get(key))
+ new_networks.append(net)
+ self.networks += new_networks
+ return new_networks
+
class NetworksTest(test.TestCase):
@@ -204,3 +248,21 @@ class NetworksTest(test.TestCase):
req.environ["nova.context"].is_admin = True
res_dict = self.controller.show(req, uuid)
self.assertEqual(res_dict['network']['project_id'], 'fake')
+
+ def test_network_create(self):
+ req = fakes.HTTPRequest.blank('/v2/1234/os-networks')
+ res_dict = self.controller.create(req, NEW_NETWORK)
+ self.assertTrue('network' in res_dict)
+ uuid = res_dict['network']['id']
+ req = fakes.HTTPRequest.blank('/v2/1234/os-networks/%s' % uuid)
+ res_dict = self.controller.show(req, uuid)
+ self.assertTrue(res_dict['network']['label'].
+ startswith(NEW_NETWORK['network']['label']))
+
+ def test_network_create_large(self):
+ req = fakes.HTTPRequest.blank('/v2/1234/os-networks')
+ large_network = copy.deepcopy(NEW_NETWORK)
+ large_network['network']['cidr'] = '128.0.0.0/4'
+ res_dict = self.controller.create(req, large_network)
+ self.assertEqual(res_dict['network']['cidr'],
+ large_network['network']['cidr'])
diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py
index f6d9496b1..f0fde3588 100644
--- a/nova/tests/fake_flags.py
+++ b/nova/tests/fake_flags.py
@@ -39,6 +39,7 @@ def set_defaults(conf):
conf.set_default('iscsi_num_targets', 8)
conf.set_default('network_size', 8)
conf.set_default('num_networks', 2)
+ conf.set_default('vlan_interface', 'eth0')
conf.set_default('rpc_backend', 'nova.openstack.common.rpc.impl_fake')
conf.set_default('sql_connection', "sqlite://")
conf.set_default('sqlite_synchronous', False)
diff --git a/nova/tests/network/test_linux_net.py b/nova/tests/network/test_linux_net.py
index 94b2ac8d9..47b853a8a 100644
--- a/nova/tests/network/test_linux_net.py
+++ b/nova/tests/network/test_linux_net.py
@@ -373,6 +373,7 @@ class LinuxNetworkTestCase(test.TestCase):
"bridge_interface": "base_interface",
"vlan": "fake"
}
+ self.flags(vlan_interface="")
driver.plug(network, "fakemac")
self.assertEqual(info['passed_interface'], "base_interface")
self.flags(vlan_interface="override_interface")
diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py
index 805ac8e0d..6cadeb2ef 100644
--- a/nova/tests/test_nova_manage.py
+++ b/nova/tests/test_nova_manage.py
@@ -171,13 +171,13 @@ class NetworkCommandsTestCase(test.TestCase):
fake_create_networks)
self.commands.create(
label='Test',
- fixed_range_v4='10.2.0.0/24',
+ cidr='10.2.0.0/24',
num_networks=1,
network_size=256,
multi_host='F',
vlan_start=200,
vpn_start=2000,
- fixed_range_v6='fd00:2::/120',
+ cidr_v6='fd00:2::/120',
gateway='10.2.0.1',
gateway_v6='fd00:2::22',
bridge='br200',