示例#1
0
文件: controllers.py 项目: zbx/kuryr
def network_driver_leave():
    """Unbinds a Neutron Port to a network interface attached to a container.

    This function takes the following JSON data and delete the veth pair
    corresponding to the given info. ::

        {
            "NetworkID": string,
            "EndpointID": string
        }
    """
    json_data = flask.request.get_json(force=True)
    app.logger.debug("Received JSON data {0} for"
                     " /NetworkDriver.DeleteEndpoint"
                     .format(json_data))
    jsonschema.validate(json_data, schemata.LEAVE_SCHEMA)

    neutron_network_identifier = _make_net_identifier(json_data['NetworkID'],
                                                      tags=app.tag)
    endpoint_id = json_data['EndpointID']
    filtered_networks = _get_networks_by_identifier(neutron_network_identifier)

    if not filtered_networks:
        return flask.jsonify({
            'Err': "Neutron net associated with identifier {0} doesn't exit."
            .format(neutron_network_identifier)
        })
    else:
        neutron_port_name = utils.get_neutron_port_name(endpoint_id)
        filtered_ports = _get_ports_by_attrs(name=neutron_port_name)
        if not filtered_ports:
            raise exceptions.NoResourceException(
                "The port doesn't exist for the name {0}"
                .format(neutron_port_name))
        neutron_port = filtered_ports[0]
        try:
            stdout, stderr = binding.port_unbind(endpoint_id, neutron_port)
            app.logger.debug(stdout)
            if stderr:
                app.logger.error(stderr)
        except processutils.ProcessExecutionError:
            with excutils.save_and_reraise_exception():
                app.logger.error(_LE(
                    'Could not unbind the Neutron port from the veth '
                    'endpoint.'))
        except exceptions.VethDeletionFailure:
            with excutils.save_and_reraise_exception():
                app.logger.error(_LE('Cleaning the veth pair up was failed.'))

    return flask.jsonify(const.SCHEMA['SUCCESS'])
示例#2
0
def network_driver_leave():
    """Unbinds a Neutron Port to a network interface attached to a container.

    This function takes the following JSON data and delete the veth pair
    corresponding to the given info. ::

        {
            "NetworkID": string,
            "EndpointID": string
        }
    """
    json_data = flask.request.get_json(force=True)
    app.logger.debug("Received JSON data {0} for"
                     " /NetworkDriver.DeleteEndpoint".format(json_data))
    jsonschema.validate(json_data, schemata.LEAVE_SCHEMA)

    neutron_network_identifier = _make_net_identifier(json_data['NetworkID'],
                                                      tags=app.tag)
    endpoint_id = json_data['EndpointID']
    filtered_networks = _get_networks_by_identifier(neutron_network_identifier)

    if not filtered_networks:
        return flask.jsonify({
            'Err':
            "Neutron net associated with identifier {0} doesn't exit.".format(
                neutron_network_identifier)
        })
    else:
        neutron_port_name = utils.get_neutron_port_name(endpoint_id)
        filtered_ports = _get_ports_by_attrs(name=neutron_port_name)
        if not filtered_ports:
            raise exceptions.NoResourceException(
                "The port doesn't exist for the name {0}".format(
                    neutron_port_name))
        neutron_port = filtered_ports[0]
        try:
            stdout, stderr = binding.port_unbind(endpoint_id, neutron_port)
            app.logger.debug(stdout)
            if stderr:
                app.logger.error(stderr)
        except processutils.ProcessExecutionError:
            with excutils.save_and_reraise_exception():
                app.logger.error(
                    _LE('Could not unbind the Neutron port from the veth '
                        'endpoint.'))
        except exceptions.VethDeletionFailure:
            with excutils.save_and_reraise_exception():
                app.logger.error(_LE('Cleaning the veth pair up was failed.'))

    return flask.jsonify(const.SCHEMA['SUCCESS'])
示例#3
0
文件: controllers.py 项目: zbx/kuryr
def ipam_release_pool():
    """Deletes a new Neutron subnetpool from the given reuest.

    This function takes the following JSON data and delegates the subnetpool
    deletion to the Neutron client. ::

       {
           "PoolID": string
       }

    Then the following JSON response is returned. ::

       {}

    See the following link for more details about the spec:

      https://github.com/docker/libnetwork/blob/master/docs/ipam.md#releasepool  # noqa
    """
    json_data = flask.request.get_json(force=True)
    app.logger.debug("Received JSON data {0} for /IpamDriver.ReleasePool"
                     .format(json_data))
    jsonschema.validate(json_data, schemata.RELEASE_POOL_SCHEMA)
    pool_id = json_data['PoolID']
    try:
        app.neutron.delete_subnetpool(pool_id)
    except n_exceptions.Conflict as ex:
        app.logger.info(_LI("The subnetpool with ID {0} is still in use."
                        " It can't be deleted for now.").format(pool_id))
    except n_exceptions.NeutronClientException as ex:
        app.logger.error(_LE("Error happend during deleting a "
                             "Neutron subnetpool: {0}").format(ex))
        raise

    return flask.jsonify(const.SCHEMA['SUCCESS'])
示例#4
0
文件: utils.py 项目: huikang/kuryr
 def make_json_error(ex):
     app.logger.error(_LE("Unexpected error happened: {0}").format(ex))
     traceback.print_exc(file=sys.stderr)
     response = flask.jsonify({"Err": str(ex)})
     response.status_code = w_exceptions.InternalServerError.code
     if isinstance(ex, w_exceptions.HTTPException):
         response.status_code = ex.code
     elif isinstance(ex, n_exceptions.NeutronClientException):
         response.status_code = ex.status_code
     elif isinstance(ex, jsonschema.ValidationError):
         response.status_code = w_exceptions.BadRequest.code
     content_type = 'application/vnd.docker.plugins.v1+json; charset=utf-8'
     response.headers['Content-Type'] = content_type
     return response
示例#5
0
文件: utils.py 项目: lezbar/kuryr
 def make_json_error(ex):
     app.logger.error(_LE("Unexpected error happened: {0}").format(ex))
     traceback.print_exc(file=sys.stderr)
     response = flask.jsonify({"Err": str(ex)})
     response.status_code = w_exceptions.InternalServerError.code
     if isinstance(ex, w_exceptions.HTTPException):
         response.status_code = ex.code
     elif isinstance(ex, n_exceptions.NeutronClientException):
         response.status_code = ex.status_code
     elif isinstance(ex, jsonschema.ValidationError):
         response.status_code = w_exceptions.BadRequest.code
     content_type = 'application/vnd.docker.plugins.v1+json; charset=utf-8'
     response.headers['Content-Type'] = content_type
     return response
