2 # -*- coding: utf-8 -*-
5 from nepi.core.design import ExperimentDescription, FactoriesProvider
6 from nepi.core.execute import ExperimentController
7 from nepi.util import proxy
8 from nepi.util.constants import DeploymentConfiguration as DC, ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP
17 class PlanetLabMultiIntegrationTestCase(unittest.TestCase):
18 testbed_id = "planetlab"
20 slicename1 = "inria_nepi"
21 plchost1 = "nepiplc.pl.sophia.inria.fr"
22 plcvnet1 = "192.168.2"
24 slicename2 = "inria_nepi2"
25 plchost2 = "nepiplc.pl.sophia.inria.fr"
26 plcvnet2 = "192.168.3"
28 host1pl1 = "nepi1.pl.sophia.inria.fr"
29 host2pl1 = "nepi2.pl.sophia.inria.fr"
31 host1pl2 = "nepi3.pl.sophia.inria.fr"
32 host2pl2 = "nepi5.pl.sophia.inria.fr"
34 port_base = 2000 + (os.getpid() % 1000) * 13
37 self.root_dir = tempfile.mkdtemp()
38 self.__class__.port_base = self.port_base + 100
42 shutil.rmtree(self.root_dir)
46 shutil.rmtree(self.root_dir)
48 def make_experiment_desc(self):
49 testbed_id = self.testbed_id
51 slicename1 = self.slicename1
52 plchost1 = self.plchost1
54 slicename2 = self.slicename2
55 plchost2 = self.plchost2
57 pl_ssh_key = os.environ.get(
59 "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'],) )
60 pl_user, pl_pwd = test_util.pl_auth()
62 exp_desc = ExperimentDescription()
63 pl_provider = FactoriesProvider(testbed_id)
64 pl_desc = exp_desc.add_testbed_description(pl_provider)
65 pl_desc.set_attribute_value("homeDirectory", self.root_dir)
66 pl_desc.set_attribute_value("slice", slicename1)
67 pl_desc.set_attribute_value("sliceSSHKey", pl_ssh_key)
68 pl_desc.set_attribute_value("authUser", pl_user)
69 pl_desc.set_attribute_value("authPass", pl_pwd)
70 pl_desc.set_attribute_value("plcHost", plchost1)
71 pl_desc.set_attribute_value("tapPortBase", self.port_base)
72 pl_desc.set_attribute_value("p2pDeployment", False) # it's interactive, we don't want it in tests
73 pl_desc.set_attribute_value("dedicatedSlice", True)
75 pl_desc2 = exp_desc.add_testbed_description(pl_provider)
76 pl_desc2.set_attribute_value("homeDirectory", self.root_dir+"v2")
77 pl_desc2.set_attribute_value("slice", slicename2)
78 pl_desc2.set_attribute_value("sliceSSHKey", pl_ssh_key)
79 pl_desc2.set_attribute_value("authUser", pl_user)
80 pl_desc2.set_attribute_value("authPass", pl_pwd)
81 pl_desc2.set_attribute_value("plcHost", plchost2)
82 pl_desc2.set_attribute_value("tapPortBase", self.port_base+500)
83 pl_desc2.set_attribute_value("p2pDeployment", False) # it's interactive, we don't want it in tests
84 pl_desc2.set_attribute_value("dedicatedSlice", True)
86 return pl_desc, pl_desc2, exp_desc
88 def make_pl_tapnode(self, pl, tapip, hostname, label_prefix):
89 node1 = pl.create("Node")
90 node1.set_attribute_value("hostname", hostname)
91 node1.set_attribute_value("label", label_prefix)
92 iface1 = pl.create("NodeInterface")
93 iface1.set_attribute_value("label", label_prefix+"iface")
94 tap1 = pl.create("TapInterface")
95 tap1.enable_trace("packets") # for error output
96 tap1.set_attribute_value("label", label_prefix+"tap")
97 inet = pl.create("Internet")
98 node1.connector("devs").connect(iface1.connector("node"))
99 node1.connector("devs").connect(tap1.connector("node"))
100 iface1.connector("inet").connect(inet.connector("devs"))
102 tap1ip = tap1.add_address()
103 tap1ip.set_attribute_value("Address", tapip)
104 tap1ip.set_attribute_value("NetPrefix", 24)
105 tap1ip.set_attribute_value("Broadcast", False)
107 return node1, iface1, tap1, tap1ip, inet
109 def _test_plpl_crossconnect(self, proto, recover = False):
110 pl, pl2, exp = self.make_experiment_desc()
113 pl.set_attribute_value(DC.RECOVERY_POLICY, DC.POLICY_RECOVER)
114 pl2.set_attribute_value(DC.RECOVERY_POLICY, DC.POLICY_RECOVER)
116 # Create PL node, ifaces, assign addresses
117 node1, iface1, tap1, tap1ip, inet1 = self.make_pl_tapnode(pl,
118 self.plcvnet1+".2", self.host1pl1, "node1")
119 node2, iface2, tap2, tap2ip, inet2 = self.make_pl_tapnode(pl2,
120 self.plcvnet2+".3", self.host1pl2, "node2")
123 tap1.connector(proto).connect(tap2.connector(proto))
124 tap1.set_attribute_value("pointopoint", "{#[node2tap].addr[0].[Address]#}")
125 tap2.set_attribute_value("pointopoint", "{#[node1tap].addr[0].[Address]#}")
127 # Disable encryption for GRE
129 tap1.set_attribute_value("tun_cipher", "PLAIN")
130 tap2.set_attribute_value("tun_cipher", "PLAIN")
132 # Create PlanetLab ping application, pinging the from one PL to another
133 ping = pl.create("Application")
134 ping.set_attribute_value("command", "ping -qc10 {#[node2tap].addr[0].[Address]#}")
135 ping.enable_trace("stdout")
136 ping.enable_trace("stderr")
137 ping.connector("node").connect(node1.connector("apps"))
139 comp_result = r"""PING .* \(.*\) \d*\(\d*\) bytes of data.
141 --- .* ping statistics ---
142 10 packets transmitted, 10 received, 0% packet loss, time \d*ms.*
148 controller = ExperimentController(xml, self.root_dir)
153 controller = ExperimentController(None, self.root_dir)
156 while not controller.is_finished(ping.guid):
159 ping_result = controller.trace(ping.guid, "stdout")
160 tap_trace = controller.trace(tap1.guid, "packets")
161 tap2_trace = controller.trace(tap2.guid, "packets")
164 if controller is not None:
169 traceback.print_exc()
171 controller.shutdown()
174 traceback.print_exc()
176 # asserts at the end, to make sure there's proper cleanup
177 self.assertTrue(re.match(comp_result, ping_result, re.MULTILINE),
178 "Unexpected trace:\n%s\nTap trace at origin:\n%s\nTap trace at destination:\n%s\n" % (
183 @test_util.skipUnless(test_util.pl_auth() is not None,
184 "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
185 def test_plpl_crossconnect_udp(self):
186 self._test_plpl_crossconnect("udp")
188 @test_util.skipUnless(test_util.pl_auth() is not None,
189 "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
190 def test_plpl_crossconnect_tcp(self):
191 self._test_plpl_crossconnect("tcp")
193 @test_util.skipUnless(test_util.pl_auth() is not None,
194 "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
195 def test_plpl_crossconnect_gre(self):
196 self._test_plpl_crossconnect("gre")
198 @test_util.skipUnless(test_util.pl_auth() is not None,
199 "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
200 def test_plpl_crossconnect_udp_recover(self):
201 self._test_plpl_crossconnect("udp",
205 if __name__ == '__main__':