sap-linuxlab / community.sap_libs

Automation for SAP - Collection of Ansible Modules for SAP for low-level activities which are highly reusable
Apache License 2.0
16 stars 7 forks source link

Run SAP task lists with a variant #31

Closed joanba68 closed 10 months ago

joanba68 commented 11 months ago

Summary

We're automating the bootstraping of an SAP application server with ansible and DevOps. We're able to create the server, install OS, install SAP application instance with SWPM, update profiles and restart it. To finish this initial setup we want to run a task list we've created in the SAP system using community.sap_libs.sap_task_list_execute module but it looks like there is no option to specify a variant. I see it's possible to pass parameters to an specific step, but in our case we should run the step twice so how to identify each one. As example, these are two steps:

CL_STCT_CREATE_LOGONGROUP --> with defaults to add server in PUBLIC logon group and parallel_generators RFC group CL_STCT_CREATE_LOGONGROUP --> to add to an additional RFC server named 390

Any idea ?

Issue Type

Feature Idea

Component Name

community.sap_libs ansible module

Additional Information

Code of Conduct

rainerleber commented 11 months ago

Hi @joanba68 ,

thank you for recreating the issue.

I assume your tasklist contains two tasks with the same function in different fields. Is this correct?

To be able to set different values for the same function you have to define the fieldname.

Example:


- name: Pass in input parameters
  community.sap_libs.sap_task_list_execute:
    conn_username: DDIC
    conn_password: Passwd1234
    host: 10.1.8.10
    sysnr: '00'
    client: '000'
    task_to_execute: SAP_BASIS_SSL_CHECK
    task_parameters :
      - { 'TASKNAME': 'CL_STCT_CHECK_SEC_CRYPTO', 'FIELDNAME': 'P_OPT2', 'VALUE': 'X' }
      - TASKNAME: CL_STCT_CHECK_SEC_CRYPTO
        FIELDNAME: P_OPT3
        VALUE: X
    task_settings: batch

Please let me know if this will solve your problem.

joanba68 commented 11 months ago

Hi @rainerleber

Answer solves the question partially: basically I should run the task list with the duplicated step with specific values and after the complete task list with defaults, this is because task list contains SICK check at the end and it will grant a full check.

- name: Run SAP task list
  hosts: sap
  become: true 

  tasks:

# Now, just one additional step with the required RFC group 390 
  - name: Pass in input parameters
    community.sap_libs.sap_task_list_execute:
      conn_username: "{{ sap_user }}"
      conn_password: "{{ sap_pwd }}"
      host: "{{ inventory_hostname }}"
      sysnr: "{{ instnum }}"
      client: "{{ client }}"
      task_to_execute: ZBC_SCALEUP_SERVER_CONFIG
      task_parameters :
          - { 'TASKNAME': 'CL_STCT_CREATE_LOGONGROUP', 'FIELDNAME': 'PLG_NAME', 'VALUE': '390', 'FIELDNAME': 'PLG_TYPE', 'VALUE': 'S' }
      task_settings: batch

 # Run the complete task list for default values: PUBLIC and parallel_generators groups
  - name: Test task execution
    community.sap_libs.sap_task_list_execute:
      conn_username: "{{ user }}"
      conn_password: "{{ pwd }}"
      host: "{{ inventory_hostname }}"
      sysnr: "{{ instnum }}"
      client: "{{ client }}"
      task_to_execute: ZBC_SCALEUP_SERVER_CONFIG
      task_settings: batch

Nevertheless, we want to run this ansible task in an SAP application server which already has an active SAP kernel, so in theory should not be needed to install the NW RFC SDK. So now features required are two:

joanba68 commented 11 months ago

Finally installed pyrfc and nwrfcsdk on target server to try to run the SAP task list... but ansible complains as it's not finding pyrfc:

