204 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			204 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import ipaddress
 | 
						|
 | 
						|
from builtins import hasattr
 | 
						|
from rest_framework import serializers
 | 
						|
 | 
						|
from oca import OpenNebulaException
 | 
						|
 | 
						|
from .models import OpenNebulaManager
 | 
						|
 | 
						|
 | 
						|
class VirtualMachineTemplateSerializer(serializers.Serializer):
 | 
						|
    """Serializer to map the virtual machine template instance into JSON format."""
 | 
						|
    id = serializers.IntegerField(read_only=True)
 | 
						|
    name = serializers.SerializerMethodField()
 | 
						|
    cores = serializers.SerializerMethodField()
 | 
						|
    disk_size = serializers.SerializerMethodField()
 | 
						|
    memory = serializers.SerializerMethodField()
 | 
						|
 | 
						|
    def get_cores(self, obj):
 | 
						|
        if hasattr(obj.template, 'vcpu'):
 | 
						|
            return obj.template.vcpu
 | 
						|
 | 
						|
        return ''
 | 
						|
 | 
						|
    def get_disk_size(self, obj):
 | 
						|
        template = obj.template
 | 
						|
        disk_size = 0
 | 
						|
        try:
 | 
						|
            for disk in template.disks:
 | 
						|
                disk_size += int(disk.size)
 | 
						|
            return disk_size / 1024
 | 
						|
        except:
 | 
						|
            return 0
 | 
						|
 | 
						|
    def get_memory(self, obj):
 | 
						|
        return int(obj.template.memory) / 1024
 | 
						|
 | 
						|
    def get_name(self, obj):
 | 
						|
        if obj.name.startswith('public-'):
 | 
						|
            return obj.name.lstrip('public-')
 | 
						|
        else:
 | 
						|
            return obj.name
 | 
						|
 | 
						|
 | 
						|
