A Node module to help Node.JS developers interacting with z/OS easily. It provides both a library wrapping z/OS FTP service and a CLI tool zos
that exposes the same functionality at the command line.
IBM SDK for Node.js - z/OS Beta is available at https://developer.ibm.com/node/sdk/ztp/.
npm install zos-node-accessor # Put latest version in your package.json
npm test # You'll need the dev dependencies to launch tests
- List MVS dataset or USS files
- Download/Upload MVS dataset or USS files
- Submit JCL and query its status to track its completion
- Access SYSOUT dataset
- Some simple JCL, like initiating HRECALL, allocating dataset, and so on.
This accessor leverages z/OS FTP server to interact with z/OS, it requires JESINTERFACELevel
set to 2
Before connecting to a z/OS server, you need to initialize an instance using the constructor new zosAccessor()
, then call the connect(config)
method, where:
- config - object - Configuration passed to the underlying ftp library, valid properties:
- user - string - Username for authentication on z/OS. Default: 'anonymous'
- password - string - Password for authentication on z/OS. Default: 'anonymous@'
- host - string - The hostname or IP address of the z/OS server to connect to. Default: 'localhost'
- port - integer - The port of the z/OS FTP server. Default: 21
- secure - mixed - Set to true for both control and data connection encryption, 'control' for control connection encryption only, or 'implicit' for implicitly encrypted control connection (this mode is deprecated in modern times, but usually uses port 990) Default: false
- secureOptions - object - Additional options to be passed to
tls.connect()
. Default: (none) - connTimeout - integer - How long (in milliseconds) to wait for the control connection to be established. Default: 10000
- pasvTimeout - integer - How long (in milliseconds) to wait for a PASV data connection to be established. Default: 10000
- keepalive - integer - How often (in milliseconds) to send a 'dummy' (NOOP) command to keep the connection alive. Default: 10000
A promise that resolves itself (the connection to z/OS), and rejects on any error.
var Client = require('zosAccessor');
var c = new Client();
// connect to localhost:21 as hansome using password
c.connect({user: 'myname', password:'mypassword'})
.then(function(connection) {
// here connection equals to outer c
})
.catch(function(err) {
// handle error
});
allocateDataset(datasetName, allocateParams)
- Allocate dataset.
- datasetName - string - Dataset name to allocate.
- allocateParams - object | string - A string of space separated DCB attributes or an object of DCB attribute key-value pairs, eg. "LRECL=80 RECFM=VB" or {"LRECL": 80, "RECFM": "VB"}.
Option Key | Description |
---|---|
SPACETYPE | allocation units |
BLKSIZE | blocksize |
DATACLASS | data class |
DIRECTORY | directory blocks |
DSNTYPE | data set name type |
EATTR | extended attributes |
LRECL | logical record length |
MGMTCLASS | management class |
DCBDSN | model DCB values |
PDSTYPE | PDS type |
PRIMARY | primary space |
RECFM | record format |
RETPD | retention period |
SECONDARY | secondary space |
STORCLASS | storage class |
UNITNAME | unit |
VCOUNT | volume count |
UCOUNT | unit count |
VOLUME | volume serial number |
A promise that resolves on success, rejects on error.
connection.allocateDataset('ABC.DEF', {'LRECL': 80, 'RECFM': 'FB', 'BLKSIZE': 320})
.then(function() {
console.log('Success');
})
.catch(function(err) {
// handle error
});
listDataset(dsnOrDir)
- List MVS datasets or USS files
- dsnOrDir - string - Specify a full qualified dataset name, supporting wildcards (* or ?), PDS members (HLQ.JCL(*)) and USS directory.
A promise that resolves a list of
-
dataset entries. Each entry has the property of
Volume
,Unit
,Referred
,Ext
,Used
,Recfm
,Lrecl
,BlkSz
,Dsorg
, andDsname
. -
USS file entries. Each entry has the property of
name
,size
,owner
,group
, andpermissions
.
connection.listDataset('HQL.*.JCL')
.then(function(list) {
for(var i=0; i<list.length; ++i) {
var entry = list[i];
console.log('name:', entry['Dsname'], 'dsorg', entry['Dsorg']);
}
})
.catch(function(err) {
// handle error
});
connection.listDataset('/u/user1/')
.then(function(list) {
for(var i=0; i<list.length; ++i) {
var entry = list[i];
console.log(entry.name, entry.owner, entry.group, entry.size);
}
})
.catch(function(err) {
// handle error
});
uploadDataset(input, destDataset, dataType, allocateParams)
- Upload a local file to MVS dataset or USS file.
- input - any - A ReadableStream, a Buffer, or a path to a local file that needs uploading.
- destDataset - string - Dataset name to used to store the uploaded file, if it starts with
/
this file will be uploaded to USS. - dataType - string (default: ascii) - Transfer data type, it should be 'ascii' or 'binary', when transfering 'ascii' files, the end-of-line sequence of input should always be
\r\n
, otherwise the transfered file will get truncated. - allocateParams - object | string - A string of space separated DCB attributes or an object of DCB attribute key-value pairs, eg. "LRECL=80 RECFM=VB" or {"LRECL": 80, "RECFM": "VB"}.
A promise that resolves on success, rejects on error.
var fs = require('fs');
var input = fs.readFileSync('/etc/hosts', 'utf8').replace(/\r?\n/g, '\r\n');
connection.uploadDataset(input, 'hosts')
.then(function() {
console.log('Success');
})
.catch(function(err) {
// handle error
});
getDataset(dsn, dataType, stream)
- Get the contents of the MVS dataset or USS file.
- dsn - string - Specify a full qualified dataset name, or USS file name. It CAN NOT contain any wildcard (*).
- dataType - string (default: 'ascii') - Transfer data type, accepts three options
binary
,ascii
,ascii_strip_eol
. When downloading an ascii dataset, dataType should be eitherascii
orascii_strip_eol
so that the FTP server convertsEBCDIC
characters toASCII
,ascii_strip_eol
tells FTP server not the append a CLRF to the end of each record. - stream - boolean (default: false) -
true
if you want to obtain a ReadableStream of the data set content, orfalse
to read a full dataset into memory (in Buffer).
A promise that resolves content of the dataset or file in either Buffer
or ReadableStream
.
connection.getDataset('HQL.AA.JCL', 'ascii')
.then(function(jclBuffer) {
console.log('JCL is:');
console.log(jclBuffer.toString());
})
.catch(function(err) {
// handle error
});
delete(dsn)
- Delete a dataset or USS file.
- dsn - string - Specify a full qualified dataset name to delete, it CAN NOT contain a wildcard (*).
A promise that resolves on success, rejects on error.
connection.deleteDataset('HQL.AA.JCL')
.then(function() {
console.log('Deleted');
})
.catch(function(err) {
// handle error
});
rename(oldDataset, newDataset)
- Renames oldDataset to newDataset.
- oldDataset - string - Old dataset name.
- newDataset - string - New dataset name to rename to.
A promise that resolves on success, rejects on error.
connection.rename('HQL.AA.JCL', 'HQL.BB.JCL')
.then(function() {
console.log('Renamed');
})
.catch(function(err) {
// handle error
});
listJobs(jobName)
- List JES jobs matching query condition
- condition - object - An object whose valid keys are:
- jobName: specify a JES job name, it can contain a wildcard (*)
- owner: specify a JES job owner, it can contain a wildcard (*)
- status: specify a JES job status, eg. ALL, OUTPUT
A promise that resolves an array of jobs, each item in the array is a string separated by space, for JESINTERFACELEVEL=2, those fields are JOBNAME, JOBID, OWNER, STATUS, CLASS
connection.listJobs({jobName: 'TSU*', owner: 'MY-NAME'})
.then(function(jobList) {
})
.catch(function(err) {
// handle error
});
submitJCL(JCLText, cfg)
- Submit raw JCL text to JES server, or submitting built-in helper JCLs
-
JCLText - string - The raw JCL string to be submitted, or the name of built-in JCLs if
cfg
is specified. -
cfg - object - configurations to the JCL, if this parameter is specified, then JCLText should be a name of the built-in JCLs, and the
cfg
should contain parameters for that JCL. Following is a list of built-in JCLs and their supported configurations:-
- name:
ALLOC
- supported configurations:
{ DSN: 'abc' }
- name:
-
- name:
COPY
- supported configurations:
{ from: 'abc', to: 'edf' }
- name:
-
A promise that resolves the submitted job id.
- Submit raw JCL
var fs = require('fs');
fs.readFile('./unpaxz.jcl', function(err, jclContent) {
connection.submitJCL(jclContent)
.then(function(jobId) {
console.log('Job id is', jobId);
})
.catch(function(err) {
// handle error
});
});
- Submit a built-in JCL
connection.submitJCL('HRECALLW', {INPUT: 'AA.BB'})
.then(function(jobId) {
console.log('Job id is', jobId);
})
.catch(function(err) {
// handle error
});
queryJob(jobName, jobId)
- Query job status identified by job name and job id. (Deprecated, use getJobStatus
for more details.)
- jobName - string - Name of the job.
- jobId - string - Id of the job.
A promise that resolves status of the job, it is one of the following values:
- RC_SUCCESS - Job succeeds
- RC_ACTIVE - Job running
- RC_FAIL - Job fails
- RC_WAITING - Job waiting
- RC_NOT_FOUND - Cannot find job specified by the jobName and jobId
connection.queryJob(jobName, jobId)
.then(function (status) {
switch(status) {
case connection.RC_SUCCESS:
console.log('Job succeeded');
break;
case connection.RC_FAIL:
console.log('Job failed');
break;
case connection.RC_ACTIVE:
console.log('Job running');
break;
case connection.RC_NOT_FOUND:
console.log('Job not found');
break;
default:
console.log('Unknown status');
}
});
getJobStatus(jobId)
- Get job status specified by jobId.
- jobId - string - Id of the job.
A promise that resolves job status
{
jobname: "HRECALLW",
jobid: "JOB06385",
owner: "USER",
status: "OUTPUT",
class: "A",
rc: 0,
spoolFiles: [
{
id: 2,
stepname: "JES2",
procstep: "N/A",
c: "H",
ddname: "JESJCL",
byteCount: 315
}
]}
connection.getJobStatus(jobId)
.then(function(jobStatus) {
console.log('Job status is:');
console.log(jobStatus);
})
.catch(function(err) {
// handle error
});
getJobLog(jobName, jobId)
- Get jes spool files identified by jobName and jobId.
- jobName - string - Name of the job. Default: '*'
- jobId - string - Id of the job.
- spoolFileIndex - string | integer - Index of the spool file to get. Number of spool files can be found using
getJobStatus
, specifying 'x' will return all spool files joined with the!! END OF JES SPOOL FILE !!
. Default: 'x'
A promise that resolves spool files populated by the job
connection.getJobLog(jobName, jobId, 'x')
.then(function(jobLog) {
console.log('Job id is:');
console.log(jobLog);
})
.catch(function(err) {
// handle error
});
deleteJob(jobId)
- Purge/delete job by job id.
- jobId - string - Id of the job.
A promise that resolves on success, rejects on error.
connection.deleteJob('JOB25186')
.then(function() {
console.log('Deleted');
})
.catch(function(err) {
// handle error
});
This module adopts the Module Long Term Support (LTS) policy, with the following End Of Life (EOL) dates:
Module Version | Release Date | Minimum EOL | EOL With | Status |
---|---|---|---|---|
1.x.x | Oct 2018 | Dec 2019 | Current |