Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
8b495f8
Updates for image removal
SimonFair May 8, 2024
6663975
Update VMSettings.page
SimonFair May 8, 2024
12da995
Update rc.libvirt
SimonFair May 8, 2024
81dd45a
Add libvirt_update script
SimonFair May 9, 2024
c1cf813
Make script executable
SimonFair May 9, 2024
ea49630
Update rc.libvirt
SimonFair May 10, 2024
f2822c7
Changes to VM Settings
SimonFair Apr 19, 2025
28ec848
revert rc.libvirt changes
SimonFair Apr 19, 2025
de53cf4
Initial moving libvirt image to folder and vice versa.
SimonFair Apr 20, 2025
3ffebdf
Update help text
SimonFair Apr 20, 2025
a9d8167
Merge remote-tracking branch 'upstream/master' into Remove-Vm-Image
SimonFair May 6, 2025
7b03382
Remove secondary path.
SimonFair May 6, 2025
fca221a
Remove secondary code.
SimonFair May 6, 2025
d5d3bad
Merge remote-tracking branch 'upstream/master' into Remove-Vm-Image
SimonFair Oct 24, 2025
79e2e53
Merge remote-tracking branch 'upstream/master' into Remove-Vm-Image
SimonFair Jan 7, 2026
7256297
Create location file.
SimonFair Jan 7, 2026
00ed5d2
Make script executable
SimonFair Jan 7, 2026
d13e6b2
XML movements
SimonFair Jan 7, 2026
a41622b
Make script executable
SimonFair Jan 7, 2026
092af90
Udates to XML movement.
SimonFair Jan 8, 2026
6d7c50c
Updates
SimonFair Jan 9, 2026
5287435
Add XML processing to save configs in vm dir.
SimonFair Jan 22, 2026
111f3d0
Update libvirt.php
SimonFair Jan 22, 2026
75ffb61
Update libvirt.php
SimonFair Jan 22, 2026
eab65bf
Update emhttp/languages/en_US/helptext.txt
SimonFair Jan 22, 2026
f82fc7b
Update emhttp/plugins/dynamix.vm.manager/VMSettings.page
SimonFair Jan 22, 2026
3b4139b
Update emhttp/plugins/dynamix.vm.manager/include/fs_helpers.php
SimonFair Jan 22, 2026
ab766fb
Update emhttp/plugins/dynamix.vm.manager/scripts/libvirt_init
SimonFair Jan 22, 2026
2e45d29
Update emhttp/plugins/dynamix.vm.manager/scripts/libvirt_init
SimonFair Jan 22, 2026
4e7b667
Update emhttp/plugins/dynamix.vm.manager/scripts/libvirtcopy
SimonFair Jan 22, 2026
80b04cb
Update etc/rc.d/rc.libvirt
SimonFair Jan 22, 2026
835b348
Update emhttp/plugins/dynamix.vm.manager/scripts/libvirtmigrate
SimonFair Jan 22, 2026
9668907
Update emhttp/plugins/dynamix.vm.manager/scripts/libvirtrestore
SimonFair Jan 22, 2026
62629a1
Update emhttp/plugins/dynamix.vm.manager/scripts/savehook.php
SimonFair Jan 22, 2026
a9c4b21
Update libvirt.php
SimonFair Jan 22, 2026
1b1f4f4
Merge branch 'Remove-Vm-Image' of https://github.com/SimonFair/webgui…
SimonFair Jan 22, 2026
a640587
Update libvirtmigrate
SimonFair Jan 22, 2026
0f4cda7
Coderabbit updates
SimonFair Jan 23, 2026
c2533c6
check for new model flag and change paths
SimonFair Jan 26, 2026
b1ae311
Update libvirt_paths.php
SimonFair Jan 26, 2026
43d6d87
Create rc.libvirt.conf
SimonFair Jan 26, 2026
b689eab
Merge remote-tracking branch 'upstream/master' into Remove-Vm-Image
SimonFair Jan 26, 2026
560ed51
Make script executable
SimonFair Jan 27, 2026
0f8de49
Path changes.
SimonFair Jan 28, 2026
3283bfe
Path processing.
SimonFair Jan 28, 2026
e0524d9
Fix delete issue.
SimonFair Jan 29, 2026
9ff9afb
fix snapshot GPF
SimonFair Jan 29, 2026
6fff228
fix nvram creation issue and snapshotdb location.
SimonFair Jan 29, 2026
f0f671a
fix nvram processing.
SimonFair Feb 2, 2026
28de0ee
add delete all option
SimonFair Feb 2, 2026
62a461f
remove debug logging
SimonFair Feb 2, 2026
c9ec4dd
Code rabbit changes
SimonFair Feb 2, 2026
36b7e58
further updates
SimonFair Feb 2, 2026
cae0c9c
Updates
SimonFair Feb 2, 2026
5c10559
Remove nvram for block commit.
SimonFair Feb 2, 2026
6569d17
purge nvram during block operations if removed by qemu
SimonFair Feb 2, 2026
091bb18
Remove directory if empty.
SimonFair Feb 2, 2026
44d7fcf
refactor by creating single is_vm_new_model
SimonFair Feb 2, 2026
e6bba6b
code rabbit updates.
SimonFair Feb 3, 2026
23dd144
Migrate to new model
SimonFair Feb 3, 2026
fbcc6db
Update libvirt_init
SimonFair Feb 3, 2026
7203a1f
Update libvirt.php
SimonFair Feb 3, 2026
9d745cc
Update libvirt.php
SimonFair Feb 3, 2026
827c65a
Update libvirt.php
SimonFair Feb 3, 2026
e0cae04
Update migration process.
SimonFair Feb 3, 2026
05dae8f
Update rc.libvirt
SimonFair Feb 3, 2026
b9c7a1b
fix snapshot lookups
SimonFair Feb 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions emhttp/languages/en_US/helptext.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1711,7 +1711,11 @@ Stop VMs from Autostarting\Starting when VM Manager starts or open is run from t
:end

