Merge "Fix vlan leak"
[pharos-tools.git] / dashboard / src / booking / quick_deployer.py
index f076a2e..763c8a0 100644 (file)
@@ -22,7 +22,6 @@ from resource_inventory.models import (
     Image,
     GenericResourceBundle,
     ConfigBundle,
-    Vlan,
     Host,
     HostProfile,
     HostConfiguration,
@@ -30,7 +29,11 @@ from resource_inventory.models import (
     GenericHost,
     GenericInterface,
     OPNFVRole,
-    OPNFVConfig
+    OPNFVConfig,
+    Network,
+    NetworkConnection,
+    NetworkRole,
+    HostOPNFVConfig,
 )
 from resource_inventory.resource_manager import ResourceManager
 from resource_inventory.pdf_templater import PDFTemplater
@@ -90,6 +93,10 @@ class NoRemainingPublicNetwork(Exception):
     pass
 
 
+class BookingPermissionException(Exception):
+    pass
+
+
 def parse_host_field(host_field_contents):
     host_json = json.loads(host_field_contents)
     lab_dict = host_json['labs'][0]
@@ -179,18 +186,30 @@ def generate_hostconfig(generic_host, image, config_bundle):
     hconf = HostConfiguration()
     hconf.host = generic_host
     hconf.image = image
-
-    opnfvrole = OPNFVRole.objects.get(name="Jumphost")
-    if not opnfvrole:
-        raise OPNFVRoleDNE("No jumphost role was found.")
-
-    hconf.opnfvRole = opnfvrole
     hconf.bundle = config_bundle
+    hconf.is_head_node = True
     hconf.save()
 
     return hconf
 
 
+def generate_hostopnfv(hostconfig, opnfvconfig):
+    config = HostOPNFVConfig()
+    role = None
+    try:
+        role = OPNFVRole.objects.get(name="Jumphost")
+    except Exception:
+        role = OPNFVRole.objects.create(
+            name="Jumphost",
+            description="Single server jumphost role"
+        )
+    config.role = role
+    config.host_config = hostconfig
+    config.opnfv_config = opnfvconfig
+    config.save()
+    return config
+
+
 def generate_resource_bundle(generic_resource_bundle, config_bundle):  # warning: requires cleanup
     try:
         resource_manager = ResourceManager.getInstance()
@@ -226,6 +245,20 @@ def check_invariants(request, **kwargs):
         raise BookingLengthException("Booking must be between 1 and 21 days long")
 
 
+def configure_networking(grb, config):
+    # create network
+    net = Network.objects.create(name="public", bundle=grb, is_public=True)
+    # connect network to generic host
+    grb.getHosts()[0].generic_interfaces.first().connections.add(
+        NetworkConnection.objects.create(network=net, vlan_is_tagged=False)
+    )
+    # asign network role
+    role = NetworkRole.objects.create(name="public", network=net)
+    opnfv_config = config.opnfv_config.first()
+    if opnfv_config:
+        opnfv_config.networks.add(role)
+
+
 def create_from_form(form, request):
     quick_booking_id = str(uuid.uuid4())
 
@@ -246,62 +279,56 @@ def create_from_form(form, request):
     data['host_profile'] = host_profile
     check_invariants(request, **data)
 
+    # check booking privileges
+    if Booking.objects.filter(owner=request.user, end__gt=timezone.now()).count() >= 3 and not request.user.userprofile.booking_privledge:
+        raise BookingPermissionException("You do not have permission to have more than 3 bookings at a time.")
+
     check_available_matching_host(lab, host_profile)  # requires cleanup if failure after this point
 
     grbundle = generate_grb(request.user, lab, quick_booking_id)
-
     gresource = generate_gresource(grbundle, hostname)
-
     ghost = generate_ghost(gresource, host_profile)
-
     cbundle = generate_config_bundle(request.user, quick_booking_id, grbundle)
+    hconf = generate_hostconfig(ghost, image, cbundle)
 
     # if no installer provided, just create blank host
+    opnfv_config = None
     if installer:
-        generate_opnfvconfig(scenario, installer, cbundle)
-
-    generate_hostconfig(ghost, image, cbundle)
+        opnfv_config = generate_opnfvconfig(scenario, installer, cbundle)
+        generate_hostopnfv(hconf, opnfv_config)
 
     # construct generic interfaces
     for interface_profile in host_profile.interfaceprofile.all():
         generic_interface = GenericInterface.objects.create(profile=interface_profile, host=ghost)
         generic_interface.save()
 
-    # get vlan, assign to first interface
-    publicnetwork = lab.vlan_manager.get_public_vlan()
-    if not publicnetwork:
-        raise NoRemainingPublicNetwork("No public networks were available for your pod")
-    publicvlan = publicnetwork.vlan
-    lab.vlan_manager.reserve_public_vlan(publicvlan)
-
-    vlan = Vlan.objects.create(vlan_id=publicvlan, tagged=False, public=True)
-    vlan.save()
-
-    ghost.generic_interfaces.first().vlans.add(vlan)
-    ghost.generic_interfaces.first().save()
+    configure_networking(grbundle, cbundle)
 
     # generate resource bundle
     resource_bundle = generate_resource_bundle(grbundle, cbundle)
 
     # generate booking
-    booking = Booking()
-    booking.purpose = purpose_field
-    booking.project = project_field
-    booking.lab = lab
-    booking.owner = request.user
-    booking.start = timezone.now()
-    booking.end = timezone.now() + timedelta(days=int(length))
-    booking.resource = resource_bundle
-    booking.pdf = PDFTemplater.makePDF(booking.resource)
-    booking.config_bundle = cbundle
-    booking.save()
+    booking = Booking.objects.create(
+        purpose=purpose_field,
+        project=project_field,
+        lab=lab,
+        owner=request.user,
+        start=timezone.now(),
+        end=timezone.now() + timedelta(days=int(length)),
+        resource=resource_bundle,
+        config_bundle=cbundle,
+        opnfv_config=opnfv_config
+    )
+    booking.pdf = PDFTemplater.makePDF(booking)
+
     users_field = users_field[2:-2]
     if users_field:  # may be empty after split, if no collaborators entered
         users_field = json.loads(users_field)
         for collaborator in users_field:
             user = User.objects.get(id=collaborator['id'])
             booking.collaborators.add(user)
-        booking.save()
+
+    booking.save()
 
     # generate job
     JobFactory.makeCompleteJob(booking)