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
« prev ^ index » next coverage.py v7.6.12, created at 2025-05-06 19:04 +0000
1# -*- coding: utf-8 -*-
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##
24import logging
25import traceback
26from lxml import etree as XmlElementTree
28import requests
29from pyvcloud.vcd.client import BasicLoginCredentials
30from pyvcloud.vcd.client import Client
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
37log = logging.getLogger(__name__)
39API_VERSION = "27.0"
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 )
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.
61 Returns:
62 The return client object that letter can be used to connect to vcloud direct as admin for provider vdc
63 """
65 log.debug("Logging into vCD org as admin.")
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
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 )
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)
94 vim_account["vim_url"] = vim_account_info["vim_url"]
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"]
103 return vim_account
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)
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 )
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 )
137 return vm_moref_id
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 = {}
147 if vapp_uuid is None:
148 return parsed_respond
150 vca = self.connect_as_admin()
152 if not vca:
153 log.error("Failed to connect to vCD")
154 return parsed_respond
156 url_list = [self.vcloud_site, "/api/vApp/vapp-", vapp_uuid]
157 get_vapp_restcall = "".join(url_list)
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)
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
176 try:
177 xmlroot_respond = XmlElementTree.fromstring(response.content)
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 }
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
203 except Exception as exp:
204 log.warning(
205 "Error occurred for getting vApp details: {}\n{}".format(
206 exp, traceback.format_exc()
207 )
208 )
210 return parsed_respond
212 def collect(self, vnfr: dict):
213 vnfd = self.common_db.get_vnfd(vnfr["vnfd-id"])
214 vdu_mappings = {}
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"] = ""
225 # Fetch the list of all known resources from vROPS.
226 resource_list = self.vrops.get_vm_resource_list_from_vrops()
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"]))
234 if "monitoring-parameter" not in vdu:
235 continue
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
246 vdu_mappings[vim_id] = {"name": vdur["name"]}
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"]
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 []