mirror of
https://github.com/unraid/webgui.git
synced 2026-05-21 21:59:27 -05:00
Add timer support
This commit is contained in:
@@ -281,6 +281,7 @@
|
||||
$pciboot = $config['pciboot'];
|
||||
$audios = $config['audio'];
|
||||
$template = $config['template'];
|
||||
$clocks = $config['clock'];
|
||||
|
||||
$type = $domain['type'];
|
||||
$name = $domain['name'];
|
||||
@@ -442,6 +443,7 @@
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
if ($os_type == "windows") $hypervclock = "<timer name='hypervclock' present='yes'/>" ; else $hypervclock = "" ;
|
||||
|
||||
$clock = "<clock offset='" . $domain['clock'] . "'>
|
||||
@@ -465,6 +467,42 @@
|
||||
<timer name='hpet' present='no'/>
|
||||
</clock>";
|
||||
}
|
||||
*/
|
||||
|
||||
$clock = "<clock offset='" . $domain['clock'] . "'>" ;
|
||||
foreach ($clocks as $clockname => $clockvalues) {
|
||||
switch ($clockname){
|
||||
case "rtc":
|
||||
if ($clockvalues['present'] == "yes") $clock .= "<timer name='rtc' tickpolicy='{$clockvalues['tickpolicy']}'/>";
|
||||
break ;
|
||||
case "pit":
|
||||
if ($clockvalues['present'] == "yes") $clock .= "<timer name='pit' tickpolicy='{$clockvalues['tickpolicy']}'/>";
|
||||
break ;
|
||||
case "hpet":
|
||||
$clock .= "<timer name='hpet' present='{$clockvalues['present']}'/>" ;
|
||||
break ;
|
||||
case "hypervclock":
|
||||
$clock .= "<timer name='hypervclock' present='{$clockvalues['present']}'/>" ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
$hyperv = "" ;
|
||||
if ($domain['hyperv'] == 1 && $os_type == "windows") {
|
||||
$hyperv = "<hyperv>
|
||||
<relaxed state='on'/>
|
||||
<vapic state='on'/>
|
||||
<spinlocks state='on' retries='8191'/>
|
||||
<vendor_id state='on' value='none'/>
|
||||
";
|
||||
|
||||
if ($clocks['hypervclock']['present'] == "yes")
|
||||
$hyperv .= "<vpindex state='on'/><synic state='on'/><stimer state='on'/>" ;
|
||||
$hyperv .="</hyperv>";
|
||||
#$clock = "<clock offset='" . $domain['clock'] . "'>
|
||||
# <timer name='hypervclock' present='yes'/>
|
||||
# <timer name='hpet' present='no'/>";
|
||||
}
|
||||
$clock .= "</clock>" ;
|
||||
|
||||
$usbstr = '';
|
||||
if (!empty($usb)) {
|
||||
|
||||
@@ -650,6 +650,64 @@ private static $encoding = 'UTF-8';
|
||||
]
|
||||
];}
|
||||
|
||||
$arrDefaultClocks = [
|
||||
"windows" => [
|
||||
"hpet" => [
|
||||
"present" => "no",
|
||||
"tickpolicy" => "delay"
|
||||
],
|
||||
"hypervclock" => [
|
||||
"present" => "yes",
|
||||
"tickpolicy" => "delay"
|
||||
],
|
||||
"pit" => [
|
||||
"present" => "yes",
|
||||
"tickpolicy" => "delay"
|
||||
],
|
||||
"rtc" => [
|
||||
"present" => "yes",
|
||||
"tickpolicy" => "catchup"
|
||||
]
|
||||
],
|
||||
"hyperv" => [
|
||||
"hpet" => [
|
||||
"present" => "no",
|
||||
"tickpolicy" => "delay"
|
||||
],
|
||||
"hypervclock" => [
|
||||
"present" => "yes",
|
||||
"tickpolicy" => "delay"
|
||||
],
|
||||
"pit" => [
|
||||
"present" => "no",
|
||||
"tickpolicy" => "delay"
|
||||
],
|
||||
"rtc" => [
|
||||
"present" => "no",
|
||||
"tickpolicy" => "catchup"
|
||||
]
|
||||
] ,
|
||||
"other" => [
|
||||
"hpet" => [
|
||||
"present" => "no",
|
||||
"tickpolicy" => "delay"
|
||||
],
|
||||
"hypervclock" => [
|
||||
"present" => "no",
|
||||
"tickpolicy" => "delay"
|
||||
],
|
||||
"pit" => [
|
||||
"present" => "yes",
|
||||
"tickpolicy" => "delay"
|
||||
],
|
||||
"rtc" => [
|
||||
"present" => "yes",
|
||||
"tickpolicy" => "catchup"
|
||||
]
|
||||
]
|
||||
] ;
|
||||
|
||||
|
||||
// Read configuration file (guaranteed to exist)
|
||||
$domain_cfgfile = "/boot/config/domain.cfg";
|
||||
$domain_cfg = parse_ini_file($domain_cfgfile);
|
||||
@@ -1351,7 +1409,7 @@ private static $encoding = 'UTF-8';
|
||||
foreach ($old['devices']['disk'] as $k => $d) if ($source==$d['source']['@attributes']['file']) $new['devices']['disk'][$key]['driver']['@attributes'] = $d['driver']['@attributes'];
|
||||
}
|
||||
// settings not in the GUI, but maybe customized
|
||||
unset($new['clock']);
|
||||
unset($old['clock']);
|
||||
// preserve vnc/spice port settings
|
||||
// unset($new['devices']['graphics']['@attributes']['port'],$new['devices']['graphics']['@attributes']['autoport']);
|
||||
if (!$new['devices']['graphics']) unset($old['devices']['graphics']);
|
||||
@@ -1454,7 +1512,6 @@ private static $encoding = 'UTF-8';
|
||||
$clocks = new SimpleXMLElement($xml);
|
||||
$clocks = json_decode(json_encode($clocks->clock),true) ;
|
||||
$arrClocks = [
|
||||
"offset" => $clocks['@attributes']['offset'] ,
|
||||
"hpet" => [
|
||||
"present" => "no",
|
||||
"tickpolicy" => "delay"
|
||||
@@ -1477,7 +1534,7 @@ private static $encoding = 'UTF-8';
|
||||
$tickpolicy = $timer["@attributes"]["tickpolicy"] ;
|
||||
$present = $timer["@attributes"]["present"] ;
|
||||
if (isset($present)) $arrClocks[$name]['present'] = $present ;
|
||||
if (isset($tickpolicy)) $arrClocks[$name]['tickpolicy'] = $tickpolicy ;
|
||||
if (isset($tickpolicy)) { $arrClocks[$name]['tickpolicy'] = $tickpolicy ; $arrClocks[$name]['present'] = 'yes' ; }
|
||||
}
|
||||
return json_encode($arrClocks) ;
|
||||
}
|
||||
|
||||
@@ -275,6 +275,11 @@
|
||||
$arrConfig['template']['os'] = ($arrConfig['domain']['clock']=='localtime' ? 'windows' : 'linux');
|
||||
}
|
||||
$os_type = ((empty($arrConfig['template']['os']) || stripos($arrConfig['template']['os'], 'windows') === false) ? 'other' : 'windows');
|
||||
if (isset($arrConfig['clocks'])) $arrClocks = json_decode($arrConfig['clocks'],true) ; else {
|
||||
if ($os_type == "windows") {
|
||||
if ($arrConfig['domain']['hyperv'] == 1) $arrClocks = $arrDefaultClocks['hyperv'] ; else $arrClocks = $arrDefaultClocks['windows'] ;
|
||||
} else $arrClocks = $arrDefaultClocks['other'] ;
|
||||
}
|
||||
?>
|
||||
|
||||
<link rel="stylesheet" href="<?autov('/plugins/dynamix.vm.manager/scripts/codemirror/lib/codemirror.css')?>">
|
||||
@@ -288,11 +293,9 @@
|
||||
<input type="hidden" name="template[os]" id="template_os" value="<?=htmlspecialchars($arrConfig['template']['os'])?>">
|
||||
<input type="hidden" name="domain[persistent]" value="<?=htmlspecialchars($arrConfig['domain']['persistent'])?>">
|
||||
<input type="hidden" name="domain[uuid]" value="<?=htmlspecialchars($arrConfig['domain']['uuid'])?>">
|
||||
<input type="hidden" name="domain[clock]" id="domain_clock" value="<?=htmlspecialchars($arrConfig['domain']['clock'])?>">
|
||||
<input type="hidden" name="domain[arch]" value="<?=htmlspecialchars($arrConfig['domain']['arch'])?>">
|
||||
<input type="hidden" name="domain[oldname]" id="domain_oldname" value="<?=htmlspecialchars($arrConfig['domain']['name'])?>">
|
||||
<input type="hidden" name="domain[memoryBacking]" id="domain_memorybacking" value="<?=htmlspecialchars($arrConfig['domain']['memoryBacking'])?>">
|
||||
<input type="hidden" name="clocks" value="<?=htmlspecialchars($arrConfig['clocks'])?>">
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
@@ -1356,7 +1359,7 @@
|
||||
<label for="usb<?=$i?>">    <input type="checkbox" name="usb[]" id="usb<?=$i?>" value="<?=htmlspecialchars($arrDev['id'])?>" <?if (count(array_filter($arrConfig['usb'], function($arr) use ($arrDev) { return ($arr['id'] == $arrDev['id']); }))) echo 'checked="checked"';?>
|
||||
/>         <input type="checkbox" name="usbopt[<?=htmlspecialchars($arrDev['id'])?>]" id="usbopt<?=$i?>" value="<?=htmlspecialchars($arrDev['id'])?>" <?if ($arrDev["startupPolicy"] =="optional") echo 'checked="checked"';?>/>     
|
||||
<input type="number" size="5" maxlength="5" id="usbboot<?=$i?>" class="narrow bootorder" <?=$bootdisable?> style="width: 50px;" name="usbboot[<?=htmlspecialchars($arrDev['id'])?>]" title="_(Boot order)_" value="<?=$arrDev['usbboot']?>" >
|
||||
<?=htmlspecialchars($arrDev['name'])?> (<?=htmlspecialchars($arrDev['id'])?>)</label><br/>
|
||||
<?=htmlspecialchars(substr($arrDev['name'],0,100))?> (<?=htmlspecialchars($arrDev['id'])?>)</label><br/>
|
||||
<?
|
||||
}
|
||||
} else {
|
||||
@@ -1418,19 +1421,7 @@
|
||||
<p>Use boot order to set device as bootable and boot sequence. Only NVMe and Network devices (PCI types 0108 and 02xx) supported for boot order.</p>
|
||||
</blockquote>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>_(QEMU Command Line)_:</td>
|
||||
<td>
|
||||
<textarea id="qemucmdline" name="qemucmdline" rows=15 style="width: 850px"><?=htmlspecialchars($arrConfig['qemucmdline'])?></textarea></td></tr>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<blockquote class="inline_help">
|
||||
<p>If you need to add QEMU arguments to the XML</p>
|
||||
Examples can be found on the Libvirt page => <a href="https://libvirt.org/kbase/qemu-passthrough-security.html " target="_blank">https://libvirt.org/kbase/qemu-passthrough-security.html </a>
|
||||
</p>
|
||||
</blockquote>
|
||||
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
@@ -1454,6 +1445,78 @@
|
||||
<p>Click Create to generate the vDisks and return to the Virtual Machines page where your new VM will be created.</p>
|
||||
</blockquote>
|
||||
<?}?>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td></td> <td>_(Advanced tuning options)_</td></tr>
|
||||
<tr>
|
||||
<td>_(QEMU Command Line)_:</td>
|
||||
<?
|
||||
if ($arrConfig['qemucmdline'] == "") $qemurows = 2 ; else $qemurows = 15 ;
|
||||
?>
|
||||
<td>
|
||||
<textarea id="qemucmdline" name="qemucmdline" rows=<?=$qemurows?> style="width: 850px" onchange="QEMUChgCmd(this)"><?=htmlspecialchars($arrConfig['qemucmdline'])?> </textarea></td></tr>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<blockquote class="inline_help">
|
||||
<p>If you need to add QEMU arguments to the XML</p>
|
||||
Examples can be found on the Libvirt page => <a href="https://libvirt.org/kbase/qemu-passthrough-security.html " target="_blank">https://libvirt.org/kbase/qemu-passthrough-security.html </a>
|
||||
</p>
|
||||
</blockquote>
|
||||
|
||||
<table class="timers">
|
||||
<tr><td></td><td>_(Clocks)_</td></tr>
|
||||
<tr><td>_(Clocks Offset)_:<?=$arrConfig['domain']['clock']?></td>
|
||||
<td>
|
||||
<?$clockdisabled = "" ;?>
|
||||
<select name="domain[clock]" <?=$clockdisabled?> id="clockoffset" class="narrow" title="_(Clock Offset)_" <?=$arrConfig["domain"]['clock']?>>
|
||||
<?
|
||||
echo mk_option($arrConfig['domain']['clock'], 'localtime', 'Localtime');
|
||||
echo mk_option($arrConfig['domain']['clock'], 'utc', "UTC");
|
||||
?>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<?$clockcount = 0 ;
|
||||
if (!empty($arrClocks)) {
|
||||
foreach($arrClocks as $i => $arrTimer) {
|
||||
if ($i =="offset") continue ;
|
||||
if ($clockcount == 0) $clocksourcetext = _("Clocks Source").":" ;else $clocksourcetext = "" ;
|
||||
?>
|
||||
<tr><td><?=$clocksourcetext?></td>
|
||||
<td>
|
||||
<span class="narrow" style="width: 50px"><?=ucfirst($i)?></span></td><td>
|
||||
<span class="narrow" style="width: 50px">_(Present)_:</span>
|
||||
<select name="clock[<?=$i?>][present]" <?=$clockdisabled?> id="clock[<?=$i?>]['present']" class="narrow" title="_(Clock Offset)_" <?=$arrTimer["present"]?>>
|
||||
<?
|
||||
echo mk_option($arrTimer["present"], 'yes', 'Yes');
|
||||
echo mk_option($arrTimer["present"], 'no', "No");
|
||||
?>
|
||||
</select></td><td>
|
||||
<span class="narrow" style="width: 50px">_(Tickpolicy)_:</span>
|
||||
<select name="clock[<?=$i?>][tickpolicy]" <?=$clockdisabled?> id="clock[<?=$i?>]['tickpolicy']" class="narrow" title="_(Clock Offset)_" <?=$arrTimer["tickpolicy"]?>>
|
||||
<?
|
||||
echo mk_option($arrTimer["tickpolicy"], 'delay', 'Delay');
|
||||
echo mk_option($arrTimer["tickpolicy"], 'catchup', 'Catchup');
|
||||
echo mk_option($arrTimer["tickpolicy"], 'merge', "Merge");
|
||||
echo mk_option($arrTimer["tickpolicy"], 'discard', "Discard");
|
||||
?>
|
||||
</select>
|
||||
</td></tr>
|
||||
<?
|
||||
$clockcount++ ;
|
||||
}
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<blockquote class="inline_help">
|
||||
<p>Allows setting of timers and offset into the XML</p>
|
||||
Details can be found on the Libvirt XML page => <a href="https://libvirt.org/formatdomain.html#id25" target="_blank">https://libvirt.org/formatdomain.html#id25 </a>
|
||||
</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
|
||||
<div class="xmlview">
|
||||
@@ -1526,6 +1589,15 @@ function BIOSChange(bios) {
|
||||
}
|
||||
}
|
||||
|
||||
function QEMUChgCmd(qemu) {
|
||||
var value = qemu.value;
|
||||
if (value != "") {
|
||||
document.getElementById("qemucmdline").setAttribute("rows","15");
|
||||
} else {
|
||||
document.getElementById("qemucmdline").setAttribute("rows","2");
|
||||
}
|
||||
}
|
||||
|
||||
function SetBootorderfields(usbbootvalue) {
|
||||
var bootelements = document.getElementsByClassName("bootorder");
|
||||
for(var i = 0; i < bootelements.length; i++) {
|
||||
@@ -2043,6 +2115,7 @@ $(function() {
|
||||
});
|
||||
} else {
|
||||
$('#vmform #domain_clock').val('utc');
|
||||
$('#vmform #clockoffset').val('utc');
|
||||
$("#vmform #domain_machine option").each(function(){
|
||||
if ($(this).val().indexOf('q35') != -1) {
|
||||
$('#vmform #domain_machine').val($(this).val()).change();
|
||||
|
||||
Reference in New Issue
Block a user