Re-implemented IP policies with offset and length
* Implemented CRUD ip_policies plugin methods
* Implemented plugin ip_policy unit tests
* Added IP Policy logic to ipam.allocate_ip_address
* Implemented ip_policy ipam unit tests
* Implemented ip_policies extension
* Added ip_policies db models
* Implemented db_api ip_policy methods
* Implemented _make_ip_policy_dict view
* Fixed existing tests
An IP Policy is defined on a subnet or network definining what IPs to
exclude from allocation. From a user perspective an IP Policy looks
like the following:
{
"id": <id>,
"tenant_id": <tenant_id>,
"name": "foobar",
"subnet_ids": [] (list of uuids),
"network_ids": [] (list of uuids),
"exclude": list of dictionaries (e.g. [{"offset": -1, "length": 3}])
}
"exclude" is always required. One of "subnet_ids" or "network_ids"
is required. Only one policy is allowed per network.
A default policy is enabled on all subnets if no ip policies are
specified on that subnet or its network. This default policy is
established via JSON configuration as "default_ip_policy". The
default for "default_ip_policy" is no policy.
This commit is contained in:
@@ -13,8 +13,6 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import netaddr
|
||||
|
||||
from neutron.common import exceptions
|
||||
from neutron.openstack.common import log as logging
|
||||
from oslo.config import cfg
|
||||
@@ -23,10 +21,8 @@ from quark.db import api as db_api
|
||||
from quark import exceptions as quark_exceptions
|
||||
from quark import plugin_views as v
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
LOG = logging.getLogger("neutron.quark")
|
||||
DEFAULT_SG_UUID = "00000000-0000-0000-0000-000000000000"
|
||||
|
||||
|
||||
def create_ip_policy(context, ip_policy):
|
||||
@@ -38,29 +34,35 @@ def create_ip_policy(context, ip_policy):
|
||||
raise exceptions.BadRequest(resource="ip_policy",
|
||||
msg="Empty ip_policy.exclude regions")
|
||||
|
||||
ipp["exclude"] = netaddr.IPSet(ipp["exclude"])
|
||||
network_id = ipp.get("network_id")
|
||||
subnet_id = ipp.get("subnet_id")
|
||||
network_ids = ipp.get("network_ids")
|
||||
subnet_ids = ipp.get("subnet_ids")
|
||||
|
||||
model = None
|
||||
if subnet_id:
|
||||
model = db_api.subnet_find(context, id=subnet_id, scope=db_api.ONE)
|
||||
if not model:
|
||||
raise exceptions.SubnetNotFound(id=subnet_id)
|
||||
elif network_id:
|
||||
model = db_api.network_find(context, id=network_id,
|
||||
scope=db_api.ONE)
|
||||
if not model:
|
||||
raise exceptions.NetworkNotFound(id=network_id)
|
||||
else:
|
||||
if not subnet_ids and not network_ids:
|
||||
raise exceptions.BadRequest(
|
||||
resource="ip_policy",
|
||||
msg="network_id or subnet_id unspecified")
|
||||
msg="network_ids or subnet_ids not specified")
|
||||
|
||||
models = []
|
||||
if subnet_ids:
|
||||
subnets = db_api.subnet_find(
|
||||
context, id=subnet_ids, scope=db_api.ALL)
|
||||
if not subnets:
|
||||
raise exceptions.SubnetNotFound(id=subnet_ids)
|
||||
models.extend(subnets)
|
||||
|
||||
if network_ids:
|
||||
nets = db_api.network_find(
|
||||
context, id=network_ids, scope=db_api.ALL)
|
||||
if not nets:
|
||||
raise exceptions.NetworkNotFound(net_id=network_ids)
|
||||
models.extend(nets)
|
||||
|
||||
for model in models:
|
||||
if model["ip_policy"]:
|
||||
raise quark_exceptions.IPPolicyAlreadyExists(
|
||||
id=model["ip_policy"]["id"], n_id=model["id"])
|
||||
model["ip_policy"] = db_api.ip_policy_create(context, **ipp)
|
||||
|
||||
if model["ip_policy"]:
|
||||
raise quark_exceptions.IPPolicyAlreadyExists(
|
||||
id=model["ip_policy"]["id"], n_id=model["id"])
|
||||
model["ip_policy"] = db_api.ip_policy_create(context, **ipp)
|
||||
return v._make_ip_policy_dict(model["ip_policy"])
|
||||
|
||||
|
||||
@@ -78,9 +80,51 @@ def get_ip_policies(context, **filters):
|
||||
return [v._make_ip_policy_dict(ipp) for ipp in ipps]
|
||||
|
||||
|
||||
def update_ip_policy(context, id, ip_policy):
|
||||
LOG.info("update_ip_policy for tenant %s" % context.tenant_id)
|
||||
|
||||
ipp = ip_policy["ip_policy"]
|
||||
|
||||
ipp_db = db_api.ip_policy_find(context, id=id, scope=db_api.ONE)
|
||||
if not ipp_db:
|
||||
raise quark_exceptions.IPPolicyNotFound(id=id)
|
||||
|
||||
network_ids = ipp.get("network_ids")
|
||||
subnet_ids = ipp.get("subnet_ids")
|
||||
|
||||
models = []
|
||||
if subnet_ids:
|
||||
for subnet in ipp_db["subnets"]:
|
||||
subnet["ip_policy"] = None
|
||||
subnets = db_api.subnet_find(
|
||||
context, id=subnet_ids, scope=db_api.ALL)
|
||||
if len(subnets) != len(subnet_ids):
|
||||
raise exceptions.SubnetNotFound(id=subnet_ids)
|
||||
models.extend(subnets)
|
||||
|
||||
if network_ids:
|
||||
for network in ipp_db["networks"]:
|
||||
network["ip_policy"] = None
|
||||
nets = db_api.network_find(context, id=network_ids, scope=db_api.ALL)
|
||||
if len(nets) != len(network_ids):
|
||||
raise exceptions.NetworkNotFound(net_id=network_ids)
|
||||
models.extend(nets)
|
||||
|
||||
for model in models:
|
||||
if model["ip_policy"]:
|
||||
raise quark_exceptions.IPPolicyAlreadyExists(
|
||||
id=model["ip_policy"]["id"], n_id=model["id"])
|
||||
model["ip_policy"] = ipp_db
|
||||
|
||||
ipp_db = db_api.ip_policy_update(context, ipp_db, **ipp)
|
||||
return v._make_ip_policy_dict(ipp_db)
|
||||
|
||||
|
||||
def delete_ip_policy(context, id):
|
||||
LOG.info("delete_ip_policy %s for tenant %s" % (id, context.tenant_id))
|
||||
ipp = db_api.ip_policy_find(context, id=id, scope=db_api.ONE)
|
||||
if not ipp:
|
||||
raise quark_exceptions.IPPolicyNotFound(id=id)
|
||||
if ipp["networks"] or ipp["subnets"]:
|
||||
raise quark_exceptions.IPPolicyInUse(id=id)
|
||||
db_api.ip_policy_delete(context, ipp)
|
||||
|
||||
@@ -94,7 +94,7 @@ def create_subnet(context, subnet):
|
||||
gateway_ip = utils.pop_param(sub_attrs, "gateway_ip", str(cidr[1]))
|
||||
dns_ips = utils.pop_param(sub_attrs, "dns_nameservers", [])
|
||||
host_routes = utils.pop_param(sub_attrs, "host_routes", [])
|
||||
allocation_pools = utils.pop_param(sub_attrs, "allocation_pools", [])
|
||||
allocation_pools = utils.pop_param(sub_attrs, "allocation_pools", None)
|
||||
sub_attrs["network"] = net
|
||||
|
||||
new_subnet = db_api.subnet_create(context, **sub_attrs)
|
||||
@@ -116,13 +116,20 @@ def create_subnet(context, subnet):
|
||||
new_subnet["dns_nameservers"].append(db_api.dns_create(
|
||||
context, ip=netaddr.IPAddress(dns_ip)))
|
||||
|
||||
if allocation_pools:
|
||||
exclude = netaddr.IPSet([cidr])
|
||||
if isinstance(allocation_pools, list):
|
||||
ranges = []
|
||||
cidrset = netaddr.IPSet([netaddr.IPNetwork(new_subnet["cidr"])])
|
||||
for p in allocation_pools:
|
||||
x = netaddr.IPSet(netaddr.IPRange(p["start"], p["end"]))
|
||||
exclude = exclude - x
|
||||
cidrset -= netaddr.IPSet(netaddr.IPRange(p["start"], p["end"]))
|
||||
non_allocation_pools = v._pools_from_cidr(cidrset)
|
||||
for p in non_allocation_pools:
|
||||
r = netaddr.IPRange(p["start"], p["end"])
|
||||
ranges.append(dict(
|
||||
length=len(r),
|
||||
offset=int(r[0]) - int(cidr[0])))
|
||||
new_subnet["ip_policy"] = db_api.ip_policy_create(context,
|
||||
exclude=exclude)
|
||||
exclude=ranges)
|
||||
|
||||
subnet_dict = v._make_subnet_dict(new_subnet,
|
||||
default_route=routes.DEFAULT_ROUTE)
|
||||
subnet_dict["gateway_ip"] = gateway_ip
|
||||
|
||||
Reference in New Issue
Block a user