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-05-06 19:20:39 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/os-autoinst (Old) and /work/SRC/openSUSE:Factory/.os-autoinst.new.30200 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "os-autoinst" Wed May 6 19:20:39 2026 rev:594 rq:1351238 version:5.1778069368.c751b82 Changes: -------- --- /work/SRC/openSUSE:Factory/os-autoinst/os-autoinst.changes 2026-05-05 15:17:51.173255564 +0200 +++ /work/SRC/openSUSE:Factory/.os-autoinst.new.30200/os-autoinst.changes 2026-05-06 19:24:57.034540014 +0200 @@ -1,0 +2,10 @@ +Wed May 06 12:09:38 UTC 2026 - [email protected] + +- Update to version 5.1778069368.c751b82: + * feat(qemu): improve port conflict detection and VNC error diagnostics + * fix: restore serial marker hook after switching users + * fix: handle pre-marker pending text in script_output + * fix: echo json_cmd_token in isotovideo responses + * fix: re-install serial marker hook after console reset + +------------------------------------------------------------------- Old: ---- os-autoinst-5.1777891128.f572829.obscpio New: ---- os-autoinst-5.1778069368.c751b82.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ os-autoinst-devel-test.spec ++++++ --- /var/tmp/diff_new_pack.2fntU3/_old 2026-05-06 19:24:59.262631927 +0200 +++ /var/tmp/diff_new_pack.2fntU3/_new 2026-05-06 19:24:59.278632588 +0200 @@ -18,7 +18,7 @@ %define short_name os-autoinst-devel Name: %{short_name}-test -Version: 5.1777891128.f572829 +Version: 5.1778069368.c751b82 Release: 0 Summary: Test package for %{short_name} License: GPL-2.0-or-later ++++++ os-autoinst-openvswitch-test.spec ++++++ --- /var/tmp/diff_new_pack.2fntU3/_old 2026-05-06 19:24:59.554643974 +0200 +++ /var/tmp/diff_new_pack.2fntU3/_new 2026-05-06 19:24:59.570644634 +0200 @@ -19,7 +19,7 @@ %define name_ext -test %define short_name os-autoinst-openvswitch Name: %{short_name}%{?name_ext} -Version: 5.1777891128.f572829 +Version: 5.1778069368.c751b82 Release: 0 Summary: test package for %{short_name} License: GPL-2.0-or-later ++++++ os-autoinst-test.spec ++++++ --- /var/tmp/diff_new_pack.2fntU3/_old 2026-05-06 19:24:59.890657835 +0200 +++ /var/tmp/diff_new_pack.2fntU3/_new 2026-05-06 19:24:59.906658495 +0200 @@ -19,7 +19,7 @@ %define name_ext -test %define short_name os-autoinst Name: %{short_name}%{?name_ext} -Version: 5.1777891128.f572829 +Version: 5.1778069368.c751b82 Release: 0 Summary: test package for os-autoinst License: GPL-2.0-or-later ++++++ os-autoinst.spec ++++++ --- /var/tmp/diff_new_pack.2fntU3/_old 2026-05-06 19:25:00.270673512 +0200 +++ /var/tmp/diff_new_pack.2fntU3/_new 2026-05-06 19:25:00.282674007 +0200 @@ -17,7 +17,7 @@ Name: os-autoinst -Version: 5.1777891128.f572829 +Version: 5.1778069368.c751b82 Release: 0 Summary: OS-level test automation License: GPL-2.0-or-later ++++++ os-autoinst-5.1777891128.f572829.obscpio -> os-autoinst-5.1778069368.c751b82.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-autoinst-5.1777891128.f572829/backend/qemu.pm new/os-autoinst-5.1778069368.c751b82/backend/qemu.pm --- old/os-autoinst-5.1777891128.f572829/backend/qemu.pm 2026-05-04 12:38:48.000000000 +0200 +++ new/os-autoinst-5.1778069368.c751b82/backend/qemu.pm 2026-05-06 14:09:28.000000000 +0200 @@ -11,6 +11,7 @@ use File::Which; use Time::HiRes qw(sleep gettimeofday); use Time::Seconds; +use IO::Socket::UNIX 'SOCK_STREAM'; use IO::Handle; use POSIX qw(strftime :sys_wait_h mkfifo); use Mojo::File 'path'; @@ -922,6 +923,7 @@ for (my $i = 0; $i < $num_networks; $i++) { if ($vars->{NICTYPE} eq 'user') { + _assert_port_availability($_, 'hostfwd') for _extract_hostfwd_ports($vars->{NICTYPE_USER_OPTIONS} // ''); my $nictype_user_options = $vars->{NICTYPE_USER_OPTIONS} ? ',' . $vars->{NICTYPE_USER_OPTIONS} : ''; $nictype_user_options .= ",smb=${\(dirname($basedir))}" if ($vars->{QEMU_ENABLE_SMBD}); sp('netdev', [qv "user id=qanet$i$nictype_user_options"]); @@ -1058,20 +1060,23 @@ $self->{qmpsocket} = $self->{proc}->connect_qmp(); my $init = myjsonrpc::read_json($self->{qmpsocket}); my $hash = $self->handle_qmp_command({execute => 'qmp_capabilities'}); - + my $vncport = 5900 + $bmwqemu::vars{VNC}; my $vnc = $testapi::distri->add_console( 'sut', 'vnc-base', { hostname => 'localhost', connect_timeout => 3, - port => 5900 + $bmwqemu::vars{VNC}, + port => $vncport, description => q{QEMU's VNC}}); $vnc->backend($self); my $ret = $self->select_console({testapi_console => 'sut'}); - die $ret->{error} if $ret->{error}; + if ($ret->{error}) { + bmwqemu::fctinfo("VNC port details:\n" . _port_details($vncport)); + die $ret->{error}; + } if ($vars->{NICTYPE} eq 'tap') { $self->{allocated_networks} = $num_networks; $self->{allocated_tap_devices} = \@tapdev; @@ -1223,6 +1228,29 @@ return $self->SUPER::check_socket($fh); } +sub _extract_hostfwd_ports ($args) { return $args =~ /hostfwd=(?:tcp|udp)::(\d+)-/g; } + +sub _port_details ($port) { + my @ss_output = qx{ss -tlnp 2>/dev/null}; + my @port_info = grep { /\b$port\b/ } @ss_output; + return @port_info ? join('', @port_info) : 'no details found'; +} + +sub _assert_port_availability ($port, $service) { + bmwqemu::fctinfo("checking $port port availability"); + my $sock = IO::Socket::IP->new( + PeerAddr => 'localhost', + PeerPort => $port, + Type => SOCK_STREAM, + Timeout => 1, + ); + if ($sock) { + $sock->close; + die "Port $port ($service) is already in use\n" . _port_details($port); + } + return 0; +} + sub freeze_vm ($self, @) { # qemu specific - all other backends will crash my $ret = $self->handle_qmp_command({execute => 'stop'}, fatal => 1); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-autoinst-5.1777891128.f572829/distribution.pm new/os-autoinst-5.1778069368.c751b82/distribution.pm --- old/os-autoinst-5.1777891128.f572829/distribution.pm 2026-05-04 12:38:48.000000000 +0200 +++ new/os-autoinst-5.1778069368.c751b82/distribution.pm 2026-05-06 14:09:28.000000000 +0200 @@ -85,6 +85,7 @@ testapi::enter_cmd('test $(id -u) -eq 0 && echo "imroot" > /dev/' . $testapi::serialdev, 0); testapi::wait_serial('imroot') || die 'Root prompt not there'; testapi::enter_cmd('cd /tmp'); + $self->invalidate_serial_marker_hook(); } =head 2 disable_key_repeat @@ -449,12 +450,49 @@ my $marker_match = 'OA:START'; my $hook_cmd = "for f in ~/.bashrc ~/.profile; do grep -q '$marker_match' \"\$f\" 2>/dev/null || cat <<'EOF' >> \"\$f\"\n$pc\nEOF\ndone\n"; testapi::type_string $hook_cmd; - my $console = testapi::current_console() // 'sut'; + my $console = testapi::current_console(); + return undef unless defined $console; $self->{_serial_marker_hook_installed}->{$console} = 1; } -sub reset_console_cache ($self, $console) { +=head2 reset_serial_marker + + reset_serial_marker([$console]) + +Perform a full reset of the serial marker state for the given C<$console> (or +the current console if omitted). This clears both the detected shell capability +level and the hook installation status, forcing a complete re-detection and +re-installation on the next command. + +Useful when the console environment has fundamentally changed, such as after +a reboot or when switching to a different OS/shell. + +=cut + +sub reset_serial_marker ($self, $console = undef) { + $console //= testapi::current_console(); + return undef unless defined $console; delete $self->{_serial_marker_level}->{$console}; + $self->invalidate_serial_marker_hook($console); +} + +=head2 invalidate_serial_marker_hook + + invalidate_serial_marker_hook([$console]) + +Invalidate the synchronization hook (e.g. C<PROMPT_COMMAND>) for the given +C<$console> (or the current console if omitted). Unlike L</reset_serial_marker>, +this preserves the detected shell capability level. + +Useful when switching users within the same shell (e.g. via C<sudo> or C<su>), +where we know the shell still supports the same level of markers, but the +environment-specific hook needs to be re-installed for the new user. + +=cut + +sub invalidate_serial_marker_hook ($self, $console = undef) { + $console //= testapi::current_console(); + return undef unless defined $console; delete $self->{_serial_marker_hook_installed}->{$console}; } @@ -471,7 +509,8 @@ =cut sub _detect_serial_marker_capability ($self) { - my $console = testapi::current_console() // 'sut'; + my $console = testapi::current_console(); + return 1 unless defined $console; if (my $level = $self->{_serial_marker_level}->{$console}) { return $level if $level < 2 || $self->{_serial_marker_hook_installed}->{$console}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-autoinst-5.1777891128.f572829/t/05-distribution.t new/os-autoinst-5.1778069368.c751b82/t/05-distribution.t --- old/os-autoinst-5.1777891128.f572829/t/05-distribution.t 2026-05-04 12:38:48.000000000 +0200 +++ new/os-autoinst-5.1778069368.c751b82/t/05-distribution.t 2026-05-06 14:09:28.000000000 +0200 @@ -145,7 +145,7 @@ $mock_testapi->redefine(type_string => sub { $typed .= $_[0] }); $d->{_serial_marker_level}->{'test-console'} = 2; - delete $d->{_serial_marker_hook_installed}->{'test-console'}; + $d->invalidate_serial_marker_hook('test-console'); is $d->_detect_serial_marker_capability(), 2, 'Returns cached level 2'; like $typed, qr/PROMPT_COMMAND=/, 'Calls install_serial_marker_hook (types PROMPT_COMMAND)'; @@ -189,10 +189,10 @@ like $typed_string, qr/bar\n/, 'Command typed'; # Case 2: manual clear (e.g. if we know it was lost) - $d->reset_console_cache('test-console'); + $d->reset_serial_marker('test-console'); $typed_string = ''; $d->script_run('baz'); - like $typed_string, qr/PROMPT_COMMAND=.*OA:DONE/, 'Re-detect and re-install after resetting the console cache'; + like $typed_string, qr/PROMPT_COMMAND=.*OA:DONE/, 'Re-detect and re-install after resetting the serial marker'; like $typed_string, qr/baz\n/, 'Command typed after re-installation'; # Case 3: select_console triggers reset diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-autoinst-5.1777891128.f572829/t/18-backend-qemu.t new/os-autoinst-5.1778069368.c751b82/t/18-backend-qemu.t --- old/os-autoinst-5.1777891128.f572829/t/18-backend-qemu.t 2026-05-04 12:38:48.000000000 +0200 +++ new/os-autoinst-5.1778069368.c751b82/t/18-backend-qemu.t 2026-05-06 14:09:28.000000000 +0200 @@ -814,6 +814,39 @@ }; }; +subtest 'extract hostfwd ports from NICTYPE_USER_OPTIONS' => sub { + is_deeply [backend::qemu::_extract_hostfwd_ports('hostfwd=tcp::39100-:39100')], [39100], 'single tcp hostfwd'; + is_deeply [backend::qemu::_extract_hostfwd_ports('hostfwd=tcp::39100-:39100,hostfwd=tcp::5555-:22')], + [39100, 5555], 'multiple tcp hostfwd'; + is_deeply [backend::qemu::_extract_hostfwd_ports('hostfwd=udp::1234-:1234')], [1234], 'udp hostfwd'; + is_deeply [backend::qemu::_extract_hostfwd_ports('restrict=on')], [], 'no hostfwd options'; + is_deeply [backend::qemu::_extract_hostfwd_ports('')], [], 'empty string'; +}; + +subtest 'port availability checks' => sub { + my %initial_vars = %bmwqemu::vars; + my $sock_mock = Test::MockModule->new('IO::Socket::IP'); + subtest VNC => sub { + combined_like { lives_ok { backend::qemu::_assert_port_availability(5991, 'test') } 'free port passes' } + qr/checking 5991 port availability/, 'logs port post-qemu check for VNC'; + $backend_mock->redefine(select_console => sub { {error => 'VNC connection failed'} }); + combined_like { + throws_ok { $backend->start_qemu } qr/VNC connection failed/, 'dies on VNC error' + } qr/VNC port details/, 'logs port details on VNC failure'; + $backend_mock->redefine(select_console => undef); + }; + subtest hostfwd => sub { + $bmwqemu::vars{NICTYPE} = 'user'; + $bmwqemu::vars{NICTYPE_USER_OPTIONS} = 'hostfwd=tcp::39100-:39100'; + combined_like { lives_ok { backend::qemu::_assert_port_availability(39100, 'test') } 'free port passes' } + qr/checking 39100 port availability/, 'logs port pre-qemu check with hostfwd'; + $sock_mock->redefine(new => sub { Test::MockObject->new->set_true('close') }); + combined_like { throws_ok { $backend->start_qemu } qr/Port 39100 \(hostfwd\) is already in use/, 'dies on hostfwd port conflict' } + qr/qemu version/si, 'expected logs before hostfwd port check'; + }; + %bmwqemu::vars = %initial_vars; +}; + subtest 'special cases when handling QMP command' => sub { my $create_virtio_console_fifo_called; # uncoverable statement count:2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-autoinst-5.1777891128.f572829/testapi.pm new/os-autoinst-5.1778069368.c751b82/testapi.pm --- old/os-autoinst-5.1777891128.f572829/testapi.pm 2026-05-04 12:38:48.000000000 +0200 +++ new/os-autoinst-5.1778069368.c751b82/testapi.pm 2026-05-06 14:09:28.000000000 +0200 @@ -1706,7 +1706,7 @@ $autotest::selected_console = $testapi_console; if ($ret->{activated}) { push @$autotest::activated_consoles, $testapi_console; - $testapi::distri->reset_console_cache($testapi_console); + $testapi::distri->reset_serial_marker($testapi_console); $testapi::distri->activate_console($testapi_console, @args); } $testapi::distri->console_selected($testapi_console, @args); ++++++ os-autoinst.obsinfo ++++++ --- /var/tmp/diff_new_pack.2fntU3/_old 2026-05-06 19:25:05.750899583 +0200 +++ /var/tmp/diff_new_pack.2fntU3/_new 2026-05-06 19:25:05.754899748 +0200 @@ -1,5 +1,5 @@ name: os-autoinst -version: 5.1777891128.f572829 -mtime: 1777891128 -commit: f5728294afb1ee469327074230e3df21639643cd +version: 5.1778069368.c751b82 +mtime: 1778069368 +commit: c751b829cb8f524a6b2761581ef7de297bf304e1
