Automating JCL job submission from z/VM


Important

This is public domain code.

This topic describes how to coordinate z/OS jobs with z/VM work, by submitting z/OS jobs directly from z/VM.

Overview

This section demonstrates how to:

  • Submit jobs with the FILETYPE=JES mode of the z/OS FTP server.
  • Use the VMFTP tool to process output from FTP.
  • Automate JCL job submission using a REXX wrapper.

Automating JCL job submission

z/OS Job Control Language (JCL) is a powerful and mature language and environment for submitting work or jobs to the mainframe. JCL jobs can be submitted in a number of different ways, including:

  • Interactively through a z/OS TSO session
  • Remotely through RSCS from different environments
  • Remotely through FTP from different environments

This section focuses on submitting JCL from z/VM through FTP. It consists of the following sections:

Submitting JCL Jobs Using FTP

The z/OS FTP server has a special mode for submitting JCL jobs and retrieving their output. When the FTP subcommand site filetype=jes is issued, the subcommands get, put, and delete take on a different meaning. For example, in an FTP session to z/OS, consider the following subcommands:

ftp> site filetype=jes
...
ftp> put myjob.jcl
...
ftp> get myjob.x
...

After issuing the site filetype=jes subcommand, the put subcommand submits a JCL job with the specified file name. After the job has completed, the get subcommand retrieves the output. The file type of X is special as the FTP server concatenates all output files from the job into one. The output files include:

  • The job log
  • The JCL
  • System messages
  • Program output (DD SYSOUT=)

Consider the following example where MDMS JCL is a file on the user’s A disk with a sample JCL job:

==> ftp
OPEN (name of foreign host):
====> myzos
Connecting to myzos 192.168.1.1, port 21
220-ENFTP001 IBM FTP CS V2R1 at MYZOS.EXAMPLE.COM, 15:38:34 on 2014-04-11.
USER (identify yourself to the host):
====> myuserid
>>>USER myuserid
331 Send password please.
Password:
====> mypasswd
>>>PASS ********
230 MYUSERID is logged on. Working directory is "MYUSERID.".
Command:
====> site filetype=jes

...
200 SITE command was accepted
====> put mdms.jcl
...
125 Sending Job to JES internal reader FIXrecfm 80
250-It is known to JES as JOB09623
====> dir
...
MDMS JOB09623 OUTPUT 3 Spool Files
====> get job09623.x mdms.output
...
125 Sending all spool files for requested Jobid
250 Transfer completed successfully.
1651 bytes transferred in 0.056 seconds. Transfer rate 29.48 Kbytes/sec.
====> quit


In this example, the job named MDMS is submitted through FTP. It is given the next available job number, 09623 in this example. That job number is then used on the get subcommand with the .X file type to retrieve all output from the job.

Obtaining and Installing the VMFTP Tool

To automate the submission of JCL jobs, the job number must be obtained from the FTP server output after each job is submitted. The code to read the FTP output could be written from scratch, or an existing tool could be used. Many people suggested using the VMFTP tool when this question came up on the IBM-VM list server. For access to this resource see:

http://listserv.uark.edu/cgi-bin/wa?A0=IBMVM

