Browse Source

A lot of updates

master
Joshua Rubingh 10 months ago
parent
commit
2b649ce046
  1. 2
      .gitignore
  2. 4
      VRE/apps/storage/models.py
  3. 18
      VRE/apps/study/migrations/0003_alter_studyrole_active.py
  4. 18
      VRE/apps/study/migrations/0004_alter_studyrole_active.py
  5. 18
      VRE/apps/study/migrations/0005_alter_studyrole_active.py
  6. 18
      VRE/apps/study/migrations/0006_alter_studyrole_active.py
  7. 18
      VRE/apps/study/migrations/0007_alter_studyrole_active.py
  8. 6
      VRE/apps/study/models.py
  9. 8
      VRE/apps/vrw/admin.py
  10. 26
      VRE/apps/vrw/migrations/0004_workspacequeue.py
  11. 18
      VRE/apps/vrw/migrations/0005_workspacequeue_status.py
  12. 17
      VRE/apps/vrw/migrations/0006_remove_workspacequeue_status.py
  13. 17
      VRE/apps/vrw/migrations/0007_alter_workspacequeue_options.py
  14. 29
      VRE/apps/vrw/models.py
  15. 21
      VRE/apps/vrw/serializers.py
  16. 31
      VRE/apps/vrw/signals.py
  17. 12
      VRE/apps/vrw/views.py

2
.gitignore vendored

@ -142,3 +142,5 @@ dmypy.json @@ -142,3 +142,5 @@ dmypy.json
# Cython debug symbols
cython_debug/
VRE/test.py
VRE/db.sqlite3.org

4
VRE/apps/storage/models.py

@ -128,8 +128,10 @@ class StorageLocation(MetaDataModel): @@ -128,8 +128,10 @@ class StorageLocation(MetaDataModel):
encryption_password = encrypt(models.CharField(_('Encryption password'), default=generate_encryption_key, max_length=100, blank=True, help_text=_('Password for encryption the uploaded data. Leave empty to disable encryption.')))
def researcher(self):
return self.study.researcher
# TODO: Find the researcher based on the StudyRole -> admin
return self.study.owner
def encrypted(self):
"""boolean: Returns true when the storage has encryption enabled."""

18
VRE/apps/study/migrations/0003_alter_studyrole_active.py

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
# Generated by Django 3.2 on 2021-07-06 07:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('study', '0002_alter_studyrole_active'),
]
operations = [
migrations.AlterField(
model_name='studyrole',
name='active',
field=models.BooleanField(default=True, help_text='', verbose_name='Active'),
),
]

18
VRE/apps/study/migrations/0004_alter_studyrole_active.py

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
# Generated by Django 3.2 on 2021-07-06 11:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('study', '0003_alter_studyrole_active'),
]
operations = [
migrations.AlterField(
model_name='studyrole',
name='active',
field=models.BooleanField(default=True, help_text='', verbose_name='Active'),
),
]

18
VRE/apps/study/migrations/0005_alter_studyrole_active.py

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
# Generated by Django 3.2 on 2021-07-06 11:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('study', '0004_alter_studyrole_active'),
]
operations = [
migrations.AlterField(
model_name='studyrole',
name='active',
field=models.BooleanField(default=True, help_text='', verbose_name='Active'),
),
]

18
VRE/apps/study/migrations/0006_alter_studyrole_active.py

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
# Generated by Django 3.2 on 2021-09-17 09:29
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('study', '0005_alter_studyrole_active'),
]
operations = [
migrations.AlterField(
model_name='studyrole',
name='active',
field=models.BooleanField(default=True, help_text='', verbose_name='Active'),
),
]

18
VRE/apps/study/migrations/0007_alter_studyrole_active.py

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
# Generated by Django 3.2 on 2021-09-17 09:30
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('study', '0006_alter_studyrole_active'),
]
operations = [
migrations.AlterField(
model_name='studyrole',
name='active',
field=models.BooleanField(default=True, help_text='', verbose_name='Active'),
),
]

6
VRE/apps/study/models.py

