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