mirror of
https://github.com/unraid/webgui.git
synced 2026-04-25 20:01:38 -05:00
VM Manager: completely revamp templates, added iso downloader, auto vdisk location
This commit is contained in:
@@ -69,11 +69,7 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
// determine the actual disk if user share is being used
|
||||
if (strpos($folder, '/mnt/user/') === 0) {
|
||||
$tmp = parse_ini_string(shell_exec("getfattr -n user.LOCATION " . escapeshellarg($folder) . " | grep user.LOCATION"));
|
||||
$folder = str_replace('/mnt/user', '/mnt/' . $tmp['user.LOCATION'], $folder); // replace 'user' with say 'cache' or 'disk1' etc
|
||||
}
|
||||
$folder = transpose_user_path($folder);
|
||||
|
||||
@shell_exec("chattr +C -R " . escapeshellarg($folder) . " &>/dev/null");
|
||||
|
||||
@@ -120,7 +116,7 @@
|
||||
}
|
||||
|
||||
if (is_file($disk['image'])) {
|
||||
$json_info = json_decode(shell_exec("qemu-img info --output json " . escapeshellarg($disk['image'])), true);
|
||||
$json_info = getDiskImageInfo($disk['image']);
|
||||
$disk['driver'] = $json_info['format'];
|
||||
|
||||
if (!empty($disk['size'])) {
|
||||
@@ -199,14 +195,33 @@
|
||||
|
||||
|
||||
if (is_file($strImgPath)) {
|
||||
$json_info = json_decode(shell_exec("qemu-img info --output json " . escapeshellarg($strImgPath)), true);
|
||||
$json_info = getDiskImageInfo($strImgPath);
|
||||
$disk['driver'] = $json_info['format'];
|
||||
$return_value = 0;
|
||||
} else {
|
||||
$strLastLine = exec("qemu-img create -q -f " . escapeshellarg($disk['driver']) . " " . escapeshellarg($strImgPath) . " " . escapeshellarg($disk['size']), $output, $return_value);
|
||||
chmod($strImgPath, 0777);
|
||||
chown($strImgPath, 'nobody');
|
||||
chgrp($strImgPath, 'users');
|
||||
$strImgRawLocationPath = $strImgPath;
|
||||
if (!empty($disk['select']) && (!in_array($disk['select'], ['auto', 'manual'])) && (is_dir('/mnt/'.$disk['select']))) {
|
||||
// Force qemu disk creation to happen directly on either cache/disk1/disk2 ect based on dropdown selection
|
||||
$strImgRawLocationPath = str_replace('/mnt/user/', '/mnt/'.$disk['select'].'/', $strImgPath);
|
||||
|
||||
// create folder if needed
|
||||
$strImgRawLocationParent = dirname($strImgRawLocationPath);
|
||||
if (!is_dir($strImgRawLocationParent)) {
|
||||
mkdir($strImgRawLocationParent, 0777, true);
|
||||
chown($strImgRawLocationParent, 'nobody');
|
||||
chgrp($strImgRawLocationParent, 'users');
|
||||
}
|
||||
|
||||
$this->set_folder_nodatacow($strImgRawLocationParent);
|
||||
}
|
||||
|
||||
$strLastLine = exec("qemu-img create -q -f ".escapeshellarg($disk['driver'])." ".escapeshellarg($strImgRawLocationPath)." ".escapeshellarg($disk['size'])." 2>&1", $output, $return_value);
|
||||
|
||||
if (is_file($strImgPath)) {
|
||||
chmod($strImgPath, 0777);
|
||||
chown($strImgPath, 'nobody');
|
||||
chgrp($strImgPath, 'users');
|
||||
}
|
||||
}
|
||||
|
||||
if ($return_value != 0) {
|
||||
@@ -246,40 +261,44 @@
|
||||
$usb = $config['usb'];
|
||||
$shares = $config['shares'];
|
||||
$gpus = $config['gpu'];
|
||||
$pcis = $config['pci'];
|
||||
$audios = $config['audio'];
|
||||
$template = $config['template'];
|
||||
|
||||
|
||||
$type = $domain['type'];
|
||||
$name = $domain['name'];
|
||||
$mem = $domain['mem'];
|
||||
$maxmem = $mem;
|
||||
if (!empty($domain['maxmem'])) {
|
||||
$maxmem = $domain['maxmem'];
|
||||
}
|
||||
$maxmem = (!empty($domain['maxmem'])) ? $domain['maxmem'] : $mem;
|
||||
$uuid = (!empty($domain['uuid']) ? $domain['uuid'] : $this->domain_generate_uuid());
|
||||
$machine = $domain['machine'];
|
||||
$machine_type = (stripos($machine, 'q35') !== false ? 'q35' : 'pc');
|
||||
$os_type = ((empty($template['os']) || stripos($template['os'], 'windows') === false) ? 'other' : 'windows');
|
||||
$emulator = $this->get_default_emulator();
|
||||
//$emulator = $this->get_default_emulator();
|
||||
$emulator = '/usr/local/emhttp/plugins/dynamix.vm.manager/scripts/qemu.sh';
|
||||
$arch = $domain['arch'];
|
||||
$pae = '';
|
||||
if ($arch == 'i686'){
|
||||
$pae = '<pae/>';
|
||||
}
|
||||
$pae = ($arch == 'i686') ? '<pae/>' : '';
|
||||
|
||||
$loader = '';
|
||||
if (!empty($domain['ovmf'])) {
|
||||
$loader = "<loader type='pflash'>/usr/share/qemu/ovmf-x64/OVMF-pure-efi.fd</loader>";
|
||||
if (!is_file('/etc/libvirt/qemu/nvram/'.$uuid.'_VARS-pure-efi.fd')) {
|
||||
// Create a new copy of OVMF VARS for this VM
|
||||
mkdir('/etc/libvirt/qemu/nvram/', 0777, true);
|
||||
copy('/usr/share/qemu/ovmf-x64/OVMF_VARS-pure-efi.fd', '/etc/libvirt/qemu/nvram/'.$uuid.'_VARS-pure-efi.fd');
|
||||
}
|
||||
|
||||
$loader = "<loader readonly='yes' type='pflash'>/usr/share/qemu/ovmf-x64/OVMF_CODE-pure-efi.fd</loader>
|
||||
<nvram>/etc/libvirt/qemu/nvram/".$uuid."_VARS-pure-efi.fd</nvram>";
|
||||
}
|
||||
|
||||
$metadata = '';
|
||||
if (!empty($template)) {
|
||||
$metadata .= "<metadata>";
|
||||
$template_options = '';
|
||||
foreach ($template as $key => $value) {
|
||||
$template_options .= $key . "='" . htmlspecialchars($value, ENT_QUOTES | ENT_XML1) . "' ";
|
||||
}
|
||||
$metadata = "<metadata><vmtemplate " . $template_options . "/></metadata>";
|
||||
$metadata .= "<vmtemplate xmlns='unraid' " . $template_options . "/>";
|
||||
$metadata .= "</metadata>";
|
||||
}
|
||||
|
||||
$vcpus = 1;
|
||||
@@ -297,29 +316,62 @@
|
||||
}
|
||||
}
|
||||
|
||||
$intCores = $vcpus;
|
||||
$intThreads = 1;
|
||||
$intCPUThreadsPerCore = 1;
|
||||
|
||||
$cpumode = '';
|
||||
if (!empty($domain['cpumode']) && $domain['cpumode'] == 'host-passthrough') {
|
||||
$cpumode .= "mode='host-passthrough'";
|
||||
|
||||
// detect if the processor is hyperthreaded:
|
||||
$intCPUThreadsPerCore = max(intval(shell_exec('/usr/bin/lscpu | grep \'Thread(s) per core\' | awk \'{print $4}\'')), 1);
|
||||
|
||||
// even amount of cores assigned and cpu is hyperthreaded: pass that info along to the cpu section below
|
||||
if ($intCPUThreadsPerCore > 1 && ($vcpus % $intCPUThreadsPerCore == 0)) {
|
||||
$intCores = $vcpus / $intCPUThreadsPerCore;
|
||||
$intThreads = $intCPUThreadsPerCore;
|
||||
}
|
||||
}
|
||||
|
||||
$cpustr = "<cpu $cpumode>
|
||||
<topology sockets='1' cores='{$vcpus}' threads='1'/>
|
||||
<topology sockets='1' cores='{$intCores}' threads='{$intThreads}'/>
|
||||
</cpu>
|
||||
<vcpu placement='static'>{$vcpus}</vcpu>
|
||||
<cputune>
|
||||
$vcpupinstr
|
||||
</cputune>";
|
||||
|
||||
$bus = "ide";
|
||||
$usbmode = 'usb3';
|
||||
if (!empty($domain['usbmode'])) {
|
||||
$usbmode = $domain['usbmode'];
|
||||
}
|
||||
|
||||
$ctrl = '';
|
||||
if ($machine_type == 'q35'){
|
||||
$bus = "sata";
|
||||
$ctrl = "<controller type='usb' index='0' model='ich9-ehci1'/>
|
||||
<controller type='usb' index='0' model='ich9-uhci1'/>";
|
||||
if (!empty($domain['ovmf'])) {
|
||||
// OVMF + Q35 needs the bus set to usb for cdroms
|
||||
$bus = "usb";
|
||||
}
|
||||
switch ($usbmode) {
|
||||
case 'usb3':
|
||||
$ctrl = "<controller type='usb' index='0' model='nec-xhci'>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
|
||||
</controller>";
|
||||
break;
|
||||
|
||||
case 'usb2':
|
||||
$ctrl = "<controller type='usb' index='0' model='ich9-ehci1'>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x7'/>
|
||||
</controller>
|
||||
<controller type='usb' index='0' model='ich9-uhci1'>
|
||||
<master startport='0'/>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0' multifunction='on'/>
|
||||
</controller>
|
||||
<controller type='usb' index='0' model='ich9-uhci2'>
|
||||
<master startport='2'/>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x1'/>
|
||||
</controller>
|
||||
<controller type='usb' index='0' model='ich9-uhci3'>
|
||||
<master startport='4'/>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x2'/>
|
||||
</controller>";
|
||||
break;
|
||||
}
|
||||
|
||||
$clock = "<clock offset='" . $domain['clock'] . "'>
|
||||
@@ -334,6 +386,7 @@
|
||||
<relaxed state='on'/>
|
||||
<vapic state='on'/>
|
||||
<spinlocks state='on' retries='8191'/>
|
||||
<vendor id='none'/>
|
||||
</hyperv>";
|
||||
|
||||
$clock = "<clock offset='" . $domain['clock'] . "'>
|
||||
@@ -346,7 +399,7 @@
|
||||
if (!empty($usb)) {
|
||||
foreach($usb as $i => $v){
|
||||
$usbx = explode(':', $v);
|
||||
$usbstr .= "<hostdev mode='subsystem' type='usb' managed='yes'>
|
||||
$usbstr .= "<hostdev mode='subsystem' type='usb'>
|
||||
<source>
|
||||
<vendor id='0x".$usbx[0]."'/>
|
||||
<product id='0x".$usbx[1]."'/>
|
||||
@@ -362,6 +415,11 @@
|
||||
$arrUsedBootOrders = [];
|
||||
|
||||
//media settings
|
||||
$bus = "ide";
|
||||
if ($machine_type == 'q35'){
|
||||
$bus = "sata";
|
||||
}
|
||||
|
||||
$mediastr = '';
|
||||
if (!empty($media['cdrom'])) {
|
||||
unset($arrAvailableDevs['hda']);
|
||||
@@ -369,7 +427,7 @@
|
||||
$mediastr = "<disk type='file' device='cdrom'>
|
||||
<driver name='qemu'/>
|
||||
<source file='" . htmlspecialchars($media['cdrom'], ENT_QUOTES | ENT_XML1) . "'/>
|
||||
<target dev='hda' bus='$bus'/>
|
||||
<target dev='hda' bus='" . (!empty($media['cdrombus']) ? $media['cdrombus'] : $bus) . "'/>
|
||||
<readonly/>
|
||||
<boot order='2'/>
|
||||
</disk>";
|
||||
@@ -381,7 +439,7 @@
|
||||
$driverstr = "<disk type='file' device='cdrom'>
|
||||
<driver name='qemu'/>
|
||||
<source file='" . htmlspecialchars($media['drivers'], ENT_QUOTES | ENT_XML1) . "'/>
|
||||
<target dev='hdb' bus='$bus'/>
|
||||
<target dev='hdb' bus='" . (!empty($media['driversbus']) ? $media['driversbus'] : $bus) . "'/>
|
||||
<readonly/>
|
||||
</disk>";
|
||||
}
|
||||
@@ -390,6 +448,11 @@
|
||||
$diskstr = '';
|
||||
$diskcount = 0;
|
||||
if (!empty($disks)) {
|
||||
|
||||
// force any hard drives to start with hdc, hdd, hde, etc
|
||||
unset($arrAvailableDevs['hda']);
|
||||
unset($arrAvailableDevs['hdb']);
|
||||
|
||||
foreach ($disks as $i => $disk) {
|
||||
if (!empty($disk['image']) | !empty($disk['new']) ) {
|
||||
//TODO: check if image/new is a block device
|
||||
@@ -406,7 +469,7 @@
|
||||
$disk['driver'] = 'raw';
|
||||
|
||||
if (is_file($disk['image'])) {
|
||||
$json_info = json_decode(shell_exec("qemu-img info --output json " . escapeshellarg($disk['image'])), true);
|
||||
$json_info = getDiskImageInfo($disk['image']);
|
||||
$disk['driver'] = $json_info['format'];
|
||||
}
|
||||
}
|
||||
@@ -441,7 +504,7 @@
|
||||
}
|
||||
|
||||
if (is_file($strImgPath)) {
|
||||
$json_info = json_decode(shell_exec("qemu-img info --output json " . escapeshellarg($strImgPath)), true);
|
||||
$json_info = getDiskImageInfo($strImgPath);
|
||||
$disk['driver'] = $json_info['format'];
|
||||
}
|
||||
|
||||
@@ -503,10 +566,15 @@
|
||||
continue;
|
||||
}
|
||||
|
||||
$netmodel = 'virtio';
|
||||
if (!empty($nic['model'])) {
|
||||
$netmodel = $nic['model'];
|
||||
}
|
||||
|
||||
$netstr .= "<interface type='bridge'>
|
||||
<mac address='{$nic['mac']}'/>
|
||||
<source bridge='" . htmlspecialchars($nic['network'], ENT_QUOTES | ENT_XML1) . "'/>
|
||||
<model type='virtio'/>
|
||||
<model type='{$netmodel}'/>
|
||||
</interface>";
|
||||
}
|
||||
}
|
||||
@@ -525,25 +593,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
$passwdstr = '';
|
||||
if (!empty($domain['password'])){
|
||||
$passwdstr = "passwd='" . htmlspecialchars($domain['password'], ENT_QUOTES | ENT_XML1) . "'";
|
||||
}
|
||||
|
||||
$pcidevs='';
|
||||
$gpuargs='';
|
||||
$gpudevs=[];
|
||||
$gpuargsdevs=[];
|
||||
$gpuincr=0;
|
||||
$gpudevs_used=[];
|
||||
$vnc='';
|
||||
if (!empty($gpus)) {
|
||||
foreach ($gpus as $i => $gpu) {
|
||||
if (empty($gpu['id'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip duplicate video devices
|
||||
if (in_array($gpu['id'], $gpudevs)) {
|
||||
if (empty($gpu['id']) || in_array($gpu['id'], $gpudevs_used)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -553,143 +609,96 @@
|
||||
$strKeyMap = "keymap='" . $gpu['keymap'] . "'";
|
||||
}
|
||||
|
||||
$passwdstr = '';
|
||||
if (!empty($domain['password'])){
|
||||
$passwdstr = "passwd='" . htmlspecialchars($domain['password'], ENT_QUOTES | ENT_XML1) . "'";
|
||||
}
|
||||
|
||||
$strModelType = 'qxl';
|
||||
if (!empty($gpu['model'])) {
|
||||
$strModelType = $gpu['model'];
|
||||
|
||||
if (!empty($domain['ovmf']) && $strModelType == 'vmvga') {
|
||||
// OVMF doesn't work with vmvga
|
||||
$strModelType = 'qxl';
|
||||
}
|
||||
}
|
||||
|
||||
$vnc = "<input type='tablet' bus='usb'/>
|
||||
<input type='mouse' bus='ps2'/>
|
||||
<input type='keyboard' bus='ps2'/>
|
||||
<graphics type='vnc' port='-1' autoport='yes' websocket='-1' listen='0.0.0.0' $passwdstr $strKeyMap>
|
||||
<listen type='address' address='0.0.0.0'/>
|
||||
</graphics>";
|
||||
</graphics>
|
||||
<video>
|
||||
<model type='$strModelType'/>
|
||||
</video>";
|
||||
|
||||
$gpudevs_used[] = $gpu['id'];
|
||||
|
||||
if (!empty($domain['ovmf'])) {
|
||||
// OVMF doesn't work with vmvga
|
||||
$vnc .= "<video>
|
||||
<model type='cirrus'/>
|
||||
</video>";
|
||||
} else {
|
||||
// SeaBIOS is cool with vmvga
|
||||
$vnc .= "<video>
|
||||
<model type='vmvga'/>
|
||||
</video>";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
list($gpu_bus, $gpu_slot, $gpu_function) = explode(":", str_replace('.', ':', $gpu['id']));
|
||||
|
||||
if (!empty($domain['ovmf'])) {
|
||||
$pcidevs .= "<hostdev mode='subsystem' type='pci' managed='yes'".((empty($gpudevs_used) && empty($domain['ovmf'])) ? " xvga='on'" : "").">
|
||||
<driver name='vfio'/>
|
||||
<source>
|
||||
<address domain='0x0000' bus='0x".$gpu_bus."' slot='0x".$gpu_slot."' function='0x".$gpu_function."'/>
|
||||
</source>
|
||||
</hostdev>";
|
||||
|
||||
// OVMF passthrough uses the normal hostdev and libvirt can fully manage the device
|
||||
$pcidevs .= "<hostdev mode='subsystem' type='pci' managed='yes'>
|
||||
<driver name='vfio'/>
|
||||
<source>
|
||||
<address domain='0x0000' bus='0x" . $gpu_bus . "' slot='0x" . $gpu_slot . "' function='0x" . $gpu_function . "'/>
|
||||
</source>
|
||||
</hostdev>";
|
||||
|
||||
} else {
|
||||
|
||||
// VGA BIOS passthrough uses qemu args and we have to manage the device (libvirt wont attach/detach the device driver to vfio-pci)
|
||||
switch ($machine_type) {
|
||||
|
||||
case 'q35':
|
||||
$gpuargs .= "<qemu:arg value='-device'/>
|
||||
<qemu:arg value='vfio-pci,host={$gpu_bus}:{$gpu_slot}.{$gpu_function},bus=pcie.0,multifunction=on" . ((empty($gpuargs) && empty($vnc)) ? ',x-vga=on' : '') . "'/>";
|
||||
$gpuargsdevs[$gpu['id']] = ""; // no address needed
|
||||
break;
|
||||
|
||||
case 'pc':
|
||||
$gpuargs .= "<qemu:arg value='-device'/>
|
||||
<qemu:arg value='vfio-pci,host={$gpu_bus}:{$gpu_slot}.{$gpu_function},bus=root.1,addr=0{$gpuincr}.0,multifunction=on" . ((empty($gpuargs) && empty($vnc)) ? ',x-vga=on' : '') . "'/>";
|
||||
$gpuargsdevs[$gpu['id']] = "0{$gpuincr}.0";
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$gpudevs[] = $gpu['id'];
|
||||
$gpuincr++;
|
||||
$gpudevs_used[] = $gpu['id'];
|
||||
}
|
||||
}
|
||||
|
||||
$audioargs='';
|
||||
$audiodevs=[];
|
||||
$audiodevs_used=[];
|
||||
if (!empty($audios)) {
|
||||
foreach ($audios as $i => $audio) {
|
||||
if (empty($audio['id'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip duplicate audio devices
|
||||
if (in_array($audio['id'], $audiodevs)) {
|
||||
if (empty($audio['id']) || in_array($audio['id'], $audiodevs_used)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list($audio_bus, $audio_slot, $audio_function) = explode(":", str_replace('.', ':', $audio['id']));
|
||||
|
||||
if (!empty($domain['ovmf']) || empty($gpuargsdevs)) {
|
||||
$pcidevs .= "<hostdev mode='subsystem' type='pci' managed='yes'>
|
||||
<driver name='vfio'/>
|
||||
<source>
|
||||
<address domain='0x0000' bus='0x".$audio_bus."' slot='0x".$audio_slot."' function='0x".$audio_function."'/>
|
||||
</source>
|
||||
</hostdev>";
|
||||
|
||||
$pcidevs .= "<hostdev mode='subsystem' type='pci' managed='yes'>
|
||||
<driver name='vfio'/>
|
||||
<source>
|
||||
<address domain='0x0000' bus='0x" . $audio_bus . "' slot='0x" . $audio_slot . "' function='0x" . $audio_function . "'/>
|
||||
</source>
|
||||
</hostdev>";
|
||||
|
||||
} else {
|
||||
|
||||
// VGA BIOS passthrough uses qemu args and we have to manage the device (libvirt wont attach/detach the device driver to vfio-pci)
|
||||
switch ($machine_type) {
|
||||
|
||||
case 'q35':
|
||||
$audioargs .= "<qemu:arg value='-device'/>
|
||||
<qemu:arg value='vfio-pci,host={$audio_bus}:{$audio_slot}.{$audio_function},bus=pcie.0'/>";
|
||||
break;
|
||||
|
||||
case 'pc':
|
||||
// Look for video device and see if this sound device is a function of that video card
|
||||
$addr = '';
|
||||
if (isset($gpuargsdevs[$audio_bus . ':' . $audio_slot . '.0'])) {
|
||||
$addr = str_replace('.0', '.' . $audio_function, $gpuargsdevs[$audio_bus . ':' . $audio_slot . '.0']);
|
||||
} else {
|
||||
$addr = "0" . $gpuincr++ . ".0";
|
||||
}
|
||||
|
||||
$audioargs .= "<qemu:arg value='-device'/>
|
||||
<qemu:arg value='vfio-pci,host={$audio_bus}:{$audio_slot}.{$audio_function},bus=root.1,addr=" . $addr . "'/>";
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$audiodevs[] = $audio['id'];
|
||||
$audiodevs_used[] = $audio['id'];
|
||||
}
|
||||
}
|
||||
|
||||
$cmdargs='';
|
||||
if (!empty($gpuargs) || !empty($audioargs)) {
|
||||
switch ($machine_type) {
|
||||
$pcidevs_used=[];
|
||||
if (!empty($pcis)) {
|
||||
foreach ($pcis as $i => $pci_id) {
|
||||
// Skip duplicate other pci devices
|
||||
if (empty($pci_id) || in_array($pci_id, $pcidevs_used)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
case 'q35':
|
||||
$cmdargs .= "<qemu:commandline>
|
||||
<qemu:arg value='-device'/>
|
||||
<qemu:arg value='ioh3420,bus=pcie.0,addr=1c.0,multifunction=on,port=2,chassis=1,id=root.1'/>
|
||||
$gpuargs
|
||||
$audioargs
|
||||
</qemu:commandline>";
|
||||
break;
|
||||
list($pci_bus, $pci_slot, $pci_function) = explode(":", str_replace('.', ':', $pci_id));
|
||||
|
||||
case 'pc':
|
||||
$cmdargs .= "<qemu:commandline>
|
||||
<qemu:arg value='-device'/>
|
||||
<qemu:arg value='ioh3420,bus=pci.0,addr=1c.0,multifunction=on,port=2,chassis=1,id=root.1'/>
|
||||
$gpuargs
|
||||
$audioargs
|
||||
</qemu:commandline>";
|
||||
break;
|
||||
$pcidevs .= "<hostdev mode='subsystem' type='pci' managed='yes'>
|
||||
<driver name='vfio'/>
|
||||
<source>
|
||||
<address domain='0x0000' bus='0x" . $pci_bus . "' slot='0x" . $pci_slot . "' function='0x" . $pci_function . "'/>
|
||||
</source>
|
||||
</hostdev>";
|
||||
|
||||
$pcidevs_used[] = $pci_id;
|
||||
}
|
||||
}
|
||||
|
||||
$memorybacking='<nosharepages/>';
|
||||
if (!empty($pcidevs)) {
|
||||
$memorybacking .= '<locked/>';
|
||||
}
|
||||
|
||||
|
||||
return "<domain type='$type' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
|
||||
<uuid>$uuid</uuid>
|
||||
@@ -699,8 +708,7 @@
|
||||
<currentMemory>$mem</currentMemory>
|
||||
<memory>$maxmem</memory>
|
||||
<memoryBacking>
|
||||
<nosharepages/>
|
||||
<locked/>
|
||||
$memorybacking
|
||||
</memoryBacking>
|
||||
$cpustr
|
||||
<os>
|
||||
@@ -736,7 +744,6 @@
|
||||
<alias name='balloon0'/>
|
||||
</memballoon>
|
||||
</devices>
|
||||
$cmdargs
|
||||
</domain>";
|
||||
|
||||
}
|
||||
@@ -1538,6 +1545,12 @@
|
||||
if (!$dom)
|
||||
return false;
|
||||
|
||||
$uuid = $this->domain_get_uuid($dom);
|
||||
// remove OVMF VARS if this domain had them
|
||||
if (is_file('/etc/libvirt/qemu/nvram/'.$uuid.'_VARS-pure-efi.fd')) {
|
||||
unlink('/etc/libvirt/qemu/nvram/'.$uuid.'_VARS-pure-efi.fd');
|
||||
}
|
||||
|
||||
$tmp = libvirt_domain_undefine($dom);
|
||||
return ($tmp) ? $tmp : $this->_set_last_error();
|
||||
}
|
||||
@@ -1547,7 +1560,7 @@
|
||||
if (!$dom)
|
||||
return false;
|
||||
$disks = $this->get_disk_stats($dom);
|
||||
$tmp = libvirt_domain_undefine($dom);
|
||||
$tmp = $this->domain_undefine($dom);
|
||||
if (!$tmp)
|
||||
return $this->_set_last_error();
|
||||
|
||||
@@ -1559,24 +1572,39 @@
|
||||
|
||||
// remove the vm config
|
||||
$cfg_vm = $dir.'/'.$domain.'.cfg';
|
||||
if (file_exists($cfg_vm));
|
||||
unlink($cfg_vm);
|
||||
if (is_file($cfg_vm)) unlink($cfg_vm);
|
||||
|
||||
$cfg = $dir.'/'.$pathinfo['filename'].'.cfg';
|
||||
$xml = $dir.'/'.$pathinfo['filename'].'.xml';
|
||||
if (file_exists($disk));
|
||||
unlink($disk);
|
||||
if (file_exists($cfg));
|
||||
unlink($cfg);
|
||||
if (file_exists($xml));
|
||||
unlink($xml);
|
||||
if (is_dir($dir) && $this->is_dir_empty($dir))
|
||||
rmdir($dir);
|
||||
if (is_file($disk)) unlink($disk);
|
||||
if (is_file($cfg)) unlink($cfg);
|
||||
if (is_file($xml)) unlink($xml);
|
||||
if (is_dir($dir) && $this->is_dir_empty($dir)) rmdir($dir);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function nvram_backup($uuid) {
|
||||
// move OVMF VARS to a backup file if this domain has them
|
||||
if (is_file('/etc/libvirt/qemu/nvram/'.$uuid.'_VARS-pure-efi.fd')) {
|
||||
rename('/etc/libvirt/qemu/nvram/'.$uuid.'_VARS-pure-efi.fd', '/etc/libvirt/qemu/nvram/'.$uuid.'_VARS-pure-efi.fd_backup');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function nvram_restore($uuid) {
|
||||
// restore backup OVMF VARS if this domain had them
|
||||
if (is_file('/etc/libvirt/qemu/nvram/'.$uuid.'_VARS-pure-efi.fd_backup')) {
|
||||
rename('/etc/libvirt/qemu/nvram/'.$uuid.'_VARS-pure-efi.fd_backup', '/etc/libvirt/qemu/nvram/'.$uuid.'_VARS-pure-efi.fd');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function is_dir_empty($dir) {
|
||||
if (!is_readable($dir)) return NULL;
|
||||
$handle = opendir($dir);
|
||||
@@ -1637,6 +1665,17 @@
|
||||
return $var;
|
||||
}
|
||||
|
||||
function domain_get_vnc_model($domain) {
|
||||
$tmp = $this->get_xpath($domain, '//domain/devices/video/model/@type', false);
|
||||
if (!$tmp)
|
||||
return 'qxl';
|
||||
|
||||
$var = $tmp[0];
|
||||
unset($tmp);
|
||||
|
||||
return $var;
|
||||
}
|
||||
|
||||
function domain_get_vnc_keymap($domain) {
|
||||
$tmp = $this->get_xpath($domain, '//domain/devices/graphics/@keymap', false);
|
||||
if (!$tmp)
|
||||
|
||||
@@ -16,35 +16,381 @@
|
||||
if (! isset($var)){
|
||||
if (! is_file("/usr/local/emhttp/state/var.ini")) shell_exec("wget -qO /dev/null localhost:$(lsof -nPc emhttp | grep -Po 'TCP[^\d]*\K\d+')");
|
||||
$var = @parse_ini_file("/usr/local/emhttp/state/var.ini");
|
||||
$disks = @parse_ini_file("/usr/local/emhttp/state/disks.ini", true);
|
||||
extract(parse_plugin_cfg("dynamix",true));
|
||||
}
|
||||
|
||||
|
||||
// Check if program is running and
|
||||
$libvirt_running = trim(shell_exec( "[ -f /proc/`cat /var/run/libvirt/libvirtd.pid 2> /dev/null`/exe ] && echo 'yes' || echo 'no' 2> /dev/null" ));
|
||||
|
||||
|
||||
$arrAllTemplates = [
|
||||
' Windows ' => '', /* Windows Header */
|
||||
|
||||
'Windows 10' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'windows.png',
|
||||
'os' => 'windows10',
|
||||
'overrides' => [
|
||||
'domain' => [
|
||||
'mem' => 2048 * 1024,
|
||||
'maxmem' => 2048 * 1024
|
||||
],
|
||||
'disk' => [
|
||||
[
|
||||
'size' => '30G'
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
|
||||
'Windows 8.x' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'windows.png',
|
||||
'os' => 'windows',
|
||||
'overrides' => [
|
||||
'domain' => [
|
||||
'name' => 'Windows 8.1',
|
||||
'mem' => 2048 * 1024,
|
||||
'maxmem' => 2048 * 1024
|
||||
],
|
||||
'disk' => [
|
||||
[
|
||||
'size' => '30G'
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
|
||||
'Windows 7' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'windows7.png',
|
||||
'os' => 'windows7',
|
||||
'overrides' => [
|
||||
'domain' => [
|
||||
'mem' => 2048 * 1024,
|
||||
'maxmem' => 2048 * 1024,
|
||||
'ovmf' => 0,
|
||||
'usbmode' => 'usb2'
|
||||
],
|
||||
'disk' => [
|
||||
[
|
||||
'size' => '30G'
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
|
||||
'Windows XP' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'windowsxp.png',
|
||||
'os' => 'windowsxp',
|
||||
'overrides' => [
|
||||
'domain' => [
|
||||
'ovmf' => 0,
|
||||
'usbmode' => 'usb2'
|
||||
],
|
||||
'disk' => [
|
||||
[
|
||||
'size' => '15G'
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
|
||||
'Windows Server 2016' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'windows.png',
|
||||
'os' => 'windows2016',
|
||||
'overrides' => [
|
||||
'domain' => [
|
||||
'mem' => 2048 * 1024,
|
||||
'maxmem' => 2048 * 1024
|
||||
],
|
||||
'disk' => [
|
||||
[
|
||||
'size' => '30G'
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
|
||||
'Windows Server 2012' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'windows.png',
|
||||
'os' => 'windows2012',
|
||||
'overrides' => [
|
||||
'domain' => [
|
||||
'mem' => 2048 * 1024,
|
||||
'maxmem' => 2048 * 1024
|
||||
],
|
||||
'disk' => [
|
||||
[
|
||||
'size' => '30G'
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
|
||||
'Windows Server 2008' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'windowsxp.png',
|
||||
'os' => 'windows2008',
|
||||
'overrides' => [
|
||||
'domain' => [
|
||||
'usbmode' => 'usb2'
|
||||
],
|
||||
'disk' => [
|
||||
[
|
||||
'size' => '30G'
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
|
||||
'Windows Server 2003' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'windowsxp.png',
|
||||
'os' => 'windows2003',
|
||||
'overrides' => [
|
||||
'domain' => [
|
||||
'usbmode' => 'usb2'
|
||||
],
|
||||
'disk' => [
|
||||
[
|
||||
'size' => '15G'
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
|
||||
|
||||
' Pre-packaged ' => '', /* Pre-built Header */
|
||||
|
||||
'OpenELEC' => [
|
||||
'form' => 'OpenELEC.form.php',
|
||||
'icon' => 'openelec.png'
|
||||
],
|
||||
|
||||
|
||||
' Linux ' => '', /* Linux Header */
|
||||
|
||||
'Linux' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'linux.png',
|
||||
'os' => 'linux'
|
||||
],
|
||||
'Arch' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'arch.png',
|
||||
'os' => 'arch'],
|
||||
'CentOS' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'centos.png',
|
||||
'os' => 'centos'
|
||||
],
|
||||
'ChromeOS' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'chromeos.png',
|
||||
'os' => 'chromeos'
|
||||
],
|
||||
'CoreOS' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'coreos.png',
|
||||
'os' => 'coreos'
|
||||
],
|
||||
'Debian' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'debian.png',
|
||||
'os' => 'debian'
|
||||
],
|
||||
'Fedora' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'fedora.png',
|
||||
'os' => 'fedora'
|
||||
],
|
||||
'FreeBSD' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'freebsd.png',
|
||||
'os' => 'freebsd'
|
||||
],
|
||||
'OpenSUSE' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'opensuse.png',
|
||||
'os' => 'opensuse'
|
||||
],
|
||||
'RedHat' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'redhat.png',
|
||||
'os' => 'redhat'
|
||||
],
|
||||
'Scientific' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'scientific.png',
|
||||
'os' => 'scientific'
|
||||
],
|
||||
'Slackware' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'slackware.png',
|
||||
'os' => 'slackware'
|
||||
],
|
||||
'SteamOS' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'steamos.png',
|
||||
'os' => 'steamos'
|
||||
],
|
||||
'Ubuntu' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'ubuntu.png',
|
||||
'os' => 'ubuntu'
|
||||
],
|
||||
'VyOS' => [
|
||||
'form' => 'Custom.form.php',
|
||||
'icon' => 'vyos.png',
|
||||
'os' => 'vyos'
|
||||
],
|
||||
|
||||
|
||||
' ' => '', /* Custom / XML Expert Header */
|
||||
|
||||
'Custom' => [
|
||||
'form' => 'XML_Expert.form.php',
|
||||
'icon' => 'default.png'
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
$virtio_isos = [
|
||||
'virtio-win-0.1.110-2' => [
|
||||
'name' => 'virtio-win-0.1.110-2.iso',
|
||||
'url' => 'https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.110-2/virtio-win-0.1.110.iso',
|
||||
'size' => 56586240,
|
||||
'md5' => '93357a5105f1255591f1c389748288a9'
|
||||
],
|
||||
'virtio-win-0.1.110-1' => [
|
||||
'name' => 'virtio-win-0.1.110-1.iso',
|
||||
'url' => 'https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.110-1/virtio-win-0.1.110.iso',
|
||||
'size' => 56586240,
|
||||
'md5' => '239e0eb442bb63c177deb4af39397731'
|
||||
],
|
||||
'virtio-win-0.1.109-2' => [
|
||||
'name' => 'virtio-win-0.1.109-2.iso',
|
||||
'url' => 'https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.109-2/virtio-win-0.1.109.iso',
|
||||
'size' => 56606720,
|
||||
'md5' => '2a9f78f648f03fe72decdadb38837db3'
|
||||
],
|
||||
'virtio-win-0.1.109-1' => [
|
||||
'name' => 'virtio-win-0.1.109-1.iso',
|
||||
'url' => 'https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.109-1/virtio-win-0.1.109.iso',
|
||||
'size' => 56606720,
|
||||
'md5' => '1b0da008d0ec79a6223d21be2fcce2ee'
|
||||
],
|
||||
'virtio-win-0.1.108-1' => [
|
||||
'name' => 'virtio-win-0.1.108-1.iso',
|
||||
'url' => 'https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.108-1/virtio-win-0.1.108.iso',
|
||||
'size' => 56598528,
|
||||
'md5' => '46deb991f8c382f2d9af0fb786792990'
|
||||
],
|
||||
'virtio-win-0.1.106-1' => [
|
||||
'name' => 'virtio-win-0.1.106-1.iso',
|
||||
'url' => 'https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.106-1/virtio-win-0.1.106.iso',
|
||||
'size' => 56586240,
|
||||
'md5' => '66228ea20fae1a28d7a1583b9a5a1b8b'
|
||||
],
|
||||
'virtio-win-0.1.105-1' => [
|
||||
'name' => 'virtio-win-0.1.105-1.iso',
|
||||
'url' => 'https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.105-1/virtio-win-0.1.105.iso',
|
||||
'size' => 56584192,
|
||||
'md5' => 'c3194fa62a4a1ccbecfe784a52feda66'
|
||||
],
|
||||
'virtio-win-0.1.104-1' => [
|
||||
'name' => 'virtio-win-0.1.104-1.iso',
|
||||
'url' => 'https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.104-1/virtio-win-0.1.104.iso',
|
||||
'size' => 56584192,
|
||||
'md5' => '9aa28b6f5b18770d796194aaaeeea31a'
|
||||
],
|
||||
'virtio-win-0.1.103-2' => [
|
||||
'name' => 'virtio-win-0.1.103-2.iso',
|
||||
'url' => 'https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.103-2/virtio-win-0.1.103.iso',
|
||||
'size' => 56340480,
|
||||
'md5' => '07c4356880f0b385d6908392e48d6e75'
|
||||
],
|
||||
'virtio-win-0.1.103' => [
|
||||
'name' => 'virtio-win-0.1.103.iso',
|
||||
'url' => 'https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.103/virtio-win-0.1.103.iso',
|
||||
'size' => 49903616,
|
||||
'md5' => 'd31069b620820b75730d2def7690c271'
|
||||
],
|
||||
'virtio-win-0.1.102' => [
|
||||
'name' => 'virtio-win-0.1.102.iso',
|
||||
'url' => 'https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.102/virtio-win-0.1.102.iso',
|
||||
'size' => 160755712,
|
||||
'md5' => '712561dd78ef532c54f8fee927c1ce2e'
|
||||
],
|
||||
'virtio-win-0.1.101' => [
|
||||
'name' => 'virtio-win-0.1.101.iso',
|
||||
'url' => 'https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.101/virtio-win-0.1.101.iso',
|
||||
'size' => 160755712,
|
||||
'md5' => 'cf73576efc03685907c1fa49180ea388'
|
||||
],
|
||||
'virtio-win-0.1.100' => [
|
||||
'name' => 'virtio-win-0.1.100.iso',
|
||||
'url' => 'https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.100/virtio-win-0.1.100.iso',
|
||||
'size' => 160704512,
|
||||
'md5' => '8b21136f988bef7981ee580e9101b6b4'
|
||||
],
|
||||
'virtio-win-0.1.96' => [
|
||||
'name' => 'virtio-win-0.1.96.iso',
|
||||
'url' => 'https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.96/virtio-win-0.1.96.iso',
|
||||
'size' => 160659456,
|
||||
'md5' => 'd406bf6748b9ba4c872c5b5301ba7272'
|
||||
]
|
||||
];
|
||||
|
||||
$domain_cfg_defaults = [
|
||||
"SERVICE" => "disable",
|
||||
"DEBUG" => "no",
|
||||
"DOMAINDIR" => "/mnt/user/domains/",
|
||||
"MEDIADIR" => "/mnt/user/isos/",
|
||||
"VIRTIOISO" => "",
|
||||
"BRNAME" => "",
|
||||
"VMSTORAGEMODE" => "auto"
|
||||
];
|
||||
$domain_cfg = $domain_cfg_defaults;
|
||||
|
||||
// Create domain config if needed
|
||||
$domain_cfgfile = "/boot/config/domain.cfg";
|
||||
if (!file_exists($domain_cfgfile)) {
|
||||
file_put_contents($domain_cfgfile, 'SERVICE="disable"'."\n".'DEBUG="no"'."\n".'MEDIADIR="/mnt/"'."\n".'VIRTIOISO=""'."\n".'DISKDIR="/mnt/"'."\n".'BRNAME=""'."\n");
|
||||
$tmp = '';
|
||||
foreach ($domain_cfg_defaults as $key => $value) $tmp .= "$key=\"$value\"\n";
|
||||
file_put_contents($domain_cfgfile, $tmp);
|
||||
} else {
|
||||
// This will clean any ^M characters (\r) caused by windows from the config file
|
||||
shell_exec("sed -i 's!\r!!g' '$domain_cfgfile'");
|
||||
|
||||
$domain_cfg_existing = parse_ini_file($domain_cfgfile);
|
||||
if (!empty($domain_cfg_existing)) {
|
||||
$domain_cfg = array_merge($domain_cfg_defaults, $domain_cfg_existing);
|
||||
}
|
||||
}
|
||||
|
||||
$domain_cfg = parse_ini_file($domain_cfgfile);
|
||||
|
||||
if (!isset($domain_cfg['VIRTIOISO'])) {
|
||||
$domain_cfg['VIRTIOISO'] = "";
|
||||
}
|
||||
|
||||
$domain_debug = isset($domain_cfg['DEBUG']) ? $domain_cfg['DEBUG'] : "no";
|
||||
if ($domain_debug != "yes") {
|
||||
if ($domain_cfg['DEBUG'] != "yes") {
|
||||
error_reporting(0);
|
||||
}
|
||||
|
||||
if (empty($domain_cfg['VMSTORAGEMODE'])) {
|
||||
$domain_cfg['VMSTORAGEMODE'] = "auto";
|
||||
}
|
||||
if (!empty($domain_cfg['DOMAINDIR'])) {
|
||||
$domain_cfg['DOMAINDIR'] = rtrim($domain_cfg['DOMAINDIR'], '/') . '/';
|
||||
}
|
||||
if (!empty($domain_cfg['MEDIADIR'])) {
|
||||
$domain_cfg['MEDIADIR'] = rtrim($domain_cfg['MEDIADIR'], '/') . '/';
|
||||
}
|
||||
|
||||
$domain_bridge = (!($domain_cfg['BRNAME'])) ? 'virbr0' : $domain_cfg['BRNAME'];
|
||||
$msg = (empty($domain_bridge)) ? "Error: Setup Bridge in Settings/Network Settings" : false;
|
||||
$libvirt_service = isset($domain_cfg['SERVICE']) ? $domain_cfg['SERVICE'] : "disable";
|
||||
$libvirt_service = isset($domain_cfg['SERVICE']) ? $domain_cfg['SERVICE'] : "disable";
|
||||
|
||||
if ($libvirt_running == "yes"){
|
||||
$lv = new Libvirt('qemu:///system', null, null, false);
|
||||
@@ -53,55 +399,16 @@
|
||||
$maxmem = number_format(($arrHostInfo['memory'] / 1048576), 1, '.', ' ');
|
||||
}
|
||||
|
||||
$theme = $display['theme'];
|
||||
//set color on even rows for white or black theme
|
||||
function bcolor($row, $color) {
|
||||
if ($color == "white")
|
||||
$color = ($row % 2 == 0) ? "transparent" : "#F8F8F8";
|
||||
else
|
||||
$color = ($row % 2 == 0) ? "transparent" : "#0C0C0C";
|
||||
return $color;
|
||||
}
|
||||
function bcolor($row) {
|
||||
global $display;
|
||||
|
||||
//create checkboxes for usb devices
|
||||
function usb_checkbox($usb, $key) {
|
||||
$deviceid = substr(strstr($usb, 'ID'),3,9);
|
||||
echo '<input class="checkbox" type="checkbox" value="'.$deviceid.'" name="usb['.$key.']" />';
|
||||
echo "<label>$usb</label><br />";
|
||||
}
|
||||
if (empty($display) || $display['theme'] == "white")
|
||||
return ($row % 2 == 0) ? "transparent" : "#F8F8F8";
|
||||
|
||||
//create memory drop down option based on max memory
|
||||
function memOption($maxmem) {
|
||||
for ($i = 1; $i <= ($maxmem*2); $i++) {
|
||||
$mem = ($i*512);
|
||||
echo "<option value='$mem'>$mem</option>";
|
||||
}
|
||||
return ($row % 2 == 0) ? "transparent" : "#0C0C0C";
|
||||
}
|
||||
|
||||
//create drop down options from arrays
|
||||
function arrayOptions($ValueArray, $DisplayArray, $value) {
|
||||
for ($i = 0; $i < sizeof($ValueArray); $i++) {
|
||||
echo "<option value='$ValueArray[$i]'";
|
||||
if ($ValueArray[$i] == $value)
|
||||
echo " selected='selected'>$DisplayArray[$i] *</option>";
|
||||
else
|
||||
echo ">$DisplayArray[$i]</option>";
|
||||
}
|
||||
}
|
||||
|
||||
//create memory drop down options
|
||||
function memOptions($maxmem, $mem) {
|
||||
for ($i = 1; $i <= ($maxmem*2); $i++) {
|
||||
$mem2 = ($i*512);
|
||||
echo "<option value=".$mem2*1024;
|
||||
if ((int)$mem == $mem2*1024)
|
||||
echo " selected='selected'>$mem2 *</option>";
|
||||
else
|
||||
echo ">$mem2</option>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function mk_dropdown_options($arrOptions, $strSelected) {
|
||||
foreach ($arrOptions as $key => $label) {
|
||||
echo mk_option($strSelected, $key, $label);
|
||||
@@ -120,6 +427,11 @@
|
||||
return $abbreviation;
|
||||
}
|
||||
|
||||
function getDiskImageInfo($strImgPath) {
|
||||
$arrJSON = json_decode(shell_exec("qemu-img info --output json " . escapeshellarg($strImgPath) . " 2>/dev/null"), true);
|
||||
return $arrJSON;
|
||||
}
|
||||
|
||||
|
||||
$cacheValidPCIDevices = null;
|
||||
function getValidPCIDevices() {
|
||||
@@ -177,6 +489,15 @@
|
||||
continue;
|
||||
}
|
||||
|
||||
// Attempt to get the current kernel-bound driver for this pci device
|
||||
$strDriver = '';
|
||||
if (is_link('/sys/bus/pci/devices/0000:' . $arrMatch['id'] . '/driver')) {
|
||||
$strLink = @readlink('/sys/bus/pci/devices/0000:' . $arrMatch['id'] . '/driver');
|
||||
if (!empty($strLink)) {
|
||||
$strDriver = basename($strLink);
|
||||
}
|
||||
}
|
||||
|
||||
// Specialized vendor name cleanup
|
||||
// e.g.: Advanced Micro Devices, Inc. [AMD/ATI] --> Advanced Micro Devices, Inc.
|
||||
if (preg_match('/(?P<gpuvendor>.+) \[.+\]/', $arrMatch['vendorname'], $arrGPUMatch)) {
|
||||
@@ -197,6 +518,7 @@
|
||||
'productid' => $arrMatch['productid'],
|
||||
'productname' => $arrMatch['productname'],
|
||||
'class' => $strClass,
|
||||
'driver' => $strDriver,
|
||||
'name' => $arrMatch['vendorname'] . ' ' . $arrMatch['productname']
|
||||
);
|
||||
}
|
||||
@@ -241,6 +563,17 @@
|
||||
}
|
||||
|
||||
|
||||
function getValidOtherStubbedDevices() {
|
||||
$arrValidPCIDevices = getValidPCIDevices();
|
||||
|
||||
$arrValidOtherStubbedDevices = array_filter($arrValidPCIDevices, function($arrDev) {
|
||||
return ($arrDev['class'] == 'other' && in_array($arrDev['driver'], ['pci-stub', 'vfio-pci']));
|
||||
});
|
||||
|
||||
return $arrValidOtherStubbedDevices;
|
||||
}
|
||||
|
||||
|
||||
$cacheValidUSBDevices = null;
|
||||
function getValidUSBDevices() {
|
||||
global $cacheValidUSBDevices;
|
||||
@@ -346,6 +679,29 @@
|
||||
}
|
||||
|
||||
|
||||
function getValidBusTypes() {
|
||||
$arrValidBusTypes = [
|
||||
'virtio' => 'VirtIO',
|
||||
'sata' => 'SATA',
|
||||
'ide' => 'IDE',
|
||||
'usb' => 'USB'
|
||||
];
|
||||
|
||||
return $arrValidBusTypes;
|
||||
}
|
||||
|
||||
|
||||
function getValidVNCModels() {
|
||||
$arrValidVNCModels = [
|
||||
'cirrus' => 'Cirrus',
|
||||
'qxl' => 'QXL (best)',
|
||||
'vmvga' => 'vmvga'
|
||||
];
|
||||
|
||||
return $arrValidVNCModels;
|
||||
}
|
||||
|
||||
|
||||
function getValidKeyMaps() {
|
||||
$arrValidKeyMaps = [
|
||||
'ar' => 'Arabic (ar)',
|
||||
@@ -414,6 +770,7 @@
|
||||
|
||||
function domain_to_config($uuid) {
|
||||
global $lv;
|
||||
global $domain_cfg;
|
||||
|
||||
$arrValidGPUDevices = getValidGPUDevices();
|
||||
$arrValidAudioDevices = getValidAudioDevices();
|
||||
@@ -436,7 +793,7 @@
|
||||
$xmldoc = new DOMDocument();
|
||||
$xmldoc->loadXML($strDOMXML);
|
||||
$xpath = new DOMXPath($xmldoc);
|
||||
$objNodes = $xpath->query('//domain/metadata/vmtemplate/@*');
|
||||
$objNodes = $xpath->query('//domain/metadata/*[local-name()=\'vmtemplate\']/@*');
|
||||
|
||||
$arrTemplateValues = [];
|
||||
if ($objNodes->length > 0) {
|
||||
@@ -459,6 +816,7 @@
|
||||
if (!empty($intVNCPort)) {
|
||||
$arrGPUDevices[] = [
|
||||
'id' => 'vnc',
|
||||
'model' => $lv->domain_get_vnc_model($res),
|
||||
'keymap' => $lv->domain_get_vnc_keymap($res)
|
||||
];
|
||||
}
|
||||
@@ -500,10 +858,17 @@
|
||||
'size' => '',
|
||||
'driver' => 'raw',
|
||||
'dev' => $disk['device'],
|
||||
'bus' => $disk['bus']
|
||||
'bus' => $disk['bus'],
|
||||
'select' => $domain_cfg['VMSTORAGEMODE']
|
||||
];
|
||||
}
|
||||
|
||||
// HACK: If there's only 1 cdrom and the dev=hdb then it's most likely a VirtIO Driver ISO instead of the OS Install ISO
|
||||
if (!empty($medias) && count($medias) == 1 && array_key_exists('device', $medias[0]) && $medias[0]['device'] == 'hdb') {
|
||||
$medias[] = null;
|
||||
$medias = array_reverse($medias);
|
||||
}
|
||||
|
||||
return [
|
||||
'template' => $arrTemplateValues,
|
||||
'domain' => [
|
||||
@@ -523,11 +888,14 @@
|
||||
'hyperv' => ($lv->domain_get_feature($res, 'hyperv') ? 1 : 0),
|
||||
'autostart' => ($lv->domain_get_autostart($res) ? 1 : 0),
|
||||
'state' => $lv->domain_state_translate($dom['state']),
|
||||
'ovmf' => ($lv->domain_get_ovmf($res) ? 1 : 0)
|
||||
'ovmf' => ($lv->domain_get_ovmf($res) ? 1 : 0),
|
||||
'usbmode' => ($lv->_get_single_xpath_result($res, '//domain/devices/controller[@model=\'nec-xhci\']') ? 'usb3' : 'usb2')
|
||||
],
|
||||
'media' => [
|
||||
'cdrom' => (!empty($medias) && !empty($medias[0]) && array_key_exists('file', $medias[0])) ? $medias[0]['file'] : '',
|
||||
'drivers' => (!empty($medias) && !empty($medias[1]) && array_key_exists('file', $medias[1])) ? $medias[1]['file'] : ''
|
||||
'cdrombus' => (!empty($medias) && !empty($medias[0]) && array_key_exists('bus', $medias[0])) ? $medias[0]['bus'] : 'ide',
|
||||
'drivers' => (!empty($medias) && !empty($medias[1]) && array_key_exists('file', $medias[1])) ? $medias[1]['file'] : '',
|
||||
'driversbus' => (!empty($medias) && !empty($medias[1]) && array_key_exists('bus', $medias[1])) ? $medias[1]['bus'] : 'ide'
|
||||
],
|
||||
'disk' => $arrDisks,
|
||||
'gpu' => $arrGPUDevices,
|
||||
|
||||
Reference in New Issue
Block a user