IBM i Global

IBM i 

A space for professionals working with IBM’s integrated OS for Power systems to exchange ideas, ask questions, and share expertise on topics like RPG and COBOL development, application modernization, open source integration, system administration, and business continuity.


#Power


#IBMi
#Power
 View Only
  • 1.  python iToolKit - How to correctly call an API (QWDRSBSD) from python

    Posted Mon October 07, 2024 09:43 AM

    Greetings team,

    Ref
    https://community.ibm.com/community/user/power/discussion/python-itoolkit-how-to-retrieve-a-return-value-from-a-cl-program

    Background
    I'm currently looking into developing some Ansible code to monitor systems on my IBMi LPAR(s).  I checked the ibm.power_ibmi collection modules [https://galaxy.ansible.com/ui/repo/published/ibm/power_ibmi/] however wasn't able to find a module|task|role which returned the status of a subsystem (for example).

    So, with that said I started looking at iToolKit [https://pypi.org/project/itoolkit/] (and the XMLSERVICE) and came up with the below.  My question is why am I getting the *BADPARSE error message as the API is actually returning the correct status of QINTER namely that being "*ACTIVE"?

    import sys
    from itoolkit import *
    from itoolkit.transport import DirectTransport
    
    # Create an instance of the iToolkit
    itool = iToolKit()
    
    transport = DirectTransport()
    
    itool.add(
        iPgm('qwdrsbsd','QWDRSBSD')
        .addParm(iDS('QWDRSBSD_t',{'len':'sbslen'})
        .addData(iData('sbsRet','10i0',''))
        .addData(iData('sbsAvl','10i0',''))
        .addData(iData('sbsNam','10a',''))
        .addData(iData('sbsLib','10a',''))
        .addData(iData('sbsSts','10a',''))
        .addData(iData('sbsDevNam','10a',''))
        .addData(iData('sbsDevLib','10a',''))
        .addData(iData('sbsSecLng','10a',''))
        .addData(iData('sbsMaxAct','10i0',''))
        .addData(iData('sbsCurAct','10i0',''))
        .addData(iData('sbsStrPoolCnt','10i0','',{'enddo':'mycnt'}))
        .addData(iDS('sbs_pool',{'dim':'999','dou':'mycnt'})
            .addData(iData('sbspoolNam','10a',''))
            .addData(iData('sbspoolRes1','6a',''))
            .addData(iData('sbspoolSiz','10i0',''))
            .addData(iData('sbspoolActLvl','10i0',''))
            )
        )
        .addParm(iData('rcvlen','10i0','',{'setlen':'sbslen'}))
        .addParm(iData('fmtNam','8a','SBSI0100'))
        .addParm(iData('qualSbsNam','20a','QINTER    *LIBL     '))
        .addParm(iDS('ERRC0100_t',{'len':'errlen'})
            .addData(iData('errRet','10i0',''))
            .addData(iData('errAvl','10i0',''))
            .addData(iData('errExp','7a','',{'setlen':'errlen'}))
            .addData(iData('errRsv','1a',''))
        )
    )
    
    # Debug
    print('XML_IN:')
    print(itool.xml_in())
    print('')
    
    itool.call(transport)
    
    # Retrieve the results
    result = itool.dict_out('qwdrsbsd')  # Get the output buffer
    
    # Debug
    print('Result:')
    print(result)
    print('')
    
    # Debug
    print('XML_OUT:')
    print(itool.xml_out())
    
    sys.exit(0)

    "print(itool.xml_in())" generates the below.

    <xmlservice><pgm name="QWDRSBSD" error="fast" var="qwdrsbsd"><parm io="both" var="p1"><ds len="sbslen" var="QWDRSBSD_t"><data type="10i0" var="sbsRet"/><data type="10i0" var="sbsAvl"/><data type="10a" var="sbsNam"/><data type="10a" var="sbsLib"/><data type="10a" var="sbsSts"/><data type="10a" var="sbsDevNam"/><data type="10a" var="sbsDevLib"/><data type="10a" var="sbsSecLng"/><data type="10i0" var="sbsMaxAct"/><data type="10i0" var="sbsCurAct"/><data type="10i0" enddo="mycnt" var="sbsStrPoolCnt"/><ds dim="999" dou="mycnt" var="sbs_pool"><data type="10a" var="sbspoolNam"/><data type="6a" var="sbspoolRes1"/><data type="10i0" var="sbspoolSiz"/><data type="10i0" var="sbspoolActLvl"/></ds></ds></parm><parm io="both" var="p2"><data type="10i0" setlen="sbslen" var="rcvlen"/></parm><parm io="both" var="p3"><data type="8a" var="fmtNam"><![CDATA[SBSI0100]]></data></parm><parm io="both" var="p4"><data type="20a" var="qualSbsNam"><![CDATA[QINTER    *LIBL     ]]></data></parm><parm io="both" var="p5"><ds len="errlen" var="ERRC0100_t"><data type="10i0" var="errRet"/><data type="10i0" var="errAvl"/><data type="7a" setlen="errlen" var="errExp"/><data type="1a" var="errRsv"/></ds></parm></pgm></xmlservice>

    "print(result)" generates the below.

    {'error': {'error': '*BADPARSE', 'error1': ' ?xml version=\'1.0\'? xmlservice pgm name="QWDRSBSD" error="fast" var="qwdrsbsd" parm io="both" var="p1" ds len="sbslen" var="QWDRSBSD_t" data type="10i0" var="sbsRet" 136 /data data type="10i0" var="sbsAvl" 136 /data data type="10a" var="sbsNam" QINTER /data data type="10a" var="sbsLib" QSYS /data data type="10a" var="sbsSts" *ACTIVE /data data type="10a" var="sbsDevNam" QDSIGNON /data data type="10a" var="sbsDevLib" QSYS /data data type="10a" var="sbsSecLng" *NONE /data data type="10i0" var="sbsMaxAct" -1 /data data type="10i0" var="sbsCurAct" 0 /data data type="10i0" enddo="mycnt" var="sbsStrPoolCnt" 2 /data ds dim="999" dou="mycnt" var="sbs_pool" data type="10a" var="sbspoolNam" ', 'qwdrsbsd': {...}}}

    "print(itool.xml_out())" generates the below.

    <error>*BADPARSE</error>
    <error><![CDATA[ ?xml version='1.0'? xmlservice pgm name="QWDRSBSD" error="fast" var="qwdrsbsd" parm io="both" var="p1" ds len="sbslen" var="QWDRSBSD_t" data type="10i0" var="sbsRet" 136 /data data type="10i0" var="sbsAvl" 136 /data data type="10a" var="sbsNam" QINTER /data data type="10a" var="sbsLib" QSYS /data data type="10a" var="sbsSts" *ACTIVE /data data type="10a" var="sbsDevNam" QDSIGNON /data data type="10a" var="sbsDevLib" QSYS /data data type="10a" var="sbsSecLng" *NONE /data data type="10i0" var="sbsMaxAct" -1 /data data type="10i0" var="sbsCurAct" 0 /data data type="10i0" enddo="mycnt" var="sbsStrPoolCnt" 2 /data ds dim="999" dou="mycnt" var="sbs_pool" data type="10a" var="sbspoolNam" ]]></error>
    </xmlservice>
    {'error': '*BADPARSE', 'error1': ' ?xml version=\'1.0\'? xmlservice pgm name="QWDRSBSD" error="fast" var="qwdrsbsd" parm io="both" var="p1" ds len="sbslen" var="QWDRSBSD_t" data type="10i0" var="sbsRet" 136 /data data type="10i0" var="sbsAvl" 136 /data data type="10a" var="sbsNam" QINTER /data data type="10a" var="sbsLib" QSYS /data data type="10a" var="sbsSts" *ACTIVE /data data type="10a" var="sbsDevNam" QDSIGNON /data data type="10a" var="sbsDevLib" QSYS /data data type="10a" var="sbsSecLng" *NONE /data data type="10i0" var="sbsMaxAct" -1 /data data type="10i0" var="sbsCurAct" 0 /data data type="10i0" enddo="mycnt" var="sbsStrPoolCnt" 2 /data ds dim="999" dou="mycnt" var="sbs_pool" data type="10a" var="sbspoolNam" '}

    pip3 list gives me the below.

    $ pip3 list
    Package    Version
    ---------- --------
    ibm-db     2.0.5.12
    itoolkit   1.7.2
    pip        21.1.2
    setuptools 57.0.0
    six        1.10.0
    wheel      0.36.2
    $

    IBMi wise, I'm running 7.5 with Cume 23306 (IBM PowerVS stock image).

    Many thanks, Steve



    ------------------------------
    Steve Munday
    AIX, IBM i, HMC, PowerVM
    ------------------------------


  • 2.  RE: python iToolKit - How to correctly call an API (QWDRSBSD) from python

    Posted Mon October 07, 2024 09:39 PM
    Edited by Satid S Mon October 07, 2024 10:05 PM

    Dear Steve

    I have no answer for your issue but I would like to offer an idea that you can also use SQL call instead (iSqlQuery) to SUBSYSTEM_INFO view (which returns columns that are closely related to the values returned by WRKSBS command and by QWDRSBSD API) to see if you can avoid the BADPARSE error.   I have a wild guess that asterisk in *ACTIVE and *NONE in the returned result you get may be the cause and expect that changing to SQL query to SUBSYSTEM_INFO view does not return asterisk (ACTIVE and NONE).  



    ------------------------------
    Satid S
    ------------------------------



  • 3.  RE: python iToolKit - How to correctly call an API (QWDRSBSD) from python

    Posted Tue October 08, 2024 03:01 AM

    Hi Steve, 

      As Satid said you can use  SUBSYSTEM_INFO view   but you can use it directly from Ansible with the module ibmi_sql_query – Executes a SQL DQL(Data Query Language) statement. - IBM power_ibmi collection 1.0.0 documentation



    ------------------------------
    Nicolae Chirea
    System Architect
    Seidor Iberia
    Madrid/Spain
    ------------------------------



  • 4.  RE: python iToolKit - How to correctly call an API (QWDRSBSD) from python

    Posted Tue October 08, 2024 04:41 AM

    To monitor interactive system status I personally use, for this task, from the monitoring system, the simple database query

    SELECT STATUS FROM SUBSYSTEM_INFO
    WHERE (SUBSYSTEM_DESCRIPTION_LIBRARY, SUBSYSTEM_DESCRIPTION) = ('QSYS', 'QINTER')

    you can very easily compose "assert" type things.

    If you really want to wade across pure call based semantics, and marshalling demarshalling xml hell and string parsing, I would suggest to create a *PGM wrapper (that then calls the API) with a clean and simple parameter interface, to be used by any caller, would be easier to debug and maintain in case something goes awry along the way...



    ------------------------------
    --ft
    ------------------------------



  • 5.  RE: python iToolKit - How to correctly call an API (QWDRSBSD) from python

    Posted Tue October 08, 2024 05:03 AM

    Satid, Nicolae, ace-ace,

    Thanks for all your replies.  One thing I didn't mention is that whilst I'm initially testing out my theory on 7.5 I will have to ensure it works for 7.1 (shocking I know).

    So, with that said, whilst the SQL approach works very nicely on the new(er) OS's I will be needing to delve into the iToolKit landscape to realise my objective.  I'm going to check some old RPG/API code I have to see if that throws up any guidance when it comes to defining the DS(s) just in case the *BADPARSE is more about field lengths rather than overall function as the call I've defined does return *ACTIVE for the QSYS/QINTER subsystem I'm checking (in my example).

    I also plan to tap up the iToolKit team to get their take on things.

    Many thanks, Steve



    ------------------------------
    Steve Munday
    AIX, IBM i, HMC, PowerVM
    ------------------------------



  • 6.  RE: python iToolKit - How to correctly call an API (QWDRSBSD) from python

    Posted Tue October 08, 2024 10:46 AM

    Looks like you missed the Pool ID under your sbs_pool struct.



    ------------------------------
    Korinne Adler
    ------------------------------



  • 7.  RE: python iToolKit - How to correctly call an API (QWDRSBSD) from python

    Posted Tue October 08, 2024 12:05 PM

    Korinne,

    Thank-you so much, I thought I was going nuts!!

    The corrected DS with the missing Pool ID :-)

    itool.add(
        iPgm('qwdrsbsd','QWDRSBSD')
        .addParm(iDS('QWDRSBSD_t',{'len':'sbslen'})
        .addData(iData('sbsRet','10i0',''))
        .addData(iData('sbsAvl','10i0',''))
        .addData(iData('sbsNam','10a',''))
        .addData(iData('sbsLib','10a',''))
        .addData(iData('sbsSts','10a',''))
        .addData(iData('sbsDevNam','10a',''))
        .addData(iData('sbsDevLib','10a',''))
        .addData(iData('sbsSecLng','10a',''))
        .addData(iData('sbsMaxAct','10i0',''))
        .addData(iData('sbsCurAct','10i0',''))
        .addData(iData('sbsStrPoolCnt','10i0','',{'enddo':'mycnt'}))
        .addData(iDS('sbs_pool',{'dim':'999','dou':'mycnt'})
            .addData(iData('sbspoolID','10i0',''))
            .addData(iData('sbspoolNam','10a',''))
            .addData(iData('sbspoolRes1','6a',''))
            .addData(iData('sbspoolSiz','10i0',''))
            .addData(iData('sbspoolActLvl','10i0',''))
            )
        )
        .addParm(iData('rcvlen','10i0','',{'setlen':'sbslen'}))
        .addParm(iData('fmtNam','8a','SBSI0100'))
        .addParm(iData('qualSbsNam','20a','QINTER    *LIBL     '))
        .addParm(iDS('ERRC0100_t',{'len':'errlen'})
            .addData(iData('errRet','10i0',''))
            .addData(iData('errAvl','10i0',''))
            .addData(iData('errExp','7a','',{'setlen':'errlen'}))
            .addData(iData('errRsv','1a',''))
        )
    )

    {u'success': u'+++ success  QWDRSBSD', u'rcvlen': u'28052', u'fmtNam': u'SBSI0100', u'QWDRSBSD_t': {u'sbsNam': u'QINTER', u'sbsLib': u'QSYS', u'sbsAvl': u'136', u'sbsDevLib': u'QSYS', u'sbsCurAct': u'0', u'sbsDevNam': u'QDSIGNON', u'sbsSecLng': u'*NONE', u'sbsSts': u'*ACTIVE', u'sbsMaxAct': u'-1', u'sbsStrPoolCnt': u'2', u'sbsRet': u'136', u'sbs_pool': [{u'sbspoolRes1': '', u'sbspoolID': u'1', u'sbspoolSiz': u'0', u'sbspoolNam': u'*BASE', u'sbspoolActLvl': u'0'}, {u'sbspoolRes1': '', u'sbspoolID': u'2', u'sbspoolSiz': u'0', u'sbspoolNam': u'*INTERACT', u'sbspoolActLvl': u'0'}]}, u'qualSbsNam': u'QINTER    *LIBL', u'ERRC0100_t': {u'errExp': '', u'errRet': u'0', u'errRsv': '', u'errAvl': u'0'}}

    All the best, Steve



    ------------------------------
    Steve Munday
    AIX, IBM i, HMC, PowerVM
    ------------------------------