mirror of
https://github.com/retspen/webvirtcloud
synced 2024-12-25 23:55:24 +00:00
362 lines
11 KiB
Python
362 lines
11 KiB
Python
|
import os
|
||
|
import random
|
||
|
import string
|
||
|
from collections import OrderedDict
|
||
|
|
||
|
from django.conf import settings
|
||
|
from django.contrib.auth.models import User
|
||
|
from django.utils.translation import ugettext_lazy as _
|
||
|
|
||
|
from accounts.models import UserInstance
|
||
|
from appsettings.settings import app_settings
|
||
|
from logs.views import addlogmsg
|
||
|
from vrtManager.connection import connection_manager
|
||
|
from vrtManager.hostdetails import wvmHostDetails
|
||
|
from vrtManager.instance import wvmInstance, wvmInstances
|
||
|
|
||
|
from .models import Instance
|
||
|
|
||
|
|
||
|
def filesizefstr(size_str):
|
||
|
if size_str == '':
|
||
|
return 0
|
||
|
size_str = size_str.upper().replace("B", "")
|
||
|
if size_str[-1] == 'K':
|
||
|
return int(float(size_str[:-1])) << 10
|
||
|
elif size_str[-1] == 'M':
|
||
|
return int(float(size_str[:-1])) << 20
|
||
|
elif size_str[-1] == 'G':
|
||
|
return int(float(size_str[:-1])) << 30
|
||
|
elif size_str[-1] == 'T':
|
||
|
return int(float(size_str[:-1])) << 40
|
||
|
elif size_str[-1] == 'P':
|
||
|
return int(float(size_str[:-1])) << 50
|
||
|
else:
|
||
|
return int(float(size_str))
|
||
|
|
||
|
|
||
|
def get_clone_free_names(size=10):
|
||
|
prefix = app_settings.CLONE_INSTANCE_DEFAULT_PREFIX
|
||
|
free_names = []
|
||
|
existing_names = [i.name for i in Instance.objects.filter(name__startswith=prefix)]
|
||
|
index = 1
|
||
|
while len(free_names) < size:
|
||
|
new_name = prefix + str(index)
|
||
|
if new_name not in existing_names:
|
||
|
free_names.append(new_name)
|
||
|
index += 1
|
||
|
return free_names
|
||
|
|
||
|
|
||
|
def check_user_quota(user, instance, cpu, memory, disk_size):
|
||
|
ua = user.userattributes
|
||
|
msg = ""
|
||
|
|
||
|
if user.is_superuser:
|
||
|
return msg
|
||
|
|
||
|
quota_debug = app_settings.QUOTA_DEBUG
|
||
|
|
||
|
user_instances = UserInstance.objects.filter(user=user, instance__is_template=False)
|
||
|
instance += user_instances.count()
|
||
|
for usr_inst in user_instances:
|
||
|
if connection_manager.host_is_up(
|
||
|
usr_inst.instance.compute.type,
|
||
|
usr_inst.instance.compute.hostname,
|
||
|
):
|
||
|
conn = wvmInstance(
|
||
|
usr_inst.instance.compute.hostname,
|
||
|
usr_inst.instance.compute.login,
|
||
|
usr_inst.instance.compute.password,
|
||
|
usr_inst.instance.compute.type,
|
||
|
usr_inst.instance.name,
|
||
|
)
|
||
|
cpu += int(conn.get_vcpu())
|
||
|
memory += int(conn.get_memory())
|
||
|
for disk in conn.get_disk_devices():
|
||
|
if disk['size']:
|
||
|
disk_size += int(disk['size']) >> 30
|
||
|
|
||
|
if ua.max_instances > 0 and instance > ua.max_instances:
|
||
|
msg = "instance"
|
||
|
if quota_debug:
|
||
|
msg += f" ({instance} > {ua.max_instances})"
|
||
|
if ua.max_cpus > 0 and cpu > ua.max_cpus:
|
||
|
msg = "cpu"
|
||
|
if quota_debug:
|
||
|
msg += f" ({cpu} > {ua.max_cpus})"
|
||
|
if ua.max_memory > 0 and memory > ua.max_memory:
|
||
|
msg = "memory"
|
||
|
if quota_debug:
|
||
|
msg += f" ({memory} > {ua.max_memory})"
|
||
|
if ua.max_disk_size > 0 and disk_size > ua.max_disk_size:
|
||
|
msg = "disk"
|
||
|
if quota_debug:
|
||
|
msg += f" ({disk_size} > {ua.max_disk_size})"
|
||
|
return msg
|
||
|
|
||
|
|
||
|
def get_new_disk_dev(media, disks, bus):
|
||
|
existing_disk_devs = []
|
||
|
existing_media_devs = []
|
||
|
if bus == "virtio":
|
||
|
dev_base = "vd"
|
||
|
elif bus == "ide":
|
||
|
dev_base = "hd"
|
||
|
elif bus == "fdc":
|
||
|
dev_base = "fd"
|
||
|
else:
|
||
|
dev_base = "sd"
|
||
|
|
||
|
if disks:
|
||
|
existing_disk_devs = [disk['dev'] for disk in disks]
|
||
|
|
||
|
# cd-rom bus could be virtio/sata, because of that we should check it also
|
||
|
if media:
|
||
|
existing_media_devs = [m['dev'] for m in media]
|
||
|
|
||
|
for al in string.ascii_lowercase:
|
||
|
dev = dev_base + al
|
||
|
if dev not in existing_disk_devs and dev not in existing_media_devs:
|
||
|
return dev
|
||
|
raise Exception(_('None available device name'))
|
||
|
|
||
|
|
||
|
def get_network_tuple(network_source_str):
|
||
|
network_source_pack = network_source_str.split(":", 1)
|
||
|
if len(network_source_pack) > 1:
|
||
|
return network_source_pack[1], network_source_pack[0]
|
||
|
else:
|
||
|
return network_source_pack[0], 'net'
|
||
|
|
||
|
|
||
|
def migrate_instance(
|
||
|
new_compute,
|
||
|
instance,
|
||
|
user,
|
||
|
live=False,
|
||
|
unsafe=False,
|
||
|
xml_del=False,
|
||
|
offline=False,
|
||
|
autoconverge=False,
|
||
|
compress=False,
|
||
|
postcopy=False,
|
||
|
):
|
||
|
status = connection_manager.host_is_up(new_compute.type, new_compute.hostname)
|
||
|
if not status:
|
||
|
return
|
||
|
if new_compute == instance.compute:
|
||
|
return
|
||
|
try:
|
||
|
conn_migrate = wvmInstances(
|
||
|
new_compute.hostname,
|
||
|
new_compute.login,
|
||
|
new_compute.password,
|
||
|
new_compute.type,
|
||
|
)
|
||
|
|
||
|
autostart = instance.autostart
|
||
|
conn_migrate.moveto(
|
||
|
instance.proxy,
|
||
|
instance.name,
|
||
|
live,
|
||
|
unsafe,
|
||
|
xml_del,
|
||
|
offline,
|
||
|
autoconverge,
|
||
|
compress,
|
||
|
postcopy,
|
||
|
)
|
||
|
|
||
|
conn_new = wvmInstance(
|
||
|
new_compute.hostname,
|
||
|
new_compute.login,
|
||
|
new_compute.password,
|
||
|
new_compute.type,
|
||
|
instance.name,
|
||
|
)
|
||
|
|
||
|
if autostart:
|
||
|
conn_new.set_autostart(1)
|
||
|
finally:
|
||
|
conn_migrate.close()
|
||
|
conn_new.close()
|
||
|
|
||
|
instance.compute = new_compute
|
||
|
instance.save()
|
||
|
|
||
|
|
||
|
def get_hosts_status(computes):
|
||
|
"""
|
||
|
Function return all hosts all vds on host
|
||
|
"""
|
||
|
compute_data = []
|
||
|
for compute in computes:
|
||
|
compute_data.append({
|
||
|
'id': compute.id,
|
||
|
'name': compute.name,
|
||
|
'hostname': compute.hostname,
|
||
|
'status': connection_manager.host_is_up(compute.type, compute.hostname),
|
||
|
'type': compute.type,
|
||
|
'login': compute.login,
|
||
|
'password': compute.password,
|
||
|
'details': compute.details,
|
||
|
})
|
||
|
return compute_data
|
||
|
|
||
|
|
||
|
def get_userinstances_info(instance):
|
||
|
info = {}
|
||
|
uis = UserInstance.objects.filter(instance=instance)
|
||
|
info['count'] = uis.count()
|
||
|
if info['count'] > 0:
|
||
|
info['first_user'] = uis[0]
|
||
|
else:
|
||
|
info['first_user'] = None
|
||
|
return info
|
||
|
|
||
|
|
||
|
def refr(compute):
|
||
|
if compute.status is True:
|
||
|
domains = compute.proxy.wvm.listAllDomains()
|
||
|
domain_names = [d.name() for d in domains]
|
||
|
# Delete instances that're not on host
|
||
|
Instance.objects.filter(compute=compute).exclude(name__in=domain_names).delete()
|
||
|
# Create instances that're not in DB
|
||
|
names = Instance.objects.filter(compute=compute).values_list('name', flat=True)
|
||
|
for domain in domains:
|
||
|
if domain.name() not in names:
|
||
|
Instance(compute=compute, name=domain.name(), uuid=domain.UUIDString()).save()
|
||
|
|
||
|
|
||
|
def refresh_instance_database(comp, inst_name, info, all_host_vms, user):
|
||
|
# Multiple Instance Name Check
|
||
|
instances = Instance.objects.filter(name=inst_name)
|
||
|
if instances.count() > 1:
|
||
|
for i in instances:
|
||
|
user_instances_count = UserInstance.objects.filter(instance=i).count()
|
||
|
if user_instances_count == 0:
|
||
|
addlogmsg(user.username, i.name, _("Deleting due to multiple(Instance Name) records."))
|
||
|
i.delete()
|
||
|
|
||
|
# Multiple UUID Check
|
||
|
instances = Instance.objects.filter(uuid=info['uuid'])
|
||
|
if instances.count() > 1:
|
||
|
for i in instances:
|
||
|
if i.name != inst_name:
|
||
|
addlogmsg(user.username, i.name, _("Deleting due to multiple(UUID) records."))
|
||
|
i.delete()
|
||
|
|
||
|
try:
|
||
|
inst_on_db = Instance.objects.get(compute_id=comp["id"], name=inst_name)
|
||
|
if inst_on_db.uuid != info['uuid']:
|
||
|
inst_on_db.save()
|
||
|
|
||
|
all_host_vms[comp["id"], comp["name"], comp["status"], comp["cpu"], comp["mem_size"],
|
||
|
comp["mem_perc"]][inst_name]['is_template'] = inst_on_db.is_template
|
||
|
all_host_vms[comp["id"], comp["name"], comp["status"], comp["cpu"], comp["mem_size"],
|
||
|
comp["mem_perc"]][inst_name]['userinstances'] = get_userinstances_info(inst_on_db)
|
||
|
except Instance.DoesNotExist:
|
||
|
inst_on_db = Instance(compute_id=comp["id"], name=inst_name, uuid=info['uuid'])
|
||
|
inst_on_db.save()
|
||
|
|
||
|
|
||
|
def get_user_instances(user):
|
||
|
all_user_vms = {}
|
||
|
user_instances = UserInstance.objects.filter(user=user)
|
||
|
for usr_inst in user_instances:
|
||
|
if connection_manager.host_is_up(usr_inst.instance.compute.type, usr_inst.instance.compute.hostname):
|
||
|
conn = wvmHostDetails(
|
||
|
usr_inst.instance.compute.hostname,
|
||
|
usr_inst.instance.compute.login,
|
||
|
usr_inst.instance.compute.password,
|
||
|
usr_inst.instance.compute.type,
|
||
|
)
|
||
|
all_user_vms[usr_inst] = conn.get_user_instances(usr_inst.instance.name)
|
||
|
all_user_vms[usr_inst].update({'compute_id': usr_inst.instance.compute.id})
|
||
|
return all_user_vms
|
||
|
|
||
|
|
||
|
def get_host_instances(compute):
|
||
|
all_host_vms = OrderedDict()
|
||
|
|
||
|
# if compute.status:
|
||
|
comp_node_info = compute.proxy.get_node_info()
|
||
|
comp_mem = compute.proxy.get_memory_usage()
|
||
|
comp_instances = compute.proxy.get_host_instances(True)
|
||
|
|
||
|
# if comp_instances:
|
||
|
comp_info = {
|
||
|
"id": compute.id,
|
||
|
"name": compute.name,
|
||
|
"status": compute.status,
|
||
|
"cpu": comp_node_info[3],
|
||
|
"mem_size": comp_node_info[2],
|
||
|
"mem_perc": comp_mem['percent'],
|
||
|
}
|
||
|
# refr(compute)
|
||
|
all_host_vms[comp_info["id"], comp_info["name"], comp_info["status"], comp_info["cpu"], comp_info["mem_size"],
|
||
|
comp_info["mem_perc"]] = comp_instances
|
||
|
for vm, info in comp_instances.items():
|
||
|
# TODO: Delete this function completely
|
||
|
refresh_instance_database(comp_info, vm, info, all_host_vms, User.objects.get(pk=1))
|
||
|
|
||
|
# else:
|
||
|
# raise libvirtError(_(f"Problem occurred with host: {compute.name} - {status}"))
|
||
|
return all_host_vms
|
||
|
|
||
|
|
||
|
def get_dhcp_mac_address(vname):
|
||
|
dhcp_file = settings.BASE_DIR + '/dhcpd.conf'
|
||
|
mac = ''
|
||
|
if os.path.isfile(dhcp_file):
|
||
|
with open(dhcp_file, 'r') as f:
|
||
|
name_found = False
|
||
|
for line in f:
|
||
|
if "host %s." % vname in line:
|
||
|
name_found = True
|
||
|
if name_found and "hardware ethernet" in line:
|
||
|
mac = line.split(' ')[-1].strip().strip(';')
|
||
|
break
|
||
|
return mac
|
||
|
|
||
|
|
||
|
def get_random_mac_address():
|
||
|
mac = '52:54:00:%02x:%02x:%02x' % (
|
||
|
random.randint(0x00, 0xff),
|
||
|
random.randint(0x00, 0xff),
|
||
|
random.randint(0x00, 0xff),
|
||
|
)
|
||
|
return mac
|
||
|
|
||
|
|
||
|
def get_clone_disk_name(disk, prefix, clone_name=''):
|
||
|
if not disk['image']:
|
||
|
return None
|
||
|
if disk['image'].startswith(prefix) and clone_name:
|
||
|
suffix = disk['image'][len(prefix):]
|
||
|
image = f"{clone_name}{suffix}"
|
||
|
elif "." in disk['image'] and len(disk['image'].rsplit(".", 1)[1]) <= 7:
|
||
|
name, suffix = disk['image'].rsplit(".", 1)
|
||
|
image = f"{name}-clone.{suffix}"
|
||
|
else:
|
||
|
image = f"{disk['image']}-clone"
|
||
|
return image
|
||
|
|
||
|
|
||
|
# TODO: this function is not used
|
||
|
def _get_clone_disks(disks, vname=''):
|
||
|
clone_disks = []
|
||
|
for disk in disks:
|
||
|
new_image = get_clone_disk_name(disk, vname)
|
||
|
if not new_image:
|
||
|
continue
|
||
|
new_disk = {
|
||
|
'dev': disk['dev'],
|
||
|
'storage': disk['storage'],
|
||
|
'image': new_image,
|
||
|
'format': disk['format'],
|
||
|
}
|
||
|
clone_disks.append(new_disk)
|
||
|
return clone_disks
|