2017-05-11 02:05:58 +00:00
|
|
|
import oca
|
2017-05-19 14:39:56 +00:00
|
|
|
import ipaddress
|
2017-05-11 02:05:58 +00:00
|
|
|
|
|
|
|
from rest_framework import serializers
|
|
|
|
|
|
|
|
from oca import OpenNebulaException
|
2017-05-12 10:07:05 +00:00
|
|
|
from oca.template import VmTemplate
|
2017-05-11 02:05:58 +00:00
|
|
|
|
2017-05-12 10:07:05 +00:00
|
|
|
from .models import OpenNebulaManager
|
2017-05-11 02:05:58 +00:00
|
|
|
|
2017-05-12 10:07:05 +00:00
|
|
|
class VirtualMachineTemplateSerializer(serializers.Serializer):
|
2017-05-11 02:05:58 +00:00
|
|
|
"""Serializer to map the virtual machine template instance into JSON format."""
|
2017-05-12 10:07:05 +00:00
|
|
|
id = serializers.IntegerField(read_only=True)
|
2017-05-13 11:47:53 +00:00
|
|
|
name = serializers.SerializerMethodField()
|
2017-05-22 03:01:26 +00:00
|
|
|
cores = serializers.SerializerMethodField()
|
2017-05-12 10:07:05 +00:00
|
|
|
disk_size = serializers.SerializerMethodField()
|
|
|
|
memory = serializers.SerializerMethodField()
|
2017-05-11 02:05:58 +00:00
|
|
|
|
2017-05-22 03:01:26 +00:00
|
|
|
def get_cores(self, obj):
|
|
|
|
if hasattr(obj.template, 'vcpu'):
|
|
|
|
return obj.template.vcpu
|
|
|
|
|
|
|
|
return ''
|
|
|
|
|
2017-05-12 10:07:05 +00:00
|
|
|
def get_disk_size(self, obj):
|
|
|
|
template = obj.template
|
|
|
|
disk_size = 0
|
2017-05-13 23:02:22 +00:00
|
|
|
try:
|
|
|
|
for disk in template.disks:
|
|
|
|
disk_size += int(disk.size)
|
|
|
|
return disk_size / 1024
|
|
|
|
except:
|
|
|
|
return 0
|
2017-05-12 10:07:05 +00:00
|
|
|
|
|
|
|
def get_memory(self, obj):
|
|
|
|
return int(obj.template.memory)/1024
|
|
|
|
|
2017-05-13 11:47:53 +00:00
|
|
|
def get_name(self, obj):
|
2017-05-23 08:36:57 +00:00
|
|
|
return obj.name.strip('public-')
|
2017-05-13 11:47:53 +00:00
|
|
|
|
2017-06-01 22:49:17 +00:00
|
|
|
|
|
|
|
|
2017-05-12 10:07:05 +00:00
|
|
|
class VirtualMachineSerializer(serializers.Serializer):
|
2017-05-11 03:51:30 +00:00
|
|
|
"""Serializer to map the virtual machine instance into JSON format."""
|
|
|
|
|
2017-05-26 21:23:39 +00:00
|
|
|
name = serializers.SerializerMethodField()
|
2017-05-13 13:50:00 +00:00
|
|
|
cores = serializers.IntegerField(source='template.vcpu')
|
|
|
|
disk = serializers.IntegerField(write_only=True)
|
2017-05-13 15:32:55 +00:00
|
|
|
set_memory = serializers.IntegerField(write_only=True, label='Memory')
|
|
|
|
memory = serializers.SerializerMethodField()
|
2017-05-13 13:50:00 +00:00
|
|
|
|
2017-05-12 10:07:05 +00:00
|
|
|
|
|
|
|
disk_size = serializers.SerializerMethodField()
|
2017-05-23 09:30:10 +00:00
|
|
|
ipv4 = serializers.SerializerMethodField()
|
|
|
|
ipv6 = serializers.SerializerMethodField()
|
2017-05-12 10:07:05 +00:00
|
|
|
vm_id = serializers.IntegerField(read_only=True, source='id')
|
|
|
|
state = serializers.CharField(read_only=True, source='str_state')
|
|
|
|
price = serializers.SerializerMethodField()
|
2017-05-13 13:50:00 +00:00
|
|
|
ssh_key = serializers.CharField(write_only=True)
|
2017-05-14 01:41:30 +00:00
|
|
|
configuration = serializers.SerializerMethodField()
|
2017-05-12 10:07:05 +00:00
|
|
|
|
|
|
|
template_id = serializers.ChoiceField(
|
|
|
|
choices=[(key.id, key.name) for key in
|
2017-05-14 10:22:10 +00:00
|
|
|
OpenNebulaManager().try_get_templates()
|
|
|
|
],
|
2017-05-12 10:07:05 +00:00
|
|
|
source='template.template_id',
|
2017-05-14 10:22:10 +00:00
|
|
|
write_only=True,
|
|
|
|
default=[]
|
2017-05-11 03:51:30 +00:00
|
|
|
)
|
|
|
|
|
2017-05-12 10:07:05 +00:00
|
|
|
def create(self, validated_data):
|
|
|
|
owner = validated_data['owner']
|
2017-05-13 13:50:00 +00:00
|
|
|
ssh_key = validated_data['ssh_key']
|
|
|
|
cores = validated_data['template']['vcpu']
|
2017-05-13 15:32:55 +00:00
|
|
|
memory = validated_data['set_memory']
|
2017-05-13 13:50:00 +00:00
|
|
|
disk = validated_data['disk']
|
|
|
|
|
2017-05-12 10:07:05 +00:00
|
|
|
template_id = validated_data['template']['template_id']
|
2017-05-13 13:50:00 +00:00
|
|
|
specs = {
|
|
|
|
'cpu' : cores,
|
|
|
|
'disk_size' : disk,
|
|
|
|
'memory' : memory,
|
|
|
|
}
|
|
|
|
|
2017-05-11 03:51:30 +00:00
|
|
|
|
|
|
|
try:
|
2017-05-11 10:45:09 +00:00
|
|
|
manager = OpenNebulaManager(email=owner.email,
|
2017-05-12 17:13:18 +00:00
|
|
|
password=owner.password,
|
2017-05-13 04:59:57 +00:00
|
|
|
)
|
2017-05-13 13:50:00 +00:00
|
|
|
opennebula_id = manager.create_vm(template_id=template_id,
|
|
|
|
ssh_key=ssh_key,
|
|
|
|
specs=specs)
|
2017-05-11 03:51:30 +00:00
|
|
|
except OpenNebulaException as err:
|
|
|
|
raise serializers.ValidationError("OpenNebulaException occured. {0}".format(err))
|
|
|
|
|
2017-05-12 10:07:05 +00:00
|
|
|
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_price(self, obj):
|
|
|
|
template = obj.template
|
2017-05-14 00:17:48 +00:00
|
|
|
price = float(template.vcpu) * 5.0
|
2017-05-13 23:21:10 +00:00
|
|
|
price += (int(template.memory)/1024 * 2.0)
|
2017-05-12 10:07:05 +00:00
|
|
|
for disk in template.disks:
|
2017-05-13 23:21:10 +00:00
|
|
|
price += int(disk.size)/1024 * 0.6
|
2017-05-12 10:07:05 +00:00
|
|
|
return price
|
2017-05-14 01:41:30 +00:00
|
|
|
def get_configuration(self, obj):
|
|
|
|
template_id = obj.template.template_id
|
|
|
|
template = OpenNebulaManager().get_template(template_id)
|
2017-05-23 16:58:48 +00:00
|
|
|
return template.name.strip('public-')
|
2017-05-19 14:39:56 +00:00
|
|
|
|
2017-05-23 09:30:10 +00:00
|
|
|
def get_ipv4(self, obj):
|
2017-05-19 14:39:56 +00:00
|
|
|
nic = obj.template.nics[0]
|
2017-05-23 09:17:38 +00:00
|
|
|
if 'vm-ipv6-nat64-ipv4' in nic.network and is_in_v4_range(nic.mac):
|
2017-05-19 14:39:56 +00:00
|
|
|
return str(v4_from_mac(nic.mac))
|
|
|
|
else:
|
|
|
|
return '-'
|
|
|
|
|
2017-05-23 09:30:10 +00:00
|
|
|
def get_ipv6(self, obj):
|
|
|
|
nic = obj.template.nics[0]
|
|
|
|
return nic.ip6_global
|
2017-05-19 14:39:56 +00:00
|
|
|
|
2017-05-26 21:23:39 +00:00
|
|
|
def get_name(self, obj):
|
|
|
|
return obj.name.strip('public-')
|
2017-05-19 14:39:56 +00:00
|
|
|
|
|
|
|
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
|