diff options
Diffstat (limited to 'src/resource_inventory/resource_manager.py')
-rw-r--r-- | src/resource_inventory/resource_manager.py | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/src/resource_inventory/resource_manager.py b/src/resource_inventory/resource_manager.py new file mode 100644 index 0000000..652e4e3 --- /dev/null +++ b/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) |