IBM Blog 2017 September

Converting a queue manager to a QSG

In the UK we have an expression you wait a long time for a bus, and then two buses come along together. I don’t remember the last time we were asked to help split a queue manager into a Queue Sharing Group, but we have had two requests in the last month – so just like buses.

Ive been blogging topics relevant to this, but here is a high level plan that we came up with – with help from Gwydion.

Scenario

Today we have queue manger a MQPA today, and want to create a QSG QSGA, containing MQPA and a new queue manager MQPB.

MQPA has

  1. Application 1 using queues APP1.IN and APP1.out
  2. Application 2 using queues APP2.IN and APP2.out
  3. Sender Channel TO.MQPZ using XMITQ MQPZ
  4. Receiver channel TO.MQPA

Plan your QSG environment

  1. How much space do you need for shared messages
  2. Review which applications you want to make shared
  3. include your normal and exception volumes, e.g. usually queue depth is 10 message. If we have to hold 4 hours of messages we need to support 1 million messages
  4. Consider SMDS or SCM offload for peak volumes
  5. You may need to talk to the networking people about setting up VIPA channels
  6. You will have to work with the Db2 people to create some DB2 tables
  7. You will have to work with the Z/OS sysprogs to create structures
  8. For a system with a high throughput of persistent messages in the CF, you may want have a queue manager dedicated to backing up the structures.

Create your new queue managers

Set up queue manager MQPB. You may want to use a different name CSQZPARMS, especially as you will be changing it to turn on QSG using QSGDATA.

Set up the QSG

These steps will set up MQPB for QSG

Follow the steps below in the existing MQ documentation

  1. Tasks 9 Select and set up your coupling facility offload storage environment If you get this wrong it is not difficult to change
  2. Task 10, Set up the coupling facility If you get this wrong it is not difficult to change
  3. Task 16, Add the IBM MQ entries to the Db2 data-sharing group If you get this wrong it is not easy to change
  4. Task 17 set csq6sysp QSGDATA=(…) and recompile your ZPARMs module – you may want to use a different name CSQZPARMS
  5. Restart your queue manager
  6. Define application structures and set up SMDS
  7. Set up RACF profiles
    1. Colin’s rexx see blog post MQRACF.rexx to extract the defintions from RACFThis is no longer available
  8. Create objects in QSG or second queue manager
    1. CSQUTIL MAKEDEF for user objects – queue, process etc
    2. Create application objects in new QSG with QSGDISP(GROUP) or QSGDISP(SHARED), or private to each queue manager
      1. Either MQPB or QSGA
    3. CSQUTIL MAKEDEF for chlauth
      1. Run on MQPB to create chlauth rules that mirror those on MQPA
  9. Define QMGR ALIAS so messages from external queue managers can be put on either QM
    1. On MQPA defined QR(MQPB) TARGQM(MQPA)
    2. On MQPB defined QR(MQPA) TARGQM(MQPA)
  10. Add existing QM to QSG
    1. Shut down cleanly
    2. Run CSQ5PQSG using the ADD QMGR function.
    3. Change zParms
      1. task 17 setcsq6sysp QSGDATA=(…) and recompile your module
      2. Restart your queue manager

Migrate work from MQPA to QSG

  1. Install applications on the LPAR where MQPB runs
  2. Make the XMITQ Shared. You can either use CSQUTIL MAKEDEF and copy the queue definition or use
    1. Define ql(TEMP) like(MQPZ)
    2. Delete ql(MQPZ)
    3. Define QL(MQPZ) like(TEMP) QSGDISP(SHARED) CFSTRUCT(STRUCT1)
  3. Review application APP1 for queues used, processes etc
    1. Make APP1.IN a shared queue
    2. Make APP1.OUT a shared queue (or a remote queue definition defined as QSGDISP(SHARED))
    3. Messages will still flow over the existing channels on MQPA

Make channels shared

You will need to create shared channels into and out of the QSG.
See my bog post Connecting channels to and from a Queue Sharing Group

  1. Shared input channel
    1. Set up VIPA address:port or hardware router
    2. DEFINE CHL(..) QSGDISP(GROUP)
      1. This sends a define command to all the queue managers
    3. START LSTR PORT(XX) INDISP(GROUP) on each QMGR
    4. Reset chl(…) this is needed because the Syncq is different.
  2. Shared output channels
    1. Make XMITQ shared
    2. DEFINE CHL(…) QSGDISP(GROUP) DEFCDISP(SHARED) …
      1. Sends a DEFINE command to all queue managers
    3. Reset chl(…) this is needed because the Syncq is different.
    4. START CHL(..)
  3. Change channels coming into the QSG. They may need to use a shared channel.

Operational tasks

There is more work you need to do!

  1. Automate any CSQ5* messages
  2. Arrange backup of pagesets for the new queue managers
  3. Arrange for backup of CF structures periodically (5 minutes is not unusual)
  4. Check your DASD storage pools, as you now have more queue managers archiving into the same space.
  5. Backup your objects – regularly
  6. Backup your DB2 tables – regularly
  7. etc

