[DRBD-cvs] svn commit by rasto - r2201 - in trunk: . tools - added files

drbd-cvs at lists.linbit.com drbd-cvs at lists.linbit.com
Thu May 18 16:14:24 CEST 2006


Author: rasto
Date: 2006-05-18 16:14:23 +0200 (Thu, 18 May 2006)
New Revision: 2201

Added:
   trunk/tools/
   trunk/tools/README
   trunk/tools/dopd.c
   trunk/tools/dopd.h
   trunk/tools/drbd-peer-outdater.c
Log:
added files


Added: trunk/tools/README
===================================================================
--- trunk/tools/README	2006-05-18 12:57:18 UTC (rev 2200)
+++ trunk/tools/README	2006-05-18 14:14:23 UTC (rev 2201)
@@ -0,0 +1,20 @@
+1) compile
+
+copy this directory into heartbeat tools directory and compile it 
+with heartbeat.
+
+2) prepare drbdmeta
+
+cd /sbin
+chown .haclient drbdmeta
+chmod o-x drbdmeta
+chmod u+s drbdmeta
+
+3) Configure Heartbeat to run the DRBD outdate peer daemon
+
+Add these lines to /etc/ha.d/ha.cf
+---
+respawn hacluster /usr/lib/heartbeat/dopd
+apiauth dopd gid=haclient uid=hacluster
+---
+

