aboutsummaryrefslogtreecommitdiffstats
path: root/bin/common/srtool_backup.py
diff options
context:
space:
mode:
Diffstat (limited to 'bin/common/srtool_backup.py')
-rwxr-xr-xbin/common/srtool_backup.py216
1 files changed, 208 insertions, 8 deletions
diff --git a/bin/common/srtool_backup.py b/bin/common/srtool_backup.py
index b37e2d08..f065e2f2 100755
--- a/bin/common/srtool_backup.py
+++ b/bin/common/srtool_backup.py
@@ -5,7 +5,7 @@
#
# Security Response Tool Commandline Tool
#
-# Copyright (C) 2018-2019 Wind River Systems
+# Copyright (C) 2018-2021 Wind River Systems
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
@@ -27,7 +27,6 @@
import os
import sys
import argparse
-import sqlite3
import json
from datetime import datetime, date
@@ -35,11 +34,17 @@ from datetime import datetime, date
dir_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
sys.path.insert(0, dir_path)
from common.srt_schema import ORM
+from common.srtool_sql import *
# Setup:
verbose = False
+force_update = False
srtDbName = 'srt.sqlite'
+BACKUP_DIR = 'backups'
+BACKUP_PREFIX = 'backup_'
+BACKUP_LOG_DIR = 'update_logs'
+BACKUP_LOG_PREFIX = 'backup_log_'
#################################
# Common routines
@@ -57,20 +62,35 @@ def _log(msg):
f1.close()
#################################
+# Set backup database stamp file
+#
+
+def backup_stamp(backup_dir):
+ if not os.path.isdir(backup_dir):
+ print("ERROR: no such directory '%s'" % backup_dir)
+ exit(1)
+ statinfo = os.stat(os.path.join(backup_dir, 'srt.sqlite'))
+ mod_timestamp = datetime.fromtimestamp(statinfo.st_mtime)
+ stamp_str = mod_timestamp.strftime('%Y-%m-%d %H:%M:%S | %A, %B %d %Y')
+ with open(os.path.join(backup_dir,'timestamp.txt'), 'w') as file:
+ file.write('%s\n' % stamp_str)
+ print("* Set Timestamp:%s" % mod_timestamp.strftime('%Y-%m-%d|%H:%M:%S|%A, %B %d %Y'))
+
+#################################
# Backup the database and data files
#
def backup_db(is_daily):
today = datetime.today()
weeknum = today.strftime("%W")
- weekday = today.isoweekday()
+ weekday = today.strftime("%A") #today.isoweekday()
year = today.strftime("%Y")
# Where are we backing up to
if is_daily:
- backup_dir = os.path.join(script_pathname, "backups/backup_%s" % (weekday))
+ backup_dir = os.path.join(script_pathname, "%s/%s%s" % (BACKUP_DIR,BACKUP_PREFIX,weekday))
else:
- backup_dir = os.path.join(script_pathname, "backups/backup_%s_%s" % (year,weeknum))
+ backup_dir = os.path.join(script_pathname, "%s/%s%s_%s" % (BACKUP_DIR,BACKUP_PREFIX,year,weeknum))
# Make sure directory exists
try:
os.makedirs(backup_dir)
@@ -82,36 +102,199 @@ def backup_db(is_daily):
print("*** Backup dir='%s' ***" % backup_dir)
print("* Copy database")
- cmd = 'cp %s %s' % (os.path.join(script_pathname,srtDbName),os.path.join(script_pathname,backup_dir))
+ cmd = 'cp -p %s %s' % (os.path.join(script_pathname,srtDbName),backup_dir)
print(cmd)
os.system(cmd)
# Copy data but skip cache dir (no deep copy)
print("* Copy data files")
- cmd = 'cp %s/data/* %s/data' % (script_pathname,os.path.join(script_pathname,backup_dir))
+ cmd = 'cp -p %s/data/* %s/data' % (script_pathname,backup_dir)
print(cmd)
os.system(cmd)
# Copy attachments
print("* Copy attachment files")
- cmd = 'cp -r %s/downloads %s' % (script_pathname,os.path.join(script_pathname,backup_dir))
+ cmd = 'cp -r -p %s/downloads %s' % (script_pathname,backup_dir)
print(cmd)
os.system(cmd)
+ # Set stamp file
+ backup_stamp(backup_dir)
+
+ # Additional remote backup directory copy
+ conn = SQL_CONNECT()
+ cur = conn.cursor()
+ sql = '''SELECT * FROM orm_srtsetting WHERE name=?'''
+ setting = SQL_EXECUTE(cur, sql, ('SRT_REMOTE_BACKUP_PATH',)).fetchone()
+ print("* Check for remote backup (%s) " % str(setting))
+ cur.close()
+ conn.close()
+ if setting and setting[ORM.SRTSETTING_VALUE].strip():
+ remote_backup_dir = setting[ORM.SRTSETTING_VALUE]
+ if is_daily:
+ remote_backup_dir = os.path.join(script_pathname, "%s/%s%s" % (remote_backup_dir,BACKUP_PREFIX,weekday))
+ else:
+ remote_backup_dir = os.path.join(script_pathname, "%s/%s%s_%s" % (remote_backup_dir,BACKUP_PREFIX,year,weeknum))
+
+ print("* Safety copy to remote location '%s'" % remote_backup_dir)
+ try:
+ os.makedirs(remote_backup_dir)
+ except:
+ # If exists, clean it out
+ os.system("rm -rf %s/*" % (remote_backup_dir))
+
+ # Is path a failure?
+ if not os.path.isdir(remote_backup_dir):
+ print("ERROR: no such remote backup path '%s'" % remote_backup_dir)
+ return(-1)
+
+ # Copy the backup directory to the remote location
+ cmd = 'cp -r -p %s %s' % (backup_dir,remote_backup_dir)
+ print(cmd)
+ os.system(cmd)
+
+ os.system('bash -c "echo \"BACKUP:`date`:%s\" >> backup_db.log"' % cmd)
+
+
+
+#######################################################################
+# backup_logs:
+#
+# Back up the logs to a daily wheel, and reset the logs
+# to empty for the next day.
+# If end of week, concatenate the respective daily logs into a
+# week-of-year log
+#
+
+def backup_logs():
+ today = datetime.today()
+ date_str = today.strftime("%Y/%m/%d")
+ weeknum = today.strftime("%W") # 00, 01, ... , 53
+ weekday = today.strftime("%A") # Sunday, Monday, ... , Saturday
+ weekday_num = today.strftime("%w") # 0, 1, ..., 6
+ year = today.strftime("%Y")
+ log_name_list = ('srt_web.log','srt_update.log','srt_dbg.log','update_logs/master_log.txt')
+
+ # Perform the daily back up
+ backup_day_dir = os.path.join(script_pathname, "%s/%s%s" % (BACKUP_LOG_DIR,BACKUP_LOG_PREFIX,weekday))
+ # Make sure directory exists
+ try:
+ os.makedirs(backup_day_dir)
+ except:
+ # If exists, clean it out
+ os.system("rm -rf %s/*" % (backup_day_dir))
+ pass
+ os.makedirs(os.path.join(backup_day_dir,'data'))
+
+ print("*** Backup dir[%s]='%s' ***" % (weekday_num,backup_day_dir))
+ print("* Copy logs")
+ for logname in log_name_list:
+ logname_base = os.path.basename(logname)
+ # Backup log file
+ cmd = 'echo "=== Backup: %s ===" > %s' % (date_str,os.path.join(backup_day_dir,logname_base))
+ print(cmd)
+ os.system(cmd)
+ cmd = 'cat %s | grep -v "/srtgui/mostrecentjobs?format=json" >> %s' % (os.path.join(script_pathname,logname),os.path.join(backup_day_dir,logname_base))
+ print(cmd)
+ os.system(cmd)
+ # Reset log file to empty
+ cmd = 'echo "" > %s' % (os.path.join(script_pathname,logname))
+ print(cmd)
+ os.system(cmd)
+
+ # If week's end, perform the weekly backup
+ if (6 == weekday) or force_update:
+ backup_week_dir = os.path.join(script_pathname, "%s/%s%s_%s" % (BACKUP_LOG_DIR,BACKUP_LOG_PREFIX,year,weeknum))
+ if not os.path.isdir(backup_week_dir):
+ os.makedirs(backup_week_dir)
+ day_names = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
+ concat = '>'
+ for weekday_num,weekday in enumerate(day_names):
+ backup_day_dir = os.path.join(script_pathname, "%s/%s%s" % (BACKUP_LOG_DIR,BACKUP_LOG_PREFIX,weekday))
+ if os.path.isdir(backup_day_dir):
+ # Concatinate the respective logs
+ for logname in log_name_list:
+ logname_base = os.path.basename(logname)
+ cmd = 'cat %s %s %s' % (os.path.join(backup_day_dir,logname_base),concat,os.path.join(backup_week_dir,logname_base))
+ print(cmd)
+ os.system(cmd)
+ concat = '>>'
+
+#######################################################################
+# list
+#
+
+def backup_list():
+ def sort_key(elem):
+ return elem[0]+elem[2]
+
+ stamps = []
+ for directory in os.listdir(os.path.join(script_pathname, 'backups')):
+ prefix = '1Week' if not directory[len(BACKUP_PREFIX)].isalpha() else '2Day'
+ directory = os.path.join(script_pathname, 'backups', directory)
+ with open(os.path.join(directory,'timestamp.txt'), 'r') as file:
+ line = file.read().strip()
+ #print("DIR=%s,%s" % (directory,line))
+ stamps.append([prefix, directory, line])
+
+ # Add the current database (now)
+ prefix = '3Now'
+ directory = script_pathname
+ statinfo = os.stat(os.path.join(directory, 'srt.sqlite'))
+ mod_timestamp = datetime.fromtimestamp(statinfo.st_mtime)
+ stamp_str = mod_timestamp.strftime('%Y-%m-%d %H:%M:%S | %A, %B %d %Y')
+ stamps.append([prefix, directory, stamp_str])
+
+ # Sort my time and return
+ stamps.sort(key=sort_key)
+ return stamps
+
+def list(db_list=False):
+ stamps = backup_list()
+ for stamp in stamps:
+ # Insert a separator between the date and the time
+ stamp[2] = stamp[2].replace(' ','|',1)
+ if db_list:
+ print("%s|%s|%s" % (stamp[0][1:],os.path.basename(stamp[1]),stamp[2].replace(' | ','|')))
+ else:
+ snap_date,snap_time,snap_day = stamp[2].split('|')
+ print("%-4s,%-16s,%s" % (stamp[0][1:],os.path.basename(stamp[1]),stamp[2].replace(' | ','|')))
+
+#################################
+# Init stamps
+#
+
+def init_stamps():
+ stamps = backup_list()
+ for stamp in stamps:
+ stamp_prefix, stamp_directory, stamp_line = stamp
+ backup_stamp(stamp_directory)
+
#################################
# main loop
#
+
def main(argv):
global verbose
global cmd_skip
global cmd_count
+ global force_update
# setup
parser = argparse.ArgumentParser(description='srtool_backup.py: backup the SRTool database')
parser.add_argument('--backup-db', '-b', action='store_const', const='backup', dest='command', help='Backup the database, save to year_weeknum dir')
parser.add_argument('--backup-db-daily', '-d', action='store_const', const='backup-daily', dest='command', help='Backup the database, save to weekday dir')
+ parser.add_argument('--backup-logs', '-B', action='store_const', const='backup_logs', dest='command', help='Backup the logs, save to year_weeknum and weekday dir')
+
+ parser.add_argument('--init-stamps', '-I', action='store_const', const='init-stamps', dest='command', help='Initialize the backup directory timestamps')
+ parser.add_argument('--init-dir-stamp', '-D', dest='init_dir_stamp', help='Initialize a specific backup directory timestamp')
+
+ parser.add_argument('--list-backups', '-l', action='store_const', const='list', dest='command', help='List the backup directory timestamps')
+ parser.add_argument('--list-backups-db', '-L', action='store_const', const='list-db', dest='command', help='Dump the backup directory timestamps')
+
parser.add_argument('--force', '-f', action='store_true', dest='force', help='Force the update')
+ parser.add_argument('--update-skip-history', '-H', action='store_true', dest='update_skip_history', help='Skip history updates')
parser.add_argument('--verbose', '-v', action='store_true', dest='verbose', help='Debugging: verbose output')
parser.add_argument('--skip', dest='skip', help='Debugging: skip record count')
parser.add_argument('--count', dest='count', help='Debugging: short run record count')
@@ -121,6 +304,7 @@ def main(argv):
master_log = open(os.path.join(script_pathname, "update_logs/master_log.txt"), "a")
verbose = args.verbose
+ force_update = args.force
cmd_skip = 0
if None != args.skip:
cmd_skip = int(args.skip)
@@ -136,6 +320,22 @@ def main(argv):
except Exception as e:
print ("DATABASE BACKUP FAILED ... %s" % e)
master_log.write("SRTOOL:%s:DATABASE BACKUP:\t\t\t\t...\t\t\tFAILED ... %s\n" % (date.today(), e))
+
+ elif 'backup_logs' == args.command:
+ try:
+ backup_logs()
+ except Exception as e:
+ print ("Log BACKUP FAILED ... %s" % e)
+ master_log.write("SRTOOL:%s:LOGS BACKUP:\t\t\t\t...\t\t\tFAILED ... %s\n" % (date.today(), e))
+ elif 'list' == args.command:
+ list()
+ elif 'list-db' == args.command:
+ list(True)
+ elif 'init-stamps' == args.command:
+ init_stamps()
+ elif args.init_dir_stamp:
+ backup_stamp(args.init_dir_stamp)
+
else:
print("Command not found")
master_log.close()