CVSROOT:        /cvs/cluster
Module name:    cluster
Changes by:     [EMAIL PROTECTED]       2007-11-30 20:06:55

Modified files:
        rgmanager      : ChangeLog 
        rgmanager/src/resources: clusterfs.sh fs.sh ocf-shellfuncs 
                                 service.sh vm.sh 
        rgmanager/src/utils: clulog.c clustat.c clusvcadm.c 

Log message:
        Merges from RHEL5 branch - round 1.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/ChangeLog.diff?cvsroot=cluster&r1=1.59&r2=1.60
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/clusterfs.sh.diff?cvsroot=cluster&r1=1.19&r2=1.20
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/fs.sh.diff?cvsroot=cluster&r1=1.23&r2=1.24
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/ocf-shellfuncs.diff?cvsroot=cluster&r1=1.4&r2=1.5
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/service.sh.diff?cvsroot=cluster&r1=1.11&r2=1.12
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/vm.sh.diff?cvsroot=cluster&r1=1.7&r2=1.8
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/utils/clulog.c.diff?cvsroot=cluster&r1=1.4&r2=1.5
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/utils/clustat.c.diff?cvsroot=cluster&r1=1.35&r2=1.36
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/utils/clusvcadm.c.diff?cvsroot=cluster&r1=1.22&r2=1.23

