-fix ftbfs
[oweals/gnunet.git] / src / sensor / profiler.py
index 55187db1c07fd0e13c047563dca435046c192556..cdd9172848e62cfe55cf9f27c6bd19c7ac8b19de 100644 (file)
@@ -5,26 +5,44 @@ import random
 import tempfile
 import os
 import time
+import matplotlib.pyplot as plt
 from subprocess import Popen, PIPE, STDOUT
 
+node_colors = None
+graph = None
+pos = None
+
 def get_args():
   parser = argparse.ArgumentParser(description="Sensor profiler")
   parser.add_argument('-p', '--peers', action='store', type=int, required=True,
                       help='Number of peers to run')
+  parser.add_argument('-l', '--links', action='store', type=int, required=False,
+                      help='Number of links to create')
+  parser.add_argument('-i', '--sensors-interval', action='store', type=int,
+                      required=False,
+                      help='Change the interval of running sensors to given value')
+  parser.add_argument('-a', '--anomalous-peers', action='store', type=int,
+                      required=True,
+                      help='Number of peers to simulate anomalies on')
   return parser.parse_args()
 
 def generate_topology(peers, links):
-  G = networkx.empty_graph(peers)
+  global graph
+  global node_colors
+  global pos
+  graph = networkx.empty_graph(peers)
   for i in range(0, links):
     a = 0
     b = 0
     while a == b:
-      a = random.randint(0, peers)
-      b = random.randint(0, peers)
-    G.add_edge(a, b)
-  return G
+      a = random.randint(0, peers - 1)
+      b = random.randint(0, peers - 1)
+    graph.add_edge(a, b)
+  node_colors = [0] * peers
+  pos = networkx.layout.spring_layout(graph)
 
-def create_topology_file(graph):
+def create_topology_file():
+  global graph
   nodes = list()
   for i in range(len(graph.edge)):
     nodes.append(list())
@@ -41,13 +59,79 @@ def create_topology_file(graph):
   # f.close()
   return f.name
 
+def draw_graph():
+  global graph
+  global node_colors
+  global pos
+  t = int(time.time())
+  inc = 2
+  name = str(t) + '.png'
+  while os.path.exists(name):
+    name = '%d(%d).png' % (t, inc)
+    inc += 1
+  print 'Drawing graph to file: %s' % name
+  plt.clf()
+  anomaly_lbls = {}
+  for i in range(len(graph.node)):
+    if node_colors[i] >= 1:
+      anomaly_lbls[i] = '\n\n\n' + str(node_colors[i] - 1)
+  networkx.draw(graph, pos=pos, node_color=node_colors, with_labels=range(len(graph.node)), cmap=plt.cm.Reds, vmin=0, vmax=2)
+  networkx.draw_networkx_labels(graph, pos, anomaly_lbls)
+  plt.savefig(name)
+
+def peers_reconnected(p1, p2):
+  global graph
+  if p2 in graph[p1]:
+    print 'Link already exists'
+    return
+  graph.add_edge(p1, p2)
+  draw_graph()
+
+def peers_disconnected(p1, p2):
+  global graph
+  print 'Disconnected peers %d and %d' % (p1, p2)
+  if p2 not in graph[p1]:
+    print 'Link does not exist'
+    return
+  graph.remove_edge(p1, p2)
+  draw_graph()
+
+def anomaly_report(report):
+  global node_colors
+  if 0 == report['anomalous']:
+    node_colors[report['peer']] = 0
+  else:
+    clr = 1 + report['neighbors']
+    if node_colors[report['peer']] >= clr:
+      return
+    node_colors[report['peer']] = clr
+  draw_graph()
+
 def handle_profiler_line(line):
   if not line:
     return
   print line
+  if 'Peer disconnection request sent' in line: # Peers disconnected
+    parts = line.split(':')
+    peers = parts[-1].split(',')
+    peers_disconnected(int(peers[0]), int(peers[1]))
+    return
+  if 'Anomaly report:' in line:
+    parts = line.split('Anomaly report:')
+    anomaly_report(eval(parts[1]))
+    return
+  if 'Peer connection request sent' in line: # Peers reconnected
+    parts = line.split(':')
+    peers = parts[-1].split(',')
+    peers_reconnected(int(peers[0]), int(peers[1]))
 
-def run_profiler(peers, topology_file):
-  cmd = "GNUNET_FORCE_LOG='gnunet-sensor-profiler;;;;DEBUG' gnunet-sensor-profiler -p %d -t %s > log 2>&1" % (peers, topology_file)
+def run_profiler(peers, topology_file, sensors_interval, anomalous_peers):
+  cmd1 = "./gnunet-sensor-profiler -p %d -t %s -a %d" % (peers, topology_file, anomalous_peers)
+  if sensors_interval:
+    cmd1 += " -i %d" % sensors_interval
+  cmd2 = "> log 2>&1"
+  cmd = "%s %s" % (cmd1, cmd2)
+  print cmd
   process = Popen([cmd], shell=True)
   time.sleep(0.5)
   line = ''
@@ -59,7 +143,6 @@ def run_profiler(peers, topology_file):
         line = ''
       else:
         line += c
-  os.remove('log')
 
 def main():
   args = vars(get_args())
@@ -67,15 +150,26 @@ def main():
   if num_peers < 3:
     print 'Min number of peers is 3'
     return
-  num_links = int(math.log(num_peers) * math.log(num_peers) * num_peers / 2)
+  sensors_interval = None
+  if 'sensors_interval' in args:
+    sensors_interval = args['sensors_interval']
+  if 'links' in args:
+    num_links = args['links']
+  else:
+    #num_links = int(math.log(num_peers) * math.log(num_peers) * num_peers / 2)
+    num_links = int(math.log(num_peers) * num_peers)
   # Generate random topology
-  graph = generate_topology(num_peers, num_links)
+  generate_topology(num_peers, num_links)
   print 'Generated random topology with %d peers and %d links' % (num_peers, num_links)
+  # Create a file with links to cut to split the topology into two
   # Create TESTBED topology file
-  top_file = create_topology_file(graph)
+  top_file = create_topology_file()
   print 'Created TESTBED topology file %s' % top_file
+  draw_graph()
   # Run c profiler
-  run_profiler(num_peers, top_file)
+  if os.path.isfile('log'):
+    os.remove('log')
+  run_profiler(num_peers, top_file, sensors_interval, args['anomalous_peers'])
   
 if __name__ == "__main__":
   main()