1 |
#!/usr/bin/python |
2 |
|
3 |
import urllib2 |
4 |
import sys |
5 |
import time |
6 |
import stat |
7 |
import os |
8 |
from optparse import OptionParser |
9 |
|
10 |
### |
11 |
# Script to check if a local mirror is in sync with an HTTP-accessible remote |
12 |
# mirror (based on the /debian/project/trace file) |
13 |
# |
14 |
# Copyright (c) 2006 Andrew Pollock <me@andrew.net.au> |
15 |
# |
16 |
# Permission to use granted under the GNU General Public License v2 |
17 |
|
18 |
class DefaultErrorHandler(urllib2.HTTPDefaultErrorHandler): |
19 |
"""The class you need to have to get useful IMS functionality""" |
20 |
|
21 |
def http_error_default(self, req, fp, code, msg, headers): |
22 |
"""Returns the result code of the transaction""" |
23 |
|
24 |
result = urllib2.HTTPError( |
25 |
req.get_full_url(), code, msg, headers, fp) |
26 |
result.status = code |
27 |
return result |
28 |
|
29 |
|
30 |
def getLastModifiedTime(url): |
31 |
"""Makes a request for url and returns the Last-Modified header""" |
32 |
|
33 |
request = urllib2.Request(url) |
34 |
opener = urllib2.build_opener() |
35 |
data = opener.open(request) |
36 |
return(data.headers.dict["last-modified"]) |
37 |
|
38 |
|
39 |
def URLisNewerThan(url, epoch): |
40 |
"""Makes an IMS request for url with epoch as the modification time and returns if URL has changed""" |
41 |
|
42 |
request = urllib2.Request(url) |
43 |
request.add_header('If-Modified-Since', time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(epoch))) |
44 |
opener = urllib2.build_opener(DefaultErrorHandler()) |
45 |
data = opener.open(request) |
46 |
if (hasattr(data, 'status') and data.status == 304): |
47 |
return False |
48 |
else: |
49 |
return True |
50 |
|
51 |
|
52 |
def main(): |
53 |
parser = OptionParser() |
54 |
|
55 |
parser.set_description("Program to check if a local Debian mirror is out of sync with a remote Debian mirror") |
56 |
parser.add_option("-w", "--wait-time", dest="wait", default=300, type="int", |
57 |
help="Seconds to wait between checks for") |
58 |
parser.add_option("-m", "--max-retry", dest="maxretries", default=0, type="int", |
59 |
help="Maximum number of interations before giving up") |
60 |
parser.add_option("-v", "--verbose", action="store_true", |
61 |
dest="verbose", default=False, |
62 |
help="Print additional information about behaviour") |
63 |
|
64 |
(options, args) = parser.parse_args() |
65 |
|
66 |
if len(args) != 2: |
67 |
parser.print_usage() |
68 |
else: |
69 |
|
70 |
UPSTREAM=args[0] |
71 |
MIRROR_ROOT=args[1] |
72 |
upstream_trace = "".join(['http://', UPSTREAM, '/debian/project/trace/', UPSTREAM]) |
73 |
local_trace = os.path.join(MIRROR_ROOT, "debian", "project", "trace", UPSTREAM) |
74 |
|
75 |
#upstream_timestamp = calendar.timegm(time.strptime(getLastModifiedTime(upstream_trace), "%a, %d %b %Y %H:%M:%S %Z")) |
76 |
upstream_timestamp = getLastModifiedTime(upstream_trace) |
77 |
|
78 |
if options.verbose: |
79 |
print "Upstream trace file last modified on", upstream_timestamp |
80 |
|
81 |
local_trace_timestamp = os.stat(local_trace)[stat.ST_MTIME] |
82 |
|
83 |
if options.verbose: |
84 |
print "Our copy of trace file last modified on", time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(local_trace_timestamp)) |
85 |
|
86 |
if URLisNewerThan(upstream_trace, local_trace_timestamp): |
87 |
if options.verbose: |
88 |
print "Because the upstream trace file is newer than what is on the mirror, I think it's time to resync the mirror" |
89 |
sys.exit(0) |
90 |
else: |
91 |
if options.verbose: |
92 |
print "I believe our mirror to be in sync with the upstream" |
93 |
iterations = 0 |
94 |
while iterations < options.maxretries: |
95 |
if options.verbose: |
96 |
print "Sleeping for %d seconds" % options.wait |
97 |
time.sleep(options.wait) |
98 |
if URLisNewerThan(upstream_trace, local_trace_timestamp): |
99 |
upstream_timestamp = getLastModifiedTime(upstream_trace) |
100 |
break |
101 |
else: |
102 |
if options.verbose: |
103 |
print "Upstream trace file last modified on", upstream_timestamp |
104 |
iterations += 1 |
105 |
else: |
106 |
if options.verbose and iterations > 0: |
107 |
print "Giving up" |
108 |
sys.exit(1) |
109 |
if options.verbose: |
110 |
print "Upstream trace file last modified on", upstream_timestamp |
111 |
print "Because the upstream trace file is newer than what is on the mirror, I think it's time to resync the mirror" |
112 |
sys.exit(0) |
113 |
|
114 |
if __name__ == '__main__': |
115 |
main() |