Lab as a Service 2.0
[laas.git] / src / resource_inventory / resource_manager.py
1 ##############################################################################
2 # Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, and others.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10
11 from django.core.exceptions import *
12 from django.template.loader import render_to_string
13
14 import booking
15 from dashboard.exceptions import *
16 from resource_inventory.models import *
17
18 class ResourceManager:
19
20     instance = None
21
22     def __init__(self):
23         pass
24
25     @staticmethod
26     def getInstance():
27         if ResourceManager.instance is None:
28             ResourceManager.instance = ResourceManager()
29         return ResourceManager.instance
30
31     #public interface
32     def deleteResourceBundle(self, resourceBundle):
33         for host in Host.objects.filter(bundle=resourceBundle):
34             self.releaseHost(host)
35         resourceBundle.delete()
36
37     def convertResourceBundle(self, genericResourceBundle, lab=None, config=None):
38         """
39         Takes in a GenericResourceBundle and 'converts' it into a ResourceBundle
40         """
41         resource_bundle = ResourceBundle()
42         resource_bundle.template = genericResourceBundle
43         resource_bundle.save()
44
45         hosts = genericResourceBundle.getHosts()
46
47         #current supported case: user creating new booking
48         #currently unsupported: editing existing booking
49
50         physical_hosts = []
51
52         for host in hosts:
53             host_config=None
54             if config:
55                 host_config = HostConfiguration.objects.get(bundle=config, host=host)
56             try:
57                 physical_host = self.acquireHost(host, genericResourceBundle.lab.name)
58             except ResourceAvailabilityException:
59                 self.fail_acquire(physical_hosts)
60                 raise ResourceAvailabilityException("Could not provision hosts, not enough available")
61             try:
62                 physical_host.bundle = resource_bundle
63                 physical_host.template = host
64                 physical_host.config = host_config
65                 physical_hosts.append(physical_host)
66
67                 self.configureNetworking(physical_host)
68             except:
69                 self.fail_acquire(physical_hosts)
70                 raise ResourceProvisioningException("Network configuration failed.")
71             try:
72                 physical_host.save()
73             except:
74                 self.fail_acquire(physical_hosts)
75                 raise ModelValidationException("Saving hosts failed")
76
77         return resource_bundle
78
79     def configureNetworking(self, host):
80         generic_interfaces = list(host.template.generic_interfaces.all())
81         for int_num, physical_interface in enumerate(host.interfaces.all()):
82             generic_interface = generic_interfaces[int_num]
83             physical_interface.config.clear()
84             for vlan in generic_interface.vlans.all():
85                 physical_interface.config.add(vlan)
86
87     #private interface
88     def acquireHost(self, genericHost, labName):
89         host_full_set = Host.objects.filter(lab__name__exact=labName, profile=genericHost.profile)
90         if not host_full_set.first():
91             raise ResourceExistenceException("No matching servers found")
92         host_set = host_full_set.filter(booked=False)
93         if not host_set.first():
94             raise ResourceAvailabilityException("No unbooked hosts match requested hosts")
95         host = host_set.first()
96         host.booked = True
97         host.template = genericHost
98         host.save()
99         return host
100
101     def releaseHost(self, host):
102         host.template = None
103         host.bundle = None
104         host.booked = False
105         host.save()
106
107     def fail_acquire(self, hosts):
108         for host in hosts:
109             self.releaseHost(host)
110
111     def makePDF(self, resource):
112         """
113         fills the pod descriptor file template with info about the resource
114         """
115         template = "dashboard/pdf.yaml"
116         info = {}
117         info['details'] = self.get_pdf_details(resource)
118         info['jumphost'] = self.get_pdf_jumphost(resource)
119         info['nodes'] = self.get_pdf_nodes(resource)
120
121         return render_to_string(template, context=info)
122
123     def get_pdf_details(self, resource):
124         details = {}
125         owner = "Anon"
126         email = "email@mail.com"
127         resource_lab = resource.template.lab
128         lab = resource_lab.name
129         location = resource_lab.location
130         pod_type = "development"
131         link = "https://wiki.opnfv.org/display/INF/Pharos+Laas"
132
133         try:
134             # try to get more specific info that may fail, we dont care if it does
135             booking_owner = booking.models.Booking.objects.get(resource=resource).owner
136             owner = booking_owner.username
137             email = booking_owner.userprofile.email_addr
138         except Exception as e:
139             pass
140
141         details['owner'] = owner
142         details['email'] = email
143         details['lab'] = lab
144         details['location'] = location
145         details['type'] = pod_type
146         details['link'] = link
147
148         return details
149
150     def get_pdf_jumphost(self, resource):
151         jumphost = Host.objects.get(bundle=resource, config__opnfvRole__name__iexact="jumphost")
152         return self.get_pdf_host(jumphost)
153
154     def get_pdf_nodes(self, resource):
155         pdf_nodes = []
156         nodes = Host.objects.filter(bundle=resource).exclude(config__opnfvRole__name__iexact="jumphost")
157         for node in nodes:
158             pdf_nodes.append(self.get_pdf_host(node))
159
160         return pdf_nodes
161
162
163     def get_pdf_host(self, host):
164         host_info = {}
165         host_info['name'] = host.template.resource.name
166         host_info['node'] = {}
167         host_info['node']['type'] = "baremetal"
168         host_info['node']['vendor'] = host.vendor
169         host_info['node']['model'] = host.model
170         host_info['node']['arch'] = host.profile.cpuprofile.first().architecture
171         host_info['node']['cpus'] = host.profile.cpuprofile.first().cpus
172         host_info['node']['cores'] = host.profile.cpuprofile.first().cores
173         cflags = host.profile.cpuprofile.first().cflags
174         if cflags and cflags.strip():
175             host_info['node']['cpu_cflags'] = cflags
176         host_info['node']['memory'] = str(host.profile.ramprofile.first().amount) + "G"
177         host_info['disks'] = []
178         for disk in host.profile.storageprofile.all():
179             disk_info = {}
180             disk_info['name'] = disk.name
181             disk_info['capacity'] = str(disk.size) + "G"
182             disk_info['type'] = disk.media_type
183             disk_info['interface'] = disk.interface
184             disk_info['rotation'] = disk.rotation
185             host_info['disks'].append(disk_info)
186
187         host_info['interfaces'] = []
188         for interface in host.interfaces.all():
189             iface_info = {}
190             iface_info['name'] = interface.name
191             iface_info['address'] = "unknown"
192             iface_info['mac_address'] = interface.mac_address
193             vlans = "|".join([str(vlan.vlan_id) for vlan in interface.config.all()])
194             iface_info['vlans'] = vlans
195             host_info['interfaces'].append(iface_info)
196
197         return host_info