last modifications for OMF6 before test
[nepi.git] / examples / omf / nepi_omf_ccncat_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      content              ccncat
28      b1                   b2
29      0 ------------------ 0
30    
31       - Experiment:
32         * t0 : b2 retrives video published in b1
33
34 """
35
36 #!/usr/bin/env python
37 from nepi.execution.resource import ResourceFactory, ResourceAction, ResourceState
38 from nepi.execution.ec import ExperimentController
39
40 from optparse import OptionParser, SUPPRESS_HELP
41
42 ###  Define OMF Method to simplify definition of resources ###
43 def add_node(ec, hostname, xmppSlice, xmppHost, xmppPort = "5222", xmppPassword = "1234"):
44     node = ec.register_resource("OMFNode")
45     ec.set(node, 'hostname', hostname)
46     ec.set(node, 'xmppSlice', xmppSlice)
47     ec.set(node, 'xmppHost', xmppHost)
48     ec.set(node, 'xmppPort', xmppPort)
49     ec.set(node, 'xmppPassword', xmppPassword)
50     return node
51
52 def add_interface(ec, ip, xmppSlice, xmppHost, essid = "ccn", alias = "w0", mode = "adhoc",
53                  typ = "g", xmppPort = "5222", xmppPassword = "1234"):
54     iface = ec.register_resource("OMFWifiInterface")
55     ec.set(iface, 'alias', alias)
56     ec.set(iface, 'mode', mode)
57     ec.set(iface, 'type', typ)
58     ec.set(iface, 'essid', essid)
59     ec.set(iface, 'ip', ip)
60     return iface
61
62 def add_channel(ec, channel, xmppSlice, xmppHost, xmppPort = "5222", xmppPassword = "1234"):
63     chan = ec.register_resource("OMFChannel")
64     ec.set(chan, 'channel', channel)
65     ec.set(chan, 'xmppSlice', xmppSlice)
66     ec.set(chan, 'xmppHost', xmppHost)
67     ec.set(chan, 'xmppPort', xmppPort)
68     ec.set(chan, 'xmppPassword', xmppPassword)
69     return chan
70
71 def add_app(ec, appid, command, args, env, xmppSlice, xmppHost, 
72                 xmppPort = "5222", xmppPassword = "1234"):
73     app = ec.register_resource("OMFApplication")
74     ec.set(app, 'appid', appid)
75     ec.set(app, 'path', command)
76     ec.set(app, 'args', args)
77     ec.set(app, 'env', env)
78     return app
79
80
81 ###  Define a CCND application  ###
82 def add_ccnd(ec, peers, xmppSlice, xmppHost, xmppPort = "5222", xmppPassword = "1234"):
83     env = 'PATH=$PATH:/root/ccnx-0.7.2/bin HOME=/root \
84 CCNR_DIRECTORY="/root" CCNR_STATUS_PORT="8080"'
85
86     # BASH command -> ' ccndstart ; ccndc add ccnx:/ udp host ; ccnr '
87     peers = map(lambda peer: "ccndc add ccnx:/ udp  %s" % peer, peers)
88     #command += " ; ".join(peers) + " && "
89     command = peers[0]
90
91     app = add_app(ec, "#ccnd", command, "", env, xmppSlice, xmppHost,
92                      xmppPort = xmppPort, xmppPassword = xmppPassword)
93     return app
94
95 ###  Define a CCN SeqWriter application ###
96 def add_publish(ec, movie, xmppSlice, xmppHost, xmppPort = "5222", xmppPassword = "1234"):
97     env = 'PATH=$PATH:/root/ccnx-0.7.2/bin HOME=/root CCNR_DIRECTORY="/root" CCNR_STATUS_PORT="8080"'
98
99     # BASH command -> 'ccnseqwriter -r ccnx:/VIDEO < movie'
100     command = "ccnseqwriter -r ccnx:/VIDEO"
101     command += " < " + movie
102
103     app = add_app(ec, "#ccn_write", command, "", env, xmppSlice, xmppHost,
104                   xmppPort = xmppPort, xmppPassword = xmppPassword)
105     return app
106
107 ###  Define a streaming application ###
108 def add_stream(ec, xmppSlice, xmppHost, xmppPort = "5222", xmppPassword = "1234"):
109     env = 'PATH=$PATH:/root/ccnx-0.7.2/bin HOME=/root CCNR_DIRECTORY="/root" CCNR_STATUS_PORT="8080"'
110     command = " ddbus-uuidgen --ensure ; ( /root/ccnx-0.7.2/bin/ccncat ccnx:/VIDEO | /root/vlc-1.1.13/cvlc - )  "
111     #command = "ccncat ccnx:/VIDEO | /root/vlc-1.1.13/cvlc - "
112     app = add_app(ec, "#ccn_stream", command, "", env, xmppSlice, xmppHost,
113                   xmppPort = xmppPort, xmppPassword = xmppPassword)
114     return app
115
116 ###  Many options to easily addapt the script ####
117 def get_options():
118     usage = "usage: %prog -w <sender-node> -r <receiver-node> -s <slice> -m <movie>"
119
120     parser = OptionParser(usage=usage)
121     parser.add_option("-w", "--sender-host", dest="sender_host", 
122             help="Hostname of the sender Node", type="str")
123     parser.add_option("-i", "--sender-ip", dest="sender_ip", 
124             help="IP of the sender Node", type="str")
125     parser.add_option("-r", "--receiver-host", dest="receiver_host", 
126             help="Hostname of the receiver node", type="str")
127     parser.add_option("-p", "--receiver-ip", dest="receiver_ip", 
128             help="IP of the receiver node", type="str")
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
138     (options, args) = parser.parse_args()
139
140     if not options.movie:
141         parser.error("movie is a required argument")
142
143     return (options.sender_host, options.sender_ip, options.receiver_host, options.receiver_ip, options.channel, options.xmpp_slice, 
144             options.xmpp_host ,options.movie)
145
146 ### Script itself ###
147 if __name__ == '__main__':
148     (sender, sender_ip, receiver, receiver_ip, channel, xmpp_slice, xmpp_host, movie) = get_options()
149
150     env = 'PATH=$PATH:/root/ccnx-0.7.2/bin HOME=/root CCNR_DIRECTORY="/root" CCNR_STATUS_PORT="8080"'
151
152 # Create the EC
153     ec = ExperimentController()
154
155 # Create the topology
156     node1 = add_node(ec,sender, xmpp_slice, xmpp_host)
157     iface1 = add_interface(ec, sender_ip, xmpp_slice, xmpp_host)
158     ec.register_connection(node1, iface1)
159
160     node2 = add_node(ec, receiver, xmpp_slice, xmpp_host)
161     iface2 = add_interface(ec, receiver_ip, xmpp_slice, xmpp_host)
162     ec.register_connection(node2, iface2)
163
164     chann = add_channel(ec, channel, xmpp_slice, xmpp_host)
165     ec.register_connection(iface1, chann)
166     ec.register_connection(iface2, chann)
167
168 # CCN setup for the sender
169     ccndstart1 = add_app(ec, "#ccndstart", "ccndstart &", "", env,xmpp_slice, xmpp_host)
170     ec.register_connection(ccndstart1, node1)
171
172     peers = [receiver_ip]
173     ccnd1 = add_ccnd(ec, peers, xmpp_slice, xmpp_host)
174     ec.register_connection(ccnd1, node1)
175
176     ccnr1 = add_app(ec, "#ccnr", "ccnr &", "", env, xmpp_slice, xmpp_host)
177     ec.register_connection(ccnr1, node1)
178
179     # Register content producer application (ccnseqwriter)
180     pub = add_publish(ec, movie, xmpp_slice, xmpp_host)
181     ec.register_connection(pub, node1)
182
183     # The movie can only be published after ccnd is running
184     ec.register_condition(ccnd1, ResourceAction.START, ccndstart1, ResourceState.STARTED, "1s")
185     ec.register_condition(ccnr1, ResourceAction.START, ccnd1, ResourceState.STARTED, "1s")
186     ec.register_condition(pub, ResourceAction.START, ccnr1, ResourceState.STARTED, "2s")
187    
188 # CCN setup for the receiver
189     ccndstart2 = add_app(ec, "#ccndstart", "ccndstart &", "", env,xmpp_slice, xmpp_host)
190     ec.register_connection(ccndstart2, node2)
191
192     peers = [sender_ip]
193     ccnd2 = add_ccnd(ec, peers, xmpp_slice, xmpp_host)
194     ec.register_connection(ccnd2, node2)
195
196     ccnr2 = add_app(ec, "#ccnr", "ccnr &", "", env,xmpp_slice, xmpp_host)
197     ec.register_connection(ccnr2, node2)
198      
199     # Register consumer application (ccncat)
200     stream = add_stream(ec, xmpp_slice, xmpp_host)
201     ec.register_connection(stream, node2)
202
203     # The stream can only be retrieved after ccnd is running
204     ec.register_condition(ccnd2, ResourceAction.START, ccndstart2, ResourceState.STARTED, "1s")
205     ec.register_condition(ccnr2, ResourceAction.START, ccnd2, ResourceState.STARTED, "1s")
206     ec.register_condition(stream, ResourceAction.START, ccnr2, ResourceState.STARTED, "2s")
207
208 # And also, the stream can only be retrieved after it was published
209     ec.register_condition(stream, ResourceAction.START, pub, ResourceState.STARTED, "5s")
210
211
212 # Cleaning when the experiment stop
213     ccndstop1 = add_app(ec, "#ccndstop", "ccndstop", "", env, xmpp_slice, xmpp_host)
214     ec.register_connection(ccndstop1, node1)
215     ccndstop2 = add_app(ec, "#ccndstop", "ccndstop", "", env, xmpp_slice, xmpp_host)
216     ec.register_connection(ccndstop2, node2)
217     ccndstops = [ccndstop1,ccndstop2]
218
219     killall = add_app(ec, "#kill", "killall sh", "", "", xmpp_slice, xmpp_host)
220     ec.register_connection(killall, node2)
221
222     apps = [ccndstart1, ccnd1, ccnr1, pub, ccndstart2, ccnd2, ccnr2, stream]
223
224     ec.register_condition(apps, ResourceAction.STOP, stream, ResourceState.STARTED, "20s")
225
226     ec.register_condition(ccndstops, ResourceAction.START, apps, ResourceState.STOPPED, "1s")
227     ec.register_condition(killall, ResourceAction.START, ccndstops, ResourceState.STARTED)
228     ec.register_condition(ccndstops, ResourceAction.STOP, ccndstops, ResourceState.STARTED, "1s")
229     ec.register_condition(killall, ResourceAction.STOP, ccndstops, ResourceState.STOPPED)
230
231 # Deploy all ResourceManagers
232     ec.deploy()
233
234 # Wait until the applications are finished
235     ec.wait_finished(ccndstops)
236
237 # Shutdown the experiment controller
238     ec.shutdown()
239