added /api/labs endpoint and tracebacks 10/72610/2
authorJacob Hodgdon <jhodgdon@iol.unh.edu>
Thu, 22 Jul 2021 20:49:26 +0000 (16:49 -0400)
committerSawyer Bergeron <sbergeron@iol.unh.edu>
Wed, 4 Aug 2021 19:01:12 +0000 (15:01 -0400)
Change-Id: I59d06d19806e892daed007689b0dab139eae3160
Signed-off-by: Jacob Hodgdon <jhodgdon@iol.unh.edu>
Signed-off-by: Sawyer Bergeron <sbergeron@iol.unh.edu>
src/api/urls.py
src/api/views.py
src/resource_inventory/resource_manager.py

index 3d78ed6..1878d9c 100644 (file)
@@ -82,6 +82,7 @@ urlpatterns = [
     path('resource_inventory/<int:template_id>/images', images_for_template),
 
     path('users', all_users),
+    path('labs', all_labs),
 
     url(r'^token$', GenerateTokenView.as_view(), name='generate_token'),
 ]
index 3c8445d..84085b4 100644 (file)
@@ -10,6 +10,7 @@
 
 import json
 import math
+import traceback
 from datetime import timedelta
 
 from django.contrib.auth.decorators import login_required
@@ -362,7 +363,8 @@ def make_booking(request):
     try:
         booking = create_from_API(request.body, token.user)
     except Exception as e:
-        return HttpResponse(str(e), status=400)
+        exc_type, exc_value, exc_traceback = sys.exc_info()
+        return HttpResponse(str(traceback.format_exception(exc_type, exc_value, exc_traceback)), status=400)
 
     sbooking = AutomationAPIManager.serialize_booking(booking)
     return JsonResponse(sbooking, safe=False)
@@ -383,7 +385,7 @@ def available_templates(request):
     # mirrors MultipleSelectFilter Widget
     avt = []
     for lab in Lab.objects.all():
-        for template in ResourceTemplate.objects.filter(lab=lab, owner=token.user, public=True):
+        for template in ResourceTemplate.objects.filter(Q(lab=lab), Q(owner=token.user) | Q(public=True)):
             available_resources = lab.get_available_resources()
             required_resources = template.get_required_resources()
             least_available = 100
@@ -417,7 +419,7 @@ def images_for_template(request, template_id=""):
 """
 User API Views
 """
-
+lab_info
 
 def all_users(request):
     token = auth_and_log(request, 'users')
@@ -429,3 +431,28 @@ def all_users(request):
              for up in UserProfile.objects.exclude(user=token.user)]
 
     return JsonResponse(users, safe=False)
+
+
+"""
+Lab API Views
+"""
+
+
+def all_labs():
+    lab_list=[]
+    for lab in Lab.objects.all():
+        lab_info = {
+        'name':lab.name,
+        'username':lab.lab_user.username,
+        'status':lab.status,
+        'project':lab.project,
+        'description':lab.description,
+        'location':lab.location,
+        'info':lab.lab_info_link,
+        'email':lab.contact_email,
+        'phone':lab.contact_phone
+        }
+        lab_list.append(lab_info)
+
+    return JsonResponse(lab_list, safe=False)
+    
index 9406977..1935e0c 100644 (file)
@@ -7,6 +7,8 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 import re
+import typing
+from typing import Optional
 from django.db.models import Q
 
 from dashboard.exceptions import ResourceAvailabilityException
@@ -14,6 +16,7 @@ from dashboard.exceptions import ResourceAvailabilityException
 from resource_inventory.models import (
     ResourceBundle,
     ResourceTemplate,
+    ResourceConfiguration,
     Network,
     Vlan,
     PhysicalNetwork,
@@ -29,19 +32,19 @@ class ResourceManager:
         pass
 
     @staticmethod
-    def getInstance():
+    def getInstance() -> ResourceManager:
         if ResourceManager.instance is None:
             ResourceManager.instance = ResourceManager()
         return ResourceManager.instance
 
-    def getAvailableResourceTemplates(self, lab, user=None):
+    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):
+    def templateIsReservable(self, resource_template: ResourceTemplate):
         """
         Check if the required resources to reserve this template is available.
 
@@ -63,13 +66,16 @@ class ResourceManager:
         return True
 
     # public interface
-    def deleteResourceBundle(self, resourceBundle):
+    def deleteResourceBundle(self, resourceBundle: ResourceBundle):
         raise NotImplementedError("Resource Bundle Deletion Not Implemented")
 
-    def releaseResourceBundle(self, resourceBundle):
+    def releaseResourceBundle(self, resourceBundle: ResourceBundle):
         resourceBundle.release()
 
-    def get_vlans(self, resourceTemplate):
+    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():
@@ -84,7 +90,7 @@ class ResourceManager:
                 networks[network.name] = vlans[0]
         return networks
 
-    def instantiateTemplate(self, resource_template):
+    def instantiateTemplate(self, resource_template: ResourceTemplate):
         """
         Convert a ResourceTemplate into a ResourceBundle.
 
@@ -113,16 +119,18 @@ class ResourceManager:
 
         return resource_bundle
 
-    def configureNetworking(self, resource_bundle, resource, vlan_map):
+    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_configs = InterfaceConfiguration.objects.filter(
+            # assign interface configs
+            iface_config = InterfaceConfiguration.objects.get(
                 profile=physical_interface.profile,
                 resource_config=resource.config
             )
 
-            iface_config = iface_configs.first()
             physical_interface.acts_as = iface_config
             physical_interface.acts_as.save()
 
@@ -143,7 +151,7 @@ class ResourceManager:
                 )
 
     # private interface
-    def acquireHost(self, resource_config):
+    def acquireHost(self, resource_config: ResourceConfiguration) -> Resource:
         resources = resource_config.profile.get_resources(
             lab=resource_config.template.lab,
             unreserved=True