summaryrefslogtreecommitdiffstats
path: root/dashboard/src/resource_inventory/resource_manager.py
diff options
context:
space:
mode:
Diffstat (limited to 'dashboard/src/resource_inventory/resource_manager.py')
-rw-r--r--dashboard/src/resource_inventory/resource_manager.py174
1 files changed, 174 insertions, 0 deletions
diff --git a/dashboard/src/resource_inventory/resource_manager.py b/dashboard/src/resource_inventory/resource_manager.py
new file mode 100644
index 0000000..652e4e3
--- /dev/null
+++ b/dashboard/src/resource_inventory/resource_manager.py
@@ -0,0 +1,174 @@
+##############################################################################
+# 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 dashboard.exceptions import (
+ ResourceExistenceException,
+ ResourceAvailabilityException,
+ ResourceProvisioningException,
+ ModelValidationException,
+)
+from resource_inventory.models import (
+ Host,
+ HostConfiguration,
+ ResourceBundle,
+ HostProfile,
+ Network,
+ Vlan
+)
+
+
+class ResourceManager:
+
+ instance = None
+
+ def __init__(self):
+ pass
+
+ @staticmethod
+ def getInstance():
+ if ResourceManager.instance is None:
+ ResourceManager.instance = ResourceManager()
+ return ResourceManager.instance
+
+ def getAvailableHostTypes(self, lab):
+ hostset = Host.objects.filter(lab=lab).filter(booked=False).filter(working=True)
+ hostprofileset = HostProfile.objects.filter(host__in=hostset, labs=lab)
+ return set(hostprofileset)
+
+ def hostsAvailable(self, grb):
+ """
+ This method will check if the given GenericResourceBundle
+ is available. No changes to the database
+ """
+
+ # count up hosts
+ profile_count = {}
+ for host in grb.getHosts():
+ if host.profile not in profile_count:
+ profile_count[host.profile] = 0
+ profile_count[host.profile] += 1
+
+ # check that all required hosts are available
+ for profile in profile_count.keys():
+ available = Host.objects.filter(
+ booked=False,
+ lab=grb.lab,
+ profile=profile
+ ).count()
+ needed = profile_count[profile]
+ if available < needed:
+ return False
+ return True
+
+ # public interface
+ def deleteResourceBundle(self, resourceBundle):
+ for host in Host.objects.filter(bundle=resourceBundle):
+ self.releaseHost(host)
+ resourceBundle.delete()
+
+ def get_vlans(self, genericResourceBundle):
+ networks = {}
+ vlan_manager = genericResourceBundle.lab.vlan_manager
+ for network in genericResourceBundle.networks.all():
+ if network.is_public:
+ public_net = vlan_manager.get_public_vlan()
+ vlan_manager.reserve_public_vlan(public_net.vlan)
+ networks[network.name] = public_net.vlan
+ else:
+ vlan = vlan_manager.get_vlan()
+ vlan_manager.reserve_vlans(vlan)
+ networks[network.name] = vlan
+ return networks
+
+ def convertResourceBundle(self, genericResourceBundle, config=None):
+ """
+ Takes in a GenericResourceBundle and 'converts' it into a ResourceBundle
+ """
+ resource_bundle = ResourceBundle.objects.create(template=genericResourceBundle)
+ generic_hosts = genericResourceBundle.getHosts()
+ physical_hosts = []
+
+ vlan_map = self.get_vlans(genericResourceBundle)
+
+ for generic_host in generic_hosts:
+ host_config = None
+ if config:
+ host_config = HostConfiguration.objects.get(bundle=config, host=generic_host)
+ try:
+ physical_host = self.acquireHost(generic_host, genericResourceBundle.lab.name)
+ except ResourceAvailabilityException:
+ self.fail_acquire(physical_hosts, vlan_map, genericResourceBundle)
+ raise ResourceAvailabilityException("Could not provision hosts, not enough available")
+ try:
+ physical_host.bundle = resource_bundle
+ physical_host.template = generic_host
+ physical_host.config = host_config
+ physical_hosts.append(physical_host)
+
+ self.configureNetworking(physical_host, vlan_map)
+ except Exception:
+ self.fail_acquire(physical_hosts, vlan_map, genericResourceBundle)
+ raise ResourceProvisioningException("Network configuration failed.")
+ try:
+ physical_host.save()
+ except Exception:
+ self.fail_acquire(physical_hosts, vlan_map, genericResourceBundle)
+ raise ModelValidationException("Saving hosts failed")
+
+ return resource_bundle
+
+ def configureNetworking(self, host, vlan_map):
+ 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 connection in generic_interface.connections.all():
+ physical_interface.config.add(
+ Vlan.objects.create(
+ vlan_id=vlan_map[connection.network.name],
+ tagged=connection.vlan_is_tagged,
+ public=connection.network.is_public,
+ network=connection.network
+ )
+ )
+
+ # 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 releaseNetworks(self, grb, vlan_manager, vlans):
+ for net_name, vlan_id in vlans.items():
+ net = Network.objects.get(name=net_name, bundle=grb)
+ if(net.is_public):
+ vlan_manager.release_public_vlan(vlan_id)
+ else:
+ vlan_manager.release_vlans(vlan_id)
+
+ def fail_acquire(self, hosts, vlans, grb):
+ vlan_manager = grb.lab.vlan_manager
+ self.releaseNetworks(grb, vlan_manager, vlans)
+ for host in hosts:
+ self.releaseHost(host)