Time synchronization check in recon.
This change add call time to recon middleware and param --time to recon CLI. This is usefull for checking if time in cluster is synchronized. Change-Id: I62373e681f64d0bd71f4aeb287953dd3b2ea5662
This commit is contained in:
parent
f3f1f1cab9
commit
dd2f1be3b1
1
AUTHORS
1
AUTHORS
@ -156,6 +156,7 @@ Maru Newby (mnewby@internap.com)
|
|||||||
Newptone (xingchao@unitedstack.com)
|
Newptone (xingchao@unitedstack.com)
|
||||||
Colin Nicholson (colin.nicholson@iomart.com)
|
Colin Nicholson (colin.nicholson@iomart.com)
|
||||||
Zhenguo Niu (zhenguo@unitedstack.com)
|
Zhenguo Niu (zhenguo@unitedstack.com)
|
||||||
|
Ondrej Novy (ondrej.novy@firma.seznam.cz)
|
||||||
Timothy Okwii (tokwii@cisco.com)
|
Timothy Okwii (tokwii@cisco.com)
|
||||||
Matthew Oliver (matt@oliver.net.au)
|
Matthew Oliver (matt@oliver.net.au)
|
||||||
Hisashi Osanai (osanai.hisashi@jp.fujitsu.com)
|
Hisashi Osanai (osanai.hisashi@jp.fujitsu.com)
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.LP
|
.LP
|
||||||
.B swift-recon
|
.B swift-recon
|
||||||
\ <server_type> [-v] [--suppress] [-a] [-r] [-u] [-d] [-l] [--md5] [--auditor] [--updater] [--expirer] [--sockstat]
|
\ <server_type> [-v] [--suppress] [-a] [-r] [-u] [-d] [-l] [-T] [--md5] [--auditor] [--updater] [--expirer] [--sockstat]
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.PP
|
.PP
|
||||||
@ -80,8 +80,10 @@ Get md5sum of servers ring and compare to local copy
|
|||||||
Get cluster socket usage stats
|
Get cluster socket usage stats
|
||||||
.IP "\fB--driveaudit\fR"
|
.IP "\fB--driveaudit\fR"
|
||||||
Get drive audit error stats
|
Get drive audit error stats
|
||||||
|
.IP "\fB-T, --time\fR"
|
||||||
|
Check time synchronization
|
||||||
.IP "\fB--all\fR"
|
.IP "\fB--all\fR"
|
||||||
Perform all checks. Equivalent to \-arudlq \-\-md5
|
Perform all checks. Equivalent to \-arudlqT \-\-md5
|
||||||
.IP "\fB--region=REGION\fR"
|
.IP "\fB--region=REGION\fR"
|
||||||
Only query servers in specified region
|
Only query servers in specified region
|
||||||
.IP "\fB-z ZONE, --zone=ZONE\fR"
|
.IP "\fB-z ZONE, --zone=ZONE\fR"
|
||||||
|
@ -555,7 +555,7 @@ This information can also be queried via the swift-recon command line utility::
|
|||||||
fhines@ubuntu:~$ swift-recon -h
|
fhines@ubuntu:~$ swift-recon -h
|
||||||
Usage:
|
Usage:
|
||||||
usage: swift-recon <server_type> [-v] [--suppress] [-a] [-r] [-u] [-d]
|
usage: swift-recon <server_type> [-v] [--suppress] [-a] [-r] [-u] [-d]
|
||||||
[-l] [--md5] [--auditor] [--updater] [--expirer] [--sockstat]
|
[-l] [-T] [--md5] [--auditor] [--updater] [--expirer] [--sockstat]
|
||||||
|
|
||||||
<server_type> account|container|object
|
<server_type> account|container|object
|
||||||
Defaults to object server.
|
Defaults to object server.
|
||||||
@ -578,7 +578,8 @@ This information can also be queried via the swift-recon command line utility::
|
|||||||
-q, --quarantined Get cluster quarantine stats
|
-q, --quarantined Get cluster quarantine stats
|
||||||
--md5 Get md5sum of servers ring and compare to local copy
|
--md5 Get md5sum of servers ring and compare to local copy
|
||||||
--sockstat Get cluster socket usage stats
|
--sockstat Get cluster socket usage stats
|
||||||
--all Perform all checks. Equal to -arudlq --md5 --sockstat
|
-T, --time Check time synchronization
|
||||||
|
--all Perform all checks. Equal to -arudlqT --md5 --sockstat
|
||||||
-z ZONE, --zone=ZONE Only query servers in specified zone
|
-z ZONE, --zone=ZONE Only query servers in specified zone
|
||||||
-t SECONDS, --timeout=SECONDS
|
-t SECONDS, --timeout=SECONDS
|
||||||
Time to wait for a response from a server
|
Time to wait for a response from a server
|
||||||
|
@ -100,11 +100,14 @@ class Scout(object):
|
|||||||
Obtain telemetry from a host running the swift recon middleware.
|
Obtain telemetry from a host running the swift recon middleware.
|
||||||
|
|
||||||
:param host: host to check
|
:param host: host to check
|
||||||
:returns: tuple of (recon url used, response body, and status)
|
:returns: tuple of (recon url used, response body, status, time start
|
||||||
|
and time end)
|
||||||
"""
|
"""
|
||||||
base_url = "http://%s:%s/recon/" % (host[0], host[1])
|
base_url = "http://%s:%s/recon/" % (host[0], host[1])
|
||||||
|
ts_start = time.time()
|
||||||
url, content, status = self.scout_host(base_url, self.recon_type)
|
url, content, status = self.scout_host(base_url, self.recon_type)
|
||||||
return url, content, status
|
ts_end = time.time()
|
||||||
|
return url, content, status, ts_start, ts_end
|
||||||
|
|
||||||
def scout_server_type(self, host):
|
def scout_server_type(self, host):
|
||||||
"""
|
"""
|
||||||
@ -253,7 +256,8 @@ class SwiftRecon(object):
|
|||||||
if self.verbose:
|
if self.verbose:
|
||||||
for ring_file, ring_sum in rings.items():
|
for ring_file, ring_sum in rings.items():
|
||||||
print("-> On disk %s md5sum: %s" % (ring_file, ring_sum))
|
print("-> On disk %s md5sum: %s" % (ring_file, ring_sum))
|
||||||
for url, response, status in self.pool.imap(recon.scout, hosts):
|
for url, response, status, ts_start, ts_end in self.pool.imap(
|
||||||
|
recon.scout, hosts):
|
||||||
if status != 200:
|
if status != 200:
|
||||||
errors = errors + 1
|
errors = errors + 1
|
||||||
continue
|
continue
|
||||||
@ -291,7 +295,8 @@ class SwiftRecon(object):
|
|||||||
printfn("[%s] Checking swift.conf md5sum" % self._ptime())
|
printfn("[%s] Checking swift.conf md5sum" % self._ptime())
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
printfn("-> On disk swift.conf md5sum: %s" % (conf_sum,))
|
printfn("-> On disk swift.conf md5sum: %s" % (conf_sum,))
|
||||||
for url, response, status in self.pool.imap(recon.scout, hosts):
|
for url, response, status, ts_start, ts_end in self.pool.imap(
|
||||||
|
recon.scout, hosts):
|
||||||
if status == 200:
|
if status == 200:
|
||||||
if response[SWIFT_CONF_FILE] != conf_sum:
|
if response[SWIFT_CONF_FILE] != conf_sum:
|
||||||
printfn("!! %s (%s) doesn't match on disk md5sum" %
|
printfn("!! %s (%s) doesn't match on disk md5sum" %
|
||||||
@ -317,7 +322,8 @@ class SwiftRecon(object):
|
|||||||
recon = Scout("async", self.verbose, self.suppress_errors,
|
recon = Scout("async", self.verbose, self.suppress_errors,
|
||||||
self.timeout)
|
self.timeout)
|
||||||
print("[%s] Checking async pendings" % self._ptime())
|
print("[%s] Checking async pendings" % self._ptime())
|
||||||
for url, response, status in self.pool.imap(recon.scout, hosts):
|
for url, response, status, ts_start, ts_end in self.pool.imap(
|
||||||
|
recon.scout, hosts):
|
||||||
if status == 200:
|
if status == 200:
|
||||||
scan[url] = response['async_pending']
|
scan[url] = response['async_pending']
|
||||||
stats = self._gen_stats(scan.values(), 'async_pending')
|
stats = self._gen_stats(scan.values(), 'async_pending')
|
||||||
@ -338,7 +344,8 @@ class SwiftRecon(object):
|
|||||||
recon = Scout("driveaudit", self.verbose, self.suppress_errors,
|
recon = Scout("driveaudit", self.verbose, self.suppress_errors,
|
||||||
self.timeout)
|
self.timeout)
|
||||||
print("[%s] Checking drive-audit errors" % self._ptime())
|
print("[%s] Checking drive-audit errors" % self._ptime())
|
||||||
for url, response, status in self.pool.imap(recon.scout, hosts):
|
for url, response, status, ts_start, ts_end in self.pool.imap(
|
||||||
|
recon.scout, hosts):
|
||||||
if status == 200:
|
if status == 200:
|
||||||
scan[url] = response['drive_audit_errors']
|
scan[url] = response['drive_audit_errors']
|
||||||
stats = self._gen_stats(scan.values(), 'drive_audit_errors')
|
stats = self._gen_stats(scan.values(), 'drive_audit_errors')
|
||||||
@ -361,7 +368,8 @@ class SwiftRecon(object):
|
|||||||
self.timeout)
|
self.timeout)
|
||||||
print("[%s] Getting unmounted drives from %s hosts..." %
|
print("[%s] Getting unmounted drives from %s hosts..." %
|
||||||
(self._ptime(), len(hosts)))
|
(self._ptime(), len(hosts)))
|
||||||
for url, response, status in self.pool.imap(recon.scout, hosts):
|
for url, response, status, ts_start, ts_end in self.pool.imap(
|
||||||
|
recon.scout, hosts):
|
||||||
if status == 200:
|
if status == 200:
|
||||||
unmounted[url] = []
|
unmounted[url] = []
|
||||||
errors[url] = []
|
errors[url] = []
|
||||||
@ -414,7 +422,8 @@ class SwiftRecon(object):
|
|||||||
recon = Scout("expirer/%s" % self.server_type, self.verbose,
|
recon = Scout("expirer/%s" % self.server_type, self.verbose,
|
||||||
self.suppress_errors, self.timeout)
|
self.suppress_errors, self.timeout)
|
||||||
print("[%s] Checking on expirers" % self._ptime())
|
print("[%s] Checking on expirers" % self._ptime())
|
||||||
for url, response, status in self.pool.imap(recon.scout, hosts):
|
for url, response, status, ts_start, ts_end in self.pool.imap(
|
||||||
|
recon.scout, hosts):
|
||||||
if status == 200:
|
if status == 200:
|
||||||
stats['object_expiration_pass'].append(
|
stats['object_expiration_pass'].append(
|
||||||
response.get('object_expiration_pass'))
|
response.get('object_expiration_pass'))
|
||||||
@ -447,7 +456,8 @@ class SwiftRecon(object):
|
|||||||
least_recent_url = None
|
least_recent_url = None
|
||||||
most_recent_time = 0
|
most_recent_time = 0
|
||||||
most_recent_url = None
|
most_recent_url = None
|
||||||
for url, response, status in self.pool.imap(recon.scout, hosts):
|
for url, response, status, ts_start, ts_end in self.pool.imap(
|
||||||
|
recon.scout, hosts):
|
||||||
if status == 200:
|
if status == 200:
|
||||||
stats['replication_time'].append(
|
stats['replication_time'].append(
|
||||||
response.get('replication_time'))
|
response.get('replication_time'))
|
||||||
@ -511,7 +521,8 @@ class SwiftRecon(object):
|
|||||||
least_recent_url = None
|
least_recent_url = None
|
||||||
most_recent_time = 0
|
most_recent_time = 0
|
||||||
most_recent_url = None
|
most_recent_url = None
|
||||||
for url, response, status in self.pool.imap(recon.scout, hosts):
|
for url, response, status, ts_start, ts_end in self.pool.imap(
|
||||||
|
recon.scout, hosts):
|
||||||
if status == 200:
|
if status == 200:
|
||||||
stats[url] = response['object_replication_time']
|
stats[url] = response['object_replication_time']
|
||||||
last = response.get('object_replication_last', 0)
|
last = response.get('object_replication_last', 0)
|
||||||
@ -562,7 +573,8 @@ class SwiftRecon(object):
|
|||||||
recon = Scout("updater/%s" % self.server_type, self.verbose,
|
recon = Scout("updater/%s" % self.server_type, self.verbose,
|
||||||
self.suppress_errors, self.timeout)
|
self.suppress_errors, self.timeout)
|
||||||
print("[%s] Checking updater times" % self._ptime())
|
print("[%s] Checking updater times" % self._ptime())
|
||||||
for url, response, status in self.pool.imap(recon.scout, hosts):
|
for url, response, status, ts_start, ts_end in self.pool.imap(
|
||||||
|
recon.scout, hosts):
|
||||||
if status == 200:
|
if status == 200:
|
||||||
if response['%s_updater_sweep' % self.server_type]:
|
if response['%s_updater_sweep' % self.server_type]:
|
||||||
stats.append(response['%s_updater_sweep' %
|
stats.append(response['%s_updater_sweep' %
|
||||||
@ -592,7 +604,8 @@ class SwiftRecon(object):
|
|||||||
recon = Scout("auditor/%s" % self.server_type, self.verbose,
|
recon = Scout("auditor/%s" % self.server_type, self.verbose,
|
||||||
self.suppress_errors, self.timeout)
|
self.suppress_errors, self.timeout)
|
||||||
print("[%s] Checking auditor stats" % self._ptime())
|
print("[%s] Checking auditor stats" % self._ptime())
|
||||||
for url, response, status in self.pool.imap(recon.scout, hosts):
|
for url, response, status, ts_start, ts_end in self.pool.imap(
|
||||||
|
recon.scout, hosts):
|
||||||
if status == 200:
|
if status == 200:
|
||||||
scan[url] = response
|
scan[url] = response
|
||||||
if len(scan) < 1:
|
if len(scan) < 1:
|
||||||
@ -665,7 +678,8 @@ class SwiftRecon(object):
|
|||||||
recon = Scout("auditor/object", self.verbose, self.suppress_errors,
|
recon = Scout("auditor/object", self.verbose, self.suppress_errors,
|
||||||
self.timeout)
|
self.timeout)
|
||||||
print("[%s] Checking auditor stats " % self._ptime())
|
print("[%s] Checking auditor stats " % self._ptime())
|
||||||
for url, response, status in self.pool.imap(recon.scout, hosts):
|
for url, response, status, ts_start, ts_end in self.pool.imap(
|
||||||
|
recon.scout, hosts):
|
||||||
if status == 200:
|
if status == 200:
|
||||||
if response['object_auditor_stats_ALL']:
|
if response['object_auditor_stats_ALL']:
|
||||||
all_scan[url] = response['object_auditor_stats_ALL']
|
all_scan[url] = response['object_auditor_stats_ALL']
|
||||||
@ -736,7 +750,8 @@ class SwiftRecon(object):
|
|||||||
recon = Scout("load", self.verbose, self.suppress_errors,
|
recon = Scout("load", self.verbose, self.suppress_errors,
|
||||||
self.timeout)
|
self.timeout)
|
||||||
print("[%s] Checking load averages" % self._ptime())
|
print("[%s] Checking load averages" % self._ptime())
|
||||||
for url, response, status in self.pool.imap(recon.scout, hosts):
|
for url, response, status, ts_start, ts_end in self.pool.imap(
|
||||||
|
recon.scout, hosts):
|
||||||
if status == 200:
|
if status == 200:
|
||||||
load1[url] = response['1m']
|
load1[url] = response['1m']
|
||||||
load5[url] = response['5m']
|
load5[url] = response['5m']
|
||||||
@ -765,7 +780,8 @@ class SwiftRecon(object):
|
|||||||
recon = Scout("quarantined", self.verbose, self.suppress_errors,
|
recon = Scout("quarantined", self.verbose, self.suppress_errors,
|
||||||
self.timeout)
|
self.timeout)
|
||||||
print("[%s] Checking quarantine" % self._ptime())
|
print("[%s] Checking quarantine" % self._ptime())
|
||||||
for url, response, status in self.pool.imap(recon.scout, hosts):
|
for url, response, status, ts_start, ts_end in self.pool.imap(
|
||||||
|
recon.scout, hosts):
|
||||||
if status == 200:
|
if status == 200:
|
||||||
objq[url] = response['objects']
|
objq[url] = response['objects']
|
||||||
conq[url] = response['containers']
|
conq[url] = response['containers']
|
||||||
@ -799,7 +815,8 @@ class SwiftRecon(object):
|
|||||||
recon = Scout("sockstat", self.verbose, self.suppress_errors,
|
recon = Scout("sockstat", self.verbose, self.suppress_errors,
|
||||||
self.timeout)
|
self.timeout)
|
||||||
print("[%s] Checking socket usage" % self._ptime())
|
print("[%s] Checking socket usage" % self._ptime())
|
||||||
for url, response, status in self.pool.imap(recon.scout, hosts):
|
for url, response, status, ts_start, ts_end in self.pool.imap(
|
||||||
|
recon.scout, hosts):
|
||||||
if status == 200:
|
if status == 200:
|
||||||
inuse4[url] = response['tcp_in_use']
|
inuse4[url] = response['tcp_in_use']
|
||||||
mem[url] = response['tcp_mem_allocated_bytes']
|
mem[url] = response['tcp_mem_allocated_bytes']
|
||||||
@ -835,7 +852,8 @@ class SwiftRecon(object):
|
|||||||
recon = Scout("diskusage", self.verbose, self.suppress_errors,
|
recon = Scout("diskusage", self.verbose, self.suppress_errors,
|
||||||
self.timeout)
|
self.timeout)
|
||||||
print("[%s] Checking disk usage now" % self._ptime())
|
print("[%s] Checking disk usage now" % self._ptime())
|
||||||
for url, response, status in self.pool.imap(recon.scout, hosts):
|
for url, response, status, ts_start, ts_end in self.pool.imap(
|
||||||
|
recon.scout, hosts):
|
||||||
if status == 200:
|
if status == 200:
|
||||||
hostusage = []
|
hostusage = []
|
||||||
for entry in response:
|
for entry in response:
|
||||||
@ -915,6 +933,47 @@ class SwiftRecon(object):
|
|||||||
host = urlparse(url).netloc.split(':')[0]
|
host = urlparse(url).netloc.split(':')[0]
|
||||||
print('%.02f%% %s' % (used, '%-15s %s' % (host, device)))
|
print('%.02f%% %s' % (used, '%-15s %s' % (host, device)))
|
||||||
|
|
||||||
|
def time_check(self, hosts):
|
||||||
|
"""
|
||||||
|
Check a time synchronization of hosts with current time
|
||||||
|
|
||||||
|
:param hosts: set of hosts to check. in the format of:
|
||||||
|
set([('127.0.0.1', 6020), ('127.0.0.2', 6030)])
|
||||||
|
"""
|
||||||
|
|
||||||
|
matches = 0
|
||||||
|
errors = 0
|
||||||
|
recon = Scout("time", self.verbose, self.suppress_errors,
|
||||||
|
self.timeout)
|
||||||
|
print("[%s] Checking time-sync" % self._ptime())
|
||||||
|
for url, ts_remote, status, ts_start, ts_end in self.pool.imap(
|
||||||
|
recon.scout, hosts):
|
||||||
|
if status != 200:
|
||||||
|
errors = errors + 1
|
||||||
|
continue
|
||||||
|
if (ts_remote < ts_start or ts_remote > ts_end):
|
||||||
|
diff = abs(ts_end - ts_remote)
|
||||||
|
ts_end_f = time.strftime(
|
||||||
|
"%Y-%m-%d %H:%M:%S",
|
||||||
|
time.localtime(ts_end))
|
||||||
|
ts_remote_f = time.strftime(
|
||||||
|
"%Y-%m-%d %H:%M:%S",
|
||||||
|
time.localtime(ts_remote))
|
||||||
|
|
||||||
|
print("!! %s current time is %s, but remote is %s, "
|
||||||
|
"differs by %.2f sec" % (
|
||||||
|
url,
|
||||||
|
ts_end_f,
|
||||||
|
ts_remote_f,
|
||||||
|
diff))
|
||||||
|
continue
|
||||||
|
matches += 1
|
||||||
|
if self.verbose:
|
||||||
|
print("-> %s matches." % url)
|
||||||
|
print("%s/%s hosts matched, %s error[s] while checking hosts." % (
|
||||||
|
matches, len(hosts), errors))
|
||||||
|
print("=" * 79)
|
||||||
|
|
||||||
def main(self):
|
def main(self):
|
||||||
"""
|
"""
|
||||||
Retrieve and report cluster info from hosts running recon middleware.
|
Retrieve and report cluster info from hosts running recon middleware.
|
||||||
@ -922,7 +981,7 @@ class SwiftRecon(object):
|
|||||||
print("=" * 79)
|
print("=" * 79)
|
||||||
usage = '''
|
usage = '''
|
||||||
usage: %prog <server_type> [-v] [--suppress] [-a] [-r] [-u] [-d]
|
usage: %prog <server_type> [-v] [--suppress] [-a] [-r] [-u] [-d]
|
||||||
[-l] [--md5] [--auditor] [--updater] [--expirer] [--sockstat]
|
[-l] [-T] [--md5] [--auditor] [--updater] [--expirer] [--sockstat]
|
||||||
[--human-readable]
|
[--human-readable]
|
||||||
|
|
||||||
<server_type>\taccount|container|object
|
<server_type>\taccount|container|object
|
||||||
@ -964,13 +1023,15 @@ class SwiftRecon(object):
|
|||||||
help="Get cluster socket usage stats")
|
help="Get cluster socket usage stats")
|
||||||
args.add_option('--driveaudit', action="store_true",
|
args.add_option('--driveaudit', action="store_true",
|
||||||
help="Get drive audit error stats")
|
help="Get drive audit error stats")
|
||||||
|
args.add_option('--time', '-T', action="store_true",
|
||||||
|
help="Check time synchronization")
|
||||||
args.add_option('--top', type='int', metavar='COUNT', default=0,
|
args.add_option('--top', type='int', metavar='COUNT', default=0,
|
||||||
help='Also show the top COUNT entries in rank order.')
|
help='Also show the top COUNT entries in rank order.')
|
||||||
args.add_option('--lowest', type='int', metavar='COUNT', default=0,
|
args.add_option('--lowest', type='int', metavar='COUNT', default=0,
|
||||||
help='Also show the lowest COUNT entries in rank \
|
help='Also show the lowest COUNT entries in rank \
|
||||||
order.')
|
order.')
|
||||||
args.add_option('--all', action="store_true",
|
args.add_option('--all', action="store_true",
|
||||||
help="Perform all checks. Equal to \t\t\t-arudlq "
|
help="Perform all checks. Equal to \t\t\t-arudlqT "
|
||||||
"--md5 --sockstat --auditor --updater --expirer")
|
"--md5 --sockstat --auditor --updater --expirer")
|
||||||
args.add_option('--region', type="int",
|
args.add_option('--region', type="int",
|
||||||
help="Only query servers in specified region")
|
help="Only query servers in specified region")
|
||||||
@ -1031,6 +1092,7 @@ class SwiftRecon(object):
|
|||||||
self.socket_usage(hosts)
|
self.socket_usage(hosts)
|
||||||
self.server_type_check(hosts)
|
self.server_type_check(hosts)
|
||||||
self.driveaudit_check(hosts)
|
self.driveaudit_check(hosts)
|
||||||
|
self.time_check(hosts)
|
||||||
else:
|
else:
|
||||||
if options.async:
|
if options.async:
|
||||||
if self.server_type == 'object':
|
if self.server_type == 'object':
|
||||||
@ -1075,6 +1137,8 @@ class SwiftRecon(object):
|
|||||||
self.socket_usage(hosts)
|
self.socket_usage(hosts)
|
||||||
if options.driveaudit:
|
if options.driveaudit:
|
||||||
self.driveaudit_check(hosts)
|
self.driveaudit_check(hosts)
|
||||||
|
if options.time:
|
||||||
|
self.time_check(hosts)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import errno
|
import errno
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
from swift import gettext_ as _
|
from swift import gettext_ as _
|
||||||
|
|
||||||
from swift import __version__ as swiftver
|
from swift import __version__ as swiftver
|
||||||
@ -328,6 +329,11 @@ class ReconMiddleware(object):
|
|||||||
raise
|
raise
|
||||||
return sockstat
|
return sockstat
|
||||||
|
|
||||||
|
def get_time(self):
|
||||||
|
"""get current time"""
|
||||||
|
|
||||||
|
return time.time()
|
||||||
|
|
||||||
def GET(self, req):
|
def GET(self, req):
|
||||||
root, rcheck, rtype = req.split_path(1, 3, True)
|
root, rcheck, rtype = req.split_path(1, 3, True)
|
||||||
all_rtypes = ['account', 'container', 'object']
|
all_rtypes = ['account', 'container', 'object']
|
||||||
@ -368,6 +374,8 @@ class ReconMiddleware(object):
|
|||||||
content = self.get_version()
|
content = self.get_version()
|
||||||
elif rcheck == "driveaudit":
|
elif rcheck == "driveaudit":
|
||||||
content = self.get_driveaudit_error()
|
content = self.get_driveaudit_error()
|
||||||
|
elif rcheck == "time":
|
||||||
|
content = self.get_time()
|
||||||
else:
|
else:
|
||||||
content = "Invalid path: %s" % req.path
|
content = "Invalid path: %s" % req.path
|
||||||
return Response(request=req, status="404 Not Found",
|
return Response(request=req, status="404 Not Found",
|
||||||
|
@ -61,7 +61,7 @@ class TestScout(unittest.TestCase):
|
|||||||
@mock.patch('eventlet.green.urllib2.urlopen')
|
@mock.patch('eventlet.green.urllib2.urlopen')
|
||||||
def test_scout_ok(self, mock_urlopen):
|
def test_scout_ok(self, mock_urlopen):
|
||||||
mock_urlopen.return_value.read = lambda: json.dumps([])
|
mock_urlopen.return_value.read = lambda: json.dumps([])
|
||||||
url, content, status = self.scout_instance.scout(
|
url, content, status, ts_start, ts_end = self.scout_instance.scout(
|
||||||
("127.0.0.1", "8080"))
|
("127.0.0.1", "8080"))
|
||||||
self.assertEqual(url, self.url)
|
self.assertEqual(url, self.url)
|
||||||
self.assertEqual(content, [])
|
self.assertEqual(content, [])
|
||||||
@ -70,7 +70,7 @@ class TestScout(unittest.TestCase):
|
|||||||
@mock.patch('eventlet.green.urllib2.urlopen')
|
@mock.patch('eventlet.green.urllib2.urlopen')
|
||||||
def test_scout_url_error(self, mock_urlopen):
|
def test_scout_url_error(self, mock_urlopen):
|
||||||
mock_urlopen.side_effect = urllib2.URLError("")
|
mock_urlopen.side_effect = urllib2.URLError("")
|
||||||
url, content, status = self.scout_instance.scout(
|
url, content, status, ts_start, ts_end = self.scout_instance.scout(
|
||||||
("127.0.0.1", "8080"))
|
("127.0.0.1", "8080"))
|
||||||
self.assertTrue(isinstance(content, urllib2.URLError))
|
self.assertTrue(isinstance(content, urllib2.URLError))
|
||||||
self.assertEqual(url, self.url)
|
self.assertEqual(url, self.url)
|
||||||
@ -80,7 +80,7 @@ class TestScout(unittest.TestCase):
|
|||||||
def test_scout_http_error(self, mock_urlopen):
|
def test_scout_http_error(self, mock_urlopen):
|
||||||
mock_urlopen.side_effect = urllib2.HTTPError(
|
mock_urlopen.side_effect = urllib2.HTTPError(
|
||||||
self.url, 404, "Internal error", None, None)
|
self.url, 404, "Internal error", None, None)
|
||||||
url, content, status = self.scout_instance.scout(
|
url, content, status, ts_start, ts_end = self.scout_instance.scout(
|
||||||
("127.0.0.1", "8080"))
|
("127.0.0.1", "8080"))
|
||||||
self.assertEqual(url, self.url)
|
self.assertEqual(url, self.url)
|
||||||
self.assertTrue(isinstance(content, urllib2.HTTPError))
|
self.assertTrue(isinstance(content, urllib2.HTTPError))
|
||||||
@ -218,7 +218,7 @@ class TestRecon(unittest.TestCase):
|
|||||||
'/etc/swift/object-1.ring.gz': empty_file_hash,
|
'/etc/swift/object-1.ring.gz': empty_file_hash,
|
||||||
}
|
}
|
||||||
status = 200
|
status = 200
|
||||||
scout_instance.scout.return_value = (url, response, status)
|
scout_instance.scout.return_value = (url, response, status, 0, 0)
|
||||||
mock_scout.return_value = scout_instance
|
mock_scout.return_value = scout_instance
|
||||||
stdout = StringIO()
|
stdout = StringIO()
|
||||||
mock_hash = mock.MagicMock()
|
mock_hash = mock.MagicMock()
|
||||||
@ -274,7 +274,7 @@ class TestRecon(unittest.TestCase):
|
|||||||
url = 'http://%s:%s/recon/quarantined' % host
|
url = 'http://%s:%s/recon/quarantined' % host
|
||||||
response = responses[host[1]]
|
response = responses[host[1]]
|
||||||
status = 200
|
status = 200
|
||||||
return url, response, status
|
return url, response, status, 0, 0
|
||||||
|
|
||||||
stdout = StringIO()
|
stdout = StringIO()
|
||||||
patches = [
|
patches = [
|
||||||
@ -311,7 +311,7 @@ class TestRecon(unittest.TestCase):
|
|||||||
url = 'http://%s:%s/recon/driveaudit' % host
|
url = 'http://%s:%s/recon/driveaudit' % host
|
||||||
response = responses[host[1]]
|
response = responses[host[1]]
|
||||||
status = 200
|
status = 200
|
||||||
return url, response, status
|
return url, response, status, 0, 0
|
||||||
|
|
||||||
stdout = StringIO()
|
stdout = StringIO()
|
||||||
patches = [
|
patches = [
|
||||||
@ -491,7 +491,7 @@ class TestReconCommands(unittest.TestCase):
|
|||||||
return [('http://127.0.0.1:6010/recon/auditor/object', {
|
return [('http://127.0.0.1:6010/recon/auditor/object', {
|
||||||
'object_auditor_stats_ALL': values,
|
'object_auditor_stats_ALL': values,
|
||||||
'object_auditor_stats_ZBF': values,
|
'object_auditor_stats_ZBF': values,
|
||||||
}, 200)]
|
}, 200, 0, 0)]
|
||||||
|
|
||||||
response = {}
|
response = {}
|
||||||
|
|
||||||
@ -535,7 +535,9 @@ class TestReconCommands(unittest.TestCase):
|
|||||||
"avail": 15, "used": 85, "size": 100},
|
"avail": 15, "used": 85, "size": 100},
|
||||||
{"device": "sdd1", "mounted": True,
|
{"device": "sdd1", "mounted": True,
|
||||||
"avail": 15, "used": 85, "size": 100}],
|
"avail": 15, "used": 85, "size": 100}],
|
||||||
200)]
|
200,
|
||||||
|
0,
|
||||||
|
0)]
|
||||||
|
|
||||||
cli = recon.SwiftRecon()
|
cli = recon.SwiftRecon()
|
||||||
cli.pool.imap = dummy_request
|
cli.pool.imap = dummy_request
|
||||||
@ -586,11 +588,15 @@ class TestReconCommands(unittest.TestCase):
|
|||||||
('http://127.0.0.1:6010/recon/replication/object',
|
('http://127.0.0.1:6010/recon/replication/object',
|
||||||
{"object_replication_time": 61,
|
{"object_replication_time": 61,
|
||||||
"object_replication_last": now},
|
"object_replication_last": now},
|
||||||
200),
|
200,
|
||||||
|
0,
|
||||||
|
0),
|
||||||
('http://127.0.0.1:6020/recon/replication/object',
|
('http://127.0.0.1:6020/recon/replication/object',
|
||||||
{"object_replication_time": 23,
|
{"object_replication_time": 23,
|
||||||
"object_replication_last": now},
|
"object_replication_last": now},
|
||||||
200),
|
200,
|
||||||
|
0,
|
||||||
|
0),
|
||||||
]
|
]
|
||||||
|
|
||||||
cli = recon.SwiftRecon()
|
cli = recon.SwiftRecon()
|
||||||
@ -625,7 +631,9 @@ class TestReconCommands(unittest.TestCase):
|
|||||||
"remote_merge": 0, "diff_capped": 0, "start": now,
|
"remote_merge": 0, "diff_capped": 0, "start": now,
|
||||||
"hashmatch": 0, "diff": 0, "empty": 0},
|
"hashmatch": 0, "diff": 0, "empty": 0},
|
||||||
"replication_time": 42},
|
"replication_time": 42},
|
||||||
200),
|
200,
|
||||||
|
0,
|
||||||
|
0),
|
||||||
('http://127.0.0.1:6021/recon/replication/container',
|
('http://127.0.0.1:6021/recon/replication/container',
|
||||||
{"replication_last": now,
|
{"replication_last": now,
|
||||||
"replication_stats": {
|
"replication_stats": {
|
||||||
@ -634,7 +642,9 @@ class TestReconCommands(unittest.TestCase):
|
|||||||
"remote_merge": 0, "diff_capped": 0, "start": now,
|
"remote_merge": 0, "diff_capped": 0, "start": now,
|
||||||
"hashmatch": 0, "diff": 0, "empty": 0},
|
"hashmatch": 0, "diff": 0, "empty": 0},
|
||||||
"replication_time": 23},
|
"replication_time": 23},
|
||||||
200),
|
200,
|
||||||
|
0,
|
||||||
|
0),
|
||||||
]
|
]
|
||||||
|
|
||||||
cli = recon.SwiftRecon()
|
cli = recon.SwiftRecon()
|
||||||
@ -671,11 +681,15 @@ class TestReconCommands(unittest.TestCase):
|
|||||||
('http://127.0.0.1:6010/recon/load',
|
('http://127.0.0.1:6010/recon/load',
|
||||||
{"1m": 0.2, "5m": 0.4, "15m": 0.25,
|
{"1m": 0.2, "5m": 0.4, "15m": 0.25,
|
||||||
"processes": 10000, "tasks": "1/128"},
|
"processes": 10000, "tasks": "1/128"},
|
||||||
200),
|
200,
|
||||||
|
0,
|
||||||
|
0),
|
||||||
('http://127.0.0.1:6020/recon/load',
|
('http://127.0.0.1:6020/recon/load',
|
||||||
{"1m": 0.4, "5m": 0.8, "15m": 0.75,
|
{"1m": 0.4, "5m": 0.8, "15m": 0.75,
|
||||||
"processes": 9000, "tasks": "1/200"},
|
"processes": 9000, "tasks": "1/200"},
|
||||||
200),
|
200,
|
||||||
|
0,
|
||||||
|
0),
|
||||||
]
|
]
|
||||||
|
|
||||||
cli = recon.SwiftRecon()
|
cli = recon.SwiftRecon()
|
||||||
@ -695,3 +709,75 @@ class TestReconCommands(unittest.TestCase):
|
|||||||
# We need any_order=True because the order of calls depends on the dict
|
# We need any_order=True because the order of calls depends on the dict
|
||||||
# that is returned from the recon middleware, thus can't rely on it
|
# that is returned from the recon middleware, thus can't rely on it
|
||||||
mock_print.assert_has_calls(default_calls, any_order=True)
|
mock_print.assert_has_calls(default_calls, any_order=True)
|
||||||
|
|
||||||
|
@mock.patch('__builtin__.print')
|
||||||
|
@mock.patch('time.time')
|
||||||
|
def test_time_check(self, mock_now, mock_print):
|
||||||
|
now = 1430000000.0
|
||||||
|
mock_now.return_value = now
|
||||||
|
|
||||||
|
def dummy_request(*args, **kwargs):
|
||||||
|
return [
|
||||||
|
('http://127.0.0.1:6010/recon/load',
|
||||||
|
now,
|
||||||
|
200,
|
||||||
|
now - 0.5,
|
||||||
|
now + 0.5),
|
||||||
|
('http://127.0.0.1:6020/recon/load',
|
||||||
|
now,
|
||||||
|
200,
|
||||||
|
now,
|
||||||
|
now),
|
||||||
|
]
|
||||||
|
|
||||||
|
cli = recon.SwiftRecon()
|
||||||
|
cli.pool.imap = dummy_request
|
||||||
|
|
||||||
|
default_calls = [
|
||||||
|
mock.call('2/2 hosts matched, 0 error[s] while checking hosts.')
|
||||||
|
]
|
||||||
|
|
||||||
|
cli.time_check([('127.0.0.1', 6010), ('127.0.0.1', 6020)])
|
||||||
|
# We need any_order=True because the order of calls depends on the dict
|
||||||
|
# that is returned from the recon middleware, thus can't rely on it
|
||||||
|
mock_print.assert_has_calls(default_calls, any_order=True)
|
||||||
|
|
||||||
|
@mock.patch('__builtin__.print')
|
||||||
|
@mock.patch('time.time')
|
||||||
|
def test_time_check_mismatch(self, mock_now, mock_print):
|
||||||
|
now = 1430000000.0
|
||||||
|
mock_now.return_value = now
|
||||||
|
|
||||||
|
def dummy_request(*args, **kwargs):
|
||||||
|
return [
|
||||||
|
('http://127.0.0.1:6010/recon/time',
|
||||||
|
now,
|
||||||
|
200,
|
||||||
|
now + 0.5,
|
||||||
|
now + 1.3),
|
||||||
|
('http://127.0.0.1:6020/recon/time',
|
||||||
|
now,
|
||||||
|
200,
|
||||||
|
now,
|
||||||
|
now),
|
||||||
|
]
|
||||||
|
|
||||||
|
cli = recon.SwiftRecon()
|
||||||
|
cli.pool.imap = dummy_request
|
||||||
|
|
||||||
|
default_calls = [
|
||||||
|
mock.call("!! http://127.0.0.1:6010/recon/time current time is "
|
||||||
|
"2015-04-25 22:13:21, but remote is "
|
||||||
|
"2015-04-25 22:13:20, differs by 1.30 sec"),
|
||||||
|
mock.call('1/2 hosts matched, 0 error[s] while checking hosts.'),
|
||||||
|
]
|
||||||
|
|
||||||
|
def mock_localtime(*args, **kwargs):
|
||||||
|
return time.gmtime(*args, **kwargs)
|
||||||
|
|
||||||
|
with mock.patch("time.localtime", mock_localtime):
|
||||||
|
cli.time_check([('127.0.0.1', 6010), ('127.0.0.1', 6020)])
|
||||||
|
|
||||||
|
# We need any_order=True because the order of calls depends on the dict
|
||||||
|
# that is returned from the recon middleware, thus can't rely on it
|
||||||
|
mock_print.assert_has_calls(default_calls, any_order=True)
|
||||||
|
@ -175,6 +175,9 @@ class FakeRecon(object):
|
|||||||
def fake_driveaudit(self):
|
def fake_driveaudit(self):
|
||||||
return {'driveaudittest': "1"}
|
return {'driveaudittest': "1"}
|
||||||
|
|
||||||
|
def fake_time(self):
|
||||||
|
return {'timetest': "1"}
|
||||||
|
|
||||||
def nocontent(self):
|
def nocontent(self):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -855,6 +858,15 @@ class TestReconSuccess(TestCase):
|
|||||||
'/var/cache/swift/drive.recon'), {})])
|
'/var/cache/swift/drive.recon'), {})])
|
||||||
self.assertEquals(rv, {'drive_audit_errors': 7})
|
self.assertEquals(rv, {'drive_audit_errors': 7})
|
||||||
|
|
||||||
|
def test_get_time(self):
|
||||||
|
def fake_time():
|
||||||
|
return 1430000000.0
|
||||||
|
|
||||||
|
with mock.patch("time.time", fake_time):
|
||||||
|
now = fake_time()
|
||||||
|
rv = self.app.get_time()
|
||||||
|
self.assertEquals(rv, now)
|
||||||
|
|
||||||
|
|
||||||
class TestReconMiddleware(unittest.TestCase):
|
class TestReconMiddleware(unittest.TestCase):
|
||||||
|
|
||||||
@ -884,6 +896,7 @@ class TestReconMiddleware(unittest.TestCase):
|
|||||||
self.app.get_quarantine_count = self.frecon.fake_quarantined
|
self.app.get_quarantine_count = self.frecon.fake_quarantined
|
||||||
self.app.get_socket_info = self.frecon.fake_sockstat
|
self.app.get_socket_info = self.frecon.fake_sockstat
|
||||||
self.app.get_driveaudit_error = self.frecon.fake_driveaudit
|
self.app.get_driveaudit_error = self.frecon.fake_driveaudit
|
||||||
|
self.app.get_time = self.frecon.fake_time
|
||||||
|
|
||||||
def test_recon_get_mem(self):
|
def test_recon_get_mem(self):
|
||||||
get_mem_resp = ['{"memtest": "1"}']
|
get_mem_resp = ['{"memtest": "1"}']
|
||||||
@ -1118,5 +1131,12 @@ class TestReconMiddleware(unittest.TestCase):
|
|||||||
resp = self.app(req.environ, start_response)
|
resp = self.app(req.environ, start_response)
|
||||||
self.assertEquals(resp, get_driveaudit_resp)
|
self.assertEquals(resp, get_driveaudit_resp)
|
||||||
|
|
||||||
|
def test_recon_get_time(self):
|
||||||
|
get_time_resp = ['{"timetest": "1"}']
|
||||||
|
req = Request.blank('/recon/time',
|
||||||
|
environ={'REQUEST_METHOD': 'GET'})
|
||||||
|
resp = self.app(req.environ, start_response)
|
||||||
|
self.assertEquals(resp, get_time_resp)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Loading…
Reference in New Issue
Block a user