fb4f74d3b50621dec1e32b858a6004efc230547e
[nepi.git] / examples / linux / ccn_transfer_using_linuxapp.py
1 #!/usr/bin/env python
2
3 #
4 #    NEPI, a framework to manage network experiments
5 #    Copyright (C) 2013 INRIA
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU General Public License version 2 as
9 #    published by the Free Software Foundation;
10 #
11 #    This program is distributed in the hope that it will be useful,
12 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 #    GNU General Public License for more details.
15 #
16 #    You should have received a copy of the GNU General Public License
17 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 #
19 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
20
21 # NOTE: This experiment example uses the generic LinuxApplication
22 #       ResourceManager to do the CCN set up in the hosts.
23 #       Alternatively, CCN specific ResourceManagers can be used
24 #       (i.e. LinuxCCND, LinuxCCNR, etc...), and those require less 
25 #       manual configuration.
26 #
27 #
28
29 # CCN topology:
30 #
31 #                
32 #                 
33 #  content                ccncat
34 #  Linux host               Linux host
35 #  0 ------- Internet ------ 0
36 #           
37
38 # Example of how to run this experiment (replace with your information):
39 #
40 # $ cd <path-to-nepi>
41 # python examples/linux/ccn_advanced_transfer.py -a <hostname1> -b <hostname2> -u <username> -i <ssh-key>
42
43 from nepi.execution.ec import ExperimentController
44 from nepi.execution.resource import ResourceAction, ResourceState
45
46 from optparse import OptionParser
47 import os
48
49 usage = ("usage: %prog -a <hostname1> -b <hostname2> -u <username> -i <ssh-key>")
50
51 parser = OptionParser(usage = usage)
52 parser.add_option("-a", "--hostname1", dest="hostname1", 
53         help="Remote host 1", type="str")
54 parser.add_option("-b", "--hostname2", dest="hostname2", 
55         help="Remote host 2", type="str")
56 parser.add_option("-u", "--username", dest="username", 
57         help="Username to SSH to remote host", type="str")
58 parser.add_option("-i", "--ssh-key", dest="ssh_key", 
59         help="Path to private SSH key to be used for connection", 
60         type="str")
61 (options, args) = parser.parse_args()
62
63 hostname1 = options.hostname1
64 hostname2 = options.hostname2
65 username = options.username
66 ssh_key = options.ssh_key
67
68 def add_node(ec, host, user, ssh_key = None):
69     node = ec.register_resource("linux::Node")
70     ec.set(node, "hostname", host)
71     ec.set(node, "username", user)
72     ec.set(node, "identity", ssh_key)
73     ec.set(node, "cleanHome", True)
74     ec.set(node, "cleanProcesses", True)
75     return node
76
77 def add_ccnd(ec, peers):
78     # Dependencies for Fedora
79     depends = ( " autoconf openssl-devel  expat-devel libpcap-devel "
80                 " ecryptfs-utils-devel libxml2-devel automake gawk " 
81                 " gcc gcc-c++ git pcre-devel make ")
82
83     # UBUNTU / DEBIAN
84     # depends = ( " autoconf libssl-dev libexpat-dev libpcap-dev "
85     #            " libecryptfs0 libxml2-utils automake gawk gcc g++ "
86     #            " git-core pkg-config libpcre3-dev make ")
87
88     sources = "http://www.ccnx.org/releases/ccnx-0.8.2.tar.gz"
89
90     build = (
91         # Evaluate if ccnx binaries are already installed
92         " ( "
93             "  test -f ${BIN}/ccnx-0.8.2/bin/ccnd"
94         " ) || ( "
95         # If not, untar and build
96             " ( "
97             " mkdir -p ${SRC}/ccnx-0.8.2 && "
98                 " tar xf ${SRC}/ccnx-0.8.2.tar.gz --strip-components=1 -C ${SRC}/ccnx-0.8.2 "
99              " ) && "
100                 "cd ${SRC}/ccnx-0.8.2 && "
101                 # Just execute and silence warnings...
102                 "( ./configure && make ) "
103          " )") 
104
105     install = (
106         # Evaluate if ccnx binaries are already installed
107         " ( "
108             "  test -f ${BIN}/ccnx-0.8.2/bin/ccnd"
109         " ) || ( "
110             "  mkdir -p ${BIN}/ccnx-0.8.2/bin && "
111             "  cp -r ${SRC}/ccnx-0.8.2/bin ${BIN}/ccnx-0.8.2"
112         " )"
113     )
114
115     env = "PATH=$PATH:${BIN}/ccnx-0.8.2/bin"
116
117     # BASH command -> ' ccndstart ; ccndc add ccnx:/ udp  host ;  ccnr '
118     command = "ccndstart && "
119     peers = map(lambda peer: "ccndc add ccnx:/ udp  %s" % peer, peers)
120     command += " ; ".join(peers) + " && "
121     command += " ccnr & "
122
123     app = ec.register_resource("linux::Application")
124     ec.set(app, "depends", depends)
125     ec.set(app, "sources", sources)
126     ec.set(app, "install", install)
127     ec.set(app, "build", build)
128     ec.set(app, "env", env)
129     ec.set(app, "command", command)
130
131     return app
132
133 def add_publish(ec, movie, content_name):
134     env = "PATH=$PATH:${BIN}/ccnx-0.8.2/bin"
135     command = "ccnseqwriter -r %s" % content_name
136
137     app = ec.register_resource("linux::Application")
138     ec.set(app, "stdin", movie)
139     ec.set(app, "env", env)
140     ec.set(app, "command", command)
141
142     return app
143
144 def add_ccncat(ec, content_name):
145     env = "PATH=$PATH:${BIN}/ccnx-0.8.2/bin"
146     command = "ccncat %s" % content_name
147
148     app = ec.register_resource("linux::Application")
149     ec.set(app, "env", env)
150     ec.set(app, "command", command)
151
152     return app
153
154 ## Create the experiment controller
155 ec = ExperimentController(exp_id = "ccn_advanced_transfer")
156
157 # Register first PlanetLab host
158 node1 = add_node(ec, hostname1, username, ssh_key)
159
160 # Register CCN setup for host
161 peers = [hostname2]
162 ccnd1 = add_ccnd(ec, peers)
163 ec.register_connection(ccnd1, node1)
164
165 # Register content producer application (ccnseqwriter)
166 ## Push the file into the repository
167 local_path_to_content = os.path.join(
168         os.path.dirname(os.path.realpath(__file__)),
169             "..", "big_buck_bunny_240p_mpeg4_lq.ts")
170
171 content_name = "ccnx:/test/FILE"
172
173 pub = add_publish(ec, local_path_to_content, content_name)
174 ec.register_connection(pub, node1)
175
176 # The movie can only be published after ccnd is running
177 ec.register_condition(pub, ResourceAction.START, 
178         ccnd1, ResourceState.STARTED)
179
180 # Register Linux host
181 node2 = add_node(ec, hostname2, username, ssh_key)
182
183 # Register CCN setup for Linux host
184 peers = [hostname1]
185 ccnd2 = add_ccnd(ec, peers)
186 ec.register_connection(ccnd2, node2)
187  
188 # Register consumer application (ccncat)
189 ccncat = add_ccncat(ec, content_name)
190 ec.register_connection(ccncat, node2)
191
192 # The file can only be retrieved after ccnd is running
193 ec.register_condition(ccncat, ResourceAction.START, 
194         ccnd2, ResourceState.STARTED)
195
196 # And also, the file can only be retrieved after it was published
197 ec.register_condition(ccncat, ResourceAction.START, 
198         pub, ResourceState.STARTED)
199
200 # Deploy all ResourceManagers
201 ec.deploy()
202
203 # Wait until the applications are finished
204 apps = [ccncat]
205 ec.wait_finished(apps)
206
207 stdout = ec.trace(ccncat, "stdout")
208 f = open("video.ts", "w")
209 f.write(stdout)
210 f.close()
211
212 # Shutdown the experiment controller
213 ec.shutdown()
214
215 print "Transfered FILE stored localy at video.ts"
216