コード例 #1
0
ファイル: subnets.py プロジェクト: openstack/quark
def get_subnet(context, id, fields=None):
    """Retrieve a subnet.

    : param context: neutron api request context
    : param id: UUID representing the subnet to fetch.
    : param fields: a list of strings that are valid keys in a
        subnet dictionary as listed in the RESOURCE_ATTRIBUTE_MAP
        object in neutron/api/v2/attributes.py. Only these fields
        will be returned.
    """
    LOG.info("get_subnet %s for tenant %s with fields %s" %
             (id, context.tenant_id, fields))
    subnet = db_api.subnet_find(context=context, limit=None,
                                page_reverse=False, sorts=['id'],
                                marker_obj=None, fields=None, id=id,
                                join_dns=True, join_routes=True,
                                scope=db_api.ONE)
    if not subnet:
        raise n_exc.SubnetNotFound(subnet_id=id)

    cache = subnet.get("_allocation_pool_cache")
    if not cache:
        new_cache = subnet.allocation_pools
        db_api.subnet_update_set_alloc_pool_cache(context, subnet, new_cache)
    return v._make_subnet_dict(subnet)
コード例 #2
0
def get_subnet(context, id, fields=None):
    """Retrieve a subnet.

    : param context: neutron api request context
    : param id: UUID representing the subnet to fetch.
    : param fields: a list of strings that are valid keys in a
        subnet dictionary as listed in the RESOURCE_ATTRIBUTE_MAP
        object in neutron/api/v2/attributes.py. Only these fields
        will be returned.
    """
    LOG.info("get_subnet %s for tenant %s with fields %s" %
             (id, context.tenant_id, fields))
    subnet = db_api.subnet_find(context,
                                None,
                                None,
                                None,
                                False,
                                id=id,
                                join_dns=True,
                                join_routes=True,
                                scope=db_api.ONE)
    if not subnet:
        raise n_exc.SubnetNotFound(subnet_id=id)

    cache = subnet.get("_allocation_pool_cache")
    if not cache:
        new_cache = subnet.allocation_pools
        db_api.subnet_update_set_alloc_pool_cache(context, subnet, new_cache)
    return v._make_subnet_dict(subnet)
コード例 #3
0
ファイル: subnets.py プロジェクト: evanscottgray/quark
def get_subnet(context, id, fields=None):
    """Retrieve a subnet.

    : param context: neutron api request context
    : param id: UUID representing the subnet to fetch.
    : param fields: a list of strings that are valid keys in a
        subnet dictionary as listed in the RESOURCE_ATTRIBUTE_MAP
        object in neutron/api/v2/attributes.py. Only these fields
        will be returned.
    """
    LOG.info("get_subnet %s for tenant %s with fields %s" %
             (id, context.tenant_id, fields))
    subnet = db_api.subnet_find(context, None, None, None, False, id=id,
                                join_dns=True, join_routes=True,
                                scope=db_api.ONE)
    if not subnet:
        raise exceptions.SubnetNotFound(subnet_id=id)

    # Check the network_id against the strategies
    net_id = subnet["network_id"]
    net_id = STRATEGY.get_parent_network(net_id)
    subnet["network_id"] = net_id

    cache = subnet.get("_allocation_pool_cache")
    if not cache:
        new_cache = subnet.allocation_pools
        db_api.subnet_update_set_alloc_pool_cache(context, subnet, new_cache)
    return v._make_subnet_dict(subnet)
