lib/sles4sap/qesap/qesapdeployment.pm

NAME

qe-sap-deployment test lib

COPYRIGHT

Copyright 2025 SUSE LLC
SPDX-License-Identifier: FSFAP

AUTHORS

QE SAP <qe-sap@suse.de>

DESCRIPTION

Package with common methods and default or constant values for qe-sap-deployment

Methods

qesap_get_file_paths

Returns a hash containing file paths for configuration files

qesap_create_folder_tree

Create all needed folders

qesap_get_variables

Scans yaml configuration for '%OPENQA_VARIABLE%' placeholders and
searches for values in OpenQA defined variables.
Returns hash with openqa variable key/value pairs.

qesap_create_ansible_section

Writes "ansible" section into yaml configuration file.
$args{ansible_section} defines section(key) name.
$args{section_content} defines content of names section.
    Example:
        @playbook_list = ("pre-cluster.yaml", "cluster_sbd_prep.yaml");
        qesap_create_ansible_section(ansible_section=>'create', section_content=>\@playbook_list);

qesap_venv_cmd_exec

Run a command within the Python virtualenv
created by qesap_pip_install.

This function never dies: it always returns an error to the caller.
Timeout error is 124 (the one reported by timeout command line utility).
CMD - command to run within the .venv, usually it is a qesap.py based command
TIMEOUT - default 90 secs, has to be an integer greater than 0
LOG_FILE - optional argument that results in changing the command to redirect the output to a log file

qesap_py

Return string of the python to use

qesap_pip

Return string of the pip to use

qesap_pip_install

Install all Python requirements of the qe-sap-deployment
in a dedicated virtual environment.
This function has no return code but it is expected to die
if something internally fails.

qesap_galaxy_install

Install all Ansible requirements of the qe-sap-deployment.
This function has no return code but it is expected to die
if something internally fails.

qesap_upload_logs

qesap_upload_logs([failok=1])

Collect and upload logs present in @log_files.
This is about logs generated locally on the jumphost.
FAILOK - used as failok for the upload_logs. continue even in case upload fails

qesap_get_deployment_code

Get the qe-sap-deployment code

qesap_get_roles_code Get the Ansible roles code from github.com/sap-linuxlab/community.sles-for-sap

Keep in mind that to allow qe-sap-deployment to use roles from this repo,
your config.yaml has to have a specific setting ansible::roles_path.

qesap_yaml_replace

Replaces yaml configuration file variables with parameters
defined by OpenQA test code, yaml template or yaml schedule.
Openqa variables need to be added as a hash
with key/value pair inside %run_args{openqa_variables}.
Example:
    my %variables;
    $variables{HANA_SAR} = get_required_var("HANA_SAR");
    $variables{HANA_CLIENT_SAR} = get_required_var("HANA_CLIENT_SAR");
    qesap_yaml_replace(openqa_variables=>\%variables);

qesap_execute

qesap_execute(
    cmd => '<configure|terraform,|ansible>',
    logname => '<SOMENAME>.log.txt'
    [, verbose => 1, cmd_options => <cmd_options>] );

Example:
    qesap_execute(cmd => 'terraform', logname => 'terraform_destroy.log.txt', cmd_options => '-d')
result in:
    qesap.py terraform -d

Execute qesap glue script commands. Check project documentation for available options:
https://github.com/SUSE/qe-sap-deployment
Function returns a two element array:
  - first element is an integer representing the execution result
  - second element is the file path of the execution log
This function is not expected to internally die, any failure has to be handled by the caller.
CMD - qesap.py subcommand to run
LOGNAME - filename of the log file. This file will be saved in `/tmp` folder
CMD_OPTIONS - set of arguments for the qesap.py subcommand
VERBOSE - activate verbosity in qesap.py. 0 is no verbosity (default), 1 is to enable verbosity
TIMEOUT - max expected execution time, default 90sec

qesap_terraform_conditional_retry

qesap_terraform_conditional_retry(
    error_list => ['Fatal:'],
    logname => 'somefile.txt'
    [, verbose => 1, cmd_options => '--parallel 3', timeout => 1200, retries => 5, destroy => 1] );

