Fix improper restriction of XMl External Entity Reference, by using lxml
[osm/MON.git] / osm_mon / collector / infra_collectors / vmware.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 # pylint: disable=E1101
25
26 import logging
27 from typing import List
28 from lxml import etree as XmlElementTree
29
30 import requests
31 from pyvcloud.vcd.client import BasicLoginCredentials
32 from pyvcloud.vcd.client import Client
33
34 from osm_mon.collector.infra_collectors.base_vim import BaseVimInfraCollector
35 from osm_mon.collector.metric import Metric
36 from osm_mon.core.common_db import CommonDbClient
37 from osm_mon.core.config import Config
38
39 log = logging.getLogger(__name__)
40 API_VERSION = "27.0"
41
42
43 class VMwareInfraCollector(BaseVimInfraCollector):
44 def __init__(self, config: Config, vim_account_id: str):
45 super().__init__(config, vim_account_id)
46 self.vim_account_id = vim_account_id
47 self.common_db = CommonDbClient(config)
48 vim_account = self.get_vim_account(vim_account_id)
49 self.vcloud_site = vim_account["vim_url"]
50 self.admin_username = vim_account["admin_username"]
51 self.admin_password = vim_account["admin_password"]
52 self.vim_uuid = vim_account["vim_uuid"]
53 self.org_name = vim_account["orgname"]
54 self.vim_project_id = vim_account["project_id"]
55 self.verify_ssl = vim_account.get("insecure", False)
56
57 def connect_vim_as_admin(self):
58 """Method connect as pvdc admin user to vCloud director.
59 There are certain action that can be done only by provider vdc admin user.
60 Organization creation / provider network creation etc.
61
62 Returns:
63 The return client object that letter can be used to connect to vcloud direct as admin for provider vdc
64 """
65
66 log.info("Logging into vCD org as admin.")
67
68 admin_user = None
69 try:
70 host = self.vcloud_site
71 admin_user = self.admin_username
72 admin_passwd = self.admin_password
73 org = "System"
74 client = Client(host, verify_ssl_certs=self.verify_ssl)
75 client.set_highest_supported_version()
76 client.set_credentials(BasicLoginCredentials(admin_user, org, admin_passwd))
77 return client
78
79 except Exception as e:
80 log.info(
81 "Can't connect to a vCloud director as: {} with exception {}".format(
82 admin_user, e
83 )
84 )
85
86 def get_vim_account(self, vim_account_id: str):
87 """
88 Method to get VIM account details by its ID
89 arg - VIM ID
90 return - dict with vim account details
91 """
92 vim_account = {}
93 vim_account_info = self.common_db.get_vim_account(vim_account_id)
94
95 vim_account["name"] = vim_account_info["name"]
96 vim_account["vim_tenant_name"] = vim_account_info["vim_tenant_name"]
97 vim_account["vim_type"] = vim_account_info["vim_type"]
98 vim_account["vim_url"] = vim_account_info["vim_url"]
99 vim_account["org_user"] = vim_account_info["vim_user"]
100 vim_account["vim_uuid"] = vim_account_info["_id"]
101 if vim_account_info["_admin"]["projects_read"]:
102 vim_account["project_id"] = vim_account_info["_admin"]["projects_read"][0]
103 else:
104 vim_account["project_id"] = ""
105
106 vim_config = vim_account_info["config"]
107 vim_account["admin_username"] = vim_config["admin_username"]
108 vim_account["admin_password"] = vim_config["admin_password"]
109
110 if vim_config["orgname"] is not None:
111 vim_account["orgname"] = vim_config["orgname"]
112
113 return vim_account
114
115 def check_vim_status(self):
116 try:
117 client = self.connect_vim_as_admin()
118 if client._session:
119 org_list = client.get_org_list()
120 for org in org_list.Org:
121 if org.get("name") == self.org_name:
122 org_uuid = org.get("href").split("/")[-1]
123
124 url = "{}/api/org/{}".format(self.vcloud_site, org_uuid)
125
126 headers = {
127 "Accept": "application/*+xml;version=" + API_VERSION,
128 "x-vcloud-authorization": client._session.headers[
129 "x-vcloud-authorization"
130 ],
131 }
132
133 response = requests.get(
134 url=url, headers=headers, verify=self.verify_ssl
135 )
136
137 if (
138 response.status_code != requests.codes.ok
139 ): # pylint: disable=no-member
140 log.info("check_vim_status(): failed to get org details")
141 else:
142 org_details = XmlElementTree.fromstring(response.content)
143 vdc_list = {}
144 for child in org_details:
145 if "type" in child.attrib:
146 if (
147 child.attrib["type"]
148 == "application/vnd.vmware.vcloud.vdc+xml"
149 ):
150 vdc_list[
151 child.attrib["href"].split("/")[-1:][0]
152 ] = child.attrib["name"]
153
154 if vdc_list:
155 return True
156 else:
157 return False
158 except Exception as e:
159 log.info("Exception occured while checking vim status {}".format(str(e)))
160
161 def check_vm_status(self, vapp_id):
162 try:
163 client = self.connect_vim_as_admin()
164 if client._session:
165 url = "{}/api/vApp/vapp-{}".format(self.vcloud_site, vapp_id)
166
167 headers = {
168 "Accept": "application/*+xml;version=" + API_VERSION,
169 "x-vcloud-authorization": client._session.headers[
170 "x-vcloud-authorization"
171 ],
172 }
173
174 response = requests.get(
175 url=url, headers=headers, verify=self.verify_ssl
176 )
177
178 if (
179 response.status_code != requests.codes.ok
180 ): # pylint: disable=no-member
181 log.info("check_vm_status(): failed to get vApp details")
182 else:
183 vapp_details = XmlElementTree.fromstring(response.content)
184 vm_list = []
185 for child in vapp_details:
186 if child.tag.split("}")[1] == "Children":
187 for item in child.getchildren():
188 vm_list.append(item.attrib)
189 return vm_list
190 except Exception as e:
191 log.info("Exception occured while checking vim status {}".format(str(e)))
192
193 def collect(self) -> List[Metric]:
194 metrics = []
195 vim_status = self.check_vim_status()
196 vim_account_id = self.vim_account_id
197 vim_project_id = self.vim_project_id
198 vim_tags = {"vim_account_id": vim_account_id, "project_id": vim_project_id}
199 vim_status_metric = Metric(vim_tags, "vim_status", vim_status)
200 metrics.append(vim_status_metric)
201 vnfrs = self.common_db.get_vnfrs(vim_account_id=vim_account_id)
202 if self.conf.get("collector", "vm_infra_metrics"):
203 vm_infra_metrics_enabled = str(
204 self.conf.get("collector", "vm_infra_metrics")
205 ).lower() in ("yes", "true", "1")
206 else:
207 vm_infra_metrics_enabled = True
208 if vm_infra_metrics_enabled:
209 for vnfr in vnfrs:
210 nsr_id = vnfr["nsr-id-ref"]
211 ns_name = self.common_db.get_nsr(nsr_id)["name"]
212 vnf_member_index = vnfr["member-vnf-index-ref"]
213 if vnfr["_admin"]["projects_read"]:
214 vnfr_project_id = vnfr["_admin"]["projects_read"][0]
215 else:
216 vnfr_project_id = ""
217 for vdur in vnfr["vdur"]:
218 resource_uuid = vdur["vim-id"]
219 tags = {
220 "vim_account_id": self.vim_account_id,
221 "resource_uuid": resource_uuid,
222 "nsr_id": nsr_id,
223 "ns_name": ns_name,
224 "vnf_member_index": vnf_member_index,
225 "vdur_name": vdur["name"],
226 "project_id": vnfr_project_id,
227 }
228 try:
229 vm_list = self.check_vm_status(resource_uuid)
230 for vm in vm_list:
231 if vm["status"] == "4" and vm["deployed"] == "true":
232 vm_status = 1
233 else:
234 vm_status = 0
235 vm_status_metric = Metric(tags, "vm_status", vm_status)
236 except Exception:
237 log.exception("VM status is not OK!")
238 vm_status_metric = Metric(tags, "vm_status", 0)
239 metrics.append(vm_status_metric)
240 return metrics