Commit 8401ce4e authored by Killian Lufau's avatar Killian Lufau Committed by Julien Muchembled

demo: new ping monitoring script and option to stop demo after some time

See "./demo --help" for more information.

/reviewed-on !8
parent 8c4cc9b6
...@@ -58,13 +58,14 @@ Requirements ...@@ -58,13 +58,14 @@ Requirements
- Babel_ (with Nexedi patches) - Babel_ (with Nexedi patches)
- geoip2: `python library`_ and `country lite database`_ (optional) - geoip2: `python library`_ and `country lite database`_ (optional)
- python-miniupnpc for UPnP support (optional) - python-miniupnpc for UPnP support (optional)
- for the demo: miniupnpd_, Graphviz, Screen_, Nemu_ - for the demo: miniupnpd_, Graphviz, Screen_, Nemu_, MultiPing_
See also `setup.py` for Python dependencies. See also `setup.py` for Python dependencies.
.. _Babel: https://lab.nexedi.com/nexedi/babeld .. _Babel: https://lab.nexedi.com/nexedi/babeld
.. _Nemu: https://github.com/thetincho/nemu .. _Nemu: https://github.com/thetincho/nemu
.. _miniupnpd: http://miniupnp.free.fr/ .. _miniupnpd: http://miniupnp.free.fr/
.. _MultiPing: https://github.com/romana/multi-ping
.. _Screen: http://savannah.gnu.org/projects/screen .. _Screen: http://savannah.gnu.org/projects/screen
.. _python library: https://pypi.org/project/geoip2/ .. _python library: https://pypi.org/project/geoip2/
.. _country lite database: https://dev.maxmind.com/geoip/geoip2/geolite2/ .. _country lite database: https://dev.maxmind.com/geoip/geoip2/geolite2/
......
#!/usr/bin/python2 #!/usr/bin/python2
import math, nemu, os, re, signal, socket, subprocess, sys, time, weakref import argparse, math, nemu, os, re, signal
import socket, subprocess, sys, time, weakref
from collections import defaultdict from collections import defaultdict
IPTABLES = 'iptables' IPTABLES = 'iptables'
SCREEN = 'screen' SCREEN = 'screen'
...@@ -38,6 +39,22 @@ def _add_interface(node, iface): ...@@ -38,6 +39,22 @@ def _add_interface(node, iface):
return Node__add_interface(node, iface) return Node__add_interface(node, iface)
nemu.Node._add_interface = _add_interface nemu.Node._add_interface = _add_interface
parser = argparse.ArgumentParser()
parser.add_argument('port', type = int,
help = 'port used to display tunnels')
parser.add_argument('-d', '--duration', type = int,
help = 'time of the demo execution in seconds')
parser.add_argument('-p', '--ping', action = 'store_true',
help = 'execute ping utility')
args = parser.parse_args()
def handler(signum, frame):
sys.exit()
if args.duration:
signal.signal(signal.SIGALRM, handler)
signal.alarm(args.duration)
execfile("fixnemu.py") execfile("fixnemu.py")
# create nodes # create nodes
...@@ -225,6 +242,18 @@ if 1: ...@@ -225,6 +242,18 @@ if 1:
re6stnet(machine8, 'm8') re6stnet(machine8, 'm8')
db.close() db.close()
if args.ping:
for j, machine in enumerate(nodes):
ips = [
'2001:db8:42::1' if i == 0 else
'2001:db8:42:2::' if i == 2 else
# Only 1 address for machine2 because prefix_len = 80,+48 = 128
'2001:db8:42:%s::1' % i
for i in xrange(9)
if i != j]
name = 'm' + machine.short if machine.short != 'R' else 'registry'
machine.screen('python ping.py {} {}'.format(name, ' '.join(ips)))
_ll = {} _ll = {}
def node_by_ll(addr): def node_by_ll(addr):
try: try:
...@@ -302,7 +331,7 @@ def route_svg(ipv4, z = 4, default = type('', (), {'short': None})): ...@@ -302,7 +331,7 @@ def route_svg(ipv4, z = 4, default = type('', (), {'short': None})):
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
).communicate('\n'.join(gv))[0] ).communicate('\n'.join(gv))[0]
if len(sys.argv) > 1: if args.port:
import SimpleHTTPServer, SocketServer import SimpleHTTPServer, SocketServer
class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler): class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler):
...@@ -392,6 +421,6 @@ if len(sys.argv) > 1: ...@@ -392,6 +421,6 @@ if len(sys.argv) > 1:
class TCPServer(SocketServer.TCPServer): class TCPServer(SocketServer.TCPServer):
allow_reuse_address = True allow_reuse_address = True
TCPServer(('', int(sys.argv[1])), Handler).serve_forever() TCPServer(('', args.port), Handler).serve_forever()
import pdb; pdb.set_trace() import pdb; pdb.set_trace()
# -*- coding: utf-8 -*-
'''
Script launched on machines from the demo with the option -p/--ping
It uses Multiping to ping several IPs passed as arguments.
After Re6st is stable, this script logs when it does not get response from a
machine in a csv file stored in the directory of the machine in this format:
time, sequence number, number of non-responding machines, ip of these machines
'''
import argparse, errno, logging, os, socket, time
from multiping import MultiPing
from threading import Thread, Lock
PING_INTERVAL = 0.1
PING_TIMEOUT = 4
csv_lock = Lock()
class MultiPing(MultiPing):
# Patch of Multiping because it stays blocked to ipv4
# emission when we want to ping only ipv6 addresses.
# So we only keep the ipv6 part for the demo.
# Bug issued: https://github.com/romana/multi-ping/issues/22
def _read_all_from_socket(self, timeout):
pkts = []
if self._ipv6_address_present:
try:
self._sock6.settimeout(timeout)
while True:
p = self._sock6.recv(128)
pkts.append((bytearray(p), time.time()))
self._sock6.settimeout(0)
except socket.timeout:
pass
except socket.error as e:
if e.errno == errno.EWOULDBLOCK:
pass
else:
raise
return pkts
class Ping(Thread):
seq = None
seq_lock = Lock()
def run(self):
mp = MultiPing(addrs)
assert mp._last_used_id is None
cls = self.__class__
with cls.seq_lock:
mp._last_used_id = cls.seq
mp.send()
seq = cls.seq = mp._last_used_id
responses, no_responses = mp.receive(PING_TIMEOUT)
x = list(responses)
x += no_responses
assert sorted(x) == sorted(addrs), (addrs, responses, no_responses)
with csv_lock:
if no_responses:
my_csv.write('%r,%d,%d,%s\n' % (time.time(), seq,
len(no_responses), ' '.join(no_responses)))
my_csv.flush()
else :
# Update modification/access time of csv
os.utime(csv_path, (time.time(), time.time()))
for add in no_responses:
print('No response from %s with seq no %d' % (add, seq))
parser = argparse.ArgumentParser()
parser.add_argument('n', help = 'my machine name (m1,m2...)')
parser.add_argument('a', nargs = '+', help = 'the list of addresses to ping')
args = parser.parse_args()
my_name = args.n
addrs = args.a
print('Waiting for every machine to answer ping..')
while True:
mp = MultiPing(addrs)
mp.send()
_, no_responses = mp.receive(0.5)
if not no_responses:
break
# Currently useless because MultiPing does not return earlier if it
# couldn't send any ping (e.g. no route to host). Let's hope it will
# improve.
time.sleep(PING_INTERVAL)
print('Network is stable, starting to ping..')
csv_path = '{}/ping_logs.csv'.format(my_name)
my_csv = open(csv_path, 'w+')
my_csv.write('%r,%s,%d\n' % (time.time(), 0, 0))
my_csv.flush()
while True:
Ping().start()
time.sleep(PING_INTERVAL)
...@@ -6,11 +6,12 @@ def __file__(): ...@@ -6,11 +6,12 @@ def __file__():
from argparse import ArgumentParser from argparse import ArgumentParser
_parse_args = ArgumentParser.parse_args _parse_args = ArgumentParser.parse_args
ArgumentParser.parse_args = lambda self: _parse_args(self, sys.argv[2:]) ArgumentParser.parse_args = lambda self: _parse_args(self, sys.argv[2:])
# Always import to prevent re6st.node.cli from altering the first sys.path
from re6st import registry
if 1: if 1:
# Check renewal of certificate. # Check renewal of certificate.
from random import randrange from random import randrange
from re6st import registry
registry.RENEW_PERIOD = 60 registry.RENEW_PERIOD = 60
_createCertificate = registry.RegistryServer.createCertificate _createCertificate = registry.RegistryServer.createCertificate
def createCertificate(self, client_prefix, *args): def createCertificate(self, client_prefix, *args):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment