summaryrefslogtreecommitdiffstats
path: root/dashboard/src/workflow
diff options
context:
space:
mode:
Diffstat (limited to 'dashboard/src/workflow')
-rw-r--r--dashboard/src/workflow/models.py94
-rw-r--r--dashboard/src/workflow/resource_bundle_workflow.py214
2 files changed, 136 insertions, 172 deletions
diff --git a/dashboard/src/workflow/models.py b/dashboard/src/workflow/models.py
index 7d24668..4ebb042 100644
--- a/dashboard/src/workflow/models.py
+++ b/dashboard/src/workflow/models.py
@@ -205,27 +205,6 @@ class Confirmation_Step(WorkflowStep):
title = "Confirm Changes"
description = "Does this all look right?"
- def get_vlan_warning(self):
- grb = self.repo_get(self.repo.SELECTED_GRESOURCE_BUNDLE, False)
- if not grb:
- return 0
- if self.repo.BOOKING_MODELS not in self.repo.el:
- return 0
- vlan_manager = grb.lab.vlan_manager
- if vlan_manager is None:
- return 0
- hosts = grb.getHosts()
- for host in hosts:
- for interface in host.generic_interfaces.all():
- for vlan in interface.vlans.all():
- if vlan.public:
- if not vlan_manager.public_vlan_is_available(vlan.vlan_id):
- return 1
- else:
- if not vlan_manager.is_available(vlan.vlan_id):
- return 1 # There is a problem with these vlans
- return 0
-
def get_context(self):
context = super(Confirmation_Step, self).get_context()
context['form'] = ConfirmationForm()
@@ -233,7 +212,6 @@ class Confirmation_Step(WorkflowStep):
self.repo_get(self.repo.CONFIRMATION),
default_flow_style=False
).strip()
- context['vlan_warning'] = self.get_vlan_warning()
return context
@@ -264,33 +242,8 @@ class Confirmation_Step(WorkflowStep):
pass
else:
- if "vlan_input" in request.POST:
- if request.POST.get("vlan_input") == "True":
- self.translate_vlans()
- return self.render(request)
pass
- def translate_vlans(self):
- grb = self.repo_get(self.repo.SELECTED_GRESOURCE_BUNDLE, False)
- if not grb:
- return 0
- vlan_manager = grb.lab.vlan_manager
- if vlan_manager is None:
- return 0
- hosts = grb.getHosts()
- for host in hosts:
- for interface in host.generic_interfaces.all():
- for vlan in interface.vlans.all():
- if not vlan.public:
- if not vlan_manager.is_available(vlan.vlan_id):
- vlan.vlan_id = vlan_manager.get_vlan()
- vlan.save()
- else:
- if not vlan_manager.public_vlan_is_available(vlan.vlan_id):
- pub_vlan = vlan_manager.get_public_vlan()
- vlan.vlan_id = pub_vlan.vlan
- vlan.save()
-
class Workflow():
@@ -455,6 +408,11 @@ class Repository():
except Exception as e:
return "GRB, saving hosts generated exception: " + str(e) + " CODE:0x0005"
+ if 'networks' in models:
+ for net in models['networks'].values():
+ net.bundle = bundle
+ net.save()
+
if 'interfaces' in models:
for interface_set in models['interfaces'].values():
for interface in interface_set:
@@ -466,20 +424,21 @@ class Repository():
else:
return "GRB, no interface set provided. CODE:0x001a"
- if 'vlans' in models:
- for resource_name, mapping in models['vlans'].items():
- for profile_name, vlan_set in mapping.items():
+ if 'connections' in models:
+ for resource_name, mapping in models['connections'].items():
+ for profile_name, connection_set in mapping.items():
interface = GenericInterface.objects.get(
profile__name=profile_name,
host__resource__name=resource_name,
host__resource__bundle=models['bundle']
)
- for vlan in vlan_set:
+ for connection in connection_set:
try:
- vlan.save()
- interface.vlans.add(vlan)
+ connection.network = connection.network
+ connection.save()
+ interface.connections.add(connection)
except Exception as e:
- return "GRB, saving vlan " + str(vlan) + " failed. Exception: " + str(e) + ". CODE:0x0017"
+ return "GRB, saving vlan " + str(connection) + " failed. Exception: " + str(e) + ". CODE:0x0017"
else:
return "GRB, no vlan set provided. CODE:0x0018"
@@ -536,9 +495,6 @@ class Repository():
else:
return "BOOK, no selected resource. CODE:0x000e"
- if not self.reserve_vlans(selected_grb):
- return "BOOK, vlans not available"
-
if 'booking' in models:
booking = models['booking']
else:
@@ -595,30 +551,6 @@ class Repository():
except Exception as e:
return "BOOK, saving booking generated exception: " + str(e) + " CODE:0x0016"
- def reserve_vlans(self, grb):
- """
- True is success
- """
- vlans = []
- public_vlan = None
- vlan_manager = grb.lab.vlan_manager
- if vlan_manager is None:
- return True
- for host in grb.getHosts():
- for interface in host.generic_interfaces.all():
- for vlan in interface.vlans.all():
- if vlan.public:
- public_vlan = vlan
- else:
- vlans.append(vlan.vlan_id)
-
- try:
- vlan_manager.reserve_vlans(vlans)
- vlan_manager.reserve_public_vlan(public_vlan.vlan_id)
- return True
- except Exception:
- return False
-
def __init__(self):
self.el = {}
self.el[self.CONFIRMATION] = {}
diff --git a/dashboard/src/workflow/resource_bundle_workflow.py b/dashboard/src/workflow/resource_bundle_workflow.py
index 4858ebe..536187f 100644
--- a/dashboard/src/workflow/resource_bundle_workflow.py
+++ b/dashboard/src/workflow/resource_bundle_workflow.py
@@ -10,6 +10,7 @@
from django.shortcuts import render
from django.forms import formset_factory
+from django.conf import settings
import json
import re
@@ -25,11 +26,12 @@ from workflow.forms import (
)
from resource_inventory.models import (
GenericResourceBundle,
- Vlan,
GenericInterface,
GenericHost,
GenericResource,
- HostProfile
+ HostProfile,
+ Network,
+ NetworkConnection
)
from dashboard.exceptions import (
InvalidVlanConfigurationException,
@@ -185,6 +187,7 @@ class Define_Nets(WorkflowStep):
hostlist = self.repo_get(self.repo.GRB_LAST_HOSTLIST, None)
added_list = []
added_dict = {}
+ context['debug'] = settings.DEBUG
context['added_hosts'] = []
if hostlist is not None:
new_hostlist = []
@@ -239,15 +242,15 @@ class Define_Nets(WorkflowStep):
self.metastep.set_valid("Networks applied successfully")
except ResourceAvailabilityException:
self.metastep.set_invalid("Public network not availble")
- except Exception:
- self.metastep.set_invalid("An error occurred when applying networks")
+ except Exception as e:
+ self.metastep.set_invalid("An error occurred when applying networks: " + str(e))
return self.render(request)
def updateModels(self, xmlData):
models = self.repo_get(self.repo.GRESOURCE_BUNDLE_MODELS, {})
- models["vlans"] = {}
- given_hosts, interfaces = self.parseXml(xmlData)
- vlan_manager = models['bundle'].lab.vlan_manager
+ models["connections"] = {}
+ models['networks'] = {}
+ given_hosts, interfaces, networks = self.parseXml(xmlData)
existing_host_list = models.get("hosts", [])
existing_hosts = {} # maps id to host
for host in existing_host_list:
@@ -255,104 +258,133 @@ class Define_Nets(WorkflowStep):
bundle = models.get("bundle", GenericResourceBundle(owner=self.repo_get(self.repo.SESSION_USER)))
+ for net_id, net in networks.items():
+ network = Network()
+ network.name = net['name']
+ network.bundle = bundle
+ network.is_public = net['public']
+ models['networks'][net_id] = network
+
for hostid, given_host in given_hosts.items():
existing_host = existing_hosts[hostid[5:]]
for ifaceId in given_host['interfaces']:
iface = interfaces[ifaceId]
- if existing_host.resource.name not in models['vlans']:
- models['vlans'][existing_host.resource.name] = {}
- models['vlans'][existing_host.resource.name][iface['profile_name']] = []
- for network in iface['networks']:
- vlan_id = network['network']['vlan']
- is_public = network['network']['public']
- if is_public:
- public_net = vlan_manager.get_public_vlan()
- if public_net is None:
- raise ResourceAvailabilityException("No public networks available")
- vlan_id = vlan_manager.get_public_vlan().vlan
- vlan = Vlan(vlan_id=vlan_id, tagged=network['tagged'], public=is_public)
- models['vlans'][existing_host.resource.name][iface['profile_name']].append(vlan)
+ if existing_host.resource.name not in models['connections']:
+ models['connections'][existing_host.resource.name] = {}
+ models['connections'][existing_host.resource.name][iface['profile_name']] = []
+ for connection in iface['connections']:
+ network_id = connection['network']
+ net = models['networks'][network_id]
+ connection = NetworkConnection(vlan_is_tagged=connection['tagged'], network=net)
+ models['connections'][existing_host.resource.name][iface['profile_name']].append(connection)
bundle.xml = xmlData
self.repo_put(self.repo.GRESOURCE_BUNDLE_MODELS, models)
- # serialize and deserialize xml from mxGraph
- def parseXml(self, xmlString):
- parent_nets = {} # map network ports to networks
- networks = {} # maps net id to network object
- hosts = {} # cotains id -> hosts, each containing interfaces, referencing networks
- interfaces = {} # maps id -> interface
+ def decomposeXml(self, xmlString):
+ """
+ This function takes in an xml doc from our front end
+ and returns dictionaries that map cellIds to the xml
+ nodes themselves. There is no unpacking of the
+ xml objects, just grouping and organizing
+ """
+
+ connections = {}
+ networks = {}
+ hosts = {}
+ interfaces = {}
+ network_ports = {}
+
xmlDom = minidom.parseString(xmlString)
root = xmlDom.documentElement.firstChild
- netids = {}
- untagged_ints = {}
for cell in root.childNodes:
cellId = cell.getAttribute('id')
+ group = cellId.split("_")[0]
+ parentGroup = cell.getAttribute("parent").split("_")[0]
+ # place cell into correct group
if cell.getAttribute("edge"):
- # cell is a network connection
- escaped_json_str = cell.getAttribute("value")
- json_str = escaped_json_str.replace('"', '"')
- attributes = json.loads(json_str)
- tagged = attributes['tagged']
- interface = None
- network = None
- src = cell.getAttribute("source")
- tgt = cell.getAttribute("target")
- if src in parent_nets:
- # src is a network port
- network = networks[parent_nets[src]]
- if tgt in untagged_ints and not tagged:
- raise InvalidVlanConfigurationException("More than one untagged vlan on an interface")
- interface = interfaces[tgt]
- untagged_ints[tgt] = True
- else:
- network = networks[parent_nets[tgt]]
- if src in untagged_ints and not tagged:
- raise InvalidVlanConfigurationException("More than one untagged vlan on an interface")
- interface = interfaces[src]
- untagged_ints[src] = True
- interface['networks'].append({"network": network, "tagged": tagged})
-
- elif "network" in cellId: # cell is a network
- escaped_json_str = cell.getAttribute("value")
- json_str = escaped_json_str.replace('"', '"')
- net_info = json.loads(json_str)
- nid = net_info['vlan_id']
- public = net_info['public']
- try:
- int_netid = int(nid)
- assert public or int_netid > 1, "Net id is 1 or lower"
- assert int_netid < 4095, "Net id is 4095 or greater"
- except Exception:
- raise InvalidVlanConfigurationException("VLAN ID is not an integer more than 1 and less than 4095")
- if nid in netids:
- raise NetworkExistsException("Non unique network id found")
- else:
- pass
- network = {"name": net_info['name'], "vlan": net_info['vlan_id'], "public": public}
- netids[net_info['vlan_id']] = True
- networks[cellId] = network
-
- elif "host" in cellId: # cell is a host/machine
- # TODO gather host info
- cell_json_str = cell.getAttribute("value")
- cell_json = json.loads(cell_json_str)
- host = {"interfaces": [], "name": cellId, "profile_name": cell_json['name']}
- hosts[cellId] = host
-
- elif cell.hasAttribute("parent"):
- parentId = cell.getAttribute('parent')
- if "network" in parentId:
- parent_nets[cellId] = parentId
- elif "host" in parentId:
- # TODO gather iface info
- cell_json_str = cell.getAttribute("value")
- cell_json = json.loads(cell_json_str)
- iface = {"name": cellId, "networks": [], "profile_name": cell_json['name']}
- hosts[parentId]['interfaces'].append(cellId)
- interfaces[cellId] = iface
- return hosts, interfaces
+ connections[cellId] = cell
+
+ elif "network" in group:
+ networks[cellId] = cell
+
+ elif "host" in group:
+ hosts[cellId] = cell
+
+ elif "host" in parentGroup:
+ interfaces[cellId] = cell
+
+ # make network ports also map to thier network
+ elif "network" in parentGroup:
+ network_ports[cellId] = cell.getAttribute("parent") # maps port ID to net ID
+
+ return connections, networks, hosts, interfaces, network_ports
+
+ # serialize and deserialize xml from mxGraph
+ def parseXml(self, xmlString):
+ networks = {} # maps net name to network object
+ hosts = {} # cotains id -> hosts, each containing interfaces, referencing networks
+ interfaces = {} # maps id -> interface
+ untagged_ifaces = set() # used to check vlan config
+ network_names = set() # used to check network names
+ xml_connections, xml_nets, xml_hosts, xml_ifaces, xml_ports = self.decomposeXml(xmlString)
+
+ # parse Hosts
+ for cellId, cell in xml_hosts.items():
+ cell_json_str = cell.getAttribute("value")
+ cell_json = json.loads(cell_json_str)
+ host = {"interfaces": [], "name": cellId, "profile_name": cell_json['name']}
+ hosts[cellId] = host
+
+ # parse networks
+ for cellId, cell in xml_nets.items():
+ escaped_json_str = cell.getAttribute("value")
+ json_str = escaped_json_str.replace('&quot;', '"')
+ net_info = json.loads(json_str)
+ net_name = net_info['name']
+ public = net_info['public']
+ if net_name in network_names:
+ raise NetworkExistsException("Non unique network name found")
+ network = {"name": net_name, "public": public, "id": cellId}
+ networks[cellId] = network
+ network_names.add(net_name)
+
+ # parse interfaces
+ for cellId, cell in xml_ifaces.items():
+ parentId = cell.getAttribute('parent')
+ cell_json_str = cell.getAttribute("value")
+ cell_json = json.loads(cell_json_str)
+ iface = {"name": cellId, "connections": [], "profile_name": cell_json['name']}
+ hosts[parentId]['interfaces'].append(cellId)
+ interfaces[cellId] = iface
+
+ # parse connections
+ for cellId, cell in xml_connections.items():
+ escaped_json_str = cell.getAttribute("value")
+ json_str = escaped_json_str.replace('&quot;', '"')
+ attributes = json.loads(json_str)
+ tagged = attributes['tagged']
+ interface = None
+ network = None
+ src = cell.getAttribute("source")
+ tgt = cell.getAttribute("target")
+ if src in interfaces:
+ interface = interfaces[src]
+ network = networks[xml_ports[tgt]]
+ else:
+ interface = interfaces[tgt]
+ network = networks[xml_ports[src]]
+
+ if not tagged:
+ if interface['name'] in untagged_ifaces:
+ raise InvalidVlanConfigurationException("More than one untagged vlan on an interface")
+ untagged_ifaces.add(interface['name'])
+
+ # add connection to interface
+ interface['connections'].append({"tagged": tagged, "network": network['id']})
+
+ return hosts, interfaces, networks
class Resource_Meta_Info(WorkflowStep):