aboutsummaryrefslogtreecommitdiffstats
path: root/src/resource_inventory/resource_manager.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/resource_inventory/resource_manager.py')
-rw-r--r--src/resource_inventory/resource_manager.py197
1 files changed, 0 insertions, 197 deletions
diff --git a/src/resource_inventory/resource_manager.py b/src/resource_inventory/resource_manager.py
deleted file mode 100644
index 16c106e..0000000
--- a/src/resource_inventory/resource_manager.py
+++ /dev/null
@@ -1,197 +0,0 @@
-##############################################################################
-# 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 __future__ import annotations # noqa: F407
-
-import re
-from typing import Optional
-from django.db.models import Q
-
-from dashboard.exceptions import ResourceAvailabilityException
-
-from resource_inventory.models import (
- Resource,
- ResourceBundle,
- ResourceTemplate,
- ResourceConfiguration,
- Network,
- Vlan,
- PhysicalNetwork,
- InterfaceConfiguration,
-)
-
-from account.models import Lab
-from django.contrib.auth.models import User
-
-
-class ResourceManager:
-
- instance = None
-
- def __init__(self):
- pass
-
- @staticmethod
- def getInstance() -> ResourceManager:
- if ResourceManager.instance is None:
- ResourceManager.instance = ResourceManager()
- return ResourceManager.instance
-
- def getAvailableResourceTemplates(self, lab: Lab, user: Optional[User] = None) -> list[ResourceTemplate]:
- filter = Q(public=True)
- if user:
- filter = filter | Q(owner=user)
- filter = filter & Q(temporary=False) & Q(lab=lab)
- return ResourceTemplate.objects.filter(filter)
-
- def templateIsReservable(self, resource_template: ResourceTemplate):
- """
- Check if the required resources to reserve this template is available.
-
- No changes to the database
- """
- # count up hosts
- profile_count = {}
- for config in resource_template.getConfigs():
- if config.profile not in profile_count:
- profile_count[config.profile] = 0
- profile_count[config.profile] += 1
-
- # check that all required hosts are available
- for profile in profile_count.keys():
- available = len(profile.get_resources(lab=resource_template.lab, unreserved=True))
- needed = profile_count[profile]
- if available < needed:
- return False
- return True
-
- # public interface
- def deleteResourceBundle(self, resourceBundle: ResourceBundle):
- raise NotImplementedError("Resource Bundle Deletion Not Implemented")
-
- def releaseResourceBundle(self, resourceBundle: ResourceBundle):
- resourceBundle.release()
-
- def get_vlans(self, resourceTemplate: ResourceTemplate) -> dict[str, int]:
- """
- returns: dict from network name to the associated vlan number (backend vlan id)
- """
- networks = {}
- vlan_manager = resourceTemplate.lab.vlan_manager
- for network in resourceTemplate.networks.all():
- if network.is_public:
- # already throws if can't get requested count, so can always expect public_net to be Some
- public_net = vlan_manager.get_public_vlan(within=resourceTemplate.public_vlan_pool_set())
- vlan_manager.reserve_public_vlan(public_net.vlan)
- networks[network.name] = public_net.vlan
- else:
- # already throws if can't get requested count, so can always index in @ 0
- vlans = vlan_manager.get_vlans(count=1, within=resourceTemplate.private_vlan_pool_set())
- vlan_manager.reserve_vlans(vlans[0])
- networks[network.name] = vlans[0]
- return networks
-
- def instantiateTemplate(self, resource_template: ResourceTemplate):
- """
- Convert a ResourceTemplate into a ResourceBundle.
-
- Takes in a ResourceTemplate and reserves all the
- Resources needed and returns a completed ResourceBundle.
- """
- resource_bundle = ResourceBundle.objects.create(template=resource_template)
- res_configs = resource_template.getConfigs()
- resources = []
-
- vlan_map = self.get_vlans(resource_template)
-
- for config in res_configs:
- try:
- phys_res = self.acquireHost(config)
- phys_res.bundle = resource_bundle
- phys_res.config = config
- resources.append(phys_res)
-
- self.configureNetworking(resource_bundle, phys_res, vlan_map)
- phys_res.save()
-
- except Exception as e:
- self.fail_acquire(resources, vlan_map, resource_template)
- raise e
-
- return resource_bundle
-
- def configureNetworking(self, resource_bundle: ResourceBundle, resource: Resource, vlan_map: dict[str, int]):
- """
- @vlan_map: dict from network name to the associated vlan number (backend vlan id)
- """
- for physical_interface in resource.interfaces.all():
-
- # assign interface configs
- iface_config = InterfaceConfiguration.objects.get(
- profile=physical_interface.profile,
- resource_config=resource.config
- )
-
- physical_interface.acts_as = iface_config
- physical_interface.acts_as.save()
-
- physical_interface.config.clear()
- for connection in iface_config.connections.all():
- physicalNetwork = PhysicalNetwork.objects.create(
- vlan_id=vlan_map[connection.network.name],
- generic_network=connection.network,
- bundle=resource_bundle,
- )
- 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=physicalNetwork
- )
- )
-
- # private interface
- def acquireHost(self, resource_config: ResourceConfiguration) -> Resource:
- resources = resource_config.profile.get_resources(
- lab=resource_config.template.lab,
- unreserved=True
- )
-
- try:
- resource = resources[0] # TODO: should we randomize and 'load balance' the servers?
- resource.config = resource_config
- resource.reserve()
- return resource
- except IndexError:
- raise ResourceAvailabilityException("No available resources of requested type")
-
- def releaseNetworks(self, template, vlans):
- vlan_manager = template.lab.vlan_manager
- for net_name, vlan_id in vlans.items():
- net = Network.objects.get(name=net_name, bundle=template)
- if (net.is_public):
- vlan_manager.release_public_vlan(vlan_id)
- else:
- vlan_manager.release_vlans(vlan_id)
-
- def fail_acquire(self, hosts, vlans, template):
- self.releaseNetworks(template, vlans)
- for host in hosts:
- host.release()
-
-
-class HostNameValidator(object):
- regex = r'^[A-Za-z0-9][A-Za-z0-9-]*$'
- message = "Hostnames can only contain alphanumeric characters and hyphens (-). Hostnames must start with a letter"
- pattern = re.compile(regex)
-
- @classmethod
- def is_valid_hostname(cls, hostname):
- return len(hostname) < 65 and cls.pattern.fullmatch(hostname) is not None