To utilize the VMFTP tool, perform the following steps:

  • Download VMARC to a workstation so you can unpack the VFMTP file. It can be obtained from the z/VM downloads page:
    http://www.vm.ibm.com/download/
    It can be directly downloaded from:
    http://www.vm.ibm.com/download/vmarc.module
  • Download the VMFTP tool to a workstation. It can be downloaded from:
    http://zvm.sru.edu/~DOWNLOAD/
    Search for VMFTPUPD.

    Important

    There is an older package VMFTP from 1997. Do not use that one as it has known bugs fixed buy VMFTPUPD.

  • From the workstation, FTP the files vmarc.module and vmftp.vmarc in binary to a z/VM virtual machine from where the JCL jobs will be submitted.
  • Start a 3270 session to the same z/VM virtual machine where the two files were copied.
  • Deblock the VMARC MODULE with the following pipe command:
    ==> pipe < vmarc module a | deblock cms | > vmarc module a
  • Deblock the VMFTP VMARC file with the following pipe command:
    ==> pipe < vmftpupd vmarc a | fblock 80 00 | > vmftpupd vmarc a f 80
  • Use the VMARC command to unpack the VMFTP package:

    ==> vmarc unpk vmftpupd vmarc a
    VMFTP ASSEMBLE A1. Bytes in= 26880, bytes out= 52224 ( 194%)
    VMFTP CNTRL A1. Bytes in= 240, bytes out= 400 ( 166%)
    VMFTP HELPCMS A1. Bytes in= 3920, bytes out= 7078 ( 180%)
    VMFTP MEMO A1. Bytes in= 2080, bytes out= 3416 ( 164%)
    VMFTP MODULE A1. Bytes in= 5520, bytes out= 7843 ( 142%)
    VMFTP NODELAY A1. Bytes in= 320, bytes out= 480 ( 150%)
    VMFTP NOMASKPW A1. Bytes in= 1920, bytes out= 3886 ( 202%)
    VMFTP TEXT A1. Bytes in= 7200, bytes out= 12640 ( 175%)
    VMFTP UPDTCONT A1. Bytes in= 1440, bytes out= 3040 ( 211%)
    VMFTP UPDTC250 A1. Bytes in= 400, bytes out= 560 ( 140%)
    VMFTP UPDTPASV A1. Bytes in= 400, bytes out= 400 ( 100%)
    VMFTP UPDTXLAT A1. Bytes in= 1600, bytes out= 3600 ( 225%)
    GETDIR VMFTP A1. Bytes in= 1280, bytes out= 5920 ( 462%)
    TEST VMFTP A1. Bytes in= 640, bytes out= 2720 ( 425%)
    TESTNOPW VMFTP A1. Bytes in= 480, bytes out= 2080 ( 433%)

You should now be able to use the VMFTP tool by creating FTP macros with a file type of VMFTP and invoking them with the VMFTP command. Some brief help with “drill-down” capability is invoked with the following command:

==> vmftp ?
COMMANDS VMFTP Brief Help Information
===================================================================
VMFTP Version 1 Release 0.5
Copyright (c) MiraSoft, Inc. 1996 All rights reserved.
===================================================================
VMFTP provides a macro environment for the VM TCP/IP File Transfer
Protocol (FTP) command. It invokes a REXX or EXEC 2 program as a
macro and provides facilities to allow it to issue FTP subcommands
and process the resulting output.

Command syntax:
 VMFTP macro|? ,[,( options ,[,),] ]

Options:
 ALLoutput ECHO IDentify
 NOPASSword PARM string Type

Writing a VMFTP Macro

Following is a VMFTP macro, named FTPJOB VMFTP, to submit a JCL job. It is passed one argument, the JCL job name. It does the following:

  • Reads the input argument and sets the jobName variable
  • Starts an FTP session with the OPENUSER, and PASSWORD subcommands
  • Goes into JCL mode with the SITE FILETYPE=JES subcommand
  • Submits the job with the PUT subcommand
  • Obtains the JCL job name
  • Gets the JCL output with the GET subcommand
  • Searches for error messages (FDRnnn**) and prints them when found
  • Ends the FTP session

Important

In the code examples that follow, text in monospace bold italics should be replaced with values correct for your environment.

==> type ftpjob vmftp

/* VMFTP Macro to submit a JCL job and extract output */
Parse upper arg jobName . /* get the one argument */
system = 'myzos' /* target z/OS system */
userID = 'myuserid' /* z/OS user ID */
password = 'mypasswd' /* password: case sensitive */
jobFile = jobName||'.JCL' /* input file */
 /* do the work */
'open' system /* start the FTP session */
If (rc <> 220) Then Call oops 'open' /* rc of 220 is expected */
i = output.0 /* number of output lines */
Parse Var output.i user rest /* expect USER keyword */
If (user <> 'USER') Then Call oops 'USER prompt'
userID /* send the user ID */
If (rc <> 331) Then Call oops 'userID'
password /* send the password */
If (rc <> 230) Then Call oops 'password'
'site filetype=jes' /* set server to JCL mode */
If (rc <> 200) Then Call oops 'site filetype=jes'
'put' jobFile /* send the JCL job */
If (rc <> 250) Then Do
 Say 'Unexpected return code from put' jobFile||':' rc
 Do i = 1 To output.0 /* loop through output */
 Say output.i
 End
 Call oops 'put'
