uncloud/uncloud/opennebula/management/commands/migrate-one-vm-to-regular.py

140 lines
4.9 KiB
Python

from datetime import datetime
from django.core.management.base import BaseCommand
from django.utils import timezone
from opennebula.models import VM as VMModel
from uncloud_vm.models import VMHost, VMProduct, VMNetworkCard, VMDiskImageProduct, VMDiskProduct
from uncloud_pay.models import Order
def convert_mac_to_int(mac_address: str):
# Remove octet connecting characters
mac_address = mac_address.replace(':', '')
mac_address = mac_address.replace('.', '')
mac_address = mac_address.replace('-', '')
mac_address = mac_address.replace(' ', '')
# Parse the resulting number as hexadecimal
mac_address = int(mac_address, base=16)
return mac_address
def get_vm_price(core, ram, storage, n_of_ipv4, n_of_ipv6):
storage = storage / 10 # Division by 10 because our base storage unit is 10 GB
total = 3 * core + 4 * ram + 3.5 * storage + 8 * n_of_ipv4 + 0 * n_of_ipv6
# TODO: Find some reason about the following magical subtraction.
total -= 8
return total
def create_nics(one_vm, vm_product):
for nic in one_vm.nics:
mac_address = convert_mac_to_int(nic.get('MAC'))
ip_address = nic.get('IP', None) or nic.get('IP6_GLOBAL', None)
VMNetworkCard.objects.update_or_create(
mac_address=mac_address, vm=vm_product, defaults={'ip_address': ip_address}
)
def create_disk_and_image(one_vm, vm_product):
for disk in one_vm.disks:
owner = one_vm.owner
name = disk.get('image')
# TODO: Fix the following hard coded values
is_os_image, is_public, status = True, True, 'active'
image_size_in_gb = disk.get('image_size_in_gb')
disk_size_in_gb = disk.get('size_in_gb')
storage_class = disk.get('pool_name')
image_source = disk.get('source')
image_source_type = disk.get('source_type')
image, _ = VMDiskImageProduct.objects.update_or_create(
name=name,
defaults={
'owner': owner,
'is_os_image': is_os_image,
'is_public': is_public,
'size_in_gb': image_size_in_gb,
'storage_class': storage_class,
'image_source': image_source,
'image_source_type': image_source_type,
'status': status
}
)
VMDiskProduct.objects.update_or_create(
owner=owner, vm=vm_product,
defaults={
'image': image,
'size_in_gb': disk_size_in_gb
}
)
class Command(BaseCommand):
help = 'Migrate Opennebula VM to regular (uncloud) vm'
def handle(self, *args, **options):
for one_vm in VMModel.objects.all():
# Host on which the VM is currently residing
host = VMHost.objects.filter(vms__icontains=one_vm.vmid).first()
# VCPU, RAM, Owner, Status
# TODO: Set actual status instead of hard coded 'active'
vm_id, cores, ram_in_gb = one_vm.vmid, one_vm.cores, one_vm.ram_in_gb
owner, status = one_vm.owner, 'active'
# Total Amount of SSD Storage
# TODO: What would happen if the attached storage is not SSD but HDD?
total_storage_in_gb = sum([disk['size_in_gb'] for disk in one_vm.disks])
# List of IPv4 addresses and Global IPv6 addresses
ipv4, ipv6 = one_vm.ips
# TODO: Insert actual/real creation_date, starting_date, ending_date
# instead of pseudo one we are putting currently
creation_date = starting_date = ending_date = datetime.now(tz=timezone.utc)
# Price calculation
# TODO: Make the following non-hardcoded
one_time_price = 0
recurring_period = 'per_month'
recurring_price = get_vm_price(cores, ram_in_gb, total_storage_in_gb, len(ipv4), len(ipv6))
try:
vm_product = VMProduct.objects.get(vmid=vm_id)
except VMProduct.DoesNotExist:
order = Order.objects.create(
owner=one_vm.owner,
creation_date=creation_date,
starting_date=starting_date,
ending_date=ending_date,
one_time_price=one_time_price,
recurring_price=recurring_price,
recurring_period=recurring_period
)
vm_product, _ = VMProduct.objects.update_or_create(
vmid=vm_id,
defaults={
'cores': cores,
'ram_in_gb': ram_in_gb,
'owner': owner,
'vmhost': host,
'order': order,
'status': status
}
)
# Create VMNetworkCards
create_nics(one_vm, vm_product)
# Create VMDiskImageProduct and VMDiskProduct
create_disk_and_image(one_vm, vm_product)