aboutsummaryrefslogtreecommitdiffstats
path: root/src/dashboard
diff options
context:
space:
mode:
Diffstat (limited to 'src/dashboard')
-rw-r--r--src/dashboard/__init__.py8
-rw-r--r--src/dashboard/admin.py16
-rw-r--r--src/dashboard/admin_utils.py811
-rw-r--r--src/dashboard/apps.py15
-rw-r--r--src/dashboard/context_processors.py13
-rw-r--r--src/dashboard/exceptions.py52
-rw-r--r--src/dashboard/fixtures/dashboard.json164
-rw-r--r--src/dashboard/models.py9
-rw-r--r--src/dashboard/populate_db_iol.py352
-rw-r--r--src/dashboard/tasks.py98
-rw-r--r--src/dashboard/templatetags/__init__.py8
-rw-r--r--src/dashboard/testing_utils.py315
-rw-r--r--src/dashboard/tests/__init__.py8
-rw-r--r--src/dashboard/tests/test_views.py30
-rw-r--r--src/dashboard/urls.py42
-rw-r--r--src/dashboard/utils.py52
-rw-r--r--src/dashboard/views.py119
17 files changed, 0 insertions, 2112 deletions
diff --git a/src/dashboard/__init__.py b/src/dashboard/__init__.py
deleted file mode 100644
index b6fef6c..0000000
--- a/src/dashboard/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-##############################################################################
-# Copyright (c) 2016 Max Breitenfeldt 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
-##############################################################################
diff --git a/src/dashboard/admin.py b/src/dashboard/admin.py
deleted file mode 100644
index bd4d96c..0000000
--- a/src/dashboard/admin.py
+++ /dev/null
@@ -1,16 +0,0 @@
-##############################################################################
-# Copyright (c) 2016 Max Breitenfeldt and others.
-# Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, 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.contrib import admin
-
-
-admin.site.site_header = "Laas Dashboard Administration"
-admin.site.site_title = "Laas Dashboard"
diff --git a/src/dashboard/admin_utils.py b/src/dashboard/admin_utils.py
deleted file mode 100644
index 75e4f3e..0000000
--- a/src/dashboard/admin_utils.py
+++ /dev/null
@@ -1,811 +0,0 @@
-##############################################################################
-# Copyright (c) 2021 Sawyer Bergeron 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 (
- ResourceTemplate,
- Image,
- Server,
- ResourceBundle,
- ResourceProfile,
- InterfaceProfile,
- PhysicalNetwork,
- ResourceConfiguration,
- NetworkConnection,
- InterfaceConfiguration,
- Network,
- DiskProfile,
- CpuProfile,
- RamProfile,
- Interface,
- CloudInitFile,
-)
-
-import json
-import yaml
-import sys
-import inspect
-import pydoc
-import csv
-
-from django.contrib.auth.models import User
-
-from account.models import (
- Lab,
- PublicNetwork
-)
-
-from resource_inventory.resource_manager import ResourceManager
-from resource_inventory.pdf_templater import PDFTemplater
-
-from booking.quick_deployer import update_template
-
-from datetime import timedelta, date, datetime, timezone
-
-from booking.models import Booking
-from notifier.manager import NotificationHandler
-from api.models import JobFactory
-
-from api.models import JobStatus, Job, GeneratedCloudConfig
-
-
-def print_div():
- """
- Utility function for printing dividers, does nothing directly useful as a utility
- """
- print("=" * 68)
-
-
-def book_host(owner_username, host_labid, lab_username, hostname, image_id, template_name, length_days=21, collaborator_usernames=[], purpose="internal", project="LaaS"):
- """
- creates a quick booking using the given host
-
- @owner_username is the simple username for the user who will own the resulting booking.
- Do not set this to a lab username!
-
- @image_id is the django id of the image in question, NOT the labid of the image.
- Query Image objects by their public status and compatible host types
-
- @host_labid is usually of the form `hpe3` or similar, is the labid of the Server (subtype of Resource) object
-
- @lab_username for iol is `unh_iol`, other labs will be documented here
-
- @hostname the hostname that the resulting host should have set
-
- @template_name the name of the (public, or user accessible) template to use for this booking
-
- @length_days how long the booking should be, no hard limit currently
-
- @collaborator_usernames a list of usernames for collaborators to the booking
-
- @purpose what this booking will be used for
-
- @project what project/group this booking is on behalf of or the owner represents
- """
- lab = Lab.objects.get(lab_user__username=lab_username)
- host = Server.objects.filter(lab=lab).get(labid=host_labid)
- if host.booked:
- print("Can't book host, already marked as booked")
- return
- else:
- host.booked = True
- host.save()
-
- template = ResourceTemplate.objects.filter(public=True).get(name=template_name)
- image = Image.objects.get(id=image_id)
-
- owner = User.objects.get(username=owner_username)
-
- new_template = update_template(template, image, hostname, owner)
-
- rmanager = ResourceManager.getInstance()
-
- vlan_map = rmanager.get_vlans(new_template)
-
- # only a single host so can reuse var for iter here
- resource_bundle = ResourceBundle.objects.create(template=new_template)
- res_configs = new_template.getConfigs()
-
- for config in res_configs:
- try:
- host.bundle = resource_bundle
- host.config = config
- rmanager.configureNetworking(resource_bundle, host, vlan_map)
- host.save()
- except Exception:
- host.booked = False
- host.save()
- print("Failed to book host due to error configuring it")
- return
-
- new_template.save()
-
- booking = Booking.objects.create(
- purpose=purpose,
- project=project,
- lab=lab,
- owner=owner,
- start=timezone.now(),
- end=timezone.now() + timedelta(days=int(length_days)),
- resource=resource_bundle,
- opnfv_config=None
- )
-
- booking.pdf = PDFTemplater.makePDF(booking)
-
- booking.save()
-
- for collaborator_username in collaborator_usernames:
- try:
- user = User.objects.get(username=collaborator_username)
- booking.collaborators.add(user)
- except Exception:
- print("couldn't add user with username ", collaborator_username)
-
- booking.save()
-
- JobFactory.makeCompleteJob(booking)
- NotificationHandler.notify_new_booking(booking)
-
-
-def mark_working(host_labid, lab_username, working=True):
- """
- Mark a host working/not working so that it is either bookable or hidden in the dashboard.
-
- @host_labid is usually of the form `hpe3` or similar, is the labid of the Server (subtype of Resource) object
-
- @lab_username: param of the form `unh_iol` or similar
-
- @working: bool, whether by the end of execution the host should be considered working or not working
- """
-
- lab = Lab.objects.get(lab_user__username=lab_username)
- server = Server.objects.filter(lab=lab).get(labid=host_labid)
- print("changing server working status from ", server.working, "to", working)
- server.working = working
- server.save()
-
-
-def mark_booked(host_labid, lab_username, booked=True):
- """
- Mark a host as booked/unbooked
-
- @host_labid is usually of the form `hpe3` or similar, is the labid of the Server (subtype of Resource) object
-
- @lab_username: param of the form `unh_iol` or similar
-
- @working: bool, whether by the end of execution the host should be considered booked or not booked
- """
-
- lab = Lab.objects.get(lab_user__username=lab_username)
- server = Server.objects.filter(lab=lab).get(labid=host_labid)
- print("changing server booked status from ", server.booked, "to", booked)
- server.booked = booked
- server.save()
-
-
-def get_host(host_labid, lab_username):
- """
- Returns host filtered by lab and then unique id within lab
-
- @host_labid is usually of the form `hpe3` or similar, is the labid of the Server (subtype of Resource) object
-
- @lab_username: param of the form `unh_iol` or similar
- """
- lab = Lab.objects.get(lab_user__username=lab_username)
- return Server.objects.filter(lab=lab).get(labid=host_labid)
-
-
-def get_info(host_labid, lab_username):
- """
- Returns various information on the host queried by the given parameters
-
- @host_labid is usually of the form `hpe3` or similar, is the labid of the Server (subtype of Resource) object
-
- @lab_username: param of the form `unh_iol` or similar
- """
- info = {}
- host = get_host(host_labid, lab_username)
- info['host_labid'] = host_labid
- info['booked'] = host.booked
- info['working'] = host.working
- info['profile'] = str(host.profile)
- if host.bundle:
- binfo = {}
- info['bundle'] = binfo
- if host.config:
- cinfo = {}
- info['config'] = cinfo
-
- return info
-
-
-class CumulativeData:
- use_days = 0
- count_bookings = 0
- count_extensions = 0
-
- def __init__(self, file_writer):
- self.file_writer = file_writer
-
- def account(self, booking, usage_days):
- self.count_bookings += 1
- self.count_extensions += booking.ext_count
- self.use_days += usage_days
-
- def write_cumulative(self):
- self.file_writer.writerow([])
- self.file_writer.writerow([])
- self.file_writer.writerow(['Lab Use Days', 'Count of Bookings', 'Total Extensions Used'])
- self.file_writer.writerow([self.use_days, self.count_bookings, (self.count_bookings * 2) - self.count_extensions])
-
-
-def get_years_booking_data(start_year=None, end_year=None):
- """
- Outputs yearly booking information from the past 'start_year' years (default: current year)
- until the last day of the end year (default current year) as a csv file.
- """
- if start_year is None and end_year is None:
- start = datetime.combine(date(datetime.now().year, 1, 1), datetime.min.time()).replace(tzinfo=timezone.utc)
- end = datetime.combine(date(start.year + 1, 1, 1), datetime.min.time()).replace(tzinfo=timezone.utc)
- elif end_year is None:
- start = datetime.combine(date(start_year, 1, 1), datetime.min.time()).replace(tzinfo=timezone.utc)
- end = datetime.combine(date(datetime.now().year, 1, 1), datetime.min.time()).replace(tzinfo=timezone.utc)
- else:
- start = datetime.combine(date(start_year, 1, 1), datetime.min.time()).replace(tzinfo=timezone.utc)
- end = datetime.combine(date(end_year + 1, 1, 1), datetime.min.time()).replace(tzinfo=timezone.utc)
-
- if (start.year == end.year - 1):
- file_name = "yearly_booking_data_" + str(start.year) + ".csv"
- else:
- file_name = "yearly_booking_data_" + str(start.year) + "-" + str(end.year - 1) + ".csv"
-
- with open(file_name, "w", newline="") as file:
- file_writer = csv.writer(file)
- cumulative_data = CumulativeData(file_writer)
- file_writer.writerow(
- [
- 'ID',
- 'Project',
- 'Purpose',
- 'User',
- 'Collaborators',
- 'Extensions Left',
- 'Usage Days',
- 'Start',
- 'End'
- ]
- )
-
- for booking in Booking.objects.filter(start__gte=start, start__lte=end):
- filtered = False
- booking_filter = [279]
- user_filter = ["ParkerBerberian", "ssmith", "ahassick", "sbergeron", "jhodgdon", "rhodgdon", "aburch", "jspewock"]
- user = booking.owner.username if booking.owner.username is not None else "None"
-
- for b in booking_filter:
- if b == booking.id:
- filtered = True
-
- for u in user_filter:
- if u == user:
- filtered = True
- # trims time delta to the the specified year(s) if between years
- usage_days = ((end if booking.end > end else booking.end) - (start if booking.start < start else booking.start)).days
- collaborators = []
-
- for c in booking.collaborators.all():
- collaborators.append(c.username)
-
- if (not filtered):
- cumulative_data.account(booking, usage_days)
- file_writer.writerow([
- str(booking.id),
- str(booking.project),
- str(booking.purpose),
- str(booking.owner.username),
- ','.join(collaborators),
- str(booking.ext_count),
- str(usage_days),
- str(booking.start),
- str(booking.end)
- ])
- cumulative_data.write_cumulative()
-
-
-def map_cntt_interfaces(labid: str):
- """
- Use this during cntt migrations, call it with a host labid and it will change profiles for this host
- as well as mapping its interfaces across. interface ens1f2 should have the mac address of interface eno50
- as an invariant before calling this function
- """
- host = get_host(labid, "unh_iol")
- host.profile = ResourceProfile.objects.get(name="HPE x86 CNTT")
- host.save()
- host = get_host(labid, "unh_iol")
-
- for iface in host.interfaces.all():
- new_ifprofile = None
- if iface.profile.name == "ens1f2":
- new_ifprofile = InterfaceProfile.objects.get(host=host.profile, name="eno50")
- else:
- new_ifprofile = InterfaceProfile.objects.get(host=host.profile, name=iface.profile.name)
-
- iface.profile = new_ifprofile
-
- iface.save()
-
-
-def detect_leaked_hosts(labid="unh_iol"):
- """
- Use this to try to detect leaked hosts.
- These hosts may still be in the process of unprovisioning,
- but if they are not (or unprovisioning is frozen) then
- these hosts are instead leaked
- """
- working_servers = Server.objects.filter(working=True, lab__lab_user__username=labid)
- booked = working_servers.filter(booked=True)
- filtered = booked
- print_div()
- print("In use now:")
- for booking in Booking.objects.filter(end__gte=timezone.now()):
- res_for_booking = booking.resource.get_resources()
- print(res_for_booking)
- for resource in res_for_booking:
- filtered = filtered.exclude(id=resource.id)
- print_div()
- print("Possibly leaked:")
- for host in filtered:
- print(host)
- print_div()
- return filtered
-
-
-def booking_for_host(host_labid: str, lab_username="unh_iol"):
- """
- Returns the booking that this server is a part of, if any.
- Fails with an exception if no such booking exists
-
- @host_labid is usually of the form `hpe3` or similar, is the labid of the Server (subtype of Resource) object
-
- @lab_username: param of the form `unh_iol` or similar
- """
- server = Server.objects.get(lab__lab_user__username=lab_username, labid=host_labid)
- booking = server.bundle.booking_set.first()
- print_div()
- print(booking)
- print("id:", booking.id)
- print("owner:", booking.owner)
- print("job (id):", booking.job, "(" + str(booking.job.id) + ")")
- print_div()
- return booking
-
-
-def force_release_booking(booking_id: int):
- """
- Takes a booking id and forces the booking to end whether or not the tasks have
- completed normally.
-
- Use with caution! Hosts may or may not be released depending on other underlying issues
-
- @booking_id: the id of the Booking object to be released
- """
- booking = Booking.objects.get(id=booking_id)
- job = booking.job
- tasks = job.get_tasklist()
- for task in tasks:
- task.status = JobStatus.DONE
- task.save()
-
-
-def free_leaked_public_vlans(safety_buffer_days=2):
- for lab in Lab.objects.all():
- current_booking_set = Booking.objects.filter(end__gte=timezone.now() + timedelta(days=safety_buffer_days))
-
- marked_nets = set()
-
- for booking in current_booking_set:
- for network in get_network_metadata(booking.id):
- marked_nets.add(network["vlan_id"])
-
- for net in PublicNetwork.objects.filter(lab=lab).filter(in_use=True):
- if net.vlan not in marked_nets:
- lab.vlan_manager.release_public_vlan(net.vlan)
-
-
-def get_network_metadata(booking_id: int):
- """
- Takes a booking id and prints all (known) networks that are owned by it.
- Returns an object of the form {<network name>: {"vlan_id": int, "netname": str <network name>, "public": bool <whether network is public/routable}}
-
- @booking_id: the id of the Booking object to be queried
- """
- booking = Booking.objects.get(id=booking_id)
- bundle = booking.resource
- pnets = PhysicalNetwork.objects.filter(bundle=bundle).all()
- metadata = {}
- for pnet in pnets:
- net = pnet.generic_network
- mdata = {"vlan_id": pnet.vlan_id, "netname": net.name, "public": net.is_public}
- metadata[net.name] = mdata
- return metadata
-
-
-def print_dict_pretty(a_dict):
- """
- admin_utils internal function
- """
-
- print(json.dumps(a_dict, sort_keys=True, indent=4))
-
-
-def import_host(filenames):
- """
- Imports host from an array of converted inspection files and if needed creates a new profile for the host.
- NOTE: CONVERT INSPECTION FILES USING convert_inspect_results(["file", "file"])
- (original file names not including "-import.yaml" i.e. hpe44) AND FILL IN <NEEDED FIELDS> BEFORE THIS
- @filenames: array of host import file names to import
- """
-
- for filename in filenames:
-
- # open import file
- file = open("dashboard/" + filename + "-import.yaml", "r")
- data = yaml.safe_load(file)
-
- # if a new profile is needed create one and a matching template
- if (data["new_profile"]):
- add_profile(data)
- print("Profile: " + data["name"] + " created!")
- make_default_template(
- ResourceProfile.objects.get(name=data["name"]),
- Image.objects.get(lab_id=data["image"]).id,
- None,
- None,
- False,
- False,
- data["owner"],
- "unh_iol",
- True,
- False,
- data["temp_desc"]
- )
-
- print(" Template: " + data["temp_name"] + " created!")
-
- # add the server
- add_server(
- ResourceProfile.objects.get(name=data["name"]),
- data["hostname"],
- data["interfaces"],
- data["lab"],
- data["vendor"],
- data["model"]
- )
-
- print(data["hostname"] + " imported!")
-
-
-def convert_inspect_results(files):
- """
- Converts an array of inspection result files into templates (filename-import.yaml) to be filled out for importing the servers into the dashboard
- @files an array of file names (not including the file type. i.e hpe44). Default: []
- """
- for filename in files:
- # open host inspect file
- file = open("dashboard/" + filename + ".yaml")
- output = open("dashboard/" + filename + "-import.yaml", "w")
- data = json.load(file)
-
- # gather data about disks
- disk_data = {}
- for i in data["disk"]:
-
- # don't include loops in disks
- if "loop" not in i:
- disk_data[i["name"]] = {
- "capacity": i["size"][:-3],
- "media_type": "<\"SSD\" or \"HDD\">",
- "interface": "<\"sata\", \"sas\", \"ssd\", \"nvme\", \"scsi\", or \"iscsi\">",
- }
-
- # gather interface data
- interface_data = {}
- for i in data["interfaces"]:
- interface_data[data["interfaces"][i]["name"]] = {
- "speed": data["interfaces"][i]["speed"],
- "nic_type": "<\"onboard\" or \"pcie\">",
- "order": "<order in switch>",
- "mac_address": data["interfaces"][i]["mac"],
- "bus_addr": data["interfaces"][i]["busaddr"],
- }
-
- # gather cpu data
- cpu_data = {
- "cores": data["cpu"]["cores"],
- "architecture": data["cpu"]["arch"],
- "cpus": data["cpu"]["cpus"],
- "cflags": "<cflags string>",
- }
-
- # gather ram data
- ram_data = {
- "amount": data["memory"][:-1],
- "channels": "<int of ram channels used>",
- }
-
- # assemble data for host import file
- import_data = {
- "new_profile": "<True or False> (Set to True to create a new profile for the host's type)",
- "name": "<profile name> (Used to set the profile of a host and for creating a new profile)",
- "description": "<profile description>",
- "labs": "<labs using profile>",
- "temp_name": "<Template name>",
- "temp_desc": "<template description>",
- "image": "<image lab_id>",
- "owner": "<template owner>",
- "hostname": data["hostname"],
- "lab": "<lab server is in> (i.e. \"unh_iol\")",
- "disks": disk_data,
- "interfaces": interface_data,
- "cpus": cpu_data,
- "ram": ram_data,
- "vendor": "<host vendor>",
- "model": "<host model>",
- }
-
- # export data as yaml
- yaml.dump(import_data, output)
-
-
-def add_profile(data):
- """
- Used for adding a host profile to the dashboard
-
- schema (of dict passed as "data" param):
- {
- "name": str
- "description": str
- "labs": [
- str (lab username)
- ]
- "disks": {
- <diskname> : {
- capacity: int (GiB)
- media_type: str ("SSD" or "HDD")
- interface: str ("sata", "sas", "ssd", "nvme", "scsi", or "iscsi")
- }
- }
- interfaces: {
- <intname>: {
- "speed": int (mbit)
- "nic_type": str ("onboard" or "pcie")
- "order": int (compared to the other interfaces, indicates the "order" that the ports are laid out)
- }
- }
- cpus: {
- cores: int (hardware threads count)
- architecture: str (x86_64" or "aarch64")
- cpus: int (number of sockets)
- cflags: str
- }
- ram: {
- amount: int (GiB)
- channels: int
- }
- }
- """
- base_profile = ResourceProfile.objects.create(name=data['name'], description=data['description'])
- base_profile.save()
-
- for lab_username in data['labs']:
- lab = Lab.objects.get(lab_user__username=lab_username)
-
- base_profile.labs.add(lab)
- base_profile.save()
-
- for diskname in data['disks'].keys():
- disk = data['disks'][diskname]
-
- disk_profile = DiskProfile.objects.create(name=diskname, size=disk['capacity'], media_type=disk['media_type'], interface=disk['interface'], host=base_profile)
- disk_profile.save()
-
- for ifacename in data['interfaces'].keys():
- iface = data['interfaces'][ifacename]
-
- iface_profile = InterfaceProfile.objects.create(name=ifacename, speed=iface['speed'], nic_type=iface['nic_type'], order=iface['order'], host=base_profile)
- iface_profile.save()
-
- cpu = data['cpus']
- cpu_prof = CpuProfile.objects.create(cores=cpu['cores'], architecture=cpu['architecture'], cpus=cpu['cpus'], cflags=cpu['cflags'], host=base_profile)
- cpu_prof.save()
-
- ram_prof = RamProfile.objects.create(amount=data['ram']['amount'], channels=data['ram']['channels'], host=base_profile)
- ram_prof.save()
-
-
-def make_default_template(resource_profile, image_id=None, template_name=None, connected_interface_names=None, interfaces_tagged=False, connected_interface_tagged=False, owner_username="root", lab_username="unh_iol", public=True, temporary=False, description=""):
- """
- Do not call this function without reading the related source code, it may have unintended effects.
-
- Used for creating a default template from some host profile
- """
-
- if not resource_profile:
- raise Exception("No viable continuation from none resource_profile")
-
- if not template_name:
- template_name = resource_profile.name
-
- if not connected_interface_names:
- connected_interface_names = [InterfaceProfile.objects.filter(host=resource_profile).first().name]
- print("setting connected interface names to", connected_interface_names)
-
- if not image_id:
- image_id = Image.objects.filter(host_type=resource_profile).first().id
-
- image = Image.objects.get(id=image_id)
-
- base = ResourceTemplate.objects.create(
- name=template_name,
- xml="",
- owner=User.objects.get(username=owner_username),
- lab=Lab.objects.get(lab_user__username=lab_username), description=description,
- public=public, temporary=temporary, copy_of=None)
-
- rconf = ResourceConfiguration.objects.create(profile=resource_profile, image=image, template=base, is_head_node=True, name="opnfv_host")
- rconf.save()
-
- connected_interfaces = []
-
- for iface_prof in InterfaceProfile.objects.filter(host=resource_profile).all():
- iface_conf = InterfaceConfiguration.objects.create(profile=iface_prof, resource_config=rconf)
-
- if iface_prof.name in connected_interface_names:
- connected_interfaces.append(iface_conf)
-
- network = Network.objects.create(name="public", bundle=base, is_public=True)
-
- for iface in connected_interfaces:
- connection = NetworkConnection.objects.create(network=network, vlan_is_tagged=interfaces_tagged)
- connection.save()
-
- iface.connections.add(connection)
- print("adding connection to iface ", iface)
- iface.save()
- connection.save()
-
-
-def add_server(profile, name, interfaces, lab_username="unh_iol", vendor="unknown", model="unknown"):
- """
- Used to enroll a new host of some profile
-
- @profile: the ResourceProfile in question (by reference to a model object)
-
- @name: the unique name of the server, currently indistinct from labid
-
- @interfaces: interfaces should be dict from interface name (eg ens1f0) to dict of schema:
- {
- mac_address: <mac addr>,
- bus_addr: <bus addr>, //this field is optional, "" is default
- }
-
- @lab_username: username of the lab to be added to
-
- @vendor: vendor name of the host, such as "HPE" or "Gigabyte"
-
- @model: specific model of the host, such as "DL380 Gen 9"
-
- """
- server = Server.objects.create(
- bundle=None,
- profile=profile,
- config=None,
- working=True,
- vendor=vendor,
- model=model,
- labid=name,
- lab=Lab.objects.get(lab_user__username=lab_username),
- name=name,
- booked=False)
-
- for iface_prof in InterfaceProfile.objects.filter(host=profile).all():
- mac_addr = interfaces[iface_prof.name]["mac_address"]
- bus_addr = "unknown"
- if "bus_addr" in interfaces[iface_prof.name].keys():
- bus_addr = interfaces[iface_prof.name]["bus_addr"]
-
- iface = Interface.objects.create(acts_as=None, profile=iface_prof, mac_address=mac_addr, bus_address=bus_addr)
- iface.save()
-
- server.interfaces.add(iface)
- server.save()
-
-
-def extend_booking(booking_id, days=0, hours=0, minutes=0, weeks=0):
- """
- Extend a booking by n <days, hours, minutes, weeks>
-
- @booking_id: id of the booking
-
- @days/@hours/@minutes/@weeks: the cumulative amount of delta to add to the length of the booking
- """
-
- booking = Booking.objects.get(id=booking_id)
- booking.end = booking.end + timedelta(days=days, hours=hours, minutes=minutes, weeks=weeks)
- booking.save()
-
-
-def regenerate_cloud_configs(booking_id):
- b = Booking.objects.get(id=booking_id)
- for res in b.resource.get_resources():
- res.config.cloud_init_files.set(res.config.cloud_init_files.filter(generated=False)) # careful!
- res.config.save()
- cif = GeneratedCloudConfig.objects.create(resource_id=res.labid, booking=b, rconfig=res.config)
- cif.save()
- cif = CloudInitFile.create(priority=0, text=cif.serialize())
- cif.save()
- res.config.cloud_init_files.add(cif)
- res.config.save()
-
-
-def set_job_new(job_id):
- j = Job.objects.get(id=job_id)
- b = j.booking
- regenerate_cloud_configs(b.id)
- for task in j.get_tasklist():
- task.status = JobStatus.NEW
- task.save()
- j.status = JobStatus.NEW
- j.save()
-
-
-def docs(function=None, fulltext=False):
- """
- Print documentation for a given function in admin_utils.
- Call without arguments for more information
- """
-
- fn = None
-
- if isinstance(function, str):
- try:
- fn = globals()[function]
- except KeyError:
- print("Couldn't find a function by the given name")
- return
- elif callable(function):
- fn = function
- else:
- print("docs(function: callable | str, fulltext: bool) was called with a 'function' that was neither callable nor a string name of a function")
- print("usage: docs('some_function_in_admin_utils', fulltext=True)")
- print("The 'fulltext' argument is used to choose if you want the complete source of the function printed. If this argument is false then you will only see the pydoc rendered documentation for the function")
- return
-
- if not fn:
- print("couldn't find a function by that name")
-
- if not fulltext:
- print("Pydoc documents the function as such:")
- print(pydoc.render_doc(fn))
- else:
- print("The full source of the function is this:")
- print(inspect.getsource(fn))
-
-
-def admin_functions():
- """
- List functions available to call within admin_utils
- """
-
- return [name for name, func in inspect.getmembers(sys.modules[__name__]) if (inspect.isfunction(func) and func.__module__ == __name__)]
-
-
-print("Hint: call `docs(<function name>)` or `admin_functions()` for help on using the admin utils")
-print("docs(<function name>) displays documentation on a given function")
-print("admin_functions() lists all functions available to call within this module")
diff --git a/src/dashboard/apps.py b/src/dashboard/apps.py
deleted file mode 100644
index e0c4f44..0000000
--- a/src/dashboard/apps.py
+++ /dev/null
@@ -1,15 +0,0 @@
-##############################################################################
-# Copyright (c) 2016 Max Breitenfeldt 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.apps import AppConfig
-
-
-class DashboardConfig(AppConfig):
- name = 'dashboard'
diff --git a/src/dashboard/context_processors.py b/src/dashboard/context_processors.py
deleted file mode 100644
index 338f609..0000000
--- a/src/dashboard/context_processors.py
+++ /dev/null
@@ -1,13 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, 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.conf import settings
-
-
-def debug(context):
- return {'DEBUG': settings.DEBUG}
diff --git a/src/dashboard/exceptions.py b/src/dashboard/exceptions.py
deleted file mode 100644
index 61df145..0000000
--- a/src/dashboard/exceptions.py
+++ /dev/null
@@ -1,52 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, 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
-##############################################################################
-
-
-class ResourceProvisioningException(Exception):
- """Resources could not be provisioned."""
-
- pass
-
-
-class ModelValidationException(Exception):
- """Validation before saving model returned issues."""
-
- pass
-
-
-class ResourceAvailabilityException(ResourceProvisioningException):
- """Requested resources are not *currently* available."""
-
- pass
-
-
-class ResourceExistenceException(ResourceAvailabilityException):
- """Requested resources do not exist or do not match any known resources."""
-
- pass
-
-
-class NonUniqueHostnameException(Exception):
- pass
-
-
-class InvalidHostnameException(Exception):
- pass
-
-
-class InvalidVlanConfigurationException(Exception):
- pass
-
-
-class NetworkExistsException(Exception):
- pass
-
-
-class BookingLengthException(Exception):
- pass
diff --git a/src/dashboard/fixtures/dashboard.json b/src/dashboard/fixtures/dashboard.json
deleted file mode 100644
index f0ac3b2..0000000
--- a/src/dashboard/fixtures/dashboard.json
+++ /dev/null
@@ -1,164 +0,0 @@
-[
-{
- "model": "dashboard.resource",
- "pk": 1,
- "fields": {
- "name": "Linux Foundation POD 1",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Lf+Lab"
- }
-},
-{
- "model": "dashboard.resource",
- "pk": 2,
- "fields": {
- "name": "Linux Foundation POD 2",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Lf+Lab"
- }
-},
-{
- "model": "dashboard.resource",
- "pk": 3,
- "fields": {
- "name": "Ericsson POD 2",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Ericsson+Hosting+and+Request+Process"
- }
-},
-{
- "model": "dashboard.resource",
- "pk": 4,
- "fields": {
- "name": "Intel POD 2",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Intel+Pod2"
- }
-},
-{
- "model": "dashboard.resource",
- "pk": 5,
- "fields": {
- "name": "Intel POD 5",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Intel+Pod5"
- }
-},
-{
- "model": "dashboard.resource",
- "pk": 6,
- "fields": {
- "name": "Intel POD 6",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Intel+Pod6"
- }
-},
-{
- "model": "dashboard.resource",
- "pk": 7,
- "fields": {
- "name": "Intel POD 8",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Intel+Pod8"
- }
-},
-{
- "model": "dashboard.resource",
- "pk": 8,
- "fields": {
- "name": "Huawei POD 1",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Huawei+Hosting"
- }
-},
-{
- "model": "dashboard.resource",
- "pk": 9,
- "fields": {
- "name": "Intel POD 3",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Intel+Pod3"
- }
-},
-{
- "model": "dashboard.resource",
- "pk": 10,
- "fields": {
- "name": "Dell POD 1",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Dell+Hosting"
- }
-},
-{
- "model": "dashboard.resource",
- "pk": 11,
- "fields": {
- "name": "Dell POD 2",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Dell+Hosting"
- }
-},
-{
- "model": "dashboard.resource",
- "pk": 12,
- "fields": {
- "name": "Orange POD 2",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Opnfv-orange-pod2"
- }
-},
-{
- "model": "dashboard.resource",
- "pk": 13,
- "fields": {
- "name": "Arm POD 1",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Enea-pharos-lab"
- }
-},
-{
- "model": "dashboard.resource",
- "pk": 14,
- "fields": {
- "name": "Ericsson POD 1",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Ericsson+Hosting+and+Request+Process"
- }
-},
-{
- "model": "dashboard.resource",
- "pk": 15,
- "fields": {
- "name": "Huawei POD 2",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Huawei+Hosting"
- }
-},
-{
- "model": "dashboard.resource",
- "pk": 16,
- "fields": {
- "name": "Huawei POD 3",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Huawei+Hosting"
- }
-},
-{
- "model": "dashboard.resource",
- "pk": 17,
- "fields": {
- "name": "Huawei POD 4",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Huawei+Hosting"
- }
-},
-{
- "model": "dashboard.resource",
- "pk": 18,
- "fields": {
- "name": "Intel POD 9",
- "description": "Some description",
- "url": "https://wiki.opnfv.org/display/pharos/Intel+Pod9"
- }
-}
-]
diff --git a/src/dashboard/models.py b/src/dashboard/models.py
deleted file mode 100644
index f9bd07e..0000000
--- a/src/dashboard/models.py
+++ /dev/null
@@ -1,9 +0,0 @@
-##############################################################################
-# Copyright (c) 2016 Max Breitenfeldt and others.
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, 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
-##############################################################################
diff --git a/src/dashboard/populate_db_iol.py b/src/dashboard/populate_db_iol.py
deleted file mode 100644
index d8df03f..0000000
--- a/src/dashboard/populate_db_iol.py
+++ /dev/null
@@ -1,352 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, 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
-##############################################################################
-
-import json
-import yaml
-
-from account.models import Lab, UserProfile
-from django.contrib.auth.models import User
-from resource_inventory.models import (
- HostProfile,
- InterfaceProfile,
- DiskProfile,
- CpuProfile,
- RamProfile,
- VlanManager,
- Scenario,
- Installer,
- Opsys,
- OPNFVRole,
- Image,
- Interface,
- Host
-)
-
-
-class Populator:
-
- def __init__(self):
- self.host_profile_count = 0
- self.generic_host_count = 0
- self.host_profiles = []
- self.generic_bundle_count = 0
- self.booking_count = 0
-
- def make_host_profile(self, lab, data):
- hostProfile = HostProfile.objects.create(
- host_type=data['host']['type'],
- name=data['host']['name'],
- description=data['host']['description']
- )
- hostProfile.save()
-
- for iface_data in data['interfaces']:
-
- interfaceProfile = InterfaceProfile.objects.create(
- speed=iface_data['speed'],
- name=iface_data['name'],
- host=hostProfile
- )
- interfaceProfile.save()
-
- for disk_data in data['disks']:
-
- diskProfile = DiskProfile.objects.create(
- size=disk_data['size'],
- media_type=disk_data['type'],
- name=disk_data['name'],
- host=hostProfile
- )
- diskProfile.save()
-
- cpuProfile = CpuProfile.objects.create(
- cores=data['cpu']['cores'],
- architecture=data['cpu']['arch'],
- cpus=data['cpu']['cpus'],
- host=hostProfile
- )
- cpuProfile.save()
- ramProfile = RamProfile.objects.create(
- amount=data['ram']['amount'],
- channels=data['ram']['channels'],
- host=hostProfile
- )
- ramProfile.save()
- hostProfile.labs.add(lab)
- return hostProfile
-
- def make_users(self):
- user_pberberian = User.objects.create(username="pberberian")
- user_pberberian.save()
- user_pberberian_prof = UserProfile.objects.create(user=user_pberberian)
- user_pberberian_prof.save()
-
- user_sbergeron = User.objects.create(username="sbergeron")
- user_sbergeron.save()
- user_sbergeron_prof = UserProfile.objects.create(user=user_sbergeron)
- user_sbergeron_prof.save()
- return [user_sbergeron, user_pberberian]
-
- def make_labs(self):
- unh_iol = User.objects.create(username="unh_iol")
- unh_iol.save()
- vlans = []
- reserved = []
- for i in range(1, 4096):
- vlans.append(1)
- reserved.append(0)
- iol = Lab.objects.create(
- lab_user=unh_iol,
- name="UNH_IOL",
- vlan_manager=VlanManager.objects.create(
- vlans=json.dumps(vlans),
- reserved_vlans=json.dumps(reserved),
- allow_overlapping=False,
- block_size=20,
- ),
- api_token=Lab.make_api_token(),
- contact_email="nfv-lab@iol.unh.edu",
- location="University of New Hampshire, Durham NH, 03824 USA"
- )
- return [iol]
-
- def make_configurations(self):
- # scenarios
- scen1 = Scenario.objects.create(name="os-nosdn-nofeature-noha")
- scen2 = Scenario.objects.create(name="os-odl-kvm-ha")
- scen3 = Scenario.objects.create(name="os-nosdn-nofeature-ha")
-
- # installers
- fuel = Installer.objects.create(name="Fuel")
- fuel.sup_scenarios.add(scen1)
- fuel.sup_scenarios.add(scen3)
- fuel.save()
- joid = Installer.objects.create(name="Joid")
- joid.sup_scenarios.add(scen1)
- joid.sup_scenarios.add(scen2)
- joid.save()
- apex = Installer.objects.create(name="Apex")
- apex.sup_scenarios.add(scen2)
- apex.sup_scenarios.add(scen3)
- apex.save()
- daisy = Installer.objects.create(name="Daisy")
- daisy.sup_scenarios.add(scen1)
- daisy.sup_scenarios.add(scen2)
- daisy.sup_scenarios.add(scen3)
- daisy.save()
- compass = Installer.objects.create(name="Compass")
- compass.sup_scenarios.add(scen1)
- compass.sup_scenarios.add(scen3)
- compass.save()
-
- # operating systems
- ubuntu = Opsys.objects.create(name="Ubuntu")
- ubuntu.sup_installers.add(compass)
- ubuntu.sup_installers.add(joid)
- ubuntu.save()
- centos = Opsys.objects.create(name="CentOs")
- centos.sup_installers.add(apex)
- centos.sup_installers.add(fuel)
- centos.save()
- suse = Opsys.objects.create(name="Suse")
- suse.sup_installers.add(fuel)
- suse.save()
-
- # opnfv roles
- OPNFVRole.objects.create(name="Compute", description="Does the heavy lifting")
- OPNFVRole.objects.create(name="Controller", description="Controls everything")
- OPNFVRole.objects.create(name="Jumphost", description="Entry Point")
-
- lab = Lab.objects.first()
- user = UserProfile.objects.first().user
- Image.objects.create(
- lab_id=23,
- name="hpe centos",
- from_lab=lab,
- owner=user,
- host_type=HostProfile.objects.get(name="hpe")
- )
- Image.objects.create(
- lab_id=25,
- name="hpe ubuntu",
- from_lab=lab,
- owner=user,
- host_type=HostProfile.objects.get(name="hpe")
- )
-
- Image.objects.create(
- lab_id=26,
- name="hpe suse",
- from_lab=lab,
- owner=user,
- host_type=HostProfile.objects.get(name="hpe")
- )
-
- Image.objects.create(
- lab_id=27,
- name="arm ubuntu",
- from_lab=lab,
- owner=user,
- host_type=HostProfile.objects.get(name="arm")
- )
-
- def make_lab_hosts(self, hostcount, profile, lab, data, offset=1):
- for i in range(hostcount):
- name = "Host_" + lab.name + "_" + profile.name + "_" + str(i + offset)
- host = Host.objects.create(
- name=name,
- lab=lab,
- profile=profile,
- labid=data[i]['labid']
- )
- for iface_profile in profile.interfaceprofile.all():
- iface_data = data[i]['interfaces'][iface_profile.name]
- Interface.objects.create(
- mac_address=iface_data['mac'],
- bus_address=iface_data['bus'],
- name=iface_profile.name,
- host=host
- )
-
- def make_profile_data(self):
- """
- Create Profile Data.
-
- returns a dictionary of data from the yaml files
- created by inspection scripts
- """
- data = []
- for prof in ["hpe", "arm"]: # TODO
- profile_dict = {}
- host = {
- "name": prof,
- "type": 0,
- "description": "some LaaS servers"
- }
- profile_dict['host'] = host
- profile_dict['interfaces'] = []
- for interface in [{"name": "eno1", "speed": 1000}, {"name": "eno2", "speed": 10000}]: # TODO
- iface_dict = {}
- iface_dict["name"] = interface['name']
- iface_dict['speed'] = interface['speed']
- profile_dict['interfaces'].append(iface_dict)
-
- profile_dict['disks'] = []
- for disk in [{"size": 1000, "type": "ssd", "name": "sda"}]: # TODO
- disk_dict = {}
- disk_dict['size'] = disk['size']
- disk_dict['type'] = disk['type']
- disk_dict['name'] = disk['name']
- profile_dict['disks'].append(disk_dict)
-
- # cpu
- cpu = {}
- cpu['cores'] = 4
- cpu['arch'] = "x86"
- cpu['cpus'] = 2
- profile_dict['cpu'] = cpu
-
- # ram
- ram = {}
- ram['amount'] = 256
- ram['channels'] = 4
- profile_dict['ram'] = ram
-
- data.append(profile_dict)
-
- return data
-
- def get_lab_data(self, lab):
- data = {}
- path = "/laas_dashboard/data/" + lab.name + "/"
- host_file = open(path + "hostlist.json")
- host_structure = json.loads(host_file.read())
- host_file.close()
- for profile in host_structure['profiles'].keys():
- data[profile] = {}
- prof_path = path + profile
- for host in host_structure['profiles'][profile]:
- host_file = open(prof_path + "/" + host + ".yaml")
- host_data = yaml.load(host_file.read())
- host_file.close()
- data[profile][host] = host_data
- return data
-
- def make_profiles_and_hosts(self, lab, lab_data):
- for host_profile_name, host_data_dict in lab_data.items():
- if len(host_data_dict) < 1:
- continue
- host_profile = HostProfile.objects.create(
- name=host_profile_name,
- description=""
- )
- host_profile.labs.add(lab)
- example_host_data = list(host_data_dict.values())[0]
-
- cpu_data = example_host_data['cpu']
- CpuProfile.objects.create(
- cores=cpu_data['cores'],
- architecture=cpu_data['arch'],
- cpus=cpu_data['cpus'],
- host=host_profile
- )
-
- ram_data = example_host_data['memory']
- RamProfile.objects.create(
- amount=int(ram_data[:-1]),
- channels=1,
- host=host_profile
- )
-
- disks_data = example_host_data['disk']
- for disk_data in disks_data:
- size = 0
- try:
- size = int(disk_data['size'].split('.')[0])
- except Exception:
- size = int(disk_data['size'].split('.')[0][:-1])
- DiskProfile.objects.create(
- size=size,
- media_type="SSD",
- name=disk_data['name'],
- host=host_profile
- )
-
- ifaces_data = example_host_data['interface']
- for iface_data in ifaces_data:
- InterfaceProfile.objects.create(
- speed=iface_data['speed'],
- name=iface_data['name'],
- host=host_profile
- )
-
- # all profiles created
- for hostname, host_data in host_data_dict.items():
- host = Host.objects.create(
- name=hostname,
- labid=hostname,
- profile=host_profile,
- lab=lab
- )
- for iface_data in host_data['interface']:
- Interface.objects.create(
- mac_address=iface_data['mac'],
- bus_address=iface_data['busaddr'],
- name=iface_data['name'],
- host=host
- )
-
- def populate(self):
- self.labs = self.make_labs()
- # We should use the existing users, not creating our own
- for lab in self.labs:
- lab_data = self.get_lab_data(lab)
- self.make_profiles_and_hosts(lab, lab_data)
-
- # We will add opnfv info and images as they are created and supported
diff --git a/src/dashboard/tasks.py b/src/dashboard/tasks.py
deleted file mode 100644
index 93e6a22..0000000
--- a/src/dashboard/tasks.py
+++ /dev/null
@@ -1,98 +0,0 @@
-##############################################################################
-# Copyright (c) 2016 Max Breitenfeldt and others.
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, 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 celery import shared_task
-from django.utils import timezone
-from booking.models import Booking
-from notifier.manager import NotificationHandler
-from api.models import (
- Job,
- JobStatus,
- SoftwareRelation,
- HostHardwareRelation,
- HostNetworkRelation,
- AccessRelation,
- JobFactory
-)
-
-from resource_inventory.resource_manager import ResourceManager
-from resource_inventory.models import ConfigState
-
-
-@shared_task
-def booking_poll():
- def cleanup_resource_task(qs):
- for hostrelation in qs:
- hostrelation.config.state = ConfigState.CLEAN
- hostrelation.config.save()
- hostrelation.status = JobStatus.NEW
- hostrelation.save()
-
- def cleanup_software(qs):
- if qs.exists():
- relation = qs.first()
- software = relation.config.opnfv
- software.clear_delta()
- software.save()
- relation.status = JobStatus.NEW
- relation.save()
-
- def cleanup_access(qs):
- for relation in qs:
- if "vpn" in relation.config.access_type.lower():
- relation.config.set_revoke(True)
- relation.config.save()
- relation.status = JobStatus.NEW
- relation.save()
-
- cleanup_set = Booking.objects.filter(end__lte=timezone.now()).filter(job__complete=False)
-
- for booking in cleanup_set:
- if not booking.job.complete:
- job = booking.job
- cleanup_software(SoftwareRelation.objects.filter(job=job))
- cleanup_resource_task(HostHardwareRelation.objects.filter(job=job))
- cleanup_resource_task(HostNetworkRelation.objects.filter(job=job))
- cleanup_access(AccessRelation.objects.filter(job=job))
- job.complete = True
- job.save()
- NotificationHandler.notify_booking_end(booking)
-
-
-@shared_task
-def free_hosts():
- """Free all hosts that should be freed."""
- undone_statuses = [JobStatus.NEW, JobStatus.CURRENT, JobStatus.ERROR]
- undone_jobs = Job.objects.filter(
- hostnetworkrelation__status__in=undone_statuses,
- hosthardwarerelation__status__in=undone_statuses
- )
-
- bookings = Booking.objects.exclude(
- job__in=undone_jobs
- ).filter(
- end__lt=timezone.now(),
- job__complete=True,
- complete=False,
- resource__isnull=False,
- )
-
- for booking in bookings:
- ResourceManager.getInstance().releaseResourceBundle(booking.resource)
- booking.complete = True
- print("Booking", booking.id, "is now completed")
- booking.save()
-
-
-@shared_task
-def query_vpn_users():
- """ get active vpn users """
- JobFactory.makeActiveUsersTask()
diff --git a/src/dashboard/templatetags/__init__.py b/src/dashboard/templatetags/__init__.py
deleted file mode 100644
index b6fef6c..0000000
--- a/src/dashboard/templatetags/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-##############################################################################
-# Copyright (c) 2016 Max Breitenfeldt 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
-##############################################################################
diff --git a/src/dashboard/testing_utils.py b/src/dashboard/testing_utils.py
deleted file mode 100644
index 5be6379..0000000
--- a/src/dashboard/testing_utils.py
+++ /dev/null
@@ -1,315 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, 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.contrib.auth.models import User
-from django.core.files.base import ContentFile
-from django.utils import timezone
-
-import json
-from datetime import timedelta
-
-from booking.models import Booking
-from account.models import UserProfile, Lab, LabStatus, VlanManager, PublicNetwork
-from resource_inventory.models import (
- ResourceTemplate,
- ResourceProfile,
- ResourceConfiguration,
- InterfaceProfile,
- InterfaceConfiguration,
- Server,
- DiskProfile,
- CpuProfile,
- Opsys,
- Image,
- Scenario,
- Installer,
- OPNFVRole,
- RamProfile,
- Network,
-)
-from resource_inventory.resource_manager import ResourceManager
-
-"""
-Info for make_booking() function:
-[topology] argument structure:
- the [topology] argument should describe the structure of the pod
- the top level should be a dictionary, with each key being a hostname
- each value in the top level should be a dictionary with two keys:
- "type" should map to a host profile instance
- "nets" should map to a list of interfaces each with a list of
- dictionaries each defining a network in the format
- { "name": "netname", "tagged": True|False, "public": True|False }
- each network is defined if a matching name is not found
-
- sample argument structure:
- topology={
- "host1": {
- "type": instanceOf HostProfile,
- "role": instanceOf OPNFVRole
- "image": instanceOf Image
- "nets": [
- 0: [
- 0: { "name": "public", "tagged": True, "public": True },
- 1: { "name": "private", "tagged": False, "public": False },
- ]
- 1: []
- ]
- }
- }
-"""
-
-
-def make_booking(owner=None, start=timezone.now(),
- end=timezone.now() + timedelta(days=1),
- lab=None, purpose="my_purpose",
- project="my_project", collaborators=[],
- topology={}, installer=None, scenario=None):
-
- resource_template = make_resource_template()
- resource = ResourceManager.getInstance().convertResourceBundle(resource_template)
- if not resource:
- raise Exception("Resource not created")
-
- return Booking.objects.create(
- resource=resource,
- start=start,
- end=end,
- owner=owner,
- purpose=purpose,
- project=project,
- lab=lab,
- )
-
-
-def make_network(name, lab, grb, public):
- network = Network(name=name, bundle=grb, is_public=public)
- if public:
- public_net = lab.vlan_manager.get_public_vlan()
- if not public_net:
- raise Exception("No more public networks available")
- lab.vlan_manager.reserve_public_vlan(public_net.vlan)
- network.vlan_id = public_net.vlan
- else:
- private_nets = lab.vlan_manager.get_vlans(count=1)
- if not private_nets:
- raise Exception("No more generic vlans are available")
- lab.vlan_manager.reserve_vlans(private_nets)
- network.vlan_id = private_nets[0]
-
- network.save()
- return network
-
-
-def make_resource_template(owner=None, lab=None, name="Test Template"):
- if owner is None:
- owner = make_user(username="template_owner")
- if lab is None:
- lab = make_lab(name="template_lab")
- rt = ResourceTemplate.objects.create(name=name, owner=owner, lab=lab, public=True)
- config = make_resource_config(rt)
- make_interface_config(config)
- return rt
-
-
-def make_resource_config(template, profile=None, image=None):
- if profile is None:
- profile = make_resource_profile(lab=template.lab)
-
- if image is None:
- image = make_image(profile, lab=template.lab)
-
- return ResourceConfiguration.objects.create(profile=profile, image=image, template=template)
-
-
-def make_interface_config(resource_config):
- # lets just grab one of the iface profiles from the related host
- iface_profile = resource_config.profile.interfaceprofile.all()[0]
-
- # not adding any connections here
- return InterfaceConfiguration.objects.create(profile=iface_profile, resource_config=resource_config)
-
-
-def make_user(is_superuser=False, username="testuser",
- password="testpassword", email="default_email@user.com"):
- user = User.objects.get_or_create(username=username, email=email, password=password)[0]
-
- user.is_superuser = is_superuser
- user.save()
-
- return user
-
-
-def make_user_profile(user=None, email_addr="email@email.com",
- company="company", full_name="John Doe",
- booking_privledge=True, ssh_file=None):
- user = user or make_user()
- profile = UserProfile.objects.get_or_create(
- email_addr=email_addr,
- company=company,
- full_name=full_name,
- booking_privledge=booking_privledge,
- user=user
- )[0]
- profile.ssh_public_key.save("user_ssh_key", ssh_file if ssh_file else ContentFile("public key content string"))
-
- return profile
-
-
-def make_vlan_manager(vlans=None, block_size=20, allow_overlapping=False, reserved_vlans=None):
- if not vlans:
- vlans = [vlan % 2 for vlan in range(4095)]
- if not reserved_vlans:
- reserved_vlans = [0 for i in range(4095)]
-
- return VlanManager.objects.create(
- vlans=json.dumps(vlans),
- reserved_vlans=json.dumps(vlans),
- block_size=block_size,
- allow_overlapping=allow_overlapping
- )
-
-
-def make_lab(user=None, name="Test_Lab_Instance",
- status=LabStatus.UP, vlan_manager=None,
- pub_net_count=5):
- if Lab.objects.filter(name=name).exists():
- return Lab.objects.get(name=name)
-
- if not vlan_manager:
- vlan_manager = make_vlan_manager()
-
- if not user:
- user = make_user(username=name + " user")
-
- lab = Lab.objects.create(
- lab_user=user,
- name=name,
- contact_email='test_lab@test_site.org',
- contact_phone='603 123 4567',
- status=status,
- vlan_manager=vlan_manager,
- description='test lab instantiation',
- api_token='12345678'
- )
-
- for i in range(pub_net_count):
- make_public_net(vlan=i * 2 + 1, lab=lab)
-
- return lab
-
-
-"""
-resource_inventory instantiation section for permanent resources
-"""
-
-
-def make_resource_profile(lab, name="test_hostprofile"):
- if ResourceProfile.objects.filter(name=name).exists():
- return ResourceProfile.objects.get(name=name)
-
- resource_profile = ResourceProfile.objects.create(
- name=name,
- description='test resourceprofile instance'
- )
- resource_profile.labs.add(lab)
-
- RamProfile.objects.create(host=resource_profile, amount=8, channels=2)
- CpuProfile.objects.create(cores=4, architecture="x86_64", cpus=1, host=resource_profile)
- DiskProfile.objects.create(
- name="test disk profile",
- size=256,
- media_type="SSD",
- host=resource_profile
- )
-
- InterfaceProfile.objects.create(
- host=resource_profile,
- name="test interface profile",
- speed=1000,
- nic_type="pcie"
- )
-
- return resource_profile
-
-
-def make_image(resource_profile, lab=None, lab_id="4", owner=None, os=None,
- public=True, name="default image", description="default image"):
- if lab is None:
- lab = make_lab()
-
- if owner is None:
- owner = make_user()
-
- if os is None:
- os = make_os()
-
- return Image.objects.create(
- from_lab=lab,
- lab_id=lab_id,
- os=os,
- host_type=resource_profile,
- public=public,
- name=name,
- description=description
- )
-
-
-def make_scenario(name="test scenario"):
- return Scenario.objects.create(name=name)
-
-
-def make_installer(scenarios, name="test installer"):
- installer = Installer.objects.create(name=name)
- for scenario in scenarios:
- installer.sup_scenarios.add(scenario)
-
- return installer
-
-
-def make_os(installers=None, name="test OS"):
- if not installers:
- installers = [make_installer([make_scenario()])]
- os = Opsys.objects.create(name=name)
- for installer in installers:
- os.sup_installers.add(installer)
-
- return os
-
-
-def make_server(host_profile, lab, labid="test_host", name="test_host",
- booked=False, working=True, config=None,
- bundle=None, model="Model 1", vendor="ACME"):
- return Server.objects.create(
- lab=lab,
- profile=host_profile,
- name=name,
- booked=booked,
- working=working,
- config=config,
- bundle=bundle,
- model=model,
- vendor=vendor
- )
-
-
-def make_opnfv_role(name="Jumphost", description="test opnfvrole"):
- return OPNFVRole.objects.create(
- name=name,
- description=description
- )
-
-
-def make_public_net(vlan, lab, in_use=False,
- cidr="0.0.0.0/0", gateway="0.0.0.0"):
- return PublicNetwork.objects.create(
- lab=lab,
- vlan=vlan,
- cidr=cidr,
- gateway=gateway
- )
diff --git a/src/dashboard/tests/__init__.py b/src/dashboard/tests/__init__.py
deleted file mode 100644
index b6fef6c..0000000
--- a/src/dashboard/tests/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-##############################################################################
-# Copyright (c) 2016 Max Breitenfeldt 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
-##############################################################################
diff --git a/src/dashboard/tests/test_views.py b/src/dashboard/tests/test_views.py
deleted file mode 100644
index f2d5490..0000000
--- a/src/dashboard/tests/test_views.py
+++ /dev/null
@@ -1,30 +0,0 @@
-##############################################################################
-# Copyright (c) 2020 Parker Berberian, Sawyer Bergeron, 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.test import TestCase, Client
-from dashboard.testing_utils import make_lab
-
-
-class DashboardViewTestCase(TestCase):
- @classmethod
- def setUpTestData(cls):
- make_lab(name="TestLab")
- cls.client = Client()
-
- def test_landing_view_anon(self):
- response = self.client.get('/')
- self.assertEqual(response.status_code, 200)
-
- def test_lab_list_view(self):
- response = self.client.get('/lab/')
- self.assertEqual(response.status_code, 200)
-
- def test_lab_detail_view(self):
- response = self.client.get('/lab/TestLab/')
- self.assertEqual(response.status_code, 200)
diff --git a/src/dashboard/urls.py b/src/dashboard/urls.py
deleted file mode 100644
index c87dacc..0000000
--- a/src/dashboard/urls.py
+++ /dev/null
@@ -1,42 +0,0 @@
-##############################################################################
-# Copyright (c) 2016 Max Breitenfeldt and others.
-# Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, 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
-##############################################################################
-
-
-"""
-laas_dashboard URL Configuration.
-
-The `urlpatterns` list routes URLs to views. For more information please see:
- https://docs.djangoproject.com/en/1.10/topics/http/urls/
-Examples:
-Function views
- 1. Add an import: from my_app import views
- 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
-Class-based views
- 1. Add an import: from other_app.views import Home
- 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
-Including another URLconf
- 1. Import the include() function: from django.conf.urls import url, include
- 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
-"""
-from django.conf.urls import url
-from dashboard.views import (
- landing_view,
- lab_list_view,
- lab_detail_view,
- host_profile_detail_view
-)
-
-app_name = 'dashboard'
-urlpatterns = [
- url(r'^$', landing_view, name='index'),
- url(r'^lab/$', lab_list_view, name='all_labs'),
- url(r'^lab/(?P<lab_name>.+)/$', lab_detail_view, name='lab_detail'),
- url(r'^hosts/$', host_profile_detail_view, name="hostprofile_detail")
-]
diff --git a/src/dashboard/utils.py b/src/dashboard/utils.py
deleted file mode 100644
index 97c9ac7..0000000
--- a/src/dashboard/utils.py
+++ /dev/null
@@ -1,52 +0,0 @@
-##############################################################################
-# Copyright (c) 2020 Parker Berberian 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 (ObjectDoesNotExist, MultipleObjectsReturned)
-
-
-class AbstractModelQuery():
- """
- This is a class made for querying abstract models.
-
- This class is itself abstract. create subclasses to
- query your own abstract models.
- """
-
- model_list = []
-
- @classmethod
- def filter(cls, *args, **kwargs):
- """
- Query all concrete model classes.
-
- Iterates over the model list and returns a list of all
- matching models from the classes given.
- Filter queries are given here as normal and are passed into the Django ORM
- for each concrete model
- """
- result = []
- for model in cls.model_list:
- result += list(model.objects.filter(*args, **kwargs))
-
- return result
-
- @classmethod
- def get(cls, *args, **kwargs):
- """
- Gets a single matching resource
- Throws ObjectDoesNotExist if none found matching, or MultipleObjectsReturned if
- the query does not narrow to a single object
- """
- try:
- ls = cls.filter(*args, **kwargs)
- if len(ls) > 1:
- raise MultipleObjectsReturned()
- return cls.filter(*args, **kwargs)[0]
- except IndexError:
- raise ObjectDoesNotExist()
diff --git a/src/dashboard/views.py b/src/dashboard/views.py
deleted file mode 100644
index ff26c64..0000000
--- a/src/dashboard/views.py
+++ /dev/null
@@ -1,119 +0,0 @@
-##############################################################################
-# Copyright (c) 2016 Max Breitenfeldt and others.
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, 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.shortcuts import get_object_or_404
-from django.views.generic import TemplateView
-from django.shortcuts import render
-from django.db.models import Q
-from datetime import datetime
-import pytz
-
-from account.models import Lab
-from booking.models import Booking
-
-from resource_inventory.models import Image, ResourceProfile, ResourceQuery
-from workflow.workflow_manager import ManagerTracker
-
-from laas_dashboard import settings
-
-
-def lab_list_view(request):
- labs = Lab.objects.all()
- context = {"labs": labs, 'title': 'Labs'}
-
- return render(request, "dashboard/lab_list.html", context)
-
-
-def lab_detail_view(request, lab_name):
- user = None
- if request.user.is_authenticated:
- user = request.user
-
- lab = get_object_or_404(Lab, name=lab_name)
-
- images = Image.objects.filter(from_lab=lab).filter(public=True)
- if user:
- images = images | Image.objects.filter(from_lab=lab).filter(owner=user)
-
- hosts = ResourceQuery.filter(lab=lab)
-
- return render(
- request,
- "dashboard/lab_detail.html",
- {
- 'title': "Lab Overview",
- 'lab': lab,
- 'hostprofiles': ResourceProfile.objects.filter(labs=lab),
- 'images': images,
- 'hosts': hosts
- }
- )
-
-
-def host_profile_detail_view(request):
-
- return render(
- request,
- "dashboard/host_profile_detail.html",
- {
- 'title': "Host Types",
- }
- )
-
-
-def landing_view(request):
- manager = ManagerTracker.managers.get(request.session.get('manager_session'))
- user = request.user
- if not user.is_anonymous:
- bookings = Booking.objects.filter(
- Q(owner=user) | Q(collaborators=user),
- end__gte=datetime.now(pytz.utc)
- )
- else:
- bookings = None
-
- LFID = True if settings.AUTH_SETTING == 'LFID' else False
- return render(
- request,
- 'dashboard/landing.html',
- {
- 'manager': manager is not None,
- 'title': "Welcome to the Lab as a Service Dashboard",
- 'bookings': bookings,
- 'LFID': LFID
- }
- )
-
-
-class LandingView(TemplateView):
- template_name = "dashboard/landing.html"
-
- def get_context_data(self, **kwargs):
- context = super(LandingView, self).get_context_data(**kwargs)
-
- hosts = []
-
- for host_profile in ResourceProfile.objects.all():
- name = host_profile.name
- description = host_profile.description
- in_labs = host_profile.labs
-
- interfaces = host_profile.interfaceprofile
- storage = host_profile.storageprofile
- cpu = host_profile.cpuprofile
- ram = host_profile.ramprofile
-
- host = (name, description, in_labs, interfaces, storage, cpu, ram)
- hosts.append(host)
-
- context.update({'hosts': hosts})
-
- return context