Introduction
In the second of this series, we look at the installation and execution of the second ansible pre-req: IBM z/OS Open Automation (ZOA) Utilities. These provide a raft of additional functionality to the Python world, include z/OS dataset handling, batch job submission and tracking and z/OS console use. These features are in turn used by ansible.
Installing ZOA Utilities
These utilities are installed via CBPDO and SMP/E as with other z/OS software. They can be ordered separately (Program ID is 5698-PA1) or as part of other tooling – e.g. Dependency Based Builder (DBB).
The end result should be a new path in USS:
/usr/lpp/IBM/zoautil
Configuration
To make use of these utilities, we will need to configure them into the USS environment. We did this by updating a single userid profile, by adding the following:
Note that the MANPATH export adds the ZOA Utilities into the scope of the “man” (manual) Unix command which provides syntax and parameters for each of the commands supplied by this feature.
Note also that the last entry (PYTHONPATH) is in place for ansible.
Documentation
The documentation for ZOA Utilities is all online and can be found here:
https://www.ibm.com/support/knowledgecenter/SSKFYE_1.0.3/zoautil_overview.html
The Python doc is here (for 1.0.3):
https://www.ibm.com/support/knowledgecenter/SSKFYE_1.0.3/python_doc_zoautil/index.html?view=embed
The product is updated (so far) by PTFs, so make sure that you’re looking at the correct version (selectable with the “Change version or product” pull down on the top left of the web page).
Example Commands
As well as Python modules and Java interfaces, the ZOA Utilities are implemented as shell commands as well. These provide extensions to the USS shell environment. Here are some examples:
- List PDS members
-
- mls “ZPDT.SYSTEM.JCL”
-
- List a PDS member – this method uses the dtail (cf Linux tail command) starting with line 1 (-n +1)
-
- dtail -n +1 “ZPDT.SYSTEM.JCL(DSNTEP2)”
-
- Submit a batch job – this returns (in the job_id variable) the JOBnnnnn ID – e.g. JOB00637.
-
- job_id=$( jsub “ZPDT.SYSTEM.JCL(DSNTEP2)” )
-
- Check batch job status. BEWARE! If you issue this command without parameters, it will attempt to list every job in the system – active and completed. Make sure that you at least restrict it to the job owner (IBMUSER in this case), and better is to include a job name profile (as you would in SDSF). The columnar output headers are: Owner, Job/TSU/STC name, Job/TSU/STC id, status (AC = active, CC = finished, ABEND = abended, JCLERR = JCL error) and resulting code (active = ? (not yet set), ABEND = System or User Abend code, CC = max condition code):
-
- jls /IBMUSER/IBMUSER*
-
- Check a specific batch job status:
-
- jls JOB00637
-
- List batch job output DD names
-
- ddls JOB00637. This gives a columnar list – the headings could have been something like step name, proc step name, DD name, record format, logical record length, number of records.
-
- Retrieve batch job output
-
- pjdd JOB00601 DSNTEP2 SYSPRINT
-
- Get console output. There are a lot of different options, but the shortest about of time that it will retrieve is 10 minutes. This could be quite a lot of data in a busy service.
-
- pcon -r
-
- Issue a console command. Note that at the time of writing, a command prefixed with a hyphen (“-“) will fail. This can be a problem for customers who use hyphen-db2 as the subsystem command prefix – e.g. -DB2T DIS GROUP.
-
- opercmd “d prog,apf”
-
Example Python Scripts
Example 1 – Working With Jobs
The following is a short Python script which brings together most of the commands from above. Things to note:
- We checked that the dataset member with the JCL exists before we submit it
- The Jobs.list() returns one entry for the job submitted because we used the JOBxxxxx form returned by Jobs.submit().
- The ‘status’ dictionary entry is the current status of the batch job. ‘AC’ = active, ‘CC’ = finished with condition code set in ‘return’, ‘JCLERR’ = JCL error and ‘ABEND’ = system or user abend (see ‘return’)
Here’s what it looks like when run:
Example 2 – Issuing Console Commands
This next example issues a dynamic APF display command and then reports the output:
Here’s what the output looks like when run:
Note that we don’t have the same challenge with the OperatorCmd.execute() as with “opercmd” implementation – i.e. if we change the command issued in the above example to “-DB2T DIS DDF DETAIL” we get the following:
Observations
This evolving set of utilities provides a whole set of additional capabilities into the USS environment that have not previously been available to scripting languages like Java and Python, let alone shell scripts. As an enabling technology, it provides a big uplift in capability for the environment and could make something like a Jenkins node running in USS significantly more capable.
We haven’t investigated driving these capabilities from Jenkins and Groovy, as our main focus has been on ansible. We will try and add this in to the end of the current blog run.
Next Time
In the next blog in this series, we’ll get Ansible installed and run some simple playbooks using the z/OS core and zOSMF collections.
View all blogs in James Gill’s Ansible series.