aboutsummaryrefslogtreecommitdiffstats
path: root/src/resource_inventory
diff options
context:
space:
mode:
authorParker Berberian <pberberian@iol.unh.edu>2019-04-16 13:59:21 +0000
committerGerrit Code Review <gerrit@opnfv.org>2019-04-16 13:59:21 +0000
commitd8e9f0e33648426a95ae50bf27fa089036f6a1fd (patch)
treeea21a6032f6ee21aecc5ea12b3971455825edfe2 /src/resource_inventory
parentc4fd0505788fd3b0cac96bc2dd0c627b1a0054ce (diff)
parentf446907704b9cc0fee83cf4b4633cbfda03d2430 (diff)
Merge "Fixing Network Models"
Diffstat (limited to 'src/resource_inventory')
-rw-r--r--src/resource_inventory/migrations/0009_auto_20190315_1757.py73
-rw-r--r--src/resource_inventory/models.py57
-rw-r--r--src/resource_inventory/resource_manager.py78
3 files changed, 162 insertions, 46 deletions
diff --git a/src/resource_inventory/migrations/0009_auto_20190315_1757.py b/src/resource_inventory/migrations/0009_auto_20190315_1757.py
new file mode 100644
index 0000000..92ed0e9
--- /dev/null
+++ b/src/resource_inventory/migrations/0009_auto_20190315_1757.py
@@ -0,0 +1,73 @@
+# Generated by Django 2.1 on 2019-03-15 17:57
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('resource_inventory', '0008_host_remote_management'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='NetworkConnection',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('vlan_is_tagged', models.BooleanField()),
+ ],
+ ),
+ migrations.CreateModel(
+ name='NetworkRole',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=100)),
+ ],
+ ),
+ migrations.RemoveField(
+ model_name='genericinterface',
+ name='vlans',
+ ),
+ migrations.RemoveField(
+ model_name='network',
+ name='vlan_id',
+ ),
+ migrations.AddField(
+ model_name='network',
+ name='bundle',
+ field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='networks', to='resource_inventory.GenericResourceBundle'),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name='network',
+ name='is_public',
+ field=models.BooleanField(default=False),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name='vlan',
+ name='network',
+ field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='resource_inventory.Network'),
+ ),
+ migrations.AddField(
+ model_name='networkrole',
+ name='network',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='resource_inventory.Network'),
+ ),
+ migrations.AddField(
+ model_name='networkconnection',
+ name='network',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='resource_inventory.Network'),
+ ),
+ migrations.AddField(
+ model_name='genericinterface',
+ name='connections',
+ field=models.ManyToManyField(to='resource_inventory.NetworkConnection'),
+ ),
+ migrations.AddField(
+ model_name='opnfvconfig',
+ name='networks',
+ field=models.ManyToManyField(to='resource_inventory.NetworkRole'),
+ ),
+ ]
diff --git a/src/resource_inventory/models.py b/src/resource_inventory/models.py
index bdc1f5d..d3f47d4 100644
--- a/src/resource_inventory/models.py
+++ b/src/resource_inventory/models.py
@@ -105,26 +105,6 @@ class RamProfile(models.Model):
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)
@@ -145,6 +125,32 @@ 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.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 (_)")
@@ -188,14 +194,11 @@ class ResourceBundle(models.Model):
return Host.objects.filter(bundle=self, config__opnfvRole__name=role).first()
-# Networking
-
-
class GenericInterface(models.Model):
id = models.AutoField(primary_key=True)
- vlans = models.ManyToManyField(Vlan)
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)
@@ -227,6 +230,11 @@ 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)
@@ -243,6 +251,7 @@ 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)
def __str__(self):
return "OPNFV job with " + str(self.installer) + " and " + str(self.scenario)
diff --git a/src/resource_inventory/resource_manager.py b/src/resource_inventory/resource_manager.py
index 52b0055..d3d3ed4 100644
--- a/src/resource_inventory/resource_manager.py
+++ b/src/resource_inventory/resource_manager.py
@@ -14,7 +14,14 @@ from dashboard.exceptions import (
ResourceProvisioningException,
ModelValidationException,
)
-from resource_inventory.models import Host, HostConfiguration, ResourceBundle, HostProfile
+from resource_inventory.models import (
+ Host,
+ HostConfiguration,
+ ResourceBundle,
+ HostProfile,
+ Network,
+ Vlan
+)
class ResourceManager:
@@ -66,39 +73,48 @@ class ResourceManager:
self.releaseHost(host)
resourceBundle.delete()
- def convertResourceBundle(self, genericResourceBundle, lab=None, config=None):
+ 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()
- resource_bundle.template = genericResourceBundle
- resource_bundle.save()
-
- hosts = genericResourceBundle.getHosts()
-
- # current supported case: user creating new booking
- # currently unsupported: editing existing booking
-
+ resource_bundle = ResourceBundle.objects.create(template=genericResourceBundle)
+ generic_hosts = genericResourceBundle.getHosts()
physical_hosts = []
- for host in 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=host)
+ host_config = HostConfiguration.objects.get(bundle=config, host=generic_host)
try:
- physical_host = self.acquireHost(host, genericResourceBundle.lab.name)
+ physical_host = self.acquireHost(generic_host, genericResourceBundle.lab.name)
except ResourceAvailabilityException:
- self.fail_acquire(physical_hosts)
+ self.fail_acquire(physical_hosts, vlan_map)
raise ResourceAvailabilityException("Could not provision hosts, not enough available")
try:
physical_host.bundle = resource_bundle
- physical_host.template = host
+ physical_host.template = generic_host
physical_host.config = host_config
physical_hosts.append(physical_host)
- self.configureNetworking(physical_host)
+ self.configureNetworking(physical_host, vlan_map)
except Exception:
- self.fail_acquire(physical_hosts)
+ self.fail_acquire(physical_hosts, vlan_map)
raise ResourceProvisioningException("Network configuration failed.")
try:
physical_host.save()
@@ -108,13 +124,20 @@ class ResourceManager:
return resource_bundle
- def configureNetworking(self, host):
+ 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 vlan in generic_interface.vlans.all():
- physical_interface.config.add(vlan)
+ 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):
@@ -136,6 +159,17 @@ class ResourceManager:
host.booked = False
host.save()
- def fail_acquire(self, hosts):
+ 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 = hosts[0].template.resource.bundle
+ vlan_manager = hosts[0].lab.vlan_manager
+ self.releaseNetworks(grb, vlan_manager, vlans)
for host in hosts:
self.releaseHost(host)