Esempio n. 1
0
    def test_join(self, m_create_veth, m_set_mac):
        """
        Test the join() processing correctly creates the veth.
        """
        # Actually make the request to the plugin.
        rv = self.app.post('/NetworkDriver.Join',
                           data='{"EndpointID": "%s", "NetworkID": "%s"}' %
                           (TEST_ENDPOINT_ID, TEST_NETWORK_ID))

        host_interface_name = generate_cali_interface_name(
            IF_PREFIX, TEST_ENDPOINT_ID)
        temp_interface_name = generate_cali_interface_name(
            "tmp", TEST_ENDPOINT_ID)

        m_create_veth.assert_called_once_with(host_interface_name,
                                              temp_interface_name)
        m_set_mac.assert_called_once_with(temp_interface_name,
                                          "EE:EE:EE:EE:EE:EE")

        expected_response = """
        {
          "Gateway": "",
          "InterfaceName": { "DstPrefix": "cali", "SrcName": "tmpTEST_ENDPOI" }
        }"""
        self.maxDiff = None
        self.assertDictEqual(json.loads(rv.data),
                             json.loads(expected_response))
    def test_join_veth_fail(self, m_del_veth, m_create_veth, m_set_veth_mac, m_next_hops):
        """
        Test the join() processing when create_veth fails.
        """
        m_create_veth.side_effect = CalledProcessError(2, "testcmd")

        m_next_hops.return_value = {4: IPAddress("1.2.3.4"),
                                    6: None}

        # Actually make the request to the plugin.
        rv = self.app.post('/NetworkDriver.Join',
                           data='{"EndpointID": "%s", "NetworkID": "%s"}' %
                                (TEST_ENDPOINT_ID, TEST_NETWORK_ID))

        # Expect a 500 response.
        self.assertDictEqual(json.loads(rv.data), {u'Err': u"Command 'testcmd' returned non-zero exit status 2"})

        # Check that create veth is called with the expected endpoint, and
        # that set_endpoint is not (since create_veth is raising an exception).
        host_interface_name = generate_cali_interface_name(IF_PREFIX, TEST_ENDPOINT_ID)
        temp_interface_name = generate_cali_interface_name("tmp", TEST_ENDPOINT_ID)

        m_create_veth.assert_called_once_with(host_interface_name, temp_interface_name)

        # Check that we delete the veth.
        m_del_veth.assert_called_once_with(host_interface_name)
    def test_join_veth_fail(self, m_del_veth, m_create_veth, m_set_veth_mac,
                            m_next_hops):
        """
        Test the join() processing when create_veth fails.
        """
        m_create_veth.side_effect = CalledProcessError(2, "testcmd")

        m_next_hops.return_value = {4: IPAddress("1.2.3.4"), 6: None}

        # Actually make the request to the plugin.
        rv = self.app.post('/NetworkDriver.Join',
                           data='{"EndpointID": "%s", "NetworkID": "%s"}' %
                           (TEST_ENDPOINT_ID, TEST_NETWORK_ID))

        # Expect a 500 response.
        self.assertDictEqual(
            json.loads(rv.data),
            {u'Err': u"Command 'testcmd' returned non-zero exit status 2"})

        # Check that create veth is called with the expected endpoint, and
        # that set_endpoint is not (since create_veth is raising an exception).
        host_interface_name = generate_cali_interface_name(
            IF_PREFIX, TEST_ENDPOINT_ID)
        temp_interface_name = generate_cali_interface_name(
            "tmp", TEST_ENDPOINT_ID)

        m_create_veth.assert_called_once_with(host_interface_name,
                                              temp_interface_name)

        # Check that we delete the veth.
        m_del_veth.assert_called_once_with(host_interface_name)
    def test_join_calico_ipam(self, m_create_veth, m_set_mac, m_get_network,
                              m_get_endpoint, m_get_link_local, m_intf_up):
        """
        Test the join() processing with Calico IPAM.
        """
        m_get_network.return_value = {
            "NetworkID": TEST_NETWORK_ID,
            "IPv4Data": [{
                "Gateway": "0.0.0.0/0",
                "Pool": "0.0.0.0/0"
            }],
            "IPv6Data": [{
                "Gateway": "::/0",
                "Pool": "::/0"
            }]
        }
        m_get_endpoint.return_value = Endpoint(hostname, "libnetwork",
                                               "docker", TEST_ENDPOINT_ID,
                                               None, None)

        # Actually make the request to the plugin.
        rv = self.app.post('/NetworkDriver.Join',
                           data='{"EndpointID": "%s", "NetworkID": "%s"}' %
                           (TEST_ENDPOINT_ID, TEST_NETWORK_ID))

        host_interface_name = generate_cali_interface_name(
            IF_PREFIX, TEST_ENDPOINT_ID)
        temp_interface_name = generate_cali_interface_name(
            "tmp", TEST_ENDPOINT_ID)

        m_create_veth.assert_called_once_with(host_interface_name,
                                              temp_interface_name)
        m_set_mac.assert_called_once_with(temp_interface_name,
                                          "EE:EE:EE:EE:EE:EE")

        expected_data = {
            "Gateway":
            "169.254.1.1",
            "GatewayIPv6":
            "fe80::1/128",
            "InterfaceName": {
                "DstPrefix": "cali",
                "SrcName": "tmpTEST_ENDPOI"
            },
            "StaticRoutes": [{
                "Destination": "169.254.1.1/32",
                "RouteType": 1,
                "NextHop": ""
            }, {
                "Destination": "fe80::1/128",
                "RouteType": 1,
                "NextHop": ""
            }]
        }
        self.maxDiff = None
        self.assertDictEqual(json.loads(rv.data), expected_data)
    def test_join_calico_ipam(self, m_create_veth, m_set_mac, m_get_network,
                              m_get_endpoint):
        """
        Test the join() processing with Calico IPAM.
        """
        m_get_network.return_value = {
            "NetworkID": TEST_NETWORK_ID,
            "IPv4Data":[{
                "Gateway": "0.0.0.0/0",
                "Pool": "0.0.0.0/0"
            }],
            "IPv6Data":[{
                "Gateway": "::/0",
                "Pool": "::/0"
            }]}
        m_get_endpoint.return_value = Endpoint(hostname,
                                               "libnetwork",
                                               "docker",
                                               TEST_ENDPOINT_ID,
                                               None,
                                               None)
        m_get_endpoint.return_value.ipv4_gateway = IPAddress("1.2.3.4")
        m_get_endpoint.return_value.ipv6_gateway = IPAddress("aa::ff")

        # Actually make the request to the plugin.
        rv = self.app.post('/NetworkDriver.Join',
                           data='{"EndpointID": "%s", "NetworkID": "%s"}' %
                                (TEST_ENDPOINT_ID, TEST_NETWORK_ID))

        host_interface_name = generate_cali_interface_name(IF_PREFIX, TEST_ENDPOINT_ID)
        temp_interface_name = generate_cali_interface_name("tmp", TEST_ENDPOINT_ID)

        m_create_veth.assert_called_once_with(host_interface_name, temp_interface_name)
        m_set_mac.assert_called_once_with(temp_interface_name, "EE:EE:EE:EE:EE:EE")

        expected_data = {
            "Gateway": str(m_get_endpoint.return_value.ipv4_gateway),
            "GatewayIPv6": str(m_get_endpoint.return_value.ipv6_gateway),
            "InterfaceName": {
                "DstPrefix": "cali",
                "SrcName": "tmpTEST_ENDPOI"
            },
            "StaticRoutes": [{
                "Destination": str(m_get_endpoint.return_value.ipv4_gateway) +"/32",
                "RouteType": 1,
                "NextHop": ""
            }, {
                "Destination": str(m_get_endpoint.return_value.ipv6_gateway) + "/128",
                "RouteType": 1,
                "NextHop": ""
            }]
        }
        self.maxDiff = None
        self.assertDictEqual(json.loads(rv.data),
                             expected_data)
