def _validate_subnet(self, context, s, cur_subnet=None):

        # 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 validators.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 exc.InvalidInput(error_message=error_message)

            net = netaddr.IPNetwork(s['cidr'])
            if net.is_multicast():
                error_message = _("Multicast IP subnet is not supported "
                                  "if enable_dhcp is True.")
                raise exc.InvalidInput(error_message=error_message)
            elif net.is_loopback():
                error_message = _("Loopback IP subnet is not supported "
                                  "if enable_dhcp is True.")
                raise exc.InvalidInput(error_message=error_message)

        if validators.is_attr_set(s.get('gateway_ip')):
            self._validate_ip_version(ip_ver, s['gateway_ip'], 'gateway_ip')
            is_gateway_not_valid = (
                ipam.utils.check_gateway_invalid_in_subnet(
                    s['cidr'], s['gateway_ip']))
            if is_gateway_not_valid:
                error_message = _("Gateway is not valid on subnet")
                raise 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 and not ipv6_utils.is_ipv6_pd_enabled(s):
                ipal = models_v2.IPAllocation
                alloc_qry = context.session.query(ipal)
                alloc_qry = alloc_qry.join("port", "routerport")
                allocated = alloc_qry.filter(
                    ipal.ip_address == cur_subnet['gateway_ip'],
                    ipal.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 validators.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 exc.InvalidInput(
                        error_message=(_("Error parsing dns address %s") %
                                       dns))
                self._validate_ip_version(ip_ver, dns, 'dns_nameserver')

        if validators.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 validators.is_attr_set(s.get('ipv6_ra_mode')):
                raise exc.InvalidInput(
                    error_message=(_("ipv6_ra_mode is not valid when "
                                     "ip_version is 4")))
            if validators.is_attr_set(s.get('ipv6_address_mode')):
                raise 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)
Validate a subnet spec.
dataset/ETHPy150Open openstack/neutron/neutron/db/db_base_plugin_v2.py/NeutronDbPluginV2._validate_subnet