# Copyright 2014 Budapest University of Technology and Economics (BME IK) # # This file is part of CIRCLE Cloud. # # CIRCLE is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along # with CIRCLE. If not, see <http://www.gnu.org/licenses/>. from django.contrib import messages from django.urls import reverse from django.db.models import Q from django.utils.translation import ugettext_lazy as _ from django.views.generic import UpdateView from django.http import JsonResponse from braces.views import SuperuserRequiredMixin from sizefield.utils import filesizeformat from rest_framework.authentication import TokenAuthentication, BasicAuthentication from rest_framework.permissions import IsAdminUser from rest_framework.views import APIView from common.models import WorkerNotFound from storage.models import DataStore, Disk from ..tables import DiskListTable from ..forms import DataStoreForm, DiskForm from dashboard.serializers import DiskSerializer class StorageDetail(SuperuserRequiredMixin, UpdateView): model = DataStore form_class = DataStoreForm template_name = "dashboard/storage/detail.html" def get_object(self): datastore = 'default' if 'name' in self.kwargs: datastore = self.kwargs['name'] return DataStore.objects.filter(name=datastore).get() def get_context_data(self, **kwargs): context = super(StorageDetail, self).get_context_data(**kwargs) context["stores"] = DataStore.objects.all() ds = self.get_object() try: context['name'] = ds.name context['stats'] = self._get_stats() context['g'] = ds.get_missing_disks() context['orphan_disks'] = ds.get_orphan_disks() except WorkerNotFound: messages.error(self.request, _("The DataStore is offline.")) context['disk_table'] = DiskListTable( self.get_table_data(), request=self.request, template_name="django_tables2/with_pagination.html") context['filter_names'] = ( ('vm', _("virtual machine")), ('template', _("template")), ('none', _("none")), ) return context def get_table_data(self): ds = self.get_object() qs = Disk.objects.filter(datastore=ds, destroyed=None) filter_name = self.request.GET.get("filter") search = self.request.GET.get("s") filter_queries = { 'vm': { 'instance_set__isnull': False, }, 'template': { 'template_set__isnull': False, }, 'none': { 'template_set__isnull': True, 'instance_set__isnull': True, } } if filter_name: qs = qs.filter(**filter_queries.get(filter_name, {})) if search: search = search.strip() qs = qs.filter(Q(name__icontains=search) | Q(filename__icontains=search)) return qs def _get_stats(self): # datastore stats stats = self.object.get_statistics() free_space = int(stats['free_space']) free_percent = float(stats['free_percent']) total_space = free_space / (free_percent/100.0) used_space = total_space - free_space # file stats data = self.get_object().get_file_statistics() dumps_size = sum(d['size'] for d in data['dumps']) trash = sum(d['size'] for d in data['trash']) iso_raw = sum(d['size'] for d in data['disks'] if d['format'] in ("iso", "raw")) vm_size = vm_actual_size = template_actual_size = 0 for d in data['disks']: if d['format'] == "qcow2" and d['type'] == "normal": template_actual_size += d['actual_size'] else: vm_size += d['size'] vm_actual_size += d['actual_size'] return { 'used_percent': int(100 - free_percent), 'free_space': filesizeformat(free_space), 'used_space': filesizeformat(used_space), 'total_space': filesizeformat(total_space), 'dumps': dumps_size, 'trash': trash, 'iso_raw': iso_raw, 'vm_size': vm_size, 'vm_actual_size': vm_actual_size, 'template_actual_size': template_actual_size, } def get_success_url(self): return reverse("dashboard.views.storage") class DiskDetail(SuperuserRequiredMixin, UpdateView): model = Disk form_class = DiskForm template_name = "dashboard/storage/disk.html" def form_valid(self, form): pass class DiskRest(APIView): authentication_classes = [TokenAuthentication,BasicAuthentication] permission_classes = [IsAdminUser] def get(self, request, format=None): templates = Disk.objects.all() serializer = DiskSerializer(templates, many=True) return JsonResponse(serializer.data, safe=False) class GetDiskRest(APIView): authentication_classes = [TokenAuthentication,BasicAuthentication] permission_classes = [IsAdminUser] def get(self, request, pk, format=None): disk = Disk.objects.get(pk=pk) serializer = DiskSerializer(disk, many=False) return JsonResponse(serializer.data, safe=False) def delete(self, request, pk, format=None): return JsonResponse(status=204)