Fix session error with INSPECTOR_TYPE=congress
[doctor.git] / tests / monitor.py
1 ##############################################################################
2 # Copyright (c) 2016 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 argparse
11 from datetime import datetime
12 import json
13 import logger as doctor_log
14 import os
15 import requests
16 import socket
17 import sys
18 import time
19
20 from keystoneauth1 import session
21 from congressclient.v1 import client
22
23 import identity_auth
24
25 # NOTE: icmp message with all zero data (checksum = 0xf7ff)
26 #       see https://tools.ietf.org/html/rfc792
27 ICMP_ECHO_MESSAGE = '\x08\x00\xf7\xff\x00\x00\x00\x00'
28
29 SUPPORTED_INSPECTOR_TYPES = ['sample', 'congress']
30
31 LOG = doctor_log.Logger('doctor_monitor').getLogger()
32
33
34 class DoctorMonitorSample(object):
35
36     interval = 0.1  # second
37     timeout = 0.1  # second
38     event_type = "compute.host.down"
39
40     def __init__(self, args):
41         if args.inspector_type not in SUPPORTED_INSPECTOR_TYPES:
42             raise Exception("Inspector type '%s' not supported", args.inspector_type)
43
44         self.hostname = args.hostname
45         self.inspector_type = args.inspector_type
46         self.ip_addr = args.ip or socket.gethostbyname(self.hostname)
47
48         if self.inspector_type == 'sample':
49             self.inspector_url = 'http://127.0.0.1:12345/events'
50         elif self.inspector_type == 'congress':
51             auth=identity_auth.get_identity_auth()
52             self.session=session.Session(auth=auth)
53             congress = client.Client(session=self.session, service_type='policy')
54             ds = congress.list_datasources()['results']
55             doctor_ds = next((item for item in ds if item['driver'] == 'doctor'),
56                              None)
57
58             congress_endpoint = congress.httpclient.get_endpoint(auth=auth)
59             self.inspector_url = ('%s/v1/data-sources/%s/tables/events/rows' %
60                                   (congress_endpoint, doctor_ds['id']))
61
62     def start_loop(self):
63         LOG.debug("start ping to host %(h)s (ip=%(i)s)" % {'h': self.hostname,
64                                                        'i': self.ip_addr})
65         sock = socket.socket(socket.AF_INET, socket.SOCK_RAW,
66                              socket.IPPROTO_ICMP)
67         sock.settimeout(self.timeout)
68         while True:
69             try:
70                 sock.sendto(ICMP_ECHO_MESSAGE, (self.ip_addr, 0))
71                 data = sock.recv(4096)
72             except socket.timeout:
73                 LOG.info("doctor monitor detected at %s" % time.time())
74                 self.report_error()
75                 LOG.info("ping timeout, quit monitoring...")
76                 return
77             time.sleep(self.interval)
78
79     def report_error(self):
80         payload = [
81             {
82                 'id': 'monitor_sample_id1',
83                 'time': datetime.now().isoformat(),
84                 'type': self.event_type,
85                 'details': {
86                     'hostname': self.hostname,
87                     'status': 'down',
88                     'monitor': 'monitor_sample',
89                     'monitor_event_id': 'monitor_sample_event1'
90                 },
91             },
92         ]
93         data = json.dumps(payload)
94
95         if self.inspector_type == 'sample':
96             headers = {'content-type': 'application/json'}
97             requests.post(self.inspector_url, data=data, headers=headers)
98         elif self.inspector_type == 'congress':
99             headers = {
100                 'Content-Type': 'application/json',
101                 'Accept': 'application/json',
102                 'X-Auth-Token':self.session.get_token(),
103             }
104             requests.put(self.inspector_url, data=data, headers=headers)
105
106
107 def get_args():
108     parser = argparse.ArgumentParser(description='Doctor Sample Monitor')
109     parser.add_argument('hostname', metavar='HOSTNAME', type=str, nargs='?',
110                         help='a hostname to monitor connectivity')
111     parser.add_argument('ip', metavar='IP', type=str, nargs='?',
112                         help='an IP address to monitor connectivity')
113     parser.add_argument('inspector_type', metavar='INSPECTOR_TYPE', type=str, nargs='?',
114                         help='inspector to report',
115                         default='sample')
116     return parser.parse_args()
117
118
119 def main():
120     args = get_args()
121     monitor = DoctorMonitorSample(args)
122     monitor.start_loop()
123
124
125 if __name__ == '__main__':
126     main()