[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [Linux-cluster] Fwd: fence-agent : ipmilan : power_wait : missing in ipmi_off.



Hi Christine, all,

This is definitely true.

I do not have so nice patches against git master, but I'd like to
present my patches against 3.1.7 which I use for a quite long time (I
send them as I promised year ago or so on pacemaker list).

I attach them in order they are applied in my srpm, and I hope that
their names and contents are self-describing. If not please do not
hesitate to write me.

I would describe some patches here:

01-fence-agents-3.1.7-ipmilan-uniq.patch fixes parameter uniqueness
report (needed for newer pacemaker)

02-fence-agents-3.1.2-ipmilan-cycle.patch fixes return value for cycle
method (nobody uses it yet?)

06-fence-agents-3.1.7-ipmilan-reset-method.patch just adds IPMI reset
method, because some IPMI controllers have bugs in cycle or on-off
implementations and admin may want to use reset which always work with
them.

08-fence-agents-3.1.7-ipmilan-force-ops.patch and
09-fence-agents-3.1.7-ipmilan-status-recheck.patch add more workarounds
against buggy IPMI controllers which may report status incorrectly right
after operation is completed (Supermicro on-board ones are examples of
them).

I definitely do not like amount of function arguments I have after that
all, but it is better to leave it to package maintainer to decide what
to do with them

Pleas do not kick me for sending non-git patches, it is over my skills
to do that.

Best,
Vladislav

03.02.2012 17:22, Christine Caulfield wrote:
> 
> 
> -------- Original Message --------
> Subject: fence-agent : ipmilan : power_wait : missing in ipmi_off.
> Date: Fri, 03 Feb 2012 15:20:47 +0100 (CET)
> From: Alexandre DERUMIER <aderumier odiso com>
> To: ccaulfie redhat com
> 
> Hi,
> 
> I'm working to implement a redhat cluster  and I think I found a bug in
> ipmilan.c
> 
> On this commit:
> 
> fence-agents: Add power_wait to fence_ipmilan
> 
> http://git.fedorahosted.org/git/?p=fence-agents.git;a=commitdiff;h=7d53eb8ab06a8713d2b52500da741b6170fbfc91
> 
> 
> in ipmi_off , the sleep(2) is still hardcorded
> 
> I think It must replace with  sleep(ipmi->i_power_wait), like ipmi_on ?
> 
> 
> index 52be371..46814a8 100644
> --- a/fence/agents/ipmilan/ipmilan.c
> +++ b/fence/agents/ipmilan/ipmilan.c
> @@ -473,7 +473,7 @@ ipmi_off(struct ipmi *ipmi)
>                 if (ret != 0)
>                         return ret;
> 
> -               sleep(2);
> +               sleep(ipmi->i_power_wait);
>                 --retries;
>                 ret = ipmi_op(ipmi, ST_STATUS, power_status);
> 
> 
> 
> What do you thinks about it ?
> 
> 
> 
> Best Regards,
> 
> Alexandre Derumier
> System Engineer
> aderumier odiso com
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> -- 
> Linux-cluster mailing list
> Linux-cluster redhat com
> https://www.redhat.com/mailman/listinfo/linux-cluster

--- fence-agents-3.1.7.orig/fence/agents/ipmilan/ipmilan.c	2011-02-03 21:46:45.000000000 +0100
+++ fence-agents-3.1.7/fence/agents/ipmilan/ipmilan.c	2011-03-26 07:34:47.455695999 +0100
@@ -156,6 +156,7 @@ struct xml_parameter_s {
   const char *name;
   const char *getopt;
   const int required;
+  const int unique;
   const char *content_type;
   const char *default_value;
   const char *description;
@@ -163,20 +164,20 @@ struct xml_parameter_s {
 
 /* Array of xml metadatas*/
 struct xml_parameter_s xml_parameters[]={
-  {"auth","-A",0,"string",NULL,"IPMI Lan Auth type (md5, password, or none)"},
-  {"ipaddr","-a",1,"string",NULL,"IPMI Lan IP to talk to"},
-  {"passwd","-p",0,"string",NULL,"Password (if required) to control power on IPMI device"},
-  {"passwd_script","-S",0,"string",NULL,"Script to retrieve password (if required)"},
-  {"lanplus","-P",0,"boolean",NULL,"Use Lanplus"},
-  {"login","-l",0,"string",NULL,"Username/Login (if required) to control power on IPMI device"},
-  {"action","-o",0,"string","reboot","Operation to perform. Valid operations: on, off, reboot, status, list, diag, monitor or metadata"},
-  {"timeout","-t",0,"string",NULL,"Timeout (sec) for IPMI operation"},
-  {"cipher","-C",0,"string",NULL,"Ciphersuite to use (same as ipmitool -C parameter)"},
-  {"method","-M",0,"string",DEFAULT_METHOD,"Method to fence (onoff or cycle)"},
-  {"power_wait","-T",0,"string","2","Wait X seconds after on/off operation"},
-  {"delay","-f",0,"string",NULL,"Wait X seconds before fencing is started"},
-  {"privlvl","-L",0,"string",NULL,"Privilege level on IPMI device"},
-  {"verbose","-v",0,"boolean",NULL,"Verbose mode"}};
+  {"auth","-A",0,0,"string",NULL,"IPMI Lan Auth type (md5, password, or none)"},
+  {"ipaddr","-a",1,1,"string",NULL,"IPMI Lan IP to talk to"},
+  {"passwd","-p",0,0,"string",NULL,"Password (if required) to control power on IPMI device"},
+  {"passwd_script","-S",0,0,"string",NULL,"Script to retrieve password (if required)"},
+  {"lanplus","-P",0,0,"boolean",NULL,"Use Lanplus"},
+  {"login","-l",0,0,"string",NULL,"Username/Login (if required) to control power on IPMI device"},
+  {"action","-o",0,0,"string","reboot","Operation to perform. Valid operations: on, off, reboot, status, list, diag, monitor or metadata"},
+  {"timeout","-t",0,0,"string",NULL,"Timeout (sec) for IPMI operation"},
+  {"cipher","-C",0,0,"string",NULL,"Ciphersuite to use (same as ipmitool -C parameter)"},
+  {"method","-M",0,0,"string",DEFAULT_METHOD,"Method to fence (onoff or cycle)"},
+  {"power_wait","-T",0,0,"string","2","Wait X seconds after on/off operation"},
+  {"delay","-f",0,0,"string",NULL,"Wait X seconds before fencing is started"},
+  {"privlvl","-L",0,0,"string",NULL,"Privilege level on IPMI device"},
+  {"verbose","-v",0,0,"boolean",NULL,"Verbose mode"}};
 
 /*
    Search for ipmitool
@@ -911,7 +912,7 @@ static void print_xml_metadata(char *pna
   printf("%s\n","<parameters>");
 
   for (i=0;i<(sizeof(xml_parameters)/sizeof(struct xml_parameter_s));i++) {
-    printf("\t<parameter name=\"%s\" unique=\"1\">\n",xml_parameters[i].name);
+    printf("\t<parameter name=\"%s\" unique=\"%d\">\n",xml_parameters[i].name,xml_parameters[i].unique);
 
     printf("\t\t<getopt mixed=\"%s\" />\n",xml_parameters[i].getopt);
     if (xml_parameters[i].default_value == NULL) {
--- fence-agents-3.1.2.orig/fence/agents/ipmilan/ipmilan.c	2011-03-26 07:43:59.000000000 +0100
+++ fence-agents-3.1.2/fence/agents/ipmilan/ipmilan.c	2011-03-26 08:03:03.358695907 +0100
@@ -1125,6 +1125,7 @@ main(int argc, char **argv)
 
 		if (!strcasecmp(method, "cycle")) {
 			ret = ipmi_cycle(i);
+			translated_ret = (ret==0?ERR_OFF_SUCCESSFUL:ERR_OFF_FAIL);
 		} else {
 			/* Original onoff method */
 			ret = ipmi_off(i);
diff -urNp fence-agents-3.1.2.orig/fence/agents/ipmilan/ipmilan.c fence-agents-3.1.2/fence/agents/ipmilan/ipmilan.c
--- fence-agents-3.1.2.orig/fence/agents/ipmilan/ipmilan.c	2011-03-26 08:07:13.000000000 +0100
+++ fence-agents-3.1.2/fence/agents/ipmilan/ipmilan.c	2011-03-26 15:02:05.135947265 +0100
@@ -456,7 +456,7 @@ ipmi_off(struct ipmi *ipmi)
 		if (ret != 0)
 			return ret;
 
-		sleep(2);
+		sleep(ipmi->i_power_wait);
 		--retries;
 		ret = ipmi_op(ipmi, ST_STATUS, power_status);
 
diff -urNp fence-agents-3.1.2.orig/fence/agents/ipmilan/ipmilan.c fence-agents-3.1.2/fence/agents/ipmilan/ipmilan.c
--- fence-agents-3.1.2.orig/fence/agents/ipmilan/ipmilan.c	2011-03-26 15:02:05.000000000 +0100
+++ fence-agents-3.1.2/fence/agents/ipmilan/ipmilan.c	2011-03-26 15:03:36.791070636 +0100
@@ -847,7 +847,7 @@ printf("   ipaddr=<#>            Same as
 printf("   passwd=<pass>         Same as -p\n");
 printf("   passwd_script=<path>  Same as -S\n");
 printf("   lanplus               Same as -P\n");
-printf("   login=<login>         Same as -u\n");
+printf("   login=<login>         Same as -l\n");
 printf("   option=<op>           Same as -o\n");
 printf("   operation=<op>        Same as -o\n");
 printf("   action=<op>           Same as -o\n");
diff -urNp fence-agents-3.1.2.orig/fence/agents/ipmilan/ipmilan.c fence-agents-3.1.2/fence/agents/ipmilan/ipmilan.c
--- fence-agents-3.1.2.orig/fence/agents/ipmilan/ipmilan.c	2011-03-28 09:19:03.000000000 +0200
+++ fence-agents-3.1.2/fence/agents/ipmilan/ipmilan.c	2011-03-28 09:19:35.012696209 +0200
@@ -1088,7 +1088,7 @@ main(int argc, char **argv)
 
 	if (strcasecmp(method, "onoff") &&
 	    strcasecmp(method, "cycle")) {
-		fail_exit("method, if included, muse be 'onoff', 'cycle'.");
+		fail_exit("method, if included, must be 'onoff', 'cycle'.");
 	}
 
 	if (!strcasecmp(method, "cycle") &&
--- fence-agents-3.1.7.orig/fence/agents/ipmilan/ipmilan.c	2011-03-26 15:03:36.000000000 +0100
+++ fence-agents-3.1.7/fence/agents/ipmilan/ipmilan.c	2011-03-26 15:14:11.340695714 +0100
@@ -29,7 +29,8 @@
 #define ST_POWEROFF 2
 #define ST_GENERIC_RESET 3
 #define ST_CYCLE 4
-#define ST_DIAG 5
+#define ST_RESET 5
+#define ST_DIAG 6
 
 #define DEFAULT_TIMEOUT 20
 #define DEFAULT_POWER_WAIT 2
@@ -138,6 +139,17 @@ static struct Etoken power_cycle_complet
 	{NULL, 0, 0}
 };
 
+static struct Etoken power_reset_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},
+	{": Reset", 0, 0},
+	{NULL, 0, 0}
+};
+
 #define STATE_OFF 4096
 #define STATE_ON  8192
 static struct Etoken power_status[] = {
@@ -173,7 +185,7 @@ struct xml_parameter_s xml_parameters[]=
   {"action","-o",0,0,"string","reboot","Operation to perform. Valid operations: on, off, reboot, status, list, diag, monitor or metadata"},
   {"timeout","-t",0,0,"string",NULL,"Timeout (sec) for IPMI operation"},
   {"cipher","-C",0,0,"string",NULL,"Ciphersuite to use (same as ipmitool -C parameter)"},
-  {"method","-M",0,0,"string",DEFAULT_METHOD,"Method to fence (onoff or cycle)"},
+  {"method","-M",0,0,"string",DEFAULT_METHOD,"Method to fence (onoff, cycle or reset)"},
   {"power_wait","-T",0,0,"string","2","Wait X seconds after on/off operation"},
   {"delay","-f",0,0,"string",NULL,"Wait X seconds before fencing is started"},
   {"privlvl","-L",0,0,"string",NULL,"Privilege level on IPMI device"},
@@ -319,6 +331,10 @@ build_cmd(char *command, size_t cmdlen, 
 		snprintf(arg, sizeof(arg),
 			 "%s chassis power cycle", cmd);
 		break;
+	case ST_RESET:
+		snprintf(arg, sizeof(arg),
+			 "%s chassis power reset", cmd);
+		break;
 	case ST_DIAG:
 		snprintf(arg, sizeof(arg),
 			 "%s chassis power diag", cmd);
@@ -548,6 +564,16 @@ ipmi_cycle(struct ipmi *ipmi)
 }
 
 static int
+ipmi_reset(struct ipmi *ipmi)
+{
+	int ret;
+
+	ret = ipmi_op(ipmi, ST_RESET, power_reset_complete);
+
+	return ret;
+}
+
+static int
 ipmi_diag(struct ipmi *ipmi)
 {
 	int ret;
@@ -870,7 +896,7 @@ printf("   -t <timeout>   Timeout (sec) 
 printf("   -T <timeout>   Wait X seconds after on/off operation\n");
 printf("   -f <timeout>   Wait X seconds before fencing is started\n");
 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("   -M <method>    Method to fence (onoff, cycle or reset) (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");
@@ -1130,8 +1156,9 @@ main(int argc, char **argv)
 	}
 
 	if (strcasecmp(method, "onoff") &&
-	    strcasecmp(method, "cycle")) {
-		fail_exit("method, if included, must be 'onoff', 'cycle'.");
+	    strcasecmp(method, "cycle") &&
+	    strcasecmp(method, "reset")) {
+		fail_exit("method, if included, must be 'onoff', 'cycle', 'reset'.");
 	}
 
 	if (!strcasecmp(method, "cycle") &&
@@ -1139,6 +1166,11 @@ main(int argc, char **argv)
 		fail_exit("cycle method supports only 'reboot' operation (not 'on' or 'off').");
 	}
 
+	if (!strcasecmp(method, "reset") &&
+	    (!strcasecmp(op, "on") || !strcasecmp(op, "off"))) {
+		fail_exit("reset method supports only 'reboot' operation (not 'on' or 'off').");
+	}
+
 	/* Delay fencing if requested */
 	if (delay) {
 		if (!strcasecmp(op, "reboot") || !strcasecmp(op, "off")) {
@@ -1157,7 +1189,7 @@ main(int argc, char **argv)
 	if (!strcasecmp(op, "reboot")) {
 		printf("Rebooting machine @ IPMI:%s...", ip);
 		fflush(stdout);
-		if (!strcasecmp(method, "cycle")) {
+		if (!strcasecmp(method, "cycle") || !strcasecmp(method, "reset")) {
 			ret = ipmi_op(i, ST_STATUS, power_status);
 
 			if (ret == STATE_OFF) {
@@ -1169,6 +1201,9 @@ main(int argc, char **argv)
 		if (!strcasecmp(method, "cycle")) {
 			ret = ipmi_cycle(i);
 			translated_ret = (ret==0?ERR_OFF_SUCCESSFUL:ERR_OFF_FAIL);
+		} else if (!strcasecmp(method, "reset")) {
+			ret = ipmi_reset(i);
+			translated_ret = (ret==0?ERR_OFF_SUCCESSFUL:ERR_OFF_FAIL);
 		} else {
 			/* Original onoff method */
 			ret = ipmi_off(i);
diff -urNp fence-agents-3.1.2.orig/fence/agents/ipmilan/ipmilan.c fence-agents-3.1.2/fence/agents/ipmilan/ipmilan.c
--- fence-agents-3.1.2.orig/fence/agents/ipmilan/ipmilan.c	2011-03-26 15:15:58.000000000 +0100
+++ fence-agents-3.1.2/fence/agents/ipmilan/ipmilan.c	2011-03-26 15:19:30.869070840 +0100
@@ -1129,9 +1129,12 @@ main(int argc, char **argv)
 	}
 
 	/* Delay fencing if requested */
-	if (delay) {
+	if (delay[0] != '\0') {
 		if (!strcasecmp(op, "reboot") || !strcasecmp(op, "off")) {
-			sleep(atoi(delay));
+			int delay_time = atoi(delay);
+			if (delay_time) {
+				sleep(delay_time);
+			}
 		}
 	}
 
--- fence-agents-3.1.7.orig/fence/agents/ipmilan/ipmilan.c	2011-03-28 11:15:41.052950785 +0200
+++ fence-agents-3.1.7/fence/agents/ipmilan/ipmilan.c	2011-03-28 11:16:16.338820731 +0200
@@ -87,6 +87,7 @@ struct ipmi {
 	int i_timeout;
 	int i_power_wait;
 	int i_cipher;
+	int i_force_ops;
 };
 
 
@@ -189,7 +190,8 @@ struct xml_parameter_s xml_parameters[]=
   {"power_wait","-T",0,0,"string","2","Wait X seconds after on/off operation"},
   {"delay","-f",0,0,"string",NULL,"Wait X seconds before fencing is started"},
   {"privlvl","-L",0,0,"string",NULL,"Privilege level on IPMI device"},
-  {"verbose","-v",0,0,"boolean",NULL,"Verbose mode"}};
+  {"verbose","-v",0,0,"boolean",NULL,"Verbose mode"},
+  {"force","-F",0,0,"boolean",NULL,"Force power operations even if status reports matching power state."}};
 
 /*
    Search for ipmitool
@@ -480,7 +482,10 @@ ipmi_off(struct ipmi *ipmi)
 	case STATE_ON:
 		break;
 	case STATE_OFF:
-		return 0;
+		if (!ipmi->i_force_ops) {
+			return 0;
+		}
+		break;
 	default:
 		return ret;
 	}
@@ -520,7 +525,10 @@ ipmi_on(struct ipmi *ipmi)
 	ret = ipmi_op(ipmi, ST_STATUS, power_status);
 	switch(ret) {
 	case STATE_ON:
-		return 0;
+		if (!ipmi->i_force_ops) {
+			return 0;
+		}
+		break;
 	case STATE_OFF:
 		break;
 	default:
@@ -620,7 +628,7 @@ static struct ipmi *
 ipmi_init(struct ipmi *i, char *host, char *authtype,
 	  char *user, char *password, int lanplus, int verbose,int timeout,
 	  int power_wait,
-	  int cipher, char *privlvl)
+	  int cipher, char *privlvl, int force_ops)
 {
 	const char *p;
 
@@ -698,6 +706,7 @@ ipmi_init(struct ipmi *i, char *host, ch
 	i->i_timeout = timeout;
 	i->i_power_wait = power_wait;
 	i->i_cipher = cipher;
+	i->i_force_ops = force_ops;
 
 	return i;
 }
@@ -763,7 +772,7 @@ get_options_stdin(char *ip, size_t iplen
 		  int *power_wait,
 	          int *cipher, char *method, int methodlen,
 	          char *delay, size_t delaylen,
-		  char *privlvl, size_t privlen)
+		  char *privlvl, size_t privlen, int *force_ops)
 {
 	char in[256];
 	int line = 0;
@@ -857,6 +866,8 @@ get_options_stdin(char *ip, size_t iplen
 				strncpy(delay, val, delaylen);
 			else
 				delay[0] = 0;
+		} else if (!strcasecmp(name, "force")) {
+			(*force_ops) = 1;
 		}
 	}
 
@@ -898,7 +909,9 @@ printf("   -f <timeout>   Wait X seconds
 printf("   -C <cipher>    Ciphersuite to use (same as ipmitool -C parameter)\n");
 printf("   -M <method>    Method to fence (onoff, cycle or reset) (default %s)\n", DEFAULT_METHOD);
 printf("   -V             Print version and exit\n");
-printf("   -v             Verbose mode\n\n");
+printf("   -v             Verbose mode\n");
+printf("   -F             Force power operations (on, off) even if current status\n"
+       "                  matches required state\n\n");
 printf("If no options are specified, the following options will be read\n");
 printf("from standard input (one per line):\n\n");
 printf("   auth=<auth>           Same as -A\n");
@@ -916,7 +929,8 @@ printf("   power_wait=<time>     Same as
 printf("   cipher=<cipher>       Same as -C\n");
 printf("   method=<method>       Same as -M\n");
 printf("   privlvl=<privlvl>     Same as -L\n");
-printf("   verbose               Same as -v\n\n");
+printf("   verbose               Same as -v\n");
+printf("   force                 Same as -F\n\n");
 	exit(1);
 }
 
@@ -984,6 +998,7 @@ main(int argc, char **argv)
 	char pwd_script[PATH_MAX] = { 0, };
 	int lanplus=0;
 	int verbose=0;
+	int force_ops=0;
 	char *pname = basename(argv[0]);
 	struct ipmi *i;
 	int timeout=DEFAULT_TIMEOUT;
@@ -1005,7 +1020,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:T:C:M:f:L:")) != EOF) {
+		while ((opt = getopt(argc, argv, "A:a:i:l:p:S:Po:vV?hHt:T:C:M:f:L:F")) != EOF) {
 			switch(opt) {
 			case 'A':
 				/* Auth type */
@@ -1077,6 +1092,9 @@ main(int argc, char **argv)
         			printf("%s\n",
 				       REDHAT_COPYRIGHT);
 				return 0;
+			case 'F':
+				force_ops=1;
+				break;
 			default:
 				usage_exit(pname);
 			}
@@ -1094,7 +1112,7 @@ main(int argc, char **argv)
 				      &down_sleep,
 				      &cipher, method, sizeof(method),
 				      delay, sizeof(delay),
-				      privlvl, sizeof(privlvl)) != 0)
+				      privlvl, sizeof(privlvl), &force_ops) != 0)
 			return 1;
 	}
 
@@ -1182,7 +1200,7 @@ main(int argc, char **argv)
 	}
 
 	/* Ok, set up the IPMI struct */
-	i = ipmi_init(NULL, ip, authtype, user, passwd, lanplus, verbose, timeout, down_sleep, cipher, privlvl);
+	i = ipmi_init(NULL, ip, authtype, user, passwd, lanplus, verbose, timeout, down_sleep, cipher, privlvl, force_ops);
 	if (!i)
 		fail_exit("Failed to initialize\n");
 
--- fence-agents-3.1.7.orig/fence/agents/ipmilan/ipmilan.c	2011-03-28 12:22:26.504946459 +0200
+++ fence-agents-3.1.7/fence/agents/ipmilan/ipmilan.c	2011-03-28 12:16:26.819695689 +0200
@@ -34,6 +34,7 @@
 
 #define DEFAULT_TIMEOUT 20
 #define DEFAULT_POWER_WAIT 2
+#define DEFAULT_RECHECK_WAIT 1
 
 #define DEFAULT_METHOD "onoff"
 
@@ -88,6 +89,8 @@ struct ipmi {
 	int i_power_wait;
 	int i_cipher;
 	int i_force_ops;
+	int i_status_rechecks;
+	int i_recheck_wait;
 };
 
 
@@ -191,7 +194,9 @@ struct xml_parameter_s xml_parameters[]=
   {"delay","-f",0,0,"string",NULL,"Wait X seconds before fencing is started"},
   {"privlvl","-L",0,0,"string",NULL,"Privilege level on IPMI device"},
   {"verbose","-v",0,0,"boolean",NULL,"Verbose mode"},
-  {"force","-F",0,0,"boolean",NULL,"Force power operations even if status reports matching power state."}};
+  {"force","-F",0,0,"boolean",NULL,"Force power operations even if status reports matching power state."},
+  {"rechecks","-R",0,0,"string",NULL,"Number of status re-checks after on and off operations."},
+  {"recheck_wait","-W",0,0,"string",NULL,"Wait X seconds between status re-checks."}};
 
 /*
    Search for ipmitool
@@ -476,38 +481,62 @@ static int
 ipmi_off(struct ipmi *ipmi)
 {
 	int ret, retries = 7;
+	int status_retries = 3;
+	int successes = 0;
 
-	ret = ipmi_op(ipmi, ST_STATUS, power_status);
-	switch(ret) {
-	case STATE_ON:
-		break;
-	case STATE_OFF:
-		if (!ipmi->i_force_ops) {
-			return 0;
+	if (ipmi->i_status_rechecks > status_retries) {
+		status_retries = ipmi->i_status_rechecks;
+	}
+	while (status_retries>0) {
+		ret = ipmi_op(ipmi, ST_STATUS, power_status);
+		status_retries--;
+		switch(ret) {
+		case STATE_ON:
+			break;
+		case STATE_OFF:
+			if (!ipmi->i_force_ops) {
+				if (successes >= ipmi->i_status_rechecks) {
+					return 0;
+				} else {
+					successes++;
+				}
+			}
+			break;
+		default:
+			return ret;
 		}
-		break;
-	default:
-		return ret;
+		sleep(ipmi->i_recheck_wait);
 	}
 
+	successes = 0;
 	while (retries>=0) {
-		ret = ipmi_op(ipmi, ST_POWEROFF, power_off_complete);
-		if (ret != 0)
-			return ret;
+		if (successes == 0) {
+			ret = ipmi_op(ipmi, ST_POWEROFF, power_off_complete);
+			if (ret != 0)
+				return ret;
+			sleep(ipmi->i_power_wait);
+			--retries;
+		} else {
+			sleep(ipmi->i_recheck_wait);
+		}
 
-		sleep(ipmi->i_power_wait);
-		--retries;
 		ret = ipmi_op(ipmi, ST_STATUS, power_status);
 
 		switch(ret) {
 		case STATE_OFF:
-			return 0;
+			if (successes >= ipmi->i_status_rechecks) {
+				return 0;
+			} else {
+				successes++;
+				continue;
+			}
 		case EFAULT:
 			/* We're done. */
 			retries = 0;
 			break;
 		case STATE_ON:
 		default:
