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 0 ------------------ 0
32 * t0 : b2 retrives video published in b1
37 from nepi.execution.resource import ResourceFactory, ResourceAction, ResourceState
38 from nepi.execution.ec import ExperimentController
40 from optparse import OptionParser, SUPPRESS_HELP
42 ### Define OMF Method to simplify definition of resources ###
43 def add_node(ec, hostname, xmppServer, xmppUser, xmppPort = "5222", xmppPassword = "1234"):
44 node = ec.register_resource("OMFNode")
45 ec.set(node, 'hostname', hostname)
46 ec.set(node, 'xmppServer', xmppServer)
47 ec.set(node, 'xmppUser', xmppUser)
48 ec.set(node, 'xmppPort', xmppPort)
49 ec.set(node, 'xmppPassword', xmppPassword)
50 ec.set(node, 'version', "5")
53 def add_interface(ec, ip, xmppServer, xmppUser, essid = "ccn", name = "wlan0", mode = "adhoc",
54 typ = "g", xmppPort = "5222", xmppPassword = "1234"):
55 iface = ec.register_resource("OMFWifiInterface")
56 ec.set(iface, 'name', name)
57 ec.set(iface, 'mode', mode)
58 ec.set(iface, 'hw_mode', typ)
59 ec.set(iface, 'essid', essid)
60 ec.set(iface, 'ip', ip)
61 ec.set(iface, 'version', "5")
64 def add_channel(ec, channel, xmppServer, xmppUser, xmppPort = "5222", xmppPassword = "1234"):
65 chan = ec.register_resource("OMFChannel")
66 ec.set(chan, 'channel', channel)
67 ec.set(chan, 'xmppServer', xmppServer)
68 ec.set(chan, 'xmppUser', xmppUser)
69 ec.set(chan, 'xmppPort', xmppPort)
70 ec.set(chan, 'xmppPassword', xmppPassword)
71 ec.set(chan, 'version', "5")
74 def add_app(ec, appid, command, env, xmppServer, xmppUser,
75 xmppPort = "5222", xmppPassword = "1234"):
76 app = ec.register_resource("OMFApplication")
77 ec.set(app, 'appid', appid)
78 ec.set(app, 'command', command)
79 ec.set(app, 'env', env)
80 ec.set(app, 'version', "5")
84 ### Define a CCND application ###
85 def add_ccnd(ec, peers, xmppServer, xmppUser, xmppPort = "5222", xmppPassword = "1234"):
86 env = 'PATH=$PATH:/root/ccnx-0.7.2/bin HOME=/root \
87 CCNR_DIRECTORY="/root" CCNR_STATUS_PORT="8080"'
89 # BASH command -> ' ccndstart ; ccndc add ccnx:/ udp host ; ccnr '
90 peers = map(lambda peer: "ccndc add ccnx:/ udp %s" % peer, peers)
91 #command += " ; ".join(peers) + " && "
94 app = add_app(ec, "#ccnd", command, env, xmppServer, xmppUser,
95 xmppPort = xmppPort, xmppPassword = xmppPassword)
98 ### Define a CCN SeqWriter application ###
99 def add_publish(ec, movie, xmppServer, xmppUser, xmppPort = "5222", xmppPassword = "1234"):
100 env = 'PATH=$PATH:/root/ccnx-0.7.2/bin HOME=/root CCNR_DIRECTORY="/root" CCNR_STATUS_PORT="8080"'
102 # BASH command -> 'ccnseqwriter -r ccnx:/VIDEO < movie'
103 command = "ccnseqwriter -r ccnx:/VIDEO"
104 command += " < " + movie
106 app = add_app(ec, "#ccn_write", command, env, xmppServer, xmppUser,
107 xmppPort = xmppPort, xmppPassword = xmppPassword)
110 ### Define a streaming application ###
111 def add_stream(ec, xmppServer, xmppUser, xmppPort = "5222", xmppPassword = "1234"):
112 env = 'PATH=$PATH:/root/ccnx-0.7.2/bin HOME=/root CCNR_DIRECTORY="/root" CCNR_STATUS_PORT="8080"'
113 command = " ddbus-uuidgen --ensure ; ( /root/ccnx-0.7.2/bin/ccncat ccnx:/VIDEO | /root/vlc-1.1.13/cvlc - ) "
114 #command = "ccncat ccnx:/VIDEO | /root/vlc-1.1.13/cvlc - "
115 app = add_app(ec, "#ccn_stream", command, env, xmppServer, xmppUser,
116 xmppPort = xmppPort, xmppPassword = xmppPassword)
119 ### Many options to easily addapt the script ####
121 usage = "usage: %prog -w <sender-node> -r <receiver-node> -s <slice> -m <movie>"
123 parser = OptionParser(usage=usage)
124 parser.add_option("-w", "--sender-host", dest="sender_host",
125 help="Hostname of the sender Node", type="str")
126 parser.add_option("-i", "--sender-ip", dest="sender_ip",
127 help="IP of the sender Node", type="str")
128 parser.add_option("-r", "--receiver-host", dest="receiver_host",
129 help="Hostname of the receiver node", type="str")
130 parser.add_option("-p", "--receiver-ip", dest="receiver_ip",
131 help="IP of the receiver node", type="str")
132 parser.add_option("-c", "--channel", dest="channel",
133 help="Channel of the communication", type="str")
134 parser.add_option("-s", "--xmpp-slice", dest="xmpp_slice",
135 help="Name of the slice XMPP", type="str")
136 parser.add_option("-x", "--xmpp-host", dest="xmpp_host",
137 help="Name of the host XMPP", type="str")
138 parser.add_option("-m", "--movie", dest="movie",
139 help="Stream movie", type="str")
141 (options, args) = parser.parse_args()
143 if not options.movie:
144 parser.error("movie is a required argument")
146 return (options.sender_host, options.sender_ip, options.receiver_host, options.receiver_ip, options.channel, options.xmpp_slice,
147 options.xmpp_host ,options.movie)
149 ### Script itself ###
150 if __name__ == '__main__':
151 (sender, sender_ip, receiver, receiver_ip, channel, xmpp_slice, xmpp_host, movie) = get_options()
153 env = 'PATH=$PATH:/root/ccnx-0.7.2/bin HOME=/root CCNR_DIRECTORY="/root" CCNR_STATUS_PORT="8080"'
156 ec = ExperimentController()
158 # Create the topology
159 node1 = add_node(ec,sender, xmpp_slice, xmpp_host)
160 iface1 = add_interface(ec, sender_ip, xmpp_slice, xmpp_host)
161 ec.register_connection(node1, iface1)
163 node2 = add_node(ec, receiver, xmpp_slice, xmpp_host)
164 iface2 = add_interface(ec, receiver_ip, xmpp_slice, xmpp_host)
165 ec.register_connection(node2, iface2)
167 chann = add_channel(ec, channel, xmpp_slice, xmpp_host)
168 ec.register_connection(iface1, chann)
169 ec.register_connection(iface2, chann)
171 # CCN setup for the sender
172 ccndstart1 = add_app(ec, "#ccndstart", "ccndstart &", env,xmpp_slice, xmpp_host)
173 ec.register_connection(ccndstart1, node1)
175 peers = [receiver_ip]
176 ccnd1 = add_ccnd(ec, peers, xmpp_slice, xmpp_host)
177 ec.register_connection(ccnd1, node1)
179 ccnr1 = add_app(ec, "#ccnr", "ccnr &", env, xmpp_slice, xmpp_host)
180 ec.register_connection(ccnr1, node1)
182 # Register content producer application (ccnseqwriter)
183 pub = add_publish(ec, movie, xmpp_slice, xmpp_host)
184 ec.register_connection(pub, node1)
186 # The movie can only be published after ccnd is running
187 ec.register_condition(ccnd1, ResourceAction.START, ccndstart1, ResourceState.STARTED, "1s")
188 ec.register_condition(ccnr1, ResourceAction.START, ccnd1, ResourceState.STARTED, "1s")
189 ec.register_condition(pub, ResourceAction.START, ccnr1, ResourceState.STARTED, "2s")
191 # CCN setup for the receiver
192 ccndstart2 = add_app(ec, "#ccndstart", "ccndstart &", env,xmpp_slice, xmpp_host)
193 ec.register_connection(ccndstart2, node2)
196 ccnd2 = add_ccnd(ec, peers, xmpp_slice, xmpp_host)
197 ec.register_connection(ccnd2, node2)
199 ccnr2 = add_app(ec, "#ccnr", "ccnr &", env,xmpp_slice, xmpp_host)
200 ec.register_connection(ccnr2, node2)
202 # Register consumer application (ccncat)
203 stream = add_stream(ec, xmpp_slice, xmpp_host)
204 ec.register_connection(stream, node2)
206 # The stream can only be retrieved after ccnd is running
207 ec.register_condition(ccnd2, ResourceAction.START, ccndstart2, ResourceState.STARTED, "1s")
208 ec.register_condition(ccnr2, ResourceAction.START, ccnd2, ResourceState.STARTED, "1s")
209 ec.register_condition(stream, ResourceAction.START, ccnr2, ResourceState.STARTED, "2s")
211 # And also, the stream can only be retrieved after it was published
212 ec.register_condition(stream, ResourceAction.START, pub, ResourceState.STARTED, "5s")
215 # Cleaning when the experiment stop
216 ccndstop1 = add_app(ec, "#ccndstop", "ccndstop", env, xmpp_slice, xmpp_host)
217 ec.register_connection(ccndstop1, node1)
218 ccndstop2 = add_app(ec, "#ccndstop", "ccndstop", env, xmpp_slice, xmpp_host)
219 ec.register_connection(ccndstop2, node2)
220 ccndstops = [ccndstop1,ccndstop2]
222 killall = add_app(ec, "#kill", "killall sh", "", xmpp_slice, xmpp_host)
223 ec.register_connection(killall, node2)
225 apps = [ccndstart1, ccnd1, ccnr1, pub, ccndstart2, ccnd2, ccnr2, stream]
227 ec.register_condition(apps, ResourceAction.STOP, stream, ResourceState.STARTED, "20s")
229 ec.register_condition(ccndstops, ResourceAction.START, apps, ResourceState.STOPPED, "1s")
230 ec.register_condition(killall, ResourceAction.START, ccndstops, ResourceState.STARTED)
231 ec.register_condition(ccndstops, ResourceAction.STOP, ccndstops, ResourceState.STARTED, "1s")
232 ec.register_condition(killall, ResourceAction.STOP, ccndstops, ResourceState.STOPPED)
234 # Deploy all ResourceManagers
237 # Wait until the applications are finished
238 ec.wait_finished(ccndstops)
240 # Shutdown the experiment controller