Esempio n. 6
0
    def __init__(self,
                 hostname,
                 orchestrator_id,
                 workload_id,
                 endpoint_id,
                 state,
                 mac,
                 name=None,
                 active_instance_id=""):
        self.hostname = hostname
        self.orchestrator_id = orchestrator_id
        self.workload_id = workload_id
        self.endpoint_id = endpoint_id
        self.state = state
        self.mac = mac
        self.name = name or generate_cali_interface_name(
            IF_PREFIX, endpoint_id)
        self.active_instance_id = active_instance_id

        self.ipv4_nets = set()
        self.ipv6_nets = set()

        self.profile_ids = []
        self._original_json = None

        self.labels = {}
Esempio n. 7
0
    def _configure_interface(self):
        """Configure the Calico interface for a pod.

        This involves the following steps:
        1) Determine the IP that docker assigned to the interface inside the
           container
        2) Delete the docker-assigned veth pair that's attached to the docker
           bridge
        3) Create a new calico veth pair, using the docker-assigned IP for the
           end in the container's namespace
        4) Assign the node's IP to the host end of the veth pair (required for
           compatibility with kube-proxy REDIRECT iptables rules).
        """
        container_ip = self._read_docker_ip()
        self._delete_docker_interface()
        print('Configuring Calico network interface')
        ep = container_add(self.docker_id, container_ip, 'eth0')
        interface_name = generate_cali_interface_name(IF_PREFIX, ep.endpoint_id)
        node_ip = self._get_node_ip()
        print('Adding IP %s to interface %s' % (node_ip, interface_name))

        # This is slightly tricky. Since the kube-proxy sometimes
        # programs REDIRECT iptables rules, we MUST have an IP on the host end
        # of the caliXXX veth pairs. This is because the REDIRECT rule
        # rewrites the destination ip/port of traffic from a pod to a service
        # VIP. The destination port is rewriten to an arbitrary high-numbered
        # port, and the destination IP is rewritten to one of the IPs allocated
        # to the interface. This fails if the interface doesn't have an IP,
        # so we allocate an IP which is already allocated to the node. We set
        # the subnet to /32 so that the routing table is not affected;
        # no traffic for the node_ip's subnet will use the /32 route.
        check_call(['ip', 'addr', 'add', node_ip + '/32',
                    'dev', interface_name])
        print('Finished configuring network interface')
        return ep
    def test_join_default_ipam(self, m_create_veth, m_set_mac, m_get_network,
                               m_intf_up):
        """
        Test the join() processing with default IPAM.
        """
        request_data = {
            "EndpointID": TEST_ENDPOINT_ID,
            "NetworkID": TEST_NETWORK_ID
        }

        m_get_network.return_value = {
            "NetworkID": TEST_NETWORK_ID,
            "IPv4Data": [{
                "Gateway": "6.5.4.3/21",
                "Pool": "6.5.4.3/21"
            }],
            "IPv6Data": []
        }

        # Actually make the request to the plugin.
        rv = self.app.post('/NetworkDriver.Join',
                           data=json.dumps(request_data))

        # Check the expected response.
        response_data = {
            "Gateway": "",
            "GatewayIPv6": "",
            "InterfaceName": {
                "DstPrefix": "cali",
                "SrcName": "tmpTEST_ENDPOI"
            }
        }
        self.maxDiff = None
        self.assertDictEqual(json.loads(rv.data), response_data)

        # Check appropriate netns calls.
        host_interface_name = generate_cali_interface_name(
            IF_PREFIX, TEST_ENDPOINT_ID)
        temp_interface_name = generate_cali_interface_name(
            "tmp", TEST_ENDPOINT_ID)

        m_create_veth.assert_called_once_with(host_interface_name,
                                              temp_interface_name)
        m_set_mac.assert_called_once_with(temp_interface_name,
                                          "EE:EE:EE:EE:EE:EE")
    def test_leave(self, m_veth):
        """
        Test leave() processing removes the veth.
        """
        # Send the leave request.
        rv = self.app.post("/NetworkDriver.Leave", data='{"EndpointID": "%s"}' % TEST_ENDPOINT_ID)
        self.assertDictEqual(json.loads(rv.data), {})

        m_veth.assert_called_once_with(generate_cali_interface_name(IF_PREFIX, TEST_ENDPOINT_ID))
    def test_remove_veth_fail(self, m_remove):
        """
        Test remove_veth calls through to netns to remove the veth.
        Fail with a CalledProcessError to write the log.
        """
        name = generate_cali_interface_name(IF_PREFIX, TEST_ENDPOINT_ID)

        driver_plugin.remove_veth(name)
        m_remove.assert_called_once_with(name)
    def test_remove_veth_fail(self, m_remove):
        """
        Test remove_veth calls through to netns to remove the veth.
        Fail with a CalledProcessError to write the log.
        """
        name = generate_cali_interface_name(IF_PREFIX, TEST_ENDPOINT_ID)

        driver_plugin.remove_veth(name)
        m_remove.assert_called_once_with(name)
