Adding validations to CCND and PING log parser in nepi data
[nepi.git] / examples / ccn_emu_live / planetlab.py
1 #!/usr/bin/env python
2
3 ###############################################################################
4 #
5 #    NEPI, a framework to manage network experiments
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 ###############################################################################
23
24 from nepi.execution.ec import ExperimentController 
25 from nepi.execution.runner import ExperimentRunner
26 from nepi.util.netgraph import NetGraph, TopologyType
27 import nepi.data.processing.ccn.parser as ccn_parser
28
29 import networkx
30 import socket
31 import os
32
33 PL_NODES = dict({
34     "0": "iraplab1.iralab.uni-karlsruhe.de",
35     "1": "planetlab1.informatik.uni-goettingen.de",
36     "2": "dfn-ple1.x-win.dfn.de",
37     "3": "mars.planetlab.haw-hamburg.de",
38     "4": "planetlab2.unineuchatel.ch", 
39     "5": "planetlab-node3.it-sudparis.eu",
40     "6": "planetlab2.extern.kuleuven.be",
41     "7": "node2pl.planet-lab.telecom-lille1.eu",
42     "8": "planetvs2.informatik.uni-stuttgart.de",
43     "9": "planetlab1.informatik.uni-wuerzburg.de",
44     "10": "planet1.l3s.uni-hannover.de",
45     "11": "planetlab1.wiwi.hu-berlin.de",
46     "12": "pl2.uni-rostock.de", 
47     "13": "planetlab1.u-strasbg.fr",
48     "14": "peeramidion.irisa.fr"
49     })
50
51 pl_slice = os.environ.get("PL_SLICE")
52 pl_user = os.environ.get("PL_USER")
53 pl_password = os.environ.get("PL_PASS")
54 pl_ssh_key = os.environ.get("PL_SSHKEY")
55
56 content_name = "ccnx:/test/bunny.ts"
57
58 pipeline = 4 # Default value for ccncat
59
60 operating_system = "f14"
61
62 country = "germany"
63
64 repofile = os.path.join(
65         os.path.dirname(os.path.realpath(__file__)), "repoFile1.0.8.2")
66
67 def add_collector(ec, trace_name, subdir, newname = None):
68     collector = ec.register_resource("Collector")
69     ec.set(collector, "traceName", trace_name)
70     ec.set(collector, "subDir", subdir)
71     if newname:
72         ec.set(collector, "rename", newname)
73
74     return collector
75
76 def add_pl_host(ec, nid):
77     hostname = PL_NODES[nid]
78
79     # Add a planetlab host to the experiment description
80     host = ec.register_resource("PlanetlabNode")
81     ec.set(host, "hostname", hostname)
82     ec.set(host, "username", pl_slice)
83     ec.set(host, "identity", pl_ssh_key)
84     #ec.set(host, "pluser", pl_user)
85     #ec.set(host, "plpassword", pl_password)
86     #ec.set(host, "country", country)
87     #ec.set(host, "operatingSystem", operating_system)
88     ec.set(host, "cleanExperiment", True)
89     ec.set(host, "cleanProcesses", True)
90
91     # Annotate the graph
92     ec.netgraph.annotate_node(nid, "hostname", hostname)
93     ec.netgraph.annotate_node(nid, "host", host)
94     
95     # Annotate the graph node with an ip address
96     ip = socket.gethostbyname(hostname)
97     ec.netgraph.annotate_node_ip(nid, ip)
98
99 def add_pl_ccnd(ec, nid):
100     # Retrieve annotation from netgraph
101     host = ec.netgraph.node_annotation(nid, "host")
102     
103     # Add a CCN daemon to the planetlab node
104     ccnd = ec.register_resource("LinuxCCND")
105     ec.set(ccnd, "debug", 7)
106     ec.register_connection(ccnd, host)
107     
108     # Collector to retrieve ccnd log
109     collector = add_collector(ec, "stderr", nid, "log")
110     ec.register_connection(collector, ccnd)
111
112     # Annotate the graph
113     ec.netgraph.annotate_node(nid, "ccnd", ccnd)
114
115 def add_pl_ccnr(ec, nid):
116     # Retrieve annotation from netgraph
117     ccnd = ec.netgraph.node_annotation(nid, "ccnd")
118     
119     # Add a CCN content repository to the planetlab node
120     ccnr = ec.register_resource("LinuxCCNR")
121
122     ec.set(ccnr, "repoFile1", repofile)
123     ec.register_connection(ccnr, ccnd)
124
125 def add_pl_ccncat(ec, nid):
126     # Retrieve annotation from netgraph
127     ccnd = ec.netgraph.node_annotation(nid, "ccnd")
128     
129     # Add a CCN cat application to the planetlab node
130     ccncat = ec.register_resource("LinuxCCNCat")
131     ec.set(ccncat, "pipeline", pipeline)
132     ec.set(ccncat, "contentName", content_name)
133     ec.register_connection(ccncat, ccnd)
134
135 def add_pl_fib_entry(ec, nid1, nid2):
136     # Retrieve annotations from netgraph
137     ccnd1 = ec.netgraph.node_annotation(nid1, "ccnd")
138     hostname2 = ec.netgraph.node_annotation(nid2, "hostname")
139     
140     # Add a FIB entry between one planetlab node and its peer
141     entry = ec.register_resource("LinuxFIBEntry")
142     ec.set(entry, "host", hostname2)
143     ec.register_connection(entry, ccnd1)
144
145     # Collector to retrieve peering ping output (to measure neighbors delay)
146     ec.enable_trace(entry, "ping")
147     collector = add_collector(ec, "ping", nid1)
148     ec.register_connection(collector, entry)
149
150     return entry
151
152 def avg_interests(ec, run):
153     ## Process logs
154     logs_dir = ec.run_dir
155
156     (graph,
157         content_names,
158         interest_expiry_count,
159         interest_dupnonce_count,
160         interest_count,
161         content_count) = ccn_parser.process_content_history_logs(
162                 logs_dir,
163                 ec.netgraph.topology,
164                 parse_ping_logs = True)
165
166     shortest_path = networkx.shortest_path(graph, 
167             source = ec.netgraph.sources()[0], 
168             target = ec.netgraph.targets()[0])
169
170     ### Compute metric: Avg number of Interests seen per content name
171     ###                 normalized by the number of nodes in the shortest path
172     content_name_count = len(content_names.values())
173     nodes_in_shortest_path = len(shortest_path) - 1
174     metric = interest_count / (float(content_name_count) * float(nodes_in_shortest_path))
175
176     # TODO: DUMP RESULTS TO FILE
177     # TODO: DUMP GRAPH DELAYS!
178     f = open("/tmp/metric", "w+")
179     f.write("%.2f\n" % metric)
180     f.close()
181     print " METRIC", metric
182
183     return metric
184
185 def add_pl_edge(ec, nid1, nid2):
186     #### Add connections between CCN nodes
187     add_pl_fib_entry(ec, nid1, nid2)
188     add_pl_fib_entry(ec, nid2, nid1)
189
190 def add_pl_node(ec, nid):
191     ### Add CCN nodes (ec.netgraph holds the topology graph)
192     add_pl_host(ec, nid)
193     add_pl_ccnd(ec, nid)
194         
195     if nid == ec.netgraph.targets()[0]:
196         add_pl_ccnr(ec, nid)
197
198     if nid == ec.netgraph.sources()[0]:
199         add_pl_ccncat(ec, nid)
200
201 if __name__ == '__main__':
202
203     #### Create NEPI Experiment Description with LINEAR topology 
204     ec = ExperimentController("pl_ccn", 
205             topo_type = TopologyType.LINEAR, 
206             node_count = 4, 
207             #assign_ips = True,
208             assign_st = True,
209             add_node_callback = add_pl_node, 
210             add_edge_callback = add_pl_edge)
211     
212     print "Results stored at", ec.exp_dir
213
214     #### Retrieve the content producing resource to wait for ot to finish
215     ccncat = ec.filter_resources("LinuxCCNCat")
216    
217     #### Run experiment until metric convergences
218     rnr = ExperimentRunner()
219     runs = rnr.run(ec, min_runs = 10, max_runs = 300, 
220             compute_metric_callback = avg_interests,
221             wait_guids = ccncat,
222             wait_time = 0)
223