:vms_libvirt_volume_help:
This is the libvirt volume.
This is the libvirt volume/directory.
:end

:vms_libvirt_secondary_volume_help:
This is a location for storing previous versions of XML and NVRAM when changes are made.
:end

:vms_libvirt_vdisk_size_help:
Expand All @@ -1720,7 +1724,11 @@ To resize an existing image file, specify the new size here. Next time the Libvi
:end

:vms_libvirt_location_help:
You must specify an image file for Libvirt. The system will automatically create this file when the Libvirt service is first started.
You must specify an image file/directory for Libvirt. The system will automatically create this file/directory when the Libvirt service is first started.
:end

:vms_libvirt_secondary_location_help:
This is a directory for storing previous versions of xml and nvram at change. Does not need to be specified.
:end

:vms_libvirt_storage_help:
Expand Down
13 changes: 8 additions & 5 deletions emhttp/plugins/dynamix.vm.manager/VMSettings.page
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ $libvirt_log = file_exists("/var/log/libvirt/libvirtd.log");
<input type="hidden" name="#file" value="<?=htmlspecialchars($domain_cfgfile)?>">
<input type="hidden" name="#command" value="/plugins/dynamix/scripts/emcmd">
<input type="hidden" name="#arg[1]" value="cmdStatus=Apply">

<input type="hidden" id="OLD_IMAGE_FILE" name="OLD_IMAGE_FILE" value="<?=htmlspecialchars($domain_cfg['IMAGE_FILE']);?>">
_(Enable VMs)_:
: <select id="SERVICE" name="SERVICE">
<?= mk_option($libvirt_service, 'disable', _('No'))?>
Expand All @@ -150,6 +150,7 @@ _(Disable Autostart/Start option for VMs)_:
<?if ($libvirt_up):?>
<?$libvirt_info = libvirt_version('libvirt')?>
<?$qemu_info = $lv->get_connect_information()?>

_(Libvirt version)_:
: <?=$libvirt_info['libvirt.major'].'.'.$libvirt_info['libvirt.minor'].'.'.$libvirt_info['libvirt.release']?>

Expand All @@ -161,14 +162,15 @@ _(Libvirt storage location)_:

:vms_libvirt_volume_help:

<?else: /* Libvirt is stopped */ ?>
_(Libvirt vdisk size)_ (_(GB)_):
<?else : /* Libvirt is stopped */ ?>

_(Libvirt vdisk size)_ (_(GB)_):
: <input type="number" id="IMAGE_SIZE" name="IMAGE_SIZE" min="1" value="<?=htmlspecialchars($domain_cfg['IMAGE_SIZE']);?>" required="required" /><span id="SIZE_ERROR" class="errortext"></span>

:vms_libvirt_vdisk_size_help:

_(Libvirt storage location)_:
: <input type="text" id="IMAGE_FILE" name="IMAGE_FILE" autocomplete="off" spellcheck="false" value="<?=htmlspecialchars($domain_cfg['IMAGE_FILE']);?>" placeholder="e.g. /mnt/user/system/libvirt/libvirt.img" data-pickcloseonfile="true" data-pickfilter="img" data-pickroot="/mnt" data-pickfolders="true" required pattern="^[^\\]*libvirt\.img$">
: <input type="text" id="IMAGE_FILE" name="IMAGE_FILE" autocomplete="off" spellcheck="false" value="<?=htmlspecialchars($domain_cfg['IMAGE_FILE']);?>" placeholder="e.g. /mnt/user/system/libvirt/libvirt.img" data-pickcloseonfile="true" data-pickfilter="img" data-pickroot="/mnt" data-pickfolders="true" >
<?if (file_exists($domain_cfg['IMAGE_FILE'])):?>
<span id="deletePanel"><label><input type="checkbox" id="deleteCheckbox" /> _(Delete Image File)_</label></span><?endif;?>
<?if (!$started):?>
Expand All @@ -179,6 +181,7 @@ _(Libvirt storage location)_:
:vms_libvirt_location_help:

