From 22e46ad121a5b952b008f5b475314d883270b4cc Mon Sep 17 00:00:00 2001 From: Michele Pagot Date: Wed, 17 Jul 2024 17:30:54 +0200 Subject: [PATCH] Add registration to IpAddr2 test Optionally add registration. Enabled by IPADDR2_REGISTER configured to 1. The SCC code has to be provided in SCC_REGCODE_SLES4SAP. Add code to wait for ssh stable connection to internal VMs. --- lib/sles4sap/ipaddr2.pm | 77 ++++++++++++++++++++++++++--- t/22_ipaddr2.t | 39 +++++++++++++++ tests/sles4sap/ipaddr2/configure.pm | 14 +++++- 3 files changed, 121 insertions(+), 9 deletions(-) diff --git a/lib/sles4sap/ipaddr2.pm b/lib/sles4sap/ipaddr2.pm index 5012138c61d7..f966aac265c9 100644 --- a/lib/sles4sap/ipaddr2.pm +++ b/lib/sles4sap/ipaddr2.pm @@ -11,6 +11,7 @@ use warnings FATAL => 'all'; use testapi; use Carp qw(croak); use Exporter qw(import); +use Mojo::JSON qw(decode_json); use mmapi 'get_current_job_id'; use sles4sap::azure_cli; use publiccloud::utils; @@ -26,6 +27,7 @@ our @EXPORT = qw( ipaddr2_bastion_key_accept ipaddr2_destroy ipaddr2_create_cluster + ipaddr2_configure_register ipaddr2_deployment_sanity ipaddr2_deployment_logs ipaddr2_os_sanity @@ -765,7 +767,6 @@ sub ipaddr2_ssh_bastion_assert_script_run { "'$args{cmd}'")); } - =head2 ipaddr2_ssh_bastion_script_run my $ret = ipaddr2_ssh_bastion_script_run( @@ -881,11 +882,13 @@ using the assert_script_run API =item B - ID of the internal VM. Used to compose its name and as address for ssh. +=item B - Command to be run on the internal VM. + =item B - Public IP address of the bastion. Calculated if not provided. Providing it as an argument is recommended in order to avoid having to query Azure to get it. -=item B - Command to be run on the internal VM. +=item B - Execution timeout, default 90sec =back =cut @@ -895,11 +898,14 @@ sub ipaddr2_ssh_internal { foreach (qw(id cmd)) { croak("Argument < $_ > missing") unless $args{$_}; } $args{bastion_ip} //= ipaddr2_bastion_pubip(); + $args{timeout} //= 90; - assert_script_run(ipaddr2_ssh_internal_cmd( + assert_script_run( + ipaddr2_ssh_internal_cmd( id => $args{id}, bastion_ip => $args{bastion_ip}, - cmd => $args{cmd})); + cmd => $args{cmd}), + timeout => $args{timeout}); } =head2 ipaddr2_ssh_internal_output @@ -916,11 +922,13 @@ Return the command output. =item B - ID of the internal VM. Used to compose its name and as address for ssh. +=item B - Command to be run on the internal VM. + =item B - Public IP address of the bastion. Calculated if not provided. Providing it as an argument is recommended in order to avoid having to query Azure to get it. -=item B - Command to be run on the internal VM. +=item B - Execution timeout, default 90sec =back =cut @@ -930,11 +938,14 @@ sub ipaddr2_ssh_internal_output { foreach (qw(id cmd)) { croak("Argument < $_ > missing") unless $args{$_}; } $args{bastion_ip} //= ipaddr2_bastion_pubip(); + $args{timeout} //= 90; - return script_output(ipaddr2_ssh_internal_cmd( + return script_output( + ipaddr2_ssh_internal_cmd( id => $args{id}, bastion_ip => $args{bastion_ip}, - cmd => $args{cmd})); + cmd => $args{cmd}), + timeout => $args{timeout}); } =head2 ipaddr2_create_cluster @@ -999,6 +1010,58 @@ sub ipaddr2_create_cluster { bastion_ip => $args{bastion_ip}); } +=head2 ipaddr2_configure_register + + ipaddr2_configure_register(id => 1, code => '1234567890'); + +Register the image + +=over 3 + +=item B - VM id where to install and configure the web server + +=item B - registration code + +=item B - Public IP address of the bastion. Calculated if not provided. + Providing it as an argument is recommended in order + to avoid having to query Azure to get it. + +=back + +=cut + +sub ipaddr2_configure_register { + my (%args) = @_; + foreach (qw(id code)) { + croak("Argument < $_ > missing") unless $args{$_}; } + + $args{bastion_ip} //= ipaddr2_bastion_pubip(); + + # Initially suppose is registered + my $registered = 1; + my $json = decode_json(ipaddr2_ssh_internal_output( + id => $args{id}, + cmd => 'sudo SUSEConnect -s', + bastion_ip => $args{bastion_ip})); + foreach (@$json) { + if ($_->{status} =~ '^Not Registered') { + $registered = 0; + last; + } + } + return if $registered; + ipaddr2_ssh_internal( + id => $args{id}, + cmd => 'sudo registercloudguest --clean', + bastion_ip => $args{bastion_ip}); + + ipaddr2_ssh_internal( + id => $args{id}, + cmd => "sudo registercloudguest --force-new -r $args{code} -e \"testing\@suse.com\" || sudo cat /var/log/cloudregister", + bastion_ip => $args{bastion_ip}, + timeout => 300); +} + =head2 ipaddr2_deployment_logs ipaddr2_deployment_logs() diff --git a/t/22_ipaddr2.t b/t/22_ipaddr2.t index 862343931d7d..ea64967abe9b 100644 --- a/t/22_ipaddr2.t +++ b/t/22_ipaddr2.t @@ -264,4 +264,43 @@ subtest '[ipaddr2_deployment_logs]' => sub { ok(($called eq 1), "az_vm_diagnostic_log_get called"); }; +subtest '[ipaddr2_configure_register] all registered' => sub { + my $ipaddr2 = Test::MockModule->new('sles4sap::ipaddr2', no_auto => 1); + $ipaddr2->redefine(ipaddr2_bastion_pubip => sub { return '1.2.3.4'; }); + + my @calls; + $ipaddr2->redefine(assert_script_run => sub { push @calls, $_[0]; }); + $ipaddr2->redefine(script_output => sub { + push @calls, $_[0]; + # due to the itnernal implementation of the + #function under test, this status is equivalent to `Registered` + return '[{"status":"Bialetti"}]'; }); + + ipaddr2_configure_register(id => 42, code => 'Olivetti'); + + note("\n --> " . join("\n --> ", @calls)); + + ok((any { /SUSEConnect -s/ } @calls), 'SUSEConnect -s called'); + ok((none { /registercloudguest/ } @calls), 'registercloudguest not expected as all registered'); +}; + +subtest '[ipaddr2_configure_register] not registered' => sub { + my $ipaddr2 = Test::MockModule->new('sles4sap::ipaddr2', no_auto => 1); + $ipaddr2->redefine(ipaddr2_bastion_pubip => sub { return '1.2.3.4'; }); + + my @calls; + $ipaddr2->redefine(assert_script_run => sub { push @calls, $_[0]; }); + $ipaddr2->redefine(script_output => sub { + push @calls, $_[0]; + # due to the itnernal implementation of the + #function under test, this status is equivalent to `Registered` + return '[{"status":"Bialetti"}, {"status":"Not Registered2"}]'; }); + + ipaddr2_configure_register(id => 42, code => 'Olivetti'); + + note("\n --> " . join("\n --> ", @calls)); + ok((any { /SUSEConnect -s/ } @calls), 'SUSEConnect -s called'); + ok((any { /registercloudguest/ } @calls), 'registercloudguest expected as some are not registered'); +}; + done_testing; diff --git a/tests/sles4sap/ipaddr2/configure.pm b/tests/sles4sap/ipaddr2/configure.pm index 5caffc7a9dbf..0172525bab37 100644 --- a/tests/sles4sap/ipaddr2/configure.pm +++ b/tests/sles4sap/ipaddr2/configure.pm @@ -19,13 +19,23 @@ sub run { select_serial_terminal; - record_info("STAGE 1", "Prepare all the ssh connections within the 2 internal VMs"); + record_info("TEST STAGE", "Prepare all the ssh connections within the 2 internal VMs"); my $bastion_ip = ipaddr2_bastion_pubip(); ipaddr2_bastion_key_accept(bastion_ip => $bastion_ip); ipaddr2_internal_key_accept(bastion_ip => $bastion_ip); ipaddr2_internal_key_gen(bastion_ip => $bastion_ip); - record_info("STAGE 2", "Init and configure the Pacemaker cluster"); + if (check_var('IPADDR2_REGISTER', 1)) { + record_info("TEST STAGE", "Registration"); + foreach (1 .. 2) { + ipaddr2_configure_register( + bastion_ip => $bastion_ip, + id => $_, + code => get_required_var('SCC_REGCODE_SLES4SAP')); + } + } + + record_info("TEST STAGE", "Init and configure the Pacemaker cluster"); ipaddr2_create_cluster(bastion_ip => $bastion_ip); }