• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

sapcc / vrops-exporter / 10267240180

06 Aug 2024 01:12PM UTC coverage: 71.476% (-2.3%) from 73.73%
10267240180

push

github

viennaa
Update dependency itsdangerous to v2.2.0

1521 of 2128 relevant lines covered (71.48%)

0.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

65.81
/BaseCollector.py
1
from abc import ABC, abstractmethod
1✔
2
import requests
1✔
3
import time
1✔
4
import os
1✔
5
import re
1✔
6
import logging
1✔
7
from tools.helper import yaml_read
1✔
8
from tools.Vrops import Vrops
1✔
9
from prometheus_client.core import GaugeMetricFamily, InfoMetricFamily
1✔
10

11
logger = logging.getLogger('vrops-exporter')
1✔
12

13

14
class BaseCollector(ABC):
1✔
15

16
    def __init__(self):
1✔
17
        self.vrops_entity_name = 'base'
1✔
18
        while os.environ['TARGET'] not in self.get_vrops_target():
1✔
19
            logger.critical(f'Cannot start exporter. Missing inventory pod for {os.environ["TARGET"]}, retry in 60s')
×
20
            time.sleep(60)
×
21
        self.target = os.environ.get('TARGET')
1✔
22
        self.vrops = Vrops()
1✔
23
        self.name = self.__class__.__name__
1✔
24
        self.label_names = []
1✔
25
        self.project_ids = []
1✔
26
        self.collect_running = False
1✔
27
        self.nested_value_metric_keys = []
1✔
28

29
    @abstractmethod
1✔
30
    def collect(self):
1✔
31
        pass
×
32

33
    def read_collector_config(self):
1✔
34
        config_file = yaml_read(os.environ['COLLECTOR_CONFIG'])
1✔
35
        return config_file
1✔
36

37
    def get_vcenters(self, target):
1✔
38
        self.wait_for_inventory_data()
1✔
39
        current_iteration = self.get_iteration()
1✔
40
        url = "http://" + os.environ['INVENTORY'] + "/" + target + "/vcenters/{}".format(current_iteration)
1✔
41
        request = requests.get(url)
1✔
42
        self.vcenters = request.json() if request else {}
1✔
43
        return self.vcenters
1✔
44

45
    def get_datacenters(self, target):
1✔
46
        self.wait_for_inventory_data()
×
47
        current_iteration = self.get_iteration()
×
48
        url = "http://" + os.environ['INVENTORY'] + "/" + target + "/datacenters/{}".format(current_iteration)
×
49
        request = requests.get(url)
×
50
        self.datacenters = request.json() if request else {}
×
51
        return self.datacenters
×
52

53
    def get_clusters(self, target):
1✔
54
        self.wait_for_inventory_data()
1✔
55
        current_iteration = self.get_iteration()
1✔
56
        url = "http://" + os.environ['INVENTORY'] + "/" + target + "/clusters/{}".format(current_iteration)
1✔
57
        request = requests.get(url)
1✔
58
        self.clusters = request.json() if request else {}
1✔
59
        return self.clusters
1✔
60

61
    def get_hosts(self, target):
1✔
62
        self.wait_for_inventory_data()
1✔
63
        current_iteration = self.get_iteration()
1✔
64
        url = "http://" + os.environ['INVENTORY'] + "/" + target + "/hosts/{}".format(current_iteration)
1✔
65
        request = requests.get(url)
1✔
66
        self.hosts = request.json() if request else {}
1✔
67
        return self.hosts
1✔
68

69
    def get_SDRS_cluster(self, target):
1✔
70
        self.wait_for_inventory_data()
1✔
71
        current_iteration = self.get_iteration()
1✔
72
        url = "http://" + os.environ['INVENTORY'] + "/" + target + "/storagepod/{}".format(current_iteration)
1✔
73
        request = requests.get(url)
1✔
74
        self.sdrs_clusters = request.json() if request else {}
1✔
75
        return self.sdrs_clusters
1✔
76

77
    def get_datastores(self, target):
1✔
78
        self.wait_for_inventory_data()
1✔
79
        current_iteration = self.get_iteration()
1✔
80
        url = "http://" + os.environ['INVENTORY'] + "/" + target + "/datastores/{}".format(current_iteration)
1✔
81
        request = requests.get(url)
1✔
82
        self.datastores = request.json() if request else {}
1✔
83
        return self.datastores
1✔
84

85
    def get_vms(self, target):
1✔
86
        self.wait_for_inventory_data()
1✔
87
        current_iteration = self.get_iteration()
