From 25e6381fc90be918a9ca5a09e5dfa8e4ae981e68 Mon Sep 17 00:00:00 2001 From: catborise Date: Fri, 28 Sep 2018 13:33:21 +0300 Subject: [PATCH] add Compute instances tab. Minimal invasion. minimal change. keep structure --- accounts/templates/login.html | 2 +- computes/templates/overview.html | 3 + computes/urls.py | 27 +- instances/templates/allinstances.html | 184 ++++++++ ...d.html => allinstances_index_grouped.html} | 0 ...tml => allinstances_index_nongrouped.html} | 0 instances/templates/instances.html | 253 ++++++----- instances/urls.py | 1 + instances/views.py | 429 ++++++++++-------- interfaces/templates/interface.html | 3 + interfaces/templates/interfaces.html | 3 + networks/templates/network.html | 3 + networks/templates/networks.html | 3 + nwfilters/templates/nwfilter.html | 3 + nwfilters/templates/nwfilters.html | 3 + secrets/templates/secrets.html | 3 + storages/templates/storage.html | 3 + storages/templates/storages.html | 3 + templates/navbar.html | 2 +- webvirtcloud/settings.py.template | 3 +- webvirtcloud/urls.py | 22 +- 21 files changed, 618 insertions(+), 335 deletions(-) create mode 100644 instances/templates/allinstances.html rename instances/templates/{instances_grouped.html => allinstances_index_grouped.html} (100%) rename instances/templates/{instances_nongrouped.html => allinstances_index_nongrouped.html} (100%) diff --git a/accounts/templates/login.html b/accounts/templates/login.html index c3ca001..c55a07a 100644 --- a/accounts/templates/login.html +++ b/accounts/templates/login.html @@ -17,7 +17,7 @@

{% trans "Sign In" %}

