~ubuntu-branches/ubuntu/trusty/swift/trusty-updates

« back to all changes in this revision

Viewing changes to bin/swift-recon

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2013-01-28 09:40:30 UTC
  • mfrom: (1.2.16)
  • Revision ID: package-import@ubuntu.com-20130128094030-aetz57x2qz9ye2d4
Tags: 1.7.6-0ubuntu1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
import os
20
20
 
21
21
 
 
22
def seconds2timeunit(seconds):
 
23
    elapsed = seconds
 
24
    unit = 'seconds'
 
25
    if elapsed >= 60:
 
26
        elapsed = elapsed / 60.0
 
27
        unit = 'minutes'
 
28
        if elapsed >= 60:
 
29
            elapsed = elapsed / 60.0
 
30
            unit = 'hours'
 
31
            if elapsed >= 24:
 
32
                elapsed = elapsed / 24.0
 
33
                unit = 'days'
 
34
    return elapsed, unit
 
35
 
 
36
 
22
37
class Scout(object):
23
38
    """
24
39
    Obtain swift recon information
25
40
    """
26
41
 
27
42
    def __init__(self, recon_type, verbose=False, suppress_errors=False,
28
 
                    timeout=5):
 
43
                 timeout=5):
29
44
        self.recon_type = recon_type
30
45
        self.verbose = verbose
31
46
        self.suppress_errors = suppress_errors
132
147
        """
133
148
        ring_data = Ring(swift_dir, ring_name=ring_name)
134
149
        if zone_filter:
135
 
            ips = set((n['ip'], n['port']) for n in ring_data.devs if n \
136
 
                if n['zone'] == zone_filter)
 
150
            ips = set((n['ip'], n['port']) for n in ring_data.devs
 
151
                      if n and n['zone'] == zone_filter)
137
152
        else:
138
153
            ips = set((n['ip'], n['port']) for n in ring_data.devs if n)
139
154
        return ips
157
172
                block = f.read(4096)
158
173
        ring_sum = md5sum.hexdigest()
159
174
        recon = Scout("ringmd5", self.verbose, self.suppress_errors,
160
 
                        self.timeout)
 
175
                      self.timeout)
161
176
        print "[%s] Checking ring md5sums" % self._ptime()
162
177
        if self.verbose:
163
178
            print "-> On disk %s md5sum: %s" % (ringfile, ring_sum)
173
188
                        print "-> %s matches." % url
174
189
            else:
175
190
                errors = errors + 1
176
 
        print "%s/%s hosts matched, %s error[s] while checking hosts." % \
177
 
                (matches, len(hosts), errors)
 
191
        print "%s/%s hosts matched, %s error[s] while checking hosts." \
 
192
            % (matches, len(hosts), errors)
178
193
        print "=" * 79
179
194
 
180
195
    def async_check(self, hosts):
186
201
        """
187
202
        scan = {}
188
203
        recon = Scout("async", self.verbose, self.suppress_errors,
189
 
                        self.timeout)
 
204
                      self.timeout)
190
205
        print "[%s] Checking async pendings" % self._ptime()
191
206
        for url, response, status in self.pool.imap(recon.scout, hosts):
192
207
            if status == 200:
