Coverage for osm_mon/collector/vnf_collectors/vrops/vrops_helper.py: 98%

97 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-05-06 19:04 +0000

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 

24import logging 

25import json 

26import requests 

27import traceback 

28 

29from osm_mon.collector.vnf_metric import VnfMetric 

30from osm_mon.collector.vnf_collectors.vrops.metrics import METRIC_MAPPINGS 

31import copy 

32 

33log = 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. 

38METRIC_MULTIPLIERS = { 

39 "disk_read_bytes": 1024, 

40 "disk_write_bytes": 1024, 

41 "packets_received": 1024, 

42 "packets_sent": 1024, 

43} 

44 

45 

46class vROPS_Helper: 

47 def __init__( 

48 self, 

49 vrops_site="https://vrops", 

50 vrops_user="", 

51 vrops_password="", 

52 verify_ssl=False, 

53 ): 

54 self.vrops_site = vrops_site 

55 self.vrops_user = vrops_user 

56 self.vrops_password = vrops_password 

57 self.verify_ssl = verify_ssl 

58 

59 def get_vrops_token(self): 

60 """Fetches token from vrops""" 

61 auth_url = "/suite-api/api/auth/token/acquire" 

62 headers = {"Content-Type": "application/json", "Accept": "application/json"} 

63 req_body = {"username": self.vrops_user, "password": self.vrops_password} 

64 resp = requests.post( 

65 self.vrops_site + auth_url, 

66 json=req_body, 

67 verify=self.verify_ssl, 

68 headers=headers, 

69 ) 

70 if resp.status_code != 200: 

71 log.error( 

72 "Failed to get token from vROPS: {} {}".format( 

73 resp.status_code, resp.content 

74 ) 

75 ) 

76 return None 

77 

78 resp_data = json.loads(resp.content.decode("utf-8")) 

79 return resp_data["token"] 

80 

81 def get_vm_resource_list_from_vrops(self): 

82 """Find all known resource IDs in vROPs""" 

83 auth_token = self.get_vrops_token() 

84 api_url = "/suite-api/api/resources?resourceKind=VirtualMachine" 

85 headers = { 

86 "Accept": "application/json", 

87 "Authorization": "vRealizeOpsToken {}".format(auth_token), 

88 } 

89 resource_list = [] 

90 

91 resp = requests.get( 

92 self.vrops_site + api_url, verify=self.verify_ssl, headers=headers 

93 ) 

94 

95 if resp.status_code != 200: 

96 log.error( 

97 "Failed to get resource list from vROPS: {} {}".format( 

98 resp.status_code, resp.content 

99 ) 

100 ) 

101 return resource_list 

102 

103 try: 

104 resp_data = json.loads(resp.content.decode("utf-8")) 

105 if resp_data.get("resourceList") is not None: 

106 resource_list = resp_data.get("resourceList") 

107 

108 except Exception as exp: 

109 log.error( 

110 "get_vm_resource_id: Error in parsing {}\n{}".format( 

111 exp, traceback.format_exc() 

112 ) 

113 ) 

114 

115 return resource_list 

116 

117 def get_metrics(self, vdu_mappings={}, monitoring_params={}, vnfr=None, tags={}): 

118 monitoring_keys = {} 

119 # Collect the names of all the metrics we need to query 

120 for metric_entry in monitoring_params: 

121 metric_name = metric_entry["performance-metric"] 

122 if metric_name not in METRIC_MAPPINGS: 

123 log.debug("Metric {} not supported, ignoring".format(metric_name)) 

124 continue 

125 monitoring_keys[metric_name] = METRIC_MAPPINGS[metric_name] 

126 

127 metrics = [] 

128 # Make a query for only the stats we have been asked for 

129 stats_key = "" 

130 for stat in monitoring_keys.values(): 

131 stats_key += "&statKey={}".format(stat) 

132 

133 # And only ask for the resource ids that we are interested in 

134 resource_ids = "" 

135 sanitized_vdu_mappings = copy.deepcopy(vdu_mappings) 

136 for key in vdu_mappings.keys(): 

137 vdu = vdu_mappings[key] 

138 if "vrops_id" not in vdu: 

139 log.info("Could not find vROPS id for vdu {}".format(vdu)) 

140 del sanitized_vdu_mappings[key] 

141 continue 

142 resource_ids += "&resourceId={}".format(vdu["vrops_id"]) 

143 vdu_mappings = sanitized_vdu_mappings 

144 

145 try: 

146 # Now we can make a single call to vROPS to collect all relevant metrics for resources we need to monitor 

147 api_url = ( 

148 "/suite-api/api/resources/stats?IntervalType=MINUTES&IntervalCount=1" 

149 "&rollUpType=MAX&currentOnly=true{}{}".format(stats_key, resource_ids) 

150 ) 

151 

152 auth_token = self.get_vrops_token() 

153 headers = { 

154 "Accept": "application/json", 

155 "Authorization": "vRealizeOpsToken {}".format(auth_token), 

156 } 

157 

158 resp = requests.get( 

159 self.vrops_site + api_url, verify=self.verify_ssl, headers=headers 

160 ) 

161 

162 if resp.status_code != 200: 

163 log.error( 

164 "Failed to get Metrics data from vROPS for {} {}".format( 

165 resp.status_code, resp.content 

166 ) 

167 ) 

168 return metrics 

169 

170 m_data = json.loads(resp.content.decode("utf-8")) 

171 if "values" not in m_data: 

172 return metrics 

173 

174 statistics = m_data["values"] 

175 for vdu_stat in statistics: 

176 vrops_id = vdu_stat["resourceId"] 

177 vdu_name = None 

178 for vdu in vdu_mappings.values(): 

179 if vdu["vrops_id"] == vrops_id: 

180 vdu_name = vdu["name"] 

181 if vdu_name is None: 

182 continue 

183 for item in vdu_stat["stat-list"]["stat"]: 

184 reported_metric = item["statKey"]["key"] 

185 if reported_metric not in METRIC_MAPPINGS.values(): 

186 continue 

187 

188 # Convert the vROPS metric name back to OSM key 

189 metric_name = list(METRIC_MAPPINGS.keys())[ 

190 list(METRIC_MAPPINGS.values()).index(reported_metric) 

191 ] 

192 if metric_name in monitoring_keys.keys(): 

193 metric_value = item["data"][-1] 

194 if metric_name in METRIC_MULTIPLIERS: 

195 metric_value *= METRIC_MULTIPLIERS[metric_name] 

196 metric = VnfMetric( 

197 vnfr["nsr-id-ref"], 

198 vnfr["member-vnf-index-ref"], 

199 vdu_name, 

200 metric_name, 

201 metric_value, 

202 tags, 

203 ) 

204 

205 metrics.append(metric) 

206 

207 except Exception as exp: 

208 log.error( 

209 "Exception while parsing metrics data from vROPS {}\n{}".format( 

210 exp, traceback.format_exc() 

211 ) 

212 ) 

213 

214 return metrics