Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 at change.
:end
Comment on lines +1717 to 1719
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix grammar in help text.

The phrase "at change" is awkward. Consider one of these alternatives:

-This is a location for storing previous versions of xml and nvram at change.
+This is a location for storing previous versions of xml and nvram when changed.

or

-This is a location for storing previous versions of xml and nvram at change.
+This is a location for storing previous versions of xml and nvram on change.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
:vms_libvirt_secondary_volume_help:
This is a location for storing previous versions of xml and nvram at change.
:end
:vms_libvirt_secondary_volume_help:
This is a location for storing previous versions of xml and nvram when changed.
:end
🤖 Prompt for AI Agents
In emhttp/languages/en_US/helptext.txt around lines 1717 to 1719, the help text
"This is a location for storing previous versions of xml and nvram at change."
is grammatically awkward; replace it with a clearer phrase such as "This is a
location for storing previous versions of XML and NVRAM when changes are made."
Ensure XML and NVRAM are capitalized and the new sentence reads fluently.


: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
Comment on lines +1730 to 1732
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix grammar in help text.

Same grammar issue as line 1718. The phrase "at change" should be improved:

-This is a directory for storing previous versions of xml and nvram at change. Does not need to be specified.
+This is a directory for storing previous versions of xml and nvram when changed. Does not need to be specified.

or

-This is a directory for storing previous versions of xml and nvram at change. Does not need to be specified.
+This is a directory for storing previous versions of xml and nvram on change. Does not need to be specified.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
: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_secondary_location_help:
This is a directory for storing previous versions of xml and nvram when changed. Does not need to be specified.
:end
Suggested change
: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_secondary_location_help:
This is a directory for storing previous versions of xml and nvram on change. Does not need to be specified.
:end
🤖 Prompt for AI Agents
In emhttp/languages/en_US/helptext.txt around lines 1730 to 1732, the help text
uses the awkward phrase "at change"; update the sentence for correct grammar and
clarity by replacing "This is a directory for storing previous versions of xml
and nvram at change. Does not need to be specified." with a single clear
sentence such as "This directory stores previous versions of XML and NVRAM when
they change and does not need to be specified." or alternatively "This directory
stores previous versions of XML and NVRAM on change; it does not need to be
specified."


:vms_libvirt_storage_help:
Expand Down
5 changes: 3 additions & 2 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 Down Expand Up @@ -299,7 +300,7 @@ _(VFIO allow unsafe interrupts)_:

<?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' && strpos($domain_cfg['IMAGE_FILE'],".img")) :?>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix imprecise string matching for .img check.

The condition strpos($domain_cfg['IMAGE_FILE'],".img") has potential issues:

  1. It will return false when ".img" is at position 0, though this is unlikely for a path
  2. More importantly, it will match ".img" appearing anywhere in the path, including in directory names (e.g., /mnt/user/my.images/libvirt/ or /path/.img-backup/libvirt/)

Since the intent is to show this section only for image files (not directories), consider using a more precise check:

-<?if ($libvirt_up && trim(shell_exec('stat -c %T -f /etc/libvirt'))=='btrfs' && strpos($domain_cfg['IMAGE_FILE'],".img")) :?>
+<?if ($libvirt_up && trim(shell_exec('stat -c %T -f /etc/libvirt'))=='btrfs' && substr($domain_cfg['IMAGE_FILE'], -4) === '.img') :?>

This checks if the path ends with .img rather than containing it anywhere.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<?if ($libvirt_up && trim(shell_exec('stat -c %T -f /etc/libvirt'))=='btrfs' && strpos($domain_cfg['IMAGE_FILE'],".img")) :?>
<?if ($libvirt_up && trim(shell_exec('stat -c %T -f /etc/libvirt'))=='btrfs' && substr($domain_cfg['IMAGE_FILE'], -4) === '.img') :?>
🤖 Prompt for AI Agents
In emhttp/plugins/dynamix.vm.manager/VMSettings.page around line 303, the
current check strpos($domain_cfg['IMAGE_FILE'],".img") is imprecise (matches
anywhere and fails when at position 0); replace it with an end-of-string match
to ensure the path is an image file — for example, use a case-insensitive regex
or a suffix check such as preg_match('/\.img$/i',
trim($domain_cfg['IMAGE_FILE'])) or
strtolower(substr(trim($domain_cfg['IMAGE_FILE']), -4)) === '.img' so only paths
that actually end with ".img" trigger the condition.

