peerfinder.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. from flask import Flask
  2. from flask import request, render_template
  3. from flask.ext.sqlalchemy import SQLAlchemy
  4. #from flask import session, request, url_for, redirect, render_template
  5. from netaddr import IPAddress
  6. # Hack for python3
  7. from netaddr.strategy.ipv4 import packed_to_int as unpack_v4
  8. from netaddr.strategy.ipv6 import packed_to_int as unpack_v6
  9. from datetime import datetime
  10. app = Flask(__name__)
  11. app.config.from_pyfile('config.py')
  12. db = SQLAlchemy(app)
  13. def unpack(ip):
  14. if len(ip) == 4:
  15. return unpack_v4(ip)
  16. elif len(ip) == 16:
  17. return unpack_v6(ip)
  18. class Target(db.Model):
  19. """Target IP to ping"""
  20. id = db.Column(db.Integer, primary_key=True)
  21. # IP addresses are encoded as their binary representation
  22. ip = db.Column(db.BINARY(length=16))
  23. # Date at which a user asked for measurements to this target
  24. submitted = db.Column(db.DateTime)
  25. def __init__(self, ip):
  26. self.ip = IPAddress(ip).packed
  27. self.submitted = datetime.now()
  28. def get_ip(self):
  29. return IPAddress(unpack(self.ip))
  30. def is_v4(self):
  31. return self.get_ip().version == 4
  32. def is_v6(self):
  33. return self.get_ip().version == 6
  34. def __repr__(self):
  35. return '%r' % self.get_ip()
  36. def __str__(self):
  37. return str(self.get_ip())
  38. class Result(db.Model):
  39. """Result of a ping measurement"""
  40. id = db.Column(db.Integer, primary_key=True)
  41. target_id = db.Column(db.Integer, db.ForeignKey('target.id'))
  42. target = db.relationship('Target',
  43. backref=db.backref('results', lazy='dynamic'))
  44. # Free-form (e.g. machine name). No IP, for privacy.
  45. source = db.Column(db.String)
  46. # In milliseconds
  47. rtt = db.Column(db.Float)
  48. def __init__(self, target_id, source, rtt):
  49. target = Target.query.get_or_404(int(target_id))
  50. self.target = target
  51. self.source = source
  52. self.rtt = float(rtt)
  53. def init_db():
  54. db.create_all()
  55. @app.route('/')
  56. def homepage():
  57. return render_template('home.html')
  58. @app.route('/submit', methods=['POST'])
  59. def submit_job():
  60. if 'target' in request.form:
  61. target = Target(request.form['target'])
  62. db.session.add(target)
  63. db.session.commit()
  64. return "Launching jobs towards {}".format(target)
  65. else:
  66. return "Invalid arguments"
  67. @app.route('/targets/all')
  68. def get_jobs():
  69. """"List of targets to ping"""
  70. targets = Target.query.order_by('-id').all()
  71. return "\n".join("{} {}".format(t.id, t) for t in targets)
  72. @app.route('/targets/ipv4')
  73. def get_v4jobs():
  74. """"List of IPv4 targets to ping"""
  75. targets = Target.query.order_by('-id').all()
  76. return "\n".join("{} {}".format(t.id, t) for t in targets if t.is_v4())
  77. @app.route('/targets/ipv6')
  78. def get_v6jobs():
  79. """"List of IPv6 targets to ping"""
  80. targets = Target.query.order_by('-id').all()
  81. return "\n".join("{} {}".format(t.id, t) for t in targets if t.is_v6())
  82. @app.route('/result/report', methods=['POST'])
  83. def report_result():
  84. if {'rtt', 'target'}.issubset(request.form):
  85. target = request.form['target']
  86. rtt = request.form['rtt']
  87. source = request.form.get('source', "")
  88. result = Result(target, source, rtt)
  89. db.session.add(result)
  90. db.session.commit()
  91. return "OK\n"
  92. else:
  93. return "Invalid arguments\n"
  94. @app.route('/result/show/<int:target_id>')
  95. def show_results(target_id):
  96. target = Target.query.get_or_404(target_id)
  97. return "<br >\n".join("Result: {} to {} in {} ms".format(r.source, r.target, r.rtt) for r in target.results.order_by('-id').all())
  98. if __name__ == '__main__':
  99. init_db()
  100. app.run(host='0.0.0.0', port=8888)