1✔
88
        url = "http://" + os.environ['INVENTORY'] + "/" + target + "/vms/{}".format(current_iteration)
1✔
89
        request = requests.get(url)
1✔
90
        self.vms = request.json() if request else {}
1✔
91
        return self.vms
1✔
92

93
    def get_distributed_vswitches(self, target):
1✔
94
        self.wait_for_inventory_data()
×
95
        current_iteration = self.get_iteration()
×
96
        url = "http://" + os.environ['INVENTORY'] + "/" + target + "/dvs/{}".format(current_iteration)
×
97
        request = requests.get(url)
×
98
        self.dvs = request.json() if request else {}
×
99
        return self.dvs
×
100

101
    def get_nsxt_adapter(self, target):
1✔
102
        self.wait_for_inventory_data()
×
103
        current_iteration = self.get_iteration()
×
104
        url = "http://" + os.environ['INVENTORY'] + "/" + target + "/nsxt_adapter/{}".format(current_iteration)
×
105
        request = requests.get(url)
×
106
        self.nsxt_adapter = request.json() if request else {}
×
107
        return self.nsxt_adapter
×
108

109
    def get_nsxt_mgmt_cluster(self, target):
1✔
110
        self.wait_for_inventory_data()
1✔
111
        current_iteration = self.get_iteration()
1✔
112
        url = "http://" + os.environ['INVENTORY'] + "/" + target + "/nsxt_mgmt_cluster/{}".format(current_iteration)
1✔
113
        request = requests.get(url)
1✔
114
        self.nsxt_mgmt_cluster = request.json() if request else {}
1✔
115
        return self.nsxt_mgmt_cluster
1✔
116

117
    def get_nsxt_mgmt_nodes(self, target):
1✔
118
        self.wait_for_inventory_data()
1✔
119
        current_iteration = self.get_iteration()
1✔
120
        url = "http://" + os.environ['INVENTORY'] + "/" + target + "/nsxt_mgmt_nodes/{}".format(current_iteration)
1✔
121
        request = requests.get(url)
1✔
122
        self.nsxt_mgmt_nodes = request.json() if request else {}
1✔
123
        return self.nsxt_mgmt_nodes
1✔
124

125
    def get_nsxt_mgmt_service(self, target):
1✔
126
        self.wait_for_inventory_data()
×
127
        current_iteration = self.get_iteration()
×
128
        url = "http://" + os.environ['INVENTORY'] + "/" + target + "/nsxt_mgmt_service/{}".format(current_iteration)
×
129
        request = requests.get(url)
×
130
        self.nsxt_mgmt_service = request.json() if request else {}
×
131
        return self.nsxt_mgmt_service
×
132

133
    def get_nsxt_transport_nodes(self, target):
1✔
134
        self.wait_for_inventory_data()
×
135
        current_iteration = self.get_iteration()
×
136
        url = "http://" + os.environ['INVENTORY'] + "/" + target + "/nsxt_transport_nodes/{}".format(current_iteration)
×
137
        request = requests.get(url)
×
138
        self.nsxt_transport_nodes = request.json() if request else {}
×
139
        return self.nsxt_transport_nodes
×
140

141
    def get_nsxt_logical_switches(self, target):
1✔
142
        self.wait_for_inventory_data()
×
143
        current_iteration = self.get_iteration()
×
144
        url = "http://" + os.environ['INVENTORY'] + "/" + target + "/nsxt_logical_switches/{}".format(current_iteration)
×
145
        request = requests.get(url)
×
146
        self.nsxt_logical_switches = request.json() if request else {}
×
147
        return self.nsxt_logical_switches
×
148

149
    def get_vcops_objects(self, target):
1✔
150
        self.wait_for_inventory_data()
×
151
        current_iteration = self.get_iteration()
×
152
        url = "http://" + os.environ['INVENTORY'] + "/" + target + "/vcops_objects/{}".format(
×
153
            current_iteration)
154
        request = requests.get(url)
×
155
        self.vcops_objects = request.json() if request else {}
×
156
        return self.vcops_objects
×
157

158
    def get_sddc_objects(self, target):
1✔
159
        self.wait_for_inventory_data()
×
160
        current_iteration = self.get_iteration()
×
161
        url = "http://" + os.environ['INVENTORY'] + "/" + target + "/sddc_objects/{}".format(
×
162
            current_iteration)
163
        request = requests.get(url)
×
164
        self.sddc_objects = request.json() if request else {}
×
165
        return self.sddc_objects
×
166

