Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F3151651
clustat.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
22 KB
Referenced Files
None
Subscribers
None
clustat.c
View Options
#include <members.h>
#include <message.h>
#include <msgsimple.h>
#include <resgroup.h>
#include <platform.h>
#include <libgen.h>
#include <ncurses.h>
#include <term.h>
#include <rg_types.h>
#include <termios.h>
#include <ccs.h>
#include <libcman.h>
#include <signal.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define FLAG_UP 0x1
#define FLAG_LOCAL 0x2
#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
#define QSTAT_ONLY 1
#define VERSION_ONLY 2
#define NODEID_ONLY 3
int running = 1;
int dimx = 80, dimy = 24, stdout_is_tty = 0;
int rgmanager_master_present = 0;
void
term_handler(int sig)
{
running = 0;
}
typedef struct {
int rgl_count;
rg_state_t rgl_states[0];
} 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)
{
msgctx_t ctx;
int max = 0, n;
generic_msg_hdr *msgp;
fd_set rfds;
struct timeval tv;
if (msg_open(MSG_SOCKET, 0, 0, &ctx, 10) < 0) {
//perror("msg_open");
return;
}
msg_send_simple(&ctx, RG_STATUS_NODE, 0, 0);
while (1) {
FD_ZERO(&rfds);
msg_fd_set(&ctx, &rfds, &max);
tv.tv_sec = 10;
tv.tv_usec = 0;
n = select(max+1, &rfds, NULL, NULL, &tv);
if (n == 0) {
fprintf(stderr, "Timed out waiting for a response "
"from Resource Group Manager\n");
break;
}
if (n < 0) {
if (errno == EAGAIN ||
errno == EINTR)
continue;
fprintf(stderr, "Failed to receive "
"service data: select: %s\n",
strerror(errno));
break;
}
n = msg_receive_simple(&ctx, &msgp, tv.tv_sec);
if (n < 0) {
if (errno == EAGAIN)
continue;
perror("msg_receive_simple");
break;
}
if (n < sizeof(generic_msg_hdr)) {
printf("Error: Malformed message\n");
break;
}
if (!msgp) {
printf("Error: no message?!\n");
break;
}
swab_generic_msg_hdr(msgp);
if (msgp->gh_command == RG_FAIL) {
printf("Member states unavailable: %s\n",
rg_strerror(msgp->gh_arg1));
free(msgp);
msg_close(&ctx);
return;
}
if (msgp->gh_command == RG_SUCCESS) {
free(msgp);
break;
}
for (n = 0; n < cml->cml_count; n++) {
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);
msgp = NULL;
}
msg_send_simple(&ctx, RG_SUCCESS, 0, 0);
msg_close(&ctx);
return;
}
rg_state_list_t *
rg_state_list(int local_node_id, int fast)
{
msgctx_t ctx;
int max = 0, n, x;
rg_state_list_t *rsl = NULL;
generic_msg_hdr *msgp = NULL;
rg_state_msg_t *rsmp = NULL;
fd_set rfds;
struct timeval tv;
if (msg_open(MSG_SOCKET, 0, 0, &ctx, 10) < 0) {
//perror("msg_open");
return NULL;
}
msg_send_simple(&ctx, RG_STATUS, fast, 0);
rsl = malloc(sizeof(rg_state_list_t));
if (!rsl) {
printf("Try again, out of memory\n");
exit(0);
}
memset(rsl, 0, sizeof(rg_state_list_t));
while (1) {
FD_ZERO(&rfds);
msg_fd_set(&ctx, &rfds, &max);
tv.tv_sec = 10;
tv.tv_usec = 0;
n = select(max+1, &rfds, NULL, NULL, &tv);
if (n == 0) {
fprintf(stderr, "Timed out waiting for a response "
"from Resource Group Manager\n");
break;
}
if (n < 0) {
if (errno == EAGAIN ||
errno == EINTR)
continue;
fprintf(stderr, "Failed to receive "
"service data: select: %s\n",
strerror(errno));
break;
}
n = msg_receive_simple(&ctx, &msgp, tv.tv_sec);
if (n < 0) {
if (errno == EAGAIN)
continue;
perror("msg_receive_simple");
break;
}
if (n < sizeof(generic_msg_hdr)) {
printf("Error: Malformed message\n");
break;
}
if (!msgp) {
printf("Error: no message?!\n");
break;
}
swab_generic_msg_hdr(msgp);
if (msgp->gh_command == RG_FAIL) {
printf("Service states unavailable: %s\n",
rg_strerror(msgp->gh_arg1));
msg_close(&ctx);
return NULL;
}
if (msgp->gh_command == RG_SUCCESS) {
free(msgp);
break;
}
if (n < sizeof(*rsmp)) {
msg_close(&ctx);
return NULL;
}
rsmp = (rg_state_msg_t *)msgp;
swab_rg_state_t(&rsmp->rsm_state);
rsl->rgl_count++;
x = sizeof(rg_state_list_t) +
(sizeof(rg_state_t) * rsl->rgl_count);
rsl = realloc(rsl, x);
if (!rsl) {
printf("Try again; out of RAM\n");
exit(1);
}
memcpy(&rsl->rgl_states[(rsl->rgl_count-1)],
&rsmp->rsm_state, sizeof(rg_state_t));
free(msgp);
msgp = NULL;
}
msg_send_simple(&ctx, RG_SUCCESS, 0, 0);
msg_close(&ctx);
if (!rsl->rgl_count) {
free(rsl);
return NULL;
}
qsort(rsl->rgl_states, rsl->rgl_count, sizeof(rg_state_t),
rg_name_sort);
return rsl;
}
cluster_member_list_t *ccs_member_list(void)
{
int desc;
int x;
char buf[128];
char *name;
cluster_member_list_t *ret = NULL;
cman_node_t *nodes = NULL;
desc = ccs_connect();
if (desc < 0) {
return NULL;
}
while ((ret = malloc(sizeof(*ret))) == NULL)
sleep(1);
x = 0;
memset(buf, 0, sizeof(buf));
while (++x) {
name = NULL;
snprintf(buf, sizeof(buf)-1,
"/cluster/clusternodes/clusternode[%d]/@name", x);
if (ccs_get(desc, buf, &name) != 0)
break;
if (!name)
break;
if (!strlen(name)) {
free(name);
continue;
}
if (!nodes) {
nodes = malloc(x * sizeof(cman_node_t));
if (!nodes) {
perror("malloc");
ccs_disconnect(desc);
exit(1);
}
} else {
nodes = realloc(nodes, x * sizeof(cman_node_t));
if (!nodes) {
perror("realloc");
ccs_disconnect(desc);
exit(1);
}
}
memset(&nodes[x-1], 0, sizeof(cman_node_t));
strncpy(nodes[x-1].cn_name, name,
sizeof(nodes[x-1].cn_name));
free(name);
/* Add node ID */
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);
free(name);
}
ret->cml_count = x;
}
ccs_disconnect(desc);
ret->cml_members = nodes;
qsort(ret->cml_members, ret->cml_count, sizeof(cman_node_t),
member_id_sort);
return ret;
}
void
flag_nodes(cluster_member_list_t *all, cluster_member_list_t *these,
uint8_t flag)
{
int x;
cman_node_t *m;
for (x=0; x<all->cml_count; x++) {
m = memb_name_to_p(these, all->cml_members[x].cn_name);
if (m && m->cn_member) {
all->cml_members[x].cn_nodeid = m->cn_nodeid;
all->cml_members[x].cn_member |= flag;
}
}
}
cluster_member_list_t *
add_missing(cluster_member_list_t *all, cluster_member_list_t *these)
{
int x, y, addflag;
cman_node_t *m, *nn;
if (!these)
return all;
for (x=0; x<these->cml_count; x++) {
m = NULL;
for (y = 0; y < all->cml_count; y++) {
if (!strcmp(all->cml_members[y].cn_name,
these->cml_members[x].cn_name))
m = &all->cml_members[y];
}
if (!m) {
all->cml_members = realloc(all->cml_members,
(all->cml_count+1) *
sizeof(cman_node_t));
if (!all->cml_members) {
perror("realloc");
exit(1);
}
nn = &all->cml_members[all->cml_count];
memcpy(nn, &these->cml_members[x],
sizeof(cman_node_t));
if (nn->cn_nodeid == 0) { /* quorum disk? */
addflag = FLAG_QDISK;
} else {
addflag = FLAG_NOCFG;
}
if (nn->cn_member) {
nn->cn_member = FLAG_UP | addflag;
} else {
nn->cn_member = addflag;
}
++all->cml_count;
}
}
return all;
}
char *
my_memb_id_to_name(cluster_member_list_t *members, int memb_id)
{
int x;
if (memb_id == 0)
return "none";
for (x = 0; x < members->cml_count; x++) {
if (members->cml_members[x].cn_nodeid == memb_id)
return members->cml_members[x].cn_name;
}
return "unknown";
}
void
_txt_rg_state(rg_state_t *rs, cluster_member_list_t *members, int flags,
int svcsize, int nodesize, int statsize)
{
char owner[MAXHOSTNAMELEN+1];
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));
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)-1, "(%-.*s)", nodesize-2,
my_memb_id_to_name(members, rs->rs_last_owner));
} else {
snprintf(owner, sizeof(owner)-1, "%-.*s", nodesize,
my_memb_id_to_name(members, rs->rs_owner));
}
printf(" %-*.*s %-*.*s %-*.*s\n",
svcsize, svcsize, rs->rs_name,
nodesize, nodesize, owner,
statsize, statsize, rg_state_str(rs->rs_state));
}
void
_txt_rg_state_v(rg_state_t *rs, cluster_member_list_t *members, int flags)
{
time_t t;
printf("Service Name : %s\n", rs->rs_name);
printf(" Current State : %s (%d)\n",
rg_state_str(rs->rs_state), rs->rs_state);
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));
t = (time_t)(rs->rs_transition);
printf(" Last Transition : %s\n", ctime(&t));
}
void
txt_rg_state(rg_state_t *rs, cluster_member_list_t *members, int flags, int svcsize,
int nodesize, int statsize)
{
if (flags & RG_VERBOSE)
_txt_rg_state_v(rs, members, flags);
else
_txt_rg_state(rs, members, flags, svcsize, nodesize, statsize);
}
void
xml_rg_state(rg_state_t *rs, cluster_member_list_t *members, int flags)
{
char time_str[32];
int x;
time_t t;
/* Chop off newlines */
t = (time_t)(rs->rs_transition);
ctime_r(&t, time_str);
for (x = 0; time_str[x]; x++) {
if (time_str[x] < 32) {
time_str[x] = 0;
break;
}
}
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),
my_memb_id_to_name(members, rs->rs_owner),
my_memb_id_to_name(members, rs->rs_last_owner),
rs->rs_restarts,
(long long unsigned)rs->rs_transition,
time_str);
}
void
build_service_field_sizes(int cols, int *svcsize, int *nodesize, int *statsize)
{
/* Based on 80 columns */
*svcsize = 30;
*nodesize = 30;
*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;
}
int
txt_rg_states(rg_state_list_t *rgl, cluster_member_list_t *members,
char *svcname, int flags)
{
int x, ret = 0, svcsize, nodesize, statsize;
if (!rgl || !members)
return -1;
if (svcname)
ret = -1;
build_service_field_sizes(dimx, &svcsize, &nodesize, &statsize);
if (!(flags & RG_VERBOSE)) {
printf(" %-*.*s %-*.*s %-*.*s\n",
svcsize, svcsize, "Service Name",
nodesize, nodesize, "Owner (Last)",
statsize, statsize, "State");
printf(" %-*.*s %-*.*s %-*.*s\n",
svcsize, svcsize, "------- ----",
nodesize, nodesize, "----- ------",
statsize, statsize, "-----");
} else {
printf("Service Information\n"
"------- -----------\n\n");
}
for (x = 0; x < rgl->rgl_count; x++) {
if (svcname &&
strcmp(rgl->rgl_states[x].rs_name, svcname))
continue;
txt_rg_state(&rgl->rgl_states[x], members, flags,
svcsize, nodesize, statsize);
if (svcname) {
switch (rgl->rgl_states[x].rs_state) {
case RG_STATE_STARTING:
case RG_STATE_STARTED:
case RG_STATE_STOPPING:
ret = 0;
break;
default:
ret = rgl->rgl_states[x].rs_state;
}
}
}
return ret;
}
int
xml_rg_states(rg_state_list_t *rgl, cluster_member_list_t *members,
char *svcname, int flags)
{
int x;
int ret = 0;
if (!rgl || !members)
return -1;
printf(" <groups>\n");
for (x = 0; x < rgl->rgl_count; x++) {
if (svcname &&
strcmp(rgl->rgl_states[x].rs_name, svcname))
continue;
xml_rg_state(&rgl->rgl_states[x], members, flags);
if (svcname) {
switch (rgl->rgl_states[x].rs_state) {
case RG_STATE_STARTING:
case RG_STATE_STARTED:
case RG_STATE_STOPPING:
break;
default:
ret = rgl->rgl_states[x].rs_state;
}
}
}
printf(" </groups>\n");
return ret;
}
void
txt_quorum_state(int qs)
{
printf("Member Status: ");
if (qs) {
printf("Quorate\n\n");
} else {
printf("Inquorate\n\n");
}
}
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) */
printf(" <quorum ");
if (qs & FLAG_UP) {
printf("quorate=\"1\"");
} else {
printf("quorate=\"0\"\n");
}
if (qs & FLAG_RGMGR) {
printf(" groupmember=\"1\"");
} else {
printf(" groupmember=\"0\"");
}
printf("/>\n");
}
void
build_member_field_size(int cols, int *nodesize)
{
/* Based on 80 columns */
*nodesize = 40;
*nodesize = (cols / 2);
if (*nodesize > MAXHOSTNAMELEN)
*nodesize = MAXHOSTNAMELEN;
}
void
txt_member_state(cman_node_t *node, int nodesize)
{
/* If it's down and not in cluster.conf, don't show it */
if ((node->cn_member & (FLAG_NOCFG | FLAG_UP)) == FLAG_NOCFG)
return;
printf(" %-*.*s ", nodesize, nodesize, node->cn_name);
printf("%4d ", node->cn_nodeid);
if (node->cn_member & FLAG_UP)
printf("Online");
else
printf("Offline");
if (node->cn_member & FLAG_LOCAL)
printf(", Local");
if (node->cn_member & FLAG_NOCFG)
printf(", Estranged");
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");
}
void
xml_member_state(cman_node_t *node)
{
/* If it's down and not in cluster.conf, don't show it */
if ((node->cn_member & (FLAG_NOCFG | FLAG_UP)) == FLAG_NOCFG)
return;
printf(" <node name=\"%s\" state=\"%d\" local=\"%d\" "
"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));
}
int
txt_member_states(cluster_member_list_t *membership, char *name)
{
int x, ret = 0, nodesize;
if (!membership) {
printf("Membership information not available\n");
return -1;
}
build_member_field_size(dimx, &nodesize);
printf(" %-*.*s", nodesize, nodesize, "Member Name");
printf("%-4.4s %s\n", "ID", "Status");
printf(" %-*.*s", nodesize, nodesize, "------ ----");
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], nodesize);
ret = !(membership->cml_members[x].cn_member & FLAG_UP);
}
printf("\n");
return ret;
}
int
xml_member_states(cluster_member_list_t *membership, char *name)
{
int x, ret = 0;
if (!membership) {
printf(" <nodes/>\n");
return -1;
}
printf(" <nodes>\n");
for (x = 0; x < membership->cml_count; x++) {
if (name && strcmp(membership->cml_members[x].cn_name, name))
continue;
xml_member_state(&membership->cml_members[x]);
if (name)
ret = !(membership->cml_members[x].cn_member & FLAG_UP);
}
printf(" </nodes>\n");
return ret;
}
int
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 = 0;
if (!svcname && !name) {
txt_cluster_info(ci);
txt_quorum_state(qs);
if (!membership) {
/* XXX Check for rgmanager?! */
printf("Resource Group Manager not running; "
"no service information available.\n\n");
}
}
if (!svcname || (name && svcname))
ret = txt_member_states(membership, name);
if (name && !svcname)
return ret;
if (!name || (name && svcname))
ret = txt_rg_states(rgs, membership, svcname, flags);
return ret;
}
int
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)
{
int ret1 = 0, ret2 = -1;
int x;
printf("<?xml version=\"1.0\"?>\n");
printf("<clustat version=\"4.1.1\">\n");
if (qs) {
qs = FLAG_UP;
if (membership) {
for (x = 0; x < membership->cml_count; x++) {
if ((membership->cml_members[x].cn_member &
(FLAG_LOCAL|FLAG_RGMGR)) ==
(FLAG_LOCAL|FLAG_RGMGR)) {
qs |= FLAG_RGMGR;
break;
}
}
}
}
if (!svcname && !name)
xml_cluster_info(ci);
if (!svcname && !name)
xml_quorum_state(qs);
if (!svcname || (name && svcname))
ret1 = xml_member_states(membership, name);
if (rgs &&
(!name || (name && svcname)))
ret2 = xml_rg_states(rgs, membership, svcname, flags);
printf("</clustat>\n");
if (name && ret1)
return ret1;
if (svcname && ret2)
return ret2;
return 0;
}
cluster_member_list_t *
build_member_list(cman_handle_t ch, int *lid)
{
cluster_member_list_t *all, *part;
cman_node_t *m;
int root = 0;
int x;
/* Get all members from ccs, and all members reported by the cluster
infrastructure */
root = (getuid() == 0 || geteuid() == 0);
part = get_member_list(ch);
if (root && (all = ccs_member_list())) {
/* See if our config has anyone missed. If so, flag
them as missing from the config file */
all = add_missing(all, part);
/* Flag online nodes */
flag_nodes(all, part, FLAG_UP);
free_member_list(part);
} else {
/* not root - keep it simple for the next block */
all = part;
}
if (!all) {
*lid = 0;
return NULL;
}
/* Grab the local node ID and flag it from the list of reported
online nodes */
*lid = get_my_nodeid(ch);
/* */
for (x=0; x<all->cml_count; x++) {
if (all->cml_members[x].cn_nodeid == *lid) {
m = &all->cml_members[x];
m->cn_member |= FLAG_LOCAL;
break;
}
}
return all;
}
void
usage(char *arg0)
{
printf(
"usage: %s <options>\n"
" -i <interval> Refresh every <interval> seconds. May not be used\n"
" with -x.\n"
" -I Display local node ID and exit\n"
" -m <member> Display status of <member> and exit\n"
" -s <service> Display status of <service> and exit\n"
" -v Display version & cluster plugin and exit\n"
" -x Dump information as XML\n"
" -Q Return 0 if quorate, 1 if not (no output)\n"
" -f Enable fast clustat reports\n"
" -l Use long format for services\n"
"\n", basename(arg0));
}
int
main(int argc, char **argv)
{
int qs, ret = 0;
cluster_member_list_t *membership;
rg_state_list_t *rgs = NULL;
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;
char *member_name = NULL;
char *rg_name = NULL, real_rg_name[64];
while ((opt = getopt(argc, argv, "fIls:m:i:xvQh?")) != EOF) {
switch(opt) {
case 'v':
runtype = VERSION_ONLY;
break;
case 'I':
runtype = NODEID_ONLY;
break;
case 'i':
refresh_sec = atoi(optarg);
if (refresh_sec <= 0)
refresh_sec = 1;
break;
case 'l':
flags |= RG_VERBOSE;
break;
case 'm':
member_name = optarg;
break;
case 'Q':
/* Return to shell: 0 true, 1 false... */
runtype = QSTAT_ONLY;
break;
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)-1,
"service:%s", rg_name);
rg_name = real_rg_name;
}
break;
case 'x':
if (refresh_sec) {
printf("Error: Options '-i' and '-x' are "
"mutually exclusive\n");
ret = 1;
goto cleanup;
}
xml = 1;
break;
case 'f':
++fast;
break;
case '?':
case 'h':
usage(argv[0]);
return 0;
break;
default:
errors++;
break;
}
}
if (errors) {
usage(argv[0]);
return 1;
}
signal(SIGPIPE, SIG_IGN);
/* Connect & grab all our info */
ch = cman_init(NULL);
if (!ch) {
perror("Could not connect to CMAN");
return 1;
}
switch(runtype) {
case QSTAT_ONLY:
if (!ch)
break;
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;
case NODEID_ONLY:
if (!ch)
break;
local_node_id = get_my_nodeid(ch);
printf("0x%08x\n",(uint32_t)(local_node_id));
goto cleanup;
}
if (!ch) {
printf("Could not connect to cluster service\n");
return 1;
}
/* XXX add member/rg single-shot state */
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);
if (!member_name)
rgs = rg_state_list(local_node_id, fast);
if (rgs) {
flag_rgmanager_nodes(membership);
}
if (refresh_sec) {
tputs(clear_screen, lines > 0 ? lines : 1, putchar);
now = time(NULL);
}
if (xml)
ret = xml_cluster_status(&ci, qs, membership, rgs,
member_name, rg_name,
flags);
else
ret = txt_cluster_status(&ci, qs, membership, rgs,
member_name, rg_name,
flags);
if (membership)
free_member_list(membership);
if (rgs)
free(rgs);
if (!refresh_sec || !running)
break;
sleep(refresh_sec);
}
cleanup:
cman_finish(ch);
return ret;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Mon, Feb 24, 8:14 AM (1 d, 57 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1464061
Default Alt Text
clustat.c (22 KB)
Attached To
Mode
rF Fence Agents
Attached
Detach File
Event Timeline
Log In to Comment