Added: trunk/tools/dopd.c
===================================================================
--- trunk/tools/dopd.c	2006-05-18 12:57:18 UTC (rev 2200)
+++ trunk/tools/dopd.c	2006-05-18 14:14:23 UTC (rev 2201)
@@ -0,0 +1,557 @@
+/* $Id$ */
+/* drbd outdate peer daemon
+ * Copyright (C) 2006 LINBIT <http://www.linbit.com/>
+ * Written by Rasto Levrinc <rasto at linbit.at>
+ *
+ * based on ipfail.c and attrd.c
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <portability.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <stdarg.h>
+#include <libgen.h>
+#include <heartbeat.h>
+#include <ha_msg.h>
+#include <hb_api.h>
+#include <clplumbing/cl_signal.h>
+#include <clplumbing/GSource.h>
+#include <clplumbing/Gmain_timeout.h>
+#include <clplumbing/coredumps.h>
+#include <dopd.h>
+#include <clplumbing/cl_misc.h>
+
+#include <crm/crm.h>
+#include <crm/common/ipc.h>
+
+
+const char *node_name;	   /* The node we are connected to            */
+char other_node[SYS_NMLN]; /* The remote node in the pair             */
+int node_stable;           /* Other node stable?                      */
+int need_standby;          /* Are we waiting for stability?           */
+int quitnow = 0;           /* Allows a signal to break us out of loop */
+GMainLoop *mainloop;       /* Reference to the mainloop for events    */
+ll_cluster_t *dopd_cluster_conn;
+
+/* only one client can be connected at a time */
+
+typedef struct dopd_client_s
+{
+	char  *id;
+
+	IPC_Channel *channel;
+	GCHSource   *source;
+} dopd_client_t;
+
+IPC_Channel *CURR_CLIENT_CHANNEL = NULL;
+
+/* send_message_to_other_node()
+ * send message with drbd resource to other node.
+ */
+static gboolean
+send_message_to_other_node(const char *drbd_resource)
+{
+	ll_cluster_t *hb = dopd_cluster_conn;
+        HA_Message *msg = NULL;
+
+        crm_info("sending start_outdate message to the other node %s -> %s",
+		  node_name, other_node);
+
+        msg = ha_msg_new(3);
+        ha_msg_add(msg, F_TYPE, "start_outdate");
+        ha_msg_add(msg, F_ORIG, node_name);
+        ha_msg_add(msg, F_DOPD_RES, drbd_resource);
+
+	crm_debug("sending [start_outdate res: %s] to other node", 
+		  drbd_resource);
+        hb->llc_ops->sendnodemsg(hb, msg, other_node);
+	ha_msg_del(msg);
+
+        return TRUE;
+}
+
+/* msg_start_outdate()
+ * got start_outdate message with resource from other node. Execute drbd
+ * outdate command, convert return code and send message to other node
+ * with return code.
+ *
+ * Conversion of return codes:
+ *     0 => 4
+ *     5 => 3
+ *    17 => 6
+ * other => 5
+ */
+void
+msg_start_outdate(struct ha_msg *msg, void *private)
+{
+	ll_cluster_t *hb = (ll_cluster_t *)private;
+	int rc = 5;
+	int command_ret;
+
+	char rc_string[4];
+        HA_Message *msg2 = NULL;
+	const char *drbd_resource = ha_msg_value(msg, F_DOPD_RES);
+	char *command;
+
+	/* execute outdate command */
+        crm_malloc0(command, strlen(OUTDATE_COMMAND) + 1 + strlen(drbd_resource) + 1);
+	strcpy(command, OUTDATE_COMMAND);
+	strcat(command, " ");
+	strcat(command, drbd_resource);
+	crm_debug("command: %s", command);
+	command_ret = system(command) >> 8;
+
+	/* convert return code */
+	crm_free(command);
+	if (command_ret == 0)
+		rc = 4;
+	else if (command_ret == 5)
+		rc = 3;
+	else if (command_ret == 17)
+		rc = 6;
+	else
+		crm_info("unknown exit code from "OUTDATE_COMMAND": %i",
+				command_ret);
+
+	crm_debug("msg_start_outdate: %s, command rc: %i, rc: %i", 
+			 ha_msg_value(msg, F_ORIG), command_ret, rc);
+	sprintf(rc_string, "%i", rc);
+
+	/* send return code to oder node */
+	msg2 = ha_msg_new(3);
+	ha_msg_add(msg2, F_TYPE, "outdate_rc");
+	ha_msg_add(msg2, F_DOPD_VALUE, rc_string);
+	ha_msg_add(msg2, F_ORIG, node_name);
+
+	hb->llc_ops->sendnodemsg(hb, msg2, other_node);
+	ha_msg_del(msg2);
+}
+
+/* msg_outdate_rc()
+ * got outdate_rc message with return code from other node. Send the 
+ * return code to the outdater client.
+ */
+void
+msg_outdate_rc(struct ha_msg *msg_in, void *private)
+{
+        HA_Message *msg_out = NULL;
+	const char *rc_string = ha_msg_value(msg_in, F_DOPD_VALUE);
+
+	if (CURR_CLIENT_CHANNEL == NULL)
+		return;
+	crm_debug("msg_outdate_rc: %s", rc_string);
+	msg_out = ha_msg_new(3);
+	ha_msg_add(msg_out, F_TYPE, "outdater_rc");
+	ha_msg_add(msg_out, F_ORIG, node_name);
+	ha_msg_add(msg_out, F_DOPD_VALUE, rc_string);
+
+	if (send_ipc_message(CURR_CLIENT_CHANNEL, msg_out) == FALSE) {
+		crm_err("Could not send message to the client");
+	}
+	CURR_CLIENT_CHANNEL = NULL;
+}
+
+/* outdater_callback()
+ * got message from outdater client with drbd resource, it will be sent
+ * to the other node.
+ */
+static gboolean
+outdater_callback(IPC_Channel *client, gpointer user_data)
+{
+	int lpc = 0;
+	HA_Message *msg = NULL;
+	const char *drbd_resource = NULL;
+	dopd_client_t *curr_client = (dopd_client_t*)user_data;
+	gboolean stay_connected = TRUE;
+
+	crm_debug("invoked: %s", curr_client->id);
+
+	/* allow one connection from outdater at a time */
+	if (CURR_CLIENT_CHANNEL != NULL &&
+	    CURR_CLIENT_CHANNEL != curr_client->channel) {
+		crm_debug("one client already connected");
+		return FALSE;
+	}
+	CURR_CLIENT_CHANNEL = curr_client->channel;
+
+	while (IPC_ISRCONN(client)) {
+		if(client->ops->is_message_pending(client) == 0) {
+			break;
+		}
+
+                msg = msgfromIPC_noauth(client);
+                if (msg == NULL) {
+                        crm_debug("%s: no message this time",
+				  curr_client->id);
+                        continue;
+		}
+
+		lpc++;
+
+		crm_debug("Processing msg from %s", curr_client->id);
+		crm_debug("Got message from (%s). (%s)",
+				ha_msg_value(msg, F_ORIG),
+				ha_msg_value(msg, F_OUTDATER_RES));
+
+		drbd_resource = ha_msg_value(msg, F_OUTDATER_RES);
+		send_message_to_other_node(drbd_resource);
+
+		crm_msg_del(msg);
+		msg = NULL;
+
+		if(client->ch_status != IPC_CONNECT) {
+			break;
+		}
+	}
+	crm_debug("Processed %d messages", lpc);
+	if (client->ch_status != IPC_CONNECT) {
+		stay_connected = FALSE;
+	}
+	return stay_connected;
+}
+
+
+/* outdater_ipc_connection_destroy()
+ * clean client struct
+ */
+static void
+outdater_ipc_connection_destroy(gpointer user_data)
+{
+	dopd_client_t *client = (dopd_client_t*)user_data;
+
+	if (client == NULL)
+		return;
+
+	if (client->source != NULL) {
+		crm_debug("Deleting %s (%p) from mainloop",
+				client->id, client->source);
+		G_main_del_IPC_Channel(client->source);
+		client->source = NULL;
+	}
+	crm_free(client->id);
+	if (client->channel == CURR_CLIENT_CHANNEL) {
+		crm_debug("connection from client closed");
+		CURR_CLIENT_CHANNEL = NULL;
+	}
+	crm_free(client);
+	return;
+}
+
+/* outdater_client_connect()
+ * outdater is connected set outdater_callback.
+ */
+static gboolean
+outdater_client_connect(IPC_Channel *channel, gpointer user_data)
+{
+        dopd_client_t *new_client = NULL;
+        crm_debug("Connecting channel");
+        if(channel == NULL) {
+                crm_err("Channel was NULL");
+                return FALSE;
+
+        } else if(channel->ch_status != IPC_CONNECT) {
+                crm_err("Channel was disconnected");
+                return FALSE;
+        }
+
+        crm_malloc0(new_client, sizeof(dopd_client_t));
+        new_client->channel = channel;
+        crm_malloc0(new_client->id, 10);
+        strcpy(new_client->id, "outdater");
+
+        new_client->source = G_main_add_IPC_Channel(
+                G_PRIORITY_DEFAULT, channel, FALSE, outdater_callback,
+                new_client, outdater_ipc_connection_destroy);
+
+        crm_debug("Client %s (%p) connected",
+			  new_client->id,
+			  new_client->source);
+
+        return TRUE;
+}
+
+static void
+outdater_client_destroy(gpointer user_data)
+{
+	crm_info("ipc server destroy");
+}
+
+int
+is_stable(ll_cluster_t *hb)
+{
+	const char *resources = hb->llc_ops->get_resources(hb);
+	if (!resources)
+		/* Heartbeat is not providing resource management */
+	        return -1;
+
+	if (!strcmp(resources, "transition"))
+		return 0;
+
+	return 1;
+}
+
+/* node_walk()
+ * get name of other node and set other_node string
+ */
+void
+node_walk(ll_cluster_t *hb)
+{
+	const char *node;
+
+	crm_debug("Starting node walk");
+	if (hb->llc_ops->init_nodewalk(hb) != HA_OK) {
+		crm_err("Cannot start node walk");
+		crm_err("REASON: %s", hb->llc_ops->errmsg(hb));
+		exit(9);
+	}
+	while((node = hb->llc_ops->nextnode(hb)) != NULL) {
+		crm_debug("Cluster node: %s: status: %s", node,
+				hb->llc_ops->node_status(hb, node));
+
+		/* Look for our partner */
+		if (!strcmp("normal", hb->llc_ops->node_type(hb, node))
+		    && strcmp(node, node_name)) {
+			strcpy(other_node, node);
+			crm_debug("[They are %s]", other_node);
+		}
+	}
+	if (hb->llc_ops->end_nodewalk(hb) != HA_OK) {
+		crm_err("Cannot end node walk");
+		crm_err("REASON: %s", hb->llc_ops->errmsg(hb));
+		exit(12);
+	}
+}
+
+/* set_callbacks()
+ * set callbacks for communication between two nodes
+ */
+void
+set_callbacks(ll_cluster_t *hb)
+{
+	/* Add each of the callbacks we use with the API */
+	if (hb->llc_ops->set_msg_callback(hb, "start_outdate",
+					  msg_start_outdate, hb) != HA_OK) {
+		crm_err("Cannot set msg_start_outdate callback");
+		crm_err("REASON: %s", hb->llc_ops->errmsg(hb));
+		exit(2);
+	}
+
+	if (hb->llc_ops->set_msg_callback(hb, "outdate_rc",
+					  msg_outdate_rc, hb) != HA_OK) {
+		crm_err("Cannot set msg_outdate_rc callback");
+		crm_err("REASON: %s", hb->llc_ops->errmsg(hb));
+		exit(2);
+	}
+}
+
+void
+set_signals(ll_cluster_t *hb)
+{
+	/* Setup the various signals */
+
+	CL_SIGINTERRUPT(SIGINT, 1);
+	CL_SIGNAL(SIGINT, gotsig);
+	CL_SIGINTERRUPT(SIGTERM, 1);
+	CL_SIGNAL(SIGTERM, gotsig);
+
+	crm_debug("Setting message signal");
+	if (hb->llc_ops->setmsgsignal(hb, 0) != HA_OK) {
+		crm_err("Cannot set message signal");
+		crm_err("REASON: %s", hb->llc_ops->errmsg(hb));
+		exit(13);
+	}
+}
+
+void
+gotsig(int nsig)
+{
+	(void)nsig;
+	quitnow = 1;
+}
+
+/* Used to handle the API in the gmainloop */
+gboolean
+dopd_dispatch(IPC_Channel* ipc, gpointer user_data)
+{
+	struct ha_msg *reply;
+	ll_cluster_t *hb = user_data;
+
+	reply = hb->llc_ops->readmsg(hb, 0);
+
+	if (reply != NULL) {
+		ha_msg_del(reply); reply=NULL;
+		return TRUE;
+	}
+	return TRUE;
+}
+
+void
+dopd_dispatch_destroy(gpointer user_data)
+{
+	return;
+}
+
+gboolean
+dopd_timeout_dispatch(gpointer user_data)
+{
+	ll_cluster_t *hb = user_data;
+
+	if (quitnow) {
+		g_main_quit(mainloop);
+		return FALSE;
+	}
+
+	if (hb->llc_ops->msgready(hb)) {
+		return dopd_dispatch(NULL, user_data);
+	}
+	return TRUE;
+}
+
+/* Sign in to the API */
+void
+open_api(ll_cluster_t *hb)
+{
+	crm_debug("Signing in with heartbeat");
+	if (hb->llc_ops->signon(hb, "dopd")!= HA_OK) {
+		crm_err("Cannot sign on with heartbeat");
+		crm_err("REASON: %s", hb->llc_ops->errmsg(hb));
+		exit(1);
+	}
+}
+
+/* Log off of the API and clean up */
+void
+close_api(ll_cluster_t *hb)
+{
+	if (hb->llc_ops->signoff(hb, FALSE) != HA_OK) {
+		crm_err("Cannot sign off from heartbeat.");
+		crm_err("REASON: %s", hb->llc_ops->errmsg(hb));
+		exit(14);
+	}
+	if (hb->llc_ops->delete(hb) != HA_OK) {
+		crm_err("REASON: %s", hb->llc_ops->errmsg(hb));
+		crm_err("Cannot delete API object.");
+		exit(15);
+	}
+}
+
+int
+main(int argc, char **argv)
+{
+	unsigned fmask;
+	ll_cluster_t *hb;
+	char pid[10];
+	char *bname, *parameter;
+	IPC_Channel *apiIPC;
+
+	/* Get the name of the binary for logging purposes */
+	bname = ha_strdup(argv[0]);
+	crm_log_init(bname);
+
+	hb = ll_cluster_new("heartbeat");
+	dopd_cluster_conn = hb;
+
+	memset(other_node, 0, sizeof(other_node));
+	need_standby = 0;
+
+	memset(pid, 0, sizeof(pid));
+	snprintf(pid, sizeof(pid), "%ld", (long)getpid());
+	crm_debug("PID=%s", pid);
+
+	open_api(hb);
+
+	node_stable = is_stable(hb);
+	if (node_stable == -1) {
+		crm_err("No managed resources");
+		exit(100);
+	}
+
+	/* Obtain our local node name */
+	node_name = hb->llc_ops->get_mynodeid(hb);
+	if (node_name == NULL) {
+		crm_err("Cannot get my nodeid");
+		crm_err("REASON: %s", hb->llc_ops->errmsg(hb));
+		exit(19);
+	}
+	crm_debug("[We are %s]", node_name);
+
+	/* See if we should drop cores somewhere odd... */
+	parameter = hb->llc_ops->get_parameter(hb, KEY_COREROOTDIR);
+	if (parameter) {
+		cl_set_corerootdir(parameter);
+		cl_cdtocoredir();
+	}
+	cl_cdtocoredir();
+
+
+	set_callbacks(hb);
+
+	fmask = LLC_FILTER_DEFAULT;
+
+	crm_debug("Setting message filter mode");
+	if (hb->llc_ops->setfmode(hb, fmask) != HA_OK) {
+		crm_err("Cannot set filter mode");
+		crm_err("REASON: %s", hb->llc_ops->errmsg(hb));
+		exit(8);
+	}
+
+	node_walk(hb);
+
+	set_signals(hb);
+
+	crm_debug("Waiting for messages...");
+	errno = 0;
+
+	mainloop = g_main_new(TRUE);
+
+        apiIPC = hb->llc_ops->ipcchan(hb);
+
+	/* Watch the API IPC for input */
+        G_main_add_IPC_Channel(G_PRIORITY_HIGH, apiIPC, FALSE,
+                               dopd_dispatch, (gpointer)hb,
+                               dopd_dispatch_destroy);
+
+	Gmain_timeout_add_full(G_PRIORITY_DEFAULT, 1000,
+	                        dopd_timeout_dispatch, (gpointer)hb,
+	                        dopd_dispatch_destroy);
+	int rc = init_server_ipc_comms(
+			ha_strdup(T_OUTDATER),
+			outdater_client_connect,
+			outdater_client_destroy);
+	if (rc != 0)
+		crm_err("Could not start IPC server");
+
+	g_main_run(mainloop);
+	g_main_destroy(mainloop);
+
+	if (!quitnow && errno != EAGAIN && errno != EINTR) {
+		crm_err("read_hb_msg returned NULL");
+		crm_err("REASON: %s", hb->llc_ops->errmsg(hb));
+	}
+
+	close_api(hb);
+
+	return 0;
+}

