def create_subnet(context, subnet):
LOG.info("<STR_LIT>" % context.tenant_id)<EOL>net_id = subnet["<STR_LIT>"]["<STR_LIT>"]<EOL>with context.session.begin():<EOL><INDENT>net = db_api.network_find(context=context, limit=None, sorts=['<STR_LIT:id>'],<EOL>marker=None, page_reverse=False, fields=None,<EOL>id=net_id, scope=db_api.ONE)<EOL>if not net:<EOL><INDENT>raise n_exc.NetworkNotFound(net_id=net_id)<EOL><DEDENT>sub_attrs = subnet["<STR_LIT>"]<EOL>always_pop = ["<STR_LIT>", "<STR_LIT>", "<STR_LIT>", "<STR_LIT>",<EOL>"<STR_LIT>"]<EOL>admin_only = ["<STR_LIT>", "<STR_LIT>", "<STR_LIT>",<EOL>"<STR_LIT>"]<EOL>utils.filter_body(context, sub_attrs, admin_only, always_pop)<EOL>_validate_subnet_cidr(context, net_id, sub_attrs["<STR_LIT>"])<EOL>cidr = netaddr.IPNetwork(sub_attrs["<STR_LIT>"])<EOL>err_vals = {'<STR_LIT>': sub_attrs["<STR_LIT>"], '<STR_LIT>': net_id}<EOL>err = _("<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>")<EOL>if cidr.version == <NUM_LIT:6> and cidr.prefixlen > <NUM_LIT:64>:<EOL><INDENT>err_vals["<STR_LIT>"] = <NUM_LIT><EOL>err_msg = err % err_vals<EOL>raise n_exc.InvalidInput(error_message=err_msg)<EOL><DEDENT>elif cidr.version == <NUM_LIT:4> and cidr.prefixlen > <NUM_LIT:30>:<EOL><INDENT>err_vals["<STR_LIT>"] = <NUM_LIT><EOL>err_msg = err % err_vals<EOL>raise n_exc.InvalidInput(error_message=err_msg)<EOL><DEDENT>net_subnets = get_subnets(context,<EOL>filters=dict(network_id=net_id))<EOL>if not context.is_admin:<EOL><INDENT>v4_count, v6_count = <NUM_LIT:0>, <NUM_LIT:0><EOL>for subnet in net_subnets:<EOL><INDENT>if netaddr.IPNetwork(subnet['<STR_LIT>']).version == <NUM_LIT:6>:<EOL><INDENT>v6_count += <NUM_LIT:1><EOL><DEDENT>else:<EOL><INDENT>v4_count += <NUM_LIT:1><EOL><DEDENT><DEDENT>if cidr.version == <NUM_LIT:6>:<EOL><INDENT>tenant_quota_v6 = context.session.query(qdv.Quota).filter_by(<EOL>tenant_id=context.tenant_id,<EOL>resource='<STR_LIT>').first()<EOL>if tenant_quota_v6 != -<NUM_LIT:1>:<EOL><INDENT>quota.QUOTAS.limit_check(<EOL>context, context.tenant_id,<EOL>v6_subnets_per_network=v6_count + <NUM_LIT:1>)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>tenant_quota_v4 = context.session.query(qdv.Quota).filter_by(<EOL>tenant_id=context.tenant_id,<EOL>resource='<STR_LIT>').first()<EOL>if tenant_quota_v4 != -<NUM_LIT:1>:<EOL><INDENT>quota.QUOTAS.limit_check(<EOL>context, context.tenant_id,<EOL>v4_subnets_per_network=v4_count + <NUM_LIT:1>)<EOL><DEDENT><DEDENT><DEDENT>gateway_ip = utils.pop_param(sub_attrs, "<STR_LIT>")<EOL>dns_ips = utils.pop_param(sub_attrs, "<STR_LIT>", [])<EOL>host_routes = utils.pop_param(sub_attrs, "<STR_LIT>", [])<EOL>allocation_pools = utils.pop_param(sub_attrs, "<STR_LIT>", None)<EOL>sub_attrs["<STR_LIT>"] = net<EOL>new_subnet = db_api.subnet_create(context, **sub_attrs)<EOL>cidrs = []<EOL>alloc_pools = allocation_pool.AllocationPools(sub_attrs["<STR_LIT>"],<EOL>allocation_pools)<EOL>if isinstance(allocation_pools, list):<EOL><INDENT>cidrs = alloc_pools.get_policy_cidrs()<EOL><DEDENT>quota.QUOTAS.limit_check(<EOL>context,<EOL>context.tenant_id,<EOL>alloc_pools_per_subnet=len(alloc_pools))<EOL>ip_policies.ensure_default_policy(cidrs, [new_subnet])<EOL>new_subnet["<STR_LIT>"] = db_api.ip_policy_create(context,<EOL>exclude=cidrs)<EOL>quota.QUOTAS.limit_check(context, context.tenant_id,<EOL>routes_per_subnet=len(host_routes))<EOL>default_route = None<EOL>for route in host_routes:<EOL><INDENT>netaddr_route = netaddr.IPNetwork(route["<STR_LIT>"])<EOL>if netaddr_route.value == routes.DEFAULT_ROUTE.value:<EOL><INDENT>if default_route:<EOL><INDENT>raise q_exc.DuplicateRouteConflict(<EOL>subnet_id=new_subnet["<STR_LIT:id>"])<EOL><DEDENT>default_route = route<EOL>gateway_ip = default_route["<STR_LIT>"]<EOL>alloc_pools.validate_gateway_excluded(gateway_ip)<EOL><DEDENT>new_subnet["<STR_LIT>"].append(db_api.route_create(<EOL>context, cidr=route["<STR_LIT>"], gateway=route["<STR_LIT>"]))<EOL><DEDENT>quota.QUOTAS.limit_check(context, context.tenant_id,<EOL>dns_nameservers_per_subnet=len(dns_ips))<EOL>for dns_ip in dns_ips:<EOL><INDENT>new_subnet["<STR_LIT>"].append(db_api.dns_create(<EOL>context, ip=netaddr.IPAddress(dns_ip)))<EOL><DEDENT>if gateway_ip and default_route is None:<EOL><INDENT>alloc_pools.validate_gateway_excluded(gateway_ip)<EOL>new_subnet["<STR_LIT>"].append(db_api.route_create(<EOL>context, cidr=str(routes.DEFAULT_ROUTE), gateway=gateway_ip))<EOL><DEDENT><DEDENT>subnet_dict = v._make_subnet_dict(new_subnet)<EOL>subnet_dict["<STR_LIT>"] = gateway_ip<EOL>return subnet_dict<EOL>
Create a subnet.

    Create a subnet which represents a range of IP addresses
    that can be allocated to devices

    : param context: neutron api request context
    : param subnet: dictionary describing the subnet, with keys
        as listed in the RESOURCE_ATTRIBUTE_MAP object in
        neutron/api/v2/attributes.py.  All keys will be populated.