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:
@@ -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):
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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, "
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user