示例#6
0
文件: controllers.py 项目: zbx/kuryr
def _update_port(port, endpoint_id):
    port['name'] = utils.get_neutron_port_name(endpoint_id)
    try:
        response_port = app.neutron.update_port(
                port['id'],
                {'port': {
                    'name': port['name'],
                    'device_owner': const.DEVICE_OWNER,
                    'device_id': endpoint_id}})
    except n_exceptions.NeutronClientException as ex:
        app.logger.error(_LE("Error happend during creating a "
                             "Neutron port: {0}").format(ex))
        raise
    return response_port['port']
示例#7
0
文件: controllers.py 项目: zbx/kuryr
def _cache_default_subnetpool_ids(app):
    """Caches IDs of the default subnetpools as app.DEFAULT_POOL_IDS."""
    if not hasattr(app, 'DEFAULT_POOL_IDS'):
        default_subnetpool_id_set = set()
        try:
            subnetpool_names = SUBNET_POOLS_V4 + SUBNET_POOLS_V6
            for subnetpool_name in subnetpool_names:
                subnetpools = app.neutron.list_subnetpools(
                    name=subnetpool_name)
                for subnetpool in subnetpools['subnetpools']:
                    default_subnetpool_id_set.add(subnetpool['id'])
        except n_exceptions.NeutronClientException as ex:
            app.logger.error(_LE("Error happened during retrieving the default"
                                 " subnet pools.").format(ex))
        app.DEFAULT_POOL_IDS = frozenset(default_subnetpool_id_set)
示例#8
0
def _cache_default_subnetpool_ids(app):
    """Caches IDs of the default subnetpools as app.DEFAULT_POOL_IDS."""
    if not hasattr(app, 'DEFAULT_POOL_IDS'):
        default_subnetpool_id_set = set()
        try:
            subnetpool_names = SUBNET_POOLS_V4 + SUBNET_POOLS_V6
            for subnetpool_name in subnetpool_names:
                subnetpools = app.neutron.list_subnetpools(
                    name=subnetpool_name)
                for subnetpool in subnetpools['subnetpools']:
                    default_subnetpool_id_set.add(subnetpool['id'])
        except n_exceptions.NeutronClientException as ex:
            app.logger.error(
                _LE("Error happened during retrieving the default"
                    " subnet pools.").format(ex))
        app.DEFAULT_POOL_IDS = frozenset(default_subnetpool_id_set)
示例#9
0
def _update_port(port, endpoint_id):
    port['name'] = utils.get_neutron_port_name(endpoint_id)
    try:
        response_port = app.neutron.update_port(
            port['id'], {
                'port': {
                    'name': port['name'],
                    'device_owner': const.DEVICE_OWNER,
                    'device_id': endpoint_id
                }
            })
    except n_exceptions.NeutronClientException as ex:
        app.logger.error(
            _LE("Error happend during creating a "
                "Neutron port: {0}").format(ex))
        raise
    return response_port['port']
示例#10
0
文件: controllers.py 项目: zbx/kuryr
def _create_port(endpoint_id, neutron_network_id, interface_mac, fixed_ips):
    port = {
        'name': utils.get_neutron_port_name(endpoint_id),
        'admin_state_up': True,
        'network_id': neutron_network_id,
        'device_owner': const.DEVICE_OWNER,
        'device_id': endpoint_id,
        'binding:host_id': utils.get_hostname(),
        'fixed_ips': fixed_ips
    }
    if interface_mac:
        port['mac_address'] = interface_mac
    try:
        rcvd_port = app.neutron.create_port({'port': port})
    except n_exceptions.NeutronClientException as ex:
        app.logger.error(_LE("Error happend during creating a"
                             " Neutron port: {0}").format(ex))
        raise
    return rcvd_port['port']
示例#11
0
def _create_port(endpoint_id, neutron_network_id, interface_mac, fixed_ips):
    port = {
        'name': utils.get_neutron_port_name(endpoint_id),
        'admin_state_up': True,
        'network_id': neutron_network_id,
        'device_owner': const.DEVICE_OWNER,
        'device_id': endpoint_id,
        'binding:host_id': utils.get_hostname(),
        'fixed_ips': fixed_ips
    }
    if interface_mac:
        port['mac_address'] = interface_mac
    try:
        rcvd_port = app.neutron.create_port({'port': port})
    except n_exceptions.NeutronClientException as ex:
        app.logger.error(
            _LE("Error happend during creating a"
                " Neutron port: {0}").format(ex))
        raise
    return rcvd_port['port']
示例#12
0
def ipam_release_pool():
    """Deletes a new Neutron subnetpool from the given reuest.

    This function takes the following JSON data and delegates the subnetpool
    deletion to the Neutron client. ::

       {
           "PoolID": string
       }

    Then the following JSON response is returned. ::

       {}

    See the following link for more details about the spec:

      https://github.com/docker/libnetwork/blob/master/docs/ipam.md#releasepool  # noqa
    """
    json_data = flask.request.get_json(force=True)
    app.logger.debug(
        "Received JSON data {0} for /IpamDriver.ReleasePool".format(json_data))
    jsonschema.validate(json_data, schemata.RELEASE_POOL_SCHEMA)
    pool_id = json_data['PoolID']
    try:
        app.neutron.delete_subnetpool(pool_id)
    except n_exceptions.Conflict as ex:
        app.logger.info(
            _LI("The subnetpool with ID {0} is still in use."
                " It can't be deleted for now.").format(pool_id))
    except n_exceptions.NeutronClientException as ex:
        app.logger.error(
            _LE("Error happend during deleting a "
                "Neutron subnetpool: {0}").format(ex))
        raise

    return flask.jsonify(const.SCHEMA['SUCCESS'])
示例#13
0
def ipam_release_address():
    """Deallocates the IP address in the given request.

    This function takes the following JSON data and remove the given IP address
    from the allocation_pool attribute of the subnet. ::

        {
            "PoolID": string
            "Address": string
        }

    Then the following response is returned. ::

        {}

    See the following link for more details about the spec:

      https://github.com/docker/libnetwork/blob/master/docs/ipam.md#releaseaddress  # noqa
    """
    json_data = flask.request.get_json(force=True)
    app.logger.debug(
        "Received JSON data {0} for /IpamDriver.ReleaseAddress".format(
            json_data))
    jsonschema.validate(json_data, schemata.RELEASE_ADDRESS_SCHEMA)
    pool_id = json_data['PoolID']
    rel_address = json_data['Address']
    pools = _get_subnetpools_by_attrs(id=pool_id)
    if pools:
        pool = pools[0]
        prefixes = pool['prefixes']
        for prefix in prefixes:
            cidr = netaddr.IPNetwork(prefix)
            subnet_network = str(cidr.network)
            subnet_cidr = '/'.join([subnet_network, str(cidr.prefixlen)])
    else:
        raise exceptions.NoResourceException(
            "No subnetpools with id {0} is found.".format(pool_id))
    # check if any subnet with matching cidr is present
    subnets = _get_subnets_by_attrs(cidr=subnet_cidr)
    if not len(subnets):
        raise exceptions.NoResourceException(
            "No subnet is found using pool {0} "
            "and pool_cidr {1}".format(pool_id, cidr))
    subnet = subnets[0]
    cidr_address = netaddr.IPNetwork(rel_address)
    rcvd_fixed_ips = []
    fixed_ip = {'subnet_id': subnet['id']}
    fixed_ip['ip_address'] = str(cidr_address.ip)
    rcvd_fixed_ips.append(fixed_ip)

    try:
        filtered_ports = []
        all_ports = app.neutron.list_ports()
        for port in all_ports['ports']:
            if port['fixed_ips'] == rcvd_fixed_ips:
                filtered_ports.append(port)
        for port in filtered_ports:
            app.neutron.delete_port(port['id'])
    except n_exceptions.NeutronClientException as ex:
        app.logger.error(
            _LE("Error happend while fetching and deleting port, "
                "{0}").format(ex))
        raise

    return flask.jsonify(const.SCHEMA['SUCCESS'])
