Skip to content

Commit 085515f

Browse files
committed
Add geni-fetch-aggmon
Add script to fetch up/down status of aggregate managers from the GENI monitoring server.
1 parent 0757bcb commit 085515f

File tree

4 files changed

+157
-1
lines changed

4 files changed

+157
-1
lines changed

man/Makefile.am

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
dist_man_MANS = \
2-
geni-fetch-amdown.1 \
2+
geni-fetch-aggmon.1 \
3+
geni-fetch-amdown.1 \
34
geni-get-ad-rspecs.1 \
45
geni-parse-map-data.1 \
56
geni-portal-install-templates.1 \

man/geni-fetch-aggmon.1

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
.\" Hey, EMACS: -*- nroff -*-
2+
.TH GENI-FETCH-AGGMON 1 "March 29, 2016"
3+
.SH NAME
4+
geni-fetch-aggmon \- Fetch status of aggregate managers from GENI monitoring
5+
.SH SYNOPSIS
6+
.B geni-fetch-aggmon
7+
[-h] [-d DEST]
8+
.br
9+
.SH DESCRIPTION
10+
.B geni-fetch-aggmon
11+
fetches aggregate status from the GENI monitoring server.
12+
.B geni-fetch-aggmon
13+
reads the "available" event data to determine whether an aggregate
14+
is available. A JSON file is output, mapping aggregate URNs to either
15+
"up" or "down". The data is written to the destination specified with the
16+
.I \-d
17+
argument.
18+
.SH OPTIONS
19+
A summary of options is included below.
20+
.TP
21+
.B \-d, \-\-dest <DEST>
22+
The name of the output file
23+
.TP
24+
.B \-h, \-\-help
25+
Show summary of options
26+
.SH BUGS
27+
None known.
28+
.SH AUTHOR
29+
geni-fetch-aggmon was written by Raytheon BBN Technologies.

sbin/Makefile.am

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ edit = sed \
99
-e 's|@templatesdir[@]|$(templatesdir)|g'
1010

1111
TEMPLATES = \
12+
geni-fetch-aggmon \
1213
geni-fetch-amdown \
1314
geni-portal-install-templates
1415

@@ -30,6 +31,7 @@ EXTRA_DIST = $(TEMPLATES.IN)
3031
CLEANFILES = $(TEMPLATES)
3132

3233
dist_sbin_SCRIPTS = \
34+
geni-fetch-aggmon \
3335
geni-fetch-amdown \
3436
geni-portal-install-templates \
3537
import_database.py \

sbin/geni-fetch-aggmon.in

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
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

Comments
 (0)