Esempio n. 12
0
def leave():
    json_data = request.get_json(force=True)
    app.logger.debug("Leave JSON=%s", json_data)
    ep_id = json_data["EndpointID"]
    app.logger.info("Leaving endpoint %s", ep_id)

    remove_veth(generate_cali_interface_name(IF_PREFIX, ep_id))

    app.logger.debug("Leave response JSON=%s", "{}")
    return jsonify({})
def leave():
    json_data = request.get_json(force=True)
    app.logger.debug("Leave JSON=%s", json_data)
    ep_id = json_data["EndpointID"]
    app.logger.info("Leaving endpoint %s", ep_id)

    remove_veth(generate_cali_interface_name(IF_PREFIX, ep_id))

    app.logger.debug("Leave response JSON=%s", "{}")
    return jsonify({})
    def test_leave(self, m_veth):
        """
        Test leave() processing removes the veth.
        """
        # Send the leave request.
        rv = self.app.post('/NetworkDriver.Leave',
                           data='{"EndpointID": "%s"}' % TEST_ENDPOINT_ID)
        self.assertDictEqual(json.loads(rv.data), {})

        m_veth.assert_called_once_with(
            generate_cali_interface_name(IF_PREFIX, TEST_ENDPOINT_ID))
    def test_join(self, m_create_veth, m_set_mac):
        """
        Test the join() processing correctly creates the veth.
        """
        # Actually make the request to the plugin.
        rv = self.app.post(
            "/NetworkDriver.Join", data='{"EndpointID": "%s", "NetworkID": "%s"}' % (TEST_ENDPOINT_ID, TEST_NETWORK_ID)
        )

        host_interface_name = generate_cali_interface_name(IF_PREFIX, TEST_ENDPOINT_ID)
        temp_interface_name = generate_cali_interface_name("tmp", TEST_ENDPOINT_ID)

        m_create_veth.assert_called_once_with(host_interface_name, temp_interface_name)
        m_set_mac.assert_called_once_with(temp_interface_name, "EE:EE:EE:EE:EE:EE")

        expected_response = """
        {
          "Gateway": "",
          "InterfaceName": { "DstPrefix": "cali", "SrcName": "tmpTEST_ENDPOI" }
        }"""
        self.maxDiff = None
        self.assertDictEqual(json.loads(rv.data), json.loads(expected_response))
