def endpoint_profile_show(hostname, orchestrator_id, workload_id, endpoint_id): """ List the profiles assigned to a particular endpoint. :param hostname: The hostname. :param orchestrator_id: The orchestrator ID. :param workload_id: The workload ID. :param endpoint_id: The endpoint ID. :return: None """ try: endpoint = client.get_endpoint(hostname=hostname, orchestrator_id=orchestrator_id, workload_id=workload_id, endpoint_id=endpoint_id) except MultipleEndpointsMatch: print "Failed to list profiles in endpoint.\n" print_paragraph("More than 1 endpoint matches the provided " "criteria. Please provide additional parameters to " "refine the search.") sys.exit(1) except KeyError: print "Failed to list profiles in endpoint.\n" print_paragraph("Endpoint %s is unknown to Calico.\n" % endpoint_id) sys.exit(1) if endpoint.profile_ids: x = PrettyTable(["Name"], sortby="Name") for name in endpoint.profile_ids: x.add_row([name]) print str(x) + "\n" else: print "Endpoint has no profiles associated with it."
def container_ip_remove(container_name, ip, interface): """ Add an IP address to an existing Calico networked container. :param container_name: The name of the container. :param ip: The IP to add :param interface: The name of the interface in the container. :return: None """ address = IPAddress(ip) # The netns manipulations must be done as root. enforce_root() pool = get_pool_or_exit(address) info = get_container_info_or_exit(container_name) container_id = info["Id"] # Check the container is actually running. if not info["State"]["Running"]: print "%s is not currently running." % container_name sys.exit(1) # Check that the container is already networked try: endpoint = client.get_endpoint(hostname=hostname, orchestrator_id=ORCHESTRATOR_ID, workload_id=container_id) if address.version == 4: nets = endpoint.ipv4_nets else: nets = endpoint.ipv6_nets if not IPNetwork(address) in nets: print "IP address is not assigned to container. Aborting." sys.exit(1) except KeyError: print "Container is unknown to Calico." sys.exit(1) try: nets.remove(IPNetwork(address)) client.update_endpoint(endpoint) except (KeyError, ValueError): print "Error updating datastore. Aborting." sys.exit(1) try: container_pid = info["State"]["Pid"] netns.remove_ip_from_ns_veth(container_pid, address, interface) except CalledProcessError: print "Error updating networking in container. Aborting." sys.exit(1) client.unassign_address(pool, ip) print "IP %s removed from %s" % (ip, container_name)
def container_remove(container_id): """ Remove a container (on this host) from Calico networking. The container may be left in a state without any working networking. If there is a network adaptor in the host namespace used by the container then it is removed. :param container_id: The namespace path or the ID of the container. """ # The netns manipulations must be done as root. enforce_root() # Resolve the name to ID. if container_id.startswith("/") and os.path.exists(container_id): # The ID is a path. Don't do any docker lookups workload_id = escape_etcd(container_id) orchestrator_id = NAMESPACE_ORCHESTRATOR_ID else: workload_id = get_workload_id(container_id) orchestrator_id = DOCKER_ORCHESTRATOR_ID # Find the endpoint ID. We need this to find any ACL rules try: endpoint = client.get_endpoint(hostname=hostname, orchestrator_id=orchestrator_id, workload_id=workload_id) except KeyError: print "Container %s doesn't contain any endpoints" % container_id sys.exit(1) # Remove any IP address assignments that this endpoint has for net in endpoint.ipv4_nets | endpoint.ipv6_nets: assert(net.size == 1) ip = net.ip pools = client.get_ip_pools(ip.version) for pool in pools: if ip in pool: # Ignore failure to unassign address, since we're not # enforcing assignments strictly in datastore.py. client.unassign_address(pool, ip) try: # Remove the interface if it exists netns.remove_veth(endpoint.name) except CalledProcessError: print "Could not remove Calico interface %s" % endpoint.name sys.exit(1) # Remove the container from the datastore. client.remove_workload(hostname, orchestrator_id, workload_id) print "Removed Calico interface from %s" % container_id
def container_remove(container_id): """ Remove a container (on this host) from Calico networking. The container may be left in a state without any working networking. If there is a network adaptor in the host namespace used by the container then it is removed. :param container_id: The namespace path or the ID of the container. """ # The netns manipulations must be done as root. enforce_root() # Resolve the name to ID. if container_id.startswith("/") and os.path.exists(container_id): # The ID is a path. Don't do any docker lookups workload_id = escape_etcd(container_id) orchestrator_id = NAMESPACE_ORCHESTRATOR_ID else: workload_id = get_workload_id(container_id) orchestrator_id = DOCKER_ORCHESTRATOR_ID # Find the endpoint ID. We need this to find any ACL rules try: endpoint = client.get_endpoint(hostname=hostname, orchestrator_id=orchestrator_id, workload_id=workload_id) except KeyError: print "Container %s doesn't contain any endpoints" % container_id sys.exit(1) # Remove any IP address assignments that this endpoint has for net in endpoint.ipv4_nets | endpoint.ipv6_nets: assert (net.size == 1) ip = net.ip pools = client.get_ip_pools(ip.version) for pool in pools: if ip in pool: # Ignore failure to unassign address, since we're not # enforcing assignments strictly in datastore.py. client.unassign_address(pool, ip) try: # Remove the interface if it exists netns.remove_veth(endpoint.name) except CalledProcessError: print "Could not remove Calico interface %s" % endpoint.name sys.exit(1) # Remove the container from the datastore. client.remove_workload(hostname, orchestrator_id, workload_id) print "Removed Calico interface from %s" % container_id
def container_endpoint_id_show(container_name): """ Prints the endpoint-id of the endpoint attached to the specified container, or an appropriate Not-found error message. :param container_name: Name of the container the target endpoint is attached to. :return: None """ workload_id = get_container_id(container_name) try: endpoint = client.get_endpoint(hostname=hostname, orchestrator_id=ORCHESTRATOR_ID, workload_id=workload_id) print endpoint.endpoint_id except KeyError: print "No endpoint was found for %s" % container_name
def container_remove(container_name): """ Remove a container (on this host) from Calico networking. The container may be left in a state without any working networking. If there is a network adaptor in the host namespace used by the container then it is removed. :param container_name: The name or ID of the container. """ # The netns manipulations must be done as root. enforce_root() # Resolve the name to ID. workload_id = get_container_id(container_name) # Find the endpoint ID. We need this to find any ACL rules try: endpoint = client.get_endpoint(hostname=hostname, orchestrator_id=ORCHESTRATOR_ID, workload_id=workload_id) except KeyError: print "Container %s doesn't contain any endpoints" % container_name sys.exit(1) # Remove any IP address assignments that this endpoint has for net in endpoint.ipv4_nets | endpoint.ipv6_nets: assert(net.size == 1) ip = net.ip pools = client.get_ip_pools(ip.version) for pool in pools: if ip in pool: # Ignore failure to unassign address, since we're not # enforcing assignments strictly in datastore.py. client.unassign_address(pool, ip) # Remove the endpoint netns.remove_veth(endpoint.name) # Remove the container from the datastore. client.remove_workload(hostname, ORCHESTRATOR_ID, workload_id) print "Removed Calico interface from %s" % container_name
def container_remove(container_name): """ Remove a container (on this host) from Calico networking. The container may be left in a state without any working networking. If there is a network adaptor in the host namespace used by the container then it is removed. :param container_name: The name or ID of the container. """ # The netns manipulations must be done as root. enforce_root() # Resolve the name to ID. workload_id = get_container_id(container_name) # Find the endpoint ID. We need this to find any ACL rules try: endpoint = client.get_endpoint(hostname=hostname, orchestrator_id=ORCHESTRATOR_ID, workload_id=workload_id) except KeyError: print "Container %s doesn't contain any endpoints" % container_name sys.exit(1) # Remove any IP address assignments that this endpoint has for net in endpoint.ipv4_nets | endpoint.ipv6_nets: assert net.size == 1 ip = net.ip pools = client.get_ip_pools(ip.version) for pool in pools: if ip in pool: # Ignore failure to unassign address, since we're not # enforcing assignments strictly in datastore.py. client.unassign_address(pool, ip) # Remove the endpoint netns.remove_veth(endpoint.name) # Remove the container from the datastore. client.remove_workload(hostname, ORCHESTRATOR_ID, workload_id) print "Removed Calico interface from %s" % container_name
def container_ip_remove(container_id, ip, interface): """ Add an IP address to an existing Calico networked container. :param container_id: The namespace path or container_id of the container. :param ip: The IP to add :param interface: The name of the interface in the container. :return: None """ address = IPAddress(ip) # The netns manipulations must be done as root. enforce_root() pool = get_pool_or_exit(address) if container_id.startswith("/") and os.path.exists(container_id): # The ID is a path. Don't do any docker lookups workload_id = escape_etcd(container_id) namespace = netns.Namespace(container_id) orchestrator_id = NAMESPACE_ORCHESTRATOR_ID else: info = get_container_info_or_exit(container_id) workload_id = info["Id"] namespace = netns.PidNamespace(info["State"]["Pid"]) orchestrator_id = DOCKER_ORCHESTRATOR_ID # Check the container is actually running. if not info["State"]["Running"]: print "%s is not currently running." % container_id sys.exit(1) # Check that the container is already networked try: endpoint = client.get_endpoint(hostname=hostname, orchestrator_id=orchestrator_id, workload_id=workload_id) if address.version == 4: nets = endpoint.ipv4_nets else: nets = endpoint.ipv6_nets if not IPNetwork(address) in nets: print "IP address is not assigned to container. Aborting." sys.exit(1) except KeyError: print "Container is unknown to Calico." sys.exit(1) try: nets.remove(IPNetwork(address)) client.update_endpoint(endpoint) except (KeyError, ValueError): print "Error updating datastore. Aborting." sys.exit(1) try: netns.remove_ip_from_ns_veth(namespace, address, interface) except CalledProcessError: print "Error updating networking in container. Aborting." sys.exit(1) client.release_ips({address}) print "IP %s removed from %s" % (ip, container_id)
def container_ip_add(container_id, ip, interface): """ Add an IP address to an existing Calico networked container. :param container_id: The namespace path or container_id of the container. :param ip: The IP to add :param interface: The name of the interface in the container. :return: None """ # The netns manipulations must be done as root. enforce_root() if container_id.startswith("/") and os.path.exists(container_id): # The ID is a path. Don't do any docker lookups workload_id = escape_etcd(container_id) namespace = netns.Namespace(container_id) orchestrator_id = NAMESPACE_ORCHESTRATOR_ID else: info = get_container_info_or_exit(container_id) workload_id = info["Id"] namespace = netns.PidNamespace(info["State"]["Pid"]) orchestrator_id = DOCKER_ORCHESTRATOR_ID # Check the container is actually running. if not info["State"]["Running"]: print "%s is not currently running." % container_id sys.exit(1) # Check that the container is already networked try: endpoint = client.get_endpoint(hostname=hostname, orchestrator_id=orchestrator_id, workload_id=workload_id) except KeyError: print "Failed to add IP address to container.\n" print_container_not_in_calico_msg(container_id) sys.exit(1) # From here, this method starts having side effects. If something # fails then at least try to leave the system in a clean state. address, pool = get_ip_and_pool(ip) try: if address.version == 4: endpoint.ipv4_nets.add(IPNetwork(address)) else: endpoint.ipv6_nets.add(IPNetwork(address)) client.update_endpoint(endpoint) except (KeyError, ValueError): client.release_ips({address}) print "Error updating datastore. Aborting." sys.exit(1) if not netns.ns_veth_exists(namespace, interface): print "Interface provided does not exist in container. Aborting." sys.exit(1) try: netns.add_ip_to_ns_veth(namespace, address, interface) except CalledProcessError: print "Error updating networking in container. Aborting." if address.version == 4: endpoint.ipv4_nets.remove(IPNetwork(address)) else: endpoint.ipv6_nets.remove(IPNetwork(address)) client.update_endpoint(endpoint) client.release_ips({address}) sys.exit(1) print "IP %s added to %s" % (str(address), container_id)
def container_add(container_id, ip, interface): """ Add a container (on this host) to Calico networking with the given IP. :param container_id: The namespace path or the docker name/ID of the container. :param ip: An IPAddress object with the desired IP to assign. :param interface: The name of the interface in the container. """ # The netns manipulations must be done as root. enforce_root() # TODO: This section is redundant in container_add_ip and elsewhere if container_id.startswith("/") and os.path.exists(container_id): # The ID is a path. Don't do any docker lookups workload_id = escape_etcd(container_id) orchestrator_id = NAMESPACE_ORCHESTRATOR_ID namespace = netns.Namespace(container_id) else: info = get_container_info_or_exit(container_id) workload_id = info["Id"] orchestrator_id = DOCKER_ORCHESTRATOR_ID namespace = netns.PidNamespace(info["State"]["Pid"]) # Check the container is actually running. if not info["State"]["Running"]: print_paragraph("%s is not currently running." % container_id) sys.exit(1) # We can't set up Calico if the container shares the host namespace. if info["HostConfig"]["NetworkMode"] == "host": print_paragraph("Can't add %s to Calico because it is " "running NetworkMode = host." % container_id) sys.exit(1) # Check if the container already exists try: _ = client.get_endpoint(hostname=hostname, orchestrator_id=orchestrator_id, workload_id=workload_id) except KeyError: # Calico doesn't know about this container. Continue. pass else: # Calico already set up networking for this container. Since we got # called with an IP address, we shouldn't just silently exit, since # that would confuse the user: the container would not be reachable on # that IP address. print_paragraph("%s has already been configured with Calico " "Networking." % container_id) sys.exit(1) ip, pool = get_ip_and_pool(ip) try: # The next hop IPs for this host are stored in etcd. next_hops = client.get_default_next_hops(hostname) next_hops[ip.version] except KeyError: print_paragraph("This node is not configured for IPv%d. " "Is calico-node running?" % ip.version) unallocated_ips = client.release_ips({ip}) if unallocated_ips: print_paragraph("Error during cleanup. %s was already" "unallocated." % ip) sys.exit(1) # Get the next hop for the IP address. next_hop = next_hops[ip.version] network = IPNetwork(IPAddress(ip)) ep = Endpoint(hostname=hostname, orchestrator_id=DOCKER_ORCHESTRATOR_ID, workload_id=workload_id, endpoint_id=uuid.uuid1().hex, state="active", mac=None) if network.version == 4: ep.ipv4_nets.add(network) ep.ipv4_gateway = next_hop else: ep.ipv6_nets.add(network) ep.ipv6_gateway = next_hop # Create the veth, move into the container namespace, add the IP and # set up the default routes. netns.increment_metrics(namespace) netns.create_veth(ep.name, ep.temp_interface_name) netns.move_veth_into_ns(namespace, ep.temp_interface_name, interface) netns.add_ip_to_ns_veth(namespace, ip, interface) netns.add_ns_default_route(namespace, next_hop, interface) # Grab the MAC assigned to the veth in the namespace. ep.mac = netns.get_ns_veth_mac(namespace, interface) # Register the endpoint with Felix. client.set_endpoint(ep) # Let the caller know what endpoint was created. print_paragraph("IP %s added to %s" % (str(ip), container_id)) return ep
def container_ip_remove(container_id, ip, interface): """ Add an IP address to an existing Calico networked container. :param container_id: The namespace path or container_id of the container. :param ip: The IP to add :param interface: The name of the interface in the container. :return: None """ address = IPAddress(ip) # The netns manipulations must be done as root. enforce_root() pool = get_pool_or_exit(address) if container_id.startswith("/") and os.path.exists(container_id): # The ID is a path. Don't do any docker lookups workload_id = escape_etcd(container_id) namespace = netns.Namespace(container_id) orchestrator_id = NAMESPACE_ORCHESTRATOR_ID else: info = get_container_info_or_exit(container_id) workload_id = info["Id"] namespace = netns.PidNamespace(info["State"]["Pid"]) orchestrator_id = DOCKER_ORCHESTRATOR_ID # Check the container is actually running. if not info["State"]["Running"]: print "%s is not currently running." % container_id sys.exit(1) # Check that the container is already networked try: endpoint = client.get_endpoint(hostname=hostname, orchestrator_id=orchestrator_id, workload_id=workload_id) if address.version == 4: nets = endpoint.ipv4_nets else: nets = endpoint.ipv6_nets if not IPNetwork(address) in nets: print "IP address is not assigned to container. Aborting." sys.exit(1) except KeyError: print "Container is unknown to Calico." sys.exit(1) try: nets.remove(IPNetwork(address)) client.update_endpoint(endpoint) except (KeyError, ValueError): print "Error updating datastore. Aborting." sys.exit(1) try: netns.remove_ip_from_ns_veth(namespace, address, interface) except CalledProcessError: print "Error updating networking in container. Aborting." sys.exit(1) client.unassign_address(pool, address) print "IP %s removed from %s" % (ip, container_id)
def container_ip_add(container_id, ip, interface): """ Add an IP address to an existing Calico networked container. :param container_id: The namespace path or container_id of the container. :param ip: The IP to add :param interface: The name of the interface in the container. :return: None """ address = IPAddress(ip) # The netns manipulations must be done as root. enforce_root() pool = get_pool_or_exit(address) if container_id.startswith("/") and os.path.exists(container_id): # The ID is a path. Don't do any docker lookups workload_id = escape_etcd(container_id) namespace = netns.Namespace(container_id) orchestrator_id = NAMESPACE_ORCHESTRATOR_ID else: info = get_container_info_or_exit(container_id) workload_id = info["Id"] namespace = netns.PidNamespace(info["State"]["Pid"]) orchestrator_id = DOCKER_ORCHESTRATOR_ID # Check the container is actually running. if not info["State"]["Running"]: print "%s is not currently running." % container_id sys.exit(1) # Check that the container is already networked try: endpoint = client.get_endpoint(hostname=hostname, orchestrator_id=orchestrator_id, workload_id=workload_id) except KeyError: print "Failed to add IP address to container.\n" print_container_not_in_calico_msg(container_id) sys.exit(1) # From here, this method starts having side effects. If something # fails then at least try to leave the system in a clean state. if not client.assign_address(pool, address): print "IP address is already assigned in pool %s " % pool sys.exit(1) try: if address.version == 4: endpoint.ipv4_nets.add(IPNetwork(address)) else: endpoint.ipv6_nets.add(IPNetwork(address)) client.update_endpoint(endpoint) except (KeyError, ValueError): client.unassign_address(pool, ip) print "Error updating datastore. Aborting." sys.exit(1) try: netns.add_ip_to_ns_veth(namespace, address, interface) except CalledProcessError: print "Error updating networking in container. Aborting." if address.version == 4: endpoint.ipv4_nets.remove(IPNetwork(address)) else: endpoint.ipv6_nets.remove(IPNetwork(address)) client.update_endpoint(endpoint) client.unassign_address(pool, ip) sys.exit(1) print "IP %s added to %s" % (ip, container_id)
def container_add(container_id, ip, interface): """ Add a container (on this host) to Calico networking with the given IP. :param container_id: The namespace path or the docker name/ID of the container. :param ip: An IPAddress object with the desired IP to assign. :param interface: The name of the interface in the container. """ # The netns manipulations must be done as root. enforce_root() if container_id.startswith("/") and os.path.exists(container_id): # The ID is a path. Don't do any docker lookups workload_id = escape_etcd(container_id) orchestrator_id = NAMESPACE_ORCHESTRATOR_ID namespace = netns.Namespace(container_id) else: info = get_container_info_or_exit(container_id) workload_id = info["Id"] orchestrator_id = DOCKER_ORCHESTRATOR_ID namespace = netns.PidNamespace(info["State"]["Pid"]) # Check the container is actually running. if not info["State"]["Running"]: print "%s is not currently running." % container_id sys.exit(1) # We can't set up Calico if the container shares the host namespace. if info["HostConfig"]["NetworkMode"] == "host": print "Can't add %s to Calico because it is " \ "running NetworkMode = host." % container_id sys.exit(1) # Check if the container already exists try: _ = client.get_endpoint(hostname=hostname, orchestrator_id=orchestrator_id, workload_id=workload_id) except KeyError: # Calico doesn't know about this container. Continue. pass else: # Calico already set up networking for this container. Since we got # called with an IP address, we shouldn't just silently exit, since # that would confuse the user: the container would not be reachable on # that IP address. print "%s has already been configured with Calico Networking." % \ container_id sys.exit(1) # Check the IP is in the allocation pool. If it isn't, BIRD won't export # it. ip = IPAddress(ip) pool = get_pool_or_exit(ip) # The next hop IPs for this host are stored in etcd. next_hops = client.get_default_next_hops(hostname) try: next_hops[ip.version] except KeyError: print "This node is not configured for IPv%d." % ip.version sys.exit(1) # Assign the IP if not client.assign_address(pool, ip): print "IP address is already assigned in pool %s " % pool sys.exit(1) # Get the next hop for the IP address. next_hop = next_hops[ip.version] network = IPNetwork(IPAddress(ip)) ep = Endpoint(hostname=hostname, orchestrator_id=DOCKER_ORCHESTRATOR_ID, workload_id=workload_id, endpoint_id=uuid.uuid1().hex, state="active", mac=None) if network.version == 4: ep.ipv4_nets.add(network) ep.ipv4_gateway = next_hop else: ep.ipv6_nets.add(network) ep.ipv6_gateway = next_hop # Create the veth, move into the container namespace, add the IP and # set up the default routes. netns.create_veth(ep.name, ep.temp_interface_name) netns.move_veth_into_ns(namespace, ep.temp_interface_name, interface) netns.add_ip_to_ns_veth(namespace, ip, interface) netns.add_ns_default_route(namespace, next_hop, interface) # Grab the MAC assigned to the veth in the namespace. ep.mac = netns.get_ns_veth_mac(namespace, interface) # Register the endpoint with Felix. client.set_endpoint(ep) # Let the caller know what endpoint was created. return ep
def container_ip_add(container_name, ip, interface): """ Add an IP address to an existing Calico networked container. :param container_name: The name of the container. :param ip: The IP to add :param interface: The name of the interface in the container. :return: None """ address = IPAddress(ip) # The netns manipulations must be done as root. enforce_root() pool = get_pool_or_exit(address) info = get_container_info_or_exit(container_name) container_id = info["Id"] # Check the container is actually running. if not info["State"]["Running"]: print "%s is not currently running." % container_name sys.exit(1) # Check that the container is already networked try: endpoint = client.get_endpoint(hostname=hostname, orchestrator_id=ORCHESTRATOR_ID, workload_id=container_id) except KeyError: print "Failed to add IP address to container.\n" print_container_not_in_calico_msg(container_name) sys.exit(1) # From here, this method starts having side effects. If something # fails then at least try to leave the system in a clean state. if not client.assign_address(pool, address): print "IP address is already assigned in pool %s " % pool sys.exit(1) try: if address.version == 4: endpoint.ipv4_nets.add(IPNetwork(address)) else: endpoint.ipv6_nets.add(IPNetwork(address)) client.update_endpoint(endpoint) except (KeyError, ValueError): client.unassign_address(pool, ip) print "Error updating datastore. Aborting." sys.exit(1) try: container_pid = info["State"]["Pid"] netns.add_ip_to_ns_veth(container_pid, address, interface) except CalledProcessError: print "Error updating networking in container. Aborting." if address.version == 4: endpoint.ipv4_nets.remove(IPNetwork(address)) else: endpoint.ipv6_nets.remove(IPNetwork(address)) client.update_endpoint(endpoint) client.unassign_address(pool, ip) sys.exit(1) print "IP %s added to %s" % (ip, container_id)
def container_add(container_name, ip, interface): """ Add a container (on this host) to Calico networking with the given IP. :param container_name: The name or ID of the container. :param ip: An IPAddress object with the desired IP to assign. :param interface: The name of the interface in the container. """ # The netns manipulations must be done as root. enforce_root() info = get_container_info_or_exit(container_name) container_id = info["Id"] # Check if the container already exists try: _ = client.get_endpoint(hostname=hostname, orchestrator_id=ORCHESTRATOR_ID, workload_id=container_id) except KeyError: # Calico doesn't know about this container. Continue. pass else: # Calico already set up networking for this container. Since we got # called with an IP address, we shouldn't just silently exit, since # that would confuse the user: the container would not be reachable on # that IP address. print "%s has already been configured with Calico Networking." % \ container_name sys.exit(1) # Check the container is actually running. if not info["State"]["Running"]: print "%s is not currently running." % container_name sys.exit(1) # We can't set up Calico if the container shares the host namespace. if info["HostConfig"]["NetworkMode"] == "host": print "Can't add %s to Calico because it is " \ "running NetworkMode = host." % container_name sys.exit(1) # Check the IP is in the allocation pool. If it isn't, BIRD won't export # it. ip = IPAddress(ip) pool = get_pool_or_exit(ip) # The next hop IPs for this host are stored in etcd. next_hops = client.get_default_next_hops(hostname) try: next_hops[ip.version] except KeyError: print "This node is not configured for IPv%d." % ip.version sys.exit(1) # Assign the IP if not client.assign_address(pool, ip): print "IP address is already assigned in pool %s " % pool sys.exit(1) # Get the next hop for the IP address. next_hop = next_hops[ip.version] network = IPNetwork(IPAddress(ip)) ep = Endpoint(hostname=hostname, orchestrator_id=ORCHESTRATOR_ID, workload_id=container_id, endpoint_id=uuid.uuid1().hex, state="active", mac=None) if network.version == 4: ep.ipv4_nets.add(network) ep.ipv4_gateway = next_hop else: ep.ipv6_nets.add(network) ep.ipv6_gateway = next_hop # Create the veth, move into the container namespace, add the IP and # set up the default routes. pid = info["State"]["Pid"] netns.create_veth(ep.name, ep.temp_interface_name) netns.move_veth_into_ns(pid, ep.temp_interface_name, interface) netns.add_ip_to_ns_veth(pid, ip, interface) netns.add_ns_default_route(pid, next_hop, interface) # Grab the MAC assigned to the veth in the namespace. ep.mac = netns.get_ns_veth_mac(pid, interface) # Register the endpoint with Felix. client.set_endpoint(ep) # Let the caller know what endpoint was created. return ep
def container_add(container_id, ip, interface): """ Add a container (on this host) to Calico networking with the given IP. :param container_id: The namespace path or the docker name/ID of the container. :param ip: An IPAddress object with the desired IP to assign. :param interface: The name of the interface in the container. """ # The netns manipulations must be done as root. enforce_root() # TODO: This section is redundant in container_add_ip and elsewhere if container_id.startswith("/") and os.path.exists(container_id): # The ID is a path. Don't do any docker lookups workload_id = escape_etcd(container_id) orchestrator_id = NAMESPACE_ORCHESTRATOR_ID namespace = netns.Namespace(container_id) else: info = get_container_info_or_exit(container_id) workload_id = info["Id"] orchestrator_id = DOCKER_ORCHESTRATOR_ID namespace = netns.PidNamespace(info["State"]["Pid"]) # Check the container is actually running. if not info["State"]["Running"]: print_paragraph("%s is not currently running." % container_id) sys.exit(1) # We can't set up Calico if the container shares the host namespace. if info["HostConfig"]["NetworkMode"] == "host": print_paragraph("Can't add %s to Calico because it is " "running NetworkMode = host." % container_id) sys.exit(1) # Check if the container already exists try: _ = client.get_endpoint(hostname=hostname, orchestrator_id=orchestrator_id, workload_id=workload_id) except KeyError: # Calico doesn't know about this container. Continue. pass else: # Calico already set up networking for this container. Since we got # called with an IP address, we shouldn't just silently exit, since # that would confuse the user: the container would not be reachable on # that IP address. print_paragraph("%s has already been configured with Calico " "Networking." % container_id) sys.exit(1) ep = Endpoint(hostname=hostname, orchestrator_id=DOCKER_ORCHESTRATOR_ID, workload_id=workload_id, endpoint_id=uuid.uuid1().hex, state="active", mac=None) ip, _ = get_ip_and_pool(ip) network = IPNetwork(ip) if network.version == 4: ep.ipv4_nets.add(network) else: ep.ipv6_nets.add(network) # Create the veth, move into the container namespace, add the IP and # set up the default routes. netns.increment_metrics(namespace) netns.create_veth(ep.name, ep.temp_interface_name) netns.move_veth_into_ns(namespace, ep.temp_interface_name, interface) netns.add_ip_to_ns_veth(namespace, ip, interface) netns.add_ns_default_route(namespace, ep.name, interface) # Grab the MAC assigned to the veth in the namespace. ep.mac = netns.get_ns_veth_mac(namespace, interface) # Register the endpoint with Felix. client.set_endpoint(ep) # Let the caller know what endpoint was created. print_paragraph("IP %s added to %s" % (str(ip), container_id)) return ep