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',
|
||||
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):
|
||||
try:
|
||||
netaddr.IPNetwork(route['destination'])
|
||||
|
@ -160,32 +112,6 @@ class NeutronDbPluginV2(ipam_non_pluggable_backend.IpamNonPluggableBackend,
|
|||
self._validate_ip_version(ip_version, route['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):
|
||||
# The only case that needs to be validated is when 'shared'
|
||||
# goes from True to False
|
||||
|
@ -514,48 +440,6 @@ class NeutronDbPluginV2(ipam_non_pluggable_backend.IpamNonPluggableBackend,
|
|||
external_gateway_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):
|
||||
cidr = subnet.get('cidr')
|
||||
subnet_id = subnet.get('id', uuidutils.generate_uuid())
|
||||
|
|
|
@ -167,6 +167,80 @@ class IpamBackendMixin(db_base_plugin_common.DbBasePluginCommon):
|
|||
subnet.update(s)
|
||||
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):
|
||||
"""Validate IP allocation pools.
|
||||
|
||||
|
@ -283,3 +357,45 @@ class IpamBackendMixin(db_base_plugin_common.DbBasePluginCommon):
|
|||
if not context.is_admin:
|
||||
query = query.filter_by(tenant_id=context.tenant_id)
|
||||
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