Ejemplo n.º 1
0
    def test_get_host_ips_exclude(self, m_check_output):
        # Exclude "docker0"
        m_check_output.return_value = MOCK_IP_ADDR
        addrs = get_host_ips(version=4, exclude=["docker0"])
        m_check_output.assert_called_once_with(["ip", "-4", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(addrs, ['172.24.114.18'])

        addrs = get_host_ips(version=6, exclude=["docker0"])
        m_check_output.assert_called_once_with(["ip", "-6", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(addrs, [
            '2620:104:4008:69:8d7c:499f:2f04:9e55',
            '2620:104:4008:69:a00:27ff:fe73:c8d0', 'fe80::a00:27ff:fe73:c8d0'
        ])

        # Exclude empty list
        addrs = get_host_ips(version=4, exclude=[""])
        m_check_output.assert_called_once_with(["ip", "-4", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(addrs, ['172.24.114.18', '172.17.42.1'])

        addrs = get_host_ips(version=6, exclude=[""])
        m_check_output.assert_called_once_with(["ip", "-6", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(addrs, [
            '2620:104:4008:69:8d7c:499f:2f04:9e55',
            '2620:104:4008:69:a00:27ff:fe73:c8d0', 'fe80::a00:27ff:fe73:c8d0',
            'fe80::188f:d6ff:fe1f:1482'
        ])
Ejemplo n.º 2
0
  def test_get_host_ips_exclude(self, m_check_output):
    # Exclude "docker0"
    m_check_output.return_value = MOCK_IP_ADDR
    addrs = get_host_ips(version=4, exclude=["docker0"])
    m_check_output.assert_called_once_with(["ip", "-4", "addr"])
    m_check_output.reset_mock()
    self.assertEquals(addrs, ['172.24.114.18'])

    addrs = get_host_ips(version=6, exclude=["docker0"])
    m_check_output.assert_called_once_with(["ip", "-6", "addr"])
    m_check_output.reset_mock()
    self.assertEquals(addrs, ['2620:104:4008:69:8d7c:499f:2f04:9e55',
                  '2620:104:4008:69:a00:27ff:fe73:c8d0',
                  'fe80::a00:27ff:fe73:c8d0'])

    # Exclude empty list
    addrs = get_host_ips(version=4, exclude=[""])
    m_check_output.assert_called_once_with(["ip", "-4", "addr"])
    m_check_output.reset_mock()
    self.assertEquals(addrs, ['172.24.114.18', '172.17.42.1'])

    addrs = get_host_ips(version=6, exclude=[""])
    m_check_output.assert_called_once_with(["ip", "-6", "addr"])
    m_check_output.reset_mock()
    self.assertEquals(addrs, ['2620:104:4008:69:8d7c:499f:2f04:9e55',
                  '2620:104:4008:69:a00:27ff:fe73:c8d0',
                  'fe80::a00:27ff:fe73:c8d0',
                  'fe80::188f:d6ff:fe1f:1482'])
Ejemplo n.º 3
0
    def test_get_host_ips_loopback_only(self, m_check_output):
        # Test Loopback
        m_check_output.return_value = MOCK_IP_ADDR_LOOPBACK
        addrs = get_host_ips(version=4)
        m_check_output.assert_called_once_with(["ip", "-4", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(addrs, [])

        addrs = get_host_ips(version=6)
        m_check_output.assert_called_once_with(["ip", "-6", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(addrs, [])
Ejemplo n.º 4
0
  def test_get_host_ips_loopback_only(self, m_check_output):
    # Test Loopback
    m_check_output.return_value = MOCK_IP_ADDR_LOOPBACK
    addrs = get_host_ips(version=4)
    m_check_output.assert_called_once_with(["ip", "-4", "addr"])
    m_check_output.reset_mock()
    self.assertEquals(addrs, [])

    addrs = get_host_ips(version=6)
    m_check_output.assert_called_once_with(["ip", "-6", "addr"])
    m_check_output.reset_mock()
    self.assertEquals(addrs, [])
Ejemplo n.º 5
0
def warn_if_unknown_ip(ip, ip6):
    """
    Prints a warning message if the IP addresses are not assigned to interfaces
    on the current host.

    :param ip: IPv4 address which should be present on the host.
    :param ip6: IPv6 address which should be present on the host.
    :return: None
    """
    if ip and IPAddress(ip) not in get_host_ips(version=4, exclude=["docker0"]):
        print "WARNING: Could not confirm that the provided IPv4 address is" " assigned to this host."

    if ip6 and IPAddress(ip6) not in get_host_ips(version=6, exclude=["docker0"]):
        print "WARNING: Could not confirm that the provided IPv6 address is" " assigned to this host."
Ejemplo n.º 6
0
    def test_get_host_ips_loopback_only(self, m_check_output):
        '''Test get_host_ips with loopback'''
        # Test IPv4
        m_check_output.return_value = MOCK_IP_ADDR_LOOPBACK
        addrs = util.get_host_ips(version=4)
        m_check_output.assert_called_once_with(["ip", "-4", "addr"])
        m_check_output.reset_mock()
        self.assertEqual(addrs, [])

        # Test IPv6
        addrs = util.get_host_ips(version=6)
        m_check_output.assert_called_once_with(["ip", "-6", "addr"])
        m_check_output.reset_mock()
        self.assertEqual(addrs, [])
Ejemplo n.º 7
0
    def _get_node_ip(self):
        """ 
        Determine the IP for the host node.
        """
        # Compile list of addresses on network, return the first entry.
        # Try IPv4 and IPv6.
        addrs = get_host_ips(version=4) or get_host_ips(version=6)

        try:
            addr = addrs[0]
            print('Using IP Address %s' % (addr))
            return addr
        except IndexError:
            # If both get_host_ips return empty lists, print message and exit.
            print('No Valid IP Address Found for Host - cannot configure networking for pod %s' % (self.pod_name))
            sys.exit(1)
Ejemplo n.º 8
0
def warn_if_unknown_ip(ip, ip6):
    """
    Prints a warning message if the IP addresses are not assigned to interfaces
    on the current host.

    :param ip: IPv4 address which should be present on the host.
    :param ip6: IPv6 address which should be present on the host.
    :return: None
    """
    if ip and ip not in get_host_ips(version=4, exclude=["docker0"]):
        print "WARNING: Could not confirm that the provided IPv4 address is assigned" \
              " to this host."

    if ip6 and ip6 not in get_host_ips(version=6, exclude=["docker0"]):
        print "WARNING: Could not confirm that the provided IPv6 address is assigned" \
              " to this host."
Ejemplo n.º 9
0
  def test_get_host_ips_standard(self, m_check_output):
    # Test IPv4
    m_check_output.return_value = MOCK_IP_ADDR
    addrs = get_host_ips(version=4)
    m_check_output.assert_called_once_with(["ip", "-4", "addr"])
    m_check_output.reset_mock()
    self.assertEquals(addrs, ['172.24.114.18', '172.17.42.1'])

    # Test IPv6
    addrs = get_host_ips(version=6)
    m_check_output.assert_called_once_with(["ip", "-6", "addr"])
    m_check_output.reset_mock()
    self.assertEquals(addrs, ['2620:104:4008:69:8d7c:499f:2f04:9e55',
                  '2620:104:4008:69:a00:27ff:fe73:c8d0',
                  'fe80::a00:27ff:fe73:c8d0',
                  'fe80::188f:d6ff:fe1f:1482'])
Ejemplo n.º 10
0
def get_ip(v6=False):
    """
    Return a string of the IP of the hosts interface.
    Try to get the local IP from the environment variables.  This allows
    testers to specify the IP address in cases where there is more than one
    configured IP address for the test system.
    """
    env = LOCAL_IPv6_ENV if v6 else LOCAL_IP_ENV
    ip = os.environ.get(env)
    if not ip:
        try:
            # No env variable set; try to auto detect.
            socket_type = socket.AF_INET6 if v6 else socket.AF_INET
            s = socket.socket(socket_type, socket.SOCK_DGRAM)
            remote_ip = "2001:4860:4860::8888" if v6 else "8.8.8.8"
            s.connect((remote_ip, 0))
            ip = s.getsockname()[0]
            s.close()
        except BaseException:
            # Failed to connect, just try to get the address from the interfaces
            version = 6 if v6 else 4
            ips = get_host_ips(version)
            if ips:
                ip = str(ips[0])

    return ip
Ejemplo n.º 11
0
    def test_get_host_ips_exclude_docker_prefix(self, m_check_output):
        '''Test get_host_ips exclude "docker0.*'''
        # Test IPv4
        m_check_output.return_value = MOCK_IP_ADDR_DOCKER_NONE
        addrs = get_host_ips(version=4, exclude=["docker0.*"])
        m_check_output.assert_called_once_with(["ip", "-4", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(addrs, ['172.24.114.18'])

        # Test IPv6
        addrs = get_host_ips(version=6, exclude=["docker0.*"])
        m_check_output.assert_called_once_with(["ip", "-6", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(addrs, ['2620:104:4008:69:8d7c:499f:2f04:9e55',
                                  '2620:104:4008:69:a00:27ff:fe73:c8d0',
                                  'fe80::a00:27ff:fe73:c8d0'])
Ejemplo n.º 12
0
def get_ip(v6=False):
    """
    Return a string of the IP of the hosts interface.
    Try to get the local IP from the environment variables.  This allows
    testers to specify the IP address in cases where there is more than one
    configured IP address for the test system.
    """
    env = LOCAL_IPv6_ENV if v6 else LOCAL_IP_ENV
    ip = os.environ.get(env)
    if not ip:
        try:
            # No env variable set; try to auto detect.
            socket_type = socket.AF_INET6 if v6 else socket.AF_INET
            s = socket.socket(socket_type, socket.SOCK_DGRAM)
            remote_ip = "2001:4860:4860::8888" if v6 else "8.8.8.8"
            s.connect((remote_ip, 0))
            ip = s.getsockname()[0]
            s.close()
        except BaseException:
            # Failed to connect, just try to get the address from the interfaces
            version = 6 if v6 else 4
            ips = get_host_ips(version)
            if ips:
                ip = ips[0]

    return ip
Ejemplo n.º 13
0
    def test_get_host_ips_exclude_docker(self, m_check_output):
        '''Test get_host_ips exclude "docker0"'''
        # Test IPv4
        m_check_output.return_value = MOCK_IP_ADDR
        addrs = get_host_ips(version=4, exclude=["docker0"])
        m_check_output.assert_called_once_with(["ip", "-4", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(addrs, ["172.24.114.18"])

        # Test IPv6
        addrs = get_host_ips(version=6, exclude=["docker0"])
        m_check_output.assert_called_once_with(["ip", "-6", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(
            addrs,
            ["2620:104:4008:69:8d7c:499f:2f04:9e55", "2620:104:4008:69:a00:27ff:fe73:c8d0", "fe80::a00:27ff:fe73:c8d0"],
        )
Ejemplo n.º 14
0
    def test_get_host_ips_standard(self, m_check_output):
        # Test IPv4
        m_check_output.return_value = MOCK_IP_ADDR
        addrs = get_host_ips(version=4)
        m_check_output.assert_called_once_with(["ip", "-4", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(addrs, ['172.24.114.18', '172.17.42.1'])

        # Test IPv6
        addrs = get_host_ips(version=6)
        m_check_output.assert_called_once_with(["ip", "-6", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(addrs, [
            '2620:104:4008:69:8d7c:499f:2f04:9e55',
            '2620:104:4008:69:a00:27ff:fe73:c8d0', 'fe80::a00:27ff:fe73:c8d0',
            'fe80::188f:d6ff:fe1f:1482'
        ])
Ejemplo n.º 15
0
    def test_get_host_ips_exclude_docker_prefix(self, m_check_output):
        '''Test get_host_ips exclude "docker0.*'''
        # Test IPv4
        m_check_output.return_value = MOCK_IP_ADDR_DOCKER_NONE
        addrs = get_host_ips(version=4, exclude=["docker0.*"])
        m_check_output.assert_called_once_with(["ip", "-4", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(addrs, ['172.24.114.18'])

        # Test IPv6
        addrs = get_host_ips(version=6, exclude=["docker0.*"])
        m_check_output.assert_called_once_with(["ip", "-6", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(addrs, [
            '2620:104:4008:69:8d7c:499f:2f04:9e55',
            '2620:104:4008:69:a00:27ff:fe73:c8d0', 'fe80::a00:27ff:fe73:c8d0'
        ])
Ejemplo n.º 16
0
    def _get_node_ip(self):
        """
        Determine the IP for the host node.
        """
        # Compile list of addresses on network, return the first entry.
        # Try IPv4 and IPv6.
        addrs = get_host_ips(version=4) or get_host_ips(version=6)

        try:
            addr = addrs[0]
            logger.debug("Node's IP address: %s", addr)
            return addr
        except IndexError:
            # If both get_host_ips return empty lists, print message and exit.
            logger.exception('No Valid IP Address Found for Host - cannot '
                             'configure networking for pod %s. '
                             'Exiting', self.pod_name)
            sys.exit(1)
Ejemplo n.º 17
0
    def _get_node_ip(self):
        """ 
        Determine the IP for the host node.
        """
        # Compile list of addresses on network, return the first entry.
        # Try IPv4 and IPv6.
        addrs = get_host_ips(version=4) or get_host_ips(version=6)

        try:
            addr = addrs[0]
            print('Using IP Address %s' % (addr))
            return addr
        except IndexError:
            # If both get_host_ips return empty lists, print message and exit.
            print(
                'No Valid IP Address Found for Host - cannot configure networking for pod %s'
                % (self.pod_name))
            sys.exit(1)
Ejemplo n.º 18
0
    def test_get_host_ips_exclude_empty(self, m_check_output):
        '''Test get_host_ips exclude empty list'''
        # Test IPv4
        m_check_output.return_value = MOCK_IP_ADDR
        addrs = get_host_ips(version=4, exclude=["^$"])
        m_check_output.assert_called_once_with(["ip", "-4", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(addrs, [IPAddress('172.24.114.18'),
                                  IPAddress('172.17.42.1')])

        # Test IPv6
        addrs = get_host_ips(version=6, exclude=["^$"])
        m_check_output.assert_called_once_with(["ip", "-6", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(addrs,
                          [IPAddress('2620:104:4008:69:8d7c:499f:2f04:9e55'),
                           IPAddress('2620:104:4008:69:a00:27ff:fe73:c8d0'),
                           IPAddress('fe80::a00:27ff:fe73:c8d0'),
                           IPAddress('fe80::188f:d6ff:fe1f:1482')])
Ejemplo n.º 19
0
    def test_get_host_ips_standard(self, m_check_output):
        '''Test general case for get_host_ips'''
        # Test IPv4
        m_check_output.return_value = MOCK_IP_ADDR
        addrs = util.get_host_ips(version=4)
        m_check_output.assert_called_once_with(["ip", "-4", "addr"])
        m_check_output.reset_mock()
        self.assertEqual(addrs, [IPAddress('172.24.114.18'),
                                 IPAddress('172.17.42.1')])

        # Test IPv6
        addrs = util.get_host_ips(version=6)
        m_check_output.assert_called_once_with(["ip", "-6", "addr"])
        m_check_output.reset_mock()
        self.assertEqual(addrs,
                         [IPAddress('2620:104:4008:69:8d7c:499f:2f04:9e55'),
                          IPAddress('2620:104:4008:69:a00:27ff:fe73:c8d0'),
                          IPAddress('fe80::a00:27ff:fe73:c8d0'),
                          IPAddress('fe80::188f:d6ff:fe1f:1482')])
Ejemplo n.º 20
0
    def test_get_host_ips_exclude_empty(self, m_check_output):
        '''Test get_host_ips exclude empty list'''
        # Test IPv4
        m_check_output.return_value = MOCK_IP_ADDR
        addrs = get_host_ips(version=4, exclude=["^$"])
        m_check_output.assert_called_once_with(["ip", "-4", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(
            addrs, [IPAddress('172.24.114.18'),
                    IPAddress('172.17.42.1')])

        # Test IPv6
        addrs = get_host_ips(version=6, exclude=["^$"])
        m_check_output.assert_called_once_with(["ip", "-6", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(addrs, [
            IPAddress('2620:104:4008:69:8d7c:499f:2f04:9e55'),
            IPAddress('2620:104:4008:69:a00:27ff:fe73:c8d0'),
            IPAddress('fe80::a00:27ff:fe73:c8d0'),
            IPAddress('fe80::188f:d6ff:fe1f:1482')
        ])
Ejemplo n.º 21
0
    def test_get_host_ips_standard(self, m_check_output):
        """Test general case for get_host_ips"""
        # Test IPv4
        m_check_output.return_value = MOCK_IP_ADDR
        addrs = get_host_ips(version=4)
        m_check_output.assert_called_once_with(["ip", "-4", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(addrs, ["172.24.114.18", "172.17.42.1"])

        # Test IPv6
        addrs = get_host_ips(version=6)
        m_check_output.assert_called_once_with(["ip", "-6", "addr"])
        m_check_output.reset_mock()
        self.assertEquals(
            addrs,
            [
                "2620:104:4008:69:8d7c:499f:2f04:9e55",
                "2620:104:4008:69:a00:27ff:fe73:c8d0",
                "fe80::a00:27ff:fe73:c8d0",
                "fe80::188f:d6ff:fe1f:1482",
            ],
        )
Ejemplo n.º 22
0
    def test_isolate(self):
        # Test isolate
        hostname = socket.gethostname()

        indata = {
            "command": "isolate",
            "args": {
                "hostname": hostname,
                "container-id": self.container_id,
                "ipv4_addrs": ["192.168.23.4"],
                "ipv6_addrs": [],
                "netgroups": ["prod", "frontend"],
                "labels": {
                    "rack": "3A",
                    "pop": "houston"
                },
                "pid": 3789
            }
        }

        # Prepare network environment
        calicoctl("pool", "add", "192.168.0.0/16")

        # Set up bgp host configuration
        calicoctl("node")

        output = self.binary_exec(indata)
        self.assertEqual(self.stderr, '')
        self.assertEqual(output, error_msg())

        # Check if the endpoint was correctly written to etcd
        host = "127.0.0.1"
        port = 4001
        etcd_client = etcd.Client(host=host, port=port)
        leaves = etcd_client.read('/calico/v1/host/%s/workload/%s/%s/endpoint' % \
                                  (hostname, "mesos", self.container_id), recursive=True).leaves
        values = [leaf for leaf in leaves]
        self.assertEqual(
            len(values), 1,
            "Only 1 endpoint should exist: %d were found" % len(values))
        endpoint = values.pop()
        endpoint_dict = json.loads(endpoint.value)
        self.assertEqual(endpoint_dict["ipv4_gateway"],
                         get_host_ips(exclude="docker0").pop())
        self.assertEqual(endpoint_dict["ipv4_nets"], ["192.168.23.4"])
        self.assertEqual(endpoint_dict["profile_ids"], ["prod", "frontend"])
Ejemplo n.º 23
0
def create_profile_with_default_mesos_rules(profile):
    _log.info("Autocreating profile %s", profile)
    datastore.create_profile(profile)
    prof = datastore.get_profile(profile)
    # Set up the profile rules to allow incoming connections from the host
    # since the slave process will be running there.
    # Also allow connections from others in the profile.
    # Deny other connections (default, so not explicitly needed).
    # TODO: confirm that we're not getting more interfaces than we bargained for
    ipv4 = get_host_ips(4, exclude=["docker0"]).pop()
    host_net = ipv4 + "/32"
    _log.info("adding accept rule for %s" % host_net)
    allow_slave = Rule(action="allow", src_net=host_net)
    allow_self = Rule(action="allow", src_tag=profile)
    allow_all = Rule(action="allow")
    prof.rules = Rules(id=profile,
                       inbound_rules=[allow_slave, allow_self],
                       outbound_rules=[allow_all])
    datastore.profile_update_rules(prof)
Ejemplo n.º 24
0
    def test_isolate(self):
        # Test isolate
        hostname = socket.gethostname()

        indata = {
            "command": "isolate",
            "args": {
                "hostname": hostname,
                "container-id": self.container_id,
                "ipv4_addrs": ["192.168.23.4"],
                "ipv6_addrs": [],
                "netgroups": ["prod", "frontend"],
                "labels": {
                    "rack": "3A",
                    "pop": "houston"
                },
                "pid": 3789
            }
        }

        # Prepare network environment
        calicoctl("pool", "add", "192.168.0.0/16")

        # Set up bgp host configuration
        calicoctl("node")

        output = self.binary_exec(indata)
        self.assertEqual(self.stderr, '')
        self.assertEqual(output, error_msg())

        # Check if the endpoint was correctly written to etcd
        host = "127.0.0.1"
        port = 4001
        etcd_client = etcd.Client(host=host, port=port)
        leaves = etcd_client.read('/calico/v1/host/%s/workload/%s/%s/endpoint' % \
                                  (hostname, "mesos", self.container_id), recursive=True).leaves
        values = [leaf for leaf in leaves]
        self.assertEqual(len(values), 1, "Only 1 endpoint should exist: %d were found" % len(values))
        endpoint = values.pop()
        endpoint_dict = json.loads(endpoint.value)
        self.assertEqual(endpoint_dict["ipv4_gateway"], get_host_ips(exclude="docker0").pop())
        self.assertEqual(endpoint_dict["ipv4_nets"], ["192.168.23.4"])
        self.assertEqual(endpoint_dict["profile_ids"], ["prod", "frontend"])
Ejemplo n.º 25
0
def _create_profile_with_default_mesos_rules(profile):
    _log.info("Autocreating profile %s", profile)
    datastore.create_profile(profile)
    prof = datastore.get_profile(profile)
    # Set up the profile rules to allow incoming connections from the host
    # since the slave process will be running there.
    # Also allow connections from others in the profile.
    # Deny other connections (default, so not explicitly needed).
    # TODO: confirm that we're not getting more interfaces than we bargained for
    ipv4 = get_host_ips(4, exclude=["docker0"]).pop()
    host_net = str(_get_host_ip_net())
    _log.info("adding accept rule for %s" % host_net)
    allow_slave = Rule(action="allow", src_net=host_net)
    allow_self = Rule(action="allow", src_tag=profile)
    allow_all = Rule(action="allow")
    prof.rules = Rules(id=profile,
                       inbound_rules=[allow_slave, allow_self],
                       outbound_rules=[allow_all])
    datastore.profile_update_rules(prof)
Ejemplo n.º 26
0
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()
Ejemplo n.º 27
0
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)

    # Check etcd connectivity first.
    if not check_etcd_version():
        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.*"])
        try:
            ip = 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

    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)

    # 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 and ipv6_enabled():
        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()
Ejemplo n.º 28
0
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()
Ejemplo n.º 29
0
def node_start(node_image, runtime, log_dir, ip, ip6, as_num, detach,
               libnetwork_image):
    """
    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.
    :param libnetwork_image: The name of the Calico libnetwork driver image to
    use.  None, if not using libnetwork.
    :return:  None.
    """
    # Normally, Felix will load the modules it needs, but when running inside a
    # container it might not be able to do so. Ensure the required modules are
    # loaded each time the node starts.
    # We only make a best effort attempt because the command may fail if the
    # modules are built in.
    # We'll warn during the check_system() if the modules are unavailable.
    if not running_in_container():
        try:
            call(["modprobe", "-a"] + REQUIRED_MODULES)
        except OSError:
            pass

        # We will always want to setup IP forwarding
        _setup_ip_forwarding()

    # Print warnings for any known system issues before continuing
        if runtime == 'docker' and not running_in_container():
            using_docker = True
        else:
            using_docker = False

        (_, _, etcd_ok) = \
            check_system(quit_if_error=False, libnetwork=libnetwork_image,
                         check_docker=using_docker,
                         check_modules=not running_in_container())

        if not etcd_ok:
            sys.exit(1)

    # Ensure log directory exists
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)

    # Get IP address of host, if none was specified
    if not ip:
        ips = get_host_ips(exclude=["^docker.*", "^cbr.*",
                                    "virbr.*", "lxcbr.*", "veth.*",
                                    "cali.*", "tunl.*"])
        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 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)

    # Warn if this hostname conflicts with an existing host
    warn_if_hostname_conflict(ip)

    # 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)

    # 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()

    # The format of the authority string has already been validated.
    etcd_authority = os.getenv(ETCD_AUTHORITY_ENV, ETCD_AUTHORITY_DEFAULT)

    # Get etcd SSL environment variables if they exist
    etcd_scheme = os.getenv(ETCD_SCHEME_ENV, ETCD_SCHEME_DEFAULT)
    etcd_key_file = os.getenv(ETCD_KEY_FILE_ENV, None)
    etcd_cert_file = os.getenv(ETCD_CERT_FILE_ENV, None)
    etcd_ca_cert_file = os.getenv(ETCD_CA_CERT_FILE_ENV, None)

    etcd_volumes = []
    etcd_binds = {}
    etcd_envs = ["ETCD_AUTHORITY=%s" % etcd_authority,
                 "ETCD_SCHEME=%s" % etcd_scheme]
    felix_envs = ["FELIX_ETCDADDR=%s" % etcd_authority,
                  "FELIX_ETCDSCHEME=%s" % etcd_scheme]

    if etcd_ca_cert_file and etcd_key_file and etcd_cert_file:
        etcd_volumes.append(ETCD_CA_CERT_NODE_FILE)
        etcd_binds[etcd_ca_cert_file] = {"bind": ETCD_CA_CERT_NODE_FILE,
                                         "ro": True}
        etcd_envs.append("ETCD_CA_CERT_FILE=%s" % ETCD_CA_CERT_NODE_FILE)
        felix_envs.append("FELIX_ETCDCAFILE=%s" % ETCD_CA_CERT_NODE_FILE)

        etcd_volumes.append(ETCD_KEY_NODE_FILE)
        etcd_binds[etcd_key_file] = {"bind": ETCD_KEY_NODE_FILE,
                                     "ro": True}
        etcd_envs.append("ETCD_KEY_FILE=%s" % ETCD_KEY_NODE_FILE)
        felix_envs.append("FELIX_ETCDKEYFILE=%s" % ETCD_KEY_NODE_FILE)

        etcd_volumes.append(ETCD_CERT_NODE_FILE)
        etcd_binds[etcd_cert_file] = {"bind": ETCD_CERT_NODE_FILE,
                                      "ro": True}
        etcd_envs.append("ETCD_CERT_FILE=%s" % ETCD_CERT_NODE_FILE)
        felix_envs.append("FELIX_ETCDCERTFILE=%s" % ETCD_CERT_NODE_FILE)

    if runtime == 'docker':
        _start_node_container_docker(ip, ip6, log_dir, node_image, detach, etcd_envs,
                                     felix_envs, etcd_volumes, etcd_binds)
        if libnetwork_image:
            _start_libnetwork_container(libnetwork_image, etcd_envs,
                                        etcd_volumes, etcd_binds)
    if runtime == 'rkt':
        _start_node_container_rkt(ip, ip6, node_image, etcd_envs, felix_envs,
                                  etcd_volumes, etcd_binds)
Ejemplo n.º 30
0
 def test_get_host_ips_fail_check_output(self, m_check_output):
     '''Test get_host_ip failing to check output of ip addr'''
     m_check_output.side_effect = CalledProcessError(
         returncode=1, cmd=check_output(["ip", "-4", "addr"]))
     with self.assertRaises(SystemExit):
         addrs = get_host_ips(version=4)
Ejemplo n.º 31
0
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()
Ejemplo n.º 32
0
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
Ejemplo n.º 33
0
def node_start(node_image, runtime, log_dir, ip, ip6, as_num, detach,
               kubernetes_version, rkt, libnetwork_image):
    """
    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.
    :param kubernetes_version: The version of the calico-kubernetes plugin to
     install, or None if the plugin should not be installed.
    :param rkt: True to install the rkt plugin, False otherwise.
    :param libnetwork_image: The name of the Calico libnetwork driver image to
    use.  None, if not using libnetwork.
    :return:  None.
    """
    # Normally, Felix will load the modules it needs, but when running inside a
    # container it might not be able to so ensure the required modules are
    # loaded each time the node starts.
    # This is just a best error attempt, as the modules might be builtins.
    # We'll warn during the check_system() if the modules are unavailable.
    try:
        call(["modprobe", "-a"] + REQUIRED_MODULES)
    except OSError:
        pass

    # Print warnings for any known system issues before continuing
    using_docker = True if runtime == 'docker' else False
    (_, _, etcd_ok) = \
        check_system(quit_if_error=False, libnetwork=libnetwork_image,
                     check_docker=using_docker)

    if not etcd_ok:
        sys.exit(1)

    # We will always want to setup IP forwarding
    _setup_ip_forwarding()

    # Ensure log directory exists
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)

    # Get IP address of host, if none was specified
    if not ip:
        ips = get_host_ips(exclude=["^docker.*", "^cbr.*"])
        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_version:
        # Build a URL based on the provided Kubernetes_version.
        url = KUBERNETES_BINARY_URL % kubernetes_version
        try:
            # Attempt to install to the default Kubernetes directory
            install_plugin(KUBERNETES_PLUGIN_DIR, url)
        except OSError:
            # Use the backup directory
            install_plugin(KUBERNETES_PLUGIN_DIR_BACKUP, url)

    # Install rkt plugin
    if rkt:
        try:
            # Attempt to install to the default rkt directory
            install_plugin(RKT_PLUGIN_DIR, RKT_BINARY_URL)
        except OSError:
            # Use the backup directory
            install_plugin(RKT_PLUGIN_DIR_BACKUP, RKT_BINARY_URL)

    # 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)

    # Always try to convert the address(hostname) to an IP. This is a noop if
    # the address is already an IP address.  Note that the format of the authority
    # string has already been validated.
    etcd_authority = os.getenv(ETCD_AUTHORITY_ENV, ETCD_AUTHORITY_DEFAULT)
    etcd_authority_address, etcd_authority_port = etcd_authority.split(':')
    etcd_authority = '%s:%s' % (socket.gethostbyname(etcd_authority_address),
                                etcd_authority_port)
    if runtime == 'docker':
        _start_node_container(ip, ip6, etcd_authority, log_dir, node_image, detach)
        if libnetwork_image:
            _start_libnetwork_container(etcd_authority, libnetwork_image)
Ejemplo n.º 34
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)
Ejemplo n.º 35
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.
    """
    # Print warnings for any known system issues before continuing
    check_system(fix=False, quit_if_error=False)

    # Ensure log directory exists
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)

    # 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

    # Always try to convert the address(hostname) to an IP. This is a noop if
    # the address is already an IP address.  Note that the format of the authority
    # string has already been validated.
    etcd_authority = os.getenv(ETCD_AUTHORITY_ENV, ETCD_AUTHORITY_DEFAULT)
    etcd_authority_address, etcd_authority_port = etcd_authority.split(':')
    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
        "POLICY_ONLY_CALICO=%s" % os.getenv(POLICY_ONLY_ENV, ""),
    ]

    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)
    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)
Ejemplo n.º 36
0
def node_start(node_image, runtime, log_dir, ip, ip6, as_num, detach,
               kubernetes_version, rkt, libnetwork_image):
    """
    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.
    :param kubernetes_version: The version of the calico-kubernetes plugin to
     install, or None if the plugin should not be installed.
    :param rkt: True to install the rkt plugin, False otherwise.
    :param libnetwork_image: The name of the Calico libnetwork driver image to
    use.  None, if not using libnetwork.
    :return:  None.
    """
    # Normally, Felix will load the modules it needs, but when running inside a
    # container it might not be able to so ensure the required modules are
    # loaded each time the node starts.
    # This is just a best error attempt, as the modules might be builtins.
    # We'll warn during the check_system() if the modules are unavailable.
    try:
        call(["modprobe", "-a"] + REQUIRED_MODULES)
    except OSError:
        pass

    # Print warnings for any known system issues before continuing
    using_docker = True if runtime == 'docker' else False
    (_, _, etcd_ok) = \
        check_system(quit_if_error=False, libnetwork=libnetwork_image,
                     check_docker=using_docker)

    if not etcd_ok:
        sys.exit(1)

    # We will always want to setup IP forwarding
    _setup_ip_forwarding()

    # Ensure log directory exists
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)

    # Get IP address of host, if none was specified
    if not ip:
        ips = get_host_ips(exclude=["^docker.*", "^cbr.*"])
        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_version:
        # Build a URL based on the provided Kubernetes_version.
        url = KUBERNETES_BINARY_URL % kubernetes_version
        try:
            # Attempt to install to the default Kubernetes directory
            install_plugin(KUBERNETES_PLUGIN_DIR, url)
        except OSError:
            # Use the backup directory
            install_plugin(KUBERNETES_PLUGIN_DIR_BACKUP, url)

    # Install rkt plugin
    if rkt:
        try:
            # Attempt to install to the default rkt directory
            install_plugin(RKT_PLUGIN_DIR, RKT_BINARY_URL)
        except OSError:
            # Use the backup directory
            install_plugin(RKT_PLUGIN_DIR_BACKUP, RKT_BINARY_URL)

    # 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)

    # Always try to convert the address(hostname) to an IP. This is a noop if
    # the address is already an IP address.  Note that the format of the authority
    # string has already been validated.
    etcd_authority = os.getenv(ETCD_AUTHORITY_ENV, ETCD_AUTHORITY_DEFAULT)
    etcd_authority_address, etcd_authority_port = etcd_authority.split(':')
    etcd_authority = '%s:%s' % (socket.gethostbyname(etcd_authority_address),
                                etcd_authority_port)
    if runtime == 'docker':
        _start_node_container(ip, ip6, etcd_authority, log_dir, node_image,
                              detach)
        if libnetwork_image:
            _start_libnetwork_container(etcd_authority, libnetwork_image)
Ejemplo n.º 37
0
def node_start(node_image, runtime, log_dir, ip, ip6, as_num, detach,
               libnetwork_image):
    """
    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.
    :param libnetwork_image: The name of the Calico libnetwork driver image to
    use.  None, if not using libnetwork.
    :return:  None.
    """
    # Normally, Felix will load the modules it needs, but when running inside a
    # container it might not be able to do so. Ensure the required modules are
    # loaded each time the node starts.
    # We only make a best effort attempt because the command may fail if the
    # modules are built in.
    # We'll warn during the check_system() if the modules are unavailable.
    if not running_in_container():
        try:
            call(["modprobe", "-a"] + REQUIRED_MODULES)
        except OSError:
            pass

        # We will always want to setup IP forwarding
        _setup_ip_forwarding()

        # Print warnings for any known system issues before continuing
        if runtime == 'docker' and not running_in_container():
            using_docker = True
        else:
            using_docker = False

        (_, _, etcd_ok) = \
            check_system(quit_if_error=False, libnetwork=libnetwork_image,
                         check_docker=using_docker,
                         check_modules=not running_in_container())

        if not etcd_ok:
            sys.exit(1)

    # Ensure log directory exists
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)

    # Get IP address of host, if none was specified
    if not ip:
        ips = get_host_ips(exclude=[
            "^docker.*", "^cbr.*", "virbr.*", "lxcbr.*", "veth.*", "cali.*",
            "tunl.*"
        ])
        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 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)

    # Warn if this hostname conflicts with an existing host
    warn_if_hostname_conflict(ip)

    # 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)

    # 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()

    # The format of the authority string has already been validated.
    etcd_authority = os.getenv(ETCD_AUTHORITY_ENV, ETCD_AUTHORITY_DEFAULT)

    # Get etcd SSL environment variables if they exist
    etcd_scheme = os.getenv(ETCD_SCHEME_ENV, ETCD_SCHEME_DEFAULT)
    etcd_key_file = os.getenv(ETCD_KEY_FILE_ENV, None)
    etcd_cert_file = os.getenv(ETCD_CERT_FILE_ENV, None)
    etcd_ca_cert_file = os.getenv(ETCD_CA_CERT_FILE_ENV, None)

    etcd_volumes = []
    etcd_binds = {}
    etcd_envs = [
        "ETCD_AUTHORITY=%s" % etcd_authority,
        "ETCD_SCHEME=%s" % etcd_scheme
    ]
    felix_envs = [
        "FELIX_ETCDADDR=%s" % etcd_authority,
        "FELIX_ETCDSCHEME=%s" % etcd_scheme
    ]

    if etcd_ca_cert_file and etcd_key_file and etcd_cert_file:
        etcd_volumes.append(ETCD_CA_CERT_NODE_FILE)
        etcd_binds[etcd_ca_cert_file] = {
            "bind": ETCD_CA_CERT_NODE_FILE,
            "ro": True
        }
        etcd_envs.append("ETCD_CA_CERT_FILE=%s" % ETCD_CA_CERT_NODE_FILE)
        felix_envs.append("FELIX_ETCDCAFILE=%s" % ETCD_CA_CERT_NODE_FILE)

        etcd_volumes.append(ETCD_KEY_NODE_FILE)
        etcd_binds[etcd_key_file] = {"bind": ETCD_KEY_NODE_FILE, "ro": True}
        etcd_envs.append("ETCD_KEY_FILE=%s" % ETCD_KEY_NODE_FILE)
        felix_envs.append("FELIX_ETCDKEYFILE=%s" % ETCD_KEY_NODE_FILE)

        etcd_volumes.append(ETCD_CERT_NODE_FILE)
        etcd_binds[etcd_cert_file] = {"bind": ETCD_CERT_NODE_FILE, "ro": True}
        etcd_envs.append("ETCD_CERT_FILE=%s" % ETCD_CERT_NODE_FILE)
        felix_envs.append("FELIX_ETCDCERTFILE=%s" % ETCD_CERT_NODE_FILE)

    if runtime == 'docker':
        _start_node_container_docker(ip, ip6, log_dir, node_image, detach,
                                     etcd_envs, felix_envs, etcd_volumes,
                                     etcd_binds)
        if libnetwork_image:
            _start_libnetwork_container(libnetwork_image, etcd_envs,
                                        etcd_volumes, etcd_binds)
    if runtime == 'rkt':
        _start_node_container_rkt(ip, ip6, node_image, etcd_envs, felix_envs,
                                  etcd_volumes, etcd_binds)
Ejemplo n.º 38
0
 def test_get_host_ips_fail_check_output(self, m_check_output):
     '''Test get_host_ip failing to check output of ip addr'''
     m_check_output.side_effect = CalledProcessError(returncode=1, cmd=check_output(["ip", "-4", "addr"]))
     with self.assertRaises(SystemExit):
         addrs = get_host_ips(version=4)
Ejemplo n.º 39
0
def node_start(node_image, log_dir, ip, ip6, as_num, detach, kubernetes, rkt,
               libnetwork_image):
    """
    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.
    :param kubernetes: True to install the kubernetes plugin, False otherwise.
    :param rkt: True to install the rkt plugin, False otherwise.
    :param libnetwork_image: The name of the Calico libnetwork driver image to
    use.  None, if not using libnetwork.
    :return:  None.
    """
    # Print warnings for any known system issues before continuing
    check_system(fix=False, quit_if_error=False)

    # Ensure log directory exists
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)

    # Get IP address of host, if none was specified
    if not ip:
        ips = get_host_ips(exclude=["^docker.*", "^cbr.*"])
        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_plugin(KUBERNETES_PLUGIN_DIR, KUBERNETES_BINARY_URL)
        except OSError:
            # Use the backup directory
            install_plugin(KUBERNETES_PLUGIN_DIR_BACKUP, KUBERNETES_BINARY_URL)

    # Install rkt plugin
    if rkt:
        try:
            # Attempt to install to the default rkt directory
            install_plugin(RKT_PLUGIN_DIR, RKT_BINARY_URL)
        except OSError:
            # Use the backup directory
            install_plugin(RKT_PLUGIN_DIR_BACKUP, RKT_BINARY_URL)

    # 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)

    # Always try to convert the address(hostname) to an IP. This is a noop if
    # the address is already an IP address.  Note that the format of the authority
    # string has already been validated.
    etcd_authority = os.getenv(ETCD_AUTHORITY_ENV, ETCD_AUTHORITY_DEFAULT)
    etcd_authority_address, etcd_authority_port = etcd_authority.split(':')
    etcd_authority = '%s:%s' % (socket.gethostbyname(etcd_authority_address),
                                etcd_authority_port)

    _start_node_container(ip, ip6, etcd_authority, log_dir, node_image, detach)
    if libnetwork_image:
        _start_libnetwork_container(etcd_authority, libnetwork_image)