@ -31,9 +31,9 @@ class StudyManager(models.Manager): @@ -31,9 +31,9 @@ class StudyManager(models.Manager):
This will overrule/alter the existing queryset.
"""
return super().get_queryset().select_related('storagelocation').annotate(
_total_files=Count('files', distinct=True),
_total_file_size=Sum('files__filesize', distinct=True),
_total_invitations=Count('invitations', distinct=True),
_total_files=Count('files', distinct=True),
_total_file_size=Sum('files__filesize', distinct=True),
_total_invitations=Count('invitations', distinct=True),
)
class StudyRoleNames(models.TextChoices):

8
VRE/apps/vrw/admin.py

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
from django.contrib import admin
from .models import WorkspacePart, Workspace
from .models import WorkspacePart, Workspace, WorkspaceQueue
from lib.models.admin import VMRelatedSelectWidget
# Register your models here.
@ -21,4 +21,10 @@ class VRWPartAdmin(admin.ModelAdmin): @@ -21,4 +21,10 @@ class VRWPartAdmin(admin.ModelAdmin):
class VRWWorkspaceAdmin(admin.ModelAdmin):
list_display = ('virtual_machine', 'created_at')
ordering = ('-created_at', )
readonly_fields = ('created_at', 'updated_at')
@admin.register(WorkspaceQueue)
class VRWWorkspaceQueueAdmin(admin.ModelAdmin):
list_display = ('study', 'researcher', 'status', 'created_at')
ordering = ('-created_at', )
readonly_fields = ('created_at', 'updated_at')

26
VRE/apps/vrw/migrations/0004_workspacequeue.py

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
# Generated by Django 3.2 on 2021-07-06 07:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('vrw', '0003_alter_workspace_status'),
]
operations = [
migrations.CreateModel(
name='WorkspaceQueue',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True, help_text='The date and time this model has been created', verbose_name='Date created')),
('updated_at', models.DateTimeField(auto_now=True, help_text='The date and time this model has been updated', verbose_name='Date updated')),
('data', models.JSONField(help_text='JSON Data for VRW agent', verbose_name='Data')),
],
options={
'verbose_name': 'virtual workspace queue',
'verbose_name_plural': 'virtual workspace queues',
},
),
]

18
VRE/apps/vrw/migrations/0005_workspacequeue_status.py

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
# Generated by Django 3.2 on 2021-07-06 11:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('vrw', '0004_workspacequeue'),
]
operations = [
migrations.AddField(
model_name='workspacequeue',
name='status',
field=models.CharField(choices=[('NEW', 'New'), ('CHANGE', 'Change'), ('DONE', 'Done'), ('ERROR', 'Error'), ('OFFLINE', 'Offline'), ('DELETE', 'Delete'), ('TERMINATED', 'Terminated')], default='NEW', help_text='The status of the workspace.', max_length=10, verbose_name='Status'),
),
]

17
VRE/apps/vrw/migrations/0006_remove_workspacequeue_status.py

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
# Generated by Django 3.2 on 2021-07-06 11:42
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('vrw', '0005_workspacequeue_status'),
]
operations = [
migrations.RemoveField(
model_name='workspacequeue',
name='status',
),
]

17
VRE/apps/vrw/migrations/0007_alter_workspacequeue_options.py

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
# Generated by Django 3.2 on 2021-09-17 09:29
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('vrw', '0006_remove_workspacequeue_status'),
]
operations = [
migrations.AlterModelOptions(
name='workspacequeue',
options={'verbose_name': 'virtual workspace queue', 'verbose_name_plural': 'virtual workspace queue'},
),
]

29
VRE/apps/vrw/models.py

@ -2,6 +2,7 @@ from django.db import models @@ -2,6 +2,7 @@ from django.db import models
from django.utils.translation import gettext_lazy as _
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from apps.study.models import StudyRoleNames
from lib.models.base import MetaDataModel
from lib.models.cloud import CloudBasicDataModel
@ -124,7 +125,31 @@ class Workspace(MetaDataModel, CloudBasicDataModel): @@ -124,7 +125,31 @@ class Workspace(MetaDataModel, CloudBasicDataModel):
except WorkspacePart.DoesNotExist:
return self.virtual_machine.profile.name
# TODO: We need to speed up this query...
# TODO: We need to speed up this query... And we do not want the 'owner' role here...
@property
def role(self):
return self.virtual_machine.study.studyrole_set.get(researcher=self.virtual_machine.researcher).role
return self.virtual_machine.study.studyrole_set.filter(researcher=self.virtual_machine.researcher).exclude(role=StudyRoleNames.OWNER).first().role
class WorkspaceQueue(MetaDataModel):
class Meta:
verbose_name = _('virtual workspace queue')
verbose_name_plural = _('virtual workspace queue')
data = models.JSONField(_('Data'), help_text=_('JSON Data for VRW agent'))
@property
def status(self):
return self.data['status']
@property
def cloud_id(self):
return self.data['cloud_id']
@property
def study(self):
return self.data['study']['name']
@property
def researcher(self):
return f"{self.data['researcher']['first_name']} {self.data['researcher']['last_name']}"

21
VRE/apps/vrw/serializers.py

@ -106,7 +106,22 @@ class WorkspaceStatusUpdateSerializer(serializers.Serializer): @@ -106,7 +106,22 @@ class WorkspaceStatusUpdateSerializer(serializers.Serializer):
Returns:
VirtualWorkspace: The :term:`VRW` object with the new status and optional remote id.
"""
instance.status = validated_data.get('status', instance.status)
instance.cloud_id = validated_data.get('cloud_id', instance.cloud_id)
# Update the Queue model
instance.data['status'] = validated_data.get('status', instance.data['status'])
instance.data['cloud_id'] = validated_data.get('cloud_id', instance.data['cloud_id'])
instance.save()
return instance
# Update workspace data
workspace = Workspace.objects.get(pk=instance.data['vrw_workspace_id'])
workspace.status = instance.data['status']
workspace.cloud_id = instance.data['cloud_id']
workspace.save()
return instance
class WorkspaceQueueSerializer(serializers.Serializer):
id = serializers.IntegerField(source='pk', read_only=True)
workspace = serializers.JSONField(source='data', read_only=True)

