def diagnose_network(context, id, fields): if id == "*": return {'networks': [_diag_network(context, net, fields) for net in db_api.network_find(context, scope=db_api.ALL)]} db_net = db_api.network_find(context, id=id, scope=db_api.ONE) if not db_net: raise exceptions.NetworkNotFound(net_id=id) net = _diag_network(context, db_net, fields) return {'networks': net}
def diagnose_network(context, id, fields): if not context.is_admin: raise n_exc.NotAuthorized() if id == "*": return {'networks': [_diag_network(context, net, fields) for net in db_api.network_find(context, scope=db_api.ALL)]} db_net = db_api.network_find(context, id=id, scope=db_api.ONE) if not db_net: raise n_exc.NetworkNotFound(net_id=id) net = _diag_network(context, db_net, fields) return {'networks': net}
def get_networks(context, filters=None, fields=None): """Retrieve a list of networks. 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 network 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 network dictionary as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. Only these fields will be returned. """ LOG.info("get_networks for tenant %s with filters %s, fields %s" % (context.tenant_id, filters, fields)) filters = filters or {} nets = db_api.network_find(context, join_subnets=True, **filters) or [] nets = [v._make_network_dict(net, fields=fields) for net in nets] return nets
def create_ip_policy(context, ip_policy): LOG.info("create_ip_policy for tenant %s" % context.tenant_id) ipp = ip_policy["ip_policy"] if not ipp.get("exclude"): raise exceptions.BadRequest(resource="ip_policy", msg="Empty ip_policy.exclude regions") ipp["exclude"] = netaddr.IPSet(ipp["exclude"]) network_id = ipp.get("network_id") subnet_id = ipp.get("subnet_id") model = None if subnet_id: model = db_api.subnet_find(context, id=subnet_id, scope=db_api.ONE) if not model: raise exceptions.SubnetNotFound(id=subnet_id) elif network_id: model = db_api.network_find(context, id=network_id, scope=db_api.ONE) if not model: raise exceptions.NetworkNotFound(id=network_id) else: raise exceptions.BadRequest( resource="ip_policy", msg="network_id or subnet_id unspecified") if model["ip_policy"]: raise quark_exceptions.IPPolicyAlreadyExists( id=model["ip_policy"]["id"], n_id=model["id"]) model["ip_policy"] = db_api.ip_policy_create(context, **ipp) return v._make_ip_policy_dict(model["ip_policy"])
def diagnose_network(context, id, fields): if not context.is_admin: raise n_exc.NotAuthorized() if id == "*": return { 'networks': [ _diag_network(context, net, fields) for net in db_api.network_find(context, scope=db_api.ALL) ] } db_net = db_api.network_find(context, id=id, scope=db_api.ONE) if not db_net: raise n_exc.NetworkNotFound(net_id=id) net = _diag_network(context, db_net, fields) return {'networks': net}
def delete_network(context, id): """Delete a network. : param context: neutron api request context : param id: UUID representing the network to delete. """ LOG.info("delete_network %s for tenant %s" % (id, context.tenant_id)) with context.session.begin(): net = db_api.network_find(context=context, limit=None, sorts=['id'], marker=None, page_reverse=False, id=id, scope=db_api.ONE) if not net: raise n_exc.NetworkNotFound(net_id=id) if not context.is_admin: if STRATEGY.is_provider_network(net.id): raise n_exc.NotAuthorized(net_id=id) if net.ports: raise n_exc.NetworkInUse(net_id=id) net_driver = registry.DRIVER_REGISTRY.get_driver(net["network_plugin"]) net_driver.delete_network(context, id) for subnet in net["subnets"]: subnets._delete_subnet(context, subnet) db_api.network_delete(context, net)
def create_ip_policy(context, ip_policy): LOG.info("create_ip_policy for tenant %s" % context.tenant_id) ipp = ip_policy["ip_policy"] if not ipp.get("exclude"): raise exceptions.BadRequest(resource="ip_policy", msg="Empty ip_policy.exclude regions") ipp["exclude"] = netaddr.IPSet(ipp["exclude"]) network_id = ipp.get("network_id") subnet_id = ipp.get("subnet_id") model = None if subnet_id: model = db_api.subnet_find(context, id=subnet_id, scope=db_api.ONE) if not model: raise exceptions.SubnetNotFound(id=subnet_id) elif network_id: model = db_api.network_find(context, id=network_id, scope=db_api.ONE) if not model: raise exceptions.NetworkNotFound(id=network_id) else: raise exceptions.BadRequest(resource="ip_policy", msg="network_id or subnet_id unspecified") if model["ip_policy"]: raise quark_exceptions.IPPolicyAlreadyExists( id=model["ip_policy"]["id"], n_id=model["id"]) model["ip_policy"] = db_api.ip_policy_create(context, **ipp) return v._make_ip_policy_dict(model["ip_policy"])
def update_ip_policy(context, id, ip_policy): LOG.info("update_ip_policy for tenant %s" % context.tenant_id) ipp = ip_policy["ip_policy"] with context.session.begin(): ipp_db = db_api.ip_policy_find(context, id=id, scope=db_api.ONE) if not ipp_db: raise quark_exceptions.IPPolicyNotFound(id=id) ip_policy_cidrs = ipp.get("exclude") network_ids = ipp.get("network_ids") subnet_ids = ipp.get("subnet_ids") if subnet_ids and network_ids: raise exceptions.BadRequest( resource="ip_policy", msg="network_ids and subnet_ids specified. only one allowed" ) models = [] all_subnets = [] if subnet_ids: for subnet in ipp_db["subnets"]: subnet["ip_policy"] = None subnets = db_api.subnet_find(context, id=subnet_ids, scope=db_api.ALL) if len(subnets) != len(subnet_ids): raise exceptions.SubnetNotFound(id=subnet_ids) if ip_policy_cidrs is not None: ensure_default_policy(ip_policy_cidrs, subnets) _validate_cidrs_fit_into_subnets(ip_policy_cidrs, subnets) all_subnets.extend(subnets) models.extend(subnets) if network_ids: for network in ipp_db["networks"]: network["ip_policy"] = None nets = db_api.network_find(context, id=network_ids, scope=db_api.ALL) if len(nets) != len(network_ids): raise exceptions.NetworkNotFound(net_id=network_ids) subnets = [subnet for net in nets for subnet in net.get("subnets", [])] if ip_policy_cidrs is not None: ensure_default_policy(ip_policy_cidrs, subnets) _validate_cidrs_fit_into_subnets(ip_policy_cidrs, subnets) all_subnets.extend(subnets) models.extend(nets) if not subnet_ids and not network_ids and ip_policy_cidrs is not None: ensure_default_policy(ip_policy_cidrs, ipp_db["subnets"]) _validate_cidrs_fit_into_subnets(ip_policy_cidrs, ipp_db["subnets"]) for model in models: if model["ip_policy"]: raise quark_exceptions.IPPolicyAlreadyExists(id=model["ip_policy"]["id"], n_id=model["id"]) model["ip_policy"] = ipp_db if ip_policy_cidrs: _validate_policy_with_routes(context, ip_policy_cidrs, all_subnets) ipp_db = db_api.ip_policy_update(context, ipp_db, **ipp) return v._make_ip_policy_dict(ipp_db)
def create_subnet(context, subnet): """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. """ LOG.info("create_subnet for tenant %s" % context.tenant_id) net_id = subnet["subnet"]["network_id"] net = db_api.network_find(context, id=net_id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=net_id) sub_attrs = subnet["subnet"] _validate_subnet_cidr(context, net_id, sub_attrs["cidr"]) cidr = netaddr.IPNetwork(sub_attrs["cidr"]) gateway_ip = utils.pop_param(sub_attrs, "gateway_ip", str(cidr[1])) dns_ips = utils.pop_param(sub_attrs, "dns_nameservers", []) host_routes = utils.pop_param(sub_attrs, "host_routes", []) allocation_pools = utils.pop_param(sub_attrs, "allocation_pools", []) sub_attrs["network"] = net new_subnet = db_api.subnet_create(context, **sub_attrs) 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 gateway_ip = default_route["nexthop"] new_subnet["routes"].append(db_api.route_create( context, cidr=route["destination"], gateway=route["nexthop"])) if default_route is None: new_subnet["routes"].append(db_api.route_create( context, cidr=str(routes.DEFAULT_ROUTE), gateway=gateway_ip)) for dns_ip in dns_ips: new_subnet["dns_nameservers"].append(db_api.dns_create( context, ip=netaddr.IPAddress(dns_ip))) if allocation_pools: exclude = netaddr.IPSet([cidr]) for p in allocation_pools: x = netaddr.IPSet(netaddr.IPRange(p["start"], p["end"])) exclude = exclude - x new_subnet["ip_policy"] = db_api.ip_policy_create(context, exclude=exclude) subnet_dict = v._make_subnet_dict(new_subnet, default_route=routes.DEFAULT_ROUTE) subnet_dict["gateway_ip"] = gateway_ip return subnet_dict
def create_ip_policy(context, ip_policy): LOG.info("create_ip_policy for tenant %s" % context.tenant_id) ipp = ip_policy['ip_policy'] if not ipp.get("exclude"): raise exceptions.BadRequest(resource="ip_policy", msg="Empty ip_policy.exclude") network_ids = ipp.get("network_ids") subnet_ids = ipp.get("subnet_ids") if subnet_ids and network_ids: raise exceptions.BadRequest( resource="ip_policy", msg="network_ids and subnet_ids specified. only one allowed") if not subnet_ids and not network_ids: raise exceptions.BadRequest( resource="ip_policy", msg="network_ids or subnet_ids not specified") with context.session.begin(): if subnet_ids: subnets = db_api.subnet_find(context, id=subnet_ids, scope=db_api.ALL) if not subnets: raise exceptions.SubnetNotFound(id=subnet_ids) _check_for_pre_existing_policies_in(subnets) ensure_default_policy(ipp["exclude"], subnets) _validate_cidrs_fit_into_subnets(ipp["exclude"], subnets) ipp.pop("subnet_ids") ipp["subnets"] = subnets if network_ids: nets = db_api.network_find(context, id=network_ids, scope=db_api.ALL) if not nets: raise exceptions.NetworkNotFound(net_id=network_ids) _check_for_pre_existing_policies_in(nets) subnets = [ subnet for net in nets for subnet in net.get("subnets", []) ] ensure_default_policy(ipp["exclude"], subnets) _validate_cidrs_fit_into_subnets(ipp["exclude"], subnets) ipp.pop("network_ids") ipp["networks"] = nets ip_policy = db_api.ip_policy_create(context, **ipp) return v._make_ip_policy_dict(ip_policy)
def create_ip_policy(context, ip_policy): LOG.info("create_ip_policy for tenant %s" % context.tenant_id) ipp = ip_policy['ip_policy'] if not ipp.get("exclude"): raise exceptions.BadRequest(resource="ip_policy", msg="Empty ip_policy.exclude") ip_policy_cidrs = ipp.get("exclude", []) network_ids = ipp.get("network_ids") subnet_ids = ipp.get("subnet_ids") if subnet_ids and network_ids: raise exceptions.BadRequest( resource="ip_policy", msg="network_ids and subnet_ids specified. only one allowed") if not subnet_ids and not network_ids: raise exceptions.BadRequest( resource="ip_policy", msg="network_ids or subnet_ids not specified") with context.session.begin(): models = [] if subnet_ids: subnets = db_api.subnet_find( context, id=subnet_ids, scope=db_api.ALL) if not subnets: raise exceptions.SubnetNotFound(id=subnet_ids) if ip_policy_cidrs: _validate_cidrs_fit_into_subnets(ip_policy_cidrs, subnets) models.extend(subnets) if network_ids: nets = db_api.network_find( context, id=network_ids, scope=db_api.ALL) if not nets: raise exceptions.NetworkNotFound(net_id=network_ids) subnets = [subnet for net in nets for subnet in net.get("subnets", [])] if ip_policy_cidrs and subnets: _validate_cidrs_fit_into_subnets(ip_policy_cidrs, subnets) models.extend(nets) for model in models: if model["ip_policy"]: raise quark_exceptions.IPPolicyAlreadyExists( id=model["ip_policy"]["id"], n_id=model["id"]) model["ip_policy"] = db_api.ip_policy_create(context, **ipp) return v._make_ip_policy_dict(model["ip_policy"])
def create_ip_policy(context, ip_policy): LOG.info("create_ip_policy for tenant %s" % context.tenant_id) ipp = ip_policy['ip_policy'] if not ipp.get("exclude"): raise n_exc.BadRequest(resource="ip_policy", msg="Empty ip_policy.exclude") network_ids = ipp.get("network_ids") subnet_ids = ipp.get("subnet_ids") if subnet_ids and network_ids: raise n_exc.BadRequest( resource="ip_policy", msg="network_ids and subnet_ids specified. only one allowed") if not subnet_ids and not network_ids: raise n_exc.BadRequest( resource="ip_policy", msg="network_ids or subnet_ids not specified") with context.session.begin(): if subnet_ids: subnets = db_api.subnet_find( context, id=subnet_ids, scope=db_api.ALL) if not subnets: raise n_exc.SubnetNotFound(subnet_id=subnet_ids) _check_for_pre_existing_policies_in(subnets) ensure_default_policy(ipp["exclude"], subnets) _validate_cidrs_fit_into_subnets(ipp["exclude"], subnets) ipp.pop("subnet_ids") ipp["subnets"] = subnets if network_ids: nets = db_api.network_find( context, id=network_ids, scope=db_api.ALL) if not nets: raise n_exc.NetworkNotFound(net_id=network_ids) _check_for_pre_existing_policies_in(nets) subnets = [subnet for net in nets for subnet in net.get("subnets", [])] ensure_default_policy(ipp["exclude"], subnets) _validate_cidrs_fit_into_subnets(ipp["exclude"], subnets) ipp.pop("network_ids") ipp["networks"] = nets ip_policy = db_api.ip_policy_create(context, **ipp) return v._make_ip_policy_dict(ip_policy)
def delete_network(context, id): """Delete a network. : param context: neutron api request context : param id: UUID representing the network to delete. """ LOG.info("delete_network %s for tenant %s" % (id, context.tenant_id)) net = db_api.network_find(context, id=id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=id) if net.ports: raise exceptions.NetworkInUse(net_id=id) net_driver.delete_network(context, id) for subnet in net["subnets"]: subnets._delete_subnet(context, subnet) db_api.network_delete(context, net)
def update_network(context, id, network): """Update values of a network. : param context: neutron api request context : param id: UUID representing the network to update. : param network: 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_network %s for tenant %s" % (id, context.tenant_id)) net = db_api.network_find(context, id=id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=id) net = db_api.network_update(context, net, **network["network"]) return v._make_network_dict(net)
def get_network(context, id, fields=None): """Retrieve a network. : param context: neutron api request context : param id: UUID representing the network to fetch. : param fields: a list of strings that are valid keys in a network dictionary as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. Only these fields will be returned. """ LOG.info("get_network %s for tenant %s fields %s" % (id, context.tenant_id, fields)) network = db_api.network_find(context, id=id, scope=db_api.ONE) if not network: raise exceptions.NetworkNotFound(net_id=id) return v._make_network_dict(network)
def delete_network(context, id): """Delete a network. : param context: neutron api request context : param id: UUID representing the network to delete. """ LOG.info("delete_network %s for tenant %s" % (id, context.tenant_id)) with context.session.begin(): net = db_api.network_find(context, None, None, None, False, id=id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=id) if net.ports: raise exceptions.NetworkInUse(net_id=id) net_driver = registry.DRIVER_REGISTRY.get_driver(net["network_plugin"]) net_driver.delete_network(context, id) for subnet in net["subnets"]: subnets._delete_subnet(context, subnet) db_api.network_delete(context, net)
def update_ip_policy(context, id, ip_policy): LOG.info("update_ip_policy for tenant %s" % context.tenant_id) ipp = ip_policy["ip_policy"] with context.session.begin(): ipp_db = db_api.ip_policy_find(context, id=id, scope=db_api.ONE) if not ipp_db: raise quark_exceptions.IPPolicyNotFound(id=id) network_ids = ipp.get("network_ids") subnet_ids = ipp.get("subnet_ids") models = [] if subnet_ids: for subnet in ipp_db["subnets"]: subnet["ip_policy"] = None subnets = db_api.subnet_find( context, id=subnet_ids, scope=db_api.ALL) if len(subnets) != len(subnet_ids): raise exceptions.SubnetNotFound(id=subnet_ids) models.extend(subnets) if network_ids: for network in ipp_db["networks"]: network["ip_policy"] = None nets = db_api.network_find(context, id=network_ids, scope=db_api.ALL) if len(nets) != len(network_ids): raise exceptions.NetworkNotFound(net_id=network_ids) models.extend(nets) for model in models: if model["ip_policy"]: raise quark_exceptions.IPPolicyAlreadyExists( id=model["ip_policy"]["id"], n_id=model["id"]) model["ip_policy"] = ipp_db ipp_db = db_api.ip_policy_update(context, ipp_db, **ipp) return v._make_ip_policy_dict(ipp_db)
def update_network(context, id, network): """Update values of a network. : param context: neutron api request context : param id: UUID representing the network to update. : param network: 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_network %s for tenant %s" % (id, context.tenant_id)) with context.session.begin(): net = db_api.network_find(context, id=id, scope=db_api.ONE) if not net: raise n_exc.NetworkNotFound(net_id=id) net_dict = network["network"] utils.pop_param(net_dict, "network_plugin") if not context.is_admin and "ipam_strategy" in net_dict: utils.pop_param(net_dict, "ipam_strategy") net = db_api.network_update(context, net, **net_dict) return v._make_network_dict(net)
def get_networks(context, filters=None, fields=None): """Retrieve a list of networks. 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 network 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 network dictionary as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. Only these fields will be returned. """ LOG.info("get_networks for tenant %s with filters %s, fields %s" % (context.tenant_id, filters, fields)) nets = db_api.network_find(context, **filters) return [v._make_network_dict(net) for net in nets]
def create_subnet(context, subnet): """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. """ LOG.info("create_subnet for tenant %s" % context.tenant_id) net_id = subnet["subnet"]["network_id"] with context.session.begin(): net = db_api.network_find(context, id=net_id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=net_id) sub_attrs = subnet["subnet"] _validate_subnet_cidr(context, net_id, sub_attrs["cidr"]) cidr = netaddr.IPNetwork(sub_attrs["cidr"]) gateway_ip = utils.pop_param(sub_attrs, "gateway_ip", str(cidr[1])) dns_ips = utils.pop_param(sub_attrs, "dns_nameservers", []) host_routes = utils.pop_param(sub_attrs, "host_routes", []) allocation_pools = utils.pop_param(sub_attrs, "allocation_pools", None) sub_attrs["network"] = net new_subnet = db_api.subnet_create(context, **sub_attrs) 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 gateway_ip = default_route["nexthop"] new_subnet["routes"].append(db_api.route_create( context, cidr=route["destination"], gateway=route["nexthop"])) if default_route is None: new_subnet["routes"].append(db_api.route_create( context, cidr=str(routes.DEFAULT_ROUTE), gateway=gateway_ip)) for dns_ip in dns_ips: new_subnet["dns_nameservers"].append(db_api.dns_create( context, ip=netaddr.IPAddress(dns_ip))) if isinstance(allocation_pools, list): ranges = [] cidrset = netaddr.IPSet([netaddr.IPNetwork(new_subnet["cidr"])]) for p in allocation_pools: cidrset -= netaddr.IPSet(netaddr.IPRange(p["start"], p["end"])) non_allocation_pools = v._pools_from_cidr(cidrset) for p in non_allocation_pools: r = netaddr.IPRange(p["start"], p["end"]) ranges.append(dict( length=len(r), offset=int(r[0]) - int(cidr[0]))) new_subnet["ip_policy"] = db_api.ip_policy_create(context, exclude=ranges) subnet_dict = v._make_subnet_dict(new_subnet, default_route=routes.DEFAULT_ROUTE) subnet_dict["gateway_ip"] = gateway_ip notifier_api.notify(context, notifier_api.publisher_id("network"), "ip_block.create", notifier_api.CONF.default_notification_level, dict(tenant_id=subnet_dict["tenant_id"], ip_block_id=subnet_dict["id"], created_at=new_subnet["created_at"])) return subnet_dict
def create_port(context, port): """Create a port Create a port which is a connection point of a device (e.g., a VM NIC) to attach to a L2 Neutron network. : param context: neutron api request context : param port: dictionary describing the port, with keys as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. All keys will be populated. """ LOG.info("create_port for tenant %s" % context.tenant_id) port_attrs = port["port"] mac_address = utils.pop_param(port_attrs, "mac_address", None) segment_id = utils.pop_param(port_attrs, "segment_id") fixed_ips = utils.pop_param(port_attrs, "fixed_ips") net_id = port_attrs["network_id"] addresses = [] with context.session.begin(): port_id = uuidutils.generate_uuid() net = db_api.network_find(context, id=net_id, segment_id=segment_id, scope=db_api.ONE) if not net: # Maybe it's a tenant network net = db_api.network_find(context, id=net_id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=net_id) if not STRATEGY.is_parent_network(net_id): quota.QUOTAS.limit_check(context, context.tenant_id, ports_per_network=len(net.get("ports", [])) + 1) ipam_driver = ipam.IPAM_REGISTRY.get_strategy(net["ipam_strategy"]) if fixed_ips: for fixed_ip in fixed_ips: subnet_id = fixed_ip.get("subnet_id") ip_address = fixed_ip.get("ip_address") if not (subnet_id and ip_address): raise exceptions.BadRequest(resource="fixed_ips", msg="subnet_id and ip_address required") addresses.extend( ipam_driver.allocate_ip_address( context, net["id"], port_id, CONF.QUARK.ipam_reuse_after, ip_address=ip_address ) ) else: addresses.extend(ipam_driver.allocate_ip_address(context, net["id"], port_id, CONF.QUARK.ipam_reuse_after)) group_ids, security_groups = v.make_security_group_list(context, port["port"].pop("security_groups", None)) mac = ipam_driver.allocate_mac_address( context, net["id"], port_id, CONF.QUARK.ipam_reuse_after, mac_address=mac_address ) mac_address_string = str(netaddr.EUI(mac["address"], dialect=netaddr.mac_unix)) address_pairs = [ {"mac_address": mac_address_string, "ip_address": address.get("address_readable", "")} for address in addresses ] net_driver = registry.DRIVER_REGISTRY.get_driver(net["network_plugin"]) backend_port = net_driver.create_port( context, net["id"], port_id=port_id, security_groups=group_ids, allowed_pairs=address_pairs ) port_attrs["network_id"] = net["id"] port_attrs["id"] = port_id port_attrs["security_groups"] = security_groups LOG.info("Including extra plugin attrs: %s" % backend_port) port_attrs.update(backend_port) new_port = db_api.port_create( context, addresses=addresses, mac_address=mac["address"], backend_key=backend_port["uuid"], **port_attrs ) # Include any driver specific bits return v._make_port_dict(new_port)
def create_ip_address(context, body): LOG.info("create_ip_address for tenant %s" % context.tenant_id) iptype = (ip_types.SHARED if _shared_ip_request(body) else ip_types.FIXED) if 'ip_address' not in body: raise n_exc.BadRequest(resource="ip_addresses", msg="Invalid request body.") if iptype == ip_types.FIXED and not CONF.QUARK.ipaddr_allow_fixed_ip: raise n_exc.BadRequest(resource="ip_addresses", msg="Only shared IPs may be made with " "this resource.") ip_dict = body.get("ip_address") port_ids = ip_dict.get('port_ids', []) network_id = ip_dict.get('network_id') tenant_id = ip_dict.get('tenant_id') device_ids = ip_dict.get('device_ids') ip_version = ip_dict.get('version') ip_address = ip_dict.get('ip_address') # If no version is passed, you would get what the network provides, # which could be both v4 and v6 addresses. Rather than allow for such # an ambiguous outcome, we'll raise instead if not ip_version: raise n_exc.BadRequest(resource="ip_addresses", msg="version is required.") if network_id is None: raise n_exc.BadRequest(resource="ip_addresses", msg="network_id is required.") if network_id == "": raise n_exc.NetworkNotFound(net_id=network_id) net = db_api.network_find(context, None, None, None, False, id=network_id, scope=db_api.ONE) if not net: raise n_exc.NetworkNotFound(net_id=network_id) if not port_ids and not device_ids: raise n_exc.BadRequest(resource="ip_addresses", msg="port_ids or device_ids required.") new_addresses = [] ports = [] by_device = False with context.session.begin(): if network_id and device_ids: by_device = True for device_id in device_ids: port = db_api.port_find( context, network_id=network_id, device_id=device_id, tenant_id=tenant_id, scope=db_api.ONE) if port is not None: ports.append(port) elif port_ids: for port_id in port_ids: port = db_api.port_find(context, id=port_id, tenant_id=tenant_id, scope=db_api.ONE) if port is not None: ports.append(port) if not ports: raise n_exc.PortNotFoundOnNetwork(port_id=port_ids, net_id=network_id) if ((by_device and len(device_ids) != len(ports)) or (not by_device and len(port_ids) != len(ports))): raise q_exc.NotAllPortOrDeviceFound() segment_id = validate_and_fetch_segment(ports, network_id) if iptype == ip_types.SHARED: old_addresses = db_api.ip_address_find(context, network_id=network_id, tenant_id=tenant_id, address_type=ip_types.SHARED, scope=db_api.ALL) validate_shared_ips_quotas(context, network_id, old_addresses) validate_port_ip_quotas(context, network_id, ports) # Shared Ips are only new IPs. Two use cases: if we got device_id # or if we got port_ids. We should check the case where we got port_ids # and device_ids. The device_id must have a port on the network, # and any port_ids must also be on that network already. If we have # more than one port by this step, it's considered a shared IP, # and therefore will be marked as unconfigured (enabled=False) # for all ports. ipam_driver.allocate_ip_address(context, new_addresses, network_id, None, CONF.QUARK.ipam_reuse_after, version=ip_version, ip_addresses=[ip_address] if ip_address else [], segment_id=segment_id, address_type=iptype) with context.session.begin(): address = new_addresses[0] new_address = db_api.port_associate_ip(context, ports, address) return v._make_ip_dict(new_address)
def create_port(context, port): """Create a port Create a port which is a connection point of a device (e.g., a VM NIC) to attach to a L2 Neutron network. : param context: neutron api request context : param port: dictionary describing the port, with keys as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. All keys will be populated. """ LOG.info("create_port for tenant %s" % context.tenant_id) port_attrs = port["port"] admin_only = [ "mac_address", "device_owner", "bridge", "admin_state_up", "use_forbidden_mac_range", "network_plugin", "instance_node_id" ] utils.filter_body(context, port_attrs, admin_only=admin_only) port_attrs = port["port"] mac_address = utils.pop_param(port_attrs, "mac_address", None) use_forbidden_mac_range = utils.pop_param(port_attrs, "use_forbidden_mac_range", False) segment_id = utils.pop_param(port_attrs, "segment_id") fixed_ips = utils.pop_param(port_attrs, "fixed_ips") if "device_id" not in port_attrs: port_attrs['device_id'] = "" device_id = port_attrs['device_id'] # NOTE(morgabra) This should be instance.node from nova, only needed # for ironic_driver. if "instance_node_id" not in port_attrs: port_attrs['instance_node_id'] = "" instance_node_id = port_attrs['instance_node_id'] net_id = port_attrs["network_id"] port_id = uuidutils.generate_uuid() net = db_api.network_find(context=context, limit=None, sorts=['id'], marker=None, page_reverse=False, fields=None, id=net_id, scope=db_api.ONE) if not net: raise n_exc.NetworkNotFound(net_id=net_id) _raise_if_unauthorized(context, net) # NOTE (Perkins): If a device_id is given, try to prevent multiple ports # from being created for a device already attached to the network if device_id: existing_ports = db_api.port_find(context, network_id=net_id, device_id=device_id, scope=db_api.ONE) if existing_ports: raise n_exc.BadRequest( resource="port", msg="This device is already connected to the " "requested network via another port") # Try to fail early on quotas and save ourselves some db overhead if fixed_ips: quota.QUOTAS.limit_check(context, context.tenant_id, fixed_ips_per_port=len(fixed_ips)) if not STRATEGY.is_provider_network(net_id): # We don't honor segmented networks when they aren't "shared" segment_id = None port_count = db_api.port_count_all(context, network_id=[net_id], tenant_id=[context.tenant_id]) quota.QUOTAS.limit_check(context, context.tenant_id, ports_per_network=port_count + 1) else: if not segment_id: raise q_exc.AmbiguousNetworkId(net_id=net_id) network_plugin = utils.pop_param(port_attrs, "network_plugin") if not network_plugin: network_plugin = net["network_plugin"] port_attrs["network_plugin"] = network_plugin ipam_driver = _get_ipam_driver(net, port=port_attrs) net_driver = _get_net_driver(net, port=port_attrs) # NOTE(morgabra) It's possible that we select a driver different than # the one specified by the network. However, we still might need to use # this for some operations, so we also fetch it and pass it along to # the backend driver we are actually using. base_net_driver = _get_net_driver(net) # TODO(anyone): security groups are not currently supported on port create. # Please see JIRA:NCP-801 security_groups = utils.pop_param(port_attrs, "security_groups") if security_groups is not None: raise q_exc.SecurityGroupsNotImplemented() group_ids, security_groups = _make_security_group_list( context, security_groups) quota.QUOTAS.limit_check(context, context.tenant_id, security_groups_per_port=len(group_ids)) addresses = [] backend_port = None with utils.CommandManager().execute() as cmd_mgr: @cmd_mgr.do def _allocate_ips(fixed_ips, net, port_id, segment_id, mac, **kwargs): if fixed_ips: if (STRATEGY.is_provider_network(net_id) and not context.is_admin): raise n_exc.NotAuthorized() ips, subnets = split_and_validate_requested_subnets( context, net_id, segment_id, fixed_ips) kwargs["ip_addresses"] = ips kwargs["subnets"] = subnets ipam_driver.allocate_ip_address(context, addresses, net["id"], port_id, CONF.QUARK.ipam_reuse_after, segment_id=segment_id, mac_address=mac, **kwargs) @cmd_mgr.undo def _allocate_ips_undo(addr, **kwargs): LOG.info("Rolling back IP addresses...") if addresses: for address in addresses: try: with context.session.begin(): ipam_driver.deallocate_ip_address( context, address, **kwargs) except Exception: LOG.exception("Couldn't release IP %s" % address) @cmd_mgr.do def _allocate_mac(net, port_id, mac_address, use_forbidden_mac_range=False, **kwargs): mac = ipam_driver.allocate_mac_address( context, net["id"], port_id, CONF.QUARK.ipam_reuse_after, mac_address=mac_address, use_forbidden_mac_range=use_forbidden_mac_range, **kwargs) return mac @cmd_mgr.undo def _allocate_mac_undo(mac, **kwargs): LOG.info("Rolling back MAC address...") if mac: try: with context.session.begin(): ipam_driver.deallocate_mac_address( context, mac["address"]) except Exception: LOG.exception("Couldn't release MAC %s" % mac) @cmd_mgr.do def _allocate_backend_port(mac, addresses, net, port_id, **kwargs): backend_port = net_driver.create_port( context, net["id"], port_id=port_id, security_groups=group_ids, device_id=device_id, instance_node_id=instance_node_id, mac_address=mac, addresses=addresses, base_net_driver=base_net_driver) _filter_backend_port(backend_port) return backend_port @cmd_mgr.undo def _allocate_back_port_undo(backend_port, **kwargs): LOG.info("Rolling back backend port...") try: backend_port_uuid = None if backend_port: backend_port_uuid = backend_port.get("uuid") net_driver.delete_port(context, backend_port_uuid) except Exception: LOG.exception("Couldn't rollback backend port %s" % backend_port) @cmd_mgr.do def _allocate_db_port(port_attrs, backend_port, addresses, mac, **kwargs): port_attrs["network_id"] = net["id"] port_attrs["id"] = port_id port_attrs["security_groups"] = security_groups LOG.info("Including extra plugin attrs: %s" % backend_port) port_attrs.update(backend_port) with context.session.begin(): new_port = db_api.port_create(context, addresses=addresses, mac_address=mac["address"], backend_key=backend_port["uuid"], **port_attrs) return new_port @cmd_mgr.undo def _allocate_db_port_undo(new_port, **kwargs): LOG.info("Rolling back database port...") if not new_port: return try: with context.session.begin(): db_api.port_delete(context, new_port) except Exception: LOG.exception("Couldn't rollback db port %s" % backend_port) # addresses, mac, backend_port, new_port mac = _allocate_mac(net, port_id, mac_address, use_forbidden_mac_range=use_forbidden_mac_range) _allocate_ips(fixed_ips, net, port_id, segment_id, mac) backend_port = _allocate_backend_port(mac, addresses, net, port_id) new_port = _allocate_db_port(port_attrs, backend_port, addresses, mac) return v._make_port_dict(new_port)
def update_ip_policy(context, id, ip_policy): LOG.info("update_ip_policy for tenant %s" % context.tenant_id) ipp = ip_policy["ip_policy"] with context.session.begin(): ipp_db = db_api.ip_policy_find(context, id=id, scope=db_api.ONE) if not ipp_db: raise q_exc.IPPolicyNotFound(id=id) ip_policy_cidrs = ipp.get("exclude") network_ids = ipp.get("network_ids") subnet_ids = ipp.get("subnet_ids") if subnet_ids and network_ids: raise n_exc.BadRequest( resource="ip_policy", msg="network_ids and subnet_ids specified. only one allowed") models = [] all_subnets = [] if subnet_ids: for subnet in ipp_db["subnets"]: subnet["ip_policy"] = None subnets = db_api.subnet_find(context, id=subnet_ids, scope=db_api.ALL) if len(subnets) != len(subnet_ids): raise n_exc.SubnetNotFound(subnet_id=subnet_ids) if ip_policy_cidrs is not None: ensure_default_policy(ip_policy_cidrs, subnets) _validate_cidrs_fit_into_subnets(ip_policy_cidrs, subnets) all_subnets.extend(subnets) models.extend(subnets) if network_ids: for network in ipp_db["networks"]: network["ip_policy"] = None nets = db_api.network_find(context, id=network_ids, scope=db_api.ALL) if len(nets) != len(network_ids): raise n_exc.NetworkNotFound(net_id=network_ids) subnets = [ subnet for net in nets for subnet in net.get("subnets", []) ] if ip_policy_cidrs is not None: ensure_default_policy(ip_policy_cidrs, subnets) _validate_cidrs_fit_into_subnets(ip_policy_cidrs, subnets) all_subnets.extend(subnets) models.extend(nets) if not subnet_ids and not network_ids and ip_policy_cidrs is not None: ensure_default_policy(ip_policy_cidrs, ipp_db["subnets"]) _validate_cidrs_fit_into_subnets(ip_policy_cidrs, ipp_db["subnets"]) for model in models: if model["ip_policy"]: raise q_exc.IPPolicyAlreadyExists(id=model["ip_policy"]["id"], n_id=model["id"]) model["ip_policy"] = ipp_db if ip_policy_cidrs: _validate_policy_with_routes(context, ip_policy_cidrs, all_subnets) ipp_db = db_api.ip_policy_update(context, ipp_db, **ipp) return v._make_ip_policy_dict(ipp_db)
def create_ip_address(context, body): LOG.info("create_ip_address for tenant %s" % context.tenant_id) iptype = (ip_types.SHARED if _shared_ip_request(body) else ip_types.FIXED) if 'ip_address' not in body: raise n_exc.BadRequest(resource="ip_addresses", msg="Invalid request body.") if iptype == ip_types.FIXED and not CONF.QUARK.ipaddr_allow_fixed_ip: raise n_exc.BadRequest(resource="ip_addresses", msg="Only shared IPs may be made with " "this resource.") ip_dict = body.get("ip_address") port_ids = ip_dict.get('port_ids', []) network_id = ip_dict.get('network_id') device_ids = ip_dict.get('device_ids') ip_version = ip_dict.get('version') ip_address = ip_dict.get('ip_address') # If no version is passed, you would get what the network provides, # which could be both v4 and v6 addresses. Rather than allow for such # an ambiguous outcome, we'll raise instead if not ip_version: raise n_exc.BadRequest(resource="ip_addresses", msg="version is required.") if network_id is None: raise n_exc.BadRequest(resource="ip_addresses", msg="network_id is required.") if network_id == "": raise n_exc.NetworkNotFound(net_id=network_id) net = db_api.network_find(context, None, None, None, False, id=network_id, scope=db_api.ONE) if not net: raise n_exc.NetworkNotFound(net_id=network_id) if not port_ids and not device_ids: raise n_exc.BadRequest(resource="ip_addresses", msg="port_ids or device_ids required.") new_addresses = [] ports = [] by_device = False with context.session.begin(): if network_id and device_ids: by_device = True for device_id in device_ids: port = db_api.port_find(context, network_id=network_id, device_id=device_id, tenant_id=context.tenant_id, scope=db_api.ONE) if port is not None: ports.append(port) elif port_ids: for port_id in port_ids: port = db_api.port_find(context, id=port_id, tenant_id=context.tenant_id, scope=db_api.ONE) if port is not None: ports.append(port) if not ports: raise n_exc.PortNotFoundOnNetwork(port_id=port_ids, net_id=network_id) if ((by_device and len(device_ids) != len(ports)) or (not by_device and len(port_ids) != len(ports))): raise q_exc.NotAllPortOrDeviceFound() segment_id = validate_and_fetch_segment(ports, network_id) if iptype == ip_types.SHARED: old_addresses = db_api.ip_address_find(context, network_id=network_id, address_type=ip_types.SHARED, scope=db_api.ALL) validate_shared_ips_quotas(context, network_id, old_addresses) validate_port_ip_quotas(context, network_id, ports) # Shared Ips are only new IPs. Two use cases: if we got device_id # or if we got port_ids. We should check the case where we got port_ids # and device_ids. The device_id must have a port on the network, # and any port_ids must also be on that network already. If we have # more than one port by this step, it's considered a shared IP, # and therefore will be marked as unconfigured (enabled=False) # for all ports. ipam_driver.allocate_ip_address( context, new_addresses, network_id, None, CONF.QUARK.ipam_reuse_after, version=ip_version, ip_addresses=[ip_address] if ip_address else [], segment_id=segment_id, address_type=iptype) with context.session.begin(): address = new_addresses[0] new_address = db_api.port_associate_ip(context, ports, address) return v._make_ip_dict(new_address)
def create_port(context, port): """Create a port Create a port which is a connection point of a device (e.g., a VM NIC) to attach to a L2 Neutron network. : param context: neutron api request context : param port: dictionary describing the port, with keys as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. All keys will be populated. """ LOG.info("create_port for tenant %s" % context.tenant_id) port_attrs = port["port"] mac_address = utils.pop_param(port_attrs, "mac_address", None) segment_id = utils.pop_param(port_attrs, "segment_id") fixed_ips = utils.pop_param(port_attrs, "fixed_ips") net_id = port_attrs["network_id"] device_id = port_attrs["device_id"] port_id = uuidutils.generate_uuid() net = db_api.network_find(context, id=net_id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=net_id) if not STRATEGY.is_parent_network(net_id): # We don't honor segmented networks when they aren't "shared" segment_id = None port_count = db_api.port_count_all(context, network_id=[net_id], tenant_id=[context.tenant_id]) quota.QUOTAS.limit_check( context, context.tenant_id, ports_per_network=port_count + 1) else: if not segment_id: raise q_exc.AmbiguousNetworkId(net_id=net_id) ipam_driver = ipam.IPAM_REGISTRY.get_strategy(net["ipam_strategy"]) net_driver = registry.DRIVER_REGISTRY.get_driver(net["network_plugin"]) group_ids, security_groups = v.make_security_group_list( context, port["port"].pop("security_groups", None)) addresses = [] mac = None backend_port = None with utils.CommandManager().execute() as cmd_mgr: @cmd_mgr.do def _allocate_ips(fixed_ips, net, port_id, segment_id, mac): if fixed_ips: for fixed_ip in fixed_ips: subnet_id = fixed_ip.get("subnet_id") ip_address = fixed_ip.get("ip_address") if not (subnet_id and ip_address): raise exceptions.BadRequest( resource="fixed_ips", msg="subnet_id and ip_address required") ipam_driver.allocate_ip_address( context, addresses, net["id"], port_id, CONF.QUARK.ipam_reuse_after, segment_id=segment_id, ip_address=ip_address, subnets=[subnet_id], mac_address=mac) else: ipam_driver.allocate_ip_address( context, addresses, net["id"], port_id, CONF.QUARK.ipam_reuse_after, segment_id=segment_id, mac_address=mac) @cmd_mgr.undo def _allocate_ips_undo(addr): LOG.info("Rolling back IP addresses...") if addresses: for address in addresses: try: with context.session.begin(): ipam_driver.deallocate_ip_address(context, address) except Exception: LOG.exception("Couldn't release IP %s" % address) @cmd_mgr.do def _allocate_mac(net, port_id, mac_address): mac = ipam_driver.allocate_mac_address( context, net["id"], port_id, CONF.QUARK.ipam_reuse_after, mac_address=mac_address) return mac @cmd_mgr.undo def _allocate_mac_undo(mac): LOG.info("Rolling back MAC address...") if mac: try: with context.session.begin(): ipam_driver.deallocate_mac_address(context, mac["address"]) except Exception: LOG.exception("Couldn't release MAC %s" % mac) @cmd_mgr.do def _allocate_backend_port(mac, addresses, net, port_id): backend_port = net_driver.create_port(context, net["id"], port_id=port_id, security_groups=group_ids, device_id=device_id) return backend_port @cmd_mgr.undo def _allocate_back_port_undo(backend_port): LOG.info("Rolling back backend port...") try: net_driver.delete_port(context, backend_port["uuid"]) except Exception: LOG.exception( "Couldn't rollback backend port %s" % backend_port) @cmd_mgr.do def _allocate_db_port(port_attrs, backend_port, addresses, mac): port_attrs["network_id"] = net["id"] port_attrs["id"] = port_id port_attrs["security_groups"] = security_groups LOG.info("Including extra plugin attrs: %s" % backend_port) port_attrs.update(backend_port) with context.session.begin(): new_port = db_api.port_create( context, addresses=addresses, mac_address=mac["address"], backend_key=backend_port["uuid"], **port_attrs) return new_port @cmd_mgr.undo def _allocate_db_port_undo(new_port): LOG.info("Rolling back database port...") if not new_port: return try: with context.session.begin(): db_api.port_delete(context, new_port) except Exception: LOG.exception( "Couldn't rollback db port %s" % backend_port) # addresses, mac, backend_port, new_port mac = _allocate_mac(net, port_id, mac_address) _allocate_ips(fixed_ips, net, port_id, segment_id, mac) backend_port = _allocate_backend_port(mac, addresses, net, port_id) new_port = _allocate_db_port(port_attrs, backend_port, addresses, mac) return v._make_port_dict(new_port)
def create_network(context, network): """Create a network. Create a network which represents an L2 network segment which can have a set of subnets and ports associated with it. : param context: neutron api request context : param network: dictionary describing the network, with keys as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. All keys will be populated. """ LOG.info("create_network for tenant %s" % context.tenant_id) with context.session.begin(): net_attrs = network["network"] subs = net_attrs.pop("subnets", []) # Enforce subnet quotas if not context.is_admin: if len(subs) > 0: v4_count, v6_count = 0, 0 for s in subs: version = netaddr.IPNetwork(s['subnet']['cidr']).version if version == 6: v6_count += 1 else: v4_count += 1 if v4_count > 0: tenant_q_v4 = context.session.query(qdv.Quota).filter_by( tenant_id=context.tenant_id, resource='v4_subnets_per_network').first() if tenant_q_v4 != -1: quota.QUOTAS.limit_check( context, context.tenant_id, v4_subnets_per_network=v4_count) if v6_count > 0: tenant_q_v6 = context.session.query(qdv.Quota).filter_by( tenant_id=context.tenant_id, resource='v6_subnets_per_network').first() if tenant_q_v6 != -1: quota.QUOTAS.limit_check( context, context.tenant_id, v6_subnets_per_network=v6_count) # Generate a uuid that we're going to hand to the backend and db net_uuid = utils.pop_param(net_attrs, "id", None) net_type = None if net_uuid and context.is_admin: net = db_api.network_find(context=context, limit=None, sorts=['id'], marker=None, page_reverse=False, id=net_uuid, scope=db_api.ONE) net_type = utils.pop_param(net_attrs, "network_plugin", None) if net: raise q_exc.NetworkAlreadyExists(id=net_uuid) else: net_uuid = uuidutils.generate_uuid() # TODO(mdietz) this will be the first component registry hook, but # lets make it work first pnet_type, phys_net, seg_id = _adapt_provider_nets(context, network) ipam_strategy = utils.pop_param(net_attrs, "ipam_strategy", None) if not ipam_strategy or not context.is_admin: ipam_strategy = CONF.QUARK.default_ipam_strategy if not ipam.IPAM_REGISTRY.is_valid_strategy(ipam_strategy): raise q_exc.InvalidIpamStrategy(strat=ipam_strategy) net_attrs["ipam_strategy"] = ipam_strategy # NOTE(mdietz) I think ideally we would create the providernet # elsewhere as a separate driver step that could be # kept in a plugin and completely removed if desired. We could # have a pre-callback/observer on the netdriver create_network # that gathers any additional parameters from the network dict default_net_type = net_type or CONF.QUARK.default_network_type net_driver = registry.DRIVER_REGISTRY.get_driver(default_net_type) net_driver.create_network(context, net_attrs["name"], network_id=net_uuid, phys_type=pnet_type, phys_net=phys_net, segment_id=seg_id) net_attrs["id"] = net_uuid net_attrs["tenant_id"] = context.tenant_id net_attrs["network_plugin"] = default_net_type new_net = db_api.network_create(context, **net_attrs) new_subnets = [] for sub in subs: sub["subnet"]["network_id"] = new_net["id"] sub["subnet"]["tenant_id"] = context.tenant_id s = db_api.subnet_create(context, **sub["subnet"]) new_subnets.append(s) new_net["subnets"] = new_subnets # if not security_groups.get_security_groups( # context, # filters={"id": security_groups.DEFAULT_SG_UUID}): # security_groups._create_default_security_group(context) return v._make_network_dict(new_net)
def create_port(context, port): """Create a port Create a port which is a connection point of a device (e.g., a VM NIC) to attach to a L2 Neutron network. : param context: neutron api request context : param port: dictionary describing the port, with keys as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. All keys will be populated. """ LOG.info("create_port for tenant %s" % context.tenant_id) port_attrs = port["port"] mac_address = utils.pop_param(port_attrs, "mac_address", None) segment_id = utils.pop_param(port_attrs, "segment_id") fixed_ips = utils.pop_param(port_attrs, "fixed_ips") net_id = port_attrs["network_id"] addresses = [] port_id = uuidutils.generate_uuid() net = db_api.network_find(context, id=net_id, shared=True, segment_id=segment_id, scope=db_api.ONE) if not net: # Maybe it's a tenant network net = db_api.network_find(context, id=net_id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=net_id) quota.QUOTAS.limit_check(context, context.tenant_id, ports_per_network=len(net.get('ports', [])) + 1) if fixed_ips: for fixed_ip in fixed_ips: subnet_id = fixed_ip.get("subnet_id") ip_address = fixed_ip.get("ip_address") if not (subnet_id and ip_address): raise exceptions.BadRequest( resource="fixed_ips", msg="subnet_id and ip_address required") addresses.append( ipam_driver.allocate_ip_address(context, net["id"], port_id, CONF.QUARK.ipam_reuse_after, ip_address=ip_address)) else: addresses.append( ipam_driver.allocate_ip_address(context, net["id"], port_id, CONF.QUARK.ipam_reuse_after)) group_ids, security_groups = v.make_security_group_list( context, port["port"].pop("security_groups", None)) mac = ipam_driver.allocate_mac_address(context, net["id"], port_id, CONF.QUARK.ipam_reuse_after, mac_address=mac_address) mac_address_string = str( netaddr.EUI(mac['address'], dialect=netaddr.mac_unix)) address_pairs = [{ 'mac_address': mac_address_string, 'ip_address': address.get('address_readable', '') } for address in addresses] backend_port = net_driver.create_port(context, net["id"], port_id=port_id, security_groups=group_ids, allowed_pairs=address_pairs) port_attrs["network_id"] = net["id"] port_attrs["id"] = port_id port_attrs["security_groups"] = security_groups new_port = db_api.port_create(context, addresses=addresses, mac_address=mac["address"], backend_key=backend_port["uuid"], **port_attrs) return v._make_port_dict(new_port)
def create_floatingip(context, content): LOG.info("create_floatingip %s for tenant %s and body %s" % (id, context.tenant_id, content)) tenant_id = content.get("tenant_id") network_id = content.get("floating_network_id") fixed_ip_address = content.get("fixed_ip_address") ip_address = content.get("floating_ip_address") port_id = content.get("port_id") if not tenant_id: tenant_id = context.tenant_id if not network_id: raise exceptions.BadRequest(resource="floating_ip", msg="floating_network_id is required.") network = db_api.network_find(context, id=network_id, scope=db_api.ONE) if not network: raise exceptions.NetworkNotFound(net_id=network_id) fixed_ip = None port = None if port_id: port = db_api.port_find(context, id=port_id, scope=db_api.ONE) if not port: raise exceptions.PortNotFound(port_id=port_id) if not port.ip_addresses or len(port.ip_addresses) == 0: raise quark_exceptions.NoAvailableFixedIPsForPort(port_id=port_id) if not fixed_ip_address: fixed_ip = _get_next_available_fixed_ip(port) if not fixed_ip: raise quark_exceptions.NoAvailableFixedIPsForPort( port_id=port_id) else: fixed_ip = next((ip for ip in port.ip_addresses if (ip["address_readable"] == fixed_ip_address and ip.get("address_type") == ip_types.FIXED)), None) if not fixed_ip: raise quark_exceptions.FixedIpDoesNotExistsForPort( fixed_ip=fixed_ip_address, port_id=port_id) if any(ip for ip in port.ip_addresses if (ip.get("address_type") == ip_types.FLOATING and ip.fixed_ip["address_readable"] == fixed_ip_address)): raise quark_exceptions.PortAlreadyContainsFloatingIp( port_id=port_id) new_addresses = [] ip_addresses = [] if ip_address: ip_addresses.append(ip_address) seg_name = CONF.QUARK.floating_ip_segment_name strategy_name = network.get("ipam_strategy") ipam_driver = ipam.IPAM_REGISTRY.get_strategy(strategy_name) ipam_driver.allocate_ip_address(context, new_addresses, network_id, port_id, CONF.QUARK.ipam_reuse_after, seg_name, version=4, ip_addresses=ip_addresses, address_type=ip_types.FLOATING) floating_ip = new_addresses[0] if fixed_ip and port: with context.session.begin(): floating_ip = db_api.floating_ip_associate_fixed_ip(context, floating_ip, fixed_ip) flip_driver_type = CONF.QUARK.default_floating_ip_driver flip_driver = registry.DRIVER_REGISTRY.get_driver(flip_driver_type) flip_driver.register_floating_ip(floating_ip, port, fixed_ip) return v._make_floating_ip_dict(floating_ip)
def _get_network(context, network_id): network = db_api.network_find(context, id=network_id, scope=db_api.ONE) if not network: raise n_exc.NetworkNotFound(net_id=network_id) return network
def create_port(context, port): """Create a port Create a port which is a connection point of a device (e.g., a VM NIC) to attach to a L2 Neutron network. : param context: neutron api request context : param port: dictionary describing the port, with keys as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. All keys will be populated. """ LOG.info("create_port for tenant %s" % context.tenant_id) port_attrs = port["port"] admin_only = ["mac_address", "device_owner", "bridge", "admin_state_up", "use_forbidden_mac_range", "network_plugin", "instance_node_id"] utils.filter_body(context, port_attrs, admin_only=admin_only) port_attrs = port["port"] mac_address = utils.pop_param(port_attrs, "mac_address", None) use_forbidden_mac_range = utils.pop_param(port_attrs, "use_forbidden_mac_range", False) segment_id = utils.pop_param(port_attrs, "segment_id") fixed_ips = utils.pop_param(port_attrs, "fixed_ips") if "device_id" not in port_attrs: port_attrs['device_id'] = "" device_id = port_attrs['device_id'] # NOTE(morgabra) This should be instance.node from nova, only needed # for ironic_driver. if "instance_node_id" not in port_attrs: port_attrs['instance_node_id'] = "" instance_node_id = port_attrs['instance_node_id'] net_id = port_attrs["network_id"] port_id = uuidutils.generate_uuid() net = db_api.network_find(context=context, limit=None, sorts=['id'], marker=None, page_reverse=False, fields=None, id=net_id, scope=db_api.ONE) if not net: raise n_exc.NetworkNotFound(net_id=net_id) _raise_if_unauthorized(context, net) # NOTE (Perkins): If a device_id is given, try to prevent multiple ports # from being created for a device already attached to the network if device_id: existing_ports = db_api.port_find(context, network_id=net_id, device_id=device_id, scope=db_api.ONE) if existing_ports: raise n_exc.BadRequest( resource="port", msg="This device is already connected to the " "requested network via another port") # Try to fail early on quotas and save ourselves some db overhead if fixed_ips: quota.QUOTAS.limit_check(context, context.tenant_id, fixed_ips_per_port=len(fixed_ips)) if not STRATEGY.is_provider_network(net_id): # We don't honor segmented networks when they aren't "shared" segment_id = None port_count = db_api.port_count_all(context, network_id=[net_id], tenant_id=[context.tenant_id]) quota.QUOTAS.limit_check( context, context.tenant_id, ports_per_network=port_count + 1) else: if not segment_id: raise q_exc.AmbiguousNetworkId(net_id=net_id) network_plugin = utils.pop_param(port_attrs, "network_plugin") if not network_plugin: network_plugin = net["network_plugin"] port_attrs["network_plugin"] = network_plugin ipam_driver = _get_ipam_driver(net, port=port_attrs) net_driver = _get_net_driver(net, port=port_attrs) # NOTE(morgabra) It's possible that we select a driver different than # the one specified by the network. However, we still might need to use # this for some operations, so we also fetch it and pass it along to # the backend driver we are actually using. base_net_driver = _get_net_driver(net) # TODO(anyone): security groups are not currently supported on port create. # Please see JIRA:NCP-801 security_groups = utils.pop_param(port_attrs, "security_groups") if security_groups is not None: raise q_exc.SecurityGroupsNotImplemented() group_ids, security_groups = _make_security_group_list(context, security_groups) quota.QUOTAS.limit_check(context, context.tenant_id, security_groups_per_port=len(group_ids)) addresses = [] backend_port = None with utils.CommandManager().execute() as cmd_mgr: @cmd_mgr.do def _allocate_ips(fixed_ips, net, port_id, segment_id, mac, **kwargs): if fixed_ips: if (STRATEGY.is_provider_network(net_id) and not context.is_admin): raise n_exc.NotAuthorized() ips, subnets = split_and_validate_requested_subnets(context, net_id, segment_id, fixed_ips) kwargs["ip_addresses"] = ips kwargs["subnets"] = subnets ipam_driver.allocate_ip_address( context, addresses, net["id"], port_id, CONF.QUARK.ipam_reuse_after, segment_id=segment_id, mac_address=mac, **kwargs) @cmd_mgr.undo def _allocate_ips_undo(addr, **kwargs): LOG.info("Rolling back IP addresses...") if addresses: for address in addresses: try: with context.session.begin(): ipam_driver.deallocate_ip_address(context, address, **kwargs) except Exception: LOG.exception("Couldn't release IP %s" % address) @cmd_mgr.do def _allocate_mac(net, port_id, mac_address, use_forbidden_mac_range=False, **kwargs): mac = ipam_driver.allocate_mac_address( context, net["id"], port_id, CONF.QUARK.ipam_reuse_after, mac_address=mac_address, use_forbidden_mac_range=use_forbidden_mac_range, **kwargs) return mac @cmd_mgr.undo def _allocate_mac_undo(mac, **kwargs): LOG.info("Rolling back MAC address...") if mac: try: with context.session.begin(): ipam_driver.deallocate_mac_address(context, mac["address"]) except Exception: LOG.exception("Couldn't release MAC %s" % mac) @cmd_mgr.do def _allocate_backend_port(mac, addresses, net, port_id, **kwargs): backend_port = net_driver.create_port( context, net["id"], port_id=port_id, security_groups=group_ids, device_id=device_id, instance_node_id=instance_node_id, mac_address=mac, addresses=addresses, base_net_driver=base_net_driver) _filter_backend_port(backend_port) return backend_port @cmd_mgr.undo def _allocate_back_port_undo(backend_port, **kwargs): LOG.info("Rolling back backend port...") try: backend_port_uuid = None if backend_port: backend_port_uuid = backend_port.get("uuid") net_driver.delete_port(context, backend_port_uuid) except Exception: LOG.exception( "Couldn't rollback backend port %s" % backend_port) @cmd_mgr.do def _allocate_db_port(port_attrs, backend_port, addresses, mac, **kwargs): port_attrs["network_id"] = net["id"] port_attrs["id"] = port_id port_attrs["security_groups"] = security_groups LOG.info("Including extra plugin attrs: %s" % backend_port) port_attrs.update(backend_port) with context.session.begin(): new_port = db_api.port_create( context, addresses=addresses, mac_address=mac["address"], backend_key=backend_port["uuid"], **port_attrs) return new_port @cmd_mgr.undo def _allocate_db_port_undo(new_port, **kwargs): LOG.info("Rolling back database port...") if not new_port: return try: with context.session.begin(): db_api.port_delete(context, new_port) except Exception: LOG.exception( "Couldn't rollback db port %s" % backend_port) # addresses, mac, backend_port, new_port mac = _allocate_mac(net, port_id, mac_address, use_forbidden_mac_range=use_forbidden_mac_range) _allocate_ips(fixed_ips, net, port_id, segment_id, mac) backend_port = _allocate_backend_port(mac, addresses, net, port_id) new_port = _allocate_db_port(port_attrs, backend_port, addresses, mac) return v._make_port_dict(new_port)
def create_network(context, network): """Create a network. Create a network which represents an L2 network segment which can have a set of subnets and ports associated with it. : param context: neutron api request context : param network: dictionary describing the network, with keys as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. All keys will be populated. """ LOG.info("create_network for tenant %s" % context.tenant_id) with context.session.begin(): net_attrs = network["network"] subs = net_attrs.pop("subnets", []) # Enforce subnet quotas if not context.is_admin: if len(subs) > 0: v4_count, v6_count = 0, 0 for s in subs: version = netaddr.IPNetwork(s['subnet']['cidr']).version if version == 6: v6_count += 1 else: v4_count += 1 if v4_count > 0: tenant_q_v4 = context.session.query(qdb.Quota).filter_by( tenant_id=context.tenant_id, resource='v4_subnets_per_network').first() if tenant_q_v4 != -1: quota.QUOTAS.limit_check( context, context.tenant_id, v4_subnets_per_network=v4_count) if v6_count > 0: tenant_q_v6 = context.session.query(qdb.Quota).filter_by( tenant_id=context.tenant_id, resource='v6_subnets_per_network').first() if tenant_q_v6 != -1: quota.QUOTAS.limit_check( context, context.tenant_id, v6_subnets_per_network=v6_count) # Generate a uuid that we're going to hand to the backend and db net_uuid = utils.pop_param(net_attrs, "id", None) net_type = None if net_uuid and context.is_admin: net = db_api.network_find(context, id=net_uuid, scope=db_api.ONE) net_type = utils.pop_param(net_attrs, "network_plugin", None) if net: raise q_exc.NetworkAlreadyExists(id=net_uuid) else: net_uuid = uuidutils.generate_uuid() # TODO(mdietz) this will be the first component registry hook, but # lets make it work first pnet_type, phys_net, seg_id = _adapt_provider_nets(context, network) ipam_strategy = utils.pop_param(net_attrs, "ipam_strategy", None) if not ipam_strategy or not context.is_admin: ipam_strategy = CONF.QUARK.default_ipam_strategy if not ipam.IPAM_REGISTRY.is_valid_strategy(ipam_strategy): raise q_exc.InvalidIpamStrategy(strat=ipam_strategy) net_attrs["ipam_strategy"] = ipam_strategy # NOTE(mdietz) I think ideally we would create the providernet # elsewhere as a separate driver step that could be # kept in a plugin and completely removed if desired. We could # have a pre-callback/observer on the netdriver create_network # that gathers any additional parameters from the network dict default_net_type = net_type or CONF.QUARK.default_network_type net_driver = registry.DRIVER_REGISTRY.get_driver(default_net_type) net_driver.create_network(context, net_attrs["name"], network_id=net_uuid, phys_type=pnet_type, phys_net=phys_net, segment_id=seg_id) net_attrs["id"] = net_uuid net_attrs["tenant_id"] = context.tenant_id net_attrs["network_plugin"] = default_net_type new_net = db_api.network_create(context, **net_attrs) new_subnets = [] for sub in subs: sub["subnet"]["network_id"] = new_net["id"] sub["subnet"]["tenant_id"] = context.tenant_id s = db_api.subnet_create(context, **sub["subnet"]) new_subnets.append(s) new_net["subnets"] = new_subnets # if not security_groups.get_security_groups( # context, # filters={"id": security_groups.DEFAULT_SG_UUID}): # security_groups._create_default_security_group(context) return v._make_network_dict(new_net)
def create_subnet(context, subnet): """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. """ LOG.info("create_subnet for tenant %s" % context.tenant_id) net_id = subnet["subnet"]["network_id"] with context.session.begin(): net = db_api.network_find(context, None, None, None, False, id=net_id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=net_id) sub_attrs = subnet["subnet"] always_pop = [ "enable_dhcp", "ip_version", "first_ip", "last_ip", "_cidr" ] admin_only = [ "segment_id", "do_not_use", "created_at", "next_auto_assign_ip" ] utils.filter_body(context, sub_attrs, admin_only, always_pop) _validate_subnet_cidr(context, net_id, sub_attrs["cidr"]) cidr = netaddr.IPNetwork(sub_attrs["cidr"]) err_vals = {'cidr': sub_attrs["cidr"], 'network_id': net_id} err = _("Requested subnet with cidr: %(cidr)s for " "network: %(network_id)s. Prefix is too small, must be a " "larger subnet. A prefix less than /%(prefix)s is required.") if cidr.version == 6 and cidr.prefixlen > 64: err_vals["prefix"] = 65 err_msg = err % err_vals raise exceptions.InvalidInput(error_message=err_msg) elif cidr.version == 4 and cidr.prefixlen > 30: err_vals["prefix"] = 31 err_msg = err % err_vals raise exceptions.InvalidInput(error_message=err_msg) # Enforce subnet quotas net_subnets = get_subnets(context, filters=dict(network_id=net_id)) if not context.is_admin: v4_count, v6_count = 0, 0 for subnet in net_subnets: if netaddr.IPNetwork(subnet['cidr']).version == 6: v6_count += 1 else: v4_count += 1 if cidr.version == 6: tenant_quota_v6 = context.session.query(qdv.Quota).filter_by( tenant_id=context.tenant_id, resource='v6_subnets_per_network').first() if tenant_quota_v6 != -1: quota.QUOTAS.limit_check(context, context.tenant_id, v6_subnets_per_network=v6_count + 1) else: tenant_quota_v4 = context.session.query(qdv.Quota).filter_by( tenant_id=context.tenant_id, resource='v4_subnets_per_network').first() if tenant_quota_v4 != -1: quota.QUOTAS.limit_check(context, context.tenant_id, v4_subnets_per_network=v4_count + 1) # See RM981. The default behavior of setting a gateway unless # explicitly asked to not is no longer desirable. gateway_ip = utils.pop_param(sub_attrs, "gateway_ip") dns_ips = utils.pop_param(sub_attrs, "dns_nameservers", []) host_routes = utils.pop_param(sub_attrs, "host_routes", []) allocation_pools = utils.pop_param(sub_attrs, "allocation_pools", None) sub_attrs["network"] = net new_subnet = db_api.subnet_create(context, **sub_attrs) cidrs = [] alloc_pools = allocation_pool.AllocationPools(sub_attrs["cidr"], allocation_pools) if isinstance(allocation_pools, list): cidrs = alloc_pools.get_policy_cidrs() quota.QUOTAS.limit_check(context, context.tenant_id, alloc_pools_per_subnet=len(alloc_pools)) ip_policies.ensure_default_policy(cidrs, [new_subnet]) new_subnet["ip_policy"] = db_api.ip_policy_create(context, exclude=cidrs) quota.QUOTAS.limit_check(context, context.tenant_id, routes_per_subnet=len(host_routes)) default_route = None for route in host_routes: netaddr_route = netaddr.IPNetwork(route["destination"]) if netaddr_route.value == routes.DEFAULT_ROUTE.value: if default_route: raise q_exc.DuplicateRouteConflict( subnet_id=new_subnet["id"]) default_route = route gateway_ip = default_route["nexthop"] alloc_pools.validate_gateway_excluded(gateway_ip) new_subnet["routes"].append( db_api.route_create(context, cidr=route["destination"], gateway=route["nexthop"])) quota.QUOTAS.limit_check(context, context.tenant_id, dns_nameservers_per_subnet=len(dns_ips)) for dns_ip in dns_ips: new_subnet["dns_nameservers"].append( db_api.dns_create(context, ip=netaddr.IPAddress(dns_ip))) # if the gateway_ip is IN the cidr for the subnet and NOT excluded by # policies, we should raise a 409 conflict if gateway_ip and default_route is None: alloc_pools.validate_gateway_excluded(gateway_ip) new_subnet["routes"].append( db_api.route_create(context, cidr=str(routes.DEFAULT_ROUTE), gateway=gateway_ip)) subnet_dict = v._make_subnet_dict(new_subnet) subnet_dict["gateway_ip"] = gateway_ip n_rpc.get_notifier("network").info( context, "ip_block.create", dict(tenant_id=subnet_dict["tenant_id"], ip_block_id=subnet_dict["id"], created_at=new_subnet["created_at"])) return subnet_dict
def create_subnet(context, subnet): """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. """ LOG.info("create_subnet for tenant %s" % context.tenant_id) net_id = subnet["subnet"]["network_id"] with context.session.begin(): net = db_api.network_find(context, None, None, None, False, id=net_id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=net_id) sub_attrs = subnet["subnet"] always_pop = ["enable_dhcp", "ip_version", "first_ip", "last_ip", "_cidr"] admin_only = ["segment_id", "do_not_use", "created_at", "next_auto_assign_ip"] utils.filter_body(context, sub_attrs, admin_only, always_pop) _validate_subnet_cidr(context, net_id, sub_attrs["cidr"]) cidr = netaddr.IPNetwork(sub_attrs["cidr"]) err_vals = {'cidr': sub_attrs["cidr"], 'network_id': net_id} err = _("Requested subnet with cidr: %(cidr)s for " "network: %(network_id)s. Prefix is too small, must be a " "larger subnet. A prefix less than /%(prefix)s is required.") if cidr.version == 6 and cidr.prefixlen > 64: err_vals["prefix"] = 65 err_msg = err % err_vals raise exceptions.InvalidInput(error_message=err_msg) elif cidr.version == 4 and cidr.prefixlen > 30: err_vals["prefix"] = 31 err_msg = err % err_vals raise exceptions.InvalidInput(error_message=err_msg) # Enforce subnet quotas net_subnets = get_subnets(context, filters=dict(network_id=net_id)) if not context.is_admin: v4_count, v6_count = 0, 0 for subnet in net_subnets: if netaddr.IPNetwork(subnet['cidr']).version == 6: v6_count += 1 else: v4_count += 1 if cidr.version == 6: tenant_quota_v6 = context.session.query(qdv.Quota).filter_by( tenant_id=context.tenant_id, resource='v6_subnets_per_network').first() if tenant_quota_v6 != -1: quota.QUOTAS.limit_check( context, context.tenant_id, v6_subnets_per_network=v6_count + 1) else: tenant_quota_v4 = context.session.query(qdv.Quota).filter_by( tenant_id=context.tenant_id, resource='v4_subnets_per_network').first() if tenant_quota_v4 != -1: quota.QUOTAS.limit_check( context, context.tenant_id, v4_subnets_per_network=v4_count + 1) # See RM981. The default behavior of setting a gateway unless # explicitly asked to not is no longer desirable. gateway_ip = utils.pop_param(sub_attrs, "gateway_ip") dns_ips = utils.pop_param(sub_attrs, "dns_nameservers", []) host_routes = utils.pop_param(sub_attrs, "host_routes", []) allocation_pools = utils.pop_param(sub_attrs, "allocation_pools", None) sub_attrs["network"] = net new_subnet = db_api.subnet_create(context, **sub_attrs) cidrs = [] alloc_pools = allocation_pool.AllocationPools(sub_attrs["cidr"], allocation_pools) if isinstance(allocation_pools, list): cidrs = alloc_pools.get_policy_cidrs() quota.QUOTAS.limit_check( context, context.tenant_id, alloc_pools_per_subnet=len(alloc_pools)) ip_policies.ensure_default_policy(cidrs, [new_subnet]) new_subnet["ip_policy"] = db_api.ip_policy_create(context, exclude=cidrs) quota.QUOTAS.limit_check(context, context.tenant_id, routes_per_subnet=len(host_routes)) default_route = None for route in host_routes: netaddr_route = netaddr.IPNetwork(route["destination"]) if netaddr_route.value == routes.DEFAULT_ROUTE.value: if default_route: raise q_exc.DuplicateRouteConflict( subnet_id=new_subnet["id"]) default_route = route gateway_ip = default_route["nexthop"] alloc_pools.validate_gateway_excluded(gateway_ip) new_subnet["routes"].append(db_api.route_create( context, cidr=route["destination"], gateway=route["nexthop"])) quota.QUOTAS.limit_check(context, context.tenant_id, dns_nameservers_per_subnet=len(dns_ips)) for dns_ip in dns_ips: new_subnet["dns_nameservers"].append(db_api.dns_create( context, ip=netaddr.IPAddress(dns_ip))) # if the gateway_ip is IN the cidr for the subnet and NOT excluded by # policies, we should raise a 409 conflict if gateway_ip and default_route is None: alloc_pools.validate_gateway_excluded(gateway_ip) new_subnet["routes"].append(db_api.route_create( context, cidr=str(routes.DEFAULT_ROUTE), gateway=gateway_ip)) subnet_dict = v._make_subnet_dict(new_subnet) subnet_dict["gateway_ip"] = gateway_ip n_rpc.get_notifier("network").info( context, "ip_block.create", dict(tenant_id=subnet_dict["tenant_id"], ip_block_id=subnet_dict["id"], created_at=new_subnet["created_at"])) return subnet_dict
def create_port(context, port): """Create a port Create a port which is a connection point of a device (e.g., a VM NIC) to attach to a L2 Neutron network. : param context: neutron api request context : param port: dictionary describing the port, with keys as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. All keys will be populated. """ LOG.info("create_port for tenant %s" % context.tenant_id) port_attrs = port["port"] admin_only = ["mac_address", "device_owner", "bridge", "admin_state_up"] utils.filter_body(context, port_attrs, admin_only=admin_only) port_attrs = port["port"] mac_address = utils.pop_param(port_attrs, "mac_address", None) segment_id = utils.pop_param(port_attrs, "segment_id") fixed_ips = utils.pop_param(port_attrs, "fixed_ips") net_id = port_attrs["network_id"] device_id = port_attrs["device_id"] port_id = uuidutils.generate_uuid() net = db_api.network_find(context, id=net_id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=net_id) # NOTE (Perkins): If a device_id is given, try to prevent multiple ports # from being created for a device already attached to the network if device_id: existing_ports = db_api.port_find(context, network_id=net_id, device_id=device_id, scope=db_api.ONE) if existing_ports: raise exceptions.BadRequest( resource="port", msg="This device is already connected to the " "requested network via another port") if not STRATEGY.is_parent_network(net_id): # We don't honor segmented networks when they aren't "shared" segment_id = None port_count = db_api.port_count_all(context, network_id=[net_id], tenant_id=[context.tenant_id]) quota.QUOTAS.limit_check(context, context.tenant_id, ports_per_network=port_count + 1) else: if not segment_id: raise q_exc.AmbiguousNetworkId(net_id=net_id) ipam_driver = ipam.IPAM_REGISTRY.get_strategy(net["ipam_strategy"]) net_driver = registry.DRIVER_REGISTRY.get_driver(net["network_plugin"]) group_ids, security_groups = v.make_security_group_list( context, port["port"].pop("security_groups", None)) addresses = [] mac = None backend_port = None with utils.CommandManager().execute() as cmd_mgr: @cmd_mgr.do def _allocate_ips(fixed_ips, net, port_id, segment_id, mac): if fixed_ips: for fixed_ip in fixed_ips: subnet_id = fixed_ip.get("subnet_id") ip_address = fixed_ip.get("ip_address") if not (subnet_id and ip_address): raise exceptions.BadRequest( resource="fixed_ips", msg="subnet_id and ip_address required") ipam_driver.allocate_ip_address( context, addresses, net["id"], port_id, CONF.QUARK.ipam_reuse_after, segment_id=segment_id, ip_address=ip_address, subnets=[subnet_id], mac_address=mac) else: ipam_driver.allocate_ip_address(context, addresses, net["id"], port_id, CONF.QUARK.ipam_reuse_after, segment_id=segment_id, mac_address=mac) @cmd_mgr.undo def _allocate_ips_undo(addr): LOG.info("Rolling back IP addresses...") if addresses: for address in addresses: try: with context.session.begin(): ipam_driver.deallocate_ip_address(context, address) except Exception: LOG.exception("Couldn't release IP %s" % address) @cmd_mgr.do def _allocate_mac(net, port_id, mac_address): mac = ipam_driver.allocate_mac_address(context, net["id"], port_id, CONF.QUARK.ipam_reuse_after, mac_address=mac_address) return mac @cmd_mgr.undo def _allocate_mac_undo(mac): LOG.info("Rolling back MAC address...") if mac: try: with context.session.begin(): ipam_driver.deallocate_mac_address( context, mac["address"]) except Exception: LOG.exception("Couldn't release MAC %s" % mac) @cmd_mgr.do def _allocate_backend_port(mac, addresses, net, port_id): backend_port = net_driver.create_port(context, net["id"], port_id=port_id, security_groups=group_ids, device_id=device_id) return backend_port @cmd_mgr.undo def _allocate_back_port_undo(backend_port): LOG.info("Rolling back backend port...") try: net_driver.delete_port(context, backend_port["uuid"]) except Exception: LOG.exception("Couldn't rollback backend port %s" % backend_port) @cmd_mgr.do def _allocate_db_port(port_attrs, backend_port, addresses, mac): port_attrs["network_id"] = net["id"] port_attrs["id"] = port_id port_attrs["security_groups"] = security_groups LOG.info("Including extra plugin attrs: %s" % backend_port) port_attrs.update(backend_port) with context.session.begin(): new_port = db_api.port_create(context, addresses=addresses, mac_address=mac["address"], backend_key=backend_port["uuid"], **port_attrs) return new_port @cmd_mgr.undo def _allocate_db_port_undo(new_port): LOG.info("Rolling back database port...") if not new_port: return try: with context.session.begin(): db_api.port_delete(context, new_port) except Exception: LOG.exception("Couldn't rollback db port %s" % backend_port) # addresses, mac, backend_port, new_port mac = _allocate_mac(net, port_id, mac_address) _allocate_ips(fixed_ips, net, port_id, segment_id, mac) backend_port = _allocate_backend_port(mac, addresses, net, port_id) new_port = _allocate_db_port(port_attrs, backend_port, addresses, mac) return v._make_port_dict(new_port)
def create_port(context, port): """Create a port Create a port which is a connection point of a device (e.g., a VM NIC) to attach to a L2 Neutron network. : param context: neutron api request context : param port: dictionary describing the port, with keys as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. All keys will be populated. """ LOG.info("create_port for tenant %s" % context.tenant_id) port_attrs = port["port"] mac_address = utils.pop_param(port_attrs, "mac_address", None) segment_id = utils.pop_param(port_attrs, "segment_id") fixed_ips = utils.pop_param(port_attrs, "fixed_ips") net_id = port_attrs["network_id"] addresses = [] port_id = uuidutils.generate_uuid() net = db_api.network_find(context, id=net_id, shared=True, segment_id=segment_id, scope=db_api.ONE) if not net: # Maybe it's a tenant network net = db_api.network_find(context, id=net_id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=net_id) quota.QUOTAS.limit_check( context, context.tenant_id, ports_per_network=len(net.get('ports', [])) + 1) if fixed_ips: for fixed_ip in fixed_ips: subnet_id = fixed_ip.get("subnet_id") ip_address = fixed_ip.get("ip_address") if not (subnet_id and ip_address): raise exceptions.BadRequest( resource="fixed_ips", msg="subnet_id and ip_address required") addresses.append(ipam_driver.allocate_ip_address( context, net["id"], port_id, CONF.QUARK.ipam_reuse_after, ip_address=ip_address)) else: addresses.append(ipam_driver.allocate_ip_address( context, net["id"], port_id, CONF.QUARK.ipam_reuse_after)) group_ids, security_groups = v.make_security_group_list( context, port["port"].pop("security_groups", None)) mac = ipam_driver.allocate_mac_address(context, net["id"], port_id, CONF.QUARK.ipam_reuse_after, mac_address=mac_address) mac_address_string = str(netaddr.EUI(mac['address'], dialect=netaddr.mac_unix)) address_pairs = [{'mac_address': mac_address_string, 'ip_address': address.get('address_readable', '')} for address in addresses] backend_port = net_driver.create_port(context, net["id"], port_id=port_id, security_groups=group_ids, allowed_pairs=address_pairs) port_attrs["network_id"] = net["id"] port_attrs["id"] = port_id port_attrs["security_groups"] = security_groups new_port = db_api.port_create( context, addresses=addresses, mac_address=mac["address"], backend_key=backend_port["uuid"], **port_attrs) return v._make_port_dict(new_port)
def _get_ipam_driver_for_network(context, net_id): return ipam.IPAM_REGISTRY.get_strategy(db_api.network_find( context, id=net_id, scope=db_api.ONE)['ipam_strategy'])
def create_floatingip(context, content): """Allocate or reallocate a floating IP. :param context: neutron api request context. :param content: dictionary describing the floating ip, with keys as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. All keys will be populated. :returns: Dictionary containing details for the new floating IP. If values are declared in the fields parameter, then only those keys will be present. """ LOG.info('create_floatingip %s for tenant %s and body %s' % (id, context.tenant_id, content)) tenant_id = content.get('tenant_id') network_id = content.get('floating_network_id') fixed_ip_address = content.get('fixed_ip_address') ip_address = content.get('floating_ip_address') port_id = content.get('port_id') if not tenant_id: tenant_id = context.tenant_id if not network_id: raise exceptions.BadRequest(resource='floating_ip', msg='floating_network_id is required.') network = db_api.network_find(context, id=network_id, scope=db_api.ONE) if not network: raise exceptions.NetworkNotFound(net_id=network_id) fixed_ip = None port = None if port_id: port = db_api.port_find(context, id=port_id, scope=db_api.ONE) if not port: raise exceptions.PortNotFound(port_id=port_id) if not port.ip_addresses or len(port.ip_addresses) == 0: raise qex.NoAvailableFixedIPsForPort(port_id=port_id) if not fixed_ip_address: fixed_ip = _get_next_available_fixed_ip(port) if not fixed_ip: raise qex.NoAvailableFixedIPsForPort( port_id=port_id) else: fixed_ip = next((ip for ip in port.ip_addresses if (ip['address_readable'] == fixed_ip_address and ip.get('address_type') == ip_types.FIXED)), None) if not fixed_ip: raise qex.FixedIpDoesNotExistsForPort( fixed_ip=fixed_ip_address, port_id=port_id) if any(ip for ip in port.ip_addresses if (ip.get('address_type') == ip_types.FLOATING and ip.fixed_ip['address_readable'] == fixed_ip_address)): raise qex.PortAlreadyContainsFloatingIp( port_id=port_id) new_addresses = [] ip_addresses = [] if ip_address: ip_addresses.append(ip_address) seg_name = CONF.QUARK.floating_ip_segment_name strategy_name = CONF.QUARK.floating_ip_ipam_strategy if strategy_name.upper() == 'NETWORK': strategy_name = network.get("ipam_strategy") ipam_driver = ipam.IPAM_REGISTRY.get_strategy(strategy_name) ipam_driver.allocate_ip_address(context, new_addresses, network_id, port_id, CONF.QUARK.ipam_reuse_after, seg_name, version=4, ip_addresses=ip_addresses, address_type=ip_types.FLOATING) flip = new_addresses[0] if fixed_ip and port: with context.session.begin(): flip = db_api.port_associate_ip(context, [port], flip, [port_id]) flip = db_api.floating_ip_associate_fixed_ip(context, flip, fixed_ip) flip_driver = registry.DRIVER_REGISTRY.get_driver() flip_driver.register_floating_ip(flip, port, fixed_ip) return v._make_floating_ip_dict(flip, port_id)
def create_port(context, port): """Create a port Create a port which is a connection point of a device (e.g., a VM NIC) to attach to a L2 Neutron network. : param context: neutron api request context : param port: dictionary describing the port, with keys as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. All keys will be populated. """ LOG.info("create_port for tenant %s" % context.tenant_id) port_attrs = port["port"] admin_only = ["mac_address", "device_owner", "bridge", "admin_state_up", "use_forbidden_mac_range"] utils.filter_body(context, port_attrs, admin_only=admin_only) port_attrs = port["port"] mac_address = utils.pop_param(port_attrs, "mac_address", None) use_forbidden_mac_range = utils.pop_param(port_attrs, "use_forbidden_mac_range", False) segment_id = utils.pop_param(port_attrs, "segment_id") fixed_ips = utils.pop_param(port_attrs, "fixed_ips") if "device_id" not in port_attrs: port_attrs['device_id'] = "" device_id = port_attrs['device_id'] net_id = port_attrs["network_id"] port_id = uuidutils.generate_uuid() net = db_api.network_find(context, None, None, None, False, id=net_id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=net_id) _raise_if_unauthorized(context.tenant_id, net) # NOTE (Perkins): If a device_id is given, try to prevent multiple ports # from being created for a device already attached to the network if device_id: existing_ports = db_api.port_find(context, network_id=net_id, device_id=device_id, scope=db_api.ONE) if existing_ports: raise exceptions.BadRequest( resource="port", msg="This device is already connected to the " "requested network via another port") # Try to fail early on quotas and save ourselves some db overhead if fixed_ips: quota.QUOTAS.limit_check(context, context.tenant_id, fixed_ips_per_port=len(fixed_ips)) if not STRATEGY.is_parent_network(net_id): # We don't honor segmented networks when they aren't "shared" segment_id = None port_count = db_api.port_count_all(context, network_id=[net_id], tenant_id=[context.tenant_id]) quota.QUOTAS.limit_check( context, context.tenant_id, ports_per_network=port_count + 1) else: if not segment_id: raise q_exc.AmbiguousNetworkId(net_id=net_id) ipam_driver = ipam.IPAM_REGISTRY.get_strategy(net["ipam_strategy"]) net_driver = registry.DRIVER_REGISTRY.get_driver(net["network_plugin"]) # TODO(anyone): security groups are not currently supported on port create, # nor on isolated networks today. Please see RM8615 security_groups = utils.pop_param(port_attrs, "security_groups") if security_groups is not None: raise q_exc.SecurityGroupsNotImplemented() group_ids, security_groups = _make_security_group_list(context, security_groups) quota.QUOTAS.limit_check(context, context.tenant_id, security_groups_per_port=len(group_ids)) addresses = [] backend_port = None with utils.CommandManager().execute() as cmd_mgr: @cmd_mgr.do def _allocate_ips(fixed_ips, net, port_id, segment_id, mac): fixed_ip_kwargs = {} if fixed_ips: if STRATEGY.is_parent_network(net_id) and not context.is_admin: raise exceptions.NotAuthorized() ips, subnets = split_and_validate_requested_subnets(context, net_id, segment_id, fixed_ips) fixed_ip_kwargs["ip_addresses"] = ips fixed_ip_kwargs["subnets"] = subnets ipam_driver.allocate_ip_address( context, addresses, net["id"], port_id, CONF.QUARK.ipam_reuse_after, segment_id=segment_id, mac_address=mac, **fixed_ip_kwargs) @cmd_mgr.undo def _allocate_ips_undo(addr): LOG.info("Rolling back IP addresses...") if addresses: for address in addresses: try: with context.session.begin(): ipam_driver.deallocate_ip_address(context, address) except Exception: LOG.exception("Couldn't release IP %s" % address) @cmd_mgr.do def _allocate_mac(net, port_id, mac_address, use_forbidden_mac_range=False): mac = ipam_driver.allocate_mac_address( context, net["id"], port_id, CONF.QUARK.ipam_reuse_after, mac_address=mac_address, use_forbidden_mac_range=use_forbidden_mac_range) return mac @cmd_mgr.undo def _allocate_mac_undo(mac): LOG.info("Rolling back MAC address...") if mac: try: with context.session.begin(): ipam_driver.deallocate_mac_address(context, mac["address"]) except Exception: LOG.exception("Couldn't release MAC %s" % mac) @cmd_mgr.do def _allocate_backend_port(mac, addresses, net, port_id): backend_port = net_driver.create_port(context, net["id"], port_id=port_id, security_groups=group_ids, device_id=device_id) return backend_port @cmd_mgr.undo def _allocate_back_port_undo(backend_port): LOG.info("Rolling back backend port...") try: net_driver.delete_port(context, backend_port["uuid"]) except Exception: LOG.exception( "Couldn't rollback backend port %s" % backend_port) @cmd_mgr.do def _allocate_db_port(port_attrs, backend_port, addresses, mac): port_attrs["network_id"] = net["id"] port_attrs["id"] = port_id port_attrs["security_groups"] = security_groups LOG.info("Including extra plugin attrs: %s" % backend_port) port_attrs.update(backend_port) with context.session.begin(): new_port = db_api.port_create( context, addresses=addresses, mac_address=mac["address"], backend_key=backend_port["uuid"], **port_attrs) return new_port @cmd_mgr.undo def _allocate_db_port_undo(new_port): LOG.info("Rolling back database port...") if not new_port: return try: with context.session.begin(): db_api.port_delete(context, new_port) except Exception: LOG.exception( "Couldn't rollback db port %s" % backend_port) # addresses, mac, backend_port, new_port mac = _allocate_mac(net, port_id, mac_address, use_forbidden_mac_range=use_forbidden_mac_range) _allocate_ips(fixed_ips, net, port_id, segment_id, mac) backend_port = _allocate_backend_port(mac, addresses, net, port_id) new_port = _allocate_db_port(port_attrs, backend_port, addresses, mac) return v._make_port_dict(new_port)
def create_floatingip(context, content): LOG.info("create_floatingip %s for tenant %s and body %s" % (id, context.tenant_id, content)) tenant_id = content.get("tenant_id") network_id = content.get("floating_network_id") fixed_ip_address = content.get("fixed_ip_address") ip_address = content.get("floating_ip_address") port_id = content.get("port_id") if not tenant_id: tenant_id = context.tenant_id if not network_id: raise exceptions.BadRequest(resource="floating_ip", msg="floating_network_id is required.") network = db_api.network_find(context, id=network_id, scope=db_api.ONE) if not network: raise exceptions.NetworkNotFound(net_id=network_id) fixed_ip = None port = None if port_id: port = db_api.port_find(context, id=port_id, scope=db_api.ONE) if not port: raise exceptions.PortNotFound(port_id=port_id) if not port.ip_addresses or len(port.ip_addresses) == 0: raise quark_exceptions.NoAvailableFixedIPsForPort(port_id=port_id) if not fixed_ip_address: fixed_ip = _get_next_available_fixed_ip(port) if not fixed_ip: raise quark_exceptions.NoAvailableFixedIPsForPort( port_id=port_id) else: fixed_ip = next( (ip for ip in port.ip_addresses if (ip["address_readable"] == fixed_ip_address and ip.get("address_type") == ip_types.FIXED)), None) if not fixed_ip: raise quark_exceptions.FixedIpDoesNotExistsForPort( fixed_ip=fixed_ip_address, port_id=port_id) if any(ip for ip in port.ip_addresses if (ip.get("address_type") == ip_types.FLOATING and ip.fixed_ip["address_readable"] == fixed_ip_address)): raise quark_exceptions.PortAlreadyContainsFloatingIp( port_id=port_id) new_addresses = [] ip_addresses = [] if ip_address: ip_addresses.append(ip_address) seg_name = CONF.QUARK.floating_ip_segment_name strategy_name = network.get("ipam_strategy") ipam_driver = ipam.IPAM_REGISTRY.get_strategy(strategy_name) ipam_driver.allocate_ip_address(context, new_addresses, network_id, port_id, CONF.QUARK.ipam_reuse_after, seg_name, version=4, ip_addresses=ip_addresses, address_type=ip_types.FLOATING) floating_ip = new_addresses[0] if fixed_ip and port: with context.session.begin(): floating_ip = db_api.floating_ip_associate_fixed_ip( context, floating_ip, fixed_ip) flip_driver_type = CONF.QUARK.default_floating_ip_driver flip_driver = registry.DRIVER_REGISTRY.get_driver(flip_driver_type) flip_driver.register_floating_ip(floating_ip, port, fixed_ip) return v._make_floating_ip_dict(floating_ip)
def create_floatingip(context, content): """Allocate or reallocate a floating IP. :param context: neutron api request context. :param content: dictionary describing the floating ip, with keys as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. All keys will be populated. :returns: Dictionary containing details for the new floating IP. If values are declared in the fields parameter, then only those keys will be present. """ LOG.info('create_floatingip %s for tenant %s and body %s' % (id, context.tenant_id, content)) tenant_id = content.get('tenant_id') network_id = content.get('floating_network_id') fixed_ip_address = content.get('fixed_ip_address') ip_address = content.get('floating_ip_address') port_id = content.get('port_id') if not tenant_id: tenant_id = context.tenant_id if not network_id: raise exceptions.BadRequest(resource='floating_ip', msg='floating_network_id is required.') network = db_api.network_find(context, id=network_id, scope=db_api.ONE) if not network: raise exceptions.NetworkNotFound(net_id=network_id) fixed_ip = None port = None if port_id: port = db_api.port_find(context, id=port_id, scope=db_api.ONE) if not port: raise exceptions.PortNotFound(port_id=port_id) if not port.ip_addresses or len(port.ip_addresses) == 0: raise qex.NoAvailableFixedIpsForPort(port_id=port_id) if not fixed_ip_address: fixed_ip = _get_next_available_fixed_ip(port) if not fixed_ip: raise qex.NoAvailableFixedIpsForPort( port_id=port_id) else: fixed_ip = next((ip for ip in port.ip_addresses if (ip['address_readable'] == fixed_ip_address and ip.get('address_type') == ip_types.FIXED)), None) if not fixed_ip: raise qex.FixedIpDoesNotExistsForPort( fixed_ip=fixed_ip_address, port_id=port_id) if any(ip for ip in port.ip_addresses if (ip.get('address_type') == ip_types.FLOATING and ip.fixed_ip['address_readable'] == fixed_ip_address)): raise qex.PortAlreadyContainsFloatingIp( port_id=port_id) new_addresses = [] ip_addresses = [] if ip_address: ip_addresses.append(ip_address) seg_name = CONF.QUARK.floating_ip_segment_name strategy_name = CONF.QUARK.floating_ip_ipam_strategy if strategy_name.upper() == 'NETWORK': strategy_name = network.get("ipam_strategy") ipam_driver = ipam.IPAM_REGISTRY.get_strategy(strategy_name) ipam_driver.allocate_ip_address(context, new_addresses, network_id, port_id, CONF.QUARK.ipam_reuse_after, seg_name, version=4, ip_addresses=ip_addresses, address_type=ip_types.FLOATING) flip = new_addresses[0] if fixed_ip and port: context.session.begin() try: flip = db_api.port_associate_ip(context, [port], flip, [port_id]) flip = db_api.floating_ip_associate_fixed_ip(context, flip, fixed_ip) flip_driver = registry.DRIVER_REGISTRY.get_driver() flip_driver.register_floating_ip(flip, port, fixed_ip) context.session.commit() except Exception: context.session.rollback() raise return v._make_floating_ip_dict(flip, port_id)
def create_subnet(context, subnet): """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. """ LOG.info("create_subnet for tenant %s" % context.tenant_id) net_id = subnet["subnet"]["network_id"] net = db_api.network_find(context, id=net_id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=net_id) sub_attrs = subnet["subnet"] _validate_subnet_cidr(context, net_id, sub_attrs["cidr"]) cidr = netaddr.IPNetwork(sub_attrs["cidr"]) gateway_ip = utils.pop_param(sub_attrs, "gateway_ip", str(cidr[1])) dns_ips = utils.pop_param(sub_attrs, "dns_nameservers", []) host_routes = utils.pop_param(sub_attrs, "host_routes", []) allocation_pools = utils.pop_param(sub_attrs, "allocation_pools", []) sub_attrs["network"] = net new_subnet = db_api.subnet_create(context, **sub_attrs) 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 gateway_ip = default_route["nexthop"] new_subnet["routes"].append( db_api.route_create(context, cidr=route["destination"], gateway=route["nexthop"])) if default_route is None: new_subnet["routes"].append( db_api.route_create(context, cidr=str(routes.DEFAULT_ROUTE), gateway=gateway_ip)) for dns_ip in dns_ips: new_subnet["dns_nameservers"].append( db_api.dns_create(context, ip=netaddr.IPAddress(dns_ip))) if allocation_pools: exclude = netaddr.IPSet([cidr]) for p in allocation_pools: x = netaddr.IPSet(netaddr.IPRange(p["start"], p["end"])) exclude = exclude - x new_subnet["ip_policy"] = db_api.ip_policy_create(context, exclude=exclude) subnet_dict = v._make_subnet_dict(new_subnet, default_route=routes.DEFAULT_ROUTE) subnet_dict["gateway_ip"] = gateway_ip return subnet_dict
def create_subnet(context, subnet): """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. """ LOG.info("create_subnet for tenant %s" % context.tenant_id) net_id = subnet["subnet"]["network_id"] with context.session.begin(): net = db_api.network_find(context, id=net_id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=net_id) sub_attrs = subnet["subnet"] _validate_subnet_cidr(context, net_id, sub_attrs["cidr"]) cidr = netaddr.IPNetwork(sub_attrs["cidr"]) err_vals = {'cidr': sub_attrs["cidr"], 'network_id': net_id} err = _("Requested subnet with cidr: %(cidr)s for " "network: %(network_id)s. Prefix is too small, must be a " "larger subnet. A prefix less than /%(prefix)s is required.") if cidr.version == 6 and cidr.prefixlen > 64: err_vals["prefix"] = 65 err_msg = err % err_vals raise exceptions.InvalidInput(error_message=err_msg) elif cidr.version == 4 and cidr.prefixlen > 30: err_vals["prefix"] = 31 err_msg = err % err_vals raise exceptions.InvalidInput(error_message=err_msg) gateway_ip = utils.pop_param(sub_attrs, "gateway_ip", str(cidr[1])) dns_ips = utils.pop_param(sub_attrs, "dns_nameservers", []) host_routes = utils.pop_param(sub_attrs, "host_routes", []) allocation_pools = utils.pop_param(sub_attrs, "allocation_pools", None) if not context.is_admin and "segment_id" in sub_attrs: sub_attrs.pop("segment_id") sub_attrs["network"] = net new_subnet = db_api.subnet_create(context, **sub_attrs) default_route = None for route in host_routes: netaddr_route = netaddr.IPNetwork(route["destination"]) if netaddr_route.value == routes.DEFAULT_ROUTE.value: if default_route: raise q_exc.DuplicateRouteConflict( subnet_id=new_subnet["id"]) default_route = route gateway_ip = default_route["nexthop"] new_subnet["routes"].append(db_api.route_create( context, cidr=route["destination"], gateway=route["nexthop"])) if gateway_ip and default_route is None: new_subnet["routes"].append(db_api.route_create( context, cidr=str(routes.DEFAULT_ROUTE), gateway=gateway_ip)) for dns_ip in dns_ips: new_subnet["dns_nameservers"].append(db_api.dns_create( context, ip=netaddr.IPAddress(dns_ip))) if isinstance(allocation_pools, list) and allocation_pools: subnet_net = netaddr.IPNetwork(new_subnet["cidr"]) cidrset = netaddr.IPSet( netaddr.IPRange( netaddr.IPAddress(subnet_net.first), netaddr.IPAddress(subnet_net.last)).cidrs()) for p in allocation_pools: start = netaddr.IPAddress(p["start"]) end = netaddr.IPAddress(p["end"]) cidrset -= netaddr.IPSet(netaddr.IPRange( netaddr.IPAddress(start), netaddr.IPAddress(end)).cidrs()) default_cidrset = models.IPPolicy.get_ip_policy_cidrs(new_subnet) cidrset.update(default_cidrset) cidrs = [str(x.cidr) for x in cidrset.iter_cidrs()] new_subnet["ip_policy"] = db_api.ip_policy_create(context, exclude=cidrs) subnet_dict = v._make_subnet_dict(new_subnet) subnet_dict["gateway_ip"] = gateway_ip notifier_api.notify(context, notifier_api.publisher_id("network"), "ip_block.create", notifier_api.CONF.default_notification_level, dict(tenant_id=subnet_dict["tenant_id"], ip_block_id=subnet_dict["id"], created_at=new_subnet["created_at"])) return subnet_dict
def create_port(self, context, port): """Create a port Create a port which is a connection point of a device (e.g., a VM NIC) to attach to a L2 Quantum network. : param context: quantum api request context : param port: dictionary describing the port, with keys as listed in the RESOURCE_ATTRIBUTE_MAP object in quantum/api/v2/attributes.py. All keys will be populated. """ LOG.info("create_port for tenant %s" % context.tenant_id) mac_address = port["port"].pop("mac_address", None) if mac_address and mac_address is attributes.ATTR_NOT_SPECIFIED: mac_address = None segment_id = port["port"].pop("segment_id", None) addresses = [] port_id = uuidutils.generate_uuid() net_id = port["port"]["network_id"] net = db_api.network_find(context, id=net_id, shared=True, segment_id=segment_id, scope=db_api.ONE) if not net: # Maybe it's a tenant network net = db_api.network_find(context, id=net_id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=net_id) fixed_ips = port["port"].pop("fixed_ips", None) if fixed_ips and fixed_ips is not attributes.ATTR_NOT_SPECIFIED: for fixed_ip in fixed_ips: subnet_id = fixed_ip.get("subnet_id") ip_address = fixed_ip.get("ip_address") if not (subnet_id and ip_address): raise exceptions.BadRequest( resource="fixed_ips", msg="subnet_id and ip_address required") # Note: we don't allow overlapping subnets, thus subnet_id is # ignored. addresses.append(self.ipam_driver.allocate_ip_address( context, net["id"], port_id, self.ipam_reuse_after, ip_address=ip_address)) else: addresses.append(self.ipam_driver.allocate_ip_address( context, net["id"], port_id, self.ipam_reuse_after)) mac = self.ipam_driver.allocate_mac_address(context, net["id"], port_id, self.ipam_reuse_after, mac_address=mac_address) backend_port = self.net_driver.create_port(context, net["id"], port_id=port_id) port["port"]["network_id"] = net["id"] port["port"]["id"] = port_id new_port = db_api.port_create( context, addresses=addresses, mac_address=mac["address"], backend_key=backend_port["uuid"], **port["port"]) return self._make_port_dict(new_port)