diff options
-rw-r--r-- | conf/supervisord.conf | 1 | ||||
-rw-r--r-- | conf/uwsgi.ini | 1 | ||||
-rw-r--r-- | omaha_server/crash/admin.py | 4 | ||||
-rw-r--r-- | omaha_server/crash/forms.py | 23 | ||||
-rw-r--r-- | omaha_server/crash/models.py | 6 | ||||
-rw-r--r-- | omaha_server/crash/tests/test_forms.py | 37 | ||||
-rw-r--r-- | omaha_server/omaha/admin.py | 18 | ||||
-rw-r--r-- | omaha_server/omaha/static/statistics/js/live_charts.js | 20 | ||||
-rw-r--r-- | pavement.py | 2 |
9 files changed, 91 insertions, 21 deletions
diff --git a/conf/supervisord.conf b/conf/supervisord.conf index a186f26..ea6312a 100644 --- a/conf/supervisord.conf +++ b/conf/supervisord.conf @@ -10,6 +10,7 @@ autorestart=true command=/usr/local/bin/uwsgi --ini /srv/omaha/conf/uwsgi.ini autostart=true autorestart=true +stopsignal=QUIT [program:celery] command=celery worker -B -A omaha_server --loglevel=INFO diff --git a/conf/uwsgi.ini b/conf/uwsgi.ini index dac8d63..d4c0b8f 100644 --- a/conf/uwsgi.ini +++ b/conf/uwsgi.ini @@ -6,3 +6,4 @@ chunked-input-limit = 25000000 chunked-input-timeout = 300 socket-timeout = 300 buffer-size = 65535 +master = 1 diff --git a/omaha_server/crash/admin.py b/omaha_server/crash/admin.py index e45f1f1..8483449 100644 --- a/omaha_server/crash/admin.py +++ b/omaha_server/crash/admin.py @@ -114,11 +114,11 @@ class CrashAdmin(admin.ModelAdmin): archive_field.short_description = 'Instrumental file' def os_field(self, obj): - return obj.stacktrace_json['system_info']['os'] if obj.stacktrace_json else '' + return obj.stacktrace_json.get('system_info', {}).get('os', '') if obj.stacktrace_json else '' os_field.short_description = 'OS' def cpu_architecture_field(self, obj): - return obj.stacktrace_json['system_info']['cpu_arch'] if obj.stacktrace_json else '' + return obj.stacktrace_json.get('system_info', {}).get('cpu_arch', '') if obj.stacktrace_json else '' cpu_architecture_field.short_description = "CPU Architecture" def sentry_link_field(self, obj): diff --git a/omaha_server/crash/forms.py b/omaha_server/crash/forms.py index 27cbb16..233e97a 100644 --- a/omaha_server/crash/forms.py +++ b/omaha_server/crash/forms.py @@ -52,17 +52,20 @@ class CrashFrom(forms.ModelForm): def clean_upload_file_minidump(self): file = self.cleaned_data["upload_file_minidump"] - if file.name.endswith('.tar'): - t_file = BytesIO(file.read()) - t_file = tarfile.open(fileobj=t_file, mode='r') - self.cleaned_data['archive_file'] = file - dump_name = filter(lambda i: i.endswith('.dmp'), t_file.getnames()) + if file and file.name.endswith('.tar'): try: - file_name = next(dump_name) - file = t_file.extractfile(file_name) - file = SimpleUploadedFile(file_name, file.read()) - except StopIteration: - return None + t_file = BytesIO(file.read()) + t_file = tarfile.open(fileobj=t_file, mode='r') + self.cleaned_data['archive_file'] = file + dump_name = filter(lambda i: i.endswith('.dmp'), t_file.getnames()) + try: + file_name = next(dump_name) + file = t_file.extractfile(file_name) + file = SimpleUploadedFile(file_name, file.read()) + except StopIteration: + return None + except tarfile.TarError as err: + raise forms.ValidationError('The tar file is broken, error: {0}'.format(err.message)) return file def clean_minidump_size(self): diff --git a/omaha_server/crash/models.py b/omaha_server/crash/models.py index aa18980..434b26a 100644 --- a/omaha_server/crash/models.py +++ b/omaha_server/crash/models.py @@ -65,9 +65,13 @@ class Crash(BaseModel): class Meta(BaseModel.Meta): verbose_name_plural = 'Crashes' + def __unicode__(self): + return u"Crash #{0}".format(self.id) + (" ({0})".format(self.signature) if self.signature else '') + @property def size(self): - return self.archive_size + self.minidump_size + return self.archive_size + self.minidump_size + class CrashDescription(BaseModel): crash = models.OneToOneField(Crash, related_name='crash_description') diff --git a/omaha_server/crash/tests/test_forms.py b/omaha_server/crash/tests/test_forms.py index 9e41e82..9ddf202 100644 --- a/omaha_server/crash/tests/test_forms.py +++ b/omaha_server/crash/tests/test_forms.py @@ -19,6 +19,8 @@ the License. """ import os +import string +import random from django.test import TestCase from django.core.files.uploadedfile import SimpleUploadedFile @@ -32,6 +34,10 @@ SYM_FILE = os.path.join(TEST_DATA_DIR, 'BreakpadTestApp.sym') TAR_FILE = os.path.join(TEST_DATA_DIR, 'foo.tar') +def string_generator(size, chars=string.ascii_uppercase + string.ascii_lowercase + string.digits): + return ''.join(random.choice(chars) for _ in range(size)) + + class SymbolsAdminFormTest(TestCase): def test_form(self): form_data = {} @@ -78,4 +84,33 @@ class CrashFormTest(TestCase): self.assertEqual(form.cleaned_data['upload_file_minidump'].name, '7b05e196-7e23-416b-bd13-99287924e214.dmp') self.assertEqual(form.cleaned_data['archive'].name, 'foo.tar') self.assertEqual(form.cleaned_data['archive_size'], 85504) - self.assertEqual(form.cleaned_data['minidump_size'], 14606)
\ No newline at end of file + self.assertEqual(form.cleaned_data['minidump_size'], 14606) + + def test_invalid_data(self): + with open(TAR_FILE, 'rb') as f: + form_file_data = dict(upload_file_minidump=SimpleUploadedFile( + "foo.tar", f.read(100))) + form_data = dict( + appid=string_generator(40), + userid=string_generator(40), + meta=string_generator(40), + stacktrace=string_generator(40), + stacktrace_json=string_generator(40), + signature=string_generator(256), + ip=string_generator(40), + groupid=string_generator(40), + eventid=string_generator(40), + ) + + form = CrashFrom(form_data, form_file_data) + self.assertFalse(form.is_valid()) + self.assertIn('upload_file_minidump', form.errors) + self.assertIn('appid', form.errors) + self.assertIn('userid', form.errors) + self.assertIn('meta', form.errors) + self.assertNotIn('stacktrace', form.errors) + self.assertIn('stacktrace_json', form.errors) + self.assertIn('signature', form.errors) + self.assertIn('ip', form.errors) + self.assertIn('groupid', form.errors) + self.assertIn('eventid', form.errors) diff --git a/omaha_server/omaha/admin.py b/omaha_server/omaha/admin.py index b3c7ffc..8519567 100644 --- a/omaha_server/omaha/admin.py +++ b/omaha_server/omaha/admin.py @@ -17,11 +17,18 @@ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ +import copy from django.contrib import admin +from django.contrib.admin import utils +from django.utils.encoding import smart_text + +from dynamic_preferences.models import GlobalPreferenceModel, UserPreferenceModel +from versionfield import VersionField + from omaha.models import Channel, Platform, Application, Version, Action, PartialUpdate, Data from omaha.forms import ApplicationAdminForm, VersionAdminForm, ActionAdminForm, DataAdminForm -from dynamic_preferences.models import GlobalPreferenceModel, UserPreferenceModel + admin.site.unregister(GlobalPreferenceModel) admin.site.unregister(UserPreferenceModel) @@ -68,3 +75,12 @@ class VersionAdmin(admin.ModelAdmin): list_filter = ('channel__name', 'platform__name', 'app__name',) readonly_fields = ('file_hash',) form = VersionAdminForm + + +def my_display_for_field(value, field, *args, **kwargs): + if isinstance(field, VersionField): + return smart_text(value) + return django_display_for_field(value, field, *args, **kwargs) + +django_display_for_field = copy.deepcopy(utils.display_for_field) +utils.display_for_field = my_display_for_field
\ No newline at end of file diff --git a/omaha_server/omaha/static/statistics/js/live_charts.js b/omaha_server/omaha/static/statistics/js/live_charts.js index 31263b4..18f6da5 100644 --- a/omaha_server/omaha/static/statistics/js/live_charts.js +++ b/omaha_server/omaha/static/statistics/js/live_charts.js @@ -28,20 +28,29 @@ function getVersions(data){ function getData(data){ - return getVersions(data).map(function(d){ + var result = getVersions(data).map(function(d){ return { key: d, values: data[d] } }); + + if (result.length) { + result.map(function(x){ + x.values.pop(); + }); + } + return result; } function getHours(data){ if (Object.keys(data).length) { - return data[Object.keys(data)[0]].map(function (d) { - return new Date(d[0]) + var res = data[Object.keys(data)[0]].map(function (d) { + return new Date(d[0]); }); + res.pop(); + return res; } else return []; } @@ -70,7 +79,10 @@ function makePlatformGraph(chartName, chartDataName, data, platform){ .y(function(d) { return d[1] }) .useInteractiveGuideline(true) .showControls(false); - + chart.interactiveLayer.tooltip.headerFormatter(function(d) { + var top_limit = moment(d, 'MMMM DD hh:mm a').add(1, 'h'); + return d + ' - ' + top_limit.format('hh:mm A'); + }); chart.xAxis.showMaxMin(false) .tickValues(hours.filter(function(d, i){ return !(i % tickSize); diff --git a/pavement.py b/pavement.py index 5b459c2..e63f951 100644 --- a/pavement.py +++ b/pavement.py @@ -82,8 +82,6 @@ def loaddata(): @task def migrate(): - sh('./manage.py migrate sites --noinput', cwd='omaha_server') - sh('./manage.py migrate auth --noinput', cwd='omaha_server') sh('./manage.py migrate --noinput', cwd='omaha_server') |