diff --git a/src/opnsense/scripts/netflow/flowd_aggregate.py b/src/opnsense/scripts/netflow/flowd_aggregate.py index de090d0e1..9e0c31f11 100755 --- a/src/opnsense/scripts/netflow/flowd_aggregate.py +++ b/src/opnsense/scripts/netflow/flowd_aggregate.py @@ -30,6 +30,7 @@ import time import os import sys +import fcntl import signal import glob import copy @@ -190,6 +191,17 @@ if len(sys.argv) > 1 and 'console' in sys.argv[1:]: print s.getvalue() else: Main() +elif len(sys.argv) > 1 and 'repair' in sys.argv[1:]: + # force a database repair, when + try: + lck = open('/var/run/flowd_aggregate.pid', 'a+') + fcntl.flock(lck, fcntl.LOCK_EX | fcntl.LOCK_NB) + check_and_repair(filename_mask='/var/netflow/*.sqlite', force_repair=True) + lck.close() + os.remove('/var/run/flowd_aggregate.pid') + except IOError: + # already running, exit status 99 + sys.exit(99) else: # Daemonize flowd aggregator daemon = Daemonize(app="flowd_aggregate", pid='/var/run/flowd_aggregate.pid', action=Main) diff --git a/src/opnsense/service/conf/actions.d/actions_netflow.conf b/src/opnsense/service/conf/actions.d/actions_netflow.conf index d16bc6eb1..23de1f5ff 100644 --- a/src/opnsense/service/conf/actions.d/actions_netflow.conf +++ b/src/opnsense/service/conf/actions.d/actions_netflow.conf @@ -58,6 +58,12 @@ command:/usr/local/etc/rc.d/flowd_aggregate start type:script message:start netflow data aggregator +[aggregate.repair] +command:/usr/local/opnsense/scripts/netflow/flowd_aggregate.py repair && /usr/local/etc/rc.d/flowd_aggregate start +parameters: +type:script +message:force database repair + [aggregate.restart] command:/usr/local/etc/rc.d/flowd_aggregate restart type:script diff --git a/src/opnsense/site-python/sqlite3_helper.py b/src/opnsense/site-python/sqlite3_helper.py index bd1811e6b..bb276d4cb 100644 --- a/src/opnsense/site-python/sqlite3_helper.py +++ b/src/opnsense/site-python/sqlite3_helper.py @@ -32,7 +32,7 @@ import sqlite3 import syslog import os -def check_and_repair(filename_mask): +def check_and_repair(filename_mask, force_repair=False): """ check and repair sqlite databases :param filename_mask: filenames (glob pattern) :return: None @@ -54,10 +54,12 @@ def check_and_repair(filename_mask): # force a repair when corrupted, using a dump / import if cur is not None: try: + if force_repair: + raise sqlite3.DatabaseError("Requested forced repair") cur.execute('pragma integrity_check') cur.execute('analyze') except sqlite3.DatabaseError, e: - if e.message.find('malformed') > -1: + if e.message.find('malformed') > -1 or force_repair: syslog.syslog(syslog.LOG_ERR, "sqlite3 repair %s" % filename) filename_tmp = '%s.fix'%filename filename_sql = '%s.sql'%filename diff --git a/src/www/reporting_settings.php b/src/www/reporting_settings.php index 52b1615b0..bebfeead5 100644 --- a/src/www/reporting_settings.php +++ b/src/www/reporting_settings.php @@ -51,6 +51,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { } elseif (!empty($pconfig['action']) && $pconfig['action'] == "flush_netflow") { $savemsg = gettext('All local netflow data has been cleared.'); configd_run("netflow flush"); + } elseif (!empty($pconfig['action']) && $pconfig['action'] == "repair_netflow") { + $savemsg = gettext('Database repair in progress, daemon will start when done.'); + configd_run("netflow aggregate stop"); + configd_run("netflow aggregate repair", true); } else { $rrdcfg['enable'] = !empty($pconfig['rrdenable']); $savemsg = get_std_save_message(); @@ -116,6 +120,26 @@ $(document).ready(function() { }] }); }); + $("#repair_netflow").click(function(event){ + event.preventDefault(); + BootstrapDialog.show({ + type:BootstrapDialog.TYPE_DANGER, + title: "", + message: "", + buttons: [{ + label: "", + action: function(dialogRef) { + dialogRef.close(); + }}, { + label: "", + action: function(dialogRef) { + $("#action").val("repair_netflow"); + $("#iform").submit() + } + }] + }); + }); + $(".act_flush").click(function(event){ var filename = $(this).data('id'); event.preventDefault(); @@ -173,6 +197,7 @@ $(document).ready(function() { " /> " /> " /> + " />