3 # NEPI, a framework to manage network experiments
4 # Copyright (C) 2013 INRIA
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.
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.
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/>.
19 # Author: Lucia Guevgeozian <lucia.guevgeozian_odizzio@inria.fr>
21 from nepi.execution.ec import ExperimentController
23 from nepi.resources.planetlab.node import PlanetlabNode
24 from nepi.resources.planetlab.plcapi import PLCAPI, PLCAPIFactory
29 import multiprocessing
31 def create_node(ec, username, pl_user, pl_password, hostname = None,
32 country = None, operatingSystem = None, minBandwidth = None,
35 node = ec.register_resource("PlanetlabNode")
38 ec.set(node, "username", username)
40 ec.set(node, "pluser", pl_user)
42 ec.set(node, "plpassword", pl_password)
45 ec.set(node, "hostname", hostname)
47 ec.set(node, "country", country)
49 ec.set(node, "operatingSystem", operatingSystem)
51 iec.set(node, "minBandwidth", minBandwidth)
53 ec.set(node, "minCpu", minCpu)
55 ec.set(node, "cleanHome", True)
56 ec.set(node, "cleanProcesses", True)
60 class PLNodeFactoryTestCase(unittest.TestCase):
61 def test_creation_phase(self):
62 self.assertEquals(PlanetlabNode.get_rtype(), "PlanetlabNode")
63 self.assertEquals(len(PlanetlabNode._attributes), 29)
66 class PLNodeTestCase(unittest.TestCase):
68 This tests use inria_sfatest slice, and planetlab2.utt.fr already added to
69 the slice, and ONLY this one in order for the test not to fail.
73 self.ec = ExperimentController()
74 self.username = "inria_sfatest"
75 self.pl_user = os.environ.get("PL_USER")
76 self.pl_password = os.environ.get("PL_PASS")
77 self.pl_url = "www.planet-lab.eu"
78 self.pl_ptn = "https://%(hostname)s:443/PLCAPI/"
82 Check that the api to discover and reserve resources is well
83 instanciated, and is an instance of PLCAPI. Ignore error while
84 executing the ec.shutdown method, the error is due to the name
85 of the host not being defined yet for this test.
87 node1 = create_node(self.ec, self.username, self.pl_user,
88 self.pl_password, country="France")
90 plnode_rm1 = self.ec.get_resource(node1)
91 hostname = plnode_rm1.get("hostname")
92 self.assertIsNone(hostname)
94 self.assertIsNone(plnode_rm1._node_to_provision)
96 api1 = plnode_rm1.plapi
97 self.assertIsInstance(api1, PLCAPI)
98 self.assertEquals(len(api1.reserved()), 0)
99 self.assertEquals(len(api1.blacklisted()), 0)
101 node2 = create_node(self.ec, self.username, self.pl_user,
102 self.pl_password, country="France")
104 plnode_rm2 = self.ec.get_resource(node2)
105 api2 = plnode_rm2.plapi
106 self.assertEquals(api1, api2)
108 # Set hostname attribute in order for the shutdown method not to fail
109 plnode_rm1._set_hostname_attr(7057)
110 plnode_rm2._set_hostname_attr(7057)
112 def test_discover_inslice(self):
114 This test uses the fact that the node planetlab2.utt.fr is already in
115 the slice and match the constraints OS Fedora12 and country France.
116 Check planetlab2.utt.fr is alive if the test fails.
118 node = create_node(self.ec, self.username, self.pl_user,
119 self.pl_password, country="France", operatingSystem="f12")
121 plnode_rm = self.ec.get_resource(node)
123 hostname = plnode_rm.get("hostname")
124 self.assertIsNone(hostname)
127 self.assertEquals(plnode_rm._node_to_provision, 7057)
129 # Set hostname attribute in order for the shutdown method not to fail
130 plnode_rm._set_hostname_attr(plnode_rm._node_to_provision)
132 def test_discover_not_inslice(self):
134 This test checks that if the node is not in the slice, anyway the
135 discover method picks one that match constraints outside from the
138 node = create_node(self.ec, self.username, self.pl_user,
139 self.pl_password, country="France", operatingSystem="f14")
141 plnode_rm = self.ec.get_resource(node)
144 result = [14281, 1034, 7035] # nodes matching f14 and France
145 self.assertIn(plnode_rm._node_to_provision, result)
146 self.assertIsNot(plnode_rm.plapi.reserved(), set())
148 # Set hostname attribute in order for the shutdown method not to fail
149 plnode_rm._set_hostname_attr(plnode_rm._node_to_provision)
151 def test_discover_hostname(self):
153 This test checks that if the user specify the hostname, only that node
156 node = create_node(self.ec, self.username, self.pl_user,
157 self.pl_password, hostname="planetlab1.sics.se")
159 plnode_rm = self.ec.get_resource(node)
162 self.assertEquals(plnode_rm._node_to_provision, 14871)
163 self.assertEquals(plnode_rm.plapi.reserved(), set([14871]))
165 def test_discover_with_ranges(self):
167 Checks that defining max or min attributes, the discover method works.
169 node = create_node(self.ec, self.username, self.pl_user,
170 self.pl_password, minCpu=50) #minBandwidth=500)
172 plnode_rm = self.ec.get_resource(node)
175 #result = [15815, 15814, 425, 417, 1054, 1102, 1107, 505, 1031]
176 result = [425, 15815, 15814, 14842, 427, 41, 14466]
177 self.assertIn(plnode_rm._node_to_provision, result)
178 self.assertIsNot(plnode_rm.plapi.reserved(), set())
180 # Set hostname attribute in order for the shutdown method not to fail
181 plnode_rm._set_hostname_attr(plnode_rm._node_to_provision)
183 def test_blacklist_nodes(self):
185 Test that if the node is malfunctioning it gets blacklisted, the node
186 planetlab-1a.ics.uci.edu is used, if the test fails, check that the
187 result of the plcapi query is actually empty.
189 node = create_node(self.ec, self.username, self.pl_user,
190 self.pl_password, hostname="planetlab-1a.ics.uci.edu")
192 plnode_rm = self.ec.get_resource(node)
193 self.assertEquals(plnode_rm.plapi.blacklisted(), set())
195 # check that the node is actually malfunctioning
196 api = plnode_rm.plapi
197 filters = {'boot_state': 'boot', '>last_contact': 1378299413,
198 'node_type': 'regular', 'hostname': 'planetlab-1a.ics.uci.edu',
200 node_id = api.get_nodes(filters, fields=['node_id'])
203 with self.assertRaises(RuntimeError):
205 self.assertEquals(plnode_rm.plapi.blacklisted(), set([14871]))
207 def test_provision_node_inslice(self):
209 Check provision of the node planetlab2.utt.fr.
211 node = create_node(self.ec, self.username, self.pl_user,
212 self.pl_password, country="France", operatingSystem="f12")
214 plnode_rm = self.ec.get_resource(node)
215 self.assertEquals(len(plnode_rm.plapi.blacklisted()), 0)
216 self.assertEquals(len(plnode_rm.plapi.reserved()), 0)
219 plnode_rm.provision()
220 ip = plnode_rm.get("ip")
221 self.assertEquals(ip, "194.254.215.12")
222 self.assertEquals(len(plnode_rm.plapi.reserved()), 1)
224 def test_provision_node_not_inslice(self):
226 Check provision of one of the nodes f14 France, nodes:
227 node1pl.planet-lab.telecom-lille1.eu
229 node2pl.planet-lab.telecom-lille1.eu
231 node = create_node(self.ec, self.username, self.pl_user,
232 self.pl_password, country="France", operatingSystem="f14")
234 plnode_rm = self.ec.get_resource(node)
235 self.assertEquals(plnode_rm.plapi.blacklisted(), set())
236 self.assertEquals(plnode_rm.plapi.reserved(), set())
239 plnode_rm.provision()
240 ip = plnode_rm.get("ip")
242 result = ["194.167.254.18","132.227.62.123","194.167.254.19"]
243 self.assertIn(ip, result)
245 def test_provision_more_than_available(self):
247 Check that if the user wants to provision 4 nodes with fedora 14, he
248 gets RuntimeError, there are only 3 nodes f14.
250 node1 = create_node(self.ec, self.username, self.pl_user,
251 self.pl_password, country="France", operatingSystem="f14")
253 plnode_rm1 = self.ec.get_resource(node1)
254 plnode_rm1.discover()
255 plnode_rm1.provision()
257 node2 = create_node(self.ec, self.username, self.pl_user,
258 self.pl_password, country="France", operatingSystem="f14")
260 plnode_rm2 = self.ec.get_resource(node2)
261 plnode_rm2.discover()
262 plnode_rm2.provision()
264 node3 = create_node(self.ec, self.username, self.pl_user,
265 self.pl_password, country="France", operatingSystem="f14")
267 plnode_rm3 = self.ec.get_resource(node3)
268 with self.assertRaises(RuntimeError):
269 plnode_rm3.discover()
270 with self.assertRaises(RuntimeError):
271 plnode_rm3.provision()
273 node4 = create_node(self.ec, self.username, self.pl_user,
274 self.pl_password, country="France", operatingSystem="f14")
276 plnode_rm4 = self.ec.get_resource(node4)
277 with self.assertRaises(RuntimeError):
278 plnode_rm4.discover()
280 host1 = plnode_rm1.get('hostname')
282 plnode_rm3._set_hostname_attr(host1)
283 plnode_rm4._set_hostname_attr(host1)
285 def test_concurrence(self):
287 Test with the nodes being discover and provision at the same time.
289 node1 = create_node(self.ec, self.username, self.pl_user,
290 self.pl_password, country="France", operatingSystem="f14")
292 node2 = create_node(self.ec, self.username, self.pl_user,
293 self.pl_password, country="France", operatingSystem="f14")
295 node3 = create_node(self.ec, self.username, self.pl_user,
296 self.pl_password, country="France", operatingSystem="f14")
298 node4 = create_node(self.ec, self.username, self.pl_user,
299 self.pl_password, country="France", operatingSystem="f14")
302 self.ec.wait_finished([node1, node2, node3, node4])
303 state = self.ec.ecstate
304 self.assertEquals(state, 2)
307 commonapi=PLCAPIFactory.get_api(self.pl_user, self.pl_password,
308 self.pl_url, self.pl_ptn)
309 commonapi._reserved = set()
310 commonapi._blacklist = set()
314 if __name__ == '__main__':