Changes in vROPs Plugin.
[osm/MON.git] / plugins / vRealiseOps / mon_plugin_vrops.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 Montoring metrics & creating Alarm definations in vROPs
26 """
27
28 import requests
29 import logging as log
30 from pyvcloud.vcloudair import VCA
31 from xml.etree import ElementTree as XmlElementTree
32 import traceback
33 import time
34 import json
35 from OpenSSL.crypto import load_certificate, FILETYPE_PEM
36 import os
37 import datetime
38
39 OPERATION_MAPPING = {'GE':'GT_EQ', 'LE':'LT_EQ', 'GT':'GT', 'LT':'LT', 'EQ':'EQ'}
40 severity_mano2vrops = {'WARNING':'WARNING', 'MINOR':'WARNING', 'MAJOR':"IMMEDIATE",\
41 'CRITICAL':'CRITICAL', 'INDETERMINATE':'UNKNOWN'}
42 PERIOD_MSEC = {'HR':3600000,'DAY':86400000,'WEEK':604800000,'MONTH':2678400000,'YEAR':31536000000}
43
44 #To Do - Add actual webhook url & certificate
45 #SSL_CERTIFICATE_FILE_NAME = 'vROPs_Webservice/SSL_certificate/www.vrops_webservice.com.cert'
46 webhook_url = "https://mano-dev-1:8080/notify/" #for testing
47 SSL_CERTIFICATE_FILE_NAME = 'vROPs_Webservice/SSL_certificate/10.172.137.214.cert' #for testing
48
49 MODULE_DIR = os.path.dirname(__file__)
50 CONFIG_FILE_NAME = 'vrops_config.xml'
51 CONFIG_FILE_PATH = os.path.join(MODULE_DIR, CONFIG_FILE_NAME)
52 SSL_CERTIFICATE_FILE_PATH = os.path.join(MODULE_DIR, SSL_CERTIFICATE_FILE_NAME)
53
54 class MonPlugin():
55 """MON Plugin class for vROPs telemetry plugin
56 """
57 def __init__(self):
58 """Constructor of MON plugin
59 Params:
60 'access_config': dictionary with VIM access information based on VIM type.
61 This contains a consolidate version of VIM & monitoring tool config at creation and
62 particular VIM config at their attachment.
63 For VIM type: 'vmware',
64 access_config - {'vrops_site':<>, 'vrops_user':<>, 'vrops_password':<>,
65 'vcloud-site':<>,'admin_username':<>,'admin_password':<>,
66 'nsx_manager':<>,'nsx_user':<>,'nsx_password':<>,
67 'vcenter_ip':<>,'vcenter_port':<>,'vcenter_user':<>,'vcenter_password':<>,
68 'vim_tenant_name':<>,'orgname':<>}
69
70 #To Do
71 Returns: Raise an exception if some needed parameter is missing, but it must not do any connectivity
72 check against the VIM
73 """
74 access_config = self.get_default_Params('Access_Config')
75 self.access_config = access_config
76 if not bool(access_config):
77 log.error("Access configuration not provided in vROPs Config file")
78 raise KeyError("Access configuration not provided in vROPs Config file")
79
80 try:
81 self.vrops_site = access_config['vrops_site']
82 self.vrops_user = access_config['vrops_user']
83 self.vrops_password = access_config['vrops_password']
84 self.vcloud_site = access_config['vcloud-site']
85 self.admin_username = access_config['admin_username']
86 self.admin_password = access_config['admin_password']
87 self.tenant_id = access_config['tenant_id']
88 except KeyError as exp:
89 log.error("Check Access configuration in vROPs Config file: {}".format(exp))
90 raise KeyError("Check Access configuration in vROPs Config file: {}".format(exp))
91
92
93 def configure_alarm(self, config_dict = {}):
94 """Configures or creates a new alarm using the input parameters in config_dict
95 Params:
96 "alarm_name": Alarm name in string format
97 "description": Description of alarm in string format
98 "resource_uuid": Resource UUID for which alarm needs to be configured. in string format
99 "Resource type": String resource type: 'VDU' or 'host'
100 "Severity": 'WARNING', 'MINOR', 'MAJOR', 'CRITICAL'
101 "metric_name": Metric key in string format
102 "operation": One of ('GE', 'LE', 'GT', 'LT', 'EQ')
103 "threshold_value": Defines the threshold (up to 2 fraction digits) that,
104 if crossed, will trigger the alarm.
105 "unit": Unit of measurement in string format
106 "statistic": AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM
107
108 Default parameters for each alarm are read from the plugin specific config file.
109 Dict of default parameters is as follows:
110 default_params keys = {'cancel_cycles','wait_cycles','resource_kind','adapter_kind',
111 'alarm_type','alarm_subType',impact}
112
113 Returns the UUID of created alarm or None
114 """
115 alarm_def = None
116 #1) get alarm & metrics parameters from plugin specific file
117 def_a_params = self.get_default_Params(config_dict['alarm_name'])
118 if not def_a_params:
119 log.warn("Alarm not supported: {}".format(config_dict['alarm_name']))
120 return None
121 metric_key_params = self.get_default_Params(config_dict['metric_name'])
122 if not metric_key_params:
123 log.warn("Metric not supported: {}".format(config_dict['metric_name']))
124 return None
125 #2) create symptom definition
126 vrops_alarm_name = def_a_params['vrops_alarm']+ '-' + config_dict['resource_uuid']
127 symptom_params ={'cancel_cycles': (def_a_params['cancel_period']/300)*def_a_params['cancel_cycles'],
128 'wait_cycles': (def_a_params['period']/300)*def_a_params['evaluation'],
129 'resource_kind_key': def_a_params['resource_kind'],
130 'adapter_kind_key': def_a_params['adapter_kind'],
131 'symptom_name':vrops_alarm_name,
132 'severity': severity_mano2vrops[config_dict['severity']],
133 'metric_key':metric_key_params['metric_key'],
134 'operation':OPERATION_MAPPING[config_dict['operation']],
135 'threshold_value':config_dict['threshold_value']}
136 symptom_uuid = self.create_symptom(symptom_params)
137 if symptom_uuid is not None:
138 log.info("Symptom defined: {} with ID: {}".format(symptom_params['symptom_name'],symptom_uuid))
139 else:
140 log.warn("Failed to create Symptom: {}".format(symptom_params['symptom_name']))
141 return None
142 #3) create alert definition
143 #To Do - Get type & subtypes for all 5 alarms
144 alarm_params = {'name':vrops_alarm_name,
145 'description':config_dict['description']\
146 if config_dict['description'] is not None else config_dict['alarm_name'],
147 'adapterKindKey':def_a_params['adapter_kind'],
148 'resourceKindKey':def_a_params['resource_kind'],
149 'waitCycles':1, 'cancelCycles':1,
150 'type':def_a_params['alarm_type'], 'subType':def_a_params['alarm_subType'],
151 'severity':severity_mano2vrops[config_dict['severity']],
152 'symptomDefinitionId':symptom_uuid,
153 'impact':def_a_params['impact']}
154
155 alarm_def = self.create_alarm_definition(alarm_params)
156 if alarm_def is None:
157 log.warn("Failed to create Alert: {}".format(alarm_params['name']))
158 return None
159
160 log.info("Alarm defined: {} with ID: {}".format(alarm_params['name'],alarm_def))
161
162 #4) Find vm_moref_id from vApp uuid in vCD
163 vm_moref_id = self.get_vm_moref_id(config_dict['resource_uuid'])
164 if vm_moref_id is None:
165 log.warn("Failed to find vm morefid for vApp in vCD: {}".format(config_dict['resource_uuid']))
166 return None
167
168 #5) Based on vm_moref_id, find VM's corresponding resource_id in vROPs to set notification
169 resource_id = self.get_vm_resource_id(vm_moref_id)
170 if resource_id is None:
171 log.warn("Failed to find resource in vROPs: {}".format(config_dict['resource_uuid']))
172 return None
173
174 #6) Configure alarm notification for a particular VM using it's resource_id
175 notification_id = self.create_alarm_notification_rule(vrops_alarm_name, alarm_def, resource_id)
176 if notification_id is None:
177 return None
178 else:
179 alarm_def_uuid = alarm_def.split('-', 1)[1]
180 log.info("Alarm defination created with notification: {} with ID: {}"\
181 .format(alarm_params['name'],alarm_def_uuid))
182 #Return alarm defination UUID by removing 'AlertDefinition' from UUID
183 return (alarm_def_uuid)
184
185 def get_default_Params(self, metric_alarm_name):
186 """
187 Read the default config parameters from plugin specific file stored with plugin file.
188 Params:
189 metric_alarm_name: Name of the alarm, whose congif params to be read from the config file.
190 """
191 a_params = {}
192 try:
193 source = open(CONFIG_FILE_PATH, 'r')
194 except IOError as exp:
195 msg = ("Could not read Config file: {}, \nException: {}"\
196 .format(CONFIG_FILE_PATH, exp))
197 log.error(msg)
198 raise IOError(msg)
199
200 tree = XmlElementTree.parse(source)
201 alarms = tree.getroot()
202 for alarm in alarms:
203 if alarm.tag == metric_alarm_name:
204 for param in alarm:
205 if param.tag in ("period", "evaluation", "cancel_period", "alarm_type",\
206 "cancel_cycles", "alarm_subType"):
207 a_params[param.tag] = int(param.text)
208 elif param.tag in ("enabled", "repeat"):
209 if(param.text.lower() == "true"):
210 a_params[param.tag] = True
211 else:
212 a_params[param.tag] = False
213 else:
214 a_params[param.tag] = param.text
215 source.close()
216 return a_params
217
218
219 def create_symptom(self, symptom_params):
220 """Create Symptom definition for an alarm
221 Params:
222 symptom_params: Dict of parameters required for defining a symptom as follows
223 cancel_cycles
224 wait_cycles
225 resource_kind_key = "VirtualMachine"
226 adapter_kind_key = "VMWARE"
227 symptom_name = Test_Memory_Usage_TooHigh
228 severity
229 metric_key
230 operation = GT_EQ
231 threshold_value = 85
232 Returns the uuid of Symptom definition
233 """
234 symptom_id = None
235
236 try:
237 api_url = '/suite-api/api/symptomdefinitions'
238 headers = {'Content-Type': 'application/xml'}
239 data = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
240 <ops:symptom-definition cancelCycles="{0:s}" waitCycles="{1:s}"
241 resourceKindKey="{2:s}" adapterKindKey="{3:s}"
242 xmlns:xs="http://www.w3.org/2001/XMLSchema"
243 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
244 xmlns:ops="http://webservice.vmware.com/vRealizeOpsMgr/1.0/">
245 <ops:name>{4:s}</ops:name>
246 <ops:state severity="{5:s}">
247 <ops:condition xsi:type="ops:htCondition">
248 <ops:key>{6:s}</ops:key>
249 <ops:operator>{7:s}</ops:operator>
250 <ops:value>{8:s}</ops:value>
251 <ops:valueType>NUMERIC</ops:valueType>
252 <ops:instanced>false</ops:instanced>
253 <ops:thresholdType>STATIC</ops:thresholdType>
254 </ops:condition>
255 </ops:state>
256 </ops:symptom-definition>"""\
257 .format(str(symptom_params['cancel_cycles']),str(symptom_params['wait_cycles']),
258 symptom_params['resource_kind_key'], symptom_params['adapter_kind_key'],
259 symptom_params['symptom_name'],symptom_params['severity'],
260 symptom_params['metric_key'],symptom_params['operation'],
261 str(symptom_params['threshold_value']))
262
263 resp = requests.post(self.vrops_site + api_url,
264 auth=(self.vrops_user, self.vrops_password),
265 headers=headers,
266 verify = False,
267 data=data)
268
269 if resp.status_code != 201:
270 log.warn("Failed to create Symptom definition: {}, response {}"\
271 .format(symptom_params['symptom_name'], resp.content))
272 return None
273
274 symptom_xmlroot = XmlElementTree.fromstring(resp.content)
275 if symptom_xmlroot is not None and 'id' in symptom_xmlroot.attrib:
276 symptom_id = symptom_xmlroot.attrib['id']
277
278 return symptom_id
279
280 except Exception as exp:
281 log.warn("Error creating symptom definition : {}\n{}"\
282 .format(exp, traceback.format_exc()))
283
284
285 def create_alarm_definition(self, alarm_params):
286 """
287 Create an alarm definition in vROPs
288 Params:
289 'name': Alarm Name,
290 'description':Alarm description,
291 'adapterKindKey': Adapter type in vROPs "VMWARE",
292 'resourceKindKey':Resource type in vROPs "VirtualMachine",
293 'waitCycles': No of wait cycles,
294 'cancelCycles': No of cancel cycles,
295 'type': Alarm type,
296 'subType': Alarm subtype,
297 'severity': Severity in vROPs "CRITICAL",
298 'symptomDefinitionId':symptom Definition uuid,
299 'impact': impact 'risk'
300 Returns:
301 'alarm_uuid': returns alarm uuid
302 """
303
304 alarm_uuid = None
305
306 try:
307 api_url = '/suite-api/api/alertdefinitions'
308 headers = {'Content-Type': 'application/xml'}
309 data = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
310 <ops:alert-definition xmlns:xs="http://www.w3.org/2001/XMLSchema"
311 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
312 xmlns:ops="http://webservice.vmware.com/vRealizeOpsMgr/1.0/">
313 <ops:name>{0:s}</ops:name>
314 <ops:description>{1:s}</ops:description>
315 <ops:adapterKindKey>{2:s}</ops:adapterKindKey>
316 <ops:resourceKindKey>{3:s}</ops:resourceKindKey>
317 <ops:waitCycles>1</ops:waitCycles>
318 <ops:cancelCycles>1</ops:cancelCycles>
319 <ops:type>{4:s}</ops:type>
320 <ops:subType>{5:s}</ops:subType>
321 <ops:states>
322 <ops:state severity="{6:s}">
323 <ops:symptom-set>
324 <ops:symptomDefinitionIds>
325 <ops:symptomDefinitionId>{7:s}</ops:symptomDefinitionId>
326 </ops:symptomDefinitionIds>
327 <ops:relation>SELF</ops:relation>
328 <ops:aggregation>ALL</ops:aggregation>
329 <ops:symptomSetOperator>AND</ops:symptomSetOperator>
330 </ops:symptom-set>
331 <ops:impact>
332 <ops:impactType>BADGE</ops:impactType>
333 <ops:detail>{8:s}</ops:detail>
334 </ops:impact>
335 </ops:state>
336 </ops:states>
337 </ops:alert-definition>"""\
338 .format(alarm_params['name'],alarm_params['description'],
339 alarm_params['adapterKindKey'],alarm_params['resourceKindKey'],
340 str(alarm_params['type']),str(alarm_params['subType']),
341 alarm_params['severity'],alarm_params['symptomDefinitionId'],
342 alarm_params['impact'])
343
344 resp = requests.post(self.vrops_site + api_url,
345 auth=(self.vrops_user, self.vrops_password),
346 headers=headers,
347 verify = False,
348 data=data)
349
350 if resp.status_code != 201:
351 log.warn("Failed to create Alarm definition: {}, response {}"\
352 .format(alarm_params['name'], resp.content))
353 return None
354
355 alarm_xmlroot = XmlElementTree.fromstring(resp.content)
356 for child in alarm_xmlroot:
357 if child.tag.split("}")[1] == 'id':
358 alarm_uuid = child.text
359
360 return alarm_uuid
361
362 except Exception as exp:
363 log.warn("Error creating alarm definition : {}\n{}".format(exp, traceback.format_exc()))
364
365
366 def configure_rest_plugin(self):
367 """
368 Creates REST Plug-in for vROPs outbound alerts
369
370 Returns Plugin ID
371 """
372 plugin_id = None
373 plugin_name = 'MON_module_REST_Plugin'
374 plugin_id = self.check_if_plugin_configured(plugin_name)
375
376 #If REST plugin not configured, configure it
377 if plugin_id is not None:
378 return plugin_id
379 else:
380 try:
381 cert_file_string = open(SSL_CERTIFICATE_FILE_PATH, "rb").read()
382 except IOError as exp:
383 msg = ("Could not read SSL certificate file: {}".format(SSL_CERTIFICATE_FILE_PATH))
384 log.error(msg)
385 raise IOError(msg)
386 cert = load_certificate(FILETYPE_PEM, cert_file_string)
387 certificate = cert.digest("sha1")
388 api_url = '/suite-api/api/alertplugins'
389 headers = {'Content-Type': 'application/xml'}
390 data = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
391 <ops:notification-plugin version="0" xmlns:xs="http://www.w3.org/2001/XMLSchema"
392 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
393 xmlns:ops="http://webservice.vmware.com/vRealizeOpsMgr/1.0/">
394 <ops:pluginTypeId>RestPlugin</ops:pluginTypeId>
395 <ops:name>{0:s}</ops:name>
396 <ops:configValues>
397 <ops:configValue name="Url">{1:s}</ops:configValue>
398 <ops:configValue name="Content-type">application/xml</ops:configValue>
399 <ops:configValue name="Certificate">{2:s}</ops:configValue>
400 <ops:configValue name="ConnectionCount">20</ops:configValue>
401 </ops:configValues>
402 </ops:notification-plugin>""".format(plugin_name, webhook_url, certificate)
403
404 resp = requests.post(self.vrops_site + api_url,
405 auth=(self.vrops_user, self.vrops_password),
406 headers=headers,
407 verify = False,
408 data=data)
409
410 if resp.status_code is not 201:
411 log.warn("Failed to create REST Plugin: {} for url: {}, \nresponse code: {},"\
412 "\nresponse content: {}".format(plugin_name, webhook_url,\
413 resp.status_code, resp.content))
414 return None
415
416 plugin_xmlroot = XmlElementTree.fromstring(resp.content)
417 if plugin_xmlroot is not None:
418 for child in plugin_xmlroot:
419 if child.tag.split("}")[1] == 'pluginId':
420 plugin_id = plugin_xmlroot.find('{http://webservice.vmware.com/vRealizeOpsMgr/1.0/}pluginId').text
421
422 if plugin_id is None:
423 log.warn("Failed to get REST Plugin ID for {}, url: {}".format(plugin_name, webhook_url))
424 return None
425 else:
426 log.info("Created REST Plugin: {} with ID : {} for url: {}".format(plugin_name, plugin_id, webhook_url))
427 status = self.enable_rest_plugin(plugin_id, plugin_name)
428 if status is False:
429 log.warn("Failed to enable created REST Plugin: {} for url: {}".format(plugin_name, webhook_url))
430 return None
431 else:
432 log.info("Enabled REST Plugin: {} for url: {}".format(plugin_name, webhook_url))
433 return plugin_id
434
435 def check_if_plugin_configured(self, plugin_name):
436 """Check if the REST plugin is already created
437 Returns: plugin_id: if already created, None: if needs to be created
438 """
439 plugin_id = None
440 #Find the REST Plugin id details for - MON_module_REST_Plugin
441 api_url = '/suite-api/api/alertplugins'
442 headers = {'Accept': 'application/xml'}
443 namespace = {'params':"http://webservice.vmware.com/vRealizeOpsMgr/1.0/"}
444
445 resp = requests.get(self.vrops_site + api_url,
446 auth=(self.vrops_user, self.vrops_password),
447 verify = False, headers = headers)
448
449 if resp.status_code is not 200:
450 log.warn("Failed to REST GET Alarm plugin details \nResponse code: {}\nResponse content: {}"\
451 .format(resp.status_code, resp.content))
452 return None
453
454 # Look for specific plugin & parse pluginId for 'MON_module_REST_Plugin'
455 xmlroot_resp = XmlElementTree.fromstring(resp.content)
456 for notify_plugin in xmlroot_resp.findall('params:notification-plugin',namespace):
457 if notify_plugin.find('params:name',namespace) is not None and\
458 notify_plugin.find('params:pluginId',namespace) is not None:
459 if notify_plugin.find('params:name',namespace).text == plugin_name:
460 plugin_id = notify_plugin.find('params:pluginId',namespace).text
461
462 if plugin_id is None:
463 log.warn("REST plugin {} not found".format('MON_module_REST_Plugin'))
464 return None
465 else:
466 log.info("Found REST Plugin: {}".format(plugin_name))
467 return plugin_id
468
469
470 def enable_rest_plugin(self, plugin_id, plugin_name):
471 """
472 Enable the REST plugin using plugin_id
473 Params: plugin_id: plugin ID string that is to be enabled
474 Returns: status (Boolean) - True for success, False for failure
475 """
476
477 if plugin_id is None or plugin_name is None:
478 log.debug("enable_rest_plugin() : Plugin ID or plugin_name not provided for {} plugin"\
479 .format(plugin_name))
480 return False
481
482 try:
483 api_url = "/suite-api/api/alertplugins/{}/enable/True".format(plugin_id)
484
485 resp = requests.put(self.vrops_site + api_url,
486 auth=(self.vrops_user, self.vrops_password),
487 verify = False)
488
489 if resp.status_code is not 204:
490 log.warn("Failed to enable REST plugin {}. \nResponse code {}\nResponse Content: {}"\
491 .format(plugin_name, resp.status_code, resp.content))
492 return False
493
494 log.info("Enabled REST plugin {}.".format(plugin_name))
495 return True
496
497 except Exception as exp:
498 log.warn("Error enabling REST plugin for {} plugin: Exception: {}\n{}"\
499 .format(plugin_name, exp, traceback.format_exc()))
500
501 def create_alarm_notification_rule(self, alarm_name, alarm_id, resource_id):
502 """
503 Create notification rule for each alarm
504 Params:
505 alarm_name
506 alarm_id
507 resource_id
508
509 Returns:
510 notification_id: notification_id or None
511 """
512 notification_name = 'notify_' + alarm_name
513 notification_id = None
514 plugin_name = 'MON_module_REST_Plugin'
515
516 #1) Find the REST Plugin id details for - MON_module_REST_Plugin
517 plugin_id = self.check_if_plugin_configured(plugin_name)
518 if plugin_id is None:
519 log.warn("Failed to get REST plugin_id for : {}".format('MON_module_REST_Plugin'))
520 return None
521
522 #2) Create Alarm notification rule
523 api_url = '/suite-api/api/notifications/rules'
524 headers = {'Content-Type': 'application/xml'}
525 data = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
526 <ops:notification-rule xmlns:xs="http://www.w3.org/2001/XMLSchema"
527 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
528 xmlns:ops="http://webservice.vmware.com/vRealizeOpsMgr/1.0/">
529 <ops:name>{0:s}</ops:name>
530 <ops:pluginId>{1:s}</ops:pluginId>
531 <ops:resourceFilter resourceId="{2:s}">
532 <ops:matchResourceIdOnly>true</ops:matchResourceIdOnly>
533 </ops:resourceFilter>
534 <ops:alertDefinitionIdFilters>
535 <ops:values>{3:s}</ops:values>
536 </ops:alertDefinitionIdFilters>
537 </ops:notification-rule>"""\
538 .format(notification_name, plugin_id, resource_id, alarm_id)
539
540 resp = requests.post(self.vrops_site + api_url,
541 auth=(self.vrops_user, self.vrops_password),
542 headers=headers,
543 verify = False,
544 data=data)
545
546 if resp.status_code is not 201:
547 log.warn("Failed to create Alarm notification rule {} for {} alarm."\
548 "\nResponse code: {}\nResponse content: {}"\
549 .format(notification_name, alarm_name, resp.status_code, resp.content))
550 return None
551
552 #parse notification id from response
553 xmlroot_resp = XmlElementTree.fromstring(resp.content)
554 if xmlroot_resp is not None and 'id' in xmlroot_resp.attrib:
555 notification_id = xmlroot_resp.attrib.get('id')
556
557 log.info("Created Alarm notification rule {} for {} alarm.".format(notification_name, alarm_name))
558 return notification_id
559
560 def get_vm_moref_id(self, vapp_uuid):
561 """
562 Get the moref_id of given VM
563 """
564 try:
565 if vapp_uuid:
566 vm_details = self.get_vapp_details_rest(vapp_uuid)
567 if vm_details and "vm_vcenter_info" in vm_details:
568 vm_moref_id = vm_details["vm_vcenter_info"].get("vm_moref_id", None)
569
570 log.info("Found vm_moref_id: {} for vApp UUID: {}".format(vm_moref_id, vapp_uuid))
571 return vm_moref_id
572
573 except Exception as exp:
574 log.warn("Error occurred while getting VM moref ID for VM : {}\n{}"\
575 .format(exp, traceback.format_exc()))
576
577
578 def get_vapp_details_rest(self, vapp_uuid=None):
579 """
580 Method retrieve vapp detail from vCloud director
581
582 Args:
583 vapp_uuid - is vapp identifier.
584
585 Returns:
586 Returns VM MOref ID or return None
587 """
588
589 parsed_respond = {}
590 vca = None
591
592 vca = self.connect_as_admin()
593
594 if not vca:
595 log.warn("connect() to vCD is failed")
596 if vapp_uuid is None:
597 return None
598
599 url_list = [vca.host, '/api/vApp/vapp-', vapp_uuid]
600 get_vapp_restcall = ''.join(url_list)
601
602 if vca.vcloud_session and vca.vcloud_session.organization:
603 response = requests.get(get_vapp_restcall,
604 headers=vca.vcloud_session.get_vcloud_headers(),
605 verify=vca.verify)
606
607 if response.status_code != 200:
608 log.warn("REST API call {} failed. Return status code {}"\
609 .format(get_vapp_restcall, response.content))
610 return parsed_respond
611
612 try:
613 xmlroot_respond = XmlElementTree.fromstring(response.content)
614
615 namespaces = {'vm': 'http://www.vmware.com/vcloud/v1.5',
616 "vmext":"http://www.vmware.com/vcloud/extension/v1.5",
617 "xmlns":"http://www.vmware.com/vcloud/v1.5"
618 }
619
620 # parse children section for other attrib
621 children_section = xmlroot_respond.find('vm:Children/', namespaces)
622 if children_section is not None:
623 vCloud_extension_section = children_section.find('xmlns:VCloudExtension', namespaces)
624 if vCloud_extension_section is not None:
625 vm_vcenter_info = {}
626 vim_info = vCloud_extension_section.find('vmext:VmVimInfo', namespaces)
627 vmext = vim_info.find('vmext:VmVimObjectRef', namespaces)
628 if vmext is not None:
629 vm_vcenter_info["vm_moref_id"] = vmext.find('vmext:MoRef', namespaces).text
630 parsed_respond["vm_vcenter_info"]= vm_vcenter_info
631
632 except Exception as exp :
633 log.warn("Error occurred calling rest api for getting vApp details: {}\n{}"\
634 .format(exp, traceback.format_exc()))
635
636 return parsed_respond
637
638
639 def connect_as_admin(self):
640 """ Method connect as pvdc admin user to vCloud director.
641 There are certain action that can be done only by provider vdc admin user.
642 Organization creation / provider network creation etc.
643
644 Returns:
645 The return vca object that letter can be used to connect to vcloud direct as admin for provider vdc
646 """
647
648 log.info("Logging in to a VCD org as admin.")
649
650 vca_admin = VCA(host=self.vcloud_site,
651 username=self.admin_username,
652 service_type='standalone',
653 version='5.9',
654 verify=False,
655 log=False)
656 result = vca_admin.login(password=self.admin_password, org='System')
657 if not result:
658 log.warn("Can't connect to a vCloud director as: {}".format(self.admin_username))
659 result = vca_admin.login(token=vca_admin.token, org='System', org_url=vca_admin.vcloud_session.org_url)
660 if result is True:
661 log.info("Successfully logged to a vcloud direct org: {} as user: {}"\
662 .format('System', self.admin_username))
663
664 return vca_admin
665
666
667 def get_vm_resource_id(self, vm_moref_id):
668 """ Find resource ID in vROPs using vm_moref_id
669 """
670 if vm_moref_id is None:
671 return None
672
673 api_url = '/suite-api/api/resources'
674 headers = {'Accept': 'application/xml'}
675 namespace = {'params':"http://webservice.vmware.com/vRealizeOpsMgr/1.0/"}
676
677 resp = requests.get(self.vrops_site + api_url,
678 auth=(self.vrops_user, self.vrops_password),
679 verify = False, headers = headers)
680
681 if resp.status_code is not 200:
682 log.warn("Failed to get resource details from vROPs for {}\nResponse code:{}\nResponse Content: {}"\
683 .format(vm_moref_id, resp.status_code, resp.content))
684 return None
685
686 try:
687 xmlroot_respond = XmlElementTree.fromstring(resp.content)
688 for resource in xmlroot_respond.findall('params:resource',namespace):
689 if resource is not None:
690 resource_key = resource.find('params:resourceKey',namespace)
691 if resource_key is not None:
692 if resource_key.find('params:adapterKindKey',namespace).text == 'VMWARE' and \
693 resource_key.find('params:resourceKindKey',namespace).text == 'VirtualMachine':
694 for child in resource_key:
695 if child.tag.split('}')[1]=='resourceIdentifiers':
696 resourceIdentifiers = child
697 for r_id in resourceIdentifiers:
698 if r_id.find('params:value',namespace).text == vm_moref_id:
699 log.info("Found Resource ID : {} in vROPs for {}"\
700 .format(resource.attrib['identifier'], vm_moref_id))
701 return resource.attrib['identifier']
702 except Exception as exp:
703 log.warn("Error in parsing {}\n{}".format(exp, traceback.format_exc()))
704
705
706 def get_metrics_data(self, metric={}):
707 """Get an individual metric's data of a resource.
708 Params:
709 'metric_name': Normalized name of metric (string)
710 'resource_uuid': Resource UUID (string)
711 'period': Time period in Period Unit for which metrics data to be collected from
712 Monitoring tool from now.
713 'period_unit': Period measurement unit can be one of 'HR', 'DAY', 'MONTH', 'YEAR'
714
715 Return a dict that contains:
716 'metric_name': Normalized name of metric (string)
717 'resource_uuid': Resource UUID (string)
718 'tenant_id': tenent id name in which the resource is present in string format
719 'metrics_data': Dictionary containing time_series & metric_series data.
720 'time_series': List of individual time stamp values in msec
721 'metric_series': List of individual metrics data values
722 Raises an exception upon error or when network is not found
723 """
724 return_data = {}
725 return_data['schema_version'] = 1.0
726 return_data['schema_type'] = 'read_metric_data_response'
727 return_data['metric_name'] = metric['metric_name']
728 #To do - No metric_uuid in vROPs, thus returning metric_name
729 return_data['metric_uuid'] = metric['metric_name']
730 return_data['correlation_id'] = metric['correlation_id']
731 return_data['resource_uuid'] = metric['resource_uuid']
732 return_data['metrics_data'] = {'time_series':[], 'metric_series':[]}
733 #To do - Need confirmation about uuid & id
734 return_data['tenant_uuid'] = metric['tenant_uuid']
735 return_data['unit'] = None
736 #return_data['tenant_id'] = self.tenant_id
737 #log.warn("return_data: {}".format(return_data))
738
739 #1) Get metric details from plugin specific file & format it into vROPs metrics
740 metric_key_params = self.get_default_Params(metric['metric_name'])
741
742 if not metric_key_params:
743 log.warn("Metric not supported: {}".format(metric['metric_name']))
744 #To Do: Return message
745 return return_data
746
747 return_data['unit'] = metric_key_params['unit']
748
749 #2) Find the resource id in vROPs based on OSM resource_uuid
750 #2.a) Find vm_moref_id from vApp uuid in vCD
751 vm_moref_id = self.get_vm_moref_id(metric['resource_uuid'])
752 if vm_moref_id is None:
753 log.warn("Failed to find vm morefid for vApp in vCD: {}".format(config_dict['resource_uuid']))
754 return return_data
755 #2.b) Based on vm_moref_id, find VM's corresponding resource_id in vROPs to set notification
756 resource_id = self.get_vm_resource_id(vm_moref_id)
757 if resource_id is None:
758 log.warn("Failed to find resource in vROPs: {}".format(config_dict['resource_uuid']))
759 return return_data
760
761 #3) Calculate begin & end time for period & period unit
762 end_time = int(round(time.time() * 1000))
763 if metric['collection_unit'] == 'YR':
764 time_diff = PERIOD_MSEC[metric['collection_unit']]
765 else:
766 time_diff = metric['collection_period']* PERIOD_MSEC[metric['collection_unit']]
767 begin_time = end_time - time_diff
768
769 #4) Get the metrics data
770 log.info("metric_key_params['metric_key'] = {}".format(metric_key_params['metric_key']))
771 log.info("end_time: {}, begin_time: {}".format(end_time, begin_time))
772
773 url_list = ['/suite-api/api/resources/', resource_id, '/stats?statKey=',\
774 metric_key_params['metric_key'], '&begin=', str(begin_time),'&end=',str(end_time)]
775 api_url = ''.join(url_list)
776 headers = {'Accept': 'application/json'}
777
778 resp = requests.get(self.vrops_site + api_url,
779 auth=(self.vrops_user, self.vrops_password),
780 verify = False, headers = headers)
781
782 if resp.status_code is not 200:
783 log.warn("Failed to retrive Metric data from vROPs for {}\nResponse code:{}\nResponse Content: {}"\
784 .format(metric['metric_name'], resp.status_code, resp.content))
785 return return_data
786
787 #5) Convert to required format
788 metrics_data = {}
789 json_data = json.loads(resp.content)
790 for resp_key,resp_val in json_data.iteritems():
791 if resp_key == 'values':
792 data = json_data['values'][0]
793 for data_k,data_v in data.iteritems():
794 if data_k == 'stat-list':
795 stat_list = data_v
796 for stat_list_k,stat_list_v in stat_list.iteritems():
797 for stat_keys,stat_vals in stat_list_v[0].iteritems():
798 if stat_keys == 'timestamps':
799 metrics_data['time_series'] = stat_list_v[0]['timestamps']
800 if stat_keys == 'data':
801 metrics_data['metric_series'] = stat_list_v[0]['data']
802
803 return_data['metrics_data'] = metrics_data
804
805 return return_data
806
807 def update_alarm_configuration(self, new_alarm_config):
808 """Update alarm configuration (i.e. Symptom & alarm) as per request
809 """
810 #1) Get Alarm details from it's uuid & find the symptom defination
811 alarm_details_json, alarm_details = self.get_alarm_defination_details(new_alarm_config['alarm_uuid'])
812 if alarm_details_json is None:
813 return None
814
815 try:
816 #2) Update the symptom defination
817 if alarm_details['alarm_id'] is not None and alarm_details['symptom_definition_id'] is not None:
818 symptom_defination_id = alarm_details['symptom_definition_id']
819 else:
820 log.info("Symptom Defination ID not found for {}".format(new_alarm_config['alarm_uuid']))
821 return None
822
823 symptom_uuid = self.update_symptom_defination(symptom_defination_id, new_alarm_config)
824
825 #3) Update the alarm defination & Return UUID if successful update
826 if symptom_uuid is None:
827 return None
828 else:
829 alarm_uuid = self.reconfigure_alarm(alarm_details_json, new_alarm_config)
830 if alarm_uuid is None:
831 return None
832 else:
833 return alarm_uuid
834 except:
835 log.error("Exception while updating alarm: {}".format(traceback.format_exc()))
836
837 def get_alarm_defination_details(self, alarm_uuid):
838 """Get alarm details based on alarm UUID
839 """
840 if alarm_uuid is None:
841 log.warn("get_alarm_defination_details: Alarm UUID not provided")
842 return None
843
844 alarm_details = {}
845 json_data = {}
846 api_url = '/suite-api/api/alertdefinitions/AlertDefinition-'
847 headers = {'Accept': 'application/json'}
848
849 resp = requests.get(self.vrops_site + api_url + alarm_uuid,
850 auth=(self.vrops_user, self.vrops_password),
851 verify = False, headers = headers)
852
853 if resp.status_code is not 200:
854 log.warn("Failed to get alarm details from vROPs for {}\nResponse code:{}\nResponse Content: {}"\
855 .format(alarm_uuid, resp.status_code, resp.content))
856 return None
857
858 try:
859 json_data = json.loads(resp.content)
860 if json_data['id'] is not None:
861 alarm_details['alarm_id'] = json_data['id']
862 alarm_details['alarm_name'] = json_data['name']
863 alarm_details['adapter_kind'] = json_data['adapterKindKey']
864 alarm_details['resource_kind'] = json_data['resourceKindKey']
865 alarm_details['type'] = ['type']
866 alarm_details['sub_type'] = json_data['subType']
867 alarm_details['symptom_definition_id'] = json_data['states'][0]['base-symptom-set']['symptomDefinitionIds'][0]
868 except exception as exp:
869 log.warn("Exception while retriving alarm defination details: {}".format(exp))
870
871 return json_data, alarm_details
872
873
874 def update_symptom_defination(self, symptom_uuid, new_alarm_config):
875 """Update symptom defination based on new alarm input configuration
876 """
877 #1) Get symptom defination details
878 symptom_details = self.get_symptom_defination_details(symptom_uuid)
879 #print "\n\nsymptom_details: {}".format(symptom_details)
880 if symptom_details is None:
881 return None
882
883 if new_alarm_config.has_key('severity') and new_alarm_config['severity'] is not None:
884 symptom_details['state']['severity'] = severity_mano2vrops[new_alarm_config['severity']]
885 if new_alarm_config.has_key('operation') and new_alarm_config['operation'] is not None:
886 symptom_details['state']['condition']['operator'] = OPERATION_MAPPING[new_alarm_config['operation']]
887 if new_alarm_config.has_key('threshold_value') and new_alarm_config['threshold_value'] is not None:
888 symptom_details['state']['condition']['value'] = new_alarm_config['threshold_value']
889 #Find vrops metric key from metric_name, if required
890 """
891 if new_alarm_config.has_key('metric_name') and new_alarm_config['metric_name'] is not None:
892 metric_key_params = self.get_default_Params(new_alarm_config['metric_name'])
893 if not metric_key_params:
894 log.warn("Metric not supported: {}".format(config_dict['metric_name']))
895 return None
896 symptom_details['state']['condition']['key'] = metric_key_params['metric_key']
897 """
898 log.info("Fetched Symptom details : {}".format(symptom_details))
899
900 api_url = '/suite-api/api/symptomdefinitions'
901 headers = {'Content-Type': 'application/json', 'Accept':'application/json'}
902 data = json.dumps(symptom_details)
903 resp = requests.put(self.vrops_site + api_url,
904 auth=(self.vrops_user, self.vrops_password),
905 headers=headers,
906 verify = False,
907 data=data)
908
909 if resp.status_code != 200:
910 log.warn("Failed to update Symptom definition: {}, response {}"\
911 .format(symptom_uuid, resp.content))
912 return None
913
914
915 if symptom_uuid is not None:
916 log.info("Symptom defination updated {} for alarm: {}"\
917 .format(symptom_uuid, new_alarm_config['alarm_uuid']))
918 return symptom_uuid
919 else:
920 log.warn("Failed to update Symptom Defination {} for : {}"\
921 .format(symptom_uuid, new_alarm_config['alarm_uuid']))
922 return None
923
924
925 def get_symptom_defination_details(self, symptom_uuid):
926 """Get symptom defination details
927 """
928 symptom_details = {}
929 if symptom_uuid is None:
930 log.warn("get_symptom_defination_details: Symptom UUID not provided")
931 return None
932
933 api_url = '/suite-api/api/symptomdefinitions/'
934 headers = {'Accept': 'application/json'}
935
936 resp = requests.get(self.vrops_site + api_url + symptom_uuid,
937 auth=(self.vrops_user, self.vrops_password),
938 verify = False, headers = headers)
939
940 if resp.status_code is not 200:
941 log.warn("Failed to get symptom details for {} \nResponse code:{}\nResponse Content: {}"\
942 .format(symptom_uuid, resp.status_code, resp.content))
943 return None
944
945 symptom_details = json.loads(resp.content)
946 #print "New symptom Details: {}".format(symptom_details)
947 return symptom_details
948
949
950 def reconfigure_alarm(self, alarm_details_json, new_alarm_config):
951 """Reconfigure alarm defination as per input
952 """
953 if new_alarm_config.has_key('severity') and new_alarm_config['severity'] is not None:
954 alarm_details_json['states'][0]['severity'] = new_alarm_config['severity']
955
956 api_url = '/suite-api/api/alertdefinitions'
957 headers = {'Content-Type': 'application/json', 'Accept':'application/json'}
958 data = json.dumps(alarm_details_json)
959 resp = requests.put(self.vrops_site + api_url,
960 auth=(self.vrops_user, self.vrops_password),
961 headers=headers,
962 verify = False,
963 data=data)
964
965 if resp.status_code != 200:
966 log.warn("Failed to create Symptom definition: {}, response code {}, response content: {}"\
967 .format(symptom_uuid, resp.status_code, resp.content))
968 return None
969 else:
970 parsed_alarm_details = json.loads(resp.content)
971 alarm_def_uuid = parsed_alarm_details['id'].split('-', 1)[1]
972 log.info("Successfully updated Alarm defination: {}".format(alarm_def_uuid))
973 return alarm_def_uuid
974
975 def delete_alarm_configuration(self, delete_alarm_req_dict):
976 """Delete complete alarm configuration
977 """
978 if delete_alarm_req_dict['alarm_uuid'] is None:
979 log.info("delete_alarm_configuration: Alarm UUID not provided")
980 return None
981 #1)Get alarm & symptom defination details
982 alarm_details_json, alarm_details = self.get_alarm_defination_details(delete_alarm_req_dict['alarm_uuid'])
983 if alarm_details is None or alarm_details_json is None:
984 return None
985
986 #2) Delete alarm notfication
987 rule_id = self.delete_notification_rule(alarm_details['alarm_name'])
988 if rule_id is None:
989 return None
990
991 #3) Delete alarm configuraion
992 alarm_id = self.delete_alarm_defination(alarm_details['alarm_id'])
993 if alarm_id is None:
994 return None
995
996 #4) Delete alarm symptom
997 symptom_id = self.delete_symptom_definition(alarm_details['symptom_definition_id'])
998 if symptom_id is None:
999 return None
1000 else:
1001 log.info("Completed deleting alarm configuration: {}"\
1002 .format(delete_alarm_req_dict['alarm_uuid']))
1003 return delete_alarm_req_dict['alarm_uuid']
1004
1005 def delete_notification_rule(self, alarm_name):
1006 """Deleted notification rule defined for a particular alarm
1007 """
1008 rule_id = self.get_notification_rule_id_by_alarm_name(alarm_name)
1009 if rule_id is None:
1010 return None
1011 else:
1012 api_url = '/suite-api/api/notifications/rules/'
1013 headers = {'Accept':'application/json'}
1014 resp = requests.delete(self.vrops_site + api_url + rule_id,
1015 auth=(self.vrops_user, self.vrops_password),
1016 verify = False, headers = headers)
1017 if resp.status_code is not 204:
1018 log.warn("Failed to delete notification rules for {}".format(alarm_name))
1019 return None
1020 else:
1021 log.info("Deleted notification rules for {}".format(alarm_name))
1022 return rule_id
1023
1024 def get_notification_rule_id_by_alarm_name(self, alarm_name):
1025 """Find created Alarm notification rule id by alarm name
1026 """
1027 alarm_notify_id = 'notify_' + alarm_name
1028 api_url = '/suite-api/api/notifications/rules'
1029 headers = {'Content-Type': 'application/json', 'Accept':'application/json'}
1030 resp = requests.get(self.vrops_site + api_url,
1031 auth=(self.vrops_user, self.vrops_password),
1032 verify = False, headers = headers)
1033
1034 if resp.status_code is not 200:
1035 log.warn("Failed to get notification rules details for {}"\
1036 .format(delete_alarm_req_dict['alarm_name']))
1037 return None
1038
1039 notifications = json.loads(resp.content)
1040 if notifications is not None and notifications.has_key('notification-rule'):
1041 notifications_list = notifications['notification-rule']
1042 for dict in notifications_list:
1043 if dict['name'] is not None and dict['name'] == alarm_notify_id:
1044 notification_id = dict['id']
1045 log.info("Found Notification id to be deleted: {} for {}"\
1046 .format(notification_id, alarm_name))
1047 return notification_id
1048
1049 log.warn("Notification id to be deleted not found for {}"\
1050 .format(notification_id, alarm_name))
1051 return None
1052
1053 def delete_alarm_defination(self, alarm_id):
1054 """Delete created Alarm defination
1055 """
1056 api_url = '/suite-api/api/alertdefinitions/'
1057 headers = {'Accept':'application/json'}
1058 resp = requests.delete(self.vrops_site + api_url + alarm_id,
1059 auth=(self.vrops_user, self.vrops_password),
1060 verify = False, headers = headers)
1061 if resp.status_code is not 204:
1062 log.warn("Failed to delete alarm definition {}".format(alarm_id))
1063 return None
1064 else:
1065 log.info("Deleted alarm definition {}".format(alarm_id))
1066 return alarm_id
1067
1068 def delete_symptom_definition(self, symptom_id):
1069 """Delete symptom defination
1070 """
1071 api_url = '/suite-api/api/symptomdefinitions/'
1072 headers = {'Accept':'application/json'}
1073 resp = requests.delete(self.vrops_site + api_url + symptom_id,
1074 auth=(self.vrops_user, self.vrops_password),
1075 verify = False, headers = headers)
1076 if resp.status_code is not 204:
1077 log.warn("Failed to delete symptom definition {}".format(symptom_id))
1078 return None
1079 else:
1080 log.info("Deleted symptom definition {}".format(symptom_id))
1081 return symptom_id
1082
1083
1084 def verify_metric_support(self, metric_info):
1085 """Verify, if Metric is supported by vROPs plugin, verify metric unit & return status
1086 Returns:
1087 status: True if supported, False if not supported
1088 """
1089 status = False
1090 metric_key_params = self.get_default_Params(metric_info['metric_name'])
1091 if not metric_key_params:
1092 log.warn("Metric not supported: {}".format(metric_info['metric_name']))
1093 return status
1094 else:
1095 #If Metric is supported, verify metric unit & return status
1096 if metric_key_params['unit'] == metric_info['metric_unit']:
1097 log.info("Metric is supported: {}".format(metric_info['metric_name']))
1098 status = True
1099 else:
1100 log.warn("Metric not supported: {}".format(metric_info['metric_name']))
1101 status = False
1102 return status
1103
1104 def get_triggered_alarms_list(self, list_alarm_input):
1105 """Get list of triggered alarms on a resource based on alarm input request.
1106 """
1107 #TO Do - Need to add filtering of alarms based on Severity & alarm name
1108
1109 triggered_alarms_list = []
1110 if list_alarm_input['resource_uuid'] is None:
1111 return triggered_alarms_list
1112
1113 #1)Find vROPs resource ID using RO resource UUID
1114 vrops_resource_id = self.get_vrops_resourceid_from_ro_uuid(list_alarm_input['resource_uuid'])
1115 if vrops_resource_id is None:
1116 return triggered_alarms_list
1117
1118 #2)Get triggered alarms on particular resource
1119 triggered_alarms_list = self.get_triggered_alarms_on_resource(list_alarm_input['resource_uuid'], vrops_resource_id)
1120 return triggered_alarms_list
1121
1122 def get_vrops_resourceid_from_ro_uuid(self, ro_resource_uuid):
1123 """Fetch vROPs resource ID using resource UUID from RO/SO
1124 """
1125 #1) Find vm_moref_id from vApp uuid in vCD
1126 vm_moref_id = self.get_vm_moref_id(ro_resource_uuid)
1127 if vm_moref_id is None:
1128 log.warn("Failed to find vm morefid for vApp in vCD: {}".format(ro_resource_uuid))
1129 return None
1130
1131 #2) Based on vm_moref_id, find VM's corresponding resource_id in vROPs to set notification
1132 vrops_resource_id = self.get_vm_resource_id(vm_moref_id)
1133 if vrops_resource_id is None:
1134 log.warn("Failed to find resource in vROPs: {}".format(ro_resource_uuid))
1135 return None
1136 return vrops_resource_id
1137
1138
1139 def get_triggered_alarms_on_resource(self, ro_resource_uuid, vrops_resource_id):
1140 """Get triggered alarms on particular resource & return list of dictionary of alarms
1141 """
1142 resource_alarms = []
1143 api_url = '/suite-api/api/alerts?resourceId='
1144 headers = {'Accept':'application/json'}
1145 resp = requests.get(self.vrops_site + api_url + vrops_resource_id,
1146 auth=(self.vrops_user, self.vrops_password),
1147 verify = False, headers = headers)
1148
1149 if resp.status_code is not 200:
1150 log.warn("Failed to get notification rules details for {}"\
1151 .format(delete_alarm_req_dict['alarm_name']))
1152 return None
1153
1154 all_alerts = json.loads(resp.content)
1155 if all_alerts.has_key('alerts'):
1156 if not all_alerts['alerts']:
1157 log.info("No alarms present on resource {}".format(ro_resource_uuid))
1158 return resource_alarms
1159 all_alerts_list = all_alerts['alerts']
1160 for alarm in all_alerts_list:
1161 #log.info("Triggered Alarm {}".format(alarm))
1162 if alarm['alertDefinitionName'] is not None and\
1163 len(alarm['alertDefinitionName'].split('-', 1)) == 2:
1164 if alarm['alertDefinitionName'].split('-', 1)[1] == ro_resource_uuid:
1165 alarm_instance = {}
1166 alarm_instance['alarm_uuid'] = alarm['alertDefinitionId'].split('-', 1)[1]
1167 alarm_instance['resource_uuid'] = ro_resource_uuid
1168 alarm_instance['alarm_instance_uuid'] = alarm['alertId']
1169 alarm_instance['vim_type'] = 'VMware'
1170 #find severity of alarm
1171 severity = None
1172 for key,value in severity_mano2vrops.iteritems():
1173 if value == alarm['alertLevel']:
1174 severity = key
1175 if severity is None:
1176 severity = 'INDETERMINATE'
1177 alarm_instance['severity'] = severity
1178 alarm_instance['status'] = alarm['status']
1179 alarm_instance['start_date'] = self.convert_date_time(alarm['startTimeUTC'])
1180 alarm_instance['update_date'] = self.convert_date_time(alarm['updateTimeUTC'])
1181 alarm_instance['cancel_date'] = self.convert_date_time(alarm['cancelTimeUTC'])
1182 log.info("Triggered Alarm on resource {}".format(alarm_instance))
1183 resource_alarms.append(alarm_instance)
1184 if not resource_alarms:
1185 log.info("No alarms present on resource {}".format(ro_resource_uuid))
1186 return resource_alarms
1187
1188 def convert_date_time(self, date_time):
1189 """Convert the input UTC time in msec to OSM date time format
1190 """
1191 date_time_formatted = '0000-00-00T00:00:00'
1192 if date_time != 0:
1193 complete_datetime = datetime.datetime.fromtimestamp(date_time/1000.0).isoformat('T')
1194 date_time_formatted = complete_datetime.split('.',1)[0]
1195 return date_time_formatted
1196