class VirtualMachineSerializer(serializers.Serializer):
 | 
						|
    """Serializer to map the virtual machine instance into JSON format."""
 | 
						|
 | 
						|
    name = serializers.SerializerMethodField()
 | 
						|
    cores = serializers.IntegerField(source='template.vcpu')
 | 
						|
    disk = serializers.IntegerField(write_only=True)
 | 
						|
    set_memory = serializers.IntegerField(write_only=True, label='Memory')
 | 
						|
    memory = serializers.SerializerMethodField()
 | 
						|
 | 
						|
    disk_size = serializers.SerializerMethodField()
 | 
						|
    hdd_size = serializers.SerializerMethodField()
 | 
						|
    ssd_size = serializers.SerializerMethodField()
 | 
						|
    ipv4 = serializers.SerializerMethodField()
 | 
						|
    ipv6 = serializers.SerializerMethodField()
 | 
						|
    vm_id = serializers.IntegerField(read_only=True, source='id')
 | 
						|
    state = serializers.CharField(read_only=True, source='str_state')
 | 
						|
    price = serializers.SerializerMethodField()
 | 
						|
    ssh_key = serializers.CharField(write_only=True)
 | 
						|
    configuration = serializers.SerializerMethodField()
 | 
						|
 | 
						|
    template_id = serializers.ChoiceField(
 | 
						|
        choices=[(key.id, key.name) for key in
 | 
						|
                 OpenNebulaManager().try_get_templates()
 | 
						|
                 ],
 | 
						|
        source='template.template_id',
 | 
						|
        write_only=True,
 | 
						|
        default=[]
 | 
						|
    )
 | 
						|
 | 
						|
    def create(self, validated_data):
 | 
						|
        owner = validated_data['owner']
 | 
						|
        ssh_key = validated_data['ssh_key']
 | 
						|
        cores = validated_data['template']['vcpu']
 | 
						|
        memory = validated_data['set_memory']
 | 
						|
        disk = validated_data['disk']
 | 
						|
 | 
						|
        template_id = validated_data['template']['template_id']
 | 
						|
        specs = {
 | 
						|
            'cpu': cores,
 | 
						|
            'disk_size': disk,
 | 
						|
            'memory': memory,
 | 
						|
        }
 | 
						|
 | 
						|
        try:
 | 
						|
            manager = OpenNebulaManager(email=owner.email,
 | 
						|
                                        password=owner.password,
 | 
						|
                                        )
 | 
						|
            opennebula_id = manager.create_vm(template_id=template_id,
 | 
						|
                                              ssh_key=ssh_key,
 | 
						|
                                              specs=specs)
 | 
						|
        except OpenNebulaException as err:
 | 
						|
            raise serializers.ValidationError(
 | 
						|
                "OpenNebulaException occured. {0}".format(err)
 | 
						|
            )
 | 
						|
 | 
						|
        return manager.get_vm(opennebula_id)
 | 
						|
 | 
						|
    def get_memory(self, obj):
 | 
						|
        return int(obj.template.memory) / 1024
 | 
						|
 | 
						|
    def get_disk_size(self, obj):
 | 
						|
        template = obj.template
 | 
						|
        disk_size = 0
 | 
						|
        for disk in template.disks:
 | 
						|
            disk_size += int(disk.size)
 | 
						|
        return disk_size / 1024
 | 
						|
 | 
						|
    def get_ssd_size(self, obj):
 | 
						|
        template = obj.template
 | 
						|
        disk_size = 0
 | 
						|
        for disk in template.disks:
 | 
						|
            if disk.datastore == 'cephds':
 | 
						|
                disk_size += int(disk.size)
 | 
						|
        return disk_size / 1024
 | 
						|
 | 
						|
    def get_hdd_size(self, obj):
 | 
						|
        template = obj.template
 | 
						|
        disk_size = 0
 | 
						|
        for disk in template.disks:
 | 
						|
            if disk.datastore == 'ceph_hdd_ds':
 | 
						|
                disk_size += int(disk.size)
 | 
						|
        return disk_size / 1024
 | 
						|
 | 
						|
    def get_price(self, obj):
 | 
						|
        template = obj.template
 | 
						|
        price = float(template.vcpu) * 5.0
 | 
						|
        price += (int(template.memory) / 1024 * 2.0)
 | 
						|
        for disk in template.disks:
 | 
						|
            price += int(disk.size) / 1024 * 0.6
 | 
						|
        return price
 | 
						|
 | 
						|
    def get_configuration(self, obj):
 | 
						|
        template_id = obj.template.template_id
 | 
						|
        template = OpenNebulaManager().get_template(template_id)
 | 
						|
        if template.name.startswith('public-'):
 | 
						|
            return template.name.lstrip('public-')
 | 
						|
        else:
 | 
						|
            return template.name
 | 
						|
 | 
						|
    def get_ipv4(self, obj):
 | 
						|
        """
 | 
						|
        Get the IPv4s from the given VM
 | 
						|
 | 
						|
        :param obj: The VM in contention
 | 
						|
        :return: Returns csv string of all IPv4s added to this VM otherwise returns "-" if no IPv4 is available
 | 
						|
        """
 | 
						|
        ipv4 = []
 | 
						|
        for nic in obj.template.nics:
 | 
						|
            if hasattr(nic, 'ip'):
 | 
						|
                ipv4.append(nic.ip)
 | 
						|
        if len(ipv4) > 0:
 | 
						|
            return ', '.join(ipv4)
 | 
						|
        else:
 | 
						|
            return '-'
 | 
						|
 | 
						|
    def get_ipv6(self, obj):
 | 
						|
        ipv6 = []
 | 
						|
        for nic in obj.template.nics:
 | 
						|
            if hasattr(nic, 'ip6_global'):
 | 
						|
                ipv6.append(nic.ip6_global)
 | 
						|
        if len(ipv6) > 0:
 | 
						|
            return ', '.join(ipv6)
 | 
						|
        else:
 | 
						|
            return '-'
 | 
						|
 | 
						|
    def get_name(self, obj):
 | 
						|
        if obj.name.startswith('public-'):
 | 
						|
            return obj.name.lstrip('public-')
 | 
						|
        else:
 | 
						|
            return obj.name
 | 
						|
 | 
						|
 | 
						|
class VMTemplateSerializer(serializers.Serializer):
 | 
						|
    """Serializer to map the VMTemplate instance into JSON format."""
 | 
						|
    id = serializers.IntegerField(
 | 
						|
        read_only=True, source='opennebula_vm_template_id'
 | 
						|
    )
 | 
						|
    name = serializers.CharField(read_only=True)
 | 
						|
 | 
						|
 | 
						|
def hexstr2int(string):
 | 
						|
    return int(string.replace(':', ''), 16)
 | 
						|
 | 
						|
 | 
						|
FIRST_MAC = hexstr2int('02:00:b3:39:79:4d')
 | 
						|
FIRST_V4 = ipaddress.ip_address('185.203.112.2')
 | 
						|
COUNT = 1000
 | 
						|
 | 
						|
 | 
						|
def v4_from_mac(mac):
 | 
						|
    """Calculates the IPv4 address from a MAC address.
 | 
						|
 | 
						|
    mac: string (the colon-separated representation)
 | 
						|
    returns: ipaddress.ip_address object with the v4 address
 | 
						|
    """
 | 
						|
    return FIRST_V4 + (hexstr2int(mac) - FIRST_MAC)
 | 
						|
 | 
						|
 | 
						|
def is_in_v4_range(mac):
 | 
						|
    return FIRST_MAC <= hexstr2int(mac) < FIRST_MAC + 1000
 |