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