mirror of
https://github.com/retspen/webvirtcloud
synced 2024-11-01 20:14:15 +00:00
cfce71ec2b
* Add rest framework for API: First Commit * modify some shell scripts to make variable references safer; modify some python scripts to reduce the code complexity and cyclomatic complexity of functions. * Add REST API for some webvirtcloud functions. Instance list/delete/create, compute list/delete/create, storages-network list/retrieve. Add swagger and redoc for API interface * update requirements Co-authored-by: herengui <herengui@uniontech.com>
224 lines
No EOL
9.2 KiB
Python
224 lines
No EOL
9.2 KiB
Python
from django.shortcuts import get_object_or_404
|
|
from appsettings.settings import app_settings
|
|
from computes.models import Compute
|
|
from computes import utils
|
|
from instances.models import Flavor, Instance
|
|
from instances.views import get_instance
|
|
from instances.utils import migrate_instance
|
|
from instances.views import poweron, powercycle, poweroff, force_off, suspend, resume, destroy as instance_destroy
|
|
|
|
from rest_framework import status, viewsets, permissions
|
|
from rest_framework.decorators import action
|
|
from rest_framework.response import Response
|
|
|
|
from vrtManager import util
|
|
|
|
from vrtManager.create import wvmCreate
|
|
from .serializers import FlavorSerializer, InstanceSerializer, InstanceDetailsSerializer, MigrateSerializer, CreateInstanceSerializer
|
|
|
|
class InstancesViewSet(viewsets.ViewSet):
|
|
"""
|
|
A simple ViewSet for listing or retrieving ALL/Compute Instances.
|
|
"""
|
|
permission_classes = [permissions.IsAuthenticated]
|
|
def list(self, request):
|
|
|
|
if request.user.is_superuser or request.user.has_perm("instances.view_instances"):
|
|
queryset = Instance.objects.all().prefetch_related("userinstance_set")
|
|
else:
|
|
queryset = Instance.objects.filter(userinstance__user=request.user).prefetch_related("userinstance_set")
|
|
serializer = InstanceSerializer(queryset, many=True, context={'request': request})
|
|
|
|
return Response(serializer.data)
|
|
|
|
def retrieve(self, request, pk=None, compute_pk=None):
|
|
queryset = get_instance(request.user, pk)
|
|
serializer = InstanceSerializer(queryset, context={'request': request})
|
|
|
|
return Response(serializer.data)
|
|
|
|
|
|
class InstanceViewSet(viewsets.ViewSet):
|
|
"""
|
|
A simple ViewSet for listing or retrieving Compute Instances.
|
|
"""
|
|
#serializer_class = CreateInstanceSerializer
|
|
permission_classes = [permissions.IsAuthenticated]
|
|
def list(self, request, compute_pk=None):
|
|
compute = get_object_or_404(Compute, pk=compute_pk)
|
|
|
|
utils.refresh_instance_database(compute)
|
|
|
|
queryset = Instance.objects.filter(compute=compute).prefetch_related("userinstance_set")
|
|
serializer = InstanceSerializer(queryset, many=True, context={'request': request})
|
|
|
|
return Response(serializer.data)
|
|
|
|
|
|
def retrieve(self, request, pk=None, compute_pk=None):
|
|
queryset = get_instance(request.user, pk)
|
|
serializer = InstanceDetailsSerializer(queryset, context={'request': request})
|
|
|
|
return Response(serializer.data)
|
|
|
|
|
|
def destroy(self, request, pk=None, compute_pk=None):
|
|
instance_destroy(request, pk)
|
|
return Response({'status': 'Instance is destroyed'})
|
|
|
|
@action(detail=True, methods=['post'])
|
|
def poweron(self, request, pk=None):
|
|
poweron(request, pk)
|
|
return Response({'status': 'poweron command send'})
|
|
|
|
@action(detail=True, methods=['post'])
|
|
def poweroff(self, request, pk=None):
|
|
poweroff(request, pk)
|
|
return Response({'status': 'poweroff command send'})
|
|
|
|
@action(detail=True, methods=['post'])
|
|
def powercycle(self, request, pk=None):
|
|
powercycle(request, pk)
|
|
return Response({'status': 'powercycle command send'})
|
|
|
|
@action(detail=True, methods=['post'])
|
|
def forceoff(self, request, pk=None):
|
|
force_off(request, pk)
|
|
return Response({'status': 'force off command send'})
|
|
|
|
@action(detail=True, methods=['post'])
|
|
def suspend(self, request, pk=None):
|
|
suspend(request, pk)
|
|
return Response({'status': 'suspend command send'})
|
|
|
|
@action(detail=True, methods=['post'])
|
|
def resume(self, request, pk=None):
|
|
resume(request, pk)
|
|
return Response({'status': 'resume command send'})
|
|
|
|
|
|
class MigrateViewSet(viewsets.ViewSet):
|
|
"""
|
|
A viewset for migrating instances.
|
|
"""
|
|
serializer_class = MigrateSerializer
|
|
queryset = ""
|
|
|
|
def create(self, request):
|
|
serializer = MigrateSerializer(data=request.data)
|
|
if serializer.is_valid():
|
|
instance = serializer.validated_data['instance']
|
|
target_host = serializer.validated_data['target_compute']
|
|
live = serializer.validated_data['live']
|
|
unsafe = serializer.validated_data['unsafe']
|
|
xml_del = serializer.validated_data['xml_del']
|
|
offline = serializer.validated_data['offline']
|
|
autoconverge = serializer.validated_data['autoconverge']
|
|
postcopy = serializer.validated_data['postcopy']
|
|
compress = serializer.validated_data['compress']
|
|
|
|
migrate_instance(target_host, instance, request.user, live, unsafe, xml_del, offline, autoconverge, compress, postcopy)
|
|
|
|
return Response({'status': 'instance migrate is started'})
|
|
else:
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
|
|
class FlavorViewSet(viewsets.ModelViewSet):
|
|
"""
|
|
API endpoint that allows flavor to be viewed.
|
|
"""
|
|
queryset = Flavor.objects.all().order_by('id')
|
|
serializer_class = FlavorSerializer
|
|
permission_classes = [permissions.IsAuthenticated]
|
|
|
|
|
|
class CreateInstanceViewSet(viewsets.ViewSet):
|
|
"""
|
|
A viewset for creating instances.
|
|
"""
|
|
serializer_class = CreateInstanceSerializer
|
|
queryset = ""
|
|
|
|
def create(self, request, compute_pk=None, arch=None, machine=None):
|
|
serializer = CreateInstanceSerializer(data=request.data,
|
|
context = {'compute_pk': compute_pk,
|
|
'arch': arch,
|
|
'machine': machine
|
|
})
|
|
if serializer.is_valid():
|
|
volume_list = []
|
|
default_bus = app_settings.INSTANCE_VOLUME_DEFAULT_BUS
|
|
default_io = app_settings.INSTANCE_VOLUME_DEFAULT_IO
|
|
default_discard = app_settings.INSTANCE_VOLUME_DEFAULT_DISCARD
|
|
default_zeroes = app_settings.INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES
|
|
default_scsi_disk_model = app_settings.INSTANCE_VOLUME_DEFAULT_SCSI_CONTROLLER
|
|
default_disk_format = app_settings.INSTANCE_VOLUME_DEFAULT_FORMAT
|
|
default_disk_owner_uid = int(app_settings.INSTANCE_VOLUME_DEFAULT_OWNER_UID)
|
|
default_disk_owner_gid = int(app_settings.INSTANCE_VOLUME_DEFAULT_OWNER_GID)
|
|
compute = Compute.objects.get(pk=compute_pk)
|
|
conn = wvmCreate(
|
|
compute.hostname,
|
|
compute.login,
|
|
compute.password,
|
|
compute.type,
|
|
)
|
|
|
|
path = conn.create_volume(
|
|
serializer.validated_data['storage'],
|
|
serializer.validated_data['name'],
|
|
serializer.validated_data['hdd_size'],
|
|
default_disk_format,
|
|
serializer.validated_data['meta_prealloc'],
|
|
default_disk_owner_uid,
|
|
default_disk_owner_gid,
|
|
)
|
|
volume = {}
|
|
firmware = {}
|
|
volume["device"] = "disk"
|
|
volume["path"] = path
|
|
volume["type"] = conn.get_volume_format_type(path)
|
|
volume["cache_mode"] = serializer.validated_data["cache_mode"]
|
|
volume["bus"] = default_bus
|
|
if volume["bus"] == "scsi":
|
|
volume["scsi_model"] = default_scsi_disk_model
|
|
volume["discard_mode"] = default_discard
|
|
volume["detect_zeroes_mode"] = default_zeroes
|
|
volume["io_mode"] = default_io
|
|
|
|
volume_list.append(volume)
|
|
|
|
if "UEFI" in serializer.validated_data['firmware']:
|
|
firmware["loader"] = serializer.validated_data['firmware'].split(":")[1].strip()
|
|
firmware["secure"] = "no"
|
|
firmware["readonly"] = "yes"
|
|
firmware["type"] = "pflash"
|
|
if "secboot" in firmware["loader"] and machine != "q35":
|
|
machine = "q35"
|
|
firmware["secure"] = "yes"
|
|
|
|
ret = conn.create_instance(
|
|
serializer.validated_data['name'],
|
|
serializer.validated_data['memory'],
|
|
serializer.validated_data['vcpu'],
|
|
serializer.validated_data['vcpu_mode'],
|
|
util.randomUUID(),
|
|
arch,
|
|
machine,
|
|
firmware,
|
|
volume_list,
|
|
serializer.validated_data['networks'],
|
|
serializer.validated_data['nwfilter'],
|
|
serializer.validated_data['graphics'],
|
|
serializer.validated_data['virtio'],
|
|
serializer.validated_data['listener_addr'],
|
|
serializer.validated_data['video'],
|
|
serializer.validated_data['console_pass'],
|
|
serializer.validated_data['mac'],
|
|
serializer.validated_data['qemu_ga'],
|
|
)
|
|
msg = f"Instance {serializer.validated_data['name']} is created"
|
|
return Response({'status': msg })
|
|
else:
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) |