Connecting channels to and from a Queue Sharing Group

Overview

Using a queue sharing group you can set up your channels so you can connect to any queue manager in the QSG in the same way that you connect to a single queue manager. This provides a Single System Image view of the QSG. If one queue manager is shut down, the channel can be started to/from another queue manager in the QSG and so provide much higher availability.

You can set up a channel so the sender is

  • a shared outbound channel
  • a private outbound channel

and the receiver end is

  • shared inbound channel
  • private inbound channel

You can set up a channel that is private to private, shared to private, private to shared, or shared to shared.

Where do you put channel definitions?

You typically define a shared channel with QSGDISP(GROUP). This means the definition is available on all queue managers in the QSG.
You typically define a private channel with QSGDISP(QMGR). This means the definition is only available on a single queue manager.
You could define a shared channel as QSGDISP(QMGR) but you need to do this on all queue managers in the QSG, and there is a risk that you change the definition on one queue manager, but not the other queue managers.
You could define a private channel with QSGDISP(GROUP). Only one queue manager would use it, so this is not good practice. It does not provide Single System Image capability.

QSGDISP doesn’t have any effect on making a channel shared or private, it’s just an administrative convenience

Qmgr to Qmgr channels

What is a shared output channel

A shared output channel behaves as if it were one channel from the whole QSG. The channel can be started, stopped and restarted from any queue manager in the QSG, but can only be active on a single queue manager in the QSG at any given time.

It needs

  1. An XMITQ defined with QSGDISP(SHARED)
  2. A channel definitions with QSGDISP(GROUP) – best practice, not strictly needed
  3. Started with CHLDISP(SHARED) either explicitly, or by setting the default disposition (DEFCDISP) on the channel definition. If the CHLDISP(PRIVATE) is used or defaulted, the channel will not start. This is so you do not accidentally start a shared channel as a private channel.

The status of the channel is stored in a DB2 table when the channel starts, and the shared queue SYSTEM.QSG.CHANNEL.SYNCQ is used to hold recovery data. This means that the channel can restart after a failure on another queue manager in the QSG. The shared output channel can be running on QMA, fail, and be restarted on QMB, resolve in flight messages, and continue running.

A private output channel can only run on the queue manager where it was configured.

It needs

  1. A local XMITQ. The channel uses the local queue SYSTEM.CHANNEL.SYNC.QUEUE to hold recovery data. If the channel fails on QMA, starting the channel on QMB will not resolve any in flight messages, as a different XMITQ will be used, and a different SYSTEM.CHANNEL.SYNC.QUEUE
  2. A channel definitions with QSGDISP(QMGR) – is best practice, but a channel with a name like (TO.MYBANK) rather than a specific queue manager name could be defined as QSGDISP(GROUP).

How can I tell what my if my channel is a shared channel?

If you use DIS CHS(…) CHLDISP for a sender channel and it gives
1. CHLDISP(SHARED) this is a shared outbound channel
2. CHLDISP(PRIVATE) this is a private outbound channel

What is a shared input channel?

A channel coming into a QSG needs to be able to connect to one of the LPARs where the queue managers are running. This can be done using

  1. A hardware router which can be configured to route any TCP traffic for IPAddr:port to any LPAR where there is a listener on the port.
  2. A Virtual IP address(VIPA) within TCP on z/OS, so traffic for a VIPA can be routed to any configured LPARs. An example of this is a Sysplex Distributor
  3. Ttwo queue managers in the same LPAR listening on the same IP address if the port is defined as SHAREDPORT
  4. APPC Generic LU

MQ uses the term Generic Port to refer to the socket or LU made available on the LPAR in the above list.

The CHLDISP parameter does not affect the disposition of an inbound channel. Instead, the INDISP disposition of the listener that accepts the connection determines the disposition of the channel.

A request to start a channel through a port with a INDISP(GROUP) listener will have CHLDISP(SHARED). This will then use the shared queue SYSTEM.QSG.CHANNEL.SYNCQ to store information about in-flight work. DB2 tables track the current status of a channel, are updated when the channel starts.
A request to start a channel through a port with a INDISP(QMGR) listener will have CHLDISP(PRIVATE). This will use the local queue SYSTEM.CHANNEL.SYNC.QUEUE to store information about in-flight work.
For message channels (channels between two queue managers), an INDISP(GROUP) listener should be used to allow the channel to restart after a failure on another queue manager in the QSG.

MQI Client channels

An MQI channel is a channels between a client and a queue manager. These channels should use a INDISP(QMGR) listener to avoid the unnecessary overheads of connections to an INDISP(GROUP) listener. This overhead includes updating DB2 tables.

The channel will still be able to restart on any member of the QSG.

