updating to support configurable delay checking and rsync exit code ignoring
This commit is contained in:
parent
4bdb31541b
commit
bc9a653234
@ -69,16 +69,15 @@
|
|||||||
<long>links</long>
|
<long>links</long>
|
||||||
<long>hard-links</long>
|
<long>hard-links</long>
|
||||||
<long>delete-after</long>
|
<long>delete-after</long>
|
||||||
|
<long>perms</long>
|
||||||
<long>delay-updates</long>
|
<long>delay-updates</long>
|
||||||
<long>copy-links</long>
|
|
||||||
<long>safe-links</long>
|
<long>safe-links</long>
|
||||||
<long>delete-excluded</long>
|
<long>delete-excluded</long>
|
||||||
<long value=".*">exclude</long>
|
|
||||||
</rsyncArgs>
|
</rsyncArgs>
|
||||||
These arguments should be sane for most, if not all, rsync-driven repository mirroring. The last one (exclude) may
|
These arguments should be sane for most, if not all, rsync-driven repository mirroring.
|
||||||
be removed in future versions.
|
|
||||||
If arguments are provided, the defaults are overwritten so if you need the above, be sure to specify them.
|
If arguments are provided, the defaults are overwritten so if you need the above, be sure to specify them.
|
||||||
See the rsync man page (rsync(1)) for more details and a listing of supported flags on your system.
|
See the rsync man page (rsync(1)) for more details and a listing of supported flags on your system
|
||||||
|
(§ "OPTION SUMMARY", § "OPTIONS").
|
||||||
-->
|
-->
|
||||||
<rsyncArgs>
|
<rsyncArgs>
|
||||||
<!--
|
<!--
|
||||||
@ -94,7 +93,19 @@
|
|||||||
A "short" option (single hyphen).
|
A "short" option (single hyphen).
|
||||||
-->
|
-->
|
||||||
<short>c</short><!-- checksum -->
|
<short>c</short><!-- checksum -->
|
||||||
|
<!--
|
||||||
|
An option that requires to be enclosed in quotes. (This one excludes hidden files/directories.)
|
||||||
|
-->
|
||||||
|
<long value="".*"">exclude</long>
|
||||||
</rsyncArgs>
|
</rsyncArgs>
|
||||||
|
<!--
|
||||||
|
rsyncIgnore is an optional element that ignores certain return codes/exit statuses of rsync (otherwise they are
|
||||||
|
raised as warnings). It consists of a space-separated list of return codes that warnings should be suppressed for.
|
||||||
|
(Return code 0 never raises a warning, as it is success.)
|
||||||
|
See the rsync man page (rsync(1)) for a list of error codes and what they mean (§ "EXIT VALUES"), or refer to:
|
||||||
|
repomirror/fetcher/rsync_returns.py
|
||||||
|
-->
|
||||||
|
<rsyncIgnore returns="23 24"/>
|
||||||
<!--
|
<!--
|
||||||
Upstreams have an optional attribute, "delayCheck", which is an ISO 8601 duration type.
|
Upstreams have an optional attribute, "delayCheck", which is an ISO 8601 duration type.
|
||||||
https://en.wikipedia.org/wiki/ISO_8601#Durations
|
https://en.wikipedia.org/wiki/ISO_8601#Durations
|
||||||
|
@ -6,11 +6,11 @@ RSYNC_DEF_ARGS = ['--recursive',
|
|||||||
'--links',
|
'--links',
|
||||||
'--hard-links',
|
'--hard-links',
|
||||||
'--delete-after',
|
'--delete-after',
|
||||||
|
'--perms',
|
||||||
'--delay-updates',
|
'--delay-updates',
|
||||||
'--copy-links',
|
|
||||||
'--safe-links',
|
'--safe-links',
|
||||||
'--delete-excluded',
|
'--delete-excluded',
|
||||||
'--exclude=.*']
|
'--exclude=".*"']
|
||||||
|
|
||||||
# These are needed to convert years/months to timedeltas.
|
# These are needed to convert years/months to timedeltas.
|
||||||
# The following are averaged definitions for time units *in days* according to Google Calculator.
|
# The following are averaged definitions for time units *in days* according to Google Calculator.
|
||||||
|
@ -25,6 +25,7 @@ class RSync(_base.BaseFetcher):
|
|||||||
path,
|
path,
|
||||||
dest,
|
dest,
|
||||||
rsync_args = None,
|
rsync_args = None,
|
||||||
|
rsync_ignores = None,
|
||||||
owner = None,
|
owner = None,
|
||||||
log = True,
|
log = True,
|
||||||
filechecks = None,
|
filechecks = None,
|
||||||
@ -37,6 +38,7 @@ class RSync(_base.BaseFetcher):
|
|||||||
else:
|
else:
|
||||||
self.rsync_args = constants.RSYNC_DEF_ARGS[:]
|
self.rsync_args = constants.RSYNC_DEF_ARGS[:]
|
||||||
_logger.debug('RSync args given: {0}'.format(self.rsync_args))
|
_logger.debug('RSync args given: {0}'.format(self.rsync_args))
|
||||||
|
self.rsync_ignores = rsync_ignores[:]
|
||||||
if log:
|
if log:
|
||||||
# Do I want to do this in subprocess + logging module? Or keep this?
|
# Do I want to do this in subprocess + logging module? Or keep this?
|
||||||
# It looks a little ugly in the log but it makes more sense than doing it via subprocess just to write it
|
# It looks a little ugly in the log but it makes more sense than doing it via subprocess just to write it
|
||||||
@ -68,10 +70,10 @@ class RSync(_base.BaseFetcher):
|
|||||||
stderr = subprocess.PIPE)
|
stderr = subprocess.PIPE)
|
||||||
stdout = cmd.stdout.decode('utf-8').strip()
|
stdout = cmd.stdout.decode('utf-8').strip()
|
||||||
stderr = cmd.stderr.decode('utf-8').strip()
|
stderr = cmd.stderr.decode('utf-8').strip()
|
||||||
|
rtrn = cmd.returncode
|
||||||
if stdout != '':
|
if stdout != '':
|
||||||
_logger.debug('STDOUT: {0}'.format(stdout))
|
_logger.debug('STDOUT: {0}'.format(stdout))
|
||||||
if stderr != '' or cmd.returncode != 0:
|
if stderr != '' or (rtrn != 0 and rtrn not in self.rsync_ignores):
|
||||||
rtrn = cmd.returncode
|
|
||||||
err = rsync_returns.returns[rtrn]
|
err = rsync_returns.returns[rtrn]
|
||||||
errmsg = 'Rsync to {0}:{1} returned'.format(self.domain, self.port)
|
errmsg = 'Rsync to {0}:{1} returned'.format(self.domain, self.port)
|
||||||
debugmsg = 'Rsync command {0} returned'.format(' '.join(cmd_str))
|
debugmsg = 'Rsync command {0} returned'.format(' '.join(cmd_str))
|
||||||
@ -100,10 +102,10 @@ class RSync(_base.BaseFetcher):
|
|||||||
stderr = subprocess.PIPE)
|
stderr = subprocess.PIPE)
|
||||||
stdout = cmd.stdout.decode('utf-8').strip()
|
stdout = cmd.stdout.decode('utf-8').strip()
|
||||||
stderr = cmd.stderr.decode('utf-8').strip()
|
stderr = cmd.stderr.decode('utf-8').strip()
|
||||||
|
rtrn = cmd.returncode
|
||||||
if stdout != '':
|
if stdout != '':
|
||||||
_logger.debug('STDOUT: {0}'.format(stdout))
|
_logger.debug('STDOUT: {0}'.format(stdout))
|
||||||
if stderr != '' or cmd.returncode != 0:
|
if stderr != '' or (rtrn != 0 and rtrn not in self.rsync_ignores):
|
||||||
rtrn = cmd.returncode
|
|
||||||
err = rsync_returns.returns[rtrn]
|
err = rsync_returns.returns[rtrn]
|
||||||
errmsg = 'Rsync to {0}:{1} returned'.format(self.domain, self.port)
|
errmsg = 'Rsync to {0}:{1} returned'.format(self.domain, self.port)
|
||||||
debugmsg = 'Rsync command {0} returned'.format(' '.join(cmd_str))
|
debugmsg = 'Rsync command {0} returned'.format(' '.join(cmd_str))
|
||||||
|
@ -35,7 +35,6 @@ _duration_re = re.compile(('^P'
|
|||||||
'$'))
|
'$'))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_owner(owner_xml):
|
def get_owner(owner_xml):
|
||||||
owner = {}
|
owner = {}
|
||||||
user = owner_xml.find('user')
|
user = owner_xml.find('user')
|
||||||
@ -154,7 +153,7 @@ class TimestampFile(object):
|
|||||||
|
|
||||||
|
|
||||||
class Upstream(object):
|
class Upstream(object):
|
||||||
def __init__(self, upstream_xml, dest, rsync_args = None, owner = None, filechecks = None):
|
def __init__(self, upstream_xml, dest, rsync_args = None, owner = None, filechecks = None, rsync_ignores = None):
|
||||||
self.xml = upstream_xml
|
self.xml = upstream_xml
|
||||||
# These are required for all upstreams.
|
# These are required for all upstreams.
|
||||||
self.sync_type = self.xml.find('syncType').text.lower()
|
self.sync_type = self.xml.find('syncType').text.lower()
|
||||||
@ -179,6 +178,7 @@ class Upstream(object):
|
|||||||
self.path,
|
self.path,
|
||||||
self.dest,
|
self.dest,
|
||||||
rsync_args = rsync_args,
|
rsync_args = rsync_args,
|
||||||
|
rsync_ignores = rsync_ignores,
|
||||||
filechecks = self.filechecks,
|
filechecks = self.filechecks,
|
||||||
owner = self.owner)
|
owner = self.owner)
|
||||||
else:
|
else:
|
||||||
@ -225,6 +225,7 @@ class Distro(object):
|
|||||||
'sync': None}}
|
'sync': None}}
|
||||||
self.timestamps = {}
|
self.timestamps = {}
|
||||||
self.rsync_args = None
|
self.rsync_args = None
|
||||||
|
self.rsync_ignores = None
|
||||||
self.owner = None
|
self.owner = None
|
||||||
self.upstreams = []
|
self.upstreams = []
|
||||||
self.lockfile = '/var/run/repomirror/{0}.lck'.format(self.name)
|
self.lockfile = '/var/run/repomirror/{0}.lck'.format(self.name)
|
||||||
@ -243,12 +244,17 @@ class Distro(object):
|
|||||||
e = self.xml.find('lastRemote{0}'.format(i))
|
e = self.xml.find('lastRemote{0}'.format(i))
|
||||||
if e is not None:
|
if e is not None:
|
||||||
self.filechecks['remote'][i.lower()] = TimestampFile(e)
|
self.filechecks['remote'][i.lower()] = TimestampFile(e)
|
||||||
|
self.rsync_ignores = []
|
||||||
|
rsyncig_xml = self.xml.find('rsyncIgnore')
|
||||||
|
if rsyncig_xml is not None:
|
||||||
|
self.rsync_ignores = [int(i.strip()) for i in rsyncig_xml.attrib['returns'].split()]
|
||||||
for u in self.xml.findall('upstream'):
|
for u in self.xml.findall('upstream'):
|
||||||
self.upstreams.append(Upstream(u,
|
self.upstreams.append(Upstream(u,
|
||||||
self.dest,
|
self.dest,
|
||||||
rsync_args = self.rsync_args,
|
rsync_args = self.rsync_args,
|
||||||
owner = self.owner,
|
owner = self.owner,
|
||||||
filechecks = self.filechecks))
|
filechecks = self.filechecks,
|
||||||
|
rsync_ignores = self.rsync_ignores))
|
||||||
|
|
||||||
def check(self):
|
def check(self):
|
||||||
for k, v in self.filechecks['local'].items():
|
for k, v in self.filechecks['local'].items():
|
||||||
@ -285,11 +291,11 @@ class Distro(object):
|
|||||||
else:
|
else:
|
||||||
_logger.info('No remote update timestamp; syncing.')
|
_logger.info('No remote update timestamp; syncing.')
|
||||||
u.has_new = True
|
u.has_new = True
|
||||||
if sync:
|
if sync and u.delay:
|
||||||
td = datetime.datetime.utcnow() - sync
|
td = datetime.datetime.utcnow() - sync
|
||||||
if td.days > constants.DAYS_WARN:
|
if td.days > u.delay:
|
||||||
_logger.warning(('Upstream {0} has not synced for {1} or more days; this '
|
_logger.warning(('Upstream {0} has not synced for {1} or longer; this '
|
||||||
'repository may be out of date.').format(u.fetcher.url, constants.DAYS_WARN))
|
'repository may be out of date.').format(u.fetcher.url, u.delay))
|
||||||
warnings.warn('Upstream may be out of date')
|
warnings.warn('Upstream may be out of date')
|
||||||
return(None)
|
return(None)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user