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"
def _container_remove(hostname, orchestrator_id, container_id): """ Remove the indicated container on this host from Calico networking :param hostname (str): Host for enndpoint allocation :param orchestrator_id (str): Specifies orchestrator ('rkt') :param container_id (str): """ # Find the endpoint ID. We need this to find any ACL rules try: endpoint = datastore_client.get_endpoint( hostname=hostname, orchestrator_id=orchestrator_id, workload_id=container_id) except KeyError: _log.error("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, "Only 1 address allowed per endpoint. Found in network: %s" % net datastore_client.unassign_address(None, net.ip) # Remove the endpoint netns.remove_veth(endpoint.name) # Remove the container from the datastore. datastore_client.remove_workload(hostname=hostname, orchestrator_id=orchestrator_id, workload_id=container_id) _log.info("Removed Calico interface from %s" % container_id)
def _container_remove(self): """ Remove the indicated container on this host from Calico networking """ # Find the endpoint ID. We need this to find any ACL rules try: endpoint = self._datastore_client.get_endpoint( hostname=HOSTNAME, orchestrator_id=ORCHESTRATOR_ID, workload_id=self.docker_id ) except KeyError: logger.exception("Container %s doesn't contain any endpoints", self.docker_id) sys.exit(1) # Remove any IP address assignments that this endpoint has ip_set = set() for net in endpoint.ipv4_nets | endpoint.ipv6_nets: ip_set.add(net.ip) logger.info("Removing IP addresses %s from endpoint %s", ip_set, endpoint.name) self._datastore_client.release_ips(ip_set) # Remove the veth interface from endpoint logger.info("Removing veth interface from endpoint %s", endpoint.name) try: netns.remove_veth(endpoint.name) except CalledProcessError: logger.exception("Could not remove veth interface from " "endpoint %s", endpoint.name) # Remove the container/endpoint from the datastore. try: self._datastore_client.remove_workload(HOSTNAME, ORCHESTRATOR_ID, self.docker_id) logger.info("Successfully removed workload from datastore") except KeyError: logger.exception("Failed to remove workload.") logger.info("Removed Calico interface from %s", self.docker_id)
def _container_remove(hostname, orchestrator_id, container_id, client): """ Remove the indicated container on this host from Calico networking """ # 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=container_id) except KeyError: print_stderr("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) client.unassign_address(None, net.ip) # Remove the endpoint netns.remove_veth(endpoint.name) # Remove the container from the datastore. client.remove_workload(hostname, orchestrator_id, container_id) print_stderr("Removed Calico interface from %s" % container_id)
def _remove_endpoint(self, endpoint): """ Remove the provided endpoint on this host from Calico networking. - Removes any IP address assignments. - Removes the veth interface for this endpoint. - Removes the endpoint object from etcd. """ # Remove any IP address assignments that this endpoint has ip_set = set() for net in endpoint.ipv4_nets | endpoint.ipv6_nets: ip_set.add(net.ip) logger.info("Removing IP addresses %s from endpoint %s", ip_set, endpoint.name) self._datastore_client.release_ips(ip_set) # Remove the veth interface from endpoint logger.info("Removing veth interfaces") try: netns.remove_veth(endpoint.name) except CalledProcessError: logger.exception( "Could not remove veth interface from " "endpoint %s", endpoint.name) # Remove endpoint from the datastore. try: self._datastore_client.remove_workload(HOSTNAME, ORCHESTRATOR_ID, self.docker_id) except KeyError: logger.exception("Error removing workload.") logger.info("Removed Calico endpoint %s", endpoint.endpoint_id)
def _remove_endpoint(self, endpoint): """ Remove the provided endpoint on this host from Calico networking. - Removes any IP address assignments. - Removes the veth interface for this endpoint. - Removes the endpoint object from etcd. """ # Remove any IP address assignments that this endpoint has ip_set = set() for net in endpoint.ipv4_nets | endpoint.ipv6_nets: ip_set.add(net.ip) logger.info("Removing IP addresses %s from endpoint %s", ip_set, endpoint.name) self._datastore_client.release_ips(ip_set) # Remove the veth interface from endpoint logger.info("Removing veth interfaces") try: netns.remove_veth(endpoint.name) except CalledProcessError: logger.exception("Could not remove veth interface from " "endpoint %s", endpoint.name) # Remove endpoint from the datastore. try: self._datastore_client.remove_workload( HOSTNAME, ORCHESTRATOR_ID, self.docker_id) except KeyError: logger.exception("Error removing workload.") logger.info("Removed Calico endpoint %s", endpoint.endpoint_id)
def _container_remove(hostname, orchestrator_id, container_id): """ Remove the indicated container on this host from Calico networking :param hostname (str): Host for enndpoint allocation :param orchestrator_id (str): Specifies orchestrator ('rkt') :param container_id (str): """ # Find the endpoint ID. We need this to find any ACL rules try: endpoint = datastore_client.get_endpoint(hostname=hostname, orchestrator_id=orchestrator_id, workload_id=container_id) except KeyError: _log.error("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, "Only 1 address allowed per endpoint. Found in network: %s" % net datastore_client.unassign_address(None, net.ip) # Remove the endpoint netns.remove_veth(endpoint.name) # Remove the container from the datastore. datastore_client.remove_workload(hostname=hostname, orchestrator_id=orchestrator_id, workload_id=container_id) _log.info("Removed Calico interface from %s" % container_id)
def remove_veth(endpoint): """ Best effort removal of veth, logging if removal fails. :param endpoint: The Endpoint tied to the veth. """ try: netns.remove_veth(endpoint.name) except CalledProcessError: app.logger.warn("Failed to delete veth %s", endpoint.name)
def remove_veth(name): """ Best effort removal of veth, logging if removal fails. :param name: The name of the veth to remove """ try: netns.remove_veth(name) except CalledProcessError: app.logger.warn("Failed to delete veth %s", name)
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"
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"
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 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
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
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 test_remove_veth_success(self, m_check_output, m_veth_exists): """ Test remove_veth returns True for successfully removing a veth. """ m_veth_exists.return_value = True self.assertTrue(remove_veth("veth1")) m_veth_exists.assert_called_once_with("veth1") m_check_output.assert_called_once_with(["ip", "link", "del", "veth1"], timeout=IP_CMD_TIMEOUT)
def test_remove_veth_no_veth(self, m_check_call, m_veth_exists): """ Test remove_veth returns False when veth doesn't exist. """ m_veth_exists.return_value = False; self.assertFalse(remove_veth("veth1")) m_veth_exists.assert_called_once_with("veth1") self.assertFalse(m_check_call.called)
def test_remove_veth_success(self, m_check_call, m_veth_exists): """ Test remove_veth returns True for successfully removing a veth. """ m_veth_exists.return_value = True; self.assertTrue(remove_veth("veth1")) m_veth_exists.assert_called_once_with("veth1") m_check_call.assert_called_once_with(['ip', 'link', 'del', "veth1"], timeout=IP_CMD_TIMEOUT)
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 _remove_veth(self, endpoint): """Remove the veth from given endpoint. Handles any errors encountered while removing the endpoint. """ _log.info("Removing veth for endpoint: %s", endpoint.name) try: removed = netns.remove_veth(endpoint.name) _log.debug("Successfully removed endpoint %s? %s", endpoint.name, removed) except CalledProcessError: _log.warning("Unable to remove veth %s", endpoint.name)
def _container_remove(self): """ Remove the indicated container on this host from Calico networking """ # Find the endpoint ID. We need this to find any ACL rules try: endpoint = self._datastore_client.get_endpoint( hostname=HOSTNAME, orchestrator_id=ORCHESTRATOR_ID, workload_id=self.docker_id ) except KeyError: logger.exception("Container %s doesn't contain any endpoints", self.docker_id) sys.exit(1) # Remove any IP address assignments that this endpoint has ip_set = set() for net in endpoint.ipv4_nets | endpoint.ipv6_nets: ip_set.add(net.ip) logger.info("Removing IP addresses %s from endpoint %s", ip_set, endpoint.name) self._datastore_client.release_ips(ip_set) # Remove the veth interface from endpoint logger.info("Removing veth interfaces") try: netns.remove_veth(endpoint.name) except CalledProcessError: logger.exception("Could not remove veth interface from " "endpoint %s", endpoint.name) # Remove the container/endpoint from the datastore. try: self._datastore_client.remove_workload( HOSTNAME, ORCHESTRATOR_ID, self.docker_id) except KeyError: logger.exception("Failed to remove workload.") logger.info("Removed Calico endpoint %s", endpoint.endpoint_id)