Пример #1
0
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
        orchestrator_id = NAMESPACE_ORCHESTRATOR_ID
        endpoints = client.get_endpoints(hostname=hostname,
                                         orchestrator_id=orchestrator_id,
                                         workload_id=escape_etcd(container_id))
    else:
        # We know we're using "docker" as the orchestrator. If we have a direct
        # hit on the container id then we can proceed. Otherwise, ask docker to
        # try converting the name/id fragment into a full ID.
        orchestrator_id = DOCKER_ORCHESTRATOR_ID
        endpoints = client.get_endpoints(hostname=hostname,
                                         orchestrator_id=orchestrator_id,
                                         workload_id=container_id)

        if not endpoints:
            container_id = get_workload_id(container_id)
            endpoints = client.get_endpoints(hostname=hostname,
                                             orchestrator_id=orchestrator_id,
                                             workload_id=container_id)

    for endpoint in endpoints:
        # Remove any IP address assignments that this endpoint has
        client.release_ips(
            set(map(IPAddress, endpoint.ipv4_nets | endpoint.ipv6_nets)))

        try:
            # Remove the interface if it exists
            netns.remove_veth(endpoint.name)
        except CalledProcessError:
            print "Could not remove Calico interface %s" % endpoint.name

    # Always try to remove the workload, even if we didn't find any
    # endpoints.
    try:
        client.remove_workload(hostname, orchestrator_id, container_id)
        print "Removed Calico from %s" % container_id
    except KeyError:
        print "Failed find Calico data for %s" % container_id
Пример #2
0
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
        orchestrator_id = NAMESPACE_ORCHESTRATOR_ID
        endpoints = client.get_endpoints(hostname=hostname,
                                         orchestrator_id=orchestrator_id,
                                         workload_id=escape_etcd(container_id))
    else:
        # We know we're using "docker" as the orchestrator. If we have a direct
        # hit on the container id then we can proceed. Otherwise, ask docker to
        # try converting the name/id fragment into a full ID.
        orchestrator_id = DOCKER_ORCHESTRATOR_ID
        endpoints = client.get_endpoints(hostname=hostname,
                                         orchestrator_id=orchestrator_id,
                                         workload_id=container_id)

        if not endpoints:
            container_id = get_workload_id(container_id)
            endpoints = client.get_endpoints(hostname=hostname,
                                             orchestrator_id=orchestrator_id,
                                             workload_id=container_id)

    for endpoint in endpoints:
        # Remove any IP address assignments that this endpoint has
        client.release_ips(set(map(IPAddress,
                                   endpoint.ipv4_nets | endpoint.ipv6_nets)))

        try:
            # Remove the interface if it exists
            netns.remove_veth(endpoint.name)
        except CalledProcessError:
            print "Could not remove Calico interface %s" % endpoint.name

    # Always try to remove the workload, even if we didn't find any
    # endpoints.
    try:
        client.remove_workload(hostname, orchestrator_id, container_id)
        print "Removed Calico from %s" % container_id
    except KeyError:
        print "Failed find Calico data for %s" % container_id
Пример #3
0
def node_stop(force):
    """
    Stop the Calico node.  This stops the containers (calico/node and
    calico/node-libnetwork) that are started by calicoctl node.
    """
    endpoints = len(client.get_endpoints(hostname=hostname))
    if endpoints:
        if not force:
            print_paragraph("Current host has active endpoints so can't be "
                "stopped.  Force with --force")
            print_paragraph("Note that stopping the node while there are "
                            "active endpoints may make it difficult to clean "
                            "up the endpoints: for example, Docker containers "
                            "networked using libnetwork with Calico will not "
                            "invoke network cleanup during the normal "
                            "container lifecycle.")
            sys.exit(1)
        else:
            print_paragraph("Stopping node while host has active endpoints.  "
                            "If this in error, restart the node using the "
                            "'calicoctl node' command.")

    try:
        docker_client.stop("calico-node")
    except docker.errors.APIError as err:
        if err.response.status_code != 404:
            raise
    try:
        docker_client.stop("calico-libnetwork")
    except docker.errors.APIError as err:
        if err.response.status_code != 404:
            raise

    print "Node stopped"