--- cluster/rgmanager/ChangeLog 2007/08/30 16:09:38     1.59
+++ cluster/rgmanager/ChangeLog 2007/11/30 20:06:55     1.60
@@ -1,3 +1,7 @@
+2007-11-30 Lon Hohberger <lhh at redhat.com>
+       * src/resources/*: Merge from RHEL5 branch.
+       * src/utils/*: Merge from RHEL5 branch.
+
 2007-08-30 Lon Hohberger <lhh at redhat.com>
        * src/daemons/restree.c, rg_state.c: Fix tree-restart bug
        This is another part of #229650
--- cluster/rgmanager/src/resources/clusterfs.sh        2007/05/21 15:58:04     
1.19
+++ cluster/rgmanager/src/resources/clusterfs.sh        2007/11/30 20:06:55     
1.20
@@ -133,6 +133,18 @@
            <content type="string"/>
         </parameter>
 
+       <parameter name="self_fence">
+           <longdesc lang="en">
+               If set and unmounting the file system fails, the node will
+               immediately reboot.  Generally, this is used in conjunction
+               with force-unmount support, but it is not required.
+           </longdesc>
+           <shortdesc lang="en">
+               Seppuku Unmount
+           </shortdesc>
+           <content type="boolean"/>
+       </parameter>
+
        <parameter name="fsid">
            <longdesc lang="en">
                File system ID for NFS exports.  This can be overridden
@@ -279,9 +291,6 @@
        gfs)
                return $OCF_SUCCESS
                ;;
-       ocfs|ocfs2)
-               return $OCF_SUCCESS
-               ;;
        *)
                ocf_log err "File system type $OCF_RESKEY_fstype not supported"
                return $OCF_ERR_ARGS
@@ -798,6 +807,15 @@
                esac
        fi
 
+       if [ -n "$mp" ]; then
+               case ${OCF_RESKEY_self_fence} in
+               $YES_STR)       self_fence=$YES ;;
+               1)              self_fence=$YES ;;
+               *)              self_fence="" ;;
+               esac
+       fi
+
+
        #
        # Always do this hackery on clustered file systems.
        #
@@ -873,8 +891,13 @@
        done # while 
 
        if [ -n "$umount_failed" ]; then
-               ocf_log err "'umount $dev' failed ($mp), error=$ret_val"
+               ocf_log err "'umount $mp' failed, error=$ret_val"
 
+               if [ "$self_fence" ]; then
+                       ocf_log alert "umount failed - REBOOTING"
+                       sync
+                       reboot -fn
+               fi
                return $FAIL
        fi
 
@@ -884,8 +907,20 @@
 
 case $1 in
 start)
-       startFilesystem
-       exit $?
+       declare tries=0
+       declare rv
+
+       while [ $tries -lt 3 ]; do
+               startFilesystem
+               rv=$?
+               if [ rv -eq 0 ]; then
+                       exit 0
+               fi
+
+               ((tries++))
+               sleep 3
+       done
+       exit $rv
        ;;
 stop)
        stopFilesystem
--- cluster/rgmanager/src/resources/fs.sh       2007/05/21 15:58:04     1.23
+++ cluster/rgmanager/src/resources/fs.sh       2007/11/30 20:06:55     1.24
@@ -535,8 +535,8 @@
        do
                #echo "spec=$1 dev=$dev  tmp_dev=$tmp_dev"
                tmp_dev=$(real_device $tmp_dev)
-               tmp_mp=$(trim_trailing_slash $tmp_mp)
-               mp=$(trim_trailing_slash $mp)
+               tmp_mp=${tmp_mp/%\//}  #$(trim_trailing_slash $tmp_mp)
+               mp=${mp/%\//}                  #$(trim_trailing_slash $mp)
 
                if [ -n "$tmp_dev" -a "$tmp_dev" = "$dev" ]; then
                        #
@@ -1149,6 +1149,9 @@
                        umount_failed=
                        done=$YES
                        ;;
+               $FAIL)
+                       return $FAIL
+                       ;;
                $YES)
                        sync; sync; sync
                        ocf_log info "unmounting $mp"
--- cluster/rgmanager/src/resources/ocf-shellfuncs      2007/01/15 19:52:05     
1.4
+++ cluster/rgmanager/src/resources/ocf-shellfuncs      2007/11/30 20:06:55     
1.5
@@ -1,5 +1,5 @@
 #
-#      $Id: ocf-shellfuncs,v 1.4 2007/01/15 19:52:05 lhh Exp $
+#      $Id: ocf-shellfuncs,v 1.5 2007/11/30 20:06:55 lhh Exp $
 #
 #      Common helper functions for the OCF Resource Agents supplied by
 #      heartbeat.
@@ -174,6 +174,10 @@
        esac
 
        pretty_echo $__OCF_PRIO "$__OCF_MSG"
+
+       if [ -z "`which clulog 2> /dev/null`" ]; then
+               return 0
+       fi
        clulog -p $__LOG_PID -n $__LOG_NAME \
                -s $__OCF_PRIO_N "$__OCF_MSG"
 }
--- cluster/rgmanager/src/resources/service.sh  2007/07/31 18:00:25     1.11
+++ cluster/rgmanager/src/resources/service.sh  2007/11/30 20:06:55     1.12
@@ -77,7 +77,7 @@
             <shortdesc lang="en">
                Automatic start after quorum formation
             </shortdesc>
-            <content type="boolean"/>
+            <content type="boolean" default="1"/>
         </parameter>
 
         <parameter name="hardrecovery" reconfig="1">
@@ -92,10 +92,10 @@
             <shortdesc lang="en">
                Reboot if stop phase fails
             </shortdesc>
-            <content type="boolean"/>
+            <content type="boolean" default="0"/>
         </parameter>
 
-        <parameter name="exclusive">
+        <parameter name="exclusive" reconfig="1">
             <longdesc lang="en">
                If set, this resource group will only relocate to
                nodes which have no other resource groups running in the
@@ -109,7 +109,7 @@
             <shortdesc lang="en">
                Exclusive resource group
             </shortdesc>
-            <content type="boolean"/>
+            <content type="boolean" default="0"/>
         </parameter>
 
        <parameter name="nfslock">
@@ -125,7 +125,7 @@
            <shortdesc lang="en">
                Enable NFS lock workarounds
            </shortdesc>
-           <content type="boolean"/>
+           <content type="boolean" default="0"/>
        </parameter>
                 
         <parameter name="recovery" reconfig="1">
@@ -141,7 +141,7 @@
             <shortdesc lang="en">
                Failure recovery policy
             </shortdesc>
-            <content type="string"/>
+            <content type="string" default="restart"/>
         </parameter>
 
         <parameter name="depend">
@@ -154,6 +154,32 @@
             </shortdesc>
             <content type="string"/>
         </parameter>
+
+        <parameter name="max_restarts">
+            <longdesc lang="en">
+               Maximum restarts for this service.
+            </longdesc>
+            <shortdesc lang="en">
+               Maximum restarts for this service.
+            </shortdesc>
+            <content type="string" default="0"/>
+        </parameter>
+
+        <parameter name="restart_expire_time">
+            <longdesc lang="en">
+               Restart expiration time
+            </longdesc>
+            <shortdesc lang="en">
+               Restart expiration time.  A restart is forgotten
+               after this time.  When combined with the max_restarts
+               option, this lets administrators specify a threshold
+               for when to fail over services.  If max_restarts
+               is exceeded in this given expiration time, the service
+               is relocated instead of restarted again.
+            </shortdesc>
+            <content type="string" default="0"/>
+        </parameter>
+
     </parameters>
 
     <actions>
@@ -229,8 +255,8 @@
                exit 0
                ;;
        reconfig)
-               exit 0
-               ;;
+               exit 0
+               ;;
        *)
                exit 0
                ;;
--- cluster/rgmanager/src/resources/vm.sh       2007/08/02 14:53:38     1.7
+++ cluster/rgmanager/src/resources/vm.sh       2007/11/30 20:06:55     1.8
@@ -77,7 +77,39 @@
             <shortdesc lang="en">
                Automatic start after quorum formation
             </shortdesc>
-            <content type="boolean"/>
+            <content type="boolean" default="1"/>
+        </parameter>
+
+        <parameter name="hardrecovery" reconfig="1">
+            <longdesc lang="en">
+               If set to yes, the last owner will reboot if this resource
+               group fails to stop cleanly, thus allowing the resource
+               group to fail over to another node.  Use with caution; a
+               badly-behaved resource could cause the entire cluster to
+               reboot.  This should never be enabled if the automatic
+               start feature is used.
+            </longdesc>
+            <shortdesc lang="en">
+               Reboot if stop phase fails
+            </shortdesc>
+            <content type="boolean" default="0"/>
+        </parameter>
+
+        <parameter name="exclusive" reconfig="1">
+            <longdesc lang="en">
+               If set, this resource group will only relocate to
+               nodes which have no other resource groups running in the
+               event of a failure.  If no empty nodes are available,
+               this resource group will not be restarted after a failure.
+               Additionally, resource groups will not automatically
+               relocate to the node running this resource group.  This
+               option can be overridden by manual start and/or relocate
+               operations.
+            </longdesc>
+            <shortdesc lang="en">
+               Exclusive resource group
+            </shortdesc>
+            <content type="boolean" default="0"/>
         </parameter>
 
         <parameter name="recovery" reconfig="1">
@@ -177,6 +209,51 @@
             <content type="string"/>
         </parameter>
 
+       <parameter name="migrate">
+           <longdesc lang="en">
+               Migration type live or pause, default = live.
+           </longdesc>
+           <shortdesc lang="en">
+               Migration type live or pause, default = live.
+           </shortdesc>
+            <content type="string" default="live"/>
+        </parameter>
+
+        <parameter name="depend">
+            <longdesc lang="en">
+               Top-level service this depends on, in "service:name" format.
+            </longdesc>
+            <shortdesc lang="en">
+               Service dependency; will not start without the specified
+               service running.
+            </shortdesc>
+            <content type="string"/>
+        </parameter>
+
+        <parameter name="max_restarts" reconfig="1">
+            <longdesc lang="en">
+               Maximum restarts for this service.
+            </longdesc>
+            <shortdesc lang="en">
+               Maximum restarts for this service.
+            </shortdesc>
+            <content type="string" default="0"/>
+        </parameter>
+
+        <parameter name="restart_expire_time" reconfig="1">
+            <longdesc lang="en">
+               Restart expiration time
+            </longdesc>
+            <shortdesc lang="en">
+               Restart expiration time.  A restart is forgotten
+               after this time.  When combined with the max_restarts
+               option, this lets administrators specify a threshold
+               for when to fail over services.  If max_restarts
+               is exceeded in this given expiration time, the service
+               is relocated instead of restarted again.
+            </shortdesc>
+            <content type="string" default="0"/>
+        </parameter>
 
     </parameters>
 
@@ -202,11 +279,11 @@
     </actions>
     
     <special tag="rgmanager">
-       <!-- Destroy_on_delete / init_on_add are currently only
-            supported for migratory resources (no children
-            and the 'migrate' action; see above.  Do not try this
-            with normal services -->
-       <attributes maxinstances="1" destroy_on_delete="0" init_on_add="0"/>
+       <!-- Destroy_on_delete / init_on_add are currently only
+            supported for migratory resources (no children
+            and the 'migrate' action; see above.  Do not try this
+            with normal services -->
+        <attributes maxinstances="1" destroy_on_delete="0" init_on_add="0"/>
     </special>
 </resource-agent>
 EOT
@@ -220,7 +297,7 @@
        # controlled externally; the external monitoring app
        # should.
        #
-       declare cmdline="restart=\"never\""
+       declare cmdline="on_shutdown=\"destroy\" on_reboot=\"destroy\" 
on_crash=\"destroy\""
        declare varp val temp
 
        #
@@ -260,6 +337,8 @@
                path)
                        cmdline="$cmdline --path=\"$val\""
                        ;;
+               migrate)
+                       ;;
                *)
                        cmdline="$cmdline $varp=\"$val\""
                        ;;
@@ -285,7 +364,7 @@
        #
        declare cmdline
 
-       do_status && return 0
+       status && return 0
 
        cmdline="`build_xm_cmdline`"
 
@@ -314,7 +393,7 @@
                while [ $timeout -gt 0 ]; do
                        sleep 5
                        ((timeout -= 5))
-                       do_status || return 0
+                       status || return 0
                        while read dom state; do
                                #
                                # State is "stopped".  Kill it.
@@ -355,45 +434,12 @@
 #
 do_status()
 {
-       declare line
-
-       xm list $OCF_RESKEY_name &> /dev/null
-       if [ $? -eq 0 ]; then
-               return $OCF_SUCCESS
-       fi
-       xm list migrating-$OCF_RESKEY_name &> /dev/null
-       if [ $? -eq 1 ]; then
-               return $OCF_NOT_RUNNING
-       fi
-
-       return $OCF_ERR_GENERIC
-
-### NOT REACHED ###
-
-       # virsh doesn't handle migrating domains right now
-       # When this gets fixed, we need to revisit this status
-       # function.
-
-       line=$(virsh domstate $OCF_RESKEY_name)
-       if [ "$line" = "" ]; then
-               return $OCF_NOT_RUNNING
+       xm list $OCF_RESKEY_name &> /dev/null
+       if [ $? -eq 0 ]; then
+               return 0
        fi
-
-       if [ "$line" = "blocked" ]; then
-               return $OCF_SUCCESS
-       elif [ "$line" = "running" ]; then
-               return $OCF_SUCCESS
-       elif [ "$line" = "in shutdown" ]; then
-               return $OCF_SUCCESS
-       elif [ "$line" = "shut off" ]; then
-               return $OCF_NOT_RUNNING
-       fi
-
-       #
-       # Crashed or paused
-       #
-
-       return $OCF_ERR_GENERIC
+       xm list migrating-$OCF_RESKEY_name &> /dev/null
+       return $?
 }
 
 
@@ -412,9 +458,13 @@
 migrate()
 {
        declare target=$1
-       declare errstr rv
+       declare errstr rv migrate_opt
+
+       if [ "$OCF_RESKEY_migrate" = "live" ]; then
+               migrate_opt="-l"
+       fi
        
-       err=$(xm migrate $OCF_RESKEY_name $target 2>&1 | head -1)
+       err=$(xm migrate $migrate_opt $OCF_RESKEY_name $target 2>&1 | head -1)
        rv=$?
 
        if [ $rv -ne 0 ]; then
@@ -446,7 +496,7 @@
                exit $?
                ;;
        kill)
-               do_stop destroy
+               stop destroy
                exit $?
                ;;
        recover|restart)
@@ -457,7 +507,7 @@
                exit $?
                ;;
        migrate)
-               do_migrate $2 # Send VM to this node
+               migrate $2 # Send VM to this node
                exit $?
                ;;
        reload)
@@ -478,6 +528,6 @@
                ;;
        *)
                echo "usage: $0 
{start|stop|restart|status|reload|reconfig|meta-data|validate-all}"
-               exit $OCF_ERR_UNIMPLEMENTED
+               exit 1
                ;;
 esac
--- cluster/rgmanager/src/utils/clulog.c        2007/03/27 19:33:20     1.4
+++ cluster/rgmanager/src/utils/clulog.c        2007/11/30 20:06:55     1.5
@@ -92,9 +92,6 @@
     if (argc < 4)
        usage(argv[0]);
 
-    /* ../daemons/log.c */
-    configure_logging(-1);
-
     while ((opt = getopt(argc, argv, "f:l:s:hp:n:")) != -1) {
        switch (opt) {
        case 'l':
@@ -133,9 +130,10 @@
     if (!cmdline_loglevel) {
        /*
         * Let's see what loglevel the SM is running at.
-        * TODO Get rgmgr log level
+        * If ccsd's not available, use default.
         */
-       clu_set_loglevel(LOGLEVEL_DFLT);
+       if (configure_logging(-1) < 0)
+               clu_set_loglevel(LOGLEVEL_DFLT);
     }
     result = clulog_pid(severity, pid, progname, logmsg);
     free(progname);
--- cluster/rgmanager/src/utils/clustat.c       2007/09/19 10:56:08     1.35
+++ cluster/rgmanager/src/utils/clustat.c       2007/11/30 20:06:55     1.36
@@ -21,6 +21,7 @@
 #define FLAG_RGMGR 0x4
 #define FLAG_NOCFG 0x8 /* Shouldn't happen */
 #define FLAG_QDISK 0x10
+#define FLAG_RGMAST 0x20 /* for RIND */
 
 #define RG_VERBOSE 0x1
 
@@ -30,6 +31,8 @@
 
 
 int running = 1;
+int dimx = 80, dimy = 24, stdout_is_tty = 0;
+int rgmanager_master_present = 0;
 
 void
 term_handler(int sig)
@@ -44,6 +47,28 @@
 } rg_state_list_t;
 
 
+int
+rg_name_sort(const void *left, const void *right)
+{
+       return strcmp(((rg_state_t *)left)->rs_name,
+                     ((rg_state_t *)right)->rs_name);
+}
+
+
+int
+member_id_sort(const void *left, const void *right)
+{
+       cman_node_t *l = (cman_node_t *)left;
+       cman_node_t *r = (cman_node_t *)right;
+
+       if (l->cn_nodeid < r->cn_nodeid)
+               return -1;
+       if (l->cn_nodeid > r->cn_nodeid)
+               return 1;
+       return 0;
+}
+
+
 void
 flag_rgmanager_nodes(cluster_member_list_t *cml)
 {
@@ -55,7 +80,7 @@
        struct timeval tv;
 
        if (msg_open(MSG_SOCKET, 0, 0, &ctx, 10) < 0) {
-               perror("msg_open");
+               //perror("msg_open");
                return;
        }
 
@@ -121,6 +146,10 @@
                        if (cml->cml_members[n].cn_nodeid != msgp->gh_arg1)
                                continue;
                        cml->cml_members[n].cn_member |= FLAG_RGMGR;
+                       if (msgp->gh_arg2) {
+                               rgmanager_master_present = 1;
+                               cml->cml_members[n].cn_member |= FLAG_RGMAST;
+                       }
                }
 
                free(msgp);
@@ -147,7 +176,7 @@
        struct timeval tv;
 
        if (msg_open(MSG_SOCKET, 0, 0, &ctx, 10) < 0) {
-               perror("msg_open");
+               //perror("msg_open");
                return NULL;
        }
 
@@ -248,6 +277,9 @@
                return NULL;
        }
 
