Centralized User License Data Management Report |
Vishlashak KAPOOR |
12/26/2014 |
SAP annual license audit is a real pain for managers. SAP is transparent about its license pricing & provides publicly available license guides on http://support.sap.com/:
1. SAP System Measurement Guide 7.0: Complete instructions for how to utilize the SAP system to manage licenses.
2. PROCESS OVERVIEW: SAP SYSTEM MEASUREMENT: Procedure elaborating Activation of price list --> Setup of system data and clients -->Classification of users --> Carry out the measurement and transfer results --> Consolidation of measurement results --> Send LAW results to SAP
3. LAW: A tool overview outlining details of the collection, consolidation and correction of licenses for SAP-developed, on-premises products compared with the current license evaluation rules.
To utilize license contract value & reduce risk of unbudgeted fees, managers should understand following:
Purpose
In order to fully utilize SAP's License Administration Workbench (LAW) tool & validate compliance with license entitlements, managers need to ensure following in their multi-system landscape :
1. Validate all category ID fields: The LAW tool does not determine whether your ID categorization is correct, so if an ID does not have a category in its designated field, LAW will assign the most common user type to that ID (professional users) and report through LAW. The tool then consolidates all instances of categories showing under a single ID and reports the highest cost license in the SAP system through LAW.
2. Counting single users who have multiple IDs: It is important to identify where individuals are using multiple SAP systems, but also using different IDs. For example, David and David1 are logons for the same person in your organization but have raised two different IDs to define themselves in separate packages/engines. Based on this, each ID will count as a unique license versus one license with the highest value. All user IDs should be validated through whatever central system defines your unique employee information. Linking this unique information to the user will allow checking for each employee who has more than one ID. Checks should be made to ensure that policy is being adhered to when creating user IDs in that no employee should need two SAP IDs.
To address above two issues, I have created a custom ABAP based solution: Centralized License Data Management Report such as below:
1. RFC connection to be defined from Central to Child system. Solution Manager can be used as central system as it has already defined RFC connection with all systems
2. Accounting No. or another unique identifier for each logon must be filled. This field or any other field can be used as key identifier for a user such employee id. You can also use Second Forename Field available in User Master’s Address Data tab. This field must be filled for all users in entire SAP landscape to identify users.
3. User Group: This field makes it easier to identify the license type assigned to a group of logons such as number of users in a department, number of developers in a company. This field can be filled in Group Data Tab of User Master. Non-dialog users should have user group other than dialog users.
4. Full Name: Most of the times, Full Name is not aligned in multi-system landscape for a user. This report can easily identify such discrepancies if above 2 key identifiers are filled.
Note: Email ID Field: Sometimes, users doesn’t have email id (in case of external users), in such cases dummy email ids or email ids for person responsible is assigned to user master of such logons as per company policy. Therefore, this field cannot be used as a key field.
For creation of this report ABAP developments need to be done on Central as well as Child systems with following prerequisites.
On Each Child System:
1. Table on Child system (say ZTBLIC_CHILD_DATA) : A table needs to be created with following structure:
2. Function Module on each Child System (say ZFMLIC_RFC_CHILD)
Sample Source Code:
TYPES:
BEGIN OF tyy_adrp,
bname TYPE xubname,
persnumber TYPE ad_persnum,
name TYPE ad_namtext,
email_id TYPE ad_smtpadr,
END OF tyy_adrp,
ty_adrp TYPE STANDARD TABLE OF tyy_adrp.
DATA lt_adrp TYPE ty_adrp.
SELECT a~bname AS bname
a~accnt AS acc_no
a~class AS usergroup
b~lic_type AS lic_type
INTO CORRESPONDING FIELDS OF TABLE gt_table
FROM usr02 AS a
LEFT OUTER JOIN usr06 AS b
ON a~bname = b~bname WHERE USTYP = 'A'.
DELETE gt_table WHERE usergroup = 'TERMINATED' OR usergroup = 'COMMUSER'.
DELETE ADJACENT DUPLICATES FROM gt_table COMPARING bname.
IF gt_table[] IS INITIAL.
ev_status = 'E'.
RETURN.
ENDIF.
SELECT a~bname
b~name_text As name
c~smtp_addr As email_id
INTO CORRESPONDING FIELDS OF TABLE lt_adrp
FROM usr21 AS a
INNER JOIN adrp AS b
ON a~persnumber = b~persnumber
LEFT OUTER JOIN adr6 AS c
ON a~persnumber = c~persnumber.
FIELD-SYMBOLS <table> LIKE LINE OF gt_table.
FIELD-SYMBOLS <adrp> LIKE LINE OF lt_adrp.
SORT gt_table BY bname.
SORT lt_adrp BY bname.
LOOP AT gt_table ASSIGNING <table>.
READ TABLE lt_adrp ASSIGNING <adrp>
WITH KEY bname = <table>-bname
BINARY SEARCH.
IF <adrp> IS ASSIGNED.
<table>-name = <adrp>-name.
<table>-email_id = <adrp>-email_id.
ENDIF.
UNASSIGN <adrp>.
ENDLOOP.
ENDFUNCTION.
On Central system:
1. Centralized License Data Table (say ZTBLIC_CENTRAL_DATA): A table needs to be created with following structure:
2. Table for RFC connections (say ZTBLIC_CONNECT):
3. Central Function Module (say ZFMLIC_RFC_CENTRAL): This RFC calls RFC’s on respective destinations by passing the destination in a variable named ‘pv_rfcdest’ and imports the data in ‘gt_table’ (gt_table is an internal table of table created in Child Systems (1.1)) and a status in ‘ev_status’ to ensure successful fetching of data. ‘ev_status’ gets value ‘E’ in case there is any error in fetching the data.
Sample Code:
CALL FUNCTION 'ZLIC_RFC_CHILD'
DESTINATION pv_rfcdest
IMPORTING
ev_status = ev_status
TABLES
gt_table = gt_table.
ENDFUNCTION.
4. Centralized License Data Management Report (ZRPLIC_CENTRAL_MGMT_DATA): This report runs on Central System to collect data from each child systems to consolidate user master license data on central system:
DATA gt_table TYPE TABLE OF ZTBLIC_CHILD_DATA.
DATA gt_central_data TYPE TABLE OF ZTBLIC_CENTRAL_DATA.
DATA gt_connect TYPE TABLE OF ZTBLIC_CONNECT.
DELETE FROM ZTBLIC_CENTRAL_DATA.
START-OF-SELECTION.
PERFORM get_rfc_con_data.
PERFORM fetch_data.
END-OF-SELECTION.
PERFORM get_central_data.
IF gt_central_data IS INITIAL.
RETURN.
ENDIF.
PERFORM write_header.
PERFORM write_data.
FORM get_rfc_con_data.
SELECT *
INTO TABLE gt_connect
FROM ztblic_connect
WHERE status = 'X'.
ENDFORM.
FORM fetch_data.
FIELD-SYMBOLS <connect> LIKE LINE OF gt_connect.
FIELD-SYMBOLS <table> LIKE LINE OF gt_table.
FIELD-SYMBOLS <central_data> LIKE LINE OF gt_central_data.
DATA wa_central_data LIKE LINE OF gt_central_data.
DATA lv_status TYPE char1.
DATA lv_usergroup TYPE xuclass.
PERFORM get_central_data.
LOOP AT gt_connect ASSIGNING <connect>.
CALL FUNCTION 'ZFMLIC_RFC_CENTRAL'
EXPORTING
pv_rfcdest = <connect>-rfcdest
IMPORTING
ev_status = lv_status
TABLES
gt_table = gt_table.
DELETE gt_table WHERE usergroup = 'TERMINATED' OR usergroup = 'COMMUSER'.
DELETE gt_table WHERE acc_no = '' AND usergroup = '' AND name = ''.
SORT gt_table BY acc_no usergroup name.
DELETE ADJACENT DUPLICATES FROM gt_table COMPARING acc_no usergroup name.
LOOP AT gt_table ASSIGNING <table>.
TRANSLATE <table>-name TO UPPER CASE.
READ TABLE gt_central_data ASSIGNING <central_data>
WITH KEY acc_no = <table>-acc_no
usergroup = <table>-usergroup
name = <table>-name.
IF sy-subrc <> 0.
CLEAR wa_central_data.
SELECT SINGLE *
INTO wa_central_data
FROM ZTBLIC_CENTRAL_DATA
WHERE acc_no = <table>-acc_no
AND name = <table>-name.
IF sy-subrc = 0.
<table>-usergroup = wa_central_data-usergroup.
ENDIF.
ENDIF.
PERFORM fill_data USING <table>
CHANGING wa_central_data.
PERFORM fill_things USING <connect>-rfctytext 'LIC_TYPE'
CHANGING wa_central_data <table>.
PERFORM fill_things USING <connect>-rfctytext 'BNAME'
CHANGING wa_central_data <table>.
MODIFY ZTBLIC_CENTRAL_DATA FROM wa_central_data.
COMMIT WORK.
CLEAR wa_central_data.
UNASSIGN <central_data>.
ENDLOOP.
UNASSIGN <table>.
CLEAR gt_table[].
ENDLOOP.
ENDFORM.
FORM get_central_data.
CLEAR gt_central_data[].
SELECT *
INTO TABLE gt_central_data
FROM ZTBLIC_CENTRAL_DATA.
SORT gt_central_data BY acc_no usergroup name.
ENDFORM.
FORM fill_data USING pw_table TYPE ZTBLIC_CHILD_DATA
CHANGING pw_central_data TYPE ZTBLIC_CENTRAL_DATA.
MOVE pw_table-acc_no TO pw_central_data-acc_no.
MOVE pw_table-name TO pw_central_data-name.
MOVE pw_table-usergroup TO pw_central_data-usergroup.
MOVE pw_table-email_id TO pw_central_data-email_id.
ENDFORM.
FORM fill_things USING pv_rfctext p_fname
CHANGING pw_central_data TYPE ZTBLIC_CENTRAL_DATA
pw_table TYPE ZTBLIC_CHILD_DATA.
FIELD-SYMBOLS <fldname> TYPE any.
FIELD-SYMBOLS <fldname1> TYPE any.
DATA lv_txt TYPE char30.
DATA lv_txt1 TYPE char30.
CONCATENATE pv_rfctext '_' p_fname
INTO lv_txt.
CONDENSE lv_txt.
ASSIGN COMPONENT lv_txt OF STRUCTURE pw_central_data TO <fldname>.
IF <fldname> IS ASSIGNED.
ASSIGN COMPONENT p_fname OF STRUCTURE pw_table TO <fldname1>.
IF <fldname1> IS ASSIGNED.
IF <fldname> <> <fldname1>.
<fldname> = <fldname1>.
ENDIF.
ENDIF.
ENDIF.
ENDFORM.
FORM write_header.
WRITE:/1(12) 'ACC_NO', 13(12) 'USERGROUP', 25(40) 'NAME', 65(35) 'EMAIL_ID',
100(12) 'SYS1_BNAME', 114(12) 'SYS1_LIC_TYPE', 128(12) 'SYS2_BNAME', 142(12) 'SYS2_LIC_TYPE',156(12) 'SYS3_BNAME', 170(12) 'SYS3_LIC_TYPE', 184(12) 'SYS4_BNAME', 198(12) 'SYS4_LIC_TYPE',212(12) 'SYS5_BNAME', 226(12) 'SYS5_LIC_TYPE', 240(12) 'SYS6_BNAME', 254(12) 'SYS6_LIC_TYPE'.
ENDFORM.
FORM write_data.
FIELD-SYMBOLS <central_data> LIKE LINE OF gt_central_data.
LOOP AT gt_central_data ASSIGNING <central_data>.
WRITE:/1(12) <central_data>-acc_no, 13(12) <central_data>-usergroup, 25(40) <central_data>-name, 65(35) <central_data>-email_id, 100(12) <central_data>-sts_bname, 114(12) <central_data>-sts_lic_type,128(12) <central_data>-wel_bname, 142(12) <central_data>-wel_lic_type,156(12) <central_data>-wal_bname, 170(12) <central_data>-wal_lic_type, 184(12) <central_data>-gtl_bname, 198(12) <central_data>-gtl_lic_type,212(12) <central_data>-crl_bname, 226(12) <central_data>-crl_lic_type, 240(12) <central_data>-bwp_bname, 254(12) <central_data>-bwp_lic_type.
ENDLOOP.
ENDFORM.
Post Implementation steps
1. Centralized License Data Management Report (ZRPLIC_CENTRAL_MGMT_DATA) must be run every time you want to have current data in ZTBLIC_CENTRAL_DATA
2. Based on above consolidated report, you can perform manual actions to align following :
3. Above manual assignments can also be triggered automatically by sending data to child systems by means of RFC & changing corresponding user master
4. Automated reporting can be used by scheduling this report at due interval
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
4 | |
4 | |
4 | |
3 | |
3 | |
3 | |
3 | |
3 | |
2 | |
2 |