summaryrefslogtreecommitdiffstats
path: root/dashboard/src/resource_inventory/models.py
diff options
context:
space:
mode:
Diffstat (limited to 'dashboard/src/resource_inventory/models.py')
-rw-r--r--dashboard/src/resource_inventory/models.py137
1 files changed, 96 insertions, 41 deletions
diff --git a/dashboard/src/resource_inventory/models.py b/dashboard/src/resource_inventory/models.py
index b56317b..b9f2c44 100644
--- a/dashboard/src/resource_inventory/models.py
+++ b/dashboard/src/resource_inventory/models.py
@@ -25,7 +25,7 @@ class HostProfile(models.Model):
labs = models.ManyToManyField(Lab, related_name="hostprofiles")
def validate(self):
- validname = re.compile("^[A-Za-z0-9\-\_\.\/\, ]+$")
+ validname = re.compile(r"^[A-Za-z0-9\-\_\.\/\, ]+$")
if not validname.match(self.name):
return "Invalid host profile name given. Name must only use A-Z, a-z, 0-9, hyphens, underscores, dots, commas, or spaces."
else:
@@ -39,7 +39,7 @@ class InterfaceProfile(models.Model):
id = models.AutoField(primary_key=True)
speed = models.IntegerField()
name = models.CharField(max_length=100)
- host = models.ForeignKey(HostProfile, on_delete=models.DO_NOTHING, related_name='interfaceprofile')
+ host = models.ForeignKey(HostProfile, on_delete=models.CASCADE, related_name='interfaceprofile')
nic_type = models.CharField(
max_length=50,
choices=[
@@ -61,7 +61,7 @@ class DiskProfile(models.Model):
("HDD", "HDD")
])
name = models.CharField(max_length=50)
- host = models.ForeignKey(HostProfile, on_delete=models.DO_NOTHING, related_name='storageprofile')
+ host = models.ForeignKey(HostProfile, on_delete=models.CASCADE, related_name='storageprofile')
rotation = models.IntegerField(default=0)
interface = models.CharField(
max_length=50,
@@ -88,7 +88,7 @@ class CpuProfile(models.Model):
("aarch64", "aarch64")
])
cpus = models.IntegerField()
- host = models.ForeignKey(HostProfile, on_delete=models.DO_NOTHING, related_name='cpuprofile')
+ host = models.ForeignKey(HostProfile, on_delete=models.CASCADE, related_name='cpuprofile')
cflags = models.TextField(null=True)
def __str__(self):
@@ -99,39 +99,19 @@ class RamProfile(models.Model):
id = models.AutoField(primary_key=True)
amount = models.IntegerField()
channels = models.IntegerField()
- host = models.ForeignKey(HostProfile, on_delete=models.DO_NOTHING, related_name='ramprofile')
+ host = models.ForeignKey(HostProfile, on_delete=models.CASCADE, related_name='ramprofile')
def __str__(self):
return str(self.amount) + "G for " + str(self.host)
-# Networking -- located here due to import order requirements
-class Network(models.Model):
- id = models.AutoField(primary_key=True)
- vlan_id = models.IntegerField()
- name = models.CharField(max_length=100)
-
- def __str__(self):
- return self.name
-
-
-class Vlan(models.Model):
- id = models.AutoField(primary_key=True)
- vlan_id = models.IntegerField()
- tagged = models.BooleanField()
- public = models.BooleanField(default=False)
-
- def __str__(self):
- return str(self.vlan_id) + ("_T" if self.tagged else "")
-
-
# Generic resource templates
class GenericResourceBundle(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=300, unique=True)
xml = models.TextField()
- owner = models.ForeignKey(User, null=True, on_delete=models.DO_NOTHING)
- lab = models.ForeignKey(Lab, null=True, on_delete=models.DO_NOTHING)
+ owner = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
+ lab = models.ForeignKey(Lab, null=True, on_delete=models.SET_NULL)
description = models.CharField(max_length=1000, default="")
def getHosts(self):
@@ -145,9 +125,35 @@ class GenericResourceBundle(models.Model):
return self.name
+class Network(models.Model):
+ id = models.AutoField(primary_key=True)
+ name = models.CharField(max_length=100)
+ bundle = models.ForeignKey(GenericResourceBundle, on_delete=models.CASCADE, related_name="networks")
+ is_public = models.BooleanField()
+
+ def __str__(self):
+ return self.name
+
+
+class NetworkConnection(models.Model):
+ network = models.ForeignKey(Network, on_delete=models.CASCADE)
+ vlan_is_tagged = models.BooleanField()
+
+
+class Vlan(models.Model):
+ id = models.AutoField(primary_key=True)
+ vlan_id = models.IntegerField()
+ tagged = models.BooleanField()
+ public = models.BooleanField(default=False)
+ network = models.ForeignKey(Network, on_delete=models.DO_NOTHING, null=True)
+
+ def __str__(self):
+ return str(self.vlan_id) + ("_T" if self.tagged else "")
+
+
class GenericResource(models.Model):
- bundle = models.ForeignKey(GenericResourceBundle, related_name='generic_resources', on_delete=models.DO_NOTHING)
- hostname_validchars = RegexValidator(regex='(?=^.{1,253}$)(?=(^([A-Za-z0-9\-\_]{1,62}\.)*[A-Za-z0-9\-\_]{1,63}$))', message="Enter a valid hostname. Full domain name may be 1-253 characters, each hostname 1-63 characters (including suffixed dot), and valid characters for hostnames are A-Z, a-z, 0-9, hyphen (-), and underscore (_)")
+ bundle = models.ForeignKey(GenericResourceBundle, related_name='generic_resources', on_delete=models.CASCADE)
+ hostname_validchars = RegexValidator(regex=r'(?=^.{1,253}$)(?=(^([A-Za-z0-9\-\_]{1,62}\.)*[A-Za-z0-9\-\_]{1,63}$))', message="Enter a valid hostname. Full domain name may be 1-253 characters, each hostname 1-63 characters (including suffixed dot), and valid characters for hostnames are A-Z, a-z, 0-9, hyphen (-), and underscore (_)")
name = models.CharField(max_length=200, validators=[hostname_validchars])
def getHost(self):
@@ -157,7 +163,7 @@ class GenericResource(models.Model):
return self.name
def validate(self):
- validname = re.compile('(?=^.{1,253}$)(?=(^([A-Za-z0-9\-\_]{1,62}\.)*[A-Za-z0-9\-\_]{1,63}$))')
+ validname = re.compile(r'(?=^.{1,253}$)(?=(^([A-Za-z0-9\-\_]{1,62}\.)*[A-Za-z0-9\-\_]{1,63}$))')
if not validname.match(self.name):
return "Enter a valid hostname. Full domain name may be 1-253 characters, each hostname 1-63 characters (including suffixed dot), and valid characters for hostnames are A-Z, a-z, 0-9, hyphen (-), and underscore (_)"
else:
@@ -167,8 +173,8 @@ class GenericResource(models.Model):
# Host template
class GenericHost(models.Model):
id = models.AutoField(primary_key=True)
- profile = models.ForeignKey(HostProfile, on_delete=models.DO_NOTHING)
- resource = models.OneToOneField(GenericResource, related_name='generic_host', on_delete=models.DO_NOTHING)
+ profile = models.ForeignKey(HostProfile, on_delete=models.CASCADE)
+ resource = models.OneToOneField(GenericResource, related_name='generic_host', on_delete=models.CASCADE)
def __str__(self):
return self.resource.name
@@ -177,20 +183,22 @@ class GenericHost(models.Model):
# Physical, actual resources
class ResourceBundle(models.Model):
id = models.AutoField(primary_key=True)
- template = models.ForeignKey(GenericResourceBundle, on_delete=models.DO_NOTHING)
+ template = models.ForeignKey(GenericResourceBundle, on_delete=models.SET_NULL, null=True)
def __str__(self):
+ if self.template is None:
+ return "Resource bundle " + str(self.id) + " with no template"
return "instance of " + str(self.template)
-
-# Networking
+ def get_host(self, role="Jumphost"):
+ return Host.objects.filter(bundle=self, config__is_head_node=True).first() # should only ever be one, but it is not an invariant in the models
class GenericInterface(models.Model):
id = models.AutoField(primary_key=True)
- vlans = models.ManyToManyField(Vlan)
- profile = models.ForeignKey(InterfaceProfile, on_delete=models.DO_NOTHING)
- host = models.ForeignKey(GenericHost, on_delete=models.DO_NOTHING, related_name='generic_interfaces')
+ profile = models.ForeignKey(InterfaceProfile, on_delete=models.CASCADE)
+ host = models.ForeignKey(GenericHost, on_delete=models.CASCADE, related_name='generic_interfaces')
+ connections = models.ManyToManyField(NetworkConnection)
def __str__(self):
return "type " + str(self.profile) + " on host " + str(self.host)
@@ -222,9 +230,14 @@ class Opsys(models.Model):
return self.name
+class NetworkRole(models.Model):
+ name = models.CharField(max_length=100)
+ network = models.ForeignKey(Network, on_delete=models.CASCADE)
+
+
class ConfigBundle(models.Model):
id = models.AutoField(primary_key=True)
- owner = models.ForeignKey(User, on_delete=models.CASCADE) # consider setting to root user?
+ owner = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=200, unique=True)
description = models.CharField(max_length=1000, default="")
bundle = models.ForeignKey(GenericResourceBundle, null=True, on_delete=models.CASCADE)
@@ -238,6 +251,9 @@ class OPNFVConfig(models.Model):
installer = models.ForeignKey(Installer, on_delete=models.CASCADE)
scenario = models.ForeignKey(Scenario, on_delete=models.CASCADE)
bundle = models.ForeignKey(ConfigBundle, related_name="opnfv_config", on_delete=models.CASCADE)
+ networks = models.ManyToManyField(NetworkRole)
+ name = models.CharField(max_length=300, blank=True, default="")
+ description = models.CharField(max_length=600, blank=True, default="")
def __str__(self):
return "OPNFV job with " + str(self.installer) + " and " + str(self.scenario)
@@ -262,14 +278,18 @@ class Image(models.Model):
name = models.CharField(max_length=200)
owner = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
public = models.BooleanField(default=True)
- # may need to change host_type.on_delete to models.SET() once images are transferrable between compatible host types
host_type = models.ForeignKey(HostProfile, on_delete=models.CASCADE)
description = models.TextField()
+ os = models.ForeignKey(Opsys, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.name
+def get_sentinal_opnfv_role():
+ return OPNFVRole.objects.get_or_create(name="deleted", description="Role was deleted.")
+
+
class HostConfiguration(models.Model):
"""
model to represent a complete configuration for a single
@@ -279,12 +299,38 @@ class HostConfiguration(models.Model):
host = models.ForeignKey(GenericHost, related_name="configuration", on_delete=models.CASCADE)
image = models.ForeignKey(Image, on_delete=models.PROTECT)
bundle = models.ForeignKey(ConfigBundle, related_name="hostConfigurations", null=True, on_delete=models.CASCADE)
- opnfvRole = models.ForeignKey(OPNFVRole, on_delete=models.PROTECT)
+ is_head_node = models.BooleanField(default=False)
def __str__(self):
return "config with " + str(self.host) + " and image " + str(self.image)
+class HostOPNFVConfig(models.Model):
+ role = models.ForeignKey(OPNFVRole, related_name="host_opnfv_configs", on_delete=models.CASCADE)
+ host_config = models.ForeignKey(HostConfiguration, related_name="host_opnfv_config", on_delete=models.CASCADE)
+ opnfv_config = models.ForeignKey(OPNFVConfig, related_name="host_opnfv_config", on_delete=models.CASCADE)
+
+
+class RemoteInfo(models.Model):
+ address = models.CharField(max_length=15)
+ mac_address = models.CharField(max_length=17)
+ password = models.CharField(max_length=100)
+ user = models.CharField(max_length=100)
+ management_type = models.CharField(max_length=50, default="ipmi")
+ versions = models.CharField(max_length=100) # json serialized list of floats
+
+
+def get_default_remote_info():
+ return RemoteInfo.objects.get_or_create(
+ address="default",
+ mac_address="default",
+ password="default",
+ user="default",
+ management_type="default",
+ versions="[default]"
+ )[0].pk
+
+
# Concrete host, actual machine in a lab
class Host(models.Model):
id = models.AutoField(primary_key=True)
@@ -299,6 +345,7 @@ class Host(models.Model):
working = models.BooleanField(default=True)
vendor = models.CharField(max_length=100, default="unknown")
model = models.CharField(max_length=150, default="unknown")
+ remote_management = models.ForeignKey(RemoteInfo, default=get_default_remote_info, on_delete=models.SET(get_default_remote_info))
def __str__(self):
return self.name
@@ -314,3 +361,11 @@ class Interface(models.Model):
def __str__(self):
return self.mac_address + " on host " + str(self.host)
+
+
+class OPNFV_SETTINGS():
+ """
+ This is a static configuration class
+ """
+ # all the required network types in PDF/IDF spec
+ NETWORK_ROLES = ["public", "private", "admin", "mgmt"]