コード例 #4
0
ファイル: subnets.py プロジェクト: kilogram/quark
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
コード例 #5
0
ファイル: subnets.py プロジェクト: kilogram/quark
def update_subnet(context, id, subnet):
    """Update values of a subnet.

    : param context: neutron api request context
    : param id: UUID representing the subnet to update.
    : param subnet: dictionary with keys indicating fields to update.
        valid keys are those that have a value of True for 'allow_put'
        as listed in the RESOURCE_ATTRIBUTE_MAP object in
        neutron/api/v2/attributes.py.
    """
    LOG.info("update_subnet %s for tenant %s" % (id, context.tenant_id))

    subnet_db = db_api.subnet_find(context, id=id, scope=db_api.ONE)
    if not subnet_db:
        raise exceptions.SubnetNotFound(id=id)

    s = subnet["subnet"]

    dns_ips = s.pop("dns_nameservers", [])
    host_routes = s.pop("host_routes", [])
    gateway_ip = s.pop("gateway_ip", None)

    if gateway_ip:
        default_route = None
        for route in host_routes:
            netaddr_route = netaddr.IPNetwork(route["destination"])
            if netaddr_route.value == routes.DEFAULT_ROUTE.value:
                default_route = route
                break
        if default_route is None:
            route_model = db_api.route_find(context,
                                            cidr=str(routes.DEFAULT_ROUTE),
                                            subnet_id=id,
                                            scope=db_api.ONE)
            if route_model:
                db_api.route_update(context, route_model, gateway=gateway_ip)
            else:
                db_api.route_create(context,
                                    cidr=str(routes.DEFAULT_ROUTE),
                                    gateway=gateway_ip,
                                    subnet_id=id)

    if dns_ips:
        subnet_db["dns_nameservers"] = []
    for dns_ip in dns_ips:
        subnet_db["dns_nameservers"].append(
            db_api.dns_create(context, ip=netaddr.IPAddress(dns_ip)))

    if host_routes:
        subnet_db["routes"] = []
    for route in host_routes:
        subnet_db["routes"].append(
            db_api.route_create(context,
                                cidr=route["destination"],
                                gateway=route["nexthop"]))

    subnet = db_api.subnet_update(context, subnet_db, **s)
    return v._make_subnet_dict(subnet, default_route=routes.DEFAULT_ROUTE)
コード例 #6
0
ファイル: subnets.py プロジェクト: mohanraj1311/quark
def update_subnet(context, id, subnet):
    """Update values of a subnet.

    : param context: neutron api request context
    : param id: UUID representing the subnet to update.
    : param subnet: dictionary with keys indicating fields to update.
        valid keys are those that have a value of True for 'allow_put'
        as listed in the RESOURCE_ATTRIBUTE_MAP object in
        neutron/api/v2/attributes.py.
    """
    LOG.info("update_subnet %s for tenant %s" %
             (id, context.tenant_id))

    with context.session.begin():
        subnet_db = db_api.subnet_find(context, id=id, scope=db_api.ONE)
        if not subnet_db:
            raise exceptions.SubnetNotFound(id=id)

        s = subnet["subnet"]

        dns_ips = s.pop("dns_nameservers", [])
        host_routes = s.pop("host_routes", [])
        gateway_ip = s.pop("gateway_ip", None)

        if gateway_ip:
            default_route = None
            for route in host_routes:
                netaddr_route = netaddr.IPNetwork(route["destination"])
                if netaddr_route.value == routes.DEFAULT_ROUTE.value:
                    default_route = route
                    break
            if default_route is None:
                route_model = db_api.route_find(
                    context, cidr=str(routes.DEFAULT_ROUTE), subnet_id=id,
                    scope=db_api.ONE)
                if route_model:
                    db_api.route_update(context, route_model,
                                        gateway=gateway_ip)
                else:
                    db_api.route_create(context,
                                        cidr=str(routes.DEFAULT_ROUTE),
                                        gateway=gateway_ip, subnet_id=id)

        if dns_ips:
            subnet_db["dns_nameservers"] = []
        for dns_ip in dns_ips:
            subnet_db["dns_nameservers"].append(db_api.dns_create(
                context,
                ip=netaddr.IPAddress(dns_ip)))

        if host_routes:
            subnet_db["routes"] = []
        for route in host_routes:
            subnet_db["routes"].append(db_api.route_create(
                context, cidr=route["destination"], gateway=route["nexthop"]))

        subnet = db_api.subnet_update(context, subnet_db, **s)
    return v._make_subnet_dict(subnet)
