|
1 | 1 | """Produce Prometheus-formatted statistics about devices."""
|
| 2 | +import sys |
2 | 3 |
|
3 | 4 | from collections import Counter
|
| 5 | +from datetime import timedelta |
| 6 | +from pathlib import Path |
4 | 7 | from io import StringIO
|
5 | 8 |
|
| 9 | +from django.contrib.contenttypes.models import ContentType |
| 10 | +from django.utils import timezone |
| 11 | + |
6 | 12 | from dcim.models import Device
|
7 | 13 |
|
| 14 | +from extras import models |
| 15 | +from extras.choices import JobResultStatusChoices |
8 | 16 | from extras.scripts import Script
|
9 | 17 |
|
10 | 18 |
|
| 19 | +def get_module(module): |
| 20 | + """Get the module of this file handling the use case if its called as a script |
| 21 | +
|
| 22 | + Arguments |
| 23 | + module: the value of __module__ |
| 24 | +
|
| 25 | + Returns: |
| 26 | + A string representing the module |
| 27 | + """ |
| 28 | + if module != '__main__': |
| 29 | + return module |
| 30 | + return Path(sys.modules[module].__file__).stem |
| 31 | + |
| 32 | + |
11 | 33 | class GetDeviceStats(Script):
|
| 34 | + """Get device statistics""" |
| 35 | + |
12 | 36 | class Meta:
|
| 37 | + """Metadata""" |
13 | 38 | name = "Get Device Statistics"
|
14 | 39 | description = "Dump a set of statistics about various devices for Prometheus."
|
15 | 40 |
|
16 | 41 | def run(self, data, commit):
|
| 42 | + """The run method""" |
| 43 | + # Delete old versions of this report |
| 44 | + obj_type = ContentType.objects.get_for_model(models.Script) |
| 45 | + name = ".".join((get_module(self.__module__), self.__class__.__name__)) |
| 46 | + # Keep any reports from the last 5 minutes to make this less racy |
| 47 | + cutoff = timezone.now() - timedelta(minutes=5) |
| 48 | + jobs = models.JobResult.objects.filter( |
| 49 | + obj_type=obj_type, |
| 50 | + name=name, |
| 51 | + status__in=JobResultStatusChoices.TERMINAL_STATE_CHOICES, |
| 52 | + created__lt=cutoff, |
| 53 | + ) |
| 54 | + # Make sure we call delete on each job to trigger any customized delete methods |
| 55 | + for job in jobs: |
| 56 | + job.delete() |
17 | 57 | counts = Counter()
|
18 | 58 | output = StringIO()
|
19 | 59 | for device in Device.objects.all().values_list(
|
|
0 commit comments