> It would be good to hear why it didn't work and what did you do > to make it work. Incidentally, there is a bugzilla with a patch > which should help handling certain device releases, but for lack > of devices to try it out, it never got applied. See > http://developerbugs.linux-foundation.org/show_bug.cgi?id=1891 > > Thanks, > I've long since forgotten why it didn't work. I just realized after looking at the code that my device simply wasn't supported by and I modified it to work for me. I have 7930s running 3.3 codebase --- cluster-glue/lib/plugins/stonith/apcmaster.c 2010-01-11 04:20:07.000000000 -0500 +++ /root/apcmaster.c 2010-01-20 07:55:19.000000000 -0500 @@ -47,6 +47,10 @@ * private subnet. */ +/* + * Version string that is filled in by CVS + */ +static const char *version __attribute__ ((unused)) = "$Revision: 1.27 $"; #include #define DEVICE "APC MasterSwitch" @@ -143,8 +147,11 @@ static const char * NOTpluginID = "APCMS #define APCMSSTR "American Power Conversion" -static struct Etoken EscapeChar[] = { {"Escape character is '^]'.", 0, 0} - , {NULL,0,0}}; +static struct Etoken EscapeChar[] = { {"Escape character is '^]'.", 0, 0}, + {"User Name :", 1, 0}, + {NULL,0,0} + }; + static struct Etoken login[] = { {"User Name :", 0, 0}, {NULL,0,0}}; static struct Etoken password[] = { {"Password :", 0, 0} ,{NULL,0,0}}; static struct Etoken Prompt[] = { {"> ", 0, 0} ,{NULL,0,0}}; @@ -153,9 +160,6 @@ static struct Etoken LoginOK[] = { {APCM static struct Etoken Separator[] = { {"-----", 0, 0} ,{NULL,0,0}}; /* We may get a notice about rebooting, or a request for confirmation */ -static struct Etoken Processing[] = { {"Press to continue", 0, 0} - , {"Enter 'YES' to continue", 1, 0} - , {NULL,0,0}}; #include "stonith_config_xml.h" @@ -173,23 +177,32 @@ static int MSNametoOutlet(struct pluginD static int MSReset(struct pluginDevice*, int outletNum, const char * host); static int MSLogout(struct pluginDevice * ms); -#if defined(ST_POWERON) && defined(ST_POWEROFF) -static int apcmaster_onoff(struct pluginDevice*, int outletnum, const char * unitid -, int request); -#endif /* Login to the APC Master Switch */ static int MSLogin(struct pluginDevice * ms) { - EXPECT(ms->rdfd, EscapeChar, 10); + int rc; - /* - * We should be looking at something like this: - * User Name : + /* Patch from Dave Blaschke + * Apparently some telnet apps display the escape character while + * others don't, so we need to handle both possibilities... + * + * rc == 0 : "Escape character is '^]'." found + * rc == 1 : "User Name :" found + * rc < 0 : Neither found or timeout */ - EXPECT(ms->rdfd, login, 10); + if ((rc = StonithLookFor(ms->rdfd, EscapeChar, 10)) < 0) { + return(errno == ETIMEDOUT ? S_TIMEOUT : S_OOPS); + } else if (rc == 0) { + /* + * We should be looking at something like this: + * User Name : + */ + EXPECT(ms->rdfd, login, 10); + } + SEND(ms->wrfd, ms->user); SEND(ms->wrfd, "\r"); @@ -275,7 +288,6 @@ int MSLogout(struct pluginDevice* ms) static int MSReset(struct pluginDevice* ms, int outletNum, const char *host) { - char unum[32]; /* Make sure we're in the top level menu */ SEND(ms->wrfd, "\033"); @@ -293,13 +305,12 @@ MSReset(struct pluginDevice* ms, int out /* Request menu 1 (Device Control) */ SEND(ms->wrfd, "1\r"); - - /* Select requested outlet */ EXPECT(ms->rdfd, Prompt, 5); - snprintf(unum, sizeof(unum), "%i\r", outletNum); - SEND(ms->wrfd, unum); + SEND(ms->wrfd, "2\r"); + EXPECT(ms->rdfd, Prompt, 5); + SEND(ms->wrfd, "1\r"); - /* Select menu 1 (Control Outlet) */ + /* Select requested outlet */ EXPECT(ms->rdfd, Prompt, 5); SEND(ms->wrfd, "1\r"); @@ -307,21 +318,7 @@ MSReset(struct pluginDevice* ms, int out EXPECT(ms->rdfd, Prompt, 5); SEND(ms->wrfd, "3\r"); - /* Expect "Press " or "Enter 'YES'" (if confirmation turned on) */ - retry: - switch (StonithLookFor(ms->rdfd, Processing, 5)) { - case 0: /* Got "Press " Do so */ - SEND(ms->wrfd, "\r"); - break; - - case 1: /* Got that annoying command confirmation :-( */ - SEND(ms->wrfd, "YES\r"); - goto retry; - - default: - return(errno == ETIMEDOUT ? S_RESETFAIL : S_OOPS); - } - + SEND(ms->wrfd, "YES\r"); LOG(PIL_INFO, "Host being rebooted: %s", host); @@ -350,71 +347,6 @@ MSReset(struct pluginDevice* ms, int out return(S_OK); } -#if defined(ST_POWERON) && defined(ST_POWEROFF) -static int -apcmaster_onoff(struct pluginDevice* ms, int outletNum, const char * unitid, int req) -{ - char unum[32]; - - const char * onoff = (req == ST_POWERON ? "1\r" : "2\r"); - int rc; - - if ((rc = MSRobustLogin(ms) != S_OK)) { - LOG(PIL_CRIT, "Cannot log into %s.", ms->idinfo); - return(rc); - } - - /* Make sure we're in the top level menu */ - SEND(ms->wrfd, "\033"); - EXPECT(ms->rdfd, Prompt, 5); - SEND(ms->wrfd, "\033"); - EXPECT(ms->rdfd, Prompt, 5); - SEND(ms->wrfd, "\033"); - EXPECT(ms->rdfd, Prompt, 5); - SEND(ms->wrfd, "\033"); - EXPECT(ms->rdfd, Prompt, 5); - SEND(ms->wrfd, "\033"); - - /* Expect ">" */ - EXPECT(ms->rdfd, Prompt, 5); - - /* Request menu 1 (Device Control) */ - SEND(ms->wrfd, "1\r"); - - /* Select requested outlet */ - snprintf(unum, sizeof(unum), "%d\r", outletNum); - SEND(ms->wrfd, unum); - - /* Select menu 1 (Control Outlet) */ - SEND(ms->wrfd, "1\r"); - - /* Send ON/OFF command for given outlet */ - SEND(ms->wrfd, onoff); - - /* Expect "Press " or "Enter 'YES'" (if confirmation turned on) */ - retry: - switch (StonithLookFor(ms->rdfd, Processing, 5)) { - case 0: /* Got "Press " Do so */ - SEND(ms->wrfd, "\r"); - break; - - case 1: /* Got that annoying command confirmation :-( */ - SEND(ms->wrfd, "YES\r"); - goto retry; - - default: - return(errno == ETIMEDOUT ? S_RESETFAIL : S_OOPS); - } - - EXPECT(ms->rdfd, Prompt, 10); - - /* All Right! Command done. Life is Good! */ - LOG(PIL_INFO, "Power to MS outlet(s) %d turned %s", outletNum, onoff); - /* Pop back to main menu */ - SEND(ms->wrfd, "\033\033\033\033\033\033\033\r"); - return(S_OK); -} -#endif /* defined(ST_POWERON) && defined(ST_POWEROFF) */ /* * Map the given host name into an (AC) Outlet number on the power strip @@ -444,6 +376,10 @@ MSNametoOutlet(struct pluginDevice* ms, /* Request menu 1 (Device Control) */ SEND(ms->wrfd, "1\r"); + EXPECT(ms->rdfd, Prompt, 5); + SEND(ms->wrfd, "2\r"); + EXPECT(ms->rdfd, Prompt, 5); + SEND(ms->wrfd, "1\r"); /* Expect: "-----" so we can skip over it... */ EXPECT(ms->rdfd, Separator, 5); @@ -539,6 +475,14 @@ apcmaster_hostlist(StonithPlugin *s) /* Request menu 1 (Device Control) */ SEND(ms->wrfd, "1\r"); + /* Request menu 2 (Outlet Management) */ + NULLEXPECT(ms->rdfd, Prompt, 10); + SEND(ms->wrfd, "2\r"); + + NULLEXPECT(ms->rdfd, Prompt, 10); + SEND(ms->wrfd, "1\r"); + + /* Expect: "-----" so we can skip over it... */ NULLEXPECT(ms->rdfd, Separator, 5); @@ -654,14 +598,6 @@ apcmaster_reset_req(StonithPlugin * s, i } switch(request) { -#if defined(ST_POWERON) && defined(ST_POWEROFF) - case ST_POWERON: - rc = apcmaster_onoff(ms, noutlet, host, request); - break; - case ST_POWEROFF: - rc = apcmaster_onoff(ms, noutlet, host, request); - break; -#endif case ST_GENERIC_RESET: rc = MSReset(ms, noutlet, host); break; I'm using SLES11 running packages from openSUSE's ha repo. Patch apcmaster.c, recompile, replace your apcmaster.so file.