Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package os-autoinst for openSUSE:Factory 
checked in at 2026-10-06 19:15:39
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/os-autoinst (Old)
 and      /work/SRC/openSUSE:Factory/.os-autoinst.new.3698736 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "os-autoinst"

Tue Oct  6 19:15:39 2026 rev:627 rq:1382599 version:5.1790961809.b728c27

Changes:
--------
--- /work/SRC/openSUSE:Factory/os-autoinst/os-autoinst.changes  2026-10-01 
16:43:54.005131094 +0200
+++ /work/SRC/openSUSE:Factory/.os-autoinst.new.3698736/os-autoinst.changes     
2026-10-06 19:16:40.999180864 +0200
@@ -1,0 +2,18 @@
+Mon Oct 05 13:49:26 UTC 2026 - [email protected]
+
+- Update to version 5.1790961809.b728c27:
+  * docs: Document generic local and remote verification guidelines
+  * fix: Avoid MAC address overflow when using custom NICOFFSET
+
+-------------------------------------------------------------------
+Wed Sep 30 09:20:17 UTC 2026 - [email protected]
+
+- Update to version 5.1790759999.068642e:
+  * fix(svirt): Fix VMware copy hangs, paths, and large file transfers
+  * test: Update tests after 111e01b69 was merged
+  * feat: Record failures during post fail hook "Failed (post)"
+  * feat: Record info about entering post fail hook
+  * feat: Record failures during post fail hook as such
+  * feat: Record failures that happened during `post_fail_hook`
+
+-------------------------------------------------------------------

Old:
----
  os-autoinst-5.1790705326.6badaca.obscpio

New:
----
  os-autoinst-5.1790961809.b728c27.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ os-autoinst-devel-test.spec ++++++
--- /var/tmp/diff_new_pack.UEOXoU/_old  2026-10-06 19:16:42.504243845 +0200
+++ /var/tmp/diff_new_pack.UEOXoU/_new  2026-10-06 19:16:42.505243887 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name os-autoinst-devel
 Name:           %{short_name}-test
-Version:        5.1790705326.6badaca
+Version:        5.1790961809.b728c27
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ os-autoinst-openvswitch-test.spec ++++++
--- /var/tmp/diff_new_pack.UEOXoU/_old  2026-10-06 19:16:42.536245184 +0200
+++ /var/tmp/diff_new_pack.UEOXoU/_new  2026-10-06 19:16:42.537245226 +0200
@@ -19,7 +19,7 @@
 %define name_ext -test
 %define         short_name os-autoinst-openvswitch
 Name:           %{short_name}%{?name_ext}
-Version:        5.1790705326.6badaca
+Version:        5.1790961809.b728c27
 Release:        0
 Summary:        test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ os-autoinst-test.spec ++++++
--- /var/tmp/diff_new_pack.UEOXoU/_old  2026-10-06 19:16:42.564246356 +0200
+++ /var/tmp/diff_new_pack.UEOXoU/_new  2026-10-06 19:16:42.565246397 +0200
@@ -19,7 +19,7 @@
 %define name_ext -test
 %define         short_name os-autoinst
 Name:           %{short_name}%{?name_ext}
-Version:        5.1790705326.6badaca
+Version:        5.1790961809.b728c27
 Release:        0
 Summary:        test package for os-autoinst
 License:        GPL-2.0-or-later

++++++ os-autoinst.spec ++++++
--- /var/tmp/diff_new_pack.UEOXoU/_old  2026-10-06 19:16:42.596247695 +0200
+++ /var/tmp/diff_new_pack.UEOXoU/_new  2026-10-06 19:16:42.598247778 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           os-autoinst
-Version:        5.1790705326.6badaca
+Version:        5.1790961809.b728c27
 Release:        0
 Summary:        OS-level test automation
 License:        GPL-2.0-or-later

