Bulk move methods to ipam_backend_mixin.py
ipam_backend_mixin contains methods common for both backends: pluggable and non-pluggable, so moving methods to make them accessible by backends. Next methods were moved from db_base_plugin_v2.py to ipam_backend_mixin.py: - _validate_subnet_cidr - _validate_network_subnetpools - _allocate_pools_for_subnet - _save_subnet This commit moves methods without any internal changes. All future changes and decomposition of these methods will be handled in next commits. Partially-Implements: blueprint neutron-ipam Change-Id: I1ec786754467fc9039d2276f084f1bceaab15635
This commit is contained in:
parent
23836f6716
commit
277d89b67a
|
@ -97,54 +97,6 @@ class NeutronDbPluginV2(ipam_non_pluggable_backend.IpamNonPluggableBackend,
|
||||||
event.listen(models_v2.Port.status, 'set',
|
event.listen(models_v2.Port.status, 'set',
|
||||||
self.nova_notifier.record_port_status_changed)
|
self.nova_notifier.record_port_status_changed)
|
||||||
|
|
||||||
def _validate_subnet_cidr(self, context, network, new_subnet_cidr):
|
|
||||||
"""Validate the CIDR for a subnet.
|
|
||||||
|
|
||||||
Verifies the specified CIDR does not overlap with the ones defined
|
|
||||||
for the other subnets specified for this network, or with any other
|
|
||||||
CIDR if overlapping IPs are disabled.
|
|
||||||
"""
|
|
||||||
new_subnet_ipset = netaddr.IPSet([new_subnet_cidr])
|
|
||||||
# Disallow subnets with prefix length 0 as they will lead to
|
|
||||||
# dnsmasq failures (see bug 1362651).
|
|
||||||
# This is not a discrimination against /0 subnets.
|
|
||||||
# A /0 subnet is conceptually possible but hardly a practical
|
|
||||||
# scenario for neutron's use cases.
|
|
||||||
for cidr in new_subnet_ipset.iter_cidrs():
|
|
||||||
if cidr.prefixlen == 0:
|
|
||||||
err_msg = _("0 is not allowed as CIDR prefix length")
|
|
||||||
raise n_exc.InvalidInput(error_message=err_msg)
|
|
||||||
|
|
||||||
if cfg.CONF.allow_overlapping_ips:
|
|
||||||
subnet_list = network.subnets
|
|
||||||
else:
|
|
||||||
subnet_list = self._get_all_subnets(context)
|
|
||||||
for subnet in subnet_list:
|
|
||||||
if (netaddr.IPSet([subnet.cidr]) & new_subnet_ipset):
|
|
||||||
# don't give out details of the overlapping subnet
|
|
||||||
err_msg = (_("Requested subnet with cidr: %(cidr)s for "
|
|
||||||
"network: %(network_id)s overlaps with another "
|
|
||||||
"subnet") %
|
|
||||||
{'cidr': new_subnet_cidr,
|
|
||||||
'network_id': network.id})
|
|
||||||
LOG.info(_LI("Validation for CIDR: %(new_cidr)s failed - "
|
|
||||||
"overlaps with subnet %(subnet_id)s "
|
|
||||||
"(CIDR: %(cidr)s)"),
|
|
||||||
{'new_cidr': new_subnet_cidr,
|
|
||||||
'subnet_id': subnet.id,
|
|
||||||
'cidr': subnet.cidr})
|
|
||||||
raise n_exc.InvalidInput(error_message=err_msg)
|
|
||||||
|
|
||||||
def _validate_network_subnetpools(self, network,
|
|
||||||
new_subnetpool_id, ip_version):
|
|
||||||
"""Validate all subnets on the given network have been allocated from
|
|
||||||
the same subnet pool as new_subnetpool_id
|
|
||||||
"""
|
|
||||||
for subnet in network.subnets:
|
|
||||||
if (subnet.ip_version == ip_version and
|
|
||||||
new_subnetpool_id != subnet.subnetpool_id):
|
|
||||||
raise n_exc.NetworkSubnetPoolAffinityError()
|
|
||||||
|
|
||||||
def _validate_host_route(self, route, ip_version):
|
def _validate_host_route(self, route, ip_version):
|
||||||
try:
|
try:
|
||||||
netaddr.IPNetwork(route['destination'])
|
netaddr.IPNetwork(route['destination'])
|
||||||
|
@ -160,32 +112,6 @@ class NeutronDbPluginV2(ipam_non_pluggable_backend.IpamNonPluggableBackend,
|
||||||
self._validate_ip_version(ip_version, route['destination'],
|
self._validate_ip_version(ip_version, route['destination'],
|
||||||
'destination')
|
'destination')
|
||||||
|
|
||||||
def _allocate_pools_for_subnet(self, context, subnet):
|
|
||||||
"""Create IP allocation pools for a given subnet
|
|
||||||
|
|
||||||
Pools are defined by the 'allocation_pools' attribute,
|
|
||||||
a list of dict objects with 'start' and 'end' keys for
|
|
||||||
defining the pool range.
|
|
||||||
"""
|
|
||||||
pools = []
|
|
||||||
# Auto allocate the pool around gateway_ip
|
|
||||||
net = netaddr.IPNetwork(subnet['cidr'])
|
|
||||||
first_ip = net.first + 1
|
|
||||||
last_ip = net.last - 1
|
|
||||||
gw_ip = int(netaddr.IPAddress(subnet['gateway_ip'] or net.last))
|
|
||||||
# Use the gw_ip to find a point for splitting allocation pools
|
|
||||||
# for this subnet
|
|
||||||
split_ip = min(max(gw_ip, net.first), net.last)
|
|
||||||
if split_ip > first_ip:
|
|
||||||
pools.append({'start': str(netaddr.IPAddress(first_ip)),
|
|
||||||
'end': str(netaddr.IPAddress(split_ip - 1))})
|
|
||||||
if split_ip < last_ip:
|
|
||||||
pools.append({'start': str(netaddr.IPAddress(split_ip + 1)),
|
|
||||||
'end': str(netaddr.IPAddress(last_ip))})
|
|
||||||
# return auto-generated pools
|
|
||||||
# no need to check for their validity
|
|
||||||
return pools
|
|
||||||
|
|
||||||
def _validate_shared_update(self, context, id, original, updated):
|
def _validate_shared_update(self, context, id, original, updated):
|
||||||
# The only case that needs to be validated is when 'shared'
|
# The only case that needs to be validated is when 'shared'
|
||||||
# goes from True to False
|
# goes from True to False
|
||||||
|
@ -514,48 +440,6 @@ class NeutronDbPluginV2(ipam_non_pluggable_backend.IpamNonPluggableBackend,
|
||||||
external_gateway_info}}
|
external_gateway_info}}
|
||||||
l3plugin.update_router(context, id, info)
|
l3plugin.update_router(context, id, info)
|
||||||
|
|
||||||
def _save_subnet(self, context,
|
|
||||||
network,
|
|
||||||
subnet_args,
|
|
||||||
dns_nameservers,
|
|
||||||
host_routes,
|
|
||||||
allocation_pools):
|
|
||||||
|
|
||||||
if not attributes.is_attr_set(allocation_pools):
|
|
||||||
allocation_pools = self._allocate_pools_for_subnet(context,
|
|
||||||
subnet_args)
|
|
||||||
else:
|
|
||||||
self._validate_allocation_pools(allocation_pools,
|
|
||||||
subnet_args['cidr'])
|
|
||||||
if subnet_args['gateway_ip']:
|
|
||||||
self._validate_gw_out_of_pools(subnet_args['gateway_ip'],
|
|
||||||
allocation_pools)
|
|
||||||
|
|
||||||
self._validate_subnet_cidr(context, network, subnet_args['cidr'])
|
|
||||||
self._validate_network_subnetpools(network,
|
|
||||||
subnet_args['subnetpool_id'],
|
|
||||||
subnet_args['ip_version'])
|
|
||||||
|
|
||||||
subnet = models_v2.Subnet(**subnet_args)
|
|
||||||
context.session.add(subnet)
|
|
||||||
if attributes.is_attr_set(dns_nameservers):
|
|
||||||
for addr in dns_nameservers:
|
|
||||||
ns = models_v2.DNSNameServer(address=addr,
|
|
||||||
subnet_id=subnet.id)
|
|
||||||
context.session.add(ns)
|
|
||||||
|
|
||||||
if attributes.is_attr_set(host_routes):
|
|
||||||
for rt in host_routes:
|
|
||||||
route = models_v2.SubnetRoute(
|
|
||||||
subnet_id=subnet.id,
|
|
||||||
destination=rt['destination'],
|
|
||||||
nexthop=rt['nexthop'])
|
|
||||||
context.session.add(route)
|
|
||||||
|
|
||||||
self._save_allocation_pools(context, subnet, allocation_pools)
|
|
||||||
|
|
||||||
return subnet
|
|
||||||
|
|
||||||
def _make_subnet_request(self, tenant_id, subnet, subnetpool):
|
def _make_subnet_request(self, tenant_id, subnet, subnetpool):
|
||||||
cidr = subnet.get('cidr')
|
cidr = subnet.get('cidr')
|
||||||
subnet_id = subnet.get('id', uuidutils.generate_uuid())
|
subnet_id = subnet.get('id', uuidutils.generate_uuid())
|
||||||
|
|
|
@ -167,6 +167,80 @@ class IpamBackendMixin(db_base_plugin_common.DbBasePluginCommon):
|
||||||
subnet.update(s)
|
subnet.update(s)
|
||||||
return subnet, changes
|
return subnet, changes
|
||||||
|
|
||||||
|
def _allocate_pools_for_subnet(self, context, subnet):
|
||||||
|
"""Create IP allocation pools for a given subnet
|
||||||
|
|
||||||
|
Pools are defined by the 'allocation_pools' attribute,
|
||||||
|
a list of dict objects with 'start' and 'end' keys for
|
||||||
|
defining the pool range.
|
||||||
|
"""
|
||||||
|
pools = []
|
||||||
|
# Auto allocate the pool around gateway_ip
|
||||||
|
net = netaddr.IPNetwork(subnet['cidr'])
|
||||||
|
first_ip = net.first + 1
|
||||||
|
last_ip = net.last - 1
|
||||||
|
gw_ip = int(netaddr.IPAddress(subnet['gateway_ip'] or net.last))
|
||||||
|
# Use the gw_ip to find a point for splitting allocation pools
|
||||||
|
# for this subnet
|
||||||
|
split_ip = min(max(gw_ip, net.first), net.last)
|
||||||
|
if split_ip > first_ip:
|
||||||
|
pools.append({'start': str(netaddr.IPAddress(first_ip)),
|
||||||
|
'end': str(netaddr.IPAddress(split_ip - 1))})
|
||||||
|
if split_ip < last_ip:
|
||||||
|
pools.append({'start': str(netaddr.IPAddress(split_ip + 1)),
|
||||||
|
'end': str(netaddr.IPAddress(last_ip))})
|
||||||
|
# return auto-generated pools
|
||||||
|
# no need to check for their validity
|
||||||
|
return pools
|
||||||
|
|
||||||
|
def _validate_subnet_cidr(self, context, network, new_subnet_cidr):
|
||||||
|
"""Validate the CIDR for a subnet.
|
||||||
|
|
||||||
|
Verifies the specified CIDR does not overlap with the ones defined
|
||||||
|
for the other subnets specified for this network, or with any other
|
||||||
|
CIDR if overlapping IPs are disabled.
|
||||||
|
"""
|
||||||
|
new_subnet_ipset = netaddr.IPSet([new_subnet_cidr])
|
||||||
|
# Disallow subnets with prefix length 0 as they will lead to
|
||||||
|
# dnsmasq failures (see bug 1362651).
|
||||||
|
# This is not a discrimination against /0 subnets.
|
||||||
|
# A /0 subnet is conceptually possible but hardly a practical
|
||||||
|
# scenario for neutron's use cases.
|
||||||
|
for cidr in new_subnet_ipset.iter_cidrs():
|
||||||
|
if cidr.prefixlen == 0:
|
||||||
|
err_msg = _("0 is not allowed as CIDR prefix length")
|
||||||
|
raise n_exc.InvalidInput(error_message=err_msg)
|
||||||
|
|
||||||
|
if cfg.CONF.allow_overlapping_ips:
|
||||||
|
subnet_list = network.subnets
|
||||||
|
else:
|
||||||
|
subnet_list = self._get_all_subnets(context)
|
||||||
|
for subnet in subnet_list:
|
||||||
|
if (netaddr.IPSet([subnet.cidr]) & new_subnet_ipset):
|
||||||
|
# don't give out details of the overlapping subnet
|
||||||
|
err_msg = (_("Requested subnet with cidr: %(cidr)s for "
|
||||||
|
"network: %(network_id)s overlaps with another "
|
||||||
|
"subnet") %
|
||||||
|
{'cidr': new_subnet_cidr,
|
||||||
|
'network_id': network.id})
|
||||||
|
LOG.info(_LI("Validation for CIDR: %(new_cidr)s failed - "
|
||||||
|
"overlaps with subnet %(subnet_id)s "
|
||||||
|
"(CIDR: %(cidr)s)"),
|
||||||
|
{'new_cidr': new_subnet_cidr,
|
||||||
|
'subnet_id': subnet.id,
|
||||||
|
'cidr': subnet.cidr})
|
||||||
|
raise n_exc.InvalidInput(error_message=err_msg)
|
||||||
|
|
||||||
|
def _validate_network_subnetpools(self, network,
|
||||||
|
new_subnetpool_id, ip_version):
|
||||||
|
"""Validate all subnets on the given network have been allocated from
|
||||||
|
the same subnet pool as new_subnetpool_id
|
||||||
|
"""
|
||||||
|
for subnet in network.subnets:
|
||||||
|
if (subnet.ip_version == ip_version and
|
||||||
|
new_subnetpool_id != subnet.subnetpool_id):
|
||||||
|
raise n_exc.NetworkSubnetPoolAffinityError()
|
||||||
|
|
||||||
def _validate_allocation_pools(self, ip_pools, subnet_cidr):
|
def _validate_allocation_pools(self, ip_pools, subnet_cidr):
|
||||||
"""Validate IP allocation pools.
|
"""Validate IP allocation pools.
|
||||||
|
|
||||||
|
@ -283,3 +357,45 @@ class IpamBackendMixin(db_base_plugin_common.DbBasePluginCommon):
|
||||||
if not context.is_admin:
|
if not context.is_admin:
|
||||||
query = query.filter_by(tenant_id=context.tenant_id)
|
query = query.filter_by(tenant_id=context.tenant_id)
|
||||||
query.delete()
|
query.delete()
|
||||||
|
|
||||||
|
def _save_subnet(self, context,
|
||||||
|
network,
|
||||||
|
subnet_args,
|
||||||
|
dns_nameservers,
|
||||||
|
host_routes,
|
||||||
|
allocation_pools):
|
||||||
|
|
||||||
|
if not attributes.is_attr_set(allocation_pools):
|
||||||
|
allocation_pools = self._allocate_pools_for_subnet(context,
|
||||||
|
subnet_args)
|
||||||
|
else:
|
||||||
|
self._validate_allocation_pools(allocation_pools,
|
||||||
|
subnet_args['cidr'])
|
||||||
|
if subnet_args['gateway_ip']:
|
||||||
|
self._validate_gw_out_of_pools(subnet_args['gateway_ip'],
|
||||||
|
allocation_pools)
|
||||||
|
|
||||||
|
self._validate_subnet_cidr(context, network, subnet_args['cidr'])
|
||||||
|
self._validate_network_subnetpools(network,
|
||||||
|
subnet_args['subnetpool_id'],
|
||||||
|
subnet_args['ip_version'])
|
||||||
|
|
||||||
|
subnet = models_v2.Subnet(**subnet_args)
|
||||||
|
context.session.add(subnet)
|
||||||
|
if attributes.is_attr_set(dns_nameservers):
|
||||||
|
for addr in dns_nameservers:
|
||||||
|
ns = models_v2.DNSNameServer(address=addr,
|
||||||
|
subnet_id=subnet.id)
|
||||||
|
context.session.add(ns)
|
||||||
|
|
||||||
|
if attributes.is_attr_set(host_routes):
|
||||||
|
for rt in host_routes:
|
||||||
|
route = models_v2.SubnetRoute(
|
||||||
|
subnet_id=subnet.id,
|
||||||
|
destination=rt['destination'],
|
||||||
|
nexthop=rt['nexthop'])
|
||||||
|
context.session.add(route)
|
||||||
|
|
||||||
|
self._save_allocation_pools(context, subnet, allocation_pools)
|
||||||
|
|
||||||
|
return subnet
|
||||||
|
|
Loading…
Reference in New Issue