Fixes VIO collection
[osm/MON.git] / osm_mon / collector / vnf_collectors / vio.py
index 0d481ea..84cebe0 100644 (file)
 
 import json
 import logging
-import re
-import time
-import traceback
-
-import requests
-import six
-from keystoneauth1 import session
-from keystoneauth1.identity import v3
-from novaclient import client as nClient
 
 from osm_mon.collector.utils.collector import CollectorUtils
 from osm_mon.collector.vnf_collectors.base_vim import BaseVimCollector
-from osm_mon.collector.vnf_metric import VnfMetric
 from osm_mon.core.common_db import CommonDbClient
 from osm_mon.core.config import Config
-from osm_mon.core.database import VimCredentialsRepository, VimCredentials
+from osm_mon.collector.vnf_collectors.vrops.vrops_helper import vROPS_Helper
 
 log = logging.getLogger(__name__)
 
-PERIOD_MSEC = {'HR': 3600000,
-               'DAY': 86400000,
-               'WEEK': 604800000,
-               'MONTH': 2678400000,
-               'YEAR': 31536000000}
-
-METRIC_MAPPINGS = {
-    "average_memory_utilization": "mem|usage_average",
-    "cpu_utilization": "cpu|usage_average",
-    "read_latency_0": "virtualDisk:scsi0:0|totalReadLatency_average",
-    "write_latency_0": "virtualDisk:scsi0:0|totalWriteLatency_average",
-    "read_latency_1": "virtualDisk:scsi0:1|totalReadLatency_average",
-    "write_latency_1": "virtualDisk:scsi0:1|totalWriteLatency_average",
-    "packets_dropped_0": "net:4000|dropped",
-    "packets_dropped_1": "net:4001|dropped",
-    "packets_dropped_2": "net:4002|dropped",
-    "packets_received": "net:Aggregate of all instances|packetsRxPerSec",
-    "packets_sent": "net:Aggregate of all instances|packetsTxPerSec",
-}
-
 
 class VIOCollector(BaseVimCollector):
     def __init__(self, config: Config, vim_account_id: str):
         super().__init__(config, vim_account_id)
         self.common_db = CommonDbClient(config)
-        vim_account_info = CollectorUtils.get_credentials(vim_account_id)
-        cfg = json.loads(vim_account_info.config)
-        self.vrops_site = cfg['vrops_site']
-        self.vrops_user = cfg['vrops_user']
-        self.vrops_password = cfg['vrops_password']
-        self.client = self.connect_client(vim_account_id)
-
-    def connect_client(self, vim_account_id: str):
-        vim_account_details = VimCredentialsRepository.get(VimCredentials.uuid == vim_account_id)
-        verify_ssl = CollectorUtils.is_verify_ssl(vim_account_details)
-        auth = v3.Password(auth_url=vim_account_details.url,
-                           username=vim_account_details.user,
-                           password=vim_account_details.password,
-                           project_name=vim_account_details.tenant_name,
-                           project_domain_id='default',
-                           user_domain_id='default')
-        sess = session.Session(auth=auth, verify=verify_ssl)
-        client = nClient.Client('2.1', session=sess, endpoint_type=None)
-        return client
-
-    def _get_resource_uuid(self, nsr_id, vnf_member_index, vdur_name) -> str:
-        vdur = self.common_db.get_vdur(nsr_id, vnf_member_index, vdur_name)
-        return vdur['vim-id']
-
-    def get_vm_name_and_id(self, resource_uuid):
-        """ Method to find vm name and id using resource_uuid
-        """
-        server = self.client.servers.find(id=resource_uuid)
-        name = server.to_dict()['name']
-        _id = server.to_dict()['id']
-        return name, _id
+        cfg = self.get_vim_account(vim_account_id)
+        self.vrops = vROPS_Helper(vrops_site=cfg['vrops_site'],
+                                  vrops_user=cfg['vrops_user'],
+                                  vrops_password=cfg['vrops_password'])
 
-    def get_vm_resource_id(self, name, _id):
-        """ Find resource ID in vROPs
-        """
-        api_url = '/suite-api/api/resources?resourceKind=VirtualMachine'
-        headers = {'Accept': 'application/json'}
-
-        resp = requests.get(self.vrops_site + api_url,
-                            auth=(self.vrops_user, self.vrops_password),
-                            verify=False, headers=headers)
-
-        if resp.status_code != 200:
-            log.error("Failed to get resource details for{} {} {}".format(name,
-                                                                          resp.status_code,
-                                                                          resp.content))
-            return None
-
-        vm_resource_id = None
-        try:
-            resp_data = json.loads(resp.content.decode('utf-8'))
-            if resp_data.get('resourceList') is not None:
-                resource_list = resp_data.get('resourceList')
-                for resource in resource_list:
-                    if resource.get('resourceKey') is not None:
-                        m = re.match(r"(.*?)\s\((.*?)\)", resource['resourceKey']['name'])
-                        if m:
-                            v_name = m.group(1)
-                            v_id = m.group(2)
-                        if name == v_name and _id == v_id:
-                            vm_resource_id = resource['identifier']
-                            log.info("Found VM resource ID: {} for vm: {}".format(vm_resource_id,
-                                                                                  v_name))
-
-        except Exception as exp:
-            log.info("get_vm_resource_id: Error in parsing {}\n{}".format(exp, traceback.format_exc()))
-
-        return vm_resource_id
+    def get_vim_account(self, vim_account_id: str):
+        vim_account_info = CollectorUtils.get_credentials(vim_account_id)
+        return json.loads(vim_account_info.config)
 
     def collect(self, vnfr: dict):
