Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from django.db import models
2from django.core.validators import RegexValidator, MinValueValidator, MaxValueValidator
3from django.utils.functional import cached_property
4from django.utils import timezone
5from django.conf import settings
8class PDU(models.Model):
9 name = models.CharField(unique=True, help_text="Name of the PDU", max_length=80)
11 pdu_model = models.CharField(max_length=80, help_text="Model of the PDU you are using")
12 config = models.JSONField(blank=True, default=dict,
13 help_text="Opaque configuration needed to instanciate the PDU")
15 def __str__(self):
16 return f"<PDU: {self.name}>"
19class Machine(models.Model):
20 # Naming and tagging
21 base_name = models.CharField(max_length=50,
22 help_text="Non-unique name that will form the basis for the full name")
23 tags = models.JSONField(blank=True, null=True, default=list,
24 help_text="List of tags that the machine has")
26 # Network
27 mac_address = \
28 models.CharField(max_length=17, unique=True, blank=False, null=False,
29 validators=[
30 RegexValidator(
31 regex='^([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})$', code='invalid_format',
32 message='Format: 60:6d:3c:51:c4:88',
33 )])
34 ip_address = models.GenericIPAddressField(blank=False, null=False)
36 local_tty_device = \
37 models.CharField(max_length=16, blank=True, null=True,
38 help_text=("Machine-local TTY device that can be used as a serial console. "
39 "See the `console=` format at "
40 "https://www.kernel.org/doc/html/latest/admin-guide/serial-console.html"))
42 # PDU
43 pdu = models.ForeignKey(PDU, null=True, blank=True, on_delete=models.SET_NULL,
44 help_text="PDU to which this machine is connected to")
45 pdu_port_id = models.CharField(max_length=80, blank=True, null=True,
46 help_text="ID of the port to which this machine is connected to")
47 pdu_off_delay = models.PositiveSmallIntegerField(default=5,
48 validators=[
49 MaxValueValidator(100),
50 MinValueValidator(1)
51 ],
52 help_text="Number of seconds to wait in a ON->OFF->ON transition")
54 # Flags
55 ready_for_service = models.BooleanField(blank=False, null=False, default=False,
56 help_text="Is the machine fit for service?")
57 is_retired = models.BooleanField(blank=False, null=False, default=False,
58 help_text="Has the machine been retired?")
60 # Some statistics
61 first_seen = models.DateTimeField(auto_now_add=True,
62 help_text='When this MAC address was first seen')
63 last_updated = models.DateTimeField(auto_now=True,
64 help_text='When this machine was last modified')
66 class Meta:
67 ordering = ['-id']
69 @cached_property
70 def full_name(self):
71 if self.pk is None:
72 raise ValueError("The Machine needs to be saved before a name can be generated")
74 idx = Machine.objects.filter(base_name=self.base_name, id__lte=self.id).count()
75 return f"{settings.FARM_NAME}-{self.base_name}-{idx}"
77 def __str__(self):
78 return f"<Machine: {self.full_name}>"
81class Event(models.Model):
82 machine = models.ForeignKey(
83 Machine,
84 on_delete=models.CASCADE,
85 help_text='The machine this event originated from.')
87 CATEGORY_MACHINE_CREATED = 'machine-created'
88 CATEGORY_MACHINE_UPDATED = 'machine-updated'
89 CATEGORY_MACHINE_RETIRED = 'machine-retired'
91 CATEGORY_CHOICES = (
92 (CATEGORY_MACHINE_CREATED, 'Machine has been created'),
93 (CATEGORY_MACHINE_UPDATED, 'Machine has been updated'),
94 (CATEGORY_MACHINE_RETIRED, 'Machine has been retired'),
95 )
97 category = models.CharField(
98 max_length=25,
99 choices=CATEGORY_CHOICES,
100 help_text='The category of the event.')
101 date = models.DateTimeField(
102 default=timezone.now,
103 help_text='The time this event was created.')
105 diff = models.JSONField(blank=True, null=True,
106 help_text="Dictionary of differences before and after the machine changed")
108 def __str__(self):
109 return f"<Event id={self.id} machine={self.machine} category={self.category}>"
111 class Meta:
112 ordering = ['-date']