Fixes the idf and pdf templates so that we can deploy opnfv
authorParker Berberian <pberberian@iol.unh.edu>
Fri, 12 Apr 2019 16:24:34 +0000 (12:24 -0400)
committerParker Berberian <pberberian@iol.unh.edu>
Wed, 17 Apr 2019 14:18:45 +0000 (10:18 -0400)
Change-Id: I0091629f8f0af423210b2e81210d65239e9662b4
Signed-off-by: Parker Berberian <pberberian@iol.unh.edu>
src/api/models.py
src/booking/migrations/0005_booking_idf.py [new file with mode: 0644]
src/booking/models.py
src/resource_inventory/admin.py
src/resource_inventory/idf_templater.py [new file with mode: 0644]
src/resource_inventory/pdf_templater.py
src/templates/dashboard/idf.yaml

index f8b8f89..4ce8c3e 100644 (file)
@@ -25,6 +25,8 @@ from resource_inventory.models import (
     Interface,
     RemoteInfo
 )
+from resource_inventory.idf_templater import IDFTemplater
+from resource_inventory.pdf_templater import PDFTemplater
 
 
 class JobStatus(object):
@@ -86,8 +88,15 @@ class LabManager(object):
         remote_info.save()
         host.remote_management = remote_info
         host.save()
+        booking = Booking.objects.get(resource=host.bundle)
+        self.update_xdf(booking)
         return {"status": "success"}
 
+    def update_xdf(self, booking):
+        booking.pdf = PDFTemplater.makePDF(booking.resource)
+        booking.idf = IDFTemplater().makeIDF(booking)
+        booking.save()
+
     def get_profile(self):
         prof = {}
         prof['name'] = self.lab.name
diff --git a/src/booking/migrations/0005_booking_idf.py b/src/booking/migrations/0005_booking_idf.py
new file mode 100644 (file)
index 0000000..31e9170
--- /dev/null
@@ -0,0 +1,18 @@
+# Generated by Django 2.1 on 2019-04-12 19:27
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('booking', '0004_auto_20190124_1700'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='booking',
+            name='idf',
+            field=models.TextField(blank=True, default=''),
+        ),
+    ]
index 8612abd..02e03cc 100644 (file)
@@ -32,6 +32,7 @@ class Booking(models.Model):
     project = models.CharField(max_length=100, default="", blank=True, null=True)
     lab = models.ForeignKey(Lab, null=True, on_delete=models.SET_NULL)
     pdf = models.TextField(blank=True, default="")
+    idf = models.TextField(blank=True, default="")
 
     class Meta:
         db_table = 'booking'
index e063cc0..7ff510b 100644 (file)
@@ -32,7 +32,8 @@ from resource_inventory.models import (
     OPNFVConfig,
     OPNFVRole,
     Image,
-    HostConfiguration
+    HostConfiguration,
+    RemoteInfo
 )
 
 profiles = [HostProfile, InterfaceProfile, DiskProfile, CpuProfile, RamProfile]
@@ -47,6 +48,6 @@ physical = [Host, Interface, Network, Vlan, ResourceBundle]
 
 admin.site.register(physical)
 
-config = [Scenario, Installer, Opsys, ConfigBundle, OPNFVConfig, OPNFVRole, Image, HostConfiguration]
+config = [Scenario, Installer, Opsys, ConfigBundle, OPNFVConfig, OPNFVRole, Image, HostConfiguration, RemoteInfo]
 
 admin.site.register(config)
