use print() - import print_function - should be fine for both py2 and py3
[nepi.git] / examples / planetlab / ping_with_filters.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 version 2 as
8 #    published by the Free Software Foundation;
9 #
10 #    This program is distributed in the hope that it will be useful,
11 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #    GNU General Public License for more details.
14 #
15 #    You should have received a copy of the GNU General Public License
16 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #
18 # Author: Lucia Guevgeozian <lucia.guevgeozian_odizzio@inria.fr>
19
20 # Example of how to run this experiment (replace with your information):
21 #
22 # $ cd <path-to-nepi>
23 # python examples/planetlab/ping_with_filters.py -s <pl-slice> -u <pl-user> -p <pl-password> -k <pl-ssh-key>  
24
25 from __future__ import print_function
26
27 from nepi.execution.ec import ExperimentController
28 from nepi.execution.resource import ResourceAction, ResourceState
29
30 from optparse import OptionParser
31 import os
32
33
34 def create_node(ec, pl_slice, pl_ssh_key, pl_user, pl_password, 
35        hostname = None, country = None, operatingSystem = None, 
36        minBandwidth = None, minCpu = None):
37
38     node = ec.register_resource("planetlab::Node")
39
40     ec.set(node, "username", pl_slice)
41     ec.set(node, "identity", pl_ssh_key)
42     ec.set(node, "pluser", pl_user)
43     ec.set(node, "plpassword", pl_password)
44
45     if hostname:
46         ec.set(node, "hostname", hostname)
47     if country:
48         ec.set(node, "country", country)
49     if operatingSystem:
50         ec.set(node, "operatingSystem", operatingSystem)
51     if minBandwidth:
52         ec.set(node, "minBandwidth", minBandwidth)
53     if minCpu:
54         ec.set(node, "minCpu", minCpu)
55
56     ec.set(node, "cleanExperiment", True)
57     ec.set(node, "cleanProcesses", True)
58     
59     return node
60
61 def add_app(ec, command, node, newname = None, sudo = None, 
62         video = None, depends = None, forward_x11 = None, env = None):
63     app = ec.register_resource("linux::Application")
64
65     if sudo is not None:
66         ec.set(app, "sudo", sudo)
67     if video is not None:
68         ec.set(app, "sources", video)
69     if depends is not None:
70         ec.set(app, "depends", depends)
71     if forward_x11 is not None:
72         ec.set(app, "forwardX11", forward_x11)
73     if env is not None:
74         ec.set(app, "env", env)
75
76     ec.set(app, "command", command)
77
78     ec.register_connection(app, node)
79
80     # add collector to download application standar output
81     collector = ec.register_resource("Collector")
82     ec.set(collector, "traceName", "stdout")
83     if newname:
84         ec.set(collector, "rename", newname)
85     ec.register_connection(app, collector)
86
87     return app
88
89 usage = ("usage: %prog -s <pl-slice> -u <pl-user> -p <pl-password> "
90     "-k <pl-ssh-key> -c <country> -o <operating-system> -H <hostname> ")
91
92 parser = OptionParser(usage = usage)
93 parser.add_option("-s", "--pl-slice", dest="pl_slice",
94         help="PlanetLab slicename", type="str")
95 parser.add_option("-u", "--pl-user", dest="pl_user",
96         help="PlanetLab web username", type="str")
97 parser.add_option("-p", "--pl-password", dest="pl_password",
98         help="PlanetLab web password", type="str")
99 parser.add_option("-k", "--pl-ssh-key", dest="pl_ssh_key",
100         help="Path to private SSH key associated with the PL account",
101         type="str")
102 parser.add_option("-c", "--country", dest="country",
103         help="Country for the PL hosts",
104         type="str")
105 parser.add_option("-o", "--os", dest="os",
106         help="Operating system for the PL hosts", default="f14",
107         type="str")
108 parser.add_option("-H", "--hostname", dest="hostname",
109         help="PlanetLab hostname",
110         type="str")
111
112 (options, args) = parser.parse_args()
113
114 pl_slice = options.pl_slice
115 pl_ssh_key = options.pl_ssh_key
116 pl_user = options.pl_user
117 pl_password = options.pl_password
118 hostname = options.hostname
119 country = options.country
120 os = options.os
121
122 # Create the entity Experiment Controller:
123 ec = ExperimentController("pl_ping_filters")
124
125 # Register the nodes resources:
126
127 # Choose the PlanetLab nodes for the experiment, in this example 5 nodes are
128 # used, and they are picked according to different criterias.
129
130 # First node will be the one defined by its hostname.
131 node1 = create_node(ec, pl_slice, pl_ssh_key, pl_user, pl_password, 
132         hostname = hostname)
133
134 # Second node will be any node in the selected country.
135 node2 = create_node(ec, pl_slice, pl_ssh_key, pl_user, pl_password, 
136         country=country)
137
138 # Third node will be a node in the selected country and with the selected
139 # fedora OS
140 node3 = create_node(ec, pl_slice, pl_ssh_key, pl_user, pl_password, 
141         country = country,
142         operatingSystem = os)
143
144 # Forth node will have at least 50% of CPU available
145 minCpu=50
146 node4 = create_node(ec, pl_slice, pl_ssh_key, pl_user, pl_password, 
147         minCpu = minCpu)
148
149 # Fifth node can be any node, constrains are not important.
150 node5 = create_node(ec, pl_slice, pl_ssh_key, pl_user, pl_password)
151
152 # Register the applications to run in the nodes, in this case just ping to the 
153 # first node:
154 apps = []
155 for node in [node2, node3, node4, node5]:
156     command = "ping -c5 %s" % hostname
157     trace_name = "%s.ping" % hostname
158     app = add_app(ec, command, node, newname = trace_name)
159     apps.append(app)
160
161 # Register conditions
162
163 # The nodes that are completely identified by their hostnames have to be provisioned 
164 # before the rest of the nodes. This assures that no other resource will use the
165 # identified node even if the constraints matchs. 
166 # In this example node2, node3, node4 and node5, are deployed after node1 is 
167 # provisioned. node1 must be the node hostname, meanwhile node2, node3,
168 # node4 and node5 just need to fulfill certain constraints.
169 # Applications are always deployed after nodes, so no need to register conditions
170 # for the apps in this example.
171
172 ec.register_condition(node2, ResourceAction.DEPLOY, node1, ResourceState.PROVISIONED)
173 ec.register_condition(node3, ResourceAction.DEPLOY, node1, ResourceState.PROVISIONED)
174 ec.register_condition(node4, ResourceAction.DEPLOY, node1, ResourceState.PROVISIONED)
175 ec.register_condition(node5, ResourceAction.DEPLOY, node1, ResourceState.PROVISIONED)
176     
177 # Deploy the experiment:
178 ec.deploy()
179
180 # Wait until the applications are finish to retrive the traces:
181 ec.wait_finished(apps)
182
183 print("Results stored at", ec.exp_dir)
184
185 # Do the experiment controller shutdown:
186 ec.shutdown()
187
188 # END