2 # -*- coding: utf-8 -*-
6 from nepi.core.design import ExperimentDescription, FactoriesProvider
7 from nepi.core.execute import ExperimentController
8 from nepi.util import proxy
9 from nepi.util.constants import DeploymentConfiguration as DC
19 class PlanetLabIntegrationTestCase(unittest.TestCase):
20 testbed_id = "planetlab"
21 slicename = "inria_nepi"
22 plchost = "nepiplc.pl.sophia.inria.fr"
24 host1 = "nepi1.pl.sophia.inria.fr"
25 host2 = "nepi2.pl.sophia.inria.fr"
26 host3 = "nepi3.pl.sophia.inria.fr"
27 host4 = "nepi5.pl.sophia.inria.fr"
29 port_base = 2000 + (os.getpid() % 1000) * 13
32 self.root_dir = tempfile.mkdtemp()
33 self.__class__.port_base = self.port_base + 100
37 shutil.rmtree(self.root_dir)
41 shutil.rmtree(self.root_dir)
43 def make_experiment_desc(self):
44 testbed_id = self.testbed_id
45 slicename = self.slicename
46 plchost = self.plchost
47 pl_ssh_key = os.environ.get(
49 "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'],) )
50 pl_user, pl_pwd = test_util.pl_auth()
52 exp_desc = ExperimentDescription()
53 pl_provider = FactoriesProvider(testbed_id)
54 pl_desc = exp_desc.add_testbed_description(pl_provider)
55 pl_desc.set_attribute_value("homeDirectory", self.root_dir)
56 pl_desc.set_attribute_value("slice", slicename)
57 pl_desc.set_attribute_value("sliceSSHKey", pl_ssh_key)
58 pl_desc.set_attribute_value("authUser", pl_user)
59 pl_desc.set_attribute_value("authPass", pl_pwd)
60 pl_desc.set_attribute_value("plcHost", plchost)
61 pl_desc.set_attribute_value("tapPortBase", self.port_base)
62 pl_desc.set_attribute_value("p2pDeployment", False) # it's interactive, we don't want it in tests
63 pl_desc.set_attribute_value("dedicatedSlice", True)
64 #pl_desc.set_attribute_value("plLogLevel", "DEBUG")
66 return pl_desc, exp_desc
68 def _test_simple(self, daemonize_testbed, controller_access_configuration, environ = None):
69 pl, exp = self.make_experiment_desc()
71 node1 = pl.create("Node")
72 node2 = pl.create("Node")
73 node1.set_attribute_value("hostname", self.host1)
74 node2.set_attribute_value("hostname", self.host2)
75 iface1 = pl.create("NodeInterface")
76 iface2 = pl.create("NodeInterface")
77 iface2.set_attribute_value("label", "node2iface")
78 inet = pl.create("Internet")
79 node1.connector("devs").connect(iface1.connector("node"))
80 node2.connector("devs").connect(iface2.connector("node"))
81 iface1.connector("inet").connect(inet.connector("devs"))
82 iface2.connector("inet").connect(inet.connector("devs"))
83 app = pl.create("Application")
84 app.set_attribute_value("command", "ping -qc1 {#[node2iface].addr[0].[Address]#}")
85 app.enable_trace("stdout")
86 app.connector("node").connect(node1.connector("apps"))
89 pl.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
90 inst_root_dir = os.path.join(self.root_dir, "instance")
91 os.mkdir(inst_root_dir)
92 pl.set_attribute_value(DC.ROOT_DIRECTORY, inst_root_dir)
93 pl.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
96 pl.set_attribute_value(DC.DEPLOYMENT_ENVIRONMENT_SETUP, environ)
100 if controller_access_configuration:
101 controller = proxy.create_experiment_controller(xml,
102 controller_access_configuration)
104 controller = ExperimentController(xml, self.root_dir)
108 while not controller.is_finished(app.guid):
110 ping_result = controller.trace(app.guid, "stdout")
111 comp_result = r"""PING .* \(.*\) \d*\(\d*\) bytes of data.
113 --- .* ping statistics ---
114 1 packets transmitted, 1 received, 0% packet loss, time \d*ms.*
116 self.assertTrue(re.match(comp_result, ping_result, re.MULTILINE),
117 "Unexpected trace:\n" + ping_result)
124 traceback.print_exc()
126 controller.shutdown()
129 traceback.print_exc()
131 @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
132 @test_util.skipUnless(os.environ.get('NEPI_FULL_TESTS','').lower() in ('1','yes','true','on'),
133 "Test is interactive, requires NEPI_FULL_TESTS=yes")
134 def test_spanning_deployment(self):
135 pl, exp = self.make_experiment_desc()
137 pl.set_attribute_value("p2pDeployment", True) # we do want it here - even if interactive
139 from nepi.testbeds import planetlab as plpackage
141 nodes = [ pl.create("Node") for i in xrange(4) ]
142 ifaces = [ pl.create("NodeInterface") for node in nodes ]
143 inet = pl.create("Internet")
144 for node, iface in zip(nodes,ifaces):
145 node.connector("devs").connect(iface.connector("node"))
146 iface.connector("inet").connect(inet.connector("devs"))
150 app = pl.create("Application")
151 app.set_attribute_value("command", "./consts")
152 app.set_attribute_value("buildDepends", "gcc")
153 app.set_attribute_value("build", "gcc ${SOURCES}/consts.c -o consts")
154 app.set_attribute_value("install", "cp consts ${SOURCES}/consts")
155 app.set_attribute_value("sources", os.path.join(
156 os.path.dirname(plpackage.__file__),'scripts','consts.c'))
157 app.enable_trace("stdout")
158 app.enable_trace("stderr")
159 app.enable_trace("buildlog")
160 node.connector("apps").connect(app.connector("node"))
164 r""".*ETH_P_ALL = 0x[0-9a-fA-F]{8}
165 ETH_P_IP = 0x[0-9a-fA-F]{8}
166 TUNGETIFF = 0x[0-9a-fA-F]{8}
167 TUNSETIFF = 0x[0-9a-fA-F]{8}
168 IFF_NO_PI = 0x[0-9a-fA-F]{8}
169 IFF_TAP = 0x[0-9a-fA-F]{8}
170 IFF_TUN = 0x[0-9a-fA-F]{8}
171 IFF_VNET_HDR = 0x[0-9a-fA-F]{8}
172 TUN_PKT_STRIP = 0x[0-9a-fA-F]{8}
173 IFHWADDRLEN = 0x[0-9a-fA-F]{8}
174 IFNAMSIZ = 0x[0-9a-fA-F]{8}
175 IFREQ_SZ = 0x[0-9a-fA-F]{8}
176 FIONREAD = 0x[0-9a-fA-F]{8}.*
179 comp_build = r".*(Identity added|gcc).*"
183 controller = ExperimentController(xml, self.root_dir)
186 while not all(controller.is_finished(app.guid) for app in apps):
190 app_result = controller.trace(app.guid, "stdout") or ""
191 self.assertTrue(re.match(comp_result, app_result, re.MULTILINE),
192 "Unexpected trace:\n" + app_result)
194 build_result = controller.trace(app.guid, "buildlog") or ""
195 self.assertTrue(re.match(comp_build, build_result, re.MULTILINE | re.DOTALL),
196 "Unexpected trace:\n" + build_result)
203 traceback.print_exc()
205 controller.shutdown()
208 traceback.print_exc()
210 @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
211 def test_simple(self):
213 daemonize_testbed = False,
214 controller_access_configuration = None)
216 @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
217 def test_simple_daemonized(self):
218 access_config = proxy.AccessConfiguration({
219 DC.DEPLOYMENT_MODE : DC.MODE_DAEMON,
220 DC.ROOT_DIRECTORY : self.root_dir,
221 DC.LOG_LEVEL : DC.DEBUG_LEVEL,
225 daemonize_testbed = False,
226 controller_access_configuration = access_config)
228 @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
229 def test_z_simple_ssh(self): # _z_ cause we want it last - it messes up the process :(
230 # Recreate environment
231 environ = ' ; '.join( map("export %s=%r".__mod__, os.environ.iteritems()) )
233 env = test_util.test_environment()
235 access_config = proxy.AccessConfiguration({
236 DC.DEPLOYMENT_MODE : DC.MODE_DAEMON,
237 DC.ROOT_DIRECTORY : self.root_dir,
238 DC.LOG_LEVEL : DC.DEBUG_LEVEL,
239 DC.DEPLOYMENT_COMMUNICATION : DC.ACCESS_SSH,
240 DC.DEPLOYMENT_PORT : env.port,
242 DC.DEPLOYMENT_ENVIRONMENT_SETUP : environ,
246 daemonize_testbed = False,
247 controller_access_configuration = access_config,
251 def _test_recover(self, daemonize_testbed, controller_access_configuration, environ = None):
252 pl, exp = self.make_experiment_desc()
254 pl.set_attribute_value(DC.RECOVERY_POLICY, DC.POLICY_RECOVER)
256 node1 = pl.create("Node")
257 node2 = pl.create("Node")
258 node1.set_attribute_value("hostname", self.host1)
259 node2.set_attribute_value("hostname", self.host2)
261 iface1 = pl.create("NodeInterface")
262 iface2 = pl.create("NodeInterface")
263 inet = pl.create("Internet")
264 node1.connector("devs").connect(iface1.connector("node"))
265 node2.connector("devs").connect(iface2.connector("node"))
266 iface1.connector("inet").connect(inet.connector("devs"))
267 iface2.connector("inet").connect(inet.connector("devs"))
269 tap1 = pl.create("TapInterface")
270 tap2 = pl.create("TapInterface")
271 node1.connector("devs").connect(tap1.connector("node"))
272 node2.connector("devs").connect(tap2.connector("node"))
273 tap1.connector("udp").connect(tap2.connector("udp"))
275 tap1ip = tap1.add_address()
276 tap1ip.set_attribute_value("Address", "192.168.2.2")
277 tap1ip.set_attribute_value("NetPrefix", 24)
278 tap1ip.set_attribute_value("Broadcast", False)
280 tap2ip = tap2.add_address()
281 tap2ip.set_attribute_value("Address", "192.168.2.3")
282 tap2ip.set_attribute_value("NetPrefix", 24)
283 tap2ip.set_attribute_value("Broadcast", False)
285 app = pl.create("Application")
286 app.set_attribute_value("command", "ping -qc10 192.168.2.3")
287 app.enable_trace("stdout")
288 app.connector("node").connect(node1.connector("apps"))
290 if daemonize_testbed:
291 pl.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
292 inst_root_dir = os.path.join(self.root_dir, "instance")
293 os.mkdir(inst_root_dir)
294 pl.set_attribute_value(DC.ROOT_DIRECTORY, inst_root_dir)
295 pl.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
298 pl.set_attribute_value(DC.DEPLOYMENT_ENVIRONMENT_SETUP, environ)
302 if controller_access_configuration:
303 controller = proxy.create_experiment_controller(xml,
304 controller_access_configuration)
306 controller = ExperimentController(xml, self.root_dir)
311 # purposedly break connection
315 if controller_access_configuration:
316 controller_access_configuration.set_attribute_value(
318 controller = proxy.create_experiment_controller(None,
319 controller_access_configuration)
321 controller = ExperimentController(None, self.root_dir)
324 while not controller.is_finished(app.guid):
326 ping_result = controller.trace(app.guid, "stdout")
327 comp_result = r"""PING .* \(.*\) \d*\(\d*\) bytes of data.
329 --- .* ping statistics ---
330 10 packets transmitted, 10 received, 0% packet loss, time \d*ms.*
332 self.assertTrue(re.match(comp_result, ping_result, re.MULTILINE),
333 "Unexpected trace:\n" + ping_result)
336 if controller is not None:
341 traceback.print_exc()
343 controller.shutdown()
346 traceback.print_exc()
348 @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
349 def test_recover(self):
351 daemonize_testbed = False,
352 controller_access_configuration = None)
354 @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
355 def test_recover_daemonized(self):
356 access_config = proxy.AccessConfiguration({
357 DC.DEPLOYMENT_MODE : DC.MODE_DAEMON,
358 DC.ROOT_DIRECTORY : self.root_dir,
359 DC.LOG_LEVEL : DC.DEBUG_LEVEL,
363 daemonize_testbed = False,
364 controller_access_configuration = access_config)
367 if __name__ == '__main__':