Doc:latest/evalguide/csa104

Contents

csa104 Provisioning

Objective

The objective is to demonstrate some of the features of the Clovis Object Registry (COR) and Clovis' Object Management (OM) framework.

What you will learn

  • How to use the Clovis Object Registry to set configuration values in a simple SAFplus Platform application.
  • How to manipulate COR values from the SAFplus Platform Console line interface.

Code

The code can be found within the following directory

<project-area_dir>/eval/src/app/csa104Comp
clCompAppMain.c
     ClUint8T clEoClientLibs[] =
    {
        COMP_EO_CLIENTLIB_COR,      /* Lib: Common Object Repository            */
        COMP_EO_CLIENTLIB_CM,       /* Lib: Chassis Management                  */
        COMP_EO_CLIENTLIB_NAME,     /* Lib: Name Service                        */
        COMP_EO_CLIENTLIB_LOG,      /* Lib: Log Service                         */
        COMP_EO_CLIENTLIB_TRACE,    /* Lib: Trace Service                       */
        COMP_EO_CLIENTLIB_DIAG,     /* Lib: Diagnostics                         */
        COMP_EO_CLIENTLIB_TXN,      /* Lib: Transaction Management              */
        CL_FALSE,                   /* NA */
        COMP_EO_CLIENTLIB_PROV,     /* Lib: Provisioning Management             */
        COMP_EO_CLIENTLIB_ALARM,    /* Lib: Alarm Management                    */
        COMP_EO_CLIENTLIB_DEBUG,    /* Lib: Debug Service                       */
        COMP_EO_CLIENTLIB_GMS       /* Lib: Cluster/Group Membership Service    */
    };
  

Here we present the Client Libraries. These are set within clCompCfg.h.

clCompCfg.h
    #define COMP_EO_CLIENTLIB_COR   CL_TRUE
    #define COMP_EO_CLIENTLIB_CM    CL_FALSE
    #define COMP_EO_CLIENTLIB_NAME    CL_FALSE        
    #define COMP_EO_CLIENTLIB_LOG    CL_FALSE
    #define COMP_EO_CLIENTLIB_TRACE    CL_FALSE
    #define COMP_EO_CLIENTLIB_DIAG    CL_FALSE
    #define COMP_EO_CLIENTLIB_TXN    CL_TRUE
    #define COMP_EO_CLIENTLIB_NA    CL_FALSE
    #define COMP_EO_CLIENTLIB_PROV    CL_TRUE
    #define COMP_EO_CLIENTLIB_ALARM    CL_FALSE
    #define COMP_EO_CLIENTLIB_DEBUG    CL_FALSE
    #define COMP_EO_CLIENTLIB_GMS    CL_FALSE
  

Within clCompCfg.h we set Clovis Object Registry (COR), the Transaction (TXN), and Provisioning (Prov) libraries to TRUE.

clCompAppMain.c
 ClCompAppInitialize()

    ...
    clCorMoIdInitialize(&moId);
    clCorMoIdAppend(&moId, CLASS_CHASSIS_MO, 0);
    clCorMoIdAppend(&moId, CLASS_CSA104RES_MO, 0);
    clCorMoIdServiceSet(&moId, CL_COR_SVC_ID_PROVISIONING_MANAGEMENT);
    rc = clCorObjectHandleGet(&moId, &objH);
    if (CL_OK != rc)
    {
        clprintf(CL_LOG_SEV_ERROR,"%s: Failed [0x%x] to get the object handle. ",
                appname, rc);
        return rc;
    }

    while (!exiting)
    {
        if (running && ha_state == CL_AMS_HA_STATE_ACTIVE)
        {
            clprintf(CL_LOG_SEV_INFO,"%s: Hello World! (count = %d)", appname, counter);
#ifdef CL_INST
            if ((rc = clDataTapSend(counter)) != CL_OK && (rc != CL_ERR_INVALID_PARAMETER))
            {
                clprintf(CL_LOG_SEV_ERROR,"%s: Failed [0x%x] to send data tap data",
                            appname, rc);
            }
#endif
            if ((rc = update_counter_in_cor(time(0), objH, counter)) != CL_OK)
            {
                clprintf(CL_LOG_SEV_ERROR,"%s: [0x%x]: cor update failed. Exiting.",
                            appname, rc);
                break;
            }

            /* Checkpoint new counter number */
            rc = checkpoint_write_counter(counter);
            if (rc != CL_OK)
            {
                clprintf(CL_LOG_SEV_ERROR,"%s: [0x%x]: Checkpoint write failed. Exiting.",
                            appname, rc);
                break;
            }
            
            counter++;
        }

        usleep((useconds_t)delta_t*1000);
    }
  

