From patchwork Wed Mar 7 02:13:11 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael-Doyle Hudson X-Patchwork-Id: 7127 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id B172223E68 for ; Wed, 7 Mar 2012 02:13:17 +0000 (UTC) Received: from mail-iy0-f180.google.com (mail-iy0-f180.google.com [209.85.210.180]) by fiordland.canonical.com (Postfix) with ESMTP id 31D47A1871F for ; Wed, 7 Mar 2012 02:13:17 +0000 (UTC) Received: by iage36 with SMTP id e36so10644540iag.11 for ; Tue, 06 Mar 2012 18:13:16 -0800 (PST) Received: by 10.50.195.234 with SMTP id ih10mr203649igc.50.1331086396664; Tue, 06 Mar 2012 18:13:16 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.231.53.18 with SMTP id k18csp240ibg; Tue, 6 Mar 2012 18:13:15 -0800 (PST) Received: by 10.180.85.69 with SMTP id f5mr448532wiz.18.1331086394887; Tue, 06 Mar 2012 18:13:14 -0800 (PST) Received: from indium.canonical.com (indium.canonical.com. [91.189.90.7]) by mx.google.com with ESMTPS id j60si16016590wed.98.2012.03.06.18.13.12 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 06 Mar 2012 18:13:14 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) client-ip=91.189.90.7; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) smtp.mail=bounces@canonical.com Received: from ackee.canonical.com ([91.189.89.26]) by indium.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1S56NL-0007KP-U5 for ; Wed, 07 Mar 2012 02:13:11 +0000 Received: from ackee.canonical.com (localhost [127.0.0.1]) by ackee.canonical.com (Postfix) with ESMTP id D2CA5E0180 for ; Wed, 7 Mar 2012 02:13:11 +0000 (UTC) MIME-Version: 1.0 X-Launchpad-Project: lava-scheduler X-Launchpad-Branch: ~linaro-validation/lava-scheduler/trunk X-Launchpad-Message-Rationale: Subscriber X-Launchpad-Branch-Revision-Number: 142 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~linaro-validation/lava-scheduler/trunk] Rev 142: make testjob a restricted resource, and update views to reflect restrictions Message-Id: <20120307021311.25596.58212.launchpad@ackee.canonical.com> Date: Wed, 07 Mar 2012 02:13:11 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="14907"; Instance="launchpad-lazr.conf" X-Launchpad-Hash: 56b92d6a6837ad12df01f9eee0baf28634f3aa17 X-Gm-Message-State: ALoCoQmXdoruZ0B/8FC+wcIsRp8T+rHXDfR6qlVDoz30dnZtVdIb5ThNDsuspa4xwwegIKx7MtaF Merge authors: Michael Hudson-Doyle (mwhudson) Related merge proposals: https://code.launchpad.net/~mwhudson/lava-scheduler/restricted-resource-job/+merge/94497 proposed by: Michael Hudson-Doyle (mwhudson) review: Approve - Zygmunt Krynicki (zkrynicki) ------------------------------------------------------------ revno: 142 [merge] committer: Michael Hudson-Doyle branch nick: trunk timestamp: Wed 2012-03-07 15:11:53 +1300 message: make testjob a restricted resource, and update views to reflect restrictions added: lava_scheduler_app/migrations/0018_auto__add_field_testjob_user__add_field_testjob_group__add_field_testj.py lava_scheduler_app/migrations/0019_set_testjob_owner.py modified: lava_scheduler_app/models.py lava_scheduler_app/tests.py lava_scheduler_app/views.py lava_scheduler_daemon/dbjobsource.py setup.py --- lp:lava-scheduler https://code.launchpad.net/~linaro-validation/lava-scheduler/trunk You are subscribed to branch lp:lava-scheduler. To unsubscribe from this branch go to https://code.launchpad.net/~linaro-validation/lava-scheduler/trunk/+edit-subscription === added file 'lava_scheduler_app/migrations/0018_auto__add_field_testjob_user__add_field_testjob_group__add_field_testj.py' --- lava_scheduler_app/migrations/0018_auto__add_field_testjob_user__add_field_testjob_group__add_field_testj.py 1970-01-01 00:00:00 +0000 +++ lava_scheduler_app/migrations/0018_auto__add_field_testjob_user__add_field_testjob_group__add_field_testj.py 2012-02-28 03:53:06 +0000 @@ -0,0 +1,134 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding field 'TestJob.user' + db.add_column('lava_scheduler_app_testjob', 'user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True), keep_default=False) + + # Adding field 'TestJob.group' + db.add_column('lava_scheduler_app_testjob', 'group', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.Group'], null=True, blank=True), keep_default=False) + + # Adding field 'TestJob.is_public' + db.add_column('lava_scheduler_app_testjob', 'is_public', self.gf('django.db.models.fields.BooleanField')(default=True), keep_default=False) + + + def backwards(self, orm): + + # Deleting field 'TestJob.user' + db.delete_column('lava_scheduler_app_testjob', 'user_id') + + # Deleting field 'TestJob.group' + db.delete_column('lava_scheduler_app_testjob', 'group_id') + + # Deleting field 'TestJob.is_public' + db.delete_column('lava_scheduler_app_testjob', 'is_public') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'lava_scheduler_app.device': { + 'Meta': {'object_name': 'Device'}, + 'current_job': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['lava_scheduler_app.TestJob']"}), + 'device_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['lava_scheduler_app.DeviceType']"}), + 'health_status': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'hostname': ('django.db.models.fields.CharField', [], {'max_length': '200', 'primary_key': 'True'}), + 'last_health_report_job': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['lava_scheduler_app.TestJob']"}), + 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['lava_scheduler_app.Tag']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'lava_scheduler_app.devicestatetransition': { + 'Meta': {'object_name': 'DeviceStateTransition'}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'created_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'device': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'transitions'", 'to': "orm['lava_scheduler_app.Device']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'job': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['lava_scheduler_app.TestJob']", 'null': 'True', 'blank': 'True'}), + 'message': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'new_state': ('django.db.models.fields.IntegerField', [], {}), + 'old_state': ('django.db.models.fields.IntegerField', [], {}) + }, + 'lava_scheduler_app.devicetype': { + 'Meta': {'object_name': 'DeviceType'}, + 'name': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'primary_key': 'True', 'db_index': 'True'}) + }, + 'lava_scheduler_app.tag': { + 'Meta': {'object_name': 'Tag'}, + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}) + }, + 'lava_scheduler_app.testjob': { + 'Meta': {'object_name': 'TestJob'}, + 'actual_device': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'+'", 'null': 'True', 'blank': 'True', 'to': "orm['lava_scheduler_app.Device']"}), + 'definition': ('django.db.models.fields.TextField', [], {}), + 'description': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'end_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.Group']", 'null': 'True', 'blank': 'True'}), + 'health_check': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'log_file': ('django.db.models.fields.files.FileField', [], {'default': 'None', 'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'requested_device': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'+'", 'null': 'True', 'blank': 'True', 'to': "orm['lava_scheduler_app.Device']"}), + 'requested_device_type': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'+'", 'null': 'True', 'blank': 'True', 'to': "orm['lava_scheduler_app.DeviceType']"}), + 'results_link': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '400', 'null': 'True', 'blank': 'True'}), + 'start_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'status': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'submit_time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'submit_token': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['linaro_django_xmlrpc.AuthToken']", 'null': 'True', 'blank': 'True'}), + 'submitter': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['lava_scheduler_app.Tag']", 'symmetrical': 'False', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}) + }, + 'linaro_django_xmlrpc.authtoken': { + 'Meta': {'object_name': 'AuthToken'}, + 'created_on': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_used_on': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'secret': ('django.db.models.fields.CharField', [], {'default': "'g13kpfwrkljb08chbabb0zyr642p4ukfqoc18qxmjc1zefpb0cfeddzotwot4cs1ltzh83wl5g0e7177da4n0nn5zmax8hyo8se7cbqf784y8qe6m03g0ch90uwfbpry'", 'unique': 'True', 'max_length': '128'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_tokens'", 'to': "orm['auth.User']"}) + } + } + + complete_apps = ['lava_scheduler_app'] === added file 'lava_scheduler_app/migrations/0019_set_testjob_owner.py' --- lava_scheduler_app/migrations/0019_set_testjob_owner.py 1970-01-01 00:00:00 +0000 +++ lava_scheduler_app/migrations/0019_set_testjob_owner.py 2012-03-07 01:56:57 +0000 @@ -0,0 +1,123 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models + +class Migration(DataMigration): + + def forwards(self, orm): + "Write your forwards methods here." + orm['lava_scheduler_app.TestJob'].objects.update( + user=models.F('submitter')) + + + def backwards(self, orm): + "Write your backwards methods here." + orm['lava_scheduler_app.TestJob'].objects.update( + user=None) + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'lava_scheduler_app.device': { + 'Meta': {'object_name': 'Device'}, + 'current_job': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['lava_scheduler_app.TestJob']"}), + 'device_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['lava_scheduler_app.DeviceType']"}), + 'health_status': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'hostname': ('django.db.models.fields.CharField', [], {'max_length': '200', 'primary_key': 'True'}), + 'last_health_report_job': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['lava_scheduler_app.TestJob']"}), + 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['lava_scheduler_app.Tag']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'lava_scheduler_app.devicestatetransition': { + 'Meta': {'object_name': 'DeviceStateTransition'}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'created_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'device': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'transitions'", 'to': "orm['lava_scheduler_app.Device']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'job': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['lava_scheduler_app.TestJob']", 'null': 'True', 'blank': 'True'}), + 'message': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'new_state': ('django.db.models.fields.IntegerField', [], {}), + 'old_state': ('django.db.models.fields.IntegerField', [], {}) + }, + 'lava_scheduler_app.devicetype': { + 'Meta': {'object_name': 'DeviceType'}, + 'health_check_job': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'primary_key': 'True', 'db_index': 'True'}) + }, + 'lava_scheduler_app.tag': { + 'Meta': {'object_name': 'Tag'}, + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}) + }, + 'lava_scheduler_app.testjob': { + 'Meta': {'object_name': 'TestJob'}, + 'actual_device': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'+'", 'null': 'True', 'blank': 'True', 'to': "orm['lava_scheduler_app.Device']"}), + 'definition': ('django.db.models.fields.TextField', [], {}), + 'description': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'end_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.Group']", 'null': 'True', 'blank': 'True'}), + 'health_check': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'log_file': ('django.db.models.fields.files.FileField', [], {'default': 'None', 'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'requested_device': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'+'", 'null': 'True', 'blank': 'True', 'to': "orm['lava_scheduler_app.Device']"}), + 'requested_device_type': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'+'", 'null': 'True', 'blank': 'True', 'to': "orm['lava_scheduler_app.DeviceType']"}), + 'results_link': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '400', 'null': 'True', 'blank': 'True'}), + 'start_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'status': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'submit_time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'submit_token': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['linaro_django_xmlrpc.AuthToken']", 'null': 'True', 'blank': 'True'}), + 'submitter': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['lava_scheduler_app.Tag']", 'symmetrical': 'False', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}) + }, + 'linaro_django_xmlrpc.authtoken': { + 'Meta': {'object_name': 'AuthToken'}, + 'created_on': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_used_on': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'secret': ('django.db.models.fields.CharField', [], {'default': "'ymu1iwklrasagpior1qddpatt0qzmf6lcy5bhctm7q4csn4gnjq5wizxljd60j4acjpjhkfiu3bc6ze6f3xakitusy0ujjiu6j2sxz0itgwf2g4h6lcmu07h98mqdtne'", 'unique': 'True', 'max_length': '128'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_tokens'", 'to': "orm['auth.User']"}) + } + } + + complete_apps = ['lava_scheduler_app'] === modified file 'lava_scheduler_app/models.py' --- lava_scheduler_app/models.py 2012-02-23 04:19:36 +0000 +++ lava_scheduler_app/models.py 2012-03-07 01:56:57 +0000 @@ -3,8 +3,14 @@ from django.contrib.auth.models import User from django.core.exceptions import ValidationError from django.db import models +from django.db.models.query import QuerySet from django.utils.translation import ugettext as _ + +from django_restricted_resource.managers import RestrictedResourceManager +from django_restricted_resource.models import RestrictedResource +from django_restricted_resource.utils import filter_bogus_users + from linaro_django_xmlrpc.models import AuthToken class JSONDataError(ValueError): @@ -117,6 +123,8 @@ "requested_device", "requested_device_type", "submitter", + "user", + "group", ).filter( actual_device=self ).order_by( @@ -153,7 +161,8 @@ # return device_type.device_set.all() -class TestJob(models.Model): + +class TestJob(RestrictedResource): """ A test job is a test process that will be run on a Device. """ @@ -179,6 +188,7 @@ submitter = models.ForeignKey( User, verbose_name = _(u"Submitter"), + related_name = '+', ) submit_token = models.ForeignKey(AuthToken, null=True, blank=True) @@ -278,7 +288,7 @@ job = TestJob( definition=json_data, submitter=user, requested_device=target, requested_device_type=device_type, description=job_name, - health_check=is_check) + health_check=is_check, user=user) job.save() for tag in tags: job.tags.add(tag) === modified file 'lava_scheduler_app/tests.py' --- lava_scheduler_app/tests.py 2012-02-23 04:12:07 +0000 +++ lava_scheduler_app/tests.py 2012-02-28 03:53:16 +0000 @@ -89,6 +89,8 @@ definition = json.dumps({}) if submitter is None: submitter = self.make_user() + if 'user' not in kwargs: + kwargs['user'] = submitter testjob = TestJob( definition=definition, submitter=submitter, **kwargs) testjob.save() === modified file 'lava_scheduler_app/views.py' --- lava_scheduler_app/views.py 2012-03-06 04:20:03 +0000 +++ lava_scheduler_app/views.py 2012-03-07 01:59:51 +0000 @@ -80,10 +80,19 @@ return pklink(record) +class RestrictedIDLinkColumn(IDLinkColumn): + + def render(self, record, table): + if record.is_accessible_by(table.context.get('request').user): + return pklink(record) + else: + return record.pk + + def all_jobs_with_device_sort(): return TestJob.objects.select_related( "actual_device", "requested_device", "requested_device_type", - "submitter").extra( + "submitter", "user", "group").extra( select={ 'device_sort': 'coalesce(actual_device_id, requested_device_id, requested_device_type_id)' }).all() @@ -106,7 +115,7 @@ else: return '' - id = IDLinkColumn() + id = RestrictedIDLinkColumn() status = Column() device = Column(accessor='device_sort') description = Column(attrs=Attrs(width="30%")) @@ -163,6 +172,11 @@ RequestContext(request)) +def get_restricted_job(user, pk): + return get_object_or_404( + TestJob.objects.accessible_by_principal(user), pk=pk) + + class DeviceHealthTable(AjaxTable): def get_queryset(self): @@ -276,7 +290,7 @@ @BreadCrumb("Job #{pk}", parent=index, needs=['pk']) def job_detail(request, pk): - job = get_object_or_404(TestJob, pk=pk) + job = get_restricted_job(request.user, pk) data = { 'job': job, @@ -313,7 +327,7 @@ def job_definition(request, pk): - job = get_object_or_404(TestJob, pk=pk) + job = get_restricted_job(request.user, pk) return render_to_response( "lava_scheduler_app/job_definition.html", { @@ -324,7 +338,7 @@ def job_definition_plain(request, pk): - job = get_object_or_404(TestJob, pk=pk) + job = get_restricted_job(request.user, pk) response = HttpResponse(job.definition, mimetype='text/plain') response['Content-Disposition'] = "attachment; filename=job_%d.json"%job.id return response @@ -332,7 +346,7 @@ @BreadCrumb("Complete log", parent=job_detail, needs=['pk']) def job_log_file(request, pk): - job = get_object_or_404(TestJob, pk=pk) + job = get_restricted_job(request.user, pk) content = formatLogFile(job.log_file) return render_to_response( "lava_scheduler_app/job_log_file.html", @@ -346,7 +360,7 @@ def job_log_file_plain(request, pk): - job = get_object_or_404(TestJob, pk=pk) + job = get_restricted_job(request.user, pk) response = HttpResponse(job.log_file, mimetype='text/plain') response['Content-Disposition'] = "attachment; filename=job_%d.log"%job.id return response @@ -354,7 +368,7 @@ def job_log_incremental(request, pk): start = int(request.GET.get('start', 0)) - job = get_object_or_404(TestJob, pk=pk) + job = get_restricted_job(request.user, pk) log_file = job.log_file log_file.seek(start) new_content = log_file.read() @@ -369,7 +383,7 @@ def job_full_log_incremental(request, pk): start = int(request.GET.get('start', 0)) - job = get_object_or_404(TestJob, pk=pk) + job = get_restricted_job(request.user, pk) log_file = job.log_file log_file.seek(start) new_content = log_file.read() @@ -396,7 +410,7 @@ except ValueError: return HttpResponseBadRequest("invalid start") count_present = 'count' in request.GET - job = get_object_or_404(TestJob, pk=pk) + job = get_restricted_job(request.user, pk) log_file = job.log_file log_file.seek(0, os.SEEK_END) size = int(request.GET.get('count', log_file.tell())) @@ -425,7 +439,7 @@ @post_only def job_cancel(request, pk): - job = get_object_or_404(TestJob, pk=pk) + job = get_restricted_job(request.user, pk) if job.can_cancel(request.user): job.cancel() return redirect(job) @@ -435,7 +449,7 @@ def job_json(request, pk): - job = get_object_or_404(TestJob, pk=pk) + job = get_restricted_job(request.user, pk) json_text = simplejson.dumps({ 'status': job.get_status_display(), 'results_link': job.results_link, === modified file 'lava_scheduler_daemon/dbjobsource.py' --- lava_scheduler_daemon/dbjobsource.py 2012-03-05 03:12:25 +0000 +++ lava_scheduler_daemon/dbjobsource.py 2012-03-07 01:59:51 +0000 @@ -126,7 +126,7 @@ job_name = job_data.get('job_name') job = TestJob( definition=job_json, submitter=user, description=job_name, - health_check=True) + health_check=True, owner=user, is_public=True) job.save() return job === modified file 'setup.py' --- setup.py 2012-03-01 04:34:01 +0000 +++ setup.py 2012-03-05 00:23:16 +0000 @@ -33,6 +33,7 @@ scheduler = lava_scheduler_app.extension:SchedulerExtension """, install_requires=[ + "django-restricted-resource", "django-tables2", "lava-server >= 0.10", "simplejson",