示例#14
0
def network_driver_delete_network():
    """Delete the Neutron Network with name as the given NetworkID.

    This function takes the following JSON data and delegates the actual
    network deletion to the Neutron client. ::

        {
            "NetworkID": string
        }

    See the following link for more details about the spec:

      https://github.com/docker/libnetwork/blob/master/docs/remote.md#delete-network  # noqa
    """
    json_data = flask.request.get_json(force=True)
    app.logger.debug("Received JSON data {0} for"
                     " /NetworkDriver.DeleteNetwork".format(json_data))
    jsonschema.validate(json_data, schemata.NETWORK_DELETE_SCHEMA)

    container_net_id = json_data['NetworkID']
    neutron_network_tags = utils.make_net_tags(container_net_id)
    existing_network_tags = neutron_network_tags + ','
    existing_network_tags += const.KURYR_EXISTING_NEUTRON_NET
    try:
        existing_networks = _get_networks_by_attrs(tags=existing_network_tags)
    except n_exceptions.NeutronClientException as ex:
        app.logger.error(
            _LE("Error happened during listing "
                "Neutron networks: {0}").format(ex))
        raise

    if existing_networks:
        app.logger.warn(
            _LW("Network is a pre existing Neutron network, "
                "not deleting in Neutron. removing tags: {0}").format(
                    existing_network_tags))
        neutron_net_id = existing_networks[0]['id']
        _neutron_net_remove_tags(neutron_net_id, container_net_id)
        _neutron_net_remove_tag(neutron_net_id,
                                const.KURYR_EXISTING_NEUTRON_NET)
        return flask.jsonify(const.SCHEMA['SUCCESS'])

    try:
        filtered_networks = _get_networks_by_attrs(tags=neutron_network_tags)
    except n_exceptions.NeutronClientException as ex:
        app.logger.error(
            _LE("Error happened during listing "
                "Neutron networks: {0}").format(ex))
        raise

    if not filtered_networks:
        app.logger.warn(
            _LW("Network with tags {0} cannot be found").format(
                neutron_network_tags))
    else:
        neutron_network_id = filtered_networks[0]['id']
        filtered_subnets = _get_subnets_by_attrs(network_id=neutron_network_id)
        for subnet in filtered_subnets:
            try:
                subnetpool_id = subnet.get('subnetpool_id', None)

                _cache_default_subnetpool_ids(app)

                if subnetpool_id not in app.DEFAULT_POOL_IDS:
                    # If the subnet to be deleted has any port, when some ports
                    # are referring to the subnets in other words,
                    # delete_subnet throws an exception, SubnetInUse that
                    # extends Conflict. This can happen when the multiple
                    # Docker endpoints are created with the same subnet CIDR
                    # and it's totally the normal case. So we'd just log that
                    # and continue to proceed.
                    app.neutron.delete_subnet(subnet['id'])
            except n_exceptions.Conflict as ex:
                app.logger.error(
                    _LE("Subnet, {0}, is in use. Network cant be deleted.").
                    format(subnet['id']))
                raise
            except n_exceptions.NeutronClientException as ex:
                app.logger.error(
                    _LE("Error happened during deleting a "
                        "Neutron subnets: {0}").format(ex))
                raise

        try:
            app.neutron.delete_network(neutron_network_id)
        except n_exceptions.NeutronClientException as ex:
            app.logger.error(
                _LE("Error happened during deleting a "
                    "Neutron network: {0}").format(ex))
            raise
        app.logger.info(
            _LI("Deleted the network with ID {0} successfully").format(
                neutron_network_id))
    return flask.jsonify(const.SCHEMA['SUCCESS'])
示例#15
0
文件: controllers.py 项目: zbx/kuryr
def network_driver_delete_network():
    """Delete the Neutron Network with name as the given NetworkID.

    This function takes the following JSON data and delegates the actual
    network deletion to the Neutron client. ::

        {
            "NetworkID": string
        }

    See the following link for more details about the spec:

      https://github.com/docker/libnetwork/blob/master/docs/remote.md#delete-network  # noqa
    """
    json_data = flask.request.get_json(force=True)
    app.logger.debug("Received JSON data {0} for"
                     " /NetworkDriver.DeleteNetwork".format(json_data))
    jsonschema.validate(json_data, schemata.NETWORK_DELETE_SCHEMA)

    container_net_id = json_data['NetworkID']
    neutron_network_identifier = _make_net_identifier(container_net_id,
                                                      tags=app.tag)
    if app.tag:
        existing_network_identifier = neutron_network_identifier + ','
        existing_network_identifier += const.KURYR_EXISTING_NEUTRON_NET
        try:
            existing_networks = _get_networks_by_identifier(
                existing_network_identifier)
        except n_exceptions.NeutronClientException as ex:
            app.logger.error(_LE("Error happened during listing "
                                 "Neutron networks: {0}").format(ex))
            raise

        if existing_networks:
            app.logger.warn(_LW("Network is a pre existing Neutron network, "
                                "not deleting in Neutron. removing tags: {0}")
                            .format(existing_network_identifier))
            neutron_net_id = existing_networks[0]['id']
            _neutron_net_remove_tags(neutron_net_id, container_net_id)
            _neutron_net_remove_tag(neutron_net_id,
                                    const.KURYR_EXISTING_NEUTRON_NET)
            return flask.jsonify(const.SCHEMA['SUCCESS'])

    try:
        filtered_networks = _get_networks_by_identifier(
            neutron_network_identifier)
    except n_exceptions.NeutronClientException as ex:
        app.logger.error(_LE("Error happened during listing "
                             "Neutron networks: {0}").format(ex))
        raise

    if not filtered_networks:
        app.logger.warn(_LW("Network with identifier {0} cannot be found")
                        .format(neutron_network_identifier))
    else:
        neutron_network_id = filtered_networks[0]['id']
        filtered_subnets = _get_subnets_by_attrs(
            network_id=neutron_network_id)
        for subnet in filtered_subnets:
            try:
                subnetpool_id = subnet.get('subnetpool_id', None)

                _cache_default_subnetpool_ids(app)

                if subnetpool_id not in app.DEFAULT_POOL_IDS:
                    # If the subnet to be deleted has any port, when some ports
                    # are referring to the subnets in other words,
                    # delete_subnet throws an exception, SubnetInUse that
                    # extends Conflict. This can happen when the multiple
                    # Docker endpoints are created with the same subnet CIDR
                    # and it's totally the normal case. So we'd just log that
                    # and continue to proceed.
                    app.neutron.delete_subnet(subnet['id'])
            except n_exceptions.Conflict as ex:
                app.logger.error(_LE(
                    "Subnet, {0}, is in use. Network cant be deleted.").format(
                        subnet['id']))
                raise
            except n_exceptions.NeutronClientException as ex:
                app.logger.error(_LE("Error happened during deleting a "
                                     "Neutron subnets: {0}").format(ex))
                raise

        try:
            app.neutron.delete_network(neutron_network_id)
        except n_exceptions.NeutronClientException as ex:
            app.logger.error(_LE("Error happened during deleting a "
                                 "Neutron network: {0}").format(ex))
            raise
        app.logger.info(_LI("Deleted the network with ID {0} successfully")
                        .format(neutron_network_id))
    return flask.jsonify(const.SCHEMA['SUCCESS'])
