1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2024-12-25 15:45:23 +00:00

Merge pull request #266 from catborise/master

add hot cpu enabling disabling functionality
This commit is contained in:
Anatoliy Guskov 2019-12-02 13:11:05 +02:00 committed by GitHub
commit 8ed1630686
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 179 additions and 60 deletions

View file

@ -52,14 +52,33 @@
</div> </div>
<div class="col-xs-8 col-sm-9"> <div class="col-xs-8 col-sm-9">
<p>{{ hostname }}</p> <p>{{ hostname }}</p>
<p>{% for arch, hpv in hypervisor.items %} <p><div class="btn-group" style="margin-left: 8px">
<span class="glyphicon glyphicon-chevron-right"></span> {% for arch, hpv in hypervisor.items %}
<span class="label label-default">{{ arch }}</span> {% if forloop.counter < 4 %}
<div class="btn-group" >
<button class="btn btn-xs btn-default dropdown-toggle" type="button" id="dropdownMenuButton{{ forloop.counter0 }}" data-toggle="dropdown">
{{ arch }}
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton{{ forloop.counter0 }}" role="menu">
{% for h in hpv %} {% for h in hpv %}
<span class="label label-primary">{{ h }}</span> <li><a href="#">{{ h }}</a></li>
{% endfor %} {% endfor %}
</ul>
</div>
{% else %}
<button class="btn btn-xs btn-default dropdown-toggle" type="button" id="dropdownMenuButton{{ forloop.counter0 }}" data-toggle="dropdown">
{{ hypervisor|length }} {% trans 'more' %}...
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton{{ forloop.counter0 }}" role="menu">
{% for arc in hypervisor.keys %}
<li><a href="#">{{ arc }}</a></li>
{% endfor %} {% endfor %}
</p> </ul>
{% endif %}
{% endfor %}
</div></p>
<p>{{ emulator }}</p> <p>{{ emulator }}</p>
<p> <p>
<span class="label label-default">Qemu</span> <span class="label label-default">Qemu</span>

View file

@ -396,7 +396,8 @@ install_centos_post() {
exit 1 exit 1
fi fi
if [ -f /etc/libvirt/qemu.conf ]; then if [ -f /etc/libvirt/qemu.conf ]; then
sed -i 's/#vnc_listen/vnc_listen/g' /etc/libvirt/qemu.conf sed -i 's/#[ ]*vnc_listen.*/vnc_listen = "0.0.0.0"/g' /etc/libvirt/qemu.conf
sed -i 's/#[ ]*spice_listen.*/spice_listen = "0.0.0.0"/g' /etc/libvirt/qemu.conf
else else
echoerror "/etc/libvirt/qemu.conf not found. Exiting..." echoerror "/etc/libvirt/qemu.conf not found. Exiting..."
exit 1 exit 1
@ -487,7 +488,8 @@ install_fedora_post() {
exit 1 exit 1
fi fi
if [ -f /etc/libvirt/qemu.conf ]; then if [ -f /etc/libvirt/qemu.conf ]; then
sed -i 's/#vnc_listen/vnc_listen/g' /etc/libvirt/qemu.conf sed -i 's/#[ ]*vnc_listen.*/vnc_listen = "0.0.0.0"/g' /etc/libvirt/qemu.conf
sed -i 's/#[ ]*spice_listen.*/spice_listen = "0.0.0.0"/g' /etc/libvirt/qemu.conf
else else
echoerror "/etc/libvirt/qemu.conf not found. Exiting..." echoerror "/etc/libvirt/qemu.conf not found. Exiting..."
exit 1 exit 1
@ -548,7 +550,8 @@ install_opensuse_post() {
exit 1 exit 1
fi fi
if [ -f /etc/libvirt/qemu.conf ]; then if [ -f /etc/libvirt/qemu.conf ]; then
sed -i 's/#vnc_listen/vnc_listen/g' /etc/libvirt/qemu.conf sed -i 's/#[ ]*vnc_listen.*/vnc_listen = "0.0.0.0"/g' /etc/libvirt/qemu.conf
sed -i 's/#[ ]*spice_listen.*/spice_listen = "0.0.0.0"/g' /etc/libvirt/qemu.conf
else else
echoerror "/etc/libvirt/qemu.conf not found. Exiting..." echoerror "/etc/libvirt/qemu.conf not found. Exiting..."
exit 1 exit 1
@ -618,11 +621,9 @@ install_ubuntu_post() {
exit 1 exit 1
fi fi
if [ -f /etc/libvirt/qemu.conf ]; then if [ -f /etc/libvirt/qemu.conf ]; then
if ([ $DISTRO_MAJOR_VERSION -eq 12 ] && [ $DISTRO_MINOR_VERSION -eq 04 ]); then sed -i 's/#[ ]*vnc_listen.*/vnc_listen = "0.0.0.0"/g' /etc/libvirt/qemu.conf
sed -i 's/# vnc_listen/vnc_listen/g' /etc/libvirt/qemu.conf sed -i 's/#[ ]*spice_listen.*/spice_listen = "0.0.0.0"/g' /etc/libvirt/qemu.conf
else
sed -i 's/#vnc_listen/vnc_listen/g' /etc/libvirt/qemu.conf
fi
else else
echoerror "/etc/libvirt/qemu.conf not found. Exiting..." echoerror "/etc/libvirt/qemu.conf not found. Exiting..."
exit 1 exit 1
@ -697,11 +698,19 @@ install_debian_post() {
exit 1 exit 1
fi fi
if [ -f /etc/libvirt/qemu.conf ]; then if [ -f /etc/libvirt/qemu.conf ]; then
sed -i 's/# vnc_listen/vnc_listen/g' /etc/libvirt/qemu.conf sed -i 's/#[ ]*vnc_listen.*/vnc_listen = "0.0.0.0"/g' /etc/libvirt/qemu.conf
sed -i 's/#[ ]*spice_listen.*/spice_listen = "0.0.0.0"/g' /etc/libvirt/qemu.conf
else else
echoerror "/etc/libvirt/qemu.conf not found. Exiting..." echoerror "/etc/libvirt/qemu.conf not found. Exiting..."
exit 1 exit 1
fi fi
if [ -f /etc/sasl2/libvirt.conf ]; then
sed -i 's/: gssapi/: digest-md5/g' /etc/sasl2/libvirt.conf
sed -i 's/#sasldb_path/sasldb_path/g' /etc/sasl2/libvirt.conf
else
echoerror "/etc/sasl2/libvirt.conf not found. Exiting..."
exit 1
fi
if [ -f /etc/supervisor/supervisord.conf ]; then if [ -f /etc/supervisor/supervisord.conf ]; then
wget -O /usr/local/bin/gstfsd https://raw.githubusercontent.com/retspen/webvirtcloud/master/conf/daemon/gstfsd wget -O /usr/local/bin/gstfsd https://raw.githubusercontent.com/retspen/webvirtcloud/master/conf/daemon/gstfsd
chmod +x /usr/local/bin/gstfsd chmod +x /usr/local/bin/gstfsd

View file

@ -363,10 +363,11 @@
<div class="tab-content"> <div class="tab-content">
<div role="tabpanel" class="tab-pane tab-pane-bordered active" id="resizevm_cpu"> <div role="tabpanel" class="tab-pane tab-pane-bordered active" id="resizevm_cpu">
{% if request.user.is_superuser or request.user.is_staff or userinstance.is_change %} {% if request.user.is_superuser or request.user.is_staff or userinstance.is_change %}
{% if status == 5 or not vcpus %}
<form class="form-horizontal" method="post" role="form">{% csrf_token %} <form class="form-horizontal" method="post" role="form">{% csrf_token %}
<p style="font-weight:bold;">{% trans "Logical host CPUs" %} : {{ vcpu_host }}</p> <p style="font-weight:bold;">{% trans "Logical host CPUs" %} : {{ vcpu_host }}</p>
<div class="form-group"> <div class="form-group">
<label class="col-sm-4 control-label" style="font-weight:normal;"> {% trans "Current allocation" %}</label> <label class="col-sm-4 control-label" style="font-weight:normal;"> {% trans "Current Allocation" %}</label>
<div class="col-sm-4"> <div class="col-sm-4">
<select name="cur_vcpu" class="form-control"> <select name="cur_vcpu" class="form-control">
{% for cpu in vcpu_range %} {% for cpu in vcpu_range %}
@ -380,7 +381,7 @@
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-4 control-label" style="font-weight:normal;">{% trans "Maximum allocation" %}</label> <label class="col-sm-4 control-label" style="font-weight:normal;">{% trans "Maximum Allocation" %}</label>
<div class="col-sm-4"> <div class="col-sm-4">
<select name="vcpu" class="form-control"> <select name="vcpu" class="form-control">
{% for cpu in vcpu_range %} {% for cpu in vcpu_range %}
@ -396,6 +397,28 @@
<button class="btn btn-lg btn-success pull-right disabled">{% trans "Resize" %}</button> <button class="btn btn-lg btn-success pull-right disabled">{% trans "Resize" %}</button>
{% endifequal %} {% endifequal %}
</form> </form>
<div class="clearfix"></div>
{% else %}
<p style="font-weight:bold;">{% trans "Logical Instance Active/Maximum CPUs" %} : {{ cur_vcpu }} / {{ vcpu }} </p>
<div class="col-sm-3"></div>
<div class="col-sm-6">
{% for id, vcpu in vcpus.items %}
<form method="post" role="form">{% csrf_token %}
<div class="col-sm-3">
<input name="id" value="{{ id }}" hidden/>
{% if vcpu.enabled == 'yes' and vcpu.hotpluggable == "yes" %}
<button type="submit" class="btn btn-block btn-success" value="False" name="set_vcpu" title="Disable">{{ id }}</button>
{% elif vcpu.enabled == 'yes' and vcpu.hotpluggable == "no" %}
<button type="button" class="btn btn btn-block btn-info" title="Constant">{{ id }}</button>
{% else %}
<button type="submit" class="btn btn btn-block btn-default" value="True" name="set_vcpu" title="Enable">{{ id }}</button>
{% endif %}
</div>
</form>
{% endfor %}
</div>
<div class="col-sm-3"></div>
{% endif %}
{% else %} {% else %}
{% trans "You don't have permission for resizing instance" %} {% trans "You don't have permission for resizing instance" %}
<button class="btn btn-lg btn-success pull-right disabled">{% trans "Resize" %}</button> <button class="btn btn-lg btn-success pull-right disabled">{% trans "Resize" %}</button>
@ -1358,6 +1381,30 @@
</form> </form>
<div class="clearfix"></div> <div class="clearfix"></div>
</div> </div>
<div class="well">
<p>{% trans "To set instance vCPUs hotpluggable" %}</p>
<form class="form-horizontal" method="post" role="form">{% csrf_token %}
<div class="form-group">
<label for="video_model_select" class="col-sm-3 control-label">{% trans "vCPU Hot Plug" %}</label>
<div class="col-sm-6">
<div class="input-group">
<select id="vcpu_hotplug" class="form-control" name="vcpu_hotplug">
<option value="True" {% if vcpus %} selected {% endif %}>{% trans 'Enabled' %}</option>
<option value="False" {% if not vcpus %} selected {% endif %}>{% trans 'Disabled' %}</option>
</select>
<span class="input-group-btn">
{% if status == 5 %}
<button type="submit" class="btn btn-success" name="set_vcpu_hotplug">{% trans "Set" %}</button>
{% else %}
<button class="btn btn-success" name="set_vcpu_hotplug" disabled>{% trans "Set" %}</button>
{% endif %}
</span>
</div>
</div>
</div>
</form>
<div class="clearfix"></div>
</div>
</div> </div>
{% endif %} {% endif %}
</div> </div>

View file

@ -26,6 +26,7 @@ from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE
from logs.views import addlogmsg from logs.views import addlogmsg
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from collections import OrderedDict
@login_required @login_required
@ -44,7 +45,7 @@ def allinstances(request):
:param request: :param request:
:return: :return:
""" """
all_host_vms = {} all_host_vms = OrderedDict()
error_messages = [] error_messages = []
computes = Compute.objects.all().order_by("name") computes = Compute.objects.all().order_by("name")
@ -76,7 +77,7 @@ def instances(request, compute_id):
:param compute_id :param compute_id
:return: :return:
""" """
all_host_vms = {} all_host_vms = OrderedDict()
error_messages = [] error_messages = []
compute = get_object_or_404(Compute, pk=compute_id) compute = get_object_or_404(Compute, pk=compute_id)
@ -266,6 +267,7 @@ def instance(request, compute_id, vname):
boot_order = conn.get_bootorder() boot_order = conn.get_bootorder()
vcpu = conn.get_vcpu() vcpu = conn.get_vcpu()
cur_vcpu = conn.get_cur_vcpu() cur_vcpu = conn.get_cur_vcpu()
vcpus = conn.get_vcpus()
uuid = conn.get_uuid() uuid = conn.get_uuid()
memory = conn.get_memory() memory = conn.get_memory()
cur_memory = conn.get_cur_memory() cur_memory = conn.get_cur_memory()
@ -668,6 +670,29 @@ def instance(request, compute_id, vname):
addlogmsg(request.user.username, instance.name, msg) addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#suspend') 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: if 'set_autostart' in request.POST:
conn.set_autostart(1) conn.set_autostart(1)
msg = _("Set autostart") 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 = Instance(compute_id=comp["id"], name=inst_name, uuid=info['uuid'])
inst_on_db.save() inst_on_db.save()
all_host_vms = {} all_host_vms = OrderedDict()
status = connection_manager.host_is_up(comp.type, comp.hostname) status = connection_manager.host_is_up(comp.type, comp.hostname)
if status is True: if status is True:

View file

@ -5,10 +5,12 @@ try:
VIR_DOMAIN_AFFECT_LIVE, VIR_DOMAIN_AFFECT_CONFIG VIR_DOMAIN_AFFECT_LIVE, VIR_DOMAIN_AFFECT_CONFIG
except: except:
from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE, VIR_MIGRATE_LIVE from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE, VIR_MIGRATE_LIVE
from vrtManager import util from vrtManager import util
from xml.etree import ElementTree from xml.etree import ElementTree
from lxml import etree from lxml import etree
from datetime import datetime from datetime import datetime
from collections import OrderedDict
from vrtManager.connection import wvmConnect from vrtManager.connection import wvmConnect
from vrtManager.storage import wvmStorage from vrtManager.storage import wvmStorage
from webvirtcloud.settings import QEMU_CONSOLE_TYPES from webvirtcloud.settings import QEMU_CONSOLE_TYPES
@ -184,6 +186,18 @@ class wvmInstance(wvmConnect):
if cur_vcpu: if cur_vcpu:
return int(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): def get_memory(self):
mem = util.get_xml_path(self._XMLDesc(0), "/domain/memory") mem = util.get_xml_path(self._XMLDesc(0), "/domain/memory")
return int(mem) / 1024 return int(mem) / 1024
@ -554,6 +568,35 @@ class wvmInstance(wvmConnect):
cpu_usage['cpu'] = 0 cpu_usage['cpu'] = 0
return cpu_usage 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 = """ <vcpus>"""
xml += """<vcpu id='0' enabled='yes' hotpluggable='no' order='1'/>"""
for i in range(1, vcpus_hotplug):
xml += """<vcpu id='{}' enabled='yes' hotpluggable='yes' order='{}'/>""".format(i, i+1)
xml += """</vcpus>"""
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): def mem_usage(self):
mem_usage = {} mem_usage = {}
if self.get_status() == 1: if self.get_status() == 1:
@ -785,51 +828,27 @@ class wvmInstance(wvmConnect):
parent.append(etree.fromstring(video_xml)) parent.append(etree.fromstring(video_xml))
self._defineXML(etree.tostring(tree)) 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): 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) xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE)
tree = ElementTree.fromstring(xml) tree = etree.fromstring(xml)
set_vcpu = tree.find('vcpu') set_vcpu = tree.find('vcpu')
set_vcpu.text = vcpu set_vcpu.text = vcpu
set_vcpu.set('current', cur_vcpu) set_vcpu.set('current', cur_vcpu)
new_xml = ElementTree.tostring(tree) new_xml = etree.tostring(tree)
self._defineXML(new_xml) self._defineXML(new_xml)
if is_vcpus_enabled:
self.set_vcpu_hotplug(True, int(cur_vcpu))
def resize_mem(self, cur_memory, memory): def resize_mem(self, cur_memory, memory):
""" """
Function change ram and cpu on vds. Function change ram and cpu on vds.

View file

@ -103,8 +103,8 @@ WS_PORT = 6080
# Websock host # Websock host
WS_HOST = '0.0.0.0' WS_HOST = '0.0.0.0'
# Websock public port # Websock public port - 80 or 443 if reverse-proxy, else 6080
WS_PUBLIC_PORT = '443' WS_PUBLIC_PORT = 6080
# Websock public host # Websock public host
WS_PUBLIC_HOST = None WS_PUBLIC_HOST = None