Esempio n. 16
0
def join():
    json_data = request.get_json(force=True)
    app.logger.debug("Join JSON=%s", json_data)
    endpoint_id = json_data["EndpointID"]
    app.logger.info("Joining endpoint %s", endpoint_id)

    network_id = json_data["NetworkID"]
    network_data = client.get_network(network_id)
    ipv4_gateway = ""
    if network_data and "IPv4Data" in network_data.keys():
        ipv4_gateway = str(IPNetwork(network_data["IPv4Data"][0]["Gateway"]).ip)

    # The host interface name matches the name given when creating the endpoint
    # during CreateEndpoint
    host_interface_name = generate_cali_interface_name(IF_PREFIX, endpoint_id)

    # The temporary interface name is what gets passed to libnetwork.
    # Libnetwork renames the interface using the DstPrefix (e.g. cali0)
    temp_interface_name = generate_cali_interface_name("tmp", endpoint_id)

    try:
        # Create the veth pair.
        netns.create_veth(host_interface_name, temp_interface_name)

        # Set the mac as libnetwork doesn't do this for us (even if we return
        # it on the CreateNetwork)
        netns.set_veth_mac(temp_interface_name, FIXED_MAC)
    except CalledProcessError as e:
        # Failed to create or configure the veth, ensure veth is removed.
        remove_veth(host_interface_name)
        raise e

    return_json = {
        "InterfaceName": {"SrcName": temp_interface_name, "DstPrefix": IF_PREFIX},
        "Gateway": ipv4_gateway,  # Leave gateway empty to trigger auto-gateway behaviour
    }

    app.logger.debug("Join Response JSON=%s", return_json)
    return jsonify(return_json)
    def test_join_default_ipam(self, m_create_veth, m_set_mac, m_get_network):
        """
        Test the join() processing with default IPAM.
        """
        request_data = {
            "EndpointID": TEST_ENDPOINT_ID,
            "NetworkID": TEST_NETWORK_ID
        }

        m_get_network.return_value = {
            "NetworkID": TEST_NETWORK_ID,
            "IPv4Data": [{
                "Gateway": "6.5.4.3/21",
                "Pool": "6.5.4.3/21"
            }],
            "IPv6Data": []}

        # Actually make the request to the plugin.
        rv = self.app.post('/NetworkDriver.Join',
                           data=json.dumps(request_data))

        # Check the expected response.
        response_data = {
            "Gateway": "",
            "GatewayIPv6": "",
            "InterfaceName": {
                "DstPrefix": "cali",
                "SrcName": "tmpTEST_ENDPOI"
            }
        }
        self.maxDiff = None
        self.assertDictEqual(json.loads(rv.data), response_data)

        # Check appropriate netns calls.
        host_interface_name = generate_cali_interface_name(IF_PREFIX, TEST_ENDPOINT_ID)
        temp_interface_name = generate_cali_interface_name("tmp", TEST_ENDPOINT_ID)

        m_create_veth.assert_called_once_with(host_interface_name, temp_interface_name)
        m_set_mac.assert_called_once_with(temp_interface_name, "EE:EE:EE:EE:EE:EE")