++++++ os-autoinst-5.1790705326.6badaca.obscpio -> 
os-autoinst-5.1790961809.b728c27.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1790705326.6badaca/AGENTS.md 
new/os-autoinst-5.1790961809.b728c27/AGENTS.md
--- old/os-autoinst-5.1790705326.6badaca/AGENTS.md      2026-09-29 
20:08:46.000000000 +0200
+++ new/os-autoinst-5.1790961809.b728c27/AGENTS.md      2026-10-02 
19:23:29.000000000 +0200
@@ -21,6 +21,9 @@
   reusing existing failing test modules (e.g. from `t/data/tests`) for
   integration tests. Prefer self-explanatory test description strings rather
   than in-file comments.
+- **Verification**: See the "Local and remote verification" section in
+  `README.md` for standard procedures on local execution and remote worker
+  verification of your changes.
 - Dependencies: Update `dependencies.yaml` and run `make update-deps`.
 
 ## Constraints
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1790705326.6badaca/README.md 
new/os-autoinst-5.1790961809.b728c27/README.md
--- old/os-autoinst-5.1790705326.6badaca/README.md      2026-09-29 
20:08:46.000000000 +0200
+++ new/os-autoinst-5.1790961809.b728c27/README.md      2026-10-02 
19:23:29.000000000 +0200
@@ -405,6 +405,39 @@
   ISOTOVIDEO="c=/var/lib/openqa/cache/podman_storage && p=\$(pwd)/podman_tmp 