-        nsr_id = vnfr['nsr-id-ref']
-        vnf_member_index = vnfr['member-vnf-index-ref']
         vnfd = self.common_db.get_vnfd(vnfr['vnfd-id'])
-        metrics = []
+        vdu_mappings = {}
+
+        # Fetch the list of all known resources from vROPS.
+        resource_list = self.vrops.get_vm_resource_list_from_vrops()
+
         for vdur in vnfr['vdur']:
             # This avoids errors when vdur records have not been completely filled
             if 'name' not in vdur:
                 continue
+
             vdu = next(
                 filter(lambda vdu: vdu['id'] == vdur['vdu-id-ref'], vnfd['vdu'])
-
             )
-            if 'monitoring-param' in vdu:
-                for param in vdu['monitoring-param']:
-                    metric_name = param['nfvi-metric']
-                    vrops_metric_name = METRIC_MAPPINGS[metric_name]
-                    resource_uuid = self._get_resource_uuid(nsr_id, vnf_member_index, vdur['name'])
-
-                    name, _id = self.get_vm_name_and_id(resource_uuid)
-                    if name and _id is not None:
-                        resource_id = self.get_vm_resource_id(name, _id)
-                    else:
-                        return
-                    try:
-                        end_time = int(round(time.time() * 1000))
-                        time_diff = PERIOD_MSEC['YEAR']
-                        begin_time = end_time - time_diff
-
-                        api_url = "/suite-api/api/resources/{}/stats?statKey={}&begin={}&end={}".format(
-                            resource_id, vrops_metric_name, str(begin_time), str(end_time))
-
-                        headers = {'Accept': 'application/json'}
-
-                        resp = requests.get(self.vrops_site + api_url,
-                                            auth=(self.vrops_user, self.vrops_password), verify=False, headers=headers
-                                            )
-
-                        if resp.status_code != 200:
-                            log.info("Failed to get Metrics data from vROPS for {} {} {}".format(vrops_metric_name,
-                                                                                                 resp.status_code,
-                                                                                                 resp.content))
-                            return
-
-                        metrics_data = {}
-                        m_data = json.loads(resp.content.decode('utf-8'))
-
-                        for resp_key, resp_val in six.iteritems(m_data):
-                            if resp_key == 'values':
-                                data = m_data['values'][0]
-                                for data_k, data_v in six.iteritems(data):
-                                    if data_k == 'stat-list':
-                                        stat_list = data_v
-                                        for stat_list_k, stat_list_v in six.iteritems(stat_list):
-                                            for stat_keys, stat_vals in six.iteritems(stat_list_v[0]):
-                                                if stat_keys == 'timestamps':
-                                                    metrics_data['time_series'] = stat_list_v[0]['timestamps']
-                                                if stat_keys == 'data':
-                                                    metrics_data['metrics_series'] = stat_list_v[0]['data']
-
-                        if metrics_data:
-                            metric = VnfMetric(nsr_id,
-                                               vnf_member_index,
-                                               vdur['name'],
-                                               metric_name,
-                                               metrics_data['metrics_series'][-1])
-
-                            metrics.append(metric)
-
-                    except Exception as e:
-                        log.debug("No metric found: %s", e)
-                        pass
+            if 'monitoring-param' not in vdu:
+                continue
 
-        return metrics
+            vim_id = vdur['vim-id']
+            vdu_mappings[vim_id] = {'name': vdur['name']}
+
+            # Map the vROPS instance id to the vim-id so we can look it up.
+            for resource in resource_list:
+                for resourceIdentifier in resource['resourceKey']['resourceIdentifiers']:
+                    if resourceIdentifier['identifierType']['name'] == 'VMEntityInstanceUUID':
+                        if resourceIdentifier['value'] != vim_id:
+                            continue
+                        vdu_mappings[vim_id]['vrops_id'] = resource['identifier']
+
+        if len(vdu_mappings) != 0:
+            return self.vrops.get_metrics(vdu_mappings=vdu_mappings,
+                                          monitoring_params=vdu['monitoring-param'],
+                                          vnfr=vnfr)
+        else:
+            return []