(...)
<10.68.16.20> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="ansibleadm"' -o ConnectTimeout=60 -o StrictHostKeyChecking=no -o 'ControlPath="/home/ansibleadm/.ansible/cp/db9d67e810"' 10.68.16.20 '/bin/sh -c '"'"'rm -f -r /home/ansibleadm/.ansible/tmp/ansible-tmp-1696953776.2899356-1906641-101072697211295/ > /dev/null 2>&1 && sleep 0'"'"''
<10.68.16.20> (0, b'', b'')
The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_community.sap_libs.sap_task_list_execute_payload_50_ncshg/ansible_community.sap_libs.sap_task_list_execute_payload.zip/ansible_collections/community/sap_libs/plugins/modules/sap_task_list_execute.py", line 191, in <module>
ModuleNotFoundError: No module named 'pyrfc'
fatal: [10.68.16.20]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "client": "100",
            "conn_password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "conn_username": "B-BC-GL-0001",
            "host": "10.68.16.20",
            "sysnr": "00",
            "task_parameters": null,
            "task_settings": [
                "batch"
            ],
            "task_skip": false,
            "task_to_execute": "ZBC_SCALEUP_SERVER_CONFIG"
        }
    },
    "msg": "Failed to import the required Python library (pyrfc) on useazsbxss199's Python /usr/libexec/platform-python. Please read the module documentation and install it in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter"
}

Questions:

Any idea ?

rainerleber commented 11 months ago

Python Modules are a bit tricky. You should consider running the task with 'delegate_to: 127.0.0.1'

install pyrfc and netweaver sdk on the ansible controller to not waste the application servers.

Your error is dependent on which default python version is used by ansible and the python version you installed pyrfc.

'pip3 list' should show you the pyrfc module.

In the ansible.cfg you could define the python version.

joanba68 commented 11 months ago

Still fighting on pyrfc availability. I see that task arrives to target server but error is, as you point, an incorrect version of python messing things. We're rebuilding the server with a clean python install in the right version.

[root@useazsbxss199 ~]# ls -la /usr/libexec/platform-python*
lrwxrwxrwx. 1 root root    20 Jun 14  2022 /usr/libexec/platform-python -> ./platform-python3.6
-rwxr-xr-x. 2 root root 11856 Jun 14  2022 /usr/libexec/platform-python3.6
-rwxr-xr-x. 2 root root 11856 Jun 14  2022 /usr/libexec/platform-python3.6m
[root@useazsbxss199 ~]# alternatives --config python

There are 3 programs which provide 'python'.

  Selection    Command
-----------------------------------------------
*  1           /usr/libexec/no-python
   2           /usr/bin/python3
 + 3           /usr/bin/python3.9

Enter to keep the current selection[+], or type selection number:

running any python command goes to v3.9 but links are not yet fixed.

joanba68 commented 11 months ago

Using ansible_python_interpreter var pointing to /usr/bin/python3.9 we solve the error, but it seems a never ending story:

