Allows easier configuration of default networks

Updates the Quark networks extension to allow the id and ipam_strategy
to be passed along with a network create. The id is specifically gated
as admin only, but as an admin, allows deployers to configure special
networks like the all 0s and 1s placeholder values we use at Rackspace.
This commit is contained in:
Matt Dietz
2013-10-08 20:01:34 +00:00
parent 3fe1f7ce29
commit 0e7aa4588e
6 changed files with 87 additions and 12 deletions

View File

@@ -18,11 +18,12 @@ RESOURCE_NAME = "network"
RESOURCE_COLLECTION = RESOURCE_NAME + "s"
EXTENDED_ATTRIBUTES_2_0 = {
RESOURCE_COLLECTION: {
"ipam_strategy": {"allow_post": False, "is_visible": True,
"default": False}}}
"ipam_strategy": {"allow_post": True, "is_visible": True,
"default": False},
"id": {"allow_post": True, "is_visible": True, "default": False}}}
class Networks(object):
class Networks_quark(object):
"""Extends Networks for quark API purposes."""
@classmethod
@@ -31,7 +32,7 @@ class Networks(object):
@classmethod
def get_alias(cls):
return "networks"
return "networks_quark"
@classmethod
def get_description(cls):
@@ -40,7 +41,7 @@ class Networks(object):
@classmethod
def get_namespace(cls):
return ("http://docs.openstack.org/network/ext/"
"networks/api/v2.0")
"networks_quark/api/v2.0")
@classmethod
def get_updated(cls):

View File

@@ -1,6 +1,10 @@
from neutron.common import exceptions
class NetworkAlreadyExists(exceptions.Conflict):
message = _("Network %(id)s already exists.")
class InvalidMacAddressRange(exceptions.NeutronException):
message = _("Invalid MAC address range %(cidr)s.")
@@ -49,6 +53,10 @@ class PhysicalNetworkNotFound(exceptions.NeutronException):
message = _("Physical network %(phys_net)s not found!")
class InvalidIpamStrategy(exceptions.BadRequest):
message = _("IPAM Strategy %(strat)s is invalid.")
class ProvidernetParamError(exceptions.NeutronException):
message = _("%(msg)s")

View File

@@ -306,8 +306,13 @@ class IpamRegistry(object):
QuarkIpamBOTH.get_name(): QuarkIpamBOTH(),
QuarkIpamBOTHREQ.get_name(): QuarkIpamBOTHREQ()}
def get_strategy(self, strategy_name):
def is_valid_strategy(self, strategy_name):
if strategy_name in self.strategies:
return True
return False
def get_strategy(self, strategy_name):
if self.is_valid_strategy(strategy_name):
return self.strategies[strategy_name]
fallback = CONF.QUARK.default_ipam_strategy
LOG.warn("IPAM strategy %s not found, "

View File

@@ -73,7 +73,8 @@ class Plugin(neutron_plugin_base_v2.NeutronPluginBaseV2,
"ip_addresses", "ports_quark",
"security-group", "diagnostics",
"subnets_quark", "provider",
"ip_policies", "quotas"]
"ip_policies", "quotas",
"networks_quark"]
def __init__(self):
neutron_db_api.configure_db()

View File

@@ -24,6 +24,8 @@ from oslo.config import cfg
from quark.db import api as db_api
from quark.drivers import registry
from quark import exceptions as q_exc
from quark import ipam
from quark import network_strategy
from quark.plugin_modules import ports
from quark.plugin_modules import subnets
@@ -62,13 +64,24 @@ def create_network(context, network):
with context.session.begin():
# Generate a uuid that we're going to hand to the backend and db
net_uuid = uuidutils.generate_uuid()
net_attrs = network["network"]
net_uuid = utils.pop_param(net_attrs, "id", None)
if net_uuid and context.is_admin:
net = db_api.network_find(context, id=net_uuid, scope=db_api.ONE)
if net:
raise q_exc.NetworkAlreadyExists(id=net_uuid)
else:
net_uuid = uuidutils.generate_uuid()
#TODO(mdietz) this will be the first component registry hook, but
# lets make it work first
pnet_type, phys_net, seg_id = _adapt_provider_nets(context, network)
net_attrs = network["network"]
net_attrs["ipam_strategy"] = CONF.QUARK.default_ipam_strategy
if "ipam_strategy" not in net_attrs:
net_attrs["ipam_strategy"] = CONF.QUARK.default_ipam_strategy
strat = net_attrs["ipam_strategy"]
if not ipam.IPAM_REGISTRY.is_valid_strategy(strat):
raise q_exc.InvalidIpamStrategy(strat=strat)
# NOTE(mdietz) I think ideally we would create the providernet
# elsewhere as a separate driver step that could be