Пример #4
0
def node_remove(remove_endpoints):
    """
    Remove a node from the Calico network.
    :param remove_endpoints: Whether the endpoint data should be forcibly
    removed.
    """
    if _container_running("calico-node") or \
       _container_running("calico-libnetwork"):
        print_paragraph("The node cannot be removed while it is running.  "
                        "Please run 'calicoctl node stop' to stop the node "
                        "before removing it.")
        sys.exit(1)

    endpoints = client.get_endpoints(hostname=hostname)
    if endpoints and not remove_endpoints:
        print_paragraph("The node has active Calico endpoints so can't be "
                        "deleted. Force with --remove-endpoints")
        print_paragraph("Note that forcible removing the node may leave some "
                        "workloads in an indeterminate networked state.  If "
                        "this is in error, you may restart the node using the "
                        "'calicoctl node' command and clean up the workloads "
                        "in the normal way.")
        sys.exit(1)

    for endpoint in endpoints:
        remove_veth(endpoint.name)
    client.remove_host(hostname)

    print "Node configuration removed"
Пример #5
0
def node_remove(remove_endpoints):
    """
    Remove a node from the Calico network.
    :param remove_endpoints: Whether the endpoint data should be forcibly
    removed.
    """
    if _container_running("calico-node") or \
       _container_running("calico-libnetwork"):
        print_paragraph("The node cannot be removed while it is running.  "
                        "Please run 'calicoctl node stop' to stop the node "
                        "before removing it.")
        sys.exit(1)

    endpoints = client.get_endpoints(hostname=hostname)
    if endpoints and not remove_endpoints:
        print_paragraph("The node has active Calico endpoints so can't be "
                        "deleted. Force with --remove-endpoints")
        print_paragraph("Note that forcible removing the node may leave some "
                        "workloads in an indeterminate networked state.  If "
                        "this is in error, you may restart the node using the "
                        "'calicoctl node' command and clean up the workloads "
                        "in the normal way.")
        sys.exit(1)

    for endpoint in endpoints:
        remove_veth(endpoint.name)
    client.remove_host(hostname)

    print "Node configuration removed"
Пример #6
0
def node_stop(force):
    """
    Stop the Calico node.  This stops the containers (calico/node and
    calico/node-libnetwork) that are started by calicoctl node.
    """
    endpoints = len(client.get_endpoints(hostname=hostname))
    if endpoints:
        if not force:
            print_paragraph("Current host has active endpoints so can't be "
                            "stopped.  Force with --force")
            print_paragraph("Note that stopping the node while there are "
                            "active endpoints may make it difficult to clean "
                            "up the endpoints: for example, Docker containers "
                            "networked using libnetwork with Calico will not "
                            "invoke network cleanup during the normal "
                            "container lifecycle.")
            sys.exit(1)
        else:
            print_paragraph("Stopping node while host has active endpoints.  "
                            "If this in error, restart the node using the "
                            "'calicoctl node' command.")

    try:
        docker_client.stop("calico-node")
    except docker.errors.APIError as err:
        if err.response.status_code != 404:
            raise
    try:
        docker_client.stop("calico-libnetwork")
    except docker.errors.APIError as err:
        if err.response.status_code != 404:
            raise

    print "Node stopped"
Пример #7
0
def node_remove(remove_endpoints, host):
    """
    Remove a node from the Calico network.
    :param remove_endpoints: Whether the endpoint data should be forcibly
    removed.
    :param host: The hostname of the host whose node will be removed, or None if
    removing this host's node.
    :return: None.
    """
    host_to_remove = host or hostname

    if host_to_remove == hostname and (
            _container_running("calico-node")
            or _container_running("calico-libnetwork")):
        print_paragraph("The node cannot be removed while it is running.  "
                        "Please run 'calicoctl node stop' to stop the node "
                        "before removing it.")
        sys.exit(1)

    endpoints = client.get_endpoints(hostname=host_to_remove)
    if endpoints and not remove_endpoints:
        print_paragraph("The node has active Calico endpoints so can't be "
                        "deleted. Force with --remove-endpoints")
        print_paragraph("Note that forcible removing the node may leave some "
                        "workloads in an indeterminate networked state.  If "
                        "this is in error, you may restart the node using the "
                        "'calicoctl node' command and clean up the workloads "
                        "in the normal way.")
        sys.exit(1)

    # Remove the veths, and release all IPs associated with the endpoints.  To
    # release the IPs, we construct a set of all IP addresses across all
    # endpoints (this assumes the endpoint nets are all single IPs).
    ips = set()
    for endpoint in endpoints:
        remove_veth(endpoint.name)
        ips |= {net.ip for net in endpoint.ipv4_nets}
        ips |= {net.ip for net in endpoint.ipv6_nets}
    client.release_ips(ips)

    # Remove the IPAM host data.
    client.remove_ipam_host(host_to_remove)

    # If the host had an IPIP tunnel address, release it back to the IPAM pool
    # so that we don't leak it when we delete the config.
    raw_addr = client.get_per_host_config(host_to_remove, "IpInIpTunnelAddr")
    try:
        ip_addr = IPAddress(raw_addr)
        client.release_ips({ip_addr})
    except (AddrFormatError, ValueError, TypeError):
        pass

    client.remove_per_host_config(host_to_remove, "IpInIpTunnelAddr")
    client.remove_host(host_to_remove)

    print "Node configuration removed"
