IBM / zos-node-accessor

z/OS Node Accessor - A Node module to help Node.JS developers interacting with z/OS easily.
Eclipse Public License 1.0
35 stars 18 forks source link
dataset jcl uss zos

z/OS Node Accessor

Build Status Module LTS Adopted' IBM Support

A Node module to help Node.JS developers interacting with z/OS easily, taking advantage of z/OS FTP service. If z/OS FTP service is not configured as FTP over SSL, it's recommended to be deployed on z/OS, to avoid transferring user account/password in clear-text over network. Otherwise, the secure connection of FTP over SSL is recommended. IBM SDK for Node.js - z/OS is available at https://developer.ibm.com/mainframe/products/ibm-sdk-for-node-js-z-os/.

For a Zowe CLI plugin based on this functionality, see https://github.com/zowe/zowe-cli-ftp-plugin

Installation & Test

npm install zos-node-accessor   # Put latest version in your package.json

Features

Migration from v1

zos-node-accessor is rewritten in TypeScript, and defines API methods in more consistent way. So some old API methods are renamed. Here are about some details useful when you migrate the code using zos-node-accessor v1 to v2.

Many list methods in v2 like listDatasets(...) and listFiles(...) returns the objects with the type like DataSetEntry, instead of the key/value pairs in v1. To make the migration easier, you can enable migrationMode to have zos-node-accessor return the v1 key/value pairs, so that you can take time to change code to use the types object. This migration mode will be dropped in future. Let us know, if you have problem in removing the code using the key/value pairs.

    const zosAccessor = new ZosAccessor();
    zosAccessor.setMigrationMode(true);
    var connectionInfo = {
        ....
    };
    await zosAccessor.connect(connectionInfo)

Usage

This accessor leverages z/OS FTP server to interact with z/OS. To work with z/OS JES better, it requires JESINTERFACELevel set to 2 on z/OS FTP settings.

Connection

Before connecting to a z/OS server, you need to initialize an instance using the constructor new ZosAccessor(), then call the connect(option: ConnectionOption) method, where:

Parameter

ConnectionOption

Return

A promise that resolves itself (ZosAccessor object), and rejects on any error.

Example
import { ZosAccessor } from '../zosAccessor';

const accessor = new ZosAccessor();
await accessor.connect({
    user: 'myname',
    password: 'mypassword',
    host: 'localhost',
    port: 21,
    pasvTimeout: 60000,
    secure: true,
    secureOptions: {
        ca: [ caBuffer ]
    }
});

MVS dataset

Allocate Dataset

allocateDataset(datasetName: string, allocateParamsOrString?: string | AllocateParams) - Allocate sequential or partition (with the DCB attribut "PDSTYPE=PDS") dataset.

Parameter

Note: DSORG=PO was defined by zos-node-accessor, not site sub command. It's deprecated by site sub command, PDSTYPE=PDS or PDSTYPE=PDSE.

The site sub commands can be found at https://www.ibm.com/docs/en/zos/2.3.0?topic=subcommands-site-subcommandsend-site-specific-information-host.

Option Key Description
BLKsize/BLOCKSIze=size block size
BLocks space allocations in blocks
CYlinders space allocations in cylinders
DATAClass=data_class data class
DCBDSN=data_set_name the data set to be used as a model for allocation of new data sets
Directory=size directory blocks
DSNTYPE=SYSTEM or BASIC or LARGE data set name type
EATTR=SYSTEM or NO or OPT extended attributes
LRecl=length logical record length
MGmtclass=mgmtclass management class
PDSTYPE=PDS or PDSE PDS type
PRImary=amount primary space
RECfm=format record format
RETpd=days retention period
SECondary=amount secondary space
STOrclass=storage_class storage class
TRacks space allocations in tracks
UCOUN=unit_count or P how many devices to allocate concurrently for this allocation request
Unit=unit_type unit type for allocation of new data sets
VCOUNT=volume_count number of tape data set volumes that an allocated data set can span
VOLume=volume_serial or (volume_serial_list) volume serial number
Return

A promise that resolves on success, rejects on error.

