def _get_subnet_for_fixed_ip(self, context, fixed, network_id): if 'subnet_id' in fixed: subnet = self._get_subnet(context, fixed['subnet_id']) if subnet['network_id'] != network_id: msg = (_("Failed to create port on network %(network_id)s" ", because fixed_ips included invalid subnet " "%(subnet_id)s") % {'network_id': network_id, 'subnet_id': fixed['subnet_id']}) raise n_exc.InvalidInput(error_message=msg) # Ensure that the IP is valid on the subnet if ('ip_address' in fixed and not ipam_utils.check_subnet_ip(subnet['cidr'], fixed['ip_address'])): raise n_exc.InvalidIpForSubnet(ip_address=fixed['ip_address']) return subnet if 'ip_address' not in fixed: msg = _('IP allocation requires subnet_id or ip_address') raise n_exc.InvalidInput(error_message=msg) filter = {'network_id': [network_id]} subnets = self._get_subnets(context, filters=filter) for subnet in subnets: if ipam_utils.check_subnet_ip(subnet['cidr'], fixed['ip_address']): return subnet raise n_exc.InvalidIpForNetwork(ip_address=fixed['ip_address'])
def _test_fixed_ips_for_port(self, context, network_id, fixed_ips, device_owner): """Test fixed IPs for port. Check that configured subnets are valid prior to allocating any IPs. Include the subnet_id in the result if only an IP address is configured. :raises: InvalidInput, IpAddressInUse, InvalidIpForNetwork, InvalidIpForSubnet """ fixed_ip_set = [] for fixed in fixed_ips: found = False if 'subnet_id' not in fixed: if 'ip_address' not in fixed: msg = _('IP allocation requires subnet_id or ip_address') raise n_exc.InvalidInput(error_message=msg) filter = {'network_id': [network_id]} subnets = self._get_subnets(context, filters=filter) for subnet in subnets: if ipam_utils.check_subnet_ip(subnet['cidr'], fixed['ip_address']): found = True subnet_id = subnet['id'] break if not found: raise n_exc.InvalidIpForNetwork( ip_address=fixed['ip_address']) else: subnet = self._get_subnet(context, fixed['subnet_id']) if subnet['network_id'] != network_id: msg = (_("Failed to create port on network %(network_id)s" ", because fixed_ips included invalid subnet " "%(subnet_id)s") % {'network_id': network_id, 'subnet_id': fixed['subnet_id']}) raise n_exc.InvalidInput(error_message=msg) subnet_id = subnet['id'] is_auto_addr_subnet = ipv6_utils.is_auto_address_subnet(subnet) if 'ip_address' in fixed: # Ensure that the IP's are unique if not IpamNonPluggableBackend._check_unique_ip( context, network_id, subnet_id, fixed['ip_address']): raise n_exc.IpAddressInUse(net_id=network_id, ip_address=fixed['ip_address']) # Ensure that the IP is valid on the subnet if (not found and not ipam_utils.check_subnet_ip(subnet['cidr'], fixed['ip_address'])): raise n_exc.InvalidIpForSubnet( ip_address=fixed['ip_address']) if (is_auto_addr_subnet and device_owner not in constants.ROUTER_INTERFACE_OWNERS): msg = (_("IPv6 address %(address)s can not be directly " "assigned to a port on subnet %(id)s since the " "subnet is configured for automatic addresses") % {'address': fixed['ip_address'], 'id': subnet_id}) raise n_exc.InvalidInput(error_message=msg) fixed_ip_set.append({'subnet_id': subnet_id, 'ip_address': fixed['ip_address']}) else: # A scan for auto-address subnets on the network is done # separately so that all such subnets (not just those # listed explicitly here by subnet ID) are associated # with the port. if (device_owner in constants.ROUTER_INTERFACE_OWNERS or device_owner == constants.DEVICE_OWNER_ROUTER_SNAT or not is_auto_addr_subnet): fixed_ip_set.append({'subnet_id': subnet_id}) if len(fixed_ip_set) > cfg.CONF.max_fixed_ips_per_port: msg = _('Exceeded maximim amount of fixed ips per port') raise n_exc.InvalidInput(error_message=msg) return fixed_ip_set