Coverage for osm_mon/collector/vnf_collectors/vmware.py: 91%

121 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 traceback 

26from lxml import etree as XmlElementTree 

27 

28import requests 

29from pyvcloud.vcd.client import BasicLoginCredentials 

30from pyvcloud.vcd.client import Client 

31 

32from osm_mon.collector.vnf_collectors.base_vim import BaseVimCollector 

33from osm_mon.collector.vnf_collectors.vrops.vrops_helper import vROPS_Helper 

34from osm_mon.core.common_db import CommonDbClient 

35from osm_mon.core.config import Config 

36 

37log = logging.getLogger(__name__) 

38 

39API_VERSION = "27.0" 

40 

41 

42class VMwareCollector(BaseVimCollector): 

43 def __init__(self, config: Config, vim_account_id: str, vim_session: object): 

44 super().__init__(config, vim_account_id) 

45 self.common_db = CommonDbClient(config) 

46 vim_account = self.get_vim_account(vim_account_id) 

47 self.vcloud_site = vim_account["vim_url"] 

48 self.admin_username = vim_account["admin_username"] 

49 self.admin_password = vim_account["admin_password"] 

50 self.vrops = vROPS_Helper( 

51 vrops_site=vim_account["vrops_site"], 

52 vrops_user=vim_account["vrops_user"], 

53 vrops_password=vim_account["vrops_password"], 

54 ) 

55 

56 def connect_as_admin(self): 

57 """Method connect as pvdc admin user to vCloud director. 

58 There are certain action that can be done only by provider vdc admin user. 

59 Organization creation / provider network creation etc. 

60 

61 Returns: 

62 The return client object that letter can be used to connect to vcloud direct as admin for provider vdc 

63 """ 

64 

65 log.debug("Logging into vCD org as admin.") 

66 

67 admin_user = None 

68 try: 

69 host = self.vcloud_site 

70 admin_user = self.admin_username 

71 admin_passwd = self.admin_password 

72 org = "System" 

73 client = Client(host, verify_ssl_certs=False) 

74 client.set_highest_supported_version() 

75 client.set_credentials(BasicLoginCredentials(admin_user, org, admin_passwd)) 

76 return client 

77 

78 except Exception as e: 

79 log.error( 

80 "Can't connect to a vCloud director as: {} with exception {}".format( 

81 admin_user, e 

82 ) 

83 ) 

84 

85 def get_vim_account(self, vim_account_id: str): 

86 """ 

87 Method to get VIM account details by its ID 

88 arg - VIM ID 

89 return - dict with vim account details 

90 """ 

91 vim_account = {} 

92 vim_account_info = self.common_db.get_vim_account(vim_account_id) 

93 

94 vim_account["vim_url"] = vim_account_info["vim_url"] 

95 

96 vim_config = vim_account_info["config"] 

97 vim_account["admin_username"] = vim_config["admin_username"] 

98 vim_account["admin_password"] = vim_config["admin_password"] 

99 vim_account["vrops_site"] = vim_config["vrops_site"] 

100 vim_account["vrops_user"] = vim_config["vrops_user"] 

101 vim_account["vrops_password"] = vim_config["vrops_password"] 

102 

103 return vim_account 

104 

105 def get_vm_moref_id(self, vapp_uuid): 

106 """ 

107 Method to get the moref_id of given VM 

108 arg - vapp_uuid 

109 return - VM mored_id 

110 """ 

111 vm_moref_id = None 

112 try: 

113 if vapp_uuid: 

114 vm_details = self.get_vapp_details_rest(vapp_uuid) 

115 

116 if vm_details and "vm_vcenter_info" in vm_details: 

117 vm_moref_id = vm_details["vm_vcenter_info"].get("vm_moref_id", None) 

118 log.debug( 

119 "Found vm_moref_id: {} for vApp UUID: {}".format( 

120 vm_moref_id, vapp_uuid 

121 ) 

122 ) 

123 else: 

124 log.error( 

125 "Failed to find vm_moref_id from vApp UUID: {}".format( 

126 vapp_uuid 

127 ) 

128 ) 

129 

130 except Exception as exp: 

131 log.warning( 

132 "Error occurred while getting VM moref ID for VM: {}\n{}".format( 

133 exp, traceback.format_exc() 

134 ) 

135 ) 

136 

137 return vm_moref_id 

138 

139 def get_vapp_details_rest(self, vapp_uuid=None): 

140 """ 

141 Method retrieve vapp detail from vCloud director 

142 vapp_uuid - is vapp identifier. 

143 Returns - VM MOref ID or return None 

144 """ 

145 parsed_respond = {} 

146 

147 if vapp_uuid is None: 

148 return parsed_respond 