コード例 #7
0
ファイル: subnets.py プロジェクト: kilogram/quark
def get_subnet(context, id, fields=None):
    """Retrieve a subnet.

    : param context: neutron api request context
    : param id: UUID representing the subnet to fetch.
    : param fields: a list of strings that are valid keys in a
        subnet dictionary as listed in the RESOURCE_ATTRIBUTE_MAP
        object in neutron/api/v2/attributes.py. Only these fields
        will be returned.
    """
    LOG.info("get_subnet %s for tenant %s with fields %s" %
             (id, context.tenant_id, fields))
    subnet = db_api.subnet_find(context, id=id, scope=db_api.ONE)
    if not subnet:
        raise exceptions.SubnetNotFound(subnet_id=id)

    # Check the network_id against the strategies
    net_id = subnet["network_id"]
    net_id = STRATEGY.get_parent_network(net_id)
    subnet["network_id"] = net_id

    return v._make_subnet_dict(subnet, default_route=routes.DEFAULT_ROUTE)
コード例 #8
0
ファイル: subnets.py プロジェクト: jkoelker/quark
def get_subnet(context, id, fields=None):
    """Retrieve a subnet.

    : param context: neutron api request context
    : param id: UUID representing the subnet to fetch.
    : param fields: a list of strings that are valid keys in a
        subnet dictionary as listed in the RESOURCE_ATTRIBUTE_MAP
        object in neutron/api/v2/attributes.py. Only these fields
        will be returned.
    """
    LOG.info("get_subnet %s for tenant %s with fields %s" %
            (id, context.tenant_id, fields))
    subnet = db_api.subnet_find(context, id=id, scope=db_api.ONE)
    if not subnet:
        raise exceptions.SubnetNotFound(subnet_id=id)

    # Check the network_id against the strategies
    net_id = subnet["network_id"]
    net_id = STRATEGY.get_parent_network(net_id)
    subnet["network_id"] = net_id

    return v._make_subnet_dict(subnet, default_route=routes.DEFAULT_ROUTE)
