icmp ping #1

Open
fil wants to merge 6 commits from dev into main
7 changed files with 144 additions and 1 deletions

2
.gitignore vendored
View file

@ -123,6 +123,7 @@ celerybeat.pid
# Environments
.env
.venv
.macvenv
env/
venv/
ENV/
@ -159,4 +160,3 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

17
config.py Normal file
View file

@ -0,0 +1,17 @@
import os
import yaml
from dotenv import load_dotenv
with open("config.yaml") as f:
cfg = yaml.load(f, Loader=yaml.FullLoader)
class Config:
def __init__(self):
load_dotenv()
self.config_data = cfg
for key in cfg.keys():
if key in os.environ:
self.config_data[key] = os.environ[key]
setattr(self, key, self.config_data[key])
CONFIG = Config()

5
config.yaml Normal file
View file

@ -0,0 +1,5 @@
db_host: ""
db_database: ""
db_user: ""
db_password: ""
location: ""

54
database.py Normal file
View file

@ -0,0 +1,54 @@
from config import CONFIG
import psycopg2.extras
import psycopg2
class Database():
def __init__(self):
self.connect()
def connect(self):
self.conn = psycopg2.connect(
host=CONFIG.db_host,
database=CONFIG.db_database,
user=CONFIG.db_user,
password=CONFIG.db_password
)
self.cur = self.conn.cursor(
cursor_factory=psycopg2.extras.RealDictCursor)
def get_all_services(self):
self.cur.execute("SELECT * FROM service")
return self.cur.fetchall()
def get_open_incident(self, id):
self.cur.execute("""SELECT incident.id FROM incident
JOIN state ON incident.state_id = state.id
JOIN service ON state.service_id = service.id
WHERE service.id = %s AND t_end IS NULL;""", (str(id),))
return self.cur.fetchall()
def create_state(self, id):
self.cur.execute("""INSERT INTO state (service_id)
VALUES (%s) RETURNING *;""", (str(id),))
self.conn.commit()
return self.cur.fetchall()
def create_incident(self, id):
self.cur.execute("""INSERT INTO incident (state_id)
VALUES (%s) RETURNING *;""", (str(id),))
self.conn.commit()
return self.cur.fetchall()
def close_incident(self, id):
fil marked this conversation as resolved
Review

Don't you have a way here to just take the state you just created? It seems pointless to me to take them all since you're only interested in the latest created anyway

Don't you have a way here to just take the state you just created? It seems pointless to me to take them all since you're only interested in the latest created anyway
self.cur.execute("""UPDATE incident
SET t_end = NOW()
WHERE id = %s RETURNING *;""", (str(id),))
self.conn.commit()
return self.cur.fetchall()
def add_latency(self, *argv):
self.cur.execute("""INSERT INTO latency
(state_id, location, ping)
VALUES (%s,%s,%s) RETURNING *;""", *argv)
self.conn.commit()
return self.cur.fetchall()

5
main.py Normal file
View file

@ -0,0 +1,5 @@
from pingpong import PingPong
if __name__ == "__main__":
runner = PingPong()
runner.start()

51
pingpong.py Normal file
View file

@ -0,0 +1,51 @@
from database import Database
from pythonping import ping
from tcppinglib import tcpping
from config import CONFIG
class PingPong:
def __init__(self):
self.db = Database()
def icmp_ping(self, service):
r = {}
ping_data = ping(service)
avg_rtt = sum([e.time_elapsed_ms for e in ping_data]) / len(ping_data)
best_effort = sorted(ping_data, key=lambda x: x.time_elapsed_ms)[0]
r['success'] = best_effort.success
r['ping'] = avg_rtt
return r
def tcp_ping(self, service):
r = {}
try:
ping_data = tcpping(service, port=80, timeout=2, count=3, interval=1)
r['success'] = ping_data.is_alive
r['ping'] = ping_data.avg_rtt
except:
r['success'] = False
return r
def start(self):
latency = {
"location": CONFIG.location
}
for el in self.db.get_all_services():
state = self.db.create_state(el['id'])[0]
open_incident = self.db.get_open_incident(el['id'])
if el['type'] == 'physical':
ping_data = self.icmp_ping(el['ipaddr'])
else:
ping_data = self.tcp_ping(el['domain'])
if ping_data['success']:
latency['ping'] = ping_data['ping']
self.db.add_latency([state['id'], *latency.values()])
if open_incident:
self.db.close_incident(open_incident[0]['id'])
else:
latency['ping'] = 0
self.db.add_latency([state['id'], *latency.values()])
if not open_incident:
self.db.create_incident(state['id'])

11
requirements.txt Normal file
View file

@ -0,0 +1,11 @@
certifi==2024.2.2
charset-normalizer==3.3.2
idna==3.7
pip-autoremove==0.10.0
psycopg2-binary==2.9.9
python-dotenv==1.0.1
pythonping==1.1.4
requests==2.31.0
setuptools==69.5.1
tcppinglib==2.0.3
urllib3==2.2.1