+			successes = 0;
 			continue;
 		}
 	}
@@ -521,38 +550,62 @@ static int
 ipmi_on(struct ipmi *ipmi)
 {
 	int ret, retries = 7;
+	int status_retries = 3;
+	int successes = 0;
 
-	ret = ipmi_op(ipmi, ST_STATUS, power_status);
-	switch(ret) {
-	case STATE_ON:
-		if (!ipmi->i_force_ops) {
-			return 0;
+	if (ipmi->i_status_rechecks > status_retries) {
+		status_retries = ipmi->i_status_rechecks;
+	}
+	while (status_retries>0) {
+		ret = ipmi_op(ipmi, ST_STATUS, power_status);
+		status_retries--;
+		switch(ret) {
+		case STATE_ON:
+			if (!ipmi->i_force_ops) {
+				if (successes >= ipmi->i_status_rechecks) {
+					return 0;
+				} else {
+					successes++;
+				}
+			}
+			break;
+		case STATE_OFF:
+			break;
+		default:
+			return ret;
 		}
-		break;
-	case STATE_OFF:
-		break;
-	default:
-		return ret;
+		sleep(ipmi->i_recheck_wait);
 	}
 
+	successes = 0;
 	while (retries>=0) {
-		ret = ipmi_op(ipmi, ST_POWERON, power_on_complete);
-		if (ret != 0)
-			return ret;
+		if (successes == 0) {
+			ret = ipmi_op(ipmi, ST_POWERON, power_on_complete);
+			if (ret != 0)
+				return ret;
+			sleep(ipmi->i_power_wait);
+			--retries;
+		} else {
+			sleep(ipmi->i_recheck_wait);
+		}
 
-		sleep(ipmi->i_power_wait);
-		--retries;
 		ret = ipmi_op(ipmi, ST_STATUS, power_status);
 
 		switch(ret) {
 		case STATE_ON:
-			return 0;
+			if (successes >= ipmi->i_status_rechecks) {
+				return 0;
+			} else {
+				successes++;
+				continue;
+			}
 		case EFAULT:
 			/* We're done. */
 			retries = 0;
 			break;
 		case STATE_OFF:
 		default:
+			successes = 0;
 			continue;
 		}
 	}
@@ -628,7 +681,7 @@ static struct ipmi *
 ipmi_init(struct ipmi *i, char *host, char *authtype,
 	  char *user, char *password, int lanplus, int verbose,int timeout,
 	  int power_wait,
-	  int cipher, char *privlvl, int force_ops)
+	  int cipher, char *privlvl, int force_ops, int status_rechecks, int recheck_wait)
 {
 	const char *p;
 
@@ -707,7 +760,8 @@ ipmi_init(struct ipmi *i, char *host, ch
 	i->i_power_wait = power_wait;
 	i->i_cipher = cipher;
 	i->i_force_ops = force_ops;
-
+	i->i_status_rechecks = status_rechecks;
+	i->i_recheck_wait = recheck_wait;
 	return i;
 }
 
@@ -772,7 +826,9 @@ get_options_stdin(char *ip, size_t iplen
 		  int *power_wait,
 	          int *cipher, char *method, int methodlen,
 	          char *delay, size_t delaylen,
-		  char *privlvl, size_t privlen, int *force_ops)
+		  char *privlvl, size_t privlen,
+		  int *force_ops,
+		  int *status_rechecks, int *recheck_wait)
 {
 	char in[256];
 	int line = 0;
@@ -868,6 +924,10 @@ get_options_stdin(char *ip, size_t iplen
 				delay[0] = 0;
 		} else if (!strcasecmp(name, "force")) {
 			(*force_ops) = 1;
+		} else if (!strcasecmp(name, "rechecks")) {
+			sscanf(val,"%d",status_rechecks);
+		} else if (!strcasecmp(name, "recheck_wait")) {
+			sscanf(val,"%d",recheck_wait);
 		}
 	}
 
@@ -911,7 +971,10 @@ printf("   -M <method>    Method to fenc
 printf("   -V             Print version and exit\n");
 printf("   -v             Verbose mode\n");
 printf("   -F             Force power operations (on, off) even if current status\n"
-       "                  matches required state\n\n");
+       "                  matches required state\n");
+printf("   -R <number>    Re-check power status X times before changing power status\n"
+       "                  and until X successes after changing it\n");
+printf("   -W <timeout>   Wait X seconds betweet power status checks operations\n\n");
 printf("If no options are specified, the following options will be read\n");
 printf("from standard input (one per line):\n\n");
 printf("   auth=<auth>           Same as -A\n");
@@ -930,7 +993,9 @@ printf("   cipher=<cipher>       Same as
 printf("   method=<method>       Same as -M\n");
 printf("   privlvl=<privlvl>     Same as -L\n");
 printf("   verbose               Same as -v\n");
-printf("   force                 Same as -F\n\n");
+printf("   force                 Same as -F\n");
+printf("   recheck=<number>      Same as -R\n");
+printf("   recheck_wait=<time>   Same as -W\n\n");
 	exit(1);
 }
 
@@ -999,6 +1064,8 @@ main(int argc, char **argv)
 	int lanplus=0;
 	int verbose=0;
 	int force_ops=0;
+	int status_rechecks=0;
+	int recheck_wait=DEFAULT_RECHECK_WAIT;
 	char *pname = basename(argv[0]);
 	struct ipmi *i;
 	int timeout=DEFAULT_TIMEOUT;
@@ -1020,7 +1087,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:T:C:M:f:L:F")) != EOF) {
+		while ((opt = getopt(argc, argv, "A:a:i:l:p:S:Po:vV?hHt:T:C:M:f:L:FR:W:")) != EOF) {
 			switch(opt) {
 			case 'A':
 				/* Auth type */
@@ -1095,6 +1162,16 @@ main(int argc, char **argv)
 			case 'F':
 				force_ops=1;
 				break;
+			case 'R':
+				if ((sscanf(optarg,"%d",&status_rechecks)!=1) || status_rechecks<1) {
+				    fail_exit("Status re-checks option expects positive number parameter");
+				}
+				break;
+			case 'W':
+				if ((sscanf(optarg,"%d",&recheck_wait)!=1) || recheck_wait<1) {
+				    fail_exit("Re-check wait time option expects positive number parameter");
+				}
+				break;
 			default:
 				usage_exit(pname);
 			}
@@ -1112,7 +1189,8 @@ main(int argc, char **argv)
 				      &down_sleep,
 				      &cipher, method, sizeof(method),
 				      delay, sizeof(delay),
-				      privlvl, sizeof(privlvl), &force_ops) != 0)
+				      privlvl, sizeof(privlvl), &force_ops,
+				      &status_rechecks, &recheck_wait) != 0)
 			return 1;
 	}
 
@@ -1200,7 +1278,8 @@ main(int argc, char **argv)
 	}
 
 	/* Ok, set up the IPMI struct */
-	i = ipmi_init(NULL, ip, authtype, user, passwd, lanplus, verbose, timeout, down_sleep, cipher, privlvl, force_ops);
+	i = ipmi_init(NULL, ip, authtype, user, passwd, lanplus, verbose, timeout, down_sleep, cipher,
+		privlvl, force_ops, status_rechecks, recheck_wait);
 	if (!i)
 		fail_exit("Failed to initialize\n");
 

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]