示例#16
0
文件: controllers.py 项目: zbx/kuryr
def network_driver_create_network():
    """Creates a new Neutron Network which name is the given NetworkID.

    This function takes the following JSON data and delegates the actual
    network creation to the Neutron client. libnetwork's NetworkID is used as
    the name of Network in Neutron. ::

        {
            "NetworkID": string,
            "IPv4Data" : [{
                "AddressSpace": string,
                "Pool": ipv4-cidr-string,
                "Gateway" : ipv4-address,
                "AuxAddresses": {
                    "<identifier1>" : "<ipv4-address1>",
                    "<identifier2>" : "<ipv4-address2>",
                    ...
                }
            }, ...],
            "IPv6Data" : [{
                "AddressSpace": string,
                "Pool": ipv6-cidr-string,
                "Gateway" : ipv6-address,
                "AuxAddresses": {
                    "<identifier1>" : "<ipv6-address1>",
                    "<identifier2>" : "<ipv6-address2>",
                    ...
                }
            }, ...],
            "Options": {
                ...
            }
        }

    See the following link for more details about the spec:

      https://github.com/docker/libnetwork/blob/master/docs/remote.md#create-network  # noqa
    """
    json_data = flask.request.get_json(force=True)
    app.logger.debug("Received JSON data {0} for"
                     " /NetworkDriver.CreateNetwork".format(json_data))
    jsonschema.validate(json_data, schemata.NETWORK_CREATE_SCHEMA)
    container_net_id = json_data['NetworkID']
    neutron_network_name = utils.make_net_name(container_net_id, tags=app.tag)
    pool_cidr = json_data['IPv4Data'][0]['Pool']
    gateway_ip = ''
    if 'Gateway' in json_data['IPv4Data'][0]:
        gateway_cidr = json_data['IPv4Data'][0]['Gateway']
        gateway_ip = gateway_cidr.split('/')[0]
        app.logger.debug("gateway_cidr {0}, gateway_ip {1}"
            .format(gateway_cidr, gateway_ip))

    neutron_uuid = None
    neutron_name = None
    options = json_data.get('Options')
    if options:
        generic_options = options.get(const.NETWORK_GENERIC_OPTIONS)
        if generic_options:
            neutron_uuid = generic_options.get(const.NEUTRON_UUID_OPTION)
            neutron_name = generic_options.get(const.NEUTRON_NAME_OPTION)

    if not neutron_uuid and not neutron_name:
        network = app.neutron.create_network(
            {'network': {'name': neutron_network_name,
                         "admin_state_up": True}})
        network_id = network['network']['id']
        _neutron_net_add_tags(network['network']['id'], container_net_id,
                              tags=app.tag)

        app.logger.info(_LI("Created a new network with name {0}"
                            " successfully: {1}")
                        .format(neutron_network_name, network))
    else:
        try:
            if neutron_uuid:
                networks = _get_networks_by_attrs(id=neutron_uuid)
            else:
                networks = _get_networks_by_attrs(name=neutron_name)
            network_id = networks[0]['id']
        except n_exceptions.NeutronClientException as ex:
            app.logger.error(_LE("Error happened during listing "
                                 "Neutron networks: {0}").format(ex))
            raise
        if app.tag:
            _neutron_net_add_tags(network_id, container_net_id, tags=app.tag)
            _neutron_net_add_tag(network_id, const.KURYR_EXISTING_NEUTRON_NET)
        else:
            network = app.neutron.update_network(
                neutron_uuid, {'network': {'name': neutron_network_name}})
            app.logger.info(_LI("Updated the network with new name {0}"
                                " successfully: {1}")
                            .format(neutron_network_name, network))
        app.logger.info(_LI("Using existing network {0} successfully")
                        .format(neutron_uuid))

    cidr = netaddr.IPNetwork(pool_cidr)
    subnet_network = str(cidr.network)
    subnet_cidr = '/'.join([subnet_network, str(cidr.prefixlen)])
    subnets = _get_subnets_by_attrs(
        network_id=network_id, cidr=subnet_cidr)
    if not subnets:
        new_subnets = [{
            'name': pool_cidr,
            'network_id': network_id,
            'ip_version': cidr.version,
            'cidr': subnet_cidr,
            'enable_dhcp': app.enable_dhcp,
        }]
        if gateway_ip:
            new_subnets[0]['gateway_ip'] = gateway_ip

        app.neutron.create_subnet({'subnets': new_subnets})

    return flask.jsonify(const.SCHEMA['SUCCESS'])