コード例 #9
0
ファイル: floating_ips.py プロジェクト: MultipleCrashes/quark
def _update_flip(context, flip_id, ip_type, requested_ports):
    """Update a flip based IPAddress

    :param context: neutron api request context.
    :param flip_id: id of the flip or scip
    :param ip_type: ip_types.FLOATING | ip_types.SCALING
    :param requested_ports: dictionary of the structure:
    {"port_id": "<id of port>", "fixed_ip": "<fixed ip address>"}
    :return: quark.models.IPAddress
    """
    # This list will hold flips that require notifications.
    # Using sets to avoid dups, if any.
    notifications = {billing.IP_ASSOC: set(), billing.IP_DISASSOC: set()}

    context.session.begin()
    try:
        flip = db_api.floating_ip_find(context, id=flip_id, scope=db_api.ONE)
        if not flip:
            if ip_type == ip_types.SCALING:
                raise q_exc.ScalingIpNotFound(id=flip_id)
            raise q_exc.FloatingIpNotFound(id=flip_id)
        current_ports = flip.ports

        # Determine what ports are being removed, being added, and remain
        req_port_ids = [
            request_port.get('port_id') for request_port in requested_ports
        ]
        curr_port_ids = [curr_port.id for curr_port in current_ports]
        added_port_ids = [
            port_id for port_id in req_port_ids
            if port_id and port_id not in curr_port_ids
        ]
        removed_port_ids = [
            port_id for port_id in curr_port_ids if port_id not in req_port_ids
        ]
        remaining_port_ids = set(curr_port_ids) - set(removed_port_ids)

        # Validations just for floating ip types
        if (ip_type == ip_types.FLOATING and curr_port_ids
                and curr_port_ids == req_port_ids):
            d = dict(flip_id=flip_id, port_id=curr_port_ids[0])
            raise q_exc.PortAlreadyAssociatedToFloatingIp(**d)
        if (ip_type == ip_types.FLOATING and not curr_port_ids
                and not req_port_ids):
            raise q_exc.FloatingIpUpdateNoPortIdSupplied()

        # Validate that GW IP is not in use on the NW.
        flip_subnet = v._make_subnet_dict(flip.subnet)
        for added_port_id in added_port_ids:
            port = _get_port(context, added_port_id)
            nw = port.network
            nw_ports = v._make_ports_list(nw.ports)
            fixed_ips = [
                ip.get('ip_address') for p in nw_ports
                for ip in p.get('fixed_ips')
            ]

            gw_ip = flip_subnet.get('gateway_ip')
            if gw_ip in fixed_ips:
                port_with_gateway_ip = None
                for port in nw_ports:
                    for ip in port.get('fixed_ips'):
                        if gw_ip in ip.get('ip_address'):
                            port_with_gateway_ip = port
                            break
                port_id = port_with_gateway_ip.get('id')
                network_id = port_with_gateway_ip.get('network_id')
                raise q_exc.FixedIpAllocatedToGatewayIp(port_id=port_id,
                                                        network_id=network_id)
        port_fixed_ips = {}

        # Keep the ports and fixed ips that have not changed
        for port_id in remaining_port_ids:
            port = db_api.port_find(context, id=port_id, scope=db_api.ONE)
            fixed_ip = _get_flip_fixed_ip_by_port_id(flip, port_id)
            port_fixed_ips[port_id] = {'port': port, 'fixed_ip': fixed_ip}

        # Disassociate the ports and fixed ips from the flip that were
        # associated to the flip but are not anymore
        for port_id in removed_port_ids:
            port = db_api.port_find(context, id=port_id, scope=db_api.ONE)
            flip = db_api.port_disassociate_ip(context, [port], flip)
            notifications[billing.IP_DISASSOC].add(flip)
            fixed_ip = _get_flip_fixed_ip_by_port_id(flip, port_id)
            if fixed_ip:
                flip = db_api.floating_ip_disassociate_fixed_ip(
                    context, flip, fixed_ip)

        # Validate the new ports with the flip and associate the new ports
        # and fixed ips with the flip
        for port_id in added_port_ids:
            port = db_api.port_find(context, id=port_id, scope=db_api.ONE)
            if not port:
                raise n_exc.PortNotFound(port_id=port_id)
            if any(ip for ip in port.ip_addresses
                   if (ip.get('address_type') == ip_types.FLOATING)):
                raise q_exc.PortAlreadyContainsFloatingIp(port_id=port_id)
            if any(ip for ip in port.ip_addresses
                   if (ip.get('address_type') == ip_types.SCALING)):
                raise q_exc.PortAlreadyContainsScalingIp(port_id=port_id)
            fixed_ip = _get_next_available_fixed_ip(port)
            LOG.info('new fixed ip: %s' % fixed_ip)
            if not fixed_ip:
                raise q_exc.NoAvailableFixedIpsForPort(port_id=port_id)
            port_fixed_ips[port_id] = {'port': port, 'fixed_ip': fixed_ip}
            flip = db_api.port_associate_ip(context, [port], flip, [port_id])
            notifications[billing.IP_ASSOC].add(flip)
            flip = db_api.floating_ip_associate_fixed_ip(
                context, flip, fixed_ip)

        flip_driver = registry.DRIVER_REGISTRY.get_driver()
        # If there are not any remaining ports and no new ones are being added,
        # remove the floating ip from unicorn
        if not remaining_port_ids and not added_port_ids:
            flip_driver.remove_floating_ip(flip)
        # If new ports are being added but there previously was not any ports,
        # then register a new floating ip with the driver because it is
        # assumed it does not exist
        elif added_port_ids and not curr_port_ids:
            flip_driver.register_floating_ip(flip, port_fixed_ips)
        else:
            flip_driver.update_floating_ip(flip, port_fixed_ips)
        context.session.commit()
    except Exception:
        context.session.rollback()
        raise

    # Send notifications for possible associate/disassociate events
    for notif_type, flip_set in notifications.iteritems():
        for flip in flip_set:
            billing.notify(context, notif_type, flip)

    # NOTE(blogan): ORM does not seem to update the model to the real state
    # of the database, so I'm doing an explicit refresh for now.
    context.session.refresh(flip)
    return flip
