![]() ![]() ![]() |
Chapter 4: Sample Clinfo Client Program
This chapter lists a sample clinfo.rc script and the source code of a C program called from that script. This program reports the status of each service network interface on a given cluster node, and of the node itself.
Overview
The sample Clinfo client application program, cl_status, is shown here within the context of a typical customized clinfo.rc script. clinfo.rc is the HACMP for AIX 5L script run by Clinfo following cluster topology changes. The clinfo.rc script is listed first, followed by the cl_status program. The script and the program are commented to explain their usage.
Sample Customized clinfo.rc Script
#!/bin/ksh ############################################################################## # Filename: /usr/sbin/cluster/etc/clinfo.rc # # Description: clinfo.rc is run by clinfo on clients following cluster # topology changes. This particular example demonstrates # user process management for a highly available database in a # two-node primary/standby configuration. Most database # client programs are state-dependent, and require #restart following a node failure. This example provides # user notification and application shutdown during # appropriate topology changes. # ############################################################################# ############################################################################## # Grab Parameters Passed ############################################################################## EVENT=$1 # action, one of {join, fail, swap} INTERFACE=$2 # target address label CLUSTERNAME="cluster1" # cluster name NODENAME="victor" # primary node name WATCHIF="svc_en0" # interface to monitor ############################################################################## # Name: _arp_flush # This function flushes the entire arp cache. # Arguments: none # Return Value: none ############################################################################## _arp_flush() { for IPADDR in $(/etc/arp -a |/bin/sed -e 's/^.*(.*).*$//' -e /incomplete/d) do /etc/arp -d $IPADDR done } ############################################################################## # # Name: _kill_user_procs # # This function kills user processes associated with the specified # interface. # # Arguments: interface # Return Value: none ############################################################################## _kill_user_procs() { print _kill_user_procs # place commands appropriate to the database in use here } # The main if statement disregards status changes for all interfaces except # WATCHIF, which in this example is svc_en0. if [[ "$INTERFACE" = "WATCHIF" ]] then case "$EVENT" in "join") # interface label $INTERFACE has joined the cluster # perform necessary activity here, such as user notification, restoration of user access, # and arp cache flushing. exit 0 ;; "fail")# Use api calls in cl_status to determine if interface # failure is a result of node failure. CLSTAT_MSG=$(cl_status $CLUSTERNAME $NODENAME) CLSTAT_RETURN=$? # return code from cl_status case "$CLSTAT_RETURN" in 0) # Node UP # Notify users of application availability wall "Primary database is now available." # flush arp cache _arp_flush ;; 1) # Node DOWN # Notify users of topology change and restart requirement touch /etc/nologin # prevent new logins wall "Primary database node failure. Please login again 2 minutes" sleep 10 # Kill all processes attached to WATCHIF interface _kill_user_procs $WATCHIF # flush arp cache _ arp_flush rm -f /etc/nologin # enable logins ;; *) # Indeterminate node state # flush arp cache _arp_flush exit 1 ;; esac # case $CLSTAT_RETURN ;; "swap")# interface has been swapped # flush arp cache. _arp_flush ;; esac # case $EVENT else # event handling for other interfaces here, if desired /bin/true ficl_status.c
/* * Program: cl_status.c * * Purpose: For systems running the clinfo daemon as a client, cl_status * will determine if the node for the network interface passed * to it is active in the cluster. * * Usage: [path/]cl_status clustername nodename * * Returns: 0 = Node up * 1 = Node down * 2 = ERROR - Status Unavailable * */ #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <cluster/clinfo.h> #include <strings.h> void usage() { printf("usage: cl_status clustername nodename"); printf("Returns status of node in HACMP cluster."); } int main(int argc, char *argv[]) { int clusterid, node_status; char *clustername, *nodename; if(argc < 3) { /* incorrect syntax to cl_status call */ usage(); exit(2); } clustername = strdup(argv[1]); if (strlen(clustername) > CL_MAXNAMELEN) { printf("error: clustername exceeds maximum length of %i characters", CL_MAXNAMELEN); exit(2); } nodename = strdup(argv[2]); if (strlen(nodename) > CL_MAXNAMELEN) { printf("error: nodename exceeds maximum length of %i characters", CL_MAXNAMELEN); exit(2); } /* convert clustername (string) to clusterid (non-negative integer) */ clusterid = cl_getclusterid(clustername); switch(clusterid) { case CLE_SYSERR: perror("system error"); exit(5); break; case CLE_NOCLINFO: cl_perror(clusterid, "error"); exit(5); break; case CLE_BADARGS: case CLE_IVCLUSTERNAME: /* typically a usage error */ cl_perror(clusterid, "error"); usage(); exit(2); default: /* valid clusterid returned */ ; } node_status = cl_isnodeavail(clusterid, nodename); switch (node_status) { case CLE_OK: /* Node up */ printf(“node %s up”, nodename); exit(0); break; case CLE_IVNODENAME: /* “Illegal node name” */ cl_perror(node_status, "node unavailable"); exit(2); break; default: cl_perror(node_status, "node unavailable"); exit(1); } }
![]() ![]() ![]() |