The full traceback is:
Traceback (most recent call last):
  File "/home/ansibleadm/.ansible/tmp/ansible-tmp-1697012550.985591-2059603-103900958887378/AnsiballZ_sap_task_list_execute.py", line 107, in <module>
    _ansiballz_main()
  File "/home/ansibleadm/.ansible/tmp/ansible-tmp-1697012550.985591-2059603-103900958887378/AnsiballZ_sap_task_list_execute.py", line 99, in _ansiballz_main
    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
  File "/home/ansibleadm/.ansible/tmp/ansible-tmp-1697012550.985591-2059603-103900958887378/AnsiballZ_sap_task_list_execute.py", line 47, in invoke_module
    runpy.run_module(mod_name='ansible_collections.community.sap_libs.plugins.modules.sap_task_list_execute', init_globals=dict(_module_fqn='ansible_collections.community.sap_libs.plugins.modules.sap_task_list_execute', _modlib_path=modlib_path),
  File "/usr/lib64/python3.9/runpy.py", line 210, in run_module
    return _run_module_code(code, init_globals, run_name, mod_spec)
  File "/usr/lib64/python3.9/runpy.py", line 97, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "/usr/lib64/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/tmp/ansible_community.sap_libs.sap_task_list_execute_payload_a4ch2qt9/ansible_community.sap_libs.sap_task_list_execute_payload.zip/ansible_collections/community/sap_libs/plugins/modules/sap_task_list_execute.py", line 348, in <module>
  File "/tmp/ansible_community.sap_libs.sap_task_list_execute_payload_a4ch2qt9/ansible_community.sap_libs.sap_task_list_execute_payload.zip/ansible_collections/community/sap_libs/plugins/modules/sap_task_list_execute.py", line 344, in main
  File "/tmp/ansible_community.sap_libs.sap_task_list_execute_payload_a4ch2qt9/ansible_community.sap_libs.sap_task_list_execute_payload.zip/ansible_collections/community/sap_libs/plugins/modules/sap_task_list_execute.py", line 334, in run_module
  File "/tmp/ansible_community.sap_libs.sap_task_list_execute_payload_a4ch2qt9/ansible_community.sap_libs.sap_task_list_execute_payload.zip/ansible_collections/community/sap_libs/plugins/modules/sap_task_list_execute.py", line 223, in xml_to_dict
  File "/usr/local/lib/python3.9/site-packages/xmltodict.py", line 378, in parse
    parser.Parse(xml_input, True)
xml.parsers.expat.ExpatError: no element found: line 1, column 0
fatal: [10.68.16.20]: FAILED! => {
    "changed": false,
    "module_stderr": "Shared connection to 10.68.16.20 closed.\r\n",
    "module_stdout": "Traceback (most recent call last):\r\n  File \"/home/ansibleadm/.ansible/tmp/ansible-tmp-1697012550.985591-2059603-103900958887378/AnsiballZ_sap_task_list_execute.py\", line 107, in <module>\r\n    _ansiballz_main()\r\n  File \"/home/ansibleadm/.ansible/tmp/ansible-tmp-1697012550.985591-2059603-103900958887378/AnsiballZ_sap_task_list_execute.py\", line 99, in _ansiballz_main\r\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n  File \"/home/ansibleadm/.ansible/tmp/ansible-tmp-1697012550.985591-2059603-103900958887378/AnsiballZ_sap_task_list_execute.py\", line 47, in invoke_module\r\n    runpy.run_module(mod_name='ansible_collections.community.sap_libs.plugins.modules.sap_task_list_execute', init_globals=dict(_module_fqn='ansible_collections.community.sap_libs.plugins.modules.sap_task_list_execute', _modlib_path=modlib_path),\r\n  File \"/usr/lib64/python3.9/runpy.py\", line 210, in run_module\r\n    return _run_module_code(code, init_globals, run_name, mod_spec)\r\n  File \"/usr/lib64/python3.9/runpy.py\", line 97, in _run_module_code\r\n    _run_code(code, mod_globals, init_globals,\r\n  File \"/usr/lib64/python3.9/runpy.py\", line 87, in _run_code\r\n    exec(code, run_globals)\r\n  File \"/tmp/ansible_community.sap_libs.sap_task_list_execute_payload_a4ch2qt9/ansible_community.sap_libs.sap_task_list_execute_payload.zip/ansible_collections/community/sap_libs/plugins/modules/sap_task_list_execute.py\", line 348, in <module>\r\n  File \"/tmp/ansible_community.sap_libs.sap_task_list_execute_payload_a4ch2qt9/ansible_community.sap_libs.sap_task_list_execute_payload.zip/ansible_collections/community/sap_libs/plugins/modules/sap_task_list_execute.py\", line 344, in main\r\n  File \"/tmp/ansible_community.sap_libs.sap_task_list_execute_payload_a4ch2qt9/ansible_community.sap_libs.sap_task_list_execute_payload.zip/ansible_collections/community/sap_libs/plugins/modules/sap_task_list_execute.py\", line 334, in run_module\r\n  File \"/tmp/ansible_community.sap_libs.sap_task_list_execute_payload_a4ch2qt9/ansible_community.sap_libs.sap_task_list_execute_payload.zip/ansible_collections/community/sap_libs/plugins/modules/sap_task_list_execute.py\", line 223, in xml_to_dict\r\n  File \"/usr/local/lib/python3.9/site-packages/xmltodict.py\", line 378, in parse\r\n    parser.Parse(xml_input, True)\r\nxml.parsers.expat.ExpatError: no element found: line 1, column 0\r\n",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 1
}
rainerleber commented 11 months ago

could you share your ansible tasks ? or is it the same as above?

rainerleber commented 11 months ago

If yes the task parameters looks wrong and should look like this:

  - name: Pass in input parameters
    community.sap_libs.sap_task_list_execute:
      conn_username: "{{ sap_user }}"
      conn_password: "{{ sap_pwd }}"
      host: "{{ inventory_hostname }}"
      sysnr: "{{ instnum }}"
      client: "{{ client }}"
      task_to_execute: ZBC_SCALEUP_SERVER_CONFIG
      task_parameters :
          - { 'TASKNAME': 'CL_STCT_CREATE_LOGONGROUP','FIELDNAME': 'PLG_NAME','VALUE': '390' }
          - { 'TASKNAME': 'CL_STCT_CREATE_LOGONGROUP','FIELDNAME': 'PLG_TYPE','VALUE': 'S' }
      task_settings: batch
joanba68 commented 11 months ago

by now we are just running the task list by default, so without parameters, this is to get server included in PUBLIC and parallel_generators groups. Here the current task

- name: Run SAP task list
  hosts: sap
  become: true

  tasks:

  - name: Load SAP vars
    include_vars: vars/main.yml

# Run the complete task list for default values: PUBLIC and parallel_generators groups
  - name: Test task execution
    community.sap_libs.sap_task_list_execute:
      conn_username: "{{ sap_user }}"
      conn_password: "{{ sap_pwd }}"
      host: "{{ inventory_hostname }}"
      sysnr: "{{ instnum }}"
      client: "{{ client }}"
      task_to_execute: ZBC_SCALEUP_SERVER_CONFIG
      task_settings: batch
    environment:
      SAPNWRFC_HOME: "{{ nwrfcsdk_home }}"
      LD_LIBRARY_PATH: "{{ nwrfcsdk_home }}/lib"
rainerleber commented 11 months ago

Error says 'xml.parsers.expat.ExpatError: no element found: line 1, column 0'

So the logs for the session are empty.

session_log = call_rfc_method(conn, 'STC_TM_SESSION_GET_LOG',
                              {'I_SESSION_ID': session_init['E_SESSION_ID']})

Normally you should see in stc02 that the task was triggered.

Maybe it's a problem with the task or the login

joanba68 commented 11 months ago

I've finally successfully exectued two tasks. Error was due because SAP user had no authorization to display task lists. This is strange as SAP Security Audit was not showing errors, SU53 was also clean. So used ABAP debugger for remote RFC calls to see that check_authority_display was not passed:

FUNCTION STC_TM_SESSION_GET_LOG .
(...)

  TRY.
    CALL METHOD cl_stc_utilities=>check_authority_display( i_session_id = i_session_id ).
    CATCH cx_stc_authority INTO lx_auth.
      et_return[] = lx_auth->get_bapirettab( ).
      EXIT.    <---- leaving here
  ENDTRY.

I would like to have this kind of exception managed in ansible side, it will save a lot of time !!

So returning to code, these are the successful tasks:

- name: Run SAP task list
  hosts: sap
  become: true 

  tasks:

  - name: Load SAP vars
    include_vars: vars/main.yml

# Run the complete task list for default values: PUBLIC and parallel_generators groups    
  - name: Pass in input parameters
    community.sap_libs.sap_task_list_execute:
      conn_username: "{{ sap_user }}"
      conn_password: "{{ sap_pwd }}"
      host: "{{ inventory_hostname }}"
      sysnr: "{{ instnum }}"
      client: "{{ client }}"
      task_to_execute: ZBC_SCALEUP_SERVER_CONFIG
      task_settings: batch
    environment:
      SAPNWRFC_HOME: "{{ nwrfcsdk_home }}"
      LD_LIBRARY_PATH: "{{ nwrfcsdk_home }}/lib"

# Now, just one additional step with the required RFC group 390
  - name: Test task execution
    community.sap_libs.sap_task_list_execute:
      conn_username: "{{ sap_user }}"
      conn_password: "{{ sap_pwd }}"
      host: "{{ inventory_hostname }}"
      sysnr: "{{ instnum }}"
      client: "{{ client }}"
      task_to_execute: ZBC_SCALEUP_SERVER_CONFIG
      task_parameters :
          - { 'TASKNAME': 'CL_STCT_CREATE_LOGONGROUP','FIELDNAME': 'PLG_NAME','VALUE': '390' }
          - { 'TASKNAME': 'CL_STCT_CREATE_LOGONGROUP','FIELDNAME': 'PLG_TYPE','VALUE': 'S' }
      task_settings: batch
    environment:
      SAPNWRFC_HOME: "{{ nwrfcsdk_home }}"
      LD_LIBRARY_PATH: "{{ nwrfcsdk_home }}/lib"
sean-freeman commented 11 months ago

@joanba68 You stated "we are automating the bootstraping of an SAP application server with ansible and DevOps. We're able to create the server, install OS, install SAP application instance with SWPM, update profiles and restart it".

Would you and your team be interested in access to Beta code that already does this all of this for ECC+AnyDB, ECConHANA, S/4HANA, BW/4HANA ? We're actively looking for testers and it might reduce your effort/investment. If yes, drop me an email.

rainerleber commented 11 months ago

@joanba68 thank for the response and solution. It seams the issue is solved. Would you closed it ?

I will think about how to include a check for this case in the module. Maybe an additional documentation will help other users as well.

rainerleber commented 10 months ago

Solved