public inbox for cluster-cvs@sourceware.org
help / color / mirror / Atom feed
From: Jan Friesse <honzaf@fedoraproject.org>
To: cluster-cvs-relay@redhat.com
Subject: fence-agents: master - fence: Support for power cycle in fence ipmi
Date: Thu, 27 Aug 2009 15:35:00 -0000	[thread overview]
Message-ID: <20090827153426.01A71120194@lists.fedorahosted.org> (raw)

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
 


                 reply	other threads:[~2009-08-27 15:35 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090827153426.01A71120194@lists.fedorahosted.org \
    --to=honzaf@fedoraproject.org \
    --cc=cluster-cvs-relay@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).