def get_subnets(context, limit=None, page_reverse=False, sorts=None, marker=None, filters=None, fields=None): """Retrieve a list of subnets. The contents of the list depends on the identity of the user making the request (as indicated by the context) as well as any filters. : param context: neutron api request context : param filters: a dictionary with keys that are valid keys for a subnet as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. Values in this dictiontary are an iterable containing values that will be used for an exact match comparison for that value. Each result returned by this function will have matched one of the values for each key in filters. : param fields: a list of strings that are valid keys in a subnet dictionary as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. Only these fields will be returned. """ LOG.info("get_subnets for tenant %s with filters %s fields %s" % (context.tenant_id, filters, fields)) filters = filters or {} subnets = db_api.subnet_find(context, limit=limit, page_reverse=page_reverse, sorts=sorts, marker_obj=marker, join_dns=True, join_routes=True, **filters) for subnet in subnets: cache = subnet.get("_allocation_pool_cache") if not cache: db_api.subnet_update_set_alloc_pool_cache( context, subnet, subnet.allocation_pools) return v._make_subnets_list(subnets, fields=fields)
def get_subnet(context, id, fields=None): """Retrieve a subnet. : param context: neutron api request context : param id: UUID representing the subnet to fetch. : param fields: a list of strings that are valid keys in a subnet dictionary as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. Only these fields will be returned. """ LOG.info("get_subnet %s for tenant %s with fields %s" % (id, context.tenant_id, fields)) subnet = db_api.subnet_find(context, None, None, None, False, id=id, join_dns=True, join_routes=True, scope=db_api.ONE) if not subnet: raise exceptions.SubnetNotFound(subnet_id=id) # Check the network_id against the strategies net_id = subnet["network_id"] net_id = STRATEGY.get_parent_network(net_id) subnet["network_id"] = net_id cache = subnet.get("_allocation_pool_cache") if not cache: new_cache = subnet.allocation_pools db_api.subnet_update_set_alloc_pool_cache(context, subnet, new_cache) return v._make_subnet_dict(subnet)
def test_subnet_update_set_alloc_pool_cache_concurrency(self): subnet = {"cidr": "192.168.10.0/24"} subnet_db = db_api.subnet_create(self.context, **subnet) self.context.session.flush() # establish second session old_session = self.context.session self.context._session = None subnet_to_delete = db_api.subnet_find( self.context, id=subnet_db.id, scope=db_api.ONE) db_api.subnet_delete(self.context, subnet_to_delete) self.context.session.flush() # restore first session self.context._session = old_session try: db_api.subnet_update_set_alloc_pool_cache( self.context, subnet_db, {"foo": "bar"}) self.context.session.flush() except exc.StaleDataError as e: self.fail("Did not expect StaleDataError exception: {0}".format(e)) self.assertEqual(subnet_db["_allocation_pool_cache"], "{\"foo\": \"bar\"}")
def get_subnet(context, id, fields=None): """Retrieve a subnet. : param context: neutron api request context : param id: UUID representing the subnet to fetch. : param fields: a list of strings that are valid keys in a subnet dictionary as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. Only these fields will be returned. """ LOG.info("get_subnet %s for tenant %s with fields %s" % (id, context.tenant_id, fields)) subnet = db_api.subnet_find(context=context, limit=None, page_reverse=False, sorts=['id'], marker_obj=None, fields=None, id=id, join_dns=True, join_routes=True, scope=db_api.ONE) if not subnet: raise n_exc.SubnetNotFound(subnet_id=id) cache = subnet.get("_allocation_pool_cache") if not cache: new_cache = subnet.allocation_pools db_api.subnet_update_set_alloc_pool_cache(context, subnet, new_cache) return v._make_subnet_dict(subnet)
def get_subnet(context, id, fields=None): """Retrieve a subnet. : param context: neutron api request context : param id: UUID representing the subnet to fetch. : param fields: a list of strings that are valid keys in a subnet dictionary as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. Only these fields will be returned. """ LOG.info("get_subnet %s for tenant %s with fields %s" % (id, context.tenant_id, fields)) subnet = db_api.subnet_find(context, None, None, None, False, id=id, join_dns=True, join_routes=True, scope=db_api.ONE) if not subnet: raise exceptions.SubnetNotFound(subnet_id=id) # Check the network_id against the strategies net_id = subnet["network_id"] net_id = STRATEGY.get_parent_network(net_id) subnet["network_id"] = net_id cache = subnet.get("_allocation_pool_cache") if not cache: new_cache = subnet.allocation_pools db_api.subnet_update_set_alloc_pool_cache(context, subnet, new_cache) return v._make_subnet_dict(subnet)
def get_subnets(context, limit=None, page_reverse=False, sorts=['id'], marker=None, filters=None, fields=None): """Retrieve a list of subnets. The contents of the list depends on the identity of the user making the request (as indicated by the context) as well as any filters. : param context: neutron api request context : param filters: a dictionary with keys that are valid keys for a subnet as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. Values in this dictiontary are an iterable containing values that will be used for an exact match comparison for that value. Each result returned by this function will have matched one of the values for each key in filters. : param fields: a list of strings that are valid keys in a subnet dictionary as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. Only these fields will be returned. """ LOG.info("get_subnets for tenant %s with filters %s fields %s" % (context.tenant_id, filters, fields)) filters = filters or {} subnets = db_api.subnet_find(context, limit=limit, page_reverse=page_reverse, sorts=sorts, marker_obj=marker, join_dns=True, join_routes=True, join_pool=True, **filters) for subnet in subnets: cache = subnet.get("_allocation_pool_cache") if not cache: db_api.subnet_update_set_alloc_pool_cache(context, subnet, subnet.allocation_pools) return v._make_subnets_list(subnets, fields=fields)
def update_subnet(context, id, subnet): """Update values of a subnet. : param context: neutron api request context : param id: UUID representing the subnet to update. : param subnet: dictionary with keys indicating fields to update. valid keys are those that have a value of True for 'allow_put' as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. """ LOG.info("update_subnet %s for tenant %s" % (id, context.tenant_id)) with context.session.begin(): subnet_db = db_api.subnet_find(context, None, None, None, False, id=id, scope=db_api.ONE) if not subnet_db: raise exceptions.SubnetNotFound(id=id) s = subnet["subnet"] always_pop = ["_cidr", "cidr", "first_ip", "last_ip", "ip_version", "segment_id", "network_id"] admin_only = ["do_not_use", "created_at", "tenant_id", "next_auto_assign_ip", "enable_dhcp"] utils.filter_body(context, s, admin_only, always_pop) dns_ips = utils.pop_param(s, "dns_nameservers", []) host_routes = utils.pop_param(s, "host_routes", []) gateway_ip = utils.pop_param(s, "gateway_ip", None) allocation_pools = utils.pop_param(s, "allocation_pools", None) if not CONF.QUARK.allow_allocation_pool_update: if allocation_pools: raise exceptions.BadRequest( resource="subnets", msg="Allocation pools cannot be updated.") alloc_pools = allocation_pool.AllocationPools( subnet_db["cidr"], policies=models.IPPolicy.get_ip_policy_cidrs(subnet_db)) else: alloc_pools = allocation_pool.AllocationPools(subnet_db["cidr"], allocation_pools) quota.QUOTAS.limit_check( context, context.tenant_id, alloc_pools_per_subnet=len(alloc_pools)) if gateway_ip: alloc_pools.validate_gateway_excluded(gateway_ip) default_route = None for route in host_routes: netaddr_route = netaddr.IPNetwork(route["destination"]) if netaddr_route.value == routes.DEFAULT_ROUTE.value: default_route = route break if default_route is None: route_model = db_api.route_find( context, cidr=str(routes.DEFAULT_ROUTE), subnet_id=id, scope=db_api.ONE) if route_model: db_api.route_update(context, route_model, gateway=gateway_ip) else: db_api.route_create(context, cidr=str(routes.DEFAULT_ROUTE), gateway=gateway_ip, subnet_id=id) if dns_ips: subnet_db["dns_nameservers"] = [] quota.QUOTAS.limit_check(context, context.tenant_id, dns_nameservers_per_subnet=len(dns_ips)) for dns_ip in dns_ips: subnet_db["dns_nameservers"].append(db_api.dns_create( context, ip=netaddr.IPAddress(dns_ip))) if host_routes: subnet_db["routes"] = [] quota.QUOTAS.limit_check(context, context.tenant_id, routes_per_subnet=len(host_routes)) for route in host_routes: subnet_db["routes"].append(db_api.route_create( context, cidr=route["destination"], gateway=route["nexthop"])) if CONF.QUARK.allow_allocation_pool_update: if isinstance(allocation_pools, list): cidrs = alloc_pools.get_policy_cidrs() ip_policies.ensure_default_policy(cidrs, [subnet_db]) subnet_db["ip_policy"] = db_api.ip_policy_update( context, subnet_db["ip_policy"], exclude=cidrs) # invalidate the cache db_api.subnet_update_set_alloc_pool_cache(context, subnet_db) subnet = db_api.subnet_update(context, subnet_db, **s) return v._make_subnet_dict(subnet)
def update_subnet(context, id, subnet): """Update values of a subnet. : param context: neutron api request context : param id: UUID representing the subnet to update. : param subnet: dictionary with keys indicating fields to update. valid keys are those that have a value of True for 'allow_put' as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. """ LOG.info("update_subnet %s for tenant %s" % (id, context.tenant_id)) with context.session.begin(): subnet_db = db_api.subnet_find(context, None, None, None, False, id=id, scope=db_api.ONE) if not subnet_db: raise exceptions.SubnetNotFound(id=id) s = subnet["subnet"] always_pop = [ "_cidr", "cidr", "first_ip", "last_ip", "ip_version", "segment_id", "network_id" ] admin_only = [ "do_not_use", "created_at", "tenant_id", "next_auto_assign_ip", "enable_dhcp" ] utils.filter_body(context, s, admin_only, always_pop) dns_ips = utils.pop_param(s, "dns_nameservers", []) host_routes = utils.pop_param(s, "host_routes", []) gateway_ip = utils.pop_param(s, "gateway_ip", None) allocation_pools = utils.pop_param(s, "allocation_pools", None) if not CONF.QUARK.allow_allocation_pool_update: if allocation_pools: raise exceptions.BadRequest( resource="subnets", msg="Allocation pools cannot be updated.") alloc_pools = allocation_pool.AllocationPools( subnet_db["cidr"], policies=models.IPPolicy.get_ip_policy_cidrs(subnet_db)) else: alloc_pools = allocation_pool.AllocationPools( subnet_db["cidr"], allocation_pools) quota.QUOTAS.limit_check(context, context.tenant_id, alloc_pools_per_subnet=len(alloc_pools)) if gateway_ip: alloc_pools.validate_gateway_excluded(gateway_ip) default_route = None for route in host_routes: netaddr_route = netaddr.IPNetwork(route["destination"]) if netaddr_route.value == routes.DEFAULT_ROUTE.value: default_route = route break if default_route is None: route_model = db_api.route_find(context, cidr=str(routes.DEFAULT_ROUTE), subnet_id=id, scope=db_api.ONE) if route_model: db_api.route_update(context, route_model, gateway=gateway_ip) else: db_api.route_create(context, cidr=str(routes.DEFAULT_ROUTE), gateway=gateway_ip, subnet_id=id) if dns_ips: subnet_db["dns_nameservers"] = [] quota.QUOTAS.limit_check(context, context.tenant_id, dns_nameservers_per_subnet=len(dns_ips)) for dns_ip in dns_ips: subnet_db["dns_nameservers"].append( db_api.dns_create(context, ip=netaddr.IPAddress(dns_ip))) if host_routes: subnet_db["routes"] = [] quota.QUOTAS.limit_check(context, context.tenant_id, routes_per_subnet=len(host_routes)) for route in host_routes: subnet_db["routes"].append( db_api.route_create(context, cidr=route["destination"], gateway=route["nexthop"])) if CONF.QUARK.allow_allocation_pool_update: if isinstance(allocation_pools, list): cidrs = alloc_pools.get_policy_cidrs() ip_policies.ensure_default_policy(cidrs, [subnet_db]) subnet_db["ip_policy"] = db_api.ip_policy_update( context, subnet_db["ip_policy"], exclude=cidrs) # invalidate the cache db_api.subnet_update_set_alloc_pool_cache(context, subnet_db) subnet = db_api.subnet_update(context, subnet_db, **s) return v._make_subnet_dict(subnet)