public inbox for cluster-cvs@sourceware.org
help / color / mirror / Atom feed
* fence-agents: master - fence: Support for power cycle in fence ipmi
@ 2009-08-27 15:35 Jan Friesse
  0 siblings, 0 replies; only message in thread
From: Jan Friesse @ 2009-08-27 15:35 UTC (permalink / raw)
  To: cluster-cvs-relay

Gitweb:        http://git.fedorahosted.org/git/fence-agents.git?p=fence-agents.git;a=commitdiff;h=0b69dfb351d7d509f2ca27a4676c6a179e0a9af4
Commit:        0b69dfb351d7d509f2ca27a4676c6a179e0a9af4
Parent:        8de93defd88b88045379c66faf694fda3d13394b
Author:        Jan Friesse <jfriesse@redhat.com>
AuthorDate:    Mon Jul 20 13:47:52 2009 +0200
Committer:     Jan Friesse <jfriesse@redhat.com>
CommitterDate: Thu Aug 27 17:32:41 2009 +0200

fence: Support for power cycle in fence ipmi

Default behaviour (off/get status/on) doesn't work on
some IPMI implementations, because chasiss power off will
turn off IPMI management card. Next power on cannot be
done automatically. But it looks, like chassis power cycle
is supported and do what we need -> reset machine.

Patch add support for -M (method) option, which can have
values:
- onoff - default old behaviour
- cycle - use new power cycle

rhbz#482913
---
 fence/agents/ipmilan/ipmilan.c |   85 ++++++++++++++++++++++++++++++++++++----
 fence/man/fence_ipmilan.8      |   10 +++++
 2 files changed, 87 insertions(+), 8 deletions(-)

diff --git a/fence/agents/ipmilan/ipmilan.c b/fence/agents/ipmilan/ipmilan.c
index 8238a11..e001f3d 100644
--- a/fence/agents/ipmilan/ipmilan.c
+++ b/fence/agents/ipmilan/ipmilan.c
@@ -28,9 +28,12 @@
 #define ST_POWERON 1
 #define ST_POWEROFF 2
 #define ST_GENERIC_RESET 3
+#define ST_CYCLE 4
 
 #define DEFAULT_TIMEOUT 10
 
+#define DEFAULT_METHOD "onoff"
+
 #define log(lvl, fmt, args...) fprintf(stderr, fmt, ##args)
 #include <libgen.h>
 #include "copyright.cf"
@@ -85,7 +88,7 @@ const char *ipmitool_paths[] = {
 
 
 #define ECIPHER 2048
-
+#define ESTATE (8192*2)
 static struct Etoken power_on_complete[] = {
 	{"Password:", EPERM, 0},
 	{"Unable to establish LAN", EAGAIN, 0},	/* Retry */
@@ -106,6 +109,17 @@ static struct Etoken power_off_complete[] = {
 	{NULL, 0, 0}
 };
 
+/** Powercycle operation */
+static struct Etoken power_cycle_complete[] = {
+	{"Password:", EPERM, 0},
+	{"Unable to establish LAN", EAGAIN, 0},	/* Retry */
+	{"IPMI mutex", EFAULT, 0},	/* Death */
+	{"Unsupported cipher suite ID", ECIPHER,0},
+	{"read_rakp2_message: no support for", ECIPHER,0},
+	{"Command not supported in present state", ESTATE, 0},
+	{": Cycle", 0, 0},
+	{NULL, 0, 0}
+};
 
 #define STATE_OFF 4096
 #define STATE_ON  8192
@@ -266,6 +280,10 @@ build_cmd(char *command, size_t cmdlen, struct ipmi *ipmi, int op)
 		snprintf(arg, sizeof(arg),
 			 "%s chassis power status", cmd);
 		break;
+	case ST_CYCLE:
+		snprintf(arg, sizeof(arg),
+			 "%s chassis power cycle", cmd);
+		break;
 	}
 
 	strncpy(command, arg, cmdlen);
@@ -374,6 +392,12 @@ ipmi_op(struct ipmi *ipmi, int op, struct Etoken *toklist)
 		return ret;
 	}
 
