3f22eb4179c6f60be0acac880565cc7dde7886b5
[nepi.git] / test / core / integration.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 from nepi.core.design import ExperimentDescription, FactoriesProvider
5 from nepi.util import proxy
6 from nepi.util.constants import DeploymentConfiguration as DC
7 import getpass
8 import mock
9 import mock.metadata
10 import mock2
11 import mock2.metadata
12 import os
13 import shutil
14 import sys
15 import tempfile
16 import test_util
17 import time
18 import unittest
19
20 class ExecuteTestCase(unittest.TestCase):
21     def setUp(self):
22         sys.modules["nepi.testbeds.mock.metadata"] = mock.metadata
23         sys.modules["nepi.testbeds.mock"] = mock
24         sys.modules["nepi.testbeds.mock2.metadata"] = mock2.metadata
25         sys.modules["nepi.testbeds.mock2"] = mock2
26         self.root_dir = tempfile.mkdtemp()
27
28     def tearDown(self):
29         try:
30             shutil.rmtree(self.root_dir)
31         except:
32             # retry
33             time.sleep(0.1)
34             shutil.rmtree(self.root_dir)
35
36     def make_testbed(self, exp_desc, testbed_id):
37         provider = FactoriesProvider(testbed_id)
38         desc = exp_desc.add_testbed_description(provider)
39         desc.set_attribute_value("fake", True)
40         node1 = desc.create("Node")
41         node2 = desc.create("Node")
42         iface1 = desc.create("Interface")
43         iface1.set_attribute_value("fake", True)
44         node1.connector("devs").connect(iface1.connector("node"))
45         iface2 = desc.create("Interface")
46         iface2.set_attribute_value("fake", True)
47         node2.connector("devs").connect(iface2.connector("node"))
48         iface1.connector("iface").connect(iface2.connector("iface"))
49         app = desc.create("Application")
50         app.connector("node").connect(node1.connector("apps"))
51         app.enable_trace("fake")
52         
53         return exp_desc, desc, app, node1, node2, iface1, iface2
54
55     def make_test_experiment(self):
56         exp_desc = ExperimentDescription()
57         testbed_id = "mock"
58         return self.make_testbed(exp_desc, testbed_id)
59
60     def make_cross_test_experiment(self):
61         exp_desc = ExperimentDescription()
62         testbed_id1 = "mock"
63         testbed_id2 = "mock2"
64         exp_desc, desc1, app1, node11, node12, iface11, iface12 = \
65                 self.make_testbed(exp_desc, testbed_id1)
66         exp_desc, desc2, app2, node21, node22, iface21, iface22 = \
67                  self.make_testbed(exp_desc, testbed_id2)
68         iface12.connector("cross").connect(iface21.connector("cross"))
69
70         return exp_desc, desc1, desc2, iface12, iface21
71
72     def test_single_process_cross_integration(self):
73         exp_desc, desc1, desc2, iface12, iface21 = \
74                 self.make_cross_test_experiment()
75         xml = exp_desc.to_xml()
76         access_config = None
77         controller = proxy.create_experiment_controller(xml, access_config)
78
79         controller.start()
80         cross1 = controller.get(iface12.guid, "cross")
81         cross2 = controller.get(iface21.guid, "cross")
82         self.assertTrue(cross1 == cross2 == True)
83         controller.stop()
84         controller.shutdown()
85
86     def test_single_process_integration(self):
87         exp_desc, desc, app, node1, node2, iface1, iface2 = self.make_test_experiment()
88         xml = exp_desc.to_xml()
89         access_config = None
90         controller = proxy.create_experiment_controller(xml, access_config)
91
92         controller.start()
93         started_time = controller.started_time
94         self.assertTrue(started_time < time.time())
95         while not controller.is_finished(app.guid):
96             time.sleep(0.5)
97         fake_result = controller.trace(app.guid, "fake")
98         comp_result = """PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
99
100 --- 10.0.0.2 ping statistics ---
101 1 packets transmitted, 1 received, 0% packet loss, time 0ms
102 """
103         self.assertTrue(fake_result.startswith(comp_result))
104
105         self.assertEquals(controller.get_testbed_id(node1.guid), "mock")
106         self.assertEquals(controller.get_testbed_version(node1.guid), "0.1")
107         self.assertEquals(controller.get_factory_id(node1.guid), "Node")
108
109         controller.stop()
110         stopped_time = controller.stopped_time
111         self.assertTrue(stopped_time < time.time())
112         controller.shutdown()
113
114     def test_daemonized_controller_integration(self):
115         exp_desc, desc, app, node1, node2, iface1, iface2 = self.make_test_experiment()
116         xml = exp_desc.to_xml()
117         access_config = proxy.AccessConfiguration()
118         access_config.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
119         access_config.set_attribute_value(DC.ROOT_DIRECTORY, self.root_dir)
120         controller = proxy.create_experiment_controller(xml, access_config)
121
122         controller.start()
123         started_time = controller.started_time
124         self.assertTrue(started_time < time.time())
125         while not controller.is_finished(app.guid):
126             time.sleep(0.5)
127         fake_result = controller.trace(app.guid, "fake")
128         comp_result = """PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
129
130 --- 10.0.0.2 ping statistics ---
131 1 packets transmitted, 1 received, 0% packet loss, time 0ms
132 """
133         self.assertTrue(fake_result.startswith(comp_result))
134
135         self.assertEquals(controller.get_testbed_id(node1.guid), "mock")
136         self.assertEquals(controller.get_testbed_version(node1.guid), "0.1")
137         self.assertEquals(controller.get_factory_id(node1.guid), "Node")
138
139         controller.stop()
140         stopped_time = controller.stopped_time
141         self.assertTrue(stopped_time < time.time())
142         controller.shutdown()
143
144     def test_daemonized_testbed_integration(self):
145         exp_desc, desc, app, node1, node2, iface1, iface2 = self.make_test_experiment()
146         
147         desc.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
148         desc.set_attribute_value(DC.ROOT_DIRECTORY, self.root_dir)
149
150         xml = exp_desc.to_xml()
151         
152         controller = proxy.create_experiment_controller(xml, access_config = None)
153
154         controller.start()
155         while not controller.is_finished(app.guid):
156             time.sleep(0.5)
157         fake_result = controller.trace(app.guid, "fake")
158         comp_result = """PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
159
160 --- 10.0.0.2 ping statistics ---
161 1 packets transmitted, 1 received, 0% packet loss, time 0ms
162 """
163         self.assertTrue(fake_result.startswith(comp_result))
164
165         self.assertEquals(controller.get_testbed_id(node1.guid), "mock")
166         self.assertEquals(controller.get_testbed_version(node1.guid), "0.1")
167         self.assertEquals(controller.get_factory_id(node1.guid), "Node")
168
169         controller.stop()
170         controller.shutdown()
171
172     def test_daemonized_all_integration(self):
173         exp_desc, desc, app, node1, node2, iface1, iface2 = self.make_test_experiment()
174         
175         desc.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
176         inst_root_dir = os.path.join(self.root_dir, "instance")
177         os.mkdir(inst_root_dir)
178         desc.set_attribute_value(DC.ROOT_DIRECTORY, inst_root_dir)
179         
180         xml = exp_desc.to_xml()
181         
182         access_config = proxy.AccessConfiguration()
183         access_config.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
184         access_config.set_attribute_value(DC.ROOT_DIRECTORY, self.root_dir)
185         controller = proxy.create_experiment_controller(xml, access_config)
186
187         controller.start()
188         while not controller.is_finished(app.guid):
189             time.sleep(0.5)
190         fake_result = controller.trace(app.guid, "fake")
191         comp_result = """PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
192
193 --- 10.0.0.2 ping statistics ---
194 1 packets transmitted, 1 received, 0% packet loss, time 0ms
195 """
196         self.assertTrue(fake_result.startswith(comp_result))
197
198         self.assertEquals(controller.get_testbed_id(node1.guid), "mock")
199         self.assertEquals(controller.get_testbed_version(node1.guid), "0.1")
200         self.assertEquals(controller.get_factory_id(node1.guid), "Node")
201
202         traces_info = controller.traces_info()
203         expected_traces_info = dict({
204             1: dict({ # testbed guid
205                 6: dict({ # element guid
206                     'fake': dict({ # trace_id
207                         'host': 'localhost', 
208                         'user': getpass.getuser(), 
209                         'filepath': '<test>'
210                         })
211                     })
212                 })
213             })
214         self.assertEquals(traces_info, expected_traces_info)
215
216         controller.stop()
217         controller.shutdown()
218
219     def test_daemonized_all_integration_recovery(self):
220         exp_desc, desc, app, node1, node2, iface1, iface2 = self.make_test_experiment()
221         
222         desc.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
223         inst_root_dir = os.path.join(self.root_dir, "instance")
224         os.mkdir(inst_root_dir)
225         desc.set_attribute_value(DC.ROOT_DIRECTORY, inst_root_dir)
226         
227         xml = exp_desc.to_xml()
228         
229         access_config = proxy.AccessConfiguration()
230         access_config.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
231         access_config.set_attribute_value(DC.ROOT_DIRECTORY, self.root_dir)
232         controller = proxy.create_experiment_controller(xml, access_config)
233
234         controller.start()
235         while not controller.is_finished(app.guid):
236             time.sleep(0.5)
237         fake_result = controller.trace(app.guid, "fake")
238         comp_result = """PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
239
240 --- 10.0.0.2 ping statistics ---
241 1 packets transmitted, 1 received, 0% packet loss, time 0ms
242 """
243         self.assertTrue(fake_result.startswith(comp_result))
244
245         self.assertEquals(controller.get_testbed_id(node1.guid), "mock")
246         self.assertEquals(controller.get_testbed_version(node1.guid), "0.1")
247         self.assertEquals(controller.get_factory_id(node1.guid), "Node")
248
249         # controller dies
250         del controller
251         
252         # recover
253         access_config.set_attribute_value(DC.RECOVER,True)
254         controller = proxy.create_experiment_controller(xml, access_config)
255         
256         # test recovery
257         self.assertTrue(controller.is_finished(app.guid))
258         fake_result = controller.trace(app.guid, "fake")
259         self.assertTrue(fake_result.startswith(comp_result))
260         
261         controller.stop()
262         controller.shutdown()
263
264     def test_reference_expressions(self):
265         exp_desc, desc, app, node1, node2, iface1, iface2 = self.make_test_experiment()
266         
267         iface1.set_attribute_value("label", "some")
268         addr = iface1.add_address()
269         addr.set_attribute_value("Address", "10.0.0.2")
270         iface2.set_attribute_value("test", "{#[some].addr[0].[Address]#}")
271         
272         xml = exp_desc.to_xml()
273         access_config = None
274         controller = proxy.create_experiment_controller(xml, access_config)
275         controller.start()
276         while not controller.is_finished(app.guid):
277             time.sleep(0.5)
278         fake_result = controller.trace(app.guid, "fake")
279         comp_result = """PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
280
281 --- 10.0.0.2 ping statistics ---
282 1 packets transmitted, 1 received, 0% packet loss, time 0ms
283 """
284         
285         self.assertTrue(fake_result.startswith(comp_result))
286         
287         self.assertEqual(
288             controller._testbeds[desc.guid].get(iface2.guid, "test"),
289             addr.get_attribute_value("Address") )
290         
291         controller.stop()
292         controller.shutdown()
293
294     def test_testbed_reference_expressions(self):
295         exp_desc, desc, app, node1, node2, iface1, iface2 = self.make_test_experiment()
296         
297         iface1.set_attribute_value("label", "some")
298         addr = iface1.add_address()
299         addr.set_attribute_value("Address", "10.0.0.2")
300
301         desc2 = exp_desc.add_testbed_description(
302             FactoriesProvider("mock2") )
303         desc2.set_attribute_value(DC.DEPLOYMENT_HOST, "{#[some].addr[0].[Address]#}")
304         # DC.DEPLOYMENT_HOST should be ignored if DC.DEPLOYMENT_CONNECTION is not set
305         # But it should be resolved anyway
306         
307         xml = exp_desc.to_xml()
308         access_config = None
309         controller = proxy.create_experiment_controller(xml, access_config)
310         controller.start()
311         while not controller.is_finished(app.guid):
312             time.sleep(0.5)
313         fake_result = controller.trace(app.guid, "fake")
314         comp_result = """PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
315
316 --- 10.0.0.2 ping statistics ---
317 1 packets transmitted, 1 received, 0% packet loss, time 0ms
318 """
319         self.assertTrue(fake_result.startswith(comp_result))
320
321         self.assertEqual(
322             controller._deployment_config[desc2.guid]
323                 .get_attribute_value(DC.DEPLOYMENT_HOST),
324             addr.get_attribute_value("Address") )
325         
326         controller.stop()
327         controller.shutdown()
328
329     def test_ssh_daemonized_integration(self):
330         # TODO: This test doesn't run because
331         # sys.modules["nepi.testbeds.mock"] = mock
332         # is not set in the ssh process
333         exp_desc, desc, app, node1, node2, iface1, iface2 = self.make_test_experiment()
334         env = test_util.test_environment()
335         
336         desc.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
337         inst_root_dir = os.path.join(self.root_dir, "instance")
338         os.mkdir(inst_root_dir)
339         desc.set_attribute_value(DC.ROOT_DIRECTORY, inst_root_dir)
340         desc.set_attribute_value(DC.DEPLOYMENT_ENVIRONMENT_SETUP, 
341             "export PYTHONPATH=%r:%r:$PYTHONPATH ; "
342             "export NEPI_TESTBEDS='mock:mock mock2:mock2' ; " % (
343                 os.path.dirname(os.path.dirname(mock.__file__)),
344                 os.path.dirname(os.path.dirname(mock2.__file__)),))
345         
346         xml = exp_desc.to_xml()
347         
348         access_config = proxy.AccessConfiguration()
349         access_config.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
350         access_config.set_attribute_value(DC.ROOT_DIRECTORY, self.root_dir)
351         access_config.set_attribute_value(DC.DEPLOYMENT_COMMUNICATION, DC.ACCESS_SSH)
352         access_config.set_attribute_value(DC.DEPLOYMENT_PORT, env.port)
353         access_config.set_attribute_value(DC.USE_AGENT, True)
354         controller = proxy.create_experiment_controller(xml, access_config)
355
356         try:
357             controller.start()
358             while not controller.is_finished(app.guid):
359                 time.sleep(0.5)
360             fake_result = controller.trace(app.guid, "fake")
361             comp_result = """PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
362
363 --- 10.0.0.2 ping statistics ---
364 1 packets transmitted, 1 received, 0% packet loss, time 0ms
365 """
366             self.assertTrue(fake_result.startswith(comp_result))
367         finally:
368             controller.stop()
369             controller.shutdown()
370  
371 if __name__ == '__main__':
372     unittest.main()
373