167
    def get_alertdefinition(self, alert_id):
1✔
168
        request = requests.get(url="http://" + os.environ['INVENTORY'] + "/alertdefinitions/{}".format(alert_id))
×
169
        self.alertdefinition = request.json() if request else {}
×
170
        return self.alertdefinition
×
171

172
    def get_iteration(self):
1✔
173
        self.iteration = self.do_request(url="http://" + os.environ['INVENTORY'] + "/iteration")
1✔
174
        return self.iteration
1✔
175

176
    def get_amount_resources(self):
1✔
177
        self.wait_for_inventory_data()
×
178
        self.amount_resources = self.do_request(url="http://" + os.environ['INVENTORY'] + "/amount_resources")
×
179
        return self.amount_resources
×
180

181
    def get_collection_times(self):
1✔
182
        self.wait_for_inventory_data()
×
183
        self.collection_times = self.do_request(url="http://" + os.environ['INVENTORY'] + "/collection_times")
×
184
        return self.collection_times
×
185

186
    def get_inventory_api_responses(self):
1✔
187
        self.wait_for_inventory_data()
×
188
        self.api_responses = self.do_request(url="http://" + os.environ['INVENTORY'] + "/api_response_codes")
×
189
        self.api_reponse_times = self.do_request(url="http://" + os.environ['INVENTORY'] + "/api_response_times")
×
190
        return self.api_responses, self.api_reponse_times
×
191

192
    def get_service_states(self):
1✔
193
        self.wait_for_inventory_data()
×
194
        self.service_states = self.do_request(url="http://" + os.environ['INVENTORY'] + "/service_states")
×
195
        return self.service_states
×
196

197
    def get_target_tokens(self):
1✔
198
        self.target_tokens = self.do_request(url="http://" + os.environ['INVENTORY'] + "/target_tokens")
×
199
        return self.target_tokens
×
200

201
    def get_vrops_target(self):
1✔
202
        vrops_target = self.do_request(url="http://" + os.environ['INVENTORY'] + "/target")
1✔
203
        return vrops_target
1✔
204

205
    def do_request(self, url):
1✔
206
        try:
1✔
207
            request = requests.get(url, timeout=60)
1✔
208
            response = request.json() if request else {}
1✔
209
            return response
1✔
210
        except (requests.exceptions.ConnectionError, requests.exceptions.ReadTimeout) as e:
×
211
            logger.critical(f'Connection error to inventory: {os.environ["INVENTORY"]} - Error: {e}')
×
212
            return {}
×
213

214
    def get_vcenters_by_target(self):
1✔
215
        vcenter_dict = self.get_vcenters(self.target)
1✔
216
        self.target_vcenters = [vcenter_dict[uuid]['uuid'] for uuid in vcenter_dict]
1✔
217
        return self.target_vcenters
1✔
218

219
    def get_clusters_by_target(self):
1✔
220
        cluster_dict = self.get_clusters(self.target)
1✔
221
        self.target_clusters = [cluster_dict[uuid]['uuid'] for uuid in cluster_dict]
1✔
222
        return self.target_clusters
1✔
223

224
    def get_hosts_by_target(self):
1✔
225
        host_dict = self.get_hosts(self.target)
1✔
226
        self.target_hosts = [host_dict[uuid]['uuid'] for uuid in host_dict]
1✔
227
        return self.target_hosts
1✔
228

229
    def get_SDRS_clusters_by_target(self):
1✔
230
        SDRS_clusters_dict = self.get_SDRS_cluster(self.target)
1✔
231
        self.target_SDRS_clusters = [SDRS_clusters_dict[uuid]['uuid'] for uuid in SDRS_clusters_dict]
1✔
232
        return self.target_SDRS_clusters
1✔
233

234
    def get_datastores_by_target(self):
1✔
235
        datastore_dict = self.get_datastores(self.target)
1✔
236
        self.target_datastores = [datastore_dict[uuid]['uuid'] for uuid in datastore_dict]
1✔
237
        return self.target_datastores
1✔
238

239
    def get_vms_by_target(self):
1✔
240
        vms_dict = self.get_vms(self.target)
1✔
241
        self.target_vms = [vms_dict[uuid]['uuid'] for uuid in vms_dict]
1✔
242
        return self.target_vms
1✔
243

244
    def get_dvs_by_target(self):
1✔
245
        dvs_dict = self.get_distributed_vswitches(self.target)
×
246
        self.target_dvs = [dvs_dict[uuid]['uuid'] for uuid in dvs_dict]