To have a channel start on any queue manager in the QSG you need

  1. The channel definition needs to be on that queue manager. The best practice is to define the channel with QSGDISP(GROUP).
  2. You need a listener defined with INDISP(QMGR).
  3. To allow the client to use one connection to come into any queue manager, you need to use the Generic Port
  1. A hardware router which can be configured to route any TCP traffic for IPAddr:port to any LPAR where there is a listener on the port.
  2. A Virtual IP address(VIPA) within TCP on z/OS, so traffic for a VIPA can be routed to any configured LPARs. An example of this is a Sysplex Distributor
  3. Ttwo queue managers in the same LPAR listening on the same IP address if the port is defined as SHAREDPORT
  4. APPC Generic LU

There are other connectivity options for clients for example

  1. Multiple connections in the CONNAME
  2. The client channel definition table (CCDT)

Changing your log size

Sep 19 2017

Ive seen a couple of questions recently about people wanting to change their active log size, because they were either too small, (causing very frequent checkpoints) – or too large – they were bigger than 3GB for V710 or 4GB for V8 and later.

Steps

Check your archive logs

Check your archive log parameters. You can use the cpf DIS ARCHIVE or the CSQY121I message at start up.
For example
CSQY121I MQPA UNIT=3390, UNIT2=, ALCUNIT=TRK,PRIQTY=500, SECQTY=100, BLKSIZE=24576
Check:

  1. The primary size PRIQTY is the same size as the maximum active log being used.
  2. BLKSIZE is a good value for your disks. An efficient value gives you 2 records per track. An inefficient value can waste up to half a track.

You can set these by using the SET ARCHIVE command, or csq6arvp and regenerate the zparms module.

Check the archive log name with your storage management team.
CSQY122I MQPA ARCPFX1=SCENDATA.D1, ARCPFX2=SCENDATA.D2, TSTAMP=YES
The archive logs should be allocated in a storage pool with enough space to hold at least a days worth of archive logs. You do not want to run out of space for archives.

Add new active logs

You will need to restart the queue manager to delete old logs.

Define your new logs and format them, you can dynamically add the logs using the DEFINE LOG command. You can issue this command at any time.

For example add logs log11, log12, log13

It is good practice to have enough active logs for a whole day’s worth of data – in case archiving has a space problem.

Deleting the old active log data sets.

Issue the cpf ARCHIVE LOG command to switch logs until one of your new logs is the current active log
Shut down the queue manager cleanly.

Print out the BSDS ( in case you need to add the logs back in).
It is good practice to backup your pagesets – in case you need to recover a page set. If you need to use a previous backup – you will have problems because the logs will not be available in the BSDS.

Use CSQJU003 to delete the old logs see here.

Delete logs1, log2, logs3.

Restart the queue manager.

You can now add new logs log1,log2 and log3 ( and delete log10, log11, and log 12).

Modified on Sep 19 2017 by ColinPaice

MQRACF.rexx to extract the defintions from RACF
Sep 18 2017

I was with a customer who wanted to replicate their queue manager. The could export the object definitions with CSQUTIL MAKEDEFS, but they asked about the RACF definitions.
I have created MQRACF.REXX
Which extracts RACF definitions in a format that can be edited and run as a batch job.

This allow you to create definitions for another queue manager, or a QSG, or you can create mixed case definitions.
The output is like

*DEL RDELETE MQCMDS   MQPC.ALTER.AUTHINFO               
*DEF RDEFINE MQCMDS   MQPC.ALTER.AUTHINFO -             
*DEF                  OWNER(PAICE1) -                   
*DEF                  UACC(NONE ) -                     
*DEF                  RAUDIT(FAILURES(READ) ) -         
*DEF                  WARNING(TRUE )                    
*PER PERMIT  ID(SCENU)    ACCESS(ALTER)                 
*PER PERMIT  ID(PAICE)    ACCESS(ALTER)                 
*PER PERMIT  ID(SCENR)    ACCESS(ALTER)                 
*DEL RDELETE MQCMDS   MQPC.ALTER.BUFFPOOL               

....

From the output you can use ISPF edit commands such as

X ALL

F *DEL ALL

DEL ALL X

RESET

C *DEL ”

which will give you just RDLETE commands.

Sample JCL

//PAICEAL  JOB 1,MSGCLASS=A
//STEP1 EXEC PGM=IRXJCL,PARM='MQRACF MQCMDS MQPC.DIS MQPC.DIS'
//* NEXT DD IS THE DATA SET EQUIVALENT TO TERMINAL OUTPUT
//SYSTSPRT DD SYSOUT=*
//SYSEXEC DD DISP=SHR,DSN=PAICE.CLIST.LIB

The first parameter is the RACF class, in this case MQCMDS

The second parameter is for the start prefix. In this example any value > MQPC.DIS

The third parameter is the end prefix. Any profile name <= the end prefix will be displayed.

In this case it will display all profiles for MQPC beginning with DIS

Another example is

PARM='MQRACF MQCMDS MQPA'

which will display any profile > MQPA, so will include MQPB, NEW1 etc

These blog posts are from when I worked at IBM and are copyright © IBM 2017.