From 25275685e9a735e51fae8b1a936ba5733f6fb770 Mon Sep 17 00:00:00 2001 From: Parker Berberian Date: Wed, 10 Oct 2018 16:06:47 -0400 Subject: Lab as a Service 2.0 See changes here: https://wiki.opnfv.org/display/INF/Pharos+Laas Change-Id: I59ada5f98e70a28d7f8c14eab3239597e236ca26 Signed-off-by: Sawyer Bergeron Signed-off-by: Parker Berberian --- .../src/resource_inventory/resource_manager.py | 197 +++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 dashboard/src/resource_inventory/resource_manager.py (limited to 'dashboard/src/resource_inventory/resource_manager.py') diff --git a/dashboard/src/resource_inventory/resource_manager.py b/dashboard/src/resource_inventory/resource_manager.py new file mode 100644 index 0000000..cd70867 --- /dev/null +++ b/dashboard/src/resource_inventory/resource_manager.py @@ -0,0 +1,197 @@ +############################################################################## +# Copyright (c) 2018 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.core.exceptions import * +from django.template.loader import render_to_string + +import booking +from dashboard.exceptions import * +from resource_inventory.models import * + +class ResourceManager: + + instance = None + + def __init__(self): + pass + + @staticmethod + def getInstance(): + if ResourceManager.instance is None: + ResourceManager.instance = ResourceManager() + return ResourceManager.instance + + #public interface + def deleteResourceBundle(self, resourceBundle): + for host in Host.objects.filter(bundle=resourceBundle): + self.releaseHost(host) + resourceBundle.delete() + + def convertResourceBundle(self, genericResourceBundle, lab=None, config=None): + """ + Takes in a GenericResourceBundle and 'converts' it into a ResourceBundle + """ + resource_bundle = ResourceBundle() + resource_bundle.template = genericResourceBundle + resource_bundle.save() + + hosts = genericResourceBundle.getHosts() + + #current supported case: user creating new booking + #currently unsupported: editing existing booking + + physical_hosts = [] + + for host in hosts: + host_config=None + if config: + host_config = HostConfiguration.objects.get(bundle=config, host=host) + try: + physical_host = self.acquireHost(host, genericResourceBundle.lab.name) + except ResourceAvailabilityException: + self.fail_acquire(physical_hosts) + raise ResourceAvailabilityException("Could not provision hosts, not enough available") + try: + physical_host.bundle = resource_bundle + physical_host.template = host + physical_host.config = host_config + physical_hosts.append(physical_host) + + self.configureNetworking(physical_host) + except: + self.fail_acquire(physical_hosts) + raise ResourceProvisioningException("Network configuration failed.") + try: + physical_host.save() + except: + self.fail_acquire(physical_hosts) + raise ModelValidationException("Saving hosts failed") + + return resource_bundle + + def configureNetworking(self, host): + generic_interfaces = list(host.template.generic_interfaces.all()) + for int_num, physical_interface in enumerate(host.interfaces.all()): + generic_interface = generic_interfaces[int_num] + physical_interface.config.clear() + for vlan in generic_interface.vlans.all(): + physical_interface.config.add(vlan) + + #private interface + def acquireHost(self, genericHost, labName): + host_full_set = Host.objects.filter(lab__name__exact=labName, profile=genericHost.profile) + if not host_full_set.first(): + raise ResourceExistenceException("No matching servers found") + host_set = host_full_set.filter(booked=False) + if not host_set.first(): + raise ResourceAvailabilityException("No unbooked hosts match requested hosts") + host = host_set.first() + host.booked = True + host.template = genericHost + host.save() + return host + + def releaseHost(self, host): + host.template = None + host.bundle = None + host.booked = False + host.save() + + def fail_acquire(self, hosts): + for host in hosts: + self.releaseHost(host) + + def makePDF(self, resource): + """ + fills the pod descriptor file template with info about the resource + """ + template = "dashboard/pdf.yaml" + info = {} + info['details'] = self.get_pdf_details(resource) + info['jumphost'] = self.get_pdf_jumphost(resource) + info['nodes'] = self.get_pdf_nodes(resource) + + return render_to_string(template, context=info) + + def get_pdf_details(self, resource): + details = {} + owner = "Anon" + email = "email@mail.com" + resource_lab = resource.template.lab + lab = resource_lab.name + location = resource_lab.location + pod_type = "development" + link = "https://wiki.opnfv.org/display/INF/Pharos+Laas" + + try: + # try to get more specific info that may fail, we dont care if it does + booking_owner = booking.models.Booking.objects.get(resource=resource).owner + owner = booking_owner.username + email = booking_owner.userprofile.email_addr + except Exception as e: + pass + + details['owner'] = owner + details['email'] = email + details['lab'] = lab + details['location'] = location + details['type'] = pod_type + details['link'] = link + + return details + + def get_pdf_jumphost(self, resource): + jumphost = Host.objects.get(bundle=resource, config__opnfvRole__name__iexact="jumphost") + return self.get_pdf_host(jumphost) + + def get_pdf_nodes(self, resource): + pdf_nodes = [] + nodes = Host.objects.filter(bundle=resource).exclude(config__opnfvRole__name__iexact="jumphost") + for node in nodes: + pdf_nodes.append(self.get_pdf_host(node)) + + return pdf_nodes + + + def get_pdf_host(self, host): + host_info = {} + host_info['name'] = host.template.resource.name + host_info['node'] = {} + host_info['node']['type'] = "baremetal" + host_info['node']['vendor'] = host.vendor + host_info['node']['model'] = host.model + host_info['node']['arch'] = host.profile.cpuprofile.first().architecture + host_info['node']['cpus'] = host.profile.cpuprofile.first().cpus + host_info['node']['cores'] = host.profile.cpuprofile.first().cores + cflags = host.profile.cpuprofile.first().cflags + if cflags and cflags.strip(): + host_info['node']['cpu_cflags'] = cflags + host_info['node']['memory'] = str(host.profile.ramprofile.first().amount) + "G" + host_info['disks'] = [] + for disk in host.profile.storageprofile.all(): + disk_info = {} + disk_info['name'] = disk.name + disk_info['capacity'] = str(disk.size) + "G" + disk_info['type'] = disk.media_type + disk_info['interface'] = disk.interface + disk_info['rotation'] = disk.rotation + host_info['disks'].append(disk_info) + + host_info['interfaces'] = [] + for interface in host.interfaces.all(): + iface_info = {} + iface_info['name'] = interface.name + iface_info['address'] = "unknown" + iface_info['mac_address'] = interface.mac_address + vlans = "|".join([str(vlan.vlan_id) for vlan in interface.config.all()]) + iface_info['vlans'] = vlans + host_info['interfaces'].append(iface_info) + + return host_info -- cgit 1.2.3-korg