1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2024-12-24 15:15:22 +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 class="col-xs-8 col-sm-9">
<p>{{ hostname }}</p>
<p>{% for arch, hpv in hypervisor.items %}
<span class="glyphicon glyphicon-chevron-right"></span>
<span class="label label-default">{{ arch }}</span>
{% for h in hpv %}
<span class="label label-primary">{{ h }}</span>
{% endfor %}
{% endfor %}
</p>
<p><div class="btn-group" style="margin-left: 8px">
{% for arch, hpv in hypervisor.items %}
{% 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 %}
<li><a href="#">{{ h }}</a></li>
{% 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 %}
</ul>
{% endif %}
{% endfor %}
</div></p>
<p>{{ emulator }}</p>
<p>
<span class="label label-default">Qemu</span>

View file

@ -396,7 +396,8 @@ install_centos_post() {
exit 1
fi
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
echoerror "/etc/libvirt/qemu.conf not found. Exiting..."
exit 1
@ -487,7 +488,8 @@ install_fedora_post() {
exit 1
fi
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
echoerror "/etc/libvirt/qemu.conf not found. Exiting..."
exit 1
@ -548,7 +550,8 @@ install_opensuse_post() {
exit 1
fi
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
echoerror "/etc/libvirt/qemu.conf not found. Exiting..."
exit 1
@ -618,11 +621,9 @@ install_ubuntu_post() {
exit 1
fi
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/g' /etc/libvirt/qemu.conf
else
sed -i 's/#vnc_listen/vnc_listen/g' /etc/libvirt/qemu.conf
fi
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
echoerror "/etc/libvirt/qemu.conf not found. Exiting..."
exit 1
@ -663,9 +664,9 @@ daemons_running_ubuntu() {
install_debian() {
apt-get update || return 1
if [ $DISTRO_MAJOR_VERSION -lt 10 ]; then
apt-get -y install qemu-kvm libvirt-bin bridge-utils sasl2-bin python-guestfs supervisor || return 1
apt-get -y install qemu-kvm libvirt-bin bridge-utils sasl2-bin python-guestfs supervisor || return 1
else
apt-get -y install qemu qemu-kvm qemu-system qemu-utils libvirt-clients libvirt-daemon-system sasl2-bin virtinst supervisor || return 1
apt-get -y install qemu qemu-kvm qemu-system qemu-utils libvirt-clients libvirt-daemon-system sasl2-bin virtinst supervisor || return 1
fi
return 0
}
@ -697,11 +698,19 @@ install_debian_post() {
exit 1
fi
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
echoerror "/etc/libvirt/qemu.conf not found. Exiting..."
exit 1
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
wget -O /usr/local/bin/gstfsd https://raw.githubusercontent.com/retspen/webvirtcloud/master/conf/daemon/gstfsd
chmod +x /usr/local/bin/gstfsd

View file

@ -363,10 +363,11 @@
<div class="tab-content">
<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 status == 5 or not vcpus %}
<form class="form-horizontal" method="post" role="form">{% csrf_token %}
<p style="font-weight:bold;">{% trans "Logical host CPUs" %} : {{ vcpu_host }}</p>
<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">
<select name="cur_vcpu" class="form-control">
{% for cpu in vcpu_range %}
@ -380,7 +381,7 @@
</div>
</div>
<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">
<select name="vcpu" class="form-control">
{% for cpu in vcpu_range %}
@ -396,6 +397,28 @@
<button class="btn btn-lg btn-success pull-right disabled">{% trans "Resize" %}</button>
{% endifequal %}
</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 %}
{% trans "You don't have permission for resizing instance" %}
<button class="btn btn-lg btn-success pull-right disabled">{% trans "Resize" %}</button>
@ -1358,6 +1381,30 @@
</form>
<div class="clearfix"></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>
{% endif %}
</div>

View file

@ -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:

View file

@ -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 = """ <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):
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.

View file

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