use print() - import print_function - should be fine for both py2 and py3
[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 __future__ import print_function
44
45 from nepi.execution.ec import ExperimentController
46 from nepi.execution.resource import ResourceAction, ResourceState
47
48 from optparse import OptionParser
49 import os
50
51 usage = ("usage: %prog -a <hostname1> -b <hostname2> -u <username> -i <ssh-key>")
52
53 parser = OptionParser(usage = usage)
54 parser.add_option("-a", "--hostname1", dest="hostname1", 
55         help="Remote host 1", type="str")
56 parser.add_option("-b", "--hostname2", dest="hostname2", 
57         help="Remote host 2", type="str")
58 parser.add_option("-u", "--username", dest="username", 
59         help="Username to SSH to remote host", type="str")
60 parser.add_option("-i", "--ssh-key", dest="ssh_key", 
61         help="Path to private SSH key to be used for connection", 
62         type="str")
63 (options, args) = parser.parse_args()
64
65 hostname1 = options.hostname1
66 hostname2 = options.hostname2
67 username = options.username
68 ssh_key = options.ssh_key
69
70 def add_node(ec, host, user, ssh_key = None):
71     node = ec.register_resource("linux::Node")
72     ec.set(node, "hostname", host)
73     ec.set(node, "username", user)
74     ec.set(node, "identity", ssh_key)
75     ec.set(node, "cleanHome", True)
76     ec.set(node, "cleanProcesses", True)
77     return node
78
79 def add_ccnd(ec, peers):
80     # Dependencies for Fedora
81     depends = ( " autoconf openssl-devel  expat-devel libpcap-devel "
82                 " ecryptfs-utils-devel libxml2-devel automake gawk " 
83                 " gcc gcc-c++ git pcre-devel make ")
84
85     # UBUNTU / DEBIAN
86     # depends = ( " autoconf libssl-dev libexpat-dev libpcap-dev "
87     #            " libecryptfs0 libxml2-utils automake gawk gcc g++ "
88     #            " git-core pkg-config libpcre3-dev make ")
89
90     sources = "http://www.ccnx.org/releases/ccnx-0.8.2.tar.gz"
91
92     build = (
93         # Evaluate if ccnx binaries are already installed
94         " ( "
95             "  test -f ${BIN}/ccnx-0.8.2/bin/ccnd"
96         " ) || ( "
97         # If not, untar and build
98             " ( "
99             " mkdir -p ${SRC}/ccnx-0.8.2 && "
100                 " tar xf ${SRC}/ccnx-0.8.2.tar.gz --strip-components=1 -C ${SRC}/ccnx-0.8.2 "
101              " ) && "
102                 "cd ${SRC}/ccnx-0.8.2 && "
103                 # Just execute and silence warnings...
104                 "( ./configure && make ) "
105          " )") 
106
107     install = (
108         # Evaluate if ccnx binaries are already installed
109         " ( "
110             "  test -f ${BIN}/ccnx-0.8.2/bin/ccnd"
111         " ) || ( "
112             "  mkdir -p ${BIN}/ccnx-0.8.2/bin && "
113             "  cp -r ${SRC}/ccnx-0.8.2/bin ${BIN}/ccnx-0.8.2"
114         " )"
115     )
116
117     env = "PATH=$PATH:${BIN}/ccnx-0.8.2/bin"
118
119     # BASH command -> ' ccndstart ; ccndc add ccnx:/ udp  host ;  ccnr '
120     command = "ccndstart && "
121     peers = map(lambda peer: "ccndc add ccnx:/ udp  %s" % peer, peers)
122     command += " ; ".join(peers) + " && "
123     command += " ccnr & "
124
125     app = ec.register_resource("linux::Application")
126     ec.set(app, "depends", depends)
127     ec.set(app, "sources", sources)
128     ec.set(app, "install", install)
129     ec.set(app, "build", build)
130     ec.set(app, "env", env)
131     ec.set(app, "command", command)
132
133     return app
134
135 def add_publish(ec, movie, content_name):
136     env = "PATH=$PATH:${BIN}/ccnx-0.8.2/bin"
137     command = "ccnseqwriter -r %s" % content_name
138
139     app = ec.register_resource("linux::Application")
140     ec.set(app, "stdin", movie)
141     ec.set(app, "env", env)
142     ec.set(app, "command", command)
143
144     return app
145
146 def add_ccncat(ec, content_name):
147     env = "PATH=$PATH:${BIN}/ccnx-0.8.2/bin"
148     command = "ccncat %s" % content_name
149
150     app = ec.register_resource("linux::Application")
151     ec.set(app, "env", env)
152     ec.set(app, "command", command)
153
154     return app
155
156 ## Create the experiment controller
157 ec = ExperimentController(exp_id = "ccn_advanced_transfer")
158
159 # Register first PlanetLab host
160 node1 = add_node(ec, hostname1, username, ssh_key)
161
162 # Register CCN setup for host
163 peers = [hostname2]
164 ccnd1 = add_ccnd(ec, peers)
165 ec.register_connection(ccnd1, node1)
166
167 # Register content producer application (ccnseqwriter)
168 ## Push the file into the repository
169 local_path_to_content = os.path.join(
170         os.path.dirname(os.path.realpath(__file__)),
171             "..", "big_buck_bunny_240p_mpeg4_lq.ts")
172
173 content_name = "ccnx:/test/FILE"
174
175 pub = add_publish(ec, local_path_to_content, content_name)
176 ec.register_connection(pub, node1)
177
178 # The movie can only be published after ccnd is running
179 ec.register_condition(pub, ResourceAction.START, 
180         ccnd1, ResourceState.STARTED)
181
182 # Register Linux host
183 node2 = add_node(ec, hostname2, username, ssh_key)
184
185 # Register CCN setup for Linux host
186 peers = [hostname1]
187 ccnd2 = add_ccnd(ec, peers)
188 ec.register_connection(ccnd2, node2)
189  
190 # Register consumer application (ccncat)
191 ccncat = add_ccncat(ec, content_name)
192 ec.register_connection(ccncat, node2)
193
194 # The file can only be retrieved after ccnd is running
195 ec.register_condition(ccncat, ResourceAction.START, 
196         ccnd2, ResourceState.STARTED)
197
198 # And also, the file can only be retrieved after it was published
199 ec.register_condition(ccncat, ResourceAction.START, 
200         pub, ResourceState.STARTED)
201
202 # Deploy all ResourceManagers
203 ec.deploy()
204
205 # Wait until the applications are finished
206 apps = [ccncat]
207 ec.wait_finished(apps)
208
209 stdout = ec.trace(ccncat, "stdout")
210 f = open("video.ts", "w")
211 f.write(stdout)
212 f.close()
213
214 # Shutdown the experiment controller
215 ec.shutdown()
216
217 print("Transfered FILE stored localy at video.ts")
218