248b9ae42fc7ba7fdf7759c4e2ddbf8dc46c5c04
[nepi.git] / test / testbeds / ns3 / 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 from nepi.util.constants import DeploymentConfiguration as DC
9 import os
10 import re
11 import shutil
12 import tempfile
13 import test_util
14 import time
15 import unittest
16
17 class Ns3IntegrationTestCase(unittest.TestCase):
18     def setUp(self):
19         self.root_dir = tempfile.mkdtemp()
20
21     def _test_fd_net_device(self, daemonize_testbed,
22             controller_access_configuration):
23         exp_desc = ExperimentDescription()
24         testbed_id = "ns3"
25         ns3_provider = FactoriesProvider(testbed_id)
26         ns3_desc1 = exp_desc.add_testbed_description(ns3_provider)
27         root_dir1 = os.path.join(self.root_dir, "1")
28         ns3_desc1.set_attribute_value("homeDirectory", root_dir1)
29         ns3_desc1.set_attribute_value("SimulatorImplementationType",
30                 "ns3::RealtimeSimulatorImpl")
31         ns3_desc1.set_attribute_value("ChecksumEnabled", True)
32         ns3_desc2 = exp_desc.add_testbed_description(ns3_provider)
33         root_dir2 = os.path.join(self.root_dir, "2")
34         ns3_desc2.set_attribute_value("homeDirectory", root_dir2)
35         ns3_desc2.set_attribute_value("SimulatorImplementationType",
36                 "ns3::RealtimeSimulatorImpl")
37         ns3_desc2.set_attribute_value("ChecksumEnabled", True)
38
39         node1 = ns3_desc1.create("ns3::Node")
40         ipv41 = ns3_desc1.create("ns3::Ipv4L3Protocol")
41         arp1  = ns3_desc1.create("ns3::ArpL3Protocol")
42         icmp1 = ns3_desc1.create("ns3::Icmpv4L4Protocol")
43         node1.connector("protos").connect(ipv41.connector("node"))
44         node1.connector("protos").connect(arp1.connector("node"))
45         node1.connector("protos").connect(icmp1.connector("node"))
46         iface1 = ns3_desc1.create("ns3::FdNetDevice")
47         node1.connector("devs").connect(iface1.connector("node"))
48         ip1 = iface1.add_address()
49         ip1.set_attribute_value("Address", "10.0.0.1")
50         tc1 = ns3_desc1.create("ns3::Nepi::TunChannel")
51         tc1.connector("fd->").connect(iface1.connector("->fd"))
52
53         node2 = ns3_desc2.create("ns3::Node")
54         ipv42 = ns3_desc2.create("ns3::Ipv4L3Protocol")
55         arp2  = ns3_desc2.create("ns3::ArpL3Protocol")
56         icmp2 = ns3_desc2.create("ns3::Icmpv4L4Protocol")
57         node2.connector("protos").connect(ipv42.connector("node"))
58         node2.connector("protos").connect(arp2.connector("node"))
59         node2.connector("protos").connect(icmp2.connector("node"))
60         iface2 = ns3_desc2.create("ns3::FdNetDevice")
61         iface2.enable_trace("FdAsciiTrace")
62         node2.connector("devs").connect(iface2.connector("node"))
63         ip2 = iface2.add_address()
64         ip2.set_attribute_value("Address", "10.0.0.2")
65         tc2 = ns3_desc2.create("ns3::Nepi::TunChannel")
66         tc2.connector("fd->").connect(iface2.connector("->fd"))
67
68         tc2.connector("udp").connect(tc1.connector("udp"))
69
70         app = ns3_desc1.create("ns3::V4Ping")
71         app.set_attribute_value("Remote", "10.0.0.2")
72         app.set_attribute_value("StartTime", "0s")
73         app.set_attribute_value("StopTime", "2s")
74         app.connector("node").connect(node1.connector("apps"))
75
76         if daemonize_testbed:
77             ns3_desc1.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
78             inst_root_dir = os.path.join(root_dir1, "instance")
79             os.makedirs(inst_root_dir)
80             ns3_desc1.set_attribute_value(DC.ROOT_DIRECTORY, inst_root_dir)
81             #ns3_desc1.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
82
83             ns3_desc2.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
84             inst_root_dir = os.path.join(root_dir2, "instance")
85             os.makedirs(inst_root_dir)
86             ns3_desc2.set_attribute_value(DC.ROOT_DIRECTORY, inst_root_dir)
87             #ns3_desc2.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
88
89         xml = exp_desc.to_xml()
90         
91         if controller_access_configuration:
92             controller = ExperimentController(xml, self.root_dir)
93         else:
94             controller = proxy.create_experiment_controller(xml, 
95                 controller_access_configuration)
96         
97         try:
98             controller.start()
99             while not controller.is_finished(app.guid):
100                 time.sleep(0.5)
101             ping_result = controller.trace(iface2.guid, "FdAsciiTrace")
102             ping_exp_result = r"""r [-+0-9.e]+ /NodeList/0/DeviceList/0/\$ns3::FdNetDevice/Rx Payload \(size=42\)
103 r [-+0-9.e]+ /NodeList/0/DeviceList/0/\$ns3::FdNetDevice/Rx Payload \(size=98\)
104 r [-+0-9.e]+ /NodeList/0/DeviceList/0/\$ns3::FdNetDevice/Rx Payload \(size=42\)
105 r [-+0-9.e]+ /NodeList/0/DeviceList/0/\$ns3::FdNetDevice/Rx Payload \(size=98\)
106 """
107             if not re.match(ping_exp_result, ping_result):
108                 self.fail("Unexpected trace: %s" % (ping_result,))
109
110         finally:
111             controller.stop()
112             controller.shutdown()
113  
114     def _test_if(self, daemonize_testbed, controller_access_configuration):
115         exp_desc = ExperimentDescription()
116         testbed_id = "ns3"
117         ns3_provider = FactoriesProvider(testbed_id)
118         ns3_desc = exp_desc.add_testbed_description(ns3_provider)
119         ns3_desc.set_attribute_value("homeDirectory", self.root_dir)
120
121         node1 = ns3_desc.create("ns3::Node")
122         ipv41 = ns3_desc.create("ns3::Ipv4L3Protocol")
123         arp1  = ns3_desc.create("ns3::ArpL3Protocol")
124         icmp1 = ns3_desc.create("ns3::Icmpv4L4Protocol")
125         node1.connector("protos").connect(ipv41.connector("node"))
126         node1.connector("protos").connect(arp1.connector("node"))
127         node1.connector("protos").connect(icmp1.connector("node"))
128         iface1 = ns3_desc.create("ns3::PointToPointNetDevice")
129         queue1 = ns3_desc.create("ns3::DropTailQueue")
130         node1.connector("devs").connect(iface1.connector("node"))
131         iface1.connector("queue").connect(queue1.connector("dev"))
132         trace1 = iface1.enable_trace("P2PAsciiTrace")
133         ip1 = iface1.add_address()
134         ip1.set_attribute_value("Address", "10.0.0.1")
135
136         node2 = ns3_desc.create("ns3::Node")
137         ipv42 = ns3_desc.create("ns3::Ipv4L3Protocol")
138         arp2  = ns3_desc.create("ns3::ArpL3Protocol")
139         icmp2 = ns3_desc.create("ns3::Icmpv4L4Protocol")
140         node2.connector("protos").connect(ipv42.connector("node"))
141         node2.connector("protos").connect(arp2.connector("node"))
142         node2.connector("protos").connect(icmp2.connector("node"))
143         iface2 = ns3_desc.create("ns3::PointToPointNetDevice")
144         queue2 = ns3_desc.create("ns3::DropTailQueue")
145         node2.connector("devs").connect(iface2.connector("node"))
146         iface2.connector("queue").connect(queue2.connector("dev"))
147         trace2 = iface2.enable_trace("P2PAsciiTrace")
148         ip2 = iface2.add_address()
149         ip2.set_attribute_value("Address", "10.0.0.2")
150
151         chan = ns3_desc.create("ns3::PointToPointChannel")
152         iface1.connector("chan").connect(chan.connector("dev2"))
153         iface2.connector("chan").connect(chan.connector("dev2"))
154
155         app = ns3_desc.create("ns3::V4Ping")
156         app.set_attribute_value("Remote", "10.0.0.2")
157         app.set_attribute_value("StartTime", "0s")
158         app.set_attribute_value("StopTime", "20s")
159         app.connector("node").connect(node1.connector("apps"))
160
161         if daemonize_testbed:
162             ns3_desc.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
163             inst_root_dir = os.path.join(self.root_dir, "instance")
164             os.mkdir(inst_root_dir)
165             ns3_desc.set_attribute_value(DC.ROOT_DIRECTORY, inst_root_dir)
166             #ns3_desc.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
167
168         xml = exp_desc.to_xml()
169         
170         if controller_access_configuration:
171             controller = ExperimentController(xml, self.root_dir)
172         else:
173             controller = proxy.create_experiment_controller(xml, 
174                 controller_access_configuration)
175         
176         try:
177             controller.start()
178             while not controller.is_finished(app.guid):
179                 time.sleep(0.5)
180             ping_result = controller.trace(iface2.guid, "P2PAsciiTrace")
181             comp_result = "- 19.021 /NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Dequeue ns3::PppHeader (Point-to-Point Protocol: IP (0x0021)) ns3::Ipv4Header (tos 0x0 ttl 64 id 19 protocol 1 offset 0 flags [none] length: 84 10.0.0.2 > 10.0.0.1) ns3::Icmpv4Header (type=0, code=0) ns3::Icmpv4Echo (identifier=0, sequence=19)"
182             if ping_result.find(comp_result) == -1:
183                 self.fail("Unexpected trace: %s" % (ping_result,))
184         finally:
185             controller.stop()
186             controller.shutdown()
187
188     @test_util.skipUnless(test_util.ns3_usable(), 
189            "Test requires working ns-3 bindings")
190     def test_all_daemonized_fd_net_device(self):
191         access_config = proxy.AccessConfiguration()
192         access_config.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
193         access_config.set_attribute_value(DC.ROOT_DIRECTORY, self.root_dir)
194         #access_config.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
195
196         self._test_fd_net_device(
197             daemonize_testbed = True,
198             controller_access_configuration = access_config)
199
200     @test_util.skipUnless(test_util.ns3_usable(), 
201            "Test requires working ns-3 bindings")
202     def test_all_ssh_daemonized_fd_net_device(self):
203         env = test_util.test_environment()
204
205         access_config = proxy.AccessConfiguration()
206         access_config.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
207         access_config.set_attribute_value(DC.ROOT_DIRECTORY, self.root_dir)
208         #access_config.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
209         access_config.set_attribute_value(DC.DEPLOYMENT_COMMUNICATION, DC.ACCESS_SSH)
210         access_config.set_attribute_value(DC.DEPLOYMENT_PORT, env.port)
211         access_config.set_attribute_value(DC.USE_AGENT, True)
212         
213         self._test_fd_net_device(
214             daemonize_testbed = True,
215             controller_access_configuration = access_config)
216
217     @test_util.skipUnless(test_util.ns3_usable(), 
218            "Test requires working ns-3 bindings")
219     def test_local_if(self):
220         self._test_if(
221             daemonize_testbed = False,
222             controller_access_configuration = None)
223
224     @test_util.skipUnless(test_util.ns3_usable(), 
225            "Test requires working ns-3 bindings")
226     def test_all_daemonized_if(self):
227         access_config = proxy.AccessConfiguration()
228         access_config.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
229         access_config.set_attribute_value(DC.ROOT_DIRECTORY, self.root_dir)
230         #access_config.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
231
232         self._test_if(
233             daemonize_testbed = True,
234             controller_access_configuration = access_config)
235
236     @test_util.skipUnless(test_util.ns3_usable(), 
237            "Test requires working ns-3 bindings")
238     def test_all_ssh_daemonized_if(self):
239         env = test_util.test_environment()
240
241         access_config = proxy.AccessConfiguration()
242         access_config.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
243         access_config.set_attribute_value(DC.ROOT_DIRECTORY, self.root_dir)
244         #access_config.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
245         access_config.set_attribute_value(DC.DEPLOYMENT_COMMUNICATION, DC.ACCESS_SSH)
246         access_config.set_attribute_value(DC.DEPLOYMENT_PORT, env.port)
247         access_config.set_attribute_value(DC.USE_AGENT, True)
248         
249         self._test_if(
250             daemonize_testbed = True,
251             controller_access_configuration = access_config)
252
253     def tearDown(self):
254         try:
255             shutil.rmtree(self.root_dir)
256         except:
257             # retry
258             time.sleep(0.1)
259             shutil.rmtree(self.root_dir)
260
261 if __name__ == '__main__':
262     unittest.main()
263