I had come across the term Workload Capping Groups (WLC) a couple of times before I actually found out what it was about – and exactly how workload capping groups could be taken advantage of. I had noticed a new Workload Capping Group (WLCGRP) attribute on the Change Job (CHGJOB command) at one point. The attribute text was written in all capital letters, revealing that the attribute had been PTF added mid-release.
This discovery didn’t prompt any further research on my part, until my eyes sometime later caught a discussion on midrange.com about the ability to restrict the processor capacity assigned to a DR/HA-product called MIMIX, which is marketed by Vision Solutions. The requirement was to use only a subset of the processor cores available on a multi core server by means of configuring a workload capping group.
The intention of this maneuver was to limit the product to only the number of processor cores needed to run the system mirroring process, rather than having to pay license fees for the processor cores required by the workload introduced by other software products, system components and business applications. Upon opening a ticket with Vision Solutions’ technical support, the customer however received the laconic reply to either purchase a license that covers all cores running on the server, or reduce the (total) number of cores.
The conclusion on this discussion points to a dilemma many vendors apparently face these days, with the current license model based on number of processor cores and CPW. The continuous improvements in the areas of processor cores in particular and server technology in general, drive towards consolidating server workloads to reduce total costs, inevitable increases the number of processor cores per server. While the processor capacity needed to run the individual vendor’s product does not increase, the customer is still in many cases forced to pay excessive license fees, due to the increase in total number of processor cores on the server.
I assume IBM by introducing the workload capping group concept was trying to accommodate this concern, allowing on one hand their customers to take advantage of technological improvements and consolidate workloads onto fewer servers, yet on the other hand still allow vendors to be competitive based on the actual workload footprint required by their product – as originally expressed and intended to be reflected in the common license fee model.
It appears however that many vendors have rather seen this development as an opportunity to increase their license fee profits – possible due to the lack of competition being the result of many product and vendor mergers in recent years. Given the reality that their customers are facing – server consolidation and virtualization is a fact of life – these vendors, sooner rather than later in my humble opinion, need to decide whether they want to become part of the solution, or remain part of the problem.
Thankfully though, IBM for one is taking its own medicine. If you for example have installed the IBM MQ or the DB2 Web Query product, both will actually honor any workload capping configured in terms of licenses required. My company has for many years with great success relied on the IBM MQ product, but it comes with a quite substantial price tag. Our use of the product however only impacts the server performance by a fraction, so using workload capping groups, we have been able to reduce our license costs significantly for this very useful and platform independent application integration product.
The Workload Capping Group Concept and Configuration
In the following section I will now try to explain the workload capping group concept in a little more detail. Basically, workload capping groups are divided into two separate aspects. The primary aspect is the capability to do the actual workload capping, tied to either individual jobs or all jobs running in a specific subsystem. Both options are in turn managed through the association of a Workload Capping Group (WLG). To give you an example – the following command will create a workload capping group named MQPROD:
ADDWLCGRP WLCGRP(MQPROD) PRCLMT(2)
The workload capping group MQPROD will limit the number of processor cores available to 2, for any job or subsystem that it is assigned to. If you want to assign MQPROD to a job directly, you do it by issuing the following command:
CHGJOB … WLCGRP(MQPROD)
When you run the above command, the specified job will be limited to two processor cores. To associate a workload capping group to a subsystem, you use a special data area named QWTWLCGRP in library QSYS for release 7.2 and earlier. To assign workload capping group MQPROD to subsystem QMQM I specify a value pair of two 10 byte names in the data area, subsystem name and workload capping group, respectively:
Value Offset *...+....1....+....2....+....3....+....4....+....5 0 'QMQM MQPROD '
Up to 100 name pairs can be stored in the data area if you create it with the maximum character data area length of 2000 bytes. A PTF has also been issued to add the ability to specify generic subsystem names, in case your subsystem naming convention allows you to take advantage of this improvement.
At release 7.3 and later, a workload capping group attribute has been added directly to the subsystem description, and this attribute is accessible using either the Create Subsystem Description (CRTSBSD) or the Change Subsystem Description (CHGSBSD) command. Anyway, once a workload capping group is assigned to a subsystem, all jobs running in that subsystem will be limited to the number of processor cores specified for that workload group.
You can verify the change the next time the subsystem starts (or immediately following the CHGSBSD command at release 7.3 or later) as message CPI146C, indicating that the subsystem processor access is limited by the workload group will be issued to the subsystem monitor job log:
Subsystem QMQM is using workload capping group MQPROD.
At this point, you have achieved the ability to control the number of processor cores assigned to a given job or subsystem. From a workload management perspective this is very useful in its own right – it allows you to individually prioritize workloads on a job or subsystem basis.
Note, that for auditing purposes the following journal entries are deposited to the system audit journal QAUDJRN:
- Workload groups operations result in a ZC (Object Change) journal entry
- Security audit records for the JS (Job Start/Change) journal entry includes the workload group name
The next part of the equation allows you to also financially benefit from this capacity, as you have the ability to associate the specific product license to the workload capping group. To continue our IBM MQ example, you achieve that by means of the Add WLC Product Entry (ADDWLCPRDE) command:
ADDWLCPRDE WLCGRP(MQPROD) PRDID(5724H72) LICTRM(V7R1M0) FEATURE(5050)
This final configuration step enables the IBM license manager component to include the workload capping group in the assessment of product license limit compliance. This also eliminates the warning messages otherwise sent to message queue QSYSOPR, if a license agreement is exceeded and thereby violated.
For products that are not actually loaded into the product license repository, the above command will mainly serve as an indication that workload capping is in effect for the product, as the license manager is not involved in license validation or usage compliance for such products. You can use the command Work with License Information (WRKLICINF) to verify if the product has been loaded into the product license repository.
Workload Capping Group Commands
I have already mentioned a couple of native CL commands available to manage workload capping groups and their associated product entries, and here’s the complete list of IBM’s offering on WLC CL commands:
ADDWLCGRP Add Workload Capping Group ADDWLCPRDE Add WLC Product Entry CHGWLCGRP Change Workload Capping Group DSPWLCGRP Display Workload Capping Group RMVWLCGRP Remove Workload Capping Group RMVWLCPRDE Remove WLC Product Entry
As you might notice there are no Work with-commands, or specialized commands to manipulate the QWTWLCGRP data area for releases prior to 7.3. But – and how lucky is that 🙂 – IBM does offer a Retrieve Workload Groups Information (QLZRTVWC) API to enable you to programmatically access all information pertaining to workload capping groups and associated WLC product entries. In addition to that IBM has also added a job attribute for Workload Group to the return information for the Retrieve Thread Attribute (QWTRTVTA) API.
Armed with that knowledge, and since I find that Workload Capping Groups are a very interesting and valuable enhancement to an already brilliant operating system, I decided to make up for some of IBMs most obvious omissions in order to make WLC management a little easier. Here’s what I came up with:
DSPJOBWLG Display Job Workload Group WRKWLCGRP Work with Workload Capping Groups WRKWLCPRDE Work with WLC Product Entries ADDWLCSBS Add Workload Capping Subsystem RMVWLCSBS Remove Workload Capping Subsystem WRKWLCSBS Work with Workload Capping Subsystem
To collect the full range of WLC commands in one place I also ended up creating a UIM menu:
CMDWLC Workload Capping Group Commands Menu
But before going further down that road, let me briefly explain the Retrieve Workload Groups Information (QLZRTVWC) API and its parameters.
The Retrieve Workload Groups Information (QLZRTVWC) API
The Retrieve Workload Groups Information (QLZRTVWC) API is not that complicated, but might look a bit confusing at first, due to the fact that it is capable of returning one of two different sets of information based on one of three different request specifications. Here’s the QLZRTVWC API parameter list:
Required Parameter Group:
1 Receiver variable Output Char(*) 2 Length of receiver variable Input Binary(4) 3 Workload groups information format name Input Char(8) 4 Workload groups query value Input Char(*) 5 Workload groups query format name Input Char(8) 6 Error code I/O Char(*)
The information returned by the QLZRTVWC API is defined by parameters 1, 2 and 3: The receiver variable where the API output information is returned, the length of the receiver variable defining the space available, and the format defining the receiver variable content, respectively. As for the latter the following two format names apply, as documented in the API manual:
WLCR0100 Capacity and software product information for a given workload group is retrieved. WLCR0200 The list of all workload groups on the partition which match the query value is retrieved.
The WLCR0100 format returns processor limit and all product entries for a given, single workload group name.
The WLCR0200 format returns a list of one or more workload groups and their associated capacity, depending on whether a single workload group name or the special value *ALL was specified for the workload group name input parameter.
For QLZRTVWC API parameters 4 and 5, all in all three query value formats are available to define the workload groups for which to return information. Parameter 4 specifies the query value(s), and parameter 5 names the format:
WLCQ0100 The workload groups query value is the product information for a given licensed program. WLCQ0200 The workload group query value is a fully qualified product directory path name. WLCQ0300 The workload groups query value is a specific workload group name or is special value *ALL.
To expand a little on the above excerpt from the API manual: The WLCQ0100 query value format allows you to identify a specific workload group based on a specified product ID, license term, feature and product option.
The WLCQ0200 query value format specifies the fully qualified product directory path name – registered with the licensed product when it was loaded – to identify a specific workload group.
The WLCQ0300 query value format specifies either a single workload group name or the special value *ALL to identify either a specific workload group or all workload groups on the system, respectively.
Typically you would use the WLCQ0100 and WLCQ0200 query value formats to retrieve capacity and software product entries in return format WLCR0100, while using query format WLCQ0300 allows you to employ either return format, depending on the actual query value being either a workload group name or the special value *ALL.
The sixth and final API parameter is the standard API error data structure. At the end of this article, I have included links to both IBM documentation of the API error data structure concept, as well as a couple of articles explaining this concept in more practical details.
Turning API documentation into RPG/IV code
Based on the above API documentation here’s how I define the QLZRTVWC API prototype:
**-- Retrieve workload groups information: D RtvWlgInf Pr ExtPgm( 'QLZRTVWC' ) D RcvVar 65535a Const Options( *VarSize ) D RcvVarLen 10i 0 Const D RcvFmtNam 8a Const D QryVal 65535a Const Options( *VarSize ) D QryFmtNam 8a Const D Error 32767a Options( *VarSize )
And here are RPG/IV data structures implementing the two return information formats as well as the three query value formats:
**-- API return information data structures: D WLCR0100 Ds 65535 Qualified D BytRtn 10i 0 D BytAvl 10i 0 D WlcGrp 10a D 2a D WlgPrcCap 10i 0 D OfsWlgLst 10i 0 D NbrWlgLstE 10i 0 D LenWlgLstE 10i 0 ** D WlgProd Ds Qualified Based( pWlgProd ) D PrdId 7a D LicTerm 6a D Feature 4a ** D WLCR0200 Ds 65535 Qualified D BytRtn 10i 0 D BytAvl 10i 0 D OfsWlgLst 10i 0 D NbrWlgLstE 10i 0 D LenWlgLstE 10i 0 ** D WlgLst Ds Qualified Based( pWlgLst ) D WlcGrp 10a D MaxPrcLmt 10i 0 **-- API query value data structures: D WLCQ0100 Ds Qualified D PrdId 7a D LicTerm 6a D Feature 4a D Option 4a ** D WLCQ0200 Ds Qualified D PrdDirNamLen 10i 0 D DirNamCcsId 10i 0 D PrdDirNam 1024a ** D WLCQ0300 Ds Qualified D WlcGrp 10a
In the following code snippets I show an example of how to call the QLZRTVWC API and subsequently process the API output information:
(1) WLCQ0300.WlcGrp = PxWlcGrp; (2) RtvWlgInf( WLCR0200 : %Size( WLCR0200 ) : 'WLCR0200' : WLCQ0300 : 'WLCQ0300' : ERRC0100 ); If ERRC0100.BytAvl > *Zero; ExSr EscApiErr; Else; (3) ExSr PrcWlcLst; EndIf; BegSr PrcWlcLst; (4) pWlgLst = %Addr( WLCR0200 ) + WLCR0200.OfsWlgLst; (5) For Idx = 1 to WLCR0200.NbrWlgLstE; LstEnt.Option = *Zero; (6) LstEnt.WlcGrp = WlgLst.WlcGrp; LstEnt.MaxPrcLmt = WlgLst.MaxPrcLmt; LstEnt.NbrPrdEnt = GetPrdCnt( WlgLst.WlcGrp ); ... (7) If Idx < WLCR0200.NbrWlgLstE; pWlgLst += WLCR0200.LenWlgLstE; EndIf; EndFor;
P GetPrdCnt B D Pi 10i 0 D PxWlcGrp 10a Const /Free (8) WLCQ0300.WlcGrp = PxWlcGrp; (9) RtvWlgInf( WLCR0100 : %Size( WLCR0100 ) : 'WLCR0100' : WLCQ0300 : 'WLCQ0300' : ERRC0100 ); If ERRC0100.BytAvl > *Zero; Return *Zero; Else; Return WLCR0100.NbrWlgLstE; EndIf; /End-Free P GetPrdCnt E
At call-out (1) the Workload group name query value is populated with an input parameter value being either a specific workload group name or the special value *ALL. Both variants are supported by the WLCQ0300 query value format.
At call-out (2) the QLZRTVWC API call is executed, specifying the workload group list return format WLCR0200 as the API output, in order to receive a list of workload groups.
At call-out (3) a subroutine is executed to process the API output in the event of a successful API call.
Call-out 4-7 details the programming logic that enables you to retrieve and process each list entry one-by-one:
(4) Set list entry basing pointer pWlgLst to the address of the beginning of list (first list entry) (5) For each returned list entry (if any) (6) Process list entry data as defined by WlgLst data structure (7) If more entries available add entry length to list entry basing pointer pWlgLst (next list entry)
Call-out 8 and 9 shows an example of calling the QLZRTVWC API with a specific workload group name and specifying the WLCR0100 return format to obtain the number of product entries registered for the workload group. In this example I do not actually retrieve each product entry also returned by return format WLCR0100, but that could easily be done by implementing the same logic as shown in call-outs 4-7.
New Workload Capping Group CL commands
In the following section, I briefly introduce each of the new Workload Capping Group commands that I mentioned at the beginning of this article. For more details please refer to the commands’ and display panels’ online help text.
The Display Job Workload Group (DSPJOBWLG) command displays in the form of a completion message the workload capping group associated with the job specified.
DSPJOBWLG Display Job Workload Group
To check if the MQ server job AMQALMPX is running in a workload capping group, run the following command for the specific job:
DSPJOBWLG JOB(319406/QMQM/AMQALMPX)
The completion message will tell you:
Job 319406/QMQM/AMQALMPX workload capping group is MQPROD.
The Work with Workload Capping Groups (WRKWLCGRP) command allows you to work with one or all workload capping groups defined on your system. The indented list below shows all commands accessible from the work with-display, either as a list option (LO) or command function key (CF).
WRKWLCGRP Work with Workload Capping Groups ADDWLCGRP Add Workload Capping Group (CF) CHGWLCGRP Change Workload Capping Group (LO) DSPWLCGRP Display Workload Capping Group (LO) RMVWLCGRP Remove Workload Capping Group (LO) WRKWLCPRDE Work with WLC Product Entries (CF) WRKWLCSBS Work with Workload Capping Subsystem (CF) 6.1+ WRKSBSD Work with Subsystem Description (CF) 7.3+
The Work with WLC Product Entries (WRKWLCPRDE) command allows you to work with all WLC product entries defined for the specified workload capping group. The indented list below shows all commands accessible from the work with-display, either as a list option (LO) or command function key (CF).
WRKWLCPRDE Work with WLC Product Entries ADDWLCPRDE Add WLC Product Entry (CF) RMVWLCPRDE Remove WLC Product Entry (LO) WRKLICINF Work with License Information (LO) WRKWLCSBS Work with Workload Capping Subsystem (CF) 6.1+ WRKSBSD Work with Subsystem Description (CF) 7.3+
The Work with WLC Subsystem (WRKWLCSBS) command allows you to work with the association between workload capping groups and subsystemsat release 7.2 and earlier. Note that as of release 7.3 and later workload groups are
associated directly to subsystems using the Create Subsystem Description (CRTSBSD) or Change Subsystem Description (CHGSBSD) commands, at which point the WLCSBS commands and the QWTWLCGRP data area become obsolete.
The WRKWLCSBS, ADDWLCSBS and RMVWLCSBS commands use APIs to retrieve and update the data area QWTWLCGRP in library QSYS. The indented list below shows all commands accessible from the work with-display, either as a list option (LO) or command function key (CF).
WRKWLCSBS Work with Workload Capping Subsystem ADDWLCSBS Add Workload Capping Subsystem (CF) RMVWLCSBS Remove Workload Capping Subsystem (LO) WRKWLCGRP Work with Workload Capping Groups (LO) WRKSBSD Work with Subsystem Descriptions (LO)
As mentioned earlier I have also created a menu named CMDWLC to make it easier to find and access all the commands related to workload capping groups – have a look
CMDWLC Workload Capping Group Commands System: WYNDHAMW Select one of the following: Workload Capping Group commands 10. Add Workload Capping Group ADDWLCGRP 11. Change Workload Capping Group CHGWLCGRP 12. Display Workload Capping Group DSPWLCGRP 13. Remove Workload Capping Group RMVWLCGRP 14. Work with Workload Capping Groups WRKWLCGRP Workload Capping Product Entry commands 20. Add WLC Product Entry ADDWLCPRDE 21. Remove WLC Product Entry RMVWLCPRDE 22. Work with WLC Product Entries WRKWLCPRDE Workload Capping Job commands 30. Display Job Workload Group DSPJOBWLG Workload Capping Subsystem commands 40. Add Workload Capping Subsystem ADDWLCSBS 41. Remove Workload Capping Subsystem RMVWLCSBS 42. Work with Workload Capping Subsystem WRKWLCSBS Service options 90. Sign off SIGNOFF Bottom Selection or command ===> F3=Exit F4=Prompt F9=Retrieve F12=Cancel
The following source members are included in the zip-file containing all the Workload Capping Group CL commands:
CBX301U UIM Workload Capping Group Commands Menu CBX301 RPGLE Display Job Workload Group CBX301H PNLGRP Display Job Workload Group - Help CBX301X CMD Display Job Workload Group CBX301M CLP Display Job Workload Group - Build command CBX3021 RPGLE Work with Workload Capping Groups - CCP CBX3021C RPGLE Work with Workload Capping Groups - UIM Cond Pgm CBX3021E RPGLE Work with Workload Capping Groups - UIM Exit Pgm CBX3021H PNLGRP Work with Workload Capping Groups - Help CBX3021P PNLGRP Work with Workload Capping Groups - Panel Group CBX3021V RPGLE Work with Workload Capping Groups - VCP CBX3021X CMD Work with Workload Capping Groups CBX3021M CLP Work with Workload Capping Groups - Build command CBX3022 RPGLE Work with WLC Product Entries - CCP CBX3022C RPGLE Work with WLC Product Entries - UIM Cond Program CBX3022E RPGLE Work with WLC Product Entries - UIM Exit Program CBX3022H PNLGRP Work with WLC Product Entries - Help CBX3022P PNLGRP Work with WLC Product Entries - Panel Group CBX3022V RPGLE Work with WLC Product Entries - VCP CBX3022X CMD Work with WLC Product Entries CBX3022M CLP Work with WLC Product Entries - Build command CBX3031 RPGLE Add Workload Capping Subsystem - CPP CBX3031H PNLGRP Add Workload Capping Subsystem - Help CBX3031V RPGLE Add Workload Capping Subsystem - VCP CBX3031X CMD Add Workload Capping Subsystem CBX3031M CLP Add Workload Capping Subsystem - Build Command CBX3032 RPGLE Remove Workload Capping Subsystem - CPP CBX3032H PNLGRP Remove Workload Capping Subsystem - Help CBX3032V RPGLE Remove Workload Capping Subsystem - VCP CBX3032X CMD Remove Workload Capping Subsystem CBX3033 RPGLE Work with Workload Capping Subsystem - CPP CBX3033E RPGLE Work with Workload Capping Subsystem - UIM Exit Pgm CBX3033H PNLGRP Work with Workload Capping Subsystem - Help CBX3033P PNLGRP Work with Workload Capping Subsystem - Panel Group CBX3033V RPGLE Work with Workload Capping Subsystem - VCP CBX3033X CMD Work with Workload Capping Subsystem
To create all the above objects, compile and run the CBX301M, CBX3021M, CBX3022M and CBX3031M CL programs, following the instructions in each of the four source headers.
You’ll also find compilation instructions in the respective source headers of the individual sources.
Download the WlcGrpSrc zip file containing the source code.
Download the WlcGrpDoc zip file containing documentation.
More information
Workload capping groups were introduced by PTFs for release 6.1 and 7.1 and have been part of the base OS since release 7.2. I have included links below to more articles discussing the WLC concept and setup quite thoroughly – in case you’d like to dive deeper into the topic.
Setting up workload groups – 7.2 and earlier
Setting up workload groups – 7.3 and later
Manage Workloads Better with IBM i 7.1
Workload Group Configuration with IBM i 7.3
Workload Groups and Performance Considerations
Manage Work Better with Better Work Management Version 7.1 TR8
IBM i Work Management – Best Kept Secrets
Software Pricing With IBM i Virtualization
Limiting WebSphere MQ Licensing and Processing Capacity with Workload Groups
Workload groups V7R3 – the QSYS/QWTWLCGRP data area is obsolete
Leverage Workload Groups (presentation)
Workload capping – reducing license costs on IBMi
Sub-capacity (Virtualization) License Counting Rules
Steve Will: IBM i “Workload Groups” Qualify for Virtualization Technologies’ Subcapacity Pricing
Retrieve Workload Groups Information (QLZRTVWC) API
Retrieve Thread Attribute (QWTRTVTA) API
Know Your Errors: Use the API Error Parameter in RPG (by Craig Rutledge)
APIs by Example: Using the ERRC0200 Data Structure
API error code parameter format
OSP-Workload Capping function V6R1
OSP-Workload Capping function V7R1
OSP QWTWLCGRP Allow use of wildcard (*) in subsystem name V7R1 and V7R2