Contrail Insights Object Plug-In
Object scope plug-in is supported to extend the instance and
host scope plug-in. It will assign an aggregate of hosts running a
plug-in script to collect data for an aggregate of objects (such as
instances). Currently, only an aggregate of instances can be monitored
and only the plug-in type object.rest is
supported.
The collector failover High Availability (HA) feature is supported in object scope plug-ins. If one of the collectors in the aggregate is down, Contrail Insights will automatically assign another host in the same aggregate as the collector. As a result, you can set up an aggregate of several collectors which will make sure downtime of some of the collectors will not affect the object monitoring.
Create an Object Scope Plug-In
To add an object scope plug-in in Contrail Insights, you need
to supply both a plug-in script and plug-in JSON file. Contrail Insights
Agent will pass a list of object_ids separated
by commas (-o) and a dictionary to MetaData (-p) to the plug-in
script. The Contrail Insights Agent expects the plug-in script to
return data with the following format:
OK - {{plugin_name}}: [{"roomKey": {"value": {{instance_id_1}}, "unit": "roomKey"}, "metric_1": {"value": {{value_1}}, "unit": "m1_unit"}, "metric_2": {"value": {{value_2}}, "unit": "m2_unit"}}, {"roomKey": {"value": {{instance_id_2}}, "unit": "roomKey"}, "metric_1": {"value": {{value_3}}, "unit": "m1_unit"}, "metric_2": {"value": {{value_4}}, "unit": "m2_unit"}}]The main body of the data should be a list of dictionaries and each entry should represent a data point with all of the metrics for one instance.
Following is an example of a plug-in script which will get instance
data from some endpoint, passed in from the MetaData variable.
$ cat check_object_plugin.py
import sys
import traceback
import requests
import json
import argparse
def main(argv):
instance_list = argv.instances.split(',')
url = json.loads(argv.metadata)['url']
data = json.dumps({'InstanceList': instance_list})
resp = requests.get(url=url, data=data,
headers={'content-type': 'application/json'})
result = json.loads(resp.text)
return_value = []
for entry in result['data']:
instance_data = \
{'roomKey': {'unit': 'roomKey', 'value': entry['id']},
'm1': {'unit': 'm1_unit', 'value': entry['m1']},
'm2': {'unit': 'm2_unit', 'value': entry['m2']}}
return_value.append(instance_data)
try:
return_value = json.dumps(return_value)
msg = 'instance_object_plugin: {}'.format(return_value)
except Exception as e:
traceback.print_exc()
msg = 'instance_object_plugin: []'
test_state = 0
logger_helper(
msg,
test_state
)
def logger_helper(message, state):
if state == 2:
print "CRITICAL - " + message
sys.exit(2)
elif state == 1:
print "WARNING - " + message
sys.exit(1)
elif state == 0:
print "OK - " + message
sys.exit(0)
else:
print "CRITICAL - Unexpected value : %d" % state + "; " + message
sys.exit(2)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
'-o', '--instances', help='instance list', required=True,
default='', type=unicode)
parser.add_argument(
'-p', '--metadata', help='metadata', required=False,
default='{}', type=unicode)
args = parser.parse_args()
sys.exit(main(args))
Following is the corresponding flask server running on localhost:9999 for the above example:
from flask import Flask, request
import json
import copy
data = {'a53a441b-fb1f-4e08-9e05-d94fd4d5a0ba': {'m1': 1, 'm2': 2},
'82c20111-32b2-4a47-a668-cd1d6c69270d': {'m1': 3, 'm2': 4},
'fd5977d4-150d-4af4-bfaf-96663902447e': {'m1': 5, 'm2': 6},
'a35414ab-e779-48a8-93d9-1ae50647fdc5': {'m1': 7, 'm2': 8}}
app = Flask(__name__)
@app.route('/', methods=['GET'])
def app_message_get():
if request.headers['Content-Type'] != 'application/json':
print "invalid"
return json.dumps({'result': "invalid"})
args = request.json
result = []
for instance_id in args.get('InstanceList', []):
if instance_id in data:
entry = copy.deepcopy(data[instance_id])
entry['id'] = instance_id
result.append(entry)
return json.dumps({'data': result})
if __name__ == '__main__':
app.run(
host="0.0.0.0",
port=int("9999")
)
For example, if you want to get data for instances fd5977d4-150d-4af4-bfaf-96663902447e and a53a441b-fb1f-4e08-9e05-d94fd4d5a0ba with URL http://localhost:9999 (because your server is running on localhost
port 9999), you can run the following command:
python check_object_plugin.py -o fd5977d4-150d-4af4-bfaf-96663902447e,a53a441b-fb1f-4e08-9e05-d94fd4d5a0ba -p '{"url": "http://localhost:9999"}'The output of the command is:
OK - instance_object_plugin: [{"roomKey": {"value": "fd5977d4-150d-4af4-bfaf-96663902447e", "unit": "roomKey"}, "m1": {"value": 5, "unit": "m1_unit"}, "m2": {"value": 6, "unit": "m2_unit"}}, {"roomKey": {"value": "a53a441b-fb1f-4e08-9e05-d94fd4d5a0ba", "unit": "roomKey"}, "m1": {"value": 1, "unit": "m1_unit"}, "m2": {"value": 2, "unit": "m2_unit"}}]The corresponding plug-in JSON file will be:
$ cat instance_usage.json
{
"Collection": "instance_plugin_usage_collection",
"Config": {
"CommandLine": "python check_object_plugin.py",
"ObjectAggregateId": "7ae841ce-ead4-11e9-b283-0242ac130005"
},
"MetaData": {"url": "http://localhost:9999"},
"AggregateId": "appformix_platform",
"MetricMap": [
{
"Name": "m1",
"Units": "m1_unit"
},
{
"Name": "m2",
"Units": "m2_unit"
}
],
"PluginId": "instance_object_plugin",
"PluginName": "instance_object_plugin",
"PluginType": "object.rest",
"Scope": "object",
"State": "enabled",
"status": "success"
}
Where ObjectAggregateId should be
the aggregate identifier of the aggregate of instances you want to
monitor and AggregateId should be the aggregate
identifier of the host aggregate which is assigned to collect the
data for the instances.
Note that you can put additional information in the MetaData field in the plug-in as needed. The above
example is just a simple example.
Add Object Scope Plug-In to Contrail Insights
To add the object scope plug-in to Contrail Insights, you need
to post your plug-in to Contrail Insights through Ansible. Add the
following lines in your Ansible group_vars/all file and re-run the Ansible playbook.
appformix_user_defined_plugins:
- { plugin_info: 'user_defined_plugins/instance_usage.json',
plugin_file: 'user_defined_plugins/check_object_plugin.py'}
The Contrail Insights Ansible playbooks will then copy these two types of files to all of the appropriate Agents and then configure the plug-in in the Contrail Insights Platform.