Esempio n. 18
0
def join():
    json_data = request.get_json(force=True)
    app.logger.debug("Join JSON=%s", json_data)
    endpoint_id = json_data["EndpointID"]
    app.logger.info("Joining endpoint %s", endpoint_id)

    # The host interface name matches the name given when creating the endpoint
    # during CreateEndpoint
    host_interface_name = generate_cali_interface_name(IF_PREFIX, endpoint_id)

    # The temporary interface name is what gets passed to libnetwork.
    # Libnetwork renames the interface using the DstPrefix (e.g. cali0)
    temp_interface_name = generate_cali_interface_name("tmp", endpoint_id)

    try:
        # Create the veth pair.
        netns.create_veth(host_interface_name, temp_interface_name)

        # Set the mac as libnetwork doesn't do this for us (even if we return
        # it on the CreateNetwork)
        netns.set_veth_mac(temp_interface_name, FIXED_MAC)
    except CalledProcessError as e:
        # Failed to create or configure the veth, ensure veth is removed.
        remove_veth(host_interface_name)
        raise e

    return_json = {
        "InterfaceName": {
            "SrcName": temp_interface_name,
            "DstPrefix": IF_PREFIX
        },
        "Gateway": "",  # Leave gateway empty to trigger auto-gateway behaviour
    }

    app.logger.debug("Join Response JSON=%s", return_json)
    return jsonify(return_json)
Esempio n. 19
0
    def __init__(self, hostname, orchestrator_id, workload_id, endpoint_id, state, mac):
        self.hostname = hostname
        self.orchestrator_id = orchestrator_id
        self.workload_id = workload_id
        self.endpoint_id = endpoint_id
        self.state = state
        self.mac = mac
        self.name = generate_cali_interface_name(IF_PREFIX, endpoint_id)

        self.ipv4_nets = set()
        self.ipv6_nets = set()
        self.ipv4_gateway = None
        self.ipv6_gateway = None

        self.profile_ids = []
        self._original_json = None
Esempio n. 20
0
    def __init__(self, hostname, orchestrator_id, workload_id, endpoint_id,
                 state, mac):
        self.hostname = hostname
        self.orchestrator_id = orchestrator_id
        self.workload_id = workload_id
        self.endpoint_id = endpoint_id
        self.state = state
        self.mac = mac
        self.name = generate_cali_interface_name(IF_PREFIX, endpoint_id)

        self.ipv4_nets = set()
        self.ipv6_nets = set()
        self.ipv4_gateway = None
        self.ipv6_gateway = None

        self.profile_ids = []
        self._original_json = None
Esempio n. 21
0
    def _configure_interface(self):
        """Configure the Calico interface for a pod.

        This involves the following steps:
        1) Determine the IP that docker assigned to the interface inside the
           container
        2) Delete the docker-assigned veth pair that's attached to the docker
           bridge
        3) Create a new calico veth pair, using the docker-assigned IP for the
           end in the container's namespace
        4) Assign the node's IP to the host end of the veth pair (required for
           compatibility with kube-proxy REDIRECT iptables rules).
        """
        # Set up parameters
        container_pid = self._get_container_pid(self.docker_id)
        interface = 'eth0'

        self._delete_docker_interface()
        logger.info('Configuring Calico network interface')
        ep = self._container_add(container_pid, interface)

        # Log our container's interfaces after adding the new interface.
        _log_interfaces(container_pid)

        interface_name = generate_cali_interface_name(IF_PREFIX,
                                                      ep.endpoint_id)
        node_ip = self._get_node_ip()
        logger.debug('Adding node IP %s to host-side veth %s', node_ip, interface_name)

        # This is slightly tricky. Since the kube-proxy sometimes
        # programs REDIRECT iptables rules, we MUST have an IP on the host end
        # of the caliXXX veth pairs. This is because the REDIRECT rule
        # rewrites the destination ip/port of traffic from a pod to a service
        # VIP. The destination port is rewriten to an arbitrary high-numbered
        # port, and the destination IP is rewritten to one of the IPs allocated
        # to the interface. This fails if the interface doesn't have an IP,
        # so we allocate an IP which is already allocated to the node. We set
        # the subnet to /32 so that the routing table is not affected;
        # no traffic for the node_ip's subnet will use the /32 route.
        check_call(['ip', 'addr', 'add', node_ip + '/32',
                    'dev', interface_name])
        logger.info('Finished configuring network interface')
        return ep
