init commit

This commit is contained in:
ahmadbilalkhalid 2020-03-03 23:46:39 +05:00
parent 531bfa1768
commit fea0568bb9
10 changed files with 318 additions and 6 deletions

View file

@ -0,0 +1,107 @@
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 get_vm_price(core, ram, storage, n_of_ipv4, n_of_ipv6):
storage = storage / 10
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 = nic.get('MAC')
ip_address = nic.get('IP', None) or nic.get('IP6_GLOBAL', None)
mac_address = mac_address.replace(':', '')
mac_address = mac_address.replace('.', '')
mac_address = mac_address.replace('-', '')
mac_address = mac_address.replace(' ', '')
mac_address = int(mac_address, base=16)
VMNetworkCard.objects.create(
mac_address=mac_address, vm=vm_product, 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 = True
is_public = True
status = '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.create(
owner=owner, name=name, 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
)
vm_disk = VMDiskProduct.objects.create(
owner=owner, vm=vm_product, image=image, size_in_gb=disk_size_in_gb
)
class Command(BaseCommand):
help = 'Migrate Opennebula VM to regular (uncloud) vm'
def add_arguments(self, parser):
pass
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'
cores, ram_in_gb, owner, status = one_vm.cores, one_vm.ram_in_gb, 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
order = Order.objects.create(
owner=one_vm.owner,
creation_date=datetime.now(tz=timezone.utc),
starting_date=datetime.now(tz=timezone.utc),
ending_date=datetime.now(tz=timezone.utc),
one_time_price=0,
recurring_price=get_vm_price(cores, ram_in_gb, total_storage_in_gb, len(ipv4), len(ipv6)),
recurring_period='per_month'
)
vm_product = VMProduct.objects.create(
cores=cores, ram_in_gb=ram_in_gb,
owner=one_vm.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)

View file

@ -0,0 +1,74 @@
import json
import uncloud.secrets as secrets
from xmlrpc.client import ServerProxy as RPCClient
from django.core.management.base import BaseCommand
from xmltodict import parse
from enum import IntEnum
from opennebula.models import VM as VMModel
from uncloud_vm.models import VMHost
from django_auth_ldap.backend import LDAPBackend
class HostStates(IntEnum):
"""
The following flags are copied from
https://docs.opennebula.org/5.8/integration/system_interfaces/api.html#schemas-for-host
"""
INIT = 0 # Initial state for enabled hosts
MONITORING_MONITORED = 1 # Monitoring the host (from monitored)
MONITORED = 2 # The host has been successfully monitored
ERROR = 3 # An error ocurrer while monitoring the host
DISABLED = 4 # The host is disabled
MONITORING_ERROR = 5 # Monitoring the host (from error)
MONITORING_INIT = 6 # Monitoring the host (from init)
MONITORING_DISABLED = 7 # Monitoring the host (from disabled)
OFFLINE = 8 # The host is totally offline
class Command(BaseCommand):
help = 'Syncronize Host information from OpenNebula'
def add_arguments(self, parser):
pass
def handle(self, *args, **options):
with RPCClient(secrets.OPENNEBULA_URL) as rpc_client:
success, response, *_ = rpc_client.one.hostpool.info(secrets.OPENNEBULA_USER_PASS)
if success:
response = json.loads(json.dumps(parse(response)))
host_pool = response.get('HOST_POOL', {}).get('HOST', {})
for host in host_pool:
host_share = host.get('HOST_SHARE', {})
host_name = host.get('NAME')
state = int(host.get('STATE', HostStates.OFFLINE.value))
if state == HostStates.MONITORED:
status = 'active'
elif state == HostStates.DISABLED:
status = 'disabled'
else:
status = 'unusable'
usable_cores = host_share.get('TOTAL_CPU')
usable_ram_in_kb = int(host_share.get('TOTAL_MEM', 0))
usable_ram_in_gb = int(usable_ram_in_kb / 2 ** 20)
vms = host.get('VMS', {}) or {}
vms = vms.get('ID', []) or []
vms = ','.join(vms)
VMHost.objects.update_or_create(
hostname=host_name,
defaults={
'usable_cores': usable_cores,
'usable_ram_in_gb': usable_ram_in_gb,
'status': status,
'vms': vms
}
)
else:
print(response)

View file

@ -6,7 +6,6 @@ import uncloud.secrets as secrets
from xmlrpc.client import ServerProxy as RPCClient from xmlrpc.client import ServerProxy as RPCClient
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.contrib.auth import get_user_model
from xmltodict import parse from xmltodict import parse
from opennebula.models import VM as VMModel from opennebula.models import VM as VMModel
@ -31,7 +30,7 @@ class Command(BaseCommand):
backend = LDAPBackend() backend = LDAPBackend()
for vm in vms: for i, vm in enumerate(vms):
vm_id = vm['ID'] vm_id = vm['ID']
vm_owner = vm['UNAME'] vm_owner = vm['UNAME']

View file

