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