End
jobNumber = Word(output.4, 7) /* get job # from output */
Say 'Job' jobName 'has been submitted - waiting for output ...'
'get' jobNumber||'.X' /* retrieve the job output */
If (rc = 250) Then Do /* expected return code */
 outFile = jobNumber 'X A' /* get CMS output file */
 'CMS PIPE <' outFile '| stem lines.' /* get output in an array */
 numErrors = 0 /* errors counter */
 Do i = 1 To lines.0 /* check line for error msg */
 If (Substr(lines.i,2,3) = 'FDR' & Substr(lines.i,8,2) = '**') Then Do
 numErrors = numErrors + 1 /* increment error count */
 errors.numErrors = lines.i /* save error message */
 End
 End
 If (numErrors <> 0) Then Do /* error messages found */
 Say 'Error messages in' outFile||':'
 Do i = 1 to numErrors
 Say ' ' errors.i /* print error message */
 End
 End
 Else /* no errors found */
 Say 'Output saved to' outFile /* print output file name */
End
Else Do /* unexpected return code */
 Say 'Unexpected return code from FTP GET' jobFile||'.X =' rc
 Do i = 1 To output.0 /* print all FTP lines */
 Say output.i
 End
End
'quit' /* end the FTP session */
If (rc <> 221) Then Call oops 'quit'
Exit 0

oops: procedure expose rc output. /* error handling procedure */
 parse arg operation
 Say 'Return code' rc 'not expected from operation' operation
 Say output.0 'lines'
 Do i = 1 To output.0
 Say output.i
 End
Exit rc

This macro can now be tested.

Two Sample JCL Jobs

Two sample JCL jobs are used to test the FTPJOB VMFTP macro, one designed to succeed and the other to fail:

  1. MDMS JCL - a job to sort the list of planets included as data within the job. It is designed to succeed.

    ==> type mdms jcl a

    //MDMS JOB ('PR=YES'),'MIKE',CLASS=M,MSGCLASS=X
    //STEP1 EXEC PGM=SORT
    //SYSIN DD *
     SORT FIELDS=(1,75,CH,A)
    /*
    //SYSOUT DD SYSOUT=*
    //SORTIN DD *
    NEPTUNE
    EARTH
    VENUS
    MERCURY
    MARS
    URANUS
    SATURN
    JUPITER
    /*
    //SORTOUT DD SYSOUT=*
    /*
  2. MDMC JCL - A job that performs an FDRPASVM SIMSWAP operation. It is designed to fail (volume serial number is not correct).

    ==> type mdmc jcl a

    //MDMC JOB ('PR=YES'),'MIKE',CLASS=M,MSGCLASS=X
    //PAS.SYSIN DD *
     SIMSWAP TYPE=FULL,LARGERSIZE=OK,MAXTASKS=4,NONRESPONDING=FAIL
    *SIMSWAPMON TYPE=FULL,LARGERSIZE=OK,MAXTASKS=4,NONRESPONDING=FAIL
    *SWAPDUMP TYPE=FULL,LARGERSIZE=OK,MAXTASKS=4,NONRESPONDING=FAIL
    *SWAP TYPE=FULL,LARGERSIZE=OK,MAXTASKS=4,NONRESPONDING=FAIL
     MOUNT VOL=73BSP1,SWAPUNIT=188B

Now that a VMFTP macro is written and sample jobs exist, they can be submitted to z/OS with the VMFTP command with the FTPJOB macro as the argument.

Submitting a Successful JCL Job

Following is an example of submitting the job to sort planets with the VMFTP command. To pass in the JCL job name, the (PARM operand is utilized.

==> vmftp ftpjob (parm mdms
Job MDMS has been submitted - waiting for output ...
Output saved to JOB00609 X A
==> type job00609 x a
1 J E S 2 J O B L O G -- S Y S T E M M Y Z O S --
...
 !! END OF JES SPOOL FILE !!
EARTH
JUPITER
MARS
MERCURY
NEPTUNE
SATURN
URANUS
VENUS
 !! END OF JES SPOOL FILE !!

The output file is a concatenation of all the output files from the z/OS job. Note that the last output file shows the sorted data.

Submitting a JCL Job that Fails

The second job, MDMC JCL, is submitted, and the error messages in the output are displayed:

==> vmftp ftpjob (parm mdmc
Job MDMC has been submitted - waiting for output ...
Error messages in JOB09753 X A:
 FDR316** FDR DID NOT FIND REQUESTED MOUNT SWAP VOL=73BSP1
 FDR032** NO VALID DISK(X) DD (OR MOUNT) STATEMENTS WERE FOUND
 FDR998** FDR COMPLETED WITH ERRORS
 FDR316** FDR DID NOT FIND REQUESTED MOUNT SWAP VOL=73BSP1
 FDR032** NO VALID DISK(X) DD (OR MOUNT) STATEMENTS WERE FOUND
 FDR998** FDR COMPLETED WITH ERRORS

The output shows that a job was submitted, its output was retrieved, and error messages were found.

Adding a Wrapper Around FTPJOB

Now that there is a process to submit a single job, a REXX EXEC wrapper can be written around it to submit a series of jobs. Following is the REXX EXEC to accomplish this:

==> type ftpjobs exec

/* EXEC to automate testing of FDRPASVM using FTP and VMFTP tool */
jobsFile = 'FTPJOBS LIST A' /* file with JCL jobs to run */
'STATE' jobsFile /* check that file exists */
If (rc <> 0) Then /* input file not found */
 Exit 1 /* fatal error */
