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 Monitoring metrics & creating Alarm definitions in vROPs
32 from pyvcloud
.vcd
.client
import BasicLoginCredentials
33 from pyvcloud
.vcd
.client
import Client
36 from xml
.etree
import ElementTree
as XmlElementTree
40 from OpenSSL
.crypto
import load_certificate
, FILETYPE_PEM
44 from socket
import getfqdn
47 urllib3
.disable_warnings(urllib3
.exceptions
.InsecureRequestWarning
)
49 sys
.path
.append(os
.path
.join(os
.path
.dirname(os
.path
.abspath(__file__
)), '..', '..', '..'))
50 from osm_mon
.core
.database
import DatabaseManager
52 OPERATION_MAPPING
= {'GE':'GT_EQ', 'LE':'LT_EQ', 'GT':'GT', 'LT':'LT', 'EQ':'EQ'}
53 severity_mano2vrops
= {'WARNING':'WARNING', 'MINOR':'WARNING', 'MAJOR':"IMMEDIATE",\
54 'CRITICAL':'CRITICAL', 'INDETERMINATE':'UNKNOWN'}
55 PERIOD_MSEC
= {'HR':3600000,'DAY':86400000,'WEEK':604800000,'MONTH':2678400000,'YEAR':31536000000}
57 #To Do - Add actual webhook url & certificate
58 #SSL_CERTIFICATE_FILE_NAME = 'vROPs_Webservice/SSL_certificate/www.vrops_webservice.com.cert'
59 #webhook_url = "https://mano-dev-1:8080/notify/" #for testing
60 webhook_url
= "https://" + getfqdn() + ":8080/notify/"
61 SSL_CERTIFICATE_FILE_NAME
= ('vROPs_Webservice/SSL_certificate/' + getfqdn() + ".cert")
62 #SSL_CERTIFICATE_FILE_NAME = 'vROPs_Webservice/SSL_certificate/10.172.137.214.cert' #for testing
64 MODULE_DIR
= os
.path
.dirname(__file__
)
65 CONFIG_FILE_NAME
= 'vrops_config.xml'
66 CONFIG_FILE_PATH
= os
.path
.join(MODULE_DIR
, CONFIG_FILE_NAME
)
67 SSL_CERTIFICATE_FILE_PATH
= os
.path
.join(MODULE_DIR
, SSL_CERTIFICATE_FILE_NAME
)
70 """MON Plugin class for vROPs telemetry plugin
72 def __init__(self
, access_config
=None):
73 """Constructor of MON plugin
75 'access_config': dictionary with VIM access information based on VIM type.
76 This contains a consolidate version of VIM & monitoring tool config at creation and
77 particular VIM config at their attachment.
78 For VIM type: 'vmware',
79 access_config - {'vrops_site':<>, 'vrops_user':<>, 'vrops_password':<>,
80 'vcloud-site':<>,'admin_username':<>,'admin_password':<>,
81 'nsx_manager':<>,'nsx_user':<>,'nsx_password':<>,
82 'vcenter_ip':<>,'vcenter_port':<>,'vcenter_user':<>,'vcenter_password':<>,
83 'vim_tenant_name':<>,'orgname':<>}
86 Returns: Raise an exception if some needed parameter is missing, but it must not do any connectivity
90 self
.logger
= logging
.getLogger('PluginReceiver.MonPlugin')
91 self
.logger
.setLevel(logging
.DEBUG
)
93 if access_config
is None:
94 self
.logger
.error("VIM Access Configuration not provided")
95 raise KeyError("VIM Access Configuration not provided")
97 self
.database_manager
= DatabaseManager()
99 self
.access_config
= access_config
100 if not bool(access_config
):
101 self
.logger
.error("VIM Account details are not added. Please add a VIM account")
102 raise KeyError("VIM Account details are not added. Please add a VIM account")
105 self
.vrops_site
= access_config
['vrops_site']
106 self
.vrops_user
= access_config
['vrops_user']
107 self
.vrops_password
= access_config
['vrops_password']
108 self
.vcloud_site
= access_config
['vim_url']
109 self
.admin_username
= access_config
['admin_username']
110 self
.admin_password
= access_config
['admin_password']
111 #self.tenant_id = access_config['tenant_id']
112 self
.vim_uuid
= access_config
['vim_uuid']
114 except KeyError as exp
:
115 self
.logger
.error("Required VIM account details not provided: {}".format(exp
))
116 raise KeyError("Required VIM account details not provided: {}".format(exp
))
120 def configure_alarm(self
, config_dict
= {}):
121 """Configures or creates a new alarm using the input parameters in config_dict
123 "alarm_name": Alarm name in string format
124 "description": Description of alarm in string format
125 "resource_uuid": Resource UUID for which alarm needs to be configured. in string format
126 "Resource type": String resource type: 'VDU' or 'host'
127 "Severity": 'WARNING', 'MINOR', 'MAJOR', 'CRITICAL'
128 "metric_name": Metric key in string format
129 "operation": One of ('GE', 'LE', 'GT', 'LT', 'EQ')
130 "threshold_value": Defines the threshold (up to 2 fraction digits) that,
131 if crossed, will trigger the alarm.
132 "statistic": AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM
134 Default parameters for each alarm are read from the plugin specific config file.
135 Dict of default parameters is as follows:
136 default_params keys = {'cancel_cycles','wait_cycles','resource_kind','adapter_kind',
137 'alarm_type','alarm_subType',impact}
139 Returns the UUID of created alarm or None
142 #1) get alarm & metrics parameters from plugin specific file
143 def_a_params
= self
.get_default_Params(config_dict
['alarm_name'])
145 self
.logger
.warning("Alarm not supported: {}".format(config_dict
['alarm_name']))
147 metric_key_params
= self
.get_default_Params(config_dict
['metric_name'])
148 if not metric_key_params
:
149 self
.logger
.warning("Metric not supported: {}".format(config_dict
['metric_name']))
152 #1.2) Check if alarm definition already exists
153 vrops_alarm_name
= def_a_params
['vrops_alarm']+ '-' + config_dict
['resource_uuid']
154 alert_def_list
= self
.get_alarm_defination_by_name(vrops_alarm_name
)
156 self
.logger
.warning("Alarm already exists: {}. Try updating by update_alarm_request"\
157 .format(vrops_alarm_name
))
160 #2) create symptom definition
161 symptom_params
={'cancel_cycles': (def_a_params
['cancel_period']/300)*def_a_params
['cancel_cycles'],
162 'wait_cycles': (def_a_params
['period']/300)*def_a_params
['evaluation'],
163 'resource_kind_key': def_a_params
['resource_kind'],
164 'adapter_kind_key': def_a_params
['adapter_kind'],
165 'symptom_name':vrops_alarm_name
,
166 'severity': severity_mano2vrops
[config_dict
['severity'].upper()],
167 'metric_key':metric_key_params
['metric_key'],
168 'operation':OPERATION_MAPPING
[config_dict
['operation']],
169 'threshold_value':config_dict
['threshold_value']}
171 symptom_uuid
= self
.create_symptom(symptom_params
)
172 if symptom_uuid
is not None:
173 self
.logger
.info("Symptom defined: {} with ID: {}".format(symptom_params
['symptom_name'],symptom_uuid
))
175 self
.logger
.warning("Failed to create Symptom: {}".format(symptom_params
['symptom_name']))
177 #3) create alert definition
178 #To Do - Get type & subtypes for all 5 alarms
179 alarm_params
= {'name':vrops_alarm_name
,
180 'description':config_dict
['description']\
181 if 'description' in config_dict
and config_dict
['description'] is not None else config_dict
['alarm_name'],
182 'adapterKindKey':def_a_params
['adapter_kind'],
183 'resourceKindKey':def_a_params
['resource_kind'],
184 'waitCycles':1, 'cancelCycles':1,
185 'type':def_a_params
['alarm_type'], 'subType':def_a_params
['alarm_subType'],
186 'severity':severity_mano2vrops
[config_dict
['severity'].upper()],
187 'symptomDefinitionId':symptom_uuid
,
188 'impact':def_a_params
['impact']}
190 alarm_def
= self
.create_alarm_definition(alarm_params
)
191 if alarm_def
is None:
192 self
.logger
.warning("Failed to create Alert: {}".format(alarm_params
['name']))
195 self
.logger
.info("Alarm defined: {} with ID: {}".format(alarm_params
['name'],alarm_def
))
197 #4) Find vm_moref_id from vApp uuid in vCD
198 vm_moref_id
= self
.get_vm_moref_id(config_dict
['resource_uuid'])
199 if vm_moref_id
is None:
200 self
.logger
.warning("Failed to find vm morefid for vApp in vCD: {}".format(config_dict
['resource_uuid']))
203 #5) Based on vm_moref_id, find VM's corresponding resource_id in vROPs to set notification
204 resource_id
= self
.get_vm_resource_id(vm_moref_id
)
205 if resource_id
is None:
206 self
.logger
.warning("Failed to find resource in vROPs: {}".format(config_dict
['resource_uuid']))
209 #6) Configure alarm notification for a particular VM using it's resource_id
210 notification_id
= self
.create_alarm_notification_rule(vrops_alarm_name
, alarm_def
, resource_id
)
211 if notification_id
is None:
214 alarm_def_uuid
= alarm_def
.split('-', 1)[1]
215 self
.logger
.info("Alarm definition created with notification: {} with ID: {}"\
216 .format(alarm_params
['name'],alarm_def_uuid
))
217 ##self.database_manager.save_alarm(alarm_def_uuid, alarm_params['name'], self.vim_uuid)
218 self
.database_manager
.save_alarm(alarm_def_uuid
,
220 ##alarm_params['name'],
221 config_dict
['threshold_value'],
222 config_dict
['operation'],
223 config_dict
['metric_name'].lower(),
224 config_dict
['vdu_name'].lower(),
225 config_dict
['vnf_member_index'].lower(),
226 config_dict
['ns_id'].lower()
229 #Return alarm definition UUID by removing 'AlertDefinition' from UUID
230 return (alarm_def_uuid
)
232 def get_default_Params(self
, metric_alarm_name
):
234 Read the default config parameters from plugin specific file stored with plugin file.
236 metric_alarm_name: Name of the alarm, whose config parameters to be read from the config file.
240 source
= open(CONFIG_FILE_PATH
, 'r')
241 except IOError as exp
:
242 msg
= ("Could not read Config file: {}, \nException: {}"\
243 .format(CONFIG_FILE_PATH
, exp
))
244 self
.logger
.error(msg
)
247 tree
= XmlElementTree
.parse(source
)
248 alarms
= tree
.getroot()
250 if alarm
.tag
.lower() == metric_alarm_name
.lower():
252 if param
.tag
in ("period", "evaluation", "cancel_period", "alarm_type",\
253 "cancel_cycles", "alarm_subType"):
254 a_params
[param
.tag
] = int(param
.text
)
255 elif param
.tag
in ("enabled", "repeat"):
256 if(param
.text
.lower() == "true"):
257 a_params
[param
.tag
] = True
259 a_params
[param
.tag
] = False
261 a_params
[param
.tag
] = param
.text
266 def create_symptom(self
, symptom_params
):
267 """Create Symptom definition for an alarm
269 symptom_params: Dict of parameters required for defining a symptom as follows
272 resource_kind_key = "VirtualMachine"
273 adapter_kind_key = "VMWARE"
274 symptom_name = Test_Memory_Usage_TooHigh
279 Returns the uuid of Symptom definition
284 api_url
= '/suite-api/api/symptomdefinitions'
285 headers
= {'Content-Type': 'application/json','Accept': 'application/json'}
288 "name": symptom_params
['symptom_name'],
289 "adapterKindKey": symptom_params
['adapter_kind_key'],
290 "resourceKindKey": symptom_params
['resource_kind_key'],
291 "waitCycles": symptom_params
['wait_cycles'],
292 "cancelCycles": symptom_params
['cancel_cycles'],
294 "severity": symptom_params
['severity'],
296 "type": "CONDITION_HT",
297 "key": symptom_params
['metric_key'],
298 "operator": symptom_params
['operation'],
299 "value": symptom_params
['threshold_value'],
300 "valueType": "NUMERIC",
302 "thresholdType": "STATIC"
307 resp
= requests
.post(self
.vrops_site
+ api_url
,
308 auth
=(self
.vrops_user
, self
.vrops_password
),
311 data
=json
.dumps(data
))
313 if resp
.status_code
!= 201:
314 self
.logger
.warning("Failed to create Symptom definition: {}, response {}"\
315 .format(symptom_params
['symptom_name'], resp
.content
))
318 resp_data
= json
.loads(resp
.content
)
319 if resp_data
.get('id') is not None:
320 symptom_id
= resp_data
['id']
324 except Exception as exp
:
325 self
.logger
.warning("Error creating symptom definition : {}\n{}"\
326 .format(exp
, traceback
.format_exc()))
329 def create_alarm_definition(self
, alarm_params
):
331 Create an alarm definition in vROPs
334 'description':Alarm description,
335 'adapterKindKey': Adapter type in vROPs "VMWARE",
336 'resourceKindKey':Resource type in vROPs "VirtualMachine",
337 'waitCycles': No of wait cycles,
338 'cancelCycles': No of cancel cycles,
340 'subType': Alarm subtype,
341 'severity': Severity in vROPs "CRITICAL",
342 'symptomDefinitionId':symptom Definition uuid,
343 'impact': impact 'risk'
345 'alarm_uuid': returns alarm uuid
351 api_url
= '/suite-api/api/alertdefinitions'
352 headers
= {'Content-Type': 'application/json', 'Accept': 'application/json'}
354 "name": alarm_params
['name'],
355 "description": alarm_params
['description'],
356 "adapterKindKey": alarm_params
['adapterKindKey'],
357 "resourceKindKey": alarm_params
['resourceKindKey'],
360 "type": alarm_params
['type'],
361 "subType": alarm_params
['subType'],
364 "severity": alarm_params
['severity'],
367 "type": "SYMPTOM_SET",
369 "aggregation": "ALL",
370 "symptomSetOperator": "AND",
371 "symptomDefinitionIds": [alarm_params
['symptomDefinitionId']]
374 "impactType": "BADGE",
375 "detail": alarm_params
['impact']
381 resp
= requests
.post(self
.vrops_site
+ api_url
,
382 auth
=(self
.vrops_user
, self
.vrops_password
),
385 data
=json
.dumps(data
))
387 if resp
.status_code
!= 201:
388 self
.logger
.warning("Failed to create Alarm definition: {}, response {}"\
389 .format(alarm_params
['name'], resp
.content
))
392 resp_data
= json
.loads(resp
.content
)
393 if resp_data
.get('id') is not None:
394 alarm_uuid
= resp_data
['id']
398 except Exception as exp
:
399 self
.logger
.warning("Error creating alarm definition : {}\n{}".format(exp
, traceback
.format_exc()))
402 def configure_rest_plugin(self
):
404 Creates REST Plug-in for vROPs outbound alerts
409 plugin_name
= 'MON_module_REST_Plugin'
410 plugin_id
= self
.check_if_plugin_configured(plugin_name
)
412 #If REST plugin not configured, configure it
413 if plugin_id
is not None:
417 cert_file_string
= open(SSL_CERTIFICATE_FILE_PATH
, "rb").read()
418 except IOError as exp
:
419 msg
= ("Could not read SSL certificate file: {}".format(SSL_CERTIFICATE_FILE_PATH
))
420 self
.logger
.error(msg
)
422 cert
= load_certificate(FILETYPE_PEM
, cert_file_string
)
423 certificate
= cert
.digest("sha1")
424 api_url
= '/suite-api/api/alertplugins'
425 headers
= {'Content-Type': 'application/json', 'Accept': 'application/json'}
427 "pluginTypeId": "RestPlugin",
435 "name": "Content-type",
436 "value": "application/json"
439 "name": "Certificate",
443 "name": "ConnectionCount",
449 resp
= requests
.post(self
.vrops_site
+ api_url
,
450 auth
=(self
.vrops_user
, self
.vrops_password
),
453 data
=json
.dumps(data
))
455 if resp
.status_code
is not 201:
456 self
.logger
.warning("Failed to create REST Plugin: {} for url: {}, \nresponse code: {},"\
457 "\nresponse content: {}".format(plugin_name
, webhook_url
,\
458 resp
.status_code
, resp
.content
))
461 resp_data
= json
.loads(resp
.content
)
462 if resp_data
.get('pluginId') is not None:
463 plugin_id
= resp_data
['pluginId']
465 if plugin_id
is None:
466 self
.logger
.warning("Failed to get REST Plugin ID for {}, url: {}".format(plugin_name
, webhook_url
))
469 self
.logger
.info("Created REST Plugin: {} with ID : {} for url: {}".format(plugin_name
, plugin_id
, webhook_url
))
470 status
= self
.enable_rest_plugin(plugin_id
, plugin_name
)
472 self
.logger
.warning("Failed to enable created REST Plugin: {} for url: {}".format(plugin_name
, webhook_url
))
475 self
.logger
.info("Enabled REST Plugin: {} for url: {}".format(plugin_name
, webhook_url
))
478 def check_if_plugin_configured(self
, plugin_name
):
479 """Check if the REST plugin is already created
480 Returns: plugin_id: if already created, None: if needs to be created
483 #Find the REST Plugin id details for - MON_module_REST_Plugin
484 api_url
= '/suite-api/api/alertplugins'
485 headers
= {'Accept': 'application/json'}
487 resp
= requests
.get(self
.vrops_site
+ api_url
,
488 auth
=(self
.vrops_user
, self
.vrops_password
),
489 verify
= False, headers
= headers
)
491 if resp
.status_code
is not 200:
492 self
.logger
.warning("Failed to REST GET Alarm plugin details \nResponse code: {}\nResponse content: {}"\
493 .format(resp
.status_code
, resp
.content
))
496 # Look for specific plugin & parse pluginId for 'MON_module_REST_Plugin'
497 plugins_list
= json
.loads(resp
.content
)
498 if plugins_list
.get('notificationPluginInstances') is not None:
499 for notify_plugin
in plugins_list
['notificationPluginInstances']:
500 if notify_plugin
.get('name') is not None and notify_plugin
['name'] == plugin_name
:
501 plugin_id
= notify_plugin
.get('pluginId')
503 if plugin_id
is None:
504 self
.logger
.warning("REST plugin {} not found".format(plugin_name
))
507 self
.logger
.info("Found REST Plugin: {}".format(plugin_name
))
511 def enable_rest_plugin(self
, plugin_id
, plugin_name
):
513 Enable the REST plugin using plugin_id
514 Params: plugin_id: plugin ID string that is to be enabled
515 Returns: status (Boolean) - True for success, False for failure
518 if plugin_id
is None or plugin_name
is None:
519 self
.logger
.debug("enable_rest_plugin() : Plugin ID or plugin_name not provided for {} plugin"\
520 .format(plugin_name
))
524 api_url
= "/suite-api/api/alertplugins/{}/enable/True".format(plugin_id
)
526 resp
= requests
.put(self
.vrops_site
+ api_url
,
527 auth
=(self
.vrops_user
, self
.vrops_password
),
530 if resp
.status_code
is not 204:
531 self
.logger
.warning("Failed to enable REST plugin {}. \nResponse code {}\nResponse Content: {}"\
532 .format(plugin_name
, resp
.status_code
, resp
.content
))
535 self
.logger
.info("Enabled REST plugin {}.".format(plugin_name
))
538 except Exception as exp
:
539 self
.logger
.warning("Error enabling REST plugin for {} plugin: Exception: {}\n{}"\
540 .format(plugin_name
, exp
, traceback
.format_exc()))
542 def create_alarm_notification_rule(self
, alarm_name
, alarm_id
, resource_id
):
544 Create notification rule for each alarm
551 notification_id: notification_id or None
553 notification_name
= 'notify_' + alarm_name
554 notification_id
= None
555 plugin_name
= 'MON_module_REST_Plugin'
557 #1) Find the REST Plugin id details for - MON_module_REST_Plugin
558 plugin_id
= self
.check_if_plugin_configured(plugin_name
)
559 if plugin_id
is None:
560 self
.logger
.warning("Failed to get REST plugin_id for : {}".format('MON_module_REST_Plugin'))
563 #2) Create Alarm notification rule
564 api_url
= '/suite-api/api/notifications/rules'
565 headers
= {'Content-Type': 'application/json', 'Accept': 'application/json'}
567 "name" : notification_name
,
568 "pluginId" : plugin_id
,
570 "matchResourceIdOnly": True,
571 "resourceId": resource_id
573 "alertDefinitionIdFilters" : {
574 "values" : [ alarm_id
]
578 resp
= requests
.post(self
.vrops_site
+ api_url
,
579 auth
=(self
.vrops_user
, self
.vrops_password
),
582 data
=json
.dumps(data
))
584 if resp
.status_code
is not 201:
585 self
.logger
.warning("Failed to create Alarm notification rule {} for {} alarm."\
586 "\nResponse code: {}\nResponse content: {}"\
587 .format(notification_name
, alarm_name
, resp
.status_code
, resp
.content
))
590 #parse notification id from response
591 resp_data
= json
.loads(resp
.content
)
592 if resp_data
.get('id') is not None:
593 notification_id
= resp_data
['id']
595 self
.logger
.info("Created Alarm notification rule {} for {} alarm.".format(notification_name
, alarm_name
))
596 return notification_id
598 def get_vm_moref_id(self
, vapp_uuid
):
600 Get the moref_id of given VM
604 vm_details
= self
.get_vapp_details_rest(vapp_uuid
)
605 if vm_details
and "vm_vcenter_info" in vm_details
:
606 vm_moref_id
= vm_details
["vm_vcenter_info"].get("vm_moref_id", None)
608 self
.logger
.info("Found vm_moref_id: {} for vApp UUID: {}".format(vm_moref_id
, vapp_uuid
))
611 except Exception as exp
:
612 self
.logger
.warning("Error occurred while getting VM moref ID for VM : {}\n{}"\
613 .format(exp
, traceback
.format_exc()))
616 def get_vapp_details_rest(self
, vapp_uuid
=None):
618 Method retrieve vapp detail from vCloud director
621 vapp_uuid - is vapp identifier.
624 Returns VM MOref ID or return None
630 if vapp_uuid
is None:
631 return parsed_respond
633 vca
= self
.connect_as_admin()
635 self
.logger
.warning("Failed to connect to vCD")
636 return parsed_respond
638 url_list
= [self
.vcloud_site
, '/api/vApp/vapp-', vapp_uuid
]
639 get_vapp_restcall
= ''.join(url_list
)
642 headers
= {'Accept':'application/*+xml;version=' + API_VERSION
,
643 'x-vcloud-authorization': vca
._session
.headers
['x-vcloud-authorization']}
644 response
= requests
.get(get_vapp_restcall
,
648 if response
.status_code
!= 200:
649 self
.logger
.warning("REST API call {} failed. Return status code {}"\
650 .format(get_vapp_restcall
, response
.content
))
651 return parsed_respond
654 xmlroot_respond
= XmlElementTree
.fromstring(response
.content
)
656 namespaces
= {'vm': 'http://www.vmware.com/vcloud/v1.5',
657 "vmext":"http://www.vmware.com/vcloud/extension/v1.5",
658 "xmlns":"http://www.vmware.com/vcloud/v1.5"
661 # parse children section for other attrib
662 children_section
= xmlroot_respond
.find('vm:Children/', namespaces
)
663 if children_section
is not None:
664 vCloud_extension_section
= children_section
.find('xmlns:VCloudExtension', namespaces
)
665 if vCloud_extension_section
is not None:
667 vim_info
= vCloud_extension_section
.find('vmext:VmVimInfo', namespaces
)
668 vmext
= vim_info
.find('vmext:VmVimObjectRef', namespaces
)
669 if vmext
is not None:
670 vm_vcenter_info
["vm_moref_id"] = vmext
.find('vmext:MoRef', namespaces
).text
671 parsed_respond
["vm_vcenter_info"]= vm_vcenter_info
673 except Exception as exp
:
674 self
.logger
.warning("Error occurred calling rest api for getting vApp details: {}\n{}"\
675 .format(exp
, traceback
.format_exc()))
677 return parsed_respond
680 def connect_as_admin(self
):
681 """ Method connect as pvdc admin user to vCloud director.
682 There are certain action that can be done only by provider vdc admin user.
683 Organization creation / provider network creation etc.
686 The return vca object that letter can be used to connect to vcloud direct as admin for provider vdc
689 self
.logger
.debug("Logging into vCD org as admin.")
692 host
= self
.vcloud_site
694 client_as_admin
= Client(host
, verify_ssl_certs
=False)
695 client_as_admin
.set_credentials(BasicLoginCredentials(self
.admin_username
, org
,\
696 self
.admin_password
))
697 except Exception as e
:
698 self
.logger
.warning("Can't connect to a vCloud director as: {} with exception {}"\
699 .format(self
.admin_username
, e
))
701 return client_as_admin
704 def get_vm_resource_id(self
, vm_moref_id
):
705 """ Find resource ID in vROPs using vm_moref_id
707 if vm_moref_id
is None:
710 api_url
= '/suite-api/api/resources?resourceKind=VirtualMachine'
711 headers
= {'Accept': 'application/json'}
713 resp
= requests
.get(self
.vrops_site
+ api_url
,
714 auth
=(self
.vrops_user
, self
.vrops_password
),
715 verify
= False, headers
= headers
)
717 if resp
.status_code
is not 200:
718 self
.logger
.warning("Failed to get resource details from vROPs for {}"\
719 "\nResponse code:{}\nResponse Content: {}"\
720 .format(vm_moref_id
, resp
.status_code
, resp
.content
))
723 vm_resource_id
= None
725 resp_data
= json
.loads(resp
.content
)
726 if resp_data
.get('resourceList') is not None:
727 resource_list
= resp_data
.get('resourceList')
728 for resource
in resource_list
:
729 if resource
.get('resourceKey') is not None:
730 resource_details
= resource
['resourceKey']
731 if resource_details
.get('resourceIdentifiers') is not None:
732 resource_identifiers
= resource_details
['resourceIdentifiers']
733 for resource_identifier
in resource_identifiers
:
734 if resource_identifier
['identifierType']['name']=='VMEntityObjectID':
735 if resource_identifier
.get('value') is not None and \
736 resource_identifier
['value']==vm_moref_id
:
737 vm_resource_id
= resource
['identifier']
738 self
.logger
.info("Found VM resource ID: {} for vm_moref_id: {}"\
739 .format(vm_resource_id
, vm_moref_id
))
741 except Exception as exp
:
742 self
.logger
.warning("get_vm_resource_id: Error in parsing {}\n{}"\
743 .format(exp
, traceback
.format_exc()))
745 return vm_resource_id
748 def get_metrics_data(self
, metric
={}):
749 """Get an individual metric's data of a resource.
751 'metric_name': Normalized name of metric (string)
752 'resource_uuid': Resource UUID (string)
753 'period': Time period in Period Unit for which metrics data to be collected from
754 Monitoring tool from now.
755 'period_unit': Period measurement unit can be one of 'HR', 'DAY', 'MONTH', 'YEAR'
757 Return a dict that contains:
758 'metric_name': Normalized name of metric (string)
759 'resource_uuid': Resource UUID (string)
760 'tenant_id': tenent id name in which the resource is present in string format
761 'metrics_data': Dictionary containing time_series & metrics_series data.
762 'time_series': List of individual time stamp values in msec
763 'metrics_series': List of individual metrics data values
764 Raises an exception upon error or when network is not found
767 return_data
['schema_version'] = "1.0"
768 return_data
['schema_type'] = 'read_metric_data_response'
769 return_data
['vim_uuid'] = metric
['vim_uuid']
770 return_data
['metric_name'] = metric
['metric_name']
771 #To do - No metric_uuid in vROPs, thus returning '0'
772 return_data
['metric_uuid'] = '0'
773 return_data
['correlation_id'] = metric
['correlation_id']
774 return_data
['resource_uuid'] = metric
['resource_uuid']
775 return_data
['metrics_data'] = {'time_series':[], 'metrics_series':[]}
776 #To do - Need confirmation about uuid & id
777 ##if 'tenant_uuid' in metric and metric['tenant_uuid'] is not None:
778 ## return_data['tenant_uuid'] = metric['tenant_uuid']
780 ## return_data['tenant_uuid'] = None
781 return_data
['unit'] = None
782 #return_data['tenant_id'] = self.tenant_id
783 #self.logger.warning("return_data: {}".format(return_data))
785 #1) Get metric details from plugin specific file & format it into vROPs metrics
786 metric_key_params
= self
.get_default_Params(metric
['metric_name'])
788 if not metric_key_params
:
789 self
.logger
.warning("Metric not supported: {}".format(metric
['metric_name']))
790 #To Do: Return message
793 return_data
['unit'] = metric_key_params
['unit']
795 #2) Find the resource id in vROPs based on OSM resource_uuid
796 #2.a) Find vm_moref_id from vApp uuid in vCD
797 vm_moref_id
= self
.get_vm_moref_id(metric
['resource_uuid'])
798 if vm_moref_id
is None:
799 self
.logger
.warning("Failed to find vm morefid for vApp in vCD: {}".format(metric
['resource_uuid']))
801 #2.b) Based on vm_moref_id, find VM's corresponding resource_id in vROPs to set notification
802 resource_id
= self
.get_vm_resource_id(vm_moref_id
)
803 if resource_id
is None:
804 self
.logger
.warning("Failed to find resource in vROPs: {}".format(metric
['resource_uuid']))
807 #3) Calculate begin & end time for period & period unit
808 end_time
= int(round(time
.time() * 1000))
809 if metric
['collection_unit'] == 'YR':
810 time_diff
= PERIOD_MSEC
[metric
['collection_unit']]
812 time_diff
= metric
['collection_period']* PERIOD_MSEC
[metric
['collection_unit']]
813 begin_time
= end_time
- time_diff
815 #4) Get the metrics data
816 self
.logger
.info("metric_key_params['metric_key'] = {}".format(metric_key_params
['metric_key']))
817 self
.logger
.info("end_time: {}, begin_time: {}".format(end_time
, begin_time
))
819 url_list
= ['/suite-api/api/resources/', resource_id
, '/stats?statKey=',\
820 metric_key_params
['metric_key'], '&begin=', str(begin_time
),'&end=',str(end_time
)]
821 api_url
= ''.join(url_list
)
822 headers
= {'Accept': 'application/json'}
824 resp
= requests
.get(self
.vrops_site
+ api_url
,
825 auth
=(self
.vrops_user
, self
.vrops_password
),
826 verify
= False, headers
= headers
)
828 if resp
.status_code
is not 200:
829 self
.logger
.warning("Failed to retrieve Metric data from vROPs for {}\nResponse code:{}\nResponse Content: {}"\
830 .format(metric
['metric_name'], resp
.status_code
, resp
.content
))
833 #5) Convert to required format
835 json_data
= json
.loads(resp
.content
)
836 for resp_key
,resp_val
in six
.iteritems(json_data
):
837 if resp_key
== 'values':
838 data
= json_data
['values'][0]
839 for data_k
,data_v
in six
.iteritems(data
):
840 if data_k
== 'stat-list':
842 for stat_list_k
,stat_list_v
in six
.iteritems(stat_list
):
843 for stat_keys
,stat_vals
in six
.iteritems(stat_list_v
[0]):
844 if stat_keys
== 'timestamps':
845 metrics_data
['time_series'] = stat_list_v
[0]['timestamps']
846 if stat_keys
== 'data':
847 metrics_data
['metrics_series'] = stat_list_v
[0]['data']
849 return_data
['metrics_data'] = metrics_data
853 def update_alarm_configuration(self
, new_alarm_config
):
854 """Update alarm configuration (i.e. Symptom & alarm) as per request
856 if new_alarm_config
.get('alarm_uuid') is None:
857 self
.logger
.warning("alarm_uuid is required to update an Alarm")
859 #1) Get Alarm details from it's uuid & find the symptom definition
860 alarm_details_json
, alarm_details
= self
.get_alarm_defination_details(new_alarm_config
['alarm_uuid'])
861 if alarm_details_json
is None:
865 #2) Update the symptom definition
866 if alarm_details
['alarm_id'] is not None and alarm_details
['symptom_definition_id'] is not None:
867 symptom_defination_id
= alarm_details
['symptom_definition_id']
869 self
.logger
.info("Symptom Definition ID not found for {}".format(new_alarm_config
['alarm_uuid']))
872 symptom_uuid
= self
.update_symptom_defination(symptom_defination_id
, new_alarm_config
)
874 #3) Update the alarm definition & Return UUID if successful update
875 if symptom_uuid
is None:
876 self
.logger
.info("Symptom Definition details not found for {}"\
877 .format(new_alarm_config
['alarm_uuid']))
880 alarm_uuid
= self
.reconfigure_alarm(alarm_details_json
, new_alarm_config
)
881 if alarm_uuid
is None:
886 self
.logger
.error("Exception while updating alarm: {}".format(traceback
.format_exc()))
888 def get_alarm_defination_details(self
, alarm_uuid
):
889 """Get alarm details based on alarm UUID
891 if alarm_uuid
is None:
892 self
.logger
.warning("get_alarm_defination_details: Alarm UUID not provided")
897 api_url
= '/suite-api/api/alertdefinitions/AlertDefinition-'
898 headers
= {'Accept': 'application/json'}
900 resp
= requests
.get(self
.vrops_site
+ api_url
+ alarm_uuid
,
901 auth
=(self
.vrops_user
, self
.vrops_password
),
902 verify
= False, headers
= headers
)
904 if resp
.status_code
is not 200:
905 self
.logger
.warning("Alarm to be updated not found: {}\nResponse code:{}\nResponse Content: {}"\
906 .format(alarm_uuid
, resp
.status_code
, resp
.content
))
910 json_data
= json
.loads(resp
.content
)
911 if json_data
['id'] is not None:
912 alarm_details
['alarm_id'] = json_data
['id']
913 alarm_details
['alarm_name'] = json_data
['name']
914 alarm_details
['adapter_kind'] = json_data
['adapterKindKey']
915 alarm_details
['resource_kind'] = json_data
['resourceKindKey']
916 alarm_details
['type'] = json_data
['type']
917 alarm_details
['sub_type'] = json_data
['subType']
918 alarm_details
['symptom_definition_id'] = json_data
['states'][0]['base-symptom-set']['symptomDefinitionIds'][0]
919 except Exception as exp
:
920 self
.logger
.warning("Exception while retrieving alarm definition details: {}".format(exp
))
923 return json_data
, alarm_details
926 def get_alarm_defination_by_name(self
, alarm_name
):
927 """Get alarm details based on alarm name
930 alert_match_list
= []
932 if alarm_name
is None:
933 self
.logger
.warning("get_alarm_defination_by_name: Alarm name not provided")
934 return alert_match_list
937 api_url
= '/suite-api/api/alertdefinitions'
938 headers
= {'Accept': 'application/json'}
940 resp
= requests
.get(self
.vrops_site
+ api_url
,
941 auth
=(self
.vrops_user
, self
.vrops_password
),
942 verify
= False, headers
= headers
)
944 if resp
.status_code
is not 200:
945 self
.logger
.warning("get_alarm_defination_by_name: Error in response: {}\nResponse code:{}"\
946 "\nResponse Content: {}".format(alarm_name
, resp
.status_code
, resp
.content
))
947 return alert_match_list
950 json_data
= json
.loads(resp
.content
)
951 if json_data
['alertDefinitions'] is not None:
952 alerts_list
= json_data
['alertDefinitions']
953 alert_match_list
= list(filter(lambda alert
: alert
['name'] == alarm_name
, alerts_list
))
954 status
= False if not alert_match_list
else True
955 #self.logger.debug("Found alert_match_list: {}for larm_name: {},\nstatus: {}".format(alert_match_list, alarm_name,status))
957 return alert_match_list
959 except Exception as exp
:
960 self
.logger
.warning("Exception while searching alarm definition: {}".format(exp
))
961 return alert_match_list
964 def update_symptom_defination(self
, symptom_uuid
, new_alarm_config
):
965 """Update symptom definition based on new alarm input configuration
967 #1) Get symptom definition details
968 symptom_details
= self
.get_symptom_defination_details(symptom_uuid
)
969 #print "\n\nsymptom_details: {}".format(symptom_details)
970 if symptom_details
is None:
973 if 'severity' in new_alarm_config
and new_alarm_config
['severity'] is not None:
974 symptom_details
['state']['severity'] = severity_mano2vrops
[new_alarm_config
['severity']]
975 if 'operation' in new_alarm_config
and new_alarm_config
['operation'] is not None:
976 symptom_details
['state']['condition']['operator'] = OPERATION_MAPPING
[new_alarm_config
['operation']]
977 if 'threshold_value' in new_alarm_config
and new_alarm_config
['threshold_value'] is not None:
978 symptom_details
['state']['condition']['value'] = new_alarm_config
['threshold_value']
979 #Find vrops metric key from metric_name, if required
981 if 'metric_name' in new_alarm_config and new_alarm_config['metric_name'] is not None:
982 metric_key_params = self.get_default_Params(new_alarm_config['metric_name'])
983 if not metric_key_params:
984 self.logger.warning("Metric not supported: {}".format(config_dict['metric_name']))
986 symptom_details['state']['condition']['key'] = metric_key_params['metric_key']
988 self
.logger
.info("Fetched Symptom details : {}".format(symptom_details
))
990 api_url
= '/suite-api/api/symptomdefinitions'
991 headers
= {'Content-Type': 'application/json', 'Accept':'application/json'}
992 data
= json
.dumps(symptom_details
)
993 resp
= requests
.put(self
.vrops_site
+ api_url
,
994 auth
=(self
.vrops_user
, self
.vrops_password
),
999 if resp
.status_code
!= 200:
1000 self
.logger
.warning("Failed to update Symptom definition: {}, response {}"\
1001 .format(symptom_uuid
, resp
.content
))
1005 if symptom_uuid
is not None:
1006 self
.logger
.info("Symptom definition updated {} for alarm: {}"\
1007 .format(symptom_uuid
, new_alarm_config
['alarm_uuid']))
1010 self
.logger
.warning("Failed to update Symptom Definition {} for : {}"\
1011 .format(symptom_uuid
, new_alarm_config
['alarm_uuid']))
1015 def get_symptom_defination_details(self
, symptom_uuid
):
1016 """Get symptom definition details
1018 symptom_details
= {}
1019 if symptom_uuid
is None:
1020 self
.logger
.warning("get_symptom_defination_details: Symptom UUID not provided")
1023 api_url
= '/suite-api/api/symptomdefinitions/'
1024 headers
= {'Accept': 'application/json'}
1026 resp
= requests
.get(self
.vrops_site
+ api_url
+ symptom_uuid
,
1027 auth
=(self
.vrops_user
, self
.vrops_password
),
1028 verify
= False, headers
= headers
)
1030 if resp
.status_code
is not 200:
1031 self
.logger
.warning("Symptom definition not found {} \nResponse code:{}\nResponse Content: {}"\
1032 .format(symptom_uuid
, resp
.status_code
, resp
.content
))
1035 symptom_details
= json
.loads(resp
.content
)
1036 #print "New symptom Details: {}".format(symptom_details)
1037 return symptom_details
1040 def reconfigure_alarm(self
, alarm_details_json
, new_alarm_config
):
1041 """Reconfigure alarm definition as per input
1043 if 'severity' in new_alarm_config
and new_alarm_config
['severity'] is not None:
1044 alarm_details_json
['states'][0]['severity'] = new_alarm_config
['severity']
1045 if 'description' in new_alarm_config
and new_alarm_config
['description'] is not None:
1046 alarm_details_json
['description'] = new_alarm_config
['description']
1048 api_url
= '/suite-api/api/alertdefinitions'
1049 headers
= {'Content-Type': 'application/json', 'Accept':'application/json'}
1050 data
= json
.dumps(alarm_details_json
)
1051 resp
= requests
.put(self
.vrops_site
+ api_url
,
1052 auth
=(self
.vrops_user
, self
.vrops_password
),
1057 if resp
.status_code
!= 200:
1058 self
.logger
.warning("Failed to update Alarm definition: {}, response code {}, response content: {}"\
1059 .format(alarm_details_json
['id'], resp
.status_code
, resp
.content
))
1062 parsed_alarm_details
= json
.loads(resp
.content
)
1063 alarm_def_uuid
= parsed_alarm_details
['id'].split('-', 1)[1]
1064 self
.logger
.info("Successfully updated Alarm definition: {}".format(alarm_def_uuid
))
1065 return alarm_def_uuid
1067 def delete_alarm_configuration(self
, delete_alarm_req_dict
):
1068 """Delete complete alarm configuration
1070 if delete_alarm_req_dict
['alarm_uuid'] is None:
1071 self
.logger
.info("delete_alarm_configuration: Alarm UUID not provided")
1073 #1)Get alarm & symptom definition details
1074 alarm_details_json
, alarm_details
= self
.get_alarm_defination_details(delete_alarm_req_dict
['alarm_uuid'])
1075 if alarm_details
is None or alarm_details_json
is None:
1078 #2) Delete alarm notification
1079 rule_id
= self
.delete_notification_rule(alarm_details
['alarm_name'])
1083 #3) Delete alarm configuration
1084 alarm_id
= self
.delete_alarm_defination(alarm_details
['alarm_id'])
1085 if alarm_id
is None:
1088 #4) Delete alarm symptom
1089 symptom_id
= self
.delete_symptom_definition(alarm_details
['symptom_definition_id'])
1090 if symptom_id
is None:
1093 self
.logger
.info("Completed deleting alarm configuration: {}"\
1094 .format(delete_alarm_req_dict
['alarm_uuid']))
1095 return delete_alarm_req_dict
['alarm_uuid']
1097 def delete_notification_rule(self
, alarm_name
):
1098 """Deleted notification rule defined for a particular alarm
1100 rule_id
= self
.get_notification_rule_id_by_alarm_name(alarm_name
)
1104 api_url
= '/suite-api/api/notifications/rules/'
1105 headers
= {'Accept':'application/json'}
1106 resp
= requests
.delete(self
.vrops_site
+ api_url
+ rule_id
,
1107 auth
=(self
.vrops_user
, self
.vrops_password
),
1108 verify
= False, headers
= headers
)
1109 if resp
.status_code
is not 204:
1110 self
.logger
.warning("Failed to delete notification rules for {}".format(alarm_name
))
1113 self
.logger
.info("Deleted notification rules for {}".format(alarm_name
))
1116 def get_notification_rule_id_by_alarm_name(self
, alarm_name
):
1117 """Find created Alarm notification rule id by alarm name
1119 alarm_notify_id
= 'notify_' + alarm_name
1120 api_url
= '/suite-api/api/notifications/rules'
1121 headers
= {'Content-Type': 'application/json', 'Accept':'application/json'}
1122 resp
= requests
.get(self
.vrops_site
+ api_url
,
1123 auth
=(self
.vrops_user
, self
.vrops_password
),
1124 verify
= False, headers
= headers
)
1126 if resp
.status_code
is not 200:
1127 self
.logger
.warning("Failed to get notification rules details for {}"\
1128 .format(alarm_name
))
1131 notifications
= json
.loads(resp
.content
)
1132 if notifications
is not None and 'notification-rule' in notifications
:
1133 notifications_list
= notifications
['notification-rule']
1134 for dict in notifications_list
:
1135 if dict['name'] is not None and dict['name'] == alarm_notify_id
:
1136 notification_id
= dict['id']
1137 self
.logger
.info("Found Notification id to be deleted: {} for {}"\
1138 .format(notification_id
, alarm_name
))
1139 return notification_id
1141 self
.logger
.warning("Notification id to be deleted not found for {}"\
1142 .format(alarm_name
))
1145 def delete_alarm_defination(self
, alarm_id
):
1146 """Delete created Alarm definition
1148 api_url
= '/suite-api/api/alertdefinitions/'
1149 headers
= {'Accept':'application/json'}
1150 resp
= requests
.delete(self
.vrops_site
+ api_url
+ alarm_id
,
1151 auth
=(self
.vrops_user
, self
.vrops_password
),
1152 verify
= False, headers
= headers
)
1153 if resp
.status_code
is not 204:
1154 self
.logger
.warning("Failed to delete alarm definition {}".format(alarm_id
))
1157 self
.logger
.info("Deleted alarm definition {}".format(alarm_id
))
1160 def delete_symptom_definition(self
, symptom_id
):
1161 """Delete symptom definition
1163 api_url
= '/suite-api/api/symptomdefinitions/'
1164 headers
= {'Accept':'application/json'}
1165 resp
= requests
.delete(self
.vrops_site
+ api_url
+ symptom_id
,
1166 auth
=(self
.vrops_user
, self
.vrops_password
),
1167 verify
= False, headers
= headers
)
1168 if resp
.status_code
is not 204:
1169 self
.logger
.warning("Failed to delete symptom definition {}".format(symptom_id
))
1172 self
.logger
.info("Deleted symptom definition {}".format(symptom_id
))
1176 def verify_metric_support(self
, metric_info
):
1177 """Verify, if Metric is supported by vROPs plugin, verify metric unit & return status
1179 status: True if supported, False if not supported
1182 if 'metric_name' not in metric_info
:
1183 self
.logger
.debug("Metric name not provided: {}".format(metric_info
))
1185 metric_key_params
= self
.get_default_Params(metric_info
['metric_name'].lower())
1186 if not metric_key_params
:
1187 self
.logger
.warning("Metric not supported: {}".format(metric_info
['metric_name']))
1190 #If Metric is supported, verify optional metric unit & return status
1191 if 'metric_unit' in metric_info
:
1192 if metric_key_params
.get('unit') == metric_info
['metric_unit']:
1193 self
.logger
.info("Metric is supported with unit: {}".format(metric_info
['metric_name']))
1196 self
.logger
.debug("Metric supported but there is unit mismatch for: {}."\
1197 "Supported unit: {}"\
1198 .format(metric_info
['metric_name'],metric_key_params
['unit']))
1202 def get_triggered_alarms_list(self
, list_alarm_input
):
1203 """Get list of triggered alarms on a resource based on alarm input request.
1205 #TO Do - Need to add filtering of alarms based on Severity & alarm name
1207 triggered_alarms_list
= []
1208 if list_alarm_input
.get('resource_uuid') is None:
1209 self
.logger
.warning("Resource UUID is required to get triggered alarms list")
1210 return triggered_alarms_list
1212 #1)Find vROPs resource ID using RO resource UUID
1213 vrops_resource_id
= self
.get_vrops_resourceid_from_ro_uuid(list_alarm_input
['resource_uuid'])
1214 if vrops_resource_id
is None:
1215 return triggered_alarms_list
1217 #2)Get triggered alarms on particular resource
1218 triggered_alarms_list
= self
.get_triggered_alarms_on_resource(list_alarm_input
['resource_uuid'], vrops_resource_id
)
1219 return triggered_alarms_list
1221 def get_vrops_resourceid_from_ro_uuid(self
, ro_resource_uuid
):
1222 """Fetch vROPs resource ID using resource UUID from RO/SO
1224 #1) Find vm_moref_id from vApp uuid in vCD
1225 vm_moref_id
= self
.get_vm_moref_id(ro_resource_uuid
)
1226 if vm_moref_id
is None:
1227 self
.logger
.warning("Failed to find vm morefid for vApp in vCD: {}".format(ro_resource_uuid
))
1230 #2) Based on vm_moref_id, find VM's corresponding resource_id in vROPs to set notification
1231 vrops_resource_id
= self
.get_vm_resource_id(vm_moref_id
)
1232 if vrops_resource_id
is None:
1233 self
.logger
.warning("Failed to find resource in vROPs: {}".format(ro_resource_uuid
))
1235 return vrops_resource_id
1238 def get_triggered_alarms_on_resource(self
, ro_resource_uuid
, vrops_resource_id
):
1239 """Get triggered alarms on particular resource & return list of dictionary of alarms
1241 resource_alarms
= []
1242 api_url
= '/suite-api/api/alerts?resourceId='
1243 headers
= {'Accept':'application/json'}
1244 resp
= requests
.get(self
.vrops_site
+ api_url
+ vrops_resource_id
,
1245 auth
=(self
.vrops_user
, self
.vrops_password
),
1246 verify
= False, headers
= headers
)
1248 if resp
.status_code
is not 200:
1249 self
.logger
.warning("Failed to get triggered alarms for {}"\
1250 .format(ro_resource_uuid
))
1253 all_alerts
= json
.loads(resp
.content
)
1254 if 'alerts' in all_alerts
:
1255 if not all_alerts
['alerts']:
1256 self
.logger
.info("No alarms present on resource {}".format(ro_resource_uuid
))
1257 return resource_alarms
1258 all_alerts_list
= all_alerts
['alerts']
1259 for alarm
in all_alerts_list
:
1260 #self.logger.info("Triggered Alarm {}".format(alarm))
1261 if alarm
['alertDefinitionName'] is not None and\
1262 len(alarm
['alertDefinitionName'].split('-', 1)) == 2:
1263 if alarm
['alertDefinitionName'].split('-', 1)[1] == ro_resource_uuid
:
1265 alarm_instance
['alarm_uuid'] = alarm
['alertDefinitionId'].split('-', 1)[1]
1266 alarm_instance
['resource_uuid'] = ro_resource_uuid
1267 alarm_instance
['alarm_instance_uuid'] = alarm
['alertId']
1268 alarm_instance
['vim_type'] = 'VMware'
1269 #find severity of alarm
1271 for key
,value
in six
.iteritems(severity_mano2vrops
):
1272 if value
== alarm
['alertLevel']:
1274 if severity
is None:
1275 severity
= 'INDETERMINATE'
1276 alarm_instance
['severity'] = severity
1277 alarm_instance
['status'] = alarm
['status']
1278 alarm_instance
['start_date'] = self
.convert_date_time(alarm
['startTimeUTC'])
1279 alarm_instance
['update_date'] = self
.convert_date_time(alarm
['updateTimeUTC'])
1280 alarm_instance
['cancel_date'] = self
.convert_date_time(alarm
['cancelTimeUTC'])
1281 self
.logger
.info("Triggered Alarm on resource {}".format(alarm_instance
))
1282 resource_alarms
.append(alarm_instance
)
1283 if not resource_alarms
:
1284 self
.logger
.info("No alarms present on resource {}".format(ro_resource_uuid
))
1285 return resource_alarms
1287 def convert_date_time(self
, date_time
):
1288 """Convert the input UTC time in msec to OSM date time format
1290 date_time_formatted
= '0000-00-00T00:00:00'
1292 complete_datetime
= datetime
.datetime
.fromtimestamp(date_time
/1000.0, tz
=pytz
.utc
).isoformat('T')
1293 date_time_formatted
= complete_datetime
.split('.',1)[0]
1294 return date_time_formatted