The Unix parts of z/OS

In the previous DBAOTM post I have introduced you to the z/OS operating system, the flagship operating system for the mainframe. In this post I will introduce you into the Unix side that z/OS has been equipped with over the past two decades.

Since the 1990s IBM has added Unix functionality to z/OS. The first extension was z/OS Unix System Services – z/OS Unix in short – and recently we IBM have added z/OS Container Extensions.

z/OS Unix

The Unix part of z/OS is a runtime environment that is an integral part of the z/OS operating system. z/OS Unix is fully Unix (Posix) compliant. z/OS Unix provides an interactive command interface that is called a shell in Unix terminology.

IBM has developed this part in the 1990s to make it easier to port applications from other platforms to z/OS. Many off-the-self and open source middleware and application packages that are available on z/OS make use of z/OS Unix. Examples are IBM’s own WebSphere Application Server and IBM Integration Bus, the banking product BASE24-eps from ACI, and open source tools like PHP and Git.

z/OS Unix has regular files the same as other Unix systems. In the z/OS Unix shell you can use normal Unix commands like ls, cd, more and many more of the standard Unix commands. You can set up a telnet or SSH session with z/OS Unix and do many more things you can also do with other Unix environments.

z/OS Container Extensions

A very recent development on z/OS (it came with z/OS 2.4, end 2019) is the possibility to run Linux Docker Containers on z/OS.

Docker containers are a hardware independent and lightweight manner to run many applications in a virtualized configuration. The Docker technology has been available on x86 platforms for a long time. With Docker containers you get a virtualization solution that does not need a complete virtual machine with an operating system running in it for every application. Instead your application is running in a small container that provides only a limited set of virtualization facilities. Just the things that the application needs. You can run many Docker containers – so applications – on a single real operating system image.

The interesting thing is that in a conceptual way Docker is a quite like z/OS as we have seen it in section Address Spaces are processes. On a z/OS operating system you can run many applications in “Address Spaces”. With Docker you run many container processes on a single real operating system image.

I will talk a bit more about Docker in section Linux in z/OS Container Extensions.

z/OS Address Spaces versus Docker containers

All Unix variants

A small elaboration, as you may already get confused with the Unix on the mainframe. I mentioned Linux for the mainframe, now I talk about z/OS Unix and Linux in Containers.

It is important to understand the difference between z/OS Unix, z/OS Container Extensions and Linux for Z.

z/OS Unix and z/OS Container Extensions are an integral part of z/OS. You get these options with z/OS.

z/OS Unix applications use the Unix flavour that z/OS provides, which is not Linux.

In z/OS Container Extensions you get the option to run applications with the Linux flavour of Unix, and run these in a containerized setup.

Linux for Z is an operating system that is in no way related to z/OS. Applications running on Linux for Z use the Linux flavour, and in an LPAR or Virtual Machine of its own.

I have tried to put all the Unix variants on z/OS in the picture below. You see z/OS Unix, as part of a z/OS operating systems, you see a z/OS container process running a Linux Docker container, and separate from z/OS there is an LPAR running Linux for Z.

The Unix flavours of z/OS and Linux for Z

What’s next

Now we have seen the basics of z/OS, we can turn to the more specialized and specific parts. In the next post I will discuss the unique clustering feature of z/OS, called parallel sysplex.

IBM Integration Bus / Message Broker operations with IBM Integration API aka CMP

  • Post category:IBM Integration Bus
  • Reading time:11 mins read

IBM provides the IBM Integration API, also known under the less accurate and descriptive name Configuration Manager Proxy (CPM), through which you can write your applications to control IBM Integration Bus components.

The Java code below provices a working example of this API. The code presented revolves around a BrokerManager class. In the code below only one method on this class has been implemented, but it can easily be extended with other methods. 

The code uses a z/OS specific way to connect to a broker. On z/OS we do not connect through the network but locally. This needs a slightly different approach using the getLocalInstance method on the Broker Proxy API.

The main() method in this sample implements the instantiation and invocation of the BrokerManager, implementing a command line solution, but the same code could be used in different contexts seamlessly.

The documentation of the API can be found in the IBM Integration Bus Knowledge Center.

Information for the App Connect enterprise version can be found through this link. I have not tried that version.

