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)
Пример #2
0
    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)
Пример #3
0
    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)