Merge "Updated the OpenStack plugins"
[osm/MON.git] / plugins / vRealiseOps / vROPs_Webservice / vrops_webservice.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 ##
5 # Copyright 2016-2017 VMware Inc.
6 # This file is part of ETSI OSM
7 # All Rights Reserved.
8 #
9 # Licensed under the Apache License, Version 2.0 (the "License"); you may
10 # not use this file except in compliance with the License. You may obtain
11 # a copy of the License at
12 #
13 # http://www.apache.org/licenses/LICENSE-2.0
14 #
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18 # License for the specific language governing permissions and limitations
19 # under the License.
20 #
21 # For those usages not covered by the Apache License, Version 2.0 please
22 # contact: osslegalrouting@vmware.com
23 ##
24
25 """
26 Webservice for vRealize Operations (vROPs) to post/notify alarms details.
27
28 """
29 __author__ = "Arpita Kate"
30 __date__ = "$15-Sept-2017 16:09:29$"
31 __version__ = '0.1'
32
33
34 from bottle import (ServerAdapter, route, run, server_names, redirect, default_app,
35 request, response, template, debug, TEMPLATE_PATH , static_file)
36 from socket import gethostname
37 from datetime import datetime
38 from xml.etree import ElementTree as ET
39 import logging
40 import os
41 import json
42 import requests
43
44 from core.message_bus.producer import KafkaProducer
45
46 try:
47 from cheroot.wsgi import Server as WSGIServer
48 from cheroot.ssl.pyopenssl import pyOpenSSLAdapter
49 except ImportError:
50 from cherrypy.wsgiserver import CherryPyWSGIServer as WSGIServer
51 from cherrypy.wsgiserver.ssl_pyopenssl import pyOpenSSLAdapter
52
53 #Set Constants
54 BASE_DIR = os.path.dirname(os.path.dirname(__file__))
55 CERT_DIR = os.path.join(BASE_DIR, "SSL_certificate")
56 CERTIFICATE = os.path.join(CERT_DIR, "www.vrops_webservice.com.cert")
57 KEY = os.path.join(CERT_DIR, "www.vrops_webservice.com.key")
58 CONFIG_FILE = os.path.join(BASE_DIR, '../vrops_config.xml')
59 #Severity Mapping from vROPs to OSM
60 VROPS_SEVERITY_TO_OSM_MAPPING = {
61 "ALERT_CRITICALITY_LEVEL_CRITICAL":"CRITICAL",
62 "ALERT_CRITICALITY_LEVEL_WARNING":"WARNING",
63 "ALERT_CRITICALITY_LEVEL_IMMEDIATE":"MAJOR",
64 "ALERT_CRITICALITY_LEVEL_INFO":"INDETERMINATE",
65 "ALERT_CRITICALITY_LEVEL_AUTO":"INDETERMINATE",
66 "ALERT_CRITICALITY_LEVEL_UNKNOWN":"INDETERMINATE",
67 "ALERT_CRITICALITY_LEVEL_NONE":"INDETERMINATE"
68 }
69
70 #Set logger
71 logger = logging.getLogger('vROPs_Webservice')
72 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
73 hdlr = logging.FileHandler(os.path.join(BASE_DIR,"vrops_webservice.log"))
74 hdlr.setFormatter(formatter)
75 logger.addHandler(hdlr)
76 logger.setLevel(logging.DEBUG)
77
78
79 def format_datetime(str_date):
80 """
81 Method to format datetime
82 Args:
83 str_date - datetime string
84 Returns:
85 formated datetime
86 """
87 date_fromat = "%Y-%m-%dT%H:%M:%S"
88 formated_datetime = None
89 try:
90 datetime_obj = datetime.fromtimestamp(float(str_date)/1000.)
91 formated_datetime = datetime_obj.strftime(date_fromat)
92 except Exception as exp:
93 logger.error('Exception: {} occured while converting date {} into format {}'.format(
94 exp,str_date, date_fromat))
95
96 return formated_datetime
97
98 def get_alarm_config():
99 """
100 Method to get configuration parameters
101 Args:
102 None
103 Returns:
104 dictionary of config parameters
105 """
106 alarm_config = {}
107 try:
108 xml_content = ET.parse(CONFIG_FILE)
109 alarms = xml_content.getroot()
110 for alarm in alarms:
111 if alarm.tag == 'Access_Config':
112 for param in alarm:
113 alarm_config[param.tag] = param.text
114 except Exception as exp:
115 logger.error('Exception: {} occured while parsing config file.'.format(exp))
116
117 return alarm_config
118
119 def get_alarm_definationID(alarm_uuid):
120 """
121 Method to get alarm/alert defination ID
122 Args:
123 alarm_uuid : UUID of alarm
124 Returns:
125 alarm defination ID
126 """
127 alarm_definationID = None
128 if alarm_uuid :
129 try:
130 access_config = get_alarm_config()
131 headers = {'Accept': 'application/json'}
132 api_url = '{}/suite-api/api/alerts/{}'.format(access_config.get('vrops_site'), alarm_uuid)
133 api_response = requests.get(
134 api_url,
135 auth=(access_config.get('vrops_user'), access_config.get('vrops_password')),
136 verify = False, headers = headers
137 )
138
139 if api_response.status_code == 200:
140 data = api_response.json()
141 if data.get("alertDefinitionId") is not None:
142 alarm_definationID = '-'.join(data.get("alertDefinitionId").split('-')[1:])
143 else:
144 logger.error("Failed to get alert definition ID for alarm {}".format(alarm_uuid))
145 except Exception as exp:
146 logger.error( "Exception occured while getting alert definition ID for alarm : {}".format(exp, alarm_uuid))
147
148 return alarm_definationID
149
150
151 @route('/notify/<alarmID>', method='POST')
152 def notify_alarm(alarmID):
153 """
154 Method notify alarm details by publishing message at Kafka message bus
155 Args:
156 alarmID - Name of alarm
157 Returns:
158 response code
159 """
160 logger.info("Request:{} from:{} {} {} ".format(request, request.remote_addr, request.method, request.url))
161 response.headers['Content-Type'] = 'application/json'
162 try:
163 postdata = json.loads(request.body.read())
164 notify_details = {}
165 alaram_config = get_alarm_config()
166 #Parse noditfy data
167 notify_details['alarm_uuid'] = get_alarm_definationID(postdata.get('alertId'))
168 notify_details['description'] = postdata.get('info')
169 notify_details['alarm_instance_uuid'] = alarmID
170 notify_details['resource_uuid'] = '-'.join(postdata.get('alertName').split('-')[1:])
171 notify_details['tenant_uuid'] = alaram_config.get('tenant_id')
172 notify_details['vim_type'] = "VMware"
173 notify_details['severity'] = VROPS_SEVERITY_TO_OSM_MAPPING.get(postdata.get('criticality'), 'INDETERMINATE')
174 notify_details['status'] = postdata.get('status')
175 if postdata.get('startDate'):
176 notify_details['start_date_time'] = format_datetime(postdata.get('startDate'))
177 if postdata.get('updateDate'):
178 notify_details['update_date_time'] = format_datetime(postdata.get('updateDate'))
179 if postdata.get('cancelDate'):
180 notify_details['cancel_date_time'] = format_datetime(postdata.get('cancelDate'))
181
182 alarm_details = {'schema_version': 1.0,
183 'schema_type': "notify_alarm",
184 'notify_details': notify_details
185 }
186 alarm_data = json.dumps(alarm_details)
187 logger.info("Alarm details: {}".format(alarm_data))
188
189 #Publish Alarm details
190 kafkaMsgProducer = KafkaProducer()
191 kafkaMsgProducer.publish(topic='alarm_response', key='notify_alarm', value=alarm_data)
192
193 #return 201 on Success
194 response.status = 201
195
196 except Exception as exp:
197 logger.error('Exception: {} occured while notifying alarm {}.'.format(exp, alarmID))
198 #return 500 on Error
199 response.status = 500
200
201 return response
202
203
204 class SSLWebServer(ServerAdapter):
205 """
206 CherryPy web server with SSL support.
207 """
208
209 def run(self, handler):
210 """
211 Runs a CherryPy Server using the SSL certificate.
212 """
213 server = WSGIServer((self.host, self.port), handler)
214 server.ssl_adapter = pyOpenSSLAdapter(
215 certificate=CERTIFICATE,
216 private_key=KEY,
217 # certificate_chain="intermediate_cert.crt"
218 )
219
220 try:
221 server.start()
222 logger.info("Started vROPs Web Serverice")
223 except Exception as exp:
224 server.stop()
225 logger.error("Exception: {} Stopped vROPs Web Serverice".format(exp))
226
227
228 if __name__ == "__main__":
229 #Start SSL Web Service
230 logger.info("Start vROPs Web Serverice")
231 app = default_app()
232 server_names['sslwebserver'] = SSLWebServer
233 run(app=app,host=gethostname(), port=8080, server='sslwebserver')
234