<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
58 changes: 58 additions & 0 deletions emhttp/plugins/dynamix.vm.manager/scripts/libvirt_init
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,64 @@
# run & log functions
. /etc/rc.d/rc.runlog


# Sync domain data if IMAGE_FILE and OLD_IMAGE_FILE differ
DOMAIN_CFG=/boot/config/domain.cfg

# Read values from domain.cfg
eval $(grep -E '^(IMAGE_FILE|OLD_IMAGE_FILE)=' "$DOMAIN_CFG")

# Remove quotes
IMAGE_FILE="${IMAGE_FILE%\"}"
IMAGE_FILE="${IMAGE_FILE#\"}"
OLD_IMAGE_FILE="${OLD_IMAGE_FILE%\"}"
OLD_IMAGE_FILE="${OLD_IMAGE_FILE#\"}"

# Proceed only if both variables are set and OLD_IMAGE_FILE exists
if [ -n "$IMAGE_FILE" ] && [ -n "$OLD_IMAGE_FILE" ] && [ "$IMAGE_FILE" != "$OLD_IMAGE_FILE" ]; then
if [ ! -e "$OLD_IMAGE_FILE" ]; then
log "OLD_IMAGE_FILE not found: $OLD_IMAGE_FILE — skipping sync"
else
log "IMAGE_FILE and OLD_IMAGE_FILE differ, syncing..."

TMP_MNT=/etc/libvirt-sync
IMG_FILE_NAME=$(basename "$IMAGE_FILE")
OLD_IMG_FILE_NAME=$(basename "$OLD_IMAGE_FILE")
TIMESTAMP=$(date +%Y%m%d-%H%M%S)

if [[ "$OLD_IMAGE_FILE" == *.img ]]; then
# Backup image before mounting
BACKUP_PATH="${OLD_IMAGE_FILE%.img}.bak-${TIMESTAMP}.img"
log "Creating backup of OLD_IMAGE_FILE: $BACKUP_PATH"
cp -p "$OLD_IMAGE_FILE" "$BACKUP_PATH"

log "Mounting $OLD_IMAGE_FILE to $TMP_MNT"
mkdir -p "$TMP_MNT"
mount "$OLD_IMAGE_FILE" "$TMP_MNT"
log "Copying full contents from image to directory $IMAGE_FILE"
rsync -a --exclude="$OLD_IMG_FILE_NAME" "$TMP_MNT/" "$IMAGE_FILE/"
umount "$TMP_MNT"
elif [[ "$IMAGE_FILE" == *.img ]]; then
log "Mounting $IMAGE_FILE to $TMP_MNT"
mkdir -p "$TMP_MNT"
mount "$IMAGE_FILE" "$TMP_MNT"
log "Copying full contents from directory $OLD_IMAGE_FILE to image"
rsync -a --exclude="$IMG_FILE_NAME" --exclude='*.bak-*.img' "$OLD_IMAGE_FILE/" "$TMP_MNT/"
umount "$TMP_MNT"
else
log "Both IMAGE_FILE and OLD_IMAGE_FILE are directories, copying full contents"
rsync -a --exclude="$IMG_FILE_NAME" "$OLD_IMAGE_FILE/" "$IMAGE_FILE/"
fi

# Update OLD_IMAGE_FILE in domain.cfg
log "Updating OLD_IMAGE_FILE in $DOMAIN_CFG"
sed -i "s|^OLD_IMAGE_FILE=.*|OLD_IMAGE_FILE=\"$IMAGE_FILE\"|" "$DOMAIN_CFG"
fi
else
log "IMAGE_FILE and OLD_IMAGE_FILE match, or one is unset — skipping sync"
fi


# missing qemu directory would indicate new libvirt image file created
if [ ! -d /etc/libvirt/qemu ]; then
log "initializing /etc/libvirt"
Expand Down
3 changes: 2 additions & 1 deletion emhttp/plugins/dynamix.vm.manager/scripts/libvirtconfig
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
$cfgfile = "/boot/config/domain.cfg";
$cfg_defaults = [
"SERVICE" => "disable",
"IMAGE_FILE" => "/mnt/user/system/libvirt/libvirt.img",
"IMAGE_FILE" => "/mnt/user/system/libvirt/",
"OLD_IMAGE_FILE" => "/mnt/user/system/libvirt/",
"IMAGE_SIZE" => "1",
"DEBUG" => "no",
"DOMAINDIR" => "/mnt/user/domains/",
Expand Down
Loading