--- /dev/null
+##############################################################################
+# Copyright (c) 2020 Sean Smith and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+from django.contrib import admin
+from analytics.models import ActiveVPNUser
+
+admin.site.register(ActiveVPNUser)
--- /dev/null
+##############################################################################
+# Copyright (c) 2020 Sean Smith and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+from django.apps import AppConfig
+
+
+class AnalyticsConfig(AppConfig):
+ name = 'analytics'
--- /dev/null
+# Generated by Django 2.2 on 2020-08-10 20:10
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='ActiveVPNUsers',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('time_stamp', models.DateTimeField(auto_now_add=True)),
+ ('active_users', models.IntegerField()),
+ ],
+ ),
+ ]
--- /dev/null
+# Generated by Django 2.2 on 2020-11-09 21:49
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('account', '0006_auto_20201109_1947'),
+ ('analytics', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='ActiveVPNUser',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('time_stamp', models.DateTimeField(auto_now_add=True)),
+ ('active_users', models.IntegerField()),
+ ('lab', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='account.Lab')),
+ ],
+ ),
+ migrations.DeleteModel(
+ name='ActiveVPNUsers',
+ ),
+ ]
--- /dev/null
+##############################################################################
+# Copyright (c) 2020 Sean Smith and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+from django.db import models
+from account.models import Lab
+
+
+class ActiveVPNUser(models.Model):
+ """ Keeps track of how many VPN Users are connected to Lab """
+ time_stamp = models.DateTimeField(auto_now_add=True)
+ lab = models.ForeignKey(Lab, on_delete=models.CASCADE, null=False)
+ active_users = models.IntegerField()
+
+ @classmethod
+ def create(cls, lab_name, active_users):
+ """
+ This creates an Active VPN Users entry from
+ from lab_name as a string
+ """
+
+ lab = Lab.objects.get(name=lab_name)
+ avu = cls(lab=lab, active_users=active_users)
+ avu.save()
+ return avu
--- /dev/null
+##############################################################################
+# Copyright (c) 2020 Sean Smith and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+# from django.test import TestCase
--- /dev/null
+##############################################################################
+# Copyright (c) 2020 Sean Smith and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+# from django.shortcuts import render
--- /dev/null
+# Generated by Django 2.2 on 2020-11-09 21:49
+
+import api.models
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0015_auto_20201109_1947'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='ActiveUsersConfig',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ],
+ ),
+ migrations.AddField(
+ model_name='job',
+ name='job_type',
+ field=models.CharField(choices=[('BOOK', 'Booking'), ('DATA', 'Analytics')], default='BOOK', max_length=4),
+ ),
+ migrations.CreateModel(
+ name='ActiveUsersRelation',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('status', models.IntegerField(default=0)),
+ ('task_id', models.CharField(default=api.models.get_task_uuid, max_length=37)),
+ ('lab_token', models.CharField(default='null', max_length=50)),
+ ('message', models.TextField(default='')),
+ ('config', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='api.ActiveUsersConfig')),
+ ('job', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Job')),
+ ],
+ options={
+ 'abstract': False,
+ },
+ ),
+ ]
return self.serialize_jobs(jobs, status=JobStatus.DONE)
+ def get_analytics_job(self):
+ """ Get analytics job with status new """
+ jobs = Job.objects.filter(
+ booking__lab=self.lab,
+ job_type='DATA'
+ )
+
+ return self.serialize_jobs(jobs, status=JobStatus.NEW)
+
def get_job(self, jobid):
return Job.objects.get(pk=jobid).to_dict()
This is the class that is serialized and put into the api
"""
+ JOB_TYPES = (
+ ('BOOK', 'Booking'),
+ ('DATA', 'Analytics')
+ )
+
booking = models.OneToOneField(Booking, on_delete=models.CASCADE, null=True)
status = models.IntegerField(default=JobStatus.NEW)
complete = models.BooleanField(default=False)
+ job_type = models.CharField(
+ max_length=4,
+ choices=JOB_TYPES,
+ default='BOOK'
+ )
def to_dict(self):
d = {}
return json.dumps(self.to_dict())
+class ActiveUsersConfig(models.Model):
+ """
+ Task for getting active VPN users
+
+ StackStorm needs no information to run this job
+ so this task is very bare, but neccessary to fit
+ job creation convention.
+ """
+
+ def clear_delta(self):
+ self.delta = '{}'
+
+ def get_delta(self):
+ return json.loads(self.to_json())
+
+ def to_json(self):
+ return json.dumps(self.to_dict())
+
+ def to_dict(self):
+ return {}
+
+
class OpnfvApiConfig(models.Model):
installer = models.CharField(max_length=200)
return super(self.__class__, self).delete(*args, **kwargs)
+class ActiveUsersRelation(TaskRelation):
+ config = models.OneToOneField(ActiveUsersConfig, on_delete=models.CASCADE)
+ job_key = "active users task"
+
+ def type_str(self):
+ return "Active Users Task"
+
+
class JobFactory(object):
"""This class creates all the API models (jobs, tasks, etc) needed to fulfill a booking."""
config.set_host(host)
config.save()
+ @classmethod
+ def makeActiveUsersTask(cls):
+ """ Append active users task to analytics job """
+ config = ActiveUsersConfig()
+ relation = ActiveUsersRelation()
+ job = Job.objects.get(job_type='DATA')
+
+ job.status = JobStatus.NEW
+
+ relation.job = job
+ relation.config = config
+ relation.config.save()
+ relation.config = relation.config
+ relation.save()
+ config.save()
+
+ @classmethod
+ def makeAnalyticsJob(cls, booking):
+ """
+ Create the analytics job
+
+ This will only run once since there will only be one analytics job.
+ All analytics tasks get appended to analytics job.
+ """
+
+ if len(Job.objects.filter(job_type='DATA')) > 0:
+ raise Exception("Cannot have more than one analytics job")
+
+ if booking.resource:
+ raise Exception("Booking is not marker for analytics job, has resoure")
+
+ job = Job()
+ job.booking = booking
+ job.job_type = 'DATA'
+ job.save()
+
+ cls.makeActiveUsersTask()
+
@classmethod
def makeCompleteJob(cls, booking):
"""Create everything that is needed to fulfill the given booking."""
AccessRelation,
HostNetworkRelation,
SoftwareRelation,
- SnapshotRelation
+ SnapshotRelation,
+ ActiveUsersRelation
]
get_idf,
lab_users,
lab_user,
- GenerateTokenView
+ GenerateTokenView,
+ analytics_job
)
urlpatterns = [
path('labs/<slug:lab_name>/jobs/new', new_jobs),
path('labs/<slug:lab_name>/jobs/current', current_jobs),
path('labs/<slug:lab_name>/jobs/done', done_jobs),
+ path('labs/<slug:lab_name>/jobs/getByType/DATA', analytics_job),
path('labs/<slug:lab_name>/users', lab_users),
path('labs/<slug:lab_name>/users/<int:user_id>', lab_user),
url(r'^token$', GenerateTokenView.as_view(), name='generate_token'),
from rest_framework import viewsets
from rest_framework.authtoken.models import Token
from django.views.decorators.csrf import csrf_exempt
+from django.core.exceptions import ObjectDoesNotExist
from api.serializers.booking_serializer import BookingSerializer
from api.serializers.old_serializers import UserSerializer
from booking.models import Booking
from api.models import LabManagerTracker, get_task
from notifier.manager import NotificationHandler
+from analytics.models import ActiveVPNUser
+import json
"""
API views.
return JsonResponse(lab_manager.get_current_jobs(), safe=False)
+@csrf_exempt
+def analytics_job(request, lab_name=""):
+ """ returns all jobs with type booking"""
+ lab_token = request.META.get('HTTP_AUTH_TOKEN')
+ lab_manager = LabManagerTracker.get(lab_name, lab_token)
+ if request.method == "GET":
+ return JsonResponse(lab_manager.get_analytics_job(), safe=False)
+ if request.method == "POST":
+ users = json.loads(request.body.decode('utf-8'))['active_users']
+ try:
+ ActiveVPNUser.create(lab_name, users)
+ except ObjectDoesNotExist:
+ return JsonResponse('Lab does not exist!', safe=False)
+ return HttpResponse(status=200)
+ return HttpResponse(status=405)
+
+
def lab_downtime(request, lab_name=""):
lab_token = request.META.get('HTTP_AUTH_TOKEN')
lab_manager = LabManagerTracker.get(lab_name, lab_token)
from django.utils import timezone
from booking.models import Booking
from notifier.manager import NotificationHandler
-from api.models import Job, JobStatus, SoftwareRelation, HostHardwareRelation, HostNetworkRelation, AccessRelation
+from api.models import (
+ Job,
+ JobStatus,
+ SoftwareRelation,
+ HostHardwareRelation,
+ HostNetworkRelation,
+ AccessRelation,
+ JobFactory
+)
+
+from resource_inventory.resource_manager import ResourceManager
from resource_inventory.models import ConfigState
resource__isnull=False
)
for booking in bookings:
- booking.resource.release()
+ ResourceManager.getInstance().deleteResourceBundle(booking.resource)
+
+
+@shared_task
+def query_vpn_users():
+ """ get active vpn users """
+ JobFactory.makeActiveUsersTask()
'notifier',
'workflow',
'api',
+ 'analytics',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'task': 'notifier.tasks.notify_expiring',
'schedule': timedelta(hours=1)
},
+ 'query_vpn_users': {
+ 'task': 'dashboard.tasks.query_vpn_users',
+ 'schedule': timedelta(hours=1)
+ }
}
# Notifier Settings