示例#17
0
文件: controllers.py 项目: zbx/kuryr
def ipam_release_address():
    """Deallocates the IP address in the given request.

    This function takes the following JSON data and remove the given IP address
    from the allocation_pool attribute of the subnet. ::

        {
            "PoolID": string
            "Address": string
        }

    Then the following response is returned. ::

        {}

    See the following link for more details about the spec:

      https://github.com/docker/libnetwork/blob/master/docs/ipam.md#releaseaddress  # noqa
    """
    json_data = flask.request.get_json(force=True)
    app.logger.debug("Received JSON data {0} for /IpamDriver.ReleaseAddress"
                     .format(json_data))
    jsonschema.validate(json_data, schemata.RELEASE_ADDRESS_SCHEMA)
    pool_id = json_data['PoolID']
    rel_address = json_data['Address']
    pools = _get_subnetpools_by_attrs(id=pool_id)
    if pools:
        pool = pools[0]
        prefixes = pool['prefixes']
        for prefix in prefixes:
            cidr = netaddr.IPNetwork(prefix)
            subnet_network = str(cidr.network)
            subnet_cidr = '/'.join([subnet_network, str(cidr.prefixlen)])
    else:
        raise exceptions.NoResourceException(
            "No subnetpools with id {0} is found."
            .format(pool_id))
    # check if any subnet with matching cidr is present
    subnets = _get_subnets_by_attrs(cidr=subnet_cidr)
    if not len(subnets):
        raise exceptions.NoResourceException(
            "No subnet is found using pool {0} "
            "and pool_cidr {1}".format(pool_id, cidr))
    subnet = subnets[0]
    cidr_address = netaddr.IPNetwork(rel_address)
    rcvd_fixed_ips = []
    fixed_ip = {'subnet_id': subnet['id']}
    fixed_ip['ip_address'] = str(cidr_address.ip)
    rcvd_fixed_ips.append(fixed_ip)

    try:
        filtered_ports = []
        all_ports = app.neutron.list_ports()
        for port in all_ports['ports']:
            if port['fixed_ips'] == rcvd_fixed_ips:
                filtered_ports.append(port)
        for port in filtered_ports:
            app.neutron.delete_port(port['id'])
    except n_exceptions.NeutronClientException as ex:
        app.logger.error(_LE("Error happend while fetching and deleting port, "
                             "{0}").format(ex))
        raise

    return flask.jsonify(const.SCHEMA['SUCCESS'])
示例#18
0
文件: controllers.py 项目: zbx/kuryr
def network_driver_join():
    """Binds a Neutron Port to a network interface attached to a container.

    This function takes the following JSON data, creates a veth pair, put one
    end inside of the container and binds another end to the Neutron Port
    specified in the request. ::

        {
            "NetworkID": string,
            "EndpointID": string,
            "SandboxKey": string,
            "Options": {
                ...
            }
        }

    If the binding is succeeded, the following JSON response is returned.::

        {
            "InterfaceName": {
                SrcName: string,
                DstPrefix: string
            },
            "Gateway": string,
            "GatewayIPv6": string,
            "StaticRoutes": [{
                "Destination": string,
                "RouteType": int,
                "NextHop": string,
            }, ...]
        }

    See the following link for more details about the spec:

      https://github.com/docker/libnetwork/blob/master/docs/remote.md#join  # noqa
    """
    json_data = flask.request.get_json(force=True)
    app.logger.debug("Received JSON data {0} for /NetworkDriver.Join"
                     .format(json_data))
    jsonschema.validate(json_data, schemata.JOIN_SCHEMA)

    neutron_network_identifier = _make_net_identifier(json_data['NetworkID'],
                                                      tags=app.tag)
    endpoint_id = json_data['EndpointID']
    filtered_networks = _get_networks_by_identifier(neutron_network_identifier)

    if not filtered_networks:
        return flask.jsonify({
            'Err': "Neutron net associated with identifier {0} doesn't exit."
            .format(neutron_network_identifier)
        })
    else:
        neutron_network_id = filtered_networks[0]['id']

        neutron_port_name = utils.get_neutron_port_name(endpoint_id)
        filtered_ports = _get_ports_by_attrs(name=neutron_port_name)
        if not filtered_ports:
            raise exceptions.NoResourceException(
                "The port doesn't exist for the name {0}"
                .format(neutron_port_name))
        neutron_port = filtered_ports[0]
        all_subnets = _get_subnets_by_attrs(network_id=neutron_network_id)

        try:
            ifname, peer_name, (stdout, stderr) = binding.port_bind(
                endpoint_id, neutron_port, all_subnets)
            app.logger.debug(stdout)
            if stderr:
                app.logger.error(stderr)
        except exceptions.VethCreationFailure as ex:
            with excutils.save_and_reraise_exception():
                app.logger.error(_LE('Preparing the veth '
                                     'pair was failed: {0}.')
                                 .format(ex))
        except processutils.ProcessExecutionError:
            with excutils.save_and_reraise_exception():
                app.logger.error(_LE(
                    'Could not bind the Neutron port to the veth endpoint.'))

        join_response = {
            "InterfaceName": {
                "SrcName": peer_name,
                "DstPrefix": config.CONF.binding.veth_dst_prefix
            },
            "StaticRoutes": []
        }

        for subnet in all_subnets:
            if subnet['ip_version'] == 4:
                join_response['Gateway'] = subnet.get('gateway_ip', '')
            else:
                join_response['GatewayIPv6'] = subnet.get('gateway_ip', '')
            host_routes = subnet.get('host_routes', [])

            for host_route in host_routes:
                static_route = {
                    'Destination': host_route['destination']
                }
                if host_route.get('nexthop', None):
                    static_route['RouteType'] = const.TYPES['NEXTHOP']
                    static_route['NextHop'] = host_route['nexthop']
                else:
                    static_route['RouteType'] = const.TYPES['CONNECTED']
                join_response['StaticRoutes'].append(static_route)

        return flask.jsonify(join_response)
示例#19
0
def ipam_request_pool():
    """Creates a new Neutron subnetpool from the given request.

    This funciton takes the following JSON data and delegates the subnetpool
    creation to the Neutron client. ::

        {
            "AddressSpace": string
            "Pool":         string
            "SubPool":      string
            "Options":      map[string]string
            "V6":           bool
        }

    Then the following JSON response is returned. ::

        {
            "PoolID": string
            "Pool":   string
            "Data":   map[string]string
        }

    See the following link for more details about the spec:

      https://github.com/docker/libnetwork/blob/master/docs/ipam.md#requestpool  # noqa
    """
    json_data = flask.request.get_json(force=True)
    app.logger.debug(
        "Received JSON data {0} for /IpamDriver.RequestPool".format(json_data))
    jsonschema.validate(json_data, schemata.REQUEST_POOL_SCHEMA)
    requested_pool = json_data['Pool']
    requested_subpool = json_data['SubPool']
    v6 = json_data['V6']
    pool_id = ''
    subnet_cidr = ''
    if requested_pool:
        app.logger.info(_LI("Creating subnetpool with the given pool CIDR"))
        if requested_subpool:
            cidr = netaddr.IPNetwork(requested_subpool)
        else:
            cidr = netaddr.IPNetwork(requested_pool)
        subnet_cidr = _get_subnet_cidr_using_cidr(cidr)
        pool_name = utils.get_neutron_subnetpool_name(subnet_cidr)
        # Check if requested pool already exist
        pools = _get_subnetpools_by_attrs(name=pool_name)
        if pools:
            pool_id = pools[0]['id']
        if not pools:
            new_subnetpool = {
                'name': pool_name,
                'default_prefixlen': cidr.prefixlen,
                'prefixes': [subnet_cidr]
            }
            created_subnetpool_response = app.neutron.create_subnetpool(
                {'subnetpool': new_subnetpool})
            pool = created_subnetpool_response['subnetpool']
            pool_id = pool['id']
    else:
        if v6:
            default_pool_list = SUBNET_POOLS_V6
        else:
            default_pool_list = SUBNET_POOLS_V4
        pool_name = default_pool_list[0]
        pools = _get_subnetpools_by_attrs(name=pool_name)
        if pools:
            pool = pools[0]
            pool_id = pool['id']
            prefixes = pool['prefixes']
            if len(prefixes) > 1:
                app.logger.warning(
                    _LW("More than one prefixes present. "
                        "Picking first one."))
            cidr = netaddr.IPNetwork(prefixes[0])
            subnet_cidr = _get_subnet_cidr_using_cidr(cidr)
        else:
            app.logger.error(_LE("Default neutron pools not found."))
    req_pool_res = {'PoolID': pool_id, 'Pool': subnet_cidr}
    return flask.jsonify(req_pool_res)
