65e739db1027321d7dd83d8b16dc844301aa551b
[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 xml.etree import ElementTree 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
56 def connect_vim_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.info("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.info(
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["name"] = vim_account_info["name"]
95 vim_account["vim_tenant_name"] = vim_account_info["vim_tenant_name"]
96 vim_account["vim_type"] = vim_account_info["vim_type"]
97 vim_account["vim_url"] = vim_account_info["vim_url"]
98 vim_account["org_user"] = vim_account_info["vim_user"]
99 vim_account["vim_uuid"] = vim_account_info["_id"]
100 if vim_account_info["_admin"]["projects_read"]:
101 vim_account["project_id"] = vim_account_info["_admin"]["projects_read"][0]
102 else:
103 vim_account["project_id"] = ""
104
105 vim_config = vim_account_info["config"]
106 vim_account["admin_username"] = vim_config["admin_username"]
107 vim_account["admin_password"] = vim_config["admin_password"]
108
109 if vim_config["orgname"] is not None:
110 vim_account["orgname"] = vim_config["orgname"]
111
112 return vim_account
113
114 def check_vim_status(self):
115 try:
116 client = self.connect_vim_as_admin()
117 if client._session:
118 org_list = client.get_org_list()
119 for org in org_list.Org:
120 if org.get("name") == self.org_name:
121 org_uuid = org.get("href").split("/")[-1]
122
123 url = "{}/api/org/{}".format(self.vcloud_site, org_uuid)
124
125 headers = {
126 "Accept": "application/*+xml;version=" + API_VERSION,
127 "x-vcloud-authorization": client._session.headers[
128 "x-vcloud-authorization"
129 ],
130 }
131
132 response = requests.get(url=url, headers=headers, verify=False)
133
134 if (
135 response.status_code != requests.codes.ok
136 ): # pylint: disable=no-member
137 log.info("check_vim_status(): failed to get org details")
138 else:
139 org_details = XmlElementTree.fromstring(response.content)
140 vdc_list = {}
141 for child in org_details:
142 if "type" in child.attrib:
143 if (
144 child.attrib["type"]
145 == "application/vnd.vmware.vcloud.vdc+xml"
146 ):
147 vdc_list[
148 child.attrib["href"].split("/")[-1:][0]
149 ] = child.attrib["name"]
150
151 if vdc_list:
152 return True
153 else:
154 return False
155 except Exception as e:
156 log.info("Exception occured while checking vim status {}".format(str(e)))
157
158 def check_vm_status(self, vapp_id):
159 try:
160 client = self.connect_vim_as_admin()
161 if client._session:
162 url = "{}/api/vApp/vapp-{}".format(self.vcloud_site, vapp_id)
163
164 headers = {
165 "Accept": "application/*+xml;version=" + API_VERSION,
166 "x-vcloud-authorization": client._session.headers[
167 "x-vcloud-authorization"
168 ],
169 }
170
171 response = requests.get(url=url, headers=headers, verify=False)
172
173 if (
174 response.status_code != requests.codes.ok
175 ): # pylint: disable=no-member
176 log.info("check_vm_status(): failed to get vApp details")
177 else:
178 vapp_details = XmlElementTree.fromstring(response.content)
179 vm_list = []
180 for child in vapp_details:
181 if child.tag.split("}")[1] == "Children":
182 for item in child.getchildren():
183 vm_list.append(item.attrib)
184 return vm_list
185 except Exception as e:
186 log.info("Exception occured while checking vim status {}".format(str(e)))
187
188 def collect(self) -> List[Metric]:
189 metrics = []
190 vim_status = self.check_vim_status()
191 vim_account_id = self.vim_account_id
192 vim_project_id = self.vim_project_id
193 vim_tags = {"vim_account_id": vim_account_id, "project_id": vim_project_id}
194 vim_status_metric = Metric(vim_tags, "vim_status", vim_status)
195 metrics.append(vim_status_metric)
196 vnfrs = self.common_db.get_vnfrs(vim_account_id=vim_account_id)
197 for vnfr in vnfrs:
198 nsr_id = vnfr["nsr-id-ref"]
199 ns_name = self.common_db.get_nsr(nsr_id)["name"]
200 vnf_member_index = vnfr["member-vnf-index-ref"]
201 if vnfr["_admin"]["projects_read"]:
202 vnfr_project_id = vnfr["_admin"]["projects_read"][0]
203 else:
204 vnfr_project_id = ""
205 for vdur in vnfr["vdur"]:
206 resource_uuid = vdur["vim-id"]
207 tags = {
208 "vim_account_id": self.vim_account_id,
209 "resource_uuid": resource_uuid,
210 "nsr_id": nsr_id,
211 "ns_name": ns_name,
212 "vnf_member_index": vnf_member_index,
213 "vdur_name": vdur["name"],
214 "project_id": vnfr_project_id,
215 }
216 try:
217 vm_list = self.check_vm_status(resource_uuid)
218 for vm in vm_list:
219 if vm["status"] == "4" and vm["deployed"] == "true":
220 vm_status = 1
221 else:
222 vm_status = 0
223 vm_status_metric = Metric(tags, "vm_status", vm_status)
224 except Exception:
225 log.exception("VM status is not OK!")
226 vm_status_metric = Metric(tags, "vm_status", 0)
227 metrics.append(vm_status_metric)
228 return metrics