<?endif;?>

_(Default VM storage path)_:
: <input type="text" id="domaindir" name="DOMAINDIR" autocomplete="off" spellcheck="false" data-pickfolders="true" data-pickfilter="HIDE_FILES_FILTER" data-pickroot="/mnt" value="<?=htmlspecialchars($domain_cfg['DOMAINDIR'])?>" placeholder="_(Click to Select)_" pattern="^[^\\]*/$" onchange="validatePath(this)">
<?if (!$started):?>
Expand Down Expand Up @@ -286,7 +289,7 @@ _(Boot Parameter Settings)_:

<?endif;?>

<?if ($libvirt_up && trim(shell_exec('stat -c %T -f /etc/libvirt'))=='btrfs'):?>
<?if ($libvirt_up && trim(shell_exec('stat -c %T -f /etc/libvirt'))=='btrfs' && substr($domain_cfg['IMAGE_FILE'], -4) === '.img') :?>
<div class="advanced" markdown="1">
<div class="title"><span class="left"><i class="title fa fa-list"></i>_(Libvirt volume info)_</span></div>
_(btrfs filesystem show)_:
Expand Down
7 changes: 5 additions & 2 deletions emhttp/plugins/dynamix.vm.manager/include/VMajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,9 @@ function embed(&$bootcfg, $env, $key, $value) {

case 'domain-delete':
requireLibvirt();
$arrResponse = $lv->domain_delete($domName)
$firstdisk = filter_var(_var($_REQUEST,'firstdisk', 'true'), FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
if ($firstdisk === null) $firstdisk = true;
$arrResponse = $lv->domain_delete($domName, $firstdisk)
? ['success' => true]
: ['error' => $lv->get_last_error()];
break;
Expand Down Expand Up @@ -484,7 +486,8 @@ function embed(&$bootcfg, $env, $key, $value) {
$list = glob($pathinfo['dirname']."/*");
$uuid = $lv->domain_get_uuid($domName);

$list2 = glob("/etc/libvirt/qemu/nvram/*$uuid*");
$vm_path = libvirt_get_vm_path($domName);
$list2 = glob(libvirt_get_nvram_dir($vm_path, $domName)."/*$uuid*");
$listnew = array();
$list=array_merge($list,$list2);
foreach($list as $key => $listent)
Expand Down
100 changes: 100 additions & 0 deletions emhttp/plugins/dynamix.vm.manager/include/fs_helpers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php
/* Filesystem helper utilities for dynamix.vm.manager
* - files_identical($a,$b)
* - copy_if_different($src,$dst, $dry_run=false)
* - dir_copy($src,$dst) (recursive, skips identical files)
* - dir_remove($dir) (recursive remove)
*/

function files_identical($a, $b) {
if (!file_exists($a) || !file_exists($b)) return false;
if (filesize($a) !== filesize($b)) return false;
$ha = @md5_file($a);
$hb = @md5_file($b);
if ($ha === false || $hb === false) return false;
return $ha === $hb;
}

function copy_if_different($src, $dst, $dry_run = false) {
$result = [
'src' => $src,
'dst' => $dst,
'would_copy' => false,
'copied' => false,
'error' => null
];

if (!file_exists($src)) {
$result['error'] = 'source not found';
return $result;
}

$dst_dir = dirname($dst);
if (!is_dir($dst_dir)) {
if ($dry_run) {
$result['would_copy'] = true;
return $result;
}
if (!@mkdir($dst_dir, 0755, true)) {
$result['error'] = 'failed to create dest dir';
return $result;
}
}

if (file_exists($dst)) {
if (files_identical($src, $dst)) {
return $result; // identical, nothing to do
}
$result['would_copy'] = true;
} else {
$result['would_copy'] = true;
}

if ($dry_run) return $result;

if (@copy($src, $dst)) {
$result['copied'] = true;
} else {
$result['error'] = 'copy_failed';
}

return $result;
}

function dir_copy($src, $dst) {
if (!is_dir($src)) return false;
if (!is_dir($dst)) {
if (!@mkdir($dst, 0755, true)) return false;
}
$items = scandir($src);
foreach ($items as $item) {
if ($item === '.' || $item === '..') continue;
$s = $src . DIRECTORY_SEPARATOR . $item;
$d = $dst . DIRECTORY_SEPARATOR . $item;
if (is_dir($s)) {
if (!dir_copy($s, $d)) return false;
} else {
if (file_exists($d)) {
if (files_identical($s, $d)) continue;
}
if (!@copy($s, $d)) return false;
}
}
return true;
}

function dir_remove($dir) {
if (!is_dir($dir)) return false;
$items = scandir($dir);
if ($items === false) return false;
foreach ($items as $item) {
if ($item === '.' || $item === '..') continue;
$path = $dir . DIRECTORY_SEPARATOR . $item;
if (is_dir($path)) {
if (!dir_remove($path)) return false;
} else {
if (!@unlink($path)) return false;
}
}
return @rmdir($dir);
}
Loading
Loading