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
|
# Environments
|
||||||
.env
|
.env
|
||||||
.venv
|
.venv
|
||||||
|
.macvenv
|
||||||
env/
|
env/
|
||||||
venv/
|
venv/
|
||||||
ENV/
|
ENV/
|
||||||
|
|
@ -159,4 +160,3 @@ cython_debug/
|
||||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
# 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.
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
#.idea/
|
#.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
|
||||||
|
|
||||||
|
fil marked this conversation as resolved
Outdated
fil
commented
use avg response time instead of fastest? use avg response time instead of fastest?
samu
commented
Makes sense to me Makes sense to me
|
|||||||
|
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