VM settings: updated ACS Override and new Unsafe Interrupts option

This commit is contained in:
bergware
2018-09-05 12:52:37 +02:00
parent 4a8ed6217f
commit bda33e970e
2 changed files with 109 additions and 137 deletions

View File

@@ -29,33 +29,38 @@ if (empty($strLoadedModules)) {
exit;
}
$arrValidBridges = getNetworkBridges();
// Check for PCIE ACS capabilities
$boolACSEnabled = (strpos(file_get_contents('/proc/cmdline'), 'pcie_acs_override=') !== false);
// Check the /boot/syslinux/syslinux.cfg for the existance of pcie_acs_override=
$arrSyslinuxCfg = file('/boot/syslinux/syslinux.cfg');
$strCurrentLabel = '';
$boolACSInSyslinux = false;
foreach ($arrSyslinuxCfg as &$strSyslinuxCfg) {
if (stripos(trim($strSyslinuxCfg), 'label ') === 0) $strCurrentLabel = trim(str_ireplace('label ', '', $strSyslinuxCfg));
if (stripos($strSyslinuxCfg, 'append ') !== false) {
if (stripos($strSyslinuxCfg, 'pcie_acs_override=') !== false) {
// pcie_acs_override= was found
$boolACSInSyslinux = true;
}
// We just examine the first append line
break;
}
function scan($area, $text) {
return strpos($area,$text)!==false;
}
$bgcolor = strstr('white,azure',$display['theme']) ? '#f2f2f2' : '#1c1c1c';
function detect(&$syslinux, $key) {
$size = count($syslinux);
$menu = $i = 0;
$value = '';
// find the default section
while ($i < $size) {
if (scan($syslinux[$i],'label ')) {
$n = $i + 1;
// find the current requested setting
while (!scan($syslinux[$n],'label ') && $n < $size) {
if (scan($syslinux[$n],'menu default')) $menu = 1;
if (scan($syslinux[$n],'append')) foreach (explode(' ',$syslinux[$n]) as $cmd) if (scan($cmd,$key)) {$value = explode('=',$cmd)[1]; break;}
$n++;
}
if ($menu) break; else $i = $n - 1;
}
$i++;
}
return $value;
}
$syslinux = file('/boot/syslinux/syslinux.cfg',FILE_IGNORE_NEW_LINES+FILE_SKIP_EMPTY_LINES); file_put_contents('/tmp/syslinux1',print_r($syslinux,true)."\n",FILE_APPEND);
$arrValidBridges = getNetworkBridges();
$pcie_acs_override = detect($syslinux, 'pcie_acs_override');
$vfio_allow_unsafe = detect($syslinux, 'allow_unsafe_interrupts');
$bgcolor = strstr('white,azure',$display['theme']) ? '#f2f2f2' : '#1c1c1c';
?>
<link type="text/css" rel="stylesheet" href="<?autov('/plugins/dynamix.vm.manager/styles/dynamix.vm.manager.css')?>">
<link type="text/css" rel="stylesheet" href="<?autov('/webGui/styles/jquery.filetree.css')?>">
<link type="text/css" rel="stylesheet" href="<?autov('/webGui/styles/jquery.switchbutton.css')?>">
<style>
body{-webkit-overflow-scrolling:touch}
.errortext{color:#EF3D47;display:none}
@@ -73,10 +78,6 @@ body{-webkit-overflow-scrolling:touch}
</style>
<span class="status vhshift"><input type="checkbox" class="advancedview"></span>
<?if ($boolACSEnabled != $boolACSInSyslinux):?>
<br><p class="notice">You must reboot for changes to take effect</p>
<?endif;?>
<form markdown="1" id="settingsForm" method="POST" action="/update.php" target="progressFrame">
<input type="hidden" name="#file" value="<?=htmlspecialchars($domain_cfgfile)?>">
<input type="hidden" name="#command" value="/plugins/dynamix/scripts/emhttpd_update">
@@ -194,15 +195,23 @@ VM shutdown time-out:
> When shutting down the server, this defines how long to wait in seconds for *graceful* VM shutdown before forcing shutdown to continue.
> NOTE: It's recommended to shut down guest VMs from within the VM.
Enable PCIe ACS Override:
PCIe ACS Override:
: <select id="pcie_acs_override" class="narrow">
<?= mk_option(($boolACSInSyslinux ? '1' : '0'), '0', 'No'); ?>
<?= mk_option(($boolACSInSyslinux ? '1' : '0'), '1', 'Yes'); ?>
<?= mk_option($pcie_acs_override, '', 'Disabled'); ?>
<?= mk_option($pcie_acs_override, 'downstream', 'Downstream'); ?>
<?= mk_option($pcie_acs_override, 'multifunction', 'Multifunction'); ?>
<?= mk_option($pcie_acs_override, 'downstream,multifunction', 'Both'); ?>
</select>
> Warning: Use of this setting could cause possible data corruption with certain hardware configurations. Please visit the Lime Technology forums for more information.
> A reboot will be required for changes to this setting to take affect.
VFIO Allow Unsafe Interrupts:
: <select id="vfio_allow_unsafe" class="narrow">
<?= mk_option($vfio_allow_unsafe, '', 'No'); ?>
<?= mk_option($vfio_allow_unsafe, '1', 'Yes'); ?>
</select>
</div>
<?if (file_exists("/var/log/libvirt/libvirtd.log")):?>
<input type="button" onclick="openWindow('/webGui/scripts/tail_log&arg1=libvirt/libvirtd.log','Libvirt Log',600,900);" value="View libvirt log"/>
@@ -211,6 +220,7 @@ Enable PCIe ACS Override:
<?endif;?>
: <input type="button" id="applyBtn" value="Apply" disabled><input type="button" value="Done" onclick="done()">
</form>
<div class="notice reboot" style="display:none;margin-bottom:24px">System must be rebooted for changes to take effect!</div>
<?if (file_exists("/var/log/libvirt/libvirtd.log")):?>
@@ -269,23 +279,17 @@ $(function(){
$("#removeForm").submit();
return;
}
if ($('#pcie_acs_override').val() == '1') {
$.getJSON("/plugins/dynamix.vm.manager/include/VMajax.php", {action: "acs-override-enable"}, function(data) {
$("#settingsForm").submit();
});
} else {
$.getJSON("/plugins/dynamix.vm.manager/include/VMajax.php", {action: "acs-override-disable"}, function(data) {
$("#settingsForm").submit();
});
}
$.getJSON("/plugins/dynamix.vm.manager/include/VMajax.php", {action:'syslinux',pcie:$('#pcie_acs_override').val(),vfio:$('#vfio_allow_unsafe').val()}, function(data){
$("#settingsForm").submit();
});
});
$("#mediadir").on("input change", function() {
$("#mediadir").on("input change", function(){
$("#winvirtio_select").change();
});
var checkDownloadTimer = null;
var checkOrInitDownload = function(checkonly) {
var checkOrInitDownload = function(checkonly){
clearTimeout(checkDownloadTimer);
var $button = $("#download_button");
@@ -300,7 +304,7 @@ $(function(){
$button.removeClass('fa-download').addClass('fa-circle-o-notch fa-spin');
$.post("/plugins/dynamix.vm.manager/include/VMajax.php", postdata, function( data ) {
$.post("/plugins/dynamix.vm.manager/include/VMajax.php", postdata, function(data){
if (postdata.download_version != $('#winvirtio_select').val())
return;
if (data.error) {
@@ -322,7 +326,7 @@ $(function(){
}, "json");
};
$("#SERVICE").change(function changeService() {
$("#SERVICE").change(function changeService(){
if ($(this).val()=='enable') {
$('#arraystopped').fadeIn('slow');
} else {
@@ -442,5 +446,9 @@ $(function(){
$("#applyBtn").val(checked ? "Delete" : "Apply").removeAttr('disabled');
});
}
$.getJSON("/plugins/dynamix.vm.manager/include/VMajax.php", {action:'reboot'}, function(data){
if (data.modified) $('div.notice.reboot').show(); else $('div.notice.reboot').hide();
});
});
</script>

View File

@@ -1,6 +1,7 @@
<?PHP
/* Copyright 2005-2017, Lime Technology
* Copyright 2015-2017, Derek Macias, Eric Schultz, Jon Panozzo.
/* 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,
@@ -25,12 +26,45 @@ function requireLibvirt() {
}
}
function scan($area, $text) {
return strpos($area,$text)!==false;
}
function embed(&$syslinux, $key, $value) {
$size = count($syslinux);
$menu = $i = 0;
$cmd = [];
$make = false;
// find the default section
while ($i < $size) {
if (scan($syslinux[$i],'label ')) {
$n = $i + 1;
// find the current requested setting
while (!scan($syslinux[$n],'label ') && $n < $size) {
if (scan($syslinux[$n],'menu default')) $menu = 1;
if (scan($syslinux[$n],'append')) {$cmd = preg_split('/\s+/',trim($syslinux[$n])); break;}
$n++;
}
if ($menu) break; else $i = $n - 1;
}
$i++;
}
if ($cmd) {
$new = strlen($value) ? "$key=$value" : "";
// replace the existing setting
for ($c = 0; $c < count($cmd); $c++) if (scan($cmd[$c],$key)) {$make = ($cmd[$c]!=$new); $cmd[$c] = $new; break;}
// or insert the new setting
if ($c==count($cmd) && $new) {array_splice($cmd,-1,0,$new); $make = true;}
$syslinux[$n] = ' '.str_replace(' ',' ',implode(' ',$cmd));
}
return $make;
}
$arrSizePrefix = [0 => '', 1 => 'K', 2 => 'M', 3 => 'G', 4 => 'T', 5 => 'P'];
$_REQUEST = array_merge($_GET, $_POST);
$action = $_REQUEST['action'] ?: '';
$uuid = $_REQUEST['uuid'] ?: '';
$_REQUEST = array_merge($_GET, $_POST);
$action = $_REQUEST['action'] ?? '';
$uuid = $_REQUEST['uuid'] ?? '';
$arrResponse = [];
if ($uuid) {
requireLibvirt();
@@ -41,11 +75,7 @@ if ($uuid) {
}
}
$arrResponse = [];
switch ($action) {
case 'domain-autostart':
requireLibvirt();
$arrResponse = $lv->domain_set_autostart($domName, ($_REQUEST['autostart'] != "false")) ?
@@ -345,7 +375,6 @@ switch ($action) {
$arrResponse = $arrValidUSBDevices;
break;
case 'hot-attach-usb':
//TODO - If usb is a block device, then attach as a <disk type="usb"> otherwise <hostdev type="usb">
/*
@@ -355,63 +384,39 @@ switch ($action) {
<product id='0xbeef'/>
</source>
</hostdev>
<disk type='block' device='disk'>
<driver name='qemu' type='raw'/>
<source dev='/dev/sda'/>
<target dev='hdX' bus='virtio'/>
</disk>
*/
break;
case 'hot-detach-usb':
//TODO
break;
case 'acs-override-enable':
// Check each boot option in /boot/syslinux/syslinux.cfg for the existance of pcie_acs_override=downstream, add it in if not found
$arrSyslinuxCfg = file('/boot/syslinux/syslinux.cfg');
$boolModded = false;
foreach ($arrSyslinuxCfg as &$strSyslinuxCfg) {
if (stripos($strSyslinuxCfg, 'append ') !== false) {
if (stripos($strSyslinuxCfg, 'pcie_acs_override=') === false) {
// pcie_acs_override=downstream was not found so append it in
$strSyslinuxCfg = str_ireplace('append ', 'append pcie_acs_override=downstream ', $strSyslinuxCfg);
$boolModded = true;
}
}
}
if ($boolModded) {
// Write Changes to syslinux.cfg
file_put_contents('/boot/syslinux/syslinux.cfg', implode('', $arrSyslinuxCfg));
}
$arrResponse = ['success' => true, 'modified' => $boolModded];
case 'syslinux':
$cfg = '/boot/syslinux/syslinux.cfg';
$syslinux = file($cfg, FILE_IGNORE_NEW_LINES+FILE_SKIP_EMPTY_LINES);
$m1 = embed($syslinux, 'pcie_acs_override', $_REQUEST['pcie']);
$m2 = embed($syslinux, 'vfio_iommu_type1.allow_unsafe_interrupts', $_REQUEST['vfio']);
if ($m1||$m2) file_put_contents($cfg, implode("\n",$syslinux)."\n");
$arrResponse = ['success' => true, 'modified' => $m1|$m2];
break;
case 'acs-override-disable':
// Check the /boot/syslinux/syslinux.cfg for the existance of pcie_acs_override=, remove them if found
$arrSyslinuxCfg = file('/boot/syslinux/syslinux.cfg');
$boolModded = false;
foreach ($arrSyslinuxCfg as &$strSyslinuxCfg) {
if (stripos($strSyslinuxCfg, 'append ') !== false) {
if (stripos($strSyslinuxCfg, 'pcie_acs_override=') !== false) {
// pcie_acs_override= was found so remove the two variations
$strSyslinuxCfg = str_ireplace('pcie_acs_override=downstream ', '', $strSyslinuxCfg);
$strSyslinuxCfg = str_ireplace('pcie_acs_override=multifunction ', '', $strSyslinuxCfg);
$boolModded = true;
}
}
case 'reboot':
$cfg = '/boot/syslinux/syslinux.cfg';
$syslinux = file($cfg, FILE_IGNORE_NEW_LINES+FILE_SKIP_EMPTY_LINES);
$cmdline = explode(' ',file_get_contents('/proc/cmdline'));
$pcie = $vfio = '';
foreach ($cmdline as $cmd) {
if (scan($cmd,'pcie_acs_override')) $pcie = explode('=',$cmd)[1];
if (scan($cmd,'allow_unsafe_interrupts')) $vfio = explode('=',$cmd)[1];
}
if ($boolModded) {
// Write Changes to syslinux.cfg
file_put_contents('/boot/syslinux/syslinux.cfg', implode('', $arrSyslinuxCfg));
}
$arrResponse = ['success' => true, 'modified' => $boolModded];
$m1 = embed($syslinux, 'pcie_acs_override', $pcie);
$m2 = embed($syslinux, 'vfio_iommu_type1.allow_unsafe_interrupts', $vfio);
$arrResponse = ['success' => true, 'modified' => $m1|$m2];
break;
case 'virtio-win-iso-info':
@@ -440,7 +445,6 @@ switch ($action) {
$arrResponse = ['exists' => true, 'pid' => $pid, 'path' => $file];
break;
}
$arrResponse = ['exists' => false, 'pid' => $pid];
break;
@@ -466,9 +470,7 @@ switch ($action) {
$arrResponse['error'] = 'Not enough free space, need at least ' . ceil($arrDownloadVirtIO['size']/1000000).'MB';
break;
}
$boolCheckOnly = !empty($_POST['checkonly']);
$strInstallScript = '/tmp/VirtIOWin_' . $strKeyName . '_install.sh';
$strInstallScriptPgrep = '-f "VirtIOWin_' . $strKeyName . '_install.sh"';
$strTargetFile = $_POST['download_path'] . $arrDownloadVirtIO['name'];
@@ -503,96 +505,62 @@ switch ($action) {
$arrResponse = [];
if (file_exists($strTargetFile)) {
if (!file_exists($strLogFile)) {
if (!pgrep($strDownloadPgrep, false)) {
// Status = done
$arrResponse['status'] = 'Done';
$arrResponse['localpath'] = $strTargetFile;
$arrResponse['localfolder'] = dirname($strTargetFile);
} else {
// Status = cleanup
$arrResponse['status'] = 'Cleanup ... ';
}
} else {
if (pgrep($strDownloadPgrep, false)) {
// Get Download percent completed
$intSize = filesize($strTargetFile);
$strPercent = 0;
if ($intSize > 0) {
$strPercent = round(($intSize / $arrDownloadVirtIO['size']) * 100);
}
$arrResponse['status'] = 'Downloading ... ' . $strPercent . '%';
} elseif (pgrep($strVerifyPgrep, false)) {
// Status = running md5 check
$arrResponse['status'] = 'Verifying ... ';
} elseif (file_exists($strMD5StatusFile)) {
// Status = running extract
$arrResponse['status'] = 'Cleanup ... ';
// Examine md5 status
$strMD5StatusContents = file_get_contents($strMD5StatusFile);
if (strpos($strMD5StatusContents, ': FAILED') !== false) {
// ERROR: MD5 check failed
unset($arrResponse['status']);
$arrResponse['error'] = 'MD5 verification failed, your download is incomplete or corrupted.';
}
} elseif (!file_exists($strMD5File)) {
// Status = running md5 check
$arrResponse['status'] = 'Downloading ... 100%';
if (!pgrep($strInstallScriptPgrep, false) && !$boolCheckOnly) {
// Run all commands
file_put_contents($strInstallScript, $strAllCmd);
chmod($strInstallScript, 0777);
exec($strInstallScript . ' >/dev/null 2>&1 &');
}
}
}
} elseif (!$boolCheckOnly) {
if (!pgrep($strInstallScriptPgrep, false)) {
// Run all commands
file_put_contents($strInstallScript, $strAllCmd);
chmod($strInstallScript, 0777);
exec($strInstallScript . ' >/dev/null 2>&1 &');
}
$arrResponse['status'] = 'Downloading ... ';
}
$arrResponse['pid'] = pgrep($strInstallScriptPgrep, false);
}
break;
case 'virtio-win-iso-cancel':
$arrDownloadVirtIO = [];
$strKeyName = basename($_POST['download_version'], '.iso');
@@ -629,7 +597,6 @@ switch ($action) {
}
break;
case 'virtio-win-iso-remove':
$path = $_REQUEST['path'];
$file = $_REQUEST['file'];
@@ -664,13 +631,10 @@ switch ($action) {
$arrResponse = ['success' => false];
break;
default:
$arrResponse = ['error' => 'Unknown action \'' . $action . '\''];
break;
}
header('Content-Type: application/json');
die(json_encode($arrResponse));