Gitweb: http://git.fedorahosted.org/git/?p=fence-agents.git;a=commitdiff;h=821478ebc... Commit: 821478ebcd1b6ee31636e7910bc35fb41b4834b1 Parent: 625c42b5b8e16171f7efc65a4e88b3be92e04f18 Author: Marek 'marx' Grac mgrac@redhat.com AuthorDate: Mon Jan 6 17:04:38 2014 +0100 Committer: Marek 'marx' Grac mgrac@redhat.com CommitterDate: Mon Jan 6 17:04:38 2014 +0100
fence_ipmilan: Remove old fence agent
--- fence/agents/ipmilan/expect.c | 343 ----------- fence/agents/ipmilan/expect.h | 52 -- fence/agents/ipmilan/ipmilan.c | 1279 ---------------------------------------- 3 files changed, 0 insertions(+), 1674 deletions(-)
diff --git a/fence/agents/ipmilan/expect.c b/fence/agents/ipmilan/expect.c deleted file mode 100644 index 2ed40f0..0000000 --- a/fence/agents/ipmilan/expect.c +++ /dev/null @@ -1,343 +0,0 @@ -/** @file - * Simple expect module for the STONITH library. - */ -#include "clusterautoconfig.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <signal.h> -#include <string.h> -#include <errno.h> -#include <syslog.h> -#include <libintl.h> -#include <sys/wait.h> -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <stdarg.h> -#include <string.h> -#include <unistd.h> -#include <signal.h> -#include <errno.h> -#include <time.h> -#include <sys/time.h> -#include <sys/times.h> -#ifdef _POSIX_PRIORITY_SCHEDULING -# include <sched.h> -#endif - -#include "expect.h" - -#ifndef EOS -# define EOS '\0' -#endif - - -/* - * Just incase we are on an out of date system - */ -#ifndef CLOCKS_PER_SEC -# ifndef CLK_TCK -# error Neither CLOCKS_PER_SEC nor CLK_TCK (obsolete) are defined -# endif /* CLK_TCK */ -# define CLOCKS_PER_SEC CLK_TCK -#endif /* CLOCKS_PER_SEC */ - - -void close_all_files (void); - -/** - * Look for ('expect') any of a series of tokens in the input - * Return the token type for the given token or -1 on error. - * - * @param fd The file descriptor to watch. - * @param toklist The series of tokens to look for. - * @param to_secs Timeout (in seconds). - * @param buf Receive buffer (preallocated). - * @param maxline Length of receive buffer. - */ -int -ExpectToken(int fd, struct Etoken * toklist, int to_secs, char * buf -, int maxline) -{ - clock_t starttime; - clock_t endtime; - int wraparound=0; - int tickstousec = (1000000/CLOCKS_PER_SEC); - clock_t now; - clock_t ticks; - int nchars = 1; /* reserve space for an EOS */ - struct timeval tv; - struct tms tms_unused; /*This tms is unused, but cygwin doesn't like NULL in times*/ - struct Etoken * this; - - /* Figure out when to give up. Handle lbolt wraparound */ - if (fd < 0) { - errno = EINVAL; - return -1; - } - - starttime = times(&tms_unused); - ticks = (to_secs*CLOCKS_PER_SEC); - endtime = starttime + ticks; - - if (endtime < starttime) { - wraparound = 1; - } - - if (buf) { - *buf = EOS; - } - - for (this=toklist; this->string; ++this) { - this->matchto = 0; - } - - - while (now = times(&tms_unused), - (wraparound && (now > starttime || now <= endtime)) - || (!wraparound && now <= endtime)) { - - fd_set infds; - char ch; - clock_t timeleft; - int retval; - - timeleft = endtime - now; - - tv.tv_sec = timeleft / CLOCKS_PER_SEC; - tv.tv_usec = (timeleft % CLOCKS_PER_SEC) * tickstousec; - - if (tv.tv_sec == 0 && tv.tv_usec < tickstousec) { - /* Give 'em a little chance */ - tv.tv_usec = tickstousec; - } - - /* Watch our FD to see when it has input. */ - FD_ZERO(&infds); - FD_SET(fd, &infds); - - retval = select(fd+1, &infds, NULL, NULL, &tv); - if (retval <= 0) { - errno = ETIMEDOUT; - return(-1); - } - /* Whew! All that work just to read one character! */ - - if (read(fd, &ch, sizeof(ch)) <= 0) { - return(-1); - } - /* Save the text, if we can */ - if (buf && nchars < maxline-1) { - *buf = ch; - ++buf; - *buf = EOS; - ++nchars; - } -#if 0 - fprintf(stderr, "%c", ch); -#endif - - /* See how this character matches our expect strings */ - - for (this=toklist; this->string; ++this) { - - if (ch == this->string[this->matchto]) { - - /* It matches the current token */ - - ++this->matchto; - if (this->string[this->matchto] == EOS){ - /* Hallelujah! We matched */ - return(this->toktype); - } - }else{ - - /* It doesn't appear to match this token */ - - int curlen; - int nomatch=1; - /* - * If we already had a match (matchto is - * greater than zero), we look for a match - * of the tail of the pattern matched so far - * (with the current character) against the - * head of the pattern. - */ - - /* - * This is to make the string "aab" match - * the pattern "ab" correctly - * Painful, but nice to do it right. - */ - - for (curlen = (this->matchto) - ; nomatch && curlen >= 0 - ; --curlen) { - const char * tail; - tail=(this->string) - + this->matchto - - curlen; - - if (strncmp(this->string, tail - , curlen) == 0 - && this->string[curlen] == ch) { - - if (this->string[curlen+1]==EOS){ - /* We matched! */ - /* (can't happen?) */ - return(this->toktype); - } - this->matchto = curlen+1; - nomatch=0; - } - } - if (nomatch) { - this->matchto = 0; - } - } - } - } - errno = ETIMEDOUT; - return(-1); -} - -/** - * Start a process with its stdin and stdout redirected to pipes - * so the parent process can talk to it. - * - * @param cmd Command line to run. - * @param readfd Filled with a pipe to the the output of the - * new child. - * @param writefd Filled with a pipe to the input of the new - * child. - * @param redir_err 0, 1 = stderr, 2 = setsid, 3 = both - * @return -1 on failure (with errno set appropriately) or - * or the PID of the new child process. - */ -int -StartProcess(const char * cmd, int * readfd, int * writefd, int flags) -{ - pid_t pid; - int wrpipe[2]; /* The pipe the parent process writes to */ - /* (which the child process reads from) */ - int rdpipe[2]; /* The pipe the parent process reads from */ - /* (which the child process writes to) */ - - if (pipe(wrpipe) < 0) { - perror("cannot create pipe\n"); - return(-1); - } - if (pipe(rdpipe) < 0) { - perror("cannot create pipe\n"); - close(wrpipe[0]); - close(wrpipe[1]); - return(-1); - } - switch(pid=fork()) { - case -1: - perror("cannot StartProcess cmd"); - close(rdpipe[0]); - close(rdpipe[1]); - close(wrpipe[0]); - close(wrpipe[1]); - return(-1); - - case 0: - /* We are the child */ - /* Redirect stdin */ - if (wrpipe[0] != 0) { - close(0); - if(dup2(wrpipe[0], 0) < 0) { - syslog(LOG_CRIT, - "StartProcess: dup2(%d,0) failed: %s\n", - wrpipe[0], - strerror(errno)); - exit(1); - } - close(wrpipe[0]); - } - close(wrpipe[1]); - - /* Redirect stdout */ - if (rdpipe[1] != 1) { - close(1); - if(dup2(rdpipe[1], 1) < 0) { - syslog(LOG_CRIT, - "StartProcess: dup2(%d,1) failed: %s\n", - rdpipe[1], - strerror(errno)); - exit(1); - } - close(rdpipe[1]); - } - close(rdpipe[0]); - - if (flags & EXP_STDERR) { - /* Redirect stderr */ - close(2); - if(dup2(1, 2) < 0) { - syslog(LOG_CRIT, - "StartProcess: dup2(1,2) failed: %s\n", - strerror(errno)); - exit(1); - } - } - - if (flags & EXP_NOCTTY) - setsid(); - close_all_files(); /* Workaround telnet bugs */ -#if defined(SCHED_OTHER) - { - /* - * Try and (re)set our scheduling to "normal" - * Sometimes our callers run in soft - * real-time mode. The program we exec might - * not be very well behaved - this is bad for - * operation in high-priority (soft real-time) - * mode. In particular, telnet is prone to - * going into infinite loops when killed. - */ - struct sched_param sp; - memset(&sp, 0, sizeof(sp)); - sp.sched_priority = 0; - sched_setscheduler(0, SCHED_OTHER, &sp); - } -#endif - execlp("/bin/bash", "bash", "-c", cmd, NULL); - perror("cannot exec shell!"); - exit(1); - - default: /* We are the parent */ - *readfd = rdpipe[0]; - close(rdpipe[1]); - *writefd = wrpipe[1]; - close(wrpipe[0]); - return(pid); - } - /*NOTREACHED*/ - return(-1); -} - -/** - * Close all file descriptors in a child process. - * - * Open fd's are inherited across exec unless they are - * marked close on exec, which must be done explicitly - * with fcntl(). While this should not affect the operation of - * telnet, it was found that in some cases it did. Its easier to - * just fix it this way than to fix telnet. - */ -void -close_all_files (void) -{ - register int i, fd_table_size; - - fd_table_size = getdtablesize (); - if (fd_table_size > 256)/* clamp to a reasonable value */ - fd_table_size = 256; - - for (i = 3; i < fd_table_size; i++) - close (i); -} diff --git a/fence/agents/ipmilan/expect.h b/fence/agents/ipmilan/expect.h deleted file mode 100644 index 41d398a..0000000 --- a/fence/agents/ipmilan/expect.h +++ /dev/null @@ -1,52 +0,0 @@ -/** @file - * Header for expect.c. - * - * Expect simple tokens. Simple expect infrastructure for STONITH API - * - */ - -#ifndef __EXPECT_H -# define __EXPECT_H -/* - * If we find any of the given tokens in the input stream, - * we return it's "toktype", so we can tell which one was - * found. - * - */ - -/** - * A token we pass to ExpectToken() - */ -struct Etoken { - const char * string; /**< The token to look for */ - int toktype; /**< The type to return on match */ - int matchto; /**< Modified during matches */ -}; - -int ExpectToken(int fd -, struct Etoken * toklist /* List of tokens to match against */ - /* Final token has NULL string */ -, int to_secs /* Timeout value in seconds */ -, char * buf /* If non-NULL, then all the text - * matched/skipped over by this match */ -, int maxline); /* Size of 'buf' area in bytes */ - - -/* - * A handy little routine. It runs the given process - * with it's standard output redirected into our *readfd, and - * its standard input redirected from our *writefd - * - * Doing this with all the pipes, etc. required for doing this - * is harder than it sounds :-) - */ - -int StartProcess(const char * cmd, int* readfd, int* writefd, int redir_err); - -#define EXP_STDERR 1 -#define EXP_NOCTTY 2 - -#ifndef EOS -# define EOS '\0' -#endif -#endif /*__EXPECT_H*/ diff --git a/fence/agents/ipmilan/ipmilan.c b/fence/agents/ipmilan/ipmilan.c deleted file mode 100644 index 83029e3..0000000 --- a/fence/agents/ipmilan/ipmilan.c +++ /dev/null @@ -1,1279 +0,0 @@ -/** @file - * clumanager 1.2.x linux-cluster fence and/or GFS fence - * module for Intel/Bull/Dell Tiger4 machines via IPMI over lan. - * (Probably works with anything ipmitool can control, though.) - * - * Note: REQUIRES ipmitool to operate. On certain machines, the hardware - * manufacturer provides this tool for you. Otherwise, check: - * - * http://ipmitool.sourceforge.net - * - */ - -#include "clusterautoconfig.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <signal.h> -#include <string.h> -#include <errno.h> -#include <limits.h> -#include <sys/wait.h> -#include <sys/stat.h> -#include <libintl.h> - -/* fenced doesn't use the remote calls */ -#define ST_STATUS 0 -#define ST_POWERON 1 -#define ST_POWEROFF 2 -#define ST_GENERIC_RESET 3 -#define ST_CYCLE 4 -#define ST_DIAG 5 - -#define DEFAULT_TIMEOUT 20 -#define DEFAULT_POWER_WAIT 2 - -#define DEFAULT_METHOD "onoff" - -/* We should follow FenceAgentsAPI standard*/ -#define ERR_OFF_SUCCESSFUL 0 -#define ERR_OFF_FAIL 1 - -#define ERR_ON_SUCCESSFUL 0 -#define ERR_ON_FAIL 1 - -#define ERR_STATUS_ON 0 -#define ERR_STATUS_FAIL 1 -#define ERR_STATUS_OFF 2 - -#define ERR_OK 0 - -#define log(lvl, fmt, args...) fprintf(stderr, fmt, ##args) -#include <libgen.h> -#include "copyright.cf" - -#include "expect.h" - -#define IPMIID "IPMI over LAN driver" -#define NOTIPMI "Destroyed IPMI over LAN driver" - - -#define dbg_printf(i, lvl, fmt, args...) \ -do { \ - if ( (i)->i_verbose >= lvl) { \ - printf(fmt, ##args); \ - fflush(stdout); \ - } \ -} while (0) - - - -struct ipmi { - const char *i_id; - const char *i_ipmitool; - char *i_host; - char *i_user; - char *i_authtype; - char *i_password; - char *i_privlvl; - int i_rdfd; - int i_wrfd; - pid_t i_pid; - int i_config; - int i_verbose; - int i_lanplus; - int i_timeout; - int i_power_wait; - int i_cipher; -}; - - -/* - Supported installation paths - */ -const char *ipmitool_paths[] = { - "/usr/local/bull/NSMasterHW/bin/ipmitool", - "/usr/bin/ipmitool", - "/usr/sbin/ipmitool", - "/bin/ipmitool", - "/sbin/ipmitool", - "/usr/local/bin/ipmitool", - "/usr/local/sbin/ipmitool", - NULL -}; - - -#define ECIPHER 2048 -#define ESTATE (8192*2) -static struct Etoken power_on_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}, - {"Up/On", 0, 0}, - {NULL, 0, 0} -}; - -static struct Etoken power_off_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}, - {"Down/Off", 0, 0}, - {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 -static struct Etoken power_status[] = { - {"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}, - {"Chassis Power is off", STATE_OFF, 0}, - {"Chassis Power is on", STATE_ON, 0}, - {NULL, 0, 0} -}; - -/* Structure describing one xml metadata value*/ -struct xml_parameter_s { - const char *name; - const char *getopt; - const int required; - const char *content_type; - const char *default_value; - const char *description; -}; - -/* 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 to improve security of connection"}, - {"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"}}; - -/* - Search for ipmitool - */ -static const char * -ipmitool_path(void) -{ - char *p; - int x = 0; - struct stat sb; - - for (x = 0; ipmitool_paths[x]; x++) { - p = (char *)ipmitool_paths[x]; - if (stat(p, &sb) != 0) - continue; - - if (!S_ISREG(sb.st_mode)) - continue; - - /* executable? */ - if ((sb.st_mode & S_IXUSR) == 0) - continue; - - return (const char *)p; - } - - return NULL; -} - - -/** Prepare string for use in sh style environment. This function take source - string and prepend/append quote (') to start/end of source string to dest - string. Any occurence of quote in source string is replaced by ''' sequence. - Dest string must be preallocated. - - @param dest Destination string - @param source Source string - @param max_len Maximum length of data written to dest string (including end 0) - @return Pointer to start of destination string. -*/ -static char *str_prepare_for_sh(char *dest,char *source,int max_len) { - char *dest_p=dest; - char *max_dest=dest+max_len; - - if (dest_p+1>=max_dest) {*dest_p=0;return dest;} - *dest_p++='''; - - while (*source) { - if (*source==''') { - if (dest_p+4>=max_dest) {*dest_p=0;return dest;} - - memcpy(dest_p,"'\''",4);dest_p+=4; - } else { - if (dest_p+1>=max_dest) {*dest_p=0;return dest;} - - *dest_p++=*source; - } - source++; - } - - if (dest_p+2>=max_dest) {*dest_p=0;return dest;} - - *dest_p++=''';*dest_p=0; - - return dest; -} - -static int -build_cmd(char *command, size_t cmdlen, struct ipmi *ipmi, int op, int nopass) -{ - char cmd[2048]; - char arg[2048]; - char tmp[2048]; - int x; - - /* Store path */ - if (ipmi->i_lanplus) { - snprintf(cmd, sizeof(cmd), "%s -I lanplus -H %s", - ipmi->i_ipmitool, - str_prepare_for_sh(tmp,ipmi->i_host,sizeof(tmp))); - } else { - snprintf(cmd, sizeof(cmd), "%s -I lan -H %s", ipmi->i_ipmitool, - str_prepare_for_sh(tmp,ipmi->i_host,sizeof(tmp))); - } - - if (ipmi->i_user) { - snprintf(arg, sizeof(arg), " -U %s", str_prepare_for_sh(tmp,ipmi->i_user,sizeof(tmp))); - strncat(cmd, arg, sizeof(cmd) - strlen(arg)); - } - - if (ipmi->i_authtype) { - snprintf(arg, sizeof(arg), " -A %s", str_prepare_for_sh(tmp,ipmi->i_authtype,sizeof(tmp))); - strncat(cmd, arg, sizeof(cmd) - strlen(arg)); - } - - if (ipmi->i_privlvl) { - snprintf(arg, sizeof(arg), " -L %s", str_prepare_for_sh(tmp,ipmi->i_privlvl,sizeof(tmp))); - strncat(cmd, arg, sizeof(cmd) - strlen(arg)); - } - - if (ipmi->i_cipher>=0) { - snprintf(arg, sizeof(arg), " -C %d", ipmi->i_cipher); - strncat(cmd, arg, sizeof(cmd) - strlen(arg)); - } - - if (ipmi->i_password) { - if (nopass) { - snprintf(arg, sizeof(arg), " -P %s", str_prepare_for_sh(tmp,(char *)"[set]",sizeof(tmp))); - } else { - snprintf(arg, sizeof(arg), " -P %s", str_prepare_for_sh(tmp,ipmi->i_password,sizeof(tmp))); - } - strncat(cmd, arg, sizeof(cmd) - strlen(arg)); - } else { - snprintf(arg, sizeof(arg), " -P ''"); - strncat(cmd, arg, sizeof(cmd) - strlen(arg)); - } - - /* Tack on the -v flags for ipmitool; in most cases, i_verbose - will be 0 */ - for (x = 0; x < ipmi->i_verbose; x++) { - snprintf(arg, sizeof(arg), " -v"); - strncat(cmd, arg, sizeof(cmd) - strlen(arg)); - } - - switch(op) { - case ST_POWERON: - snprintf(arg, sizeof(arg), - "%s chassis power on", cmd); - break; - case ST_POWEROFF: - snprintf(arg, sizeof(arg), - "%s chassis power off", cmd); - break; - case ST_STATUS: - snprintf(arg, sizeof(arg), - "%s chassis power status", cmd); - break; - case ST_CYCLE: - snprintf(arg, sizeof(arg), - "%s chassis power cycle", cmd); - break; - case ST_DIAG: - snprintf(arg, sizeof(arg), - "%s chassis power diag", cmd); - break; - } - - strncpy(command, arg, cmdlen); - return 0; -} - - -static int -ipmi_spawn(struct ipmi *ipmi, const char *cmd, const char *cmd_print) -{ - if (!ipmi) { - errno = EINVAL; - return -1; - } - dbg_printf(ipmi, 1, "Spawning: '%s'...\n", cmd_print); - - if (ipmi->i_pid != -1) { - dbg_printf(ipmi, 1, "Can't spawn: PID %d running\n", - (int)ipmi->i_pid); - errno = EINPROGRESS; - return -1; - } - - if ((ipmi->i_pid = StartProcess(cmd, &ipmi->i_rdfd, - &ipmi->i_wrfd, - EXP_STDERR|EXP_NOCTTY)) >= 0) { - dbg_printf(ipmi, 2, "Spawned: '%s' - PID %d\n", - cmd_print, (int)ipmi->i_pid); - return 0; - } - return -1; -} - - -static int -ipmi_reap(struct ipmi *ipmi) -{ - if (ipmi->i_pid >= 0) { - dbg_printf(ipmi, 2, "Reaping pid %d\n", ipmi->i_pid); - kill(ipmi->i_pid, 9); - waitpid(ipmi->i_pid, NULL, 0); - } - ipmi->i_pid = -1; - if (ipmi->i_rdfd >= 0) { - close(ipmi->i_rdfd); - ipmi->i_rdfd = -1; - } - if (ipmi->i_wrfd >= 0) { - close(ipmi->i_wrfd); - ipmi->i_wrfd = -1; - } - return 0; -} - - -static int -ipmi_expect(struct ipmi *ipmi, struct Etoken *toklist, int timeout) -{ - int ret; - char buf[32768]; /* XX hope this is enough */ - - dbg_printf(ipmi, 3, "Looking for: \n"); - for (ret = 0; toklist[ret].string; ret++) { - dbg_printf(ipmi, 3, " '%s', val = %d\n", - toklist[ret].string, - toklist[ret].toktype); - } - - ret = ExpectToken(ipmi->i_rdfd, toklist, timeout, buf, sizeof(buf)); - dbg_printf(ipmi, 3, "ExpectToken returned %d\n", ret); - if (ret == -1) { - ret = errno; - dbg_printf(ipmi, 3, "ExpectToken failed. Info returned:\n"); - dbg_printf(ipmi, 3, ">>>>>\n%s\n<<<<<\nError = %d (%s)\n", - buf, - ret, - strerror(ret)); - } - - return ret; -} - - -static int -ipmi_op(struct ipmi *ipmi, int op, struct Etoken *toklist) -{ - char cmd[2048]; - char cmd_nopass[2048]; - char *cmd_print = cmd; - int ret; - - build_cmd(cmd, sizeof(cmd), ipmi, op, 0); - if (ipmi->i_verbose >= 1 && ipmi->i_password) { - build_cmd(cmd_nopass, sizeof(cmd_nopass), - ipmi, op, 1); - cmd_print = cmd_nopass; - } - - if (ipmi_spawn(ipmi, cmd, cmd_print) != 0) - return -1; - ret = ipmi_expect(ipmi, toklist, ipmi->i_timeout); - ipmi_reap(ipmi); - - if (ret == EFAULT) { - log(LOG_CRIT, "ipmilan: ipmitool failed to create " - "mutex; unable to complete operation\n"); - return ret; - } - - if (ret == ECIPHER) { - log(LOG_CRIT, "ipmilan: ipmitool failed to operate " - "with ciphersuite %d; unable to complete operation\n",ipmi->i_cipher); - 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, - "ipmilan: Failed to connect after %d seconds\n",ipmi->i_timeout); - } - - return ret; -} - - -static int -ipmi_off(struct ipmi *ipmi) -{ - int ret, retries = 7; - - ret = ipmi_op(ipmi, ST_STATUS, power_status); - switch(ret) { - case STATE_ON: - break; - case STATE_OFF: - return 0; - default: - return ret; - } - - while (retries>=0) { - ret = ipmi_op(ipmi, ST_POWEROFF, power_off_complete); - if (ret != 0) - return ret; - - sleep(ipmi->i_power_wait); - --retries; - ret = ipmi_op(ipmi, ST_STATUS, power_status); - - switch(ret) { - case STATE_OFF: - return 0; - case EFAULT: - /* We're done. */ - retries = 0; - break; - case STATE_ON: - default: - continue; - } - } - log(LOG_WARNING, "ipmilan: Power still on\n"); - - return ret; -} - - -static int -ipmi_on(struct ipmi *ipmi) -{ - int ret, retries = 7; - - ret = ipmi_op(ipmi, ST_STATUS, power_status); - switch(ret) { - case STATE_ON: - return 0; - case STATE_OFF: - break; - default: - return ret; - } - - while (retries>=0) { - ret = ipmi_op(ipmi, ST_POWERON, power_on_complete); - if (ret != 0) - return ret; - - sleep(ipmi->i_power_wait); - --retries; - ret = ipmi_op(ipmi, ST_STATUS, power_status); - - switch(ret) { - case STATE_ON: - return 0; - case EFAULT: - /* We're done. */ - retries = 0; - break; - case STATE_OFF: - default: - continue; - } - } - log(LOG_WARNING, "ipmilan: Power still off\n"); - - return ret; -} - -static int -ipmi_cycle(struct ipmi *ipmi) -{ - int ret; - - ret = ipmi_op(ipmi, ST_CYCLE, power_cycle_complete); - - return ret; -} - -static int -ipmi_diag(struct ipmi *ipmi) -{ - int ret; - - ret = ipmi_op(ipmi, ST_DIAG, power_off_complete); - - return ret; -} - - -/** - Squash all our private data - */ -static void -ipmi_destroy(struct ipmi *i) -{ - ipmi_reap(i); - if (i->i_user) { - free(i->i_user); - i->i_user = NULL; - } - if (i->i_password) { - free(i->i_password); - i->i_password= NULL; - } - if (i->i_host) { - free(i->i_host); - i->i_host = NULL; - } - if (i->i_privlvl) { - free(i->i_privlvl); - i->i_privlvl = NULL; - } - i->i_config = 0; - i->i_id = NOTIPMI; -} - - -/** - Multipurpose initializer. Used to either create a new, blank ipmi, - or update an existing one, or both. - */ -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) -{ - const char *p; - - if (!i || !i->i_ipmitool) - p = ipmitool_path(); - else - p = i->i_ipmitool; - - if (!p) { - log(LOG_WARNING, "ipmilan: ipmitool not found!\n"); - return NULL; - } - - if (!i) - i = malloc (sizeof(*i)); - if (!i) - return NULL; - - if (host && strlen(host)) { - i->i_host = strdup(host); - if (!i->i_host) { - free(i); - return NULL; - } - } else - i->i_host = NULL; - - if (password && strlen(password)) { - i->i_password = strdup(password); - if (!i->i_password) { - free(i->i_host); - free(i); - return NULL; - } - } else - i->i_password = NULL; - - if (authtype && strlen(authtype)) { - i->i_authtype = strdup(authtype); - if (!i->i_authtype) { - free(i->i_host); - if (i->i_password) - free(i->i_password); - free(i); - return NULL; - } - } else - i->i_authtype = NULL; - - if (privlvl && strlen(privlvl)) { - i->i_privlvl = strdup(privlvl); - } else - i->i_privlvl = NULL; - - if (user && strlen(user)) { - i->i_user= strdup(user); - if (!i->i_user) { - free(i->i_host); - if (i->i_authtype) - free(i->i_authtype); - if (i->i_password) - free(i->i_password); - free(i); - return NULL; - } - } else - i->i_user = NULL; - i->i_ipmitool = p; - i->i_rdfd = -1; - i->i_wrfd = -1; - i->i_pid = -1; - i->i_id = IPMIID; - i->i_verbose = verbose; - i->i_lanplus = lanplus; - i->i_timeout = timeout; - i->i_power_wait = power_wait; - i->i_cipher = cipher; - - return i; -} - - -/** - Remove leading and trailing whitespace from a line of text. - */ -static int -cleanup(char *line, size_t linelen) -{ - char *p; - size_t x; - - /* Remove leading whitespace. */ - p = line; - for (x = 0; x <= linelen; x++) { - switch (line[x]) { - case '\t': - case ' ': - break; - case '\n': - case '\r': - return -1; - default: - goto eol; - } - } -eol: - /* Move the remainder down by as many whitespace chars as we - chewed up */ - if (x) - memmove(p, &line[x], linelen-x); - - /* Remove trailing whitespace. */ - for (x=0; x <= linelen; x++) { - switch(line[x]) { - case '\t': - case '\r': - case '\n': - line[x] = 0; - case 0: - /* End of line */ - return 0; - } - } - - return -1; -} - - -/** - Parse args from stdin. Dev + devlen + op + oplen must be valid. - */ -static int -get_options_stdin(char *ip, size_t iplen, - char *authtype, size_t atlen, - char *passwd, size_t pwlen, - 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 *power_wait, - int *cipher, char *method, int methodlen, - char *delay, size_t delaylen, - char *privlvl, size_t privlen) -{ - char in[256]; - int line = 0; - char *name, *val; - - op[0] = 0; - method[0] = 0; - - while (fgets(in, sizeof(in), stdin)) { - ++line; - - if (in[0] == '#') - continue; - - if (cleanup(in, sizeof(in)) == -1) - continue; - - name = in; - if ((val = strchr(in, '='))) { - *val = 0; - ++val; - } - - if (!strcasecmp(name, "agent")) { - /* Used by fenced? */ - } else if (!strcasecmp(name, "verbose")) { - *verbose = 1; - } else if (!strcasecmp(name, "ipaddr")) { - /* IP address to use. E.g. 10.1.1.2 */ - if (val) - strncpy(ip, val, iplen); - else - ip[0] = 0; - - } else if (!strcasecmp(name, "auth")) { - /* Authtype to use */ - if (val) - strncpy(authtype, val, atlen); - else - authtype[0] = 0; - - } else if (!strcasecmp(name, "passwd")) { - /* password */ - if (val) - strncpy(passwd, val, pwlen); - else - passwd[0] = 0; - - } else if (!strcasecmp(name, "passwd_script")) { - if (val) { - strncpy(pwd_script, val, pwd_script_len); - pwd_script[pwd_script_len - 1] = '\0'; - } else - pwd_script[0] = '\0'; - } else if (!strcasecmp(name, "privlvl")) { - if (val) { - strncpy(privlvl, val, privlen); - } else - privlvl[0] = '\0'; - } else if (!strcasecmp(name, "user") || !strcasecmp(name, "login")) { - /* username */ - if (val) - strncpy(user, val, userlen); - else - user[0] = 0; - } else if (!strcasecmp(name, "lanplus")) { - (*lanplus) = 1; - } else if (!strcasecmp(name,"timeout")) { - if ((!val) || (sscanf(val,"%d",timeout)!=1) || *timeout<1) { - *timeout=DEFAULT_TIMEOUT; - } - } else if (!strcasecmp(name,"power_wait")) { - if ((!val) || (sscanf(val,"%d",power_wait)!=1) || *power_wait<1) { - *power_wait=DEFAULT_POWER_WAIT; - } - } else if (!strcasecmp(name,"cipher")) { - if ((!val) || (sscanf(val,"%d",cipher)!=1) || *cipher<0) { - *cipher=-1; - } - } else if (!strcasecmp(name,"method")) { - if (val) - strncpy (method, val, methodlen); - else - method[0] = 0; - } else if (!strcasecmp(name, "option") || - !strcasecmp(name, "operation") || - !strcasecmp(name, "action")) { - if (val) - strncpy(op, val, oplen); - else - op[0] = 0; - } else if (!strcasecmp(name,"delay")) { - if (val) - strncpy(delay, val, delaylen); - else - delay[0] = 0; - } - } - - return 0; -} - - -/** - Print a message to stderr and call exit(1). - */ -static void -fail_exit(const char *msg) -{ - fprintf(stderr, "failed: %s\n", msg); - exit(1); -} - -static void -usage_exit(char *pname) -{ -printf("usage: %s <options>\n", pname); -printf(" -A <authtype> IPMI Lan Auth type (md5, password, or none)\n"); -printf(" -a <ipaddr> IPMI Lan IP to talk to\n"); -printf(" -i <ipaddr> IPMI Lan IP to talk to (deprecated, use -a)\n"); -printf(" -p <password> Password (if required) to control power on\n" - " IPMI device\n"); -printf(" -P Use Lanplus to improve security of connection\n"); -printf(" -S <path> Script to retrieve password (if required)\n"); -printf(" -l <login> Username/Login (if required) to control power\n" - " on IPMI device\n"); -printf(" -L <privlvl> IPMI privilege level. Defaults to ADMINISTRATOR.\n" - " See ipmitool(1) for more info.\n"); -printf(" -o <op> Operation to perform.\n"); -printf(" Valid operations: on, off, reboot, status,\n"); -printf(" diag, list or monitor\n"); -printf(" -t <timeout> Timeout (sec) for IPMI operation (default %d)\n",DEFAULT_TIMEOUT); -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(" -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"); -printf("from standard input (one per line):\n\n"); -printf(" auth=<auth> Same as -A\n"); -printf(" ipaddr=<#> Same as -a\n"); -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 -l\n"); -printf(" option=<op> Same as -o\n"); -printf(" operation=<op> Same as -o\n"); -printf(" action=<op> Same as -o\n"); -printf(" delay=<seconds> Same as -f\n"); -printf(" timeout=<timeout> Same as -t\n"); -printf(" power_wait=<time> Same as -T\n"); -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"); - exit(1); -} - - -/** Print XML metadata of fence agent*/ -static void print_xml_metadata(char *pname) { - int i; - - printf("%s\n","<?xml version=\"1.0\" ?>"); - printf("%s%s%s\n","<resource-agent name="",pname,"" shortdesc="Fence agent for IPMI over LAN">"); - printf("<symlink name="fence_ilo3" shortdesc="Fence agent for HP iLO3"/>\n"); - printf("<symlink name="fence_ilo4" shortdesc="Fence agent for HP iLO4"/>\n"); - printf("<symlink name="fence_idrac" shortdesc="Fence agent for Dell iDRAC"/>\n"); - printf("<symlink name="fence_imm" shortdesc="Fence agent for IBM Integrated Management Module"/>\n"); - printf("<longdesc>\n"); - printf("fence_ipmilan is an I/O Fencing agent which can be used with " - "machines controlled by IPMI. This agent calls support software " - "using ipmitool (http://ipmitool.sf.net/).%5Cn%5Cn" - "To use fence_ipmilan with HP iLO 3 or HP iLO 4 you have to enable lanplus " - "option (lanplus / -P) and increase wait after operation to " - "4 seconds (power_wait=4 / -T 4)"); - printf("</longdesc>\n"); - printf("<vendor-url>http://www.intel.com</vendor-url>\n"); - printf("%s\n","<parameters>"); - - for (i=0;i<(sizeof(xml_parameters)/sizeof(struct xml_parameter_s));i++) { - printf("\t<parameter name="%s" unique="0" required="%d">\n",xml_parameters[i].name, xml_parameters[i].required); - - printf("\t\t<getopt mixed="%s" />\n",xml_parameters[i].getopt); - if (xml_parameters[i].default_value == NULL) { - printf("\t\t<content type="%s" />\n",xml_parameters[i].content_type); - } else { - printf("\t\t<content type="%s" default="%s"/>\n", \ - xml_parameters[i].content_type, \ - xml_parameters[i].default_value ); - } - - printf("\t\t<shortdesc lang="en">"); - printf("%s",xml_parameters[i].description); - printf("</shortdesc>\n"); - printf("\t</parameter>\n"); - } - printf("%s\n","</parameters>"); - printf("%s\n","<actions>"); - printf("\t<action name="%s" />\n", "on"); - printf("\t<action name="%s" />\n", "off"); - printf("\t<action name="%s" />\n", "reboot"); - printf("\t<action name="%s" />\n", "status"); - printf("\t<action name="%s" />\n", "diag"); - printf("\t<action name="%s" />\n", "list"); - printf("\t<action name="%s" />\n", "monitor"); - printf("\t<action name="%s" />\n", "metadata"); - printf("%s\n","</actions>"); - printf("%s\n","</resource-agent>"); -} - -int -main(int argc, char **argv) -{ - extern char *optarg; - int opt, ret = -1; - char authtype[64]; - char ip[64]; - char passwd[64]; - char user[64]; - char op[64]; - char privlvl[64]; - char method[64]; - char delay[64]; - char pwd_script[PATH_MAX] = { 0, }; - int lanplus=0; - int verbose=0; - char *pname = basename(argv[0]); - struct ipmi *i; - int timeout=DEFAULT_TIMEOUT; - int down_sleep=DEFAULT_POWER_WAIT; - int cipher=-1; - int print_final_status=1; - int translated_ret = -1; - char *filename; - - memset(ip, 0, sizeof(ip)); - memset(authtype, 0, sizeof(authtype)); - memset(passwd, 0, sizeof(passwd)); - memset(user, 0, sizeof(user)); - memset(op, 0, sizeof(op)); - memset(privlvl, 0, sizeof(privlvl)); - memset(method, 0, sizeof(method)); - memset(delay, 0, sizeof(delay)); - - if (!strcmp(pname, "fence_ilo3")) { - lanplus = 1; - down_sleep = 4; - strncpy(method, "cycle\0", 6); - } else if (!strcmp(pname, "fence_ilo4")) { - lanplus = 1; - } - - 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:T:C:M:f:L:")) != EOF) { - switch(opt) { - case 'A': - /* Auth type */ - strncpy(authtype, optarg, sizeof(authtype)); - authtype[sizeof(authtype)-1] = 0; - break; - case 'L': - /* Privilege level - ipmitool defaults - * to ADMINISTRATOR if nothing is given - */ - strncpy(privlvl, optarg, sizeof(privlvl)); - privlvl[sizeof(privlvl)-1] = 0; - break; - case 'a': - case 'i': - /* IP address */ - strncpy(ip, optarg, sizeof(ip)); - ip[sizeof(ip)-1] = 0; - break; - case 'l': - /* user / login */ - strncpy(user, optarg, sizeof(user)); - user[sizeof(user)-1] = 0; - break; - case 'p': - /* password */ - strncpy(passwd, optarg, sizeof(passwd)); - passwd[sizeof(passwd)-1] = 0; - break; - case 'P': - lanplus = 1; - break; - case 'S': - strncpy(pwd_script, optarg, sizeof(pwd_script)); - pwd_script[sizeof(pwd_script)-1] = 0; - break; - case 'o': - /* Operation */ - strncpy(op, optarg, sizeof(op)); - op[sizeof(op)-1] = 0; - break; - case 'f': - /* Delay */ - strncpy(delay, optarg, sizeof(delay)); - delay[sizeof(delay)-1] = 0; - break; - case 't': - /* Timeout */ - if ((sscanf(optarg,"%d",&timeout)!=1) || timeout<1) { - fail_exit("Timeout option expects positive number parameter"); - } - break; - case 'T': - /* Shutdown Sleep Time */ - if ((sscanf(optarg,"%d",&down_sleep)!=1) || down_sleep<1) { - fail_exit("Shutdown time option expects positive number parameter"); - } - break; - case 'C': - /* Ciphersuite */ - if ((sscanf(optarg,"%d",&cipher)!=1) || cipher<0) { - fail_exit("Ciphersuite option expects positive number parameter"); - } - break; - case 'M': - /* Reboot method */ - strncpy(method, optarg, sizeof(method)); - method[sizeof(method)-1] = 0; - break; - case 'v': - verbose++; - break; - case 'V': - printf("%s %s (built %s %s)\n", pname, - VERSION, - __DATE__, __TIME__); - printf("%s\n", - REDHAT_COPYRIGHT); - return 0; - default: - usage_exit(pname); - } - } - } else { - /* - No command line args? Get stuff from stdin - */ - if (get_options_stdin(ip, sizeof(ip), - authtype, sizeof(authtype), - passwd, sizeof(passwd), - pwd_script, sizeof(pwd_script), - user, sizeof(user), - op, sizeof(op), &lanplus, &verbose,&timeout, - &down_sleep, - &cipher, method, sizeof(method), - delay, sizeof(delay), - privlvl, sizeof(privlvl)) != 0) - return 1; - } - - if (pwd_script[0] != '\0') { - char pwd_buf[1024]; - FILE *fp; - fp = popen(pwd_script, "r"); - if (fp != NULL) { - ssize_t len = fread(pwd_buf, 1, sizeof(pwd_buf), fp); - pwd_buf[sizeof(pwd_buf)-1] = 0; - if (len > 0) { - char *p; - p = strchr(pwd_buf, '\n'); - if (p != NULL) - *p = '\0'; - p = strchr(pwd_buf, '\r'); - if (p != NULL) - *p = '\0'; - strncpy(passwd, pwd_buf, sizeof(passwd)); - passwd[sizeof(passwd) - 1] = '\0'; - } - pclose(fp); - } - } - - if (!strcasecmp(op, "metadata")) { - print_xml_metadata(pname); - translated_ret = ERR_OK; - ret=0; - print_final_status=0; - goto metaout; - } - - /* - Validate the operating parameters - */ - if (strlen(ip) == 0) - fail_exit("no IP address specified"); - - 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") && - strcasecmp(op, "metadata") && strcasecmp(op, "diag")) { - fail_exit("operation must be 'on', 'off', 'status', " - "'reboot', 'diag', 'list', 'monitor' or 'metadata'"); - } - - if (strlen(authtype) && - strcasecmp(authtype, "md5") && - strcasecmp(authtype, "password") && - strcasecmp(authtype, "none")) { - fail_exit("authtype, if included, must be 'md5', 'password'," - " 'none'."); - } - - if (strcasecmp(method, "onoff") && - strcasecmp(method, "cycle")) { - fail_exit("method, if included, must 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')."); - } - - /* Delay fencing if requested */ - if (delay[0] != '\0') { - if (!strcasecmp(op, "reboot") || !strcasecmp(op, "off")) { - sleep(atoi(delay)); - } - } - - /* Ok, set up the IPMI struct */ - i = ipmi_init(NULL, ip, authtype, user, passwd, lanplus, verbose, timeout, down_sleep, cipher, privlvl); - if (!i) - fail_exit("Failed to initialize\n"); - - /* - Perform the requested operation - */ - if (!strcasecmp(op, "reboot")) { - printf("Rebooting machine @ IPMI:%s...", ip); - fflush(stdout); - 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); - translated_ret = (ret==0?ERR_OFF_SUCCESSFUL:ERR_OFF_FAIL); - } else { - /* Original onoff method */ - ret = ipmi_off(i); - translated_ret = (ret==0?ERR_OFF_SUCCESSFUL:ERR_OFF_FAIL); - if (ret != 0) { - goto out; - } - ret = ipmi_on(i); - } - } else if (!strcasecmp(op, "on")) { - printf("Powering on machine @ IPMI:%s...", ip); - fflush(stdout); - ret = ipmi_on(i); - translated_ret = (ret==0?ERR_ON_SUCCESSFUL:ERR_ON_FAIL); - } else if (!strcasecmp(op, "off")) { - printf("Powering off machine @ IPMI:%s...", ip); - fflush(stdout); - ret = ipmi_off(i); - translated_ret = (ret==0?ERR_ON_SUCCESSFUL:ERR_ON_FAIL); - } else if (!strcasecmp(op, "status") || !strcasecmp(op, "monitor")) { - printf("Getting status of IPMI:%s...",ip); - fflush(stdout); - ret = ipmi_op(i, ST_STATUS, power_status); - switch(ret) { - case STATE_ON: - if (!strcasecmp(op, "status")) - printf("Chassis power = On\n"); - translated_ret = ERR_STATUS_ON; - ret = 0; - break; - case STATE_OFF: - if (!strcasecmp(op, "status")) - printf("Chassis power = Off\n"); - translated_ret = ERR_STATUS_OFF; - ret = 0; - break; - default: - if (!strcasecmp(op, "status")) - printf("Chassis power = Unknown\n"); - translated_ret = ERR_STATUS_FAIL; - ret = 1; - break; - } - } else if (!strcasecmp(op, "list")) { - printf("%s\n","N/A"); - ret=0; - translated_ret = ERR_OK; - print_final_status=0; - } else if (!strcasecmp(op, "diag")) { - printf("Pulsing diagnostic interrupt to machine @ IPMI:%s...", ip); - fflush(stdout); - ret = ipmi_diag(i); - translated_ret = (ret==0?ERR_ON_SUCCESSFUL:ERR_ON_FAIL); - ret = 0; - } - - -out: - ipmi_destroy(i); - free(i); - -metaout: - if (print_final_status) { - if (ret == 0) - printf("Done\n"); - else - printf("Failed\n"); - } - - if (!strcasecmp(op, "monitor")) - translated_ret = ret; - - if (!strcasecmp(op, "diag")) { - /** .. but when a system receive the DIAG signal , it - ** switches to a kdump kernel, but the machine is always - ** "on" during the dump phase. It only become temporarily - ** "off" at the end of the dump just before rebooting. - **/ - translated_ret = 0; - } - - return translated_ret; -}