How to Call Low-Level z/OS Services from Node.js

Dan Kelosky
Zowe
Published in
5 min readJul 21, 2020

--

{Core} In a previous blog, we’ve seen how you can call low-level services (written in Metal C /HLASM) from Java. Here, we’ll do something similar but from Node.js / JavaScript.

JavaScript code writing to a z/OS log via WTO

Background / Prerequisites

Before getting started, you’ll have to go through the steps to install Node.js and build a native “Hello World” Node.js application for z/OS. Petr’s blog covers this perfectly.

Disclaimer

The approach below is admittedly a little obscure (using both the njsc++ and xlc compilers). Hopefully, this blog will be updated in the future, showing a cleaner method of calling HLASM from JavaScript.

N-API Hello World

The end of Petr’s blog cover’s an N-API example.

N-API is a way to call native (C/C++) code from Node.js / JavaScript. To get started, you’ll need several initial source files:

  • binding.gyp
  • hello.cc
  • hello.js
  • package.json

Following Petr’s blog, after you have these files, you should be able to run:

npm install && node hello.js

“world” is output after running

Troubleshooting Tips

Here are a few miscellaneous items that might help if you run into problems:

#1 Use Zowe CLI

You can use the Open Mainframe Project’s Zowe CLI to create and mount your own file system if you run out of space.

Create:

zowe files create zfs IBMUSER.PUBLIC.NATIVE.NODE.ZFS --volumes tsu063

Mount:

zowe files mount fs IBMUSER.PUBLIC.NATIVE.NODE.ZFS /a/ibmuser/native/node --mode rdwr

#2 Use Zowe Explorer

Use Zowe Explorer (a VS Code extension) to edit USS files directly (instead of using SSH):

Editing mainframe files in VS Code

#3 Update npm Cache Location

If you’re frequently installing npm packages, you may run out of cache space in your default home location. You can adjust this in your home’s .npmrc file. For example, add this line to adjust the cache to another location /a/ibmuser/native/node:

cache=/a/ibmuser/native/node/.npm

#4 Update .gyp Location

Similar to above, if you run out of space when running node-gyp (more about this tool later), adjust the .gyp folder location used in node-gyp commands via setting an environmental variable:

export npm_config_devdir=/a/ibmuser/native/node/.gyp

Source Files

Keeping with the Java to Metal C / HLASM example referenced above, we’ll add some code to call WTO from Node.js.

All source files are added into a work directory on USS .../native/node/hello-wto.

We barrow the key source files from the sample REST API project:

  • makefile
  • wto.h
  • wtoexec.c
  • wtoexec.h

We won’t go into the details of how this code works here. Instead, we’ll build it AS-IS into object code and then link it into our N-API executable.

We also tailor the N-API source files for our needs:

wto.js

Our JavaScript code will call a native function wto which accepts a string and arbitrary number as parameters (see wto(...)):

package.json

Our package will describe our main file as being wto.js:

binding.gyp

Our main C++ source file will be wto.cc:

wto.cc

Our N-API code will extract the passed parameters and invoke WTOEXE(...).

Generate Your Project — GYP

We use node.gyp in this project to build part of our native (C++ ) source code.

GYP is a Meta-Build system: a build system that generates other build systems.

node-gyp is a command line too that bundles GYP and helps build native addons for Node.js.

We’ll gloss over most of the details of GYP for the purpose of this project. A few key points:

  • node-gyp is a command we’ll run to build native applications
  • bindings.gyp in the project is read by the node-gyp command
  • node-gyp outputs makefiles among other things
  • the generated makefile will invoke njsc++ to compile native C++ code

Building

Here are the high level steps to build and call HLASM code from JavaScript:

Step 0:

npm install will download dependencies, specifically bindings into a node_modules folder.

Step 1:

make wtoexec.o will build our metal C / HLASM code into an object file, wtoexec.o using the xlc compiler.

njsc++ is used for node-gyp, but it doesn’t appear to support the metal option which is needed to build this piece (which is why we use xlc).

There are two makefiles in this project. Here, we run the makefile at the project root. The Makefile under the /build directory isn’t run yet, but is called when running node-gyp build in Step #4.

Step 2:

node-gyp configure will create a build directory in your project, including a Makefile.

Step 3:

Edit the /build/Makefile to include the wtoexec.o object created from xlc 😦. This is a bit messy but is meant as a Minimum Viable Product (MVP) example for the time-being:

Manually adding wtoexec.o object to Makefile

Step 4:

node-gyp build this will build wto.cc and link in wtoexec.o into a final artifact. If you mistakenly run node-gyp rebuild, a node-gyp configure operation runs behind the scenes and will overlay your build/Makefile.

Step 5:

node wto.js this will run the JavaScript code and display a 0 if everything is successful.

Boring output to console
WTO written to system log

Scripts

You can write some scripts to make this process a bit smoother. You can see the basis of scripts to automate uploading, build, and running code without directly logging into the system:

Conclusion

Although there is plenty of refinement to make this project clearer, you can see how it is possible to invoke a Metal C / HLASM service from Node.js.

Please comment here or update the repo with a PR if you have ideas for improving this process.

Acknowledgements

Thanks Petr Plavjaník & Vit Tomica for helping put together all of these details!

See Petr’s newest blog for additional background information on building native addons.

If you enjoyed this blog checkout more Zowe blogs here. Or, ask a question and join the conversation on the Open Mainframe Project Slack Channel #Zowe-dev, #Zowe-user or #Zowe-onboarding. If this is your first time using the OMP slack channel register here.

--

--

Dan Kelosky
Zowe

Likes programming/automation in mainframe (assembler, C/C++), distributed (Node.js), and web development (Firebase, Angular).