This is the mail archive of the cluster-cvs@sourceware.org mailing list for the cluster.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

cluster: RHEL55 - fence: Support for power cycle in fence ipmi


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=fea471dc31137bb3c2583f369cf3af4a0e7eefcb
Commit:        fea471dc31137bb3c2583f369cf3af4a0e7eefcb
Parent:        f8877454b5edee6c25830dd450895933586a9f3f
Author:        Jan Friesse <jfriesse@redhat.com>
AuthorDate:    Mon Jul 20 13:47:52 2009 +0200
Committer:     Jan Friesse <jfriesse@redhat.com>
CommitterDate: Tue Sep 1 12:22:16 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 a7e30c5..82cbbb0 100644
--- a/fence/agents/ipmilan/ipmilan.c
+++ b/fence/agents/ipmilan/ipmilan.c
@@ -51,9 +51,12 @@ do { \
 #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>
 
@@ -116,7 +119,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 */
@@ -137,6 +140,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
@@ -279,6 +293,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);
@@ -387,6 +405,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,
@@ -480,6 +504,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
@@ -870,13 +904,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;
@@ -940,6 +975,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")) {
@@ -981,6 +1018,7 @@ printf("   -o <op>        Operation to perform.\n");
 printf("                  Valid operations: on, off, reboot, status\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");
@@ -996,6 +1034,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);
 }
@@ -1011,6 +1050,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;
@@ -1029,7 +1069,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 */
@@ -1071,6 +1111,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;
@@ -1095,7 +1139,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;
 	}
 
@@ -1129,6 +1173,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")) {
 		fail_exit("operation must be 'on', 'off', 'status', "
@@ -1143,6 +1190,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);
@@ -1155,11 +1211,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 588a41c..9b10198 100644
--- a/fence/man/fence_ipmilan.8
+++ b/fence/man/fence_ipmilan.8
@@ -53,6 +53,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
@@ -94,6 +99,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
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]