149 

150 vca = self.connect_as_admin() 

151 

152 if not vca: 

153 log.error("Failed to connect to vCD") 

154 return parsed_respond 

155 

156 url_list = [self.vcloud_site, "/api/vApp/vapp-", vapp_uuid] 

157 get_vapp_restcall = "".join(url_list) 

158 

159 if vca._session: 

160 headers = { 

161 "Accept": "application/*+xml;version=" + API_VERSION, 

162 "x-vcloud-authorization": vca._session.headers[ 

163 "x-vcloud-authorization" 

164 ], 

165 } 

166 response = requests.get(get_vapp_restcall, headers=headers) 

167 

168 if response.status_code != 200: 

169 log.error( 

170 "REST API call {} failed. Return status code {}".format( 

171 get_vapp_restcall, response.content 

172 ) 

173 ) 

174 return parsed_respond 

175 

176 try: 

177 xmlroot_respond = XmlElementTree.fromstring(response.content) 

178 

179 namespaces = { 

180 "vm": "http://www.vmware.com/vcloud/v1.5", 

181 "vmext": "http://www.vmware.com/vcloud/extension/v1.5", 

182 "xmlns": "http://www.vmware.com/vcloud/v1.5", 

183 } 

184 

185 # parse children section for other attrib 

186 children_section = xmlroot_respond.find("vm:Children/", namespaces) 

187 if children_section is not None: 

188 vCloud_extension_section = children_section.find( 

189 "xmlns:VCloudExtension", namespaces 

190 ) 

191 if vCloud_extension_section is not None: 

192 vm_vcenter_info = {} 

193 vim_info = vCloud_extension_section.find( 

194 "vmext:VmVimInfo", namespaces 

195 ) 

196 vmext = vim_info.find("vmext:VmVimObjectRef", namespaces) 

197 if vmext is not None: 

198 vm_vcenter_info["vm_moref_id"] = vmext.find( 

199 "vmext:MoRef", namespaces 

200 ).text 

201 parsed_respond["vm_vcenter_info"] = vm_vcenter_info 

202 

203 except Exception as exp: 

204 log.warning( 

205 "Error occurred for getting vApp details: {}\n{}".format( 

206 exp, traceback.format_exc() 

207 ) 

208 ) 

209 

210 return parsed_respond 

211 

212 def collect(self, vnfr: dict): 

213 vnfd = self.common_db.get_vnfd(vnfr["vnfd-id"]) 

214 vdu_mappings = {} 

215 

216 # Populate extra tags for metrics 

217 nsr_id = vnfr["nsr-id-ref"] 

218 tags = {} 

219 tags["ns_name"] = self.common_db.get_nsr(nsr_id)["name"] 

220 if vnfr["_admin"]["projects_read"]: 

221 tags["project_id"] = vnfr["_admin"]["projects_read"][0] 

222 else: 

223 tags["project_id"] = "" 

224 

225 # Fetch the list of all known resources from vROPS. 

226 resource_list = self.vrops.get_vm_resource_list_from_vrops() 

227 

228 for vdur in vnfr["vdur"]: 

229 # This avoids errors when vdur records have not been completely filled 

230 if "name" not in vdur: 

231 continue 

232 vdu = next(filter(lambda vdu: vdu["id"] == vdur["vdu-id-ref"], vnfd["vdu"])) 

233 

234 if "monitoring-parameter" not in vdu: 

235 continue 

236 

237 resource_uuid = vdur["vim-id"] 

238 # Find vm_moref_id from vApp uuid in vCD 

239 vim_id = self.get_vm_moref_id(resource_uuid) 

240 if vim_id is None: 

241 log.debug( 

242 "Failed to find vROPS ID for vApp in vCD: {}".format(resource_uuid) 

243 ) 

244 continue 

245 

246 vdu_mappings[vim_id] = {"name": vdur["name"]} 

247 

248 # Map the vROPS instance id to the vim-id so we can look it up. 

249 for resource in resource_list: 

250 for resourceIdentifier in resource["resourceKey"][ 

251 "resourceIdentifiers" 

252 ]: 

253 if ( 

254 resourceIdentifier["identifierType"]["name"] 

255 == "VMEntityObjectID" 

256 ): 

257 if resourceIdentifier["value"] != vim_id: 

258 continue 

259 vdu_mappings[vim_id]["vrops_id"] = resource["identifier"] 

260 

261 if len(vdu_mappings) != 0: 

262 return self.vrops.get_metrics( 

263 vdu_mappings=vdu_mappings, 

264 monitoring_params=vdu["monitoring-parameter"], 

265 vnfr=vnfr, 

266 tags=tags, 

267 ) 

268 else: 

269 return []