Lawrence Davison 3a49409468 Initial API checkin for compass metrics
Change-Id: If914a69f3c98d0bf4a58f5d19eafd2149caf8084
2014-09-05 16:14:40 -07:00

481 lines
18 KiB
Python
Executable File

#!/usr/bin/env python
from flask import Flask
from flask.ext import restful
from flask.ext.restful import reqparse
from flask.ext.jsonpify import jsonify
#from flask import request
from flask import redirect, request, current_app
import urllib
import json
import requests
import random
import time
app = Flask(__name__)
api = restful.Api(app)
#class MyEncoder1(json.JSONEncoder):
# def default(self, obj):
class HelloWorld(restful.Resource):
def get(self):
return {'warning': 'Please use /monit/api'}
api.add_resource(HelloWorld, '/', '/monit')
class HelloInfo(restful.Resource):
def get(self):
#return {'info': 'Select host, hostgroup, topology, service from here'}
r = requests.get(ROOT_URL+"/api/v1/tagnames")
return r.json()
api.add_resource(HelloInfo, '/monit/api')
class Proxy(restful.Resource):
def get(self, url):
# Get URL Parameters for host and metric info
urlParam = request.url.split('proxy/', 9);
my_url = urlParam[1]
#return my_url
r = requests.get(my_url, stream = True)
#return r.text
return json.loads(r.text)
#return Response(stream_with_context(r.iter_content()), content_type = r.headers['content-type'])
api.add_resource(Proxy, '/monit/api/proxy/<path:url>', defaults={'url': '/HelloWorld'})
class InvalidUrl(restful.Resource):
def get(self):
return {'warning': 'Please form the URL'}
api.add_resource(InvalidUrl, '/monit')
class Hosts(restful.Resource):
def get(self):
return {'hosts': '[\'host1\',\'host2\',\'host3\',\'host4\',\'host5\',\'host6\']'}
r = requests.get(ROOT_URL +"/api/v1/tagvalues")
# weed out just the hosts if possible
return r.json()
api.add_resource(Hosts, '/monit/api/hosts')
class Metrics(restful.Resource):
def get(self):
# This is a comprehensive list of metrics not per host due to limitations
r = requests.get(ROOT_URL +"/api/v1/metricnames")
return r.json()
api.add_resource(Metrics, '/monit/api/metrics')
class TsGenerateAlarmData:
def __init__(self):
self.params = " "
self.statusStr = "failure"
#self.resultStr = " "
buildStr = '"alarms":['
buildStr += '{"id":"critical","name":"critical","data":['
for j in range(1, 30):
duration = random.randint(0,172800) # number of seconds in 2 days
starttime = long(time.time() - (j * 86400)) # number of seconds in a day
endtime = long(starttime + duration/2)
buildStr += '{"start":' + str(long(starttime*1000)) + ',"end":' + str(long(endtime*1000)) + '},'
#remove a comma
buildStr = buildStr[:-1]
buildStr += ']},{"id":"minor","name":"minor","data":['
for j in range(1, 30):
duration = random.randint(0,172800) # number of seconds in 2 days
starttime = long(time.time() - (j * 86400)) # number of seconds in a day
endtime = long(starttime + duration/2)
buildStr += '{"start":' + str(long(starttime*1000)) + ',"end":' + str(long(endtime*1000)) + '},'
#remove a comma
buildStr = buildStr[:-1]
buildStr += ']},{"id":"positive","name":"positive","data":['
for j in range(1, 30):
duration = random.randint(0,172800) # number of seconds in 2 days
starttime = long(time.time() - (j * 86400)) # number of seconds in a day
endtime = long(starttime + duration/2)
buildStr += '{"start":' + str(long(starttime*1000)) + ',"end":' + str(long(endtime*1000)) + '},'
#remove a comma
buildStr = buildStr[:-1]
buildStr += ']},{"id":"info","name":"info","data":['
for j in range(1, 30):
duration = random.randint(0,172800) # number of seconds in 2 days
starttime = long(time.time() - (j * 86400)) # number of seconds in a day
endtime = long(starttime + duration/2)
buildStr += '{"start":' + str(long(starttime*1000)) + ',"end":' + str(long(endtime*1000)) + '},'
#remove a comma
buildStr = buildStr[:-1]
self.resultStr = buildStr + ']}]'
class TsQueryBuilder:
def __init__(self, host_s, metric):
self.params = " "
self.statusStr = "failure"
buildStr = '{ "metrics":['
repeatStr = '{"tags":{ "host":["HOSTNAME"]},"name":"METRIC","group_by":[{"name":"tag", "tags":["host"]}],"aggregators":[{"name":"sum", "align_sampling": false, "sampling":{ "value": "2", "unit": "minutes"}}]}'
finStr = '],"start_relative": { "value": "17", "unit": "minutes" }}'
repeatStr = repeatStr.replace("METRIC", metric)
i = len(host_s);
for hostname in host_s:
buildStr += repeatStr.replace("HOSTNAME", host_s[i-1])
i -= 1
if i != 0:
buildStr += ','
self.params = buildStr + finStr
#print "Query: " + self.params
r = requests.post(ROOT_URL +"/api/v1/datapoints/query", data=self.params)
# check the POST status and return success or fail here
if r.status_code == requests.codes.ok:
self.statusStr = "success"
self.resp_dict = r.json()
class HostMetric(restful.Resource):
def get(self, hostname, metricname):
# Get URL Parameters for host and metric info
urlParam = request.url.split('/', 9);
MyList = [urlParam[6]]
# Create and execute the query
qb = TsQueryBuilder(MyList, urlParam[8])
# Create JSON Prefix
valStr = '{"result":[{"metrics":[{"id":"' + urlParam[8] + '","data":['
# add all time series data
for key, value in qb.resp_dict["queries"][0]["results"][0]["values"]:
# round this value down
digits = str(key)
key = key - (int(digits[8]) * 10000)
key = key - (int(digits[9]) * 1000)
key = key - (int(digits[10]) * 100)
valStr += '{"time":' + str(key) + ',"value":' + str(value) + '},'
#remove a comma
valStr = valStr[:-1]
a = TsGenerateAlarmData()
#add final braces
valStr += ']}],'
valStr += a.resultStr
valStr += ',"id":"' + urlParam[6] + '"}],"status":"' + qb.statusStr + '"}'
#return valStr
return json.loads(valStr)
api.add_resource(
HostMetric,
'/monit/api/host/<hostname>/metric/<metricname>',
defaults={'hostname': '', 'metricname': ''}
)
class HostGroupMetric(restful.Resource):
def get(self, hostgroup, metricname):
# Get URL Parameters for host and metric info
urlParam = request.url.split('/', 9);
hostgroup = urlParam[6]
# need logic to query hostgroup and convert to list
MyList = ["host1","host2","host3","host4","host5","host6"]
# Create and execute the query
qb = TsQueryBuilder(MyList, urlParam[8])
# Create JSON Prefix
valStr = '{"result":['
#return qb.resp_dict
# add all time series data
i = 0
for host in MyList:
valStr += '{"metrics":[{"id":"' + urlParam[8] + '","data":['
for skey, svalue in qb.resp_dict["queries"][i]["results"][0]["values"]:
# round this value down
digits = str(skey)
skey = skey - (int(digits[8]) * 10000)
skey = skey - (int(digits[9]) * 1000)
skey = skey - (int(digits[10]) * 100)
valStr += '{"time":' + str(skey) + ',"value":' + str(svalue) + '},'
#remove a comma
valStr = valStr[:-1]
#add final recordbraces
#valStr += ']}],"id":"' + MyList[i] + '"},'
a = TsGenerateAlarmData()
#add final record braces
valStr += ']}],'
valStr += a.resultStr
valStr += ',"id":"' + MyList[i] + '"},'
i += 1;
#remove a comma
valStr = valStr[:-1]
#add final braces
valStr += '],"status":"' + qb.statusStr + '"}'
#return valStr
return json.loads(valStr)
api.add_resource(
HostGroupMetric,
'/monit/api/hostgroup/<hostgroup>/metric/<metricname>',
defaults={'hostgroup': '', 'metricname': ''}
)
class RsHostMetric(restful.Resource):
def get(self, hostname, metricname):
# Get URL Parameters for host and metric info
urlParam = request.url.split('/', 9);
MyList = [urlParam[6]]
# Create and execute the query
qb = TsQueryBuilder(MyList, urlParam[8])
# Create JSON Prefix
valStr = '{"series":[{"metrics":[{"id":"' + urlParam[8] + '","data":['
# add all time series data
for key, value in qb.resp_dict["queries"][0]["results"][0]["values"]:
# round this value down
digits = str(key)
key = key - (int(digits[8]) * 10000)
key = key - (int(digits[9]) * 1000)
key = key - (int(digits[10]) * 100)
valStr += '{"time":' + str(key) + ',"value":' + str(value) + '},'
#remove a comma
valStr = valStr[:-1]
#add final braces
valStr += ']}],"id":"' + urlParam[6] + '"}],"status":"' + qb.statusStr + '"}'
return json.loads(valStr)
api.add_resource(
RsHostMetric,
'/monit/api/rshost/<hostname>/metric/<metricname>',
defaults={'hostname': '', 'metricname': ''}
)
class RsHostGroupMetric(restful.Resource):
def get(self, hostgroup, metricname):
# Get URL Parameters for host and metric info
urlParam = request.url.split('/', 9) #;
urlCruft = urlParam[8].split('?', 2) #;
hostgroup = urlParam[6]
themetric = urlCruft[0]
print themetric
# need logic to query hostgroup and convert to list
MyList = ["host1","host2","host3","host4","host5","host6"]
# Create and execute the query
qb = TsQueryBuilder(MyList, themetric)
# Create JSON Prefix
valStr = '['
#return qb.resp_dict
# add all time series data
i = 0
for host in MyList:
valStr += '{"name":"' + MyList[i] + ": " + themetric + '","data":['
for skey, svalue in qb.resp_dict["queries"][i]["results"][0]["values"]:
# round this value down
digits = str(skey)
skey = skey - (int(digits[8]) * 10000)
skey = skey - (int(digits[9]) * 1000)
skey = skey - (int(digits[10]) * 100)
valStr += '{"x":' + str(skey) + ',"y":' + str(svalue) + '},'
#remove a comma
valStr = valStr[:-1]
#add final recordbraces
valStr += ']},'
i += 1;
#remove a comma
valStr = valStr[:-1]
#add final braces
valStr += ']'
callback = request.args.get('callback', False)
if callback:
content = str(callback) + '(' + valStr + ')'
return current_app.response_class(content, mimetype='application/json')
#return valStr
return json.loads(valStr)
api.add_resource(
RsHostGroupMetric,
'/monit/api/rshostgroup/<hostgroup>/metric/<metricname>',
defaults={'hostgroup': '', 'metricname': ''}
)
class Alarms(restful.Resource):
def get(self):
alarms = TsGenerateAlarmData()
r = alarms.resultStr
#return r
return json.loads("{"+r+"}")
api.add_resource(Alarms, '/monit/api/alarms')
class Services(restful.Resource):
def get(self):
r = requests.get(ROOT_URL +"/api/v1/services")
return r.json()
api.add_resource(Services, '/monit/api/services')
class Topology(restful.Resource):
def get(self):
#r = requests.get(ROOT_URL +"/api/v1/topology")
#return r.json()
valAStr = '{"status":"success", "result":[ {"id":"uc-datacenter","name":"uc-datacenter","children":[ {"id":"nova-compute","name":"nova-compute","state":"running","resource":"services","type":"service","children":[ {"id":"compute-server-1.huawei.com","name":"compute-server-1.huawei.com","state":"running","resource":"hosts","type":"server", "children":[ {"id":"nova-compute","name":"nova-compute","state":"running","resource":"services","type":"service","children":[]}, {"id":"nova-consoleauth","name":"nova-consoleauth","state":"running","resource":"services","type":"service","children":[]} ]}, {"id":"compute-server-2.huawei.com","name":"compute-server-2.huawei.com","state":"running","resource":"hosts","type":"server", "children":[ {"id":"nova-novncproxy","name":"nova-novncproxy","state":"running","resource":"services","type":"service","children":[]}, {"id":"ceilometer-agent-compute","name":"ceilometer-agent-compute","state":"running","resource":"services","type":"service","children":[]}, {"id":"neutron-openvswitch-agent","name":"nova-openvswitch-agent","state":"running","resource":"services","type":"service","children":[]} ]} ]} ]} ]}'
valStr = '{"status":"success", "result":[{"id":"Huawei-Lab-C","name":"Huawei-Lab-C","children":[ {"id":"10.145.81.219","name":"10.145.81.219","state":"warning","resource":"services","type":"service","children":[ {"name":"server-1.huawei.com","id":"host1.huawei.com","state":"running","resource":"hosts","type":"server", "children":[]}, {"name":"server-2.huawei.com","id":"host2.huawei.com","state":"running","resource":"hosts","type":"server", "children":[]}, {"name":"server-3.huawei.com","id":"host3.huawei.com","state":"running","resource":"hosts","type":"server", "children":[]}, {"name":"server-4.huawei.com","id":"host4.huawei.com","state":"running","resource":"hosts","type":"server", "children":[]}, {"name":"server-5.huawei.com","id":"host5.huawei.com","state":"warning","resource":"hosts","type":"server", "children":[]}, {"name":"server-6.huawei.com","id":"host6.huawei.com","state":"running","resource":"hosts","type":"server", "children":[]}, {"name":"server-7.huawei.com","id":"host7.huawei.com","state":"critical","resource":"hosts","type":"server", "children":[]}, {"name":"monit-server-1.huawei.com","id":"10_145_81_205","state":"running","resource":"hosts","type":"server", "children":[]}]}]}]}'
return json.loads(valStr)
#return valStr
api.add_resource(Topology, '/monit/api/topologies/1')
if __name__ == '__main__':
global ROOT_URL
ROOT_URL = "http://10.145.81.205:8080"
app.run(host='0.0.0.0', debug=True, threaded=True)
#app.run(debug=True)
"""
# Topo Structure
{"status":"success", "result":[
{"id":"uc-datacenter","name":"uc-datacenter","children":[
{"id":"nova-compute","name":"nova-compute","state":"running","resource":"services","type":"service","children":[
{"id":"compute-server-1.huawei.com","name":"compute-server-1.huawei.com","state":"running","resource":"hosts","type":"server", "children":[
{"id":"nova-compute","name":"nova-compute","state":"running","resource":"services","type":"service","children":[]},
{"id":"nova-consoleauth","name":"nova-consoleauth","state":"running","resource":"services","type":"service","children":[]},
]},
{"id":"compute-server-2.huawei.com","name":"compute-server-2.huawei.com","state":"running","resource":"hosts","type":"server", "children":[
{"id":"nova-novncproxy","name":"nova-novncproxy","state":"running","resource":"services","type":"service","children":[]},
{"id":"ceilometer-agent-compute","name":"ceilometer-agent-compute","state":"running","resource":"services","type":"service","children":[]},
{"id":"neutron-openvswitch-agent","name":"nova-openvswitch-agent","state":"running","resource":"services","type":"service","children":[]}
]}
]}
]}
]}
#Query structure
{
"metrics": [
{
"tags": {
"host": [ "nova-compute_local" ]
},
"name": "cpu.0.cpu.idle.value",
"aggregators": [
{
"name": "avg",
"align_sampling": true,
"sampling": { "value": "1", "unit": "minutes" }
}
]
},
{
"tags": {
"host": [ "controller_local" ]
},
"name": "cpu.0.cpu.idle.value",
"aggregators": [
{
"name": "avg",
"align_sampling": true,
"sampling": { "value": "1", "unit": "minutes" }
}
]
},
{
"tags": {
"host": [ "nova-compute_local" ]
},
"name": "cpu.0.cpu.idle.value",
"aggregators": [
{
"name": "avg",
"align_sampling": true,
"sampling": { "value": "1", "unit": "minutes" }
}
]
},
{
"tags": {
"host": [ "neutron_local" ]
},
"name": "cpu.0.cpu.idle.value",
"aggregators": [
{
"name": "avg",
"align_sampling": true,
"sampling": { "value": "1", "unit": "minutes" }
}
]
}
],
"cache_time": 0,
"start_relative": {
"value": "1",
"unit": "hours"
}
}
# Alarms
{?[?{?[?{.. more json here ...
{"id":"uc-server-1.huawei.com","name":"uc-server-1.huawei.com","resource":"hosts","state":"running","type":"server", "metrics":[], "alarms":[
{"id":"critical","name":"critical","data":[
{"start":1406831282409,"end":1406870037149},
{"start":1406745382748,"end":1406761927670}
]},
{"id":"minor","name":"minor","data":[
{"start":1406873957790,"end":1406886655198},
{"start":1406774590378,"end":1406850781190}
]},
{"id":"positive","name":"positive","data":[
{"start":1406873957790,"end":1406886655198},
{"start":1406774590378,"end":1406850781190}
]},
{"id":"info","name":"info","data":[
{"start":1406873957790,"end":1406886655198},
{"start":1406774590378,"end":1406850781190}
]}
]}
... more json here...?}?]?}?]?}
"""