4 # NEPI, a framework to manage network experiments
5 # Copyright (C) 2013 INRIA
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.
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.
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/>.
20 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
27 # content l1 / \ l2 ccncat
29 # 0 ----- h1 0 --- 0 h3 ------ 0
35 # - t0 : b2 retrives video published in b1
41 from nepi.execution.ec import ExperimentController, ECState
42 from nepi.execution.resource import ResourceState, ResourceAction, \
44 from nepi.execution.trace import TraceAttr
47 from optparse import OptionParser, SUPPRESS_HELP
53 def add_node(ec, host, user, ssh_key = None):
54 node = ec.register_resource("LinuxNode")
55 ec.set(node, "hostname", host)
56 ec.set(node, "username", user)
57 ec.set(node, "identity", ssh_key)
58 ec.set(node, "cleanHome", True)
59 ec.set(node, "cleanProcesses", True)
62 def add_ccnd(ec, node):
63 ccnd = ec.register_resource("LinuxCCND")
64 ec.set(ccnd, "debug", 7)
65 ec.register_connection(ccnd, node)
68 def add_ccnr(ec, ccnd):
69 ccnr = ec.register_resource("LinuxCCNR")
70 ec.register_connection(ccnr, ccnd)
73 def add_fib_entry(ec, ccnd, peer_host):
74 entry = ec.register_resource("LinuxFIBEntry")
75 ec.set(entry, "host", peer_host)
76 ec.register_connection(entry, ccnd)
79 def add_content(ec, ccnr, content_name, content):
80 co = ec.register_resource("LinuxCCNContent")
81 ec.set(co, "contentName", content_name)
82 ec.set(co, "content", content)
83 ec.register_connection(co, ccnr)
86 def add_stream(ec, ccnd, content_name):
87 # ccnx v7.2 issue 101007
88 command = "ccnpeek %(content_name)s; ccncat %(content_name)s" % {
89 "content_name" : content_name}
91 app = ec.register_resource("LinuxCCNApplication")
92 ec.set(app, "command", command)
93 ec.register_connection(app, ccnd)
98 pl_slice = os.environ.get("PL_SLICE")
100 # We use a specific SSH private key for PL if the PL_SSHKEY is specified or the
101 # id_rsa_planetlab exists
102 default_key = "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])
103 default_key = default_key if os.path.exists(default_key) else None
104 pl_ssh_key = os.environ.get("PL_SSHKEY", default_key)
106 usage = "usage: %prog -s <pl-user> -m <movie> -c -e <exp-id> -i <ssh_key>"
108 parser = OptionParser(usage=usage)
109 parser.add_option("-s", "--pl-user", dest="pl_user",
110 help="PlanetLab slicename", default = pl_slice, type="str")
111 parser.add_option("-m", "--movie", dest="movie",
112 help="Stream movie", type="str")
113 parser.add_option("-e", "--exp-id", dest="exp_id",
114 help="Label to identify experiment", type="str")
115 parser.add_option("-i", "--pl-ssh-key", dest="pl_ssh_key",
116 help="Path to private SSH key to be used for connection",
117 default = pl_ssh_key, type="str")
119 (options, args) = parser.parse_args()
121 if not options.movie:
122 parser.error("movie is a required argument")
124 return (options.pl_user, options.movie, options.exp_id, options.pl_ssh_key)
127 if __name__ == '__main__':
128 content_name = "ccnx:/test/VIDEO"
130 ( pl_user, movie, exp_id, pl_ssh_key ) = get_options()
132 # Search for available RMs
135 ec = ExperimentController(exp_id = exp_id)
138 host1 = "planetlab2.u-strasbg.fr"
139 host2 = "planet1.servers.ua.pt"
140 host3 = "planetlab1.cs.uoi.gr"
141 host4 = "planetlab1.aston.ac.uk"
142 host5 = "planetlab2.willab.fi"
143 host6 = "planetlab-1.fokus.fraunhofer.de"
145 # describe nodes in the central ring
146 ring_hosts = [host1, host2, host3, host4]
149 for i in xrange(len(ring_hosts)):
151 node = add_node(ec, host, pl_user)
152 ccnd = add_ccnd(ec, node)
153 ccnr = add_ccnr(ec, ccnd)
156 ## Add ccn ring links
157 # l1 : h1 - h2 , h2 - h1
158 l1u = add_fib_entry(ec, ccnds[host1], host2)
159 l1d = add_fib_entry(ec, ccnds[host2], host1)
161 # l2 : h2 - h3 , h3 - h2
162 l2u = add_fib_entry(ec, ccnds[host2], host3)
163 l2d = add_fib_entry(ec, ccnds[host3], host2)
165 # l3 : h3 - h4 , h4 - h3
166 l3u = add_fib_entry(ec, ccnds[host3], host4)
167 l3d = add_fib_entry(ec, ccnds[host4], host3)
169 # l4 : h4 - h1 , h1 - h4
170 l4u = add_fib_entry(ec, ccnds[host4], host1)
171 l4d = add_fib_entry(ec, ccnds[host1], host4)
173 # l5 : h1 - h3 , h3 - h1
174 l5u = add_fib_entry(ec, ccnds[host1], host3)
175 l5d = add_fib_entry(ec, ccnds[host3], host1)
178 bnode1 = add_node(ec, host5, pl_user)
179 ccndb1 = add_ccnd(ec, bnode1)
180 ccnrb1 = add_ccnr(ec, ccndb1)
181 ccnds[host5] = ccndb1
182 co = add_content(ec, ccnrb1, content_name, movie)
185 bnode2 = add_node(ec, host6, pl_user)
186 ccndb2 = add_ccnd(ec, bnode2)
187 ccnrb2 = add_ccnr(ec, ccndb2)
188 ccnds[host6] = ccndb2
189 app = add_stream(ec, ccndb2, content_name)
191 # connect border nodes
192 add_fib_entry(ec, ccndb1, host1)
193 add_fib_entry(ec, ccnds[host1], host5)
195 add_fib_entry(ec, ccndb2, host3)
196 add_fib_entry(ec, ccnds[host3], host6)
198 # Put down l5 10s after transfer started
199 ec.register_condition(l5u, ResourceAction.STOP,
200 app, ResourceState.STARTED, time = "10s")
201 ec.register_condition(l5d, ResourceAction.STOP,
202 app, ResourceState.STARTED, time = "10s")
204 # deploy all ResourceManagers
207 ec.wait_started([app])
209 rvideo_path = ec.trace(app, "stdout", attr = TraceAttr.PATH)
210 command = 'tail -f %s' % rvideo_path
212 # pulling the content of the video received
213 # on b2, to stream it locally
214 proc1 = subprocess.Popen(['ssh',
215 '-o', 'StrictHostKeyChecking=no',
216 '-l', pl_user, host6,
218 stdout = subprocess.PIPE,
219 stderr = subprocess.PIPE)
221 proc2 = subprocess.Popen(['vlc',
222 '--ffmpeg-threads=1',
223 '--sub-filter', 'marq',
225 '(c) copyright 2008, Blender Foundation / www.bigbuckbunny.org',
227 '--no-video-title-show', '-'],
229 stdout=subprocess.PIPE,
230 stderr=subprocess.PIPE)
232 (stdout, stderr) = proc2.communicate()
234 dirpath = tempfile.mkdtemp()
235 print "Storing to DIRPATH ", dirpath
237 for ccnd in ccnds.values():
238 stdout = ec.trace(ccnd, "stderr")
239 fname = "log-%d" % ccnd
240 path = os.path.join(dirpath, fname)
245 # shutdown the experiment controller