def ip_pool_range_add(start_ip, end_ip, version, ipip, masquerade): """ Add the range of ip addresses as CIDRs to the IP address allocation pool. :param start_ip: The first ip address the ip range. :param end_ip: The last ip address in the ip range. :param version: 4 or 6 :param ipip: Use IP in IP for this pool. :return: None """ if version == 6 and ipip: print "IP in IP not supported for IPv6 pools" sys.exit(1) ip_range = IPRange(start_ip, end_ip) pools = client.get_ip_pools(version) for pool in pools: pool_net = IPNetwork(pool.cidr) # Reject the new ip range if any of the following are true: # - The new ip range contains all ips of any existing pool # - An existing pool overlaps ips with the start of the new ip range # - An existing pool overlaps ips with the end of the new ip range if (pool_net in ip_range or start_ip in pool_net or end_ip in pool_net): print "Cannot add range - range conflicts with pool %s" % pool.cidr sys.exit(1) cidrs = netaddr.iprange_to_cidrs(start_ip, end_ip) for ip_net in cidrs: new_pool = IPPool(ip_net.cidr, ipip=ipip, masquerade=masquerade) client.add_ip_pool(version, new_pool)
def get_pool_or_exit(ip): """ Get the first allocation pool that an IP is in. :param ip: The IPAddress to find the pool for. :return: The pool or sys.exit """ pools = client.get_ip_pools("v%s" % ip.version) pool = None for candidate_pool in pools: if ip in candidate_pool: pool = candidate_pool break if pool is None: print "%s is not in any configured pools" % ip sys.exit(1) return pool
def get_pool_or_exit(ip): """ Get the first allocation pool that an IP is in. :param ip: The IPAddress to find the pool for. :return: The pool or sys.exit """ pools = client.get_ip_pools(ip.version) pool = None for candidate_pool in pools: if ip in candidate_pool: pool = candidate_pool break if pool is None: print "%s is not in any configured pools" % ip sys.exit(1) return pool
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("v%s" % 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_endpoint(endpoint.endpoint_id) # 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 ip_pool_show(version): """ Print a list of IP allocation pools. :return: None """ assert version in ("v4", "v6") headings = ["IP%s CIDR" % version, "Options"] pools = client.get_ip_pools(version) x = PrettyTable(headings) for pool in pools: enabled_options = [] if version == "v4": if pool.ipip: enabled_options.append("ipip") if pool.masquerade: enabled_options.append("nat-outgoing") # convert option array to string row = [str(pool.cidr), ','.join(enabled_options)] x.add_row(row) print x.get_string(sortby=headings[0])
def ip_pool_show(version): """ Print a list of IP allocation pools. :return: None """ assert version in (4, 6) headings = ["IPv%s CIDR" % version, "Options"] pools = client.get_ip_pools(version) x = PrettyTable(headings) for pool in pools: enabled_options = [] if version == 4: if pool.ipip: enabled_options.append("ipip") if pool.masquerade: enabled_options.append("nat-outgoing") # convert option array to string row = [str(pool.cidr), ','.join(enabled_options)] x.add_row(row) print x.get_string(sortby=headings[0])
def node_start(node_image, log_dir, ip, ip6, as_num, detach, kubernetes): """ Create the calico-node container and establish Calico networking on this host. :param ip: The IPv4 address of the host. :param node_image: The calico-node image to use. :param ip6: The IPv6 address of the host (or None if not configured) :param as_num: The BGP AS Number to use for this node. If not specified the global default value will be used. :param detach: True to run in Docker's "detached" mode, False to run attached. :return: None. """ # Ensure log directory exists if not os.path.exists(log_dir): os.makedirs(log_dir) # Print warnings for any known system issues before continuing check_system(fix=False, quit_if_error=False) # Get IP address of host, if none was specified if not ip: ips = get_host_ips(exclude=["docker0"]) try: ip = ips.pop() except IndexError: print "Couldn't autodetect a management IP address. Please provide" \ " an IP by rerunning the command with the --ip=<IP_ADDRESS> flag." sys.exit(1) else: print "No IP provided. Using detected IP: %s" % ip # Verify that the chosen IP exists on the current host warn_if_unknown_ip(ip, ip6) # Warn if this hostname conflicts with an existing host warn_if_hostname_conflict(ip) # Install kubernetes plugin if kubernetes: try: # Attempt to install to the default kubernetes directory install_kubernetes(KUBERNETES_PLUGIN_DIR) except OSError: # Use the backup directory install_kubernetes(KUBERNETES_PLUGIN_DIR_BACKUP) # Set up etcd ipv4_pools = client.get_ip_pools(4) ipv6_pools = client.get_ip_pools(6) # Create default pools if required if not ipv4_pools: client.add_ip_pool(4, DEFAULT_IPV4_POOL) if not ipv6_pools: client.add_ip_pool(6, DEFAULT_IPV6_POOL) client.ensure_global_config() client.create_host(hostname, ip, ip6, as_num) try: docker_client.remove_container("calico-node", force=True) except docker.errors.APIError as err: if err.response.status_code != 404: raise etcd_authority = os.getenv(ETCD_AUTHORITY_ENV, ETCD_AUTHORITY_DEFAULT) etcd_authority_split = etcd_authority.split(':') if len(etcd_authority_split) != 2: print_paragraph("Invalid %s. Must take the form <address>:<port>. Value " \ "provided is '%s'" % (ETCD_AUTHORITY_ENV, etcd_authority)) sys.exit(1) etcd_authority_address = etcd_authority_split[0] etcd_authority_port = etcd_authority_split[1] # Always try to convert the address(hostname) to an IP. This is a noop if # the address is already an IP address. etcd_authority = '%s:%s' % (socket.gethostbyname(etcd_authority_address), etcd_authority_port) environment = [ "HOSTNAME=%s" % hostname, "IP=%s" % ip, "IP6=%s" % (ip6 or ""), "ETCD_AUTHORITY=%s" % etcd_authority, # etcd host:port "FELIX_ETCDADDR=%s" % etcd_authority, # etcd host:port ] binds = { "/proc": { "bind": "/proc_host", "ro": False }, log_dir: { "bind": "/var/log/calico", "ro": False }, "/run/docker/plugins": { "bind": "/usr/share/docker/plugins", "ro": False } } host_config = docker.utils.create_host_config( privileged=True, restart_policy={"Name": "Always"}, network_mode="host", binds=binds) _find_or_pull_node_image(node_image, docker_client) container = docker_client.create_container( node_image, name="calico-node", detach=True, environment=environment, host_config=host_config, volumes=["/proc_host", "/var/log/calico", "/usr/share/docker/plugins"]) cid = container["Id"] docker_client.start(container) print "Calico node is running with id: %s" % cid if not detach: _attach_and_stream(container)