Esempio n. 22
0
 def temp_interface_name(self):
     return generate_cali_interface_name("tmp", self.endpoint_id)
def join():
    json_data = request.get_json(force=True)
    app.logger.debug("Join JSON=%s", json_data)
    network_id = json_data["NetworkID"]
    endpoint_id = json_data["EndpointID"]
    app.logger.info("Joining endpoint %s", endpoint_id)

    # The host interface name matches the name given when creating the endpoint
    # during CreateEndpoint
    host_interface_name = generate_cali_interface_name(IF_PREFIX, endpoint_id)

    # The temporary interface name is what gets passed to libnetwork.
    # Libnetwork renames the interface using the DstPrefix (e.g. cali0)
    temp_interface_name = generate_cali_interface_name("tmp", endpoint_id)

    try:
        # Create the veth pair.
        netns.create_veth(host_interface_name, temp_interface_name)

        # Set the mac as libnetwork doesn't do this for us (even if we return
        # it on the CreateNetwork)
        netns.set_veth_mac(temp_interface_name, FIXED_MAC)
    except CalledProcessError as e:
        # Failed to create or configure the veth, ensure veth is removed.
        remove_veth(host_interface_name)
        raise e

    # Initialise our response data.
    json_response = {
        "InterfaceName": {
            "SrcName": temp_interface_name,
            "DstPrefix": "eth",
        }
    }

    # Extract relevant data from the Network data.
    network_data = get_network_data(network_id)
    gateway_ip4, _ = get_gateway_pool_from_network_data(network_data, 4)
    gateway_ip6, _ = get_gateway_pool_from_network_data(network_data, 6)

    if (gateway_ip4 and is_using_calico_ipam(gateway_ip4)) or \
       (gateway_ip6 and is_using_calico_ipam(gateway_ip6)):
        # One of the network gateway addresses indicate that we are using
        # Calico IPAM driver.  In this case we setup routes using the gateways
        # configured on the endpoint (which will be our host IPs).
        app.logger.debug("Using Calico IPAM driver, configure gateway and "
                         "static routes to the host")
        static_routes = []
        if gateway_ip4:
            json_response["Gateway"] = DUMMY_IPV4_NEXTHOP
            static_routes.append({
                "Destination": DUMMY_IPV4_NEXTHOP + "/32",
                "RouteType": 1,  # 1 = CONNECTED
                "NextHop": ""
            })
        if gateway_ip6:
            # Here, we'll report the link local address of the host's cali interface to libnetwork
            # as our IPv6 gateway. IPv6 link local addresses are automatically assigned to interfaces
            # when they are brought up. Unfortunately, the container link must be up as well. So
            # bring it up now
            # TODO: create_veth should already bring up both links
            bring_up_interface(temp_interface_name)
            # Then extract the link local address that was just assigned to our host's interface
            next_hop_6 = get_next_hop_6(host_interface_name)
            json_response["GatewayIPv6"] = next_hop_6
            static_routes.append({
                "Destination": str(IPNetwork(next_hop_6)),
                "RouteType": 1,  # 1 = CONNECTED
                "NextHop": ""
            })
        json_response["StaticRoutes"] = static_routes
    else:
        # We are not using Calico IPAM driver, so configure blank gateways to
        # set up auto-gateway behavior.
        app.logger.debug("Not using Calico IPAM driver")
        json_response["Gateway"] = ""
        json_response["GatewayIPv6"] = ""

    app.logger.debug("Join Response JSON=%s", json_response)
    return jsonify(json_response)
