Files
webgui/plugins/dynamix/CPUset.page
bergware 0c5abec7a1 Revamp of themes White and Black
New style themes, including fixes and enhancements.
Ported back to themes Azure and Gray
2018-08-21 07:43:04 +02:00

189 lines
7.2 KiB
Plaintext

Menu="OtherSettings"
Title="CPU Pinning"
Icon="grid.png"
Tag="map-marker"
Cond="pgrep('libvirtd')!==false || pgrep('dockerd')!==false"
---
<?PHP
/* Copyright 2005-2018, Lime Technology
* Copyright 2012-2018, Bergware International.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
?>
<?
$libvirtd = pgrep('libvirtd')!==false;
$dockerd = pgrep('dockerd')!==false;
$cpus = cpu_list();
$total = count($cpus);
$spinner = "<tr><td colspan='".($total+2)."'><div class='spinner'></div></td></tr>";
$cpuset = implode(';',$cpus);
function create() {
// create the table header. Make multiple rows when CPU cores are many ;)
global $total,$cpus;
$loop = floor(($total-1)/32)+1;
$text = [];
for ($c = 0; $c < $loop; $c++) {
$max = ($c == $loop-1 ? ($total%32?:32) : 32);
for ($n = 0; $n < $max; $n++) {
unset($cpu1,$cpu2);
list($cpu1, $cpu2) = preg_split('/[,-]/',$cpus[$c*32+$n]);
$text[$n] .="$cpu1<br>";
if ($cpu2) $text[$n] .= "$cpu2<br>";
}
}
$label = implode('<br>',array_fill(0,$loop,'CPU:'.($cpu2 ? '<br>HT:':'')));
echo "<th>$label</th>".implode(array_map(function($t){return "<th>$t</th>";},$text));
}
?>
<style>
table.tablesorter tr>th+th{text-align:right;vertical-align:top}
table.tablesorter tr>td+td+td{vertical-align:top}
table.tablesorter tr>th+th+th,table.tablesorter tr>td+td{text-align:center}
table.tablesorter th:first-child,table.tablesorter td:first-child{width:180px;text-align:left}
input.flat{margin:0}
input.lock{margin:0}
</style>
<script>
String.prototype.stripper = function(){return this.replace(/ |\(|\)|\[|\]/g,'');}
function apply(form) {
// disable buttons
$(form).find('input[value="Apply"]').prop('disabled',true);
$(form).find('input[value="Reset"]').val('Done').prop('onclick',null).off('click').click(function(){done();});
$('input[value="Done"]').prop('disabled',true);
var wait = 0;
var id = $(form).prop('name');
var args = {};
args['id'] = id;
args['names'] = form.names.value;
// get the 'checked' cpus
$(form).find('input[type=checkbox]').each(function(){
if ($(this).prop('checked')) args[$(this).prop('name')] = 'on';
});
// show the instant wait message
$('#wait-'+id).show();
// step 1: prepare the update and report back the changes
$.post('/webGui/include/UpdateOne.php',args,function(reply){
if (reply.error) {
swal({type:'error', title:'Assignment error', text:reply.error},function(){
$('#wait-'+id).hide();
$(form).find('input[value="Done"]').val('Reset').prop('disabled',false).prop('onclick',null).off('click').click(function(){reset($('form[name="'+id+'"]'));});
});
} else if (reply.success) {
var data = reply.success.split(';');
wait = data.length;
for (var i=0; i < data.length; i++) {
var name = data[i];
$('#'+id+'-'+name.stripper()).show('slow');
// step 2: apply the changes by updating the vm or container
$.post('/webGui/include/UpdateTwo.php',{id:id,name:encodeURI(name)},function(reply){
if (reply.error) {
// report error and reload table
swal({type:'error', title:'Execution error', text:reply.error},function(){
$('#wait-'+id).hide();
$('input[value="Done"]').prop('disabled',false);
reset($('form[name="'+id+'"]'));
});
} else {
$('#'+id+'-'+reply.success.stripper()).hide('slow');
// cleanup when all is done
if (!--wait) {
setTimeout(function(){$('#wait-'+id).hide();},500);
$('input[value="Done"]').prop('disabled',false);
}
}
});
}
} else {
$('#wait-'+id).hide();
$('input[value="Done"]').prop('disabled',false);
}
});
}
function vm() {
// fetch the current vm assignments
$.post('/webGui/include/CPUset.php',{id:'vm',cpus:'<?=$cpuset?>'},function(d){
var data = d.split('\0');
$('#table-vm').html(data[0]);
$('#names-vm').val(data[1]);
buttons(document.vm);
});
}
function ct() {
// fetch the current container assignments
$.post('/webGui/include/CPUset.php',{id:'ct',cpus:'<?=$cpuset?>'},function(d){
var data = d.split('\0');
$('#table-ct').html(data[0]);
$('#names-ct').val(data[1]);
buttons(document.ct);
});
}
function reset(form) {
// undo changes without a complete refresh of the page
$(form).find('input[value="Apply"]').prop('disabled',true);
$(form).find('input[value="Reset"]').val('Done').prop('onclick',null).off('click').click(function(){done();});
switch ($(form).prop('name')) {
case 'vm': $('#table-vm').html("<?=$spinner?>"); vm(); break;
case 'ct': $('#table-ct').html("<?=$spinner?>"); ct(); break;
}
}
function buttons(form) {
// we need the Apply and Done buttons react on checkbox changes
$(form).find('input[type=checkbox]').each(function(){$(this).on('input change',function(){
$(form).find('input[value="Apply"]').prop('disabled',false);
$(form).find('input[value="Done"]').val('Reset').prop('onclick',null).off('click').click(function(){reset(form);});
});});
}
$(function(){
<?if ($libvirtd):?>
vm();
<?endif;?>
<?if ($dockerd):?>
ct();
<?endif;?>
});
</script>
> This page gives a total view of the current CPU pinning assignments for both VMs and Docker containers.<br>
> It also allows to modify these assignments.
>
> Running VMs or containers are **stopped first** and restarted after the modification.<br>
> Stopped VMs or containers are instantly modified and new assignments become active when the user manually starts the VM or container.
>
> When ***Apply*** is pressed a scan is performed to find the changes, subsequently only VMs or containers which have changes are modified in parallel.
>
> *Please wait until all updates are finished*.
>
> By default NO cores are selected for a Docker container, which means it uses all available cores.<br>
> **Do not select ALL cores, just select NONE**
<?if ($libvirtd):?>
<form name="vm">
<input type="hidden" name="names" id="names-vm" value="">
<table class='tablesorter shift' style='width:auto'>
<thead><tr><th><i class="fa fa-list"></i> VM</th><?create()?></tr></thead>
<tbody id="table-vm"><?=$spinner?></tbody>
</table>
<input type="button" value="Apply" onclick="apply(this.form)" disabled><input type="button" value="Done" onclick="done()"><span id="wait-vm" class="red-text" style="display:none"><i class="fa fa-spinner fa-spin"></i> Please wait...</span>
</form>
<br>
<?endif;?>
<?if ($dockerd):?>
<form name="ct">
<input type="hidden" name="names" id="names-ct" value="">
<table class='tablesorter' style='width:auto'>
<thead><tr><th><i class="fa fa-list"></i> Container</th><?create()?></tr></thead>
<tbody id="table-ct"><?=$spinner?></tbody>
</table>
<input type="button" value="Apply" onclick="apply(this.form)" disabled><input type="button" value="Done" onclick="done()"><span id="wait-ct" class="red-text" style="display:none"><i class="fa fa-spinner fa-spin"></i> Please wait...</span>
</form>
<?endif;?>