sensor: minor fixes
[oweals/gnunet.git] / src / sensor / profiler.py
1 import argparse
2 import math
3 import networkx
4 import random
5 import tempfile
6 import os
7 import time
8 import matplotlib.pyplot as plt
9 from subprocess import Popen, PIPE, STDOUT
10
11 node_colors = None
12 graph = None
13 pos = None
14
15 def get_args():
16   parser = argparse.ArgumentParser(description="Sensor profiler")
17   parser.add_argument('-p', '--peers', action='store', type=int, required=True,
18                       help='Number of peers to run')
19   parser.add_argument('-i', '--sensors-interval', action='store', type=int,
20                       required=False,
21                       help='Change the interval of running sensors to given value')
22   return parser.parse_args()
23
24 def generate_topology(peers, links):
25   global graph
26   global node_colors
27   global pos
28   graph = networkx.empty_graph(peers)
29   for i in range(0, links):
30     a = 0
31     b = 0
32     while a == b:
33       a = random.randint(0, peers - 1)
34       b = random.randint(0, peers - 1)
35     graph.add_edge(a, b)
36   node_colors = [0] * peers
37   pos = networkx.layout.spring_layout(graph)
38
39 def create_topology_file():
40   global graph
41   nodes = list()
42   for i in range(len(graph.edge)):
43     nodes.append(list())
44   for e in graph.edges():
45     nodes[e[0]].append(e[1])
46   print nodes
47   f = tempfile.NamedTemporaryFile(delete=False)
48   for i in range(len(nodes)):
49     if len(nodes[i]) == 0:
50       continue
51     f.write('%d:' % i)
52     f.write('|'.join(map(str, nodes[i])))
53     f.write('\n')
54   # f.close()
55   return f.name
56
57 def draw_graph():
58   global graph
59   global node_colors
60   global pos
61   t = int(time.time())
62   inc = 2
63   name = str(t) + '.png'
64   while os.path.exists(name):
65     name = '%d(%d).png' % (t, inc)
66     inc += 1
67   print 'Drawing graph to file: %s' % name
68   plt.clf()
69   networkx.draw(graph, pos=pos, node_color=node_colors, with_labels=range(len(graph.node)), cmap=plt.cm.Reds, vmin=0, vmax=2)
70   plt.savefig(name)
71
72 def peers_disconnected(p1, p2):
73   global graph
74   print 'Disconnected peers %d and %d' % (p1, p2)
75   if p2 not in graph[p1]:
76     print 'Link does not exist'
77     return
78   graph.remove_edge(p1, p2)
79   draw_graph()
80
81 def anomaly_report(report):
82   global node_colors
83   if 0 == report['anomalous']:
84     node_colors[report['peer']] = 0
85   else:
86     node_colors[report['peer']] = 1 + report['neighbors']
87   draw_graph()
88
89 def handle_profiler_line(line):
90   if not line:
91     return
92   print line
93   if 'Peer disconnection request sent' in line: # Peers disconnected
94     parts = line.split(':')
95     peers = parts[-1].split(',')
96     peers_disconnected(int(peers[0]), int(peers[1]))
97     return
98   if 'Anomaly report:' in line:
99     parts = line.split('Anomaly report:')
100     anomaly_report(eval(parts[1]))
101     return
102
103 def run_profiler(peers, topology_file, sensors_interval):
104   cmd1 = "GNUNET_FORCE_LOG='gnunet-sensor-profiler;;;;DEBUG' gnunet-sensor-profiler -p %d -t %s" % (peers, topology_file)
105   if sensors_interval:
106     cmd1 += " -i %d" % sensors_interval
107   cmd2 = "> log 2>&1"
108   cmd = "%s %s" % (cmd1, cmd2)
109   print cmd
110   process = Popen([cmd], shell=True)
111   time.sleep(0.5)
112   line = ''
113   f = open('log')
114   while process.poll() is None:
115     for c in f.read():
116       if not c or c == '\n':
117         handle_profiler_line(line)
118         line = ''
119       else:
120         line += c
121   os.remove('log')
122
123 def main():
124   args = vars(get_args())
125   num_peers = args['peers']
126   if num_peers < 3:
127     print 'Min number of peers is 3'
128     return
129   sensors_interval = None
130   if 'sensors_interval' in args:
131     sensors_interval = args['sensors_interval']
132   #num_links = int(math.log(num_peers) * math.log(num_peers) * num_peers / 2)
133   num_links = int(math.log(num_peers) * num_peers)
134   # Generate random topology
135   generate_topology(num_peers, num_links)
136   print 'Generated random topology with %d peers and %d links' % (num_peers, num_links)
137   # Create TESTBED topology file
138   top_file = create_topology_file()
139   print 'Created TESTBED topology file %s' % top_file
140   draw_graph()
141   # Run c profiler
142   run_profiler(num_peers, top_file, sensors_interval)
143   
144 if __name__ == "__main__":
145   main()