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