diff --git a/emhttp/plugins/dynamix.vm.manager/VMMachines.page b/emhttp/plugins/dynamix.vm.manager/VMMachines.page
index 1fbdbf65e..92addef7c 100644
--- a/emhttp/plugins/dynamix.vm.manager/VMMachines.page
+++ b/emhttp/plugins/dynamix.vm.manager/VMMachines.page
@@ -486,7 +486,7 @@ $(function() {
|
-
+
diff --git a/emhttp/plugins/dynamix.vm.manager/VMTemplates.page b/emhttp/plugins/dynamix.vm.manager/VMTemplates.page
index 3ef5bf021..aa9987861 100644
--- a/emhttp/plugins/dynamix.vm.manager/VMTemplates.page
+++ b/emhttp/plugins/dynamix.vm.manager/VMTemplates.page
@@ -38,6 +38,16 @@ Markdown="false"
if (strpos($strName,"User-") === false) $user = ""; else $user = ' class="user"';
?>
+
+">
+">
+">
+
+
+
+
+
+
endforeach; ?>
-
+
+
+
\ No newline at end of file
+i.export{display:none;font-size:1.8rem;position:left;margin-left:1px}
+
+
+
+
+
+
+
+
+
+
+ true];
break;
+case 'vm-template-save':
+ $template = $_REQUEST['template'];
+ $name = $_REQUEST['name'];
+ $replace = $_REQUEST['replace'];
+
+ if (is_file($name) && $replace == "no"){
+ $arrResponse = ['success' => false, 'error' => _("File exists.")];
+ } else {
+ $error = file_put_contents($name,json_encode($template));
+ if ($error !== false) $arrResponse = ['success' => true];
+ else {
+ $arrResponse = ['success' => false, 'error' => _("File write failed.")];
+ }
+ }
+ break;
+
+case 'vm-template-import':
+ $template = $_REQUEST['template'];
+ $name = $_REQUEST['name'];
+ $replace = $_REQUEST['replace'];
+ $templateslocation = "/boot/config/plugins/dynamix.vm.manager/savedtemplates.json";
+
+ if ($template="*file") {
+ $template=json_decode(file_get_contents($name));
+ }
+
+ $namepathinfo = pathinfo($name);
+ $template_name = $namepathinfo['filename'];
+
+ if (is_file($templateslocation)){
+ $ut = json_decode(file_get_contents($templateslocation),true) ;
+ if (isset($ut[$template_name]) && $replace == "no"){
+ $arrResponse = ['success' => false, 'error' => _("Template exists.")];
+ } else {
+ $ut[$template_name] = $template;
+ $error = file_put_contents($templateslocation,json_encode($ut,JSON_PRETTY_PRINT));;
+ if ($error !== false) $arrResponse = ['success' => true];
+ else {
+ $arrResponse = ['success' => false, 'error' => _("Tempalte file write failed.")];
+ }
+ }
+ }
+ break;
+
default:
$arrResponse = ['error' => _('Unknown action')." '$action'"];
break;
diff --git a/emhttp/plugins/dynamix.vm.manager/include/libvirt.php b/emhttp/plugins/dynamix.vm.manager/include/libvirt.php
index 042a17ae0..5a0a1784c 100644
--- a/emhttp/plugins/dynamix.vm.manager/include/libvirt.php
+++ b/emhttp/plugins/dynamix.vm.manager/include/libvirt.php
@@ -847,6 +847,19 @@
if (($gpu['copypaste'] == "yes") && ($strProtocol == "spice")) $vmrcmousemode = "" ; else $vmrcmousemode = "" ;
if ($strProtocol == "spice") $virtualaudio = "spice" ; else $virtualaudio = "none" ;
+ $strEGLHeadless = "";
+ $strAccel3d ="";
+ if ($strModelType == "virtio3d") {
+ $strModelType = "virtio";
+ if (!isset($gpu['render'])) $gpu['render'] = "auto";
+ if ($gpu['render'] == "auto") {
+ $strEGLHeadless = '';
+ $strAccel3d = "";
+ } else {
+ $strEGLHeadless = '';
+ $strAccel3d ="";
+ }}
+
$vmrc = "
@@ -854,8 +867,11 @@
$vmrcmousemode
+ $strEGLHeadless
";
@@ -2158,7 +2174,7 @@
}
function domain_get_vnc_port($domain) {
- $tmp = $this->get_xpath($domain, '//domain/devices/graphics/@port', false);
+ $tmp = $this->get_xpath($domain, '//domain/devices/graphics[@type="spice" or @type="vnc"]/@port', false);
$var = (int)$tmp[0];
unset($tmp);
@@ -2166,7 +2182,7 @@
}
function domain_get_vmrc_autoport($domain) {
- $tmp = $this->get_xpath($domain, '//domain/devices/graphics/@autoport', false);
+ $tmp = $this->get_xpath($domain, '//domain/devices/graphics[@type="spice" or @type="vnc"]/@autoport', false);
$var = $tmp[0];
unset($tmp);
@@ -2189,6 +2205,23 @@
$var = $tmp[0];
unset($tmp);
+ if ($var=="virtio") {
+ $tmp = $this->get_xpath($domain, '//domain/devices/video/model/acceleration/@accel3d', false);
+ if ($tmp[0] == "yes") $var = "virtio3d";
+ unset($tmp);
+ }
+
+ return $var;
+ }
+
+ function domain_get_vnc_render($domain) {
+ $tmp = $this->get_xpath($domain, '//domain/devices/graphics[@type="egl-headless"]/gl/@rendernode', false);
+ if (!$tmp)
+ return 'auto';
+
+ $var = $tmp[0];
+ unset($tmp);
+ $var = str_replace(['/dev/dri/by-path/pci-0000:','-render'],['',''],$var);
return $var;
}
diff --git a/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php b/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php
index e2e9526ba..fefac0ceb 100644
--- a/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php
+++ b/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php
@@ -866,6 +866,15 @@ private static $encoding = 'UTF-8';
}
}
+ // Attempt to get the boot_vga driver for this pci device
+ $strBootVGA = '';
+ if (is_file('/sys/bus/pci/devices/0000:' . $arrMatch['id'] . '/boot_vga') && $strClass == 'vga') {
+ $strFileVal = file_get_contents('/sys/bus/pci/devices/0000:' . $arrMatch['id'] . '/boot_vga');
+ if (!empty($strFileVal)) {
+ $strBootVGA = trim($strFileVal);
+ }
+ }
+
// Clean up the vendor and product name
$arrMatch['vendorname'] = sanitizeVendor($arrMatch['vendorname']);
$arrMatch['productname'] = sanitizeProduct($arrMatch['productname']);
@@ -880,6 +889,7 @@ private static $encoding = 'UTF-8';
'productname' => $arrMatch['productname'],
'class' => $strClass,
'driver' => $strDriver,
+ 'bootvga' => $strBootVGA,
'name' => $arrMatch['vendorname'] . ' ' . $arrMatch['productname'],
'blacklisted' => $boolBlacklisted
];
@@ -1116,6 +1126,7 @@ private static $encoding = 'UTF-8';
'cirrus' => 'Cirrus',
'qxl' => 'QXL (best)',
'virtio' => 'Virtio(2d)',
+ 'virtio3d' => 'Virtio(3d)',
'vmvga' => 'vmvga'
];
@@ -1269,6 +1280,7 @@ private static $encoding = 'UTF-8';
'autoport' => $autoport,
'copypaste' => $getcopypaste,
'guest' => ['multi' => 'off' ],
+ 'render' => $lv->domain_get_vnc_render($res),
];
}
@@ -1481,7 +1493,7 @@ private static $encoding = 'UTF-8';
unset($old['devices']['input']);
// preserve vnc/spice port settings
// unset($new['devices']['graphics']['@attributes']['port'],$new['devices']['graphics']['@attributes']['autoport']);
- if (!$new['devices']['graphics']) unset($old['devices']['graphics']);
+ unset($old['devices']['graphics']);
if (!isset($new['devices']['graphics']['@attributes']['keymap']) && isset($old['devices']['graphics']['@attributes']['keymap'])) unset($old['devices']['graphics']['@attributes']['keymap']) ;
// update parent arrays
if (!$old['devices']['hostdev']) unset($old['devices']['hostdev']);
diff --git a/emhttp/plugins/dynamix.vm.manager/sheets/VMTemplates-azure.css b/emhttp/plugins/dynamix.vm.manager/sheets/VMTemplates-azure.css
new file mode 100644
index 000000000..795f64a94
--- /dev/null
+++ b/emhttp/plugins/dynamix.vm.manager/sheets/VMTemplates-azure.css
@@ -0,0 +1 @@
+.fileTree{background:#f2f2f2;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:relative;z-index:100;display:none}
\ No newline at end of file
diff --git a/emhttp/plugins/dynamix.vm.manager/sheets/VMTemplates-black.css b/emhttp/plugins/dynamix.vm.manager/sheets/VMTemplates-black.css
new file mode 100644
index 000000000..e708a6b28
--- /dev/null
+++ b/emhttp/plugins/dynamix.vm.manager/sheets/VMTemplates-black.css
@@ -0,0 +1,2 @@
+.fileTree{background:#1c1c1c;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:relative;z-index:100;display:none}
+
diff --git a/emhttp/plugins/dynamix.vm.manager/sheets/VMTemplates-gray.css b/emhttp/plugins/dynamix.vm.manager/sheets/VMTemplates-gray.css
new file mode 100644
index 000000000..e708a6b28
--- /dev/null
+++ b/emhttp/plugins/dynamix.vm.manager/sheets/VMTemplates-gray.css
@@ -0,0 +1,2 @@
+.fileTree{background:#1c1c1c;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:relative;z-index:100;display:none}
+
diff --git a/emhttp/plugins/dynamix.vm.manager/sheets/VMTemplates-white.css b/emhttp/plugins/dynamix.vm.manager/sheets/VMTemplates-white.css
new file mode 100644
index 000000000..bb0fe6cd1
--- /dev/null
+++ b/emhttp/plugins/dynamix.vm.manager/sheets/VMTemplates-white.css
@@ -0,0 +1,2 @@
+.fileTree{background:#f2f2f2;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:relative;z-index:100;display:none}
+
diff --git a/emhttp/plugins/dynamix.vm.manager/sheets/VMTemplates.css b/emhttp/plugins/dynamix.vm.manager/sheets/VMTemplates.css
index 02918f1c1..d3b144267 100644
--- a/emhttp/plugins/dynamix.vm.manager/sheets/VMTemplates.css
+++ b/emhttp/plugins/dynamix.vm.manager/sheets/VMTemplates.css
@@ -2,3 +2,7 @@
.vmtemplate{display:inline-block;width:80px;height:90px;margin-bottom:15px;margin-left:10px;text-align:center;vertical-align:top}
.vmtemplate img{width:48px;height:48px}
.vmtemplate p{text-align:center;margin-top:8px;line-height:12px}
+div.template,div#dialogWindow,input#upload{display:none}
+#resetsort{margin-left:12px;display:inline-block;width:32px}
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button[disabled]{cursor:default;color:#808080;background:-webkit-gradient(linear,left top,right top,from(#404040),to(#808080)) 0 0 no-repeat,-webkit-gradient(linear,left top,right top,from(#404040),to(#808080)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#404040),to(#404040)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#808080),to(#808080)) 100% 100% no-repeat;background:linear-gradient(90deg,#404040 0,#808080) 0 0 no-repeat,linear-gradient(90deg,#404040 0,#808080) 0 100% no-repeat,linear-gradient(0deg,#404040 0,#404040) 0 100% no-repeat,linear-gradient(0deg,#808080 0,#808080) 100% 100% no-repeat;background-size:100% 2px,100% 2px,2px 100%,2px 100%}
+.dropdown-menu{z-index:10001}
diff --git a/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php b/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php
index 616cbd878..3185b9a77 100644
--- a/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php
+++ b/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php
@@ -102,7 +102,8 @@
'keymap' => 'none',
'port' => -1 ,
'wsport' => -1,
- 'copypaste' => 'no'
+ 'copypaste' => 'no',
+ 'render' => 'auto'
]
],
'audio' => [
@@ -1159,8 +1160,8 @@
$arrGPU) {
$strLabel = ($i > 0) ? appendOrdinalSuffix($i + 1) : '';
-
- ?>
+ $bootgpuhidden = " hidden ";
+?>
@@ -1350,6 +1365,7 @@
+ | _(Graphics ROM Needed?)_: | _(GPU is primary adapater, vbios may be required.)_ |
@@ -2084,6 +2100,19 @@ function AutoportChange(autoport) {
}
}
+function VMConsoleDriverChange(driver) {
+ if (driver.value != "virtio3d") {
+ document.getElementById("vncrender").style.visibility="hidden";
+ document.getElementById("vncrendertext").style.visibility="hidden";
+
+ } else {
+ document.getElementById("vncrender").style.display="inline";
+ document.getElementById("vncrender").style.visibility="visible";
+ document.getElementById("vncrendertext").style.display="inline";
+ document.getElementById("vncrendertext").style.visibility="visible";
+ }
+}
+
function ProtocolChange(protocol) {
var autoport = document.getElementById("autoport").value ;
if (autoport == "yes") {
@@ -2391,6 +2420,7 @@ $(function() {
}) ;
$("#vmform").on("change", ".gpu", function changeGPUEvent() {
+ const ValidGPUs = =json_encode($arrValidGPUDevices);?>;
var myvalue = $(this).val();
var mylabel = $(this).children('option:selected').text();
var myindex = $(this).closest('table').data('index');
@@ -2402,6 +2432,13 @@ $(function() {
slideDownRows($vnc_sections.not(isVMAdvancedMode() ? '.basic' : '.advanced'));
var MultiSel = document.getElementById("GPUMultiSel0") ;
MultiSel.disabled = true ;
+ if (document.getElementById("vncmodel").value == "virtio3d") {
+ $("#vncrender").show();
+ $("#vncrendertext").show();
+ } else {
+ $("#vncrender").hide();
+ $("#vncrendertext").hide();
+ }
} else {
slideUpRows($vnc_sections);
$vnc_sections.filter('.advanced').removeClass('advanced').addClass('wasadvanced');
@@ -2410,6 +2447,11 @@ $(function() {
}
}
+ if (mylabel == "None") $("#gpubootvga"+myindex).hide();
+ if (myvalue != 'virtual' && myvalue != '' && myvalue !="nogpu") {
+ if (ValidGPUs[myvalue].bootvga == "1") $("#gpubootvga"+myindex).show(); else $("#gpubootvga"+myindex).hide();
+ }
+
$romfile = $(this).closest('table').find('.romfile');
if (myvalue == 'virtual' || myvalue == '' || myvalue =="nogpu") {
slideUpRows($romfile.not(isVMAdvancedMode() ? '.basic' : '.advanced'));