コード例 #10
0
ファイル: subnets.py プロジェクト: mohanraj1311/quark
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
コード例 #11
0
ファイル: subnets.py プロジェクト: Cerberus98/quark
def update_subnet(context, id, subnet):
    """Update values of a subnet.

    : param context: neutron api request context
    : param id: UUID representing the subnet to update.
    : param subnet: dictionary with keys indicating fields to update.
        valid keys are those that have a value of True for 'allow_put'
        as listed in the RESOURCE_ATTRIBUTE_MAP object in
        neutron/api/v2/attributes.py.
    """
    LOG.info("update_subnet %s for tenant %s" %
             (id, context.tenant_id))

    with context.session.begin():
        subnet_db = db_api.subnet_find(context, None, None, None, False, id=id,
                                       scope=db_api.ONE)
        if not subnet_db:
            raise exceptions.SubnetNotFound(id=id)

        s = subnet["subnet"]
        always_pop = ["_cidr", "cidr", "first_ip", "last_ip", "ip_version",
                      "segment_id", "network_id"]
        admin_only = ["do_not_use", "created_at", "tenant_id",
                      "next_auto_assign_ip", "enable_dhcp"]
        utils.filter_body(context, s, admin_only, always_pop)

        dns_ips = utils.pop_param(s, "dns_nameservers", [])
        host_routes = utils.pop_param(s, "host_routes", [])
        gateway_ip = utils.pop_param(s, "gateway_ip", None)
        allocation_pools = utils.pop_param(s, "allocation_pools", None)
        if not CONF.QUARK.allow_allocation_pool_update:
            if allocation_pools:
                raise exceptions.BadRequest(
                    resource="subnets",
                    msg="Allocation pools cannot be updated.")
            alloc_pools = allocation_pool.AllocationPools(
                subnet_db["cidr"],
                policies=models.IPPolicy.get_ip_policy_cidrs(subnet_db))
        else:
            alloc_pools = allocation_pool.AllocationPools(subnet_db["cidr"],
                                                          allocation_pools)

        quota.QUOTAS.limit_check(
            context,
            context.tenant_id,
            alloc_pools_per_subnet=len(alloc_pools))
        if gateway_ip:
            alloc_pools.validate_gateway_excluded(gateway_ip)
            default_route = None
            for route in host_routes:
                netaddr_route = netaddr.IPNetwork(route["destination"])
                if netaddr_route.value == routes.DEFAULT_ROUTE.value:
                    default_route = route
                    break

            if default_route is None:
                route_model = db_api.route_find(
                    context, cidr=str(routes.DEFAULT_ROUTE), subnet_id=id,
                    scope=db_api.ONE)
                if route_model:
                    db_api.route_update(context, route_model,
                                        gateway=gateway_ip)
                else:
                    db_api.route_create(context,
                                        cidr=str(routes.DEFAULT_ROUTE),
                                        gateway=gateway_ip, subnet_id=id)

        if dns_ips:
            subnet_db["dns_nameservers"] = []
            quota.QUOTAS.limit_check(context, context.tenant_id,
                                     dns_nameservers_per_subnet=len(dns_ips))

        for dns_ip in dns_ips:
            subnet_db["dns_nameservers"].append(db_api.dns_create(
                context,
                ip=netaddr.IPAddress(dns_ip)))

        if host_routes:
            subnet_db["routes"] = []
            quota.QUOTAS.limit_check(context, context.tenant_id,
                                     routes_per_subnet=len(host_routes))

        for route in host_routes:
            subnet_db["routes"].append(db_api.route_create(
                context, cidr=route["destination"], gateway=route["nexthop"]))
        if CONF.QUARK.allow_allocation_pool_update:
            if isinstance(allocation_pools, list):
                cidrs = alloc_pools.get_policy_cidrs()
                ip_policies.ensure_default_policy(cidrs, [subnet_db])
                subnet_db["ip_policy"] = db_api.ip_policy_update(
                    context, subnet_db["ip_policy"], exclude=cidrs)
                # invalidate the cache
                db_api.subnet_update_set_alloc_pool_cache(context, subnet_db)
        subnet = db_api.subnet_update(context, subnet_db, **s)
    return v._make_subnet_dict(subnet)
