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