Execute 'qesap.py ... teraform' and eventually retry for some specific errors.
Test returns execution result in same format of qesap_execute.
ERROR_LIST - list of error strings to search for in the log file. If any is found, it enables terraform retry
LOGNAME - filename of the log file.
CMD_OPTIONS - set of arguments for the qesap.py subcommand
TIMEOUT - max expected execution time, default 90sec
RETRIES - number of retries in case of expected error
VERBOSE - activate verbosity in qesap.py. 0 is no verbosity (default), 1 is to enable verbosity
DESTROY - destroy terraform before retrying terraform apply

qesap_file_find_strings

Search for a list of strings in the Ansible log file.
Returns 1 if any of the strings are found in the log file, 0 otherwise.
FILE - Path to the Ansible log file. (Required)
SEARCH_STRINGS - Array of strings to search for in the log file. (Required)

qesap_get_inventory

Return the path of the generated inventory
PROVIDER - Cloud provider name using same format of PUBLIC_CLOUD_PROVIDER setting

qesap_get_nodes_number

Get the number of cluster nodes from the inventory.yaml

PROVIDER - Cloud provider name using same format of PUBLIC_CLOUD_PROVIDER setting

qesap_get_nodes_names

Get the cluster nodes' names from the inventory.yaml

PROVIDER - Cloud provider name using same format of PUBLIC_CLOUD_PROVIDER setting

qesap_get_terraform_dir

Return the path used by the qesap script as -chdir argument for terraform
It is useful if test would like to call terraform
PROVIDER - Cloud provider name using same format of PUBLIC_CLOUD_PROVIDER setting

qesap_get_ansible_roles_dir

Return the path where sap-linuxlab/community.sles-for-sap
has been installed

qesap_prepare_env

qesap_prepare_env(variables=>{dict with variables}, provider => 'aws');

Prepare terraform environment.
- creates file structures
- pulls git repository
- external configuration files
- installs pip requirements and OS packages
- generates configuration files with qesap script

For variables example see 'qesap_yaml_replace'
Returns only result, failure handling has to be done by calling method.
PROVIDER - Cloud provider name, used to optionally activate AWS credential code

qesap_ansible_get_playbook

Download the playbook from the test code repo
that is on the worker within the running JompHost.

qesap_ansible_cmd

Use Ansible to run a command remotely on some or all
the hosts from the inventory.yaml
PROVIDER - Cloud provider name, used to find the inventory
CMD - command to run remotely
USER - user on remote host, default to 'cloudadmin'
FILTER - filter hosts in the inventory
FAILOK - if not set, Ansible failure result in die
HOST_KEYS_CHECK - if set, add some extra argument to the Ansible call to allow contacting hosts not in the KnownHost list yet. This enables the use of this api before the call to qesap.py ansible
TIMEOUT - default 90 secs
VERBOSE - enable verbosity, default is OFF

qesap_ansible_script_output_file

Use Ansible to run a command remotely and get the stdout.
Command could be executed with elevated privileges

qesap_ansible_script_output_file(cmd => 'crm status', provider => 'aws', host => 'vmhana01', root => 1);

It uses playbook data/sles4sap/script_output.yaml

1. ansible-playbook runs the playbook
2. the playbook executes the command remotely and redirects the output to file, both remotely
3. qesap_ansible_fetch_file downloads the file locally
4. the file is read and stored to be returned to the caller

Return is the local full path of the file containing the output of the
remotely executed command.
PROVIDER - Cloud provider name, used to find the inventory
CMD - command to run remotely
HOST - filter hosts in the inventory
FILE - result file name
OUT_PATH - path to save result file locally (without file name)
USER - user on remote host, default to 'cloudadmin'
ROOT - 1 to enable remote execution with elevated user, default to 0
FAILOK - if not set, Ansible failure result in die
VERBOSE - 1 result in ansible-playbook to be called with '-vvvv', default is 0.
TIMEOUT - max expected execution time, default 180sec. Same timeout is used both for the execution of script_output.yaml and for the fetch_file. Timeout of the same amount is started two times.
REMOTE_PATH - Path to save file in the remote (without file name)

qesap_ansible_script_output

Return the output of a command executed on the remote machine via Ansible.
PROVIDER - Cloud provider name, used to find the inventory
CMD - command to run remotely
HOST - filter hosts in the inventory
USER - user on remote host, default to 'cloudadmin'
ROOT - 1 to enable remote execution with elevated user, default to 0
FAILOK - if not set, Ansible failure result in die
TIMEOUT - max expected execution time
FILE - result file name
OUT_PATH - path to save result file locally (without file name)
REMOTE_PATH - Path to save file in the remote (without file name)

