Added new test for Planetlab node
[nepi.git] / test / resources / planetlab / node.py
1 #!/usr/bin/env python
2 #
3 #    NEPI, a framework to manage network experiments
4 #    Copyright (C) 2013 INRIA
5 #
6 #    This program is free software: you can redistribute it and/or modify
7 #    it under the terms of the GNU General Public License as published by
8 #    the Free Software Foundation, either version 3 of the License, or
9 #    (at your option) any later version.
10 #
11 #    This program is distributed in the hope that it will be useful,
12 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 #    GNU General Public License for more details.
15 #
16 #    You should have received a copy of the GNU General Public License
17 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 #
19 # Author: Lucia Guevgeozian <lucia.guevgeozian_odizzio@inria.fr>
20
21 from nepi.execution.ec import ExperimentController
22 #from nepi.execution.resource import ResourceAction, ResourceState, populate_factory
23
24 from nepi.resources.planetlab.node import PlanetlabNode
25 from nepi.resources.planetlab.plcapi import PLCAPI
26
27 import os
28 import time
29 import unittest
30
31
32 class DummyEC(ExperimentController):
33     pass
34
35 def create_node(ec, username, pl_user, pl_password, hostname=None, country=None,
36                 operatingSystem=None, minBandwidth=None, minCpu=None):
37
38     node = ec.register_resource("PlanetlabNode")
39
40     if username:
41         ec.set(node, "username", username)
42     if pl_user:
43         ec.set(node, "pluser", pl_user)
44     if pl_password:
45         ec.set(node, "password", pl_password)
46
47     if hostname:
48         ec.set(node, "hostname", hostname)
49     if country:
50         ec.set(node, "country", country)
51     if operatingSystem:
52         ec.set(node, "operatingSystem", operatingSystem)
53     if minBandwidth:
54         iec.set(node, "minBandwidth", minBandwidth)
55     if minCpu:
56         ec.set(node, "minCpu", minCpu)
57
58     ec.set(node, "cleanHome", True)
59     ec.set(node, "cleanProcesses", True)
60     
61     return ec
62
63 class PLNodeFactoryTestCase(unittest.TestCase):
64
65     def test_creation_phase(self):
66         self.assertEquals(PlanetlabNode.rtype(), "PlanetlabNode")
67         self.assertEquals(len(PlanetlabNode._attributes), 30)
68         self.assertEquals(len(PlanetlabNode.blacklist), 0)
69         self.assertEquals(len(PlanetlabNode.provisionlist), 0)
70
71
72 class PLNodeTestCase(unittest.TestCase):
73     """
74     This tests use inria_sfatest slice, and certain nodes already added to the
75     slice, and ONLY those in order for the test not to fail.
76     """
77
78     def setUp(self):
79         self.ec = DummyEC()
80         self.username = "inria_sfatest"
81         self.pl_user = os.environ.get("PL_USER")
82         self.pl_password = os.environ.get("PL_PASS")
83
84     def test_plapi(self):
85         """
86         Check that the api to discover and reserve resources is well
87         instanciated, and is an instance of PLCAPI. Ignore error while
88         executing the ec.shutdown method, the error is due to the name
89         of the host not being defined yet for this test.
90         """
91         self.ec = create_node(self.ec, self.username, self.pl_user, 
92             self.pl_password, country="France")
93
94         plnode_rm = self.ec.get_resource(1)
95         hostname = plnode_rm.get("hostname")
96         self.assertIsNone(hostname)
97
98         self.assertIsNone(plnode_rm._node_to_provision)
99
100         api = plnode_rm.plapi
101         self.assertIsInstance(api, PLCAPI)
102
103         # Set hostname attribute in order for the shutdown method not to fail
104         plnode_rm._set_hostname_attr(7057)
105
106     def test_discover_inslice(self):
107         """
108         This test uses the fact that the node planetlab2.utt.fr is already in 
109         the slice and match the constraints OS Fedora12 and country France.
110         Check planetlab2.utt.fr is alive if the test fails.
111         """
112         self.ec = create_node(self.ec, self.username, self.pl_user,
113             self.pl_password, country="France", operatingSystem="f12")
114
115         plnode_rm = self.ec.get_resource(1)
116         
117         hostname = plnode_rm.get("hostname")
118         self.assertIsNone(hostname)
119
120         plnode_rm.discoverl()
121         self.assertEquals(plnode_rm._node_to_provision, 7057)
122
123         # Set hostname attribute in order for the shutdown method not to fail
124         plnode_rm._set_hostname_attr(plnode_rm._node_to_provision)        
125
126     def test_discover_not_inslice(self):
127         """
128         This test checks that if the node is not in the slice, anyway the
129         discover method picks one that match constraints outside from the
130         slice.
131         """
132         self.ec = create_node(self.ec, self.username, self.pl_user,
133             self.pl_password, country="France", operatingSystem="f14")
134
135         plnode_rm = self.ec.get_resource(1)
136         plnode_rm.discoverl()
137     
138         result = [14281, 1034, 7035] # nodes matching f14 and France
139         self.assertIn(plnode_rm._node_to_provision, result)     
140         self.assertIsNot(PlanetlabNode.provisionlist, list())
141
142         # Set hostname attribute in order for the shutdown method not to fail
143         plnode_rm._set_hostname_attr(plnode_rm._node_to_provision)        
144
145     def test_discover_hostname(self):
146         """
147         This test checks that if the user specify the hostname, only that node
148         is discovered.
149         """
150         self.ec = create_node(self.ec, self.username, self.pl_user,
151                 self.pl_password, hostname="planetlab1.sics.se")
152
153         plnode_rm = self.ec.get_resource(1)
154         plnode_rm.discoverl()
155
156         self.assertEquals(plnode_rm._node_to_provision, 14871)
157         self.assertEquals(PlanetlabNode.provisionlist, [14871])
158
159     def test_discover_with_ranges(self):
160         """
161         Checks that defining max or min attributes, the discover method works.
162         """
163         self.ec = create_node(self.ec, self.username, self.pl_user,
164             self.pl_password, minCpu=50) #minBandwidth=500)
165
166         plnode_rm = self.ec.get_resource(1)
167         plnode_rm.discoverl()
168
169         #result = [15815, 15814, 425, 417, 1054, 1102, 1107, 505, 1031] 
170         result = [425, 15815, 15814, 14842, 427, 41, 14466]
171         self.assertIn(plnode_rm._node_to_provision, result)
172         self.assertIsNot(PlanetlabNode.provisionlist, list())
173
174         # Set hostname attribute in order for the shutdown method not to fail
175         plnode_rm._set_hostname_attr(plnode_rm._node_to_provision)        
176         
177     def test_blacklist_nodes(self):
178         """
179         Test that if the node is malfunctioning it gets blacklisted, the node
180         planetlab-1a.ics.uci.edu is used, if the test fails, check that the 
181         result of the plcapi query is actually empty.
182         """
183         self.ec = create_node(self.ec, self.username, self.pl_user,
184                 self.pl_password, hostname="planetlab-1a.ics.uci.edu")
185
186         plnode_rm = self.ec.get_resource(1)
187         self.assertEquals(PlanetlabNode.blacklist, list())
188
189         # check that the node is actually malfunctioning
190         api = plnode_rm.plapi
191         filters = {'boot_state': 'boot', '>last_contact': 1378299413, 
192             'node_type': 'regular', 'hostname': 'planetlab-1a.ics.uci.edu', 
193             'run_level': 'boot'}
194         node_id = api.get_nodes(filters, fields=['node_id'])
195
196         if not node_id:
197             with self.assertRaises(RuntimeError):
198                 plnode_rm.discoverl()
199                 self.assertEquals(PlanetlabNode.blacklist, [14871])
200
201     def test_provision_node_inslice(self):
202         """
203         Check provision of the node planetlab2.utt.fr.
204         """
205         self.ec = create_node(self.ec, self.username, self.pl_user,
206             self.pl_password, country="France", operatingSystem="f12")
207
208         plnode_rm = self.ec.get_resource(1)
209         self.assertEquals(len(PlanetlabNode.blacklist), 0)
210         self.assertEquals(len(PlanetlabNode.provisionlist), 0)
211
212         plnode_rm.discoverl()
213         plnode_rm.provisionl()
214         ip = plnode_rm.get("ip")
215         self.assertEquals(ip, "194.254.215.12")
216
217     def test_provision_node_not_inslice(self):
218         """
219         Check provision of one of the nodes f14 France, nodes:
220         node1pl.planet-lab.telecom-lille1.eu
221         ple5.ipv6.lip6.fr
222         node2pl.planet-lab.telecom-lille1.eu
223         """
224         self.ec = create_node(self.ec, self.username, self.pl_user,
225             self.pl_password, country="France", operatingSystem="f14")
226
227         plnode_rm = self.ec.get_resource(1)
228         self.assertEquals(PlanetlabNode.blacklist, list())
229         self.assertEquals(PlanetlabNode.provisionlist, list())
230
231         plnode_rm.discoverl()
232         plnode_rm.provisionl()
233         ip = plnode_rm.get("ip")       
234
235         result = ["194.167.254.18","132.227.62.123","194.167.254.19"] 
236         self.assertIn(ip, result)
237
238
239     def test_provision_more_than_available(self):
240         """
241         Check that if the user wants to provision 4 nodes with fedora 14, he
242         gets RuntimeError, there are only 3 nodes f14.
243         """
244         self.ec = create_node(self.ec, self.username, self.pl_user,
245             self.pl_password, country="France", operatingSystem="f14")
246
247         plnode_rm1 = self.ec.get_resource(1)
248         plnode_rm1.discoverl()
249         plnode_rm1.provisionl()
250
251         self.ec = create_node(self.ec, self.username, self.pl_user,
252             self.pl_password, country="France", operatingSystem="f14")
253
254         plnode_rm2 = self.ec.get_resource(2)
255         plnode_rm2.discoverl()
256         plnode_rm2.provisionl()
257
258         self.ec = create_node(self.ec, self.username, self.pl_user,
259             self.pl_password, country="France", operatingSystem="f14")
260
261         plnode_rm3 = self.ec.get_resource(3)
262         with self.assertRaises(RuntimeError):
263             plnode_rm3.discoverl()
264             with self.assertRaises(RuntimeError):
265                 plnode_rm3.provisionl()
266         
267         self.ec = create_node(self.ec, self.username, self.pl_user,
268             self.pl_password, country="France", operatingSystem="f14")
269
270         plnode_rm4 = self.ec.get_resource(4)
271         with self.assertRaises(RuntimeError):
272             plnode_rm4.discoverl()
273             with self.assertRaises(RuntimeError):
274                 plnode_rm4.provisionl()
275
276
277     def tearDown(self):
278         PlanetlabNode.provisionlist = list()
279         PlanetlabNode.blacklist = list()
280         self.ec.shutdown()
281
282
283 if __name__ == '__main__':
284     unittest.main()
285
286
287