blob: 55178fd00d36d2007d58e53cfa8789d0436751cd [file] [log] [blame]
Helena McGoughcda5f2f2017-09-12 08:30:02 +01001# Copyright 2017 Intel Research and Development Ireland Limited
2# *************************************************************
3
4# This file is part of OSM Monitoring module
5# All Rights Reserved to Intel Corporation
6
7# Licensed under the Apache License, Version 2.0 (the "License"); you may
8# not use this file except in compliance with the License. You may obtain
9# a copy of the License at
10
11# http://www.apache.org/licenses/LICENSE-2.0
12
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16# License for the specific language governing permissions and limitations
17# under the License.
18
19# For those usages not covered by the Apache License, Version 2.0 please
20# contact: helena.mcgough@intel.com or adrian.hoban@intel.com
21##
Helena McGough94f93f72017-11-23 17:29:54 +000022# __author__ = Helena McGough
23#
24"""A Webserver to send alarm notifications from Aodh to the SO."""
Helena McGoughcda5f2f2017-09-12 08:30:02 +010025import json
Helena McGough94f93f72017-11-23 17:29:54 +000026import logging
Benjamin Diaz75512472018-04-27 14:32:31 -030027import os
Helena McGough94f93f72017-11-23 17:29:54 +000028import sys
Helena McGough94f93f72017-11-23 17:29:54 +000029import time
30
Benjamin Diaz181cce82018-03-28 21:12:11 -030031from six.moves.BaseHTTPServer import BaseHTTPRequestHandler
32from six.moves.BaseHTTPServer import HTTPServer
Helena McGough94f93f72017-11-23 17:29:54 +000033
34# Initialise a logger for alarm notifier
Benjamin Diaz181cce82018-03-28 21:12:11 -030035
36logging.basicConfig(stream=sys.stdout,
Helena McGough94f93f72017-11-23 17:29:54 +000037 format='%(asctime)s %(message)s',
Benjamin Diaz181cce82018-03-28 21:12:11 -030038 datefmt='%m/%d/%Y %I:%M:%S %p',
Helena McGough94f93f72017-11-23 17:29:54 +000039 level=logging.INFO)
40log = logging.getLogger(__name__)
41
Benjamin Diaz181cce82018-03-28 21:12:11 -030042sys.path.append(os.path.abspath(os.path.join(os.path.realpath(__file__), '..', '..', '..', '..', '..')))
Helena McGoughd13405d2017-09-21 17:09:24 +010043
Benjamin Diaz181cce82018-03-28 21:12:11 -030044from osm_mon.core.database import DatabaseManager
Helena McGougheffeb7c2017-11-23 15:54:08 +000045from osm_mon.core.message_bus.producer import KafkaProducer
Helena McGoughcda5f2f2017-09-12 08:30:02 +010046
Helena McGougheffeb7c2017-11-23 15:54:08 +000047from osm_mon.plugins.OpenStack.common import Common
48from osm_mon.plugins.OpenStack.response import OpenStack_Response
Benjamin Diaz75512472018-04-27 14:32:31 -030049from osm_mon.core.settings import Config
Helena McGoughcda5f2f2017-09-12 08:30:02 +010050
Helena McGoughcda5f2f2017-09-12 08:30:02 +010051
Helena McGough94f93f72017-11-23 17:29:54 +000052class NotifierHandler(BaseHTTPRequestHandler):
53 """Handler class for alarm_actions triggered by OSM alarms."""
Helena McGoughcda5f2f2017-09-12 08:30:02 +010054
Helena McGough94f93f72017-11-23 17:29:54 +000055 def _set_headers(self):
56 """Set the headers for a request."""
57 self.send_response(200)
58 self.send_header('Content-type', 'text/html')
59 self.end_headers()
Helena McGoughcda5f2f2017-09-12 08:30:02 +010060
Helena McGough94f93f72017-11-23 17:29:54 +000061 def do_GET(self):
62 """Get request functionality."""
63 self._set_headers()
64 self.wfile.write("<html><body><h1>hi!</h1></body></html>")
Helena McGoughd00ff822017-09-20 17:42:22 +010065
Helena McGough94f93f72017-11-23 17:29:54 +000066 def do_POST(self):
67 """POST request function."""
68 # Gets header and data from the post request and records info
69 self._set_headers()
70 # Gets the size of data
71 content_length = int(self.headers['Content-Length'])
72 post_data = self.rfile.read(content_length)
Benjamin Diazb85fc8c2018-05-03 13:22:11 -030073 try:
74 post_data = post_data.decode()
75 except AttributeError:
76 pass
Helena McGough94f93f72017-11-23 17:29:54 +000077 self.wfile.write("<html><body><h1>POST!</h1></body></tml>")
78 log.info("This alarm was triggered: %s", json.loads(post_data))
Helena McGoughd00ff822017-09-20 17:42:22 +010079
Helena McGough94f93f72017-11-23 17:29:54 +000080 # Generate a notify_alarm response for the SO
81 self.notify_alarm(json.loads(post_data))
Helena McGoughcda5f2f2017-09-12 08:30:02 +010082
Helena McGough94f93f72017-11-23 17:29:54 +000083 def notify_alarm(self, values):
Benjamin Diaz181cce82018-03-28 21:12:11 -030084 """Send a notification response message to the SO."""
Helena McGoughcda5f2f2017-09-12 08:30:02 +010085
Benjamin Diaz181cce82018-03-28 21:12:11 -030086 try:
87 # Initialise configuration and authentication for response message
88 config = Config.instance()
89 config.read_environ()
90 response = OpenStack_Response()
91 producer = KafkaProducer('alarm_response')
Helena McGoughd00ff822017-09-20 17:42:22 +010092
Benjamin Diaz181cce82018-03-28 21:12:11 -030093 database_manager = DatabaseManager()
Helena McGoughcda5f2f2017-09-12 08:30:02 +010094
Benjamin Diaz181cce82018-03-28 21:12:11 -030095 alarm_id = values['alarm_id']
96 # Get vim_uuid associated to alarm
97 creds = database_manager.get_credentials_for_alarm_id(alarm_id, 'openstack')
98 auth_token = Common.get_auth_token(creds.uuid)
99 endpoint = Common.get_endpoint("alarming", creds.uuid)
Helena McGoughd00ff822017-09-20 17:42:22 +0100100
Benjamin Diaz181cce82018-03-28 21:12:11 -0300101 # If authenticated generate and send response message
102 if auth_token is not None and endpoint is not None:
103 url = "{}/v2/alarms/%s".format(endpoint) % alarm_id
104
105 # Get the resource_id of the triggered alarm
106 result = Common.perform_request(
107 url, auth_token, req_type="get")
108 alarm_details = json.loads(result.text)
109 gnocchi_rule = alarm_details['gnocchi_resources_threshold_rule']
110 resource_id = gnocchi_rule['resource_id']
111
112 # Process an alarm notification if resource_id is valid
113 if resource_id is not None:
114 # Get date and time for response message
115 a_date = time.strftime("%d-%m-%Y") + " " + time.strftime("%X")
116 # Try generate and send response
117 try:
118 resp_message = response.generate_response(
119 'notify_alarm', a_id=alarm_id,
120 r_id=resource_id,
121 sev=values['severity'], date=a_date,
122 state=values['current'], vim_type="openstack")
123 producer.notify_alarm(
124 'notify_alarm', resp_message, 'alarm_response')
125 log.info("Sent an alarm response to SO: %s", resp_message)
126 except Exception as exc:
127 log.exception("Couldn't notify SO of the alarm:")
128 else:
Benjamin Diazb85fc8c2018-05-03 13:22:11 -0300129 log.warning("No resource_id for alarm; no SO response sent.")
Helena McGough94f93f72017-11-23 17:29:54 +0000130 else:
Benjamin Diazb85fc8c2018-05-03 13:22:11 -0300131 log.warning("Authentication failure; SO notification not sent.")
Benjamin Diaz181cce82018-03-28 21:12:11 -0300132 except:
133 log.exception("Could not notify alarm.")
Helena McGough94f93f72017-11-23 17:29:54 +0000134
135
136def run(server_class=HTTPServer, handler_class=NotifierHandler, port=8662):
Benjamin Diaz181cce82018-03-28 21:12:11 -0300137 """Run the webserver application to retrieve alarm notifications."""
Helena McGough94f93f72017-11-23 17:29:54 +0000138 try:
139 server_address = ('', port)
140 httpd = server_class(server_address, handler_class)
141 print('Starting alarm notifier...')
142 log.info("Starting alarm notifier server on port: %s", port)
143 httpd.serve_forever()
144 except Exception as exc:
Benjamin Diazb85fc8c2018-05-03 13:22:11 -0300145 log.warning("Failed to start webserver, %s", exc)
Helena McGough94f93f72017-11-23 17:29:54 +0000146
Benjamin Diaz181cce82018-03-28 21:12:11 -0300147
Helena McGough94f93f72017-11-23 17:29:54 +0000148if __name__ == "__main__":
149 from sys import argv
150
151 # Runs the webserver
152 if len(argv) == 2:
153 run(port=int(argv[1]))
154 else:
155 run()