示例#20
0
def network_driver_create_network():
    """Creates a new Neutron Network which name is the given NetworkID.

    This function takes the following JSON data and delegates the actual
    network creation to the Neutron client. libnetwork's NetworkID is used as
    the name of Network in Neutron. ::

        {
            "NetworkID": string,
            "IPv4Data" : [{
                "AddressSpace": string,
                "Pool": ipv4-cidr-string,
                "Gateway" : ipv4-address,
                "AuxAddresses": {
                    "<identifier1>" : "<ipv4-address1>",
                    "<identifier2>" : "<ipv4-address2>",
                    ...
                }
            }, ...],
            "IPv6Data" : [{
                "AddressSpace": string,
                "Pool": ipv6-cidr-string,
                "Gateway" : ipv6-address,
                "AuxAddresses": {
                    "<identifier1>" : "<ipv6-address1>",
                    "<identifier2>" : "<ipv6-address2>",
                    ...
                }
            }, ...],
            "Options": {
                ...
            }
        }

    See the following link for more details about the spec:

      https://github.com/docker/libnetwork/blob/master/docs/remote.md#create-network  # noqa
    """
    json_data = flask.request.get_json(force=True)
    app.logger.debug("Received JSON data {0} for"
                     " /NetworkDriver.CreateNetwork".format(json_data))
    jsonschema.validate(json_data, schemata.NETWORK_CREATE_SCHEMA)

    container_net_id = json_data['NetworkID']
    neutron_network_name = utils.make_net_name(container_net_id)
    pool_cidr = json_data['IPv4Data'][0]['Pool']
    gateway_ip = ''
    if 'Gateway' in json_data['IPv4Data'][0]:
        gateway_cidr = json_data['IPv4Data'][0]['Gateway']
        gateway_ip = gateway_cidr.split('/')[0]
        app.logger.debug("gateway_cidr {0}, gateway_ip {1}".format(
            gateway_cidr, gateway_ip))

    neutron_uuid = None
    neutron_name = None
    options = json_data.get('Options')
    if options:
        generic_options = options.get(const.NETWORK_GENERIC_OPTIONS)
        if generic_options:
            neutron_uuid = generic_options.get(const.NEUTRON_UUID_OPTION)
            neutron_name = generic_options.get(const.NEUTRON_NAME_OPTION)

    if not neutron_uuid and not neutron_name:
        network = app.neutron.create_network({
            'network': {
                'name': neutron_network_name,
                "admin_state_up": True
            }
        })
        network_id = network['network']['id']
        _neutron_net_add_tags(network['network']['id'], container_net_id)

        app.logger.info(
            _LI("Created a new network with name {0}"
                " successfully: {1}").format(neutron_network_name, network))
    else:
        try:
            if neutron_uuid:
                networks = _get_networks_by_attrs(id=neutron_uuid)
            else:
                networks = _get_networks_by_attrs(name=neutron_name)
            network_id = networks[0]['id']
        except n_exceptions.NeutronClientException as ex:
            app.logger.error(
                _LE("Error happened during listing "
                    "Neutron networks: {0}").format(ex))
            raise
        _neutron_net_add_tags(network_id, container_net_id)
        _neutron_net_add_tag(network_id, const.KURYR_EXISTING_NEUTRON_NET)
        app.logger.info(
            _LI("Using existing network {0} successfully").format(
                neutron_uuid))

    cidr = netaddr.IPNetwork(pool_cidr)
    subnet_network = str(cidr.network)
    subnet_cidr = '/'.join([subnet_network, str(cidr.prefixlen)])
    subnets = _get_subnets_by_attrs(network_id=network_id, cidr=subnet_cidr)
    if not subnets:
        new_subnets = [{
            'name': pool_cidr,
            'network_id': network_id,
            'ip_version': cidr.version,
            'cidr': subnet_cidr,
            'enable_dhcp': app.enable_dhcp,
        }]
        if gateway_ip:
            new_subnets[0]['gateway_ip'] = gateway_ip

        app.neutron.create_subnet({'subnets': new_subnets})

    return flask.jsonify(const.SCHEMA['SUCCESS'])
示例#21
0
def network_driver_delete_network():
    """Delete the Neutron Network with name as the given NetworkID.

    This function takes the following JSON data and delegates the actual
    network deletion to the Neutron client. ::

        {
            "NetworkID": string
        }

    See the following link for more details about the spec:

      https://github.com/docker/libnetwork/blob/master/docs/remote.md#delete-network  # noqa
    """
    json_data = flask.request.get_json(force=True)
    app.logger.debug("Received JSON data {0} for"
                     " /NetworkDriver.DeleteNetwork".format(json_data))
    jsonschema.validate(json_data, schemata.NETWORK_DELETE_SCHEMA)

    neutron_network_name = json_data['NetworkID']
    try:
        filtered_networks = _get_networks_by_attrs(name=neutron_network_name)
    except n_exceptions.NeutronClientException as ex:
        app.logger.error(_LE("Error happened during listing "
                             "Neutron networks: {0}").format(ex))
        raise
    # We assume Neutron's Network names are not conflicted in Kuryr because
    # they are Docker IDs, 256 bits hashed values, which are rarely conflicted.
    # However, if there're multiple networks associated with the single
    # NetworkID, it raises DuplicatedResourceException and stops processes.
    # See the following doc for more details about Docker's IDs:
    #   https://github.com/docker/docker/blob/master/docs/terms/container.md#container-ids  # noqa
    if not filtered_networks:
        app.logger.warn("Network with name {0} cannot be found"
                        .format(neutron_network_name))
    else:
        neutron_network_id = filtered_networks[0]['id']
        filtered_subnets = _get_subnets_by_attrs(
            network_id=neutron_network_id)
        for subnet in filtered_subnets:
            try:
                subnetpool_id = subnet.get('subnetpool_id', None)

                _cache_default_subnetpool_ids(app)

                if subnetpool_id not in app.DEFAULT_POOL_IDS:
                    # If the subnet to be deleted has any port, when some ports
                    # are referring to the subnets in other words,
                    # delete_subnet throws an exception, SubnetInUse that
                    # extends Conflict. This can happen when the multiple
                    # Docker endpoints are created with the same subnet CIDR
                    # and it's totally the normal case. So we'd just log that
                    # and continue to proceed.
                    app.neutron.delete_subnet(subnet['id'])
            except n_exceptions.Conflict as ex:
                app.logger.error(_LE(
                    "Subnet, {0}, is in use. Network cant be deleted.").format(
                        subnet['id']))
                raise
            except n_exceptions.NeutronClientException as ex:
                app.logger.error(_LE("Error happened during deleting a "
                                     "Neutron subnets: {0}").format(ex))
                raise

        try:
            app.neutron.delete_network(neutron_network_id)
        except n_exceptions.NeutronClientException as ex:
            app.logger.error(_LE("Error happened during deleting a "
                                 "Neutron network: {0}").format(ex))
            raise
        app.logger.info(_LI("Deleted the network with ID {0} successfully")
                        .format(neutron_network_id))
    return flask.jsonify(constants.SCHEMA['SUCCESS'])
