# contact: osslegalrouting@vmware.com
##
-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.collector.vnf_collectors.vrops.vrops_helper import vROPS_Helper
from osm_mon.core.common_db import CommonDbClient
from osm_mon.core.config import Config
-from osm_mon.core.database import VimCredentialsRepository, VimCredentials
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
-
- 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'}
+ 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'])
- resp = requests.get(self.vrops_site + api_url,
- auth=(self.vrops_user, self.vrops_password),
- verify=False, headers=headers)
+ def get_vim_account(self, vim_account_id: str):
+ vim_account_info = self.common_db.get_vim_account(vim_account_id)
+ return vim_account_info['config']
- 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))
+ def collect(self, vnfr: dict):
+ vnfd = self.common_db.get_vnfd(vnfr['vnfd-id'])
+ vdu_mappings = {}
- except Exception as exp:
- log.info("get_vm_resource_id: Error in parsing {}\n{}".format(exp, traceback.format_exc()))
+ # Populate extra tags for metrics
+ nsr_id = vnfr['nsr-id-ref']
+ tags = {}
+ tags['ns_name'] = self.common_db.get_nsr(nsr_id)['name']
+ tags['project_id'] = vnfr['_admin']['projects_read'][0]
- return vm_resource_id
+ # Fetch the list of all known resources from vROPS.
+ resource_list = self.vrops.get_vm_resource_list_from_vrops()
- 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 = []
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,
+ tags=tags
+ )
+ else:
+ return []