HTTPD server – what is configured?

This is one of a series of blog posts on HTTPD.

You can run an Apache command, or display in the web browser, the active configuration with variables substituted, and If statements processed.

The server can dump configuration at startup. The best option was

-t -DDUMP_CONFIG

which displays the configuration with symbols substituted and after If processing. You can use this as part of your startup, or standalone, or as a web page. The web page displays more information.

/usr/lpp/ihs*/bin/apachectl -f /u/mqweb3/conf/httpd.conf -t -DDUMP_CONFIG > aa

This displays lots of good information. Below is an illustrative subset of what is available

  • Server settings
    • Server build:Jun 10 2020 16:22:51
    • Host Name/port:10.1.1.2:8831
    • Server Root: /u/mqweb3
  • Information about each module, for example ‘Module Name:mod_rewrite.c
    • Module directives, a list of all the actions supported eg
      • ‘RewriteRule – an URL-applied regexp-pattern and a substitution URL
    • Current configuration for that module, with If statements processed, and variables substituted
      • In file: /u/mqweb3/conf/80.conf
  • Information about each module, for example ‘Module Name:mod_ibm_ssl.c
    • Module directives, a list of all the actions supported eg
      • ‘SSLEnable – SSL is enabled for this server
    • Current configuration for that module, with If statements processed, and variables substituted. Line 10 was ‘Keyfile /saf ${pkiRing}’
      • In file: /u/mqweb3/conf/pkissl.conf   
      • 1:   SSLEnable  
      • 10:   Keyfile /saf START1/MQRING
      • etc

To run it as a web page, the configuration is below.

LoadModule info_module modules/mod_info.so
<Location /server-info>
SetHandler server-info
AuthType Basic
AuthBasicProvider saf
SAFRunAs PKISERV
</Location>

and the URL was

http://10.1.1.2:8831/server-info

Extending the HTTPD server on z/OS

The HTTPD web server is the Apache web server ported to run on z/OS. It runs in Unix Services, and behaves like a proper z/OS program, for example it can use z/OS userids and keyrings.

The configuration is easy, it is text driven (rather than XML), can imbed other configuration files, and can substitute variables.

I found the Apache documentation was as good, but the z/OS documentation was not very good. I prefer baby steps, taking the smallest system and adding functions, rather than configure everything and be disappointed when fails to work.

This post follows on Getting started with httpd server on z/OS and describes how to configure your first web page. Other posts on HTTPD server

Baby step number 2 – extending it

My HTTPD instance directory is /u/mqweb3/ .

I like to keep any changes I make to a configuration file, in a different file, and include this file in the original file. This way, if the original file changes, I just have to add the include statement rather than “diff” the my config file with the new config file. I also like to logically group changes, so my TLS configuration are in the tls.conf file, my definitions for port 8800 are in a file 8800.conf.

In the /u/mqweb3/conf is the httpd.conf file.

I edited this, and inserted

Include conf/colin.conf

at the bottom of the file.

I created /u/mqweb3/conf/colin.conf with

LogLevel debug

ErrorLog “/u/mqweb3/conf/error.log”

LoadModule rewrite_module modules/mod_rewrite.so
LoadModule authnz_saf_module modules/mod_authnz_saf.so
LoadModule ibm_ssl_module modules/mod_ibm_ssl.so

<Location /server-status>
AuthName “Colins Page”
AuthType Basic
AuthBasicProvider saf
Require valid-user
AuthSAFExpiration “EXPIRED! oldpw/newpw/newpw”
AuthSAFReEnter “Enter new password one more time”
CharsetSourceEnc IBM-1047
CharsetDefault ISO8859-1
SetHandler server-status
</Location>

The LoadModules provide the SAF support for logon

Shutdown the server (use P HTTPPCP6) – do not just cancel it – as there are several address spaces running for the server.

Restart the server (or do S httpcp,action=’restart’ ), fix any problems and try logging on to

http://10.1.1.2:8300/server-status

This should prompt for userid and password, and display the status of the server. The web browsers remember the userid and password, so if you want to reuse the page it will not prompt you for the userid and password. To change to a different userid and password you will need to restart the browser.

While playing with pages and logging on, I found the curl request

curl -u colin:password -i http://10.1.1.2:8830/xxxx.html

a good way of checking the page out, and logging on each time, as the password is not saved.

If you get

BPXP015I HFS PROGRAM /usr/lpp/ihsa_zos/bin/httpd IS NOT MARKED PROGRAM
CONTROLLED.
BPXP014I ENVIRONMENT MUST BE CONTROLLED FOR SERVER (BPX.SERVER)
PROCESSING.

You need to use the command

extattr +p /usr/lpp/ihsa_zos/bin/httpd

Create your a virtual host (container)

The HTTPD server can support multiple ports, and treat them as isolated environments. These are known as Virtual Hosts.

In my colin.conf I add

Include conf/vhost8831.conf

I created a file vhost8831.conf

Listen 8831
<VirtualHost *.8831>

<Location /xxxx.html>

#ServerName Colins.com
AuthName colinvh
AuthType Basic
AuthBasicProvider saf
#Require valid-user

