-
Notifications
You must be signed in to change notification settings - Fork 0
/
lib_autobk.py
executable file
·114 lines (100 loc) · 3.76 KB
/
lib_autobk.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/local/bin/python3
import logging as mLog
from logging import Formatter, FileHandler
from logging.handlers import RotatingFileHandler
from configparser import RawConfigParser
from subprocess import Popen, PIPE
from datetime import timedelta, datetime, time
import hashlib as mHash
## Exceptions
class AutoBkError(Exception): pass
###############################
# Global Configurations and Constants
oLog = mLog.getLogger() # root logger
sAt = 'autobk:%s=%s'
sCombo = '{} @ {}'
sAuthKey = '{}:{}'
sSubPath = "{}/{}"
sSqlTimeFmt = '%Y-%m-%d %H:%M:%S'
###############################
# Loads the configuration file and logger
def LoadConfig(sMod, *, sIniFile='./autobk.ini', bRotate=False):
global oLog, sAt
# Parse Config File
oINI = RawConfigParser()
oINI.read([sIniFile])
# Load Logging config
sIni = 'Logging'
sLogFile = oINI.get(sIni, 'File', fallback='./autobk.log')
iLogSize = oINI.getint(sIni, 'MaxSize', fallback=64000)
iLogCount = oINI.getint(sIni, 'Count', fallback=3)
sLogLevel = oINI.get(sIni, 'Level', fallback=mLog.INFO)
sAt = sMod + ':%s=%s'
# Logging Components
oF = Formatter('%(asctime)s - %(message)s', sSqlTimeFmt)
oH = RotatingFileHandler(sLogFile, 'a', iLogSize, iLogCount) if bRotate else FileHandler(sLogFile)
oH.setFormatter(oF)
# Setup Loggers
oLog.setLevel(mLog.WARNING)
oLog.addHandler(oH)
oLog = mLog.getLogger('AutoBk') # Switch to local logger to avoid spam from other modules
oLog.setLevel(sLogLevel)
oLog.addHandler(oH)
oLog.propagate = False
return (oINI, oLog, sAt)
###############################
# Returns the next iWeekday@iHour from tFrom
def NextWeekday(tFrom, iWeekday, iHour, iWeeks=1):
if iWeeks <= 0:
tNextDay = tFrom + timedelta(days=1)
return tNextDay.replace(hour=iHour, minute=0, second=0, microsecond=0)
else:
iOffset = (iWeekday - tFrom.isoweekday()) % 7
if iOffset > 0:
iWeeks -= 1
iOffset += iWeeks * 7
tNext = tFrom + timedelta(days=iOffset)
return tNext.replace(hour=iHour, minute=0, second=0, microsecond=0)
###############################
# Executes a script in a new process and waits for completion
def CallScript(sName, sScript, *, lsArg=None, iTimeout=60, bOutIsErr=True):
# Prepare arguments for process call
lsParam = ['python3', sScript]
if (lsArg is not None): lsParam += lsArg
# Execute script
oLog.info(sAt, sName, 'calling')
oProc = Popen(lsParam, stdout=PIPE, text=True)
sOut = None
# Wait for completion
try:
(sOut, sErr) = oProc.communicate(timeout=iTimeout)
except Exception as oErr:
oLog.error(sAt, sName, 'timeout')
oProc.kill()
if (oProc.returncode == 0):
oLog.info(sAt, sName, 'complete')
return None if (bOutIsErr) else sOut
else:
oLog.error(sAt, sName, 'failed')
return sOut if (bOutIsErr) else None
###############################
# Sends an HTTP request and returns the response
def HttpRequest(oHttpCnx, sURL, dnHdrs, *, bPost=False, bData=True, sMsg=None, sFallbackURL=None):
# Send HTTP transfer request message to get a file
oHttpCnx.request('POST' if (bPost) else 'GET', sURL, sMsg, dnHdrs)
oResponse = oHttpCnx.getresponse()
if (oResponse.status == 200 or oResponse.status == 302):
return oResponse.read() if bData else oResponse
elif (oResponse.status == 404 and sFallbackURL is not None):
oResponse.read() # Must read all data before trying fallback
return HttpRequest(oHttpCnx, sFallbackURL, dnHdrs, bPost=bPost, bData=bData, sMsg=sMsg)
else:
raise AutoBkError('Bad HTTP Response: {}'.format(oResponse.status))
###############################
# Calculate MD5 Hash of a file
def FileHash(sFile):
oHash = mHash.md5()
with open(sFile, 'rb') as oF:
for sData in iter(lambda: oF.read(4096), b''):
oHash.update(sData)
return oHash.hexdigest()