Ticket #45: spanning tree deployment
[nepi.git] / test / testbeds / planetlab / integration.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import getpass
5 from nepi.core.design import ExperimentDescription, FactoriesProvider
6 from nepi.core.execute import ExperimentController
7 from nepi.util import proxy
8 import os
9 import shutil
10 import tempfile
11 import test_util
12 import time
13 import unittest
14 import re
15 import sys
16
17 class PlanetLabIntegrationTestCase(unittest.TestCase):
18     testbed_id = "planetlab"
19     testbed_version = "01"
20     slicename = "inria_nepi"
21     plchost = "nepiplc.pl.sophia.inria.fr"
22     
23     host1 = "nepi1.pl.sophia.inria.fr"
24     host2 = "nepi2.pl.sophia.inria.fr"
25     host3 = "nepi3.pl.sophia.inria.fr"
26     host4 = "nepi5.pl.sophia.inria.fr"
27
28     def setUp(self):
29         self.root_dir = tempfile.mkdtemp()
30
31     def tearDown(self):
32         return
33         try:
34             shutil.rmtree(self.root_dir)
35         except:
36             # retry
37             time.sleep(0.1)
38             shutil.rmtree(self.root_dir)
39
40     def make_experiment_desc(self):
41         testbed_id = self.testbed_id
42         testbed_version = self.testbed_version
43         slicename = self.slicename
44         plchost = self.plchost
45         pl_ssh_key = os.environ.get(
46             "PL_SSH_KEY",
47             "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'],) )
48         pl_user, pl_pwd = test_util.pl_auth()
49
50         exp_desc = ExperimentDescription()
51         pl_provider = FactoriesProvider(testbed_id, testbed_version)
52         pl_desc = exp_desc.add_testbed_description(pl_provider)
53         pl_desc.set_attribute_value("homeDirectory", self.root_dir)
54         pl_desc.set_attribute_value("slice", slicename)
55         pl_desc.set_attribute_value("sliceSSHKey", pl_ssh_key)
56         pl_desc.set_attribute_value("authUser", pl_user)
57         pl_desc.set_attribute_value("authPass", pl_pwd)
58         pl_desc.set_attribute_value("plcHost", plchost)
59         
60         return pl_desc, exp_desc
61
62     @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
63     def test_simple(self):
64         pl, exp = self.make_experiment_desc()
65         
66         node1 = pl.create("Node")
67         node2 = pl.create("Node")
68         node1.set_attribute_value("hostname", self.host1)
69         node2.set_attribute_value("hostname", self.host2)
70         iface1 = pl.create("NodeInterface")
71         iface2 = pl.create("NodeInterface")
72         iface2.set_attribute_value("label", "node2iface")
73         inet = pl.create("Internet")
74         node1.connector("devs").connect(iface1.connector("node"))
75         node2.connector("devs").connect(iface2.connector("node"))
76         iface1.connector("inet").connect(inet.connector("devs"))
77         iface2.connector("inet").connect(inet.connector("devs"))
78         app = pl.create("Application")
79         app.set_attribute_value("command", "ping -qc1 {#[node2iface].addr[0].[Address]#}")
80         app.enable_trace("stdout")
81         app.connector("node").connect(node1.connector("apps"))
82
83         xml = exp.to_xml()
84
85         controller = ExperimentController(xml, self.root_dir)
86         try:
87             controller.start()
88             while not controller.is_finished(app.guid):
89                 time.sleep(0.5)
90             ping_result = controller.trace(app.guid, "stdout")
91             comp_result = r"""PING .* \(.*\) \d*\(\d*\) bytes of data.
92
93 --- .* ping statistics ---
94 1 packets transmitted, 1 received, 0% packet loss, time \d*ms.*
95 """
96             self.assertTrue(re.match(comp_result, ping_result, re.MULTILINE),
97                 "Unexpected trace:\n" + ping_result)
98         
99         finally:
100             controller.stop()
101             controller.shutdown()
102
103
104     @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
105     def test_spanning_deployment(self):
106         pl, exp = self.make_experiment_desc()
107         
108         from nepi.testbeds import planetlab as plpackage
109         
110         nodes = [ pl.create("Node") for i in xrange(4) ]
111         ifaces = [ pl.create("NodeInterface") for node in nodes ]
112         inet = pl.create("Internet")
113         for node, iface in zip(nodes,ifaces):
114             node.connector("devs").connect(iface.connector("node"))
115             iface.connector("inet").connect(inet.connector("devs"))
116         
117         apps = []
118         for node in nodes:
119             app = pl.create("Application")
120             app.set_attribute_value("command", "./consts")
121             app.set_attribute_value("buildDepends", "gcc")
122             app.set_attribute_value("build", "gcc ${SOURCES}/consts.c -o consts")
123             app.set_attribute_value("install", "cp consts ${SOURCES}/consts")
124             app.set_attribute_value("sources", os.path.join(
125                 os.path.dirname(plpackage.__file__),'scripts','consts.c'))
126             app.enable_trace("stdout")
127             app.enable_trace("stderr")
128             app.enable_trace("buildlog")
129             node.connector("apps").connect(app.connector("node"))
130             apps.append(app)
131
132         comp_result = \
133 r""".*ETH_P_ALL = 0x[0-9a-fA-F]{8}
134 ETH_P_IP = 0x[0-9a-fA-F]{8}
135 TUNGETIFF = 0x[0-9a-fA-F]{8}
136 TUNSETIFF = 0x[0-9a-fA-F]{8}
137 IFF_NO_PI = 0x[0-9a-fA-F]{8}
138 IFF_TAP = 0x[0-9a-fA-F]{8}
139 IFF_TUN = 0x[0-9a-fA-F]{8}
140 IFF_VNET_HDR = 0x[0-9a-fA-F]{8}
141 TUN_PKT_STRIP = 0x[0-9a-fA-F]{8}
142 IFHWADDRLEN = 0x[0-9a-fA-F]{8}
143 IFNAMSIZ = 0x[0-9a-fA-F]{8}
144 IFREQ_SZ = 0x[0-9a-fA-F]{8}
145 FIONREAD = 0x[0-9a-fA-F]{8}.*
146 """
147
148         comp_build = r".*(Identity added|gcc).*"
149
150         xml = exp.to_xml()
151
152         controller = ExperimentController(xml, self.root_dir)
153         try:
154             controller.start()
155             while not all(controller.is_finished(app.guid) for app in apps):
156                 time.sleep(0.5)
157             
158             for app in apps:
159                 app_result = controller.trace(app.guid, "stdout") or ""
160                 self.assertTrue(re.match(comp_result, app_result, re.MULTILINE),
161                     "Unexpected trace:\n" + app_result)
162
163                 build_result = controller.trace(app.guid, "buildlog") or ""
164                 self.assertTrue(re.match(comp_build, build_result, re.MULTILINE | re.DOTALL),
165                     "Unexpected trace:\n" + build_result)
166         
167         finally:
168             controller.stop()
169             controller.shutdown()
170         
171
172 if __name__ == '__main__':
173     unittest.main()
174