+	if (ret == ESTATE) {
+		log(LOG_CRIT, "ipmilan: ipmitool failed to complete "
+		    "command in current state\n");
+		return ret;
+	}
+
 	if (ret == ETIMEDOUT) {
 		/*!!! Still couldn't get through?! */
 		log(LOG_WARNING,
@@ -467,6 +491,16 @@ ipmi_on(struct ipmi *ipmi)
 	return ret;
 }
 
+static int
+ipmi_cycle(struct ipmi *ipmi)
+{
+	int ret;
+
+	ret = ipmi_op(ipmi, ST_CYCLE, power_cycle_complete);
+
+	return ret;
+}
+
 
 /**
   Squash all our private data
@@ -635,13 +669,14 @@ get_options_stdin(char *ip, size_t iplen,
 		  char *user, size_t userlen,
 		  char *op, size_t oplen,
 		  int *lanplus, int *verbose,int *timeout,
-	          int *cipher)
+	          int *cipher, char *method, int methodlen)
 {
 	char in[256];
 	int line = 0;
 	char *name, *val;
 
 	op[0] = 0;
+	method[0] = 0;
 
 	while (fgets(in, sizeof(in), stdin)) {
 		++line;
@@ -705,6 +740,8 @@ get_options_stdin(char *ip, size_t iplen,
 			if ((sscanf(val,"%d",cipher)!=1) || *cipher<0) {
 			    *cipher=-1;
 			}
+		} else if (!strcasecmp(name,"method")) {
+			strncpy (method, val, methodlen);
 		} else if (!strcasecmp(name, "option") ||
 			   !strcasecmp(name, "operation") ||
 			   !strcasecmp(name, "action")) {
@@ -746,6 +783,7 @@ printf("   -o <op>        Operation to perform.\n");
 printf("                  Valid operations: on, off, reboot, status, list or monitor\n");
 printf("   -t <timeout>   Timeout (sec) for IPMI operation (default %d)\n",DEFAULT_TIMEOUT);
 printf("   -C <cipher>    Ciphersuite to use (same as ipmitool -C parameter)\n");
+printf("   -M <method>    Method to fence (onoff or cycle (default %s)\n", DEFAULT_METHOD);
 printf("   -V             Print version and exit\n");
 printf("   -v             Verbose mode\n\n");
 printf("If no options are specified, the following options will be read\n");
@@ -761,6 +799,7 @@ printf("   operation=<op>        Same as -o\n");
 printf("   action=<op>           Same as -o\n");
 printf("   timeout=<timeout>     Same as -t\n");
 printf("   cipher=<cipher>       Same as -C\n");
+printf("   method=<method>       Same as -M\n");
 printf("   verbose               Same as -v\n\n");
 	exit(1);
 }
@@ -796,6 +835,7 @@ main(int argc, char **argv)
 	char passwd[64];
 	char user[64];
 	char op[64];
+	char method[64];
 	char pwd_script[PATH_MAX] = { 0, };
 	int lanplus=0;
 	int verbose=0;
@@ -815,7 +855,7 @@ main(int argc, char **argv)
 		/*
 		   Parse command line options if any were specified
 		 */
-		while ((opt = getopt(argc, argv, "A:a:i:l:p:S:Po:vV?hHt:C:")) != EOF) {
+		while ((opt = getopt(argc, argv, "A:a:i:l:p:S:Po:vV?hHt:C:M:")) != EOF) {
 			switch(opt) {
 			case 'A':
 				/* Auth type */
@@ -857,6 +897,10 @@ main(int argc, char **argv)
 				    fail_exit("Ciphersuite option expects positive number parameter");
 				}
 				break;
+			case 'M':
+				/* Reboot method */
+				strncpy(method, optarg, sizeof(method));
+				break;
 			case 'v':
 				verbose++;
 				break;
@@ -881,7 +925,7 @@ main(int argc, char **argv)
 					  pwd_script, sizeof(pwd_script),
 				      user, sizeof(user),
 				      op, sizeof(op), &lanplus, &verbose,&timeout,
-				      &cipher) != 0)
+				      &cipher, method, sizeof(method)) != 0)
 			return 1;
 	}
 
