2017-09-01 00:55:55 -04:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
2017-09-01 14:47:48 -04:00
|
|
|
# Thanks to Matt Rude and https://gist.github.com/mattrude/b0ac735d07b0031bb002 so I can know what the hell I'm doing.
|
2017-09-01 00:55:55 -04:00
|
|
|
|
2017-09-13 18:32:28 -04:00
|
|
|
import argparse
|
2018-04-15 15:20:48 -04:00
|
|
|
import base64
|
2017-09-15 12:50:45 -04:00
|
|
|
import configparser
|
2017-09-01 00:55:55 -04:00
|
|
|
import datetime
|
2017-09-01 14:47:48 -04:00
|
|
|
import getpass
|
2017-09-01 00:55:55 -04:00
|
|
|
import os
|
|
|
|
import subprocess
|
2017-09-01 14:47:48 -04:00
|
|
|
from pwd import getpwnam
|
|
|
|
from grp import getgrnam
|
2017-09-01 00:55:55 -04:00
|
|
|
|
|
|
|
NOW = datetime.datetime.utcnow()
|
|
|
|
NOWstr = NOW.strftime('%Y-%m-%d')
|
|
|
|
|
2017-09-13 18:32:28 -04:00
|
|
|
# TODO:
|
|
|
|
# - cleanup/rotation should be optional
|
2018-05-05 07:05:15 -04:00
|
|
|
# - turn into a class so we can more easily share vars across functions
|
|
|
|
# - also, create the "CURRENT" symlink *AFTER* the dump completes?
|
2017-09-13 18:32:28 -04:00
|
|
|
|
2018-03-13 12:15:32 -04:00
|
|
|
cfgfile = os.path.join(os.environ['HOME'], '.config', 'optools', 'sksdump.ini')
|
2017-09-01 00:55:55 -04:00
|
|
|
|
2017-09-15 12:50:45 -04:00
|
|
|
def getDefaults():
|
|
|
|
# Hardcoded defaults
|
|
|
|
dflt = {'system': {'user': 'sks',
|
|
|
|
'group': 'sks',
|
|
|
|
'compress': 'xz',
|
|
|
|
'svcs': ['sks-db', 'sks-recon'],
|
|
|
|
'logfile': '/var/log/sksdump.log',
|
|
|
|
'days': 1,
|
|
|
|
'dumpkeys': 15000},
|
2017-10-08 03:48:51 -04:00
|
|
|
'sync': {'throttle': 0},
|
2017-09-15 12:50:45 -04:00
|
|
|
'paths': {'basedir': '/var/lib/sks',
|
|
|
|
'destdir': '/srv/http/sks/dumps',
|
2018-04-15 15:20:48 -04:00
|
|
|
'rsync': ('root@mirror.square-r00t.net:' +
|
|
|
|
'/srv/http/sks/dumps'),
|
2018-04-14 13:03:07 -04:00
|
|
|
'sksbin': '/usr/bin/sks'},
|
2017-09-15 12:50:45 -04:00
|
|
|
'runtime': {'nodump': None, 'nocompress': None, 'nosync': None}}
|
|
|
|
## Build out the default .ini.
|
2018-04-15 15:20:48 -04:00
|
|
|
dflt_b64 = ("""IyBJTVBPUlRBTlQ6IFRoaXMgc2NyaXB0IHVzZXMgY2VydGFpbiBwZXJtaXNz
|
|
|
|
aW9ucyBmdW5jdGlvbnMgdGhhdCByZXF1aXJlIHNvbWUKIyBmb3JldGhvdWdo
|
|
|
|
dC4KIyBZb3UgY2FuIGVpdGhlciBydW4gYXMgcm9vdCwgd2hpY2ggaXMgdGhl
|
|
|
|
ICJlYXN5IiB3YXksIE9SIHlvdSBjYW4gcnVuIGFzIHRoZQojIHNrcyB1c2Vy
|
|
|
|
IChvci4uLiB3aGF0ZXZlciB1c2VyIHlvdXIgU0tTIGluc3RhbmNlIHJ1bnMg
|
|
|
|
YXMpLgojIEl0IGhhcyB0byBiZSBvbmUgb3IgdGhlIG90aGVyOyB5b3UnbGwg
|
|
|
|
U0VSSU9VU0xZIG1lc3MgdGhpbmdzIHVwIG90aGVyd2lzZS4KIyBJZiB5b3Ug
|
|
|
|
cnVuIGFzIHRoZSBza3MgdXNlciwgTUFLRSBTVVJFIHRoZSBmb2xsb3dpbmcg
|
|
|
|
aXMgc2V0IGluIHlvdXIgc3Vkb2VycwojICh3aGVyZSBTS1NVU0VSIGlzIHRo
|
|
|
|
ZSB1c2VybmFtZSBza3MgcnVucyBhcyk6CiMJQ21uZF9BbGlhcyBTS1NDTURT
|
|
|
|
ID0gL3Vzci9iaW4vc3lzdGVtY3RsIHN0YXJ0IHNrcy1kYixcCiMJICAgICAg
|
|
|
|
ICAgICAgICAgICAgICAgL3Vzci9iaW4vc3lzdGVtY3RsIHN0b3Agc2tzLWRi
|
|
|
|
LFwKIyAgICAgICAgICAgICAgICAgICAgICAgIC91c3IvYmluL3N5c3RlbWN0
|
|
|
|
bCBzdGFydCBza3MtcmVjb24sXAojCQkgICAgICAgICAgICAgICAgIC91c3Iv
|
|
|
|
YmluL3N5c3RlbWN0bCBzdG9wIHNrcy1yZWNvbgojCVNLU1VTRVIgQUxMID0g
|
|
|
|
Tk9QQVNTV0Q6IFNLU0NNRFMKCiMgVGhpcyB3YXMgd3JpdHRlbiBmb3Igc3lz
|
|
|
|
dGVtZCBzeXN0ZW1zIG9ubHkuIFR3ZWFraW5nIHdvdWxkIGJlIG5lZWRlZCBm
|
|
|
|
b3IKIyBub24tc3lzdGVtZCBzeXN0ZW1zIChzaW5jZSBldmVyeSBub24tc3lz
|
|
|
|
dGVtZCB1c2VzIHRoZWlyIG93biBpbml0IHN5c3RlbQojIGNhbGxhYmxlcy4u
|
|
|
|
LikKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
|
|
|
|
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgVGhp
|
|
|
|
cyBzZWN0aW9uIGNvbnRyb2xzIHZhcmlvdXMgc3lzdGVtIGNvbmZpZ3VyYXRp
|
|
|
|
b24uCltzeXN0ZW1dCgojIFRoaXMgc2hvdWxkIGJlIHRoZSB1c2VyIFNLUyBy
|
|
|
|
dW5zIGFzLgp1c2VyID0gc2tzCgojIFRoaXMgaXMgdGhlIGdyb3VwIHRoYXQg
|
|
|
|
U0tTIHJ1bnMgYXMuCmdyb3VwID0gc2tzCgojIElmIGVtcHR5LCBkb24ndCBj
|
|
|
|
b21wcmVzcyBkdW1wcy4KIyBJZiBvbmUgb2Y6IHh6LCBneiwgYnoyLCBvciBs
|
|
|
|
cnogKGZvciBscnppcCkgdGhlbiB1c2UgdGhhdCBjb21wcmVzc2lvbiBhbGdv
|
|
|
|
LgojIE5vdGUgdGhhdCBscnppcCByZXF1aXJlcyBleHRyYSBpbnN0YWxsYXRp
|
|
|
|
b24uCmNvbXByZXNzID0geHoKCiMgVGhlc2Ugc2VydmljZXMgd2lsbCBiZSBz
|
|
|
|
dG9wcGVkL3N0YXJ0ZWQsIGluIG9yZGVyLCBiZWZvcmUvYWZ0ZXIgZHVtcHMu
|
|
|
|
IElmIG1vcmUKIyB0aGFuIG9uZSwgc2VwZXJhdGUgYnkgY29tbWFzLgpzdmNz
|
|
|
|
ID0gc2tzLWRiLHNrcy1yZWNvbgoKIyBUaGUgcGF0aCB0byB0aGUgbG9nZmls
|
|
|
|
ZS4KbG9nZmlsZSA9IC92YXIvbG9nL3Nrc2R1bXAubG9nCgojIFRoZSBudW1i
|
|
|
|
ZXIgb2YgZGF5cyBvZiByb3RhdGVkIGtleSBkdW1wcy4gSWYgZW1wdHksIGRv
|
|
|
|
bid0IHJvdGF0ZS4KZGF5cyA9IDEKCiMgSG93IG1hbnkga2V5cyB0byBpbmNs
|
|
|
|
dWRlIGluIGVhY2ggZHVtcCBmaWxlLgpkdW1wa2V5cyA9IDE1MDAwCgoKIyBU
|
|
|
|
aGlzIHNlY3Rpb24gY29udHJvbHMgc3luYyBzZXR0aW5ncy4KW3N5bmNdCgoj
|
|
|
|
IFRoaXMgc2V0dGluZyBpcyB3aGF0IHRoZSBzcGVlZCBzaG91bGQgYmUgdGhy
|
|
|
|
b3R0bGVkIHRvLCBpbiBLaUIvcy4gSWYgZW1wdHkgb3IKIyAwLCBwZXJmb3Jt
|
|
|
|
IG5vIHRocm90dGxpbmcuCnRocm90dGxlID0gMAoKCiMgVGhpcyBzZWN0aW9u
|
|
|
|
IGNvbnRyb2xzIHdoZXJlIHN0dWZmIGdvZXMgYW5kIHdoZXJlIHdlIHNob3Vs
|
|
|
|
ZCBmaW5kIGl0LgpbcGF0aHNdCgojIFdoZXJlIHlvdXIgU0tTIERCIGlzLgpi
|
|
|
|
YXNlZGlyID0gL3Zhci9saWIvc2tzCgojIFRoaXMgaXMgdGhlIGJhc2UgZGly
|
|
|
|
ZWN0b3J5IHdoZXJlIHRoZSBkdW1wcyBzaG91bGQgZ28uCiMgVGhlcmUgd2ls
|
|
|
|
bCBiZSBhIHN1Yi1kaXJlY3RvcnkgY3JlYXRlZCBmb3IgZWFjaCBkYXRlLgpk
|
|
|
|
ZXN0ZGlyID0gL3Nydi9odHRwL3Nrcy9kdW1wcwoKIyBUaGUgcGF0aCBmb3Ig
|
|
|
|
cnN5bmNpbmcgdGhlIGR1bXBzLiBJZiBlbXB0eSwgZG9uJ3QgcnN5bmMuCnJz
|
|
|
|
eW5jID0gcm9vdEBtaXJyb3Iuc3F1YXJlLXIwMHQubmV0Oi9zcnYvaHR0cC9z
|
|
|
|
a3MvZHVtcHMKCiMgVGhlIHBhdGggdG8gdGhlIHNrcyBiaW5hcnkgdG8gdXNl
|
|
|
|
Lgpza3NiaW4gPSAvdXNyL2Jpbi9za3MKCgojIFRoaXMgc2VjdGlvbiBjb250
|
|
|
|
cm9scyBydW50aW1lIG9wdGlvbnMuIFRoZXNlIGNhbiBiZSBvdmVycmlkZGVu
|
|
|
|
IGF0IHRoZQojIGNvbW1hbmRsaW5lLiBUaGV5IHRha2Ugbm8gdmFsdWVzOyB0
|
|
|
|
aGV5J3JlIG1lcmVseSBvcHRpb25zLgpbcnVudGltZV0KCiMgRG9uJ3QgZHVt
|
|
|
|
cCBhbnkga2V5cy4KIyBVc2VmdWwgZm9yIGRlZGljYXRlZCBpbi10cmFuc2l0
|
|
|
|
L3ByZXAgYm94ZXMuCjtub2R1bXAKCiMgRG9uJ3QgY29tcHJlc3MgdGhlIGR1
|
|
|
|
bXBzLCBldmVuIGlmIHdlIGhhdmUgYSBjb21wcmVzc2lvbiBzY2hlbWUgc3Bl
|
|
|
|
Y2lmaWVkIGluCiMgdGhlIFtzeXN0ZW06Y29tcHJlc3NdIHNlY3Rpb246ZGly
|
|
|
|
ZWN0aXZlLgo7bm9jb21wcmVzcwoKIyBEb24ndCBzeW5jIHRvIGFub3RoZXIg
|
|
|
|
c2VydmVyL3BhdGgsIGV2ZW4gaWYgb25lIGlzIHNwZWNpZmllZCBpbiBbcGF0
|
|
|
|
aHM6cnN5bmNdLgo7bm9zeW5j""")
|
2017-09-15 12:50:45 -04:00
|
|
|
realcfg = configparser.ConfigParser(defaults = dflt, allow_no_value = True)
|
|
|
|
if not os.path.isfile(cfgfile):
|
|
|
|
with open(cfgfile, 'w') as f:
|
2018-04-15 15:20:48 -04:00
|
|
|
f.write(base64.b64decode(dflt_b64).decode('utf-8'))
|
2017-09-15 12:50:45 -04:00
|
|
|
realcfg.read(cfgfile)
|
|
|
|
return(realcfg)
|
2017-09-01 14:47:48 -04:00
|
|
|
|
2017-09-15 12:50:45 -04:00
|
|
|
def svcMgmt(op, args):
|
2017-09-01 14:47:48 -04:00
|
|
|
if op not in ('start', 'stop'):
|
|
|
|
raise ValueError('Operation must be start or stop')
|
2017-09-15 12:50:45 -04:00
|
|
|
for svc in args['svcs'].split(','):
|
|
|
|
cmd = ['/usr/bin/systemctl', op, svc.strip()]
|
2017-09-01 14:47:48 -04:00
|
|
|
if getpass.getuser() != 'root':
|
|
|
|
cmd.insert(0, 'sudo')
|
|
|
|
subprocess.run(cmd)
|
|
|
|
return()
|
2017-09-01 00:55:55 -04:00
|
|
|
|
2017-09-15 12:50:45 -04:00
|
|
|
def destPrep(args):
|
|
|
|
nowdir = os.path.join(args['destdir'], NOWstr)
|
|
|
|
curdir = os.path.join(args['destdir'], 'current')
|
|
|
|
PAST = NOW - datetime.timedelta(days = args['days'])
|
|
|
|
for thisdir, dirs, files in os.walk(args['destdir'], topdown = False):
|
2017-09-01 14:47:48 -04:00
|
|
|
for f in files:
|
2017-09-09 12:23:13 -04:00
|
|
|
try: # we use a try here because if the link's broken, the script bails out.
|
|
|
|
fstat = os.stat(os.path.join(thisdir, f))
|
|
|
|
mtime = fstat.st_mtime
|
|
|
|
if int(mtime) < PAST.timestamp():
|
|
|
|
os.remove(os.path.join(thisdir, f))
|
|
|
|
except FileNotFoundError: # broken symlink
|
|
|
|
try:
|
|
|
|
os.remove(os.path.join(thisdir, f))
|
2017-09-09 12:25:14 -04:00
|
|
|
except:
|
|
|
|
pass # just... ignore it. it's fine, whatever.
|
2017-09-03 09:25:13 -04:00
|
|
|
# Delete if empty dir
|
2017-09-15 12:50:45 -04:00
|
|
|
if os.path.isdir(thisdir):
|
|
|
|
if len(os.listdir(thisdir)) == 0:
|
|
|
|
os.rmdir(thisdir)
|
2017-09-04 20:45:08 -04:00
|
|
|
for d in dirs:
|
2017-09-18 03:13:01 -04:00
|
|
|
_dir = os.path.join(thisdir, d)
|
|
|
|
if os.path.isdir(_dir):
|
|
|
|
if len(os.listdir(_dir)) == 0:
|
2017-10-24 06:04:54 -04:00
|
|
|
try:
|
|
|
|
os.rmdir(os.path.join(thisdir, d))
|
|
|
|
except NotADirectoryError:
|
|
|
|
pass # in case it grabs the "current" symlink
|
2017-09-03 09:25:13 -04:00
|
|
|
#try:
|
|
|
|
# os.removedirs(sks['destdir']) # Remove empty dirs
|
|
|
|
#except:
|
|
|
|
# pass # thisisfine.jpg
|
2017-09-01 14:47:48 -04:00
|
|
|
os.makedirs(nowdir, exist_ok = True)
|
|
|
|
if getpass.getuser() == 'root':
|
2017-09-15 12:50:45 -04:00
|
|
|
uid = getpwnam(args['user']).pw_uid
|
|
|
|
gid = getgrnam(args['group']).gr_gid
|
2018-04-15 15:20:48 -04:00
|
|
|
# we COULD set it as part of the os.makedirs, but iirc it doesn't set
|
|
|
|
# it for existing dirs.
|
|
|
|
for d in (args['destdir'], nowdir):
|
2017-09-01 14:47:48 -04:00
|
|
|
os.chown(d, uid, gid)
|
|
|
|
if os.path.isdir(curdir):
|
|
|
|
os.remove(curdir)
|
2017-09-29 07:00:57 -04:00
|
|
|
try:
|
|
|
|
os.symlink(NOWstr, curdir, target_is_directory = True)
|
|
|
|
except FileExistsError:
|
|
|
|
pass # Ignore if it was set earlier
|
2017-09-01 14:47:48 -04:00
|
|
|
return()
|
2017-09-01 00:55:55 -04:00
|
|
|
|
2017-09-15 12:50:45 -04:00
|
|
|
def dumpDB(args):
|
|
|
|
destPrep(args)
|
|
|
|
os.chdir(args['basedir'])
|
|
|
|
svcMgmt('stop', args)
|
2018-04-14 17:53:55 -04:00
|
|
|
cmd = [args['sksbin'],
|
2017-09-01 14:47:48 -04:00
|
|
|
'dump',
|
2017-09-15 12:50:45 -04:00
|
|
|
str(args['dumpkeys']), # How many keys per dump?
|
|
|
|
os.path.join(args['destdir'], NOWstr), # Where should it go?
|
2017-09-01 14:47:48 -04:00
|
|
|
'keydump.{0}'.format(NOWstr)] # What the filename prefix should be
|
|
|
|
if getpass.getuser() == 'root':
|
2017-09-15 12:50:45 -04:00
|
|
|
cmd2 = ['sudo', '-u', args['user']]
|
2017-09-01 14:47:48 -04:00
|
|
|
cmd2.extend(cmd)
|
|
|
|
cmd = cmd2
|
2017-09-15 12:50:45 -04:00
|
|
|
with open(args['logfile'], 'a') as f:
|
2017-09-01 14:47:48 -04:00
|
|
|
f.write('===== {0} =====\n'.format(str(datetime.datetime.utcnow())))
|
|
|
|
subprocess.run(cmd, stdout = f, stderr = f)
|
2017-09-15 12:50:45 -04:00
|
|
|
svcMgmt('start', args)
|
2017-09-01 14:47:48 -04:00
|
|
|
return()
|
|
|
|
|
2017-09-15 12:50:45 -04:00
|
|
|
def compressDB(args):
|
|
|
|
if not args['compress']:
|
2017-09-01 14:47:48 -04:00
|
|
|
return()
|
2017-09-15 12:50:45 -04:00
|
|
|
curdir = os.path.join(args['destdir'], NOWstr)
|
2018-04-15 15:20:48 -04:00
|
|
|
# I use os.walk here because we might handle this differently in the
|
|
|
|
# future...
|
|
|
|
for thisdir, dirs, files in os.walk(curdir):
|
2017-09-02 10:01:42 -04:00
|
|
|
files.sort()
|
2017-09-01 14:47:48 -04:00
|
|
|
for f in files:
|
|
|
|
fullpath = os.path.join(thisdir, f)
|
2017-09-15 12:50:45 -04:00
|
|
|
newfile = '{0}.{1}'.format(fullpath, args['compress'])
|
2017-09-03 09:25:13 -04:00
|
|
|
# TODO: add compressed tarball support.
|
|
|
|
# However, I can't do this on memory-constrained systems for lrzip.
|
|
|
|
# See: https://github.com/kata198/python-lrzip/issues/1
|
2017-09-15 12:50:45 -04:00
|
|
|
with open(args['logfile'], 'a') as f:
|
2018-04-15 15:20:48 -04:00
|
|
|
f.write('===== {0} Now compressing {1} =====\n'.format(
|
|
|
|
str(datetime.datetime.utcnow()),
|
|
|
|
fullpath))
|
2017-09-15 12:50:45 -04:00
|
|
|
if args['compress'].lower() == 'gz':
|
2017-09-01 14:47:48 -04:00
|
|
|
import gzip
|
2018-04-15 15:20:48 -04:00
|
|
|
with open(fullpath, 'rb') as fh_in, gzip.open(newfile,
|
|
|
|
'wb') as fh_out:
|
2017-09-01 14:47:48 -04:00
|
|
|
fh_out.writelines(fh_in)
|
2017-09-15 12:50:45 -04:00
|
|
|
elif args['compress'].lower() == 'xz':
|
2017-09-01 14:47:48 -04:00
|
|
|
import lzma
|
2018-04-15 15:20:48 -04:00
|
|
|
with open(fullpath, 'rb') as fh_in, \
|
|
|
|
lzma.open(newfile,
|
|
|
|
'wb',
|
|
|
|
preset = 9|lzma.PRESET_EXTREME) as fh_out:
|
2017-09-01 14:47:48 -04:00
|
|
|
fh_out.writelines(fh_in)
|
2017-09-15 12:50:45 -04:00
|
|
|
elif args['compress'].lower() == 'bz2':
|
2017-09-01 14:47:48 -04:00
|
|
|
import bz2
|
2018-04-15 15:20:48 -04:00
|
|
|
with open(fullpath, 'rb') as fh_in, bz2.open(newfile,
|
|
|
|
'wb') as fh_out:
|
2017-09-01 14:47:48 -04:00
|
|
|
fh_out.writelines(fh_in)
|
2017-09-15 12:50:45 -04:00
|
|
|
elif args['compress'].lower() == 'lrz':
|
2017-09-01 14:47:48 -04:00
|
|
|
import lrzip
|
2018-04-15 15:20:48 -04:00
|
|
|
with open(fullpath, 'rb') as fh_in, open(newfile,
|
|
|
|
'wb') as fh_out:
|
2017-09-01 14:47:48 -04:00
|
|
|
fh_out.write(lrzip.compress(fh_in.read()))
|
|
|
|
os.remove(fullpath)
|
|
|
|
if getpass.getuser() == 'root':
|
2017-09-15 12:50:45 -04:00
|
|
|
uid = getpwnam(args['user']).pw_uid
|
|
|
|
gid = getgrnam(args['group']).gr_gid
|
2017-09-01 14:47:48 -04:00
|
|
|
os.chown(newfile, uid, gid)
|
|
|
|
return()
|
|
|
|
|
2017-09-15 12:50:45 -04:00
|
|
|
def syncDB(args):
|
|
|
|
if not args['rsync']:
|
2017-09-01 14:47:48 -04:00
|
|
|
return()
|
|
|
|
cmd = ['rsync',
|
|
|
|
'-a',
|
|
|
|
'--delete',
|
2017-09-15 12:50:45 -04:00
|
|
|
os.path.join(args['destdir'], '.'),
|
|
|
|
args['rsync']]
|
2017-10-08 03:48:51 -04:00
|
|
|
if args['throttle'] > 0.0:
|
2017-10-08 03:57:59 -04:00
|
|
|
cmd.insert(-1, '--bwlimit={0}'.format(str(args['throttle'])))
|
2017-09-15 12:50:45 -04:00
|
|
|
with open(args['logfile'], 'a') as f:
|
2018-04-15 15:20:48 -04:00
|
|
|
f.write('===== {0} Rsyncing to mirror =====\n'.format(
|
|
|
|
str(datetime.datetime.utcnow())))
|
2017-09-15 12:50:45 -04:00
|
|
|
with open(args['logfile'], 'a') as f:
|
2017-09-01 14:47:48 -04:00
|
|
|
subprocess.run(cmd, stdout = f, stderr = f)
|
|
|
|
return()
|
2017-09-01 00:55:55 -04:00
|
|
|
|
2017-09-13 18:32:28 -04:00
|
|
|
def parseArgs():
|
2017-09-15 12:50:45 -04:00
|
|
|
cfg = getDefaults()
|
|
|
|
system = cfg['system']
|
|
|
|
paths = cfg['paths']
|
2017-10-08 03:48:51 -04:00
|
|
|
sync = cfg['sync']
|
2017-09-15 12:50:45 -04:00
|
|
|
runtime = cfg['runtime']
|
2018-04-15 15:20:48 -04:00
|
|
|
args = argparse.ArgumentParser(description = ('sksdump - a tool for ' +
|
|
|
|
'dumping an SKS Database'),
|
|
|
|
epilog = ('brent s. || 2018 || ' +
|
|
|
|
'https://square-r00t.net'))
|
2017-09-15 12:50:45 -04:00
|
|
|
args.add_argument('-u',
|
|
|
|
'--user',
|
|
|
|
default = system['user'],
|
|
|
|
dest = 'user',
|
|
|
|
help = 'The user that you run SKS services as.')
|
|
|
|
args.add_argument('-g',
|
|
|
|
'--group',
|
|
|
|
default = system['group'],
|
|
|
|
dest = 'group',
|
|
|
|
help = 'The group that SKS services run as.')
|
|
|
|
args.add_argument('-c',
|
|
|
|
'--compress',
|
|
|
|
default = system['compress'],
|
|
|
|
dest = 'compress',
|
|
|
|
choices = ['xz', 'gz', 'bz2', 'lrz', None],
|
|
|
|
help = 'The compression scheme to apply to the dumps.')
|
|
|
|
args.add_argument('-s',
|
|
|
|
'--services',
|
|
|
|
default = system['svcs'],
|
|
|
|
dest = 'svcs',
|
2018-04-15 15:20:48 -04:00
|
|
|
help = ('A comma-separated list of services that will ' +
|
|
|
|
'be stopped/started for the dump (in the ' +
|
|
|
|
'provided order).'))
|
2017-09-15 12:50:45 -04:00
|
|
|
args.add_argument('-l',
|
|
|
|
'--log',
|
|
|
|
default = system['logfile'],
|
|
|
|
dest = 'logfile',
|
|
|
|
help = 'The path to the logfile.')
|
|
|
|
args.add_argument('-a',
|
|
|
|
'--days',
|
|
|
|
default = system['days'],
|
|
|
|
dest = 'days',
|
|
|
|
type = int,
|
|
|
|
help = 'How many days to keep rotation for.')
|
2017-09-13 18:32:28 -04:00
|
|
|
args.add_argument('-d',
|
2017-09-15 12:50:45 -04:00
|
|
|
'--dumpkeys',
|
|
|
|
default = system['dumpkeys'],
|
|
|
|
dest = 'dumpkeys',
|
|
|
|
type = int,
|
|
|
|
help = 'How many keys to put in each dump.')
|
|
|
|
args.add_argument('-b',
|
|
|
|
'--basedir',
|
|
|
|
default = paths['basedir'],
|
|
|
|
dest = 'basedir',
|
|
|
|
help = 'The directory which holds your SKS DB.')
|
2018-04-14 13:03:07 -04:00
|
|
|
args.add_argument('-x',
|
|
|
|
'--sks-binary',
|
|
|
|
default = paths['sksbin'],
|
|
|
|
dest = 'sksbin',
|
2018-04-15 15:20:48 -04:00
|
|
|
help = ('The path to the SKS binary/executable to use ' +
|
|
|
|
'to perform the dump.'))
|
2017-09-15 12:50:45 -04:00
|
|
|
args.add_argument('-e',
|
|
|
|
'--destdir',
|
|
|
|
default = paths['destdir'],
|
|
|
|
dest = 'destdir',
|
2018-04-15 15:20:48 -04:00
|
|
|
help = ('The directory where the dumps should be ' +
|
|
|
|
'saved (a sub-directory with the date will be ' +
|
|
|
|
'created).'))
|
2017-09-15 12:50:45 -04:00
|
|
|
args.add_argument('-r',
|
|
|
|
'--rsync',
|
|
|
|
default = paths['rsync'],
|
|
|
|
dest = 'rsync',
|
2018-04-15 15:20:48 -04:00
|
|
|
help = ('The remote (user@host:/path/) or local '+
|
|
|
|
'(/path/) path to use to sync the dumps to.'))
|
2017-10-08 03:48:51 -04:00
|
|
|
args.add_argument('-t',
|
|
|
|
'--throttle',
|
|
|
|
default = float(sync['throttle']),
|
|
|
|
dest = 'throttle',
|
|
|
|
type = float,
|
2018-04-15 15:20:48 -04:00
|
|
|
help = ('The amount in KiB/s to throttle the rsync ' +
|
|
|
|
'to. Use 0 for no throttling.'))
|
2017-09-15 12:50:45 -04:00
|
|
|
args.add_argument('-D',
|
2017-09-13 18:32:28 -04:00
|
|
|
'--no-dump',
|
|
|
|
dest = 'nodump',
|
|
|
|
action = 'store_true',
|
2017-09-15 12:50:45 -04:00
|
|
|
default = ('nodump' in runtime),
|
2017-09-13 18:32:28 -04:00
|
|
|
help = 'Don\'t dump the SKS DB (default is to dump)')
|
2017-09-15 12:50:45 -04:00
|
|
|
args.add_argument('-C',
|
2017-09-13 18:32:28 -04:00
|
|
|
'--no-compress',
|
|
|
|
dest = 'nocompress',
|
|
|
|
action = 'store_true',
|
2017-09-15 12:50:45 -04:00
|
|
|
default = ('nocompress' in runtime),
|
2018-04-15 15:20:48 -04:00
|
|
|
help = ('Don\'t compress the DB dumps (default is to ' +
|
|
|
|
'compress)'))
|
2017-09-15 12:50:45 -04:00
|
|
|
args.add_argument('-S',
|
2017-09-13 18:32:28 -04:00
|
|
|
'--no-sync',
|
|
|
|
dest = 'nosync',
|
|
|
|
action = 'store_true',
|
2017-09-15 12:50:45 -04:00
|
|
|
default = ('nosync' in runtime),
|
2017-09-13 18:32:28 -04:00
|
|
|
help = 'Don\'t sync the dumps to the remote server.')
|
2017-09-15 12:50:45 -04:00
|
|
|
varargs = vars(args.parse_args())
|
|
|
|
return(varargs)
|
2017-09-13 18:32:28 -04:00
|
|
|
|
2017-09-01 00:55:55 -04:00
|
|
|
def main():
|
2017-09-15 12:50:45 -04:00
|
|
|
args = parseArgs()
|
|
|
|
if getpass.getuser() not in ('root', args['user']):
|
|
|
|
exit('ERROR: You must be root or {0}!'.format(args['user']))
|
|
|
|
with open(args['logfile'], 'a') as f:
|
2018-04-15 15:20:48 -04:00
|
|
|
f.write('===== {0} STARTING =====\n'.format(
|
|
|
|
str(datetime.datetime.utcnow())))
|
2017-09-13 18:32:28 -04:00
|
|
|
if not args['nodump']:
|
2017-09-15 12:50:45 -04:00
|
|
|
dumpDB(args)
|
2017-09-13 18:32:28 -04:00
|
|
|
if not args['nocompress']:
|
2017-09-15 12:50:45 -04:00
|
|
|
compressDB(args)
|
2017-09-13 18:32:28 -04:00
|
|
|
if not args['nosync']:
|
2017-09-15 12:50:45 -04:00
|
|
|
syncDB(args)
|
|
|
|
with open(args['logfile'], 'a') as f:
|
2018-04-15 15:20:48 -04:00
|
|
|
f.write('===== {0} DONE =====\n'.format(
|
|
|
|
str(datetime.datetime.utcnow())))
|
2018-05-05 06:57:56 -04:00
|
|
|
with open(os.path.join(args['destdir'], 'LAST_COMPLETED_DUMP.txt'),
|
|
|
|
'w') as f:
|
2018-05-05 07:05:15 -04:00
|
|
|
f.write(str(datetime.datetime.utcnow()) + ' UTC\n')
|
2017-09-01 19:30:28 -04:00
|
|
|
|
2017-09-01 00:55:55 -04:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2017-09-01 14:47:48 -04:00
|
|
|
main()
|