icmp ping #1
7 changed files with 144 additions and 1 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -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
17
config.py
Normal 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
5
config.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
db_host: ""
|
||||
db_database: ""
|
||||
db_user: ""
|
||||
db_password: ""
|
||||
location: ""
|
||||
54
database.py
Normal file
54
database.py
Normal 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
|
||||
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
5
main.py
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
from pingpong import PingPong
|
||||
|
||||
if __name__ == "__main__":
|
||||
runner = PingPong()
|
||||
runner.start()
|
||||
51
pingpong.py
Normal file
51
pingpong.py
Normal 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
11
requirements.txt
Normal 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
|
||||
Loading…
Reference in a new issue
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