&& mkdir -p \$c \$p/run && env HOME=\$p XDG_RUNTIME_DIR=\$p/run podman --root 
\$c --runroot \$p/run/containers --storage-opt ignore_chown_errors=true 
--cgroup-manager=cgroupfs --events-backend=file run --init --rm --entrypoint 
\"\" --device /dev/kvm -v \$(pwd):/pool -w /pool -v 
/var/lib/openqa/cache:/var/lib/openqa/cache 
registry.opensuse.org/devel/openqa/containers/os-autoinst_dev:latest sh -c 
'zypper -n in os-autoinst-distri-opensuse-deps && rm -rf os-autoinst && git 
clone --branch=<your_engine_branch> --depth=1 
https://github.com/<your_username>/os-autoinst.git && make -C os-autoinst 
symlinks && os-autoinst/isotovideo -d'"
 ```
 
+## Local and remote verification
+
+When developing and verifying modifications to `os-autoinst` or the test
+distributions, you can verify changes locally on your development machine or
+remotely by patching active openQA workers:
+
+### 1. Local verification
+To run `isotovideo` locally against a cloned test-distribution, execute the 
local
+`isotovideo` script from a dedicated local test run directory (where temporary
+state files will be written) instead of running directly inside your cloned
+test-distribution. This prevents polluting your test-distribution repository 
with
+test execution artifacts:
+
+```sh
+# Run from your dedicated local test run directory:
+/path/to/os-autoinst/isotovideo --debug CASEDIR=/path/to/test-distribution 
[VARIABLES]
+```
+
+### 2. Remote verification by patching workers
+To verify changes on an active, remote openQA worker without waiting
+for a package update, copy your modified local Perl modules directly to the
+corresponding path on the worker. Since a new `isotovideo` process is spawned
+for each job, the next job run will automatically load the newly-patched
+modules:
+
+```sh
+# Copy your local modified module to the remote worker:
+rsync -v --rsync-path="sudo rsync" consoles/VMWare.pm 
worker_host:/usr/lib/os-autoinst/consoles/VMWare.pm
+
+# Or if a jump host (e.g., o3) is required to reach the worker:
+rsync -v -e 'ssh -J o3' --rsync-path="sudo rsync" consoles/VMWare.pm 
worker_host:/usr/lib/os-autoinst/consoles/VMWare.pm
+```
+
 # Running isotovideo as CI check
 
 We provide a container to run `isotovideo` which can be used to run
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1790705326.6badaca/backend/qemu.pm 
new/os-autoinst-5.1790961809.b728c27/backend/qemu.pm
--- old/os-autoinst-5.1790705326.6badaca/backend/qemu.pm        2026-09-29 
20:08:46.000000000 +0200
+++ new/os-autoinst-5.1790961809.b728c27/backend/qemu.pm        2026-10-02 
19:23:29.000000000 +0200
@@ -828,8 +828,8 @@
     for (my $i = 0; $i < $num_networks; $i++) {
         # ensure MAC addresses differ globally
         # and allow MAC addresses for more than 256 workers (up to 16384)
-        my $workerid = $vars->{WORKER_ID};
-        $nicmac[$i] //= sprintf '52:54:00:12:%02x:%02x', int($workerid / 256) 
+ $i * $nic_offset, $workerid % 256;
+        my $workerid = $vars->{WORKER_ID} // 0;
+        $nicmac[$i] //= sprintf '52:54:00:12:%02x:%02x', (int($workerid / 256) 
+ $i * 64) % 256, $workerid % 256;
 
         # always set proper TAPDEV for os-autoinst when using tap network mode
         my $instance = ($vars->{WORKER_INSTANCE} || 'manual') eq 'manual' ? 
255 : $vars->{WORKER_INSTANCE};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1790705326.6badaca/consoles/VMWare.pm 
new/os-autoinst-5.1790961809.b728c27/consoles/VMWare.pm
--- old/os-autoinst-5.1790705326.6badaca/consoles/VMWare.pm     2026-09-29 
20:08:46.000000000 +0200
+++ new/os-autoinst-5.1790961809.b728c27/consoles/VMWare.pm     2026-10-02 
19:23:29.000000000 +0200
@@ -173,6 +173,10 @@
     for my $checksum_var (sort grep { /^CHECKSUM_/ } keys %bmwqemu::vars) {
         my $image = $bmwqemu::vars{$checksum_var =~ s/^CHECKSUM_//r};
         next unless defined $image && basename($image) eq $file_basename;
+        # Only return the checksum if the file extension is exactly the same!
+        # For example, if the expected image name has .xz but we are checking 
a raw .vmdk,
+        # then the checksum belongs to the .xz file, not the .vmdk file!
+        next if $image =~ /\.xz$/ && $file_basename !~ /\.xz$/;
         my $checksum = $bmwqemu::vars{$checksum_var} // next;
         # only a plain digest is safe to interpolate into the shell script
         return lc $checksum if $checksum =~ 
/^(?:[0-9a-f]{64}|[0-9a-f]{128})$/i;
@@ -185,15 +189,18 @@
 # A 64 character checksum is either SHA-256 or SHA-512 truncated, so try 
SHA-256 first
 # and then the other, in the same order as verify_checksum() of the test 
distribution.
 sub _digest_script ($file, $checksum) {
-    return <<~"EOF" if length($checksum) == 128;
-    _digest=\$(sha512sum "$file" | awk '{print \$1}')
-    _digests="SHA-512 \$_digest"
-    EOF
+    if (length($checksum) == 128) {
+        return <<~"EOF";
+        _digest=\$(openssl dgst -sha512 "$file" 2>/dev/null | awk '{print 
\$NF}')
+        _digests="SHA-512 \$_digest"
+        EOF
+    }
+
     return <<~"EOF";
-    _digest=\$(sha256sum "$file" | awk '{print \$1}')
+    _digest=\$(openssl dgst -sha256 "$file" 2>/dev/null | awk '{print \$NF}')
     _digests="SHA-256 \$_digest"
     if [ "\$_digest" != "$checksum" ]; then
-        _digest=\$(sha512sum "$file" | awk '{print \$1}' | cut -c1-64)
+        _digest=\$(openssl dgst -sha512 "$file" 2>/dev/null | awk '{print 
\$NF}' | cut -c1-64)
         _digests="\$_digests, SHA-512 truncated \$_digest"
     fi
     EOF
@@ -205,7 +212,7 @@
 # Note: This script must be in POSIX shell as ESXi uses busybox for /bin/sh
 sub _atomic_copy_script ($source, $dest, $tmp, $checksum = undef, 
$failure_note = undef) {
     my $copy = _replace_notice_script($dest) . <<~"EOF";
-    if ! cp "$source" "$tmp"; then
+    if ! dd if="$source" of="$tmp" bs=1M 2>/dev/null; then
         rm -f "$tmp"
         echo "Unable to copy $source to $dest"
         exit 1
@@ -242,11 +249,11 @@
     my $old_record = _verified_record_path($dest);
     return <<~"EOF";
     $notice
-    if xz --decompress --stdout "$source" > "$tmp" && rm -f "$old_record" && 
mv "$tmp" "$dest"; then
+    if dd if="$source" of="$tmp.xz" bs=1M 2>/dev/null && xz --decompress 
"$tmp.xz" && rm -f "$old_record" && mv "$tmp" "$dest"; then
     $record
         echo "Decompressed $source to $dest"
     else
-        rm -f "$tmp"
+        rm -f "$tmp" "$tmp.xz"
         echo "Unable to decompress $source to $dest"
         exit 1
     fi
@@ -321,11 +328,12 @@
     }
     _release_claim() {
         if [ -n "\$_heartbeat_pid" ]; then
-            { kill "\$_heartbeat_pid"; wait "\$_heartbeat_pid"; } 2>/dev/null
+            kill "\$_heartbeat_pid" 2>/dev/null
         fi
         if [ -n "\$_claimed" ] && _owns_marker; then
             rm -rf "$marker"
         fi
+        true
     }
     trap _release_claim EXIT
     _seen=''
@@ -370,6 +378,7 @@
     # expected name of uncompressed image
     my $baseimage = basename($input_file) =~ s/\.xz$//r;
     my $dest_image = "$vmware_openqa_datastore/${baseimage}";
+    $dest_image =~ s{//+}{/}g;
     # Use the standard folder for an input file without full path
     my $file_origin = ($input_file eq $basefile) ? 
"$base_dir/$vmware_nfs_datastore/$nfs_dir/$basefile" : $input_file;
     my $dest_xz = "$dest_image.xz";
@@ -380,21 +389,24 @@
     # final image also covers the .xz copy, as only the job producing the 
image needs it.
     # Note: This script must be in POSIX shell as ESXi uses busybox for /bin/sh
     my $verified = _indent(_verified_script($checksum));
-    my $claim = _indent(_claim_copy_script($dest_image, $name, $checksum));
-    my $failure_note = _failure_note_path($dest_image, $name);
-    my $copy_xz = _indent(_atomic_copy_script($file_origin, $dest_xz, 
_tmp_image_path($dest_xz, $name), $checksum, $failure_note), 3);
-    my $decompress = _indent(_atomic_decompress_script($dest_xz, $dest_image, 
_tmp_image_path($dest_image, $name), $checksum), 2);
-    my $copy_image = _indent(_atomic_copy_script($file_origin, $dest_image, 
_tmp_image_path($dest_image, $name), $checksum, $failure_note), 2);
+    my $claim = _indent(_claim_copy_script('$dest', $name, $checksum));
+    my $failure_note = _failure_note_path('$dest', $name);
+    my $copy_xz = _indent(_atomic_copy_script('$src', '$dest_xz', 
_tmp_image_path('$dest_xz', $name), $checksum, $failure_note), 3);
+    my $decompress = _indent(_atomic_decompress_script('$dest_xz', '$dest', 
_tmp_image_path('$dest', $name), $checksum), 2);
+    my $copy_image = _indent(_atomic_copy_script('$src', '$dest', 
_tmp_image_path('$dest', $name), $checksum, $failure_note), 2);
     my $cmd = <<~"EOF";
     $debug
     input_file="$input_file"
+    dest="$dest_image"
+    dest_xz="$dest_xz"
+    src="$file_origin"
     $verified
     $claim
-    if _verified "$dest_image"; then
-        echo "VMware image $dest_image ready"
+    if _verified "\$dest"; then
+        echo "VMware image \$dest ready"
     else
-        if [ "\${input_file##*.}" = "xz" ]; then
-            if ! _verified "$dest_xz"; then
+        if [ "\\\${input_file##*.}" = "xz" ]; then
+            if ! _verified "\$dest_xz"; then
     $copy_xz
             fi
     $decompress
@@ -402,11 +414,17 @@
     $copy_image
         fi
     fi
-    echo "Done: origin:" $file_origin* " ; dest.:" $dest_image*
+    echo "Done: origin: \$src ; dest.: \$dest"
+    exit 0
     EOF
 
-    my $ret = $svirt->run_cmd($cmd, domain => 'sshVMwareServer');
-    croak "Error on VMware image $input_file preparation." if $ret;
+    my ($ret, $stdout, $stderr) = $svirt->run_cmd($cmd, domain => 
'sshVMwareServer', wantarray => 1);
+    if ($ret) {
+        $stdout //= '';    # uncoverable statement
+        $stderr //= '';    # uncoverable statement
+        bmwqemu::diag "Error on VMware image preparation command. Exit code: 
$ret\nStdout:\n$stdout\nStderr:\n$stderr" if $stdout || $stderr; # uncoverable 
statement
+        croak "Error on VMware image $input_file preparation.";    # 
uncoverable statement
+    }
     return $dest_image;
 }
 
@@ -421,25 +439,34 @@
     my $vmware_nfs_datastore = $bmwqemu::vars{VMWARE_NFS_DATASTORE} or die 
'Need variable VMWARE_NFS_DATASTORE';
     # cmd debugging activable by setting VMWARE_NFS_DATASTORE_DEBUG=1
     my $ds_debug = ($bmwqemu::vars{VMWARE_NFS_DATASTORE_DEBUG} // 0) ? 'set 
-x;' : '';
-    my $dest_image = "$vmware_openqa_datastore$file_basename";
+    my $dest_image = "$vmware_openqa_datastore/$file_basename";
+    $dest_image =~ s{//+}{/}g;
     my $file_origin = 
"/vmfs/volumes/$vmware_nfs_datastore/$nfs_dir/$file_basename";
     my $checksum = _expected_checksum($file_basename);
     my $verified = _indent(_verified_script($checksum));
-    my $claim = _indent(_claim_copy_script($dest_image, $name, $checksum));
-    my $copy_image = _indent(_atomic_copy_script($file_origin, $dest_image, 
_tmp_image_path($dest_image, $name), $checksum, _failure_note_path($dest_image, 
$name)), 1);
+    my $claim = _indent(_claim_copy_script('$dest', $name, $checksum));
+    my $copy_image = _indent(_atomic_copy_script('$src', '$dest', 
_tmp_image_path('$dest', $name), $checksum, _failure_note_path('$dest', 
$name)), 1);
     # Note: This script must be in POSIX shell as ESXi uses busybox for /bin/sh
     my $cmd = <<~"EOF";
     $ds_debug
+    dest="$dest_image"
+    src="$file_origin"
     $verified
     $claim
-    if _verified "$dest_image"; then
-        echo "VMware image $dest_image is already present and verified"
+    if _verified "\$dest"; then
+        echo "VMware image \$dest is already present and verified"
     else
     $copy_image
     fi
+    exit 0
     EOF
-    my $retval = $svirt->run_cmd($cmd, domain => 'sshVMwareServer', timeout => 
$copy_timeout);
-    die "Can't copy VMware image $file_basename" if $retval;
+    my ($retval, $stdout, $stderr) = $svirt->run_cmd($cmd, domain => 
'sshVMwareServer', timeout => $copy_timeout, wantarray => 1);
+    if ($retval) {
+        $stdout //= '';    # uncoverable statement
+        $stderr //= '';    # uncoverable statement
+        bmwqemu::diag "Can't copy VMware image. Exit code: 
$retval\nStdout:\n$stdout\nStderr:\n$stderr" if $stdout || $stderr;    # 
uncoverable statement
+        die "Can't copy VMware image $file_basename";    # uncoverable 
statement
+    }
     return unless $backingfile;
     # Power VM off, delete its disk image, and create it again.
     # Then wait for some time for the VM to *really* turn off.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1790705326.6badaca/t/18-backend-qemu.t 
new/os-autoinst-5.1790961809.b728c27/t/18-backend-qemu.t
--- old/os-autoinst-5.1790705326.6badaca/t/18-backend-qemu.t    2026-09-29 
20:08:46.000000000 +0200
+++ new/os-autoinst-5.1790961809.b728c27/t/18-backend-qemu.t    2026-10-02 
19:23:29.000000000 +0200
@@ -770,6 +770,21 @@
         $process_mock->called_args_pos_is(3, 2, 'cleanup', 'cleanup event 
emitted');
     }
 
+    @qemu_params = ();
+    $bmwqemu::vars{WORKER_ID} = 4090;
+    $bmwqemu::vars{TAPDEV} = 'auto,auto';
+    $bmwqemu::vars{NICOFFSET} = 1000;
+    delete $bmwqemu::vars{NICMAC};
+    combined_like { $backend->start_qemu } qr{.*}s, 'invoked with multiple tap 
devices and NICOFFSET=1000';
+    $qemu_params = Mojo::Collection->new(\@qemu_params)->flatten->join(' ');
+    like $qemu_params, qr{tap id=qanet0 ifname=tap2 script=no downscript=no}, 
'qanet0 tapdev correct';
+    like $qemu_params, qr{tap id=qanet1 ifname=tap1002 script=no 
downscript=no}, 'qanet1 tapdev offset by NICOFFSET';
+    like $qemu_params, qr{netdev=qanet0 mac=52:54:00:12:0f:fa}, 'qanet0 MAC 
address correct';
+    like $qemu_params, qr{netdev=qanet1 mac=52:54:00:12:4f:fa}, 'qanet1 MAC 
address valid and not overflowed by NICOFFSET';
+    delete $bmwqemu::vars{TAPDEV};
+    delete $bmwqemu::vars{NICOFFSET};
+    $bmwqemu::vars{WORKER_ID} = 42;
+
     $bmwqemu::vars{NICPCIADDR} = 19;
     $bmwqemu::vars{NICTYPE} = 'user';
     combined_like { $backend->start_qemu } qr{.*}s, 'invoked with NICPCIADDR';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1790705326.6badaca/t/22-svirt.t 
new/os-autoinst-5.1790961809.b728c27/t/22-svirt.t
--- old/os-autoinst-5.1790705326.6badaca/t/22-svirt.t   2026-09-29 
20:08:46.000000000 +0200
+++ new/os-autoinst-5.1790961809.b728c27/t/22-svirt.t   2026-10-02 
19:23:29.000000000 +0200
@@ -651,9 +651,9 @@
             @last_ssh_commands = ();
             $svirt->add_disk({cdrom => 1, dev_id => $dev_id, file => 
'/my/path/to/this/file/' . $filename});
             my $tmp_file = "$vmware_openqa_datastore$filename." . $svirt->name 
. '.part';
-            like $last_ssh_commands[0], 
qr%cp\s+"/vmfs/volumes/nfs_data_store/iso/$filename"\s+"\Q$tmp_file\E"%, "Copy 
iso to temporary file in $vmware_openqa_datastore";
-            like $last_ssh_commands[0], 
qr%mv\s+"\Q$tmp_file\E"\s+"$vmware_openqa_datastore$filename"%, 'Temporary file 
renamed into place so the copy is atomic';
-            like $last_ssh_commands[0], 
qr%mkdir\s+"$vmware_openqa_datastore$filename\.copying"%, 'Right to copy 
claimed so jobs arriving together do not all transfer the image';
+            like $last_ssh_commands[0], qr%dd if="\$src" 
of="\$dest\.\Q${\$svirt->name}\E\.part"\s+bs=1M%, "Copy iso to temporary file 
in $vmware_openqa_datastore";
+            like $last_ssh_commands[0], qr%mv 
"\$dest\.\Q${\$svirt->name}\E\.part"\s+"\$dest"%, 'Temporary file renamed into 
place so the copy is atomic';
+            like $last_ssh_commands[0], qr%mkdir "\$dest\.copying"%, 'Right to 
copy claimed so jobs arriving together do not all transfer the image';
             unlike $last_ssh_commands[0], qr/lsof/, 'No guessing from a 
process list whether someone else is copying needed anymore';
 
             svirt_xml_validate($svirt,
@@ -1066,8 +1066,8 @@
         ) {
             my ($inp, $qry, $qry_xz, $backf_trig) = @$tuple;
             $svirt->provide_image_vmware_in_ds($inp, $vmware_openqa_datastore, 
backingfile => $backf_trig);
-            like $last_run_commands[$n], 
qr{cp\s.*$qry\"\s\"$vmware_openqa_datastore}, 'vmw-test-1: checking image 
management script, file origin:' . $n . 'a';
-            like $last_run_commands[$n], 
qr{xz\s.*$vmware_openqa_datastore/$qry_xz}, 'vmw-test-1: checking image 
management script, file destination: ' . $n . 'b';
+            like $last_run_commands[$n], 
qr{dd\s+if="\$src"\s+of="\$dest(?:_xz)?\.openQA-SUT-1\.part"\s+bs=1M}, 
'vmw-test-1: checking image management script, file origin:' . $n . 'a';
+            like $last_run_commands[$n], 
qr{xz\s+--decompress\s+"\$dest(?:_xz)?\.openQA-SUT-1\.part\.xz"}, 'vmw-test-1: 
checking image management script, file destination: ' . $n . 'b';
             $n += 1;
         }
     };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1790705326.6badaca/t/27-consoles-vmware.t 
new/os-autoinst-5.1790961809.b728c27/t/27-consoles-vmware.t
--- old/os-autoinst-5.1790705326.6badaca/t/27-consoles-vmware.t 2026-09-29 
20:08:46.000000000 +0200
+++ new/os-autoinst-5.1790961809.b728c27/t/27-consoles-vmware.t 2026-10-02 
19:23:29.000000000 +0200
@@ -30,6 +30,12 @@
 use Mojo::File qw(tempdir path);
 use Digest::SHA;
 
+# Maximum safe byte limit for shell scripts executed over SSH on ESXi.
+# ESXi's minimal BusyBox ash interpreter fails with a "/bin/sh: File too large"
+# kernel error (EFBIG) when parsing command strings via `sh -c` that exceed
+# roughly 8 KB (8192 bytes). We limit to 7000 as a conservative safety net.
+use constant MAX_ESXI_SHELL_SCRIPT_SIZE => 7000;
+
 use consoles::VMWare;
 
 $bmwqemu::topdir = "$Bin/..";
@@ -290,21 +296,22 @@
 
 subtest 'VMware images are verified against their published checksum before 
publishing' => sub {
     my $my_test_basedir = tempdir('/tmp/27-vmware-checksum-XXXX');
-    my $nfs_ds = 'openqa_checksum';
-    my $ds = 'datastore_checksum';
+    my $nfs_ds = 'openqa datastore space';
+    my $ds = 'datastore checksum space';
     $bmwqemu::vars{VMWARE_NFS_DATASTORE_DEBUG} = '0';
     $bmwqemu::vars{VIRSH_OPENQA_BASEDIR} = $my_test_basedir;
     $bmwqemu::vars{VMWARE_NFS_DATASTORE} = $nfs_ds;
-    my $iso = 'checksum-mock.iso';
+    my $iso = 'checksum mock.iso';
     my $source = path($my_test_basedir, $nfs_ds, 
'iso')->make_path->child($iso);
     $source->spew('VMware image with a published checksum');
     my $vmware_openqa_datastore = path($my_test_basedir, $ds, 
'openQA')->make_path;
     my $dest = path($vmware_openqa_datastore, $iso);
     my $digest = Digest::SHA->new(256)->addfile($source->to_string)->hexdigest;
     my $last_output;
+    my $last_cmd;
     # stands in for the sshVirtsh console, running the generated script on the 
local host
     my $svirt = Test::MockObject->new->set_always(name => 'openQA-SUT-1');
-    $svirt->mock(run_cmd => sub ($self, $cmd, %args) { $last_output = 
qx{($cmd) 2>&1}; $? >> 8 });
+    $svirt->mock(run_cmd => sub ($self, $cmd, %args) { $last_cmd = $cmd; 
$last_output = qx{($cmd) 2>&1}; $? >> 8 });
     $bmwqemu::vars{ISO} = "/var/lib/openqa/share/factory/iso/$iso";
     my $provide = sub { consoles::VMWare::provide_image_in_datastore($svirt, 
$source, $vmware_openqa_datastore) };
 
@@ -314,7 +321,12 @@
         lives_ok { $provide->() } 'image provided';
         is $dest->slurp, $source->slurp, 'published image matches the source';
         like $last_output, qr/Verified .*against its published checksum/, 
'verification is reported';
-        is_deeply [glob "$dest.*.part"], [], 'no temporary file left behind';
+        is_deeply $vmware_openqa_datastore->list->grep(qr/\.part$/)->to_array, 
[], 'no temporary file left behind';
+
+        ok length($last_cmd) <= MAX_ESXI_SHELL_SCRIPT_SIZE, 'generated shell 
script stays under conservative limit ' . MAX_ESXI_SHELL_SCRIPT_SIZE;
+        unlike $last_cmd, qr/\becho "Done: origin:.*?\*/, 'unsafe shell 
globbing is avoided in output messages';
+        my $path_occurrences = () = $last_cmd =~ 
/\Q$vmware_openqa_datastore\E/g;
+        ok $path_occurrences <= 3, 'path interpolation is minimized in favor 
of shell variables';
     };
 
     subtest 'mismatching checksum leaves the destination untouched' => sub {
@@ -324,7 +336,16 @@
         ok !-e $dest, 'a corrupt image is never published';
         like $last_output, qr/Checksum mismatch .*expected b{64} but computed 
SHA-256 \Q$digest\E/, 'mismatch names both digests';
         like path(consoles::VMWare::_failure_note_path($dest, 
'openQA-SUT-1'))->slurp, qr/Checksum mismatch .*expected b{64}/, 'the mismatch 
is left for the jobs waiting for this one';
-        is_deeply [glob "$dest.*.part"], [], 'temporary file removed';
+        is_deeply $vmware_openqa_datastore->list->grep(qr/\.part$/)->to_array, 
[], 'temporary file removed';
+    };
+
+    subtest 'mismatching 128 character SHA-512 checksum leaves the destination 
untouched' => sub {
+        $dest->remove;
+        $bmwqemu::vars{CHECKSUM_ISO} = 'b' x 128;
+        throws_ok { $provide->() } qr/Error on VMware image .* preparation/, 
'image preparation fails with SHA-512';
+        ok !-e $dest, 'a corrupt image is never published for SHA-512 
mismatch';
+        like $last_output, qr/Checksum mismatch .*expected b{128} but computed 
SHA-512 /, 'mismatch names SHA-512 digest';
+        is_deeply $vmware_openqa_datastore->list->grep(qr/\.part$/)->to_array, 
[], 'temporary file removed';
     };
 
     subtest 'image without a published checksum is copied unverified' => sub {
@@ -369,7 +390,7 @@
         throws_ok { $provide->() } qr/Error on VMware image .* preparation/, 
'image preparation fails on a mismatch';
         is $dest->slurp, 'verified against an older checksum', 'the existing 
image is left alone';
         is path(consoles::VMWare::_verified_record_path($dest))->slurp, 'c' x 
64, 'its record still describes it';
-        is_deeply [glob "$dest.*.part"], [], 'temporary file removed';
+        is_deeply $vmware_openqa_datastore->list->grep(qr/\.part$/)->to_array, 
[], 'temporary file removed';
     };
 
     subtest 'a job without a published checksum keeps using whatever is there' 
=> sub {

++++++ os-autoinst.obsinfo ++++++
--- /var/tmp/diff_new_pack.UEOXoU/_old  2026-10-06 19:16:44.377322226 +0200
+++ /var/tmp/diff_new_pack.UEOXoU/_new  2026-10-06 19:16:44.384322518 +0200
@@ -1,5 +1,5 @@
 name: os-autoinst
-version: 5.1790705326.6badaca
-mtime: 1790705326
-commit: 6badaca44aecd87a345b4bfb44f47c4909a7fbb3
+version: 5.1790961809.b728c27
+mtime: 1790961809
+commit: b728c272762ca2f93a58dc61fb379d2e99d60bc9
 

Reply via email to