diff options
Diffstat (limited to 'src/api/models.py')
-rw-r--r-- | src/api/models.py | 1015 |
1 files changed, 1015 insertions, 0 deletions
diff --git a/src/api/models.py b/src/api/models.py new file mode 100644 index 0000000..1f708ae --- /dev/null +++ b/src/api/models.py @@ -0,0 +1,1015 @@ +############################################################################## +# 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.auth.models import User +from django.db import models +from django.core.exceptions import PermissionDenied +from django.shortcuts import get_object_or_404 +from django.urls import reverse + +import json +import uuid + +from booking.models import Booking +from resource_inventory.models import ( + Lab, + HostProfile, + Host, + Image, + Interface, + HostOPNFVConfig, + RemoteInfo, + OPNFVConfig +) +from resource_inventory.idf_templater import IDFTemplater +from resource_inventory.pdf_templater import PDFTemplater + + +class JobStatus(object): + NEW = 0 + CURRENT = 100 + DONE = 200 + ERROR = 300 + + +class LabManagerTracker(object): + + @classmethod + def get(cls, lab_name, token): + """ + Takes in a lab name (from a url path) + returns a lab manager instance for that lab, if it exists + """ + try: + lab = Lab.objects.get(name=lab_name) + except Exception: + raise PermissionDenied("Lab not found") + if lab.api_token == token: + return LabManager(lab) + raise PermissionDenied("Lab not authorized") + + +class LabManager(object): + """ + This is the class that will ultimately handle all REST calls to + lab endpoints. + handles jobs, inventory, status, etc + may need to create helper classes + """ + + def __init__(self, lab): + self.lab = lab + + def update_host_remote_info(self, data, host_id): + host = get_object_or_404(Host, labid=host_id, lab=self.lab) + info = {} + try: + info['address'] = data['address'] + info['mac_address'] = data['mac_address'] + info['password'] = data['password'] + info['user'] = data['user'] + info['type'] = data['type'] + info['versions'] = json.dumps(data['versions']) + except Exception as e: + return {"error": "invalid arguement: " + str(e)} + remote_info = host.remote_management + if "default" in remote_info.mac_address: + remote_info = RemoteInfo() + remote_info.address = info['address'] + remote_info.mac_address = info['mac_address'] + remote_info.password = info['password'] + remote_info.user = info['user'] + remote_info.type = info['type'] + remote_info.versions = info['versions'] + remote_info.save() + host.remote_management = remote_info + host.save() + booking = Booking.objects.get(resource=host.bundle) + self.update_xdf(booking) + return {"status": "success"} + + def update_xdf(self, booking): + booking.pdf = PDFTemplater.makePDF(booking) + booking.idf = IDFTemplater().makeIDF(booking) + booking.save() + + def get_pdf(self, booking_id): + booking = get_object_or_404(Booking, pk=booking_id, lab=self.lab) + return booking.pdf + + def get_idf(self, booking_id): + booking = get_object_or_404(Booking, pk=booking_id, lab=self.lab) + return booking.idf + + def get_profile(self): + prof = {} + prof['name'] = self.lab.name + prof['contact'] = { + "phone": self.lab.contact_phone, + "email": self.lab.contact_email + } + prof['host_count'] = [] + for host in HostProfile.objects.filter(labs=self.lab): + count = Host.objects.filter(profile=host, lab=self.lab).count() + prof['host_count'].append( + { + "type": host.name, + "count": count + } + ) + return prof + + def get_inventory(self): + inventory = {} + hosts = Host.objects.filter(lab=self.lab) + images = Image.objects.filter(from_lab=self.lab) + profiles = HostProfile.objects.filter(labs=self.lab) + inventory['hosts'] = self.serialize_hosts(hosts) + inventory['images'] = self.serialize_images(images) + inventory['host_types'] = self.serialize_host_profiles(profiles) + return inventory + + def get_host(self, hostname): + host = get_object_or_404(Host, labid=hostname, lab=self.lab) + return { + "booked": host.booked, + "working": host.working, + "type": host.profile.name + } + + def update_host(self, hostname, data): + host = get_object_or_404(Host, labid=hostname, lab=self.lab) + if "working" in data: + working = data['working'] == "true" + host.working = working + host.save() + return self.get_host(hostname) + + def get_status(self): + return {"status": self.lab.status} + + def set_status(self, payload): + {} + + def get_current_jobs(self): + jobs = Job.objects.filter(booking__lab=self.lab) + + return self.serialize_jobs(jobs, status=JobStatus.CURRENT) + + def get_new_jobs(self): + jobs = Job.objects.filter(booking__lab=self.lab) + + return self.serialize_jobs(jobs, status=JobStatus.NEW) + + def get_done_jobs(self): + jobs = Job.objects.filter(booking__lab=self.lab) + + return self.serialize_jobs(jobs, status=JobStatus.DONE) + + def get_job(self, jobid): + return Job.objects.get(pk=jobid).to_dict() + + def update_job(self, jobid, data): + {} + + def serialize_jobs(self, jobs, status=JobStatus.NEW): + job_ser = [] + for job in jobs: + jsonized_job = job.get_delta(status) + if len(jsonized_job['payload']) < 1: + continue + job_ser.append(jsonized_job) + + return job_ser + + def serialize_hosts(self, hosts): + host_ser = [] + for host in hosts: + h = {} + h['interfaces'] = [] + h['hostname'] = host.name + h['host_type'] = host.profile.name + for iface in host.interfaces.all(): + eth = {} + eth['mac'] = iface.mac_address + eth['busaddr'] = iface.bus_address + eth['name'] = iface.name + eth['switchport'] = {"switch_name": iface.switch_name, "port_name": iface.port_name} + h['interfaces'].append(eth) + return host_ser + + def serialize_images(self, images): + images_ser = [] + for image in images: + images_ser.append( + { + "name": image.name, + "lab_id": image.lab_id, + "dashboard_id": image.id + } + ) + return images_ser + + def serialize_host_profiles(self, profiles): + profile_ser = [] + for profile in profiles: + p = {} + p['cpu'] = { + "cores": profile.cpuprofile.first().cores, + "arch": profile.cpuprofile.first().architecture, + "cpus": profile.cpuprofile.first().cpus, + } + p['disks'] = [] + for disk in profile.storageprofile.all(): + d = { + "size": disk.size, + "type": disk.media_type, + "name": disk.name + } + p['disks'].append(d) + p['description'] = profile.description + p['interfaces'] = [] + for iface in profile.interfaceprofile.all(): + p['interfaces'].append( + { + "speed": iface.speed, + "name": iface.name + } + ) + + p['ram'] = {"amount": profile.ramprofile.first().amount} + p['name'] = profile.name + profile_ser.append(p) + return profile_ser + + +class Job(models.Model): + """ + This is the class that is serialized and put into the api + """ + booking = models.OneToOneField(Booking, on_delete=models.CASCADE, null=True) + status = models.IntegerField(default=JobStatus.NEW) + complete = models.BooleanField(default=False) + + def to_dict(self): + d = {} + j = {} + j['id'] = self.id + for relation in AccessRelation.objects.filter(job=self): + if 'access' not in d: + d['access'] = {} + d['access'][relation.task_id] = relation.config.to_dict() + for relation in SoftwareRelation.objects.filter(job=self): + if 'software' not in d: + d['software'] = {} + d['software'][relation.task_id] = relation.config.to_dict() + for relation in HostHardwareRelation.objects.filter(job=self): + if 'hardware' not in d: + d['hardware'] = {} + d['hardware'][relation.task_id] = relation.config.to_dict() + for relation in HostNetworkRelation.objects.filter(job=self): + if 'network' not in d: + d['network'] = {} + d['network'][relation.task_id] = relation.config.to_dict() + for relation in SnapshotRelation.objects.filter(job=self): + if 'snapshot' not in d: + d['snapshot'] = {} + d['snapshot'][relation.task_id] = relation.config.to_dict() + + j['payload'] = d + + return j + + def get_tasklist(self, status="all"): + tasklist = [] + clist = [ + HostHardwareRelation, + AccessRelation, + HostNetworkRelation, + SoftwareRelation, + SnapshotRelation + ] + if status == "all": + for cls in clist: + tasklist += list(cls.objects.filter(job=self)) + else: + for cls in clist: + tasklist += list(cls.objects.filter(job=self).filter(status=status)) + return tasklist + + def is_fulfilled(self): + """ + This method should return true if all of the job's tasks are done, + and false otherwise + """ + my_tasks = self.get_tasklist() + for task in my_tasks: + if task.status != JobStatus.DONE: + return False + return True + + def get_delta(self, status): + d = {} + j = {} + j['id'] = self.id + for relation in AccessRelation.objects.filter(job=self).filter(status=status): + if 'access' not in d: + d['access'] = {} + d['access'][relation.task_id] = relation.config.get_delta() + for relation in SoftwareRelation.objects.filter(job=self).filter(status=status): + if 'software' not in d: + d['software'] = {} + d['software'][relation.task_id] = relation.config.get_delta() + for relation in HostHardwareRelation.objects.filter(job=self).filter(status=status): + if 'hardware' not in d: + d['hardware'] = {} + d['hardware'][relation.task_id] = relation.config.get_delta() + for relation in HostNetworkRelation.objects.filter(job=self).filter(status=status): + if 'network' not in d: + d['network'] = {} + d['network'][relation.task_id] = relation.config.get_delta() + for relation in SnapshotRelation.objects.filter(job=self).filter(status=status): + if 'snapshot' not in d: + d['snapshot'] = {} + d['snapshot'][relation.task_id] = relation.config.get_delta() + + j['payload'] = d + return j + + def to_json(self): + return json.dumps(self.to_dict()) + + +class TaskConfig(models.Model): + def to_dict(self): + pass + + def get_delta(self): + pass + + def to_json(self): + return json.dumps(self.to_dict()) + + def clear_delta(self): + self.delta = '{}' + + +class BridgeConfig(models.Model): + """ + Displays mapping between jumphost interfaces and + bridges + """ + interfaces = models.ManyToManyField(Interface) + opnfv_config = models.ForeignKey(OPNFVConfig, on_delete=models.CASCADE) + + def to_dict(self): + d = {} + hid = self.interfaces.first().host.labid + d[hid] = {} + for interface in self.interfaces.all(): + d[hid][interface.mac_address] = [] + for vlan in interface.config.all(): + network_role = self.opnfv_model.networks().filter(network=vlan.network) + bridge = IDFTemplater.bridge_names[network_role.name] + br_config = { + "vlan_id": vlan.vlan_id, + "tagged": vlan.tagged, + "bridge": bridge + } + d[hid][interface.mac_address].append(br_config) + return d + + def to_json(self): + return json.dumps(self.to_dict()) + + +class OpnfvApiConfig(models.Model): + + installer = models.CharField(max_length=200) + scenario = models.CharField(max_length=300) + roles = models.ManyToManyField(Host) + # pdf and idf are url endpoints, not the actual file + pdf = models.CharField(max_length=100) + idf = models.CharField(max_length=100) + bridge_config = models.OneToOneField(BridgeConfig, on_delete=models.CASCADE, null=True) + delta = models.TextField() + opnfv_config = models.ForeignKey(OPNFVConfig, null=True, on_delete=models.SET_NULL) + + def to_dict(self): + d = {} + if not self.opnfv_config: + return d + if self.installer: + d['installer'] = self.installer + if self.scenario: + d['scenario'] = self.scenario + if self.pdf: + d['pdf'] = self.pdf + if self.idf: + d['idf'] = self.idf + if self.bridge_config: + d['bridged_interfaces'] = self.bridge_config.to_dict() + + hosts = self.roles.all() + if hosts.exists(): + d['roles'] = [] + for host in hosts: + d['roles'].append({ + host.labid: self.opnfv_config.host_opnfv_config.get( + host_config__pk=host.config.pk + ).role.name + }) + + return d + + def to_json(self): + return json.dumps(self.to_dict()) + + def set_installer(self, installer): + self.installer = installer + d = json.loads(self.delta) + d['installer'] = installer + self.delta = json.dumps(d) + + def set_scenario(self, scenario): + self.scenario = scenario + d = json.loads(self.delta) + d['scenario'] = scenario + self.delta = json.dumps(d) + + def set_xdf(self, booking, update_delta=True): + kwargs = {'lab_name': booking.lab.name, 'booking_id': booking.id} + self.pdf = reverse('get-pdf', kwargs=kwargs) + self.idf = reverse('get-idf', kwargs=kwargs) + if update_delta: + d = json.loads(self.delta) + d['pdf'] = self.pdf + d['idf'] = self.idf + self.delta = json.dumps(d) + + def add_role(self, host): + self.roles.add(host) + d = json.loads(self.delta) + if 'role' not in d: + d['role'] = [] + d['roles'].append({host.labid: host.config.opnfvRole.name}) + self.delta = json.dumps(d) + + def clear_delta(self): + self.delta = '{}' + + def get_delta(self): + if not self.delta: + self.delta = self.to_json() + self.save() + return json.loads(self.delta) + + +class AccessConfig(TaskConfig): + access_type = models.CharField(max_length=50) + user = models.ForeignKey(User, on_delete=models.CASCADE) + revoke = models.BooleanField(default=False) + context = models.TextField(default="") + delta = models.TextField(default="{}") + + def to_dict(self): + d = {} + d['access_type'] = self.access_type + d['user'] = self.user.id + d['revoke'] = self.revoke + try: + d['context'] = json.loads(self.context) + except Exception: + pass + return d + + def get_delta(self): + if not self.delta: + self.delta = self.to_json() + self.save() + d = json.loads(self.delta) + d["lab_token"] = self.accessrelation.lab_token + + return d + + def to_json(self): + return json.dumps(self.to_dict()) + + def clear_delta(self): + d = {} + d["lab_token"] = self.accessrelation.lab_token + self.delta = json.dumps(d) + + def set_access_type(self, access_type): + self.access_type = access_type + d = json.loads(self.delta) + d['access_type'] = access_type + self.delta = json.dumps(d) + + def set_user(self, user): + self.user = user + d = json.loads(self.delta) + d['user'] = self.user.id + self.delta = json.dumps(d) + + def set_revoke(self, revoke): + self.revoke = revoke + d = json.loads(self.delta) + d['revoke'] = revoke + self.delta = json.dumps(d) + + def set_context(self, context): + self.context = json.dumps(context) + d = json.loads(self.delta) + d['context'] = context + self.delta = json.dumps(d) + + +class SoftwareConfig(TaskConfig): + """ + handled opnfv installations, etc + """ + opnfv = models.ForeignKey(OpnfvApiConfig, on_delete=models.CASCADE) + + def to_dict(self): + d = {} + if self.opnfv: + d['opnfv'] = self.opnfv.to_dict() + + d["lab_token"] = self.softwarerelation.lab_token + self.delta = json.dumps(d) + + return d + + def get_delta(self): + d = {} + d['opnfv'] = self.opnfv.get_delta() + d['lab_token'] = self.softwarerelation.lab_token + + return d + + def clear_delta(self): + self.opnfv.clear_delta() + + def to_json(self): + return json.dumps(self.to_dict()) + + +class HardwareConfig(TaskConfig): + """ + handles imaging, user accounts, etc + """ + image = models.CharField(max_length=100, default="defimage") + power = models.CharField(max_length=100, default="off") + hostname = models.CharField(max_length=100, default="hostname") + ipmi_create = models.BooleanField(default=False) + delta = models.TextField() + + def to_dict(self): + d = {} + d['image'] = self.image + d['power'] = self.power + d['hostname'] = self.hostname + d['ipmi_create'] = str(self.ipmi_create) + d['id'] = self.hosthardwarerelation.host.labid + return d + + def to_json(self): + return json.dumps(self.to_dict()) + + def get_delta(self): + if not self.delta: + self.delta = self.to_json() + self.save() + d = json.loads(self.delta) + d['lab_token'] = self.hosthardwarerelation.lab_token + return d + + def clear_delta(self): + d = {} + d["id"] = self.hosthardwarerelation.host.labid + d["lab_token"] = self.hosthardwarerelation.lab_token + self.delta = json.dumps(d) + + def set_image(self, image): + self.image = image + d = json.loads(self.delta) + d['image'] = self.image + self.delta = json.dumps(d) + + def set_power(self, power): + self.power = power + d = json.loads(self.delta) + d['power'] = power + self.delta = json.dumps(d) + + def set_hostname(self, hostname): + self.hostname = hostname + d = json.loads(self.delta) + d['hostname'] = hostname + self.delta = json.dumps(d) + + def set_ipmi_create(self, ipmi_create): + self.ipmi_create = ipmi_create + d = json.loads(self.delta) + d['ipmi_create'] = ipmi_create + self.delta = json.dumps(d) + + +class NetworkConfig(TaskConfig): + """ + handles network configuration + """ + interfaces = models.ManyToManyField(Interface) + delta = models.TextField() + + def to_dict(self): + d = {} + hid = self.hostnetworkrelation.host.labid + d[hid] = {} + for interface in self.interfaces.all(): + d[hid][interface.mac_address] = [] + for vlan in interface.config.all(): + d[hid][interface.mac_address].append({"vlan_id": vlan.vlan_id, "tagged": vlan.tagged}) + + return d + + def to_json(self): + return json.dumps(self.to_dict()) + + def get_delta(self): + if not self.delta: + self.delta = self.to_json() + self.save() + d = json.loads(self.delta) + d['lab_token'] = self.hostnetworkrelation.lab_token + return d + + def clear_delta(self): + self.delta = json.dumps(self.to_dict()) + self.save() + + def add_interface(self, interface): + self.interfaces.add(interface) + d = json.loads(self.delta) + hid = self.hostnetworkrelation.host.labid + if hid not in d: + d[hid] = {} + d[hid][interface.mac_address] = [] + for vlan in interface.config.all(): + d[hid][interface.mac_address].append({"vlan_id": vlan.vlan_id, "tagged": vlan.tagged}) + self.delta = json.dumps(d) + + +class SnapshotConfig(TaskConfig): + + host = models.ForeignKey(Host, null=True, on_delete=models.DO_NOTHING) + image = models.IntegerField(null=True) + dashboard_id = models.IntegerField() + delta = models.TextField(default="{}") + + def to_dict(self): + d = {} + if self.host: + d['host'] = self.host.labid + if self.image: + d['image'] = self.image + d['dashboard_id'] = self.dashboard_id + return d + + def to_json(self): + return json.dumps(self.to_dict()) + + def get_delta(self): + if not self.delta: + self.delta = self.to_json() + self.save() + + d = json.loads(self.delta) + return d + + def clear_delta(self): + self.delta = json.dumps(self.to_dict()) + self.save() + + def set_host(self, host): + self.host = host + d = json.loads(self.delta) + d['host'] = host.labid + self.delta = json.dumps(d) + + def set_image(self, image): + self.image = image + d = json.loads(self.delta) + d['image'] = self.image + self.delta = json.dumps(d) + + def clear_image(self): + self.image = None + d = json.loads(self.delta) + d.pop("image", None) + self.delta = json.dumps(d) + + def set_dashboard_id(self, dash): + self.dashboard_id = dash + d = json.loads(self.delta) + d['dashboard_id'] = self.dashboard_id + self.delta = json.dumps(d) + + +def get_task(task_id): + for taskclass in [AccessRelation, SoftwareRelation, HostHardwareRelation, HostNetworkRelation, SnapshotRelation]: + try: + ret = taskclass.objects.get(task_id=task_id) + return ret + except taskclass.DoesNotExist: + pass + from django.core.exceptions import ObjectDoesNotExist + raise ObjectDoesNotExist("Could not find matching TaskRelation instance") + + +def get_task_uuid(): + return str(uuid.uuid4()) + + +class TaskRelation(models.Model): + status = models.IntegerField(default=JobStatus.NEW) + job = models.ForeignKey(Job, on_delete=models.CASCADE) + config = models.OneToOneField(TaskConfig, on_delete=models.CASCADE) + task_id = models.CharField(default=get_task_uuid, max_length=37) + lab_token = models.CharField(default="null", max_length=50) + message = models.TextField(default="") + + def delete(self, *args, **kwargs): + self.config.delete() + return super(self.__class__, self).delete(*args, **kwargs) + + def type_str(self): + return "Generic Task" + + class Meta: + abstract = True + + +class AccessRelation(TaskRelation): + config = models.OneToOneField(AccessConfig, on_delete=models.CASCADE) + + def type_str(self): + return "Access Task" + + def delete(self, *args, **kwargs): + self.config.delete() + return super(self.__class__, self).delete(*args, **kwargs) + + +class SoftwareRelation(TaskRelation): + config = models.OneToOneField(SoftwareConfig, on_delete=models.CASCADE) + + def type_str(self): + return "Software Configuration Task" + + def delete(self, *args, **kwargs): + self.config.delete() + return super(self.__class__, self).delete(*args, **kwargs) + + +class HostHardwareRelation(TaskRelation): + host = models.ForeignKey(Host, on_delete=models.CASCADE) + config = models.OneToOneField(HardwareConfig, on_delete=models.CASCADE) + + def type_str(self): + return "Hardware Configuration Task" + + def get_delta(self): + return self.config.to_dict() + + def delete(self, *args, **kwargs): + self.config.delete() + return super(self.__class__, self).delete(*args, **kwargs) + + +class HostNetworkRelation(TaskRelation): + host = models.ForeignKey(Host, on_delete=models.CASCADE) + config = models.OneToOneField(NetworkConfig, on_delete=models.CASCADE) + + def type_str(self): + return "Network Configuration Task" + + def delete(self, *args, **kwargs): + self.config.delete() + return super(self.__class__, self).delete(*args, **kwargs) + + +class SnapshotRelation(TaskRelation): + snapshot = models.ForeignKey(Image, on_delete=models.CASCADE) + config = models.OneToOneField(SnapshotConfig, on_delete=models.CASCADE) + + def type_str(self): + return "Snapshot Task" + + def get_delta(self): + return self.config.to_dict() + + def delete(self, *args, **kwargs): + self.config.delete() + return super(self.__class__, self).delete(*args, **kwargs) + + +class JobFactory(object): + + @classmethod + def reimageHost(cls, new_image, booking, host): + """ + This method will make all necessary changes to make a lab + reimage a host. + """ + job = Job.objects.get(booking=booking) + # make hardware task new + hardware_relation = HostHardwareRelation.objects.get(host=host, job=job) + hardware_relation.config.set_image(new_image.lab_id) + hardware_relation.config.save() + hardware_relation.status = JobStatus.NEW + + # re-apply networking after host is reset + net_relation = HostNetworkRelation.objects.get(host=host, job=job) + net_relation.status = JobStatus.NEW + + # re-apply ssh access after host is reset + for relation in AccessRelation.objects.filter(job=job, config__access_type="ssh"): + relation.status = JobStatus.NEW + relation.save() + + hardware_relation.save() + net_relation.save() + + @classmethod + def makeSnapshotTask(cls, image, booking, host): + relation = SnapshotRelation() + job = Job.objects.get(booking=booking) + config = SnapshotConfig.objects.create(dashboard_id=image.id) + + relation.job = job + relation.config = config + relation.config.save() + relation.config = relation.config + relation.snapshot = image + relation.save() + + config.clear_delta() + config.set_host(host) + config.save() + + @classmethod + def makeCompleteJob(cls, booking): + hosts = Host.objects.filter(bundle=booking.resource) + job = None + try: + job = Job.objects.get(booking=booking) + except Exception: + job = Job.objects.create(status=JobStatus.NEW, booking=booking) + cls.makeHardwareConfigs( + hosts=hosts, + job=job + ) + cls.makeNetworkConfigs( + hosts=hosts, + job=job + ) + cls.makeSoftware( + booking=booking, + job=job + ) + all_users = list(booking.collaborators.all()) + all_users.append(booking.owner) + cls.makeAccessConfig( + users=all_users, + access_type="vpn", + revoke=False, + job=job + ) + for user in all_users: + try: + cls.makeAccessConfig( + users=[user], + access_type="ssh", + revoke=False, + job=job, + context={ + "key": user.userprofile.ssh_public_key.open().read().decode(encoding="UTF-8"), + "hosts": [host.labid for host in hosts] + } + ) + except Exception: + continue + + @classmethod + def makeHardwareConfigs(cls, hosts=[], job=Job()): + for host in hosts: + hardware_config = None + try: + hardware_config = HardwareConfig.objects.get(relation__host=host) + except Exception: + hardware_config = HardwareConfig() + + relation = HostHardwareRelation() + relation.host = host + relation.job = job + relation.config = hardware_config + relation.config.save() + relation.config = relation.config + relation.save() + + hardware_config.clear_delta() + hardware_config.set_image(host.config.image.lab_id) + hardware_config.set_hostname(host.template.resource.name) + hardware_config.set_power("on") + hardware_config.set_ipmi_create(True) + hardware_config.save() + + @classmethod + def makeAccessConfig(cls, users, access_type, revoke=False, job=Job(), context=False): + for user in users: + relation = AccessRelation() + relation.job = job + config = AccessConfig() + config.access_type = access_type + config.user = user + config.save() + relation.config = config + relation.save() + config.clear_delta() + if context: + config.set_context(context) + config.set_access_type(access_type) + config.set_revoke(revoke) + config.set_user(user) + config.save() + + @classmethod + def makeNetworkConfigs(cls, hosts=[], job=Job()): + for host in hosts: + network_config = None + try: + network_config = NetworkConfig.objects.get(relation__host=host) + except Exception: + network_config = NetworkConfig.objects.create() + + relation = HostNetworkRelation() + relation.host = host + relation.job = job + network_config.save() + relation.config = network_config + relation.save() + network_config.clear_delta() + + for interface in host.interfaces.all(): + network_config.add_interface(interface) + network_config.save() + + @classmethod + def make_bridge_config(cls, booking): + if booking.resource.hosts.count() < 2: + return None + try: + jumphost_config = HostOPNFVConfig.objects.filter( + role__name__iexact="jumphost" + ) + jumphost = Host.objects.get( + bundle=booking.resource, + config=jumphost_config.host_config + ) + except Exception: + return None + br_config = BridgeConfig.objects.create(opnfv_config=booking.opnfv_config) + for iface in jumphost.interfaces.all(): + br_config.interfaces.add(iface) + return br_config + + @classmethod + def makeSoftware(cls, booking=None, job=Job()): + + if not booking.opnfv_config: + return None + + opnfv_api_config = OpnfvApiConfig.objects.create( + opnfv_config=booking.opnfv_config, + installer=booking.opnfv_config.installer.name, + scenario=booking.opnfv_config.scenario.name, + bridge_config=cls.make_bridge_config(booking) + ) + + opnfv_api_config.set_xdf(booking, False) + opnfv_api_config.save() + + for host in booking.resource.hosts.all(): + opnfv_api_config.roles.add(host) + software_config = SoftwareConfig.objects.create(opnfv=opnfv_api_config) + software_relation = SoftwareRelation.objects.create(job=job, config=software_config) + return software_relation |