@ -35,15 +35,21 @@ class VM(models.Model):
if 'DISK' in self.data['TEMPLATE']: if 'DISK' in self.data['TEMPLATE']:
if type(self.data['TEMPLATE']['DISK']) is dict: if type(self.data['TEMPLATE']['DISK']) is dict:
disks = [ self.data['TEMPLATE']['DISK'] ] disks = [self.data['TEMPLATE']['DISK']]
else: else:
disks = self.data['TEMPLATE']['DISK'] disks = self.data['TEMPLATE']['DISK']
disks = [ disks = [
{ {
'size_in_gb': int(d['SIZE'])/1024. , 'size_in_gb': int(d['SIZE'])/1024.0,
'opennebula_source': d['SOURCE'], 'opennebula_source': d['SOURCE'],
'opennebula_name': d['IMAGE'], 'opennebula_name': d['IMAGE'],
'image_size_in_gb': int(d['ORIGINAL_SIZE'])/1024.0,
'pool_name': d['POOL_NAME'],
'image': d['IMAGE'],
'source': d['SOURCE'],
'source_type': d['TM_MAD']
} }
for d in disks for d in disks
] ]
@ -57,3 +63,22 @@ class VM(models.Model):
@property @property
def graphics(self): def graphics(self):
return self.data.get('TEMPLATE', {}).get('GRAPHICS', {}) return self.data.get('TEMPLATE', {}).get('GRAPHICS', {})
@property
def nics(self):
_nics = self.data.get('TEMPLATE', {}).get('NIC', {})
if isinstance(_nics, dict):
_nics = [_nics]
return _nics
@property
def ips(self):
ipv4, ipv6 = [], []
for nic in self.nics:
ip = nic.get('IP')
ip6 = nic.get('IP6_GLOBAL')
if ip:
ipv4.append(ip)
if ip6:
ipv6.append(ip6)
return ipv4, ipv6

View file

@ -0,0 +1,23 @@
# Generated by Django 3.0.3 on 2020-03-03 09:27
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('uncloud_vm', '0008_auto_20200229_1611'),
]
operations = [
migrations.AddField(
model_name='vmhost',
name='vms',
field=models.TextField(default=''),
),
migrations.AlterField(
model_name='vmdiskproduct',
name='size_in_gb',
field=models.FloatField(blank=True),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 3.0.3 on 2020-03-03 12:08
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('uncloud_vm', '0009_auto_20200303_0927'),
]
operations = [
migrations.AlterField(
model_name='vmnetworkcard',
name='mac_address',
field=models.BigIntegerField(),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 3.0.3 on 2020-03-03 18:33
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('uncloud_vm', '0010_auto_20200303_1208'),
]
operations = [
migrations.AddField(
model_name='vmdiskimageproduct',
name='source_type',
field=models.CharField(max_length=128, null=True),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 3.0.3 on 2020-03-03 18:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('uncloud_vm', '0011_vmdiskimageproduct_source_type'),
]
operations = [
migrations.AddField(
model_name='vmdiskimageproduct',
name='source',
field=models.CharField(max_length=128, null=True),
),
]

View file

@ -0,0 +1,23 @@
# Generated by Django 3.0.3 on 2020-03-03 18:45
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('uncloud_vm', '0012_vmdiskimageproduct_source'),
]
operations = [
migrations.RenameField(
model_name='vmdiskimageproduct',
old_name='source',
new_name='image_source',
),
migrations.RenameField(
model_name='vmdiskimageproduct',
old_name='source_type',
new_name='image_source_type',
),
]

View file

@ -39,6 +39,12 @@ class VMHost(models.Model):
max_length=32, choices=STATUS_CHOICES, default=STATUS_DEFAULT max_length=32, choices=STATUS_CHOICES, default=STATUS_DEFAULT
) )
# List of VMs running on this host
vms = models.TextField(default='')
def get_vms(self):
return self.vms.split(',')
class VMProduct(Product): class VMProduct(Product):
vmhost = models.ForeignKey( vmhost = models.ForeignKey(
@ -74,7 +80,8 @@ class VMDiskImageProduct(models.Model):
size_in_gb = models.FloatField(null=True, blank=True) size_in_gb = models.FloatField(null=True, blank=True)
import_url = models.URLField(null=True, blank=True) import_url = models.URLField(null=True, blank=True)
image_source = models.CharField(max_length=128, null=True)
image_source_type = models.CharField(max_length=128, null=True)
storage_class = models.CharField( storage_class = models.CharField(
max_length=32, max_length=32,
choices=( choices=(
@ -127,7 +134,7 @@ class VMDiskProduct(models.Model):
class VMNetworkCard(models.Model): class VMNetworkCard(models.Model):
vm = models.ForeignKey(VMProduct, on_delete=models.CASCADE) vm = models.ForeignKey(VMProduct, on_delete=models.CASCADE)
mac_address = models.IntegerField() mac_address = models.BigIntegerField()
ip_address = models.GenericIPAddressField(blank=True, ip_address = models.GenericIPAddressField(blank=True,
null=True) null=True)