Ansible for IBM Z - Group home

Simplified Approach to Copying Data Between z/OS and Local Machine Using Ansible

  

Copying files between local machine and remote z/OS servers is something that can be incredibly useful for developing, deploying and provisioning of applications. Current methods for data transfer include shell commands -- using SSH or FTP -- or z/OSMF APIS. Using shell commands is limited to transferring files from and to the Unix System Services (USS). Being able to copy MVS data sets would require additional steps, which can be cumbersome. To address this complexity of interacting with z/OS systems, IBM has introduced the Red Hat Ansible Certified Content for IBM Z, which is a collection of Ansible modules that can be used to perform many z/OS related tasks including copying data to and from remote z/OS systems. It should be noted that all of the complexities of the data transfer process is hidden behind simple, concise and intuitive YAML syntax of Ansible.

Before proceeding any further, I am going to assume you are somewhat familiar with Ansible. If you are new to Ansible and would like to learn the basics of how it works, here is a great place to start.

To demonstrate how to copy data to and from a z/OS host using Ansible, We are going to do the following:

  • Create a partitioned data set (PDS) on the remote z/OS host
  • Copy a local file to the newly created PDS member
  • Fetch the PDS back to the local machine
  • Add some additional files to the fetched data set
  • Copy the fetched directory back to the PDS, replacing the original

We can use the zos_data_set module to create the PDS that we want

- name: Create a PDS on remote host
  zos_data_set:
    name: USER.TEST.PDS
    type: pds
    format: fba
    record_length: 80
    size: 5M



Then, copy a local file to the PDS using the 
zos_copy module. Also, the local file is an ASCII encoded file and it should be be converted to EBCDIC when being copied. This is easily done through the zos_copy module as well by specifying the encoding parameter.

- name: Copy local file to the created PDS member
  zos_copy:
    src: /path/to/local/file
    dest: USER.TEST.PDS(MEMBER)
    encoding:
      from: ISO8859-1
      to: IBM-1047


The response for copy task is outlined below.

TASK [Copy local file to the created PDS member] ********************************************************
ok: [<remote-zos-host>] => {
    "dest": "USER.TEST.PDS(MEMBER)",
    "invocation": {
        "module_args": {
            "dest": "USER.TEST.PDS(MEMBER)",
            "encoding": {
                "from": "ISO8859-1",
                "to": "IBM-1047"
            },
            "src": "/path/to/local/file"
        }
    },
    "is_binary": false,
    "src": "/path/to/local/file"
}


To verify that the copy task was successful, let's take a look at the data set members.



Looks like the file was copied to the data set member. Next, we want to copy this data set back to our local machine. To do that, we will be using the zos_fetch module. Similar to zos_copy, we specify the name of the data set forsrc and the absolute path where we want to fetch the data set to as dest. We also have the option to convert the encoding of the PDS when fetching. Note that for partitioned data sets, encoding of all members will be converted.

- name: Fetch the PDS back to the control node
  zos_fetch:
    src: USER.TEST.PDS
    dest: /tmp/
    flat: yes
    encoding:
      from: IBM-1047
      to: ISO8859-1


The response for the fetch task outlines the data set type, source and destination.

TASK [Fetch the PDS back to the control node] *********************************************************
changed: [<remote-zos-host>] => {
    "data_set_type": "Partitioned",
    "dest": "/tmp/USER.TEST.PDS",
    "file": "USER.TEST.PDS",
    "is_binary": false
}


To verify that the PDS was fetched correctly, let's inspect the destination directory

$ ls /tmp | grep USER.TEST.PDS
USER.TEST.PDS
$ ls /tmp/USER.TEST.PDS
MEMBER


Notice that the PDS was fetched as a directory with the same name as the source data set. Now that we have fetched the PDS to our local machine, let's modify it by creating some additional files inside it.

- name: Add additional files to the fetched directory
  file:
    path: "/tmp/USER.TEST.PDS/file{{ item }}"
    state: touch
  with_sequence: count=4
  delegate_to: localhost


Verify that the files were created

$ ls /tmp/USER.TEST.PDS
MEMBER file1 file2 file3 file4


Next, copy the directory back to the remote z/OS server to a PDS, replacing the existing PDS of the same name.

- name: Copy the updated directory back to the remote host
  zos_copy:
    src: /tmp/USER.TEST.PDS
    dest: USER.TEST.PDS
    encoding:
      from: ISO8859-1
      to: IBM-1047


If we inspect the contents of the PDS again, we see that existing PDS has been replaced.



These are only some of the capabilities of zos_copy and zos_fetch modules. I encourage you to take a deeper dive into the Ansible z/OS Core Collection GitHub repository and play with the sample playbook here.