The main loop body is as we've seen several times already. But, the sleep, rather than being sleep(1) is a usleep() of a variable duration. The duration: delta_t is a number in milliseconds that is settable from COR. We'll see where it gets set later.

clCompAppMain.c
    #include <stdio.h>
    #include <string.h>
...
    #include <clDebugApi.h>
...
  

We including standard header files, including clDebugApi.h which allows the application to interact with the SAFplus Platform Console.

clcsa104CompOAMPConfig.c
    #include <clcsa104CompOAMPConfig.h>
  

Within clcsa104CompOAMPConfig.c we include clcsa104CompOAMPConfig.h.

clcsa104CompOAMPConfig.h
    #include <clOmApi.h>
    #include <clCorApi.h>
    #include <clProvOmApi.h>
    #include <clProvApi.h>
    #include <clAlarmOM.h>
    #include <clHalApi.h>
    #include <clHalObjectApi.h>
 
    typedef ClRcT (*fp) (CL_OM_PROV_CLASS*, ClHandleT,  ClProvTxnDataT*);
 
 
    CL_OM_BEGIN_CLASS(CL_OM_PROV_CLASS,  CL_OM_PROV_CSA104RES_CLASS)
 
    CL_OM_END
 
    ClRcT clcsa104CompCSA104RESProvConstructor( void *pThis, void *pUsrData,
                                                     ClUint32T usrDataLen );
    ClRcT clcsa104CompCSA104RESProvDestructor ( void *pThis , void  *pUsrData,
                                                     ClUint32T usrDataLen );
    ClRcT clcsa104CompCSA104RESProvValidate(CL_OM_PROV_CLASS* pThis, 
                               ClHandleT txnHandle, ClProvTxnDataT* pProvTxnData);
 
    ClRcT clcsa104CompCSA104RESProvUpdate(CL_OM_PROV_CLASS* pThis, 
                               ClHandleT txnHandle, ClProvTxnDataT* pProvTxnData);
 
    ClRcT clcsa104CompCSA104RESProvRollback(CL_OM_PROV_CLASS* pThis,
                               ClHandleT txnHandle, ClProvTxnDataT* pProvTxnData);

    ClRcT clcsa104CompCSA104RESProvRead(CL_OM_PROV_CLASS* pThis,
                               ClHandleT txnHandle, ClProvTxnDataT* pProvTxnData);

    void clcsa104CompCSA104RESProvObjectStart(ClCorMOIdPtrT pMoId, 
                               ClHandleT txnHandle);

    void clcsa104CompCSA104RESProvObjectEnd(ClCorMOIdPtrT pMoId, 
                               ClHandleT txnHandle);
  

Next in clcsa104CompOAMPConfig.h we have several header files being included. Included is clOmApi.h which is the main header file for using the Object Management subsystem. This is Clovis' support for object-oriented like programming in C. Next clCorApi.h is the main header for using the Clovis Object Registry. clProvOmApi.h is the main header for the Clovis Provisioning OM class. We define an Object Management class: CL_OM_PROV_CSA104RES_CLASS which inherits from another Object Management class: CL_OM_PROV_CLASS. This last class is the class whose API was imported with the #include clProvOmApi.h. The subsequent code in the above table declare functions that will be member functions of the new Object Management class: CL_OM_PROV_CSA104_CLASS. Note that function header comments have been omitted for clarity.

clcsa104Compcsa104Res.c
     extern ClUint32T delta_t;
     extern ClCharT   appname[80];
  

Above we define/declare a variable that is used for provisioning. The extern is a reference to a variable defined in clCompAppMain.c.

clcsa104CompOAMPConfig.c
     ClOmClassControlBlockT pAppOmClassTbl[] =
     {
         {
          CSA104COMP_CSA104RES_PROV_CLASS_NAME,
          sizeof(CL_OM_PROV_CSA104RES_CLASS),
          CL_OM_PROV_CLASS_TYPE,
          clcsa104CompCSA104RESProvConstructor,
          clcsa104CompCSA104RESProvDestructor,
          NULL,
          CSA104COMP_CSA104RES_PROV_CLASS_VERSION,
          0,
          CL_MAX_OBJ,
          0,
          CSA104COMP_CSA104RES_PROV_MAX_SLOTS,
          CL_OM_PROV_CSA104RES_CLASS_TYPE
     },
     
     
     };
  

