fix. --keep-within and --keep-<period> are different options.

This commit is contained in:
2022-05-22 20:18:05 -04:00
parent dfe2f4d100
commit 8e7841b4cc
4 changed files with 88 additions and 45 deletions

View File

@@ -45,6 +45,8 @@ loglvls = {'critical': logging.CRITICAL,
### DEFAULT NAMESPACE ###
dflt_ns = 'http://git.root2.io/r00t2/borgextend/'
# In code, replace "day" with "daily" when constructing command.
policyperiods = ('Second', 'Minute', 'Hour', 'Day', 'Week', 'Month', 'Year')
### THE GUTS ###
class Backup(object):
@@ -127,9 +129,6 @@ class Backup(object):
if not reponames:
reponames = []
repos = []
dfltRetention = None
if server.attrib.get('pruneRetention') is not None:
dfltRetention = isodate.parse_duration(server.attrib.get('pruneRetention'))
for repo in server.findall('{0}repo'.format(self.ns)):
if reponames and repo.attrib['name'] not in reponames:
continue
@@ -140,8 +139,8 @@ class Backup(object):
r[a] = repo.attrib[a]
for e in ('path', 'exclude'):
# TODO: have an attrib for path and exclude, "glob=<bool>"?
# If true, try using the glob module to resolve paths?
# This gives us the benefit of allowing glob per-path/exclude.
# If true, try using the glob module to resolve paths?
# This gives us the benefit of allowing glob per-path/exclude.
r[e] = [i.text for i in repo.findall(self.ns + e)]
for prep in repo.findall('{0}prep'.format(self.ns)):
if 'prep' not in r:
@@ -164,11 +163,21 @@ class Backup(object):
r['plugins'][pname]['params'][paramname] = json.loads(param.text)
else:
r['plugins'][pname]['params'][paramname] = param.text
retention = repo.attrib.get('pruneRetention')
if retention is not None:
r['retention'] = isodate.parse_duration(retention)
else:
r['retention'] = dfltRetention
keepWithin = repo.find('{0}keepWithin'.format(self.ns))
if keepWithin is not None:
if 'retention' not in r.keys():
r['retention'] = {}
r['retention']['last'] = isodate.parse_duration(keepWithin.text)
keepLast = repo.find('{0}keepLast'.format(self.ns))
if keepLast is not None:
for e in policyperiods:
k = e.lower()
policy = keepLast.find('{0}per{1}'.format(self.ns, e))
if policy is not None:
if 'retention' not in r.keys():
r['retention'] = {}
# This is safe. We validate the config.
r['retention'][k] = int(policy.text)
repos.append(r)
return(repos)
self.logger.debug('VARS (before args cleanup): {0}'.format(vars(self)))
@@ -482,12 +491,8 @@ class Backup(object):
_user = self.repos[server].get('user', pwd.getpwuid(os.geteuid()).pw_name)
for repo in self.repos[server]['repos']:
if repo.get('retention') is None:
# No prune duration was set. Skip.
# No prune retention was set. Skip.
continue
if isinstance(repo['retention'], datetime.timedelta):
retentionSeconds = repo['retention'].total_seconds()
else: # it's an isodate.Duration
retentionSeconds = repo['retention'].totimedelta(datetime.datetime.now()).total_seconds()
_loc_env = _env.copy()
if 'password' not in repo:
print('Password not supplied for {0}:{1}.'.format(server, repo['name']))
@@ -500,8 +505,21 @@ class Backup(object):
'--log-json',
'--{0}'.format(self.args['loglevel']),
'prune',
'--stats',
'--keep-secondly', int(retentionSeconds)]
'--stats']
# keepWithin
if repo['retention'].get('last') is not None:
if isinstance(repo['retention'].get('last'), datetime.timedelta): # it's a time.timedelta
retentionSeconds = repo['retention'].total_seconds()
else: # it's an isodate.Duration
retentionSeconds = repo['retention'].totimedelta(datetime.datetime.now()).total_seconds()
_cmd.extend(['--keep-within', '{0}H'.format(retentionSeconds / 60)])
# keepLast
for e in policyperiods:
if repo['retention'].get(e.lower()) is not None:
a = e.lower() + 'ly'
if e.lower() == 'day':
a = 'daily'
_cmd.extend(['--keep-{0}'.format(a), repo['retention'][e.lower()]])
if self.repos[server]['remote'].lower()[0] in ('1', 't'):
repo_tgt = '{0}@{1}'.format(_user, server)
else: