Reworks resource tests into model validation where possible. 97/70197/7
authorssmith <ssmith@iol.unh.edu>
Mon, 18 May 2020 22:08:35 +0000 (18:08 -0400)
committerssmith <ssmith@iol.unh.edu>
Wed, 20 May 2020 21:13:57 +0000 (17:13 -0400)
Change-Id: Ieb77cc38a42345107c2cac62ba1499bd7974ad77
Signed-off-by: Sean Smith <ssmith@iol.unh.edu>
src/laas_dashboard/model_test.py [new file with mode: 0644]
src/resource_inventory/admin.py
src/resource_inventory/forms.py [new file with mode: 0644]
src/resource_inventory/models.py

diff --git a/src/laas_dashboard/model_test.py b/src/laas_dashboard/model_test.py
new file mode 100644 (file)
index 0000000..ba3ef35
--- /dev/null
@@ -0,0 +1,110 @@
+##############################################################################
+# Copyright (c) 2020 Sawyer Bergeron, Parker Berberian, Sean Smith, 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 resource_inventory.models import (
+    ResourceProfile,
+    ResourceQuery,
+    Image,
+    DiskProfile,
+    CpuProfile,
+    RamProfile,
+    InterfaceProfile,
+)
+
+
+def rp_has_all_components():
+    """
+    Check that every ResourceProfile has an InterfaceProfile,
+    DiskProfile, CpuProfile, and RamProfile.
+    """
+
+    result = True
+
+    for rp in ResourceProfile.objects.all():
+        ip = InterfaceProfile.objects.filter(host=rp).exists()
+        dp = DiskProfile.objects.filter(host=rp).exists()
+        cp = CpuProfile.objects.filter(host=rp).exists()
+        ram = RamProfile.objects.filter(host=rp).exists()
+
+        if not ip:
+            print("No InterfaceProfiles for host", rp.name)
+            result = False
+
+        if not dp:
+            print("No DiskProfile for host", rp.name)
+            result = False
+
+        if not cp:
+            print("No CpuProfile for host", rp.name)
+            result = False
+
+        if not ram:
+            print("No RamProfile for host", rp.name)
+            result = False
+
+    return result
+
+
+def ip_for_all_ifaces():
+    """
+    Check that every InterfaceProfile for a Resource has
+    an Interface.
+    """
+
+    result = True
+
+    for res in ResourceQuery.filter():
+        iface_set = res.get_interfaces()
+        iface_profile_set = InterfaceProfile.objects.filter(host=res.profile)
+
+        # find out what profiles we have
+        curr_profiles = [iface.profile for iface in iface_set]
+        missing_profiles = set(iface_profile_set) - set(curr_profiles)
+
+        if missing_profiles:
+            print('No interface for profiles', missing_profiles, 'for host', res.name)
+            result = False
+
+    return result
+
+
+def rp_has_image():
+    """
+    Make sure every ResourceProfile has an Image.
+    """
+
+    result = True
+
+    rp_set = ResourceProfile.objects.all()
+    image_set = Image.objects.all()
+    image_profiles = set([image.host_type for image in image_set])
+
+    for rp in rp_set:
+        if rp not in image_profiles:
+            print("ResourceProfile", rp.name, "has no image associated with it.")
+            result = False
+    return result
+
+
+def run_test(test):
+    print('RUNNING TEST', test)
+    result = test()
+    if result:
+        print(test, 'WAS A SUCCESS!')
+    else:
+        print(test, 'FAILED')
+    print('============================================')
+
+
+def run_tests():
+    tests = [rp_has_all_components, ip_for_all_ifaces, rp_has_image]
+
+    for test in tests:
+        run_test(test)
index 439dad3..2444a98 100644 (file)
@@ -10,6 +10,8 @@
 
 from django.contrib import admin
 
+from resource_inventory.forms import InterfaceConfigurationForm
+
 from resource_inventory.models import (
     ResourceProfile,
     InterfaceProfile,
@@ -32,9 +34,10 @@ from resource_inventory.models import (
     Image,
     RemoteInfo,
     PhysicalNetwork,
-    NetworkConnection
+    NetworkConnection,
 )
 
+
 admin.site.register([
     ResourceProfile,
     InterfaceProfile,
@@ -43,7 +46,6 @@ admin.site.register([
     RamProfile,
     ResourceTemplate,
     ResourceConfiguration,
-    InterfaceConfiguration,
     Server,
     Interface,
     Network,
@@ -57,4 +59,12 @@ admin.site.register([
     Image,
     PhysicalNetwork,
     NetworkConnection,
-    RemoteInfo])
+    RemoteInfo]
+)
+
+
+class InterfaceConfigurationAdmin(admin.ModelAdmin):
+    form = InterfaceConfigurationForm
+
+
+admin.site.register(InterfaceConfiguration, InterfaceConfigurationAdmin)
diff --git a/src/resource_inventory/forms.py b/src/resource_inventory/forms.py
new file mode 100644 (file)
index 0000000..fb8c102
--- /dev/null
@@ -0,0 +1,31 @@
+##############################################################################
+# Copyright (c) 2020 Sawyer Bergeron, Sean Smith, 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 ValidationError
+from django import forms
+
+from resource_inventory.models import Network, InterfaceConfiguration
+
+
+class InterfaceConfigurationForm(forms.ModelForm):
+    class Meta:
+        model = InterfaceConfiguration
+        fields = ['profile', 'resource_config', 'connections']
+
+    def clean(self):
+        connections = self.cleaned_data.get('connections')
+        resource_config = self.cleaned_data.get('resource_config')
+
+        valid_nets = set(Network.objects.filter(bundle=resource_config.template))
+        curr_nets = set([conn.network for conn in connections])
+
+        if not curr_nets.issubset(valid_nets):
+            raise ValidationError("Cannot have network connection to network outside pod")
+
+        return self.cleaned_data
index d1b7a75..33d98a0 100644 (file)
@@ -439,6 +439,9 @@ class InterfaceConfiguration(models.Model):
     def __str__(self):
         return "type " + str(self.profile) + " on host " + str(self.resource_config)
 
+    def save(self, *args, **kwargs):
+        super().save(*args, **kwargs)
+
 
 """
 OPNFV / Software configuration models
@@ -504,12 +507,21 @@ class Interface(models.Model):
     mac_address = models.CharField(max_length=17)
     bus_address = models.CharField(max_length=50)
     config = models.ManyToManyField(Vlan)
-    acts_as = models.OneToOneField(InterfaceConfiguration, null=True, on_delete=models.SET_NULL)
+    acts_as = models.OneToOneField(InterfaceConfiguration, null=True, on_delete=models.CASCADE)
     profile = models.ForeignKey(InterfaceProfile, on_delete=models.CASCADE)
 
     def __str__(self):
         return self.mac_address + " on host " + str(self.profile.host.name)
 
+    def clean(self, *args, **kwargs):
+        if self.acts_as.profile != self.profile:
+            raise ValidationError("Interface Configuration's Interface Profile does not match Interface Profile chosen for Interface.")
+        super().clean(*args, **kwargs)
+
+    def save(self, *args, **kwargs):
+        self.full_clean()
+        super().save(*args, **kwargs)
+
 
 """
 Some Enums for dealing with global constants.