207
222
        """
208
223
        stats = {}
209
224
        recon = Scout("unmounted", self.verbose, self.suppress_errors,
210
 
                        self.timeout)
 
225
                      self.timeout)
211
226
        print "[%s] Getting unmounted drives from %s hosts..." % \
212
227
            (self._ptime(), len(hosts))
213
228
        for url, response, status in self.pool.imap(recon.scout, hosts):
235
250
        for url, response, status in self.pool.imap(recon.scout, hosts):
236
251
            if status == 200:
237
252
                stats['object_expiration_pass'].append(
238
 
                                response.get('object_expiration_pass'))
 
253
                    response.get('object_expiration_pass'))
239
254
                stats['expired_last_pass'].append(
240
 
                                response.get('expired_last_pass'))
 
255
                    response.get('expired_last_pass'))
241
256
        for k in stats:
242
257
            if stats[k]:
243
258
                computed = self._gen_stats(stats[k], name=k)
261
276
        recon = Scout("replication/%s" % self.server_type, self.verbose,
262
277
                      self.suppress_errors, self.timeout)
263
278
        print "[%s] Checking on replication" % self._ptime()
 
279
        least_recent_time = 9999999999
 
280
        least_recent_url = None
 
281
        most_recent_time = 0
 
282
        most_recent_url = None
264
283
        for url, response, status in self.pool.imap(recon.scout, hosts):
265
284
            if status == 200:
266
285
                stats['replication_time'].append(
269
288
                if repl_stats:
270
289
                    for stat_key in ['attempted', 'failure', 'success']:
271
290
                        stats[stat_key].append(repl_stats.get(stat_key))
 
291
                last = response.get('replication_last', 0)
 
292
                if last < least_recent_time:
 
293
                    least_recent_time = last
 
294
                    least_recent_url = url
 
295
                if last > most_recent_time:
 
296
                    most_recent_time = last
 
297
                    most_recent_url = url
272
298
        for k in stats:
273
299
            if stats[k]:
274
300
                if k != 'replication_time':
282
308
                    print "[%s] - No hosts returned valid data." % k
283
309
            else:
284
310
                print "[%s] - No hosts returned valid data." % k
 
311
        if least_recent_url is not None:
 
312
            host = urlparse(url).netloc
 
313
            if not least_recent_time:
 
314
                print 'Oldest completion was NEVER by %s.' % host
 
315
            else:
 
316
                elapsed = time.time() - least_recent_time
 
317
                elapsed, elapsed_unit = seconds2timeunit(elapsed)
 
318
                print 'Oldest completion was %s (%d %s ago) by %s.' % (
 
319
                    time.strftime('%Y-%m-%d %H:%M:%S',
 
320
                                  time.gmtime(least_recent_time)),
 
321
                    elapsed, elapsed_unit, host)
 
322
        if most_recent_url is not None:
 
323
            host = urlparse(url).netloc
 
324
            elapsed = time.time() - most_recent_time
 
325
            elapsed, elapsed_unit = seconds2timeunit(elapsed)
 
326
            print 'Most recent completion was %s (%d %s ago) by %s.' % (
 
327
                time.strftime('%Y-%m-%d %H:%M:%S',
 
328
                              time.gmtime(most_recent_time)),
 
329
                elapsed, elapsed_unit, host)
285
330
        print "=" * 79
286
331
 
287
332
    def object_replication_check(self, hosts):
293
338
        """
294
339
        stats = {}
295
340
        recon = Scout("replication", self.verbose, self.suppress_errors,
296
 
                        self.timeout)
 
341
                      self.timeout)
297
342
        print "[%s] Checking on replication" % self._ptime()
 
343
        least_recent_time = 9999999999
 
344
        least_recent_url = None
 
345
        most_recent_time = 0
 
346
        most_recent_url = None
298
347
        for url, response, status in self.pool.imap(recon.scout, hosts):
299
348
            if status == 200:
300
349
                stats[url] = response['object_replication_time']
 
350
                last = response.get('object_replication_last', 0)
 
351
                if last < least_recent_time:
 
352
                    least_recent_time = last
 
353
                    least_recent_url = url
 
354
                if last > most_recent_time:
 
355
                    most_recent_time = last
 
356
                    most_recent_url = url
301
357
        times = [x for x in stats.values() if x is not None]
302
358
        if len(stats) > 0 and len(times) > 0:
303
359
            computed = self._gen_stats(times, 'replication_time')
307
363
                print "[replication_time] - No hosts returned valid data."
308
364
        else:
309
365
            print "[replication_time] - No hosts returned valid data."
 
366
        if least_recent_url is not None:
 
367
            host = urlparse(url).netloc
 
368
            if not least_recent_time:
 
369
                print 'Oldest completion was NEVER by %s.' % host
 
370
            else:
 
371
                elapsed = time.time() - least_recent_time
 
372
                elapsed, elapsed_unit = seconds2timeunit(elapsed)
 
373
                print 'Oldest completion was %s (%d %s ago) by %s.' % (
 
374
                    time.strftime('%Y-%m-%d %H:%M:%S',
 
375
                                  time.gmtime(least_recent_time)),
 
376
                    elapsed, elapsed_unit, host)
 
377
        if most_recent_url is not None:
 
378
            host = urlparse(url).netloc
 
379
            elapsed = time.time() - most_recent_time
 
