Gitweb:
http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 517421acde2cb0d56368cfa508a95317d34f5ce7
Parent: c11570abe26008d5c5328932f2adf312978c2130
Author: Jan Friesse <jfriesse(a)redhat.com>
AuthorDate: Wed Aug 4 16:19:27 2010 +0200
Committer: Jan Friesse <jfriesse(a)redhat.com>
CommitterDate: Wed Aug 4 16:19:27 2010 +0200
fence_ipmilan: Support for power cycle in fence ipmi
Default behavior (off/get status/on) doesn't work on
some IPMI implementations, because chassis 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
Resolves: rhbz#576036
---
fence/agents/ipmilan/ipmilan.c | 88 ++++++++++++++++++++++++++++++++++++----
fence/man/fence_ipmilan.8 | 10 +++++
2 files changed, 90 insertions(+), 8 deletions(-)
diff --git a/fence/agents/ipmilan/ipmilan.c b/fence/agents/ipmilan/ipmilan.c
index 2beb15a..a4c91d2 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>
@@ -113,7 +116,7 @@ const char *ipmitool_paths[] = {
NULL
};
-
+#define ESTATE (8192*2)
static struct Etoken power_on_complete[] = {
{"Password:", EPERM, 0},
{"Unable to establish LAN", EAGAIN, 0}, /* Retry */
@@ -130,6 +133,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
@@ -265,6 +279,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);
@@ -367,6 +385,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,
@@ -460,6 +484,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
@@ -847,13 +881,15 @@ get_options_stdin(char *ip, size_t iplen,
char *pwd_script, size_t pwd_script_len,
char *user, size_t userlen,
char *op, size_t oplen,
- int *lanplus, int *verbose,int *timeout)
+ int *lanplus, int *verbose,int *timeout,
+ 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;
@@ -913,6 +949,8 @@ get_options_stdin(char *ip, size_t iplen,
if ((sscanf(val,"%d",timeout)!=1) || *timeout<1) {
*timeout=DEFAULT_TIMEOUT;
}
+ } else if (!strcasecmp(name,"method")) {
+ strncpy (method, val, methodlen);
} else if (!strcasecmp(name, "option") ||
!strcasecmp(name, "operation") ||
!strcasecmp(name, "action")) {
@@ -953,6 +991,7 @@ printf(" -l <login> Username/Login (if required) to
control power\n"
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(" -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");
@@ -967,6 +1006,7 @@ printf(" option=<op> Same as -o\n");
printf(" operation=<op> Same as -o\n");
printf(" action=<op> Same as -o\n");
printf(" timeout=<timeout> Same as -t\n");
+printf(" method=<method> Same as -M\n");
printf(" verbose Same as -v\n\n");
exit(1);
}
@@ -982,6 +1022,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;
@@ -994,12 +1035,13 @@ main(int argc, char **argv)
memset(passwd, 0, sizeof(passwd));
memset(user, 0, sizeof(user));
memset(op, 0, sizeof(op));
+ memset(method, 0 ,sizeof(method));
if (argc > 1) {
/*
Parse command line options if any were specified
*/
- while ((opt = getopt(argc, argv, "A:a:i:l:p:S:Po:vV?hHt:")) != EOF) {
+ while ((opt = getopt(argc, argv, "A:a:i:l:p:S:Po:vV?hHt:M:")) != EOF) {
switch(opt) {
case 'A':
/* Auth type */
@@ -1035,6 +1077,10 @@ main(int argc, char **argv)
fail_exit("Timeout option expects positive number parameter");
}
break;
+ case 'M':
+ /* Reboot method */
+ strncpy(method, optarg, sizeof(method));
+ break;
case 'v':
verbose++;
break;
@@ -1058,7 +1104,8 @@ main(int argc, char **argv)
passwd, sizeof(passwd),
pwd_script, sizeof(pwd_script),
user, sizeof(user),
- op, sizeof(op), &lanplus, &verbose,&timeout) != 0)
+ op, sizeof(op), &lanplus, &verbose,&timeout,
+ method, sizeof(method)) != 0)
return 1;
}
@@ -1092,6 +1139,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',
"
@@ -1106,6 +1156,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);
@@ -1118,11 +1177,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 d6f3daf..5bcdf8c 100644
--- a/fence/man/fence_ipmilan.8
+++ b/fence/man/fence_ipmilan.8
@@ -48,6 +48,11 @@ Full path to an executable to generate the password for login.
\fB-A\fP \fIAuthentication Type\fP
Can be set to none, password, md2, or md5.
.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
@@ -86,6 +91,11 @@ Authentication type (none, password, md2, md5).
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
cause strange problems).
+.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.
.SH SEE ALSO
fence(8), fence_node(8)