def test_add_ip(self): """ Test adding multiple IPs per workload. """ host = DockerHost('host') ip11 = "192.168.1.1" ip12 = "192.168.1.2" ip21 = "192.168.2.1" ip22 = "192.168.2.2" ip31 = "192.168.3.1" node1 = host.create_workload("node1", ip11) node2 = host.create_workload("node2") host.calicoctl("container add %s %s --interface=hello" % (node2, ip12)) host.calicoctl("profile add TEST_GROUP") host.calicoctl("profile TEST_GROUP member add %s" % node1) host.calicoctl("profile TEST_GROUP member add %s" % node2) node1.assert_can_ping(ip12, retries=3) # Add two more addresses to node1 and one more to node2 host.calicoctl("container node1 ip add %s" % ip21) host.calicoctl("container node1 ip add %s" % ip31) host.calicoctl("container %s ip add %s --interface=hello" % (node2, ip22)) node1.assert_can_ping(ip22) node2.assert_can_ping(ip11) node2.assert_can_ping(ip21) node2.assert_can_ping(ip31) # Now stop and restart node 1 and node 2. host.execute("docker stop %s" % node1, use_powerstrip=True) host.execute("docker stop %s" % node2, use_powerstrip=True) host.execute("docker start %s" % node1, use_powerstrip=True) host.execute("docker start %s" % node2, use_powerstrip=True) # Test pings between the IPs. node1.assert_can_ping(ip12, retries=3) node1.assert_can_ping(ip22) node2.assert_can_ping(ip11) node2.assert_can_ping(ip21) node2.assert_can_ping(ip31) # Now remove and check pings to the removed addresses no longer work. host.calicoctl("container %s ip remove %s" % (node1, ip21)) host.calicoctl("container %s ip remove %s --interface=hello" % (node2, ip22)) node1.assert_can_ping(ip12) node2.assert_can_ping(ip11) with self.assertRaises(ErrorReturnCode): node1.assert_can_ping(ip22) with self.assertRaises(ErrorReturnCode): node2.assert_can_ping(ip21) node2.assert_can_ping(ip31) # Check that we can't remove addresses twice with self.assertRaises(ErrorReturnCode): host.calicoctl("container %s ip remove %s" % (node1, ip21))
def test_profile_commands(self): """ Test that the profile rule update command successfully updates. """ host = DockerHost('host', start_calico=False) host.calicoctl("profile add TEST_PROFILE") json = ('{ "id": "TEST_PROFILE", ' '"inbound_rules": [ { "action": "allow", "src_tag": "TEST_PROFILE" }, ' '{ "action": "deny" } ], ' '"outbound_rules": [ { "action": "deny" } ] }') calicoctl = "/code/dist/calicoctl %s" host.execute("echo '%s' | " % json + calicoctl % "profile TEST_PROFILE rule update") self.assertIn('1 deny', host.calicoctl("profile TEST_PROFILE rule show").stdout.rstrip()) json_piece = '"outbound_rules": [\n {\n "action": "deny"' self.assertIn(json_piece, host.calicoctl("profile TEST_PROFILE rule json").stdout.rstrip()) # Test that adding and removing a tag works. self.assertNotIn("TEST_TAG", self.show_tag(host)) host.calicoctl("profile TEST_PROFILE tag add TEST_TAG") self.assertIn("TEST_TAG", self.show_tag(host)) host.calicoctl("profile TEST_PROFILE tag remove TEST_TAG") self.assertNotIn("TEST_TAG", self.show_tag(host))
def __enter__(self): """ Set up the route reflector clusters when entering context. :return: self. """ # Construct the common environment variables passed in when starting # the route reflector. etcd_auth = "-e ETCD_AUTHORITY=%s:2379" % get_ip() # Create the route reflector hosts, grouped by redundancy. for ii in range(self.num_redundancy_groups): cluster_id = str(IPAddress(0xFF000001 + ii)) redundancy_group = [] for jj in range(self.num_in_redundancy_group): rr = DockerHost('RR.%d.%d' % (ii, jj), start_calico=False) ip = "-e IP=%s" % rr.ip rr.execute("docker load --input /code/routereflector.tar") # Check which type of etcd is being run, then invoke the # suggested curl command to add the RR entry to etcd. # # See https://github.com/projectcalico/calico-bird/tree/feature-ipinip/build_routereflector # for details. if os.getenv("ETCD_SCHEME", None) == "https": # Etcd is running with SSL/TLS, pass the key values rr.execute("docker run --privileged --net=host -d " "--name rr %s " "-e ETCD_AUTHORITY=%s:2379 " "-e ETCD_CA_CERT_FILE=%s " "-e ETCD_CERT_FILE=%s " "-e ETCD_KEY_FILE=%s " "-e ETCD_SCHEME=https " "-v %s/certs:%s/certs " "calico/routereflector" % (ip, ETCD_HOSTNAME_SSL, ETCD_CA, ETCD_CERT, ETCD_KEY, CHECKOUT_DIR, CHECKOUT_DIR)) rr.execute( r'curl --cacert %s --cert %s --key %s ' r'-L https://%s:2379/v2/keys/calico/bgp/v1/rr_v4/%s ' r'-XPUT -d value="{' r'\"ip\":\"%s\",' r'\"cluster_id\":\"%s\"' r'}"' % (ETCD_CA, ETCD_CERT, ETCD_KEY, ETCD_HOSTNAME_SSL, rr.ip, rr.ip, cluster_id)) else: rr.execute("docker run --privileged --net=host -d " "--name rr %s %s " "calico/routereflector" % (etcd_auth, ip)) rr.execute( r'curl -L http://%s:2379/v2/keys/calico/bgp/v1/rr_v4/%s ' r'-XPUT -d value="{' r'\"ip\":\"%s\",' r'\"cluster_id\":\"%s\"' r'}"' % (get_ip(), rr.ip, rr.ip, cluster_id)) # Store the redundancy group. redundancy_group.append(rr) self.redundancy_groups.append(redundancy_group) return self
def __enter__(self): """ Set up the route reflector clusters when entering context. :return: self. """ # Construct the common environment variables passed in when starting # the route reflector. etcd_auth = "-e ETCD_AUTHORITY=%s:2379" % get_ip() # Create the route reflector hosts, grouped by redundancy. for ii in range(self.num_redundancy_groups): cluster_id = str(IPAddress(0xFF000001 + ii)) redundancy_group = [] for jj in range(self.num_in_redundancy_group): rr = DockerHost('RR.%d.%d' % (ii, jj), start_calico=False) ip = "-e IP=%s" % rr.ip rr.execute("docker load --input /code/routereflector.tar") # Check which type of etcd is being run, then invoke the # suggested curl command to add the RR entry to etcd. # # See https://github.com/projectcalico/calico-bird/tree/feature-ipinip/build_routereflector # for details. if os.getenv("ETCD_SCHEME", None) == "https": # Etcd is running with SSL/TLS, pass the key values rr.execute("docker run --privileged --net=host -d " "--name rr %s " "-e ETCD_AUTHORITY=%s:2379 " "-e ETCD_CA_CERT_FILE=%s " "-e ETCD_CERT_FILE=%s " "-e ETCD_KEY_FILE=%s " "-e ETCD_SCHEME=https " "-v %s/certs:%s/certs " "calico/routereflector" % (ip, ETCD_HOSTNAME_SSL, ETCD_CA, ETCD_CERT, ETCD_KEY, CHECKOUT_DIR,CHECKOUT_DIR)) rr.execute(r'curl --cacert %s --cert %s --key %s ' r'-L https://%s:2379/v2/keys/calico/bgp/v1/rr_v4/%s ' r'-XPUT -d value="{' r'\"ip\":\"%s\",' r'\"cluster_id\":\"%s\"' r'}"' % (ETCD_CA, ETCD_CERT, ETCD_KEY, ETCD_HOSTNAME_SSL, rr.ip, rr.ip, cluster_id)) else: rr.execute("docker run --privileged --net=host -d " "--name rr %s %s " "calico/routereflector" % (etcd_auth, ip)) rr.execute(r'curl -L http://%s:2379/v2/keys/calico/bgp/v1/rr_v4/%s ' r'-XPUT -d value="{' r'\"ip\":\"%s\",' r'\"cluster_id\":\"%s\"' r'}"' % (get_ip(), rr.ip, rr.ip, cluster_id)) # Store the redundancy group. redundancy_group.append(rr) self.redundancy_groups.append(redundancy_group) return self
def test_multi_host(self): """ Run a mainline multi-host test. Almost identical in function to the vagrant coreOS demo. """ host1 = DockerHost('host1') host2 = DockerHost('host2') host1.start_etcd() host1_ip = docker.inspect("--format", "'{{ .NetworkSettings.IPAddress }}'", host1.name).stdout.rstrip() host2_ip = docker.inspect("--format", "'{{ .NetworkSettings.IPAddress }}'", host2.name).stdout.rstrip() etcd_port = "ETCD_AUTHORITY=%s:2379" % host1_ip calicoctl = etcd_port + " /code/dist/calicoctl %s" host1.listen(calicoctl % "reset || true") host1.listen(calicoctl % ("node --ip=%s" % host1_ip)) host2.listen(calicoctl % ("node --ip=%s" % host2_ip)) calico_port = "DOCKER_HOST=localhost:2377" # Wait for the Calico nodes to be created. sleep(3) host1.listen("%s docker run -e CALICO_IP=192.168.1.1 --name workload-A -tid busybox" % calico_port) host1.listen("%s docker run -e CALICO_IP=192.168.1.2 --name workload-B -tid busybox" % calico_port) host1.listen("%s docker run -e CALICO_IP=192.168.1.3 --name workload-C -tid busybox" % calico_port) host2.listen("%s docker run -e CALICO_IP=192.168.1.4 --name workload-D -tid busybox" % calico_port) host2.listen("%s docker run -e CALICO_IP=192.168.1.5 --name workload-E -tid busybox" % calico_port) host1.listen(calicoctl % "profile add PROF_A_C_E") host1.listen(calicoctl % "profile add PROF_B") host1.listen(calicoctl % "profile add PROF_D") host1.listen(calicoctl % "profile PROF_A_C_E member add workload-A") host1.listen(calicoctl % "profile PROF_B member add workload-B") host1.listen(calicoctl % "profile PROF_A_C_E member add workload-C") host2.listen(calicoctl % "profile PROF_D member add workload-D") host2.listen(calicoctl % "profile PROF_A_C_E member add workload-E") # Wait for the workload networking to converge. sleep(1) host1.execute("docker exec workload-A ping -c 4 192.168.1.3") try: host1.execute("docker exec workload-A ping -c 4 192.168.1.2") raise except ErrorReturnCode_1: pass try: host1.execute("docker exec workload-A ping -c 4 192.168.1.4") raise except ErrorReturnCode_1: pass host1.execute("docker exec workload-A ping -c 4 192.168.1.5")
def test_duplicate_ips(self): """ Start two workloads with the same IP on different hosts. Make sure they can be reached from all places even after one of them is deleted. """ host1 = DockerHost('host1') host2 = DockerHost('host2') host3 = DockerHost('host3') # Set up three workloads on three hosts workload1 = host1.create_workload("workload1", "192.168.1.1") workload2 = host2.create_workload("workload2", "192.168.1.2") workload3 = host3.create_workload("workload3", "192.168.1.3") # Set up the workloads with duplicate IPs dup_ip = "192.168.1.4" dup1 = host1.create_workload("dup1", dup_ip) dup2 = host2.create_workload("dup2", dup_ip) host1.calicoctl("profile add TEST_PROFILE") # Add everyone to the same profile workload1_epid = host1.calicoctl("container %s endpoint-id show" % workload1).strip() host1.calicoctl("endpoint %s profile append TEST_PROFILE" % workload1_epid) dup1_epid = host1.calicoctl("container %s endpoint-id show" % dup1).strip() host1.calicoctl("endpoint %s profile append TEST_PROFILE" % dup1_epid) workload2_epid = host2.calicoctl("container %s endpoint-id show" % workload2).strip() host2.calicoctl("endpoint %s profile append TEST_PROFILE" % workload2_epid) dup2_epid = host2.calicoctl("container %s endpoint-id show" % dup2).strip() host2.calicoctl("endpoint %s profile append TEST_PROFILE" % dup2_epid) workload3_dpid = host3.calicoctl("container %s endpoint-id show" % workload3).strip() host3.calicoctl("endpoint %s profile append TEST_PROFILE" % workload3_dpid) # Check for standard connectivity workload1.assert_can_ping(dup_ip, retries=3) workload2.assert_can_ping(dup_ip, retries=3) workload3.assert_can_ping(dup_ip, retries=3) # Delete one of the duplciates. host2.execute("docker rm -f dup2") # Check standard connectivity still works. workload1.assert_can_ping(dup_ip, retries=3) workload2.assert_can_ping(dup_ip, retries=3) workload3.assert_can_ping(dup_ip, retries=3)
def test_diags(self): """ Test that the diags command successfully uploads the diags file. """ host = DockerHost('host') link = host.execute("/code/dist/calicoctl diags") assert "https://transfer.sh/" in link
def test_no_powerstrip(self): """ Test mainline functionality without using powerstrip. """ host = DockerHost("host") host.calicoctl("profile add TEST_GROUP") # Remove the environment variable such that docker run does not utilize # powerstrip. node1 = host.create_workload("node1", use_powerstrip=False) node2 = host.create_workload("node2", use_powerstrip=False) # Attempt to configure the nodes with the same profiles. This will fail # since we didn't use powerstrip to create the nodes. with self.assertRaises(ErrorReturnCode): host.calicoctl("profile TEST_GROUP member add %s" % node1) with self.assertRaises(ErrorReturnCode): host.calicoctl("profile TEST_GROUP member add %s" % node2) # Add the nodes to Calico networking. ip1, ip2 = "192.168.1.1", "192.168.1.2" host.calicoctl("container add %s %s" % (node1, ip1)) host.calicoctl("container add %s %s" % (node2, ip2)) # Now add the profiles. host.calicoctl("profile TEST_GROUP member add %s" % node1) host.calicoctl("profile TEST_GROUP member add %s" % node2) # Inspect the nodes (ensure this works without powerstrip) host.execute("docker inspect %s" % node1) host.execute("docker inspect %s" % node2) # Check it works node1.assert_can_ping(ip1, retries=3) node1.assert_can_ping(ip2) node2.assert_can_ping(ip1) node2.assert_can_ping(ip2) # Test the teardown commands host.calicoctl("profile remove TEST_GROUP") host.calicoctl("container remove %s" % node1) host.calicoctl("container remove %s" % node2) host.calicoctl("pool remove 192.168.0.0/16") host.calicoctl("node stop")
def __enter__(self): """ Set up the route reflector clusters when entering context. :return: self. """ # Construct the common environment variables passed in when starting # the route reflector. etcd_auth = "-e ETCD_AUTHORITY=%s:2379" % get_ip() # Create the route reflector hosts, grouped by redundancy. for ii in range(self.num_redundancy_groups): cluster_id = str(IPAddress(0xFF000001 + ii)) redundancy_group = [] for jj in range(self.num_in_redundancy_group): rr = DockerHost('RR.%d.%d' % (ii, jj), start_calico=False) ip = "-e IP=%s" % rr.ip rr.execute( "docker load --input /code/calico_containers/routereflector.tar" ) rr.execute("docker run --privileged --net=host -d " "--name rr %s %s " "calico/routereflector" % (etcd_auth, ip)) # Invoke the suggested curl command to add the RR entry to # etcd. # # See https://github.com/projectcalico/calico-bird/tree/feature-ipinip/build_routereflector # for details. rr.execute( r'curl -L http://%s:2379/v2/keys/calico/bgp/v1/rr_v4/%s ' r'-XPUT -d value="{' r'\"ip\":\"%s\",' r'\"cluster_id\":\"%s\"' r'}"' % (get_ip(), rr.ip, rr.ip, cluster_id)) # Store the redundancy group. redundancy_group.append(rr) self.redundancy_groups.append(redundancy_group) return self
def __enter__(self): """ Set up the route reflector clusters when entering context. :return: self. """ # Construct the common environment variables passed in when starting # the route reflector. etcd_auth = "-e ETCD_AUTHORITY=%s:2379" % get_ip() # Create the route reflector hosts, grouped by redundancy. for ii in range(self.num_redundancy_groups): cluster_id = str(IPAddress(0xFF000001 + ii)) redundancy_group = [] for jj in range(self.num_in_redundancy_group): rr = DockerHost('RR.%d.%d' % (ii, jj), start_calico=False) ip = "-e IP=%s" % rr.ip rr.execute("docker load --input /code/calico_containers/routereflector.tar") rr.execute("docker run --privileged --net=host -d " "--name rr %s %s " "calico/routereflector" % (etcd_auth, ip)) # Invoke the suggested curl command to add the RR entry to # etcd. # # See https://github.com/projectcalico/calico-bird/tree/feature-ipinip/build_routereflector # for details. rr.execute(r'curl -L http://%s:2379/v2/keys/calico/bgp/v1/rr_v4/%s ' r'-XPUT -d value="{' r'\"ip\":\"%s\",' r'\"cluster_id\":\"%s\"' r'}"' % (get_ip(), rr.ip, rr.ip, cluster_id)) # Store the redundancy group. redundancy_group.append(rr) self.redundancy_groups.append(redundancy_group) return self
def run_mainline(self, ip1, ip2): """ Setup two endpoints on one host and check connectivity. """ host = DockerHost('host') host.start_etcd() host_ip = docker.inspect("--format", "'{{ .NetworkSettings.IPAddress }}'", host.name).stdout.rstrip() etcd_port = "ETCD_AUTHORITY=%s:2379" % host_ip calicoctl = etcd_port + " /code/dist/calicoctl %s" calico_port = "DOCKER_HOST=localhost:2377" host.execute("docker run --rm -v `pwd`:/target jpetazzo/nsenter", _ok_code=[0, 1]) host.execute(calicoctl % "node --ip=127.0.0.1") host.execute(calicoctl % "profile add TEST_GROUP") # Wait for powerstrip to come up. for i in range(5): try: host.listen("%s docker ps" % calico_port) break except ErrorReturnCode: if i == 4: raise AssertionError("Powerstrip failed to come up.") else: sleep(1) host.listen("%s docker run -e CALICO_IP=%s -tid --name=node1 busybox" % (calico_port, ip1)) host.listen("%s docker run -e CALICO_IP=%s -tid --name=node2 busybox" % (calico_port, ip2)) # Perform a docker inspect to extract the configured IP addresses. node1_ip = host.execute("%s docker inspect --format '{{ .NetworkSettings.IPAddress }}' node1" % calico_port).stdout.rstrip() node2_ip = host.execute("%s docker inspect --format '{{ .NetworkSettings.IPAddress }}' node2" % calico_port).stdout.rstrip() # Configure the nodes with the same profiles. host.listen(calicoctl % "profile TEST_GROUP member add node1") host.listen(calicoctl % "profile TEST_GROUP member add node2") node1_pid = host.execute("docker inspect --format {{.State.Pid}} node1").stdout.rstrip() node2_pid = host.execute("docker inspect --format {{.State.Pid}} node2").stdout.rstrip() for i in range(10): try: host.listen("./nsenter -t %s ping %s -c 1 -W 1" % (node1_pid, node2_ip)) break except ErrorReturnCode: if i == 9: raise AssertionError("Network failed to come up.") else: sleep(1) # Check connectivity. host.execute("./nsenter -t %s ping %s -c 1" % (node1_pid, node1_ip)) host.execute("./nsenter -t %s ping %s -c 1" % (node1_pid, node2_ip)) host.execute("./nsenter -t %s ping %s -c 1" % (node2_pid, node1_ip)) host.execute("./nsenter -t %s ping %s -c 1" % (node2_pid, node2_ip)) # Test calicoctl teardown commands. host.execute(calicoctl % "profile remove TEST_GROUP") host.execute(calicoctl % "container remove node1") host.execute(calicoctl % "container remove node2") host.execute(calicoctl % "pool remove 192.168.0.0/16") host.execute(calicoctl % "node stop")