Example
await connection.allocateDataset('HLQ.ABC.DEF', 'LRECL=80 RECFM=FB BLKSIZE=320');
await connection.allocateDataset('HLQ.ABC.PDS', {'LRECL': 80, 'RECFM': 'FB', 'BLKSIZE': 320, 'PDSTYPE': 'PDS', 'DIRECTORY': 20});

List Datasets

listDatasets(dsn: string) - Lists the datasets whose names match with the given dataset name.

Note: This method is renamed from listDataset(dsnOrDir) in v1.0.x, to be consistent with the other list methods.

Parameter
Return

A promise that resolves a list of DatasetEntry.

DatasetEntry

Example
await connection.listDatasets('HQL.*.JCL');
for (const entry of list) {
  console.log('name:', entry.name, 'dsorg', entry.dsOrg);
}

List members of PDS dataset

listMembers(partitionDsn: string) - Lists the members of partition dataset

Parameter
Return

A promise that resolves a list of DatasetMemberEntry.

DatasetMemberEntry

Upload MVS dataset

uploadDataset(input: Input, destDataset: string, transferMode: TransferMode = TransferMode.ASCII, allocateParamsOrString?: string | AllocateParams) - Uploads data to the specified dataset on z/OS.

Parameter
Return

A promise that resolves on success, rejects on error.

Example
import * as fs from 'fs';

const input = fs.readFileSync('/etc/hosts', 'utf8').replace(/\r?\n/g, '\r\n');
await connection.uploadDataset(input, 'HLQ.HOSTS');
await connection.uploadDataset(input, 'HLQ.HOSTS', "LRECL=80 RECFM=FB");

Download MVS dataset

downloadDataset(dsn: string, transferMode: TransferMode = TransferMode.ASCII, stream = false, siteParams?: string) - Downloads the specified dataset or member of patition dataset.

Parameter
Return

A promise that resolves content of the dataset in either Buffer or ReadableStream.

Example
const jclBuffer = await connection.downloadDataset('HQL.AA.JCL', TransferMode.ASCII);
console.log('JCL is:');
console.log(jclBuffer.toString());

const jclStream = await connection.downloadDataset('HQL.AA.JCL(MEMBER1)', TransferMode.ASCII, true);
const writable = fs.createWriteStream('file.txt');
jclStream.pipe(writable);

Delete dataset

deleteDataset(dsn) - Deletes the dataset or member of parition dataset whose names match with the given dataset name.

Parameter
Return

A promise that resolves on success, rejects on error.

Example
await connection.deleteDataset('HQL.AA.JCL');

Rename dataset

renameDataset(dsn: string, newDsn string) - Renames dataset, member in partition dataset.

Parameter
Return

A promise that resolves on success, rejects on error.

Example
await connection.renameDataset('HQL.AA.JCL', 'HQL.BB.JCL')

USS file or directory

Make directory

makeDirectory(directoryName: string) - Makes USS directory with the given directory name.

Parameter
Return

A promise that resolves on success, rejects on error.

Example
await connection.makeDirectory('/u/user/my_directory'});

List files

listFiles(dirPath: string) - Lists files whose names match with the given path name.

Parameter
Return

A promise that resolves a list of USSEntry.

USSEntry

Example
const list = await connection.listFiles('/u/user1/');
for (const entry of list) {
    console.log(entry.name, entry.owner, entry.group, entry.size);
}

Upload USS file

uploadFile(input: Input, destFilePath: string, transferMode: TransferMode = TransferMode.ASCII) - Uploads data to the specified USS file on z/OS.

Parameter
Return

A promise that resolves on success, rejects on error.

Example
import * as fs from 'fs';

const input = fs.readFileSync('/etc/hosts', 'utf8');
await connection.uploadFile(input, '/u/username/hosts');

Download USS file

downloadFile(filePath: string, transferMode: TransferMode = TransferMode.ASCII, stream = false) - Downloads the specified USS file.

Parameter
Return

A promise that resolves content of the file in either Buffer or ReadableStream.

Example
const jclBuffer = await connection.downloadFile('/etc/hosts', TransferMode.ASCII);
console.log('JCL is:');
console.log(jclBuffer.toString());

const jclStream = await connection.downloadFile('/etc/hosts', TransferMode.ASCII, true);
const writable = fs.createWriteStream('file.txt');
jclStream.pipe(writable);

