1 # -*- coding: utf-8 -*-
4 # Copyright 2016-2017 VMware Inc.
5 # This file is part of ETSI OSM
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
12 # http://www.apache.org/licenses/LICENSE-2.0
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
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact: osslegalrouting@vmware.com
25 Montoring metrics & creating Alarm definations in vROPs
30 from pyvcloud
.vcloudair
import VCA
31 from xml
.etree
import ElementTree
as XmlElementTree
35 from OpenSSL
.crypto
import load_certificate
, FILETYPE_PEM
38 from socket
import getfqdn
40 from requests
.packages
.urllib3
.exceptions
import InsecureRequestWarning
41 requests
.packages
.urllib3
.disable_warnings(InsecureRequestWarning
)
43 OPERATION_MAPPING
= {'GE':'GT_EQ', 'LE':'LT_EQ', 'GT':'GT', 'LT':'LT', 'EQ':'EQ'}
44 severity_mano2vrops
= {'WARNING':'WARNING', 'MINOR':'WARNING', 'MAJOR':"IMMEDIATE",\
45 'CRITICAL':'CRITICAL', 'INDETERMINATE':'UNKNOWN'}
46 PERIOD_MSEC
= {'HR':3600000,'DAY':86400000,'WEEK':604800000,'MONTH':2678400000,'YEAR':31536000000}
48 #To Do - Add actual webhook url & certificate
49 #SSL_CERTIFICATE_FILE_NAME = 'vROPs_Webservice/SSL_certificate/www.vrops_webservice.com.cert'
50 #webhook_url = "https://mano-dev-1:8080/notify/" #for testing
51 webhook_url
= "https://" + getfqdn() + ":8080/notify/"
52 SSL_CERTIFICATE_FILE_NAME
= ('vROPs_Webservice/SSL_certificate/' + getfqdn() + ".cert")
53 #SSL_CERTIFICATE_FILE_NAME = 'vROPs_Webservice/SSL_certificate/10.172.137.214.cert' #for testing
55 MODULE_DIR
= os
.path
.dirname(__file__
)
56 CONFIG_FILE_NAME
= 'vrops_config.xml'
57 CONFIG_FILE_PATH
= os
.path
.join(MODULE_DIR
, CONFIG_FILE_NAME
)
58 SSL_CERTIFICATE_FILE_PATH
= os
.path
.join(MODULE_DIR
, SSL_CERTIFICATE_FILE_NAME
)
61 """MON Plugin class for vROPs telemetry plugin
64 """Constructor of MON plugin
66 'access_config': dictionary with VIM access information based on VIM type.
67 This contains a consolidate version of VIM & monitoring tool config at creation and
68 particular VIM config at their attachment.
69 For VIM type: 'vmware',
70 access_config - {'vrops_site':<>, 'vrops_user':<>, 'vrops_password':<>,
71 'vcloud-site':<>,'admin_username':<>,'admin_password':<>,
72 'nsx_manager':<>,'nsx_user':<>,'nsx_password':<>,
73 'vcenter_ip':<>,'vcenter_port':<>,'vcenter_user':<>,'vcenter_password':<>,
74 'vim_tenant_name':<>,'orgname':<>}
77 Returns: Raise an exception if some needed parameter is missing, but it must not do any connectivity
80 self
.logger
= logging
.getLogger('PluginReceiver.MonPlugin')
81 self
.logger
.setLevel(logging
.DEBUG
)
83 access_config
= self
.get_default_Params('Access_Config')
84 self
.access_config
= access_config
85 if not bool(access_config
):
86 self
.logger
.error("Access configuration not provided in vROPs Config file")
87 raise KeyError("Access configuration not provided in vROPs Config file")
90 self
.vrops_site
= access_config
['vrops_site']
91 self
.vrops_user
= access_config
['vrops_user']
92 self
.vrops_password
= access_config
['vrops_password']
93 self
.vcloud_site
= access_config
['vcloud-site']
94 self
.admin_username
= access_config
['admin_username']
95 self
.admin_password
= access_config
['admin_password']
96 self
.tenant_id
= access_config
['tenant_id']
97 except KeyError as exp
:
98 self
.logger
.error("Check Access configuration in vROPs Config file: {}".format(exp
))
99 raise KeyError("Check Access configuration in vROPs Config file: {}".format(exp
))
102 def configure_alarm(self
, config_dict
= {}):
103 """Configures or creates a new alarm using the input parameters in config_dict
105 "alarm_name": Alarm name in string format
106 "description": Description of alarm in string format
107 "resource_uuid": Resource UUID for which alarm needs to be configured. in string format
108 "Resource type": String resource type: 'VDU' or 'host'
109 "Severity": 'WARNING', 'MINOR', 'MAJOR', 'CRITICAL'
110 "metric_name": Metric key in string format
111 "operation": One of ('GE', 'LE', 'GT', 'LT', 'EQ')
112 "threshold_value": Defines the threshold (up to 2 fraction digits) that,
113 if crossed, will trigger the alarm.
114 "unit": Unit of measurement in string format
115 "statistic": AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM
117 Default parameters for each alarm are read from the plugin specific config file.
118 Dict of default parameters is as follows:
119 default_params keys = {'cancel_cycles','wait_cycles','resource_kind','adapter_kind',
120 'alarm_type','alarm_subType',impact}
122 Returns the UUID of created alarm or None
125 #1) get alarm & metrics parameters from plugin specific file
126 def_a_params
= self
.get_default_Params(config_dict
['alarm_name'])
128 self
.logger
.warn("Alarm not supported: {}".format(config_dict
['alarm_name']))
130 metric_key_params
= self
.get_default_Params(config_dict
['metric_name'])
131 if not metric_key_params
:
132 self
.logger
.warn("Metric not supported: {}".format(config_dict
['metric_name']))
134 #2) create symptom definition
135 vrops_alarm_name
= def_a_params
['vrops_alarm']+ '-' + config_dict
['resource_uuid']
136 symptom_params
={'cancel_cycles': (def_a_params
['cancel_period']/300)*def_a_params
['cancel_cycles'],
137 'wait_cycles': (def_a_params
['period']/300)*def_a_params
['evaluation'],
138 'resource_kind_key': def_a_params
['resource_kind'],
139 'adapter_kind_key': def_a_params
['adapter_kind'],
140 'symptom_name':vrops_alarm_name
,
141 'severity': severity_mano2vrops
[config_dict
['severity']],
142 'metric_key':metric_key_params
['metric_key'],
143 'operation':OPERATION_MAPPING
[config_dict
['operation']],
144 'threshold_value':config_dict
['threshold_value']}
145 symptom_uuid
= self
.create_symptom(symptom_params
)
146 if symptom_uuid
is not None:
147 self
.logger
.info("Symptom defined: {} with ID: {}".format(symptom_params
['symptom_name'],symptom_uuid
))
149 self
.logger
.warn("Failed to create Symptom: {}".format(symptom_params
['symptom_name']))
151 #3) create alert definition
152 #To Do - Get type & subtypes for all 5 alarms
153 alarm_params
= {'name':vrops_alarm_name
,
154 'description':config_dict
['description']\
155 if config_dict
['description'] is not None else config_dict
['alarm_name'],
156 'adapterKindKey':def_a_params
['adapter_kind'],
157 'resourceKindKey':def_a_params
['resource_kind'],
158 'waitCycles':1, 'cancelCycles':1,
159 'type':def_a_params
['alarm_type'], 'subType':def_a_params
['alarm_subType'],
160 'severity':severity_mano2vrops
[config_dict
['severity']],
161 'symptomDefinitionId':symptom_uuid
,
162 'impact':def_a_params
['impact']}
164 alarm_def
= self
.create_alarm_definition(alarm_params
)
165 if alarm_def
is None:
166 self
.logger
.warn("Failed to create Alert: {}".format(alarm_params
['name']))
169 self
.logger
.info("Alarm defined: {} with ID: {}".format(alarm_params
['name'],alarm_def
))
171 #4) Find vm_moref_id from vApp uuid in vCD
172 vm_moref_id
= self
.get_vm_moref_id(config_dict
['resource_uuid'])
173 if vm_moref_id
is None:
174 self
.logger
.warn("Failed to find vm morefid for vApp in vCD: {}".format(config_dict
['resource_uuid']))
177 #5) Based on vm_moref_id, find VM's corresponding resource_id in vROPs to set notification
178 resource_id
= self
.get_vm_resource_id(vm_moref_id
)
179 if resource_id
is None:
180 self
.logger
.warn("Failed to find resource in vROPs: {}".format(config_dict
['resource_uuid']))
183 #6) Configure alarm notification for a particular VM using it's resource_id
184 notification_id
= self
.create_alarm_notification_rule(vrops_alarm_name
, alarm_def
, resource_id
)
185 if notification_id
is None:
188 alarm_def_uuid
= alarm_def
.split('-', 1)[1]
189 self
.logger
.info("Alarm defination created with notification: {} with ID: {}"\
190 .format(alarm_params
['name'],alarm_def_uuid
))
191 #Return alarm defination UUID by removing 'AlertDefinition' from UUID
192 return (alarm_def_uuid
)
194 def get_default_Params(self
, metric_alarm_name
):
196 Read the default config parameters from plugin specific file stored with plugin file.
198 metric_alarm_name: Name of the alarm, whose congif params to be read from the config file.
202 source
= open(CONFIG_FILE_PATH
, 'r')
203 except IOError as exp
:
204 msg
= ("Could not read Config file: {}, \nException: {}"\
205 .format(CONFIG_FILE_PATH
, exp
))
206 self
.logger
.error(msg
)
209 tree
= XmlElementTree
.parse(source
)
210 alarms
= tree
.getroot()
212 if alarm
.tag
== metric_alarm_name
:
214 if param
.tag
in ("period", "evaluation", "cancel_period", "alarm_type",\
215 "cancel_cycles", "alarm_subType"):
216 a_params
[param
.tag
] = int(param
.text
)
217 elif param
.tag
in ("enabled", "repeat"):
218 if(param
.text
.lower() == "true"):
219 a_params
[param
.tag
] = True
221 a_params
[param
.tag
] = False
223 a_params
[param
.tag
] = param
.text
228 def create_symptom(self
, symptom_params
):
229 """Create Symptom definition for an alarm
231 symptom_params: Dict of parameters required for defining a symptom as follows
234 resource_kind_key = "VirtualMachine"
235 adapter_kind_key = "VMWARE"
236 symptom_name = Test_Memory_Usage_TooHigh
241 Returns the uuid of Symptom definition
246 api_url
= '/suite-api/api/symptomdefinitions'
247 headers
= {'Content-Type': 'application/xml'}
248 data
= """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
249 <ops:symptom-definition cancelCycles="{0:s}" waitCycles="{1:s}"
250 resourceKindKey="{2:s}" adapterKindKey="{3:s}"
251 xmlns:xs="http://www.w3.org/2001/XMLSchema"
252 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
253 xmlns:ops="http://webservice.vmware.com/vRealizeOpsMgr/1.0/">
254 <ops:name>{4:s}</ops:name>
255 <ops:state severity="{5:s}">
256 <ops:condition xsi:type="ops:htCondition">
257 <ops:key>{6:s}</ops:key>
258 <ops:operator>{7:s}</ops:operator>
259 <ops:value>{8:s}</ops:value>
260 <ops:valueType>NUMERIC</ops:valueType>
261 <ops:instanced>false</ops:instanced>
262 <ops:thresholdType>STATIC</ops:thresholdType>
265 </ops:symptom-definition>"""\
266 .format(str(symptom_params
['cancel_cycles']),str(symptom_params
['wait_cycles']),
267 symptom_params
['resource_kind_key'], symptom_params
['adapter_kind_key'],
268 symptom_params
['symptom_name'],symptom_params
['severity'],
269 symptom_params
['metric_key'],symptom_params
['operation'],
270 str(symptom_params
['threshold_value']))
272 resp
= requests
.post(self
.vrops_site
+ api_url
,
273 auth
=(self
.vrops_user
, self
.vrops_password
),
278 if resp
.status_code
!= 201:
279 self
.logger
.warn("Failed to create Symptom definition: {}, response {}"\
280 .format(symptom_params
['symptom_name'], resp
.content
))
283 symptom_xmlroot
= XmlElementTree
.fromstring(resp
.content
)
284 if symptom_xmlroot
is not None and 'id' in symptom_xmlroot
.attrib
:
285 symptom_id
= symptom_xmlroot
.attrib
['id']
289 except Exception as exp
:
290 self
.logger
.warn("Error creating symptom definition : {}\n{}"\
291 .format(exp
, traceback
.format_exc()))
294 def create_alarm_definition(self
, alarm_params
):
296 Create an alarm definition in vROPs
299 'description':Alarm description,
300 'adapterKindKey': Adapter type in vROPs "VMWARE",
301 'resourceKindKey':Resource type in vROPs "VirtualMachine",
302 'waitCycles': No of wait cycles,
303 'cancelCycles': No of cancel cycles,
305 'subType': Alarm subtype,
306 'severity': Severity in vROPs "CRITICAL",
307 'symptomDefinitionId':symptom Definition uuid,
308 'impact': impact 'risk'
310 'alarm_uuid': returns alarm uuid
316 api_url
= '/suite-api/api/alertdefinitions'
317 headers
= {'Content-Type': 'application/xml'}
318 data
= """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
319 <ops:alert-definition xmlns:xs="http://www.w3.org/2001/XMLSchema"
320 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
321 xmlns:ops="http://webservice.vmware.com/vRealizeOpsMgr/1.0/">
322 <ops:name>{0:s}</ops:name>
323 <ops:description>{1:s}</ops:description>
324 <ops:adapterKindKey>{2:s}</ops:adapterKindKey>
325 <ops:resourceKindKey>{3:s}</ops:resourceKindKey>
326 <ops:waitCycles>1</ops:waitCycles>
327 <ops:cancelCycles>1</ops:cancelCycles>
328 <ops:type>{4:s}</ops:type>
329 <ops:subType>{5:s}</ops:subType>
331 <ops:state severity="{6:s}">
333 <ops:symptomDefinitionIds>
334 <ops:symptomDefinitionId>{7:s}</ops:symptomDefinitionId>
335 </ops:symptomDefinitionIds>
336 <ops:relation>SELF</ops:relation>
337 <ops:aggregation>ALL</ops:aggregation>
338 <ops:symptomSetOperator>AND</ops:symptomSetOperator>
341 <ops:impactType>BADGE</ops:impactType>
342 <ops:detail>{8:s}</ops:detail>
346 </ops:alert-definition>"""\
347 .format(alarm_params
['name'],alarm_params
['description'],
348 alarm_params
['adapterKindKey'],alarm_params
['resourceKindKey'],
349 str(alarm_params
['type']),str(alarm_params
['subType']),
350 alarm_params
['severity'],alarm_params
['symptomDefinitionId'],
351 alarm_params
['impact'])
353 resp
= requests
.post(self
.vrops_site
+ api_url
,
354 auth
=(self
.vrops_user
, self
.vrops_password
),
359 if resp
.status_code
!= 201:
360 self
.logger
.warn("Failed to create Alarm definition: {}, response {}"\
361 .format(alarm_params
['name'], resp
.content
))
364 alarm_xmlroot
= XmlElementTree
.fromstring(resp
.content
)
365 for child
in alarm_xmlroot
:
366 if child
.tag
.split("}")[1] == 'id':
367 alarm_uuid
= child
.text
371 except Exception as exp
:
372 self
.logger
.warn("Error creating alarm definition : {}\n{}".format(exp
, traceback
.format_exc()))
375 def configure_rest_plugin(self
):
377 Creates REST Plug-in for vROPs outbound alerts
382 plugin_name
= 'MON_module_REST_Plugin'
383 plugin_id
= self
.check_if_plugin_configured(plugin_name
)
385 #If REST plugin not configured, configure it
386 if plugin_id
is not None:
390 cert_file_string
= open(SSL_CERTIFICATE_FILE_PATH
, "rb").read()
391 except IOError as exp
:
392 msg
= ("Could not read SSL certificate file: {}".format(SSL_CERTIFICATE_FILE_PATH
))
393 self
.logger
.error(msg
)
395 cert
= load_certificate(FILETYPE_PEM
, cert_file_string
)
396 certificate
= cert
.digest("sha1")
397 api_url
= '/suite-api/api/alertplugins'
398 headers
= {'Content-Type': 'application/xml'}
399 data
= """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
400 <ops:notification-plugin version="0" xmlns:xs="http://www.w3.org/2001/XMLSchema"
401 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
402 xmlns:ops="http://webservice.vmware.com/vRealizeOpsMgr/1.0/">
403 <ops:pluginTypeId>RestPlugin</ops:pluginTypeId>
404 <ops:name>{0:s}</ops:name>
406 <ops:configValue name="Url">{1:s}</ops:configValue>
407 <ops:configValue name="Content-type">application/json</ops:configValue>
408 <ops:configValue name="Certificate">{2:s}</ops:configValue>
409 <ops:configValue name="ConnectionCount">20</ops:configValue>
411 </ops:notification-plugin>""".format(plugin_name
, webhook_url
, certificate
)
413 resp
= requests
.post(self
.vrops_site
+ api_url
,
414 auth
=(self
.vrops_user
, self
.vrops_password
),
419 if resp
.status_code
is not 201:
420 self
.logger
.warn("Failed to create REST Plugin: {} for url: {}, \nresponse code: {},"\
421 "\nresponse content: {}".format(plugin_name
, webhook_url
,\
422 resp
.status_code
, resp
.content
))
425 plugin_xmlroot
= XmlElementTree
.fromstring(resp
.content
)
426 if plugin_xmlroot
is not None:
427 for child
in plugin_xmlroot
:
428 if child
.tag
.split("}")[1] == 'pluginId':
429 plugin_id
= plugin_xmlroot
.find('{http://webservice.vmware.com/vRealizeOpsMgr/1.0/}pluginId').text
431 if plugin_id
is None:
432 self
.logger
.warn("Failed to get REST Plugin ID for {}, url: {}".format(plugin_name
, webhook_url
))
435 self
.logger
.info("Created REST Plugin: {} with ID : {} for url: {}".format(plugin_name
, plugin_id
, webhook_url
))
436 status
= self
.enable_rest_plugin(plugin_id
, plugin_name
)
438 self
.logger
.warn("Failed to enable created REST Plugin: {} for url: {}".format(plugin_name
, webhook_url
))
441 self
.logger
.info("Enabled REST Plugin: {} for url: {}".format(plugin_name
, webhook_url
))
444 def check_if_plugin_configured(self
, plugin_name
):
445 """Check if the REST plugin is already created
446 Returns: plugin_id: if already created, None: if needs to be created
449 #Find the REST Plugin id details for - MON_module_REST_Plugin
450 api_url
= '/suite-api/api/alertplugins'
451 headers
= {'Accept': 'application/xml'}
452 namespace
= {'params':"http://webservice.vmware.com/vRealizeOpsMgr/1.0/"}
454 resp
= requests
.get(self
.vrops_site
+ api_url
,
455 auth
=(self
.vrops_user
, self
.vrops_password
),
456 verify
= False, headers
= headers
)
458 if resp
.status_code
is not 200:
459 self
.logger
.warn("Failed to REST GET Alarm plugin details \nResponse code: {}\nResponse content: {}"\
460 .format(resp
.status_code
, resp
.content
))
463 # Look for specific plugin & parse pluginId for 'MON_module_REST_Plugin'
464 xmlroot_resp
= XmlElementTree
.fromstring(resp
.content
)
465 for notify_plugin
in xmlroot_resp
.findall('params:notification-plugin',namespace
):
466 if notify_plugin
.find('params:name',namespace
) is not None and\
467 notify_plugin
.find('params:pluginId',namespace
) is not None:
468 if notify_plugin
.find('params:name',namespace
).text
== plugin_name
:
469 plugin_id
= notify_plugin
.find('params:pluginId',namespace
).text
471 if plugin_id
is None:
472 self
.logger
.warn("REST plugin {} not found".format('MON_module_REST_Plugin'))
475 self
.logger
.info("Found REST Plugin: {}".format(plugin_name
))
479 def enable_rest_plugin(self
, plugin_id
, plugin_name
):
481 Enable the REST plugin using plugin_id
482 Params: plugin_id: plugin ID string that is to be enabled
483 Returns: status (Boolean) - True for success, False for failure
486 if plugin_id
is None or plugin_name
is None:
487 self
.logger
.debug("enable_rest_plugin() : Plugin ID or plugin_name not provided for {} plugin"\
488 .format(plugin_name
))
492 api_url
= "/suite-api/api/alertplugins/{}/enable/True".format(plugin_id
)
494 resp
= requests
.put(self
.vrops_site
+ api_url
,
495 auth
=(self
.vrops_user
, self
.vrops_password
),
498 if resp
.status_code
is not 204:
499 self
.logger
.warn("Failed to enable REST plugin {}. \nResponse code {}\nResponse Content: {}"\
500 .format(plugin_name
, resp
.status_code
, resp
.content
))
503 self
.logger
.info("Enabled REST plugin {}.".format(plugin_name
))
506 except Exception as exp
:
507 self
.logger
.warn("Error enabling REST plugin for {} plugin: Exception: {}\n{}"\
508 .format(plugin_name
, exp
, traceback
.format_exc()))
510 def create_alarm_notification_rule(self
, alarm_name
, alarm_id
, resource_id
):
512 Create notification rule for each alarm
519 notification_id: notification_id or None
521 notification_name
= 'notify_' + alarm_name
522 notification_id
= None
523 plugin_name
= 'MON_module_REST_Plugin'
525 #1) Find the REST Plugin id details for - MON_module_REST_Plugin
526 plugin_id
= self
.check_if_plugin_configured(plugin_name
)
527 if plugin_id
is None:
528 self
.logger
.warn("Failed to get REST plugin_id for : {}".format('MON_module_REST_Plugin'))
531 #2) Create Alarm notification rule
532 api_url
= '/suite-api/api/notifications/rules'
533 headers
= {'Content-Type': 'application/xml'}
534 data
= """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
535 <ops:notification-rule xmlns:xs="http://www.w3.org/2001/XMLSchema"
536 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
537 xmlns:ops="http://webservice.vmware.com/vRealizeOpsMgr/1.0/">
538 <ops:name>{0:s}</ops:name>
539 <ops:pluginId>{1:s}</ops:pluginId>
540 <ops:resourceFilter resourceId="{2:s}">
541 <ops:matchResourceIdOnly>true</ops:matchResourceIdOnly>
542 </ops:resourceFilter>
543 <ops:alertDefinitionIdFilters>
544 <ops:values>{3:s}</ops:values>
545 </ops:alertDefinitionIdFilters>
546 </ops:notification-rule>"""\
547 .format(notification_name
, plugin_id
, resource_id
, alarm_id
)
549 resp
= requests
.post(self
.vrops_site
+ api_url
,
550 auth
=(self
.vrops_user
, self
.vrops_password
),
555 if resp
.status_code
is not 201:
556 self
.logger
.warn("Failed to create Alarm notification rule {} for {} alarm."\
557 "\nResponse code: {}\nResponse content: {}"\
558 .format(notification_name
, alarm_name
, resp
.status_code
, resp
.content
))
561 #parse notification id from response
562 xmlroot_resp
= XmlElementTree
.fromstring(resp
.content
)
563 if xmlroot_resp
is not None and 'id' in xmlroot_resp
.attrib
:
564 notification_id
= xmlroot_resp
.attrib
.get('id')
566 self
.logger
.info("Created Alarm notification rule {} for {} alarm.".format(notification_name
, alarm_name
))
567 return notification_id
569 def get_vm_moref_id(self
, vapp_uuid
):
571 Get the moref_id of given VM
575 vm_details
= self
.get_vapp_details_rest(vapp_uuid
)
576 if vm_details
and "vm_vcenter_info" in vm_details
:
577 vm_moref_id
= vm_details
["vm_vcenter_info"].get("vm_moref_id", None)
579 self
.logger
.info("Found vm_moref_id: {} for vApp UUID: {}".format(vm_moref_id
, vapp_uuid
))
582 except Exception as exp
:
583 self
.logger
.warn("Error occurred while getting VM moref ID for VM : {}\n{}"\
584 .format(exp
, traceback
.format_exc()))
587 def get_vapp_details_rest(self
, vapp_uuid
=None):
589 Method retrieve vapp detail from vCloud director
592 vapp_uuid - is vapp identifier.
595 Returns VM MOref ID or return None
601 vca
= self
.connect_as_admin()
604 self
.logger
.warn("connect() to vCD is failed")
605 if vapp_uuid
is None:
608 url_list
= [vca
.host
, '/api/vApp/vapp-', vapp_uuid
]
609 get_vapp_restcall
= ''.join(url_list
)
611 if vca
.vcloud_session
and vca
.vcloud_session
.organization
:
612 response
= requests
.get(get_vapp_restcall
,
613 headers
=vca
.vcloud_session
.get_vcloud_headers(),
616 if response
.status_code
!= 200:
617 self
.logger
.warn("REST API call {} failed. Return status code {}"\
618 .format(get_vapp_restcall
, response
.content
))
619 return parsed_respond
622 xmlroot_respond
= XmlElementTree
.fromstring(response
.content
)
624 namespaces
= {'vm': 'http://www.vmware.com/vcloud/v1.5',
625 "vmext":"http://www.vmware.com/vcloud/extension/v1.5",
626 "xmlns":"http://www.vmware.com/vcloud/v1.5"
629 # parse children section for other attrib
630 children_section
= xmlroot_respond
.find('vm:Children/', namespaces
)
631 if children_section
is not None:
632 vCloud_extension_section
= children_section
.find('xmlns:VCloudExtension', namespaces
)
633 if vCloud_extension_section
is not None:
635 vim_info
= vCloud_extension_section
.find('vmext:VmVimInfo', namespaces
)
636 vmext
= vim_info
.find('vmext:VmVimObjectRef', namespaces
)
637 if vmext
is not None:
638 vm_vcenter_info
["vm_moref_id"] = vmext
.find('vmext:MoRef', namespaces
).text
639 parsed_respond
["vm_vcenter_info"]= vm_vcenter_info
641 except Exception as exp
:
642 self
.logger
.warn("Error occurred calling rest api for getting vApp details: {}\n{}"\
643 .format(exp
, traceback
.format_exc()))
645 return parsed_respond
648 def connect_as_admin(self
):
649 """ Method connect as pvdc admin user to vCloud director.
650 There are certain action that can be done only by provider vdc admin user.
651 Organization creation / provider network creation etc.
654 The return vca object that letter can be used to connect to vcloud direct as admin for provider vdc
657 self
.logger
.info("Logging in to a VCD org as admin.")
659 vca_admin
= VCA(host
=self
.vcloud_site
,
660 username
=self
.admin_username
,
661 service_type
='standalone',
665 result
= vca_admin
.login(password
=self
.admin_password
, org
='System')
667 self
.logger
.warn("Can't connect to a vCloud director as: {}".format(self
.admin_username
))
668 result
= vca_admin
.login(token
=vca_admin
.token
, org
='System', org_url
=vca_admin
.vcloud_session
.org_url
)
670 self
.logger
.info("Successfully logged to a vcloud direct org: {} as user: {}"\
671 .format('System', self
.admin_username
))
676 def get_vm_resource_id(self
, vm_moref_id
):
677 """ Find resource ID in vROPs using vm_moref_id
679 if vm_moref_id
is None:
682 api_url
= '/suite-api/api/resources'
683 headers
= {'Accept': 'application/xml'}
684 namespace
= {'params':"http://webservice.vmware.com/vRealizeOpsMgr/1.0/"}
686 resp
= requests
.get(self
.vrops_site
+ api_url
,
687 auth
=(self
.vrops_user
, self
.vrops_password
),
688 verify
= False, headers
= headers
)
690 if resp
.status_code
is not 200:
691 self
.logger
.warn("Failed to get resource details from vROPs for {}\nResponse code:{}\nResponse Content: {}"\
692 .format(vm_moref_id
, resp
.status_code
, resp
.content
))
696 xmlroot_respond
= XmlElementTree
.fromstring(resp
.content
)
697 for resource
in xmlroot_respond
.findall('params:resource',namespace
):
698 if resource
is not None:
699 resource_key
= resource
.find('params:resourceKey',namespace
)
700 if resource_key
is not None:
701 if resource_key
.find('params:adapterKindKey',namespace
).text
== 'VMWARE' and \
702 resource_key
.find('params:resourceKindKey',namespace
).text
== 'VirtualMachine':
703 for child
in resource_key
:
704 if child
.tag
.split('}')[1]=='resourceIdentifiers':
705 resourceIdentifiers
= child
706 for r_id
in resourceIdentifiers
:
707 if r_id
.find('params:value',namespace
).text
== vm_moref_id
:
708 self
.logger
.info("Found Resource ID : {} in vROPs for {}"\
709 .format(resource
.attrib
['identifier'], vm_moref_id
))
710 return resource
.attrib
['identifier']
711 except Exception as exp
:
712 self
.logger
.warn("Error in parsing {}\n{}".format(exp
, traceback
.format_exc()))
715 def get_metrics_data(self
, metric
={}):
716 """Get an individual metric's data of a resource.
718 'metric_name': Normalized name of metric (string)
719 'resource_uuid': Resource UUID (string)
720 'period': Time period in Period Unit for which metrics data to be collected from
721 Monitoring tool from now.
722 'period_unit': Period measurement unit can be one of 'HR', 'DAY', 'MONTH', 'YEAR'
724 Return a dict that contains:
725 'metric_name': Normalized name of metric (string)
726 'resource_uuid': Resource UUID (string)
727 'tenant_id': tenent id name in which the resource is present in string format
728 'metrics_data': Dictionary containing time_series & metric_series data.
729 'time_series': List of individual time stamp values in msec
730 'metric_series': List of individual metrics data values
731 Raises an exception upon error or when network is not found
734 return_data
['schema_version'] = 1.0
735 return_data
['schema_type'] = 'read_metric_data_response'
736 return_data
['metric_name'] = metric
['metric_name']
737 #To do - No metric_uuid in vROPs, thus returning '0'
738 return_data
['metric_uuid'] = '0'
739 return_data
['correlation_id'] = metric
['correlation_id']
740 return_data
['resource_uuid'] = metric
['resource_uuid']
741 return_data
['metrics_data'] = {'time_series':[], 'metric_series':[]}
742 #To do - Need confirmation about uuid & id
743 if 'tenant_uuid' in metric
and metric
['tenant_uuid'] is not None:
744 return_data
['tenant_uuid'] = metric
['tenant_uuid']
746 return_data
['tenant_uuid'] = None
747 return_data
['unit'] = None
748 #return_data['tenant_id'] = self.tenant_id
749 #self.logger.warn("return_data: {}".format(return_data))
751 #1) Get metric details from plugin specific file & format it into vROPs metrics
752 metric_key_params
= self
.get_default_Params(metric
['metric_name'])
754 if not metric_key_params
:
755 self
.logger
.warn("Metric not supported: {}".format(metric
['metric_name']))
756 #To Do: Return message
759 return_data
['unit'] = metric_key_params
['unit']
761 #2) Find the resource id in vROPs based on OSM resource_uuid
762 #2.a) Find vm_moref_id from vApp uuid in vCD
763 vm_moref_id
= self
.get_vm_moref_id(metric
['resource_uuid'])
764 if vm_moref_id
is None:
765 self
.logger
.warn("Failed to find vm morefid for vApp in vCD: {}".format(config_dict
['resource_uuid']))
767 #2.b) Based on vm_moref_id, find VM's corresponding resource_id in vROPs to set notification
768 resource_id
= self
.get_vm_resource_id(vm_moref_id
)
769 if resource_id
is None:
770 self
.logger
.warn("Failed to find resource in vROPs: {}".format(config_dict
['resource_uuid']))
773 #3) Calculate begin & end time for period & period unit
774 end_time
= int(round(time
.time() * 1000))
775 if metric
['collection_unit'] == 'YR':
776 time_diff
= PERIOD_MSEC
[metric
['collection_unit']]
778 time_diff
= metric
['collection_period']* PERIOD_MSEC
[metric
['collection_unit']]
779 begin_time
= end_time
- time_diff
781 #4) Get the metrics data
782 self
.logger
.info("metric_key_params['metric_key'] = {}".format(metric_key_params
['metric_key']))
783 self
.logger
.info("end_time: {}, begin_time: {}".format(end_time
, begin_time
))
785 url_list
= ['/suite-api/api/resources/', resource_id
, '/stats?statKey=',\
786 metric_key_params
['metric_key'], '&begin=', str(begin_time
),'&end=',str(end_time
)]
787 api_url
= ''.join(url_list
)
788 headers
= {'Accept': 'application/json'}
790 resp
= requests
.get(self
.vrops_site
+ api_url
,
791 auth
=(self
.vrops_user
, self
.vrops_password
),
792 verify
= False, headers
= headers
)
794 if resp
.status_code
is not 200:
795 self
.logger
.warn("Failed to retrive Metric data from vROPs for {}\nResponse code:{}\nResponse Content: {}"\
796 .format(metric
['metric_name'], resp
.status_code
, resp
.content
))
799 #5) Convert to required format
801 json_data
= json
.loads(resp
.content
)
802 for resp_key
,resp_val
in json_data
.iteritems():
803 if resp_key
== 'values':
804 data
= json_data
['values'][0]
805 for data_k
,data_v
in data
.iteritems():
806 if data_k
== 'stat-list':
808 for stat_list_k
,stat_list_v
in stat_list
.iteritems():
809 for stat_keys
,stat_vals
in stat_list_v
[0].iteritems():
810 if stat_keys
== 'timestamps':
811 metrics_data
['time_series'] = stat_list_v
[0]['timestamps']
812 if stat_keys
== 'data':
813 metrics_data
['metric_series'] = stat_list_v
[0]['data']
815 return_data
['metrics_data'] = metrics_data
819 def update_alarm_configuration(self
, new_alarm_config
):
820 """Update alarm configuration (i.e. Symptom & alarm) as per request
822 #1) Get Alarm details from it's uuid & find the symptom defination
823 alarm_details_json
, alarm_details
= self
.get_alarm_defination_details(new_alarm_config
['alarm_uuid'])
824 if alarm_details_json
is None:
828 #2) Update the symptom defination
829 if alarm_details
['alarm_id'] is not None and alarm_details
['symptom_definition_id'] is not None:
830 symptom_defination_id
= alarm_details
['symptom_definition_id']
832 self
.logger
.info("Symptom Defination ID not found for {}".format(new_alarm_config
['alarm_uuid']))
835 symptom_uuid
= self
.update_symptom_defination(symptom_defination_id
, new_alarm_config
)
837 #3) Update the alarm defination & Return UUID if successful update
838 if symptom_uuid
is None:
839 self
.logger
.info("Symptom Defination details not found for {}"\
840 .format(new_alarm_config
['alarm_uuid']))
843 alarm_uuid
= self
.reconfigure_alarm(alarm_details_json
, new_alarm_config
)
844 if alarm_uuid
is None:
849 self
.logger
.error("Exception while updating alarm: {}".format(traceback
.format_exc()))
851 def get_alarm_defination_details(self
, alarm_uuid
):
852 """Get alarm details based on alarm UUID
854 if alarm_uuid
is None:
855 self
.logger
.warn("get_alarm_defination_details: Alarm UUID not provided")
860 api_url
= '/suite-api/api/alertdefinitions/AlertDefinition-'
861 headers
= {'Accept': 'application/json'}
863 resp
= requests
.get(self
.vrops_site
+ api_url
+ alarm_uuid
,
864 auth
=(self
.vrops_user
, self
.vrops_password
),
865 verify
= False, headers
= headers
)
867 if resp
.status_code
is not 200:
868 self
.logger
.warn("Alarm to be updated not found: {}\nResponse code:{}\nResponse Content: {}"\
869 .format(alarm_uuid
, resp
.status_code
, resp
.content
))
873 json_data
= json
.loads(resp
.content
)
874 if json_data
['id'] is not None:
875 alarm_details
['alarm_id'] = json_data
['id']
876 alarm_details
['alarm_name'] = json_data
['name']
877 alarm_details
['adapter_kind'] = json_data
['adapterKindKey']
878 alarm_details
['resource_kind'] = json_data
['resourceKindKey']
879 alarm_details
['type'] = json_data
['type']
880 alarm_details
['sub_type'] = json_data
['subType']
881 alarm_details
['symptom_definition_id'] = json_data
['states'][0]['base-symptom-set']['symptomDefinitionIds'][0]
882 except exception
as exp
:
883 self
.logger
.warn("Exception while retriving alarm defination details: {}".format(exp
))
886 return json_data
, alarm_details
889 def update_symptom_defination(self
, symptom_uuid
, new_alarm_config
):
890 """Update symptom defination based on new alarm input configuration
892 #1) Get symptom defination details
893 symptom_details
= self
.get_symptom_defination_details(symptom_uuid
)
894 #print "\n\nsymptom_details: {}".format(symptom_details)
895 if symptom_details
is None:
898 if new_alarm_config
.has_key('severity') and new_alarm_config
['severity'] is not None:
899 symptom_details
['state']['severity'] = severity_mano2vrops
[new_alarm_config
['severity']]
900 if new_alarm_config
.has_key('operation') and new_alarm_config
['operation'] is not None:
901 symptom_details
['state']['condition']['operator'] = OPERATION_MAPPING
[new_alarm_config
['operation']]
902 if new_alarm_config
.has_key('threshold_value') and new_alarm_config
['threshold_value'] is not None:
903 symptom_details
['state']['condition']['value'] = new_alarm_config
['threshold_value']
904 #Find vrops metric key from metric_name, if required
906 if new_alarm_config.has_key('metric_name') and new_alarm_config['metric_name'] is not None:
907 metric_key_params = self.get_default_Params(new_alarm_config['metric_name'])
908 if not metric_key_params:
909 self.logger.warn("Metric not supported: {}".format(config_dict['metric_name']))
911 symptom_details['state']['condition']['key'] = metric_key_params['metric_key']
913 self
.logger
.info("Fetched Symptom details : {}".format(symptom_details
))
915 api_url
= '/suite-api/api/symptomdefinitions'
916 headers
= {'Content-Type': 'application/json', 'Accept':'application/json'}
917 data
= json
.dumps(symptom_details
)
918 resp
= requests
.put(self
.vrops_site
+ api_url
,
919 auth
=(self
.vrops_user
, self
.vrops_password
),
924 if resp
.status_code
!= 200:
925 self
.logger
.warn("Failed to update Symptom definition: {}, response {}"\
926 .format(symptom_uuid
, resp
.content
))
930 if symptom_uuid
is not None:
931 self
.logger
.info("Symptom defination updated {} for alarm: {}"\
932 .format(symptom_uuid
, new_alarm_config
['alarm_uuid']))
935 self
.logger
.warn("Failed to update Symptom Defination {} for : {}"\
936 .format(symptom_uuid
, new_alarm_config
['alarm_uuid']))
940 def get_symptom_defination_details(self
, symptom_uuid
):
941 """Get symptom defination details
944 if symptom_uuid
is None:
945 self
.logger
.warn("get_symptom_defination_details: Symptom UUID not provided")
948 api_url
= '/suite-api/api/symptomdefinitions/'
949 headers
= {'Accept': 'application/json'}
951 resp
= requests
.get(self
.vrops_site
+ api_url
+ symptom_uuid
,
952 auth
=(self
.vrops_user
, self
.vrops_password
),
953 verify
= False, headers
= headers
)
955 if resp
.status_code
is not 200:
956 self
.logger
.warn("Symptom defination not found {} \nResponse code:{}\nResponse Content: {}"\
957 .format(symptom_uuid
, resp
.status_code
, resp
.content
))
960 symptom_details
= json
.loads(resp
.content
)
961 #print "New symptom Details: {}".format(symptom_details)
962 return symptom_details
965 def reconfigure_alarm(self
, alarm_details_json
, new_alarm_config
):
966 """Reconfigure alarm defination as per input
968 if new_alarm_config
.has_key('severity') and new_alarm_config
['severity'] is not None:
969 alarm_details_json
['states'][0]['severity'] = new_alarm_config
['severity']
970 if new_alarm_config
.has_key('description') and new_alarm_config
['description'] is not None:
971 alarm_details_json
['description'] = new_alarm_config
['description']
973 api_url
= '/suite-api/api/alertdefinitions'
974 headers
= {'Content-Type': 'application/json', 'Accept':'application/json'}
975 data
= json
.dumps(alarm_details_json
)
976 resp
= requests
.put(self
.vrops_site
+ api_url
,
977 auth
=(self
.vrops_user
, self
.vrops_password
),
982 if resp
.status_code
!= 200:
983 self
.logger
.warn("Failed to create Symptom definition: {}, response code {}, response content: {}"\
984 .format(symptom_uuid
, resp
.status_code
, resp
.content
))
987 parsed_alarm_details
= json
.loads(resp
.content
)
988 alarm_def_uuid
= parsed_alarm_details
['id'].split('-', 1)[1]
989 self
.logger
.info("Successfully updated Alarm defination: {}".format(alarm_def_uuid
))
990 return alarm_def_uuid
992 def delete_alarm_configuration(self
, delete_alarm_req_dict
):
993 """Delete complete alarm configuration
995 if delete_alarm_req_dict
['alarm_uuid'] is None:
996 self
.logger
.info("delete_alarm_configuration: Alarm UUID not provided")
998 #1)Get alarm & symptom defination details
999 alarm_details_json
, alarm_details
= self
.get_alarm_defination_details(delete_alarm_req_dict
['alarm_uuid'])
1000 if alarm_details
is None or alarm_details_json
is None:
1003 #2) Delete alarm notfication
1004 rule_id
= self
.delete_notification_rule(alarm_details
['alarm_name'])
1008 #3) Delete alarm configuraion
1009 alarm_id
= self
.delete_alarm_defination(alarm_details
['alarm_id'])
1010 if alarm_id
is None:
1013 #4) Delete alarm symptom
1014 symptom_id
= self
.delete_symptom_definition(alarm_details
['symptom_definition_id'])
1015 if symptom_id
is None:
1018 self
.logger
.info("Completed deleting alarm configuration: {}"\
1019 .format(delete_alarm_req_dict
['alarm_uuid']))
1020 return delete_alarm_req_dict
['alarm_uuid']
1022 def delete_notification_rule(self
, alarm_name
):
1023 """Deleted notification rule defined for a particular alarm
1025 rule_id
= self
.get_notification_rule_id_by_alarm_name(alarm_name
)
1029 api_url
= '/suite-api/api/notifications/rules/'
1030 headers
= {'Accept':'application/json'}
1031 resp
= requests
.delete(self
.vrops_site
+ api_url
+ rule_id
,
1032 auth
=(self
.vrops_user
, self
.vrops_password
),
1033 verify
= False, headers
= headers
)
1034 if resp
.status_code
is not 204:
1035 self
.logger
.warn("Failed to delete notification rules for {}".format(alarm_name
))
1038 self
.logger
.info("Deleted notification rules for {}".format(alarm_name
))
1041 def get_notification_rule_id_by_alarm_name(self
, alarm_name
):
1042 """Find created Alarm notification rule id by alarm name
1044 alarm_notify_id
= 'notify_' + alarm_name
1045 api_url
= '/suite-api/api/notifications/rules'
1046 headers
= {'Content-Type': 'application/json', 'Accept':'application/json'}
1047 resp
= requests
.get(self
.vrops_site
+ api_url
,
1048 auth
=(self
.vrops_user
, self
.vrops_password
),
1049 verify
= False, headers
= headers
)
1051 if resp
.status_code
is not 200:
1052 self
.logger
.warn("Failed to get notification rules details for {}"\
1053 .format(delete_alarm_req_dict
['alarm_name']))
1056 notifications
= json
.loads(resp
.content
)
1057 if notifications
is not None and notifications
.has_key('notification-rule'):
1058 notifications_list
= notifications
['notification-rule']
1059 for dict in notifications_list
:
1060 if dict['name'] is not None and dict['name'] == alarm_notify_id
:
1061 notification_id
= dict['id']
1062 self
.logger
.info("Found Notification id to be deleted: {} for {}"\
1063 .format(notification_id
, alarm_name
))
1064 return notification_id
1066 self
.logger
.warn("Notification id to be deleted not found for {}"\
1067 .format(notification_id
, alarm_name
))
1070 def delete_alarm_defination(self
, alarm_id
):
1071 """Delete created Alarm defination
1073 api_url
= '/suite-api/api/alertdefinitions/'
1074 headers
= {'Accept':'application/json'}
1075 resp
= requests
.delete(self
.vrops_site
+ api_url
+ alarm_id
,
1076 auth
=(self
.vrops_user
, self
.vrops_password
),
1077 verify
= False, headers
= headers
)
1078 if resp
.status_code
is not 204:
1079 self
.logger
.warn("Failed to delete alarm definition {}".format(alarm_id
))
1082 self
.logger
.info("Deleted alarm definition {}".format(alarm_id
))
1085 def delete_symptom_definition(self
, symptom_id
):
1086 """Delete symptom defination
1088 api_url
= '/suite-api/api/symptomdefinitions/'
1089 headers
= {'Accept':'application/json'}
1090 resp
= requests
.delete(self
.vrops_site
+ api_url
+ symptom_id
,
1091 auth
=(self
.vrops_user
, self
.vrops_password
),
1092 verify
= False, headers
= headers
)
1093 if resp
.status_code
is not 204:
1094 self
.logger
.warn("Failed to delete symptom definition {}".format(symptom_id
))
1097 self
.logger
.info("Deleted symptom definition {}".format(symptom_id
))
1101 def verify_metric_support(self
, metric_info
):
1102 """Verify, if Metric is supported by vROPs plugin, verify metric unit & return status
1104 status: True if supported, False if not supported
1107 if 'metric_name' not in metric_info
:
1108 self
.logger
.debug("Metric name not provided: {}".format(metric_info
))
1110 metric_key_params
= self
.get_default_Params(metric_info
['metric_name'])
1111 if not metric_key_params
:
1112 self
.logger
.warn("Metric not supported: {}".format(metric_info
['metric_name']))
1115 #If Metric is supported, verify optional metric unit & return status
1116 if 'metric_unit' in metric_info
:
1117 if metric_key_params
.get('unit') == metric_info
['metric_unit']:
1118 self
.logger
.info("Metric is supported with unit: {}".format(metric_info
['metric_name']))
1121 self
.logger
.debug("Metric supported but there is unit mismatch for: {}."\
1122 "Supported unit: {}"\
1123 .format(metric_info
['metric_name'],metric_key_params
['unit']))
1127 def get_triggered_alarms_list(self
, list_alarm_input
):
1128 """Get list of triggered alarms on a resource based on alarm input request.
1130 #TO Do - Need to add filtering of alarms based on Severity & alarm name
1132 triggered_alarms_list
= []
1133 if list_alarm_input
['resource_uuid'] is None:
1134 return triggered_alarms_list
1136 #1)Find vROPs resource ID using RO resource UUID
1137 vrops_resource_id
= self
.get_vrops_resourceid_from_ro_uuid(list_alarm_input
['resource_uuid'])
1138 if vrops_resource_id
is None:
1139 return triggered_alarms_list
1141 #2)Get triggered alarms on particular resource
1142 triggered_alarms_list
= self
.get_triggered_alarms_on_resource(list_alarm_input
['resource_uuid'], vrops_resource_id
)
1143 return triggered_alarms_list
1145 def get_vrops_resourceid_from_ro_uuid(self
, ro_resource_uuid
):
1146 """Fetch vROPs resource ID using resource UUID from RO/SO
1148 #1) Find vm_moref_id from vApp uuid in vCD
1149 vm_moref_id
= self
.get_vm_moref_id(ro_resource_uuid
)
1150 if vm_moref_id
is None:
1151 self
.logger
.warn("Failed to find vm morefid for vApp in vCD: {}".format(ro_resource_uuid
))
1154 #2) Based on vm_moref_id, find VM's corresponding resource_id in vROPs to set notification
1155 vrops_resource_id
= self
.get_vm_resource_id(vm_moref_id
)
1156 if vrops_resource_id
is None:
1157 self
.logger
.warn("Failed to find resource in vROPs: {}".format(ro_resource_uuid
))
1159 return vrops_resource_id
1162 def get_triggered_alarms_on_resource(self
, ro_resource_uuid
, vrops_resource_id
):
1163 """Get triggered alarms on particular resource & return list of dictionary of alarms
1165 resource_alarms
= []
1166 api_url
= '/suite-api/api/alerts?resourceId='
1167 headers
= {'Accept':'application/json'}
1168 resp
= requests
.get(self
.vrops_site
+ api_url
+ vrops_resource_id
,
1169 auth
=(self
.vrops_user
, self
.vrops_password
),
1170 verify
= False, headers
= headers
)
1172 if resp
.status_code
is not 200:
1173 self
.logger
.warn("Failed to get notification rules details for {}"\
1174 .format(delete_alarm_req_dict
['alarm_name']))
1177 all_alerts
= json
.loads(resp
.content
)
1178 if all_alerts
.has_key('alerts'):
1179 if not all_alerts
['alerts']:
1180 self
.logger
.info("No alarms present on resource {}".format(ro_resource_uuid
))
1181 return resource_alarms
1182 all_alerts_list
= all_alerts
['alerts']
1183 for alarm
in all_alerts_list
:
1184 #self.logger.info("Triggered Alarm {}".format(alarm))
1185 if alarm
['alertDefinitionName'] is not None and\
1186 len(alarm
['alertDefinitionName'].split('-', 1)) == 2:
1187 if alarm
['alertDefinitionName'].split('-', 1)[1] == ro_resource_uuid
:
1189 alarm_instance
['alarm_uuid'] = alarm
['alertDefinitionId'].split('-', 1)[1]
1190 alarm_instance
['resource_uuid'] = ro_resource_uuid
1191 alarm_instance
['alarm_instance_uuid'] = alarm
['alertId']
1192 alarm_instance
['vim_type'] = 'VMware'
1193 #find severity of alarm
1195 for key
,value
in severity_mano2vrops
.iteritems():
1196 if value
== alarm
['alertLevel']:
1198 if severity
is None:
1199 severity
= 'INDETERMINATE'
1200 alarm_instance
['severity'] = severity
1201 alarm_instance
['status'] = alarm
['status']
1202 alarm_instance
['start_date'] = self
.convert_date_time(alarm
['startTimeUTC'])
1203 alarm_instance
['update_date'] = self
.convert_date_time(alarm
['updateTimeUTC'])
1204 alarm_instance
['cancel_date'] = self
.convert_date_time(alarm
['cancelTimeUTC'])
1205 self
.logger
.info("Triggered Alarm on resource {}".format(alarm_instance
))
1206 resource_alarms
.append(alarm_instance
)
1207 if not resource_alarms
:
1208 self
.logger
.info("No alarms present on resource {}".format(ro_resource_uuid
))
1209 return resource_alarms
1211 def convert_date_time(self
, date_time
):
1212 """Convert the input UTC time in msec to OSM date time format
1214 date_time_formatted
= '0000-00-00T00:00:00'
1216 complete_datetime
= datetime
.datetime
.fromtimestamp(date_time
/1000.0).isoformat('T')
1217 date_time_formatted
= complete_datetime
.split('.',1)[0]
1218 return date_time_formatted