219632664e29139d5bdb7d31e366a4f6f5446a3b
[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
107 monitoring_keys = {}
108 # Collect the names of all the metrics we need to query
109 for metric_entry in monitoring_params:
110 metric_name = metric_entry["performance-metric"]
111 if metric_name not in METRIC_MAPPINGS:
112 log.debug("Metric {} not supported, ignoring".format(metric_name))
113 continue
114 monitoring_keys[metric_name] = METRIC_MAPPINGS[metric_name]
115
116 metrics = []
117 # Make a query for only the stats we have been asked for
118 stats_key = ""
119 for stat in monitoring_keys.values():
120 stats_key += "&statKey={}".format(stat)
121
122 # And only ask for the resource ids that we are interested in
123 resource_ids = ""
124 sanitized_vdu_mappings = copy.deepcopy(vdu_mappings)
125 for key in vdu_mappings.keys():
126 vdu = vdu_mappings[key]
127 if "vrops_id" not in vdu:
128 log.info("Could not find vROPS id for vdu {}".format(vdu))
129 del sanitized_vdu_mappings[key]
130 continue
131 resource_ids += "&resourceId={}".format(vdu["vrops_id"])
132 vdu_mappings = sanitized_vdu_mappings
133
134 try:
135
136 # Now we can make a single call to vROPS to collect all relevant metrics for resources we need to monitor
137 api_url = (
138 "/suite-api/api/resources/stats?IntervalType=MINUTES&IntervalCount=1"
139 "&rollUpType=MAX&currentOnly=true{}{}".format(stats_key, resource_ids)
140 )
141
142 auth_token = self.get_vrops_token()
143 headers = {
144 "Accept": "application/json",
145 "Authorization": "vRealizeOpsToken {}".format(auth_token),
146 }
147
148 resp = requests.get(
149 self.vrops_site + api_url, verify=False, headers=headers
150 )
151
152 if resp.status_code != 200:
153 log.error(
154 "Failed to get Metrics data from vROPS for {} {}".format(
155 resp.status_code, resp.content
156 )
157 )
158 return metrics
159
160 m_data = json.loads(resp.content.decode("utf-8"))
161 if "values" not in m_data:
162 return metrics
163
164 statistics = m_data["values"]
165 for vdu_stat in statistics:
166 vrops_id = vdu_stat["resourceId"]
167 vdu_name = None
168 for vdu in vdu_mappings.values():
169 if vdu["vrops_id"] == vrops_id:
170 vdu_name = vdu["name"]
171 if vdu_name is None:
172 continue
173 for item in vdu_stat["stat-list"]["stat"]:
174 reported_metric = item["statKey"]["key"]
175 if reported_metric not in METRIC_MAPPINGS.values():
176 continue
177
178 # Convert the vROPS metric name back to OSM key
179 metric_name = list(METRIC_MAPPINGS.keys())[
180 list(METRIC_MAPPINGS.values()).index(reported_metric)
181 ]
182 if metric_name in monitoring_keys.keys():
183 metric_value = item["data"][-1]
184 if metric_name in METRIC_MULTIPLIERS:
185 metric_value *= METRIC_MULTIPLIERS[metric_name]
186 metric = VnfMetric(
187 vnfr["nsr-id-ref"],
188 vnfr["member-vnf-index-ref"],
189 vdu_name,
190 metric_name,
191 metric_value,
192 tags,
193 )
194
195 metrics.append(metric)
196
197 except Exception as exp:
198 log.error(
199 "Exception while parsing metrics data from vROPS {}\n{}".format(
200 exp, traceback.format_exc()
201 )
202 )
203
204 return metrics