31
VRE/apps/vrw/signals.py

@ -1,11 +1,12 @@ @@ -1,11 +1,12 @@
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.db.models.signals import post_save
from django.db.models.signals import post_delete, post_save
from django.dispatch import receiver
from django.utils import timezone
from apps.virtual_machine.models import VirtualMachine
from .models import Workspace, WorkspacePart
from .models import Workspace, WorkspacePart, WorkspaceQueue
from .serializers import WorkspaceSerializer
@receiver(post_save, sender=VirtualMachine)
def create_virtual_machine_vrw(sender, instance, created, **kwargs):
@ -30,6 +31,30 @@ def create_virtual_machine_vrw(sender, instance, created, **kwargs): @@ -30,6 +31,30 @@ def create_virtual_machine_vrw(sender, instance, created, **kwargs):
new_workspace = Workspace(virtual_machine=instance, starting_at=timezone.now(), ending_at=timezone.now() + settings.VRW_MACHINE_ACTIVE_DURATION)
new_workspace.save()
serializer = WorkspaceSerializer(new_workspace)
workspace_queue_data = serializer.data
# Rename a field so it is easier to see what kind of ID this is.
workspace_queue_data['vrw_workspace_id'] = workspace_queue_data['id']
del(workspace_queue_data['id'])
# Create a new VRW queue model for the VRW Agent
WorkspaceQueue.objects.create(data=workspace_queue_data)
except WorkspacePart.DoesNotExist:
# Not a Windows Operating system, so ignore here
pass
pass
@receiver(post_delete, sender=Workspace)
def delete_virtual_machine_vrw(sender, instance, **kwargs):
serializer = WorkspaceSerializer(instance)
workspace_queue_data = serializer.data
# Rename a field so it is easier to see what kind of ID this is.
workspace_queue_data['vrw_workspace_id'] = workspace_queue_data['id']
del(workspace_queue_data['id'])
workspace_queue_data['status'] = 'DELETE'
# Create a new VRW queue model for the VRW Agent
WorkspaceQueue.objects.create(data=workspace_queue_data)

12
VRE/apps/vrw/views.py

@ -2,8 +2,8 @@ from rest_framework import generics @@ -2,8 +2,8 @@ from rest_framework import generics
from rest_framework.exceptions import NotFound
from .permissions import IsVRWAPIUser
from .models import Workspace, WorkspaceStatus
from .serializers import WorkspaceSerializer, WorkspaceStatusUpdateSerializer
from .models import Workspace, WorkspaceStatus, WorkspaceQueue
from .serializers import WorkspaceSerializer, WorkspaceStatusUpdateSerializer, WorkspaceQueueSerializer
# Create your views here.
class WorkspaceStatusUpdate(generics.UpdateAPIView):
@ -12,7 +12,7 @@ class WorkspaceStatusUpdate(generics.UpdateAPIView): @@ -12,7 +12,7 @@ class WorkspaceStatusUpdate(generics.UpdateAPIView):
"""
permission_classes = [IsVRWAPIUser]
queryset = Workspace.objects.all()
queryset = WorkspaceQueue.objects.all()
serializer_class = WorkspaceStatusUpdateSerializer
http_method_names = ['put']
@ -33,7 +33,7 @@ class WorkspaceList(generics.ListAPIView): @@ -33,7 +33,7 @@ class WorkspaceList(generics.ListAPIView):
"""
permission_classes = [IsVRWAPIUser]
serializer_class = WorkspaceSerializer
serializer_class = WorkspaceQueueSerializer
def get_queryset(self):
"""
@ -45,7 +45,7 @@ class WorkspaceList(generics.ListAPIView): @@ -45,7 +45,7 @@ class WorkspaceList(generics.ListAPIView):
Returns:
list: A list of :term:`VRW` items based on `status`
"""
objects = Workspace.objects
objects = WorkspaceQueue.objects
status_filter = self.kwargs.get('status', None)
if status_filter is not None:
@ -55,7 +55,7 @@ class WorkspaceList(generics.ListAPIView): @@ -55,7 +55,7 @@ class WorkspaceList(generics.ListAPIView):
# Invalid status state
raise NotFound(f'Status filter \'{status_filter}\' is not a valid filter.')
objects = objects.filter(status=status_filter)
objects = objects.filter(data__status=status_filter)
return objects.order_by('created_at')

Loading…
Cancel
Save