Within clcsa104CompOAMPConfig.c we define the global pAppOmClassTbl so that will know about the new class and be able to instantiate members of the class. Line 27 specifies the name of the class. This is optional. Defined is the size of instances of the class, next we specify the base class, followed by the constructor and destructor for the class respectively. The NULL specifies the table of functions for the class, in this case there is no such table. 0 is the instance table pointer. The next three lines of code.
--> CL_MAX_OBJ,
--> 0,
--> CSA104COMP_CSA104RES_PROV_MAX_SLOTS,
specify the max number of object instances allowed, current number of object instances, and max number of object instances so far respectively. Followed by the Class Type ID for the class.

clcsa104Compcsa104Res.c
     ClRcT clcsa104CompCSA104RESProvConstructor( void *pThis, void *pUsrData,
                                                 ClUint32T usrDataLen )
     {
         ClRcT rc = CL_OK;
     
         /* Override "semantic check" virtual method in provClass*/
         ((CL_OM_PROV_CLASS*)pThis)->clProvObjectStart = clcsa104CompCSA104RESProvObjectStart; 	 
         ((CL_OM_PROV_CLASS*)pThis)->clProvValidate = (fp)clcsa104CompCSA104RESProvValidate; 	 
         ((CL_OM_PROV_CLASS*)pThis)->clProvUpdate = (fp)clcsa104CompCSA104RESProvUpdate; 	 
         ((CL_OM_PROV_CLASS*)pThis)->clProvRollback = (fp)clcsa104CompCSA104RESProvRollback;
         ((CL_OM_PROV_CLASS*)pThis)->clProvRead = (fp)clcsa104CompCSA104RESProvRead;
         ((CL_OM_PROV_CLASS*)pThis)->clProvObjectEnd = clcsa104CompCSA104RESProvObjectEnd; 

         ...

         return rc;
     }
     
     ClRcT clcsa104CompCSA104RESProvDestructor ( void *pThis , void  *pUsrData,
                                                 ClUint32T usrDataLen )
     {
         ClRcT rc = CL_OK;

         ...

         return rc;
     }
  

The above table presents the Contructor. It initializes the function pointers defined in the Base Class. These are the Update method, the provisioning validation method, and the provisioning rollback method. These are declared in clcsa104CompOAMPConfig.h in the class definition. The destructor doesn't do anything except return CL_OK. There's no destruction work to do for this class.

clcsa104Compcsa104Res.c
 ClRcT clcsa104CompCSA104RESProvUpdate(CL_OM_PROV_CLASS* pThis,
                            ClHandleT txnHandle, ClProvTxnDataT* pProvTxnData)
 {
     ClRcT rc = CL_OK;

     /*
       ---BEGIN_APPLICATION_CODE---
     */

     clprintf(CL_LOG_SEV_INFO, "Inside the function %s", __FUNCTION__);

     ClNameT     moIdName = {0};
    
     rc = clCorMoIdToMoIdNameGet((ClCorMOIdPtrT)pProvTxnData->pMoId, &moIdName);
     if (CL_OK != rc)
     {
         clprintf(CL_LOG_SEV_ERROR,"%s: Failed while getting the MOId Name from moid. rc[0x%x] ", appname, rc);
         return rc;
     }
     /*
       ---END_APPLICATION_CODE---
     */

clcsa104Compcsa104Res.c
     switch (pProvTxnData->provCmd)
     {
         case CL_COR_OP_CREATE :
         case CL_COR_OP_CREATE_AND_SET:
			
         /*
          * ---BEGIN_APPLICATION_CODE---
          */

         clprintf(CL_LOG_SEV_INFO,"%s: Inside create request for the object [%s] ", appname, moIdName.value);    

         /*
          * ---END_APPLICATION_CODE---
          */

         break;
         case CL_COR_OP_SET:
	    
         /*
          * ---BEGIN_APPLICATION_CODE---
          */

         if ( pProvTxnData->attrId == CSA104RES_DELTA_T)
         {
             delta_t = *(ClUint32T *)pProvTxnData->pProvData;
             clprintf(CL_LOG_SEV_INFO,"%s: The delta time is now [%d] ", appname, delta_t);
         }

         /*
          * ---END_APPLICATION_CODE---
          */

         break;

         case  CL_COR_OP_DELETE:

         /*
          * ---BEGIN_APPLICATION_CODE---
          */

         /*
          * ---END_APPLICATION_CODE---
          */

         break;
         default:
             clprintf (CL_LOG_SEV_ERROR, "Prov command is not proper");
     }

     ...

     return rc;   
 }
  