View File

@@ -17,8 +17,10 @@ import contextlib
import mock
from neutron.common import exceptions
from neutron import context
from quark.db import models
from quark import exceptions as q_exc
from quark.tests import test_quark_plugin
@@ -179,7 +181,7 @@ class TestQuarkDeleteNetwork(test_quark_plugin.TestQuarkPlugin):
class TestQuarkCreateNetwork(test_quark_plugin.TestQuarkPlugin):
@contextlib.contextmanager
def _stubs(self, net=None, subnet=None, ports=None):
def _stubs(self, net=None, subnet=None, ports=None, find_net=False):
net_mod = net
subnet_mod = None
if net:
@@ -190,14 +192,20 @@ class TestQuarkCreateNetwork(test_quark_plugin.TestQuarkPlugin):
subnet_mod = models.Subnet()
subnet_mod.update(subnet)
found_net = None
if find_net:
found_net = models.Network()
db_mod = "quark.db.api"
with contextlib.nested(
mock.patch("%s.network_create" % db_mod),
mock.patch("%s.subnet_create" % db_mod),
mock.patch("quark.drivers.base.BaseDriver.create_network"),
) as (net_create, sub_create, driver_net_create):
mock.patch("%s.network_find" % db_mod)
) as (net_create, sub_create, driver_net_create, net_find):
net_create.return_value = net_mod
sub_create.return_value = subnet_mod
net_find.return_value = found_net
yield net_create
def test_create_network(self):
@@ -234,6 +242,45 @@ class TestQuarkCreateNetwork(test_quark_plugin.TestQuarkPlugin):
self.assertEqual(net["tenant_id"], 0)
self.assertEqual(net["ipam_strategy"], None)
def test_create_network_with_id(self):
net = dict(id="abcdef", name="public", admin_state_up=True,
tenant_id=0)
ctxt = context.Context('fake', 'fake', is_admin=True,
load_admin_roles=False)
with self._stubs(net=net):
res = self.plugin.create_network(ctxt, dict(network=net))
self.assertEqual(net["id"], res["id"])
def test_create_network_with_id_already_exists_raises(self):
net = dict(id="abcdef", name="public", admin_state_up=True,
tenant_id=0)
ctxt = context.Context('fake', 'fake', is_admin=True,
load_admin_roles=False)
with self._stubs(net=net, find_net=True):
with self.assertRaises(q_exc.NetworkAlreadyExists):
self.plugin.create_network(ctxt, dict(network=net))
def test_create_network_with_id_not_admin_ignores_id(self):
net = dict(id="abcdef", name="public", admin_state_up=True,
tenant_id=0)
with self._stubs(net=net):
res = self.plugin.create_network(self.context, dict(network=net))
self.assertNotEqual(net["id"], res["id"])
def test_create_network_with_ipam_strategy(self):
net = dict(id="abcdef", name="public", admin_state_up=True,
tenant_id=0, ipam_strategy="BOTH")
with self._stubs(net=net):
res = self.plugin.create_network(self.context, dict(network=net))
self.assertEqual(res["ipam_strategy"], net["ipam_strategy"])
def test_create_network_with_bad_ipam_strategy_raises(self):
net = dict(id="abcdef", name="public", admin_state_up=True,
tenant_id=0, ipam_strategy="BUSTED")
with self._stubs(net=net):
with self.assertRaises(q_exc.InvalidIpamStrategy):
self.plugin.create_network(self.context, dict(network=net))
class TestQuarkDiagnoseNetworks(test_quark_plugin.TestQuarkPlugin):
@contextlib.contextmanager