Build High Availability App with AMF API
The program is located at /opt/demo, consists of two files:
The program will be installed to SC-1.
File /opt/demo/main.c
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <poll.h>
#include <syslog.h>
#include <signal.h>
#include <saAmf.h>
#include <saAis.h>
#define trace(fmt, ...) \
syslog(LOG_INFO, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__)
void csiSetCallback(SaInvocationT invocation, const SaNameT *name,
, SaAmfCSIDescriptorT descriptor);
SaAmfHAStateT state
void csiRemoveCallback(SaInvocationT invocation, const SaNameT *compName,
const SaNameT *csiName, SaAmfCSIFlagsT csiFlags);
void componentTerminateCallback(SaInvocationT invocation,
const SaNameT *compName);
void csiAttributeChangeCallback(SaInvocationT invocation,
const SaNameT *csiName, SaAmfCSIAttributeListT csiAttr);
;
SaAmfHandleT amfHandler
int main(int argc, char ** argv)
{
// setup syslog
("demo", LOG_PID, LOG_USER);
openlog("start");
trace
// check if program start by AMF
// SA_AMF_COMPONENT_NAME exists when started by amf
if (getenv("SA_AMF_COMPONENT_NAME") == NULL)
{
("not started by AMF, exiting...\n");
tracereturn 1;
}
// setup amf callbacks
= {0};
SaAmfCallbacksT_o4 callbacks .saAmfCSISetCallback = csiSetCallback;
callbacks.saAmfCSIRemoveCallback = csiRemoveCallback;
callbacks.saAmfComponentTerminateCallback= componentTerminateCallback;
callbacks.osafCsiAttributeChangeCallback = csiAttributeChangeCallback;
callbacks= {
SaVersionT apiVersion .releaseCode = 'B',
.majorVersion = 0x04,
.minorVersion = 0x02
};
(&amfHandler, &callbacks, &apiVersion);
saAmfInitialize_o4
// register component
;
SaNameT name(amfHandler, &name);
saAmfComponentNameGet(amfHandler, &name, 0);
saAmfComponentRegister
// get file descriptor that listens incoming amf callbacks
;
SaSelectionObjectT monitorFd(amfHandler, &monitorFd);
saAmfSelectionObjectGet
// setup pollfd to monitor amf callback events
struct pollfd fds[1];
[0].fd = monitorFd;
fds[0].events = POLLIN;
fds
// wait and handle amf callback events
while (poll(fds, 1, -1) != -1)
{
if (fds[0].revents & POLLIN)
{
("receive poll event");
trace(amfHandler, SA_DISPATCH_ONE);
saAmfDispatch}
}
return 1;
}
void csiSetCallback(SaInvocationT invocation, const SaNameT *name,
, SaAmfCSIDescriptorT descriptor)
SaAmfHAStateT state{
();
trace(amfHandler, invocation, 0, SA_AIS_OK);
saAmfResponse_4}
void csiRemoveCallback(SaInvocationT invocation, const SaNameT *compName,
const SaNameT *csiName, SaAmfCSIFlagsT csi_flags)
{
();
trace(amfHandler, invocation, 0, SA_AIS_OK);
saAmfResponse_4}
void componentTerminateCallback(SaInvocationT invocation,
const SaNameT *compName)
{
();
trace(amfHandler, invocation, 0, SA_AIS_OK);
saAmfResponse_4(0);
exit}
void csiAttributeChangeCallback(SaInvocationT invocation,
const SaNameT *csiName, SaAmfCSIAttributeListT csiAttr)
{
();
trace(amfHandler, invocation, 0, SA_AIS_OK);
saAmfResponse_4}
Compile.
$ gcc -g -o main main.c -lSaAmf
File /opt/demo/control.h
start() {
logger -st demo 'start'
start-stop-daemon --start --background \
--make-pidfile --pidfile /var/run/demo.pid \
--exec /opt/demo/main
}
stop() {
logger -st demo 'stop'
start-stop-daemon --stop --pidfile /var/run/demo.pid
}
case $1 in
start)
start;;
stop)
stop;;
*)
echo 'Usage: control.sh {start|stop}'
exit 1;;
esac
exit 0
immcfg -c SaSmfSwBundle safSmfBundle=demo
immcfg -c SaAmfNodeSwBundle \
-a saAmfNodeSwBundlePathPrefix=/opt/demo \
safInstalledSwBundle=saSmfBundle=demo,safAmfNode=SC-1,safAmfCluster=myAmfCluster
immcfg -c SaAmfAppBaseType safAppType=demo
immcfg -c SaAmfSGBaseType safSgType=demo
immcfg -c SaAmfSUBaseType safSuType=demo
immcfg -c SaAmfSvcBaseType safSvcType=demo
immcfg -c SaAmfCompBaseType safCompType=demo
immcfg -c SaAmfCSBaseType safCSType=demo
immcfg -c SaAmfCSType safVersion=1,safCSType=demo
immcfg -c SaAmfSvcType safVersion=1,safSvcType=demo
immcfg -c SaAmfCompType \
-a saAmfCtCompCategory=1 \
-a saAmfCtSwBundle=saSmfBundle=demo \
-a saAmfCtDefClcCliTimeout=10000000000 \
-a saAmfCtDefCallbackTimeout=10000000000 \
-a saAmfCtRelPathInstantiateCmd=control.sh \
-a saAmfCtDefInstantiateCmdArgv=start \
-a saAmfCtRelPathCleanupCmd=control.sh \
-a saAmfCtDefCleanupCmdArgv=stop \
-a saAmfCtDefQuiescingCompleteTimeout=10000000000 \
-a saAmfCtDefRecoveryOnError=2 \
-a saAmfCtDefDisableRestart=0 \
safVersion=1,safCompType=demo
immcfg -c SaAmfSUType \
-a saAmfSutProvidesSvcTypes=safVersion=1,safSvcType=demo \
-a saAmfSutIsExternal=0 \
-a saAmfSutDefSUFailover=1 \
safVersion=1,safSuType=demo
immcfg -c SaAmfSGType \
-a saAmfSgtValidSuTypes=safVersion=1,safSuType=demo \
-a saAmfSgtRedundancyModel=1 \
-a saAmfSgtDefSuRestartProb=4000000000 \
-a saAmfSgtDefSuRestartMax=3 \
-a saAmfSgtDefCompRestartProb=4000000000 \
-a saAmfSgtDefCompRestartMax=3 \
-a saAmfSgtDefAutoAdjustProb=10000000000 \
safVersion=1,safSgType=demo
immcfg -c SaAmfAppType \
-a saAmfApptSGTypes=safVersion=1,safSgType=demo \
safVersion=1,safAppType=demo
immcfg -c SaAmfSutCompType \
'safMemberCompType=safVersion=1\,safCompType=demo,safVersion=1,safSuType=demo'
immcfg -c SaAmfCtCsType \
-a saAmfCtCompCapability=1 \
'safSupportedCsType=safVersion=1\,safCSType=demo,safVersion=1,safCompType=demo'
immcfg -c SaAmfSvcTypeCSTypes \
'safMemberCSType=safVersion=1\,safCSType=demo,safVersion=1,safSvcType=demo'
immcfg -c SaAmfApplication \
-a saAmfAppType=safVersion=1,safAppType=demo \
safApp=demo
immcfg -c SaAmfSG \
-a saAmfSGType=safVersion=1,safSgType=demo \
-a saAmfSGSuHostNodeGroup=safAmfNodeGroup=SCs,safAmfCluster=myAmfCluster \
-a saAmfSGAutoRepair=0 \
-a saAmfSGAutoAdjust=0 \
-a saAmfSGNumPrefInserviceSUs=10 \
-a saAmfSGNumPrefAssignedSUs=10 \
safSg=demo,safApp=demo
immcfg -c SaAmfSI \
-a saAmfSvcType=safVersion=1,safSvcType=demo \
-a saAmfSIProtectedbySG=safSg=demo,safApp=demo \
safSi=demo,safApp=demo
immcfg -c SaAmfCSI \
-a saAmfCSType=safVersion=1,safCSType=demo \
safCsi=demo,safSi=demo,safApp=demo
immcfg -c SaAmfSU \
-a saAmfSUType=safVersion=1,safSuType=demo \
-a saAmfSURank=1 \
-a saAmfSUAdminState=3 \
safSu=SC-1,safSg=demo,safApp=demo
immcfg -c SaAmfComp \
-a saAmfCompType=safVersion=1,safCompType=demo \
safComp=demo,safSu=SC-1,safSg=demo,safApp=demo
immcfg -c SaAmfCompCsType \
'safSupportedCsType=safVersion=1\,safCSType=demo,safComp=demo,safSu=SC-1,safSg=demo,safApp=demo'
Unlock instantiate (start process).
amf-adm unlock-in safSu=SC-1,safSg=demo,safApp=demo
# syslog
SC-1 osafamfnd[8729]: NO 'safSu=SC-1,safSg=demo,safApp=demo' Presence State UNINSTANTIATED => INSTANTIATING
SC-1 demo: start
SC-1 demo[13044]: main: start
SC-1 osafamfnd[8729]: NO 'safSu=SC-1,safSg=demo,safApp=demo' Presence State INSTANTIATING => INSTANTIATED
Unlock SU (assign work to process).
amf-adm unlock safSu=SC-1,safSg=demo,safApp=demo
# syslog
SC-1 osafamfnd[8729]: NO Assigning 'safSi=demo,safApp=demo' ACTIVE to 'safSu=SC-1,safSg=demo,safApp=demo'
SC-1 demo[13044]: main: receive poll event
SC-1 demo[13044]: csiSetCallback:
SC-1 osafamfnd[8729]: NO Assigned 'safSi=demo,safApp=demo' ACTIVE to 'safSu=SC-1,safSg=demo,safApp=demo'
Kill the process.
/opt/demo/control.sh stop
The program will be restarted automatically by AMF.
# syslog
SC-1 demo: stop
SC-1 osafamfnd[8729]: NO 'safSu=SC-1,safSg=demo,safApp=demo' component restart probation timer started (timeout: 4000000000 ns)
SC-1 osafamfnd[8729]: NO Restarting a component of 'safSu=SC-1,safSg=demo,safApp=demo' (comp restart count: 1)
SC-1 osafamfnd[8729]: NO 'safComp=demo,safSu=SC-1,safSg=demo,safApp=demo' faulted due to 'avaDown' : Recovery is 'componentRestart'
SC-1 osafamfnd[8729]: NO 'safSu=SC-1,safSg=demo,safApp=demo' Presence State INSTANTIATED => RESTARTING
SC-1 demo: stop
SC-1 demo: start
SC-1 demo[13185]: main: start
SC-1 osafamfnd[8729]: NO 'safSu=SC-1,safSg=demo,safApp=demo' Presence State RESTARTING => INSTANTIATED
SC-1 demo[13185]: main: receive poll event
SC-1 demo[13185]: csiSetCallback:
SC-1 osafamfnd[8729]: NO 'safSu=SC-1,safSg=demo,safApp=demo' Component or SU restart probation timer expired
Lock SU (remove work from process).
amf-adm lock safSu=SC-1,safSg=demo,safApp=demo
# syslog
SC-1 osafamfnd[8729]: NO Assigning 'safSi=demo,safApp=demo' QUIESCED to 'safSu=SC-1,safSg=demo,safApp=demo'
SC-1 demo[13185]: main: receive poll event
SC-1 demo[13185]: csiSetCallback:
SC-1 osafamfnd[8729]: NO Assigned 'safSi=demo,safApp=demo' QUIESCED to 'safSu=SC-1,safSg=demo,safApp=demo'
SC-1 osafamfnd[8729]: NO Removing 'safSi=demo,safApp=demo' from 'safSu=SC-1,safSg=demo,safApp=demo'
SC-1 demo[13185]: main: receive poll event
SC-1 demo[13185]: csiRemoveCallback:
SC-1 osafamfnd[8729]: NO Removed 'safSi=demo,safApp=demo' from 'safSu=SC-1,safSg=demo,safApp=demo'
Lock instantiate (stop process).
amf-adm lock-in safSu=SC-1,safSg=demo,safApp=demo
# syslog
SC-1 osafamfnd[8729]: NO 'safSu=SC-1,safSg=demo,safApp=demo' component restart probation timer stopped
SC-1 osafamfnd[8729]: NO 'safSu=SC-1,safSg=demo,safApp=demo' Presence State INSTANTIATED => TERMINATING
SC-1 demo[13185]: main: receive poll event
SC-1 demo[13185]: componentTerminateCallback:
SC-1 demo: stop
SC-1 osafamfnd[8729]: NO 'safSu=SC-1,safSg=demo,safApp=demo' Presence State TERMINATING => UNINSTANTIATED