Added: trunk/tools/dopd.h
===================================================================
--- trunk/tools/dopd.h	2006-05-18 12:57:18 UTC (rev 2200)
+++ trunk/tools/dopd.h	2006-05-18 14:14:23 UTC (rev 2201)
@@ -0,0 +1,43 @@
+/* $Id$ */
+/* drbd outdate peer daemon
+ * Copyright (C) 2006 LINBIT <http://www.linbit.com/>
+ *
+ * Written by Rasto Levrinc <rasto at linbit.at>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#define T_OUTDATER		"outdater"
+#define F_OUTDATER_RES		"outdater_res"
+#define F_DOPD_VALUE            "dop_value"
+#define F_DOPD_RES              "dop_res"
+
+#define OUTDATE_COMMAND		"/sbin/drbdadm outdate"
+
+
+/* Prototypes */
+void node_walk(ll_cluster_t *);
+void set_signals(ll_cluster_t *);
+void gotsig(int);
+void set_callbacks(ll_cluster_t *);
+void open_api(ll_cluster_t *);
+void close_api(ll_cluster_t *);
+gboolean dopd_dispatch(IPC_Channel *, gpointer);
+void dopd_dispatch_destroy(gpointer);
+gboolean dopd_timeout_dispatch(gpointer);
+int is_stable(ll_cluster_t *);
+void msg_start_outdate(struct ha_msg *, void *);
+void msg_outdate_rc(struct ha_msg *, void *);

