diff --git a/.gitattributes b/.gitattributes index 460732fcea2b650b083cfdd2a9654e7775fb16d4..23ed5d4e7cec606cd7051998921c760e921afe19 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4247,7 +4247,7 @@ SAS/LSMR/src/lsmr/lsmrapp/__init__.py -text SAS/LSMR/src/lsmr/lsmrapp/admin.py -text SAS/LSMR/src/lsmr/lsmrapp/apps.py -text SAS/LSMR/src/lsmr/lsmrapp/migrations/0001_initial.py -text -SAS/LSMR/src/lsmr/lsmrapp/migrations/0002_auto_20190425_1501.py -text +SAS/LSMR/src/lsmr/lsmrapp/migrations/0002_auto_20190426_1408.py -text SAS/LSMR/src/lsmr/lsmrapp/migrations/0003_populate.py -text SAS/LSMR/src/lsmr/lsmrapp/migrations/CMakeLists.txt -text SAS/LSMR/src/lsmr/lsmrapp/migrations/__init__.py -text diff --git a/SAS/LSMR/src/lsmr/lsmrapp/migrations/0002_auto_20190425_1501.py b/SAS/LSMR/src/lsmr/lsmrapp/migrations/0002_auto_20190426_1408.py similarity index 53% rename from SAS/LSMR/src/lsmr/lsmrapp/migrations/0002_auto_20190425_1501.py rename to SAS/LSMR/src/lsmr/lsmrapp/migrations/0002_auto_20190426_1408.py index 9bd55584b8b09ce71c0dfa96e36a985f22b0023b..cff8d1ca87b379aae4ea4bd0b90f4cddbae2a8de 100644 --- a/SAS/LSMR/src/lsmr/lsmrapp/migrations/0002_auto_20190425_1501.py +++ b/SAS/LSMR/src/lsmr/lsmrapp/migrations/0002_auto_20190426_1408.py @@ -1,4 +1,4 @@ -# Generated by Django 2.0.6 on 2019-04-25 15:01 +# Generated by Django 2.0.6 on 2019-04-26 14:08 import django.contrib.postgres.fields import django.contrib.postgres.fields.jsonb @@ -29,11 +29,11 @@ class Migration(migrations.Migration): name='AntennaSet', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), ('rcus', django.contrib.postgres.fields.ArrayField(base_field=models.IntegerField(), size=128)), ('inputs', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=128)), ], @@ -45,12 +45,12 @@ class Migration(migrations.Migration): name='Cluster', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), - ('location', models.CharField(max_length=128)), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), + ('location', models.CharField(help_text='Human-readable location of the cluster.', max_length=128)), ], options={ 'abstract': False, @@ -69,17 +69,17 @@ class Migration(migrations.Migration): name='Cycle', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), - ('start', models.DateTimeField()), - ('stop', models.DateTimeField()), - ('number', models.IntegerField()), - ('standard_hours', models.IntegerField()), - ('expert_hours', models.IntegerField()), - ('filler_hours', models.IntegerField()), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), + ('start', models.DateTimeField(help_text='Moment at which the cycle starts, that is, when its projects can run.')), + ('stop', models.DateTimeField(help_text='Moment at which the cycle officially ends.')), + ('number', models.IntegerField(help_text='Cycle number.')), + ('standard_hours', models.IntegerField(help_text='Number of offered hours for standard observations.')), + ('expert_hours', models.IntegerField(help_text='Number of offered hours for expert observations.')), + ('filler_hours', models.IntegerField(help_text='Number of offered hours for filler observations.')), ], options={ 'abstract': False, @@ -98,18 +98,18 @@ class Migration(migrations.Migration): name='Dataproduct', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('filename', models.CharField(max_length=128)), - ('directory', models.CharField(max_length=1024)), - ('deleted_since', models.DateTimeField(null=True)), - ('pinned_since', models.DateTimeField(null=True)), - ('specifications_doc', django.contrib.postgres.fields.jsonb.JSONField()), - ('do_cancel', models.DateTimeField()), - ('expected_size', models.BigIntegerField()), - ('size', models.BigIntegerField()), - ('feedback_doc', django.contrib.postgres.fields.jsonb.JSONField()), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('filename', models.CharField(help_text='Name of the file (or top-level directory) of the dataproduct. Adheres to a naming convention, but is not meant for parsing.', max_length=128)), + ('directory', models.CharField(help_text='Directory where this dataproduct is (to be) stored.', max_length=1024)), + ('deleted_since', models.DateTimeField(help_text='When this dataproduct was removed from disk, or NULL if not deleted (NULLable).', null=True)), + ('pinned_since', models.DateTimeField(help_text='When this dataproduct was pinned to disk, that is, forbidden to be removed, or NULL if not pinned (NULLable).', null=True)), + ('specifications_doc', django.contrib.postgres.fields.jsonb.JSONField(help_text='Dataproduct properties (f.e. beam, subband), to distinguish them when produced by the same task, and to act as input for selections in the Task Input and Work Request Relation Blueprint objects.')), + ('do_cancel', models.DateTimeField(help_text='When this dataproduct was cancelled (NULLable). Cancelling a dataproduct triggers cleanup if necessary.')), + ('expected_size', models.BigIntegerField(help_text='Expected size of dataproduct size, in bytes. Used for scheduling purposes. NULL if size is unknown (NULLable).')), + ('size', models.BigIntegerField(help_text='Dataproduct size, in bytes. Used for accounting purposes. NULL if size is (yet) unknown (NULLable).')), + ('feedback_doc', django.contrib.postgres.fields.jsonb.JSONField(help_text='Dataproduct properties, as reported by the producing process.')), ('dataformat', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.DataformatChoice')), ], options={ @@ -120,13 +120,13 @@ class Migration(migrations.Migration): name='DataproductArchiveInfo', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('storage_ticket', models.CharField(max_length=128)), - ('public_since', models.DateTimeField()), - ('corrupted_since', models.DateTimeField()), - ('dataproduct', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.Dataproduct')), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('storage_ticket', models.CharField(help_text='Archive-system identifier.', max_length=128)), + ('public_since', models.DateTimeField(help_text='Dataproduct is available for public download since this moment, or NULL if dataproduct is not (NULLable).')), + ('corrupted_since', models.DateTimeField(help_text='Earliest timestamp from which this dataproduct is known to be partially or fully corrupt, or NULL if dataproduct is not known to be corrupt (NULLable).')), + ('dataproduct', models.ForeignKey(help_text='A dataproduct residing in the archive.', on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.Dataproduct')), ], options={ 'abstract': False, @@ -136,13 +136,13 @@ class Migration(migrations.Migration): name='DataproductFeedbackTemplate', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), - ('version', models.CharField(max_length=128)), - ('schema', django.contrib.postgres.fields.jsonb.JSONField()), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), + ('version', models.CharField(help_text='Version of this template (with respect to other templates of the same name).', max_length=128)), + ('schema', django.contrib.postgres.fields.jsonb.JSONField(help_text='Schema for the configurable parameters needed to use this template.')), ], options={ 'abstract': False, @@ -152,12 +152,12 @@ class Migration(migrations.Migration): name='DataproductHash', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('hash', models.CharField(max_length=128)), - ('algorithm', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.Algorithm')), - ('dataproduct', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.Dataproduct')), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('hash', models.CharField(help_text='Hash value.', max_length=128)), + ('algorithm', models.ForeignKey(help_text='Algorithm used (MD5, AES256).', on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.Algorithm')), + ('dataproduct', models.ForeignKey(help_text='The dataproduct to which this hash refers.', on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.Dataproduct')), ], options={ 'abstract': False, @@ -167,13 +167,13 @@ class Migration(migrations.Migration): name='DataproductSpecificationsTemplate', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), - ('version', models.CharField(max_length=128)), - ('schema', django.contrib.postgres.fields.jsonb.JSONField()), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), + ('version', models.CharField(help_text='Version of this template (with respect to other templates of the same name).', max_length=128)), + ('schema', django.contrib.postgres.fields.jsonb.JSONField(help_text='Schema for the configurable parameters needed to use this template.')), ], options={ 'abstract': False, @@ -183,12 +183,12 @@ class Migration(migrations.Migration): name='DataproductTransform', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('identity', models.BooleanField()), - ('input', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='inputs', to='lsmrapp.Dataproduct')), - ('output', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='outputs', to='lsmrapp.Dataproduct')), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('identity', models.BooleanField(help_text='TRUE if this transform only copies, tars, or losslessly compresses its input, FALSE if the transform changes the data. Allows for efficient reasoning about data duplication.')), + ('input', models.ForeignKey(help_text='A dataproduct that was the input of a transformation.', on_delete=django.db.models.deletion.PROTECT, related_name='inputs', to='lsmrapp.Dataproduct')), + ('output', models.ForeignKey(help_text='A dataproduct that was produced from the input dataproduct.', on_delete=django.db.models.deletion.PROTECT, related_name='outputs', to='lsmrapp.Dataproduct')), ], options={ 'abstract': False, @@ -207,9 +207,9 @@ class Migration(migrations.Migration): name='DefaultDataproductSpecificationsTemplate', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), ('name', models.CharField(max_length=128, unique=True)), ('template', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.DataproductSpecificationsTemplate')), ], @@ -221,9 +221,9 @@ class Migration(migrations.Migration): name='DefaultGeneratorTemplate', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), ('name', models.CharField(max_length=128, unique=True)), ], options={ @@ -234,9 +234,9 @@ class Migration(migrations.Migration): name='DefaultSpecificationUnitTemplate', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), ('name', models.CharField(max_length=128, unique=True)), ], options={ @@ -247,9 +247,9 @@ class Migration(migrations.Migration): name='DefaultSubtaskTemplate', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), ('name', models.CharField(max_length=128, unique=True)), ], options={ @@ -260,9 +260,9 @@ class Migration(migrations.Migration): name='DefaultTaskTemplate', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), ('name', models.CharField(max_length=128, unique=True)), ], options={ @@ -273,9 +273,9 @@ class Migration(migrations.Migration): name='DefaultWorkRelationSelectionTemplate', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), ('name', models.CharField(max_length=128, unique=True)), ], options={ @@ -286,13 +286,13 @@ class Migration(migrations.Migration): name='Filesystem', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), - ('capacity', models.BigIntegerField()), - ('cluster', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.Cluster')), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), + ('capacity', models.BigIntegerField(help_text='Capacity in bytes')), + ('cluster', models.ForeignKey(help_text='Cluster hosting this filesystem.', on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.Cluster')), ], options={ 'abstract': False, @@ -302,14 +302,14 @@ class Migration(migrations.Migration): name='GeneratorTemplate', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), - ('version', models.CharField(max_length=128)), - ('schema', django.contrib.postgres.fields.jsonb.JSONField()), - ('create_function', models.CharField(max_length=128)), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), + ('version', models.CharField(help_text='Version of this template (with respect to other templates of the same name).', max_length=128)), + ('schema', django.contrib.postgres.fields.jsonb.JSONField(help_text='Schema for the configurable parameters needed to use this template.')), + ('create_function', models.CharField(help_text='Python function to call to execute the generator.', max_length=128)), ], options={ 'abstract': False, @@ -319,17 +319,17 @@ class Migration(migrations.Migration): name='Project', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), - ('priority', models.IntegerField(default=0)), - ('can_trigger', models.BooleanField(default=False)), - ('private_data', models.BooleanField(default=True)), - ('expert', models.BooleanField(default=True)), - ('filler', models.BooleanField(default=False)), - ('cycle', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='projects', to='lsmrapp.Cycle')), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), + ('priority', models.IntegerField(default=0, help_text='Priority of this project w.r.t. other projects. Projects can interrupt observations of lower-priority projects.')), + ('can_trigger', models.BooleanField(default=False, help_text='True if this project is allowed to supply observation requests on the fly, possibly interrupting currently running observations (responsive telescope).')), + ('private_data', models.BooleanField(default=True, help_text='True if data of this project is sensitive. Sensitive data is not made public.')), + ('expert', models.BooleanField(default=True, help_text='Expert projects put more responsibility on the PI.')), + ('filler', models.BooleanField(default=False, help_text='Use this project to fill up idle telescope time.')), + ('cycle', models.ForeignKey(help_text='Cycle(s) to which this project belongs (NULLable).', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='projects', to='lsmrapp.Cycle')), ], options={ 'abstract': False, @@ -357,12 +357,12 @@ class Migration(migrations.Migration): name='SpecificationSet', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), - ('generator_doc', django.contrib.postgres.fields.jsonb.JSONField()), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), + ('generator_doc', django.contrib.postgres.fields.jsonb.JSONField(help_text='Parameters for the generator (NULLable).')), ], options={ 'abstract': False, @@ -372,12 +372,12 @@ class Migration(migrations.Migration): name='SpecificationUnitBlueprint', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), - ('requirements_doc', django.contrib.postgres.fields.jsonb.JSONField()), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), + ('requirements_doc', django.contrib.postgres.fields.jsonb.JSONField(help_text='Scheduling and/or quality requirements for this scheduling unit (IMMUTABLE).')), ('do_cancel', models.BooleanField()), ], options={ @@ -388,15 +388,15 @@ class Migration(migrations.Migration): name='SpecificationUnitDraft', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), - ('requirements_doc', django.contrib.postgres.fields.jsonb.JSONField()), - ('generator_instance_doc', models.CharField(max_length=200)), - ('copies', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='copied_from', to='lsmrapp.SpecificationUnitDraft')), - ('copy_reason', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.CopyReasonChoice')), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), + ('requirements_doc', django.contrib.postgres.fields.jsonb.JSONField(help_text='Scheduling and/or quality requirements for this run.')), + ('generator_instance_doc', models.CharField(help_text='Parameter value that generated this run draft (NULLable).', max_length=200)), + ('copies', models.ForeignKey(help_text='Source reference, if we are a copy (NULLable).', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='copied_from', to='lsmrapp.SpecificationUnitDraft')), + ('copy_reason', models.ForeignKey(help_text='Reason why source was copied (NULLable).', on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.CopyReasonChoice')), ], options={ 'abstract': False, @@ -406,13 +406,13 @@ class Migration(migrations.Migration): name='SpecificationUnitTemplate', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), - ('version', models.CharField(max_length=128)), - ('schema', django.contrib.postgres.fields.jsonb.JSONField()), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), + ('version', models.CharField(help_text='Version of this template (with respect to other templates of the same name).', max_length=128)), + ('schema', django.contrib.postgres.fields.jsonb.JSONField(help_text='Schema for the configurable parameters needed to use this template.')), ], options={ 'abstract': False, @@ -431,17 +431,17 @@ class Migration(migrations.Migration): name='Subtask', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('start_time', models.DateTimeField()), - ('stop_time', models.DateTimeField()), - ('specifications_doc', django.contrib.postgres.fields.jsonb.JSONField()), - ('do_cancel', models.DateTimeField()), - ('priority', models.IntegerField()), - ('scheduler_input_doc', django.contrib.postgres.fields.jsonb.JSONField()), - ('cluster', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.Cluster')), - ('schedule_method', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.ScheduleMethod')), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('start_time', models.DateTimeField(help_text='Start this subtask at the specified time (NULLable).')), + ('stop_time', models.DateTimeField(help_text='Stop this subtask at the specified time (NULLable).')), + ('specifications_doc', django.contrib.postgres.fields.jsonb.JSONField(help_text='Final specifications, as input for the controller.')), + ('do_cancel', models.DateTimeField(help_text='Timestamp when the subtask has been ordered to cancel (NULLable).')), + ('priority', models.IntegerField(help_text='Absolute priority of this subtask (higher value means more important).')), + ('scheduler_input_doc', django.contrib.postgres.fields.jsonb.JSONField(help_text='Partial specifications, as input for the scheduler.')), + ('cluster', models.ForeignKey(help_text='Where the Subtask is scheduled to run (NULLable).', on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.Cluster')), + ('schedule_method', models.ForeignKey(help_text='Which method to use for scheduling this Subtask. One of (MANUAL, BATCH, DYNAMIC).', on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.ScheduleMethod')), ], options={ 'abstract': False, @@ -451,9 +451,9 @@ class Migration(migrations.Migration): name='SubtaskConnector', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), ('dataformats', models.ManyToManyField(blank=True, to='lsmrapp.DataformatChoice')), ('datatype', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.DatatypeChoice')), ], @@ -465,12 +465,12 @@ class Migration(migrations.Migration): name='SubtaskInput', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('selection_doc', django.contrib.postgres.fields.jsonb.JSONField()), - ('connector', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='lsmrapp.SubtaskConnector')), - ('dataproducts', models.ManyToManyField(to='lsmrapp.Dataproduct')), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('selection_doc', django.contrib.postgres.fields.jsonb.JSONField(help_text='Filter to apply to the dataproducts of the producer, to derive input dataproducts when scheduling.')), + ('connector', models.ForeignKey(help_text='Which connector this Task Input implements.', null=True, on_delete=django.db.models.deletion.SET_NULL, to='lsmrapp.SubtaskConnector')), + ('dataproducts', models.ManyToManyField(help_text='The Dataproducts resulting from application of the filter at time of scheduling Although the dataproducts are simply the result of applying the filter on immutable data, the filter application could change over time. We thus store the result of this filtering directly to retain which input was specified for the task..', to='lsmrapp.Dataproduct')), ], options={ 'abstract': False, @@ -480,13 +480,13 @@ class Migration(migrations.Migration): name='SubtaskInputSelectionTemplate', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), - ('version', models.CharField(max_length=128)), - ('schema', django.contrib.postgres.fields.jsonb.JSONField()), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), + ('version', models.CharField(help_text='Version of this template (with respect to other templates of the same name).', max_length=128)), + ('schema', django.contrib.postgres.fields.jsonb.JSONField(help_text='Schema for the configurable parameters needed to use this template.')), ], options={ 'abstract': False, @@ -496,11 +496,11 @@ class Migration(migrations.Migration): name='SubtaskOutput', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('connector', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='lsmrapp.SubtaskConnector')), - ('subtask', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.Subtask')), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('connector', models.ForeignKey(help_text='Which connector this Subtask Output implements.', null=True, on_delete=django.db.models.deletion.SET_NULL, to='lsmrapp.SubtaskConnector')), + ('subtask', models.ForeignKey(help_text='Subtask to which this output specification refers.', on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.Subtask')), ], options={ 'abstract': False, @@ -519,13 +519,13 @@ class Migration(migrations.Migration): name='SubtaskTemplate', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), - ('version', models.CharField(max_length=128)), - ('schema', django.contrib.postgres.fields.jsonb.JSONField()), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), + ('version', models.CharField(help_text='Version of this template (with respect to other templates of the same name).', max_length=128)), + ('schema', django.contrib.postgres.fields.jsonb.JSONField(help_text='Schema for the configurable parameters needed to use this template.')), ('queue', models.BooleanField(default=False)), ('realtime', models.BooleanField(default=False)), ], @@ -554,13 +554,13 @@ class Migration(migrations.Migration): name='TaskBlueprint', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), - ('specifications_doc', django.contrib.postgres.fields.jsonb.JSONField()), - ('do_cancel', models.BooleanField()), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), + ('specifications_doc', django.contrib.postgres.fields.jsonb.JSONField(help_text='Specifications for this task (IMMUTABLE).')), + ('do_cancel', models.BooleanField(help_text='Cancel this task.')), ], options={ 'abstract': False, @@ -570,9 +570,9 @@ class Migration(migrations.Migration): name='TaskConnectors', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), ('dataformats', models.ManyToManyField(blank=True, to='lsmrapp.DataformatChoice')), ('datatype', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.DatatypeChoice')), ], @@ -584,15 +584,15 @@ class Migration(migrations.Migration): name='TaskDraft', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), - ('specifications_doc', django.contrib.postgres.fields.jsonb.JSONField()), - ('copies', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='copied_from', to='lsmrapp.TaskDraft')), - ('copy_reason', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.CopyReasonChoice')), - ('specification_unit_draft', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.SpecificationUnitDraft')), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), + ('specifications_doc', django.contrib.postgres.fields.jsonb.JSONField(help_text='Specifications for this task.')), + ('copies', models.ForeignKey(help_text='Source reference, if we are a copy (NULLable).', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='copied_from', to='lsmrapp.TaskDraft')), + ('copy_reason', models.ForeignKey(help_text='Reason why source was copied (NULLable).', on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.CopyReasonChoice')), + ('specification_unit_draft', models.ForeignKey(help_text='Scheduling Unit draft to which this task draft belongs.', on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.SpecificationUnitDraft')), ], options={ 'abstract': False, @@ -602,12 +602,12 @@ class Migration(migrations.Migration): name='TaskRelationBlueprint', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('selection_doc', django.contrib.postgres.fields.jsonb.JSONField()), - ('consumer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='consumed_by', to='lsmrapp.TaskBlueprint')), - ('dataformat', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.DataformatChoice')), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('selection_doc', django.contrib.postgres.fields.jsonb.JSONField(help_text='Filter for selecting dataproducts from the output role.')), + ('consumer', models.ForeignKey(help_text='Task Blueprint that has the input connector.', on_delete=django.db.models.deletion.CASCADE, related_name='consumed_by', to='lsmrapp.TaskBlueprint')), + ('dataformat', models.ForeignKey(help_text='Selected data format to use.', on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.DataformatChoice')), ], options={ 'abstract': False, @@ -617,15 +617,15 @@ class Migration(migrations.Migration): name='TaskRelationDraft', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('selection_doc', django.contrib.postgres.fields.jsonb.JSONField()), - ('consumer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='consumed_by', to='lsmrapp.TaskDraft')), - ('dataformat', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.DataformatChoice')), - ('input', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='inputs_task_relation_draft', to='lsmrapp.TaskConnectors')), - ('output', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='outputs_task_relation_draft', to='lsmrapp.TaskConnectors')), - ('producer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='produced_by', to='lsmrapp.TaskDraft')), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('selection_doc', django.contrib.postgres.fields.jsonb.JSONField(help_text='Filter for selecting dataproducts from the output role.')), + ('consumer', models.ForeignKey(help_text='Task Draft that has the input connector.', on_delete=django.db.models.deletion.CASCADE, related_name='consumed_by', to='lsmrapp.TaskDraft')), + ('dataformat', models.ForeignKey(help_text='Selected data format to use. One of (MS, HDF5).', on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.DataformatChoice')), + ('input', models.ForeignKey(help_text='Input connector of consumer.', on_delete=django.db.models.deletion.CASCADE, related_name='inputs_task_relation_draft', to='lsmrapp.TaskConnectors')), + ('output', models.ForeignKey(help_text='Output connector of producer.', on_delete=django.db.models.deletion.CASCADE, related_name='outputs_task_relation_draft', to='lsmrapp.TaskConnectors')), + ('producer', models.ForeignKey(help_text='Task Draft that has the output connector. NOTE: The producer does typically, but not necessarily, belong to the same Specification Unit (or even the same Project) as the consumer.', on_delete=django.db.models.deletion.CASCADE, related_name='produced_by', to='lsmrapp.TaskDraft')), ], options={ 'abstract': False, @@ -635,14 +635,14 @@ class Migration(migrations.Migration): name='TaskTemplate', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), - ('version', models.CharField(max_length=128)), - ('schema', django.contrib.postgres.fields.jsonb.JSONField()), - ('validation_code_js', models.CharField(max_length=128)), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), + ('version', models.CharField(help_text='Version of this template (with respect to other templates of the same name).', max_length=128)), + ('schema', django.contrib.postgres.fields.jsonb.JSONField(help_text='Schema for the configurable parameters needed to use this template.')), + ('validation_code_js', models.CharField(help_text='JavaScript code for additional (complex) validation.', max_length=128)), ], options={ 'abstract': False, @@ -652,13 +652,13 @@ class Migration(migrations.Migration): name='WorkRelationSelectionTemplate', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, size=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=128)), - ('description', models.CharField(max_length=255)), - ('version', models.CharField(max_length=128)), - ('schema', django.contrib.postgres.fields.jsonb.JSONField()), + ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, help_text='User-defined search keywords for object.', size=8)), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')), + ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)), + ('description', models.CharField(help_text='A longer description of this object.', max_length=255)), + ('version', models.CharField(help_text='Version of this template (with respect to other templates of the same name).', max_length=128)), + ('schema', django.contrib.postgres.fields.jsonb.JSONField(help_text='Schema for the configurable parameters needed to use this template.')), ], options={ 'abstract': False, @@ -667,37 +667,37 @@ class Migration(migrations.Migration): migrations.AddField( model_name='taskrelationdraft', name='selection_template', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.WorkRelationSelectionTemplate'), + field=models.ForeignKey(help_text='Schema used for selection_doc.', on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.WorkRelationSelectionTemplate'), ), migrations.AddField( model_name='taskrelationblueprint', name='draft', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.TaskRelationDraft'), + field=models.ForeignKey(help_text='Task Relation Draft which this work request instantiates.', on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.TaskRelationDraft'), ), migrations.AddField( model_name='taskrelationblueprint', name='input', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='inputs_task_relation_blueprint', to='lsmrapp.TaskConnectors'), + field=models.ForeignKey(help_text='Input connector of consumer.', on_delete=django.db.models.deletion.CASCADE, related_name='inputs_task_relation_blueprint', to='lsmrapp.TaskConnectors'), ), migrations.AddField( model_name='taskrelationblueprint', name='output', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='outputs_task_relation_blueprint', to='lsmrapp.TaskConnectors'), + field=models.ForeignKey(help_text='Output connector of producer.', on_delete=django.db.models.deletion.CASCADE, related_name='outputs_task_relation_blueprint', to='lsmrapp.TaskConnectors'), ), migrations.AddField( model_name='taskrelationblueprint', name='producer', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='produced_by', to='lsmrapp.TaskBlueprint'), + field=models.ForeignKey(help_text='Task Blueprint that has the output connector.', on_delete=django.db.models.deletion.CASCADE, related_name='produced_by', to='lsmrapp.TaskBlueprint'), ), migrations.AddField( model_name='taskrelationblueprint', name='selection_template', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.WorkRelationSelectionTemplate'), + field=models.ForeignKey(help_text='Schema used for selection_doc.', on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.WorkRelationSelectionTemplate'), ), migrations.AddField( model_name='taskdraft', name='specifications_template', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.TaskTemplate'), + field=models.ForeignKey(help_text='Schema used for requirements_doc.', on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.TaskTemplate'), ), migrations.AddField( model_name='taskconnectors', @@ -717,37 +717,37 @@ class Migration(migrations.Migration): migrations.AddField( model_name='taskblueprint', name='draft', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='related_task_blueprint', to='lsmrapp.TaskDraft'), + field=models.ForeignKey(help_text='Task Draft which this task instantiates.', on_delete=django.db.models.deletion.CASCADE, related_name='related_task_blueprint', to='lsmrapp.TaskDraft'), ), migrations.AddField( model_name='taskblueprint', name='specification_unit_blueprint', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.SpecificationUnitBlueprint'), + field=models.ForeignKey(help_text='Scheduling Unit Blueprint to which this task belongs.', on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.SpecificationUnitBlueprint'), ), migrations.AddField( model_name='taskblueprint', name='specifications_template', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.TaskTemplate'), + field=models.ForeignKey(help_text='Schema used for specifications_doc (IMMUTABLE).', on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.TaskTemplate'), ), migrations.AddField( model_name='subtaskinput', name='producer', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.SubtaskOutput'), + field=models.ForeignKey(help_text='The Subtask Output providing the input dataproducts.', on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.SubtaskOutput'), ), migrations.AddField( model_name='subtaskinput', name='selection_template', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.SubtaskInputSelectionTemplate'), + field=models.ForeignKey(help_text='Schema used for selection_doc.', on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.SubtaskInputSelectionTemplate'), ), migrations.AddField( model_name='subtaskinput', name='subtask', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.Subtask'), + field=models.ForeignKey(help_text='Subtask to which this input specification refers.', on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.Subtask'), ), migrations.AddField( model_name='subtaskinput', name='task_relation_blueprint', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='lsmrapp.TaskRelationBlueprint'), + field=models.ForeignKey(help_text='Task Relation Blueprint which this Subtask Input implements (NULLable).', null=True, on_delete=django.db.models.deletion.SET_NULL, to='lsmrapp.TaskRelationBlueprint'), ), migrations.AddField( model_name='subtaskconnector', @@ -767,17 +767,17 @@ class Migration(migrations.Migration): migrations.AddField( model_name='subtask', name='specifications_template', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.SubtaskTemplate'), + field=models.ForeignKey(help_text='Schema used for specifications_doc.', on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.SubtaskTemplate'), ), migrations.AddField( model_name='subtask', name='state', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='task_states', to='lsmrapp.SubtaskStateChoice'), + field=models.ForeignKey(help_text='Subtask state (see Subtask State Machine).', on_delete=django.db.models.deletion.PROTECT, related_name='task_states', to='lsmrapp.SubtaskStateChoice'), ), migrations.AddField( model_name='subtask', name='task_blueprint', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='lsmrapp.TaskBlueprint'), + field=models.ForeignKey(help_text='Task Blueprint to which this Subtask belongs.', null=True, on_delete=django.db.models.deletion.SET_NULL, to='lsmrapp.TaskBlueprint'), ), migrations.AddField( model_name='subtask', @@ -787,37 +787,37 @@ class Migration(migrations.Migration): migrations.AddField( model_name='specificationunitdraft', name='requirements_template', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.SpecificationUnitTemplate'), + field=models.ForeignKey(help_text='Schema used for requirements_doc.', on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.SpecificationUnitTemplate'), ), migrations.AddField( model_name='specificationunitdraft', name='specification_set', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='specification_unit_drafts', to='lsmrapp.SpecificationSet'), + field=models.ForeignKey(help_text='Set to which this scheduling unit draft belongs.', on_delete=django.db.models.deletion.CASCADE, related_name='specification_unit_drafts', to='lsmrapp.SpecificationSet'), ), migrations.AddField( model_name='specificationunitblueprint', name='draft', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='related_specification_unit_blueprint', to='lsmrapp.SpecificationUnitDraft'), + field=models.ForeignKey(help_text='Scheduling Unit Draft which this run instantiates.', on_delete=django.db.models.deletion.CASCADE, related_name='related_specification_unit_blueprint', to='lsmrapp.SpecificationUnitDraft'), ), migrations.AddField( model_name='specificationunitblueprint', name='requirements_template', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.SpecificationUnitTemplate'), + field=models.ForeignKey(help_text='Schema used for requirements_doc (IMMUTABLE).', on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.SpecificationUnitTemplate'), ), migrations.AddField( model_name='specificationset', name='generator_source', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='lsmrapp.SpecificationUnitDraft'), + field=models.ForeignKey(help_text='Reference for the generator to an existing collection of specifications (NULLable).', null=True, on_delete=django.db.models.deletion.SET_NULL, to='lsmrapp.SpecificationUnitDraft'), ), migrations.AddField( model_name='specificationset', name='generator_template', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='lsmrapp.GeneratorTemplate'), + field=models.ForeignKey(help_text='Generator for the specification units in this set (NULLable).', null=True, on_delete=django.db.models.deletion.SET_NULL, to='lsmrapp.GeneratorTemplate'), ), migrations.AddField( model_name='specificationset', name='project', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='specification_sets', to='lsmrapp.Project'), + field=models.ForeignKey(help_text='Project to which this specification set belongs.', on_delete=django.db.models.deletion.PROTECT, related_name='specification_sets', to='lsmrapp.Project'), ), migrations.AddField( model_name='defaultworkrelationselectiontemplate', @@ -847,17 +847,17 @@ class Migration(migrations.Migration): migrations.AddField( model_name='dataproduct', name='feedback_template', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.DataproductFeedbackTemplate'), + field=models.ForeignKey(help_text='Schema used for feedback_doc.', on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.DataproductFeedbackTemplate'), ), migrations.AddField( model_name='dataproduct', name='producer', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.SubtaskOutput'), + field=models.ForeignKey(help_text='Subtask Output which generates this dataproduct.', on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.SubtaskOutput'), ), migrations.AddField( model_name='dataproduct', name='specifications_template', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.DataproductSpecificationsTemplate'), + field=models.ForeignKey(help_text='Schema used for specifications_doc.', on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.DataproductSpecificationsTemplate'), ), migrations.AddField( model_name='antennaset', diff --git a/SAS/LSMR/src/lsmr/lsmrapp/migrations/0003_populate.py b/SAS/LSMR/src/lsmr/lsmrapp/migrations/0003_populate.py index b22b544a0cd44c8e1f0bfdd7725cee7f36e0f604..5588234b8250ac834b236e0f8583faf869fbb340 100644 --- a/SAS/LSMR/src/lsmr/lsmrapp/migrations/0003_populate.py +++ b/SAS/LSMR/src/lsmr/lsmrapp/migrations/0003_populate.py @@ -6,7 +6,7 @@ from ..populate import * class Migration(migrations.Migration): dependencies = [ - ('lsmrapp', '0002_auto_20190425_1501'), + ('lsmrapp', '0002_auto_20190426_1408'), ] operations = [ migrations.RunPython(populate_choices) ] diff --git a/SAS/LSMR/src/lsmr/lsmrapp/models/scheduling.py b/SAS/LSMR/src/lsmr/lsmrapp/models/scheduling.py index 8ca9fafc984e6835cd23a55d7238a33010f72fd3..179e1fe04006056548890607d0c83bd25904ef0e 100644 --- a/SAS/LSMR/src/lsmr/lsmrapp/models/scheduling.py +++ b/SAS/LSMR/src/lsmr/lsmrapp/models/scheduling.py @@ -13,6 +13,10 @@ from rest_framework.serializers import HyperlinkedRelatedField # class SubtaskConnector(BasicCommon): + """ + Represents the relation between input and output of the Subtasks. Some of these relations implement the Task + Relations. An input is tied to an output of another Subtask, and allows a filter to be specified. + """ role = ForeignKey('RoleChoice', null=False, on_delete=PROTECT) datatype = ForeignKey('DatatypeChoice', null=False, on_delete=PROTECT) dataformats = ManyToManyField('DataformatChoice', blank=True) @@ -124,50 +128,61 @@ class DataproductFeedbackTemplate(Template): # class Subtask(BasicCommon): + """ + Represents a low-level task, which is an atomic unit of execution, such as running an observation, running + inspection plots on the observed data, etc. Each task has a specific configuration, will have resources allocated + to it, and represents a single run. + """ type = ForeignKey('SubtaskTypeChoice', null=False, on_delete=PROTECT) - start_time = DateTimeField() - stop_time = DateTimeField() - state = ForeignKey('SubtaskStateChoice', null=False, on_delete=PROTECT, related_name='task_states') - specifications_doc = JSONField() - task_blueprint = ForeignKey('TaskBlueprint', null=True, on_delete=SET_NULL) - specifications_template = ForeignKey('SubtaskTemplate', null=False, on_delete=PROTECT) - do_cancel = DateTimeField() - priority = IntegerField() - schedule_method = ForeignKey('ScheduleMethod', null=False, on_delete=PROTECT) - cluster = ForeignKey('Cluster', null=False, on_delete=PROTECT) - scheduler_input_doc = JSONField() + start_time = DateTimeField(help_text='Start this subtask at the specified time (NULLable).') + stop_time = DateTimeField(help_text='Stop this subtask at the specified time (NULLable).') + state = ForeignKey('SubtaskStateChoice', null=False, on_delete=PROTECT, related_name='task_states', help_text='Subtask state (see Subtask State Machine).') + specifications_doc = JSONField(help_text='Final specifications, as input for the controller.') + task_blueprint = ForeignKey('TaskBlueprint', null=True, on_delete=SET_NULL, help_text='Task Blueprint to which this Subtask belongs.') + specifications_template = ForeignKey('SubtaskTemplate', null=False, on_delete=PROTECT, help_text='Schema used for specifications_doc.') + do_cancel = DateTimeField(help_text='Timestamp when the subtask has been ordered to cancel (NULLable).') + priority = IntegerField(help_text='Absolute priority of this subtask (higher value means more important).') + schedule_method = ForeignKey('ScheduleMethod', null=False, on_delete=PROTECT, help_text='Which method to use for scheduling this Subtask. One of (MANUAL, BATCH, DYNAMIC).') + cluster = ForeignKey('Cluster', null=False, on_delete=PROTECT, help_text='Where the Subtask is scheduled to run (NULLable).') + scheduler_input_doc = JSONField(help_text='Partial specifications, as input for the scheduler.') # resource_claim = ForeignKey("ResourceClaim", null=False, on_delete=PROTECT) # todo <-- how is this external reference supposed to work? class SubtaskInput(BasicCommon): - subtask = ForeignKey('Subtask', null=False, on_delete=CASCADE) - task_relation_blueprint = ForeignKey('TaskRelationBlueprint', null=True, on_delete=SET_NULL) - connector = ForeignKey('SubtaskConnector', null=True, on_delete=SET_NULL) - producer = ForeignKey('SubtaskOutput', on_delete=PROTECT) - dataproducts = ManyToManyField('Dataproduct') - selection_doc = JSONField() - selection_template = ForeignKey('SubtaskInputSelectionTemplate', on_delete=PROTECT) + subtask = ForeignKey('Subtask', null=False, on_delete=CASCADE, help_text='Subtask to which this input specification refers.') + task_relation_blueprint = ForeignKey('TaskRelationBlueprint', null=True, on_delete=SET_NULL, help_text='Task Relation Blueprint which this Subtask Input implements (NULLable).') + connector = ForeignKey('SubtaskConnector', null=True, on_delete=SET_NULL, help_text='Which connector this Task Input implements.') + producer = ForeignKey('SubtaskOutput', on_delete=PROTECT, help_text='The Subtask Output providing the input dataproducts.') + dataproducts = ManyToManyField('Dataproduct', help_text='The Dataproducts resulting from application of the filter at time of scheduling Although the dataproducts are simply the result of applying the filter on immutable data, the filter application could change over time. We thus store the result of this filtering directly to retain which input was specified for the task..') + selection_doc = JSONField(help_text='Filter to apply to the dataproducts of the producer, to derive input dataproducts when scheduling.') + selection_template = ForeignKey('SubtaskInputSelectionTemplate', on_delete=PROTECT, help_text='Schema used for selection_doc.') class SubtaskOutput(BasicCommon): - subtask = ForeignKey('Subtask', null=False, on_delete=CASCADE) - connector = ForeignKey('SubtaskConnector', null=True, on_delete=SET_NULL) + subtask = ForeignKey('Subtask', null=False, on_delete=CASCADE, help_text='Subtask to which this output specification refers.') + connector = ForeignKey('SubtaskConnector', null=True, on_delete=SET_NULL, help_text='Which connector this Subtask Output implements.') class Dataproduct(BasicCommon): - filename = CharField(max_length=128) - directory = CharField(max_length=1024) + """ + A data product represents an atomic dataset, produced and consumed by subtasks. The consumed dataproducts are those + resulting from interpreting the Subtask Connector filters of the inputs. These links are explicitly saved, should + the interpretation of the filter change over time. The produced dataproducts enumerate everything produced by a + Subtask. + """ + filename = CharField(max_length=128, help_text='Name of the file (or top-level directory) of the dataproduct. Adheres to a naming convention, but is not meant for parsing.') + directory = CharField(max_length=1024, help_text='Directory where this dataproduct is (to be) stored.') dataformat = ForeignKey('DataformatChoice', null=False, on_delete=PROTECT) - deleted_since = DateTimeField(null=True) - pinned_since = DateTimeField(null=True) - specifications_doc = JSONField() - specifications_template = ForeignKey('DataproductSpecificationsTemplate', null=False, on_delete=CASCADE) - producer = ForeignKey('SubtaskOutput', on_delete=PROTECT) - do_cancel = DateTimeField() # BooleanField() <- after consulting JDM, we opt for datetimefield for consistency - expected_size = BigIntegerField() - size = BigIntegerField() - feedback_doc = JSONField() - feedback_template = ForeignKey('DataproductFeedbackTemplate', on_delete=PROTECT) + deleted_since = DateTimeField(null=True, help_text='When this dataproduct was removed from disk, or NULL if not deleted (NULLable).') + pinned_since = DateTimeField(null=True, help_text='When this dataproduct was pinned to disk, that is, forbidden to be removed, or NULL if not pinned (NULLable).') + specifications_doc = JSONField(help_text='Dataproduct properties (f.e. beam, subband), to distinguish them when produced by the same task, and to act as input for selections in the Task Input and Work Request Relation Blueprint objects.') + specifications_template = ForeignKey('DataproductSpecificationsTemplate', null=False, on_delete=CASCADE, help_text='Schema used for specifications_doc.') + producer = ForeignKey('SubtaskOutput', on_delete=PROTECT, help_text='Subtask Output which generates this dataproduct.') + do_cancel = DateTimeField(help_text='When this dataproduct was cancelled (NULLable). Cancelling a dataproduct triggers cleanup if necessary.') + expected_size = BigIntegerField(help_text='Expected size of dataproduct size, in bytes. Used for scheduling purposes. NULL if size is unknown (NULLable).') + size = BigIntegerField(help_text='Dataproduct size, in bytes. Used for accounting purposes. NULL if size is (yet) unknown (NULLable).') + feedback_doc = JSONField(help_text='Dataproduct properties, as reported by the producing process.') + feedback_template = ForeignKey('DataproductFeedbackTemplate', on_delete=PROTECT, help_text='Schema used for feedback_doc.') class AntennaSet(NamedCommon): @@ -177,28 +192,32 @@ class AntennaSet(NamedCommon): class DataproductTransform(BasicCommon): - input = ForeignKey('Dataproduct', related_name='inputs', on_delete=PROTECT) - output = ForeignKey('Dataproduct', related_name='outputs', on_delete=PROTECT) - identity = BooleanField() + """ + Each output dataproduct of a Subtask is linked to the input dataproducts that are used to produce it. + These transforms encode the provenance information needed when tracking dependencies between dataproducts. + """ + input = ForeignKey('Dataproduct', related_name='inputs', on_delete=PROTECT, help_text='A dataproduct that was the input of a transformation.') + output = ForeignKey('Dataproduct', related_name='outputs', on_delete=PROTECT, help_text='A dataproduct that was produced from the input dataproduct.') + identity = BooleanField(help_text='TRUE if this transform only copies, tars, or losslessly compresses its input, FALSE if the transform changes the data. Allows for efficient reasoning about data duplication.') class Filesystem(NamedCommon): - capacity = BigIntegerField() - cluster = ForeignKey('Cluster', on_delete=PROTECT) + capacity = BigIntegerField(help_text='Capacity in bytes') + cluster = ForeignKey('Cluster', on_delete=PROTECT, help_text='Cluster hosting this filesystem.') class Cluster(NamedCommon): - location = CharField(max_length=128) + location = CharField(max_length=128, help_text='Human-readable location of the cluster.') class DataproductArchiveInfo(BasicCommon): - dataproduct = ForeignKey('Dataproduct', on_delete=PROTECT) - storage_ticket = CharField(max_length=128) - public_since = DateTimeField() - corrupted_since = DateTimeField() + dataproduct = ForeignKey('Dataproduct', on_delete=PROTECT, help_text='A dataproduct residing in the archive.') + storage_ticket = CharField(max_length=128, help_text='Archive-system identifier.') + public_since = DateTimeField(help_text='Dataproduct is available for public download since this moment, or NULL if dataproduct is not (NULLable).') + corrupted_since = DateTimeField(help_text='Earliest timestamp from which this dataproduct is known to be partially or fully corrupt, or NULL if dataproduct is not known to be corrupt (NULLable).') class DataproductHash(BasicCommon): - dataproduct = ForeignKey('Dataproduct', on_delete=PROTECT) - algorithm = ForeignKey('Algorithm', null=False, on_delete=PROTECT) - hash = CharField(max_length=128) + dataproduct = ForeignKey('Dataproduct', on_delete=PROTECT, help_text='The dataproduct to which this hash refers.') + algorithm = ForeignKey('Algorithm', null=False, on_delete=PROTECT, help_text='Algorithm used (MD5, AES256).') + hash = CharField(max_length=128, help_text='Hash value.') diff --git a/SAS/LSMR/src/lsmr/lsmrapp/models/specification.py b/SAS/LSMR/src/lsmr/lsmrapp/models/specification.py index ef87c5fddfe5c6ad7ea468d41d978af1cb1af5c5..298ea44437e44cce1026835f59b3d36753c2d7a8 100644 --- a/SAS/LSMR/src/lsmr/lsmrapp/models/specification.py +++ b/SAS/LSMR/src/lsmr/lsmrapp/models/specification.py @@ -17,9 +17,9 @@ from django_json_widget.widgets import JSONEditorWidget class BasicCommon(Model): # todo: we cannot use foreign keys in the array here, so we have to keep the Tags table up to date by trigger or so. # todo: we could switch to a manytomany field instead? - tags = ArrayField(CharField(max_length=128), size=8, blank=True) - created_at = DateTimeField(auto_now_add=True) - updated_at = DateTimeField(auto_now=True) + tags = ArrayField(CharField(max_length=128), size=8, blank=True, help_text='User-defined search keywords for object.') + created_at = DateTimeField(auto_now_add=True, help_text='Moment of object creation.') + updated_at = DateTimeField(auto_now=True, help_text='Moment of last object update.') class Meta: abstract = True @@ -27,8 +27,8 @@ class BasicCommon(Model): class NamedCommon(BasicCommon): - name = CharField(max_length=128) - description = CharField(max_length=255) + name = CharField(max_length=128, help_text='Human-readable name of this object.') + description = CharField(max_length=255, help_text='A longer description of this object.') def __str__(self): return self.name @@ -102,6 +102,7 @@ class DatatypeChoice(AbstractChoice): IMAGE = "image" QUALITY = "quality" + class DataformatChoice(AbstractChoice): """Defines the model and predefined list of possible DataformatChoice's for TaskRelationDraft and TaskRelationBlueprint. The items in the Choises class below are automagically populated into the database via a data migration.""" @@ -138,8 +139,8 @@ class Template(NamedCommon): formfield_overrides = { JSONField: {'widget': JSONEditorWidget}, } - version = CharField(max_length=128) - schema = JSONField() + version = CharField(max_length=128, help_text='Version of this template (with respect to other templates of the same name).') + schema = JSONField(help_text='Schema for the configurable parameters needed to use this template.') class Meta: abstract = True @@ -148,7 +149,7 @@ class Template(NamedCommon): # concrete models class GeneratorTemplate(Template): - create_function = CharField(max_length=128) + create_function = CharField(max_length=128, help_text='Python function to call to execute the generator.') class DefaultGeneratorTemplate(BasicCommon): @@ -166,7 +167,7 @@ class DefaultSpecificationUnitTemplate(BasicCommon): class TaskTemplate(Template): - validation_code_js = CharField(max_length=128) + validation_code_js = CharField(max_length=128, help_text='JavaScript code for additional (complex) validation.') class DefaultTaskTemplate(BasicCommon): @@ -188,80 +189,80 @@ class DefaultWorkRelationSelectionTemplate(BasicCommon): # class Cycle(NamedCommon): - start = DateTimeField() - stop = DateTimeField() - number = IntegerField() - standard_hours = IntegerField() - expert_hours = IntegerField() - filler_hours = IntegerField() + start = DateTimeField(help_text='Moment at which the cycle starts, that is, when its projects can run.') + stop = DateTimeField(help_text='Moment at which the cycle officially ends.') + number = IntegerField(help_text='Cycle number.') + standard_hours = IntegerField(help_text='Number of offered hours for standard observations.') + expert_hours = IntegerField(help_text='Number of offered hours for expert observations.') + filler_hours = IntegerField(help_text='Number of offered hours for filler observations.') class Project(NamedCommon): # cycle is protected since we have to manually decide to clean up projects with a cycle or keep them without cycle - cycle = ForeignKey('Cycle', related_name='projects', on_delete=PROTECT, null=True) - priority = IntegerField(default=0) # todo: define a value for the default priority - can_trigger = BooleanField(default=False) - private_data = BooleanField(default=True) - expert = BooleanField(default=True) - filler = BooleanField(default=False) + cycle = ForeignKey('Cycle', related_name='projects', on_delete=PROTECT, null=True, help_text='Cycle(s) to which this project belongs (NULLable).') + priority = IntegerField(default=0, help_text='Priority of this project w.r.t. other projects. Projects can interrupt observations of lower-priority projects.') # todo: define a value for the default priority + can_trigger = BooleanField(default=False, help_text='True if this project is allowed to supply observation requests on the fly, possibly interrupting currently running observations (responsive telescope).') + private_data = BooleanField(default=True, help_text='True if data of this project is sensitive. Sensitive data is not made public.') + expert = BooleanField(default=True, help_text='Expert projects put more responsibility on the PI.') + filler = BooleanField(default=False, help_text='Use this project to fill up idle telescope time.') class SpecificationSet(NamedCommon): - generator_doc = JSONField() - generator_template = ForeignKey('GeneratorTemplate', on_delete=SET_NULL, null=True) - generator_source = ForeignKey('SpecificationUnitDraft', on_delete=SET_NULL, null=True) - project = ForeignKey('Project', related_name="specification_sets", on_delete=PROTECT) # protected to avoid accidents + generator_doc = JSONField(help_text='Parameters for the generator (NULLable).') + generator_template = ForeignKey('GeneratorTemplate', on_delete=SET_NULL, null=True, help_text='Generator for the specification units in this set (NULLable).') + generator_source = ForeignKey('SpecificationUnitDraft', on_delete=SET_NULL, null=True, help_text='Reference for the generator to an existing collection of specifications (NULLable).') + project = ForeignKey('Project', related_name="specification_sets", on_delete=PROTECT, help_text='Project to which this specification set belongs.') # protected to avoid accidents class SpecificationUnitDraft(NamedCommon): - requirements_doc = JSONField() - copies = ForeignKey('SpecificationUnitDraft', related_name="copied_from", on_delete=SET_NULL, null=True) - copy_reason = ForeignKey('CopyReasonChoice', null=False, on_delete=PROTECT) - generator_instance_doc = CharField(max_length=200) # todo: check if the field size is good enough - specification_set = ForeignKey(SpecificationSet, related_name='specification_unit_drafts', on_delete=CASCADE) - requirements_template = ForeignKey(SpecificationUnitTemplate, on_delete=CASCADE) + requirements_doc = JSONField(help_text='Scheduling and/or quality requirements for this run.') + copies = ForeignKey('SpecificationUnitDraft', related_name="copied_from", on_delete=SET_NULL, null=True, help_text='Source reference, if we are a copy (NULLable).') + copy_reason = ForeignKey('CopyReasonChoice', on_delete=PROTECT, help_text='Reason why source was copied (NULLable).') + generator_instance_doc = CharField(max_length=200, help_text='Parameter value that generated this run draft (NULLable).') # todo: check if the field size is good enough + specification_set = ForeignKey(SpecificationSet, related_name='specification_unit_drafts', on_delete=CASCADE, help_text='Set to which this scheduling unit draft belongs.') + requirements_template = ForeignKey(SpecificationUnitTemplate, on_delete=CASCADE, help_text='Schema used for requirements_doc.') # todo: 'schema'? class SpecificationUnitBlueprint(NamedCommon): - requirements_doc = JSONField() + requirements_doc = JSONField(help_text='Scheduling and/or quality requirements for this scheduling unit (IMMUTABLE).') do_cancel = BooleanField() - requirements_template = ForeignKey('SpecificationUnitTemplate', on_delete=CASCADE) - draft = ForeignKey('SpecificationUnitDraft', related_name='related_specification_unit_blueprint', on_delete=CASCADE) + requirements_template = ForeignKey('SpecificationUnitTemplate', on_delete=CASCADE, help_text='Schema used for requirements_doc (IMMUTABLE).') + draft = ForeignKey('SpecificationUnitDraft', related_name='related_specification_unit_blueprint', on_delete=CASCADE, help_text='Scheduling Unit Draft which this run instantiates.') class TaskDraft(NamedCommon): - specifications_doc = JSONField() - copies = ForeignKey('TaskDraft', related_name="copied_from", on_delete=SET_NULL, null=True) - copy_reason = ForeignKey('CopyReasonChoice', null=False, on_delete=PROTECT) - specification_unit_draft = ForeignKey(SpecificationUnitDraft, on_delete=CASCADE) - specifications_template = ForeignKey('TaskTemplate', on_delete=CASCADE) + specifications_doc = JSONField(help_text='Specifications for this task.') + copies = ForeignKey('TaskDraft', related_name="copied_from", on_delete=SET_NULL, null=True, help_text='Source reference, if we are a copy (NULLable).') + copy_reason = ForeignKey('CopyReasonChoice', on_delete=PROTECT, help_text='Reason why source was copied (NULLable).') + specification_unit_draft = ForeignKey(SpecificationUnitDraft, on_delete=CASCADE, help_text='Scheduling Unit draft to which this task draft belongs.') + specifications_template = ForeignKey('TaskTemplate', on_delete=CASCADE, help_text='Schema used for requirements_doc.') # todo: 'schema'? class TaskBlueprint(NamedCommon): - specifications_doc = JSONField() - do_cancel = BooleanField() - specifications_template = ForeignKey('TaskTemplate', on_delete=CASCADE) - draft = ForeignKey('TaskDraft', related_name='related_task_blueprint', on_delete=CASCADE) - specification_unit_blueprint = ForeignKey('SpecificationUnitBlueprint', on_delete=CASCADE) + specifications_doc = JSONField(help_text='Specifications for this task (IMMUTABLE).') + do_cancel = BooleanField(help_text='Cancel this task.') + specifications_template = ForeignKey('TaskTemplate', on_delete=CASCADE, help_text='Schema used for specifications_doc (IMMUTABLE).') + draft = ForeignKey('TaskDraft', related_name='related_task_blueprint', on_delete=CASCADE, help_text='Task Draft which this task instantiates.') + specification_unit_blueprint = ForeignKey('SpecificationUnitBlueprint', on_delete=CASCADE, help_text='Scheduling Unit Blueprint to which this task belongs.') class TaskRelationDraft(BasicCommon): - selection_doc = JSONField() - dataformat = ForeignKey('DataformatChoice', null=False, on_delete=PROTECT) - producer = ForeignKey(TaskDraft, related_name='produced_by', on_delete=CASCADE) - consumer = ForeignKey(TaskDraft, related_name='consumed_by', on_delete=CASCADE) - input = ForeignKey(TaskConnectors, related_name='inputs_task_relation_draft', on_delete=CASCADE) - output = ForeignKey(TaskConnectors, related_name='outputs_task_relation_draft', on_delete=CASCADE) - selection_template = ForeignKey(WorkRelationSelectionTemplate, on_delete=CASCADE) + selection_doc = JSONField(help_text='Filter for selecting dataproducts from the output role.') + dataformat = ForeignKey('DataformatChoice', null=False, on_delete=PROTECT, help_text='Selected data format to use. One of (MS, HDF5).') + producer = ForeignKey(TaskDraft, related_name='produced_by', on_delete=CASCADE, help_text='Task Draft that has the output connector. NOTE: The producer does typically, but not necessarily, belong to the same Specification Unit (or even the same Project) as the consumer.') + consumer = ForeignKey(TaskDraft, related_name='consumed_by', on_delete=CASCADE, help_text='Task Draft that has the input connector.') + input = ForeignKey(TaskConnectors, related_name='inputs_task_relation_draft', on_delete=CASCADE, help_text='Input connector of consumer.') + output = ForeignKey(TaskConnectors, related_name='outputs_task_relation_draft', on_delete=CASCADE, help_text='Output connector of producer.') + selection_template = ForeignKey(WorkRelationSelectionTemplate, on_delete=CASCADE, help_text='Schema used for selection_doc.') # todo: 'schema'? class TaskRelationBlueprint(BasicCommon): - selection_doc = JSONField() - dataformat = ForeignKey('DataformatChoice', null=False, on_delete=PROTECT) - producer = ForeignKey(TaskBlueprint, related_name='produced_by', on_delete=CASCADE) - consumer = ForeignKey(TaskBlueprint, related_name='consumed_by', on_delete=CASCADE) - input = ForeignKey(TaskConnectors, related_name='inputs_task_relation_blueprint', on_delete=CASCADE) - output = ForeignKey(TaskConnectors, related_name='outputs_task_relation_blueprint', on_delete=CASCADE) - draft = ForeignKey(TaskRelationDraft, on_delete=CASCADE) - selection_template = ForeignKey(WorkRelationSelectionTemplate, on_delete=CASCADE) + selection_doc = JSONField(help_text='Filter for selecting dataproducts from the output role.') + dataformat = ForeignKey('DataformatChoice', null=False, on_delete=PROTECT, help_text='Selected data format to use.') + producer = ForeignKey(TaskBlueprint, related_name='produced_by', on_delete=CASCADE, help_text='Task Blueprint that has the output connector.') + consumer = ForeignKey(TaskBlueprint, related_name='consumed_by', on_delete=CASCADE, help_text='Task Blueprint that has the input connector.') + input = ForeignKey(TaskConnectors, related_name='inputs_task_relation_blueprint', on_delete=CASCADE, help_text='Input connector of consumer.') + output = ForeignKey(TaskConnectors, related_name='outputs_task_relation_blueprint', on_delete=CASCADE, help_text='Output connector of producer.') + draft = ForeignKey(TaskRelationDraft, on_delete=CASCADE, help_text='Task Relation Draft which this work request instantiates.') + selection_template = ForeignKey(WorkRelationSelectionTemplate, on_delete=CASCADE, help_text='Schema used for selection_doc.') # todo: 'schema'?