Пример #8
0
def node_remove(remove_endpoints, host):
    """
    Remove a node from the Calico network.
    :param remove_endpoints: Whether the endpoint data should be forcibly
    removed.
    :param host: The hostname of the host whose node will be removed, or None if
    removing this host's node.
    :return: None.
    """
    host_to_remove = host or hostname

    if host_to_remove == hostname and (_container_running("calico-node") or
                                       _container_running("calico-libnetwork")):
        print_paragraph("The node cannot be removed while it is running.  "
                        "Please run 'calicoctl node stop' to stop the node "
                        "before removing it.")
        sys.exit(1)

    endpoints = client.get_endpoints(hostname=host_to_remove)
    if endpoints and not remove_endpoints:
        print_paragraph("The node has active Calico endpoints so can't be "
                        "deleted. Force with --remove-endpoints")
        print_paragraph("Note that forcible removing the node may leave some "
                        "workloads in an indeterminate networked state.  If "
                        "this is in error, you may restart the node using the "
                        "'calicoctl node' command and clean up the workloads "
                        "in the normal way.")
        sys.exit(1)

    # Remove the veths, and release all IPs associated with the endpoints.  To
    # release the IPs, we construct a set of all IP addresses across all
    # endpoints (this assumes the endpoint nets are all single IPs).
    ips = set()
    for endpoint in endpoints:
        remove_veth(endpoint.name)
        ips |= {net.ip for net in endpoint.ipv4_nets}
        ips |= {net.ip for net in endpoint.ipv6_nets}
    client.release_ips(ips)

    # Remove the IPAM host data.
    client.remove_ipam_host(host_to_remove)

    # If the host had an IPIP tunnel address, release it back to the IPAM pool
    # so that we don't leak it when we delete the config.
    raw_addr = client.get_per_host_config(host_to_remove, "IpInIpTunnelAddr")
    try:
        ip_addr = IPAddress(raw_addr)
        client.release_ips({ip_addr})
    except (AddrFormatError, ValueError, TypeError):
        pass

    client.remove_per_host_config(host_to_remove, "IpInIpTunnelAddr")
    client.remove_host(host_to_remove)

    print "Node configuration removed"
Пример #9
0
def node_stop(force):
    if force or len(client.get_endpoints(hostname=hostname,
                                         orchestrator_id=DOCKER_ORCHESTRATOR_ID)) == 0:
        client.remove_host(hostname)
        try:
            docker_client.stop("calico-node")
        except docker.errors.APIError as err:
            if err.response.status_code != 404:
                raise

        print "Node stopped and all configuration removed"
    else:
        print "Current host has active endpoints so can't be stopped." + \
              " Force with --force"
Пример #10
0
def node_stop(force):
    if force or len(client.get_endpoints(hostname=hostname,
                                         orchestrator_id=DOCKER_ORCHESTRATOR_ID)) == 0:
        client.remove_host(hostname)
        try:
            docker_client.stop("calico-node")
        except docker.errors.APIError as err:
            if err.response.status_code != 404:
                raise

        print "Node stopped and all configuration removed"
    else:
        print "Current host has active endpoints so can't be stopped." + \
              " Force with --force"