qesap_ansible_fetch_file

Use Ansible to fetch a file from remote.
Command could be executed with elevated privileges

qesap_ansible_fetch_file(provider => 'aws', host => 'vmhana01', root => 1);

It uses playbook data/sles4sap/fetch_file.yaml

1. ansible-playbook run the playbook
3. the playbook download the file locally
4. the file is read and stored to be returned to the caller

Return the local path of the downloaded file.
PROVIDER - Cloud provider name, used to find the inventory
HOST - filter hosts in the inventory
REMOTE_PATH - path to find file in the remote (without file name)
USER - user on remote host, default to 'cloudadmin'
ROOT - 1 to enable remote execution with elevated user, default to 0
FAILOK - if not set, Ansible failure result in die
TIMEOUT - max expected execution time, default 180sec
FILE - file name of the local copy of the file
OUT_PATH - path to save file locally (without file name)
VERBOSE - 1 result in ansible-playbook to be called with '-vvvv', default is 0.

qesap_ansible_reg_module

Compose the ansible-playbook argument for the registration.yaml playbook,
about an additional module registration

-e sles_modules='[{"key":"SLES-LTSS-Extended-Security/12.5/x86_64","value":"*******"}]'

Known limitation is that registration.yaml supports multiple modules to be registered,
this code only supports one.

qesap_remote_hana_public_ips

Return a list of the public IP addresses of the systems
deployed by qe-sap-deployment, as reported by C<terraform output>.
Needs to run after C<qesap_execute(cmd => 'terraform');> call.

qesap_wait_for_ssh

Probe specified port on the remote host each 5sec till response.
Return -1 in case of timeout
Return total time of retry loop in case of pass.
HOST - IP of the host to probe
TIMEOUT - time to wait before to give up, default is 10mins
PORT - port to probe, default is 22

qesap_upload_crm_report

Run crm report on a host and upload the resulting tarball to openqa
HOST - host to get the report from
PROVIDER - Cloud provider name, used to find the inventory
FAILOK - if not set, Ansible failure result in die

qesap_upload_supportconfig_logs

Genarate supportconfig log on a host and upload the resulting tarball to openqa
HOST - host to get the report from
PROVIDER - Cloud provider name, used to find the inventory
FAILOK - if not set, Ansible failure result in die

qesap_cluster_log_cmds

List of commands to collect logs from a deployed cluster

qesap_cluster_logs

Collect logs from a deployed cluster.
This is about logs generated remotely on the two HANA nodes,
`crm report` collection is part of this function.

qesap_supportconfig_logs

Collect supportconfig logs from all HANA nodes of a deployed cluster
PROVIDER - Cloud provider name using same format of PUBLIC_CLOUD_PROVIDER setting

qesap_calculate_deployment_name

Compose the deployment name. It always has the JobId

PREFIX - optional substring prepend in front of the job id

qesap_aws_filter_query

Generic function to compose a aws cli command with:
  - `aws ec2` something
  - use both `filter` and `query`
  - has text output

qesap_add_server_to_hosts

Adds a 'ip -> name' pair in the end of /etc/hosts in the hosts
IP - ip of server to add to hosts
NAME - name of server to add to hosts

qesap_import_instances

Downloads assets required for re-using infrastructure from previously exported test.
qesap_import_instances(<$test_id>)
$test_id - OpenQA test ID from a test previously run with "QESAP_DEPLOYMENT_IMPORT=1" and infrastructure still being up and running

qesap_export_instances

Downloads assets required for re-using infrastructure from previously exported test.
qesap_export_instances()

qesap_is_job_finished

Get whether a specified job is still running or not. 
In cases of ambiguous responses, they are considered to be in `running` state.
JOB_ID - id of job to check

qesap_az_get_resource_group

Query and return the resource group used by the qe-sap-deployment

SUBSTRING - optional substring to be used with additional grep at the end of the command

qesap_calculate_address_range

Calculate a main range that can be used in Azure for vnet or in AWS for vpc. Also calculate a secondary range within the main one for Azure subnet address ranges. The format is 10.ip2.ip3.0/21 and /24 respectively. ip2 and ip3 are calculated using the slot number as seed.

SLOT - integer to be used as seed in calculating addresses

