|
| 1 | +#!/usr/bin/env python |
| 2 | + |
| 3 | +# Monitoring API: http://groups.geni.net/geni/wiki/GENIMonitoring/API |
| 4 | + |
| 5 | +import urllib |
| 6 | +import urllib2 |
| 7 | +import json |
| 8 | +import datetime |
| 9 | +import time |
| 10 | +import pprint |
| 11 | +import sys |
| 12 | +import argparse |
| 13 | + |
| 14 | +BASE_URL = 'http://genimon.uky.edu/API' |
| 15 | +INFO_URL = '%s/info/' % (BASE_URL) |
| 16 | +DATA_URL = '%s/data/' % (BASE_URL) |
| 17 | + |
| 18 | +class Aggregate(object): |
| 19 | + """A representation of an aggregate from monitoring data""" |
| 20 | + def __init__(self, data): |
| 21 | + self.data = data |
| 22 | + |
| 23 | + @property |
| 24 | + def urn(self): |
| 25 | + if 'urn' in self.data: |
| 26 | + return self.data['urn'] |
| 27 | + else: |
| 28 | + return None |
| 29 | + |
| 30 | + @property |
| 31 | + def id(self): |
| 32 | + if 'id' in self.data: |
| 33 | + return self.data['id'] |
| 34 | + else: |
| 35 | + return None |
| 36 | + |
| 37 | +# TODO: Still need to HTTP encode the resulting query |
| 38 | +def buildMonQuery(**kwargs): |
| 39 | + return json.dumps(kwargs, separators=(',', ':')) |
| 40 | + |
| 41 | +def getIsAvailableEvents(agg_list): |
| 42 | + # http://genimon.uky.edu/API/data/?q={"eventType":["is_available"],"obj":{"id":["max-ig"],"type":"aggregate"},"output":"xml","ts":{"gte":1456345005000,"lt":1456348605000}} |
| 43 | + # end = datetime.datetime.utcnow() |
| 44 | + now = datetime.datetime.now() |
| 45 | + end = now + datetime.timedelta(minutes=0) |
| 46 | + start = end - datetime.timedelta(minutes=30) |
| 47 | + end_ts = int(time.mktime(end.timetuple()) * 1000) |
| 48 | + start_ts = int(time.mktime(start.timetuple()) * 1000) |
| 49 | + query = buildMonQuery(eventType=['is_available'], |
| 50 | + obj={'id':agg_list, |
| 51 | + 'type': 'aggregate'}, |
| 52 | + output='json', |
| 53 | + ts={'gte':start_ts, |
| 54 | + 'lt':end_ts}) |
| 55 | + query = urllib.urlencode({'q': query}) |
| 56 | + url = DATA_URL + '?' + query |
| 57 | + # print url |
| 58 | + f = urllib2.urlopen(url) |
| 59 | + all = f.read() |
| 60 | + f.close() |
| 61 | + try: |
| 62 | + return json.loads(all) |
| 63 | + except: |
| 64 | + raise |
| 65 | + |
| 66 | +def getAllAggregates(): |
| 67 | + # Get a list of aggregates from the monitoring server |
| 68 | + url = INFO_URL + '?q={"obj":{"type":"aggregate"},"output":"json","infoType":"simple"}' |
| 69 | + f = urllib2.urlopen(url) |
| 70 | + all = f.read() |
| 71 | + f.close() |
| 72 | + x = json.loads(all) |
| 73 | + all_aggs = [Aggregate(agg_data) for agg_data in x] |
| 74 | + return all_aggs |
| 75 | + |
| 76 | +def parse_args(argv): |
| 77 | + parser = argparse.ArgumentParser() |
| 78 | + parser.add_argument('-d', '--dest', |
| 79 | + default='@pkgsysconfdir@/am-status-mon.json', |
| 80 | + help='destination of output file') |
| 81 | + return parser.parse_args(argv) |
| 82 | + |
| 83 | +def main(argv=None): |
| 84 | + if argv is None: |
| 85 | + argv = sys.argv[1:] |
| 86 | + args = parse_args(argv) |
| 87 | + all_aggs = getAllAggregates() |
| 88 | + |
| 89 | + for a in all_aggs: |
| 90 | + event_data = getIsAvailableEvents([a.urn]) |
| 91 | + # pprint.pprint(by_urn) |
| 92 | + |
| 93 | + # Data is wrapped in an extra list |
| 94 | + event_data = event_data[0] |
| 95 | + # print a.urn |
| 96 | + if not event_data: |
| 97 | + # print "\tNo Data" |
| 98 | + a.status = "down" |
| 99 | + continue |
| 100 | + agg_data = event_data[0] |
| 101 | + ts_data = agg_data['tsdata'] |
| 102 | + #print ts_data |
| 103 | + available = False |
| 104 | + available_ts = 0 |
| 105 | + for ts in ts_data: |
| 106 | + if ts['ts'] > available_ts: |
| 107 | + available_ts = ts['ts'] |
| 108 | + available = ts['v'] |
| 109 | + pretty_time = time.strftime('%c', time.localtime(available_ts/1000)) |
| 110 | + # print "\t%s: %r" % (pretty_time, available) |
| 111 | + a.status = (available and "up") or "down" |
| 112 | + |
| 113 | + updown_status = {} |
| 114 | + for a in all_aggs: |
| 115 | + updown_status[a.urn] = a.status |
| 116 | + |
| 117 | + # Write the data out to the destination file |
| 118 | + with open(args.dest, "w") as out: |
| 119 | + json.dump(updown_status, out, indent=2, sort_keys=True) |
| 120 | + return 0 |
| 121 | + |
| 122 | + |
| 123 | +if __name__ == '__main__': |
| 124 | + sys.exit(main()) |
0 commit comments