205 lines
6.3 KiB
Python
205 lines
6.3 KiB
Python
|
import ipaddress
|
||
|
|
||
|
from builtins import hasattr
|
||
|
from rest_framework import serializers
|
||
|
|
||
|
from oca import OpenNebulaException
|
||
|
|
||
|
from .opennebula_manager 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.username,
|
||
|
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
|