Skip to content

Commit

Permalink
dbhandle: create dbapi interface
Browse files Browse the repository at this point in the history
This patch initializes the sqliteh file (not in a usable state currently), and creates an interface for DBAPI. Any DBAPI compliant module can simply just use the existing implementations. Future work may be required to ensure there are no dialect-based conflicts.

Signed-off-by: Amy Parker <[email protected]>
  • Loading branch information
amyipdev committed Jul 26, 2023
1 parent f7e2054 commit 28595ac
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 112 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ __pycache__/
ssvp-config.json
.sass-cache/
*.css.map
*.js
*.js
*.db
117 changes: 117 additions & 0 deletions srv/dbhandle.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,120 @@ def insert_interval_log(self, srv: str, status: int) -> None:

def update_cached_stats(self, srv: str, st: int) -> None:
unimplemented()


class DBAPIAbstracted(DBAbstract):
def __init__(self, config: dict, prefix: str) -> None:
super().__init__(config=config)
self.p = prefix

def _get_ups(self, srv: str, conn) -> dict:
curr = conn.cursor()
sql = f"select monthlyUptime, yearlyUptime, allTimeUptime, currentStatus \
from {self.p}cached_stats \
where serverName = %s;"
curr.execute(sql, (srv,))
row = curr.fetchone()
if row is None:
curr.close()
raise Exception("ssvp: mysql: invalid server")
curr.close()
conn.close()
return {
"monthly_uptime": row[0],
"yearly_uptime": row[1],
"alltime_uptime": row[2],
"current_status": row[3]
}

def _fdd(self, srv: str, conn) -> dict:
curr = conn.cursor()
sql = f"select logDate, serverStatus \
from {self.p}day_logs \
where logDate between (current_date() - interval 3 month) and current_date() and serverName = %s;"
curr.execute(sql, (srv,))
res = {}
for row in curr.fetchall():
res[row[0]] = row[1]
curr.close()
conn.close()
return res

def _hdr(self, srv: str, st: int, conn) -> int:
curr = conn.cursor()
day = datetime.date.today()
sql = f"select exists( \
select serverName \
from {self.p}day_logs \
where serverName = %s \
and logDate = %s \
);"
curr.execute(sql, (srv, day))
rc_exists = curr.fetchone()[0]
sql = f"select max( \
select severity \
from {self.p}events \
where serverName = %s \
and endTime is not null \
);"
mx = None
try:
curr.execute(sql, (srv,))
mx = max(st, curr.fetchone()[0])
# we can ignore the pep violation
except:
mx = st
if not rc_exists:
sql = f"insert into {self.p}day_logs \
(logDate, serverName, serverStatus) values \
(%s, %s, %s);"
curr.execute(sql, (day, srv, mx))
else:
sql = f"update {self.p}day_logs \
set serverStatus = %s \
where logDate = %s \
and serverName = %s;"
curr.execute(sql, (mx, day, srv))
curr.fetchall()
conn.commit()
curr.close()
conn.close()
return mx

def _iil(self, srv: str, status: int, conn) -> None:
curr = conn.cursor()
sql = f"insert into {self.p}interval_logs \
(logDate, serverName, serverStatus) values \
(%s, %s, %s);"
curr.execute(sql, (datetime.datetime.now(), srv, status))
curr.fetchall()
conn.commit()
curr.close()
conn.close()

def _ucs(self, srv: str, st: int, conn) -> None:
curr = conn.cursor()
sql = f"update {self.p}cached_stats \
set monthlyUptime = \
(select AVG(NOT serverStatus) \
from {self.p}interval_logs \
where logDate between \
(CURRENT_DATE() - interval 1 month) and CURRENT_DATE() \
and serverName = %s), \
yearlyUptime = \
(select AVG(NOT serverStatus) \
from {self.p}interval_logs \
where logDate between \
(CURRENT_DATE() - interval 1 year) and CURRENT_DATE() \
and serverName = %s), \
allTimeUptime = \
(select AVG(NOT serverStatus) \
from {self.p}interval_logs \
where serverName = %s), \
currentStatus = %s\
where serverName = %s;"
curr.execute(sql, (srv, srv, srv, st, srv))
curr.fetchall()
conn.commit()
curr.close()
conn.close()
118 changes: 7 additions & 111 deletions srv/mysqlh.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,19 @@

import dbhandle
import mysql.connector
import datetime


class MySQLHandler(dbhandle.DBAbstract):
class MySQLHandler(dbhandle.DBAPIAbstracted):
def __init__(self, config: dict) -> None:
super().__init__(config=config)
super().__init__(config=config, prefix=config["prefix"])
self.host = config["host"]
self.port = config["port"]
self.login = config["username"]
self.pw = config["password"]
self.db = config["database"]
self.p = config["prefix"]

