|
@@ -1,3 +1,5 @@
|
|
|
+#!/usr/bin/env python3
|
|
|
+
|
|
|
from flask import Flask
|
|
|
from flask import request, render_template
|
|
|
from flask.ext.sqlalchemy import SQLAlchemy
|
|
@@ -7,7 +9,7 @@ from netaddr import IPAddress
|
|
|
from netaddr.strategy.ipv4 import packed_to_int as unpack_v4
|
|
|
from netaddr.strategy.ipv6 import packed_to_int as unpack_v6
|
|
|
from datetime import datetime
|
|
|
-
|
|
|
+from uuid import uuid4
|
|
|
|
|
|
app = Flask(__name__)
|
|
|
app.config.from_pyfile('config.py')
|
|
@@ -47,19 +49,46 @@ class Target(db.Model):
|
|
|
def __str__(self):
|
|
|
return str(self.get_ip())
|
|
|
|
|
|
+
|
|
|
+class Participant(db.Model):
|
|
|
+ """Participant in the ping network"""
|
|
|
+ id = db.Column(db.Integer, primary_key=True)
|
|
|
+ # Used both as identification and password
|
|
|
+ uuid = db.Column(db.String, unique=True)
|
|
|
+ # Name of the machine
|
|
|
+ name = db.Column(db.String)
|
|
|
+ # Mostly free-form (nick, mail address, ...)
|
|
|
+ contact = db.Column(db.String)
|
|
|
+ # Whether we accept this participant or not
|
|
|
+ active = db.Column(db.Boolean)
|
|
|
+
|
|
|
+ def __init__(self, name, contact):
|
|
|
+ self.uuid = str(uuid4())
|
|
|
+ self.name = name
|
|
|
+ self.contact = contact
|
|
|
+ self.active = False
|
|
|
+
|
|
|
+ def __str__(self):
|
|
|
+ return "{} ({})".format(self.name, self.contact)
|
|
|
+
|
|
|
+
|
|
|
class Result(db.Model):
|
|
|
"""Result of a ping measurement"""
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
|
target_id = db.Column(db.Integer, db.ForeignKey('target.id'))
|
|
|
target = db.relationship('Target',
|
|
|
backref=db.backref('results', lazy='dynamic'))
|
|
|
- # Free-form (e.g. machine name). No IP, for privacy.
|
|
|
- source = db.Column(db.String)
|
|
|
+ # Participant
|
|
|
+ source_id = db.Column(db.Integer, db.ForeignKey('participant.id'))
|
|
|
+ source = db.relationship('Participant',
|
|
|
+ backref=db.backref('results', lazy='dynamic'))
|
|
|
# In milliseconds
|
|
|
rtt = db.Column(db.Float)
|
|
|
|
|
|
- def __init__(self, target_id, source, rtt):
|
|
|
+ def __init__(self, target_id, source_uuid, rtt):
|
|
|
target = Target.query.get_or_404(int(target_id))
|
|
|
+ source = Participant.query.filter_by(uuid=source_uuid,
|
|
|
+ active=True).first_or_404()
|
|
|
self.target = target
|
|
|
self.source = source
|
|
|
self.rtt = float(rtt)
|
|
@@ -83,6 +112,16 @@ def submit_job():
|
|
|
else:
|
|
|
return "Invalid arguments"
|
|
|
|
|
|
+@app.route('/create/participant', methods=['POST'])
|
|
|
+def create_participant():
|
|
|
+ if {'name', 'contact'}.issubset(request.form) and request.form['name']:
|
|
|
+ participant = Participant(request.form['name'], request.form['contact'])
|
|
|
+ db.session.add(participant)
|
|
|
+ db.session.commit()
|
|
|
+ return "OK\nPlease wait for manual validation\n"
|
|
|
+ else:
|
|
|
+ return "Invalid arguments"
|
|
|
+
|
|
|
@app.route('/targets/all')
|
|
|
def get_jobs():
|
|
|
""""List of targets to ping"""
|
|
@@ -103,11 +142,11 @@ def get_v6jobs():
|
|
|
|
|
|
@app.route('/result/report', methods=['POST'])
|
|
|
def report_result():
|
|
|
- if {'rtt', 'target'}.issubset(request.form):
|
|
|
+ if {'rtt', 'target', 'source'}.issubset(request.form):
|
|
|
target = request.form['target']
|
|
|
rtt = request.form['rtt']
|
|
|
- source = request.form.get('source', "")
|
|
|
- result = Result(target, source, rtt)
|
|
|
+ source_uuid = request.form['source']
|
|
|
+ result = Result(target, source_uuid, rtt)
|
|
|
db.session.add(result)
|
|
|
db.session.commit()
|
|
|
return "OK\n"
|