コード例 #12
0
ファイル: subnets.py プロジェクト: Cerberus98/quark
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
コード例 #13
0
ファイル: subnets.py プロジェクト: alanquillin/quark
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
コード例 #14
0
ファイル: subnets.py プロジェクト: alanquillin/quark
def update_subnet(context, id, subnet):
    """Update values of a subnet.

    : param context: neutron api request context
    : param id: UUID representing the subnet to update.
    : param subnet: dictionary with keys indicating fields to update.
        valid keys are those that have a value of True for 'allow_put'
        as listed in the RESOURCE_ATTRIBUTE_MAP object in
        neutron/api/v2/attributes.py.
    """
    LOG.info("update_subnet %s for tenant %s" % (id, context.tenant_id))

    with context.session.begin():
        subnet_db = db_api.subnet_find(context,
                                       None,
                                       None,
                                       None,
                                       False,
                                       id=id,
                                       scope=db_api.ONE)
        if not subnet_db:
            raise exceptions.SubnetNotFound(id=id)

        s = subnet["subnet"]
        always_pop = [
            "_cidr", "cidr", "first_ip", "last_ip", "ip_version", "segment_id",
            "network_id"
        ]
        admin_only = [
            "do_not_use", "created_at", "tenant_id", "next_auto_assign_ip",
            "enable_dhcp"
        ]
        utils.filter_body(context, s, admin_only, always_pop)

        dns_ips = utils.pop_param(s, "dns_nameservers", [])
        host_routes = utils.pop_param(s, "host_routes", [])
        gateway_ip = utils.pop_param(s, "gateway_ip", None)
        allocation_pools = utils.pop_param(s, "allocation_pools", None)
        if not CONF.QUARK.allow_allocation_pool_update:
            if allocation_pools:
                raise exceptions.BadRequest(
                    resource="subnets",
                    msg="Allocation pools cannot be updated.")
            alloc_pools = allocation_pool.AllocationPools(
                subnet_db["cidr"],
                policies=models.IPPolicy.get_ip_policy_cidrs(subnet_db))
        else:
            alloc_pools = allocation_pool.AllocationPools(
                subnet_db["cidr"], allocation_pools)

        quota.QUOTAS.limit_check(context,
                                 context.tenant_id,
                                 alloc_pools_per_subnet=len(alloc_pools))
        if gateway_ip:
            alloc_pools.validate_gateway_excluded(gateway_ip)
            default_route = None
            for route in host_routes:
                netaddr_route = netaddr.IPNetwork(route["destination"])
                if netaddr_route.value == routes.DEFAULT_ROUTE.value:
                    default_route = route
                    break

            if default_route is None:
                route_model = db_api.route_find(context,
                                                cidr=str(routes.DEFAULT_ROUTE),
                                                subnet_id=id,
                                                scope=db_api.ONE)
                if route_model:
                    db_api.route_update(context,
                                        route_model,
                                        gateway=gateway_ip)
                else:
                    db_api.route_create(context,
                                        cidr=str(routes.DEFAULT_ROUTE),
                                        gateway=gateway_ip,
                                        subnet_id=id)

        if dns_ips:
            subnet_db["dns_nameservers"] = []
            quota.QUOTAS.limit_check(context,
                                     context.tenant_id,
                                     dns_nameservers_per_subnet=len(dns_ips))

        for dns_ip in dns_ips:
            subnet_db["dns_nameservers"].append(
                db_api.dns_create(context, ip=netaddr.IPAddress(dns_ip)))

        if host_routes:
            subnet_db["routes"] = []
            quota.QUOTAS.limit_check(context,
                                     context.tenant_id,
                                     routes_per_subnet=len(host_routes))

        for route in host_routes:
            subnet_db["routes"].append(
                db_api.route_create(context,
                                    cidr=route["destination"],
                                    gateway=route["nexthop"]))
        if CONF.QUARK.allow_allocation_pool_update:
            if isinstance(allocation_pools, list):
                cidrs = alloc_pools.get_policy_cidrs()
                ip_policies.ensure_default_policy(cidrs, [subnet_db])
                subnet_db["ip_policy"] = db_api.ip_policy_update(
                    context, subnet_db["ip_policy"], exclude=cidrs)
                # invalidate the cache
                db_api.subnet_update_set_alloc_pool_cache(context, subnet_db)
        subnet = db_api.subnet_update(context, subnet_db, **s)
    return v._make_subnet_dict(subnet)