def get_uptime_stats(self, srv: str) -> dict:
conn = self._generate_connection()
curr = conn.cursor()
sql = f"select monthlyUptime, yearlyUptime, allTimeUptime, currentStatus \
from {self.p}cached_stats \
where serverName = %s;"
curr.execute(sql, (srv,))
row = curr.fetchone()
if row is None:
curr.close()
raise Exception("ssvp: mysql: invalid server")
curr.close()
conn.close()
return {
"monthly_uptime": row[0],
"yearly_uptime": row[1],
"alltime_uptime": row[2],
"current_status": row[3]
}
return self._get_ups(srv=srv, conn=self._generate_connection())

def _generate_connection(self):
return mysql.connector.connect(user=self.login,
Expand All @@ -62,98 +43,13 @@ def _generate_connection(self):
database=self.db)

def _fetch_daily_data(self, srv: str) -> dict:
conn = self._generate_connection()
curr = conn.cursor()
sql = f"select logDate, serverStatus \
from {self.p}day_logs \
where logDate between (current_date() - interval 3 month) and current_date() and serverName = %s;"
curr.execute(sql, (srv,))
res = {}
for row in curr.fetchall():
res[row[0]] = row[1]
curr.close()
conn.close()
return res
return self._fdd(srv=srv, conn=self._generate_connection())

def handle_daily_record(self, srv: str, st: int) -> int:
conn = self._generate_connection()
curr = conn.cursor()
day = datetime.date.today()
sql = f"select exists( \
select serverName \
from {self.p}day_logs \
where serverName = %s \
and logDate = %s \
);"
curr.execute(sql, (srv, day))
rc_exists = curr.fetchone()[0]
sql = f"select max( \
select severity \
from {self.p}events \
where serverName = %s \
and endTime is not null \
);"
mx = None
try:
curr.execute(sql, (srv,))
mx = max(st, curr.fetchone()[0])
# mysql errors are internal\
# we can ignore the pep violation\
except:
mx = st
if not rc_exists:
sql = f"insert into {self.p}day_logs \
(logDate, serverName, serverStatus) values \
(%s, %s, %s);"
curr.execute(sql, (day, srv, mx))
else:
sql = f"update {self.p}day_logs \
set serverStatus = %s \
where logDate = %s \
and serverName = %s;"
curr.execute(sql, (mx, day, srv))
curr.fetchall()
conn.commit()
curr.close()
conn.close()
return mx
return self._hdr(srv=srv, st=st, conn=self._generate_connection())

def insert_interval_log(self, srv: str, status: int) -> None:
conn = self._generate_connection()
curr = conn.cursor()
sql = f"insert into {self.p}interval_logs \
(logDate, serverName, serverStatus) values \
(%s, %s, %s);"
curr.execute(sql, (datetime.datetime.now(), srv, status))
curr.fetchall()
conn.commit()
curr.close()
conn.close()
self._iil(srv=srv, status=status, conn=self._generate_connection())

def update_cached_stats(self, srv: str, st: int) -> None:
conn = self._generate_connection()
curr = conn.cursor()
sql = f"update {self.p}cached_stats \
set monthlyUptime = \
(select AVG(NOT serverStatus) \
from {self.p}interval_logs \
where logDate between \
(CURRENT_DATE() - interval 1 month) and CURRENT_DATE() \
and serverName = %s), \
yearlyUptime = \
(select AVG(NOT serverStatus) \
from {self.p}interval_logs \
where logDate between \
(CURRENT_DATE() - interval 1 year) and CURRENT_DATE() \
and serverName = %s), \
allTimeUptime = \
(select AVG(NOT serverStatus) \
from {self.p}interval_logs \
where serverName = %s), \
currentStatus = %s\
where serverName = %s;"
curr.execute(sql, (srv, srv, srv, st, srv))
curr.fetchall()
conn.commit()
curr.close()
conn.close()
self._ucs(srv=srv, st=st, conn=self._generate_connection())
36 changes: 36 additions & 0 deletions srv/sqliteh.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# ssvp: server statistics viewer project
# Copyright (C) 2023 Amy Parker <[email protected]>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA or visit the
# GNU Project at https://gnu.org/licenses. The GNU Affero General Public
# License version 3 is available at, for your convenience,
# https://www.gnu.org/licenses/agpl-3.0.en.html.

import dbhandle
import sqlite3

import datetime


class SQLite3Handler(dbhandle.DBAbstract):
def __init__(self, config: dict) -> None:
super().__init__(config=config)
self.filename = config["host"]
self.db = config["database"]
self.p = config["prefix"]


0 comments on commit 28595ac

Please sign in to comment.