Added: trunk/tools/drbd-peer-outdater.c
===================================================================
--- trunk/tools/drbd-peer-outdater.c	2006-05-18 12:57:18 UTC (rev 2200)
+++ trunk/tools/drbd-peer-outdater.c	2006-05-18 14:14:23 UTC (rev 2201)
@@ -0,0 +1,230 @@
+/* $Id$ */
+/* drbd-peer-outdater
+ * Copyright (C) 2006 LINBIT <http://www.linbit.com/>
+ *
+ * Written by Rasto Levrinc <rasto at linbit.at>
+ *
+ * based on attrd
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <portability.h>
+
+#include <sys/param.h>
+
+#include <crm/crm.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <stdlib.h>
+#include <crm/common/ipc.h>
+#include <clplumbing/lsb_exitcodes.h>
+#include <clplumbing/Gmain_timeout.h>
+#include <dopd.h>
+
+#define OPTARGS      "hVt:r:"
+
+typedef struct dop_client_s
+{
+	int timeout;
+	GMainLoop *mainloop;
+	int rc;
+} dop_client_t;
+
+const char *crm_system_name = "drbd-peer-outdater";
+
+static void usage(const char* cmd, int exit_status);
+
+static void
+dop_exit(dop_client_t *client)
+{
+	int rc;
+
+	if (client == NULL)
+		exit(5);
+	rc = client->rc;
+
+	crm_free(client);
+	exit(rc);
+}
+
+static gboolean
+outdate_callback(IPC_Channel * server, gpointer user_data)
+{
+	dop_client_t *client = (dop_client_t *)user_data;
+	HA_Message *msg = NULL;
+	const char *rc_string;
+	char *ep;
+	int rc;
+
+	msg = msgfromIPC_noauth(server);
+	if (!msg) {
+		fprintf(stderr, "no message from server or other "
+				"instance is running\n");
+		if (client->mainloop != NULL &&
+		    g_main_is_running(client->mainloop))
+			g_main_quit(client->mainloop);
+		return FALSE;
+	}
+	crm_debug_2("message: %s, %s\n",
+			ha_msg_value(msg, F_TYPE),
+			ha_msg_value(msg, F_ORIG)
+			);
+	rc_string = ha_msg_value(msg, F_DOPD_VALUE);
+
+	errno = 0;
+	rc = strtol(rc_string, &ep, 10);
+	if (errno != 0 || *ep != EOS) {
+		fprintf(stderr, "unknown message: %s from server", rc_string);
+		ha_msg_del(msg);
+		if (client->mainloop != NULL &&
+		    g_main_is_running(client->mainloop))
+			g_main_quit(client->mainloop);
+		return FALSE;
+	}
+
+	ha_msg_del(msg);
+
+	if (client->mainloop != NULL && g_main_is_running(client->mainloop)) {
+		client->rc = rc;
+		g_main_quit(client->mainloop);
+	} else
+		dop_exit(client);
+
+	return TRUE;
+}
+
+static void
+outdater_dispatch_destroy(gpointer user_data)
+{
+	return;
+}
+
+static gboolean
+outdater_timeout_dispatch(gpointer user_data)
+{
+	dop_client_t *client = (dop_client_t *)user_data;
+	fprintf(stderr, "error: could not connect to dopd after %i seconds"
+			": timeout reached\n", client->timeout);
+	if (client->mainloop != NULL && g_main_is_running(client->mainloop))
+		g_main_quit(client->mainloop);
+	return FALSE;
+}
+
+int
+main(int argc, char ** argv)
+{
+	HA_Message *update = NULL;
+	IPC_Channel *ipc_server = NULL;
+	int argerr = 0;
+	int flag;
+	char *drbd_resource = NULL;
+	char drbd_resource_default[] = "r0";
+	int timeout = 60; // timeout in seconds
+
+	dop_client_t *new_client = NULL;
+	GCHSource *src = NULL;
+
+	crm_log_init(crm_system_name);
+
+	crm_debug_3("Begining option processing");
+	while ((flag = getopt(argc, argv, OPTARGS)) != EOF) {
+		switch(flag) {
+			case 'V':
+				alter_debug(DEBUG_INC);
+				break;
+			case 'h':		/* Help message */
+				usage(crm_system_name, LSB_EXIT_OK);
+				break;
+			case 't':		/* Help message */
+				timeout = atoi(optarg);
+				break;
+			case 'r':		/* Help message */
+				drbd_resource = crm_strdup(optarg);
+				break;
+			default:
+				++argerr;
+				break;
+		}
+	}
+
+	crm_debug_3("Option processing complete");
+
+	/* the caller drbdadm sets DRBD_RESOURCE env variable, use it if
+	 * -r option was not specified, or use default value */
+	if ((drbd_resource == NULL) && !(drbd_resource = getenv("DRBD_RESOURCE"))) {
+		drbd_resource = drbd_resource_default;
+	}
+
+	if (optind > argc) {
+		++argerr;
+	}
+
+	if (argerr) {
+		usage(crm_system_name, LSB_EXIT_GENERIC);
+	}
+
+	crm_debug_2("drbd resource: %s\n", drbd_resource);
+
+	crm_malloc0(new_client, sizeof(dop_client_t));
+	new_client->timeout = timeout;
+	new_client->mainloop = g_main_new(FALSE);
+	new_client->rc = 5;
+
+	/* Connect to the IPC server */
+	src = init_client_ipc_comms(T_OUTDATER, outdate_callback,
+			      (gpointer)new_client, &ipc_server);
+
+	if (ipc_server == NULL) {
+		fprintf(stderr, "Could not connect to "T_OUTDATER" channel\n");
+		dop_exit(new_client); // unreachable
+	}
+
+	/* send message with drbd resource to dopd */
+	update = ha_msg_new(3);
+	ha_msg_add(update, F_TYPE, T_OUTDATER);
+	ha_msg_add(update, F_ORIG, crm_system_name);
+	ha_msg_add(update, F_OUTDATER_RES, drbd_resource);
+
+	if (send_ipc_message(ipc_server, update) == FALSE) {
+		fprintf(stderr, "Could not send message\n");
+		dop_exit(new_client);
+	}
+
+	Gmain_timeout_add_full(G_PRIORITY_DEFAULT, new_client->timeout * 1000,
+	                       outdater_timeout_dispatch, (gpointer)new_client,
+			       outdater_dispatch_destroy);
+
+	g_main_run(new_client->mainloop);
+	dop_exit(new_client);
+	return 5;
+}
+
+static void
+usage(const char* cmd, int exit_status)
+{
+	FILE* stream;
+
+	stream = exit_status ? stderr : stdout;
+	fprintf(stream, "usage: %s [-tr]\n", cmd);
+	fprintf(stream, "\t-t <int>\ttimeout in seconds\n");
+	fprintf(stream, "\t-r <string>\tdrbd resource, default is r0\n");
+	fflush(stream);
+
+	exit(exit_status);
+}
+



More information about the drbd-cvs mailing list