Files
webgui/plugins/dynamix.vm.manager/VMMachines.page
T

226 lines
8.8 KiB
Plaintext

Menu="VMs:1"
Title="Virtual Machines"
Tag="columns"
Cond="(pgrep('libvirtd')!==false)"
Markdown="false"
---
<?PHP
/* Copyright 2005-2018, Lime Technology
* Copyright 2015-2018, Derek Macias, Eric Schultz, Jon Panozzo.
* 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.
*/
?>
<?
require_once "$docroot/plugins/dynamix.vm.manager/classes/libvirt_helpers.php";
exec('cat /sys/devices/system/cpu/*/topology/thread_siblings_list|sort -nu', $cpus);
function showCPUs($uuid) {
global $cpus;
$vm = domain_to_config($uuid);
echo "<div class='four'>";
foreach ($cpus as $pair) {
unset($cpu1,$cpu2);
list($cpu1, $cpu2) = preg_split('/[,-]/',$pair);
$check = in_array($cpu1, $vm['domain']['vcpu']) ? 'fa-check-square-o':'fa-square-o';
if (!$cpu2) {
echo "<label><i class='$check'></i>&nbsp;&nbsp;cpu $cpu1</label>";
} else {
echo "<label class='cpu1'><i class='fa fa-fw $check'></i>&nbsp;&nbsp;cpu $cpu1 / $cpu2</label>";
$check = in_array($cpu2, $vm['domain']['vcpu']) ? 'fa-check-square-o':'fa-square-o';
echo "<label class='cpu2'><i class='fa fa-fw $check'></i></label>";
}
}
echo "</div>";
}
$uuid = $_GET['uuid'];
$subaction = $_GET['subaction'] ?? '';
if ($_GET['refresh']) {
$vm = $_GET['name'];
if ($lv->domain_is_active($vm)) {
echo "<meta http-equiv='refresh' content='5; url=/VMs?name=$vm&amp;refresh=true'>";
$msg = "Waiting for $vm to shutdown...";
} else {
echo "<script>clearHistory();</script>";
$msg = "$vm has been shutdown";
}
}
if ($subaction) {
$vm = $lv->domain_get_name_by_uuid($uuid);
if ($subaction == 'disk-resize') {
$capacity = str_replace(["KB","MB","GB","TB","PB"," ",","], ["K","M","G","T","P","",""], strtoupper($_POST['cap']));
$oldcap = str_replace(["KB","MB","GB","TB","PB"," ",","], ["K","M","G","T","P","",""], strtoupper($_GET['oldcap']));
if (substr($oldcap,0,-1) < substr($capacity,0,-1)){
shell_exec("qemu-img resize -q ".escapeshellarg($_GET['disk'])." ".escapeshellarg($capacity));
$msg = $vm." disk capacity has been changed to $capacity";
} else {
$msg = "Error: disk capacity has to be greater than {$_GET['oldcap']}";
}
} elseif ($subaction == 'disk-remove') {
$msg = $lv->domain_disk_remove($vm, $_GET['dev'])
? "$vm disk has been removed"
: "Error: ".$lv->get_last_error();
} elseif ($subaction == 'snap-create') {
$msg = $lv->domain_snapshot_create($vm)
? "Snapshot for $vm has been created"
: "Error: ".$lv->get_last_error();
} elseif ($subaction == 'snap-delete') {
$msg = $lv->domain_snapshot_delete($vm, $_GET['snap'])
? "Snapshot for $vm has been deleted"
: "Error: ".$lv->get_last_error();
} elseif ($subaction == 'snap-revert') {
$msg = $lv->domain_snapshot_revert($vm, $_GET['snap'])
? "$vm has been reverted"
: "Error: ".$lv->get_last_error();
} elseif ($subaction == 'snap-desc') {
$msg = $lv->snapshot_set_metadata($vm, $_GET['snap'], $_POST['snapdesc'])
? "Snapshot description for $vm has been saved"
: "Error: ".$lv->get_last_error();
}
echo "<script>clearHistory();</script>";
}
if ($libvirt_running=='yes') {
$vms = $lv->get_domains() ?: [];
sort($vms);
}
if (empty($vms)) {
$msg = $libvirt_running=='yes'
? 'No VMs defined. Create from template or add XML.'
: 'Libvirt is not running. Goto Settings tab then click Start.';
}
?>
<link type="text/css" rel="stylesheet" href="<?autov('/plugins/dynamix.vm.manager/styles/dynamix.vm.manager.css')?>">
<link type="text/css" rel="stylesheet" href="/webGui/styles/jquery.filetree.css">
<link type="text/css" rel="stylesheet" href="/webGui/styles/jquery.switchbutton.css">
<style type="text/css">
body{-webkit-overflow-scrolling:touch;}
.fileTree{width:305px;max-height:150px;overflow:scroll;position:absolute;z-index:100;display:none;}
div.four{font-family:arimo;font-size:12px;color:#A0A0A0;width:300px}
div.four label{float:left;display:table-cell;width:25%}
div.four label:nth-child(4n+4){float:none;clear:both}
div.four label.cpu1{width:27%}
div.four label.cpu2{width:33%}
div.Panel{float:unset;margin:4px;height:inherit;border:none;}
div.Panel:hover{background-color:unset;}
div.PanelText{display:none;}
</style>
<table class="tablesorter shift kvm" id="kvm_table">
<thead><tr><th><i class="fa fa-th-list"></i></th><th>Name</th><th>Description</th><th>CPUs</th><th>Memory</th><th>vDisks</th><th>Graphics</th><th>Autostart</th></tr></thead>
<tbody id="kvm_list"><tr><td colspan='8' style='text-align:center;padding-top:12px'><i class='fa fa-spinner fa-spin icon'></i>Please wait... retrieving VM information</td></tr></tbody>
</table>
<input type="button" onclick="addVM()" id="btnAddVM" value="Add VM"/>
<input type="button" onclick="startAll()" value="Start all VMs"/>
<input type="button" onclick="stopAll()" value="Stop all VMs"/>
<script src="<?autov('/webGui/javascript/jquery.filetree.js')?>"></script>
<script src="<?autov('/webGui/javascript/jquery.switchbutton.js')?>"></script>
<script src="<?autov('/plugins/dynamix.vm.manager/scripts/dynamix.vm.manager.js')?>"></script>
<script src="<?autov('/plugins/dynamix.vm.manager/javascript/vmmanager.js')?>"></script>
<script>
function startAll() {
$('input[type=button]').prop('disabled',true);
for (var i=0,vm; vm=kvm[i]; i++) if (vm.state!='running') $('#vm-'+vm.id).addClass('fa-spin');
$.post('/plugins/dynamix.vm.manager/classes/VMManager.php',{action:'start'}, function(){loadlist();});
}
function stopAll() {
$('input[type=button]').prop('disabled',true);
for (var i=0,vm; vm=kvm[i]; i++) if (vm.state=='running') $('#vm-'+vm.id).addClass('fa-spin');
$.post('/plugins/dynamix.vm.manager/classes/VMManager.php',{action:'stop'}, function(){loadlist();});
}
function vncOpen() {
$.post('/plugins/dynamix.vm.manager/classes/vnc.php',{cmd:'open',root:'<?=$docroot?>',file:'<?=$docroot?>/plugins/dynamix.vm.manager/vncconnect.vnc'},function(data) {
window.location.href = data;
});
}
function toggle_id(itemID){
if ((document.getElementById(itemID).style.display == 'none')) {
slideDownRows($('#'+itemID));
} else {
slideUpRows($('#'+itemID));
}
return false;
}
function showInput(){
$(this).off('click');
$(this).siblings('input').each(function(){$(this).show();});
$(this).siblings('input').focus();
$(this).hide();
}
function hideInput(){
$(this).hide();
$(this).siblings('span').show();
$(this).siblings('span').click(showInput);
}
function addVM() {
var path = location.pathname;
var x = path.indexOf("?");
if (x!=-1) path = path.substring(0,x);
location = path+"/VMTemplates";
}
<?if ($display['resize']):?>
function resize(bind) {
var width = [];
var h = $('#kvm_list').height();
var s = Math.max(window.innerHeight-300,370);
if (h>s || bind) {
$('#kvm_list').height(s);
$('#kvm_table tbody tr:first-child td').each(function(){width.push($(this).width());});
$('#kvm_table thead tr th').each(function(i){$(this).width(width[i]);});
if (!bind) $('#kvm_table thead,#kvm_table tbody').addClass('fixed');
}
}
<?endif;?>
function loadlist() {
$.get('/plugins/dynamix.vm.manager/classes/VMMachines.php',function(d) {
var data = d.split(/\0/);
$('#kvm_list').html(data[0]);
$('head').append('<script>'+data[1]+'<\/script>');
<?
$i=0;
foreach ($vms as $vm) {
$res = $lv->get_domain_by_name($vm);
$uuid = $lv->domain_get_uuid($res);
?> $('.vcpu<?=$i++?>').tooltipster({
trigger:'custom',
triggerOpen:{mouseenter:true,click:true,touchstart:true},
contentAsHTML:true,
animation:'grow',
triggerClose:{click:true,scroll:true,mouseleave:true,delay:1},
interactive:true,
viewportAware:true,
functionBefore:function(instance,helper){instance.content("<?=showCPUs($uuid)?>");}
});
<?}?>
<?if ($display['resize']):?>
resize();
$(window).bind('resize',function(){resize(true);});
<?endif;?>
$('.autostart').switchButton({labels_placement:"right"});
$('.autostart').change(function() {
$.post('/plugins/dynamix.vm.manager/VMajax.php',{action:'domain-autostart',uuid:$(this).attr('uuid'),autostart:$(this).prop('checked'),response:'json'},function(data){
$(this).prop('checked', data.autostart);
},'json');
});
context.init({preventDoubleContext:false});
$('input[type=button]').prop('disabled',false);
});
}
$(function() {
<?if ($msg):?>
<?$color = strpos($msg, "rror:")!==false ? 'red-text':'green-text'?>
$('#countdown').html("<span class='<?-$color?>'><?=$msg?></span>");
<?endif;?>
$('.text').click(showInput);
$('.input').blur(hideInput);
$('#btnAddVM').click(function AddVMEvent(){$('.tab>input#tab2').click();});
loadlist();
});
</script>