# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from datetime import datetime from itertools import chain import json import logging from pytz import UTC from blazar_dashboard import conf from horizon import exceptions from horizon.utils.memoized import memoized from openstack_dashboard.api import base from blazarclient import client as blazar_client LOG = logging.getLogger(__name__) class Lease(base.APIDictWrapper): """Represents one Blazar lease.""" _attrs = ['id', 'name', 'start_date', 'end_date', 'user_id', 'project_id', 'before_end_date', 'status', 'degraded'] def __init__(self, apiresource): super(Lease, self).__init__(apiresource) class Host(base.APIDictWrapper): """Represents one Blazar host.""" _attrs = ['id', 'hypervisor_hostname', 'hypervisor_type', 'hypervisor_version', 'vcpus', 'cpu_info', 'memory_mb', 'local_gb', 'status', 'created_at', 'updated_at', 'service_name', 'trust_id', 'reservable'] def __init__(self, apiresource): super(Host, self).__init__(apiresource) def cpu_info_dict(self): cpu_info_dict = getattr(self, 'cpu_info', '{}') if not cpu_info_dict: cpu_info_dict = '{}' return json.loads(cpu_info_dict) def extra_capabilities(self): excaps = {} for k, v in self._apidict.items(): if k not in self._attrs: excaps[k] = v return excaps class Allocation(base.APIDictWrapper): _attrs = ['resource_id', 'reservations'] @memoized def blazarclient(request): try: api_url = base.url_for(request, 'reservation') except exceptions.ServiceCatalogException: LOG.debug('No Reservation service is configured.') return None LOG.debug('blazarclient connection created using the token "%s" and url' '"%s"' % (request.user.token.id, api_url)) return blazar_client.Client( blazar_url=api_url, auth_token=request.user.token.id) def lease_list(request): """List the leases.""" leases = blazarclient(request).lease.list() return [Lease(l) for l in leases] def lease_get(request, lease_id): """Get a lease.""" lease = blazarclient(request).lease.get(lease_id) return Lease(lease) def lease_create(request, name, start, end, reservations, events): """Create a lease.""" lease = blazarclient(request).lease.create( name, start, end, reservations, events) return Lease(lease) def lease_update(request, lease_id, **kwargs): """Update a lease.""" lease = blazarclient(request).lease.update(lease_id, **kwargs) return Lease(lease) def lease_delete(request, lease_id): """Delete a lease.""" blazarclient(request).lease.delete(lease_id) def host_list(request): """List hosts.""" hosts = blazarclient(request).host.list() return [Host(h) for h in hosts] def host_get(request, host_id): """Get a host.""" host = blazarclient(request).host.get(host_id) return Host(host) def host_create(request, name, **kwargs): """Create a host.""" host = blazarclient(request).host.create(name, **kwargs) return Host(host) def host_update(request, host_id, values): """Update a host.""" host = blazarclient(request).host.update(host_id, values) return Host(host) def host_delete(request, host_id): """Delete a host.""" blazarclient(request).host.delete(host_id) def host_allocations_list(request): """List allocations for all hosts.""" request_manager = blazarclient(request).host.request_manager resp, body = request_manager.get('/os-hosts/allocations') allocations = body['allocations'] return [Allocation(a) for a in allocations] def reservation_calendar(request): """Return a list of all scheduled leases.""" def compute_host2dict(h): dictionary = dict( hypervisor_hostname=h.hypervisor_hostname, vcpus=h.vcpus, memory_mb=h.memory_mb, local_gb=h.local_gb, cpu_info=h.cpu_info, hypervisor_type=h.hypervisor_type,) # Ensure config attribute is copied over calendar_attribute = conf.host_reservation.get('calendar_attribute') dictionary[calendar_attribute] = ( h[calendar_attribute] ) return dictionary # NOTE: This filters by reservable hosts hosts_by_id = {h.id: h for h in host_list(request) if h.reservable} def host_reservation_dict(reservation, resource_id): host_reservation = dict( start_date=_parse_api_datestr(reservation['start_date']), end_date=_parse_api_datestr(reservation['end_date']), reservation_id=reservation['id'], ) calendar_attribute = conf.host_reservation.get('calendar_attribute') host_reservation[calendar_attribute] = ( hosts_by_id[resource_id][calendar_attribute] ) return {k: v for k, v in host_reservation.items() if v is not None} host_reservations = [ [host_reservation_dict(r, alloc.resource_id) for r in alloc.reservations if alloc.resource_id in hosts_by_id] for alloc in host_allocations_list(request)] compute_hosts = [compute_host2dict(h) for h in hosts_by_id.values()] return compute_hosts, list(chain(*host_reservations)) def _parse_api_datestr(datestr): if datestr is None: return datestr dateobj = datetime.strptime(datestr, "%Y-%m-%dT%H:%M:%S.%f") return dateobj.replace(tzinfo=UTC)