diff --git a/src/resource_inventory/idf_templater.py b/src/resource_inventory/idf_templater.py
new file mode 100644 (file)
index 0000000..7cd13bb
--- /dev/null
@@ -0,0 +1,148 @@
+##############################################################################
+# Copyright (c) 2019 Parker Berberian, Sawyer Bergeron, 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.template.loader import render_to_string
+
+from account.models import PublicNetwork
+
+from resource_inventory.models import (
+    OPNFVConfig,
+    Vlan
+)
+
+
+class IDFTemplater:
+    """
+    Utility class to create a full IDF yaml file
+    """
+    def __init__(self):
+        self.net_names = ["admin", "mgmt", "private", "public"]
+        self.networks = {}
+        for i, name in enumerate(self.net_names):
+            self.networks[name] = {
+                "name": name,
+                "vlan": -1,
+                "interface": i,
+                "ip": "10.250." + str(i) + ".0",
+                "netmask": 24
+            }
+
+    def makeIDF(self, booking):
+        """
+        fills the installer descriptor file template with info about the resource
+        """
+        template = "dashboard/idf.yaml"
+        info = {}
+        info['version'] = "0.1"
+        info['net_config'] = self.get_net_config(booking)
+        info['fuel'] = self.get_fuel_config(booking)
+
+        return render_to_string(template, context=info)
+
+    def get_net_config(self, booking):
+        net_config = {}
+        try:
+            net_config['oob'] = self.get_oob_net(booking)
+        except Exception:
+            net_config['oob'] = {}
+        try:
+            net_config['public'] = self.get_public_net(booking)
+        except Exception:
+            net_config['public'] = {}
+
+        for net in [net for net in self.net_names if net != "public"]:
+            try:
+                net_config[net] = self.get_single_net_config(booking, net)
+            except Exception:
+                net_config[net] = {}
+
+        return net_config
+
+    def get_public_net(self, booking):
+        public = {}
+        config = OPNFVConfig.objects.get(bundle=booking.config_bundle)
+        public_role = config.networks.get(name="public")
+        public_vlan = Vlan.objects.filter(network=public_role.network).first()
+        public_network = PublicNetwork.objects.get(vlan=public_vlan.vlan_id, lab=booking.lab)
+        self.networks['public']['vlan'] = public_vlan.vlan_id
+        public['interface'] = self.networks['public']['interface']
+        public['vlan'] = public_network.vlan  # untagged??
+        public['network'] = public_network.cidr.split("/")[0]
+        public['mask'] = public_network.cidr.split("/")[1]
+        # public['ip_range'] = 4  # necesary?
+        public['gateway'] = public_network.gateway
+        public['dns'] = ["1.1.1.1", "8.8.8.8"]
+
+        return public
+
+    def get_oob_net(self, booking):
+        net = {}
+        hosts = booking.resource.hosts.all()
+        addrs = [host.remote_management.address for host in hosts]
+        net['ip_range'] = ",".join(addrs)
+        net['vlan'] = "native"
+        return net
+
+    def get_single_net_config(self, booking, net_name):
+        config = OPNFVConfig.objects.get(bundle=booking.config_bundle)
+        role = config.networks.get(name=net_name)
+        vlan = Vlan.objects.filter(network=role.network).first()
+        self.networks[net_name]['vlan'] = vlan.vlan_id
+        net = {}
+        net['interface'] = self.networks[net_name]['interface']
+        net['vlan'] = vlan.vlan_id
+        net['network'] = self.networks[net_name]['ip']
+        net['mask'] = self.networks[net_name]['netmask']
+
+        return net
+
+    def get_fuel_config(self, booking):
+        fuel = {}
+        fuel['jumphost'] = {}
+        try:
+            fuel['jumphost']['bridges'] = self.get_fuel_bridges()
+        except Exception:
+            fuel['jumphost']['bridges'] = {}
+
+        fuel['network'] = {}
+        try:
+            fuel['network']['nodes'] = self.get_fuel_nodes(booking)
+        except Exception:
+            fuel['network']['nodes'] = {}
+
+        return fuel
+
+    def get_fuel_bridges(self):
+        bridges = {}
+        for net in self.net_names:
+            bridges[net] = "br-" + net
+
+        return bridges
+
+    def get_fuel_nodes(self, booking):
+        hosts = booking.resource.hosts.exclude(config__opnfvRole__name="jumphost")
+        nodes = []
+        for host in hosts:
+            node = {}
+            ordered_interfaces = self.get_node_interfaces(host)
+            node['interfaces'] = [iface['name'] for iface in ordered_interfaces]
+            node['bus_addrs'] = [iface['bus'] for iface in ordered_interfaces]
+            nodes.append(node)
+
+        return nodes
+
+    def get_node_interfaces(self, node):
+        # TODO: this should sync with pdf ordering
+        interfaces = []
+
+        for iface in node.interfaces.all():
+            interfaces.append({"name": iface.name, "bus": iface.bus_address})
+
+        return interfaces
index 9f7e7f1..2db2129 100644 (file)
@@ -69,10 +69,6 @@ class PDFTemplater:
         """
         jumphost = Host.objects.get(bundle=resource, config__opnfvRole__name__iexact="jumphost")
         jumphost_info = cls.get_pdf_host(jumphost)
-        remote_params = jumphost_info['remote_management']  # jumphost has extra block not in normal hosts
-        remote_params.pop("address")
-        remote_params.pop("mac_address")
-        jumphost_info['remote_params'] = remote_params
         jumphost_info['os'] = jumphost.config.image.os.name
         return jumphost_info
 
@@ -105,7 +101,7 @@ class PDFTemplater:
         for interface in host.interfaces.all():
             host_info['interfaces'].append(cls.get_pdf_host_iface(interface))
 
-        host_info['remote_management'] = cls.get_pdf_host_remote_management(host)
+        host_info['remote'] = cls.get_pdf_host_remote_management(host)
 
         return host_info
 
@@ -163,11 +159,12 @@ class PDFTemplater:
         """
         gives the remote params of the host
         """
+        man = host.remote_management
         mgmt = {}
-        mgmt['address'] = "I dunno"
-        mgmt['mac_address'] = "I dunno"
-        mgmt['pass'] = "I dunno"
-        mgmt['type'] = "I dunno"
-        mgmt['user'] = "I dunno"
-        mgmt['versions'] = ["I dunno"]
+        mgmt['address'] = man.address
+        mgmt['mac_address'] = man.mac_address
+        mgmt['pass'] = man.password
+        mgmt['type'] = man.management_type
+        mgmt['user'] = man.user
+        mgmt['versions'] = [man.versions]
         return mgmt
index 5da20c4..9e0cc26 100644 (file)
@@ -1,8 +1,9 @@
+---
 idf:
   version: {{version|default:"0.1"}}
   net_config:
     oob:
-      ip-range: {{net_config.oob.ip-range}}
+      ip-range: {{net_config.oob.ip_range}}
       vlan: {{net_config.oob.vlan}}
     admin:
       interface: {{net_config.admin.interface}}
@@ -24,13 +25,11 @@ idf:
       vlan: {{net_config.public.vlan}}
       network: {{net_config.public.network}}
       mask: {{net_config.public.mask}}
-      ip-range: {{net_config.public.ip-range}}
+      ip-range: {{net_config.public.ip_range}}
       mask: {{net_config.public.mask}}
       gateway: {{net_config.public.gateway}}
-      dns:
-      {% for serv in net_config.public.dns %}
-      - {{serv}}
-      {% endfor %}
+      dns: {% for serv in net_config.public.dns %}
+      - {{serv}}{% endfor %}
   fuel:
     jumphost:
       bridges:
@@ -38,15 +37,10 @@ idf:
         mgmt: {{fuel.jumphost.bridges.mgmt}}
         private: {{fuel.jumphost.bridges.private}}
         public: {{fuel.jumphost.bridges.public}}
-    network:
-      {% for node in fuel.network.nodes %}
+    network: {% for node in fuel.network.nodes %}
       node:
-      - interfaces:
-        {% for iface in node.interfaces %}
-        - {{ iface }}
-        {% endfor %}
-      - busaddr:
-        {% for addr in node.bus_addrs %}
-        - {{addr}}
-        {% endfor %}
+      - interfaces: {% for iface in node.interfaces %}
+        - {{ iface }}{% endfor %}
+      - busaddr: {% for addr in node.bus_addrs %}
+        - {{addr}}{% endfor %}
       {% endfor %}