forked from sapcc/vrops-exporter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
BaseCollector.py
376 lines (319 loc) · 17.2 KB
/
BaseCollector.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
from abc import ABC, abstractmethod
import requests
import time
import os
import re
import logging
from tools.helper import yaml_read
from tools.Vrops import Vrops
from prometheus_client.core import GaugeMetricFamily, InfoMetricFamily
logger = logging.getLogger('vrops-exporter')
class BaseCollector(ABC):
def __init__(self):
self.vrops_entity_name = 'base'
while os.environ['TARGET'] not in self.get_vrops_list():
logger.critical('Cannot start exporter without valid target!')
logger.critical(f'{os.environ["TARGET"]} is not in vrops_list from inventory')
logger.critical(
f'The following vrops are known from inventory: {[t for t in self.get_vrops_list()]}, retrying in 60s')
time.sleep(60)
self.target = os.environ.get('TARGET')
self.vrops = Vrops()
self.name = self.__class__.__name__
self.label_names = []
self.project_ids = []
@abstractmethod
def collect(self):
pass
def read_collector_config(self):
config_file = yaml_read(os.environ['COLLECTOR_CONFIG'])
return config_file
def get_vcenters(self, target):
self.wait_for_inventory_data()
current_iteration = self.get_iteration()
url = "http://" + os.environ['INVENTORY'] + "/" + target + "/vcenters/{}".format(current_iteration)
request = requests.get(url)
self.vcenters = request.json() if request else {}
return self.vcenters
def get_datacenters(self, target):
self.wait_for_inventory_data()
current_iteration = self.get_iteration()
url = "http://" + os.environ['INVENTORY'] + "/" + target + "/datacenters/{}".format(current_iteration)
request = requests.get(url)
self.datacenters = request.json() if request else {}
return self.datacenters
def get_clusters(self, target):
self.wait_for_inventory_data()
current_iteration = self.get_iteration()
url = "http://" + os.environ['INVENTORY'] + "/" + target + "/clusters/{}".format(current_iteration)
request = requests.get(url)
self.clusters = request.json() if request else {}
return self.clusters
def get_hosts(self, target):
self.wait_for_inventory_data()
current_iteration = self.get_iteration()
url = "http://" + os.environ['INVENTORY'] + "/" + target + "/hosts/{}".format(current_iteration)
request = requests.get(url)
self.hosts = request.json() if request else {}
return self.hosts
def get_SDRS_cluster(self, target):
self.wait_for_inventory_data()
current_iteration = self.get_iteration()
url = "http://" + os.environ['INVENTORY'] + "/" + target + "/storagepod/{}".format(current_iteration)
request = requests.get(url)
self.sdrs_clusters = request.json() if request else {}
return self.sdrs_clusters
def get_datastores(self, target):
self.wait_for_inventory_data()
current_iteration = self.get_iteration()
url = "http://" + os.environ['INVENTORY'] + "/" + target + "/datastores/{}".format(current_iteration)
request = requests.get(url)
self.datastores = request.json() if request else {}
return self.datastores
def get_vms(self, target):
self.wait_for_inventory_data()
current_iteration = self.get_iteration()
url = "http://" + os.environ['INVENTORY'] + "/" + target + "/vms/{}".format(current_iteration)
request = requests.get(url)
self.vms = request.json() if request else {}
return self.vms
def get_distributed_vswitches(self, target):
self.wait_for_inventory_data()
current_iteration = self.get_iteration()
url = "http://" + os.environ['INVENTORY'] + "/" + target + "/dvs/{}".format(current_iteration)
request = requests.get(url)
self.dvs = request.json() if request else {}
return self.dvs
def get_nsxt_adapter(self, target):
self.wait_for_inventory_data()
current_iteration = self.get_iteration()
url = "http://" + os.environ['INVENTORY'] + "/" + target + "/nsxt_adapter/{}".format(current_iteration)
request = requests.get(url)
self.nsxt_adapter = request.json() if request else {}
return self.nsxt_adapter
def get_nsxt_mgmt_cluster(self, target):
self.wait_for_inventory_data()
current_iteration = self.get_iteration()
url = "http://" + os.environ['INVENTORY'] + "/" + target + "/nsxt_mgmt_cluster/{}".format(current_iteration)
request = requests.get(url)
self.nsxt_mgmt_cluster = request.json() if request else {}
return self.nsxt_mgmt_cluster
def get_nsxt_mgmt_nodes(self, target):
self.wait_for_inventory_data()
current_iteration = self.get_iteration()
url = "http://" + os.environ['INVENTORY'] + "/" + target + "/nsxt_mgmt_nodes/{}".format(current_iteration)
request = requests.get(url)
self.nsxt_mgmt_nodes = request.json() if request else {}
return self.nsxt_mgmt_nodes
def get_nsxt_mgmt_service(self, target):
self.wait_for_inventory_data()
current_iteration = self.get_iteration()
url = "http://" + os.environ['INVENTORY'] + "/" + target + "/nsxt_mgmt_service/{}".format(current_iteration)
request = requests.get(url)
self.nsxt_mgmt_service = request.json() if request else {}
return self.nsxt_mgmt_service
def get_nsxt_transport_nodes(self, target):
self.wait_for_inventory_data()
current_iteration = self.get_iteration()
url = "http://" + os.environ['INVENTORY'] + "/" + target + "/nsxt_transport_nodes/{}".format(current_iteration)
request = requests.get(url)
self.nsxt_transport_nodes = request.json() if request else {}
return self.nsxt_transport_nodes
def get_nsxt_logical_switches(self, target):
self.wait_for_inventory_data()
current_iteration = self.get_iteration()
url = "http://" + os.environ['INVENTORY'] + "/" + target + "/nsxt_logical_switches/{}".format(current_iteration)
request = requests.get(url)
self.nsxt_logical_switches = request.json() if request else {}
return self.nsxt_logical_switches
def get_vcops_objects(self, target):
self.wait_for_inventory_data()
current_iteration = self.get_iteration()
url = "http://" + os.environ['INVENTORY'] + "/" + target + "/vcops_objects/{}".format(
current_iteration)
request = requests.get(url)
self.vcops_objects = request.json() if request else {}
return self.vcops_objects
def get_sddc_objects(self, target):
self.wait_for_inventory_data()
current_iteration = self.get_iteration()
url = "http://" + os.environ['INVENTORY'] + "/" + target + "/sddc_objects/{}".format(
current_iteration)
request = requests.get(url)
self.sddc_objects = request.json() if request else {}
return self.sddc_objects
def get_alertdefinition(self, alert_id):
request = requests.get(url="http://" + os.environ['INVENTORY'] + "/alertdefinitions/{}".format(alert_id))
self.alertdefinition = request.json() if request else {}
return self.alertdefinition
def get_iteration(self):
self.iteration = self.do_request(url="http://" + os.environ['INVENTORY'] + "/iteration")
return self.iteration
def get_amount_resources(self):
self.wait_for_inventory_data()
self.amount_resources = self.do_request(url="http://" + os.environ['INVENTORY'] + "/amount_resources")
return self.amount_resources
def get_collection_times(self):
self.wait_for_inventory_data()
self.collection_times = self.do_request(url="http://" + os.environ['INVENTORY'] + "/collection_times")
return self.collection_times
def get_inventory_api_responses(self):
self.wait_for_inventory_data()
self.api_responses = self.do_request(url="http://" + os.environ['INVENTORY'] + "/api_response_codes")
return self.api_responses
def get_target_tokens(self):
self.target_tokens = self.do_request(url="http://" + os.environ['INVENTORY'] + "/target_tokens")
return self.target_tokens
def get_vrops_list(self):
vrops_list = self.do_request(url="http://" + os.environ['INVENTORY'] + "/vrops_list")
return vrops_list
def do_request(self, url):
try:
request = requests.get(url, timeout=60)
response = request.json() if request else {}
return response
except (requests.exceptions.ConnectionError, requests.exceptions.ReadTimeout) as e:
logger.critical(f'Connection error to inventory: {os.environ["INVENTORY"]} - Error: {e}')
return {}
def get_vcenters_by_target(self):
vcenter_dict = self.get_vcenters(self.target)
self.target_vcenters = [vcenter_dict[uuid]['uuid'] for uuid in vcenter_dict]
return self.target_vcenters
def get_clusters_by_target(self):
cluster_dict = self.get_clusters(self.target)
self.target_clusters = [cluster_dict[uuid]['uuid'] for uuid in cluster_dict]
return self.target_clusters
def get_hosts_by_target(self):
host_dict = self.get_hosts(self.target)
self.target_hosts = [host_dict[uuid]['uuid'] for uuid in host_dict]
return self.target_hosts
def get_SDRS_clusters_by_target(self):
SDRS_clusters_dict = self.get_SDRS_cluster(self.target)
self.target_SDRS_clusters = [SDRS_clusters_dict[uuid]['uuid'] for uuid in SDRS_clusters_dict]
return self.target_SDRS_clusters
def get_datastores_by_target(self):
datastore_dict = self.get_datastores(self.target)
self.target_datastores = [datastore_dict[uuid]['uuid'] for uuid in datastore_dict]
return self.target_datastores
def get_vms_by_target(self):
vms_dict = self.get_vms(self.target)
self.target_vms = [vms_dict[uuid]['uuid'] for uuid in vms_dict]
return self.target_vms
def get_dvs_by_target(self):
dvs_dict = self.get_distributed_vswitches(self.target)
self.target_dvs = [dvs_dict[uuid]['uuid'] for uuid in dvs_dict]
return self.target_dvs
def get_nsxt_adapter_by_target(self):
nsxt_adapter_dict = self.get_nsxt_adapter(self.target)
self.target_nsxt_adapter = [nsxt_adapter_dict[uuid]['uuid'] for uuid in nsxt_adapter_dict]
return self.target_nsxt_adapter
def get_nsxt_mgmt_cluster_by_target(self):
nsxt_mgmt_cluster_dict = self.get_nsxt_mgmt_cluster(self.target)
self.target_nsxt_mgmt_cluster = [nsxt_mgmt_cluster_dict[uuid]['uuid'] for uuid in nsxt_mgmt_cluster_dict]
return self.target_nsxt_mgmt_cluster
def get_nsxt_mgmt_nodes_by_target(self):
nsxt_mgmt_nodes_dict = self.get_nsxt_mgmt_nodes(self.target)
self.target_nsxt_mgmt_nodes = [nsxt_mgmt_nodes_dict[uuid]['uuid'] for uuid in nsxt_mgmt_nodes_dict]
return self.target_nsxt_mgmt_nodes
def get_nsxt_mgmt_service_by_target(self):
nsxt_mgmt_service_dict = self.get_nsxt_mgmt_service(self.target)
self.target_nsxt_mgmt_service = [nsxt_mgmt_service_dict[uuid]['uuid'] for uuid in nsxt_mgmt_service_dict]
return self.target_nsxt_mgmt_service
def get_nsxt_transport_nodes_by_target(self):
nsxt_transport_nodes_dict = self.get_nsxt_transport_nodes(self.target)
self.target_nsxt_transport_nodes = [nsxt_transport_nodes_dict[uuid]['uuid'] for uuid in
nsxt_transport_nodes_dict]
return self.target_nsxt_transport_nodes
def get_nsxt_logical_switches_by_target(self):
nsxt_logical_switches_dict = self.get_nsxt_logical_switches(self.target)
self.target_nsxt_logical_switches = [nsxt_logical_switches_dict[uuid]['uuid'] for uuid in
nsxt_logical_switches_dict]
return self.target_nsxt_logical_switches
def get_vcops_objects_by_target(self):
vcops_objects_dict = self.get_vcops_objects(self.target)
self.target_vcops_objects = [vcops_objects_dict[uuid]['uuid'] for uuid in
vcops_objects_dict]
return self.target_vcops_objects
def get_sddc_objects_by_target(self):
sddc_objects_dict = self.get_sddc_objects(self.target)
self.target_sddc_objects = [sddc_objects_dict[uuid]['uuid'] for uuid in
sddc_objects_dict]
return self.target_sddc_objects
def get_project_ids_by_target(self):
try:
token = self.get_target_tokens()
token = token[self.target]
uuids = self.get_vms_by_target()
project_ids = Vrops.get_project_ids(self.target, token, uuids, self.name)
return project_ids
except requests.exceptions.ConnectionError as e:
logger.critical(f'No connection to inventory: {os.environ["INVENTORY"]} - Error: {e}')
return []
def wait_for_inventory_data(self):
iteration = self.get_iteration()
while not iteration:
time.sleep(5)
iteration = self.get_iteration()
logger.debug(f'Waiting for initial iteration: {self.name}')
return
def create_api_response_code_metric(self, collector: str, api_responding: int) -> GaugeMetricFamily:
gauge = GaugeMetricFamily('vrops_api_response', 'vrops-exporter', labels=['target', 'class'])
gauge.add_metric(labels=[self.target, collector.lower()], value=api_responding)
if api_responding > 200:
logger.critical(f'API response {api_responding} [{collector}, {self.target}], no return')
return gauge
return gauge
def create_api_response_time_metric(self, collector: str, response_time: float) -> GaugeMetricFamily:
gauge = GaugeMetricFamily('vrops_api_response_time_seconds', 'vrops-exporter',
labels=['target', 'class'])
gauge.add_metric(labels=[self.target, collector.lower()], value=response_time)
return gauge
def number_of_metric_samples_generated(self, collector: str, metric_name: str,
number_of_metric_samples_generated: int) -> GaugeMetricFamily:
gauge = GaugeMetricFamily('vrops_collector_metric_samples_generated_number', 'vrops-exporter',
labels=['target', 'class', 'metric_name'])
gauge.add_metric(labels=[self.target, collector.lower(), metric_name], value=number_of_metric_samples_generated)
return gauge
def number_of_metrics_to_collect(self, collector: str, number_of_metrics: int) -> GaugeMetricFamily:
gauge = GaugeMetricFamily('vrops_collector_metrics_number', 'vrops-exporter',
labels=['target', 'class'])
gauge.add_metric(labels=[self.target, collector.lower()], value=number_of_metrics)
return gauge
def number_of_resources(self, collector: str, number_of_resources: int) -> GaugeMetricFamily:
gauge = GaugeMetricFamily('vrops_collector_resources_number', 'vrops-exporter',
labels=['target', 'class'])
gauge.add_metric(labels=[self.target, collector.lower()], value=number_of_resources)
return gauge
def generate_metrics(self, label_names: list) -> dict:
collector_config = self.read_collector_config()
metrics = {m['key']: {'metric_suffix': m['metric_suffix'],
'key': m['key'],
'expected': m.setdefault('expected', None),
'gauge': GaugeMetricFamily(f'vrops_{self.vrops_entity_name}_{m["metric_suffix"].lower()}',
'vrops-exporter', labels=label_names)
} for m in collector_config.get(self.name, {})}
if not metrics:
logger.error(f'Cannot find {self.name} in collector_config')
return metrics
def generate_metrics_enriched_by_api(self, no_match_in_config: list, label_names: list) -> dict:
gauges = dict()
for statkey in no_match_in_config:
new_metric_suffix = re.sub("[^0-9a-zA-Z]+", "_", statkey[0])
value = statkey[1]
labels = statkey[2]
if new_metric_suffix not in gauges:
gauges[new_metric_suffix] = GaugeMetricFamily(
f'vrops_{self.vrops_entity_name}_{new_metric_suffix.lower()}', 'vrops-exporter', labels=label_names)
gauges[new_metric_suffix].add_metric(labels=labels, value=value)
return gauges
def generate_alert_metrics(self, label_names: list) -> InfoMetricFamily:
if 'alert_name' not in label_names:
label_names.extend(['alert_name', 'alert_level', 'status', 'alert_impact'])
alert_metric = InfoMetricFamily(f'vrops_{self.vrops_entity_name}_alert', 'vrops-exporter',
labels=label_names)
return alert_metric
def describe(self):
collector_config = self.read_collector_config()
for metric in collector_config[self.name]:
metric_suffix = metric['metric_suffix']
yield GaugeMetricFamily(f'vrops_{self.vrops_entity_name}_{metric_suffix.lower()}', 'vrops-exporter')