380
            elapsed, elapsed_unit = seconds2timeunit(elapsed)
 
381
            print 'Most recent completion was %s (%d %s ago) by %s.' % (
 
382
                time.strftime('%Y-%m-%d %H:%M:%S',
 
383
                              time.gmtime(most_recent_time)),
 
384
                elapsed, elapsed_unit, host)
310
385
        print "=" * 79
311
386
 
312
387
    def updater_check(self, hosts):
397
472
        errors = 'errors'
398
473
        quarantined = 'quarantined'
399
474
        recon = Scout("auditor/object", self.verbose, self.suppress_errors,
400
 
                        self.timeout)
 
475
                      self.timeout)
401
476
        print "[%s] Checking auditor stats " % self._ptime()
402
477
        for url, response, status in self.pool.imap(recon.scout, hosts):
403
478
            if status == 200:
459
534
        load5 = {}
460
535
        load15 = {}
461
536
        recon = Scout("load", self.verbose, self.suppress_errors,
462
 
                        self.timeout)
 
537
                      self.timeout)
463
538
        print "[%s] Checking load averages" % self._ptime()
464
539
        for url, response, status in self.pool.imap(recon.scout, hosts):
465
540
            if status == 200:
487
562
        conq = {}
488
563
        acctq = {}
489
564
        recon = Scout("quarantined", self.verbose, self.suppress_errors,
490
 
                        self.timeout)
 
565
                      self.timeout)
491
566
        print "[%s] Checking quarantine" % self._ptime()
492
567
        for url, response, status in self.pool.imap(recon.scout, hosts):
493
568
            if status == 200:
517
592
        timewait = {}
518
593
        orphan = {}
519
594
        recon = Scout("sockstat", self.verbose, self.suppress_errors,
520
 
                        self.timeout)
 
595
                      self.timeout)
521
596
        print "[%s] Checking socket usage" % self._ptime()
522
597
        for url, response, status in self.pool.imap(recon.scout, hosts):
523
598
            if status == 200:
527
602
                timewait[url] = response['time_wait']
528
603
                orphan[url] = response['orphan']
529
604
        stats = {"tcp_in_use": inuse4, "tcp_mem_allocated_bytes": mem,
530
 
                    "tcp6_in_use": inuse6, "time_wait": timewait,
531
 
                    "orphan": orphan}
 
605
                 "tcp6_in_use": inuse6, "time_wait": timewait,
 
606
                 "orphan": orphan}
532
607
        for item in stats:
533
608
            if len(stats[item]) > 0:
534
609
                computed = self._gen_stats(stats[item].values(), item)
537
612
                print "No hosts returned valid data."
538
613
        print "=" * 79
539
614
 
540
 
    def disk_usage(self, hosts):
 
615
    def disk_usage(self, hosts, top=0):
541
616
        """
542
617
        Obtain and print disk usage statistics
543
618
 
550
625
        raw_total_used = []
551
626
        raw_total_avail = []
552
627
        percents = {}
 
628
        top_percents = [(None, 0)] * top
553
629
        recon = Scout("diskusage", self.verbose, self.suppress_errors,
554
 
                        self.timeout)
 
630
                      self.timeout)
555
631
        print "[%s] Checking disk usage now" % self._ptime()
556
632
        for url, response, status in self.pool.imap(recon.scout, hosts):
557
633
            if status == 200:
563
639
                        raw_total_used.append(entry['used'])
564
640
                        raw_total_avail.append(entry['avail'])
565
641
                        hostusage.append(round(used, 2))
 
642
                        for ident, oused in top_percents:
 
643
                            if oused < used:
 
644
                                top_percents.append(
 
645
                                    (url + ' ' + entry['device'], used))
 
646
                                top_percents.sort(key=lambda x: -x[1])
 
647
                                top_percents.pop()
 
648
                                break
566
649
                stats[url] = hostusage
567
650
 
568
651
        for url in stats:
584
667
            print "Distribution Graph:"
585
668
            mul = 69.0 / max(percents.values())
586
669
            for percent in sorted(percents):
587
 
                print '% 3d%%%5d %s' % (percent, percents[percent], \
588
 
                    '*' * int(percents[percent] * mul))
 
670
                print '% 3d%%%5d %s' % (percent, percents[percent],
 
671
                                        '*' * int(percents[percent] * mul))
589
672
            raw_used = sum(raw_total_used)
590
673
            raw_avail = sum(raw_total_avail)
591
674
            raw_total = raw_used + raw_avail
597
680
        else:
598
681
            print "No hosts returned valid data."
599
682
        print "=" * 79
 
683
        if top_percents:
 
684
            print 'TOP %s' % top
 
685
            for ident, used in top_percents:
 
686
                if ident:
 
687
                    url, device = ident.split()
 
688
                    host = urlparse(url).netloc.split(':')[0]
 
689
                    print '%.02f%%  %s' % (used, '%-15s %s' % (host, device))
600
690
 
601
691
    def main(self):
602
692
        """