'PIPE <' jobsFile '| stem jobs.' /* get test cases in an array */
Do i = 1 To jobs.0 /* check line for error msg */
 Say 'Submitting job' jobs.i /* info message */
 'STATE' jobs.i 'jcl' /* check if file exists */
 If (rc = 0) Then /* file exists */
 Call FTPjob jobs.i /* FTPjob submits job */
End
Exit

FTPjob: procedure /* to submit one job */
Parse arg jobName /* get job name */
'VMFTP FTPJOB (PARM' jobName /* use VMFTP macro */
If (rc <> 0) Then /* check for error rc */
Say 'Unexpected return code from job' jobName||':' rc
Say '' /* output spacer */
Return

This EXEC reads the job names from the file FTPJOBS LIST A. To test, this file had three job names:

==> type ftpjobs list a

mdms
mdmc
nosuch

These three jobs have different expected outcomes:

MDMS JCL A job that should succeedMDMC JCL A job that should fail with certain error messagesNOSUCH JCL A nonexistent job (no such file)

Putting it All Together

Following is an example of running the FTPJOBS EXEC:

==> ftpjobs
Submitting job mdms

Job MDMS has been submitted - waiting for output ...
Output saved to JOB00297 X A

Submitting job mdmc

Job MDMC has been submitted - waiting for output ...
Error messages in JOB00298 X A:
 FDR316** FDR DID NOT FIND REQUESTED MOUNT SWAP VOL=73BSP1
 FDR032** NO VALID DISK(X) DD (OR MOUNT) STATEMENTS WERE FOUND
 FDR998** FDR COMPLETED WITH ERRORS
 FDR316** FDR DID NOT FIND REQUESTED MOUNT SWAP VOL=73BSP1
 FDR032** NO VALID DISK(X) DD (OR MOUNT) STATEMENTS WERE FOUND
 FDR998** FDR COMPLETED WITH ERRORS

Submitting job nosuch

DMSSTT002E File NOSUCH JCL not found

The output shows that no error messages were found in the output of the MDMS job, error messages were found in the output of the MDMC job and printed, and an error message stated that the NOSUCH job file was not found.

 

Tip: For faster searching, add an asterisk to the end of your partial query. Example: cert*