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)
74 #pl_desc.set_attribute_value("plLogLevel", "DEBUG")
76 pl_desc2 = exp_desc.add_testbed_description(pl_provider)
77 pl_desc2.set_attribute_value("homeDirectory", self.root_dir+"v2")
78 pl_desc2.set_attribute_value("slice", slicename2)
79 pl_desc2.set_attribute_value("sliceSSHKey", pl_ssh_key)
80 pl_desc2.set_attribute_value("authUser", pl_user)
81 pl_desc2.set_attribute_value("authPass", pl_pwd)
82 pl_desc2.set_attribute_value("plcHost", plchost2)
83 pl_desc2.set_attribute_value("tapPortBase", self.port_base+500)
84 pl_desc2.set_attribute_value("p2pDeployment", False) # it's interactive, we don't want it in tests
85 pl_desc2.set_attribute_value("dedicatedSlice", True)
86 #pl_desc2.set_attribute_value("plLogLevel", "DEBUG")
88 return pl_desc, pl_desc2, exp_desc
90 def make_pl_tapnode(self, pl, tapip, hostname, label_prefix):
91 node1 = pl.create("Node")
92 node1.set_attribute_value("hostname", hostname)
93 node1.set_attribute_value("label", label_prefix)
94 iface1 = pl.create("NodeInterface")
95 iface1.set_attribute_value("label", label_prefix+"iface")
96 tap1 = pl.create("TapInterface")
97 tap1.enable_trace("packets") # for error output
98 tap1.set_attribute_value("label", label_prefix+"tap")
99 inet = pl.create("Internet")
100 node1.connector("devs").connect(iface1.connector("node"))
101 node1.connector("devs").connect(tap1.connector("node"))
102 iface1.connector("inet").connect(inet.connector("devs"))
104 tap1ip = tap1.add_address()
105 tap1ip.set_attribute_value("Address", tapip)
106 tap1ip.set_attribute_value("NetPrefix", 24)
107 tap1ip.set_attribute_value("Broadcast", False)
109 return node1, iface1, tap1, tap1ip, inet
111 def _test_plpl_crossconnect(self, proto, recover = False):
112 pl, pl2, exp = self.make_experiment_desc()
115 pl.set_attribute_value(DC.RECOVERY_POLICY, DC.POLICY_RECOVER)
116 pl2.set_attribute_value(DC.RECOVERY_POLICY, DC.POLICY_RECOVER)
118 # Create PL node, ifaces, assign addresses
119 node1, iface1, tap1, tap1ip, inet1 = self.make_pl_tapnode(pl,
120 self.plcvnet1+".2", self.host1pl1, "node1")
121 node2, iface2, tap2, tap2ip, inet2 = self.make_pl_tapnode(pl2,
122 self.plcvnet2+".3", self.host1pl2, "node2")
125 tap1.connector(proto).connect(tap2.connector(proto))
126 tap1.set_attribute_value("pointopoint", "{#[node2tap].addr[0].[Address]#}")
127 tap2.set_attribute_value("pointopoint", "{#[node1tap].addr[0].[Address]#}")
129 # Disable encryption for GRE
131 tap1.set_attribute_value("tun_cipher", "PLAIN")
132 tap2.set_attribute_value("tun_cipher", "PLAIN")
134 # Create PlanetLab ping application, pinging the from one PL to another
135 ping = pl.create("Application")
136 ping.set_attribute_value("command", "ping -qc10 {#[node2tap].addr[0].[Address]#}")
137 ping.enable_trace("stdout")
138 ping.enable_trace("stderr")
139 ping.connector("node").connect(node1.connector("apps"))
141 comp_result = r"""PING .* \(.*\) \d*\(\d*\) bytes of data.
143 --- .* ping statistics ---
144 10 packets transmitted, 10 received, 0% packet loss, time \d*ms.*
150 controller = ExperimentController(xml, self.root_dir)
155 controller = ExperimentController(None, self.root_dir)
158 while not controller.is_finished(ping.guid):
161 ping_result = controller.trace(ping.guid, "stdout")
162 tap_trace = controller.trace(tap1.guid, "packets")
163 tap2_trace = controller.trace(tap2.guid, "packets")
166 if controller is not None:
171 traceback.print_exc()
173 controller.shutdown()
176 traceback.print_exc()
178 # asserts at the end, to make sure there's proper cleanup
179 self.assertTrue(re.match(comp_result, ping_result, re.MULTILINE),
180 "Unexpected trace:\n%s\nTap trace at origin:\n%s\nTap trace at destination:\n%s\n" % (
185 @test_util.skipUnless(test_util.pl_auth() is not None,
186 "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
187 def test_plpl_crossconnect_udp(self):
188 self._test_plpl_crossconnect("udp")
190 @test_util.skipUnless(test_util.pl_auth() is not None,
191 "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
192 def test_plpl_crossconnect_tcp(self):
193 self._test_plpl_crossconnect("tcp")
195 @test_util.skipUnless(test_util.pl_auth() is not None,
196 "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
197 def test_plpl_crossconnect_gre(self):
198 self._test_plpl_crossconnect("gre")
200 @test_util.skipUnless(test_util.pl_auth() is not None,
201 "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
202 def test_plpl_crossconnect_udp_recover(self):
203 self._test_plpl_crossconnect("udp",
207 if __name__ == '__main__':