IBM Z and LinuxONE IBM Z

Expand all | Collapse all

zos_copy module encoding question

  • 1.  zos_copy module encoding question

    Posted Fri January 06, 2023 10:43 AM
    Edited by Oliver Stadler Fri January 06, 2023 10:46 AM
    Hi,

    I have another encoding related question. When I copy an ASCII file using the zos_copy module it works fine if I specify IBM-1047 both in the from and to argument. If I don't specify an encoding the file arrives corrupted. Specifying the encoding it no big deal but it's somewhat confusing that I have to specify IBM-1047 as "from" encoding when copying an ASCII file.

    This is the file I use as input
    (az1) [myuser@myhost ansible-zos]$ cat iefbr14.jcl
    //MYUSERA JOB (123),'LOCAL',CLASS=A,MSGCLASS=S,MSGLEVEL=(1,1),
    // NOTIFY=&SYSUID
    //*
    //STEP001 EXEC PGM=IEFBR14
    //SYSPRINT DD SYSOUT=*
    //SYSOUT DD SYSOUT=*
    //SYSDUMP DD SYSOUT=*
    //*

    The following playbook shows the behaviour.

    (az1) [myuser@myhost ansible-zos]$ cat zos_copy_example.yml
    ---
    - name: Working with datasets
      hosts: all
      gather_facts: False
      vars:
      - my_seq: MYUSER.TEST3.SEQ

      tasks:
      - name: Create {{ my_seq }}
        ibm.ibm_zos_core.zos_data_set:
          name: "{{ my_seq }}"
          type: seq
          record_format: VB
          record_length: 255

      - name: Copy JCL with encoding
        ibm.ibm_zos_core.zos_copy:
          src: iefbr14.jcl
          dest: "{{ my_seq }}"
          backup: False
          force: True
        encoding:
          to: IBM-1047
          from: IBM-1047

      - name: Submit the job
        ibm.ibm_zos_core.zos_job_submit:
          location: DATA_SET
          src: "{{ my_seq }}"

      - name: Copy JCL without encoding
        ibm.ibm_zos_core.zos_copy:
          src: iefbr14.jcl
          dest: "{{ my_seq }}"
          backup: False
          force: True

      - name: Submit the job
        ibm.ibm_zos_core.zos_job_submit:
          location: DATA_SET
          src: "{{ my_seq }}"
    ...

    When I run it I get the following result.

    (az1) [myuser@myhost ansible-zos]$ ansible-playbook -i inventory -l mysys zos_copy_example.yml
    [DEPRECATION WARNING]: Ansible will require Python 3.8 or newer on the controller starting with Ansible 2.12. Current version: 3.6.8 (default, Aug 13 2020, 07:46:32) [GCC 4.8.5 20150623 (Red Hat
    4.8.5-39)]. This feature will be removed from ansible-core in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.

    PLAY [Working with datasets] ************************************************************************************************************************************************************************

    TASK [Create MYUSER.TEST3.SEQ] *********************************************************************************************************************************************************************
    [WARNING]: Platform os/390 on host mysys is using the discovered Python interpreter at /usr/lpp/python/bin/python3.9, but future installation of another Python interpreter could change
    the meaning of that path. See https://docs.ansible.com/ansible-core/2.11/reference_appendices/interpreter_discovery.html for more information.
    ok: [mysys]

    TASK [Copy JCL with encoding] ***********************************************************************************************************************************************************************
    changed: [mysys]

    TASK [Submit the job] *******************************************************************************************************************************************************************************
    changed: [mysys]

    TASK [Copy JCL without encoding] ********************************************************************************************************************************************************************
    changed: [mysys]

    TASK [Submit the job] *******************************************************************************************************************************************************************************
    fatal: [mysys]: FAILED! => {"changed": false, "msg": "SubmitJCLError('Submit job failed: Stderr :FSUMB408 submit: data set MYUSER.TEST3.SEQ Not accepted by JES.\\n')"}

    PLAY RECAP ******************************************************************************************************************************************************************************************
    mysys: ok=4 changed=3 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0

    ------------------------------
    Oliver Stadler
    ------------------------------


  • 2.  RE: zos_copy module encoding question

    Posted Mon January 09, 2023 03:37 AM
    Hi Oliver,
    Could it be that the dataset already exists from your first test?
    Try to delete it first with DISP=(MOD,DELETE) although I don't know this works through the ansible modules....

    Kind regards,
    Wendy Draaisma

    ------------------------------
    Wendy Draaisma
    ------------------------------



  • 3.  RE: zos_copy module encoding question

    Posted Tue January 10, 2023 03:20 AM
    Hi Wendy,

    I also tried with deleting the dataset but it didn't make a difference.

    Kind regards,
    Oliver

    ------------------------------
    Oliver Stadler
    ------------------------------



  • 4.  RE: zos_copy module encoding question

    Posted Tue January 10, 2023 11:15 AM
    If the encoding is set to the same value for 'from:' and 'to:' then I would expect no translation to occur.
    If no encoding is provided there would be a default that does not match the From value and it would corrupt the file.
    If you set the 'is_binary:  True' option it will perform no translation of the text data.  Your source and destination file will be the same.

    ------------------------------
    Christopher Hanks
    Jacksonville FL
    ------------------------------



  • 5.  RE: zos_copy module encoding question

    Posted Mon January 30, 2023 09:22 AM

    Hello Oliver,
    Looking at this snippet and from what you have shared in that you have from:to set to IBM-1047

      - name: Copy JCL without encoding
        ibm.ibm_zos_core.zos_copy:
          src: iefbr14.jcl
          dest: "{{ my_seq }}"
          backup: False
          force: True

    It seems that the JCL source `iefbr14.jcl` on the controller (eg your laptop) is encoded in EBCDIC (IBM-1047) so when you don't specify an encoding what the `zos_copy` module does is take the `locale`of the controller which in most cases is either `UTF8` or `ISO8859-1` and uses that as the `from` and when the module runs on the managed node (z/OS) it takes the `locale` there and sets it as the `to` which in most cases is `IBM-1047`.

    Why `iefbr14.jcl` ends up unreadable is because the module has used incorrect inputs/oputput (from/to) for its encoding when you don't specify. We rely on these user inputs because its very difficult to detect and correctly asses a files encoding reading a files Byte Order Mark (BOM) and has a high probability of inaccuracy in doing so.

    In your case you have a few options, if the file is already in the desired encoding on your controller eg IBM-1047, you can continue to set the FROM an TO encoding options as IBM-1047 for both so that the  module does not perform any encoding conversion or you can instruct the module the file is binary and should prevent any conversion but I don't recommend you use the binary trick. Your best option is to have the file on the controller in the controllers encoding or continue to do what you are doing.

    In this article under section "Plugins and modules" I cover the locale and architecture a bit if you are interested.
    We try to monitor all sources and this one was overlooked, feel free to also use our repositories discussions if you are permitted to access it.



    ------------------------------
    DEMETRIOS DIMATOS
    IBM zOS Ansible Core Senior Technical Lead
    IBM zOS Ansible Core Senior Technical Lead
    San Jose CA
    ------------------------------



  • 6.  RE: zos_copy module encoding question

    Posted Wed February 01, 2023 11:37 AM
    Hi Demetrios,

    Thanks a lot for the feedback. I actually wanted to place the question directly in the Github discussion forum but unfortunately we are not allowed to due to company policy.

    I checked the iefbr14.cjl source file on the controller and it is definitely not  EBCDIC (IBM-1047). 

    $ file iefbr14.jcl
    iefbr14.jcl: ASCII text

    I also doublechecked the actual hex codes of some of the characters via the od command and they are in fact ASCII encoded.

    When I look at the payload file which is copied during the execution of the task into /tmp (e.g. /tmp/ansible-zos-copy-payload-D230201-T155244) that looks fine (using -vvv to see the verbose output) . The file is not tagged and if I do a cat on it the file content is displayed correctly. So it looks like it gets converted later on. 

    I wonder if we have something configured differently on Unix System Services side on our end that might cause this.

    Kind regards,
    Oliver



    ------------------------------
    Oliver Stadler
    ------------------------------



  • 7.  RE: zos_copy module encoding question

    Posted Mon February 06, 2023 02:15 AM
    Hi Oliver,  I figured that was going to be the case with GitHub, your not the only client who has that policy, if you have Ansible Automation Hub entitlement you could go through L2, otherwise I don't mind working here.  For some reason I don't get notifications for this thread so I have to come back and review if there are updates.

    Anyhow, thank you for the diagnosis, I guess I assumed too much without a log, there are a couple of things I can think of that might cause this but without the output from
    ANSIBLE_DEBUG=1 ansible-playbook -i inventory your-playbook.yml -vvvv​

    I have seen this happen when the controller can't find the action plugin (zos_copy has both , action and modules - see my blog for more on this), and I can usually tell from the log when I see a None/Null passed in as the controllers locale.  You can trouble shoot this by adding the path in your `ansible.cfg` , the entry would look similar to this:

    [defaults]
    action_plugins=/Users/ddimatos/.ansible/collections/ansible_collections/ibm/ibm_zos_core/plugins/action

    The other time, but its slight a different error (we are working on this) is with IBM Enterprise Python 3.10 or later but you are using 3.9 according to what Ansible discovered. You might try to not rely on that discovery and tell Ansible what python to use with property `ansible_python_interpreter`, as I can't tell without a log if it really did use 3.9, you can do that from your inventory with an entry that looks like:

    zsystem:
      hosts:
        zvm:
          ansible_host: <some host>
          ansible_user: <some user>
          ansible_python_interpreter: /python2/usr/lpp/IBM/cyp/v3r9/pyz/bin/python3.9


    ------------------------------
    Demetri Dimatos
    IBM zOS Ansible Core Senior Technical Lead
    IBM
    San Jose CA
    ------------------------------



  • 8.  RE: zos_copy module encoding question

    Posted Mon February 06, 2023 12:29 PM
      |   view attached
    Hi Demetri,

    I added the action_plugins path but it didn't make a difference.

    Python version on the target server is 3.9. 

    /usr/lpp/python/bin/python --version
    Python 3.9.14

    The config I used was as follows:

    [tmyuser@controller ansible-zos]$ ansible-config dump --only-changed
    ANSIBLE_PIPELINING(/home/tmyuser/ansible-zos/ansible.cfg) = True
    COLLECTIONS_PATHS(/home/tmyuser/ansible-zos/ansible.cfg) = [u'/home/tmyuser/colltest', u'/usr/share/ansible/collections', u'/home/tmyuser/.ansible/collections', u'/usr/share/ansible/collections', u'/home/tmyuser/ansible_collections']
    DEFAULT_ACTION_PLUGIN_PATH(/home/tmyuser/ansible-zos/ansible.cfg) = [u'/home/tmyuser/colltest/ansible_collections/ibm/ibm_zos_core/plugins/action/~/.ansible/plugins/action', u'/usr/share/ansible/plugins/action']

    I also ran the playbook with the debugging enabled and verbose. Output is attached in playbook_output_clean.txt.

    Kind regards,
    Oliver

    ------------------------------
    Oliver Stadler
    ------------------------------

    Attachment(s)

    txt
    playbook_output_clean.txt   93 KB 1 version


  • 9.  RE: zos_copy module encoding question

    Posted Mon February 06, 2023 12:32 PM
    And I just realized that I spelt your first name wrongly in my previous posts. Sorry for that but I got that now :-)

    ------------------------------
    Oliver Stadler
    ------------------------------



  • 10.  RE: zos_copy module encoding question

    Posted Mon February 06, 2023 05:44 PM

    Hello Oliver, actually you had my name correct, full pronunciation is `Demetrios`, I updated it to the shortened `Demetri` the other day, no problems here on my end how you refer to me :) .

    I did a quick pass and noticed something, it appears the code is either detecting IBM-037 or your setting it to IBM-037 (but I think you are setting it to IBM-1047) , i have to look a the code to follow the path and where the swap is happening.
    - Which version of the IBM z/OS core collection are you using, eg

    cat /home/tmyuser/colltest/ansible_collections/ibm/ibm_zos_core/MANIFEST.json | grep version


    - What does USS command on the managed node (one you are connecting to) yield: `locale -c charmap`, eg I get:

    # locale -c charmap
    IBM-1047

    The log snippet that has me questioning the code is:

    {"changed": true, "src": "iefbr14.jcl", "dest": "Tmyuser.TEST4.SEQ", "ds_type": "PS", "dest_exists": true, "backup_name": null, "invocation": {"module_args": {"is_pds": false, "src_member": false, "size": 194, "local_charset": "UTF-8", "dest": "Tmyuser.TEST4.SEQ", "is_src_dir": false, "is_uss": false, "temp_path": "/tmp/ansible-zos-copy-payload-D230206-T181246", "src": "iefbr14.jcl", "copy_member": false, "is_mvs_dest": true, "is_binary": false, "backup": false, "local_follow": true, "remote_src": false, "ignore_sftp_stderr": false, "validate": false, "force": false, "follow": false, "unsafe_writes": false, "encoding": {"from": "UTF-8", "to": "IBM-037"}, "content": null, "backup_name": null, "sftp_port": null, "volume": null, "dest_data_set": null, "mode": null, "owner": null, "group": null, "seuser": null, "serole": null, "selevel": null, "setype": null, "attributes": null, "regexp": null, "delimiter": null, "directory_mode": null, "from_encoding": "UTF-8", "to_encoding": "IBM-1047"}}}


    The last thing that caught my eye which ill need some time to review is the plugin search path differs from your install path but it appears Ansible figured it out but still I want to look into, your install path is /home/tmyuser/.ansible/collections, Ansible searched paths `/usr/share/ansible/plugins/action:/usr/lib/python2.7/site-packages/ansible/plugins/action` and found the zos_copy action plugin, so I am not sure if the locale confusion has anything to do with this yet.

    Loading ActionModule 'ansible_collections.ibm.ibm_zos_core.plugins.action.zos_copy' from /home/tmyuser/colltest/ansible_collections/ibm/ibm_zos_core/plugins/action/zos_copy.py (searched paths: /usr/share/ansible/plugins/action:/usr/lib/python2.7/site-packages/ansible/plugins/action) (found_in_cache=False, class_only=True)



    ------------------------------
    Demetri Dimatos
    IBM zOS Ansible Core Senior Technical Lead
    IBM
    San Jose CA
    ------------------------------



  • 11.  RE: zos_copy module encoding question

    Posted Tue February 07, 2023 04:00 AM
    Edited by Oliver Stadler Mon February 13, 2023 03:13 AM
      |   view attached

    Hi Demetri,

    zos collection version is 1.4

    [tmyuser@mycontroller ansible-zos]$ cat /home/tmyuser/colltest/ansible_collections/ibm/ibm_zos_core/MANIFEST.json | grep version
    "version": "1.4.0",

    Locale on USS side is IBM-1047

    [tmyuser@mycontroller ansible-zos]$ ansible -i inventory myplex1 -m command -a 'locale -c charmap'
    [WARNING]: Platform os/390 on host mysys1.com is using the discovered Python interpreter at /usr/lpp/python/bin/python, but future installation of another Python interpreter could change this. See
    https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
    mysys1.com | CHANGED | rc=0 >>
    IBM-1047

    I noticed that there was actually a typo in the plugin path. I cleaned that up. Config looks like this now:

    [myuser@mycontroller ansible-zos]$ ansible-config dump --only-changed
    ANSIBLE_PIPELINING(/home/myuser/ansible-zos/ansible.cfg) = True
    COLLECTIONS_PATHS(/home/myuser/ansible-zos/ansible.cfg) = [u'/home/myuser/colltest', u'/usr/share/ansible/collections']
    DEFAULT_ACTION_PLUGIN_PATH(/home/myuser/ansible-zos/ansible.cfg) = [u'/home/myuser/colltest/ansible_collections/ibm/ibm_zos_core/plugins/action', u'/usr/share/ansible/plugins/action']

    I also rerun the playbook with this config and attached the output (playbook_output3.txt)

    It looks like the actual conversion which is done is from ASCII to IBM-1047.

    The target dataset in hex looks like this:

    Command ===> Scroll ===> CSR
    ********************************* Top of Data **********************************


    ------------------------------------------------------------------------------
    aa..@@..M.k}.Á.kÓb.k........~M.k.aa@@@@@@@......aa\.aa.....@...............aa...
    88337732D39D3639E83933333333AD39388777777733333388E38833333733333333333333388333
    11FFCCF04F20F5F2E2F2FFFFFFFF14F2D11CCCCCCCFFFFFD110D11FFFFFCFFFFFFFFFFFFFFD11FFF
    ------------------------------------------------------------------------------
    ******************************** Bottom of Data ********************************

    That corresponds to the output I get when I run an iconv on the file being copied.
    Tmyuser@mysys:/home/tmyuser ==> iconv -f UTF-8 -t IBM-1047 iefbr14.jcl | od -x
    0000000000 8181 3F3F 7C7C 3F20 D43F 92D0 3F65 3F92
    0000000020 EE82 3F92 3F3F 3F3F 3F3F 3F3F A1D4 3F92
    0000000040 3D81 817C 7C7C 7C7C 7C7C 3F3F 3F3F 3F3D
    0000000060 8181 E03D 8181 3F3F 3F3F 3F7C 3F3F 3F3F
    0000000100 3F3F 3F3F 3F3F 3F3F 3F3F 3D81 813F 3F3F
    0000000120 7C3F 7C3F 3F3F 3D81 813F 3F3F 7C7C 3F7C
    0000000140 3F3F 3F3D 8181 E03D
    0000000150



    ------------------------------
    Oliver Stadler
    ------------------------------

    Attachment(s)

    txt
    playbook_output3.txt   93 KB 1 version


  • 12.  RE: zos_copy module encoding question

    Posted Tue February 07, 2023 04:47 PM
    Edited by Demetri Dimatos Wed February 08, 2023 12:17 AM

    Hello Oliver, it looks like things are good with regard to the plugin path and discovery from what I can see in your log. I found in our code where we are setting a `IBM-037`, I think it was an oversight given the slight variation in vars were `DEFAULT_EBCDIC_USS_CHARSET` vs `DEFAULT_EBCDIC_MVS_CHARSET`. 

    I can't tell from your last message if its working for you now because it seems like you are sharing the expected HEX and the actual HEX which are the same and thus you are good now.

    If you this is working for you then I will put the investigation of our use of `DEFAULT_EBCDIC_USS_CHARSET` in the backlog.



    ------------------------------
    Demetri Dimatos
    IBM zOS Ansible Core Senior Technical Lead
    IBM
    San Jose CA
    ------------------------------



  • 13.  RE: zos_copy module encoding question

    Posted Wed February 08, 2023 02:00 AM
    Edited by Oliver Stadler Tue March 14, 2023 10:46 AM

    Hi Demetri,

    No it's not yet working. Below end to end what I see happening.

    On the controller the original file looks ASCII like this (just looking at the first line to limit the output)

    $ head -1 iefbr14.jcl
    //MYUSER JOB (123),'LOCAL',CLASS=A,MSGCLASS=S,MSGLEVEL=(1,1),

    First two characters are the forward slashes ASCII encoded as hex 2f 2f 
    $ head -1 iefbr14.jcl | od -x
    0000000 2f2f 5435 3037 3632 3241 2020 4a4f 4220
    0000020 2831 3233 292c 274c 4f43 414c 272c 434c
    0000040 4153 533d 412c 4d53 4743 4c41 5353 3d53
    0000060 2c4d 5347 4c45 5645 4c3d 2831 2c31 292c
    0000100 0a00

    When I look at the payload file that Ansible creates when doing the copy to the USS system the files is converted to EBCDIC. First two characters are now hex 61 61 which corresponds to the forward slashes in EBCDIC.

    head -1 /tmp/ansible-zos-copy-payload-D230208-T073216 | od -x
    0000000000 6161 E3F5 F0F7 F6F2 F2C1 4040 D1D6 C240
    0000000020 4DF1 F2F3 5D6B 7DD3 D6C3 C1D3 7D6B C3D3
    0000000040 C1E2 E27E C16B D4E2 C7C3 D3C1 E2E2 7EE2
    0000000060 6BD4 E2C7 D3C5 E5C5 D37E 4DF1 6BF1 5D6B
    0000000100 1500
    0000000101
    0000101

    However in the target data set the arriving content looks like this. The first two characters are encoded as hex 81.

    ********************************* Top of Data **********************************

    -----------------------------------------------------------------------------
    aa..@@..M.k}.Á.kÓb.k........~M.k.aa@@@@@@@......aa\.aa.....@...............aa...
    88337732D39D3639E83933333333AD39388777777733333388E38833333733333333333333388333
    11FFCCF04F20F5F2E2F2FFFFFFFF14F2D11CCCCCCCFFFFFD110D11FFFFFCFFFFFFFFFFFFFFD11FFF
    ------------------------------------------------------------------------------
    ******************************** Bottom of Data ********************************

    Which is what I get if I convert the already EBCDIC content as UTF-8 to IBM-1047.

    head -1 /tmp/ansible-zos-copy-payload-D230208-T073216 | iconv -f UTF-8 -t IBM-1047 | od -x
    0000000000 8181 3F3F 7C7C 3F20 D43F 92D0 3F65 3F92
    0000000020 EE82 3F92 3F3F 3F3F 3F3F 3F3F A1D4 3F92
    0000000040 3D00
    0000000041


    Kind regards,
    Oliver

    ------------------------------
    Oliver Stadler
    ------------------------------



  • 14.  RE: zos_copy module encoding question

    Posted Fri February 10, 2023 10:42 PM

    Hi Oliver, 

    I must have not understood 2 messages back, thank you for clarifying. I will try to reproduce this, this is the only way for me to track where the inconsistency is happening, thank you for clearly explaning this helps me quiet a bit. I will get back to you shortly. 



    ------------------------------
    Demetri Dimatos
    IBM zOS Ansible Core Senior Technical Lead
    IBM
    San Jose CA
    ------------------------------



  • 15.  RE: zos_copy module encoding question

    Posted Sat February 11, 2023 12:59 AM
    Edited by Demetri Dimatos Sat February 11, 2023 01:16 AM

    Hello Oliver,

    Here is what I have so far:

    1. Created file ascii.txt with this content:
      1. //T507622A JOB (123),'LOCAL',CLASS=A,MSGCLASS=S,MSGLEVEL=(1,1),(ansible-doc
      2. With hex values:
        1. 0000000 2f2f 5435 3037 3632 3241 204a 4f42 2028  //T507622A JOB (
          0000010 3132 3329 2c27 4c4f 4341 4c27 2c43 4c41  123),'LOCAL',CLA
          0000020 5353 3d41 2c4d 5347 434c 4153 533d 532c  SS=A,MSGCLASS=S,
          0000030 4d53 474c 4556 454c 3d28 312c 3129 2c0a  MSGLEVEL=(1,1),.

    2. With playbook:
      1. ---
        - hosts: zvm
          gather_facts: false
          vars:
            - SEQ: "ANSIBLE.CONTENT.SEQ"
          environment: "{{ environment_vars }}"
          collections:
            - ibm.ibm_zos_core
        
          tasks:
            - name: Create/replace the PDS
              zos_data_set:
                name: "{{ SEQ }}"
                type: seq
                space_primary: 5
                space_type: M
                record_format: fb
                record_length: 80
                block_size: 3120
                replace: true
              register: result
        
            - name: Copy local file to PDS
              zos_copy:
                src: "{{playbook_dir}}/files/ascii.txt"
                dest: "{{ SEQ }}"
                remote_src: false
                encoding:
                   from: ISO8859-1
                   to: IBM-1047
              register: result
        
            - name: Result of copying local directory
              debug:
                msg: "{{ result }}"
    3. And on z/OS when I look at the sequential data set content in Hex I have:
      1. //T507622A JOB (123),'LOCAL',CLASS=A,MSGCLASS=S,MSGLEVEL=(1,1),                 
        66EFFFFFFC4DDC44FFF567DDCCD76CDCEE7C6DECCDCEE7E6DECDCECD74F6F5644444444444444444
        113507622101620D123DBD36313DB33122E1B42733122E2B42735553ED1B1DB00000000000000000


    Looking at the last bullet (3) hex content and picking random characters they correspond to code page IBM-1047:

    • / is HEX 61
    • L is HEX D3
    • ( is HEX 4D

    What I did notice in your ASCII content (assuming ISO-8859-1) , partway through some of the characters don't seem to correspond to ISO-8859-1. Lets review this portion  //T507622A JOB (.

    Text:        //T507622A JOB (

    Mine:      2f2f 5435 3037 3632 3241 204a 4f42 2028

    Yours:    2f2f 5435 3037 3632 3241 2020 4a4f 4220

    HEX values begin to not align , my:

    • 4a vs 20
    • 4f vs 4a
    • 42 vs 4f

    It appears we don't have the same data to work with. Could you send me your ASCII content, feel free to email me or attach it here but  I wonder if that is the source of the issue where the conversion goes wrong because source may not be consistent with ISO-8859-1.



    ------------------------------
    Demetri Dimatos
    IBM zOS Ansible Core Senior Technical Lead
    IBM
    San Jose CA
    ------------------------------



  • 16.  RE: zos_copy module encoding question

    Posted Sat February 11, 2023 01:21 AM

    Hi Oliver,

    I also created a UTF-8 version of the same ISO-8859-1 content and for me they match.


    UTF-8 Hex: 2f2f 5435 3037 3632 3241 204a 4f42 2028  for //T507622A JOB (

    $ file -I utf-8.txt
    utf-8.txt: text/plain; charset=utf-8
    $ file -I ascii.txt
    ascii.txt: text/plain; charset=us-ascii


    ------------------------------
    Demetri Dimatos
    IBM zOS Ansible Core Senior Technical Lead
    IBM
    San Jose CA
    ------------------------------



  • 17.  RE: zos_copy module encoding question

    Posted Tue February 14, 2023 02:57 PM

    Hi Demetri,

    You are right the hex codes differ somewhat because in one case there were two blanks after the jobname and in other case not.

    Therefore I reproduced the problem using an input file that matches exactly with yours (same hex codes). It looks like this:

    $ od -x files/ascii.txt
    0000000 2f2f 5435 3037 3632 3241 204a 4f42 2028
    0000020 3132 3329 2c27 4c4f 4341 4c27 2c43 4c41
    0000040 5353 3d41 2c4d 5347 434c 4153 533d 532c
    0000060 4d53 474c 4556 454c 3d28 312c 3129 2c0a
    0000100

    It is identified as us-ascii:

    $ file -i files/ascii.txt
    files/ascii.txt: text/plain; charset=us-ascii

    Then I took your playbook and executed it. I just commented the line "environment: "{{ environment_vars }}" because it caused an "undefined variable" error.

    Result of playbook:

    TASK [Result of copying local directory] ******************************************************************
    ok: [mysys] => {
        "msg": {
            "changed": true,
            "dest": "MYUSER.CONTENT.SEQ",
            "failed": false,
            "is_binary": false,
            "src": "/home/myuser/ansible-zos/files/ascii.txt"
        }
    }

    PLAY RECAP ************************************************************************************************
    mysys               : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0


    The content of the dataset looks like this:
    ********************************* Top of Data **********************************


     ------------------------------------------------------------------------------
    aaãõð÷öòòÁ@ÑÖÂ@Mñòó¨k}ÓÖÃÁÓ}kÃÓÁââ~ÁkÔâÇÃÓÁââ~âkÔâÇÓÅåÅÓ~Mñkñ¨k.
    884C8ECCC676E67D4CCB9DEE66ED96E644A69E466E644A49E46E646EAD494B934444444444444444
    116FC1CDD5C9C2C49DEB20EC65E026E522152B286E522122B28E777E14929B2D0000000000000000
     ------------------------------------------------------------------------------
    ******************************** Bottom of Data ********************************

    Kind regards,

    Oliver



    ------------------------------
    Oliver Stadler
    ------------------------------



  • 18.  RE: zos_copy module encoding question

    Posted Fri February 24, 2023 04:57 PM
    Edited by Demetri Dimatos Fri February 24, 2023 05:08 PM

    Hello Oliver, 
    I am able to look at this now.

    Its been a few days so I may want to run this again but before I do, you said something that made me go back and look at the log you shared (thread says 17 days ago is the date of when the log was shared) and in the log I could not see any environment variables, usually its the first thing I notice but think by the time I got a log I was fixated on the HEX :).

    What you said that made me realize I never evaulated your envirment variables was:
    "I just commented the line "environment: "{{ environment_vars }}" because it caused an "undefined variable"

    This is important to note, Ansible does not use any `.profiles` located on the target (z/OS) , it either starts a TTY or pipes directly to PYTHON STDIN and in either case it relies on in our z/OS case, these environment variables. There are many ways to get them read by Ansible, some folks put them in their playbook, I prefer a more structured enterprise approach which I have written many such samples where each project has the same hierarchy.  I know you can not access Git but maybe from a personal device you could have a look at these links else I will have to find another way to help you as the Ansible docs are not written with z/OS in mind.

    Here is what my underlying connection to z/OS looks like (i removed sensitive info with Sanitized information):

    <Sanitized information> SSH: EXEC ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="omvsadm"' -o ConnectTimeout=10 -o 'ControlPath="/Users/ddimatos/.ansible/cp/3311113a13"' ec33017a.vmec.svl.ibm.com '/bin/sh -c '"'"'_BPXK_AUTOCVT=ON ZOAU_HOME=/zoau/v1.2.2 JAVA_HOME=/usr/lpp/java/J8.0 PYTHONPATH=/zoau/v1.2.2/lib LIBPATH=/zoau/v1.2.2/lib:/python2/usr/lpp/IBM/cyp/v3r9/pyz//lib:/lib:/usr/lib:. PATH=/zoau/v1.2.2/bin:/python2/usr/lpp/IBM/cyp/v3r9/pyz//bin:/bin:/var/bin:/usr/lpp/java/J8.0/bin _CEE_RUNOPTS='"'"'"'"'"'"'"'"'FILETAG(AUTOCVT,AUTOTAG) POSIX(ON)'"'"'"'"'"'"'"'"' _TAG_REDIR_ERR=txt _TAG_REDIR_IN=txt _TAG_REDIR_OUT=txt LANG=C /python2/usr/lpp/IBM/cyp/v3r9/pyz/bin/python3.9 && sleep 0'"'"''
    


    Here is what yours looks like (I pulled it out of the log)

    <mysys1.com> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/home/tmyuser/.ansible/cp/e40d621706 mysys1.com '/bin/sh -c '"'"'/usr/lpp/python/bin/python && sleep 0'"'"''


    When you look at the above SSH connections you will see what you are missing these environment variables over the connection:

    PYZ: "path_to_python_installation_on_zos_target"
    ZOAU: "path_to_zoau_installation_on_zos_target"
    
    environment_vars:
      _BPXK_AUTOCVT: "ON"
      ZOAU_HOME: "{{ ZOAU }}"
      PYTHONPATH: "{{ ZOAU }}/lib"
      LIBPATH: "{{ ZOAU }}/lib:{{ PYZ }}/lib:/lib:/usr/lib:."
      PATH: "{{ ZOAU }}/bin:{{ PYZ }}/bin:/bin:/var/bin:/usr/sbin"
      _CEE_RUNOPTS: "FILETAG(AUTOCVT,AUTOTAG) POSIX(ON)"
      _TAG_REDIR_ERR: "txt"
      _TAG_REDIR_IN: "txt"
      _TAG_REDIR_OUT: "txt"
      LANG: "C"


    If you can not get to any GitHub links then you could do this; add this to the top of your playbook and correctly configure the variables that will achieve what I have shared with regard to group_vars and host_vars in the included links:

    Start playbook with:

    ---
    - hosts: zvm
      collections:
        - ibm.ibm_zos_core
      gather_facts: no
      vars:
        ZOAU: "path/to/your/ZOAU/home"
        PYZ: "/path/to/python/home/up/to/pyz"
    
      environment:
        _BPXK_AUTOCVT: "ON"
        ZOAU_HOME: "{{ ZOAU }}"
        PYTHONPATH: "{{ ZOAU }}/lib"
        LIBPATH: "{{ ZOAU }}/lib:{{ PYZ }}/lib:/lib:/usr/lib:."
        PATH: "{{ ZOAU }}/bin:{{ PYZ }}/bin:/bin:/var/bin"
        _CEE_RUNOPTS: "FILETAG(AUTOCVT,AUTOTAG) POSIX(ON)"
        _TAG_REDIR_ERR: "txt"
        _TAG_REDIR_IN: "txt"
        _TAG_REDIR_OUT: "txt"
        LANG: "C"
    
      tasks:
        - name: Test copy.
          zos_copy:
            src: your_source
            dest: your_dest
            ...........
            ...................


    In the above snippet all you need to configure is the two vars:
        ZOAU: "path/to/your/ZOAU/home"
        PYZ: "/path/to/python/home/up/to/pyz"

    I look forward to a successful execution of zos_copy :) 



    ------------------------------
    Demetri Dimatos
    IBM zOS Ansible Core Senior Technical Lead
    IBM
    San Jose CA
    ------------------------------



  • 19.  RE: zos_copy module encoding question

    Posted Tue March 07, 2023 11:48 AM
      |   view attached

    Hello Demetri,

    Thanks a lot for the feedback. Took me some time to test again because I was on vacation.

    I added the variables and reran the playbook. Unfortunately the file content is still not arriving correctly on the zOS side.

    The variables are there when Ansible execute the SSH commands. Here an example:

    <mysys1.example.net> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/home/myuser/.ansible/cp/e40d621706 mysys1.example.net '/bin/sh -c '"'"'_BPXK_AUTOCVT=ON LANG=C _TAG_REDIR_IN=txt ZOAU_HOME=/usr/lpp/zoau PYTHONPATH=/usr/lpp/zoau/lib LIBPATH=/usr/lpp/zoau/lib:/usr/lpp/python/lib:/lib:/usr/lib:. _CEE_RUNOPTS='"'"'"'"'"'"'"'"'FILETAG(AUTOCVT,AUTOTAG) POSIX(ON)'"'"'"'"'"'"'"'"' PATH=/usr/lpp/zoau/bin:/usr/lpp/python/bin:/bin:/var/bin _TAG_REDIR_OUT=txt _TAG_REDIR_ERR=txt /usr/lpp/python/bin/python && sleep 0'"'"''

    I also attached the full debug output to the post.

    Kind regards,

    Oliver



    ------------------------------
    Oliver Stadler
    ------------------------------

    Attachment(s)

    txt
    run_with_vars_clean.txt   9 KB 1 version


  • 20.  RE: zos_copy module encoding question

    Posted Sun March 12, 2023 03:56 AM

    Hello Oliver,

    Thank you for the log, it appears that your environment variables are correct pointing back to the module.

    I did notice in the log that the modules thinks the controller (where ansible is running- likely your laptop) is UTF-8, out of curiosity could you run on the controller the command `locale -c charmap`?

    The second thing I noticed, in our code is that we take a slight different approach for Sequential data sets which I am not sure why we do, I will need more time with the code to understand that but had hoped you could try this same exercise with a PDS/E instead of Sequential data set to see if you have better results. 

    Thank you. 



    ------------------------------
    Demetri Dimatos
    IBM zOS Ansible Core Senior Technical Lead
    IBM
    San Jose CA
    ------------------------------



  • 21.  RE: zos_copy module encoding question

    Posted Tue March 14, 2023 10:29 AM

    Hello Demetri,

    The locale commands show the following output:

    $ locale -c charmap
    LC_CTYPE
    UTF-8

    I tried running the playbook using a PDSE as target. But unfortunately it didn't make a difference.

    Kind regards,
    Oliver



    ------------------------------
    Oliver Stadler
    ------------------------------



  • 22.  RE: zos_copy module encoding question

    Posted Tue March 14, 2023 05:26 PM

    Hi Oliver, 

    I realize this is taking a bit to resolve, we are still here and trying  :).

     I will need to dig deeper into the code and from what I have seen thus far the only thing that concerned me was that the code appeared to be using CP 1037 when a sequential data set was involved and I can only understand that when I trace the code but you ruled that out by trying a PDSE.

    One other thing is your controller (laptop) the locale is reported as being UTF-8 and not ISO8859-1 (I do realize there is an overlap in the first 256 code points for UTF8) and yet I don't know how `iconv` handles this so maybe its worth identifying the source as UTF-8 (I don't think we tried this).

    For example:

        - name: Copy local file to PDS
          zos_copy:
            src: "{{playbook_dir}}/files/ascii.txt"
            dest: "{{ SEQ }}"
            remote_src: false
            encoding:
               from: UTF-8
               to: IBM-1047
          register: result


    ------------------------------
    Demetri Dimatos
    IBM zOS Ansible Core Senior Technical Lead
    IBM
    San Jose CA
    ------------------------------



  • 23.  RE: zos_copy module encoding question

    Posted Wed March 15, 2023 08:20 AM

    Hi Demetri,

    No problem if this takes a while. Your efforts are highly appreciated.

    I did try changing to ISO8859-1 on the controller using the commands below. However it did not make a difference.

    $ export LANG=en_US
    $ locale -c charmap
    LC_CTYPE
    ISO-8859-1

    I also tried running the playbook from a different controller. Normally I use a RHEL 7.9 running in System Z LPAR. I also tried from a RHEL 7.9 running on a x86 box. On both running Ansible 2.9.27. 

    Kind regards,
    Oliver



    ------------------------------
    Oliver Stadler
    ------------------------------



  • 24.  RE: zos_copy module encoding question

    Posted Sat April 01, 2023 01:17 AM

    Hi Oliver, 
    I am still here :) , just been inundated with projects. Anyhow, if locale -c charmap resulted in UTF-8, have you tried to change your playbook to use the UTF-8 for the from encoding? I scrolled back and did not see that we tried that:

        - name: Copy local file to PDS
          zos_copy:
            src: "{{playbook_dir}}/files/ascii.txt"
            dest: "{{ SEQ }}"
            remote_src: false
            encoding:
               from: UTF-8
               to: IBM-1047
          register: result

    What I saw in the log was the from encoding was ISO8859-1 yet your controller appears to be UTF-8, so i wonder if the files are actually UTF-8.

    You could also try creating a new file on the controller to ensure its UTF-8.

    Logs:

    "module_args": {
                "dest": "myuser.CONTENT.SEQ", 
                "encoding": {
                    "from": "ISO8859-1", 
                    "to": "IBM-1047"
                }, 
                "remote_src": false, 
                "src": "/home/myuser/ansible-zos/files/ascii.txt"
            }


    ------------------------------
    Demetri Dimatos
    IBM zOS Ansible Core Senior Technical Lead
    IBM
    San Jose CA
    ------------------------------



  • 25.  RE: zos_copy module encoding question

    Posted Fri June 02, 2023 12:19 PM

    Hi Demetri,

    I finally tested again today with the zos_core collection 1.5.0.

    $ grep version  /home/myuser/.ansible/collections/ansible_collections/ibm/ibm_zos_core/MANIFEST.json
      "version": "1.5.0",

    We also upgraded to Python 3.11.2 on the target node (including PTF UI91094).

    So I tested with using UTF-8 as "from encoding" but it didn't solve the problem. However it does have an impact on the encoding because when I look at the hex codes they are different from when I use ISO8859-1 as in the past.

    This is the source file:

    $ head -1 files/ascii.txt  | od -x
    0000000 2f2f 5435 3037 3632 3241 204a 4f42 2028
    0000020 3132 3329 2c27 4c4f 4341 4c27 2c43 4c41
    0000040 5353 3d41 2c4d 5347 434c 4153 533d 532c
    0000060 4d53 474c 4556 454c 3d28 312c 3129 2c0a

    When using ISO8859-1 the file the result looks as follows:
            "dest": "MYUSER.CONTENT1.PDS",
                "encoding": {
                    "from": "ISO8859-1",
                    "to": "IBM-1047"


    Hex content of MYUSER.CONTENT1.PDS
    884C8ECCC676E67D4CCB9DEE66ED96E644A69E466E644A49E46E646EAD494B93
    116FC1CDD5C9C2C49DEB20EC65E026E522152B286E522122B28E777E14929B2D

    When using UTF-8 the file the result looks as follows:

               "dest": "MYUSER.CONTENT2.PDS",
                "encoding": {
                    "from": "UTF-8",
                    "to": "IBM-1047"
                },


    Hex content of MYUSER.CONTENT2.PDS
    8833732D39D3639E83933333333AD3934444444444444444
    11FFCF04F20F5F2E2F2FFFFFFFF14F2D0000000000000000

    And when using IBM-1047 the file is correctly copied (First two characters with hexcode 61 in EBCDIC correspond to the ASCII hexcode 2f two forward slash characters):

                "dest": "MYUSER.CONTENT3.PDS",
                "encoding": {
                    "from": "IBM-1047",
                    "to": "IBM-1047"
                },

    Hex content of MYUSER.CONTENT3.PDS
    66EFFFFFFC4DDC44FFF567DDCCD76CDCEE7C6DECCDCEE7E6DECDCECD74F6F56
    113507622101620D123DBD36313DB33122E1B42733122E2B42735553ED1B1DB

    Could you share the ansible-config dump --only-changed output from your side? On my side I currently have:

    $ ansible-config dump --only-changed
    ANSIBLE_PIPELINING(/home/myuser/ansible-zos/ansible.cfg) = True



    ------------------------------
    Oliver Stadler
    ------------------------------



  • 26.  RE: zos_copy module encoding question
    Best Answer

    Posted Mon September 18, 2023 03:43 AM
    Edited by Oliver Stadler Mon September 18, 2023 03:44 AM

    We were finally able to identify the root cause for this issue. It was caused by the statement SftpServerConvert=*  in zos_sshd_config which causes the encoding for all files to be converted when being transferred via sftp. That changes the default behaviour which the Ansible modules expect. 



    ------------------------------
    Oliver Stadler
    ------------------------------