Require saf-user COLIN JOE

# CharsetSourceEnc IBM-1047
# CharsetDefault ISO8859-1
# SetHandler server-status
</Location>

<Directory “/u/mweb3/htdocs”>
Require saf-user COLIN JOE
# Require saf-group SYS1

DocumentRoot “/u/mqweb3/htdocs”
#DirectoryIndex index_ihs.html

</Directory>
ErrorLog “/u/mqweb3/conf/zz.log”
ErrorLogFormat “[%t] [%l] %F: %E: [client %a] %M”

</VirtualHost>

Only userids COLIN and JOE are authorised to this (http://10.1.1.2:8831/xxxx.html service).

Restart the server

If you are authorised to use this service you will get

The requested URL was not found on this server.

Because this has not been set up yet.

The DocumentRoot works with the URL to identify a file.

The URL

http://10.1.1.2:8831/xxxx.html

will look for xxxx.html in DocumentRoot so it looks for file /u/mqweb3/htdocs/xxxx.html .

Baby steps 3 – create a page.

Create a file /u/mqweb3/htdocs/xxxx.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4//EN"> 
<html lang="en"> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> 
<title>Colin's page</title> 
</head> 
<body width="778" height="556" background="images/ihs/background.gif" resize="no" scroll="no"> 
<h1>Colins header</h1> 
<p>Colin</p> 
</body> 
</html> 

Retry the web browser page.

When this is displayed you get

Where

  • The title maps to the page heading
  • The background image comes from the body

Getting started with HTTPD server on z/OS

Apache web server

The HTTPD web server is the Apache web server ported to run on z/OS. It runs in Unix Services, and behaves like a proper z/OS program, for example it can use z/OS userids and keyrings. It starts in seconds!

The configuration is easy, it is text driven (rather than XML), can imbed other configuration files, and can substitute variables.

I found the Apache documentation was very good, but the z/OS documentation was not as good. I prefer baby steps, taking the smallest system and adding functions, rather than configure everything and be disappointed when it fails to work first time.

Other posts

Getting started

I used the IBM HTTP Server – Powered by Apache Version 9 PDF document. The text below is an addition to the IBM documentation, not a replacement. I’m trying to fill the holes in the documentation.

The product comes pre-installed. Mine was in /usr/lpp/ihsa_zos/bin/httpd

You need a directory for your HTTPD instance.

You need the userid to run the server.

ADDUSER WEB2 NAME(‘COLWEB’) NOPASSWORD –
OMVS(AUTOUID ASSIZE(256000000) THREADS(512) –
Program(‘/bin/sh’) home(‘/u/mqweb3/’))

CONNECT IBMUSER GROUP(COLWEB )
CONNECT WEB2 GROUP(COLWEB )

When you set up the userid, it is better to use OMVS(AUTOUID .. than to give a specific numeric id, similarly use OMVS(AUTOGID… for the group.

The userid needs OMVS, PROGRAM= /bin/sh, and a home directory.

Setup the system with environment file

The /usr/lpp/ihsa_zos/bin/envvars file allows you to set up an image wide environment file. You can rename /usr/lpp/ihsa_zos/bin/envvars-std to /usr/lpp/ihsa_zos/bin/envvars

I set up this file with

#/!bin/sh
IHS=/usr/lpp/ihsa_zos
LIBPATH=$IHS/lib:$IHS/modules:$IHS
PATH=$IHS/bin
_EDC_ADD_ERRNO2=1
_BPX_SHAREAS=NO
_BPX_BATCH_SPAWN=YES
GSK_SSL_HW_DETECT_MESSAGE=1
LC_ALL=En_US.IBM-1047

Create the instance

Follow the instructions in the documentation.

cd /usr/lpp/ihsa*
umask 022
bin/install_ihs /u/mqweb3 8300

Note down the port you specified (8300) as you will need it when you try to connect to the server.

The documentation says switch to the instance directory and issue apachectl -v. This failed for me because the path and libpath were not set up. I set up the envvars file (above) and it worked.

/usr/lpp/ihs*/bin/apachectl -v

When I ran it, it produced

test: /usr/lpp/ihsa_zos/bin/apachectl 49: FSUM7351 not found
[: /usr/lpp/ihsa_zos/bin/apachectl 74: FSUM7351 not found
[: /usr/lpp/ihsa_zos/bin/apachectl 87: FSUM7351 not found
[: /usr/lpp/ihsa_zos/bin/apachectl 92: FSUM7351 not found
Server version: IBM_HTTP_Server/9.0.5.5 (Unix) (SMP/E, 64-bit)
Server built: Jun 10 2020 16:22:51

The FSUM7351 messages are OK. For example the apachectl script has

if test -f /usr/lpp/ihsa_zos/bin/envvars; then
. /usr/lpp/ihsa_zos/bin/envvars
fi

This checks the file exists before invoking it.

The apachectl takes the following options, so you can display the configuration, or modify the start.

Options:
-D name : define a name for use in directives
-d directory : specify an initial ServerRoot
-f file : specify an alternate ServerConfigFile
-C “directive” : process directive before reading config files
-c “directive” : process directive after reading config files
-e level : show startup errors of level (see LogLevel)
-E file : log startup errors to file
-v : show version number
-V : show compile settings
-h : list available command line options (this page)
-l : list compiled in modules
-L : list available configuration directives
-t -D DUMP_VHOSTS : show parsed vhost settings
-t -D DUMP_RUN_CFG : show parsed run settings
-S : a synonym for -t -D DUMP_VHOSTS -D DUMP_RUN_CFG
-t -D DUMP_MODULES : show all loaded modules
-M : a synonym for -t -D DUMP_MODULES
-t -D DUMP_SSL_CONFIG: show parsed SSL vhost configurations
-t -D DUMP_SSL_CIPHERS: show all known SSL ciphers
-t -D DUMP_UNIFIED_CONFIG: show configuration with all includes merged
-t -D DUMP_INCLUDES: show all included configuration files
-t : run syntax check for config files
-T : start without DocumentRoot(s) check
-X : debug mode (only one worker, do not detach)

-t -DDUMP_CONFIG is very useful as it shows what you have configured after any <If…> and after variable substitution. I use this as a standalone command to see what’s configured.

Note:I had problems using //STDENV in the started task, so I had to use the envvars file.

Create the JCL procedure

See the documentation.

//HTTPCP PROC ACTION='start',
// DIR='/usr/lpp/ihsa_zos',
// CONF='/u/mqweb3/conf/httpd.conf'
//*---------------------------------------------------------
//IHS EXEC PGM=BPXBATCH,REGION=0M,
// PARM='SH &DIR/bin/apachectl -k &ACTION -f &CONF -DNO_DETACH ',
// MEMLIMIT=1236M
//STDOUT DD SYSOUT=H
//STDERR DD SYSOUT=H
// PEND

BPXBATCH needs REGION=0M, and at least MEMLIMIT=1236M

Define the STARTED task to RACF.

RDEFINE STARTED HTTPCP* STDATA(USER(WEBSRV)
SETROPTS RACLIST(STARTED ) REFRESH

Start the started task

S HTTPCP

You cannot just type P HTTPCP. In the syslog I had

CRIHS0001I IHS S0W1 is active. 83951827 0.0.0.0:8300 unspecified:-1.
Use jobname HTTPCP6 for console commands.

This means you have to issue P HTTPCP6 to stop it.

You can also use

s HTTPCP,action=’start’
s HTTPCP,action=’stop’

To start and stop the server.
Note: When you run these commands it checks the syntax of the configuration file, and if there is a problem, then the command is not executed. I kept wondering why my HTTPD instance was not shutting down; it was because I had a configuration error, and so the stop request was being ignored.

If it starts (there are no helpful messages saying success) try connecting a web browser to it in my case

http://10.1.1.2:8300

This gave me page with links to IBM sites. If you get here – you have done the first baby step. You cannot do much with the server.

Don’t try this at home, PKI certificates.

I was trying to generate z/OS certificates which I could use to check out certificate revocation. I can do it in Linux – no problem. Getting it to work on z/OS was the challenge and I don’t think it can be done.

Meanwhile, back at the ranch (‘at home’), running z/OS on the zPDT environment on Linux, I found the PKI Server environment does not support PKI for key generation on zPDT or ZD&T, because zPDT does not support ICSF TKDS.

The longer story of why it will not work.

The RACF command RACDCERT GENCERT creates a basic certificate which is suitable for many uses. It does not support the extensions, such as specifying a URI for OCSP checking of the certificate.
The PKI product has these capabilities, and together with ICSF it can store the keys in the ICSF data sets. This product seems complex to set up (two web servers), and a GUI interface instead of a command interface.

There is an API, the RACF callable services R_PKISERV, which allows you to issue API requests to administer certificate.
You can use a SAF interface and pass in a public certificate, certificate request, or use PKI to generate a full certificate with all of the optional fields etc, and do full life cycle management with it.

I could not get this to work, and when I started the PKI SERVER, it reported

IKYP040I PKI SERVICES DOES NOT HAVE KEY GENERATION CAPABILITY

This in turn pointed me to ICSF and the TKDS (Token Key Data Set), not being set up – it needed a master key. You enter this master key on a TKE (Trusted Key Entry) workstation which sits inside the z hardware. I was running on zPDT, and following the trail, the zPDT documentation said PKCS#11 (Token Key Data Set) is not available with zPDT. This means it looks like I cannot create certificates which support OCSP on my z/OS.

Using Cobol and DB2 in ADCD and ZPDT

There were questions in news group about using COBOL and DB2 under ADCD on ZPDT.

Here is an answer. It provides a proc (which you can put into USER.*.PROCLIB, and JCL to use it.

ADCD provides a proc in ADCD.Z24*.PROCLIB(DSNHICOB)

//
//* *
//* DSNCOB63 - COMPILE AND LINKEDIT A DB2 COBOL PROGRAM USING *
//* COBOL 6.3.0 P200901 *
//* *
//* NOTES: *
//* 1. THE COBOL 'SQL' COMPILER OPTION IS USED IN PLACE OF *
//* PRECOMPILE STEP. *
//* 2. THE DEFAULT DB2 VERSION IS 12. *
//* *
//* *
//
//* *
//* CHANGE LOG *
//* ---------- *
//* *
//
//* *
//* DATE/AUTHOR DESCRIPTION *
//* ----------- --------------------------------------------------- *
//*   -----------  --------------------------------------------------- * 
//*   2021/04/01   ORIGINAL FOR Z/OS 2.4 AND COBOL 6.30.               * 
//*   J. ABELL     THE SQL OPTION AND ITS SUBOPTIONS SUCH              * 
//*                AS ATTACH(CAF) AND ATTACH(RRSAF) NORMALLY USED WITH * 
//*                THE DB2 PRECOMPILER.                                * 
//*                                                                    * 
//*                NOTE: DBRMLIB IS NOW PART OF THE COMPILE STEP.      * 
//*                      OBSOLETE PARMS RENOVED.                       * 
//*                                                                    * 
//********************************************************************** 
//DSNCOB63  PROC COBOPTS=, 
//        DBRMLIB=, 
//        DBRMMOD=, 
//        DSNHLQ=DSNC10,              DEFAULT - DB2 V12 
//        LKPARM=, 
//        LOADLIB=, 
//        LOADMOD=, 
//        SQLOPTS=, 
//        SRCLIB=, 
//        SRCMOD= 
//* 
//*  ****                                                      **** 
//*  ****                                                      ****
//*  ****   DO NOT CHANGE THE DOUBLE QUOTES CODED IN THE PARM  ****
//*  ****                                                      ****
//* 
//COB      EXEC PGM=IGYCRCTL,REGION=0M, 
//      PARM='SQL("&SQLOPTS"),BUFSIZE(16K),&COBOPTS' 
//* 
//STEPLIB  DD DISP=SHR,DSN=&DSNHLQ..SDSNLOAD 
//SYSIN    DD DISP=SHR,DSN=&SRCLIB(&SRCMOD) 
//DBRMLIB  DD DISP=SHR,DSN=&DBRMLIB(&DBRMMOD) 
//SYSPRINT DD SYSOUT=* 
//SYSLIN   DD DSN=&&LOADSET,DISP=(MOD,PASS),UNIT=WRK, 
//            DCB=BLKSIZE=0, 
//            SPACE=(CYL,(10,10)) 
//SYSUT1   DD UNIT=VIO,SPACE=(CYL,(1,1)) 
//SYSUT2   DD UNIT=VIO,SPACE=(CYL,(1,1)) 
//SYSUT3   DD UNIT=VIO,SPACE=(CYL,(1,1)) 
//SYSUT4   DD UNIT=VIO,SPACE=(CYL,(1,1)) 
//SYSUT5   DD UNIT=VIO,SPACE=(CYL,(1,1)) 
//SYSUT6   DD UNIT=VIO,SPACE=(CYL,(1,1)) 
//SYSUT7   DD UNIT=VIO,SPACE=(CYL,(1,1)) 
//SYSUT8   DD UNIT=VIO,SPACE=(CYL,(1,1)) 
//SYSUT9   DD UNIT=VIO,SPACE=(CYL,(1,1)) 
//SYSUT10  DD UNIT=VIO,SPACE=(CYL,(1,1)) 
//SYSUT11  DD UNIT=VIO,SPACE=(CYL,(1,1)) 
//SYSUT12  DD UNIT=VIO,SPACE=(CYL,(1,1)) 
//SYSUT13  DD UNIT=VIO,SPACE=(CYL,(1,1)) 
//SYSUT14  DD UNIT=VIO,SPACE=(CYL,(1,1)) 
//SYSUT15  DD UNIT=VIO,SPACE=(CYL,(1,1)) 
//SYSMDECK DD UNIT=VIO,SPACE=(CYL,(1,1)) 
//* 
//*  LINKEDIT IF THE PRECOMPILE AND COMPILE 
//*      RETURN CODES ARE 4 OR LESS 
//* 
//LKED     EXEC PGM=IEWL,REGION=0M,PARM='XREF,&LKPARM', 
//             COND=(4,LT,COB) 
//* 
//SYSLIB   DD DISP=SHR,DSN=CEE.SCEELKED 
//         DD DISP=SHR,DSN=CEE.SCEELKEX 
//         DD DISP=SHR,DSN=&DSNHLQ..SDSNLOAD 
//SYSLIN   DD DSN=&&LOADSET,DISP=(OLD,DELETE) 
//         DD DDNAME=SYSIN 
//SYSLMOD  DD DSN=&LOADLIB(&LOADMOD), 
//            DISP=SHR 
//SYSPRINT DD SYSOUT=* 
//SYSUDUMP DD SYSOUT=* 
//SYSUT1   DD SPACE=(1024,(50,50)),UNIT=VIO 

Some sample JCL to use it

/*JOBPARM  S=S0W1 
//* 
//CMPTEST EXEC DSNCOB63, 
//        COBOPTS='OPTIMIZE(2),CODEPAGE(500)', 
//        DBRMLIB=TEST.DBCG.DBRM, 
//        DBRMMOD=TESTDB2, 
//        DSNHLQ=DSNC10, 
//        SQLOPTS='ATTACH(CAF)', 
//        SRCLIB=TEST.SOURCE, 
//        SRCMOD=TESTDB2, 
//        LKPARM='EDIT=NO', 
//        LOADLIB=TEST.LIBRARY, 
//        LOADMOD=TESTDB2 
//* 
//LKED.SYSLIB DD 
//            DD DISP=SHR,DSN=TEST.LIBRARY
//            DD DISP=SHR,DSN=DSNC10.SDSNLOAD 
//SYSIN DD * 
program goes here
/* 
//  

Using DB2 and ISPF with ADCD

Someone was having problems accessing the DB2 panels from ISPF with their ZPDT system.

Here are some of their notes

  • Using IBMUSER as my TSO/E login.
  • Use DBSPROCC as my TSO proc.
  • After login, issued D A,L and noticed DB2 tasks are running.
  • Navigate to and select 15 – DB2 V12
  • Select 1 – SPUFI Error message: DSNE110E DSN NOT VALID SUBSYSTEM ID, COMMAND TERMINATED
  • Issue D A,L and noticed the DB tasks have DBCG as a prefix.
  • Specified DBCG as the SSID or DB2 Name in DB2 Default panel.
  • Now able to invoke SPUFI and perform DB2 development tasks.
  • Was also able to invoke option 16 – DB2ADM and perform certain tasks

z/OSMF autostart: how to stop it, and how to use it (or not)

I upgraded my z/OS from ADCD Z24A to ADCD Z24C. This has updates to lots of the software, including z/OSMF. This includes some performance fixes, so z/OSMF start up is much quicker and uses much less CPU. However the newer level of ADCD Z24C now starts z/OSMF automatically. It took a few attempts to stop this.

When z/OS starts, it takes configuration parameters from IEASYSxx. You can see which IEASYSxx you are using with the DISPLAY IPLINFO operator command. You can see which IZU parameter you are using with

d iplinfo,izu
IEE255I SYSTEM PARAMETER ‘IZU’: AS

With the DISPLAY PARMLIB command, you get the parmlib concatenation

D PARMLIB
IEE251I 08.34.02 PARMLIB DISPLAY
PARMLIB DATA SETS SPECIFIED AT IPL
ENTRY FLAGS VOLUME DATA SET
    1   S   C4CFG1 USER.Z24C.PARMLIB
    2   S   C4CFG1 FEU.Z24C.PARMLIB
    3   S   C4SYS1 ADCD.Z24C.PARMLIB
    4   S   C4RES1 SYS1.PARMLIB

Where the ‘S’ means it came from a LOADxx parameter. A ‘D’ means Default SYS1.PARMLIB.

Look in each data set in turn for the IZUPRMxx member (xx=AS in my case).

Contents of the IZUPRMxx member

Within the member is SERVER_PROC(‘IZUSVR1’) This tells the IPL code which server to start.

Within the member is line with AUTOSTART(…). The value can be

  • CONNECT – I think of this as AUTOSTART(NO)
  • LOCAL – I think of this as AUTOSTART(MAYBE)

See here for a discussion.

It is a bit more complex than YES|NO. It has capability to allow one of a group of z/OSMF servers to start.

If you have AUTOSTART(CONNECT) specify AUTOSTART_GROUP(NONE).

If you have AUTOSTART(LOCAL) and AUTOSTART_GROUP(COLIN) for more than one IZU servers. Then at IPL it checks to see if a Z/OSM server with AUTOSTART(LOCAL) and AUTOSTART_GROUP(COLIN) is already active. If so – the instance does not start.

The documentation says it checks by having an ENQ on the file system with the AUTOSTART_GROUP value. This implies you need the z/OSMF data directories to be on the same ZFS file system.

Should I use autostart?

This is a tough question. I cannot test it because I only have one LPAR, but I have some thoughts.

Single LPAR, single Z/OSMF instance

This is relatively easy. You can start z/OSMF automatically though commands at IPL, or you can use the z/OSMF IZUPRMxx method, or start it manually.

Multiple LPARs in a sysplex, single Z/OSMF instance.

If you have a shared file system, you can start the z/OSMF instance on any LPAR. If you start the instance more than once, it detects this and will only allow one instance to be active.

You have to plan to be able to starting an instance on different systems. For example the IP address and port for the base system will be different. You’ll need to set up a TCP/IP environment to support this. See HA Liberty web server – introduction to using VIPA to provide high availability connectivity and the z/OSMF documentation

Multiple LPARs in a sysplex, multiple z/OSMF instances.

This is where the autostart may be useful. The first LPAR to be started will start the z/OSMF instance. When other LPARs start, they detect that another z/OSMF in the group is active, and will not start the z/OSMF instance. As with starting a single z/OSMF instance in a multi LPAR environment, you need to plan the connectivity. See HA Liberty web server – introduction to using VIPA to provide high availability connectivity and the z/OSMF documentation.

I struggle to see why starting just one instance is useful. For availability I would want more than once instances to be running at the same time. With only one instance. If you stop it, and restart on a different LPAR, you have a period of a minute or more where you do not have z/OSMF running.

I would have a group_token, so each instance can register the “group name” is active. An application can then ask to be notified when a member of the group becomes active, using standard z/OS services.

Stateless z/OSMF instances

If you are using z/OSMF facilities which save state, the autostart of just one server will not work. For example if you are using any workflow facilities, state is saved in the file system. You need to logon to the same instance to be able to continue working on the workflow. If today you run on LPARA’s z/OSMF and tomorrow you run on LPARB’s z/OSMF you cannot do your workflow.

You need to plan your z/OSMF usage and plan to have “stateless” z/OSMF servers which can use AUTOSTART; and workflow servers – for which you have only one instance (which can be moved around) and do not use autostart.

Can I define a disk Read Only to z/OS?

As part of migrating z/OS to a new service level, I wanted to mount old volumes Read-Only, so they were not updated when the new level was used. (For example z/OS updates the dataset last access time in the VTOC). I was running on zPDT, or z/OS on top of Linux, so all of the hardware is emulated. On a real machine you may be able to configure the storage subsystem.

I had four options

  • Make the disk on Linux read only – this worked, and was easy.
  • Copy the disks of interest so I had write access to a copy. This worked, and was easy.
  • Use the zPDT command awsmount 0ac5 -m /mnt/zimages/zOS/A4USR1 –readonly . This worked and was easy.
  • Update the Hardware Configuration Definition (HCD) to make a disk read only. I could define it, but not activate it because this read-only support is for PPRC mirrored disks. I could not vary the address online.

This blog post describes how I changed the HCD to add a read only disk.

This was a journey going into areas I had not been in before (creating IODFs).

The Hardware Configuration Definition(HCD) defines the configuration of the hardware. In day’s gone by the systems programmer would have to do a “sysgen” and used macros to define devices, then assemble it and use it. Nowadays you can maintain the configuration using ISPF panels.

What does the HCD do, and what is an OSCONFIG?

The documentation is not very clear about HCD. There are tiny clues, where it mentions making disks read-only, in OSCONFIG, but does not explain how to display and use the OSCONFIG. Now I know, it is easy.

  • You define each device, or group of similar devices in the HCD.
  • For each OS Configuration (OSCONFIG) you define each operating system image, and which devices belong in which OSCONFIG. See, … simple!

For example you define your configuration, including production and test devices, in the HCD. You then configure

  • A test system with only the test volumes
  • A production system with only the production volumes
  • The sysprog’s system with both test and production devices. From this machine, the systems programmer can create production or test configurations.

Getting started with HCD

The HCD is panel driven from ISPF.

You have to work with a copy of the IODF, and the system will generate a copy for you (suffixed with .WORK). I created a copy, made changes, then created a new IODF.

What is currently being used?

From the main HCD panel

  • 2. Activate or process configuration data
    • 5. View active configuration

Create a copy

From main menu use

  • 6. Maintain I/O definition files
    • 2. Copy I/O definition file

and follow the prompts.

On the home page it has the name of the current IODF being worked on, update it if necessary.

Display the OSCONFIG

Use the ISPF configuration panels for HCD:

  • 1. Define, modify, or view configuration data
    • 1. Operating system configurations

It then lists the available OSCONFIGs. Use / to select one, then select

  • 7. Work with attached devices

This lists the devices. You can scroll or use “L AF0” to locate the devices.

Put / in front to display the options. At the right it gives the command, so

  • 8. Delete . . . . . . . . . . . . . . (d)

I can either use /, and 8, or use ‘d’ (instead of the /) to delete an entry.

PF3 to return to “Define, Modify, or View Configuration Data”.

Add new devices

Use

  • 5. I/O devices

This lists the devices. Use F11 to add

  • Device number 0af0
  • Number of devices 16
  • Device type 3390

Press enter.

It displays a list of OS Configs, select one.

  • option 1 select

You are prompted to configure the devices

  • OFFLINE No Device considered online or offline at IPL
  • DYNAMIC Yes Device supports dynamic configuration
  • LOCANY No UCB can reside in 31 bit storage
  • WLMPAV Yes Device supports work load manager
  • READ-ONLY Sec Restrict access to read requests (SEC or NO)
  • SHARED No Device shared with other systems
  • SHAREDUP No Shared when system physically partitioned

Press enter. To make this read-only I specified Shared=no and read-only=sec. (Sec is for secondary device. The read write copy of the mirrored is is the primary device).

Use PF3 to return.

Activate the configuration

From the HCD home page,

  • 2. Activate or process configuration data
    • 1. Build production I/O definition file

Create production eg “‘SYS1.IODF88”

then

  • 6. Activate or verify configuration dynamically

This displays

  • Currently active IODF . : SYS1.IODF99
  • IODF to be activated . : SYS1.IODF88
  • Test only . . . . . . . . Yes (Yes or No)

Use Test only = YES to validate it, then repeat with Test only = NO. This will make it live.

For me, the SYS1.IODFxx dataset, was created on the wrong volume. It has to be on the same volume as the SYS1.IPLPARM and other IPL information for a successful IPL.

Move the SYS1.IODF to the IPL parm volume.

Change your IPL loadxx member in SYS1.IPLPARM to point to the new IODF.

Although I had specified A4SYS1 as the volume for the SYS1.IODF88, SMS allocation routines allocated it on a different volume. I had to move it to the correct volume. See here.

Once I had IPLed with the new IODF

The command

D U,,,,0AF0,1 gave

UNIT TYPE STATUS   VOLSER     VOLSTATE      SS   
0AF0 3390 F-NRD-RO                /RSDNT     0   

Which says there is no device mounted, but it has been defined as RO.

I varied it online and I got

V 0AF0,ONLINE
IEE103I UNIT 0AF0 NOT BROUGHT ONLINE
IEE763I NAME= IECDINIT CODE= 000000000110088F
IEA434I DEVICE ONLINE IS NOT ALLOWED, R/O SEC PPRC STATE NOT VALID
IEE764I END OF IEE103I RELATED MESSAGES

Which means it was unable to mount my disk as it was not part of a PPRC mirrored DASD environment. I had defined a disk as Read Only, but was not able to use it.

Moving a system dataset was a challenge

As part of configuring the IO on my z/OS system using HCD, I needed to create a dataset on the IPL volume. This was a challenge, but I got there, the long way.

When I used the HCD to create a SYS1.IODFxx dataset, I specified the DASD volume I wanted to put it on. Unfortunately, because SMS got in the way and overrode my the volume I had specified, and picked a different one!

I could have changed the SMS definitions to say do not play with dataset beginning with SYS1, but I thought it would be easy to move it. After a while I got the following JCL to work

//IBMIODF JOB   ACCOUNTING INFORMATION,REGION=NNNNK 
//STEP1    EXEC  PGM=ADRDSSU,REGION=0M 
//SYSPRINT DD    SYSOUT=A 
//DASD1    DD    UNIT=3390,VOL=(PRIVATE,SER=USER00),DISP=OLD 
//DASD2    DD    UNIT=3390,VOL=(PRIVATE,SER=A4SYS1),DISP=OLD 
//SYSIN    DD    * 
 COPY DATASET(INCLUDE('SYS1.IODF88.CLUSTER')) SPHERE - 
  PROCESS(SYS1)  - 
   BYPASSACS('SYS1.IODF88.CLUSTER') - 
   NULLSTORCLAS - 
  LOGINDDNAME(DASD1) OUTDDNAME(DASD2) DELETE CATALOG 
/* 

Notes:

  1. I had to specify the name with its cluster name. Without this I got message ADR383W code 05.
  2. Although I had specified the target volid of A4SYS1, it was moved to A4USR1! I had to specify
    1. PROCESS(SYS1) I think it gives an extra layer of security. For example many people can have access to DFDSS to move data sets, around, but only a few people would want to move SYS1.** data sets around.
    2. BYPASSACS(…) to bypass SMS and not use ACS routines to allocate the volume. I had to specify the dataset name, using “*” did not move it to the required volume.
    3. NULLSTORCLASS to tell SMS not to use a storage class.

How do I see what is in my z/OS HCD?

I’m running ADCD z/OS on zD&T, and wanted to see what was in my HCD (Hardware Configuration Definition). There are some ISPF panels, which allow you to print things, but they had some “required” parameters which I didn’t have and didn’t need.

This post shows the JCL I used, and gives a quick overview of the output

The JCL to create a batch report. This uses program CBDMGHCP. This parameters are described here. Note you can have the output created in XML format.

//IBMHCD JOB MSGCLASS=H
//GCREP EXEC PGM=CBDMGHCP,
// PARM='REPORT,CSMEN,,,,,00'
//HCDIODFS DD DSN=SYS1.IODF99,DISP=SHR
//HCDRPT DD SYSOUT=,
// DCB=(RECFM=FBA,LRECL=200,BLKSIZE=6400)
//HCDMLOG DD SYSOUT=,
// DCB=(RECFM=FBA,LRECL=200,BLKSIZE=6400)

The output data sets require the DCB information. If this is not provided you get messages like

IEC141I 013-34,IGG0199G,IBMHCD,GCREP,HCDRPT.

The output of the report in HCDRPT

At the top is

TIME: 16:46 DATE: 2021-07-12
IODF NAME: SYS1.IODF99
IODF TYPE: Production
IODF VERSION: 5
IODF VOLUME: A4SYS1
DESCRIPTION: m3000 with SCSI 08-0B only

It lists the sections

PROCESSOR SUMMARY REPORT                         A
PARTITION REPORT                                 B
IOCDS REPORT                                     C
CHANNEL PATH SUMMARY REPORT                      D
CONTROL UNIT SUMMARY REPORT                      G
DEVICE SUMMARY REPORT                            I
SWITCH SUMMARY REPORT                            K 
SWITCH DETAIL  REPORT                            L
SWITCH CONFIGURATION SUMMARY REPORT              M
SWITCH CONFIGURATION DETAIL REPORT               N
OPERATING SYSTEM SUMMARY REPORT                  O
OS DEVICE REPORT                                 P
OS DEVICE DETAIL REPORT                          Q
EDT REPORT  (MVS ONLY)                           R
OS CONSOLE REPORT                                S

Component reports heading

Following the list of sections are the data. Each section has a header like

CONTROL UNIT SUMMARY REPORT TIME:... DATE:...  PAGE G- 1

Where the title (CONTROL UNIT SUMMARY REPORT) and the character following the PAGE match the list of sections, which has “CONTROL UNIT SUMMARY REPORT G”.

To go to a section use Find ‘PAGE G’ .

CONTROL UNIT SUMMARY REPORT

   CONTROL UNIT        
 NUMBER  TYPE-MODEL    
 _____________________ 
 -  -  -  -  -  -  -  -
  0700   3174 
 -  -  -  -  -  -  -  -
  0A80   3990 
  0A81   3990 
  0A82   3990 
  0A83   3990 

Where 0700 is a console, and 0a80 is disk on an emulated 3990.

DEVICE SUMMARY REPORT

--- DEVICE ---    DEVICE                                                
 NUMBER,RANGE    TYPE-MODEL    ATTACHING CONTROL UNITS         
______________  _____________  |____|___
   0700         3270-X          0700 
   0A80         3390            0A80

OPERATING SYSTEM SUMMARY REPORT

 OPERATING                                     
 SYSTEM ID   TYPE        GEN    DESCRIPTION    
 _________   ________    ___    _______________
 OS390       MVS                ADCD ZOS IODF 

MVS DEVICE REPORT

DEV#,RANGE  TYPE-MODEL ... 
__________ __________  ...

0700,64    3270-X....
0A80,112   3390  ....          

Followed by columns of data with headings ( given in the report)

KEY            KEY DESCRIPTION 
---            --------------- 
DEV#,RANGE  -  DEVICE NUMBER, COUNT OF DEVICES (DECIMAL) 
TYPE-MODEL  -  DEVICE TYPE AND MODEL 
SS          -  SUBCHANNEL SET ID 
BASE        -  BASE DEVICE NUMBER FOR MULTIPLE EXPOSURE DEVICES 
UCB-TYPE    -  UCB TYPE BYTES 
ERP-NAME    -  ERROR RECOVERY PROGRAM 
DDT-NAME    -  DEVICE DESCRIPTOR TABLE 
MLT-NAME    -  MODULE LIST TABLE 
OPT         -  OPTIONAL MLT INDICATOR 
UIM-NAME    -  UNIT INFORMATION MODULE SUPPORTING THE DEVICE 
ATI         -  ATTENTION TABLE INDEX (UCBATI) 
AL          -  ALTERNATE CONTROL UNIT (UCBALTCU) 
SH          -  SHARED UP OPTION (UCBSHRUP) 
SW          -  DEVICE CAN BE SWAPPED BY DDR (UCBSWAPF) 
MX          -  DEVICE HAS MULTIPLE EXPOSURES (UCBMTPXP) 
MI          -  MIH PROCESSING SHOULD BE BYPASSED (UCBMIHPB) 
O           -  MLT IS OPTIONAL 
Y           -  DEVICE SUPPORTS THIS FEATURE 
BLANK       -  DEVICE DOES NOT SUPPORT THIS FEATURE 

The UIM is a an object with parameters defined for the device type. They are defined here. The options are defined here. For example a 3270 can have a selector pen!. a 3800 printer can have a burster.

There is a summary of devices.

        TOTAL NUMBER OF DEVICES BY CLASS 
        -------------------------------- 
CLASS NAME             CLASS TYPE    DEVICE COUNT 
----------             ----------    ------------ 
TAPE                       80               64 
COMMUNICATION DEVICES      40                0 
C-T-C                      41               24 
DASD                       20             1001 
GRAPHICS                   10               95 
UNIT RECORD                08                3 
CHARACTER READERS          04                0 
TOTAL NUMBER OF I/O DEVICES DEFINED BY THIS I/O CONFIGURATION     1187 

MVS DEVICE DETAIL REPORT

NUMBER,RANGE TYPE   SS PARAMETER                        FEATURE
____________ ______ __ _______________________________ _______
   0700,64   3270-X  0 OFFLINE=NO                       SELPEN,... 
   0A80,112  3390    0 OFFLINE=NO,DYNAMIC=YES,LOCANY=NO SHARED 

E D T REPORT

The Eligible Device Table Report has

                                AFFINITY  ALLOCATION   
 NAME TYPE  VIO  TOKEN  PREF    INDEX     DEVICE TYPE  DEVICE NUMBER LIST 
 _________  ___  _____  ______  ________  ___________  ___________________
 GENERIC                   280    FFFF     3010200F    ... 0A80- 0AFF ...
 GENERIC                  3800    FFFF     12001009    0700- 073F   

N I P Console REPORT

The Nucleus IP l Console Report has

 DEVICE #        TYPE-MODEL 
 ________       _____________ 
 0700           3270-X 
 0701           3270-X