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