+       qsort(rsl->rgl_states, rsl->rgl_count, sizeof(rg_state_t),
+             rg_name_sort);
+
        return rsl;
 }
 
@@ -270,9 +302,11 @@
                sleep(1);
        
        x = 0;
+       memset(buf, 0, sizeof(buf));
+
        while (++x) {
                name = NULL;
-               snprintf(buf, sizeof(buf),
+               snprintf(buf, sizeof(buf)-1,
                        "/cluster/clusternodes/clusternode[%d]/@name", x);
 
                if (ccs_get(desc, buf, &name) != 0)
@@ -307,7 +341,7 @@
                free(name);
 
                /* Add node ID */
-               snprintf(buf, sizeof(buf),
+               snprintf(buf, sizeof(buf)-1,
                         "/cluster/clusternodes/clusternode[%d]/@nodeid", x);
                if (ccs_get(desc, buf, &name) == 0) {
                        nodes[x-1].cn_nodeid = atoi(name);
@@ -320,6 +354,9 @@
        ccs_disconnect(desc);
        ret->cml_members = nodes;
 
+       qsort(ret->cml_members, ret->cml_count, sizeof(cman_node_t),
+             member_id_sort);
+
        return ret;
 }
 
@@ -413,68 +450,71 @@
 
 
 void
-_txt_rg_state(rg_state_t *rs, cluster_member_list_t *members, int flags)
+_txt_rg_state(rg_state_t *rs, cluster_member_list_t *members, int flags,
+             char *fmt_buf, int ns)
 {
-       char owner[31];
-       char flags_string[255] = "";
+       char owner[MAXHOSTNAMELEN+1];
+       char owner_fmt[16];
+       char *name = rs->rs_name, *ptr;
+       int l;
+
+       if (stdout_is_tty) {
+               ptr = strchr(rs->rs_name, ':');
+               if (ptr) {
+                       l = (int)(ptr - rs->rs_name);
+                       if ((l == 7) &&  /* strlen("service") == 7 */
+                           (strncmp(rs->rs_name, "service", l) == 0)) 
+                               name = ptr+1;
+               }
+       }
+
+       memset(owner, 0, sizeof(owner));
+       memset(owner_fmt, 0, sizeof(owner_fmt));
 
        if (rs->rs_state == RG_STATE_STOPPED ||
            rs->rs_state == RG_STATE_DISABLED ||
            rs->rs_state == RG_STATE_ERROR ||
            rs->rs_state == RG_STATE_FAILED) {
 
-               snprintf(owner, sizeof(owner), "(%-.28s)",
+               snprintf(owner_fmt, sizeof(owner_fmt)-1, "(%%-.%ds)", ns-2);
+               snprintf(owner, sizeof(owner)-1, owner_fmt,
                         my_memb_id_to_name(members, rs->rs_last_owner));
        } else {
 
-               snprintf(owner, sizeof(owner), "%-.30s",
+               snprintf(owner_fmt, sizeof(owner_fmt)-1, "%%-.%ds", ns);
+               snprintf(owner, sizeof(owner)-1, owner_fmt,
                         my_memb_id_to_name(members, rs->rs_owner));
        }
-       rg_flags_str(flags_string, sizeof(flags_string), rs->rs_flags, ", ");
-       printf("  %-20.20s %-30.30s %-16.16s ",
-              rs->rs_name,
+       
+       printf(fmt_buf,
+              name,
               owner,
               rg_state_str(rs->rs_state));
-       if(strlen(flags_string))
-               printf ("%-30.30s\n", flags_string);
-       else
-               printf("\n");
 }
 
 
 void
 _txt_rg_state_v(rg_state_t *rs, cluster_member_list_t *members, int flags)
 {
-       char flags_string[255] = "";
-       time_t transtime = rs->rs_transition;
-
-       rg_flags_str(flags_string, sizeof(flags_string), rs->rs_flags, ", ");
-
        printf("Service Name      : %s\n", rs->rs_name);
        printf("  Current State   : %s (%d)\n",
               rg_state_str(rs->rs_state), rs->rs_state);
-       if (rs->rs_flags)
-               printf("  Flags           : %s (%d)\n",
-                      flags_string, rs->rs_flags);
-       else
-               printf("  Flags           : none (%d)\n",
-                      rs->rs_flags);
        printf("  Owner           : %s\n",
               my_memb_id_to_name(members, rs->rs_owner));
        printf("  Last Owner      : %s\n",
               my_memb_id_to_name(members, rs->rs_last_owner));
        printf("  Last Transition : %s\n",
-              ctime(&transtime));
+              ctime((time_t *)(&rs->rs_transition)));
 }
 
 
 void
-txt_rg_state(rg_state_t *rs, cluster_member_list_t *members, int flags)
+txt_rg_state(rg_state_t *rs, cluster_member_list_t *members, int flags, char 
*fmt_buf, int ns)
 {
        if (flags & RG_VERBOSE) 
                _txt_rg_state_v(rs, members, flags);
        else
-               _txt_rg_state(rs, members, flags);
+               _txt_rg_state(rs, members, flags, fmt_buf, ns);
 }
 
 
@@ -482,12 +522,10 @@
 xml_rg_state(rg_state_t *rs, cluster_member_list_t *members, int flags)
 {
        char time_str[32];
-       char flags_string[255] = "";
-       time_t transtime = rs->rs_transition;
        int x;
 
        /* Chop off newlines */
-       ctime_r((time_t *)&transtime, time_str);
+       ctime_r((time_t *)&rs->rs_transition, time_str);
        for (x = 0; time_str[x]; x++) {
                if (time_str[x] < 32) {
                        time_str[x] = 0;
@@ -495,15 +533,12 @@
                }
        }
 
-       printf("    <group name=\"%s\" state=\"%d\" state_str=\"%s\""
-              " flags=\"%d\" flags_str=\"%s\""
+       printf("    <group name=\"%s\" state=\"%d\" state_str=\"%s\" "
               " owner=\"%s\" last_owner=\"%s\" restarts=\"%d\""
               " last_transition=\"%llu\" last_transition_str=\"%s\"/>\n",
               rs->rs_name,
               rs->rs_state,
               rg_state_str(rs->rs_state),
-              rs->rs_flags,
-              rg_flags_str(flags_string, sizeof(flags_string), rs->rs_flags, " 
"),
               my_memb_id_to_name(members, rs->rs_owner),
               my_memb_id_to_name(members, rs->rs_last_owner),
               rs->rs_restarts,
@@ -512,11 +547,37 @@
 }
 
 
+void
+build_service_format(char *buf, int buflen, int cols, int *ns)
+{
+       /* Based on 80 columns */
+       int svcsize = 30;
+       int nodesize = 30;
+       int statsize = 14;      /* uninitialized */
+       int pad = 6;            /* Spaces and such; newline */
+
+       svcsize = (cols - (statsize + pad)) / 2;
+       nodesize = (cols - (statsize + pad)) / 2;
+       if (svcsize > MAXHOSTNAMELEN)
+               svcsize = MAXHOSTNAMELEN;
+       if (nodesize > MAXHOSTNAMELEN)
+               nodesize = MAXHOSTNAMELEN;
+
+       memset(buf, 0, buflen);
+       snprintf(buf, buflen-1, "  %%-%d.%ds %%-%d.%ds %%-%d.%ds\n",
+                svcsize, svcsize, nodesize, nodesize, statsize,
+                statsize);
+
+       *ns = nodesize;
+}
+
+
 int
 txt_rg_states(rg_state_list_t *rgl, cluster_member_list_t *members, 
              char *svcname, int flags)
 {
-       int x, ret = 0;
+       int x, ret = 0, ns;
+       char fmt_buf[80];
 
        if (!rgl || !members)
                return -1;
@@ -524,11 +585,14 @@
        if (svcname)
                ret = -1;
 
+       build_service_format(fmt_buf, sizeof(fmt_buf), dimx, &ns);
+
        if (!(flags & RG_VERBOSE)) {
-               printf("  %-20.20s %-30.30s %-16.16s %-30.30s\n",
-                      "Service Name", "Owner (Last)", "State", "Flags");
-               printf("  %-20.20s %-30.30s %-16.16s %-30.30s\n",
-                      "------- ----", "----- ------", "-----", "-----");
+
+               printf(fmt_buf,
+                      "Service Name", "Owner (Last)", "State");
+               printf(fmt_buf,
+                      "------- ----", "----- ------", "-----");
        } else {
                printf("Service Information\n"
                       "------- -----------\n\n");
@@ -538,7 +602,7 @@
                if (svcname &&
                    strcmp(rgl->rgl_states[x].rs_name, svcname))
                        continue;
-               txt_rg_state(&rgl->rgl_states[x], members, flags);
+               txt_rg_state(&rgl->rgl_states[x], members, flags, fmt_buf, ns);
                if (svcname) {
                        switch (rgl->rgl_states[x].rs_state) {
                        case RG_STATE_STARTING:
@@ -551,7 +615,7 @@
                        }
                }
        }
-       
+
        return ret;
 }
 
@@ -604,6 +668,24 @@
 
 
 void
+txt_cluster_info(cman_cluster_t *ci) 
+{
+       time_t now = time(NULL);
+
+       printf("Cluster Status for %s @ %s",
+              ci->ci_name, ctime(&now));
+}
+
+
+void
+xml_cluster_info(cman_cluster_t *ci) 
+{
+       printf("  <cluster name=\"%s\" id=\"%d\" generation=\"%d\"/>\n",
+              ci->ci_name, ci->ci_number, ci->ci_generation);
+}
+
+
+void
 xml_quorum_state(int qs)
 {
        /* XXX output groupmember attr (carry over from RHCS4) */
@@ -619,15 +701,31 @@
        } else {
                printf(" groupmember=\"0\"");
        }
+
        printf("/>\n");
 }
 
+void
+build_member_format(char *buf, int buflen, int cols)
+{
+       /* Based on 80 columns */
+       int nodesize = 40;
+
+       nodesize = (cols / 2);
+       if (nodesize > MAXHOSTNAMELEN)
+               nodesize = MAXHOSTNAMELEN;
+
+       memset(buf, 0, buflen);
+       snprintf(buf, buflen-1, "  %%-%d.%ds ",
+                nodesize, nodesize);
+}
+
 
 void
-txt_member_state(cman_node_t *node)
+txt_member_state(cman_node_t *node, char *fmt_buf)
 {
-       printf("  %-34.34s %4d ", node->cn_name,
-              node->cn_nodeid);
+       printf(fmt_buf, node->cn_name);
+       printf("%4d ", node->cn_nodeid);
 
        if (node->cn_member & FLAG_UP)
                printf("Online");
@@ -640,15 +738,21 @@
        if (node->cn_member & FLAG_NOCFG)
                printf(", Estranged");
        
-       if (node->cn_member & FLAG_RGMGR)
-               printf(", rgmanager");
+       if (node->cn_member & FLAG_RGMGR) {
+               if (rgmanager_master_present) {
+                       if (node->cn_member & FLAG_RGMAST) 
+                               printf(", RG-Master");
+                       else
+                               printf(", RG-Worker");
+               } else {
+                       printf(", rgmanager");
+               }
+       }
        
        if (node->cn_member & FLAG_QDISK)
                printf(", Quorum Disk");
 
        printf("\n");
-               
-
 }
 
 
@@ -656,12 +760,14 @@
 xml_member_state(cman_node_t *node)
 {
        printf("    <node name=\"%s\" state=\"%d\" local=\"%d\" "
-              "estranged=\"%d\" rgmanager=\"%d\" qdisk=\"%d\" 
nodeid=\"0x%08x\"/>\n",
+              "estranged=\"%d\" rgmanager=\"%d\" rgmanager_master=\"%d\" "
+              "qdisk=\"%d\" nodeid=\"0x%08x\"/>\n",
               node->cn_name,
               !!(node->cn_member & FLAG_UP),
               !!(node->cn_member & FLAG_LOCAL),
               !!(node->cn_member & FLAG_NOCFG),
               !!(node->cn_member & FLAG_RGMGR),
+              !!(node->cn_member & FLAG_RGMAST),
               !!(node->cn_member & FLAG_QDISK),
               (uint32_t)((node->cn_nodeid      )&0xffffffff));
 }
@@ -670,6 +776,7 @@
 int
 txt_member_states(cluster_member_list_t *membership, char *name)
 {
+       char buf[80];
        int x, ret = 0;
 
        if (!membership) {
@@ -677,13 +784,17 @@
                return -1;
        }
 
-       printf("  %-34.34s %-4.4s %s\n", "Member Name", "ID", "Status");
-       printf("  %-34.34s %-4.4s %s\n", "------ ----", "----", "------");
+       build_member_format(buf, sizeof(buf), dimx);
+
+       printf(buf, "Member Name");
+       printf("%-4.4s %s\n", "ID", "Status");
+       printf(buf, "------ ----");
+       printf("%-4.4s %s\n", "----", "------");
 
        for (x = 0; x < membership->cml_count; x++) {
                if (name && strcmp(membership->cml_members[x].cn_name, name))
                        continue;
-               txt_member_state(&membership->cml_members[x]);
+               txt_member_state(&membership->cml_members[x], buf);
                ret = !(membership->cml_members[x].cn_member & FLAG_UP);
        }
 
@@ -717,13 +828,15 @@
 
 
 int 
-txt_cluster_status(int qs, cluster_member_list_t *membership,
+txt_cluster_status(cman_cluster_t *ci,
+                  int qs, cluster_member_list_t *membership,
                   rg_state_list_t *rgs, char *name, char *svcname, 
                   int flags)
 {
        int ret;
        
        if (!svcname && !name) {
+               txt_cluster_info(ci);
                txt_quorum_state(qs);
                if (!membership) {
                        /* XXX Check for rgmanager?! */
@@ -738,12 +851,14 @@
                return ret;
        if (!name || (name && svcname))
                ret = txt_rg_states(rgs, membership, svcname, flags);
+
        return ret;
 }
 
 
 int
-xml_cluster_status(int qs, cluster_member_list_t *membership,
+xml_cluster_status(cman_cluster_t *ci, int qs,
+                  cluster_member_list_t *membership,
                   rg_state_list_t *rgs, char *name, char *svcname,
                   int flags)
 {
@@ -768,6 +883,8 @@
        }
 
        if (!svcname && !name)
+               xml_cluster_info(ci);
+       if (!svcname && !name)
                xml_quorum_state(qs);
        if (!svcname || (name && svcname)) 
                ret1 = xml_member_states(membership, name);
@@ -862,7 +979,9 @@
        int local_node_id;
        int fast = 0;
        int runtype = 0;
+       time_t now;
        cman_handle_t ch = NULL;
+       cman_cluster_t ci;
 
        int refresh_sec = 0, errors = 0;
        int opt, xml = 0, flags = 0;
@@ -900,8 +1019,9 @@
                case 's':
                        rg_name = optarg;
                        if (!strchr(rg_name,':')) {
+                               memset(real_rg_name, 0, sizeof(real_rg_name));
                                snprintf(real_rg_name,
-                                        sizeof(real_rg_name),
+                                        sizeof(real_rg_name)-1,
                                         "service:%s", rg_name);
                                rg_name = real_rg_name;
                        }
@@ -941,7 +1061,7 @@
        /* Connect & grab all our info */
        ch = cman_init(NULL);
        if (!ch) {
-               printf("CMAN is not running.\n");
+               perror("Could not connect to CMAN");
                return 1;
        }
 
@@ -952,8 +1072,12 @@
                ret = !(cman_is_quorate(ch));
                goto cleanup;
        case VERSION_ONLY:
+#ifdef RELEASE_VERSION
                printf("%s version %s\n", basename(argv[0]),
                       RELEASE_VERSION);
+#else
+               printf("%s version DEVEL\n", basename(argv[0]));
+#endif
                if (!ch)
                       break;
                goto cleanup;
@@ -974,6 +1098,16 @@
        signal(SIGINT, term_handler);
        signal(SIGTERM, term_handler);
 
+       if (isatty(STDOUT_FILENO)) {
+               stdout_is_tty = 1;
+               setupterm((char *) 0, STDOUT_FILENO, (int *) 0);
+               dimx = tigetnum("cols");
+               dimy = tigetnum("lines");
+       }
+
+       memset(&ci, 0, sizeof(ci));
+       cman_get_cluster(ch, &ci);
+
        while (1) {
                qs = cman_is_quorate(ch);
                membership = build_member_list(ch, &local_node_id);
@@ -985,16 +1119,16 @@
                }
 
                if (refresh_sec) {
-                       setupterm((char *) 0, STDOUT_FILENO, (int *) 0);
                        tputs(clear_screen, lines > 0 ? lines : 1, putchar);
+                       now = time(NULL);
                }
 
                if (xml)
-                       ret = xml_cluster_status(qs, membership, rgs,
+                       ret = xml_cluster_status(&ci, qs, membership, rgs,
                                                 member_name, rg_name,
                                                 flags);
                else
-                       ret = txt_cluster_status(qs, membership, rgs,
+                       ret = txt_cluster_status(&ci, qs, membership, rgs,
                                                 member_name, rg_name,
                                                 flags);
 
@@ -1011,5 +1145,6 @@
 
 cleanup:
        cman_finish(ch);
+
        return ret;
 }
--- cluster/rgmanager/src/utils/clusvcadm.c     2007/08/22 08:58:47     1.22
+++ cluster/rgmanager/src/utils/clusvcadm.c     2007/11/30 20:06:55     1.23
@@ -311,7 +311,11 @@
                        node_specified = 1;
                        break;
                case 'v':
-                       printf("%s\n",RELEASE_VERSION);
+#ifdef RELEASE_VERSION
+                       printf("%s\n", RELEASE_VERSION);
+#else
+                       printf("DEVEL\n");
+#endif
                        return 0;
                case 'Z':
                        actionstr = "freezing";

Reply via email to