- + diff --git a/computes/templates/overview.html b/computes/templates/overview.html index 89251cc..88f6f2f 100644 --- a/computes/templates/overview.html +++ b/computes/templates/overview.html @@ -11,6 +11,9 @@
  • {% trans "Overview" %}
  • +
  • + {% trans "Instances" %} +
  • {% trans "Storages" %}
  • diff --git a/computes/urls.py b/computes/urls.py index 58a0497..352b156 100644 --- a/computes/urls.py +++ b/computes/urls.py @@ -1,9 +1,26 @@ from django.conf.urls import url -from . import views +from storages.views import storages, storage +from networks.views import networks, network +from secrets.views import secrets +from create.views import create_instance +from interfaces.views import interfaces, interface +from computes.views import overview, compute_graph, computes +from instances.views import instances +from nwfilters.views import nwfilter, nwfilters urlpatterns = [ - url(r'^$', views.computes, name='computes'), - url(r'^overview/(?P[0-9]+)/$', views.overview, name='overview'), - url(r'^statistics/(?P[0-9]+)/$', - views.compute_graph, name='compute_graph'), + url(r'^/', computes, name='computes'), + url(r'^(?P[0-9]+)/$', overview, name='overview'), + url(r'^(?P[0-9]+)/statistics$', compute_graph, name='compute_graph'), + url(r'^(?P[0-9]+)/instances/$', instances, name='instances'), + url(r'^(?P[0-9]+)/storages/$', storages, name='storages'), + url(r'^(?P[0-9]+)/storage/(?P[\w\-\.\/]+)/$', storage, name='storage'), + url(r'^(?P[0-9]+)/networks/$', networks, name='networks'), + url(r'^(?P[0-9]+)/network/(?P[\w\-\.]+)/$', network, name='network'), + url(r'^(?P[0-9]+)/interfaces/$', interfaces, name='interfaces'), + url(r'^(?P[0-9]+)/interface/(?P[\w\-\.\:]+)/$', interface, name='interface'), + url(r'^(?P[0-9]+)/nwfilters/$', nwfilters, name='nwfilters'), + url(r'^(?P[0-9]+)/nwfilter/(?P[\w\-\.\:]+)/$', nwfilter, name='nwfilter'), + url(r'^(?P[0-9]+)/secrets/$', secrets, name='secrets'), + url(r'^(?P[0-9]+)/create/$', create_instance, name='create_instance'), ] diff --git a/instances/templates/allinstances.html b/instances/templates/allinstances.html new file mode 100644 index 0000000..6f5cf3c --- /dev/null +++ b/instances/templates/allinstances.html @@ -0,0 +1,184 @@ +{% extends "base.html" %} +{% load i18n %} +{% load staticfiles %} +{% block title %}{% trans "Instances" %}{% endblock %} +{% block style %} + +{% endblock %} +{% block content %} + +
    +
    + {% if request.user.is_superuser %} + {% include 'create_inst_block.html' %} + {% endif %} + {% if all_host_vms or all_user_vms %} + + {% endif %} +

    {% trans "Instances" %}

    +
    +
    + + + {% include 'errors_block.html' %} + +
    +
    +
    + {% if request.user.is_superuser %} + {% if not all_host_vms %} +
    +
    + + {% trans "Warning:" %} {% trans "You don't have any Instance" %} +
    +
    + {% else %} + {% ifequal view_style "nongrouped" %} + {% include 'allinstances_index_nongrouped.html' %} + {% endifequal %} + {% ifequal view_style "grouped" %} + {% include 'allinstances_index_grouped.html' %} + {% endifequal %} + {% endif %} + {% else %} + {% if not all_user_vms %} +
    +
    + + {% trans "Warning:" %} {% trans "You don't have any Instance" %} +
    +
    + {% else %} + + + + + + + + + + + + {% for inst, vm in all_user_vms.items %} + + + + + + + + {% endfor %} + +
    NameStatusVCPUMemoryActions
    {{ vm.name }}
    {{ vm.title }}
    {% ifequal vm.status 1 %} + {% trans "Active" %} + {% endifequal %} + {% ifequal vm.status 5 %} + {% trans "Off" %} + {% endifequal %} + {% ifequal vm.status 3 %} + {% trans "Suspend" %} + {% endifequal %} + {{ vm.vcpu }}{{ vm.memory }} {% trans "MB" %}
    {% csrf_token %} + + + {% ifequal vm.status 5 %} + {% if inst.instance.is_template %} + + {% else %} + + {% endif %} + + + + {% endifequal %} + {% ifequal vm.status 3 %} + + + + + {% endifequal %} + {% ifequal vm.status 1 %} + + + + + + + {% endifequal %} +
    +
    + {% endif %} + {% endif %} +
    +
    +
    +{% endblock %} +{% block script %} + + + + +{% if request.user.is_superuser %} + +{% endif %} +{% endblock %} diff --git a/instances/templates/instances_grouped.html b/instances/templates/allinstances_index_grouped.html similarity index 100% rename from instances/templates/instances_grouped.html rename to instances/templates/allinstances_index_grouped.html diff --git a/instances/templates/instances_nongrouped.html b/instances/templates/allinstances_index_nongrouped.html similarity index 100% rename from instances/templates/instances_nongrouped.html rename to instances/templates/allinstances_index_nongrouped.html diff --git a/instances/templates/instances.html b/instances/templates/instances.html index 6750603..7edb9da 100644 --- a/instances/templates/instances.html +++ b/instances/templates/instances.html @@ -1,12 +1,12 @@ {% extends "base.html" %} {% load i18n %} {% load staticfiles %} -{% block title %}{% trans "Instances" %}{% endblock %} +{% block title %}{% trans "Instances" %} - {{ compute.name }}{% endblock %} {% block style %} {% endblock %} {% block content %} - +
    {% if request.user.is_superuser %} @@ -17,129 +17,144 @@
    {% endif %} -

    {% trans "Instances" %}

    +

    {{ compute.name }}

    - +
    +
    - {% include 'errors_block.html' %} + +
    +
    + -
    + {% include 'errors_block.html' %} +
    + {% if not all_host_vms %}
    -
    - {% if request.user.is_superuser %} - {% if not all_host_vms %} -
    -
    - - {% trans "Warning:" %} {% trans "You don't have any Instance" %} -
    -
    - {% else %} - {% ifequal view_style "nongrouped" %} - {% include 'instances_nongrouped.html' %} - {% endifequal %} - {% ifequal view_style "grouped" %} - {% include 'instances_grouped.html' %} - {% endifequal %} - {% endif %} - {% else %} - {% if not all_user_vms %} -
    -
    - - {% trans "Warning:" %} {% trans "You don't have any Instance" %} -
    -
    - {% else %} - - - - - - - - - - - - {% for inst, vm in all_user_vms.items %} - - - - - - - - {% endfor %} - -
    NameStatusVCPUMemoryActions
    {{ vm.name }}
    {{ vm.title }}
    {% ifequal vm.status 1 %} - {% trans "Active" %} - {% endifequal %} - {% ifequal vm.status 5 %} - {% trans "Off" %} - {% endifequal %} - {% ifequal vm.status 3 %} - {% trans "Suspend" %} - {% endifequal %} - {{ vm.vcpu }}{{ vm.memory }} {% trans "MB" %}
    {% csrf_token %} - - - {% ifequal vm.status 5 %} - {% if inst.instance.is_template %} - - {% else %} - - {% endif %} - - - - {% endifequal %} - {% ifequal vm.status 3 %} - - - - - {% endifequal %} - {% ifequal vm.status 1 %} - - - - - - - {% endifequal %} -
    -
    - {% endif %} - {% endif %} +
    + + {% trans "Warning:" %} {% trans "Hypervisor doesn't have any instances" %}
    -
    + {% else %} +
    + + + + + + + + + + + + + {% for host, inst in all_host_vms.items %} + {% for vm, info in inst.items %} + + + + + + + + + {% endfor %} + {% endfor %} + +
    Name
    Description
    Host
    User
    StatusVCPUMemoryActions
    {{ vm }}
    {{ info.title }}
    {{ host.1 }}
    {% if info.userinstances.count > 0 %}{{ info.userinstances.first_user.user.username }}{% if info.userinstances.count > 1 %} (+{{ info.userinstances.count|add:"-1" }}){% endif %}{% endif %}
    + {% ifequal info.status 1 %}{% trans "Active" %}{% endifequal %} + {% ifequal info.status 5 %}{% trans "Off" %}{% endifequal %} + {% ifequal info.status 3 %}{% trans "Suspend" %}{% endifequal %} + {{ info.vcpu }}{{ info.memory|filesizeformat }}
    {% csrf_token %} + + + {% ifequal info.status 5 %} + {% if info.is_template %} + + {% else %} + + {% endif %} + + + + + {% endifequal %} + {% ifequal info.status 3 %} + + + + + + {% endifequal %} + {% ifequal info.status 1 %} + + + + + + + + {% endifequal %} +
    +
    +
    + {% endif %} +
    {% endblock %} {% block script %} @@ -181,4 +196,4 @@ } {% endif %} -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/instances/urls.py b/instances/urls.py index 93ac0c4..1054ed1 100644 --- a/instances/urls.py +++ b/instances/urls.py @@ -2,6 +2,7 @@ from django.conf.urls import url from . import views urlpatterns = [ + url(r'^$', views.allinstances, name='allinstances'), url(r'^(?P[0-9]+)/(?P[\w\-\.]+)/$', views.instance, name='instance'), url(r'^statistics/(?P[0-9]+)/(?P[\w\-\.]+)/$', views.inst_graph, name='inst_graph'), url(r'^status/(?P[0-9]+)/(?P[\w\-\.]+)/$', views.inst_status, name='inst_status'), diff --git a/instances/views.py b/instances/views.py index 70fb9bf..188b8e5 100644 --- a/instances/views.py +++ b/instances/views.py @@ -26,175 +26,72 @@ 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')) + return HttpResponseRedirect(reverse('allinstances')) @login_required -def instances(request): +def allinstances(request): + """ + INSTANCES LIST FOR ALL HOSTS + :param request: + :return: + """ + all_host_vms = {} + error_messages = [] + computes = Compute.objects.all().order_by("name") + + if not request.user.is_superuser: + all_user_vms = get_user_instances(request) + else: + for comp in computes: + try: + all_host_vms.update(get_host_instances(request,comp)) + except libvirtError as lib_err: + error_messages.append(lib_err) + + if request.method == 'POST': + try: + instances_actions(request) + 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, 'allinstances.html', locals()) + + +@login_required +def instances(request, compute_id): """ :param request: :return: """ error_messages = [] - all_host_vms = {} - all_user_vms = {} - computes = Compute.objects.all().order_by("name") + compute = get_object_or_404(Compute, pk=compute_id) - 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}) + all_user_vms = get_user_instances(request) 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) + try: + all_host_vms = get_host_instances(request, compute) + 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()) - + instances_actions(request) 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()) @@ -206,7 +103,7 @@ def instance(request, compute_id, vname): """ error_messages = [] - #messages = [] + # messages = [] compute = get_object_or_404(Compute, pk=compute_id) computes = Compute.objects.all().order_by('name') computes_count = computes.count() @@ -217,8 +114,8 @@ def instance(request, compute_id, vname): 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) + instance__name=vname, + user__id=request.user.id) except UserInstance.DoesNotExist: userinstance = None @@ -231,15 +128,15 @@ def instance(request, compute_id, vname): 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 + return long(float(size_str[:-1])) << 10 elif 'M' == size_str[-1]: - return long(float(size_str[:-1]))<<20 + return long(float(size_str[:-1])) << 20 elif 'G' == size_str[-1]: - return long(float(size_str[:-1]))<<30 + return long(float(size_str[:-1])) << 30 elif 'T' == size_str[-1]: - return long(float(size_str[:-1]))<<40 + return long(float(size_str[:-1])) << 40 elif 'P' == size_str[-1]: - return long(float(size_str[:-1]))<<50 + return long(float(size_str[:-1])) << 50 else: return long(float(size_str)) @@ -268,16 +165,16 @@ def instance(request, compute_id, vname): 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) + 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 - + disk_size += int(disk['size']) >> 30 + if ua.max_instances > 0 and instance > ua.max_instances: msg = "instance" if settings.QUOTA_DEBUG: @@ -301,7 +198,7 @@ def instance(request, compute_id, vname): dev_base = "vd" else: dev_base = "sd" - existing_devs = [ disk['dev'] for disk in disks ] + existing_devs = [disk['dev'] for disk in disks] for l in string.lowercase: dev = dev_base + l if dev not in existing_devs: @@ -379,7 +276,7 @@ def instance(request, compute_id, vname): console_port = conn.get_console_port() console_keymap = conn.get_console_keymap() console_listen_address = conn.get_console_listen_addr() - snapshots = sorted(conn.get_snapshot(), reverse=True, key=lambda k:k['date']) + 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() console_passwd = conn.get_console_passwd() @@ -453,7 +350,8 @@ def instance(request, compute_id, vname): instance.delete() try: - del_userinstance = UserInstance.objects.filter(instance__compute_id=compute_id, instance__name=vname) + del_userinstance = UserInstance.objects.filter(instance__compute_id=compute_id, + instance__name=vname) del_userinstance.delete() except UserInstance.DoesNotExist: pass @@ -507,7 +405,8 @@ def instance(request, compute_id, vname): msg = _("Please shutdown 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): + 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', '') @@ -521,13 +420,13 @@ def instance(request, compute_id, vname): 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): + 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: + 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: @@ -542,9 +441,9 @@ def instance(request, compute_id, vname): if 'addvolume' in request.POST and (request.user.is_superuser or userinstance.is_change): connCreate = wvmCreate(compute.hostname, - compute.login, - compute.password, - compute.type) + compute.login, + compute.password, + compute.type) storage = request.POST.get('storage', '') name = request.POST.get('name', '') format = request.POST.get('format', default_format) @@ -553,7 +452,7 @@ def instance(request, compute_id, vname): bus = request.POST.get('bus', default_bus) cache = request.POST.get('cache', default_cache) target = get_new_disk_dev(disks, bus) - + path = connCreate.create_volume(storage, name, size, format, meta_prealloc, default_owner) conn.attach_disk(path, target, subdriver=format, cache=cache, targetbus=bus) msg = _('Attach new disk') @@ -670,7 +569,7 @@ def instance(request, compute_id, vname): 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) @@ -705,7 +604,8 @@ def instance(request, compute_id, vname): conn.change_network(network_data) addlogmsg(request.user.username, instance.name, msg) - if conn.get_status() != 5: messages.success(request, _("Network Devices are changed. Please reboot instance to activate.")) + msg = _("Network Devices are changed. Please reboot instance to activate.") + if conn.get_status() != 5: messages.success(request, msg) return HttpResponseRedirect(request.get_full_path() + '#network') if 'add_network' in request.POST: @@ -717,7 +617,9 @@ def instance(request, compute_id, vname): conn.add_network(mac, source, source_type, nwfilter=nwfilter) addlogmsg(request.user.username, instance.name, msg) - if conn.get_status() != 5: messages.success(request, _("Network Device is added. Please reboot instance to activate.")) + msg = _("Network Device is added. Please reboot instance to activate.") + if conn.get_status() != 5: messages.success(request, msg) + return HttpResponseRedirect(request.get_full_path() + '#network') if 'delete_network' in request.POST: @@ -726,17 +628,18 @@ def instance(request, compute_id, vname): conn.delete_network(mac_address) addlogmsg(request.user.username, instance.name, msg) - if conn.get_status() != 5: messages.success(request, _("Network Device is deleted. Please reboot instance to activate.")) + msg = _("Network Device is deleted. Please reboot instance to activate.") + if conn.get_status() != 5: 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) @@ -755,19 +658,18 @@ def instance(request, compute_id, vname): 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]) + 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 clone_instance_auto_name and not clone_data['name']: auto_vname = clone_free_names[0] clone_data['name'] = auto_vname @@ -776,7 +678,7 @@ def instance(request, compute_id, vname): disk_dev = "disk-{}".format(disk['dev']) disk_name = get_clone_disk_name(disk, vname, auto_vname) clone_data[disk_dev] = disk_name - + 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) @@ -786,14 +688,16 @@ def instance(request, compute_id, vname): 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): + 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 = UserInstance(instance_id=new_instance.id, user_id=request.user.id, + is_delete=True) userinstance.save() msg = _("Clone of '%s'" % instance.name) @@ -801,18 +705,19 @@ def instance(request, compute_id, vname): if settings.CLONE_INSTANCE_AUTO_MIGRATE: new_compute = Compute.objects.order_by('?').first() migrate_instance(new_compute, new_instance, xml_del=True, offline=True) - return HttpResponseRedirect(reverse('instance', args=[new_instance.compute.id, new_instance.name])) + return HttpResponseRedirect( + reverse('instance', args=[new_instance.compute.id, new_instance.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') @@ -851,6 +756,154 @@ def inst_status(request, compute_id, vname): return response +def get_host_instances(request,comp): + + def refresh_instance_database(comp, inst_name, info): + 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 + + 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(request.user.username, i.name, _("Deleting due to multiple 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() + + all_host_vms = {} + status = connection_manager.host_is_up(comp.type, comp.hostname) + + if status: + + 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() + + return all_host_vms + +def get_user_instances(request): + all_user_vms = {} + 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}) + return all_user_vms + + +def instances_actions(request): + name = request.POST.get('name', '') + compute_id = request.POST.get('compute_id', '') + instance = Instance.objects.get(compute_id=compute_id, name=name) + + 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()) + + @login_required def inst_graph(request, compute_id, vname): """ diff --git a/interfaces/templates/interface.html b/interfaces/templates/interface.html index 014a44e..5c5c2b5 100644 --- a/interfaces/templates/interface.html +++ b/interfaces/templates/interface.html @@ -10,6 +10,9 @@
  • {% trans "Overview" %}
  • +
  • + {% trans "Instances" %} +
  • {% trans "Storages" %}
  • diff --git a/interfaces/templates/interfaces.html b/interfaces/templates/interfaces.html index 58d4978..8305b88 100644 --- a/interfaces/templates/interfaces.html +++ b/interfaces/templates/interfaces.html @@ -12,6 +12,9 @@
  • {% trans "Overview" %}
  • +
  • + {% trans "Instances" %} +
  • {% trans "Storages" %}
  • diff --git a/networks/templates/network.html b/networks/templates/network.html index e3b0275..6fa0c2e 100644 --- a/networks/templates/network.html +++ b/networks/templates/network.html @@ -10,6 +10,9 @@
  • {% trans "Overview" %}
  • +
  • + {% trans "Instances" %} +
  • {% trans "Storages" %}
  • diff --git a/networks/templates/networks.html b/networks/templates/networks.html index 2acc1f3..b57f7c6 100644 --- a/networks/templates/networks.html +++ b/networks/templates/networks.html @@ -11,6 +11,9 @@
  • {% trans "Overview" %}
  • +
  • + {% trans "Instances" %} +
  • {% trans "Storages" %}
  • diff --git a/nwfilters/templates/nwfilter.html b/nwfilters/templates/nwfilter.html index 9f97831..377190d 100644 --- a/nwfilters/templates/nwfilter.html +++ b/nwfilters/templates/nwfilter.html @@ -12,6 +12,9 @@
  • {% trans "Overview" %}
  • +
  • + {% trans "Instances" %} +
  • {% trans "Storages" %}
  • diff --git a/nwfilters/templates/nwfilters.html b/nwfilters/templates/nwfilters.html index e237380..dba8377 100644 --- a/nwfilters/templates/nwfilters.html +++ b/nwfilters/templates/nwfilters.html @@ -12,6 +12,9 @@
  • {% trans "Overview" %}
  • +
  • + {% trans "Instances" %} +
  • {% trans "Storages" %}
  • diff --git a/secrets/templates/secrets.html b/secrets/templates/secrets.html index 07b104a..7f781ce 100644 --- a/secrets/templates/secrets.html +++ b/secrets/templates/secrets.html @@ -15,6 +15,9 @@
  • {% trans "Overview" %}
  • +
  • + {% trans "Instances" %} +
  • {% trans "Storages" %}
  • diff --git a/storages/templates/storage.html b/storages/templates/storage.html index 4d3c706..17ed99c 100644 --- a/storages/templates/storage.html +++ b/storages/templates/storage.html @@ -16,6 +16,9 @@
  • {% trans "Overview" %}
  • +
  • + {% trans "Instances" %} +
  • {% trans "Storages" %}
  • diff --git a/storages/templates/storages.html b/storages/templates/storages.html index 026fe13..7529842 100644 --- a/storages/templates/storages.html +++ b/storages/templates/storages.html @@ -11,6 +11,9 @@
  • {% trans "Overview" %}
  • +
  • + {% trans "Instances" %} +
  • {% trans "Storages" %}
  • diff --git a/templates/navbar.html b/templates/navbar.html index 6b69be4..1a1263b 100644 --- a/templates/navbar.html +++ b/templates/navbar.html @@ -15,7 +15,7 @@