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
115
116
117
118
119
120
121
|
#!/usr/bin/python
import logging
import urllib2
import time
import rfc822
import re
class GardCheck:
# Base class which provides some helper functions
def __init__(self, url, log=True):
self.url = url
if log:
self.logger = logging.getLogger('')
else:
self.logger = None
def log_info(self, msg):
if self.logger is not None:
self.logger.info(msg)
def log_error(self, msg):
if self.logger is not None:
self.logger.error(msg)
def check_file_exists(self, url):
ret = True
try:
f = urllib2.urlopen(url)
if len(f.read()) == 0:
raise IOError
except:
ret = False
return ret
# Takes the URL to a timestamp.{chk|x} file and returns the
# corresponding time stamp in seconds
def _get_timestamp_from_url(self, url):
try:
f = urllib2.urlopen(url)
date = f.read()
f.close()
if date is None or len(date) == 0:
raise ValueError
try:
# timestamp.chk format
ts = self.timestamp_to_secs(date)
except:
# timestamp.x format?
ts = float(date.split(' ')[0])
except:
return None
return ts
def get_lag(self, path):
ts = self._get_timestamp_from_url(self.url + path)
now = time.mktime(time.gmtime())
if ts is None or now < ts:
return None
return now - ts
def humanize_time(self, secs):
mins, secs = divmod(secs, 60)
hours, mins = divmod(mins, 60)
days, hours = divmod(hours, 24)
return '%02dd %02dh %02dm %02ds' % (days, hours, mins, secs)
def timestamp_to_secs(self, ts):
return rfc822.mktime_tz(rfc822.parsedate_tz(ts))
# OPTIONAL: Override or supplement these in child classes if desired.
def check_name(self):
return re.sub('.*\.|(Check$)', '', str(self.__class__))
def check(self, maxlag):
lag = self.lag()
if lag is None:
self.log_error('Could not get %s timestamp for %s' % (self.check_name(), self.url))
ret = False
elif lag > maxlag:
self.log_error('%s at %s is lagging (delta is %s)' \
% (self.check_name(), self.url, self.humanize_time(lag)))
ret = False
else:
ret = True
return ret
# REQUIRED: You must override these in child classes
def lag(self):
return None
# Check distfiles mirrors
class DistfilesCheck(GardCheck):
def lag(self):
path = '/distfiles/timestamp.chk'
return self.get_lag(path)
# Check releases mirrors
class ReleasesCheck(GardCheck):
def lag(self):
path = '/releases/.test/timestamp.x'
return self.get_lag(path)
def check(self, maxlag):
# Call the superclass first if exists
try: fun = getattr(GardCheck, 'check')
except AttributeError: pass
else: ret = fun(self, maxlag)
# Verify that releases/.test/THIS-FILE-SHOULD-NOT-BE-PUBLIC.txt
# is not world readable
if self.check_file_exists(self.url+'releases/.test/THIS-FILE-SHOULD-NOT-BE-PUBLIC.txt'):
self.log_error('ERROR: releases permission check failed on %s' % self.url)
ret = False
return ret
|