blob: 7e33865c016e5ef861de51c6af79515109506b78 [file] [log] [blame]
Dirk Vogtc9e10ab2016-10-12 13:58:15 +02001# -*- coding: utf-8 -*-
Mitja Nikolaus6a679132018-08-30 14:35:29 +02002"""Models for devices, heartbeats, crashreports and log files."""
3
Mitja Nikolausbcaf5022018-08-30 16:40:38 +02004import uuid
Dirk Vogtc9e10ab2016-10-12 13:58:15 +02005
Mitja Nikolausbcaf5022018-08-30 16:40:38 +02006from django.db import models, transaction
Dirk Vogtf2a33422016-10-11 17:17:26 +02007from django.contrib.auth.models import User
8from taggit.managers import TaggableManager
Dirk Vogtc9e10ab2016-10-12 13:58:15 +02009
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020010
Dirk Vogtf2a33422016-10-11 17:17:26 +020011class Device(models.Model):
Mitja Nikolaus6a679132018-08-30 14:35:29 +020012 """A device representing a phone that has been registered on Hiccup."""
13
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020014 def __str__(self):
Mitja Nikolaus6a679132018-08-30 14:35:29 +020015 """Return the UUID as string representation of a device."""
Dirk Vogt83107df2017-05-02 12:04:19 +020016 return self.uuid
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020017
Dirk Vogtf2a33422016-10-11 17:17:26 +020018 # for every device there is a django user
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020019 uuid = models.CharField(
20 db_index=True,
21 max_length=64,
22 unique=True,
23 default=uuid.uuid4,
24 editable=False,
25 )
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020026 user = models.OneToOneField(
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020027 User,
28 related_name="Hiccup_Device",
29 on_delete=models.CASCADE,
30 unique=True,
31 )
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020032 imei = models.CharField(max_length=32, null=True, blank=True)
33 board_date = models.DateTimeField(null=True, blank=True)
34 chipset = models.CharField(max_length=200, null=True, blank=True)
35 tags = TaggableManager(blank=True)
Dirk Vogtf2a33422016-10-11 17:17:26 +020036 last_heartbeat = models.DateTimeField(null=True, blank=True)
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020037 token = models.CharField(max_length=200, null=True, blank=True)
Dirk Vogt67eb1482016-10-13 12:42:56 +020038 next_per_crashreport_key = models.PositiveIntegerField(default=1)
39 next_per_heartbeat_key = models.PositiveIntegerField(default=1)
40
41 @transaction.atomic
42 def get_crashreport_key(self):
Mitja Nikolaus6a679132018-08-30 14:35:29 +020043 """Get the next key for a crashreport and update the ID-counter."""
Dirk Vogt67eb1482016-10-13 12:42:56 +020044 ret = self.next_per_crashreport_key
45 self.next_per_crashreport_key = self.next_per_crashreport_key + 1
46 self.save()
47 return ret
48
49 @transaction.atomic
50 def get_heartbeat_key(self):
Mitja Nikolaus6a679132018-08-30 14:35:29 +020051 """Get the next key for a heartbeat and update the ID-counter."""
Dirk Vogt67eb1482016-10-13 12:42:56 +020052 ret = self.next_per_heartbeat_key
Dirk Vogt0d9d5d22016-10-13 16:17:57 +020053 self.next_per_heartbeat_key = self.next_per_heartbeat_key + 1
Dirk Vogt67eb1482016-10-13 12:42:56 +020054 self.save()
55 return ret
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020056
Dirk Vogtf130c752016-08-23 14:45:01 +020057
58def crashreport_file_name(instance, filename):
Mitja Nikolaus6a679132018-08-30 14:35:29 +020059 """Generate the full path for new uploaded log files.
60
61 Args:
62 instance: The log file instance.
63 filename: The name of the actual log file.
64
65 Returns: The generated path including the file name.
66
67 """
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020068 return "/".join(
69 [
70 "crashreport_uploads",
71 instance.crashreport.device.uuid,
72 str(instance.crashreport.id),
73 str(instance.crashreport.date),
74 filename,
75 ]
76 )
Dirk Vogtf130c752016-08-23 14:45:01 +020077
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020078
Dirk Vogtf130c752016-08-23 14:45:01 +020079class Crashreport(models.Model):
Mitja Nikolaus6a679132018-08-30 14:35:29 +020080 """A crashreport that was sent by a device."""
81
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020082 BOOT_REASON_UNKOWN = "UNKNOWN"
83 BOOT_REASON_KEYBOARD_POWER_ON = "keyboard power on"
84 BOOT_REASON_RTC_ALARM = "RTC alarm"
85 CRASH_BOOT_REASONS = [BOOT_REASON_UNKOWN, BOOT_REASON_KEYBOARD_POWER_ON]
86 SMPL_BOOT_REASONS = [BOOT_REASON_RTC_ALARM]
Franz-Xaver Geiger0b3a48e2018-04-16 15:00:14 +020087
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020088 device = models.ForeignKey(
89 Device,
90 db_index=True,
91 related_name="crashreports",
92 on_delete=models.CASCADE,
93 )
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020094 is_fake_report = models.BooleanField(default=False)
95 app_version = models.IntegerField()
96 uptime = models.CharField(max_length=200)
Dirk Vogt83107df2017-05-02 12:04:19 +020097 build_fingerprint = models.CharField(db_index=True, max_length=200)
Borjan Tchakaloff6f239a62018-02-19 09:05:50 +010098 radio_version = models.CharField(db_index=True, max_length=200, null=True)
Dirk Vogt83107df2017-05-02 12:04:19 +020099 boot_reason = models.CharField(db_index=True, max_length=200)
100 power_on_reason = models.CharField(db_index=True, max_length=200)
101 power_off_reason = models.CharField(db_index=True, max_length=200)
102 date = models.DateTimeField(db_index=True)
Dirk Vogtf2a33422016-10-11 17:17:26 +0200103 tags = TaggableManager(blank=True)
Dirk Vogt67eb1482016-10-13 12:42:56 +0200104 device_local_id = models.PositiveIntegerField(blank=True)
Dirk Vogt36635692016-10-17 12:19:10 +0200105 next_logfile_key = models.PositiveIntegerField(default=1)
Dirk Vogteda80d32016-11-21 11:45:50 +0100106 created_at = models.DateTimeField(auto_now_add=True)
Dirk Vogt67eb1482016-10-13 12:42:56 +0200107
108 @transaction.atomic
109 def get_logfile_key(self):
Mitja Nikolaus6a679132018-08-30 14:35:29 +0200110 """Get the next key for a log file and update the ID-counter."""
Dirk Vogt67eb1482016-10-13 12:42:56 +0200111 ret = self.next_logfile_key
112 self.next_logfile_key = self.next_logfile_key + 1
113 self.save()
114 return ret
115
116 def save(self, *args, **kwargs):
Mitja Nikolaus6a679132018-08-30 14:35:29 +0200117 """Save the crashreport and set its local ID if it was not set."""
Dirk Vogt67eb1482016-10-13 12:42:56 +0200118 if not self.device_local_id:
119 self.device_local_id = self.device.get_crashreport_key()
120 super(Crashreport, self).save(*args, **kwargs)
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200121
Dirk Vogtf2a33422016-10-11 17:17:26 +0200122 def _get_uuid(self):
Mitja Nikolaus6a679132018-08-30 14:35:29 +0200123 """Return the device UUID."""
Dirk Vogtf2a33422016-10-11 17:17:26 +0200124 return self.device.uuid
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200125
Dirk Vogtf2a33422016-10-11 17:17:26 +0200126 uuid = property(_get_uuid)
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200127
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200128
Dirk Vogtf2a33422016-10-11 17:17:26 +0200129class LogFile(models.Model):
Mitja Nikolaus6a679132018-08-30 14:35:29 +0200130 """A log file that was sent along with a crashreport."""
131
Dirk Vogt7160b5e2016-10-12 17:04:40 +0200132 logfile_type = models.TextField(max_length=36, default="last_kmsg")
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200133 crashreport = models.ForeignKey(
134 Crashreport, related_name="logfiles", on_delete=models.CASCADE
135 )
Dirk Vogteda80d32016-11-21 11:45:50 +0100136 logfile = models.FileField(upload_to=crashreport_file_name, max_length=500)
Dirk Vogt67eb1482016-10-13 12:42:56 +0200137 crashreport_local_id = models.PositiveIntegerField(blank=True)
Dirk Vogteda80d32016-11-21 11:45:50 +0100138 created_at = models.DateTimeField(auto_now_add=True)
Dirk Vogt67eb1482016-10-13 12:42:56 +0200139
140 def save(self, *args, **kwargs):
Mitja Nikolaus6a679132018-08-30 14:35:29 +0200141 """Save the log file and set its local ID if it was not set."""
Dirk Vogt36635692016-10-17 12:19:10 +0200142 if not self.crashreport_local_id:
143 self.crashreport_local_id = self.crashreport.get_logfile_key()
Dirk Vogt67eb1482016-10-13 12:42:56 +0200144 super(LogFile, self).save(*args, **kwargs)
Dirk Vogtf2a33422016-10-11 17:17:26 +0200145
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200146
147class HeartBeat(models.Model):
Mitja Nikolaus6a679132018-08-30 14:35:29 +0200148 """A heartbeat that was sent by a device."""
149
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200150 device = models.ForeignKey(
151 Device,
Dirk Vogt83107df2017-05-02 12:04:19 +0200152 db_index=True,
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200153 related_name="heartbeats",
154 on_delete=models.CASCADE,
155 )
Dirk Vogt1433f7c2016-09-20 15:30:56 +0200156 app_version = models.IntegerField()
Dirk Vogtf130c752016-08-23 14:45:01 +0200157 uptime = models.CharField(max_length=200)
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200158 build_fingerprint = models.CharField(db_index=True, max_length=200)
Borjan Tchakaloff6f239a62018-02-19 09:05:50 +0100159 radio_version = models.CharField(db_index=True, max_length=200, null=True)
Dirk Vogt83107df2017-05-02 12:04:19 +0200160 date = models.DateTimeField(db_index=True)
Dirk Vogt67eb1482016-10-13 12:42:56 +0200161 device_local_id = models.PositiveIntegerField(blank=True)
Dirk Vogteda80d32016-11-21 11:45:50 +0100162 created_at = models.DateTimeField(auto_now_add=True)
Dirk Vogt67eb1482016-10-13 12:42:56 +0200163
164 def save(self, *args, **kwargs):
Mitja Nikolaus6a679132018-08-30 14:35:29 +0200165 """Save the heartbeat and set its local ID if it was not set."""
Dirk Vogt67eb1482016-10-13 12:42:56 +0200166 if not self.device_local_id:
167 self.device_local_id = self.device.get_heartbeat_key()
168 super(HeartBeat, self).save(*args, **kwargs)
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200169
170 def _get_uuid(self):
Mitja Nikolaus6a679132018-08-30 14:35:29 +0200171 """Return the device UUID."""
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200172 return self.device.uuid
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200173
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200174 uuid = property(_get_uuid)