package com.your.company.package.broker;
import com.ibm.broker.config.proxy.AdministeredObject;
import com.ibm.broker.config.proxy.AdministeredObjectListener;
import com.ibm.broker.config.proxy.ApplicationProxy;
import com.ibm.broker.config.proxy.AttributeConstants;
import com.ibm.broker.config.proxy.BrokerConnectionParameters;
import com.ibm.broker.config.proxy.BrokerProxy;
import com.ibm.broker.config.proxy.CompletionCodeType;
import com.ibm.broker.config.proxy.ConfigManagerProxyException;
import com.ibm.broker.config.proxy.ConfigManagerProxyLoggedException;
import com.ibm.broker.config.proxy.ConfigManagerProxyPropertyNotInitializedException;
import com.ibm.broker.config.proxy.ExecutionGroupProxy;
import com.ibm.broker.config.proxy.LogEntry;
import com.ibm.broker.config.proxy.MQBrokerConnectionParameters;
import com.ibm.broker.config.proxy.MQPropertyFileBrokerConnectionParameters;
import com.ibm.broker.config.proxy.MessageFlowProxy;
import com.ibm.mq.MQException;
import java.util.Enumeration;


public class BrokerManager {


    private BrokerProxy bp;
    private String bn;
    private String qm;
    private String hn;
    private int port;


    BrokerManager(String broker, String host, String qmgr, int port) {
        this.bn = broker;
        this.qm = qmgr;
        this.hn = host;
        this.port = port;
        System.out.println("Creating Broker Manager " + this.bn);
    }


    public boolean connect() {
        BrokerConnectionParameters bcp;
        boolean brokerIsResponding = false;
        // bcp = new MQBrokerConnectionParameters(this.hn, this.port, this.qm);
        // Not for z/OS
        // bcp = new MQBrokerConnectionParameters("", this.port, this.qm); but we will use
        // getLocalInstance for z/OS below
        try {
            this.bp = BrokerProxy.getLocalInstance(this.bn);
            // alternative this.bp = BrokerProxy.getInstance(bcp);
            // Ensure the broker is actually talking to us.
            brokerIsResponding = bp.hasBeenPopulatedByBroker(true);
            if (brokerIsResponding) {
                System.out.println("Broker" + this.hn + " broker " + this.bn + "is responding");
            } else {
                System.err.println("Broker" + this.bn + "is not responding");
                this.bp.disconnect();
                this.bp = null;
            }


        } catch (ConfigManagerProxyLoggedException e) {
            System.err.println("Broker" + this.bn + " CONNECT failed" + e.toString());
        }
        return brokerIsResponding;
    }


    public boolean setStartMode(String exg, String sm) {
        // Set startmode for all flows in given execution group
        //
        // AttributeConstants.STARTMODE_MAINTAINED which means at deploy time or
        // restart the message flow will start based on its isRunEnabled value.
        // AttributeConstants.STARTMODE_MANUAL which means at deploy time or
        // restart the message flow will be stopped.
        // AttributeConstants.STARTMODE_AUTOMATIC
        this.bp.setSynchronous(15000);
        boolean result = false;
        try {
            Enumeration<ExecutionGroupProxy> listEG = this.bp.getExecutionGroups(null);
            while (listEG.hasMoreElements()) {
                ExecutionGroupProxy eg = listEG.nextElement();
                if (eg.getName().equalsIgnoreCase(exg)) {
                    System.out.println("Connected to execution group " + exg );
                    Enumeration<MessageFlowProxy> listMsgFlow = eg.getMessageFlows(null);
                    while (listMsgFlow.hasMoreElements()) {
                        MessageFlowProxy flow = listMsgFlow.nextElement();
                        if (sm.equalsIgnoreCase("maintained")) {
                            flow.setStartMode(AttributeConstants.STARTMODE_MAINTAINED);
                        } else if (sm.equalsIgnoreCase("manual")) {
                            flow.setStartMode(AttributeConstants.STARTMODE_MANUAL);
                        } else if (sm.equalsIgnoreCase("automatic")) {
                            flow.setStartMode(AttributeConstants.STARTMODE_AUTOMATIC);
                        }
                        System.out.println(flow.getName() + " startmode set to " + sm);
                    }
                }
            }
        } catch (Exception e) {
            System.err.println("Error " + e.toString() + " during getExecutionGroup");
        }
        return result;
    }


    public static void main(String[] args) {
        // Variables, initialised
        String action = "";
        String startmode = "";
        String brokername = "";
        String exgname = "";
        String qmgr = "";
        String hostname = "";
        int brokerport = 0;
        
        // Parse the command line arguments
        // We currently only need these, so we do not make parsing of arguments more complex than this
        if (args.length < 4) {
            System.out.println("Error in input. Please provide: Brokername, Executiongroupname, Action, parametervalue");
        } else {
            brokername = args[0];
            exgname = args[1];
            action = args[2];
            startmode = args[3];
            
            // Create brokermanager and connect
            BrokerManager b = new BrokerManager(brokername, hostname, qmgr, brokerport);
            b.connect();
            // Perform given action, currently only
            if (action.equalsIgnoreCase("setstartmode")) {
                b.setStartMode(exgname, startmode);
            } else {
                System.out.println("You gave action: " + action + " Specify valid action: setstartmode.");
            }
        }
    }
}

Hope this works for you. Let me know if you have comments.

// Niek de Greef