Reformat files according to new black validation
[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 def __init__(self, vrops_site="https://vrops", vrops_user="", vrops_password=""):
48 self.vrops_site = vrops_site
49 self.vrops_user = vrops_user
50 self.vrops_password = vrops_password
51
52 def get_vrops_token(self):
53 """Fetches token from vrops"""
54 auth_url = "/suite-api/api/auth/token/acquire"
55 headers = {"Content-Type": "application/json", "Accept": "application/json"}
56 req_body = {"username": self.vrops_user, "password": self.vrops_password}
57 resp = requests.post(
58 self.vrops_site + auth_url, json=req_body, verify=False, headers=headers
59 )
60 if resp.status_code != 200:
61 log.error(
62 "Failed to get token from vROPS: {} {}".format(
63 resp.status_code, resp.content
64 )
65 )
66 return None
67
68 resp_data = json.loads(resp.content.decode("utf-8"))
69 return resp_data["token"]
70
71 def get_vm_resource_list_from_vrops(self):
72 """Find all known resource IDs in vROPs"""
73 auth_token = self.get_vrops_token()
74 api_url = "/suite-api/api/resources?resourceKind=VirtualMachine"
75 headers = {
76 "Accept": "application/json",
77 "Authorization": "vRealizeOpsToken {}".format(auth_token),
78 }
79 resource_list = []
80
81 resp = requests.get(self.vrops_site + api_url, verify=False, headers=headers)
82
83 if resp.status_code != 200:
84 log.error(
85 "Failed to get resource list from vROPS: {} {}".format(
86 resp.status_code, resp.content
87 )
88 )
89 return resource_list
90
91 try:
92 resp_data = json.loads(resp.content.decode("utf-8"))
93 if resp_data.get("resourceList") is not None:
94 resource_list = resp_data.get("resourceList")
95
96 except Exception as exp:
97 log.error(
98 "get_vm_resource_id: Error in parsing {}\n{}".format(
99 exp, traceback.format_exc()
100 )
101 )
102
103 return resource_list
104
105 def get_metrics(self, vdu_mappings={}, monitoring_params={}, vnfr=None, tags={}):
106 monitoring_keys = {}
107 # Collect the names of all the metrics we need to query
108 for metric_entry in monitoring_params:
109 metric_name = metric_entry["performance-metric"]
110 if metric_name not in METRIC_MAPPINGS:
111 log.debug("Metric {} not supported, ignoring".format(metric_name))
112 continue
113 monitoring_keys[metric_name] = METRIC_MAPPINGS[metric_name]
114
115 metrics = []
116 # Make a query for only the stats we have been asked for
117 stats_key = ""
118 for stat in monitoring_keys.values():
119 stats_key += "&statKey={}".format(stat)
120
121 # And only ask for the resource ids that we are interested in
122 resource_ids = ""
123 sanitized_vdu_mappings = copy.deepcopy(vdu_mappings)
124 for key in vdu_mappings.keys():
125 vdu = vdu_mappings[key]
126 if "vrops_id" not in vdu:
127 log.info("Could not find vROPS id for vdu {}".format(vdu))
128 del sanitized_vdu_mappings[key]
129 continue
130 resource_ids += "&resourceId={}".format(vdu["vrops_id"])
131 vdu_mappings = sanitized_vdu_mappings
132
133 try:
134 # Now we can make a single call to vROPS to collect all relevant metrics for resources we need to monitor
135 api_url = (
136 "/suite-api/api/resources/stats?IntervalType=MINUTES&IntervalCount=1"
137 "&rollUpType=MAX&currentOnly=true{}{}".format(stats_key, resource_ids)
138 )
139
140 auth_token = self.get_vrops_token()
141 headers = {
142 "Accept": "application/json",
143 "Authorization": "vRealizeOpsToken {}".format(auth_token),
144 }
145
146 resp = requests.get(
147 self.vrops_site + api_url, verify=False, headers=headers
148 )
149
150 if resp.status_code != 200:
151 log.error(
152 "Failed to get Metrics data from vROPS for {} {}".format(
153 resp.status_code, resp.content
154 )
155 )
156 return metrics
157
158 m_data = json.loads(resp.content.decode("utf-8"))
159 if "values" not in m_data:
160 return metrics
161
162 statistics = m_data["values"]
163 for vdu_stat in statistics:
164 vrops_id = vdu_stat["resourceId"]
165 vdu_name = None
166 for vdu in vdu_mappings.values():
167 if vdu["vrops_id"] == vrops_id:
168 vdu_name = vdu["name"]
169 if vdu_name is None:
170 continue
171 for item in vdu_stat["stat-list"]["stat"]:
172 reported_metric = item["statKey"]["key"]
173 if reported_metric not in METRIC_MAPPINGS.values():
174 continue
175
176 # Convert the vROPS metric name back to OSM key
177 metric_name = list(METRIC_MAPPINGS.keys())[
178 list(METRIC_MAPPINGS.values()).index(reported_metric)
179 ]
180 if metric_name in monitoring_keys.keys():
181 metric_value = item["data"][-1]
182 if metric_name in METRIC_MULTIPLIERS:
183 metric_value *= METRIC_MULTIPLIERS[metric_name]
184 metric = VnfMetric(
185 vnfr["nsr-id-ref"],
186 vnfr["member-vnf-index-ref"],
187 vdu_name,
188 metric_name,
189 metric_value,
190 tags,
191 )
192
193 metrics.append(metric)
194
195 except Exception as exp:
196 log.error(
197 "Exception while parsing metrics data from vROPS {}\n{}".format(
198 exp, traceback.format_exc()
199 )
200 )
201
202 return metrics