@@ -915,6 +959,9 @@ main(int argc, char **argv)
 	if (!strlen(op))
 		snprintf(op,sizeof(op), "reboot");
 
+	if (!strlen(method))
+		snprintf(method, sizeof(method), "onoff");
+
 	if (strcasecmp(op, "off") && strcasecmp(op, "on") &&
 	    strcasecmp(op, "status") && strcasecmp(op, "reboot") &&
 	    strcasecmp(op, "monitor") && strcasecmp(op, "list") &&
@@ -931,6 +978,15 @@ main(int argc, char **argv)
 			  " 'none'.");
 	}
 
+	if (strcasecmp(method, "onoff") &&
+	    strcasecmp(method, "cycle")) {
+		fail_exit("method, if included, muse be 'onoff', 'cycle'.");
+	}
+
+	if (!strcasecmp(method, "cycle") &&
+	    (!strcasecmp(op, "on") || !strcasecmp(op, "off"))) {
+		fail_exit("cycle method supports only 'reboot' operation (not 'on' or 'off').");
+	}
 
 	/* Ok, set up the IPMI struct */
 	i = ipmi_init(NULL, ip, authtype, user, passwd, lanplus, verbose, timeout, cipher);
@@ -943,11 +999,24 @@ main(int argc, char **argv)
 	if (!strcasecmp(op, "reboot")) {
 		printf("Rebooting machine @ IPMI:%s...", ip);
 		fflush(stdout);
-		ret = ipmi_off(i);
-		if (ret != 0)
-			goto out;
-		ret = ipmi_on(i);
+		if (!strcasecmp(method, "cycle")) {
+			ret = ipmi_op(i, ST_STATUS, power_status);
 
+			if (ret == STATE_OFF) {
+				/* State is off -> use onoff method because cycle is not able to turn on*/
+				snprintf(method, sizeof(method), "onoff");
+			}
+		}
+
+		if (!strcasecmp(method, "cycle")) {
+			ret = ipmi_cycle(i);
+		} else {
+			/* Original onoff method */
+			ret = ipmi_off(i);
+			if (ret != 0)
+				goto out;
+			ret = ipmi_on(i);
+		}
 	} else if (!strcasecmp(op, "on")) {
 		printf("Powering on machine @ IPMI:%s...", ip);
 		fflush(stdout);
diff --git a/fence/man/fence_ipmilan.8 b/fence/man/fence_ipmilan.8
index 19efa99..98006f6 100644
--- a/fence/man/fence_ipmilan.8
+++ b/fence/man/fence_ipmilan.8
@@ -49,6 +49,11 @@ If you are using lanplus, this option avails you to define type of ciphersuite t
 use. Standard is 3 (defined if you just use lanplus). For more information please
 refer ipmitool man page (option -C).
 .TP
+\fB-M\fP \fImethod\fP
+Method to fence (onoff or cycle). Default is onoff. Use cycle in case your management
+card will power off with default method so there will be no chance to power machine
+on by IPMI.
+.TP
 \fB-t\fP \fItimeout\fP
 Timeout in seconds for IPMI operation. Default is 10, but in some cases it
 must be set to higher value (anything above 30 is not recommended and may
@@ -93,6 +98,11 @@ If you are using lanplus, this option avails you to define type of ciphersuite t
 use. Standard is 3 (defined if you just use lanplus). For more information please
 refer ipmitool man page (option -C).
 .TP
+\fImethod = < param >\fR
+Method to fence (onoff or cycle). Default is onoff. Use cycle in case your management
+card will power off with default method so there will be no chance to power machine
+on by IPMI.
+.TP
 \fIlanplus\fR
 If we are using the lanplus option for ipmitool
 


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2009-08-27 15:35 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-08-27 15:35 fence-agents: master - fence: Support for power cycle in fence ipmi Jan Friesse

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).