39d3238162c585563730c35e6f2c13731cdd1586
[osm/MON.git] / osm_mon / collector / vnf_collectors / vrops / vrops_helper.py
1 # -*- coding: utf-8 -*-
2
3 # #
4 # Copyright 2016-2019 VMware Inc.
5 # This file is part of ETSI OSM
6 # All Rights Reserved.
7 #
8 # Licensed under the Apache License, Version 2.0 (the "License"); you may
9 # not use this file except in compliance with the License. You may obtain
10 # a copy of the License at
11 #
12 # http://www.apache.org/licenses/LICENSE-2.0
13 #
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17 # License for the specific language governing permissions and limitations
18 # under the License.
19 #
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact: osslegalrouting@vmware.com
22 # #
23
24 import logging
25 import json
26 import requests
27 import traceback
28
29 from osm_mon.collector.vnf_metric import VnfMetric
30 from osm_mon.collector.vnf_collectors.vrops.metrics import METRIC_MAPPINGS
31 import copy
32
33 log = logging.getLogger(__name__)
34
35
36 # If the unit from vROPS does not align with the expected value. multiply by the specified amount to ensure
37 # the correct unit is returned.
38 METRIC_MULTIPLIERS = {
39 "disk_read_bytes": 1024,
40 "disk_write_bytes": 1024,
41 "packets_received": 1024,
42 "packets_sent": 1024
43 }
44
45
46 class vROPS_Helper():
47
48 def __init__(self,
49 vrops_site='https://vrops',
50 vrops_user='',
51 vrops_password=''):
52 self.vrops_site = vrops_site
53 self.vrops_user = vrops_user
54 self.vrops_password = vrops_password
55
56 def get_vrops_token(self):
57 """Fetches token from vrops
58 """
59 auth_url = '/suite-api/api/auth/token/acquire'
60 headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
61 req_body = {"username": self.vrops_user, "password": self.vrops_password}
62 resp = requests.post(self.vrops_site + auth_url,
63 json=req_body, verify=False,
64 headers=headers)
65 if resp.status_code != 200:
66 log.error("Failed to get token from vROPS: {} {}".format(resp.status_code,
67 resp.content))
68 return None
69
70 resp_data = json.loads(resp.content.decode('utf-8'))
71 return resp_data['token']
72
73 def get_vm_resource_list_from_vrops(self):
74 """ Find all known resource IDs in vROPs
75 """
76 auth_token = self.get_vrops_token()
77 api_url = '/suite-api/api/resources?resourceKind=VirtualMachine'
78 headers = {'Accept': 'application/json', 'Authorization': 'vRealizeOpsToken {}'.format(auth_token)}
79 resource_list = []
80
81 resp = requests.get(self.vrops_site + api_url,
82 verify=False, headers=headers)
83
84 if resp.status_code != 200:
85 log.error("Failed to get resource list from vROPS: {} {}".format(resp.status_code,
86 resp.content))
87 return resource_list
88
89 try:
90 resp_data = json.loads(resp.content.decode('utf-8'))
91 if resp_data.get('resourceList') is not None:
92 resource_list = resp_data.get('resourceList')
93
94 except Exception as exp:
95 log.error("get_vm_resource_id: Error in parsing {}\n{}".format(exp, traceback.format_exc()))
96
97 return resource_list
98
99 def get_metrics(self,
100 vdu_mappings={},
101 monitoring_params={},
102 vnfr=None,
103 tags={}):
104
105 monitoring_keys = {}
106 # Collect the names of all the metrics we need to query
107 for metric_entry in monitoring_params:
108 metric_name = metric_entry['nfvi-metric']
109 if metric_name not in METRIC_MAPPINGS:
110 log.debug("Metric {} not supported, ignoring".format(metric_name))
111 continue
112 monitoring_keys[metric_name] = METRIC_MAPPINGS[metric_name]
113
114 metrics = []
115 # Make a query for only the stats we have been asked for
116 stats_key = ""
117 for stat in monitoring_keys.values():
118 stats_key += "&statKey={}".format(stat)
119
120 # And only ask for the resource ids that we are interested in
121 resource_ids = ""
122 sanitized_vdu_mappings = copy.deepcopy(vdu_mappings)
123 for key in vdu_mappings.keys():
124 vdu = vdu_mappings[key]
125 if 'vrops_id' not in vdu:
126 log.info("Could not find vROPS id for vdu {}".format(vdu))
127 del sanitized_vdu_mappings[key]
128 continue
129 resource_ids += "&resourceId={}".format(vdu['vrops_id'])
130 vdu_mappings = sanitized_vdu_mappings
131
132 try:
133
134 # Now we can make a single call to vROPS to collect all relevant metrics for resources we need to monitor
135 api_url = "/suite-api/api/resources/stats?IntervalType=MINUTES&IntervalCount=1"\
136 "&rollUpType=MAX&currentOnly=true{}{}".format(stats_key, resource_ids)
137
138 auth_token = self.get_vrops_token()
139 headers = {'Accept': 'application/json', 'Authorization': 'vRealizeOpsToken {}'.format(auth_token)}
140
141 resp = requests.get(self.vrops_site + api_url,
142 verify=False, headers=headers)
143
144 if resp.status_code != 200:
145 log.error("Failed to get Metrics data from vROPS for {} {}".format(resp.status_code,
146 resp.content))
147 return metrics
148
149 m_data = json.loads(resp.content.decode('utf-8'))
150 if 'values' not in m_data:
151 return metrics
152
153 statistics = m_data['values']
154 for vdu_stat in statistics:
155 vrops_id = vdu_stat['resourceId']
156 vdu_name = None
157 for vdu in vdu_mappings.values():
158 if vdu['vrops_id'] == vrops_id:
159 vdu_name = vdu['name']
160 if vdu_name is None:
161 continue
162 for item in vdu_stat['stat-list']['stat']:
163 reported_metric = item['statKey']['key']
164 if reported_metric not in METRIC_MAPPINGS.values():
165 continue
166
167 # Convert the vROPS metric name back to OSM key
168 metric_name = list(METRIC_MAPPINGS.keys())[list(METRIC_MAPPINGS.values()).
169 index(reported_metric)]
170 if metric_name in monitoring_keys.keys():
171 metric_value = item['data'][-1]
172 if metric_name in METRIC_MULTIPLIERS:
173 metric_value *= METRIC_MULTIPLIERS[metric_name]
174 metric = VnfMetric(vnfr['nsr-id-ref'],
175 vnfr['member-vnf-index-ref'],
176 vdu_name,
177 metric_name,
178 metric_value,
179 tags
180 )
181
182 metrics.append(metric)
183
184 except Exception as exp:
185 log.error("Exception while parsing metrics data from vROPS {}\n{}".format(exp, traceback.format_exc()))
186
187 return metrics