Esempio n. 24
0
def join():
    json_data = request.get_json(force=True)
    app.logger.debug("Join JSON=%s", json_data)
    network_id = json_data["NetworkID"]
    endpoint_id = json_data["EndpointID"]
    app.logger.info("Joining endpoint %s", endpoint_id)

    # The host interface name matches the name given when creating the endpoint
    # during CreateEndpoint
    host_interface_name = generate_cali_interface_name(IF_PREFIX, endpoint_id)

    # The temporary interface name is what gets passed to libnetwork.
    # Libnetwork renames the interface using the DstPrefix (e.g. cali0)
    temp_interface_name = generate_cali_interface_name("tmp", endpoint_id)

    try:
        # Create the veth pair.
        netns.create_veth(host_interface_name, temp_interface_name)

        # Set the mac as libnetwork doesn't do this for us (even if we return
        # it on the CreateNetwork)
        netns.set_veth_mac(temp_interface_name, FIXED_MAC)
    except CalledProcessError as e:
        # Failed to create or configure the veth, ensure veth is removed.
        remove_veth(host_interface_name)
        raise e

    # Initialise our response data.
    json_response = {
        "InterfaceName": {
            "SrcName": temp_interface_name,
            "DstPrefix": IF_PREFIX,
        }
    }

    # Extract relevant data from the Network data.
    network_data = get_network_data(network_id)
    gateway_ip4, _ = get_gateway_pool_from_network_data(network_data, 4)
    gateway_ip6, _ = get_gateway_pool_from_network_data(network_data, 6)

    if (gateway_ip4 and is_using_calico_ipam(gateway_ip4)) or \
       (gateway_ip6 and is_using_calico_ipam(gateway_ip6)):
        # One of the network gateway addresses indicate that we are using
        # Calico IPAM driver.  In this case we setup routes using the gateways
        # configured on the endpoint (which will be our host IPs).
        app.logger.debug("Using Calico IPAM driver, configure gateway and "
                         "static routes to the host")
        static_routes = []
        if gateway_ip4:
            json_response["Gateway"] = DUMMY_IPV4_NEXTHOP
            static_routes.append({
                "Destination": DUMMY_IPV4_NEXTHOP + "/32",
                "RouteType": 1,  # 1 = CONNECTED
                "NextHop": ""
            })
        if gateway_ip6:
            # Here, we'll report the link local address of the host's cali interface to libnetwork
            # as our IPv6 gateway. IPv6 link local addresses are automatically assigned to interfaces
            # when they are brought up. Unfortunately, the container link must be up as well. So
            # bring it up now
            # TODO: create_veth should already bring up both links
            bring_up_interface(temp_interface_name)
            # Then extract the link local address that was just assigned to our host's interface
            next_hop_6 = get_ipv6_link_local(host_interface_name)
            json_response["GatewayIPv6"] = next_hop_6
            static_routes.append({
                "Destination": str(IPNetwork(next_hop_6)),
                "RouteType": 1,  # 1 = CONNECTED
                "NextHop": ""
            })
        json_response["StaticRoutes"] = static_routes
    else:
        # We are not using Calico IPAM driver, so configure blank gateways to
        # set up auto-gateway behavior.
        app.logger.debug("Not using Calico IPAM driver")
        json_response["Gateway"] = ""
        json_response["GatewayIPv6"] = ""

    app.logger.debug("Join Response JSON=%s", json_response)
    return jsonify(json_response)
Esempio n. 25
0
def join():
    json_data = request.get_json(force=True)
    app.logger.debug("Join JSON=%s", json_data)
    network_id = json_data["NetworkID"]
    endpoint_id = json_data["EndpointID"]
    app.logger.info("Joining endpoint %s", endpoint_id)

    # The host interface name matches the name given when creating the endpoint
    # during CreateEndpoint
    host_interface_name = generate_cali_interface_name(IF_PREFIX, endpoint_id)

    # The temporary interface name is what gets passed to libnetwork.
    # Libnetwork renames the interface using the DstPrefix (e.g. cali0)
    temp_interface_name = generate_cali_interface_name("tmp", endpoint_id)

    try:
        # Create the veth pair.
        netns.create_veth(host_interface_name, temp_interface_name)

        # Set the mac as libnetwork doesn't do this for us (even if we return
        # it on the CreateNetwork)
        netns.set_veth_mac(temp_interface_name, FIXED_MAC)
    except CalledProcessError as e:
        # Failed to create or configure the veth, ensure veth is removed.
        remove_veth(host_interface_name)
        raise e

    # Initialise our response data.
    json_response = {
        "InterfaceName": {
            "SrcName": temp_interface_name,
            "DstPrefix": IF_PREFIX,
        }
    }

    # Extract relevant data from the Network data.
    network_data = get_network_data(network_id)
    gateway_ip4, _ = get_gateway_pool_from_network_data(network_data, 4)
    gateway_ip6, _ = get_gateway_pool_from_network_data(network_data, 6)

    if (gateway_ip4 and is_using_calico_ipam(gateway_ip4)) or \
       (gateway_ip6 and is_using_calico_ipam(gateway_ip6)):
        # One of the network gateway addresses indicate that we are using
        # Calico IPAM driver.  In this case we setup routes using the gateways
        # configured on the endpoint (which will be our host IPs).
        app.logger.debug("Using Calico IPAM driver, configure gateway and "
                         "static routes to the host")
        ep = client.get_endpoint(hostname=hostname,
                                 orchestrator_id=ORCHESTRATOR_ID,
                                 workload_id=CONTAINER_NAME,
                                 endpoint_id=endpoint_id)
        static_routes = []
        if ep.ipv4_gateway:
            json_response["Gateway"] = str(ep.ipv4_gateway)
            static_routes.append({
                "Destination": str(IPNetwork(ep.ipv4_gateway)),
                "RouteType": 1,  # 1 = CONNECTED
                "NextHop": ""
            })
        if ep.ipv6_gateway:
            json_response["GatewayIPv6"] = str(ep.ipv6_gateway)
            static_routes.append({
                "Destination": str(IPNetwork(ep.ipv6_gateway)),
                "RouteType": 1,  # 1 = CONNECTED
                "NextHop": ""
            })
        json_response["StaticRoutes"] = static_routes
    else:
        # We are not using Calico IPAM driver, so configure blank gateways to
        # set up auto-gateway behavior.
        app.logger.debug("Not using Calico IPAM driver")
        json_response["Gateway"] = ""
        json_response["GatewayIPv6"] = ""

    app.logger.debug("Join Response JSON=%s", json_response)
    return jsonify(json_response)