示例#22
0
def network_driver_join():
    """Binds a Neutron Port to a network interface attached to a container.

    This function takes the following JSON data, creates a veth pair, put one
    end inside of the container and binds another end to the Neutron Port
    specified in the request. ::

        {
            "NetworkID": string,
            "EndpointID": string,
            "SandboxKey": string,
            "Options": {
                ...
            }
        }

    If the binding is succeeded, the following JSON response is returned.::

        {
            "InterfaceName": {
                SrcName: string,
                DstPrefix: string
            },
            "Gateway": string,
            "GatewayIPv6": string,
            "StaticRoutes": [{
                "Destination": string,
                "RouteType": int,
                "NextHop": string,
            }, ...]
        }

    See the following link for more details about the spec:

      https://github.com/docker/libnetwork/blob/master/docs/remote.md#join  # noqa
    """
    json_data = flask.request.get_json(force=True)
    app.logger.debug(
        "Received JSON data {0} for /NetworkDriver.Join".format(json_data))
    jsonschema.validate(json_data, schemata.JOIN_SCHEMA)

    neutron_network_tags = utils.make_net_tags(json_data['NetworkID'])
    endpoint_id = json_data['EndpointID']
    filtered_networks = _get_networks_by_attrs(tags=neutron_network_tags)

    if not filtered_networks:
        return flask.jsonify({
            'Err':
            "Neutron network associated with tags {0} doesn't exit.".format(
                neutron_network_tags)
        })
    else:
        neutron_network_id = filtered_networks[0]['id']

        neutron_port_name = utils.get_neutron_port_name(endpoint_id)
        filtered_ports = _get_ports_by_attrs(name=neutron_port_name)
        if not filtered_ports:
            raise exceptions.NoResourceException(
                "The port doesn't exist for the name {0}".format(
                    neutron_port_name))
        neutron_port = filtered_ports[0]
        all_subnets = _get_subnets_by_attrs(network_id=neutron_network_id)

        try:
            ifname, peer_name, (stdout, stderr) = binding.port_bind(
                endpoint_id, neutron_port, all_subnets)
            app.logger.debug(stdout)
            if stderr:
                app.logger.error(stderr)
        except exceptions.VethCreationFailure as ex:
            with excutils.save_and_reraise_exception():
                app.logger.error(
                    _LE('Preparing the veth '
                        'pair was failed: {0}.').format(ex))
        except processutils.ProcessExecutionError:
            with excutils.save_and_reraise_exception():
                app.logger.error(
                    _LE('Could not bind the Neutron port to the veth endpoint.'
                        ))

        join_response = {
            "InterfaceName": {
                "SrcName": peer_name,
                "DstPrefix": config.CONF.binding.veth_dst_prefix
            },
            "StaticRoutes": []
        }

        for subnet in all_subnets:
            if subnet['ip_version'] == 4:
                join_response['Gateway'] = subnet.get('gateway_ip', '')
            else:
                join_response['GatewayIPv6'] = subnet.get('gateway_ip', '')
            host_routes = subnet.get('host_routes', [])

            for host_route in host_routes:
                static_route = {'Destination': host_route['destination']}
                if host_route.get('nexthop', None):
                    static_route['RouteType'] = const.TYPES['NEXTHOP']
                    static_route['NextHop'] = host_route['nexthop']
                else:
                    static_route['RouteType'] = const.TYPES['CONNECTED']
                join_response['StaticRoutes'].append(static_route)

        return flask.jsonify(join_response)
示例#23
0
文件: controllers.py 项目: zbx/kuryr
def ipam_request_address():
    """Allocates the IP address in the given request.

    This function takes the following JSON data and add the given IP address in
    the allocation_pools attribute of the subnet. ::

        {
            "PoolID":  string
            "Address": string
            "Options": map[string]string
        }

    Then the following response is returned. ::

        {
            "Address": string
            "Data":    map[string]string
        }

    See the following link for more details about the spec:

    https://github.com/docker/libnetwork/blob/master/docs/ipam.md#requestaddress  # noqa
    """
    json_data = flask.request.get_json(force=True)
    app.logger.debug("Received JSON data {0} for /IpamDriver.RequestAddress"
                     .format(json_data))
    jsonschema.validate(json_data, schemata.REQUEST_ADDRESS_SCHEMA)
    pool_id = json_data['PoolID']
    req_address = json_data['Address']
    allocated_address = ''
    subnet_cidr = ''
    pool_prefix_len = ''
    pools = _get_subnetpools_by_attrs(id=pool_id)
    if pools:
        pool = pools[0]
        prefixes = pool['prefixes']
        if len(prefixes) > 1:
            app.logger.warning(_LW("More than one prefixes present. Picking "
                               "first one."))

        for prefix in prefixes:
            cidr = netaddr.IPNetwork(prefix)
            pool_prefix_len = str(cidr.prefixlen)
            subnet_network = str(cidr.network)
            subnet_cidr = '/'.join([subnet_network, pool_prefix_len])
            break
    else:
        raise exceptions.NoResourceException(
            "No subnetpools with id {0} is found."
            .format(pool_id))
    # check if any subnet with matching cidr is present
    subnets = _get_subnets_by_attrs(cidr=subnet_cidr)
    if subnets:
        subnet = subnets[0]
        # allocating address for container port
        neutron_network_id = subnet['network_id']
        try:
            port = {
                'name': 'kuryr-unbound-port',
                'admin_state_up': True,
                'network_id': neutron_network_id,
                'binding:host_id': utils.get_hostname(),
            }
            fixed_ips = port['fixed_ips'] = []
            fixed_ip = {'subnet_id': subnet['id']}
            if req_address:
                fixed_ip['ip_address'] = req_address
            fixed_ips.append(fixed_ip)
            created_port_resp = app.neutron.create_port({'port': port})
            created_port = created_port_resp['port']
            allocated_address = created_port['fixed_ips'][0]['ip_address']
            allocated_address = '/'.join(
                [allocated_address, str(cidr.prefixlen)])
        except n_exceptions.NeutronClientException as ex:
            app.logger.error(_LE("Error happend during ip allocation on"
                                 "Neutron side: {0}").format(ex))
            raise
    else:
        # Auxiliary address or gw_address is received at network creation time.
        # This address cannot be reserved with neutron at this time as subnet
        # is not created yet. In /NetworkDriver.CreateNetwork this address will
        # be reserved with neutron.
        if req_address:
            allocated_address = '/'.join([req_address, pool_prefix_len])

    return flask.jsonify({'Address': allocated_address})
