Sort out DB params access for mailstats, remove DB config from SM2
This commit is contained in:
@@ -454,23 +454,28 @@ def create_graph(data_dict, graph_type="line", output_file="graph.png",iso_date=
|
||||
# return data
|
||||
|
||||
def save_summaries_to_db(cursor, conn, date_str, hour, parsed_data):
|
||||
# Convert parsed_data to JSON string
|
||||
global count_records_to_db
|
||||
json_data = json.dumps(parsed_data)
|
||||
|
||||
# Insert the record
|
||||
insert_query = """
|
||||
INSERT INTO SummaryLogs (Date, Hour, logData)
|
||||
VALUES (%s, %s, %s)
|
||||
"""
|
||||
|
||||
try:
|
||||
# Check if the cursor is open (pymysql has no explicit is_closed; handle by try/except)
|
||||
cursor.execute(insert_query, (date_str, hour, json_data))
|
||||
conn.commit()
|
||||
count_records_to_db += 1
|
||||
except pymysql.Error as err:
|
||||
# Handle cursor closed or other DB errors
|
||||
if 'closed' in str(err).lower():
|
||||
logging.error(f"DB Error {date_str} {hour} : Cursor is closed. Check connection handling.")
|
||||
else:
|
||||
logging.error(f"DB Error {date_str} {hour} : {err}")
|
||||
conn.rollback()
|
||||
except Exception as ex:
|
||||
logging.error(f"Unexpected DB Error {date_str} {hour} : {ex}")
|
||||
conn.rollback()
|
||||
|
||||
|
||||
def is_running_under_thonny():
|
||||
# Check for the 'THONNY_USER_DIR' environment variable
|
||||
@@ -1251,6 +1256,41 @@ def format_duration(seconds: float) -> str:
|
||||
return str(timedelta(seconds=seconds))
|
||||
|
||||
|
||||
DB_CONFIG_PATH = '/etc/mailstats/db.php'
|
||||
|
||||
def parse_php_config(path):
|
||||
# Read file as text and extract key-value pairs using regex
|
||||
try:
|
||||
with open(path, 'r') as f:
|
||||
content = f.read()
|
||||
cfg = {}
|
||||
for match in re.finditer(r"'(\w+)'\s*=>\s*'([^']*)'", content):
|
||||
cfg[match.group(1)] = match.group(2)
|
||||
return cfg
|
||||
except Exception as e:
|
||||
logging.error(f"Could not parse PHP config file: {e}")
|
||||
return {}
|
||||
|
||||
def load_db_config():
|
||||
db_host = os.environ.get('MAILSTATS_DB_HOST', 'localhost')
|
||||
db_user = os.environ.get('MAILSTATS_DB_USER', '')
|
||||
db_pass = os.environ.get('MAILSTATS_DB_PASS', '')
|
||||
db_name = os.environ.get('MAILSTATS_DB_NAME', '')
|
||||
|
||||
if db_user == '' or db_pass == '' or db_name == '':
|
||||
if os.path.isfile(DB_CONFIG_PATH) and os.access(DB_CONFIG_PATH, os.R_OK):
|
||||
cfg = parse_php_config(DB_CONFIG_PATH)
|
||||
db_host = cfg.get('host', db_host)
|
||||
db_user = cfg.get('user', db_user)
|
||||
db_pass = cfg.get('pass', db_pass)
|
||||
db_name = cfg.get('name', db_name)
|
||||
|
||||
if db_user == '' or db_pass == '' or db_name == '':
|
||||
logging.error('DB credentials missing (env and config file).')
|
||||
raise RuntimeError('DB credentials missing (env and config file)')
|
||||
|
||||
return db_host, db_user, db_pass, db_name
|
||||
|
||||
if __name__ == "__main__":
|
||||
start_time = datetime.now()
|
||||
try:
|
||||
@@ -1336,16 +1376,15 @@ if __name__ == "__main__":
|
||||
# Db save control
|
||||
saveData = get_value(ConfigDB,"mailstats","SaveDataToMySQL","no") == 'yes' or forceDbSave
|
||||
logging.debug(f"Save Mailstats to DB set:{saveData} ")
|
||||
|
||||
if saveData:
|
||||
# Connect to MySQL DB for saving
|
||||
DBName = "mailstats"
|
||||
DBHost = get_value(ConfigDB, 'mailstats', 'DBHost', "localhost")
|
||||
DBPort = int(get_value(ConfigDB, 'mailstats', 'DBPort', "3306")) # Ensure port is an integer
|
||||
DBPassw = 'mailstats'
|
||||
DBUser = 'mailstats'
|
||||
# Database config retrieval
|
||||
try:
|
||||
DBHost, DBUser, DBPassw, DBName = load_db_config()
|
||||
DBPort = 3306 # If you want configurability, load this from config too
|
||||
UnixSocket = "/var/lib/mysql/mysql.sock"
|
||||
|
||||
except RuntimeError as err:
|
||||
logging.error(f"Database config error: {err}")
|
||||
saveData = False
|
||||
# Try to establish a database connection
|
||||
try:
|
||||
conn = pymysql.connect(
|
||||
@@ -1355,7 +1394,7 @@ if __name__ == "__main__":
|
||||
database=DBName,
|
||||
port=DBPort,
|
||||
unix_socket=UnixSocket,
|
||||
cursorclass=pymysql.cursors.DictCursor # Optional: use DictCursor for dict output
|
||||
cursorclass=pymysql.cursors.DictCursor
|
||||
)
|
||||
cursor = conn.cursor()
|
||||
# Check if the table exists before creating it
|
||||
@@ -1363,7 +1402,6 @@ if __name__ == "__main__":
|
||||
cursor.execute(check_table_query)
|
||||
table_exists = cursor.fetchone()
|
||||
if not table_exists:
|
||||
# Create table if it doesn't exist
|
||||
cursor.execute("""
|
||||
CREATE TABLE IF NOT EXISTS SummaryLogs (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
@@ -1372,22 +1410,26 @@ if __name__ == "__main__":
|
||||
logData TEXT
|
||||
)
|
||||
""")
|
||||
|
||||
# Delete existing records for the given date
|
||||
try:
|
||||
delete_query = """
|
||||
DELETE FROM SummaryLogs
|
||||
WHERE Date = %s
|
||||
"""
|
||||
cursor.execute(delete_query, (analysis_date,)) # Don't forget the extra comma for tuple
|
||||
# Get the number of records deleted
|
||||
cursor.execute(delete_query, (analysis_date,))
|
||||
rows_deleted = cursor.rowcount
|
||||
if rows_deleted > 0:
|
||||
logging.debug(f"Deleted {rows_deleted} rows for {analysis_date} ")
|
||||
logging.debug(f"Deleted {rows_deleted} rows for {analysis_date}")
|
||||
except pymysql.Error as e:
|
||||
logging.error(f"SQL Delete failed ({delete_query}) ({e}) ")
|
||||
logging.error(f"SQL Delete failed ({delete_query}) ({e})")
|
||||
|
||||
# Commit changes & close resources after all DB operations
|
||||
conn.commit()
|
||||
#cursor.close()
|
||||
#conn.close()
|
||||
except pymysql.Error as e:
|
||||
logging.error(f"Unable to connect to {DBName} on {DBHost} port {DBPort} error ({e}) ")
|
||||
logging.error(f"Unable to connect to {DBName} on {DBHost} port {DBPort} error ({e})")
|
||||
saveData = False
|
||||
|
||||
nolinks = not saveData
|
||||
|
@@ -77,7 +77,7 @@
|
||||
|
||||
<div class=dbwanted>
|
||||
|
||||
|
||||
<!--
|
||||
<h2 class='subh2'><%=l('mst_Details_for_connection_to_database')%></h2>
|
||||
|
||||
<p><span class=label>
|
||||
@@ -108,7 +108,7 @@
|
||||
% param 'DBPassword' => $mst_data->{DBPassword} unless param 'DBPassword';
|
||||
%=password_field 'DBPassword', class => 'pass13 sme-password', autocomplete => 'off'
|
||||
</span></p>
|
||||
|
||||
-->
|
||||
|
||||
</div>
|
||||
|
||||
|
@@ -92,6 +92,8 @@ usermod -aG systemd-journal www
|
||||
%changelog
|
||||
* Thu Sep 04 2025 Brian Read <brianr@koozali.org> 11.1-6.sme
|
||||
- Add favicon to mailstats table, summary and detailed pages [SME: 13121]
|
||||
- Bring DB config reading for mailstats itself inline with php summary and detailed logs - using /etc/mailstats/db.php
|
||||
- Remove DB config fields from the SM2 config panel
|
||||
|
||||
* Tue Sep 02 2025 Brian Read <brianr@koozali.org> 11.1-5.sme
|
||||
- Speed up Journal access [SME: 13121]
|
||||
|
Reference in New Issue
Block a user