qesap_az_vnet_peering

Create a pair of network peering between
the two provided deployments.
SOURCE_GROUP - resource group of source
TARGET_GROUP - resource group of target
TIMEOUT - default is 5 mins

qesap_az_simple_peering_delete

Delete a single peering one way
RG - Name of the resource group
VNET_NAME - Name of the vnet
PEERING_NAME - Name of the peering
TIMEOUT - (Optional) Timeout for the script_run command

qesap_az_vnet_peering_delete

Delete all the network peering between the two provided deployments.
TARGET_GROUP - resource group of target. This parameter is mandatory and the associated resource group is supposed to still exist.
TIMEOUT - default is 5 mins

qesap_az_peering_list_cmd

Compose the azure peering list command, using the provided:
- resource group, and
- vnet
Returns the command string to be run.
RESOURCE_GROUP - resource group connected to the peering
VNET - vnet connected to the peering

qesap_az_get_peering_name

Search for all network peering related to both:
 - resource group related to the current job
 - the provided resource group.
Returns the peering name or
empty string if a peering doesn't exist
RESOURCE_GROUP - resource group connected to the peering

qesap_az_get_active_peerings

Get active peering for Azure jobs
RG - Resource group in question
VNET - vnet name of rg

qesap_az_clean_old_peerings

Delete leftover peering for Azure jobs that finished without cleaning up
RG - Resource group in question
VNET - vnet name of rg

qesap_az_setup_native_fencing_permissions

qesap_az_setup_native_fencing_permissions(vmname=>$vm_name,
    resource_group=>$resource_group);

Sets up managed identity (MSI) by enabling system assigned identity and
role 'Virtual Machine Contributor'
VM_NAME - VM name
RESOURCE_GROUP - resource group resource belongs to

qesap_az_get_tenant_id

qesap_az_get_tenant_id( subscription_id=>$subscription_id )

Returns tenant ID related to the specified subscription ID.
subscription_id - valid azure subscription

qesap_az_create_sas_token

Generate a SAS URI token for a storage container of choice

Return the token string

STORAGE - Storage account name used fur the --account-name argument in az commands
CONTAINER - container name within the storage account
KEYNAME - name of the access key within the storage account
PERMISSION - access permissions. Syntax is what documented in 'az storage container generate-sas --help'. Some of them of interest: (a)dd (c)reate (d)elete (e)xecute (l)ist (m)ove (r)ead (w)rite. Default is 'r'
LIFETIME - life time of the token in minutes, default is 10min

qesap_az_list_container_files

Returns a list of the files that exist inside a given path in a given container in Azure storage.

Generated command looks like this:

az storage blob list --account-name <account_name> --container-name <container_name> --sas-token "<my_token>" --prefix <path_inside_container> --query "[].{name:name}" --output tsv

STORAGE - Storage account name used fur the --account-name argument in az commands
CONTAINER - container name within the storage account
TOKEN - name of the SAS token to access the account (needs to have l permission)
PREFIX - the local path inside the container (to list file inside a folder named 'dir', this would be 'dir')

qesap_az_diagnostic_log

Call `az vm boot-diagnostics json` for each running VM in the resource group associated to this openQA job

Return a list of diagnostic file paths on the JumpHost

qesap_terrafom_ansible_deploy_retry

    qesap_terrafom_ansible_deploy_retry( error_log=>$error_log )
        error_log - ansible error log file name

    Retry to deploy terraform + ansible. This function is only expected to be called if a previous `qesap.py`
    execution returns a non zero exit code. If this function is called after a successful execution,
    the qesap_ansible_error_detection will not find anything wrong in the log, wrongly concluding that
    an unknown error is in the log and skipping the retry and this function will return 1.
.
    Return 0: this function manage the failure properly, perform a retry and retry was a successful deployment
    Return 1: something went wrong or this function does not know what to do with the failure
ERROR_LOG - error log filename
PROVIDER - cloud provider name as from PUBLIC_CLOUD_PROVIDER setting

qesap_ansible_error_detection

qesap_ansible_error_detection( error_log=>$error_log )

Inspect the provided Ansible log and search for known issue in the log
Also provide a nice record_info to summarize the error
Return:
 - 0: unable to detect errors
 - 1: generic fatal error
 - 2: reboot timeout
 - 3: no sudo password
ERROR_LOG - error log filename