Merge lp:~pandemicsyn/swift/recon-quarantine into lp:~hudson-openstack/swift/trunk

Proposed by Florian Hines
Status: Merged
Approved by: John Dickinson
Approved revision: 345
Merged at revision: 345
Proposed branch: lp:~pandemicsyn/swift/recon-quarantine
Merge into: lp:~hudson-openstack/swift/trunk
Diff against target: 163 lines (+61/-8)
2 files modified
bin/swift-recon (+46/-8)
swift/common/middleware/recon.py (+15/-0)
To merge this branch: bzr merge lp:~pandemicsyn/swift/recon-quarantine
Reviewer Review Type Date Requested Status
Jay Payne (community) Approve
John Dickinson Approve
Review via email: mp+71458@code.launchpad.net

Description of the change

Add support for pulling quarantine stats.

To post a comment you must log in.
345. By Florian Hines

pep8 fix

Revision history for this message
John Dickinson (notmyname) wrote :

lgtm

I didn't know about st_nlink. That's really cool.

review: Approve
Revision history for this message
Jay Payne (letterj) wrote :

looks good

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/swift-recon'
2--- bin/swift-recon 2011-07-27 15:41:07 +0000
3+++ bin/swift-recon 2011-08-14 15:51:20 +0000
4@@ -11,6 +11,7 @@
5 import datetime
6 import eventlet
7 import optparse
8+import sys
9 import os
10
11 VERBOSE = False
12@@ -83,6 +84,12 @@
13 return url, content, status
14
15
16+def scout_quarantine(host):
17+ base_url = "http://%s:%s/recon/" % (host[0], host[1])
18+ url, content, status = scout(base_url, "quarantined")
19+ return url, content, status
20+
21+
22 def get_ringmd5(ringfile):
23 stats = {}
24 matches = 0
25@@ -137,12 +144,11 @@
26 print "Async stats: low: %d, high: %d, avg: %d, total: %d" % (low,
27 high, average, total)
28 else:
29- print "Error: No hosts where available or returned valid information."
30+ print "Error: No hosts available or returned valid information."
31 print "=" * 79
32
33
34 def umount_check():
35- ASYNC_COUNTER = 0
36 stats = {}
37 hosts = getdevices()
38 pool = eventlet.GreenPool(20)
39@@ -174,7 +180,7 @@
40 print "[Replication Times] shortest: %s, longest: %s, avg: %s" % \
41 (low, high, average)
42 else:
43- print "Error: No hosts where available or returned valid information."
44+ print "Error: No hosts available or returned valid information."
45 print "=" * 79
46
47
48@@ -201,7 +207,34 @@
49 print "[%s load average] lowest: %s, highest: %s, avg: %s" % \
50 (item, low, high, average)
51 else:
52- print "Error: Hosts unavailable or returned valid information."
53+ print "Error: No hosts available or returned valid information."
54+ print "=" * 79
55+
56+
57+def quarantine_check():
58+ objq = {}
59+ conq = {}
60+ acctq = {}
61+ hosts = getdevices()
62+ pool = eventlet.GreenPool(20)
63+ now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
64+ print "[%s] Checking quarantine dirs on %s hosts..." % (now, len(hosts))
65+ for url, response, status in pool.imap(scout_quarantine, hosts):
66+ if status == 200:
67+ objq[url] = response['objects']
68+ conq[url] = response['containers']
69+ acctq[url] = response['accounts']
70+ stats = {"objects": objq, "containers": conq, "accounts": acctq}
71+ for item in stats:
72+ if len(stats[item]) > 0:
73+ low = min(stats[item].values())
74+ high = max(stats[item].values())
75+ total = sum(stats[item].values())
76+ average = total / len(stats[item])
77+ print "[Quarantined %s] low: %d, high: %d, avg: %d, total: %d" % \
78+ (item, low, high, average, total)
79+ else:
80+ print "Error: No hosts available or returned valid information."
81 print "=" * 79
82
83
84@@ -253,7 +286,7 @@
85 print "Disk usage: lowest: %s%%, highest: %s%%, avg: %s%%" % \
86 (low, high, average)
87 else:
88- print "Error: No hosts where available or returned valid information."
89+ print "Error: No hosts available or returned valid information."
90 print "=" * 79
91
92
93@@ -261,7 +294,7 @@
94 global VERBOSE, SUPPRESS_ERRORS, swift_dir, pool
95 print "=" * 79
96 usage = '''
97- usage: %prog [-v] [--suppress] [-a] [-r] [-u] [-d] [-l] [-c] [--objmd5]
98+ usage: %prog [-v] [--suppress] [-a] [-r] [-u] [-d] [-l] [--objmd5]
99 '''
100 args = optparse.OptionParser(usage)
101 args.add_option('--verbose', '-v', action="store_true",
102@@ -278,14 +311,17 @@
103 help="Get disk usage stats")
104 args.add_option('--loadstats', '-l', action="store_true",
105 help="Get cluster load average stats")
106- args.add_option('--connstats', '-c', action="store_true",
107- help="Get connection stats")
108+ args.add_option('--quarantined', '-q', action="store_true",
109+ help="Get cluster quarantine stats")
110 args.add_option('--objmd5', action="store_true",
111 help="Get md5sums of object.ring.gz and compare to local copy")
112 args.add_option('--swiftdir', default="/etc/swift",
113 help="Default = /etc/swift")
114 options, arguments = args.parse_args()
115
116+ if len(sys.argv) <= 1:
117+ args.print_help()
118+
119 swift_dir = options.swiftdir
120
121 VERBOSE = options.verbose
122@@ -303,6 +339,8 @@
123 disk_usage()
124 if options.objmd5:
125 get_ringmd5(os.path.join(swift_dir, 'object.ring.gz'))
126+ if options.quarantined:
127+ quarantine_check()
128
129
130 if __name__ == '__main__':
131
132=== modified file 'swift/common/middleware/recon.py'
133--- swift/common/middleware/recon.py 2011-08-02 02:43:55 +0000
134+++ swift/common/middleware/recon.py 2011-08-14 15:51:20 +0000
135@@ -154,6 +154,19 @@
136 sums[ringfile] = md5sum.hexdigest()
137 return sums
138
139+ def get_quarantine_count(self):
140+ """get obj/container/account quarantine counts"""
141+ qcounts = {"objects": 0, "containers": 0, "accounts": 0}
142+ qdir = "quarantined"
143+ for device in os.listdir(self.devices):
144+ for qtype in qcounts:
145+ qtgt = os.path.join(self.devices, device, qdir, qtype)
146+ if os.path.exists(qtgt):
147+ linkcount = os.lstat(qtgt).st_nlink
148+ if linkcount > 2:
149+ qcounts[qtype] += linkcount - 2
150+ return qcounts
151+
152 def GET(self, req):
153 error = False
154 root, type = split_path(req.path, 1, 2, False)
155@@ -186,6 +199,8 @@
156 content = json.dumps(self.get_diskusage())
157 elif type == "ringmd5":
158 content = json.dumps(self.get_ring_md5())
159+ elif type == "quarantined":
160+ content = json.dumps(self.get_quarantine_count())
161 else:
162 content = "Invalid path: %s" % req.path
163 return Response(request=req, status="400 Bad Request", \