Delete USS file

deleteFile(filePath: string, fileType: FileToOperate = FileToOperate.FILE_OR_DIRECTORY) - Deletes the USS files or directory whose names match with the given file path.

Parameter
Return

A promise that resolves on success, rejects on error.

Example
await connection.deleteFile('/u/username/myfile');
await connection.deleteFile('/u/username/mydir');                                // Delete it, if it's empty
await connection.deleteFile('/u/username/mydir', FileToOperate.WHOLE_DIRECTORY); // Delete it, even if it's not empty.

Rename USS file

renameFile(name: string, newName: string) - Renames USS file/directory.

Parameter
Return

A promise that resolves on success, rejects on error.

Example
await connection.renameFile('/u/username/myfile', '/u/username/newfile')

JES jobs

List jobs

listJobs(queryOption?: JobListOption) - Lists the jobs matching the given query option. If the query option is not provided, it will list all jobs of the current user.

Parameter

JobListOption

Return

A promise that resolves an array of Job. For JESINTERFACELEVEL=2, Job contains valid jobName, jobId, owner, status, class.

Job

Example
const jobs: Job[] = await connection.listJobs({jobName: 'TSU*', owner: 'MY-NAME'})

Submit JCL

submitJCL(jclText: string) - Submits job with the specified JCL text.

Parameter
Return

A promise that resolves the submitted job id.

Example
import * as fs from 'fs';

const jcl = fs.readFileSync('./unpaxz.jcl', 'utf8');
const jobId = await connection.submitJCL(jcl);

Query job

queryJob(queryOption: JobIdOption) - Returns the status the job identified by job id and optional job name.

Parameter

JobIdOption

Return

A promise that resolves status of the job, JobStatusResult.

JobStatusResult

Example
const status = await connection.queryJob(jobName, jobId);
switch(status) {
    case JobStatusResult.SUCCESS:
        console.log('Job succeeded');
        break;
    case JobStatusResult.FAIL:
        console.log('Job failed');
        break;
    case JobStatusResult.ACTIVE:
        console.log('Job is running');
        break;
    case JobStatusResult.WAITING:
        console.log('Job is waiting');
        break;
    case JobStatusResult.NOT_FOUND:
        console.log('Job is not found');
        break;
}

Get job status

getJobStatus(queryOption: JobIdOption) - Returns the status of the job specified by query option.

Parameter

JobIdOption

Return

A promise that resolves job status, JobStatus.

JobStatus

SpoolFile

Example
const jobStatus = await connection.getJobStatus(jobId);

Get JES spool files

getJobLog(queryOption: JobLogOption) - Returns job spool files identified by jobId.

Parameter

JobLogOption

Return

A promise that resolves spool files' contents.

Example
const spoolFileContents = await connection.getJobLog({ jobName, jobId, fileId: -1 });
spoolFileContents.split(/\s*!! END OF JES SPOOL FILE !!\s*/)
    .forEach(function (spoolFile, i) {
        if (spoolFile.length > 0) {
            console.log(`Spool file ${i}:`);
            console.log(spoolFile);
        }
    });

Delete job

deleteJob(queryOption: JobIdOption) - Deletes the job of the specified job id.

Parameter

JobIdOption

Return

A promise that resolves on success, rejects on error.

Example
await connection.deleteJob({ jobId: 'JOB25186' });

Others

Retrieve Server Status

stat(option) - Retrieve status information from a remote server. The following parameters are accepted:

Parameter
Return

A promise that resolves status of the specified option on success, rejects on error. If option is not specified, it returns all status information.

Example
const status = await connection.stat('UMASK');
console.log(status);

Submit SITE commands

site(siteCommands) - Send site-specific information to a server. The following parameters are accepted:

Parameter
Return

A promise that resolves text from server on success, rejects on error.

Example
await connection.site('UMASK 007');

Module Long Term Support Policy

This module adopts the Module Long Term Support (LTS) policy, with the following End Of Life (EOL) dates:

Module Version Release Date Minimum EOL Node Version EOL With Status
2.x.x May 2020 May 2022 v8, v10, v12 Current
1.x.x Oct 2018 Dec 2019 v6, v8, v10, v12 Node v6 EOL

License

Eclipse Public License (EPL)