last modifications for OMF6 before test
[nepi.git] / examples / omf / nepi_omf_ccnring_nitos.py
1 """
2     NEPI, a framework to manage network experiments
3     Copyright (C) 2013 INRIA
4
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.
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: Alina Quereilhac <alina.quereilhac@inria.fr>
19             Julien Tribino <julien.tribino@inria.fr>
20
21     Example :
22       - Testbed : Nitos
23       - Explanation :
24
25       CCN topology:
26     
27                    h2
28                    0 
29      content   l1 / \ l2         ccncat
30      b1          /l5 \           b2
31      0 ----- h1 0 --- 0 h3 ------ 0
32                  \   / 
33                l4 \ / l3
34                    0
35                    h4
36    
37       - Experiment:
38         * t0 : b2 retrives video published in b1
39         * t1 : l5 goes down after 15 sec
40
41 """
42
43 #!/usr/bin/env python
44 from nepi.execution.resource import ResourceFactory, ResourceAction, ResourceState
45 from nepi.execution.ec import ExperimentController
46
47 from optparse import OptionParser, SUPPRESS_HELP
48
49 ###  Define OMF Method to simplify definition of resources ###
50 def add_node(ec, hostname, xmppSlice, xmppHost, xmppPort = "5222", xmppPassword = "1234"):
51     node = ec.register_resource("OMFNode")
52     ec.set(node, 'hostname', hostname)
53     ec.set(node, 'xmppSlice', xmppSlice)
54     ec.set(node, 'xmppHost', xmppHost)
55     ec.set(node, 'xmppPort', xmppPort)
56     ec.set(node, 'xmppPassword', xmppPassword)
57     return node
58
59 def add_interface(ec, ip, xmppSlice, xmppHost, essid = "ccn", alias = "w0", mode = "adhoc",
60                  typ = "g", xmppPort = "5222", xmppPassword = "1234"):
61     iface = ec.register_resource("OMFWifiInterface")
62     ec.set(iface, 'alias', alias)
63     ec.set(iface, 'mode', mode)
64     ec.set(iface, 'type', typ)
65     ec.set(iface, 'essid', essid)
66     ec.set(iface, 'ip', ip)
67     return iface
68
69 def add_channel(ec, channel, xmppSlice, xmppHost, xmppPort = "5222", xmppPassword = "1234"):
70     chan = ec.register_resource("OMFChannel")
71     ec.set(chan, 'channel', channel)
72     ec.set(chan, 'xmppSlice', xmppSlice)
73     ec.set(chan, 'xmppHost', xmppHost)
74     ec.set(chan, 'xmppPort', xmppPort)
75     ec.set(chan, 'xmppPassword', xmppPassword)
76     return chan
77
78 def add_app(ec, host,  appid, command, args, env, xmppSlice, xmppHost, 
79                 xmppPort = "5222", xmppPassword = "1234"):
80     app = ec.register_resource("OMFApplication")
81     ec.set(app, 'appid', appid)
82     ec.set(app, 'path', command)
83     ec.set(app, 'args', args)
84     ec.set(app, 'env', env)
85     ec.register_connection(app, host)
86     return app
87
88
89 ###  Define a CCND application  ###
90 def add_ccnd(ec, host, peers, xmppSlice, xmppHost, xmppPort = "5222", xmppPassword = "1234"):
91     env = 'PATH=$PATH:/root/ccnx-0.7.2/bin HOME=/root \
92 CCNR_DIRECTORY="/root" CCNR_STATUS_PORT="8080"'
93
94     # BASH command -> ' ccndstart ; ccndc add ccnx:/ udp host ; ccnr '
95     command = "ccndc add ccnx:/ udp " + peers
96     app = add_app(ec, host, "#ccnd", command, "", env, xmppSlice, xmppHost,
97                     xmppPort = xmppPort, xmppPassword = xmppPassword)
98     return app
99
100 ###  Define a CCN SeqWriter application ###
101 def add_publish(ec, host,  movie, xmppSlice, xmppHost, xmppPort = "5222", xmppPassword = "1234"):
102     env = 'PATH=$PATH:/root/ccnx-0.7.2/bin HOME=/root CCNR_DIRECTORY="/root" CCNR_STATUS_PORT="8080"'
103
104     # BASH command -> 'ccnseqwriter -r ccnx:/VIDEO < movie'
105     command = "ccnseqwriter -r ccnx:/VIDEO"
106     command += " < " + movie
107
108     app = add_app(ec, host, "#ccn_write", command, "", env, xmppSlice, xmppHost,
109                   xmppPort = xmppPort, xmppPassword = xmppPassword)
110     return app
111
112 ###  Define a streaming application ###
113 def add_stream(ec, host, xmppSlice, xmppHost, xmppPort = "5222", xmppPassword = "1234"):
114     env = 'PATH=$PATH:/root/ccnx-0.7.2/bin HOME=/root CCNR_DIRECTORY="/root" CCNR_STATUS_PORT="8080"'
115     command = " ddbus-uuidgen --ensure ; ( /root/ccnx-0.7.2/bin/ccncat ccnx:/VIDEO | /root/vlc-1.1.13/cvlc - )  "
116     app = add_app(ec, host, "#ccn_stream", command, "", env, xmppSlice, xmppHost,
117                   xmppPort = xmppPort, xmppPassword = xmppPassword)
118     return app
119
120 ###  Many options to easily addapt the script ####
121 def get_options():
122     usage = "usage: %prog -c <channel> -s <xmpp_slice> -x <xmpp_host> -m <movie>"
123
124     parser = OptionParser(usage=usage)
125     parser.add_option("-c", "--channel", dest="channel", 
126             help="Channel of the communication", type="str")
127     parser.add_option("-s", "--xmpp-slice", dest="xmpp_slice", 
128             help="Name of the slice XMPP", type="str")
129     parser.add_option("-x", "--xmpp-host", dest="xmpp_host",
130             help="Name of the host XMPP", type="str")
131     parser.add_option("-m", "--movie", dest="movie", 
132             help="Stream movie", type="str")
133     #parser.add_option("-e", "--exp-id", dest="exp_id", 
134     #        help="Label to identify experiment", type="str")
135
136     (options, args) = parser.parse_args()
137
138     if not options.movie:
139         parser.error("movie is a required argument")
140
141     return (options.channel, options.xmpp_slice, 
142             options.xmpp_host ,options.movie)
143
144 ### Script itself ###
145 if __name__ == '__main__':
146     (channel, xmpp_slice, xmpp_host, movie) = get_options()
147
148     env = 'PATH=$PATH:/root/ccnx-0.7.2/bin HOME=/root CCNR_DIRECTORY="/root" CCNR_STATUS_PORT="8080"'
149
150 # Create the EC
151     ec = ExperimentController()
152
153 # Create the topology
154     host1 = "omf.nitos.node022"
155     host2 = "omf.nitos.node028"
156     host3 = "omf.nitos.node024"
157     host4 = "omf.nitos.node025"
158     host5 = "omf.nitos.node026"  # b1
159     host6 = "omf.nitos.node027"  # b2
160
161     ip1 = "192.168.0.22"
162     ip2 = "192.168.0.28"
163     ip3 = "192.168.0.24"
164     ip4 = "192.168.0.25"
165     ip5 = "192.168.0.26"
166     ip6 = "192.168.0.27"
167
168     all_hosts = [host1, host2, host3, host4, host5, host6]
169     all_ip = [ip1, ip2, ip3, ip4, ip5, ip6]
170
171     ring_hosts = [host1, host2, host3, host4]
172     nodes = dict()
173
174     chann = add_channel(ec, channel, xmpp_slice, xmpp_host)
175     for i in xrange(len(all_hosts)):
176         node = add_node(ec,all_hosts[i], xmpp_slice, xmpp_host)
177         iface = add_interface(ec, all_ip[i], xmpp_slice, xmpp_host)
178         ec.register_connection(node, iface)
179         ec.register_connection(iface, chann)
180         nodes[all_hosts[i]] = node
181
182 # CCN setup for the node
183     ccnds = dict()
184     ccnrs = dict()
185     for i in xrange(len(all_hosts)):
186         ccndstart = add_app(ec, nodes[all_hosts[i]],  "#ccndstart", "ccndstart &", 
187                               "", env, xmpp_slice, xmpp_host)
188         ccnr = add_app(ec, nodes[all_hosts[i]],  "#ccnr", "ccnr &", 
189                             "", env, xmpp_slice, xmpp_host)
190         ccnds[all_hosts[i]] = ccndstart
191         ccnrs[all_hosts[i]] = ccnr
192         ec.register_condition(ccnr, ResourceAction.START, ccndstart, ResourceState.STARTED, "1s")
193
194 # CCNDC setup 
195     # l1 : h1 - h2 , h2 - h1
196     l1u = add_ccnd(ec, nodes[host1], ip2, xmpp_slice, xmpp_host)
197     l1d = add_ccnd(ec, nodes[host2], ip1, xmpp_slice, xmpp_host)
198
199     # l2 : h2 - h3 , h3 - h2
200     l2u = add_ccnd(ec, nodes[host2], ip3, xmpp_slice, xmpp_host)
201     l2d = add_ccnd(ec, nodes[host3], ip2, xmpp_slice, xmpp_host)
202
203     # l3 : h3 - h4 , h4 - h3
204     l3u = add_ccnd(ec, nodes[host3], ip4, xmpp_slice, xmpp_host)
205     l3d = add_ccnd(ec, nodes[host4], ip3, xmpp_slice, xmpp_host)
206
207     # l4 : h4 - h1 , h1 - h4
208     l4u = add_ccnd(ec, nodes[host4], ip1, xmpp_slice, xmpp_host)
209     l4d = add_ccnd(ec, nodes[host1], ip4, xmpp_slice, xmpp_host)
210
211     # l5 : h1 - h3 , h3 - h1
212     l5u = add_ccnd(ec, nodes[host1], ip3, xmpp_slice, xmpp_host)
213     l5d = add_ccnd(ec, nodes[host3], ip1, xmpp_slice, xmpp_host)
214  
215     # connect border nodes
216     b1u = add_ccnd(ec, nodes[host5], ip1, xmpp_slice, xmpp_host)
217     b1d = add_ccnd(ec, nodes[host1], ip5, xmpp_slice, xmpp_host)
218
219     b2u = add_ccnd(ec, nodes[host6], ip3, xmpp_slice, xmpp_host)
220     b2d = add_ccnd(ec, nodes[host3], ip6, xmpp_slice, xmpp_host)
221
222     link = [l1u, l1d, l2u, l2d, l3u, l3d, l4u, l4d, l5u, l5d, b1u, b1d, b2u, b2d]
223
224 # List of condition
225     for i in xrange(len(all_hosts)):
226          ec.register_condition(ccnrs[all_hosts[i]], ResourceAction.START, ccnds[all_hosts[i]], ResourceState.STARTED, "1s")
227          ec.register_condition(link, ResourceAction.START, ccnrs[all_hosts[i]], ResourceState.STARTED, "1s")
228
229 # Streaming Server
230     pub = add_publish(ec, nodes[host5], movie, xmpp_slice, xmpp_host)
231
232 # Streaming client
233     stream = add_stream(ec, nodes[host6], xmpp_slice, xmpp_host)
234
235 # Streaming conditions
236     ec.register_condition(pub, ResourceAction.START, link, ResourceState.STARTED, "2s")
237     ec.register_condition(stream, ResourceAction.START, link, ResourceState.STARTED, "2s")
238     ec.register_condition(stream, ResourceAction.START, pub, ResourceState.STARTED, "2s")
239
240 # break the lin
241     ccndcstop1 = add_app(ec,nodes[host1], "#ccndc", "ccndc del ccnx:/ udp " + ip3, "", env, xmpp_slice, xmpp_host)
242     ccndcstop2 = add_app(ec,nodes[host3], "#ccndc", "ccndc del ccnx:/ udp " + ip1, "", env, xmpp_slice, xmpp_host)
243
244
245 # Change the behaviour
246     ec.register_condition(l5u, ResourceAction.STOP, stream, ResourceState.STARTED, "10s")
247     ec.register_condition(l5d, ResourceAction.STOP, stream, ResourceState.STARTED, "10s")
248
249     ec.register_condition(ccndcstop1, ResourceAction.START, stream, ResourceState.STARTED, "10s")
250     ec.register_condition(ccndcstop2, ResourceAction.START, stream, ResourceState.STARTED, "10s")
251
252 # Cleaning when the experiment stop
253     ccndstops = []
254     for i in xrange(len(all_hosts)):
255         ccndstop = add_app(ec, nodes[all_hosts[i]], "#ccndstop", "ccndstop", "", env, xmpp_slice, xmpp_host)
256         ccndstops.append(ccndstop)
257
258     killall = add_app(ec, nodes[host6], "#kill", "killall sh", "", "", xmpp_slice, xmpp_host)
259
260 # Condition to stop and clean the experiment
261     apps = []
262     for i in xrange(len(all_hosts)):
263         apps.append(ccnds[all_hosts[i]])
264         apps.append(ccnrs[all_hosts[i]])
265     apps += link
266     apps.append(pub)
267     apps.append(stream)
268
269     ec.register_condition(apps, ResourceAction.STOP, stream, ResourceState.STARTED, "30s")
270
271     ec.register_condition(ccndstops + [killall], ResourceAction.START, apps, ResourceState.STOPPED, "1s")
272     ec.register_condition(ccndstops + [killall], ResourceAction.STOP, ccndstops, ResourceState.STARTED, "1s")
273
274 # Deploy all ResourceManagers
275     ec.deploy()
276
277 # Wait until the applications are finished
278     ec.wait_finished(ccndstops)
279
280 # Shutdown the experiment controller
281     ec.shutdown()
282
283