When the COR object associated with csa104's provisioning is updated, clcsa104CompCSA104RESProvUpdate function is called. A new value is set for the delta_t variable that is used to control the sleep interval in the application's main loop.

How to Run 104 and what to observe

  1. Start the application as usual with the SAFplus Platform Console.
     # cd /root/asp/bin
     # ./asp_console
    
     cli[Test]-> setc 1
     cli[Test:SCNodeI0]-> setc cpm
     cli[Test:SCNodeI0:CPM]-> amsLockAssignment sg csa104SGI0
    

    Again, there are two log files to observe /root/asp/var/log/csa104CompI0Log.latest and /var/log/csa104CompI1Log.latest. After running the above commands you should see the following output in these logs when using tail -f.

    /root/asp/var/log/csa104CompI0Log.latest
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00051 :   INFO)
     Component [csa104CompI0] : PID [21202]. Initializing
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00052 :   INFO)
        IOC Address             : 0x1
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00053 :   INFO)
        IOC Port                : 0x80
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00054 :   INFO)
     csa104: instantiated as component instance csa104CompI0.
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00055 :   INFO)
     csa104CompI0: cpmHandle = 0x1
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00056 :   INFO)
     csa104CompI0: Waiting for CSI assignment...
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00057 :   INFO)
     csa104CompI0: checkpoint_initialize
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00064 :   INFO)
     csa104CompI0: Checkpoint service initialized (handle=0x1)
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00066 :   INFO)
     csa104CompI0: Checkpoint opened (handle=0x2)
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00067 :   INFO)
     csa104CompI0: Section created
      
    /root/asp/var/log/csa104CompI1Log.latest
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21209 : csa104CompEO.---.---.00049 :   INFO)
     Component [csa104CompI1] : PID [21209]. Initializing
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21209 : csa104CompEO.---.---.00050 :   INFO)
        IOC Address             : 0x1
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21209 : csa104CompEO.---.---.00051 :   INFO)
        IOC Port                : 0x81
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21209 : csa104CompEO.---.---.00052 :   INFO)
     csa104: instantiated as component instance csa104CompI1.
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21209 : csa104CompEO.---.---.00053 :   INFO)
     csa104CompI1: cpmHandle = 0x1
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21209 : csa104CompEO.---.---.00054 :   INFO)
     csa104CompI1: Waiting for CSI assignment...
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21209 : csa104CompEO.---.---.00055 :   INFO)
     csa104CompI1: checkpoint_initialize
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21209 : csa104CompEO.---.---.00062 :   INFO)
     csa104CompI1: Checkpoint service initialized (handle=0x1)
    Mon Jul 14 19:06:29 2008   (SCNodeI0.21209 : csa104CompEO.---.---.00064 :   INFO)
     csa104CompI1: Checkpoint opened (handle=0x2)
      
  2. As before, unlock the application with:
    cli[Test:SCNodeI0:CPM]-> amsUnlock sg csa104SGI0
    

    In the active component log file you should start to see the "Hello World" lines displaying at a rate of about 1 per second.

    /root/asp/var/log/csa104CompI0Log.latest
    Mon Jul 14 19:07:27 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00080 :   INFO)
     csa104CompI0: Hello World! (count = 0)
    Mon Jul 14 19:07:27 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00085 :   INFO)
     **** Inside the function : [clCompAppProvTxnStart] ****
    Mon Jul 14 19:07:27 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00087 :   INFO)
     Inside the function clcsa104CompCSA104RESProvObjectStart
    Mon Jul 14 19:07:27 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00089 :   INFO)
     Inside the function clcsa104CompCSA104RESProvValidate
    Mon Jul 14 19:07:27 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00105 :   INFO)
     Inside the function clcsa104CompCSA104RESProvUpdate
    Mon Jul 14 19:07:27 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00107 :   INFO)
     Inside the function clcsa104CompCSA104RESProvObjectEnd
    Mon Jul 14 19:07:27 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00116 :   INFO)
     **** Inside the function : [clCompAppProvTxnEnd] ****
    Mon Jul 14 19:07:28 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00123 :   INFO)
     csa104CompI0: Hello World! (count = 1)
    Mon Jul 14 19:07:29 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00124 :   INFO)
     csa104CompI0: Hello World! (count = 2)
    Mon Jul 14 19:07:30 2008   (SCNodeI0.21202 : csa104CompEO.---.---.00125 :   INFO)
     csa104CompI0: Hello World! (count = 3)
      
  3. In the SAFplus Platform Console return to the Slot 1 context by entering end until it prints the Slot 1 prompt: cli[Test:SCNodeI0]->.
    cli[Test:SCNodeI0:CPM]-> end
    cli[Test:SCNodeI0]->
    
  4. Now set the context to the COR server using the following command:
    cli[Test:SCNodeI0]-> setc corServer_SCNodeI0
    
  5. Then, dump the object tree:
    cli[Test:SCNodeI0:COR]-> objTreeShow
    

    You should see something like the following.

    SAFplus Platform Console
    cli[Test:SCNodeI0:COR]-> objTreeShow
    
    Objects (Instance Tree):
        \Chassis:0
            \PayloadNodeRes:0
                (provisioning)
            \PayloadNodeRes:1
                (provisioning)
            \SCNodeRes:0
                (provisioning)
            \SCNodeRes:1
                (provisioning)
            \csa104Res:0
                (provisioning)
            \csa105Res:0
                (alarm, provisioning)
    
      
  6. Next, dump the object with:
    cli[Test:SCNodeI0:COR]-> objectShow \Chassis:0\csa104Res:0 PROV
    
    SAFplus Platform Console
    Showing Object
    ClCorMOId:[Svc: 3] (/).(10001:0000).(10002:0000):
    
    [Class:0x10003] Object 
    {
    [CSA104RES_COUNTER             ] [0x0002] = [431]
    [CSA104RES_DELTA_T             ] [0x0003] = [1000]
    }
      


  7. Now, set the delta_t attribute to 10000 instead of 1000 with:
    cli[Test:SCNodeI0:COR]-> attrSet \Chassis:0\csa104Res:0 3 null 3 -1 10000
    
    SAFplus Platform Console
     Execution Result : Passed
      

    The 3 is the service ID of the object. You should see lines like the following in the logs for csa104:

    /root/asp/var/log/csa104CompI0Log.latest
    Mon Jul 14 19:15:59 2008   (SCNodeI0.21202 : csa104CompEO.---.---.04230 :   INFO)
     csa104CompI0: The delta time is now [10000] 
    Mon Jul 14 19:15:59 2008   (SCNodeI0.21202 : csa104CompEO.---.---.04232 :   INFO)
     Inside the function clcsa104CompCSA104RESProvObjectEnd
    Mon Jul 14 19:15:59 2008   (SCNodeI0.21202 : csa104CompEO.---.---.04241 :   INFO)
     **** Inside the function : [clCompAppProvTxnEnd] ****
    Mon Jul 14 19:15:59 2008   (SCNodeI0.21202 : csa104CompEO.---.---.04248 :   INFO)
     csa104CompI0: Hello World! (count = 510)
    Mon Jul 14 19:16:09 2008   (SCNodeI0.21202 : csa104CompEO.---.---.04249 :   INFO)
     csa104CompI0: Hello World! (count = 511)
    Mon Jul 14 19:16:09 2008   (SCNodeI0.21202 : csa104CompEO.---.---.04254 :   INFO)
     **** Inside the function : [clCompAppProvTxnStart] ****
      

    indicating that the component has received the updated value of delta_t

    You should also notice that the lines in the log are now being printed with a 10 second interval between lines.

    To confirm that the value of delta_t was updated you could dump the object with:

    cli[Test:SCNodeI0:COR]-> objectShow \Chassis:0\csa104Res:0 PROV
    
    SAFplus Platform Console
     Showing Object
    ClCorMOId:[Svc: 3] (/).(10001:0000).(10002:0000):
    
    [Class:0x10003] Object 
    {
    [CSA104RES_COUNTER             ] [0x0002] = [523]
    [CSA104RES_DELTA_T             ] [0x0003] = [10000]
    }
      


  8. To end the example first change the state of csa104SGI0 to LockAssignment.
    cli[Test:SCNodeI0:COR]-> end
    cli[Test:SCNodeI0]-> setc cpm
    cli[Test:SCNodeI0:CPM]-> amsLockAssignment sg csa104SGI0
    
  9. Then change the state to LockInstantiation.
    cli[Test:SCNodeI0:CPM]-> amsLockInstantiation sg csa104SGI0
    
  10. Then close the SAFplus Platform Console session.
    cli[Test:SCNodeI0:CPM]-> end
    cli[Test:SCNodeI0]-> end
    cli[Test]-> bye
    

Summary and References

We've seen how to:

  • Create a simple ProvOm class.
  • Use callbacks to the class's update method to update variables in the application at runtime.
  • Use the SAFplus Platform Console to cause the classes update method to be invoked.

For further reading :

  • Clovis SAFplus Platform User Guide: sections on COR,
  • clProvOmApi.h
  • clOmObjectManage.h
  • clOmApi.h