Пример #11
0
def endpoint_show(hostname, orchestrator_id, workload_id, endpoint_id,
                  detailed):
    """
    List the profiles for a given endpoint. All parameters will be used to
    filter down which endpoints should be shown.

    :param endpoint_id: The endpoint ID.
    :param workload_id: The workload ID.
    :param orchestrator_id: The orchestrator ID.
    :param hostname: The hostname.
    :param detailed: Optional flag, when set to True, will provide more
    information in the shown table
    :return: Nothing
    """
    endpoints = client.get_endpoints(hostname=hostname,
                                     orchestrator_id=orchestrator_id,
                                     workload_id=workload_id,
                                     endpoint_id=endpoint_id)

    if detailed:
        headings = [
            "Hostname", "Orchestrator ID", "Workload ID", "Endpoint ID",
            "Addresses", "MAC", "Profiles", "State"
        ]
        x = PrettyTable(headings, sortby="Hostname")

        for endpoint in endpoints:
            addresses = "\n".join(
                [str(net) for net in endpoint.ipv4_nets | endpoint.ipv6_nets])
            x.add_row([
                endpoint.hostname, endpoint.orchestrator_id,
                endpoint.workload_id, endpoint.endpoint_id, addresses,
                endpoint.mac, ','.join(endpoint.profile_ids), endpoint.state
            ])
    else:
        headings = [
            "Hostname", "Orchestrator ID", "Number of Workloads",
            "Number of Endpoints"
        ]
        x = PrettyTable(headings, sortby="Hostname")

        # The summary table has one entry for each host/orchestrator
        # combination.  We create a dictionary to maintain the summary
        # information, using the (hostname, orchestrator_id) as the unique
        # key, with a value of an EndpointSummary object to store unique
        # workload IDs and a count of endpoint IDs.
        #
        # We use a default dict to automatically create an "empty" (zero count)
        # EndpointSummary for each new table entry.
        host_orch_summary = defaultdict(EndpointSummary)
        for endpoint in endpoints:
            key = (endpoint.hostname, endpoint.orchestrator_id)
            summary = host_orch_summary[key]
            summary.add_endpoint(endpoint)

        # This table has one entry for each host/orchestrator combination.
        for key, summary in host_orch_summary.iteritems():
            hostname, orchestrator_id = key
            x.add_row([
                hostname, orchestrator_id,
                len(summary.workload_ids), summary.num_endpoints
            ])

    print str(x) + "\n"
Пример #12
0
def endpoint_show(hostname, orchestrator_id, workload_id, endpoint_id,
                  detailed):
    """
    List the profiles for a given endpoint. All parameters will be used to
    filter down which endpoints should be shown.

    :param endpoint_id: The endpoint ID.
    :param workload_id: The workload ID.
    :param orchestrator_id: The orchestrator ID.
    :param hostname: The hostname.
    :param detailed: Optional flag, when set to True, will provide more
    information in the shown table
    :return: Nothing
    """
    endpoints = client.get_endpoints(hostname=hostname,
                                     orchestrator_id=orchestrator_id,
                                     workload_id=workload_id,
                                     endpoint_id=endpoint_id)

    if detailed:
        headings = ["Hostname",
                    "Orchestrator ID",
                    "Workload ID",
                    "Endpoint ID",
                    "Addresses",
                    "MAC",
                    "Profiles",
                    "State"]
        x = PrettyTable(headings, sortby="Hostname")

        for endpoint in endpoints:
            addresses = "\n".join([str(net) for net in
                                   endpoint.ipv4_nets | endpoint.ipv6_nets])
            x.add_row([endpoint.hostname,
                       endpoint.orchestrator_id,
                       endpoint.workload_id,
                       endpoint.endpoint_id,
                       addresses,
                       endpoint.mac,
                       ','.join(endpoint.profile_ids),
                       endpoint.state])
    else:
        headings = ["Hostname",
                    "Orchestrator ID",
                    "Number of Workloads",
                    "Number of Endpoints"]
        x = PrettyTable(headings, sortby="Hostname")

        # The summary table has one entry for each host/orchestrator
        # combination.  We create a dictionary to maintain the summary
        # information, using the (hostname, orchestrator_id) as the unique
        # key, with a value of an EndpointSummary object to store unique
        # workload IDs and a count of endpoint IDs.
        #
        # We use a default dict to automatically create an "empty" (zero count)
        # EndpointSummary for each new table entry.
        host_orch_summary = defaultdict(EndpointSummary)
        for endpoint in endpoints:
            key = (endpoint.hostname, endpoint.orchestrator_id)
            summary = host_orch_summary[key]
            summary.add_endpoint(endpoint)

        # This table has one entry for each host/orchestrator combination.
        for key, summary in host_orch_summary.iteritems():
            hostname, orchestrator_id = key
            x.add_row([hostname,
                       orchestrator_id,
                       len(summary.workload_ids),
                       summary.num_endpoints])
                
    print str(x) + "\n"