×
247
        return self.target_dvs
×
248

249
    def get_nsxt_adapter_by_target(self):
1✔
250
        nsxt_adapter_dict = self.get_nsxt_adapter(self.target)
×
251
        self.target_nsxt_adapter = [nsxt_adapter_dict[uuid]['uuid'] for uuid in nsxt_adapter_dict]
×
252
        return self.target_nsxt_adapter
×
253

254
    def get_nsxt_mgmt_cluster_by_target(self):
1✔
255
        nsxt_mgmt_cluster_dict = self.get_nsxt_mgmt_cluster(self.target)
1✔
256
        self.target_nsxt_mgmt_cluster = [nsxt_mgmt_cluster_dict[uuid]['uuid'] for uuid in nsxt_mgmt_cluster_dict]
1✔
257
        return self.target_nsxt_mgmt_cluster
1✔
258

259
    def get_nsxt_mgmt_nodes_by_target(self):
1✔
260
        nsxt_mgmt_nodes_dict = self.get_nsxt_mgmt_nodes(self.target)
1✔
261
        self.target_nsxt_mgmt_nodes = [nsxt_mgmt_nodes_dict[uuid]['uuid'] for uuid in nsxt_mgmt_nodes_dict]
1✔
262
        return self.target_nsxt_mgmt_nodes
1✔
263

264
    def get_nsxt_mgmt_service_by_target(self):
1✔
265
        nsxt_mgmt_service_dict = self.get_nsxt_mgmt_service(self.target)
×
266
        self.target_nsxt_mgmt_service = [nsxt_mgmt_service_dict[uuid]['uuid'] for uuid in nsxt_mgmt_service_dict]
×
267
        return self.target_nsxt_mgmt_service
×
268

269
    def get_nsxt_transport_nodes_by_target(self):
1✔
270
        nsxt_transport_nodes_dict = self.get_nsxt_transport_nodes(self.target)
×
271
        self.target_nsxt_transport_nodes = [nsxt_transport_nodes_dict[uuid]['uuid'] for uuid in
×
272
                                            nsxt_transport_nodes_dict]
273
        return self.target_nsxt_transport_nodes
×
274

275
    def get_nsxt_logical_switches_by_target(self):
1✔
276
        nsxt_logical_switches_dict = self.get_nsxt_logical_switches(self.target)
×
277
        self.target_nsxt_logical_switches = [nsxt_logical_switches_dict[uuid]['uuid'] for uuid in
×
278
                                             nsxt_logical_switches_dict]
279
        return self.target_nsxt_logical_switches
×
280

281
    def get_vcops_objects_by_target(self):
1✔
282
        vcops_objects_dict = self.get_vcops_objects(self.target)
×
283
        self.target_vcops_objects = [vcops_objects_dict[uuid]['uuid'] for uuid in
×
284
                                     vcops_objects_dict]
285
        return self.target_vcops_objects
×
286

287
    def get_sddc_objects_by_target(self):
1✔
288
        sddc_objects_dict = self.get_sddc_objects(self.target)
×
289
        self.target_sddc_objects = [sddc_objects_dict[uuid]['uuid'] for uuid in
×
290
                                    sddc_objects_dict]
291
        return self.target_sddc_objects
×
292

293
    def get_project_ids_by_target(self):
1✔
294
        try:
1✔
295
            token = self.get_target_tokens()
1✔
296
            token = token[self.target]
1✔
297
            uuids = self.get_vms_by_target()
1✔
298
            project_ids = Vrops.get_project_ids(self.target, token, uuids, self.name)
1✔
299
            return project_ids
1✔
300
        except requests.exceptions.ConnectionError as e:
×
301
            logger.critical(f'No connection to inventory: {os.environ["INVENTORY"]} - Error: {e}')
×
302
            return []
×
303

304
    def wait_for_inventory_data(self):
1✔
305
        iteration = self.get_iteration()
1✔
306
        while not iteration:
1✔
307
            time.sleep(5)
×
308
            iteration = self.get_iteration()
×
309
            logger.debug(f'Waiting for initial iteration: {self.name}')
×
310
        return
1✔
311

312
    def create_api_response_code_metric(self, collector: str, api_responding: int) -> GaugeMetricFamily:
1✔
313
        gauge = GaugeMetricFamily('vrops_api_response', 'vrops-exporter', labels=['target', 'class'])
1✔
314
        gauge.add_metric(labels=[self.target, collector.lower()], value=api_responding)
1✔
315

316
        if api_responding > 200:
1✔
317
            logger.critical(f'API response {api_responding} [{collector}, {self.target}], no return')
×
318
            return gauge
×
319
        return gauge
1✔
320

321
    def create_api_response_time_metric(self, collector: str, response_time: float) -> GaugeMetricFamily:
1✔
322
        gauge = GaugeMetricFamily('vrops_api_response_time_seconds', 'vrops-exporter',
1✔
323
                                  labels=['target', 'class'])
324
        gauge.add_metric(labels=[self.target, collector.lower()], value=response_time)
1✔
325
        return gauge
1✔
326

327
    def number_of_metric_samples_generated(self, collector: str, metric_name: str,
1✔
328
                                           number_of_metric_samples_generated: int) -> GaugeMetricFamily:
329
        gauge = GaugeMetricFamily('vrops_collector_metric_samples_generated_number', 'vrops-exporter',
1✔
330
                                  labels=['target', 'class', 'metric_name'])
331
        gauge.add_metric(labels=[self.target, collector.lower(), metric_name], value=number_of_metric_samples_generated)
1✔
332
        return gauge
1✔
333

334
    def number_of_metrics_to_collect(self, collector: str, number_of_metrics: int) -> GaugeMetricFamily:
1✔
335
        gauge = GaugeMetricFamily('vrops_collector_metrics_number', 'vrops-exporter',
1✔
336
                                  labels=['target', 'class'])
337
        gauge.add_metric(labels=[self.target, collector.lower()], value=number_of_metrics)
1✔
338
        return gauge
1✔
339

340
    def number_of_resources(self, collector: str, number_of_resources: int) -> GaugeMetricFamily:
1✔
341
        gauge = GaugeMetricFamily('vrops_collector_resources_number', 'vrops-exporter',
1✔
342
                                  labels=['target', 'class'])
343
        gauge.add_metric(labels=[self.target, collector.lower()], value=number_of_resources)
1✔
344
        return gauge
1✔
345

346
    def generate_metrics(self, label_names: list) -> dict:
1✔
347
        collector_config = self.read_collector_config()
1✔
348
        metrics = {m['key']: {'metric_suffix': m['metric_suffix'],
1✔
349
                              'key': m['key'],
350
                              'expected': m.setdefault('expected', None),
351
                              'gauge': GaugeMetricFamily(f'vrops_{self.vrops_entity_name}_{m["metric_suffix"].lower()}',
352
                                                         'vrops-exporter', labels=label_names)
353
                              } for m in collector_config.get(self.name, {})}
354
        if not metrics:
1✔
355
            logger.error(f'Cannot find {self.name} in collector_config')
×
356
        return metrics
1✔
357

358
    def generate_metrics_enriched_by_api(self, no_match_in_config: list, label_names: list) -> dict:
1✔
359
        gauges = dict()
1✔
360
        for statkey in no_match_in_config:
1✔
361
            new_metric_suffix = re.sub("[^0-9a-zA-Z]+", "_", statkey[0])
1✔
362
            value = statkey[1]
1✔
363
            labels = statkey[2]
1✔
364
            if new_metric_suffix not in gauges:
1✔
365
                gauges[new_metric_suffix] = GaugeMetricFamily(
1✔
366
                    f'vrops_{self.vrops_entity_name}_{new_metric_suffix.lower()}', 'vrops-exporter', labels=label_names)
367
            gauges[new_metric_suffix].add_metric(labels=labels, value=value)
1✔
368
        return gauges
1✔
369

370
    def generate_alert_metrics(self, label_names: list) -> InfoMetricFamily:
1✔
371
        if 'alert_name' not in label_names:
×
372
            label_names.extend(['alert_name', 'alert_level', 'status', 'alert_impact'])
×
373
        alert_metric = InfoMetricFamily(f'vrops_{self.vrops_entity_name}_alert', 'vrops-exporter',
×
374
                                        labels=label_names)
375
        return alert_metric
×
376

377
    def add_metric_labels(self, metric_object: GaugeMetricFamily, labels):
1✔
378
        if labels[0] not in metric_object._labelnames:
1✔
379
            for label in labels:
1✔
380
                metric_object._labelnames += (label,)
1✔
381
        return
1✔
382

383
    def describe(self):
1✔
384
        collector_config = self.read_collector_config()
1✔
385
        for metric in collector_config[self.name]:
1✔
386
            metric_suffix = metric['metric_suffix']
1✔
387
            yield GaugeMetricFamily(f'vrops_{self.vrops_entity_name}_{metric_suffix.lower()}', 'vrops-exporter')
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc