From 6bb891f830fc03714b98ee5d594aa11c8fa32303 Mon Sep 17 00:00:00 2001 From: Data-Monkey Date: Sat, 3 Jun 2023 21:42:04 +1000 Subject: [PATCH] added default DB fixed re-import of config file --- db/pialert.db | Bin 245760 -> 180224 bytes pialert/__main__.py | 11 +- pialert/conf.py | 6 +- pialert/const.py | 24 ++-- pialert/database.py | 259 ++++++++++++++++++++++-------------------- pialert/initialise.py | 28 +++-- 6 files changed, 181 insertions(+), 147 deletions(-) mode change 100755 => 100644 db/pialert.db diff --git a/db/pialert.db b/db/pialert.db old mode 100755 new mode 100644 index 50a882253f85487ce8647ac016428d647dc9f395..ff4e27315457b56f048e1ce792b7f6e37591bc93 GIT binary patch delta 4393 zcmeI0Yj6|S6@d5b>amh+uP_+d7Dg)>Y|AhF#DGH+BMVStWP=5vwBRcC8Wh`-D#->H zhS#b|(p)mS4$C@~6#AAIT3grIYDkrpCt5ySqZH z@T2aJ{;RytbI-l^+`H#|=UxvEa)X1W($>9AftbK|h9W)w7++19DFEsPo~IhV?4~HH zl$<5xq{;EKk<#kAZmN94pq5C0n)n2VftD(seP=utNlQ8R#VK}WL~E4 z(`V>a@KbP6UydLzeK-q$Hp%3}TKr&=*#>KH%@pH+Ed0_GvjtY;;VGt=2!Auhxan}F z^tuNBbr{x?qM2dX39A&*XH5*pHVS=#b|IRHUl{>6-DSqYIVd6;d&fz8{pTP9Pn-kZ z#_28jIe?fzutPZEX*}2_^a*Wy8eHx^AsCCA6?N@66p{*M_}y`^6QSJR zC*$CNG@NsubdipCoQLg3)N0gQoK6_>i#fA)Fp2fErF3PT7?`bPDr=qMuV+id&u4SB zCY`0(DW00i7FW-$H>IKH48)>*7gCpynN+Si(L1+M8qS3|n8(<Lp`!_{H>4hI(e z)f8>LrfH%7^+f(eg*B+PC21w8$Qsf~tC`d#ii>A_nz1YW19qprTK7;lrv07vh}NLF zz}V~Ha^6}?4 zm^b5}J}QIl+F>f2s;4qmr~fM5mv+Z=+W3WWpW(LQ74|OM#ya)Cr_O7?tKYBtn=Yiw z)LxTEw~M0s+|jkYZobMgLr7d0AZ8CoyJQ~{f@ zmvZPW_4V-jfUF+QKG}hY@2(`t8o^ab?l&@wdjT~xt(#Wo+Clf~e0({cQwiG{) z9YGm-i`@=Lp9E#tA8GS6w)i9d9)b9Hw8*v3-QaWc9&e-jATOa*(cqiC{8KHyC?Rz< zH#JG>-ey-rtJ_(P(sh6{>upLp^*`nkAe->ORrhDeH4mmWWeu?LM7zk z-;RQhMl8+}VH2!VRQ@4?0pGsP7;%pXbu`lBUx>sLbCacB&CpS#6EDuJ14I1Q%r}7v zAPwF=2F3XH80q8G7?jY6!57ECf$isrZgbMMoo5Zz>@egk@TWC~(Ke|bhs1x70$!yC<8+8_^6{5)x*CF(^HTk14PfLRE z4%|4&RD&@NVWZieB#@d$L$MQegS~0$Aqzo?FrPtbuwJaJIlU zH63898V;~U%?3JLw*U>Wc_}i`WwjEaZ0sA^H8RhJmBIdpHAMWw>7S4#LuZwO^#T>v zD^*ypl%4XiP05kUb-abvW!$H@`$>;1m_Q!Rf_PY?PV%gQWl54>d4_i^p5cv*)sQHW zB1AUk%Am#^*MuM1h%qL6G5K!GoqCeXKj!3QOj7i>xoqTswTqa_if>5#T z79?afBBg!Vo5+HM+@%$|WS?|j?j(`@5ez6beaO0qo9zyCbO^!3w{a~3<~YBKq#oLATe#}k|%sr+G&mXV}bT(WbOW-tG~TlAc;EJVN>X+vOrJt z)G3?M&@Dt_De|XcWfB@g$5V`J?FxkV31Pt>6FO4bCq{ciu|Q{_omi9{5dOG{$#SWt z$15CH8crE;D5a8YL&D2QRipDT%2g6xaU$X6EaJHf6J8CCveks7kwuM28m(0`l15o- zNNUKQ<9$3b#jI9sK;4pblOkQX2PK8t8)E-VNq{9!Z~cEY^*>lm6&t194*3toQaisy QQuwcSe)eTqD{cM$4Hw8WVgLXD literal 245760 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 KO;I(t2mU|(v>@gH diff --git a/pialert/__main__.py b/pialert/__main__.py index 341233a6..426bb320 100755 --- a/pialert/__main__.py +++ b/pialert/__main__.py @@ -13,10 +13,9 @@ #=============================================================================== # IMPORTS #=============================================================================== -from __future__ import print_function +#from __future__ import print_function import sys -from collections import namedtuple import time import datetime import multiprocessing @@ -25,7 +24,7 @@ import multiprocessing import conf from const import * from logger import mylog -from helper import filePermissions, isNewVersion, timeNow, timeNowTZ, updateState +from helper import filePermissions, isNewVersion, timeNow, updateState from api import update_api from networkscan import process_scan, scan_network from initialise import importConfigs @@ -75,6 +74,7 @@ main structure of Pi Alert """ def main (): + mylog('debug', ['[MAIN] Setting up ...']) conf.time_started = datetime.datetime.now() conf.cycle = "" @@ -109,7 +109,7 @@ def main (): # Open DB once and keep open # Opening / closing DB frequently actually casues more issues db = DB() # instance of class DB - db.openDB() + db.open() sql = db.sql # To-Do replace with the db class # Upgrade DB if needed @@ -119,6 +119,7 @@ def main (): #=============================================================================== # This is the main loop of Pi.Alert #=============================================================================== + mylog('debug', ['[Import Config TEST outside loop] lastImportedConfFile :', conf.lastImportedConfFile]) while True: @@ -128,6 +129,7 @@ def main (): mylog('debug', '[MAIN] Stating loop') # re-load user configuration and plugins + mylog('debug', ['[Import Config TEST inside loop] lastImportedConfFile :', conf.lastImportedConfFile]) importConfigs(db) # check if new version is available / only check once an hour @@ -311,4 +313,5 @@ def main (): # BEGIN #=============================================================================== if __name__ == '__main__': + mylog('debug', ['[__main__] Welcome to Pi.Alert']) sys.exit(main()) diff --git a/pialert/conf.py b/pialert/conf.py index d4062d91..e613a7ac 100644 --- a/pialert/conf.py +++ b/pialert/conf.py @@ -10,7 +10,11 @@ userSubnets = [] mySchedules = [] # bad solution for global - TO-DO plugins = [] # bad solution for global - TO-DO tz = '' -lastTimeImported = 0 # Time the config was last imported + +# modified time of the most recently imported config file +# set to a small value to force import at first run +lastImportedConfFile = 1.1 + plugins_once_run = False newVersionAvailable = False time_started = '' diff --git a/pialert/const.py b/pialert/const.py index f57aca39..d848a4d4 100644 --- a/pialert/const.py +++ b/pialert/const.py @@ -26,7 +26,11 @@ piholeDhcpleases = '/etc/pihole/dhcp.leases' #=============================================================================== # SQL queries #=============================================================================== -sql_devices_all = "select dev_MAC, dev_Name, dev_DeviceType, dev_Vendor, dev_Group, dev_FirstConnection, dev_LastConnection, dev_LastIP, dev_StaticIP, dev_PresentLastScan, dev_LastNotification, dev_NewDevice, dev_Network_Node_MAC_ADDR, dev_Network_Node_port, dev_Icon from Devices" +sql_devices_all = """select dev_MAC, dev_Name, dev_DeviceType, dev_Vendor, dev_Group, + dev_FirstConnection, dev_LastConnection, dev_LastIP, dev_StaticIP, + dev_PresentLastScan, dev_LastNotification, dev_NewDevice, + dev_Network_Node_MAC_ADDR, dev_Network_Node_port, + dev_Icon from Devices""" sql_devices_stats = "SELECT Online_Devices as online, Down_Devices as down, All_Devices as 'all', Archived_Devices as archived, (select count(*) from Devices a where dev_NewDevice = 1 ) as new, (select count(*) from Devices a where dev_Name = '(unknown)' or dev_Name = '(name not found)' ) as unknown from Online_History order by Scan_Date desc limit 1" sql_nmap_scan_all = "SELECT * FROM Nmap_Scan" sql_pholus_scan_all = "SELECT * FROM Pholus_Scan" @@ -36,12 +40,12 @@ sql_plugins_objects = "SELECT * FROM Plugins_Objects" sql_language_strings = "SELECT * FROM Plugins_Language_Strings" sql_plugins_events = "SELECT * FROM Plugins_Events" sql_plugins_history = "SELECT * FROM Plugins_History ORDER BY 'Index' DESC" -sql_new_devices = """SELECT * FROM ( SELECT eve_IP as dev_LastIP, eve_MAC as dev_MAC FROM Events_Devices - WHERE eve_PendingAlertEmail = 1 - AND eve_EventType = 'New Device' - ORDER BY eve_DateTime ) t1 - LEFT JOIN - ( - SELECT dev_Name, dev_MAC as dev_MAC_t2 FROM Devices - ) t2 - ON t1.dev_MAC = t2.dev_MAC_t2""" \ No newline at end of file +sql_new_devices = """SELECT * FROM ( + SELECT eve_IP as dev_LastIP, eve_MAC as dev_MAC + FROM Events_Devices + WHERE eve_PendingAlertEmail = 1 + AND eve_EventType = 'New Device' + ORDER BY eve_DateTime ) t1 + LEFT JOIN + ( SELECT dev_Name, dev_MAC as dev_MAC_t2 FROM Devices) t2 + ON t1.dev_MAC = t2.dev_MAC_t2""" \ No newline at end of file diff --git a/pialert/database.py b/pialert/database.py index e31be40c..bc7dd350 100644 --- a/pialert/database.py +++ b/pialert/database.py @@ -15,13 +15,17 @@ from helper import json_struc, initOrSetParam, row_to_json, timeNow #, updateSta class DB(): + """ + DB Class to provide the basic database interactions. + Open / Commit / Close / read / write + """ def __init__(self): self.sql = None self.sql_connection = None - - #------------------------------------------------------------------------------- - def openDB (self): + + #------------------------------------------------------------------------------- + def open (self): # Check if DB is open if self.sql_connection != None : mylog('debug','openDB: databse already open') @@ -44,13 +48,13 @@ class DB(): # Commit changes to DB self.sql_connection.commit() return True - + #------------------------------------------------------------------------------- - def get_sql_array(self, query): + def get_sql_array(self, query): if self.sql_connection == None : mylog('debug','getQueryArray: databse is not open') return - + self.sql.execute(query) rows = self.sql.fetchall() #self.commitDB() @@ -69,81 +73,88 @@ class DB(): # Cleanup / upkeep database #=============================================================================== def cleanup_database (self, startTime, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA): - # Header - #updateState(self,"Upkeep: Clean DB") - mylog('verbose', ['[', startTime, '] Upkeep Database:' ]) + """ + Cleaning out old records from the tables that don't need to keep all data. + """ + # Header + #updateState(self,"Upkeep: Clean DB") + mylog('verbose', ['[DB Cleanup] Upkeep Database:' ]) - # Cleanup Online History - mylog('verbose', [' Online_History: Delete all but keep latest 150 entries']) - self.sql.execute ("""DELETE from Online_History where "Index" not in ( SELECT "Index" from Online_History order by Scan_Date desc limit 150)""") + # Cleanup Online History + mylog('verbose', ['[DB Cleanup] Online_History: Delete all but keep latest 150 entries']) + self.sql.execute ("""DELETE from Online_History where "Index" not in ( + SELECT "Index" from Online_History + order by Scan_Date desc limit 150)""") + mylog('verbose', ['[DB Cleanup] Optimize Database']) + # Cleanup Events + mylog('verbose', ['[DB Cleanup] Events: Delete all older than '+str(DAYS_TO_KEEP_EVENTS)+' days']) + self.sql.execute ("""DELETE FROM Events + WHERE eve_DateTime <= date('now', '-"+str(DAYS_TO_KEEP_EVENTS)+" day')""") + # Cleanup Plugin Events History + mylog('verbose', ['[DB Cleanup] Plugin Events History: Delete all older than '+str(DAYS_TO_KEEP_EVENTS)+' days']) + self.sql.execute ("""DELETE FROM Plugins_History + WHERE DateTimeChanged <= date('now', '-"+str(DAYS_TO_KEEP_EVENTS)+" day')""") + # Cleanup Pholus_Scan + if PHOLUS_DAYS_DATA != 0: + mylog('verbose', ['[DB Cleanup] Pholus_Scan: Delete all older than ' + str(PHOLUS_DAYS_DATA) + ' days']) + # improvement possibility: keep at least N per mac + self.sql.execute ("""DELETE FROM Pholus_Scan + WHERE Time <= date('now', '-"+ str(PHOLUS_DAYS_DATA) +" day')""") - mylog('verbose', [' Optimize Database']) - # Cleanup Events - mylog('verbose', [' Events: Delete all older than '+str(DAYS_TO_KEEP_EVENTS)+' days']) - self.sql.execute ("DELETE FROM Events WHERE eve_DateTime <= date('now', '-"+str(DAYS_TO_KEEP_EVENTS)+" day')") + # De-Dupe (de-duplicate - remove duplicate entries) from the Pholus_Scan table + mylog('verbose', ['[DB Cleanup] Pholus_Scan: Delete all duplicates']) + self.sql.execute ("""DELETE FROM Pholus_Scan + WHERE rowid > ( + SELECT MIN(rowid) FROM Pholus_Scan p2 + WHERE Pholus_Scan.MAC = p2.MAC + AND Pholus_Scan.Value = p2.Value + AND Pholus_Scan.Record_Type = p2.Record_Type + );""") + # De-Dupe (de-duplicate - remove duplicate entries) from the Nmap_Scan table + mylog('verbose', [' Nmap_Scan: Delete all duplicates']) + self.sql.execute ("""DELETE FROM Nmap_Scan + WHERE rowid > ( + SELECT MIN(rowid) FROM Nmap_Scan p2 + WHERE Nmap_Scan.MAC = p2.MAC + AND Nmap_Scan.Port = p2.Port + AND Nmap_Scan.State = p2.State + AND Nmap_Scan.Service = p2.Service + );""") - # Cleanup Plugin Events History - mylog('verbose', [' Plugin Events History: Delete all older than '+str(DAYS_TO_KEEP_EVENTS)+' days']) - self.sql.execute ("DELETE FROM Plugins_History WHERE DateTimeChanged <= date('now', '-"+str(DAYS_TO_KEEP_EVENTS)+" day')") - - # Cleanup Pholus_Scan - if PHOLUS_DAYS_DATA != 0: - mylog('verbose', [' Pholus_Scan: Delete all older than ' + str(PHOLUS_DAYS_DATA) + ' days']) - self.sql.execute ("DELETE FROM Pholus_Scan WHERE Time <= date('now', '-"+ str(PHOLUS_DAYS_DATA) +" day')") # improvement possibility: keep at least N per mac - - # De-Dupe (de-duplicate - remove duplicate entries) from the Pholus_Scan table - mylog('verbose', [' Pholus_Scan: Delete all duplicates']) - self.sql.execute ("""DELETE FROM Pholus_Scan - WHERE rowid > ( - SELECT MIN(rowid) FROM Pholus_Scan p2 - WHERE Pholus_Scan.MAC = p2.MAC - AND Pholus_Scan.Value = p2.Value - AND Pholus_Scan.Record_Type = p2.Record_Type - );""") - - # De-Dupe (de-duplicate - remove duplicate entries) from the Nmap_Scan table - mylog('verbose', [' Nmap_Scan: Delete all duplicates']) - self.sql.execute ("""DELETE FROM Nmap_Scan - WHERE rowid > ( - SELECT MIN(rowid) FROM Nmap_Scan p2 - WHERE Nmap_Scan.MAC = p2.MAC - AND Nmap_Scan.Port = p2.Port - AND Nmap_Scan.State = p2.State - AND Nmap_Scan.Service = p2.Service - );""") - - # Shrink DB - mylog('verbose', [' Shrink Database']) - self.sql.execute ("VACUUM;") - - self.commitDB() + # Shrink DB + mylog('verbose', [' Shrink Database']) + self.sql.execute ("VACUUM;") + self.commitDB() #------------------------------------------------------------------------------- def upgradeDB(self): - sql = self.sql #TO-DO + """ + Check the current tables in the DB and upgrade them if neccessary + """ + sql = self.sql #TO-DO - # indicates, if Online_History table is available + # indicates, if Online_History table is available onlineHistoryAvailable = sql.execute(""" SELECT name FROM sqlite_master WHERE type='table' - AND name='Online_History'; + AND name='Online_History'; """).fetchall() != [] # Check if it is incompatible (Check if table has all required columns) isIncompatible = False - + if onlineHistoryAvailable : isIncompatible = sql.execute (""" SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Online_History') WHERE name='Archived_Devices' """).fetchone()[0] == 0 - + # Drop table if available, but incompatible - if onlineHistoryAvailable and isIncompatible: + if onlineHistoryAvailable and isIncompatible: mylog('none','[upgradeDB] Table is incompatible, Dropping the Online_History table') sql.execute("DROP TABLE Online_History;") onlineHistoryAvailable = False if onlineHistoryAvailable == False : - sql.execute(""" + sql.execute(""" CREATE TABLE "Online_History" ( "Index" INTEGER, "Scan_Date" TEXT, @@ -152,7 +163,7 @@ class DB(): "All_Devices" INTEGER, "Archived_Devices" INTEGER, PRIMARY KEY("Index" AUTOINCREMENT) - ); + ); """) # Alter Devices table @@ -162,9 +173,9 @@ class DB(): """).fetchone()[0] == 0 if dev_Network_Node_MAC_ADDR_missing : - mylog('verbose', ["[upgradeDB] Adding dev_Network_Node_MAC_ADDR to the Devices table"]) - sql.execute(""" - ALTER TABLE "Devices" ADD "dev_Network_Node_MAC_ADDR" TEXT + mylog('verbose', ["[upgradeDB] Adding dev_Network_Node_MAC_ADDR to the Devices table"]) + sql.execute(""" + ALTER TABLE "Devices" ADD "dev_Network_Node_MAC_ADDR" TEXT """) # dev_Network_Node_port column @@ -173,9 +184,9 @@ class DB(): """).fetchone()[0] == 0 if dev_Network_Node_port_missing : - mylog('verbose', ["[upgradeDB] Adding dev_Network_Node_port to the Devices table"]) - sql.execute(""" - ALTER TABLE "Devices" ADD "dev_Network_Node_port" INTEGER + mylog('verbose', ["[upgradeDB] Adding dev_Network_Node_port to the Devices table"]) + sql.execute(""" + ALTER TABLE "Devices" ADD "dev_Network_Node_port" INTEGER """) # dev_Icon column @@ -184,52 +195,52 @@ class DB(): """).fetchone()[0] == 0 if dev_Icon_missing : - mylog('verbose', ["[upgradeDB] Adding dev_Icon to the Devices table"]) - sql.execute(""" - ALTER TABLE "Devices" ADD "dev_Icon" TEXT + mylog('verbose', ["[upgradeDB] Adding dev_Icon to the Devices table"]) + sql.execute(""" + ALTER TABLE "Devices" ADD "dev_Icon" TEXT """) - # indicates, if Settings table is available + # indicates, if Settings table is available settingsMissing = sql.execute(""" SELECT name FROM sqlite_master WHERE type='table' - AND name='Settings'; + AND name='Settings'; """).fetchone() == None - # Re-creating Settings table + # Re-creating Settings table mylog('verbose', ["[upgradeDB] Re-creating Settings table"]) - if settingsMissing == False: - sql.execute("DROP TABLE Settings;") + if settingsMissing == False: + sql.execute("DROP TABLE Settings;") - sql.execute(""" - CREATE TABLE "Settings" ( + sql.execute(""" + CREATE TABLE "Settings" ( "Code_Name" TEXT, "Display_Name" TEXT, - "Description" TEXT, + "Description" TEXT, "Type" TEXT, "Options" TEXT, "RegEx" TEXT, "Value" TEXT, "Group" TEXT, "Events" TEXT - ); + ); """) - # indicates, if Pholus_Scan table is available + # indicates, if Pholus_Scan table is available pholusScanMissing = sql.execute(""" SELECT name FROM sqlite_master WHERE type='table' - AND name='Pholus_Scan'; + AND name='Pholus_Scan'; """).fetchone() == None # if pholusScanMissing == False: - # # Re-creating Pholus_Scan table - # sql.execute("DROP TABLE Pholus_Scan;") - # pholusScanMissing = True + # # Re-creating Pholus_Scan table + # sql.execute("DROP TABLE Pholus_Scan;") + # pholusScanMissing = True if pholusScanMissing: mylog('verbose', ["[upgradeDB] Re-creating Pholus_Scan table"]) - sql.execute(""" - CREATE TABLE "Pholus_Scan" ( + sql.execute(""" + CREATE TABLE "Pholus_Scan" ( "Index" INTEGER, "Info" TEXT, "Time" TEXT, @@ -239,47 +250,47 @@ class DB(): "Value" TEXT, "Extra" TEXT, PRIMARY KEY("Index" AUTOINCREMENT) - ); + ); """) - # indicates, if Nmap_Scan table is available + # indicates, if Nmap_Scan table is available nmapScanMissing = sql.execute(""" SELECT name FROM sqlite_master WHERE type='table' - AND name='Nmap_Scan'; + AND name='Nmap_Scan'; """).fetchone() == None # Re-creating Parameters table mylog('verbose', ["[upgradeDB] Re-creating Parameters table"]) sql.execute("DROP TABLE Parameters;") - sql.execute(""" + sql.execute(""" CREATE TABLE "Parameters" ( "par_ID" TEXT PRIMARY KEY, "par_Value" TEXT - ); + ); """) # Initialize Parameters if unavailable initOrSetParam(self, 'Back_App_State','Initializing') # if nmapScanMissing == False: - # # Re-creating Nmap_Scan table - # sql.execute("DROP TABLE Nmap_Scan;") - # nmapScanMissing = True + # # Re-creating Nmap_Scan table + # sql.execute("DROP TABLE Nmap_Scan;") + # nmapScanMissing = True if nmapScanMissing: mylog('verbose', ["[upgradeDB] Re-creating Nmap_Scan table"]) - sql.execute(""" - CREATE TABLE "Nmap_Scan" ( + sql.execute(""" + CREATE TABLE "Nmap_Scan" ( "Index" INTEGER, "MAC" TEXT, "Port" TEXT, - "Time" TEXT, + "Time" TEXT, "State" TEXT, - "Service" TEXT, + "Service" TEXT, "Extra" TEXT, PRIMARY KEY("Index" AUTOINCREMENT) - ); + ); """) # Plugin state @@ -288,13 +299,13 @@ class DB(): Plugin TEXT NOT NULL, Object_PrimaryID TEXT NOT NULL, Object_SecondaryID TEXT NOT NULL, - DateTimeCreated TEXT NOT NULL, - DateTimeChanged TEXT NOT NULL, + DateTimeCreated TEXT NOT NULL, + DateTimeChanged TEXT NOT NULL, Watched_Value1 TEXT NOT NULL, Watched_Value2 TEXT NOT NULL, Watched_Value3 TEXT NOT NULL, Watched_Value4 TEXT NOT NULL, - Status TEXT NOT NULL, + Status TEXT NOT NULL, Extra TEXT NOT NULL, UserData TEXT NOT NULL, ForeignKey TEXT NOT NULL, @@ -308,13 +319,13 @@ class DB(): Plugin TEXT NOT NULL, Object_PrimaryID TEXT NOT NULL, Object_SecondaryID TEXT NOT NULL, - DateTimeCreated TEXT NOT NULL, - DateTimeChanged TEXT NOT NULL, + DateTimeCreated TEXT NOT NULL, + DateTimeChanged TEXT NOT NULL, Watched_Value1 TEXT NOT NULL, Watched_Value2 TEXT NOT NULL, Watched_Value3 TEXT NOT NULL, Watched_Value4 TEXT NOT NULL, - Status TEXT NOT NULL, + Status TEXT NOT NULL, Extra TEXT NOT NULL, UserData TEXT NOT NULL, ForeignKey TEXT NOT NULL, @@ -328,40 +339,40 @@ class DB(): Plugin TEXT NOT NULL, Object_PrimaryID TEXT NOT NULL, Object_SecondaryID TEXT NOT NULL, - DateTimeCreated TEXT NOT NULL, - DateTimeChanged TEXT NOT NULL, + DateTimeCreated TEXT NOT NULL, + DateTimeChanged TEXT NOT NULL, Watched_Value1 TEXT NOT NULL, Watched_Value2 TEXT NOT NULL, Watched_Value3 TEXT NOT NULL, Watched_Value4 TEXT NOT NULL, - Status TEXT NOT NULL, + Status TEXT NOT NULL, Extra TEXT NOT NULL, UserData TEXT NOT NULL, ForeignKey TEXT NOT NULL, PRIMARY KEY("Index" AUTOINCREMENT) - ); """ + ); """ sql.execute(sql_Plugins_History) # Dynamically generated language strings - # indicates, if Language_Strings table is available + # indicates, if Language_Strings table is available languageStringsMissing = sql.execute(""" SELECT name FROM sqlite_master WHERE type='table' - AND name='Plugins_Language_Strings'; + AND name='Plugins_Language_Strings'; """).fetchone() == None - + if languageStringsMissing == False: - sql.execute("DROP TABLE Plugins_Language_Strings;") + sql.execute("DROP TABLE Plugins_Language_Strings;") sql.execute(""" CREATE TABLE IF NOT EXISTS Plugins_Language_Strings( "Index" INTEGER, Language_Code TEXT NOT NULL, String_Key TEXT NOT NULL, String_Value TEXT NOT NULL, - Extra TEXT NOT NULL, + Extra TEXT NOT NULL, PRIMARY KEY("Index" AUTOINCREMENT) - ); """) - - self.commitDB() + ); """) + + self.commitDB() #------------------------------------------------------------------------------- @@ -369,15 +380,15 @@ class DB(): mylog('debug',[ '[Database] - get_table_as_json - Query: ', sqlQuery]) try: - self.sql.execute(sqlQuery) - columnNames = list(map(lambda x: x[0], self.sql.description)) - rows = self.sql.fetchall() + self.sql.execute(sqlQuery) + columnNames = list(map(lambda x: x[0], self.sql.description)) + rows = self.sql.fetchall() except sqlite3.Error as e: mylog('none',[ '[Database] - SQL ERROR: ', e]) return None - + result = {"data":[]} - for row in rows: + for row in rows: tmp = row_to_json(columnNames, row) result["data"].append(tmp) @@ -386,7 +397,7 @@ class DB(): #------------------------------------------------------------------------------- # referece from here: https://codereview.stackexchange.com/questions/241043/interface-class-for-sqlite-databases - #------------------------------------------------------------------------------- + #------------------------------------------------------------------------------- def read(self, query, *args): """check the query and arguments are aligned and are read only""" mylog('debug',[ '[Database] - SELECT Query: ', query, " params: ", args]) @@ -408,7 +419,7 @@ def get_device_stats(db): # columns = ["online","down","all","archived","new","unknown"] return db.read(sql_devices_stats) #------------------------------------------------------------------------------- -def get_all_devices(db): +def get_all_devices(db): return db.read(sql_devices_all) #------------------------------------------------------------------------------- @@ -418,7 +429,7 @@ def insertOnlineHistory(db, cycle): sql = db.sql #TO-DO startTime = timeNow() # Add to History - + History_All = db.read("SELECT * FROM Devices") History_All_Devices = len(History_All) @@ -428,7 +439,7 @@ def insertOnlineHistory(db, cycle): History_Online = db.read("SELECT * FROM CurrentScan WHERE cur_ScanCycle = ? ", cycle) History_Online_Devices = len(History_Online) History_Offline_Devices = History_All_Devices - History_Archived_Devices - History_Online_Devices - + sql.execute ("INSERT INTO Online_History (Scan_Date, Online_Devices, Down_Devices, All_Devices, Archived_Devices) "+ "VALUES ( ?, ?, ?, ?, ?)", (startTime, History_Online_Devices, History_Offline_Devices, History_All_Devices, History_Archived_Devices ) ) db.commitDB() \ No newline at end of file diff --git a/pialert/initialise.py b/pialert/initialise.py index 38a6dd5b..61f12078 100644 --- a/pialert/initialise.py +++ b/pialert/initialise.py @@ -7,8 +7,8 @@ from pathlib import Path import datetime import conf -from const import * -from helper import collect_lang_strings, timeNow, updateSubnets, initOrSetParam +from const import fullConfPath +from helper import collect_lang_strings, updateSubnets, initOrSetParam from logger import mylog from api import update_api from scheduler import schedule_class @@ -43,15 +43,26 @@ def importConfigs (db): sql = db.sql - lastTimeImported = 0 - - # get config file + # get config file name config_file = Path(fullConfPath) - # Skip import if last time of import is NEWER than file age - if (os.path.getmtime(config_file) < lastTimeImported) : + # Only import file if the file was modifed since last import. + # this avoids time zone issues as we just compare the previous timestamp to the current time stamp + mylog('debug', ['[Import Config] checking config file ']) + mylog('debug', ['[Import Config] lastImportedConfFile :', conf.lastImportedConfFile]) + mylog('debug', ['[Import Config] file modified time :', os.path.getmtime(config_file)]) + + + if (os.path.getmtime(config_file) == conf.lastImportedConfFile) : + mylog('debug', ['[Import Config] skipping config file import']) return - + + conf.lastImportedConfFile = os.path.getmtime(config_file) + + + + + mylog('debug', ['[Import Config] importing config file']) conf.mySettings = [] # reset settings conf.mySettingsSQLsafe = [] # same as above but safe to be passed into a SQL query @@ -237,6 +248,7 @@ def read_config_file(filename): """ retuns dict on the config file key:value pairs """ + mylog('info', '[Config] reading config file') # load the variables from pialert.conf code = compile(filename.read_text(), filename.name, "exec") confDict = {} # config dictionary