Coverage for server/models.py: 90%

73 statements  

« prev     ^ index     » next       coverage.py v7.17.0, created at 2026-10-24 19:06 +0000

1from django.db import models 

2from patchtime.models import Model as PatchtimeModel 

3from status.models import Model as StatusModel 

4from domain.models import Model as DomainModel 

5from location.models import Model as LocationModel 

6from operatingsystem.models import Model as OperatingsystemModel 

7from servermodel.models import Model as ServermodelModel 

8from cluster.models import Model as ClusterModel 

9from django.urls import reverse 

10from django.utils.timezone import now 

11from simple_history.models import HistoricalRecords 

12from django.contrib.auth.models import Group 

13from taggit.managers import TaggableManager 

14 

15from . import app_label 

16 

17 

18class ServerManager(models.Manager): 

19 def get_by_natural_key(self, hostname, status): 

20 if isinstance(status, (list, tuple)): 

21 status = status[0] 

22 return self.get(hostname=hostname, status__name=status) 

23 

24 

25class Model(models.Model): 

26 objects = ServerManager() 

27 hostname = models.CharField(max_length=45) 

28 domain = models.ForeignKey(DomainModel, on_delete=models.PROTECT, default=1) 

29 delivery_date = models.DateField(default=now) 

30 install_date = models.DateField(default=now) 

31 decommission_date = models.DateField(blank=True, null=True) 

32 last_update = models.DateTimeField(auto_now=True) 

33 documentation_url = models.URLField(max_length=2083, blank=True, null=True) 

34 memory_in_mb = models.IntegerField(blank=True, null=True) 

35 monitoring_from_puppet = models.BooleanField( 

36 default=False, verbose_name="Monitoring" 

37 ) 

38 location = models.ForeignKey( 

39 LocationModel, 

40 on_delete=models.PROTECT, 

41 null=True, 

42 related_name="%s_set" % app_label, 

43 related_query_name="%s" % app_label, 

44 ) 

45 operatingsystem = models.ForeignKey( 

46 OperatingsystemModel, 

47 on_delete=models.PROTECT, 

48 null=True, 

49 blank=True, 

50 related_name="%s_set" % app_label, 

51 related_query_name="%s" % app_label, 

52 ) 

53 

54 status = models.ForeignKey( 

55 StatusModel, 

56 on_delete=models.PROTECT, 

57 default=1, 

58 related_name="%s_set" % app_label, 

59 related_query_name="%s" % app_label, 

60 ) 

61 

62 servermodel = models.ForeignKey( 

63 ServermodelModel, 

64 on_delete=models.PROTECT, 

65 null=True, 

66 related_name="%s_set" % app_label, 

67 related_query_name="%s" % app_label, 

68 ) 

69 

70 cluster = models.ForeignKey( 

71 ClusterModel, 

72 on_delete=models.PROTECT, 

73 null=True, 

74 blank=True, 

75 related_name="%s_set" % app_label, 

76 related_query_name="%s" % app_label, 

77 ) 

78 

79 # => application model 

80 application = models.CharField(max_length=100, blank=True, null=True) 

81 

82 # => rack model 

83 rack = models.CharField(max_length=45, blank=True, null=True) 

84 

85 # network! 

86 primary_ip = models.GenericIPAddressField(blank=True, null=True) 

87 management_ip = models.GenericIPAddressField(blank=True, null=True) 

88 management_hostname = models.CharField(max_length=45, blank=True, null=True) 

89 delivery_note_id = models.CharField(max_length=45, blank=True, null=True) 

90 serial_nr = models.CharField(max_length=60, blank=True, null=True) 

91 description = models.CharField(max_length=100, blank=True, null=True) 

92 

93 patchtime = models.ForeignKey( 

94 PatchtimeModel, 

95 null=True, 

96 default=None, 

97 on_delete=models.PROTECT, 

98 related_name="%s_set" % app_label, 

99 related_query_name="%s" % app_label, 

100 ) 

101 

102 group = models.ForeignKey( 

103 Group, 

104 editable=False, 

105 blank=True, 

106 null=True, 

107 on_delete=models.PROTECT, 

108 related_name="servers", 

109 ) 

110 

111 tags = TaggableManager(blank=True, related_name="server_tags") 

112 

113 history = HistoricalRecords() 

114 

115 def __str__(self): 

116 return "%s" % self.hostname 

117 

118 @property 

119 def is_decommissioned(self) -> bool: 

120 return self.decommission_date is not None 

121 

122 @property 

123 def lifecycle_stage(self) -> str: 

124 """Human-readable lifecycle stage: ordered, active, decommissioned.""" 

125 if self.decommission_date is not None: 

126 return "decommissioned" 

127 if self.install_date and self.install_date > self.delivery_date: 

128 return "installed" 

129 return "ordered" 

130 

131 def natural_key(self): 

132 return (self.hostname,) + self.status.natural_key() 

133 

134 natural_key.dependencies = ["status.Model"] 

135 

136 @classmethod 

137 def get_natural_key_fields(cls): 

138 return ["hostname", "status__name"] 

139 

140 @classmethod 

141 def get_natural_key_info(cls): 

142 return [("hostname", None), ("status", StatusModel)] 

143 

144 def get_absolute_url(self): 

145 return reverse("server:detail", kwargs={"pk": self.pk}) 

146 

147 class Meta: 

148 db_table = "{}_{}".format("sm", app_label) 

149 constraints = [ 

150 models.UniqueConstraint( 

151 fields=["hostname", "status", "group"], 

152 name="unique_sm_server_hostname_status_group", 

153 ), 

154 ]