2 NEPI, a framework to manage network experiments
3 Copyright (C) 2013 INRIA
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
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.
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/>.
18 Author: Alina Quereilhac <alina.quereilhac@inria.fr>
19 Julien Tribino <julien.tribino@inria.fr>
29 content l1 / \ l2 ccncat
31 0 ----- h1 0 --- 0 h3 ------ 0
38 * t0 : b2 retrives video published in b1
39 * t1 : l5 goes down after 15 sec
44 from nepi.execution.resource import ResourceFactory, ResourceAction, ResourceState
45 from nepi.execution.ec import ExperimentController
47 from optparse import OptionParser, SUPPRESS_HELP
49 ### Define OMF Method to simplify definition of resources ###
50 def add_node(ec, hostname, xmppServer, xmppUser, xmppPort = "5222", xmppPassword = "1234"):
51 node = ec.register_resource("OMFNode")
52 ec.set(node, 'hostname', hostname)
53 ec.set(node, 'xmppServer', xmppServer)
54 ec.set(node, 'xmppUser', xmppUser)
55 ec.set(node, 'xmppPort', xmppPort)
56 ec.set(node, 'xmppPassword', xmppPassword)
57 ec.set(node, 'version', "5")
60 def add_interface(ec, ip, xmppServer, xmppUser, essid = "ccn", name = "wlan0", mode = "adhoc",
61 typ = "g", xmppPort = "5222", xmppPassword = "1234"):
62 iface = ec.register_resource("OMFWifiInterface")
63 ec.set(iface, 'name', name)
64 ec.set(iface, 'mode', mode)
65 ec.set(iface, 'hw_mode', typ)
66 ec.set(iface, 'essid', essid)
67 ec.set(iface, 'ip', ip)
68 ec.set(iface, 'version', "5")
71 def add_channel(ec, channel, xmppServer, xmppUser, xmppPort = "5222", xmppPassword = "1234"):
72 chan = ec.register_resource("OMFChannel")
73 ec.set(chan, 'channel', channel)
74 ec.set(chan, 'xmppServer', xmppServer)
75 ec.set(chan, 'xmppUser', xmppUser)
76 ec.set(chan, 'xmppPort', xmppPort)
77 ec.set(chan, 'xmppPassword', xmppPassword)
78 ec.set(chan, 'version', "5")
81 def add_app(ec, host, appid, command, env, xmppServer, xmppUser,
82 xmppPort = "5222", xmppPassword = "1234"):
83 app = ec.register_resource("OMFApplication")
84 ec.set(app, 'appid', appid)
85 ec.set(app, 'command', command)
86 ec.set(app, 'env', env)
87 ec.set(app, 'version', "5")
88 ec.register_connection(app, host)
92 ### Define a CCND application ###
93 def add_ccnd(ec, host, peers, xmppServer, xmppUser, xmppPort = "5222", xmppPassword = "1234"):
94 env = 'PATH=$PATH:/root/ccnx-0.7.2/bin HOME=/root \
95 CCNR_DIRECTORY="/root" CCNR_STATUS_PORT="8080"'
97 # BASH command -> ' ccndstart ; ccndc add ccnx:/ udp host ; ccnr '
98 command = "ccndc add ccnx:/ udp " + peers
99 app = add_app(ec, host, "#ccnd", command, env, xmppServer, xmppUser,
100 xmppPort = xmppPort, xmppPassword = xmppPassword)
103 ### Define a CCN SeqWriter application ###
104 def add_publish(ec, host, movie, xmppServer, xmppUser, xmppPort = "5222", xmppPassword = "1234"):
105 env = 'PATH=$PATH:/root/ccnx-0.7.2/bin HOME=/root CCNR_DIRECTORY="/root" CCNR_STATUS_PORT="8080"'
107 # BASH command -> 'ccnseqwriter -r ccnx:/VIDEO < movie'
108 command = "ccnseqwriter -r ccnx:/VIDEO"
109 command += " < " + movie
111 app = add_app(ec, host, "#ccn_write", command, env, xmppServer, xmppUser,
112 xmppPort = xmppPort, xmppPassword = xmppPassword)
115 ### Define a streaming application ###
116 def add_stream(ec, host, xmppServer, xmppUser, xmppPort = "5222", xmppPassword = "1234"):
117 env = 'PATH=$PATH:/root/ccnx-0.7.2/bin HOME=/root CCNR_DIRECTORY="/root" CCNR_STATUS_PORT="8080"'
118 command = " ddbus-uuidgen --ensure ; ( /root/ccnx-0.7.2/bin/ccncat ccnx:/VIDEO | /root/vlc-1.1.13/cvlc - ) "
119 app = add_app(ec, host, "#ccn_stream", command, env, xmppServer, xmppUser,
120 xmppPort = xmppPort, xmppPassword = xmppPassword)
123 ### Many options to easily addapt the script ####
125 usage = "usage: %prog -c <channel> -s <xmpp_slice> -x <xmpp_host> -m <movie>"
127 parser = OptionParser(usage=usage)
128 parser.add_option("-c", "--channel", dest="channel",
129 help="Channel of the communication", type="str")
130 parser.add_option("-s", "--xmpp-slice", dest="xmpp_slice",
131 help="Name of the slice XMPP", type="str")
132 parser.add_option("-x", "--xmpp-host", dest="xmpp_host",
133 help="Name of the host XMPP", type="str")
134 parser.add_option("-m", "--movie", dest="movie",
135 help="Stream movie", type="str")
136 #parser.add_option("-e", "--exp-id", dest="exp_id",
137 # help="Label to identify experiment", type="str")
139 (options, args) = parser.parse_args()
141 if not options.movie:
142 parser.error("movie is a required argument")
144 return (options.channel, options.xmpp_slice,
145 options.xmpp_host ,options.movie)
147 ### Script itself ###
148 if __name__ == '__main__':
149 (channel, xmpp_slice, xmpp_host, movie) = get_options()
151 env = 'PATH=$PATH:/root/ccnx-0.7.2/bin HOME=/root CCNR_DIRECTORY="/root" CCNR_STATUS_PORT="8080"'
154 ec = ExperimentController()
156 # Create the topology
157 host1 = "omf.nitos.node022"
158 host2 = "omf.nitos.node028"
159 host3 = "omf.nitos.node024"
160 host4 = "omf.nitos.node025"
161 host5 = "omf.nitos.node026" # b1
162 host6 = "omf.nitos.node027" # b2
164 ip1 = "192.168.0.22/24"
165 ip2 = "192.168.0.28/24"
166 ip3 = "192.168.0.24/24"
167 ip4 = "192.168.0.25/24"
168 ip5 = "192.168.0.26/24"
169 ip6 = "192.168.0.27/24"
171 all_hosts = [host1, host2, host3, host4, host5, host6]
172 all_ip = [ip1, ip2, ip3, ip4, ip5, ip6]
174 ring_hosts = [host1, host2, host3, host4]
177 chann = add_channel(ec, channel, xmpp_slice, xmpp_host)
178 for i in xrange(len(all_hosts)):
179 node = add_node(ec,all_hosts[i], xmpp_slice, xmpp_host)
180 iface = add_interface(ec, all_ip[i], xmpp_slice, xmpp_host)
181 ec.register_connection(node, iface)
182 ec.register_connection(iface, chann)
183 nodes[all_hosts[i]] = node
185 # CCN setup for the node
188 for i in xrange(len(all_hosts)):
189 ccndstart = add_app(ec, nodes[all_hosts[i]], "#ccndstart", "ccndstart &",
190 env, xmpp_slice, xmpp_host)
191 ccnr = add_app(ec, nodes[all_hosts[i]], "#ccnr", "ccnr &",
192 env, xmpp_slice, xmpp_host)
193 ccnds[all_hosts[i]] = ccndstart
194 ccnrs[all_hosts[i]] = ccnr
195 ec.register_condition(ccnr, ResourceAction.START, ccndstart, ResourceState.STARTED, "1s")
198 # l1 : h1 - h2 , h2 - h1
199 l1u = add_ccnd(ec, nodes[host1], ip2, xmpp_slice, xmpp_host)
200 l1d = add_ccnd(ec, nodes[host2], ip1, xmpp_slice, xmpp_host)
202 # l2 : h2 - h3 , h3 - h2
203 l2u = add_ccnd(ec, nodes[host2], ip3, xmpp_slice, xmpp_host)
204 l2d = add_ccnd(ec, nodes[host3], ip2, xmpp_slice, xmpp_host)
206 # l3 : h3 - h4 , h4 - h3
207 l3u = add_ccnd(ec, nodes[host3], ip4, xmpp_slice, xmpp_host)
208 l3d = add_ccnd(ec, nodes[host4], ip3, xmpp_slice, xmpp_host)
210 # l4 : h4 - h1 , h1 - h4
211 l4u = add_ccnd(ec, nodes[host4], ip1, xmpp_slice, xmpp_host)
212 l4d = add_ccnd(ec, nodes[host1], ip4, xmpp_slice, xmpp_host)
214 # l5 : h1 - h3 , h3 - h1
215 l5u = add_ccnd(ec, nodes[host1], ip3, xmpp_slice, xmpp_host)
216 l5d = add_ccnd(ec, nodes[host3], ip1, xmpp_slice, xmpp_host)
218 # connect border nodes
219 b1u = add_ccnd(ec, nodes[host5], ip1, xmpp_slice, xmpp_host)
220 b1d = add_ccnd(ec, nodes[host1], ip5, xmpp_slice, xmpp_host)
222 b2u = add_ccnd(ec, nodes[host6], ip3, xmpp_slice, xmpp_host)
223 b2d = add_ccnd(ec, nodes[host3], ip6, xmpp_slice, xmpp_host)
225 link = [l1u, l1d, l2u, l2d, l3u, l3d, l4u, l4d, l5u, l5d, b1u, b1d, b2u, b2d]
228 for i in xrange(len(all_hosts)):
229 ec.register_condition(ccnrs[all_hosts[i]], ResourceAction.START, ccnds[all_hosts[i]], ResourceState.STARTED, "1s")
230 ec.register_condition(link, ResourceAction.START, ccnrs[all_hosts[i]], ResourceState.STARTED, "1s")
233 pub = add_publish(ec, nodes[host5], movie, xmpp_slice, xmpp_host)
236 stream = add_stream(ec, nodes[host6], xmpp_slice, xmpp_host)
238 # Streaming conditions
239 ec.register_condition(pub, ResourceAction.START, link, ResourceState.STARTED, "2s")
240 ec.register_condition(stream, ResourceAction.START, link, ResourceState.STARTED, "2s")
241 ec.register_condition(stream, ResourceAction.START, pub, ResourceState.STARTED, "2s")
244 ccndcstop1 = add_app(ec,nodes[host1], "#ccndc", "ccndc del ccnx:/ udp " + ip3, env, xmpp_slice, xmpp_host)
245 ccndcstop2 = add_app(ec,nodes[host3], "#ccndc", "ccndc del ccnx:/ udp " + ip1, env, xmpp_slice, xmpp_host)
248 # Change the behaviour
249 ec.register_condition(l5u, ResourceAction.STOP, stream, ResourceState.STARTED, "10s")
250 ec.register_condition(l5d, ResourceAction.STOP, stream, ResourceState.STARTED, "10s")
252 ec.register_condition(ccndcstop1, ResourceAction.START, stream, ResourceState.STARTED, "10s")
253 ec.register_condition(ccndcstop2, ResourceAction.START, stream, ResourceState.STARTED, "10s")
255 # Cleaning when the experiment stop
257 for i in xrange(len(all_hosts)):
258 ccndstop = add_app(ec, nodes[all_hosts[i]], "#ccndstop", "ccndstop", env, xmpp_slice, xmpp_host)
259 ccndstops.append(ccndstop)
261 killall = add_app(ec, nodes[host6], "#kill", "killall sh", "", xmpp_slice, xmpp_host)
263 # Condition to stop and clean the experiment
265 for i in xrange(len(all_hosts)):
266 apps.append(ccnds[all_hosts[i]])
267 apps.append(ccnrs[all_hosts[i]])
272 ec.register_condition(apps, ResourceAction.STOP, stream, ResourceState.STARTED, "30s")
274 ec.register_condition(ccndstops + [killall], ResourceAction.START, apps, ResourceState.STOPPED, "1s")
275 ec.register_condition(ccndstops + [killall], ResourceAction.STOP, ccndstops, ResourceState.STARTED, "1s")
277 # Deploy all ResourceManagers
280 # Wait until the applications are finished
281 ec.wait_finished(ccndstops)
283 # Shutdown the experiment controller