614
704
        '''
615
705
        args = optparse.OptionParser(usage)
616
706
        args.add_option('--verbose', '-v', action="store_true",
617
 
            help="Print verbose info")
 
707
                        help="Print verbose info")
618
708
        args.add_option('--suppress', action="store_true",
619
 
            help="Suppress most connection related errors")
 
709
                        help="Suppress most connection related errors")
620
710
        args.add_option('--async', '-a', action="store_true",
621
 
            help="Get async stats")
 
711
                        help="Get async stats")
622
712
        args.add_option('--replication', '-r', action="store_true",
623
 
            help="Get replication stats")
 
713
                        help="Get replication stats")
624
714
        args.add_option('--auditor', action="store_true",
625
 
            help="Get auditor stats")
 
715
                        help="Get auditor stats")
626
716
        args.add_option('--updater', action="store_true",
627
 
            help="Get updater stats")
 
717
                        help="Get updater stats")
628
718
        args.add_option('--expirer', action="store_true",
629
 
            help="Get expirer stats")
 
719
                        help="Get expirer stats")
630
720
        args.add_option('--unmounted', '-u', action="store_true",
631
 
            help="Check cluster for unmounted devices")
 
721
                        help="Check cluster for unmounted devices")
632
722
        args.add_option('--diskusage', '-d', action="store_true",
633
 
            help="Get disk usage stats")
 
723
                        help="Get disk usage stats")
634
724
        args.add_option('--loadstats', '-l', action="store_true",
635
 
            help="Get cluster load average stats")
 
725
                        help="Get cluster load average stats")
636
726
        args.add_option('--quarantined', '-q', action="store_true",
637
 
            help="Get cluster quarantine stats")
 
727
                        help="Get cluster quarantine stats")
638
728
        args.add_option('--md5', action="store_true",
639
 
            help="Get md5sum of servers ring and compare to local copy")
 
729
                        help="Get md5sum of servers ring and compare to "
 
730
                        "local copy")
640
731
        args.add_option('--sockstat', action="store_true",
641
 
            help="Get cluster socket usage stats")
 
732
                        help="Get cluster socket usage stats")
 
733
        args.add_option('--top', type='int', metavar='COUNT', default=0,
 
734
                        help='Also show the top COUNT entries in rank order.')
642
735
        args.add_option('--all', action="store_true",
643
 
            help="Perform all checks. Equal to -arudlq --md5 --sockstat")
 
736
                        help="Perform all checks. Equal to -arudlq --md5 "
 
737
                        "--sockstat")
644
738
        args.add_option('--zone', '-z', type="int",
645
 
            help="Only query servers in specified zone")
 
739
                        help="Only query servers in specified zone")
646
740
        args.add_option('--timeout', '-t', type="int", metavar="SECONDS",
647
 
            help="Time to wait for a response from a server", default=5)
 
741
                        help="Time to wait for a response from a server",
 
742
                        default=5)
648
743
        args.add_option('--swiftdir', default="/etc/swift",
649
 
            help="Default = /etc/swift")
 
744
                        help="Default = /etc/swift")
650
745
        options, arguments = args.parse_args()
651
746
 
652
747
        if len(sys.argv) <= 1 or len(arguments) > 1:
728
823
            if options.loadstats:
729
824
                self.load_check(hosts)
730
825
            if options.diskusage:
731
 
                self.disk_usage(hosts)
 
826
                self.disk_usage(hosts, options.top)
732
827
            if options.md5:
733
828
                self.get_ringmd5(hosts, ring_file)
734
829
            if options.quarantined: