fix collectd's bug
[doctor.git] / doctor_tests / monitor / collectd_plugin.py
1 ##############################################################################
2 # Copyright (c) 2017 NEC Corporation and others.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10 import collectd
11 import sys
12 from datetime import datetime
13 import json
14 import requests
15 import time
16 from requests.exceptions import ConnectionError
17
18 from keystoneauth1 import loading
19 from keystoneauth1 import session
20 from congressclient.v1 import client
21
22
23 def write_debug(str_write, write_type, compute_user):
24     file_name = ('/home/%s/monitor.log' % compute_user)
25     file_tmp = open(file_name, write_type)
26     file_tmp.write( "%s" % str_write)
27     file_tmp.close()
28
29
30 class DoctorMonitorCollectd(object):
31     def __init__(self):
32         self.control_ip = ''
33         self.compute_user = ''
34         self.compute_ip = ''
35         self.host_name = ''
36         self.inspector_type = ''
37         self.inspector_url = ''
38         self.os_auth_url = ''
39         self.os_username = ''
40         self.os_password = ''
41         self.os_project_name = ''
42         self.os_user_domain_name = ''
43         self.os_user_domain_id = ''
44         self.os_project_domain_name = ''
45         self.os_project_domain_id = ''
46         self.sess = ''
47         self.auth = ''
48         self.inspector_notified = 0
49         self.start_notifications = 0
50         self.monitor_type = 'sample'
51
52     def config_func(self, config):
53         for node in config.children:
54             key = node.key.lower()
55             val = node.values[0]
56
57             if key == 'compute_host':
58                 self.host_name = val
59             elif key == 'control_ip':
60                 self.control_ip = val
61             elif key == 'compute_ip':
62                 self.compute_ip = val
63             elif key == 'compute_user':
64                 self.compute_user = val
65             elif key == 'inspector_type':
66                 self.inspector_type = val
67             elif key == 'os_auth_url':
68                 self.os_auth_url = val
69             elif key == 'os_username':
70                 self.os_username = val
71             elif key == 'os_password':
72                 self.os_password = val
73             elif key == 'os_project_name':
74                 self.os_project_name = val
75             elif key == 'os_user_domain_name':
76                 self.os_user_domain_name = val
77             elif key == 'os_user_domain_id':
78                 self.os_user_domain_id = val
79             elif key == 'os_project_domain_name':
80                 self.os_project_domain_name = val
81             elif key == 'os_project_domain_id':
82                 self.os_project_domain_id = val
83             else:
84                 collectd.info('Unknown config key "%s"' % key)
85
86     def init_collectd(self):
87         write_debug("Compute node collectd monitor start at %s\n\n" % datetime.now().isoformat(), "w", self.compute_user)
88
89         if self.inspector_type == 'sample':
90             self.inspector_url = ('http://%s:12345/events' % self.control_ip)
91         elif self.inspector_type == 'congress':
92             loader = loading.get_plugin_loader('password')
93             self.auth = loader.load_from_options(auth_url=self.os_auth_url,
94                         username=self.os_username,
95                         password=self.os_password,
96                         project_name=self.os_project_name,
97                         user_domain_name=self.os_user_domain_name,
98                         user_domain_id=self.os_user_domain_id,
99                         project_domain_name=self.os_project_domain_name,
100                         project_domain_id=self.os_project_domain_id)
101             self.sess=session.Session(auth=self.auth)
102             congress = client.Client(session=self.sess, service_type='policy')
103             ds = congress.list_datasources()['results']
104             doctor_ds = next((item for item in ds if item['driver'] == 'doctor'),
105                          None)
106
107             congress_endpoint = congress.httpclient.get_endpoint(auth=self.auth)
108             self.inspector_url = ('%s/v1/data-sources/%s/tables/events/rows' %
109                               (congress_endpoint, doctor_ds['id']))
110         else:
111             sys.exit()
112         self.start_notifications = 1
113
114
115     def notify_inspector(self):
116         event_type = "compute.host.down"
117         payload = [
118             {
119                  'id': ("monitor_%s_id1" % self.monitor_type),
120                  'time': datetime.now().isoformat(),
121                  'type': event_type,
122                  'details': {
123                      'hostname': self.host_name,
124                      'status': 'down',
125                      'monitor': ("monitor_%s" % self.monitor_type),
126                      'monitor_event_id': ("monitor_%s_event1" % self.monitor_type)
127                  },
128              },
129         ]
130         data = json.dumps(payload)
131         self.inspector_notified = 1
132
133         if self.inspector_type == 'sample':
134             headers = {'content-type': 'application/json'}
135             try:
136                 requests.post(self.inspector_url, data=data, headers=headers)
137             except ConnectionError as err:
138                 print err
139         elif self.inspector_type == 'congress':
140             # TODO(umar) enhance for token expiry case
141             headers = {
142                 'Content-Type': 'application/json',
143                 'Accept': 'application/json',
144                 'X-Auth-Token': self.sess.get_token()
145             }
146             requests.put(self.inspector_url, data=data, headers=headers)
147
148
149     def handle_notif(self, notification, data=None):
150         if (notification.severity == collectd.NOTIF_FAILURE or
151             notification.severity == collectd.NOTIF_WARNING):
152             if (self.start_notifications == 1 and self.inspector_notified == 0):
153                 write_debug("Received down notification: doctor monitor detected at %s\n" % time.time(), "a", self.compute_user)
154                 self.notify_inspector()
155
156         elif notification.severity == collectd.NOTIF_OKAY:
157             collectd.info("Interface status: UP again %s\n" % time.time())
158         else:
159             collectd.info("Unknown notification severity %s\n" % notification.severity)
160
161
162 monitor = DoctorMonitorCollectd()
163
164 collectd.register_config(monitor.config_func)
165 collectd.register_init(monitor.init_collectd)
166 collectd.register_notification(monitor.handle_notif)