def create_subnet(self, context, subnet): """Creates a new subnet, and assigns it a symbolic name.""" if subnet['subnet']['gateway_ip'] is None: subnet['subnet']['gateway_ip'] = '0.0.0.0' if subnet['subnet']['host_routes'] != attr.ATTR_NOT_SPECIFIED: if (len(subnet['subnet']['host_routes']) > cfg.CONF.max_subnet_host_routes): raise exc.HostRoutesExhausted(subnet_id=subnet[ 'subnet'].get('id', _('new subnet')), quota=cfg.CONF.max_subnet_host_routes) subnet_created = self._create_resource('subnet', context, subnet) return self._make_subnet_dict(subnet_created)
def create_subnet(self, context, subnet): """Creates a new subnet, and assigns it a symbolic name.""" net = netaddr.IPNetwork(subnet['subnet']['cidr']) # turn the CIDR into a proper subnet subnet['subnet']['cidr'] = '%s/%s' % (net.network, net.prefixlen) plugin_subnet = copy.deepcopy(subnet) for key, value in subnet['subnet'].items(): if value == attr.ATTR_NOT_SPECIFIED: plugin_subnet['subnet'][key] = None if subnet['subnet']['gateway_ip'] is None: plugin_subnet['subnet']['gateway_ip'] = '0.0.0.0' if plugin_subnet['subnet']['host_routes']: if (len(plugin_subnet['subnet']['host_routes']) > cfg.CONF.max_subnet_host_routes): raise exc.HostRoutesExhausted( subnet_id=plugin_subnet['subnet'].get( 'id', _('new subnet')), quota=cfg.CONF.max_subnet_host_routes) self._validate_subnet(context, plugin_subnet['subnet']) if plugin_subnet['subnet']['allocation_pools']: self._validate_allocation_pools( plugin_subnet['subnet']['allocation_pools'], plugin_subnet['subnet']['cidr']) if (plugin_subnet['subnet']['gateway_ip'] and plugin_subnet['subnet']['allocation_pools']): self._validate_gw_out_of_pools( plugin_subnet['subnet']['gateway_ip'], plugin_subnet['subnet']['allocation_pools']) network = self._get_network(context, plugin_subnet['subnet']['network_id']) self._validate_subnet_cidr(context, network, plugin_subnet['subnet']['cidr']) return self._create_resource('subnet', context, plugin_subnet)
def _validate_subnet(self, context, s, cur_subnet=None): """Validate a subnet spec.""" # This method will validate attributes which may change during # create_subnet() and update_subnet(). # The method requires the subnet spec 's' has 'ip_version' field. # If 's' dict does not have 'ip_version' field in an API call # (e.g., update_subnet()), you need to set 'ip_version' field # before calling this method. ip_ver = s['ip_version'] if attributes.is_attr_set(s.get('cidr')): self._validate_ip_version(ip_ver, s['cidr'], 'cidr') # TODO(watanabe.isao): After we found a way to avoid the re-sync # from the agent side, this restriction could be removed. if cur_subnet: dhcp_was_enabled = cur_subnet.enable_dhcp else: dhcp_was_enabled = False if s.get('enable_dhcp') and not dhcp_was_enabled: subnet_prefixlen = netaddr.IPNetwork(s['cidr']).prefixlen error_message = _("Subnet has a prefix length that is " "incompatible with DHCP service enabled.") if ((ip_ver == 4 and subnet_prefixlen > 30) or (ip_ver == 6 and subnet_prefixlen > 126)): raise n_exc.InvalidInput(error_message=error_message) else: # NOTE(watanabe.isao): The following restriction is necessary # only when updating subnet. if cur_subnet: range_qry = context.session.query( models_v2.IPAvailabilityRange).join( models_v2.IPAllocationPool) ip_range = range_qry.filter_by(subnet_id=s['id']).first() if not ip_range: raise n_exc.IpAddressGenerationFailure( net_id=cur_subnet.network_id) if attributes.is_attr_set(s.get('gateway_ip')): self._validate_ip_version(ip_ver, s['gateway_ip'], 'gateway_ip') if (cfg.CONF.force_gateway_on_subnet and not ipam.utils.check_gateway_in_subnet( s['cidr'], s['gateway_ip'])): error_message = _("Gateway is not valid on subnet") raise n_exc.InvalidInput(error_message=error_message) # Ensure the gateway IP is not assigned to any port # skip this check in case of create (s parameter won't have id) # NOTE(salv-orlando): There is slight chance of a race, when # a subnet-update and a router-interface-add operation are # executed concurrently if cur_subnet: alloc_qry = context.session.query(models_v2.IPAllocation) allocated = alloc_qry.filter_by( ip_address=cur_subnet['gateway_ip'], subnet_id=cur_subnet['id']).first() if allocated and allocated['port_id']: raise n_exc.GatewayIpInUse( ip_address=cur_subnet['gateway_ip'], port_id=allocated['port_id']) if attributes.is_attr_set(s.get('dns_nameservers')): if len(s['dns_nameservers']) > cfg.CONF.max_dns_nameservers: raise n_exc.DNSNameServersExhausted( subnet_id=s.get('id', _('new subnet')), quota=cfg.CONF.max_dns_nameservers) for dns in s['dns_nameservers']: try: netaddr.IPAddress(dns) except Exception: raise n_exc.InvalidInput( error_message=(_("Error parsing dns address %s") % dns)) self._validate_ip_version(ip_ver, dns, 'dns_nameserver') if attributes.is_attr_set(s.get('host_routes')): if len(s['host_routes']) > cfg.CONF.max_subnet_host_routes: raise n_exc.HostRoutesExhausted( subnet_id=s.get('id', _('new subnet')), quota=cfg.CONF.max_subnet_host_routes) # check if the routes are all valid for rt in s['host_routes']: self._validate_host_route(rt, ip_ver) if ip_ver == 4: if attributes.is_attr_set(s.get('ipv6_ra_mode')): raise n_exc.InvalidInput( error_message=(_("ipv6_ra_mode is not valid when " "ip_version is 4"))) if attributes.is_attr_set(s.get('ipv6_address_mode')): raise n_exc.InvalidInput( error_message=(_("ipv6_address_mode is not valid when " "ip_version is 4"))) if ip_ver == 6: self._validate_ipv6_attributes(s, cur_subnet)