示例#24
0
def ipam_request_address():
    """Allocates the IP address in the given request.

    This function takes the following JSON data and add the given IP address in
    the allocation_pools attribute of the subnet. ::

        {
            "PoolID":  string
            "Address": string
            "Options": map[string]string
        }

    Then the following response is returned. ::

        {
            "Address": string
            "Data":    map[string]string
        }

    See the following link for more details about the spec:

    https://github.com/docker/libnetwork/blob/master/docs/ipam.md#requestaddress  # noqa
    """
    json_data = flask.request.get_json(force=True)
    app.logger.debug(
        "Received JSON data {0} for /IpamDriver.RequestAddress".format(
            json_data))
    jsonschema.validate(json_data, schemata.REQUEST_ADDRESS_SCHEMA)
    pool_id = json_data['PoolID']
    req_address = json_data['Address']
    allocated_address = ''
    subnet_cidr = ''
    pool_prefix_len = ''
    pools = _get_subnetpools_by_attrs(id=pool_id)
    if pools:
        pool = pools[0]
        prefixes = pool['prefixes']
        if len(prefixes) > 1:
            app.logger.warning(
                _LW("More than one prefixes present. Picking "
                    "first one."))

        for prefix in prefixes:
            cidr = netaddr.IPNetwork(prefix)
            pool_prefix_len = str(cidr.prefixlen)
            subnet_network = str(cidr.network)
            subnet_cidr = '/'.join([subnet_network, pool_prefix_len])
            break
    else:
        raise exceptions.NoResourceException(
            "No subnetpools with id {0} is found.".format(pool_id))
    # check if any subnet with matching cidr is present
    subnets = _get_subnets_by_attrs(cidr=subnet_cidr)
    if subnets:
        subnet = subnets[0]
        # allocating address for container port
        neutron_network_id = subnet['network_id']
        try:
            port = {
                'name': 'kuryr-unbound-port',
                'admin_state_up': True,
                'network_id': neutron_network_id,
                'binding:host_id': utils.get_hostname(),
            }
            fixed_ips = port['fixed_ips'] = []
            fixed_ip = {'subnet_id': subnet['id']}
            if req_address:
                fixed_ip['ip_address'] = req_address
            fixed_ips.append(fixed_ip)
            created_port_resp = app.neutron.create_port({'port': port})
            created_port = created_port_resp['port']
            allocated_address = created_port['fixed_ips'][0]['ip_address']
            allocated_address = '/'.join(
                [allocated_address, str(cidr.prefixlen)])
        except n_exceptions.NeutronClientException as ex:
            app.logger.error(
                _LE("Error happend during ip allocation on"
                    "Neutron side: {0}").format(ex))
            raise
    else:
        # Auxiliary address or gw_address is received at network creation time.
        # This address cannot be reserved with neutron at this time as subnet
        # is not created yet. In /NetworkDriver.CreateNetwork this address will
        # be reserved with neutron.
        if req_address:
            allocated_address = '/'.join([req_address, pool_prefix_len])

    return flask.jsonify({'Address': allocated_address})
示例#25
0
文件: controllers.py 项目: zbx/kuryr
def ipam_request_pool():
    """Creates a new Neutron subnetpool from the given request.

    This funciton takes the following JSON data and delegates the subnetpool
    creation to the Neutron client. ::

        {
            "AddressSpace": string
            "Pool":         string
            "SubPool":      string
            "Options":      map[string]string
            "V6":           bool
        }

    Then the following JSON response is returned. ::

        {
            "PoolID": string
            "Pool":   string
            "Data":   map[string]string
        }

    See the following link for more details about the spec:

      https://github.com/docker/libnetwork/blob/master/docs/ipam.md#requestpool  # noqa
    """
    json_data = flask.request.get_json(force=True)
    app.logger.debug("Received JSON data {0} for /IpamDriver.RequestPool"
                     .format(json_data))
    jsonschema.validate(json_data, schemata.REQUEST_POOL_SCHEMA)
    requested_pool = json_data['Pool']
    requested_subpool = json_data['SubPool']
    v6 = json_data['V6']
    pool_id = ''
    subnet_cidr = ''
    if requested_pool:
        app.logger.info(_LI("Creating subnetpool with the given pool CIDR"))
        if requested_subpool:
            cidr = netaddr.IPNetwork(requested_subpool)
        else:
            cidr = netaddr.IPNetwork(requested_pool)
        subnet_cidr = _get_subnet_cidr_using_cidr(cidr)
        pool_name = utils.get_neutron_subnetpool_name(subnet_cidr)
        # Check if requested pool already exist
        pools = _get_subnetpools_by_attrs(name=pool_name)
        if pools:
            pool_id = pools[0]['id']
        if not pools:
            new_subnetpool = {
                'name': pool_name,
                'default_prefixlen': cidr.prefixlen,
                'prefixes': [subnet_cidr]}
            created_subnetpool_response = app.neutron.create_subnetpool(
                {'subnetpool': new_subnetpool})
            pool = created_subnetpool_response['subnetpool']
            pool_id = pool['id']
    else:
        if v6:
            default_pool_list = SUBNET_POOLS_V6
        else:
            default_pool_list = SUBNET_POOLS_V4
        pool_name = default_pool_list[0]
        pools = _get_subnetpools_by_attrs(name=pool_name)
        if pools:
            pool = pools[0]
            pool_id = pool['id']
            prefixes = pool['prefixes']
            if len(prefixes) > 1:
                app.logger.warning(_LW("More than one prefixes present. "
                                     "Picking first one."))
            cidr = netaddr.IPNetwork(prefixes[0])
            subnet_cidr = _get_subnet_cidr_using_cidr(cidr)
        else:
            app.logger.error(_LE("Default neutron pools not found."))
    req_pool_res = {'PoolID': pool_id,
                    'Pool': subnet_cidr}
    return flask.jsonify(req_pool_res)