From ef00d676f56d115ff23c91a153c291b7c28766fc Mon Sep 17 00:00:00 2001 From: Modulos Date: Thu, 11 May 2017 05:51:30 +0200 Subject: [PATCH] Access VirtualMachine via api! Serialization of VirtualMachine objects now fully works --- opennebula_api/models.py | 84 +++++++++++++---------------------- opennebula_api/serializers.py | 72 +++++++++++++++++++++--------- opennebula_api/views.py | 21 ++++++++- 3 files changed, 101 insertions(+), 76 deletions(-) diff --git a/opennebula_api/models.py b/opennebula_api/models.py index 2d4a9f97..6a7ba2fc 100644 --- a/opennebula_api/models.py +++ b/opennebula_api/models.py @@ -15,10 +15,9 @@ class VirtualMachineTemplate(models.Model): disk_size_price = models.FloatField() def calculate_price(self): - manager = OpenNebulaManager() - template = manger._get_template(self.opennebula_id).template + template = OpenNebulaManager()._get_template(self.opennebula_id).template - price = int(template.vpcu) * self.core_price + price = int(template.vcpu) * self.core_price price += int(template.memory) / 1024 * self.memory_price try: price += int(template.disk.size) / 1024 * self.disk_size_price @@ -29,20 +28,17 @@ class VirtualMachineTemplate(models.Model): def get_name(self): - manager = OpenNebulaManager(create_user=False) - template = manager._get_template(template_id=self.opennebula_id) + template = OpenNebulaManager()._get_template(template_id=self.opennebula_id) return template.name def get_cores(self): - manager = OpenNebulaManager(create_user=False) - template = manager._get_template(template_id=self.opennebula_id).template + template = OpenNebulaManager()._get_template(template_id=self.opennebula_id).template return int(template.vcpu) def get_disk_size(self): - manager = OpenNebulaManager(create_user=False) - template = manager._get_template(template_id=self.opennebula_id).template + template = OpenNebulaManager()._get_template(template_id=self.opennebula_id).template disk_size = 0 for disk in template.disks: disk_size += int(disk.size) @@ -50,14 +46,13 @@ class VirtualMachineTemplate(models.Model): def get_memory(self): - manager = OpenNebulaManager(create_user=False) - template = manager._get_template(template_id=self.opennebula_id).template + template = OpenNebulaManager()._get_template(template_id=self.opennebula_id).template return int(template.memory) / 1024 class VirtualMachine(models.Model): """This class represents an opennebula virtual machine.""" opennebula_id = models.IntegerField() - template = models.ForeignKey(VirtualMachineTemplate) + vm_template = models.ForeignKey(VirtualMachineTemplate) VM_STATE = { '0': 'INIT', @@ -74,66 +69,42 @@ class VirtualMachine(models.Model): } def get_name(self): - if self.manager is None: - self.manager = OpenNebulaManager() - - vm = self.manager._get_vm(vm_id=self.opennebula_id) + + vm = OpenNebulaManager()._get_vm(vm_id=self.opennebula_id) return vm.name def get_cores(self): - if self.manager is None: - self.manager = OpenNebulaManager() - template = self.manager._get_vm(vm_id=self.opennebula_id).template - return int(template.vcpu) + return self.vm_template.get_cores() def get_disk_size(self): - if self.manager is None: - self.manager = OpenNebulaManager() - - template = self.manager._get_vm(vm_id=self.opennebula_id).template - try: - return template.disk.size - except AttributeError: - disk_size = 0 - for disk in template.disks: - disk_size += disk.size - return disk_size / 1024 - + + return self.vm_template.get_disk_size() def get_memory(self): - if self.manager is None: - self.manager = OpenNebulaManager() - template = self.manager._get_vm(vm_id=self.opennebula_id).template - return int(template.memory) + return self.vm_template.get_memory() def get_id(self): - if self.manager is None: - self.manager = OpenNebulaManager() - vm = self.manager._get_vm(vm_id=self.opennebula_id) + vm = OpenNebulaManager()._get_vm(vm_id=self.opennebula_id) return vm.id def get_ip(self): - if self.manager is None: - self.manager = OpenNebulaManager() - vm = self.manager._get_vm(vm_id=self.opennebula_id) + vm = OpenNebulaManager()._get_vm(vm_id=self.opennebula_id) try: return vm.user_template.ungleich_public_ip except AttributeError: return '-' def get_state(self): - if self.manager is None: - self.manager = OpenNebulaManager() - vm = self.manager._get_vm(vm_id=self.opennebula_id) + vm = OpenNebulaManager()._get_vm(vm_id=self.opennebula_id) return self.VM_STATE.get(str(vm.state)) def get_price(self): - return 0.0 + return self.vm_template.calculate_price() class OpenNebulaManager(): """This class represents an opennebula manager.""" @@ -182,6 +153,7 @@ class OpenNebulaManager(): opennebula_user = self.oneadmin_client.call(oca.User.METHODS['allocate'], email, password, 'core') return opennebula_user + #TODO: Replace with logger except ConnectionRefusedError: print('Could not connect to host: {host} via protocol {protocol}'.format( host=settings.OPENNEBULA_DOMAIN, @@ -192,6 +164,7 @@ class OpenNebulaManager(): try: user_pool = oca.UserPool(self.oneadmin_client) user_pool.info() + #TODO: Replace with logger except ConnectionRefusedError: print('Could not connect to host: {host} via protocol {protocol}'.format( host=settings.OPENNEBULA_DOMAIN, @@ -202,8 +175,9 @@ class OpenNebulaManager(): def _get_vm_pool(self): try: - vm_pool = oca.VmPool(self.oneadmin_client) + vm_pool = oca.VirtualMachinePool(self.oneadmin_client) vm_pool.info() + #TODO: Replace with logger except ConnectionRefusedError: print('Could not connect to host: {host} via protocol {protocol}'.format( host=settings.OPENNEBULA_DOMAIN, @@ -225,12 +199,15 @@ class OpenNebulaManager(): template = template_pool.get_by_id(template_id) vm_id = template.instantiate() - self.oneadmin.call( - oca.VirtualMachine.METHODS['chown'], - vm_id, - self.opennebula_user.id, - self.opennebula_user.group_ids[0] - ) + try: + self.oneadmin_client.call( + oca.VirtualMachine.METHODS['chown'], + vm_id, + self.opennebula_user.id, + self.opennebula_user.group_ids[0] + ) + except AttributeError: + pass return vm_id def delete_vm(self, vm_id): @@ -241,6 +218,7 @@ class OpenNebulaManager(): try: template_pool = oca.VmTemplatePool(self.oneadmin_client) template_pool.info() + #TODO: Replace with logger except ConnectionRefusedError: print('Could not connect to host: {host} via protocol {protocol}'.format( host=settings.OPENNEBULA_DOMAIN, diff --git a/opennebula_api/serializers.py b/opennebula_api/serializers.py index 13f6d5ab..e8ff33bd 100644 --- a/opennebula_api/serializers.py +++ b/opennebula_api/serializers.py @@ -6,27 +6,6 @@ from oca import OpenNebulaException from .models import VirtualMachine, VirtualMachineTemplate, OpenNebulaManager -class VirtualMachineSerializer(serializers.ModelSerializer): - """Serializer to map the virtual machine instance into JSON format.""" - - #TODO: Maybe we can change to template.get_cores - cores = serializers.IntegerField(read_only=True, source='get_cores') - name = serializers.CharField(read_only=True, source='get_name') - disk_size = serializers.IntegerField(read_only=True, source='get_disk_size') - memory = serializers.IntegerField(read_only=True, source='get_memory') - #TODO: See if we can change to IPAddressField - ip = serializers.CharField(read_only=True, source='get_ip') - deploy_id = serializers.IntegerField(read_only=True, source='get_deploy_id') - vm_id = serializers.IntegerField(read_only=True, source='get_vm_id') - state = serializers.CharField(read_only=True, source='get_state') - price = serializers.FloatField(read_only=True, source='get_price') - - class Meta: - model = VirtualMachine - fields = ('id', 'opennebula_id', 'template', 'cores', 'name', - 'disk_size', 'memory', 'ip', 'deploy_id', 'state', 'vm_id', - 'price') - class VirtualMachineTemplateSerializer(serializers.ModelSerializer): """Serializer to map the virtual machine template instance into JSON format.""" cores = serializers.IntegerField(source='get_cores') @@ -61,3 +40,54 @@ class VirtualMachineTemplateSerializer(serializers.ModelSerializer): def create(self, validated_data): return VirtualMachineTemplate.objects.create(**validated_data) + +class TemplatePrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField): + def display_value(self, instance): + return 'Template: {}'.format(instance.get_name()) + +class VirtualMachineSerializer(serializers.ModelSerializer): + """Serializer to map the virtual machine instance into JSON format.""" + + #TODO: Maybe we can change to template.get_cores + cores = serializers.IntegerField(read_only=True, source='get_cores') + name = serializers.CharField(read_only=True, source='get_name') + disk_size = serializers.IntegerField(read_only=True, source='get_disk_size') + memory = serializers.IntegerField(read_only=True, source='get_memory') + #TODO: See if we can change to IPAddressField + ip = serializers.CharField(read_only=True, source='get_ip') + deploy_id = serializers.IntegerField(read_only=True, source='get_deploy_id') + vm_id = serializers.IntegerField(read_only=True, source='get_vm_id') + state = serializers.CharField(read_only=True, source='get_state') + price = serializers.FloatField(read_only=True, source='get_price') + + vm_template = VirtualMachineTemplateSerializer(read_only=True) + + vm_template_id = TemplatePrimaryKeyRelatedField( + queryset=VirtualMachineTemplate.objects.all(), + source='vm_template' + ) + + class Meta: + model = VirtualMachine + fields = ('id', 'opennebula_id', 'vm_template', 'vm_template_id', 'cores', 'name', + 'disk_size', 'memory', 'ip', 'deploy_id', 'state', 'vm_id', + 'price') + read_only_fields = ('opennebula_id', ) + + def validate(self, data): + # Create the opennebula model + manager = OpenNebulaManager(create_user = False) + + try: + template_id = data['vm_template'].opennebula_id + opennebula_id = manager.create_vm(template_id) + data.update({'opennebula_id':opennebula_id}) + except OpenNebulaException as err: + raise serializers.ValidationError("OpenNebulaException occured. {0}".format(err)) + + return data + + def create(self, validated_data): + return VirtualMachine.objects.create(**validated_data) + + diff --git a/opennebula_api/views.py b/opennebula_api/views.py index be0e1a24..4cd237ae 100644 --- a/opennebula_api/views.py +++ b/opennebula_api/views.py @@ -1,6 +1,8 @@ from rest_framework import generics -from .serializers import VirtualMachineTemplateSerializer -from .models import VirtualMachineTemplate, OpenNebulaManager + +from .serializers import VirtualMachineTemplateSerializer, \ + VirtualMachineSerializer +from .models import VirtualMachineTemplate, VirtualMachine, OpenNebulaManager class TemplateCreateView(generics.ListCreateAPIView): """This class defines the create behavior of our rest api.""" @@ -16,3 +18,18 @@ class TemplateDetailsView(generics.RetrieveUpdateDestroyAPIView): queryset = VirtualMachineTemplate.objects.all() serializer_class = VirtualMachineTemplateSerializer + +class VmCreateView(generics.ListCreateAPIView): + """This class defines the create behavior of our rest api.""" + queryset = VirtualMachine.objects.all() + serializer_class = VirtualMachineSerializer + + def perform_create(self, serializer): + """Save the post data when creating a new template.""" + serializer.save() + +class VmDetailsView(generics.RetrieveUpdateDestroyAPIView): + """This class handles the http GET, PUT and DELETE requests.""" + + queryset = VirtualMachine.objects.all() + serializer_class = VirtualMachineSerializer