Esempio n. 26
0
 def temp_interface_name(self):
     return generate_cali_interface_name("tmp", self.endpoint_id)
Esempio n. 27
0
def join():
    json_data = request.get_json(force=True)
    app.logger.debug("Join JSON=%s", json_data)
    network_id = json_data["NetworkID"]
    endpoint_id = json_data["EndpointID"]
    app.logger.info("Joining endpoint %s", endpoint_id)

    # The host interface name matches the name given when creating the endpoint
    # during CreateEndpoint
    host_interface_name = generate_cali_interface_name(IF_PREFIX, endpoint_id)

    # The temporary interface name is what gets passed to libnetwork.
    # Libnetwork renames the interface using the DstPrefix (e.g. cali0)
    temp_interface_name = generate_cali_interface_name("tmp", endpoint_id)

    try:
        # Create the veth pair.
        netns.create_veth(host_interface_name, temp_interface_name)

        # Set the mac as libnetwork doesn't do this for us (even if we return
        # it on the CreateNetwork)
        netns.set_veth_mac(temp_interface_name, FIXED_MAC)
    except CalledProcessError as e:
        # Failed to create or configure the veth, ensure veth is removed.
        remove_veth(host_interface_name)
        raise e

    # Initialise our response data.
    json_response = {
        "InterfaceName": {
            "SrcName": temp_interface_name,
            "DstPrefix": IF_PREFIX,
        }
    }

    # Extract relevant data from the Network data.
    network_data = get_network_data(network_id)
    gateway_ip4, _ = get_gateway_pool_from_network_data(network_data, 4)
    gateway_ip6, _ = get_gateway_pool_from_network_data(network_data, 6)

    if (gateway_ip4 and is_using_calico_ipam(gateway_ip4)) or \
       (gateway_ip6 and is_using_calico_ipam(gateway_ip6)):
        # One of the network gateway addresses indicate that we are using
        # Calico IPAM driver.  In this case we setup routes using the gateways
        # configured on the endpoint (which will be our host IPs).
        app.logger.debug("Using Calico IPAM driver, configure gateway and "
                         "static routes to the host")
        ep = client.get_endpoint(hostname=hostname,
                                 orchestrator_id=ORCHESTRATOR_ID,
                                 workload_id=CONTAINER_NAME,
                                 endpoint_id=endpoint_id)
        static_routes = []
        if ep.ipv4_gateway:
            json_response["Gateway"] = str(ep.ipv4_gateway)
            static_routes.append({
                "Destination": str(IPNetwork(ep.ipv4_gateway)),
                "RouteType": 1,  # 1 = CONNECTED
                "NextHop": ""
            })
        if ep.ipv6_gateway:
            json_response["GatewayIPv6"] = str(ep.ipv6_gateway)
            static_routes.append({
                "Destination": str(IPNetwork(ep.ipv6_gateway)),
                "RouteType": 1,  # 1 = CONNECTED
                "NextHop": ""
            })
        json_response["StaticRoutes"] = static_routes
    else:
        # We are not using Calico IPAM driver, so configure blank gateways to
        # set up auto-gateway behavior.
        app.logger.debug("Not using Calico IPAM driver")
        json_response["Gateway"] = ""
        json_response["GatewayIPv6"] = ""

    app.logger.debug("Join Response JSON=%s", json_response)
    return jsonify(json_response)