def validate_arguments(arguments): """ Validate argument values: <PEER_IP> <AS_NUM> Arguments not validated: :param arguments: Docopt processed arguments """ # Validate IPs peer_ip_ok = arguments.get("<PEER_IP>") is None or \ validate_ip(arguments["<PEER_IP>"], 4) or \ validate_ip(arguments["<PEER_IP>"], 6) asnum_ok = True asnum = arguments.get("<AS_NUM>") if asnum: asnum_ok = validate_asn(asnum) # Print error messages if not peer_ip_ok: print "Invalid IP address specified." if not asnum_ok: print "Invalid AS Number specified." # Exit if not valid arguments if not (peer_ip_ok and asnum_ok): sys.exit(1)
def test_validate_asn(self, input_str, expected_result): """ Test validate_asn function """ test_result = util.validate_asn(input_str) self.assertEqual(test_result, expected_result)
def main(): # If we're running with the k8s backend, don't do any of this, # since it currently doesn't support BGP, Calico IPAM, and doesn't # require any of the etcd interactions below. if os.getenv("DATASTORE_TYPE", "") == "kubernetes": print "Using k8s backend" with open('startup.env', 'w') as f: f.write("DATASTORE_TYPE=kubernetes\n") f.write("HOSTNAME=%s\n" % hostname) return # Check to see if etcd is available. If not, wait until it is before # continuing. This is to avoid etcd / node startup race conditions. print "Waiting for etcd connection..." while os.getenv("WAIT_FOR_DATASTORE", "false") == "true": try: # Just try accessing etcd to see if we can reach it or not. client.get_host_as(hostname) except DataStoreError: # Not connected to etcd yet, wait a bit. time.sleep(1) continue else: # Connected to etcd - break out of loop. print "Connected to etcd" break # Start node. ip = os.getenv("IP") ip = ip or None if ip and not netaddr.valid_ipv4(ip): print "IP environment (%s) is not a valid IPv4 address." % ip sys.exit(1) ip6 = os.getenv("IP6") ip6 = ip6 or None if ip6 and not netaddr.valid_ipv6(ip6): print "IP6 environment (%s) is not a valid IPv6 address." % ip6 sys.exit(1) as_num = os.getenv("AS") as_num = as_num or None if as_num and not validate_asn(as_num): print "AS environment (%s) is not a AS number." % as_num sys.exit(1) # Get IP address of host, if none was specified if not ip: ips = get_host_ips(exclude=[ "^docker.*", "^cbr.*", "virbr.*", "lxcbr.*", "veth.*", "cali.*", "tunl.*", "flannel.*" ]) try: ip = str(ips.pop()) except IndexError: print "Couldn't autodetect a management IP address. Please " \ "provide an IP address by rerunning the container with the" \ " IP environment variable set." sys.exit(1) else: print "No IP provided. Using detected IP: %s" % ip # Write a startup environment file containing the IP address that may have # just been detected. # This is required because the confd templates expect to be able to fill in # some templates by fetching them from the environment. with open('startup.env', 'w') as f: f.write("IP=%s\n" % ip) f.write("HOSTNAME=%s\n" % hostname) warn_if_hostname_conflict(ip) # Verify that IPs are not already in use by another host. error_if_bgp_ip_conflict(ip, ip6) # Verify that the chosen IP exists on the current host warn_if_unknown_ip(ip, ip6) if os.getenv("NO_DEFAULT_POOLS", "").lower() != "true": # 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 the OS has not been built with IPv6 then the /proc config for IPv6 # will not be present. if not ipv6_pools and os.path.exists('/proc/sys/net/ipv6'): client.add_ip_pool(6, DEFAULT_IPV6_POOL) client.ensure_global_config() client.create_host(hostname, ip, ip6, as_num) # If IPIP is enabled, the host requires an IP address for its tunnel # device, which is in an IPIP pool. Without this, a host can't originate # traffic to a pool address because the response traffic would not be # routed via the tunnel (likely being dropped by RPF checks in the fabric). ipv4_pools = client.get_ip_pools(4) ipip_pools = [p for p in ipv4_pools if p.ipip] if ipip_pools: # IPIP is enabled, make sure the host has an address for its tunnel. _ensure_host_tunnel_addr(ipv4_pools, ipip_pools) else: # No IPIP pools, clean up any old address. _remove_host_tunnel_addr()
def main(): # If we're running with the k8s backend, don't do any of this, # since it currently doesn't support BGP, Calico IPAM, and doesn't # require any of the etcd interactions below. if os.getenv("DATASTORE_TYPE", "") == "kubernetes": print "Using k8s backend" with open("startup.env", "w") as f: f.write("export DATASTORE_TYPE=kubernetes\n") f.write("export HOSTNAME=%s\n" % hostname) return # Check to see if etcd is available. If not, wait until it is before # continuing. This is to avoid etcd / node startup race conditions. print "Waiting for etcd connection..." while os.getenv("WAIT_FOR_DATASTORE", "false") == "true": try: # Just try accessing etcd to see if we can reach it or not. client.get_host_as(hostname) except DataStoreError: # Not connected to etcd yet, wait a bit. time.sleep(1) continue else: # Connected to etcd - break out of loop. print "Connected to etcd" break # Query the currently configured host IPs try: current_ip, current_ip6 = client.get_host_bgp_ips(hostname) except KeyError: current_ip, current_ip6 = None, None # Determine the IP addresses and AS Number to use ip = os.getenv("IP") or None if ip == "autodetect": # If explicitly requesting auto-detection, set the ip to None to force # auto-detection. We print below if we are auto-detecting the IP. ip = None elif ip: if not netaddr.valid_ipv4(ip): print "IP environment (%s) is not a valid IPv4 address." % ip sys.exit(1) print "Using IPv4 address from IP environment: %s" % ip elif current_ip: print "Using configured IPv4 address: %s" % current_ip ip = current_ip # Get IP address of host, if none was specified or previously configured. if not ip: ips = get_host_ips( exclude=["^docker.*", "^cbr.*", "dummy.*", "virbr.*", "lxcbr.*", "veth.*", "cali.*", "tunl.*", "flannel.*"] ) try: ip = str(ips.pop()) except IndexError: print "Couldn't autodetect a management IPv4 address. Please " "provide an IP address either by configuring one in the " "node resource, or by re-running the container with the " "IP environment variable set." sys.exit(1) else: print "Using auto-detected IPv4 address: %s" % ip ip6 = os.getenv("IP6") or None if ip6: if not netaddr.valid_ipv6(ip6): print "IP6 environment (%s) is not a valid IPv6 address." % ip6 sys.exit(1) print "Using IPv6 address from IP6 environment: %s" % ip6 elif current_ip6: print "Using configured IPv6 address: %s" % current_ip6 ip6 = current_ip6 else: print "No IPv6 address configured" as_num = os.getenv("AS") if as_num: if not validate_asn(as_num): print "AS environment (%s) is not a valid AS number." % as_num sys.exit(1) print "Using AS number from AS environment: %s" % as_num else: as_num = client.get_host_as(hostname) if as_num: print "Using configured AS number: %s" % as_num else: print "Using global AS number" # Write a startup environment file containing the IP address that may have # just been detected. # This is required because the confd templates expect to be able to fill in # some templates by fetching them from the environment. with open("startup.env", "w") as f: f.write("export IP=%s\n" % ip) f.write("export HOSTNAME=%s\n" % hostname) warn_if_hostname_conflict(ip) # Verify that IPs are not already in use by another host. error_if_bgp_ip_conflict(ip, ip6) # Verify that the chosen IP exists on the current host warn_if_unknown_ip(ip, ip6) if os.getenv("NO_DEFAULT_POOLS", "").lower() != "true": # 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 the OS has not been built with IPv6 then the /proc config for IPv6 # will not be present. if not ipv6_pools and os.path.exists("/proc/sys/net/ipv6"): client.add_ip_pool(6, DEFAULT_IPV6_POOL) client.ensure_global_config() client.create_host(hostname, ip, ip6, as_num) # If IPIP is enabled, the host requires an IP address for its tunnel # device, which is in an IPIP pool. Without this, a host can't originate # traffic to a pool address because the response traffic would not be # routed via the tunnel (likely being dropped by RPF checks in the fabric). ipv4_pools = client.get_ip_pools(4) ipip_pools = [p for p in ipv4_pools if p.ipip] if ipip_pools: # IPIP is enabled, make sure the host has an address for its tunnel. _ensure_host_tunnel_addr(ipv4_pools, ipip_pools) else: # No IPIP pools, clean up any old address. _remove_host_tunnel_addr() # Tell the user what the name of the node is. print "Calico node name: ", hostname
def validate_arguments(arguments): """ Validate argument values: <IP> <IP6> <PEER_IP> <AS_NUM> <DETACH> Arguments not validated: <DOCKER_IMAGE_NAME> <LOG_DIR> :param arguments: Docopt processed arguments """ # Validate IPs ip_ok = arguments.get("--ip") is None or \ arguments.get("--ip") is "" or \ validate_ip(arguments.get("--ip"), 4) ip6_ok = arguments.get("--ip6") is None or \ arguments.get("--ip6") is "" or \ validate_ip(arguments.get("--ip6"), 6) container_ip_ok = arguments.get("<IP>") is None or \ validate_ip(arguments["<IP>"], 4) or \ validate_ip(arguments["<IP>"], 6) peer_ip_ok = arguments.get("<PEER_IP>") is None or \ validate_ip(arguments["<PEER_IP>"], 4) or \ validate_ip(arguments["<PEER_IP>"], 6) runtime_ok = arguments.get("--runtime") in [None, "none", "docker", "rkt"] asnum_ok = True asnum = arguments.get("<AS_NUM>") or arguments.get("--as") if asnum: asnum_ok = validate_asn(asnum) detach_ok = True if arguments.get("<DETACH>") or arguments.get("--detach"): detach_ok = arguments.get("--detach") in ["true", "false"] detach_libnetwork_ok = (arguments.get("--detach") == "true" or not arguments.get("--libnetwork")) # Print error message if not ip_ok: print "Invalid IPv4 address specified with --ip argument." if not ip6_ok: print "Invalid IPv6 address specified with --ip6 argument." if not container_ip_ok or not peer_ip_ok: print "Invalid IP address specified." if not asnum_ok: print "Invalid AS Number specified." if not detach_ok: print "Valid values for --detach are 'true' and 'false'" if not detach_libnetwork_ok: print "The only valid value for --detach is 'true' when using libnetwork" if not runtime_ok: print "Runtime must be 'docker', 'rkt' or 'none'." # Exit if not valid argument if not (ip_ok and ip6_ok and container_ip_ok and peer_ip_ok and asnum_ok and detach_ok and detach_libnetwork_ok and runtime_ok): sys.exit(1)
def main(): # Check to see if etcd is available. If not, wait until it is before # continuing. This is to avoid etcd / node startup race conditions. print "Waiting for etcd connection..." while os.getenv("WAIT_FOR_DATASTORE", "false") == "true": try: # Just try accessing etcd to see if we can reach it or not. client.get_host_as(hostname) except DataStoreError: # Not connected to etcd yet, wait a bit. time.sleep(1) continue else: # Connected to etcd - break out of loop. print "Connected to etcd" break # Start node. ip = os.getenv("IP") ip = ip or None if ip and not netaddr.valid_ipv4(ip): print "IP environment (%s) is not a valid IPv4 address." % ip sys.exit(1) ip6 = os.getenv("IP6") ip6 = ip6 or None if ip6 and not netaddr.valid_ipv6(ip6): print "IP6 environment (%s) is not a valid IPv6 address." % ip6 sys.exit(1) as_num = os.getenv("AS") as_num = as_num or None if as_num and not validate_asn(as_num): print "AS environment (%s) is not a AS number." % as_num sys.exit(1) # Get IP address of host, if none was specified if not ip: ips = get_host_ips(exclude=["^docker.*", "^cbr.*", "virbr.*", "lxcbr.*", "veth.*", "cali.*", "tunl.*", "flannel.*"]) try: ip = str(ips.pop()) except IndexError: print "Couldn't autodetect a management IP address. Please " \ "provide an IP address by rerunning the container with the" \ " IP environment variable set." sys.exit(1) else: print "No IP provided. Using detected IP: %s" % ip # Write a startup environment file containing the IP address that may have # just been detected. # This is required because the confd templates expect to be able to fill in # some templates by fetching them from the environment. with open('startup.env', 'w') as f: f.write("IP=%s\n" % ip) f.write("HOSTNAME=%s\n" % hostname) warn_if_hostname_conflict(ip) # Verify that IPs are not already in use by another host. error_if_bgp_ip_conflict(ip, ip6) # Verify that the chosen IP exists on the current host warn_if_unknown_ip(ip, ip6) if os.getenv("NO_DEFAULT_POOLS", "").lower() != "true": # 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 the OS has not been built with IPv6 then the /proc config for IPv6 # will not be present. if not ipv6_pools and os.path.exists('/proc/sys/net/ipv6'): client.add_ip_pool(6, DEFAULT_IPV6_POOL) client.ensure_global_config() client.create_host(hostname, ip, ip6, as_num) # If IPIP is enabled, the host requires an IP address for its tunnel # device, which is in an IPIP pool. Without this, a host can't originate # traffic to a pool address because the response traffic would not be # routed via the tunnel (likely being dropped by RPF checks in the fabric). ipv4_pools = client.get_ip_pools(4) ipip_pools = [p for p in ipv4_pools if p.ipip] if ipip_pools: # IPIP is enabled, make sure the host has an address for its tunnel. _ensure_host_tunnel_addr(ipv4_pools, ipip_pools) else: # No IPIP pools, clean up any old address. _remove_host_tunnel_addr()
def main(): ip = os.getenv("IP") ip = ip or None if ip and not netaddr.valid_ipv4(ip): print "IP environment (%s) is not a valid IPv4 address." % ip sys.exit(1) ip6 = os.getenv("IP6") ip6 = ip6 or None if ip6 and not netaddr.valid_ipv6(ip6): print "IP6 environment (%s) is not a valid IPv6 address." % ip6 sys.exit(1) as_num = os.getenv("AS") as_num = as_num or None if as_num and not validate_asn(as_num): print "AS environment (%s) is not a AS number." % as_num sys.exit(1) # Get IP address of host, if none was specified if not ip: ips = get_host_ips(exclude=[ "^docker.*", "^cbr.*", "virbr.*", "lxcbr.*", "veth.*", "cali.*", "tunl.*", "flannel.*" ]) try: ip = str(ips.pop()) except IndexError: print "Couldn't autodetect a management IP address. Please " \ "provide an IP address by rerunning the container with the" \ " IP environment variable set." sys.exit(1) else: print "No IP provided. Using detected IP: %s" % ip # Write a startup environment file containing the IP address that may have # just been detected. # This is required because the confd templates expect to be able to fill in # some templates by fetching them from the environment. with open('startup.env', 'w') as f: f.write("IP=%s\n" % ip) f.write("HOSTNAME=%s\n" % hostname) warn_if_hostname_conflict(ip) # Verify that IPs are not already in use by another host. error_if_bgp_ip_conflict(ip, ip6) # Verify that the chosen IP exists on the current host warn_if_unknown_ip(ip, ip6) if os.getenv("NO_DEFAULT_POOLS", "").lower() != "true": # 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 the OS has not been built with IPv6 then the /proc config for IPv6 # will not be present. if not ipv6_pools and os.path.exists('/proc/sys/net/ipv6'): client.add_ip_pool(6, DEFAULT_IPV6_POOL) client.ensure_global_config() client.create_host(hostname, ip, ip6, as_num) # If IPIP is enabled, the host requires an IP address for its tunnel # device, which is in an IPIP pool. Without this, a host can't originate # traffic to a pool address because the response traffic would not be # routed via the tunnel (likely being dropped by RPF checks in the fabric). ipv4_pools = client.get_ip_pools(4) ipip_pools = [p for p in ipv4_pools if p.ipip] if ipip_pools: # IPIP is enabled, make sure the host has an address for its tunnel. _ensure_host_tunnel_addr(ipv4_pools, ipip_pools) else: # No IPIP pools, clean up any old address. _remove_host_tunnel_addr()