Adds support for OSMMON_DATABASE_COMMONKEY to decrypt vim passwords
[osm/MON.git] / osm_mon / plugins / vRealiseOps / plugin_receiver.py
1 # -*- coding: utf-8 -*-
2
3 ##
4 # Copyright 2016-2017 VMware Inc.
5 # This file is part of ETSI OSM
6 # All Rights Reserved.
7 #
8 # Licensed under the Apache License, Version 2.0 (the "License"); you may
9 # not use this file except in compliance with the License. You may obtain
10 # a copy of the License at
11 #
12 # http://www.apache.org/licenses/LICENSE-2.0
13 #
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17 # License for the specific language governing permissions and limitations
18 # under the License.
19 #
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact: osslegalrouting@vmware.com
22 ##
23
24 """
25 Monitoring plugin receiver that consumes the request messages &
26 responds using producer for vROPs
27 """
28
29 import json
30 import logging
31 import os
32 import sys
33 import traceback
34 from io import UnsupportedOperation
35
36 import six
37
38 from osm_mon.core.settings import Config
39 from osm_mon.plugins.vRealiseOps.mon_plugin_vrops import MonPlugin
40
41 sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', '..'))
42
43 from osm_mon.core.auth import AuthManager
44
45 from xml.etree import ElementTree as XmlElementTree
46
47 schema_version = "1.0"
48 req_config_params = ('vrops_site', 'vrops_user', 'vrops_password',
49 'vcloud-site', 'admin_username', 'admin_password',
50 'vcenter_ip', 'vcenter_port', 'vcenter_user', 'vcenter_password',
51 'vim_tenant_name', 'orgname')
52 MODULE_DIR = os.path.dirname(__file__)
53 CONFIG_FILE_NAME = 'vrops_config.xml'
54 CONFIG_FILE_PATH = os.path.join(MODULE_DIR, CONFIG_FILE_NAME)
55
56 cfg = Config.instance()
57 logging.basicConfig(stream=sys.stdout,
58 format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
59 datefmt='%m/%d/%Y %I:%M:%S %p',
60 level=logging.getLevelName(cfg.OSMMON_LOG_LEVEL))
61
62 logger = logging.getLogger(__name__)
63
64
65 class PluginReceiver:
66 """MON Plugin receiver receiving request messages & responding using producer for vROPs
67 telemetry plugin
68 """
69
70 def __init__(self):
71 """Constructor of PluginReceiver
72 """
73 self._cfg = Config.instance()
74
75 def handle_alarm_requests(self, key: str, values: dict, vim_uuid: str):
76 values['vim_uuid'] = vim_uuid
77 if key == "create_alarm_request":
78 config_alarm_info = values
79 alarm_uuid = self.create_alarm(config_alarm_info)
80 logger.info("Alarm created with alarm uuid: {}".format(alarm_uuid))
81 # Publish message using producer
82 return self.publish_create_alarm_status(alarm_uuid, config_alarm_info)
83 elif key == "update_alarm_request":
84 update_alarm_info = values
85 alarm_uuid = self.update_alarm(update_alarm_info)
86 logger.info("Alarm definition updated : alarm uuid: {}".format(alarm_uuid))
87 # Publish message using producer
88 return self.publish_update_alarm_status(alarm_uuid, update_alarm_info)
89 elif key == "delete_alarm_request":
90 delete_alarm_info = values
91 alarm_uuid = self.delete_alarm(delete_alarm_info)
92 logger.info("Alarm definition deleted : alarm uuid: {}".format(alarm_uuid))
93 # Publish message using producer
94 return self.publish_delete_alarm_status(alarm_uuid, delete_alarm_info)
95 elif key == "list_alarm_request":
96 request_input = values
97 triggered_alarm_list = self.list_alarms(request_input)
98 # Publish message using producer
99 return self.publish_list_alarm_response(triggered_alarm_list, request_input)
100 else:
101 raise UnsupportedOperation("Unknown key, no action will be performed")
102
103 def handle_metric_requests(self, key: str, values: dict, vim_uuid: str):
104 values['vim_uuid'] = vim_uuid
105 if key == "read_metric_data_request":
106 metric_request_info = values
107 access_config = self.get_vim_access_config(metric_request_info['vim_uuid'])
108 mon_plugin_obj = MonPlugin(access_config)
109 metrics_data = mon_plugin_obj.get_metrics_data(metric_request_info)
110 logger.info("Collected Metrics Data: {}".format(metrics_data))
111 # Publish message using producer
112 return self.publish_metrics_data_status(metrics_data)
113 elif key == "create_metric_request":
114 metric_info = values
115 metric_status = self.verify_metric(metric_info)
116 # Publish message using producer
117 return self.publish_create_metric_response(metric_info, metric_status)
118 elif key == "update_metric_request":
119 metric_info = values
120 metric_status = self.verify_metric(metric_info)
121 # Publish message using producer
122 return self.publish_update_metric_response(metric_info, metric_status)
123 elif key == "delete_metric_request":
124 metric_info = values
125 # Deleting Metric Data is not allowed. Publish status as False
126 logger.warning("Deleting Metric is not allowed by VMware vROPs plugin: {}"
127 .format(metric_info['metric_name']))
128 # Publish message using producer
129 return self.publish_delete_metric_response(metric_info)
130
131 else:
132 raise UnsupportedOperation("Unknown key, no action will be performed")
133
134 def create_alarm(self, config_alarm_info):
135 """Create alarm using vROPs plugin
136 """
137 access_config = self.get_vim_access_config(config_alarm_info['vim_uuid'])
138 mon_plugin = MonPlugin(access_config)
139 mon_plugin.configure_rest_plugin()
140 alarm_uuid = mon_plugin.configure_alarm(config_alarm_info['alarm_create_request'])
141 return alarm_uuid
142
143 def publish_create_alarm_status(self, alarm_uuid, config_alarm_info):
144 """Publish create alarm status using producer
145 """
146 topic = 'alarm_response'
147 msg_key = 'create_alarm_response'
148 response_msg = {"schema_version": schema_version,
149 "schema_type": "create_alarm_response",
150 "vim_uuid": config_alarm_info["vim_uuid"],
151 "alarm_create_response":
152 {"correlation_id": config_alarm_info["alarm_create_request"]["correlation_id"],
153 "alarm_uuid": alarm_uuid,
154 "status": True if alarm_uuid else False
155 }
156 }
157 logger.info("Publishing response:\nTopic={}\nKey={}\nValue={}"
158 .format(topic, msg_key, response_msg))
159
160 return response_msg
161
162 def update_alarm(self, update_alarm_info):
163 """Update already created alarm
164 """
165 access_config = self.get_vim_access_config(update_alarm_info['vim_uuid'])
166 mon_plugin = MonPlugin(access_config)
167 alarm_uuid = mon_plugin.update_alarm_configuration(update_alarm_info['alarm_update_request'])
168 return alarm_uuid
169
170 def publish_update_alarm_status(self, alarm_uuid, update_alarm_info):
171 """Publish update alarm status requests using producer
172 """
173 topic = 'alarm_response'
174 msg_key = 'update_alarm_response'
175 response_msg = {"schema_version": schema_version,
176 "schema_type": "update_alarm_response",
177 "vim_uuid": update_alarm_info["vim_uuid"],
178 "alarm_update_response":
179 {"correlation_id": update_alarm_info["alarm_update_request"]["correlation_id"],
180 "alarm_uuid": update_alarm_info["alarm_update_request"]["alarm_uuid"] \
181 if update_alarm_info["alarm_update_request"].get('alarm_uuid') is not None else None,
182 "status": True if alarm_uuid else False
183 }
184 }
185 logger.info("Publishing response:\nTopic={}\nKey={}\nValue={}"
186 .format(topic, msg_key, response_msg))
187
188 return response_msg
189
190 def delete_alarm(self, delete_alarm_info):
191 """Delete alarm configuration
192 """
193 access_config = self.get_vim_access_config(delete_alarm_info['vim_uuid'])
194 mon_plugin = MonPlugin(access_config)
195 alarm_uuid = mon_plugin.delete_alarm_configuration(delete_alarm_info['alarm_delete_request'])
196 return alarm_uuid
197
198 def publish_delete_alarm_status(self, alarm_uuid, delete_alarm_info):
199 """Publish update alarm status requests using producer
200 """
201 topic = 'alarm_response'
202 msg_key = 'delete_alarm_response'
203 response_msg = {"schema_version": schema_version,
204 "schema_type": "delete_alarm_response",
205 "vim_uuid": delete_alarm_info['vim_uuid'],
206 "alarm_deletion_response":
207 {"correlation_id": delete_alarm_info["alarm_delete_request"]["correlation_id"],
208 "alarm_uuid": delete_alarm_info["alarm_delete_request"]["alarm_uuid"],
209 "status": True if alarm_uuid else False
210 }
211 }
212 logger.info("Publishing response:\nTopic={}\nKey={}\nValue={}"
213 .format(topic, msg_key, response_msg))
214
215 return response_msg
216
217 def publish_metrics_data_status(self, metrics_data):
218 """Publish the requested metric data using producer
219 """
220 topic = 'metric_response'
221 msg_key = 'read_metric_data_response'
222 logger.info("Publishing response:\nTopic={}\nKey={}\nValue={}"
223 .format(topic, msg_key, metrics_data))
224
225 return metrics_data
226
227 def verify_metric(self, metric_info):
228 """Verify if metric is supported or not
229 """
230 access_config = self.get_vim_access_config(metric_info['vim_uuid'])
231 mon_plugin = MonPlugin(access_config)
232 if 'metric_create_request' in metric_info:
233 metric_key_status = mon_plugin.verify_metric_support(metric_info['metric_create_request'])
234 else:
235 metric_key_status = mon_plugin.verify_metric_support(metric_info['metric_update_request'])
236 return metric_key_status
237
238 def publish_create_metric_response(self, metric_info, metric_status):
239 """Publish create metric response
240 """
241 topic = 'metric_response'
242 msg_key = 'create_metric_response'
243 response_msg = {"schema_version": schema_version,
244 "schema_type": "create_metric_response",
245 ##"vim_uuid":metric_info['vim_uuid'],
246 ##"correlation_id":metric_info['correlation_id'],
247 "metric_create_response":
248 {
249 ##"metric_uuid":'0',
250 ##"resource_uuid":metric_info['metric_create']['resource_uuid'],
251 ##"vim_uuid":metric_info['vim_uuid'], #May be required. TODO - Confirm
252 "correlation_id": metric_info['correlation_id'],
253 "status": metric_status
254 }
255 }
256 logger.info("Publishing response:\nTopic={}\nKey={}\nValue={}"
257 .format(topic, msg_key, response_msg))
258
259 return response_msg
260
261 def publish_update_metric_response(self, metric_info, metric_status):
262 """Publish update metric response
263 """
264 topic = 'metric_response'
265 msg_key = 'update_metric_response'
266 response_msg = {"schema_version": schema_version,
267 "schema_type": "metric_update_response",
268 "vim_uuid": metric_info['vim_uuid'],
269 "metric_update_response":
270 {
271 "metric_uuid": '0',
272 "correlation_id": metric_info['correlation_id'],
273 "resource_uuid": metric_info['metric_create']['resource_uuid'],
274 "status": metric_status
275 }
276 }
277 logger.info("Publishing response:\nTopic={}\nKey={}\nValue={}"
278 .format(topic, msg_key, response_msg))
279
280 return response_msg
281
282 def publish_delete_metric_response(self, metric_info):
283 """Publish delete metric response
284 """
285 topic = 'metric_response'
286 msg_key = 'delete_metric_response'
287 if 'tenant_uuid' in metric_info and metric_info['tenant_uuid'] is not None:
288 tenant_uuid = metric_info['tenant_uuid']
289 else:
290 tenant_uuid = None
291
292 response_msg = {"schema_version": schema_version,
293 "schema_type": "delete_metric_response",
294 "vim_uuid": metric_info['vim_uuid'],
295 "correlation_id": metric_info['correlation_id'],
296 "metric_name": metric_info['metric_name'],
297 "metric_uuid": '0',
298 "resource_uuid": metric_info['resource_uuid'],
299 "tenant_uuid": tenant_uuid,
300 "status": False
301 }
302 logger.info("Publishing response:\nTopic={}\nKey={}\nValue={}"
303 .format(topic, msg_key, response_msg))
304
305 return response_msg
306
307 def list_alarms(self, list_alarm_input):
308 """Collect list of triggered alarms based on input
309 """
310 access_config = self.get_vim_access_config(list_alarm_input['vim_uuid'])
311 mon_plugin = MonPlugin(access_config)
312 triggered_alarms = mon_plugin.get_triggered_alarms_list(list_alarm_input['alarm_list_request'])
313 return triggered_alarms
314
315 def publish_list_alarm_response(self, triggered_alarm_list, list_alarm_input):
316 """Publish list of triggered alarms
317 """
318 topic = 'alarm_response'
319 msg_key = 'list_alarm_response'
320 response_msg = {"schema_version": schema_version,
321 "schema_type": "list_alarm_response",
322 "vim_type": "VMware",
323 "vim_uuid": list_alarm_input['vim_uuid'],
324 "correlation_id": list_alarm_input['alarm_list_request']['correlation_id'],
325 "list_alarm_response": triggered_alarm_list
326 }
327 logger.info("Publishing response:\nTopic={}\nKey={}\nValue={}"
328 .format(topic, msg_key, response_msg))
329
330 return response_msg
331
332 def update_access_credentials(self, access_info):
333 """Verify if all the required access config params are provided and
334 updates access config in default vrops config file
335 """
336 update_status = False
337 # Check if all the required config params are passed in request
338 if not all(keys in access_info for keys in req_config_params):
339 logger.debug("All required Access Config Parameters not provided")
340 logger.debug("List of required Access Config Parameters: {}".format(req_config_params))
341 logger.debug("List of given Access Config Parameters: {}".format(access_info))
342 return update_status
343
344 wr_status = self.write_access_config(access_info)
345 return wr_status # True/False
346
347 def write_access_config(self, access_info):
348 """Write access configuration to vROPs config file.
349 """
350 wr_status = False
351 try:
352 tree = XmlElementTree.parse(CONFIG_FILE_PATH)
353 root = tree.getroot()
354 alarmParams = {}
355 for config in root:
356 if config.tag == 'Access_Config':
357 for param in config:
358 for key, val in six.iteritems(access_info):
359 if param.tag == key:
360 # print param.tag, val
361 param.text = val
362
363 tree.write(CONFIG_FILE_PATH)
364 wr_status = True
365 except Exception as exp:
366 logger.warning("Failed to update Access Config Parameters: {}".format(exp))
367
368 return wr_status
369
370 def publish_access_update_response(self, access_update_status, access_info_req):
371 """Publish access update response
372 """
373 topic = 'access_credentials'
374 msg_key = 'vim_access_credentials_response'
375 response_msg = {"schema_version": schema_version,
376 "schema_type": "vim_access_credentials_response",
377 "correlation_id": access_info_req['access_config']['correlation_id'],
378 "status": access_update_status
379 }
380 logger.info("Publishing response:\nTopic={}\nKey={}\nValue={}" \
381 .format(topic, msg_key, response_msg))
382 # Core Add producer
383 return response_msg
384
385 def get_vim_access_config(self, vim_uuid):
386 """Get VIM access configuration & account details from path: VIM_ACCOUNTS_FILE_PATH
387 """
388 vim_account = {}
389 auth_manager = AuthManager()
390 vim_account_details = auth_manager.get_credentials(vim_uuid)
391
392 try:
393 if vim_account_details is not None:
394 vim_account['name'] = vim_account_details.name
395 vim_account['vim_tenant_name'] = vim_account_details.tenant_name
396 vim_account['vim_type'] = vim_account_details.type
397 vim_account['vim_url'] = vim_account_details.url
398 vim_account['org_user'] = vim_account_details.user
399 vim_account['org_password'] = vim_account_details.password
400 vim_account['vim_uuid'] = vim_account_details.uuid
401
402 vim_config = json.loads(vim_account_details.config)
403 vim_account['admin_username'] = vim_config['admin_username']
404 vim_account['admin_password'] = vim_config['admin_password']
405 vim_account['vrops_site'] = vim_config['vrops_site']
406 vim_account['vrops_user'] = vim_config['vrops_user']
407 vim_account['vrops_password'] = vim_config['vrops_password']
408 vim_account['vcenter_ip'] = vim_config['vcenter_ip']
409 vim_account['vcenter_port'] = vim_config['vcenter_port']
410 vim_account['vcenter_user'] = vim_config['vcenter_user']
411 vim_account['vcenter_password'] = vim_config['vcenter_password']
412
413 if vim_config['nsx_manager'] is not None:
414 vim_account['nsx_manager'] = vim_config['nsx_manager']
415 if vim_config['nsx_user'] is not None:
416 vim_account['nsx_user'] = vim_config['nsx_user']
417 if vim_config['nsx_password'] is not None:
418 vim_account['nsx_password'] = vim_config['nsx_password']
419 if vim_config['orgname'] is not None:
420 vim_account['orgname'] = vim_config['orgname']
421 except Exception as exp:
422 logger.error("VIM account details not sufficient: {}".format(exp))
423 return vim_account
424
425
426 """
427 def main():
428 #log.basicConfig(filename='mon_vrops_log.log',level=log.DEBUG)
429 set_logger()
430 plugin_rcvr = PluginReceiver()
431 plugin_rcvr.consume()
432
433 if __name__ == "__main__":
434 main()
435 """