1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2024-12-24 23:25:24 +00:00
webvirtcloud/instances/views.py

1039 lines
44 KiB
Python

import os
import time
import json
import socket
import crypt
import re
import string
import random
from bisect import insort
from django.http import HttpResponse, HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.shortcuts import render, get_object_or_404
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.decorators import login_required
from computes.models import Compute
from instances.models import Instance
from django.contrib.auth.models import User
from accounts.models import UserInstance, UserSSHKey
from vrtManager.hostdetails import wvmHostDetails
from vrtManager.instance import wvmInstance, wvmInstances
from vrtManager.connection import connection_manager
from vrtManager.create import wvmCreate
from vrtManager.util import randomPasswd
from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE
from logs.views import addlogmsg
from django.conf import settings
from django.contrib import messages
@login_required
def index(request):
"""
:param request:
:return:
"""
return HttpResponseRedirect(reverse('instances'))
@login_required
def instances(request):
"""
:param request:
:return:
"""
error_messages = []
all_host_vms = {}
all_user_vms = {}
computes = Compute.objects.all().order_by("name")
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 refresh_instance_database(comp, vm, info):
instances = Instance.objects.filter(name=vm)
if instances.count() > 1:
for i in instances:
user_instances_count = UserInstance.objects.filter(instance=i).count()
if user_instances_count == 0:
addlogmsg(request.user.username, i.name, _("Deleting due to multiple records."))
i.delete()
try:
check_uuid = Instance.objects.get(compute_id=comp["id"], name=vm)
if check_uuid.uuid != info['uuid']:
check_uuid.save()
all_host_vms[comp["id"],
comp["name"],
comp["status"],
comp["cpu"],
comp["mem_size"],
comp["mem_perc"]][vm]['is_template'] = check_uuid.is_template
all_host_vms[comp["id"],
comp["name"],
comp["status"],
comp["cpu"],
comp["mem_size"],
comp["mem_perc"]][vm]['userinstances'] = get_userinstances_info(check_uuid)
except Instance.DoesNotExist:
check_uuid = Instance(compute_id=comp["id"], name=vm, uuid=info['uuid'])
check_uuid.save()
if not request.user.is_superuser:
user_instances = UserInstance.objects.filter(user_id=request.user.id)
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,
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})
else:
for comp in computes:
status = connection_manager.host_is_up(comp.type, comp.hostname)
if status:
try:
conn = wvmHostDetails(comp, comp.login, comp.password, comp.type)
comp_node_info = conn.get_node_info()
comp_mem = conn.get_memory_usage()
comp_instances = conn.get_host_instances(True)
if comp_instances:
comp_info= {
"id": comp.id,
"name": comp.name,
"status": status,
"cpu": comp_node_info[3],
"mem_size": comp_node_info[2],
"mem_perc": comp_mem['percent']
}
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():
refresh_instance_database(comp_info, vm, info)
conn.close()
except libvirtError as lib_err:
error_messages.append(lib_err)
if request.method == 'POST':
name = request.POST.get('name', '')
compute_id = request.POST.get('compute_id', '')
instance = Instance.objects.get(compute_id=compute_id, name=name)
try:
conn = wvmInstances(instance.compute.hostname,
instance.compute.login,
instance.compute.password,
instance.compute.type)
if 'poweron' in request.POST:
msg = _("Power On")
addlogmsg(request.user.username, instance.name, msg)
conn.start(name)
return HttpResponseRedirect(request.get_full_path())
if 'poweroff' in request.POST:
msg = _("Power Off")
addlogmsg(request.user.username, instance.name, msg)
conn.shutdown(name)
return HttpResponseRedirect(request.get_full_path())
if 'powercycle' in request.POST:
msg = _("Power Cycle")
conn.force_shutdown(name)
conn.start(name)
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path())
if 'getvvfile' in request.POST:
msg = _("Send console.vv file")
addlogmsg(request.user.username, instance.name, msg)
response = HttpResponse(content='', content_type='application/x-virt-viewer', status=200, reason=None, charset='utf-8')
response.writelines('[virt-viewer]\n')
response.writelines('type=' + conn.graphics_type(name) + '\n')
response.writelines('host=' + conn.graphics_listen(name) + '\n')
response.writelines('port=' + conn.graphics_port(name) + '\n')
response.writelines('title=' + conn.domain_name(name) + '\n')
response.writelines('password=' + conn.graphics_passwd(name) + '\n')
response.writelines('enable-usbredir=1\n')
response.writelines('disable-effects=all\n')
response.writelines('secure-attention=ctrl+alt+ins\n')
response.writelines('release-cursor=ctrl+alt\n')
response.writelines('fullscreen=1\n')
response.writelines('delete-this-file=1\n')
response['Content-Disposition'] = 'attachment; filename="console.vv"'
return response
if request.user.is_superuser:
if 'suspend' in request.POST:
msg = _("Suspend")
addlogmsg(request.user.username, instance.name, msg)
conn.suspend(name)
return HttpResponseRedirect(request.get_full_path())
if 'resume' in request.POST:
msg = _("Resume")
addlogmsg(request.user.username, instance.name, msg)
conn.resume(name)
return HttpResponseRedirect(request.get_full_path())
except libvirtError as lib_err:
error_messages.append(lib_err)
addlogmsg(request.user.username, instance.name, lib_err.message)
view_style = settings.VIEW_INSTANCES_LIST_STYLE
return render(request, 'instances.html', locals())
@login_required
def instance(request, compute_id, vname):
"""
:param request:
:return:
"""
error_messages = []
#messages = []
compute = get_object_or_404(Compute, pk=compute_id)
computes = Compute.objects.all().order_by('name')
computes_count = computes.count()
users = User.objects.all().order_by('username')
publickeys = UserSSHKey.objects.filter(user_id=request.user.id)
keymaps = settings.QEMU_KEYMAPS
console_types = settings.QEMU_CONSOLE_TYPES
console_listen_addresses = settings.QEMU_CONSOLE_LISTEN_ADDRESSES
try:
userinstance = UserInstance.objects.get(instance__compute_id=compute_id,
instance__name=vname,
user__id=request.user.id)
except UserInstance.DoesNotExist:
userinstance = None
if not request.user.is_superuser:
if not userinstance:
return HttpResponseRedirect(reverse('index'))
def show_clone_disk(disks, vname=''):
clone_disk = []
for disk in disks:
if disk['image'] is None:
continue
if disk['image'].count("-") and disk['image'].rsplit("-", 1)[0] == vname:
name, suffix = disk['image'].rsplit("-", 1)
image = name + "-clone" + "-" + suffix
elif disk['image'].count(".") and len(disk['image'].rsplit(".", 1)[1]) <= 7:
name, suffix = disk['image'].rsplit(".", 1)
image = name + "-clone" + "." + suffix
else:
image = disk['image'] + "-clone"
clone_disk.append(
{'dev': disk['dev'], 'storage': disk['storage'],
'image': image, 'format': disk['format']})
return clone_disk
def filesizefstr(size_str):
if size_str == '':
return 0
size_str = size_str.encode('ascii', 'ignore').upper().translate(None, " B")
if 'K' == size_str[-1]:
return long(float(size_str[:-1]))<<10
elif 'M' == size_str[-1]:
return long(float(size_str[:-1]))<<20
elif 'G' == size_str[-1]:
return long(float(size_str[:-1]))<<30
elif 'T' == size_str[-1]:
return long(float(size_str[:-1]))<<40
elif 'P' == size_str[-1]:
return long(float(size_str[:-1]))<<50
else:
return long(float(size_str))
def get_clone_free_names(size=10):
prefix = 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(instance, cpu, memory, disk_size):
user_instances = UserInstance.objects.filter(user_id=request.user.id, 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,
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_device():
if disk['size']:
disk_size += int(disk['size'])>>30
ua = request.user.userattributes
msg = ""
if ua.max_instances > 0 and instance > ua.max_instances:
msg = "instance"
if settings.QUOTA_DEBUG:
msg += " (%s > %s)" % (instance, ua.max_instances)
if ua.max_cpus > 0 and cpu > ua.max_cpus:
msg = "cpu"
if settings.QUOTA_DEBUG:
msg += " (%s > %s)" % (cpu, ua.max_cpus)
if ua.max_memory > 0 and memory > ua.max_memory:
msg = "memory"
if settings.QUOTA_DEBUG:
msg += " (%s > %s)" % (memory, ua.max_memory)
if ua.max_disk_size > 0 and disk_size > ua.max_disk_size:
msg = "disk"
if settings.QUOTA_DEBUG:
msg += " (%s > %s)" % (disk_size, ua.max_disk_size)
return msg
def get_new_disk_dev(disks, bus):
if bus == "virtio":
dev_base = "vd"
else:
dev_base = "sd"
existing_devs = [ disk['dev'] for disk in disks ]
for l in string.lowercase:
dev = dev_base + l
if dev not in existing_devs:
return dev
raise Exception(_('None available device name'))
try:
conn = wvmInstance(compute.hostname,
compute.login,
compute.password,
compute.type,
vname)
compute_networks = sorted(conn.get_networks())
status = conn.get_status()
autostart = conn.get_autostart()
vcpu = conn.get_vcpu()
cur_vcpu = conn.get_cur_vcpu()
uuid = conn.get_uuid()
memory = conn.get_memory()
cur_memory = conn.get_cur_memory()
title = conn.get_title()
description = conn.get_description()
disks = conn.get_disk_device()
media = conn.get_media_device()
networks = conn.get_net_device()
if len(media) != 0:
media_iso = sorted(conn.get_iso_media())
else:
media_iso = []
vcpu_range = conn.get_max_cpus()
memory_range = [256, 512, 768, 1024, 2048, 4096, 6144, 8192, 16384]
if memory not in memory_range:
insort(memory_range, memory)
if cur_memory not in memory_range:
insort(memory_range, cur_memory)
memory_host = conn.get_max_memory()
vcpu_host = len(vcpu_range)
telnet_port = conn.get_telnet_port()
console_type = conn.get_console_type()
console_port = conn.get_console_port()
console_keymap = conn.get_console_keymap()
snapshots = sorted(conn.get_snapshot(), reverse=True, key=lambda k:k['date'])
inst_xml = conn._XMLDesc(VIR_DOMAIN_XML_SECURE)
has_managed_save_image = conn.get_managed_save_image()
clone_disks = show_clone_disk(disks, vname)
console_passwd = conn.get_console_passwd()
clone_free_names = get_clone_free_names()
user_quota_msg = check_user_quota(0, 0, 0, 0)
storages = sorted(conn.get_storages())
cache_modes = sorted(conn.get_cache_modes().items())
default_cache = settings.INSTANCE_VOLUME_DEFAULT_CACHE
default_format = settings.INSTANCE_VOLUME_DEFAULT_FORMAT
formats = conn.get_image_formats()
busses = conn.get_busses()
default_bus = settings.INSTANCE_VOLUME_DEFAULT_BUS
show_access_root_password = settings.SHOW_ACCESS_ROOT_PASSWORD
show_access_ssh_keys = settings.SHOW_ACCESS_SSH_KEYS
try:
instance = Instance.objects.get(compute_id=compute_id, name=vname)
if instance.uuid != uuid:
instance.uuid = uuid
instance.save()
except Instance.DoesNotExist:
instance = Instance(compute_id=compute_id, name=vname, uuid=uuid)
instance.save()
userinstances = UserInstance.objects.filter(instance=instance).order_by('user__username')
if request.method == 'POST':
if 'poweron' in request.POST:
conn.start()
msg = _("Power On")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#poweron')
if 'powercycle' in request.POST:
conn.force_shutdown()
conn.start()
msg = _("Power Cycle")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#powercycle')
if 'poweroff' in request.POST:
conn.shutdown()
msg = _("Power Off")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#poweroff')
if 'powerforce' in request.POST:
conn.force_shutdown()
msg = _("Force Off")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#powerforce')
if 'delete' in request.POST and (request.user.is_superuser or userinstance.is_delete):
if conn.get_status() == 1:
conn.force_shutdown()
if request.POST.get('delete_disk', ''):
for snap in snapshots:
conn.snapshot_delete(snap['name'])
conn.delete_disk()
conn.delete()
instance = Instance.objects.get(compute_id=compute_id, name=vname)
instance_name = instance.name
instance.delete()
try:
del_userinstance = UserInstance.objects.filter(instance__compute_id=compute_id, instance__name=vname)
del_userinstance.delete()
except UserInstance.DoesNotExist:
pass
msg = _("Destroy")
addlogmsg(request.user.username, instance_name, msg)
return HttpResponseRedirect(reverse('instances'))
if 'rootpasswd' in request.POST:
passwd = request.POST.get('passwd', '')
passwd_hash = crypt.crypt(passwd, '$6$kgPoiREy')
data = {'action': 'password', 'passwd': passwd_hash, 'vname': vname}
if conn.get_status() == 5:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((compute.hostname, 16510))
s.send(json.dumps(data))
result = json.loads(s.recv(1024))
s.close()
msg = _("Reset root password")
addlogmsg(request.user.username, instance.name, msg)
if result['return'] == 'success':
messages.success(request, msg)
else:
error_messages.append(msg)
else:
msg = _("Please shutdow down your instance and then try again")
error_messages.append(msg)
if 'addpublickey' in request.POST:
sshkeyid = request.POST.get('sshkeyid', '')
publickey = UserSSHKey.objects.get(id=sshkeyid)
data = {'action': 'publickey', 'key': publickey.keypublic, 'vname': vname}
if conn.get_status() == 5:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((compute.hostname, 16510))
s.send(json.dumps(data))
result = json.loads(s.recv(1024))
s.close()
msg = _("Installed new ssh public key %s" % publickey.keyname)
addlogmsg(request.user.username, instance.name, msg)
if result['return'] == 'success':
messages.success(request, msg)
else:
error_messages.append(msg)
else:
msg = _("Please shutdow down your instance and then try again")
error_messages.append(msg)
if 'resize' in request.POST and (request.user.is_superuser or request.user.is_staff or userinstance.is_change):
new_vcpu = request.POST.get('vcpu', '')
new_cur_vcpu = request.POST.get('cur_vcpu', '')
new_memory = request.POST.get('memory', '')
new_memory_custom = request.POST.get('memory_custom', '')
if new_memory_custom:
new_memory = new_memory_custom
new_cur_memory = request.POST.get('cur_memory', '')
new_cur_memory_custom = request.POST.get('cur_memory_custom', '')
if new_cur_memory_custom:
new_cur_memory = new_cur_memory_custom
disks_new = []
for disk in disks:
input_disk_size = filesizefstr(request.POST.get('disk_size_' + disk['dev'], ''))
if input_disk_size > disk['size']+(64<<20):
disk['size_new'] = input_disk_size
disks_new.append(disk)
disk_sum = sum([disk['size']>>30 for disk in disks_new])
disk_new_sum = sum([disk['size_new']>>30 for disk in disks_new])
quota_msg = check_user_quota(0, int(new_vcpu)-vcpu, int(new_memory)-memory, disk_new_sum-disk_sum)
if not request.user.is_superuser and quota_msg:
msg = _("User %s quota reached, cannot resize '%s'!" % (quota_msg, instance.name))
error_messages.append(msg)
else:
cur_memory = new_cur_memory
memory = new_memory
cur_vcpu = new_cur_vcpu
vcpu = new_vcpu
conn.resize(cur_memory, memory, cur_vcpu, vcpu, disks_new)
msg = _("Resize")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#resize')
if 'addvolume' in request.POST and (request.user.is_superuser or userinstance.is_change):
connCreate = wvmCreate(compute.hostname,
compute.login,
compute.password,
compute.type)
storage = request.POST.get('storage', '')
name = request.POST.get('name', '')
format = request.POST.get('format', '')
size = request.POST.get('size', 0)
meta_prealloc = request.POST.get('meta_prealloc', False)
bus = request.POST.get('bus', '')
cache = request.POST.get('cache', '')
target = get_new_disk_dev(disks, bus)
path = connCreate.create_volume(storage, name, size, format, meta_prealloc)
conn.attach_disk(path, target, subdriver=format, cache=cache, targetbus=bus)
msg = _('Attach new disk')
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#resize')
if 'umount_iso' in request.POST:
image = request.POST.get('path', '')
dev = request.POST.get('umount_iso', '')
conn.umount_iso(dev, image)
msg = _("Mount media")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#media')
if 'mount_iso' in request.POST:
image = request.POST.get('media', '')
dev = request.POST.get('mount_iso', '')
conn.mount_iso(dev, image)
msg = _("Umount media")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#media')
if 'snapshot' in request.POST:
name = request.POST.get('name', '')
conn.create_snapshot(name)
msg = _("New snapshot")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#restoresnapshot')
if 'delete_snapshot' in request.POST:
snap_name = request.POST.get('name', '')
conn.snapshot_delete(snap_name)
msg = _("Delete snapshot")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#restoresnapshot')
if 'revert_snapshot' in request.POST:
snap_name = request.POST.get('name', '')
conn.snapshot_revert(snap_name)
msg = _("Successful revert snapshot: ")
msg += snap_name
messages.success(request, msg)
msg = _("Revert snapshot")
addlogmsg(request.user.username, instance.name, msg)
if request.user.is_superuser:
if 'suspend' in request.POST:
conn.suspend()
msg = _("Suspend")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#resume')
if 'resume' in request.POST:
conn.resume()
msg = _("Resume")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#suspend')
if 'set_autostart' in request.POST:
conn.set_autostart(1)
msg = _("Set autostart")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#autostart')
if 'unset_autostart' in request.POST:
conn.set_autostart(0)
msg = _("Unset autostart")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#autostart')
if 'change_xml' in request.POST:
exit_xml = request.POST.get('inst_xml', '')
if exit_xml:
conn._defineXML(exit_xml)
msg = _("Edit XML")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#xmledit')
if request.user.is_superuser or userinstance.is_vnc:
if 'set_console_passwd' in request.POST:
if request.POST.get('auto_pass', ''):
passwd = randomPasswd()
else:
passwd = request.POST.get('console_passwd', '')
clear = request.POST.get('clear_pass', False)
if clear:
passwd = ''
if not passwd and not clear:
msg = _("Enter the console password or select Generate")
error_messages.append(msg)
if not error_messages:
if not conn.set_console_passwd(passwd):
msg = _("Error setting console password. You should check that your instance have an graphic device.")
error_messages.append(msg)
else:
msg = _("Set VNC password")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#vncsettings')
if 'set_console_keymap' in request.POST:
keymap = request.POST.get('console_keymap', '')
clear = request.POST.get('clear_keymap', False)
if clear:
conn.set_console_keymap('')
else:
conn.set_console_keymap(keymap)
msg = _("Set VNC keymap")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#vncsettings')
if 'set_console_type' in request.POST:
console_type = request.POST.get('console_type', '')
conn.set_console_type(console_type)
msg = _("Set VNC type")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#vncsettings')
if 'set_console_listen_address' in request.POST:
console_type = request.POST.get('console_listen_address', '')
conn.set_console_listen_addr(console_type)
msg = _("Set VNC listen address")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#vncsettings')
if request.user.is_superuser:
if 'migrate' in request.POST:
compute_id = request.POST.get('compute_id', '')
live = request.POST.get('live_migrate', False)
unsafe = request.POST.get('unsafe_migrate', False)
xml_del = request.POST.get('xml_delete', False)
offline = request.POST.get('offline_migrate', False)
new_compute = Compute.objects.get(id=compute_id)
conn_migrate = wvmInstances(new_compute.hostname,
new_compute.login,
new_compute.password,
new_compute.type)
conn_migrate.moveto(conn, vname, live, unsafe, xml_del, offline)
instance.compute = new_compute
instance.save()
conn_migrate.close()
if autostart:
conn_new = wvmInstance(new_compute.hostname,
new_compute.login,
new_compute.password,
new_compute.type,
vname)
conn_new.set_autostart(1)
conn_new.close()
msg = _("Migrate to %s" % new_compute.hostname)
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(reverse('instance', args=[compute_id, vname]))
if 'change_network' in request.POST:
network_data = {}
for post in request.POST:
if post.startswith('net-'):
network_data[post] = request.POST.get(post, '')
conn.change_network(network_data)
msg = _("Edit network")
addlogmsg(request.user.username, instance.name, msg)
msg = _("Network Devices are changed. Please reboot instance to activate.")
messages.success(request, msg)
return HttpResponseRedirect(request.get_full_path() + '#network')
if 'add_owner' in request.POST:
user_id = int(request.POST.get('user_id', ''))
if settings.ALLOW_INSTANCE_MULTIPLE_OWNER:
check_inst = UserInstance.objects.filter(instance=instance, user_id=user_id)
else:
check_inst = UserInstance.objects.filter(instance=instance)
if check_inst:
msg = _("Owner already added")
error_messages.append(msg)
else:
add_user_inst = UserInstance(instance=instance, user_id=user_id)
add_user_inst.save()
msg = _("Added owner %d" % user_id)
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#users')
if 'del_owner' in request.POST:
userinstance_id = int(request.POST.get('userinstance', ''))
userinstance = UserInstance.objects.get(pk=userinstance_id)
userinstance.delete()
msg = _("Deleted owner %d" % userinstance_id)
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#users')
if request.user.is_superuser or request.user.userattributes.can_clone_instances:
if 'clone' in request.POST:
clone_data = {}
clone_data['name'] = request.POST.get('name', '')
disk_sum = sum([disk['size']>>30 for disk in disks])
quota_msg = check_user_quota(1, vcpu, memory, disk_sum)
check_instance = Instance.objects.filter(name=clone_data['name'])
for post in request.POST:
clone_data[post] = request.POST.get(post, '').strip()
if not request.user.is_superuser and quota_msg:
msg = _("User %s quota reached, cannot create '%s'!" % (quota_msg, clone_data['name']))
error_messages.append(msg)
elif check_instance:
msg = _("Instance '%s' already exists!" % clone_data['name'])
error_messages.append(msg)
elif not re.match(r'^[a-zA-Z0-9-]+$', clone_data['name']):
msg = _("Instance name '%s' contains invalid characters!" % clone_data['name'])
error_messages.append(msg)
elif not re.match(r'^([0-9A-F]{2})(\:?[0-9A-F]{2}){5}$', clone_data['clone-net-mac-0'], re.IGNORECASE):
msg = _("Instance mac '%s' invalid format!" % clone_data['clone-net-mac-0'])
error_messages.append(msg)
else:
new_uuid = conn.clone_instance(clone_data)
new_instance = Instance(compute_id=compute_id, name=clone_data['name'], uuid=new_uuid)
new_instance.save()
userinstance = UserInstance(instance_id=new_instance.id, user_id=request.user.id, is_delete=True)
userinstance.save()
msg = _("Clone of '%s'" % instance.name)
addlogmsg(request.user.username, new_instance.name, msg)
return HttpResponseRedirect(reverse('instance', args=[compute_id, clone_data['name']]))
if 'change_options' in request.POST:
instance.is_template = request.POST.get('is_template', False)
instance.save()
options = {}
for post in request.POST:
if post in ['title', 'description']:
options[post] = request.POST.get(post, '')
conn.set_options(options)
msg = _("Edit options")
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#options')
conn.close()
except libvirtError as lib_err:
error_messages.append(lib_err.message)
addlogmsg(request.user.username, vname, lib_err.message)
return render(request, 'instance.html', locals())
@login_required
def inst_status(request, compute_id, vname):
"""
:param request:
:return:
"""
compute = get_object_or_404(Compute, pk=compute_id)
response = HttpResponse()
response['Content-Type'] = "text/javascript"
try:
conn = wvmInstance(compute.hostname,
compute.login,
compute.password,
compute.type,
vname)
data = json.dumps({'status': conn.get_status()})
conn.close()
except libvirtError:
data = json.dumps({'error': 'Error 500'})
response.write(data)
return response
@login_required
def inst_graph(request, compute_id, vname):
"""
:param request:
:return:
"""
datasets = {}
json_blk = []
datasets_blk = {}
json_net = []
datasets_net = {}
cookies = {}
points = 5
curent_time = time.strftime("%H:%M:%S")
compute = get_object_or_404(Compute, pk=compute_id)
response = HttpResponse()
response['Content-Type'] = "text/javascript"
def check_points(dataset):
if len(dataset) > points:
dataset.pop(0)
return dataset
try:
conn = wvmInstance(compute.hostname,
compute.login,
compute.password,
compute.type,
vname)
cpu_usage = conn.cpu_usage()
blk_usage = conn.disk_usage()
net_usage = conn.net_usage()
conn.close()
try:
cookies['cpu'] = request.COOKIES['cpu']
cookies['blk'] = request.COOKIES['blk']
cookies['net'] = request.COOKIES['net']
cookies['timer'] = request.COOKIES['timer']
except KeyError:
cookies['cpu'] = None
cookies['blk'] = None
cookies['net'] = None
if not cookies['cpu']:
datasets['cpu'] = [0] * points
datasets['timer'] = [0] * points
else:
datasets['cpu'] = eval(cookies['cpu'])
datasets['timer'] = eval(cookies['timer'])
datasets['timer'].append(curent_time)
datasets['cpu'].append(int(cpu_usage['cpu']))
datasets['timer'] = check_points(datasets['timer'])
datasets['cpu'] = check_points(datasets['cpu'])
for blk in blk_usage:
if not cookies['blk']:
datasets_wr = [0] * points
datasets_rd = [0] * points
else:
datasets['blk'] = eval(cookies['blk'])
datasets_rd = datasets['blk'][blk['dev']][0]
datasets_wr = datasets['blk'][blk['dev']][1]
datasets_rd.append(int(blk['rd']) / 1048576)
datasets_wr.append(int(blk['wr']) / 1048576)
datasets_rd = check_points(datasets_rd)
datasets_wr = check_points(datasets_wr)
json_blk.append({'dev': blk['dev'], 'data': [datasets_rd, datasets_wr]})
datasets_blk[blk['dev']] = [datasets_rd, datasets_wr]
for net in net_usage:
if not cookies['net']:
datasets_rx = [0] * points
datasets_tx = [0] * points
else:
datasets['net'] = eval(cookies['net'])
datasets_rx = datasets['net'][net['dev']][0]
datasets_tx = datasets['net'][net['dev']][1]
datasets_rx.append(int(net['rx']) / 1048576)
datasets_tx.append(int(net['tx']) / 1048576)
datasets_rx = check_points(datasets_rx)
datasets_tx = check_points(datasets_tx)
json_net.append({'dev': net['dev'], 'data': [datasets_rx, datasets_tx]})
datasets_net[net['dev']] = [datasets_rx, datasets_tx]
data = json.dumps({'cpudata': datasets['cpu'], 'blkdata': json_blk,
'netdata': json_net, 'timeline': datasets['timer']})
response.cookies['cpu'] = datasets['cpu']
response.cookies['timer'] = datasets['timer']
response.cookies['blk'] = datasets_blk
response.cookies['net'] = datasets_net
except libvirtError:
data = json.dumps({'error': 'Error 500'})
response.write(data)
return response
def _get_dhcp_mac_address(vname):
dhcp_file = '/srv/webvirtcloud/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
@login_required
def guess_mac_address(request, vname):
data = { 'vname': vname }
mac = _get_dhcp_mac_address(vname)
if not mac:
mac = _get_random_mac_address()
data['mac'] = mac
return HttpResponse(json.dumps(data))
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
@login_required
def random_mac_address(request):
data = {}
data['mac'] = _get_random_mac_address()
return HttpResponse(json.dumps(data))
@login_required
def guess_clone_name(request):
dhcp_file = '/srv/webvirtcloud/dhcpd.conf'
prefix = settings.CLONE_INSTANCE_DEFAULT_PREFIX
if os.path.isfile(dhcp_file):
instance_names = [i.name for i in Instance.objects.filter(name__startswith=prefix)]
with open(dhcp_file, 'r') as f:
for line in f:
line = line.strip()
if "host %s" % prefix in line:
fqdn = line.split(' ')[1]
hostname = fqdn.split('.')[0]
if hostname.startswith(prefix) and hostname not in instance_names:
return HttpResponse(json.dumps({'name': hostname}))
return HttpResponse(json.dumps({}))
@login_required
def check_instance(request, vname):
check_instance = Instance.objects.filter(name=vname)
data = { 'vname': vname, 'exists': False }
if check_instance:
data['exists'] = True
return HttpResponse(json.dumps(data))
def sshkeys(request, vname):
"""
:param request:
:param vm:
:return:
"""
instance_keys = []
userinstances = UserInstance.objects.filter(instance__name=vname)
for ui in userinstances:
keys = UserSSHKey.objects.filter(user=ui.user)
for k in keys:
instance_keys.append(k.keypublic)
if request.GET.get('plain', ''):
response = '\n'.join(instance_keys)
response += '\n'
else:
response = json.dumps(instance_keys)
return HttpResponse(response)
def delete_instance(instance, delete_disk=False):
compute = instance.compute
instance_name = instance.name
try:
conn = wvmInstance(compute.hostname,
compute.login,
compute.password,
compute.type,
instance.name)
del_userinstance = UserInstance.objects.filter(instance=instance)
if del_userinstance:
print("Deleting UserInstances")
print(del_userinstance)
del_userinstance.delete()
if conn.get_status() == 1:
print("Forcing shutdown")
conn.force_shutdown()
if delete_disk:
snapshots = sorted(conn.get_snapshot(), reverse=True, key=lambda k:k['date'])
for snap in snapshots:
print("Deleting snapshot {}".format(snap['name']))
conn.snapshot_delete(snap['name'])
print("Deleting disks")
conn.delete_disk()
conn.delete()
instance.delete()
print("Instance {} on compute {} sucessfully deleted".format(instance_name, compute.hostname))
except libvirtError as lib_err:
print("Error removing instance {} on compute {}".format(instance_name, compute.hostname))
raise lib_err