diff --git a/instances/templates/instance.html b/instances/templates/instance.html index 00ab3bb..5b6d3cd 100644 --- a/instances/templates/instance.html +++ b/instances/templates/instance.html @@ -363,10 +363,11 @@
{% if request.user.is_superuser or request.user.is_staff or userinstance.is_change %} + {% if status == 5 or not vcpus %}
{% csrf_token %}

{% trans "Logical host CPUs" %} : {{ vcpu_host }}

- +
{% for cpu in vcpu_range %} @@ -396,6 +397,28 @@ {% endifequal %} +
+ {% else %} +

{% trans "Logical Instance Active/Maximum CPUs" %} : {{ cur_vcpu }} / {{ vcpu }}

+
+
+ {% for id, vcpu in vcpus.items %} +
{% csrf_token %} +
+ + {% if vcpu.enabled == 'yes' and vcpu.hotpluggable == "yes" %} + + {% elif vcpu.enabled == 'yes' and vcpu.hotpluggable == "no" %} + + {% else %} + + {% endif %} +
+
+ {% endfor %} +
+
+ {% endif %} {% else %} {% trans "You don't have permission for resizing instance" %} @@ -1358,6 +1381,30 @@
+
+

{% trans "To set instance vCPUs hotpluggable" %}

+
{% csrf_token %} +
+ +
+
+ + + {% if status == 5 %} + + {% else %} + + {% endif %} + +
+
+
+
+
+
{% endif %}
diff --git a/instances/views.py b/instances/views.py index 51246ce..019234a 100644 --- a/instances/views.py +++ b/instances/views.py @@ -26,6 +26,7 @@ from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE from logs.views import addlogmsg from django.conf import settings from django.contrib import messages +from collections import OrderedDict @login_required @@ -44,7 +45,7 @@ def allinstances(request): :param request: :return: """ - all_host_vms = {} + all_host_vms = OrderedDict() error_messages = [] computes = Compute.objects.all().order_by("name") @@ -76,7 +77,7 @@ def instances(request, compute_id): :param compute_id :return: """ - all_host_vms = {} + all_host_vms = OrderedDict() error_messages = [] compute = get_object_or_404(Compute, pk=compute_id) @@ -266,6 +267,7 @@ def instance(request, compute_id, vname): boot_order = conn.get_bootorder() vcpu = conn.get_vcpu() cur_vcpu = conn.get_cur_vcpu() + vcpus = conn.get_vcpus() uuid = conn.get_uuid() memory = conn.get_memory() cur_memory = conn.get_cur_memory() @@ -668,6 +670,29 @@ def instance(request, compute_id, vname): addlogmsg(request.user.username, instance.name, msg) return HttpResponseRedirect(request.get_full_path() + '#suspend') + if 'set_vcpu' in request.POST: + id = request.POST.get('id', '') + enabled = request.POST.get('set_vcpu', '') + if enabled == 'True': + conn.set_vcpu(id, 1) + else: + conn.set_vcpu(id, 0) + msg = _("vCPU {} is enabled={}".format(id, enabled)) + messages.success(request, msg) + addlogmsg(request.user.username, instance.name, msg) + return HttpResponseRedirect(request.get_full_path() + '#resize') + + if 'set_vcpu_hotplug' in request.POST: + status = request.POST.get('vcpu_hotplug', '') + msg = _("vCPU Hot-plug is enabled={}".format(status)) + try: + conn.set_vcpu_hotplug(eval(status)) + except libvirtError as lib_err: + messages.error(request, lib_err.message) + messages.success(request, msg) + addlogmsg(request.user.username, instance.name, msg) + return HttpResponseRedirect(request.get_full_path() + '#resize') + if 'set_autostart' in request.POST: conn.set_autostart(1) msg = _("Set autostart") @@ -1036,7 +1061,7 @@ def get_host_instances(request, comp): inst_on_db = Instance(compute_id=comp["id"], name=inst_name, uuid=info['uuid']) inst_on_db.save() - all_host_vms = {} + all_host_vms = OrderedDict() status = connection_manager.host_is_up(comp.type, comp.hostname) if status is True: diff --git a/vrtManager/instance.py b/vrtManager/instance.py index 9fe7d67..08ab9c2 100644 --- a/vrtManager/instance.py +++ b/vrtManager/instance.py @@ -5,10 +5,12 @@ try: VIR_DOMAIN_AFFECT_LIVE, VIR_DOMAIN_AFFECT_CONFIG except: from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE, VIR_MIGRATE_LIVE + from vrtManager import util from xml.etree import ElementTree from lxml import etree from datetime import datetime +from collections import OrderedDict from vrtManager.connection import wvmConnect from vrtManager.storage import wvmStorage from webvirtcloud.settings import QEMU_CONSOLE_TYPES @@ -184,6 +186,18 @@ class wvmInstance(wvmConnect): if cur_vcpu: return int(cur_vcpu) + def get_vcpus(self): + vcpus = OrderedDict() + tree = etree.fromstring(self._XMLDesc(0)) + for vcpu in tree.xpath("/domain/vcpus/vcpu"): + id = vcpu.get("id") + enabled = vcpu.get("enabled") + hotplug = vcpu.get("hotpluggable") + order = vcpu.get("order") + vcpus[id] = {"enabled": enabled, "hotpluggable": hotplug, "order": order} + + return vcpus + def get_memory(self): mem = util.get_xml_path(self._XMLDesc(0), "/domain/memory") return int(mem) / 1024 @@ -554,6 +568,35 @@ class wvmInstance(wvmConnect): cpu_usage['cpu'] = 0 return cpu_usage + def set_vcpu(self, cpu_id, enabled): + self.instance.setVcpu(str(cpu_id), enabled) + + def set_vcpu_hotplug(self, status, vcpus_hotplug=0): + """ vcpus_hotplug = 0 make all vpus hotpluggable """ + vcpus_hotplug = int(self.get_vcpu()) if vcpus_hotplug == 0 else vcpus_hotplug + if self.get_status() == 5: # shutoff + if status: + xml = """ """ + xml += """""" + for i in range(1, vcpus_hotplug): + xml += """""".format(i, i+1) + xml += """""" + + tree = etree.fromstring(self._XMLDesc(0)) + vcpus = tree.xpath("/domain/vcpus") + if not vcpus: + tree.append(etree.fromstring(xml)) + self._defineXML(etree.tostring(tree)) + else: + tree = etree.fromstring(self._XMLDesc(0)) + vcpus = tree.xpath("/domain/vcpus") + for vcpu in vcpus: + parent = vcpu.getparent() + parent.remove(vcpu) + self._defineXML(etree.tostring(tree)) + else: + raise libvirtError("Please shutdown the instance then try to enable vCPU hotplug") + def mem_usage(self): mem_usage = {} if self.get_status() == 1: @@ -785,51 +828,27 @@ class wvmInstance(wvmConnect): parent.append(etree.fromstring(video_xml)) self._defineXML(etree.tostring(tree)) - def resize(self, cur_memory, memory, cur_vcpu, vcpu, disks=[]): - """ - Function change ram and cpu on vds. - """ - memory = int(memory) * 1024 - cur_memory = int(cur_memory) * 1024 - # if dom is running change only ram - if self.get_status() == VIR_DOMAIN_RUNNING: - self.set_memory(cur_memory, VIR_DOMAIN_AFFECT_LIVE) - self.set_memory(cur_memory, VIR_DOMAIN_AFFECT_CONFIG) - return - - xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE) - tree = ElementTree.fromstring(xml) - - set_mem = tree.find('memory') - set_mem.text = str(memory) - set_cur_mem = tree.find('currentMemory') - set_cur_mem.text = str(cur_memory) - set_vcpu = tree.find('vcpu') - set_vcpu.text = vcpu - set_vcpu.set('current', cur_vcpu) - - for disk in disks: - source_dev = disk['path'] - vol = self.get_volume_by_path(source_dev) - vol.resize(disk['size_new']) - - new_xml = ElementTree.tostring(tree) - self._defineXML(new_xml) - def resize_cpu(self, cur_vcpu, vcpu): """ - Function change ram and cpu on vds. + Function change ram and cpu on instance. """ + is_vcpus_enabled = self.get_vcpus() + if is_vcpus_enabled: + self.set_vcpu_hotplug(False) + xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE) - tree = ElementTree.fromstring(xml) + tree = etree.fromstring(xml) set_vcpu = tree.find('vcpu') set_vcpu.text = vcpu set_vcpu.set('current', cur_vcpu) - new_xml = ElementTree.tostring(tree) + new_xml = etree.tostring(tree) self._defineXML(new_xml) + if is_vcpus_enabled: + self.set_vcpu_hotplug(True, int(cur_vcpu)) + def resize_mem(self, cur_memory, memory): """ Function change ram and cpu on vds.