summaryrefslogtreecommitdiffstats
path: root/dashboard
diff options
context:
space:
mode:
authorParker Berberian <pberberian@iol.unh.edu>2019-05-08 17:00:01 +0000
committerGerrit Code Review <gerrit@opnfv.org>2019-05-08 17:00:01 +0000
commite4d40617fd6ebc6ef255ff9d00f586261c1d309f (patch)
tree51a74cb1d218a8c03d389b2e844355961fe97c29 /dashboard
parent0cc66d9fa833f12c23bfe7cf79d8276ef68a8cf7 (diff)
parentb906ab1a020858d99577bd4b6476c6aec965330b (diff)
Merge "Adds pdf and idf into api"
Diffstat (limited to 'dashboard')
-rw-r--r--dashboard/src/api/migrations/0007_auto_20190417_1511.py25
-rw-r--r--dashboard/src/api/migrations/0008_auto_20190419_1414.py28
-rw-r--r--dashboard/src/api/migrations/0009_merge_20190508_1317.py14
-rw-r--r--dashboard/src/api/models.py92
-rw-r--r--dashboard/src/api/urls.py4
-rw-r--r--dashboard/src/api/views.py14
-rw-r--r--dashboard/src/resource_inventory/idf_templater.py15
7 files changed, 180 insertions, 12 deletions
diff --git a/dashboard/src/api/migrations/0007_auto_20190417_1511.py b/dashboard/src/api/migrations/0007_auto_20190417_1511.py
new file mode 100644
index 0000000..e7d2c59
--- /dev/null
+++ b/dashboard/src/api/migrations/0007_auto_20190417_1511.py
@@ -0,0 +1,25 @@
+# Generated by Django 2.1 on 2019-04-17 15:11
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0006_auto_20190313_1729'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='opnfvapiconfig',
+ name='idf',
+ field=models.CharField(default='', max_length=100),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name='opnfvapiconfig',
+ name='pdf',
+ field=models.CharField(default='', max_length=100),
+ preserve_default=False,
+ ),
+ ]
diff --git a/dashboard/src/api/migrations/0008_auto_20190419_1414.py b/dashboard/src/api/migrations/0008_auto_20190419_1414.py
new file mode 100644
index 0000000..03c3865
--- /dev/null
+++ b/dashboard/src/api/migrations/0008_auto_20190419_1414.py
@@ -0,0 +1,28 @@
+# Generated by Django 2.1 on 2019-04-19 14:14
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('resource_inventory', '0009_auto_20190315_1757'),
+ ('api', '0007_auto_20190417_1511'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='BridgeConfig',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('interfaces', models.ManyToManyField(to='resource_inventory.Interface')),
+ ('opnfv_config', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='resource_inventory.OPNFVConfig')),
+ ],
+ ),
+ migrations.AddField(
+ model_name='opnfvapiconfig',
+ name='bridge_config',
+ field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to='api.BridgeConfig'),
+ ),
+ ]
diff --git a/dashboard/src/api/migrations/0009_merge_20190508_1317.py b/dashboard/src/api/migrations/0009_merge_20190508_1317.py
new file mode 100644
index 0000000..1a34380
--- /dev/null
+++ b/dashboard/src/api/migrations/0009_merge_20190508_1317.py
@@ -0,0 +1,14 @@
+# Generated by Django 2.1 on 2019-05-08 13:17
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0008_auto_20190419_1414'),
+ ('api', '0007_opnfvapiconfig_opnfv_config'),
+ ]
+
+ operations = [
+ ]
diff --git a/dashboard/src/api/models.py b/dashboard/src/api/models.py
index c165454..1f708ae 100644
--- a/dashboard/src/api/models.py
+++ b/dashboard/src/api/models.py
@@ -12,6 +12,7 @@ from django.contrib.auth.models import User
from django.db import models
from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404
+from django.urls import reverse
import json
import uuid
@@ -23,6 +24,7 @@ from resource_inventory.models import (
Host,
Image,
Interface,
+ HostOPNFVConfig,
RemoteInfo,
OPNFVConfig
)
@@ -98,6 +100,14 @@ class LabManager(object):
booking.idf = IDFTemplater().makeIDF(booking)
booking.save()
+ def get_pdf(self, booking_id):
+ booking = get_object_or_404(Booking, pk=booking_id, lab=self.lab)
+ return booking.pdf
+
+ def get_idf(self, booking_id):
+ booking = get_object_or_404(Booking, pk=booking_id, lab=self.lab)
+ return booking.idf
+
def get_profile(self):
prof = {}
prof['name'] = self.lab.name
@@ -351,11 +361,44 @@ class TaskConfig(models.Model):
self.delta = '{}'
+class BridgeConfig(models.Model):
+ """
+ Displays mapping between jumphost interfaces and
+ bridges
+ """
+ interfaces = models.ManyToManyField(Interface)
+ opnfv_config = models.ForeignKey(OPNFVConfig, on_delete=models.CASCADE)
+
+ def to_dict(self):
+ d = {}
+ hid = self.interfaces.first().host.labid
+ d[hid] = {}
+ for interface in self.interfaces.all():
+ d[hid][interface.mac_address] = []
+ for vlan in interface.config.all():
+ network_role = self.opnfv_model.networks().filter(network=vlan.network)
+ bridge = IDFTemplater.bridge_names[network_role.name]
+ br_config = {
+ "vlan_id": vlan.vlan_id,
+ "tagged": vlan.tagged,
+ "bridge": bridge
+ }
+ d[hid][interface.mac_address].append(br_config)
+ return d
+
+ def to_json(self):
+ return json.dumps(self.to_dict())
+
+
class OpnfvApiConfig(models.Model):
installer = models.CharField(max_length=200)
scenario = models.CharField(max_length=300)
roles = models.ManyToManyField(Host)
+ # pdf and idf are url endpoints, not the actual file
+ pdf = models.CharField(max_length=100)
+ idf = models.CharField(max_length=100)
+ bridge_config = models.OneToOneField(BridgeConfig, on_delete=models.CASCADE, null=True)
delta = models.TextField()
opnfv_config = models.ForeignKey(OPNFVConfig, null=True, on_delete=models.SET_NULL)
@@ -367,6 +410,12 @@ class OpnfvApiConfig(models.Model):
d['installer'] = self.installer
if self.scenario:
d['scenario'] = self.scenario
+ if self.pdf:
+ d['pdf'] = self.pdf
+ if self.idf:
+ d['idf'] = self.idf
+ if self.bridge_config:
+ d['bridged_interfaces'] = self.bridge_config.to_dict()
hosts = self.roles.all()
if hosts.exists():
@@ -395,6 +444,16 @@ class OpnfvApiConfig(models.Model):
d['scenario'] = scenario
self.delta = json.dumps(d)
+ def set_xdf(self, booking, update_delta=True):
+ kwargs = {'lab_name': booking.lab.name, 'booking_id': booking.id}
+ self.pdf = reverse('get-pdf', kwargs=kwargs)
+ self.idf = reverse('get-idf', kwargs=kwargs)
+ if update_delta:
+ d = json.loads(self.delta)
+ d['pdf'] = self.pdf
+ d['idf'] = self.idf
+ self.delta = json.dumps(d)
+
def add_role(self, host):
self.roles.add(host)
d = json.loads(self.delta)
@@ -632,6 +691,7 @@ class SnapshotConfig(TaskConfig):
if not self.delta:
self.delta = self.to_json()
self.save()
+
d = json.loads(self.delta)
return d
@@ -823,7 +883,6 @@ class JobFactory(object):
job=job
)
cls.makeSoftware(
- hosts=hosts,
booking=booking,
job=job
)
@@ -915,18 +974,41 @@ class JobFactory(object):
network_config.save()
@classmethod
- def makeSoftware(cls, hosts=[], booking=None, job=Job()):
+ def make_bridge_config(cls, booking):
+ if booking.resource.hosts.count() < 2:
+ return None
+ try:
+ jumphost_config = HostOPNFVConfig.objects.filter(
+ role__name__iexact="jumphost"
+ )
+ jumphost = Host.objects.get(
+ bundle=booking.resource,
+ config=jumphost_config.host_config
+ )
+ except Exception:
+ return None
+ br_config = BridgeConfig.objects.create(opnfv_config=booking.opnfv_config)
+ for iface in jumphost.interfaces.all():
+ br_config.interfaces.add(iface)
+ return br_config
+
+ @classmethod
+ def makeSoftware(cls, booking=None, job=Job()):
if not booking.opnfv_config:
return None
opnfv_api_config = OpnfvApiConfig.objects.create(
opnfv_config=booking.opnfv_config,
- installer=booking.opnfv_config.installer,
- scenario=booking.opnfv_config.scenario,
+ installer=booking.opnfv_config.installer.name,
+ scenario=booking.opnfv_config.scenario.name,
+ bridge_config=cls.make_bridge_config(booking)
)
- for host in hosts:
+ opnfv_api_config.set_xdf(booking, False)
+ opnfv_api_config.save()
+
+ for host in booking.resource.hosts.all():
opnfv_api_config.roles.add(host)
software_config = SoftwareConfig.objects.create(opnfv=opnfv_api_config)
software_relation = SoftwareRelation.objects.create(job=job, config=software_config)
diff --git a/dashboard/src/api/urls.py b/dashboard/src/api/urls.py
index d18a04d..d1f772a 100644
--- a/dashboard/src/api/urls.py
+++ b/dashboard/src/api/urls.py
@@ -41,6 +41,8 @@ from api.views import (
done_jobs,
update_host_bmc,
lab_host,
+ get_pdf,
+ get_idf,
GenerateTokenView
)
@@ -55,6 +57,8 @@ urlpatterns = [
path('labs/<slug:lab_name>/inventory', lab_inventory),
path('labs/<slug:lab_name>/hosts/<slug:host_id>', lab_host),
path('labs/<slug:lab_name>/hosts/<slug:host_id>/bmc', update_host_bmc),
+ path('labs/<slug:lab_name>/booking/<slug:booking_id>/pdf', get_pdf, name="get-pdf"),
+ path('labs/<slug:lab_name>/booking/<slug:booking_id>/idf', get_idf, name="get-idf"),
path('labs/<slug:lab_name>/jobs/<int:job_id>', specific_job),
path('labs/<slug:lab_name>/jobs/<int:job_id>/<slug:task_id>', specific_task),
path('labs/<slug:lab_name>/jobs/new', new_jobs),
diff --git a/dashboard/src/api/views.py b/dashboard/src/api/views.py
index 2ae1ac5..fb28958 100644
--- a/dashboard/src/api/views.py
+++ b/dashboard/src/api/views.py
@@ -13,7 +13,7 @@ from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
from django.utils.decorators import method_decorator
from django.views import View
-from django.http.response import JsonResponse
+from django.http.response import JsonResponse, HttpResponse
from rest_framework import viewsets
from rest_framework.authtoken.models import Token
from django.views.decorators.csrf import csrf_exempt
@@ -64,6 +64,18 @@ def lab_host(request, lab_name="", host_id=""):
return JsonResponse(lab_manager.update_host(host_id, request.POST), safe=False)
+def get_pdf(request, lab_name="", booking_id=""):
+ lab_token = request.META.get('HTTP_AUTH_TOKEN')
+ lab_manager = LabManagerTracker.get(lab_name, lab_token)
+ return HttpResponse(lab_manager.get_pdf(booking_id), content_type="text/plain")
+
+
+def get_idf(request, lab_name="", booking_id=""):
+ lab_token = request.META.get('HTTP_AUTH_TOKEN')
+ lab_manager = LabManagerTracker.get(lab_name, lab_token)
+ return HttpResponse(lab_manager.get_idf(booking_id), content_type="text/plain")
+
+
def lab_status(request, lab_name=""):
lab_token = request.META.get('HTTP_AUTH_TOKEN')
lab_manager = LabManagerTracker.get(lab_name, lab_token)
diff --git a/dashboard/src/resource_inventory/idf_templater.py b/dashboard/src/resource_inventory/idf_templater.py
index 26307e3..bf6eda0 100644
--- a/dashboard/src/resource_inventory/idf_templater.py
+++ b/dashboard/src/resource_inventory/idf_templater.py
@@ -19,8 +19,15 @@ class IDFTemplater:
"""
Utility class to create a full IDF yaml file
"""
+ net_names = ["admin", "mgmt", "private", "public"]
+ bridge_names = {
+ "admin": "br-admin",
+ "mgmt": "br-mgmt",
+ "private": "br-private",
+ "public": "br-public"
+ }
+
def __init__(self):
- self.net_names = ["admin", "mgmt", "private", "public"]
self.networks = {}
for i, name in enumerate(self.net_names):
self.networks[name] = {
@@ -117,11 +124,7 @@ class IDFTemplater:
return fuel
def get_fuel_bridges(self):
- bridges = {}
- for net in self.net_names:
- bridges[net] = "br-" + net
-
- return bridges
+ return self.bridge_names
def get_fuel_nodes(self, booking):
jumphost = booking.opnfv_config.host_opnfv_config.get(