コード例 #15
0
ファイル: floating_ips.py プロジェクト: roaet/quark
def _update_flip(context, flip_id, ip_type, requested_ports):
    """Update a flip based IPAddress

    :param context: neutron api request context.
    :param flip_id: id of the flip or scip
    :param ip_type: ip_types.FLOATING | ip_types.SCALING
    :param requested_ports: dictionary of the structure:
    {"port_id": "<id of port>", "fixed_ip": "<fixed ip address>"}
    :return: quark.models.IPAddress
    """
    # This list will hold flips that require notifications.
    # Using sets to avoid dups, if any.
    notifications = {
        billing.IP_ASSOC: set(),
        billing.IP_DISASSOC: set()
    }

    context.session.begin()
    try:
        flip = db_api.floating_ip_find(context, id=flip_id, scope=db_api.ONE)
        if not flip:
            if ip_type == ip_types.SCALING:
                raise q_exc.ScalingIpNotFound(id=flip_id)
            raise q_exc.FloatingIpNotFound(id=flip_id)
        current_ports = flip.ports

        # Determine what ports are being removed, being added, and remain
        req_port_ids = [request_port.get('port_id')
                        for request_port in requested_ports]
        curr_port_ids = [curr_port.id for curr_port in current_ports]
        added_port_ids = [port_id for port_id in req_port_ids
                          if port_id and port_id not in curr_port_ids]
        removed_port_ids = [port_id for port_id in curr_port_ids
                            if port_id not in req_port_ids]
        remaining_port_ids = set(curr_port_ids) - set(removed_port_ids)

        # Validations just for floating ip types
        if (ip_type == ip_types.FLOATING and curr_port_ids and
                curr_port_ids == req_port_ids):
            d = dict(flip_id=flip_id, port_id=curr_port_ids[0])
            raise q_exc.PortAlreadyAssociatedToFloatingIp(**d)
        if (ip_type == ip_types.FLOATING and
                not curr_port_ids and not req_port_ids):
            raise q_exc.FloatingIpUpdateNoPortIdSupplied()

        # Validate that GW IP is not in use on the NW.
        flip_subnet = v._make_subnet_dict(flip.subnet)
        for added_port_id in added_port_ids:
            port = _get_port(context, added_port_id)
            nw = port.network
            nw_ports = v._make_ports_list(nw.ports)
            fixed_ips = [ip.get('ip_address') for p in nw_ports
                         for ip in p.get('fixed_ips')]

            gw_ip = flip_subnet.get('gateway_ip')
            if gw_ip in fixed_ips:
                port_with_gateway_ip = None
                for port in nw_ports:
                    for ip in port.get('fixed_ips'):
                        if gw_ip in ip.get('ip_address'):
                            port_with_gateway_ip = port
                            break
                port_id = port_with_gateway_ip.get('id')
                network_id = port_with_gateway_ip.get('network_id')
                raise q_exc.FixedIpAllocatedToGatewayIp(port_id=port_id,
                                                        network_id=network_id)
        port_fixed_ips = {}

        # Keep the ports and fixed ips that have not changed
        for port_id in remaining_port_ids:
            port = db_api.port_find(context, id=port_id, scope=db_api.ONE)
            fixed_ip = _get_flip_fixed_ip_by_port_id(flip, port_id)
            port_fixed_ips[port_id] = {'port': port, 'fixed_ip': fixed_ip}

        # Disassociate the ports and fixed ips from the flip that were
        # associated to the flip but are not anymore
        for port_id in removed_port_ids:
            port = db_api.port_find(context, id=port_id, scope=db_api.ONE)
            flip = db_api.port_disassociate_ip(context, [port], flip)
            notifications[billing.IP_DISASSOC].add(flip)
            fixed_ip = _get_flip_fixed_ip_by_port_id(flip, port_id)
            if fixed_ip:
                flip = db_api.floating_ip_disassociate_fixed_ip(
                    context, flip, fixed_ip)

        # Validate the new ports with the flip and associate the new ports
        # and fixed ips with the flip
        for port_id in added_port_ids:
            port = db_api.port_find(context, id=port_id, scope=db_api.ONE)
            if not port:
                raise n_exc.PortNotFound(port_id=port_id)
            if any(ip for ip in port.ip_addresses
                   if (ip.get('address_type') == ip_types.FLOATING)):
                raise q_exc.PortAlreadyContainsFloatingIp(port_id=port_id)
            if any(ip for ip in port.ip_addresses
                   if (ip.get('address_type') == ip_types.SCALING)):
                raise q_exc.PortAlreadyContainsScalingIp(port_id=port_id)
            fixed_ip = _get_next_available_fixed_ip(port)
            LOG.info('new fixed ip: %s' % fixed_ip)
            if not fixed_ip:
                raise q_exc.NoAvailableFixedIpsForPort(port_id=port_id)
            port_fixed_ips[port_id] = {'port': port, 'fixed_ip': fixed_ip}
            flip = db_api.port_associate_ip(context, [port], flip, [port_id])
            notifications[billing.IP_ASSOC].add(flip)
            flip = db_api.floating_ip_associate_fixed_ip(context, flip,
                                                         fixed_ip)

        flip_driver = registry.DRIVER_REGISTRY.get_driver()
        # If there are not any remaining ports and no new ones are being added,
        # remove the floating ip from unicorn
        if not remaining_port_ids and not added_port_ids:
            flip_driver.remove_floating_ip(flip)
        # If new ports are being added but there previously was not any ports,
        # then register a new floating ip with the driver because it is
        # assumed it does not exist
        elif added_port_ids and not curr_port_ids:
            flip_driver.register_floating_ip(flip, port_fixed_ips)
        else:
            flip_driver.update_floating_ip(flip, port_fixed_ips)
        context.session.commit()
    except Exception:
        context.session.rollback()
        raise

    # Send notifications for possible associate/disassociate events
    for notif_type, flip_set in notifications.iteritems():
        for flip in flip_set:
            billing.notify(context, notif_type, flip)

    # NOTE(blogan): ORM does not seem to update the model to the real state
    # of the database, so I'm doing an explicit refresh for now.
    context.session.refresh(flip)
    return flip
コード例 #16
0
ファイル: subnets.py プロジェクト: jkoelker/quark
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
コード例 #17
0
ファイル: subnets.py プロジェクト: kilogram/quark
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