Completed
Push — master ( 4056a6...1a808a )
by Kirill
12s
created

Crash.__unicode__()   A

Complexity

Conditions 2

Size

Total Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
c 1
b 0
f 0
dl 0
loc 2
rs 10
1
# coding: utf8
2
3
"""
4
This software is licensed under the Apache 2 license, quoted below.
5
6
Copyright 2014 Crystalnix Limited
7
8
Licensed under the Apache License, Version 2.0 (the "License"); you may not
9
use this file except in compliance with the License. You may obtain a copy of
10
the License at
11
12
    http://www.apache.org/licenses/LICENSE-2.0
13
14
Unless required by applicable law or agreed to in writing, software
15
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17
License for the specific language governing permissions and limitations under
18
the License.
19
"""
20
21
import os
22
import uuid
23
24
from django.db import models
25
from django.db.models.signals import post_save, pre_delete
26
from django.dispatch import receiver
27
from django.utils import timezone
28
29
from celery import signature
30
from jsonfield import JSONField
31
32
from omaha.models import BaseModel
33
from crash.managers import CrashManager, SymbolsManager
34
35
36
def crash_upload_to(obj, filename):
37
    now = timezone.now()
38
    return os.path.join(*map(str, ['minidump', now.year, now.month,
39
                                   now.day, uuid.uuid4(), filename]))
40
41
42
def crash_archive_upload_to(obj, filename):
43
    now = timezone.now()
44
    return os.path.join(*map(str, ['minidump_archive', now.year, now.month,
45
                                   now.day, uuid.uuid4(), filename]))
46
47
48
class Crash(BaseModel):
49
    upload_file_minidump = models.FileField(upload_to=crash_upload_to, blank=True, null=True, max_length=255)
50
    minidump_size = models.PositiveIntegerField(null=True, blank=True)
51
    archive = models.FileField(upload_to=crash_archive_upload_to, blank=True, null=True, max_length=255)
52
    archive_size = models.PositiveIntegerField(null=True, blank=True)
53
    appid = models.CharField(max_length=38, null=True, blank=True)
54
    userid = models.CharField(max_length=38, null=True, blank=True)
55
    meta = JSONField(verbose_name='Meta-information', help_text='JSON format', null=True, blank=True)
56
    stacktrace = models.TextField(null=True, blank=True)
57
    stacktrace_json = JSONField(null=True, blank=True)
58
    signature = models.CharField(max_length=255, db_index=True, null=True, blank=True)
59
    ip = models.GenericIPAddressField(blank=True, null=True, protocol="ipv4")
60
    groupid = models.CharField(max_length=38, null=True, blank=True)
61
    eventid = models.CharField(max_length=38, null=True, blank=True)
62
63
    objects = CrashManager()
64
65
    class Meta(BaseModel.Meta):
66
        verbose_name_plural = 'Crashes'
67
68
    def __unicode__(self):
69
        return u"Crash #{0}".format(self.id) + (" ({0})".format(self.signature) if self.signature else '')
70
71
    @property
72
    def size(self):
73
        return self.archive_size + self.minidump_size
74
75
76
class CrashDescription(BaseModel):
77
    crash = models.OneToOneField(Crash, related_name='crash_description')
78
    summary = models.CharField(max_length=500)
79
    description = models.TextField(null=True, blank=True)
80
81
def symbols_upload_to(obj, filename):
82
    sym_filename = os.path.splitext(os.path.basename(obj.debug_file))[0]
83
    sym_filename = '%s.sym' % sym_filename
84
    return os.path.join('symbols', obj.debug_file, obj.debug_id, sym_filename)
85
86
87
class Symbols(BaseModel):
88
    debug_id = models.CharField(verbose_name='Debug ID', max_length=255, db_index=True, null=True, blank=True)
89
    debug_file = models.CharField(verbose_name='Debug file name', max_length=140, null=True, blank=True)
90
    file = models.FileField(upload_to=symbols_upload_to, null=True)
91
    file_size = models.PositiveIntegerField(null=True, blank=True)
92
93
    objects = SymbolsManager()
94
95
    class Meta:
96
        verbose_name_plural = 'Symbols'
97
        unique_together = (
98
            ('debug_id', 'debug_file'),
99
        )
100
101
    @property
102
    def size(self):
103
         return self.file_size
104
105
@receiver(post_save, sender=Crash)
106
def crash_post_save(sender, instance, created, *args, **kwargs):
107
    if created and instance.upload_file_minidump:
108
        signature("tasks.processing_crash_dump", args=(instance.pk,)).apply_async(queue='private', countdown=1)
109
110
111
@receiver(pre_delete, sender=Crash)
112
def pre_crash_delete(sender, instance, **kwargs):
113
    file_fields = [instance.archive, instance.upload_file_minidump]
114
    for field in file_fields:
115
        storage, name = field.storage, field.name
116
        if name:
117
            storage.delete(name)
118
119
120
@receiver(pre_delete, sender=Symbols)
121
def pre_symbol_delete(sender, instance, **kwargs):
122
    storage, name = instance.file.storage, instance.file.name
123
    if name:
124
        storage.delete(name)
125