[Pacemaker] APC Master Stonith

Sander van Vugt mail at sandervanvugt.nl
Wed Jan 20 18:45:31 UTC 2010


On Wed, 2010-01-20 at 11:47 -0500, Errol Neal wrote:
> > 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
> 
I've got a 7920 and I would like to see Pacemaker supporting it. If I
can help by testing this patch, or the one on bugzilla, I'd be more than
happy to, but for the moment, I'm to ignorant to apply it to my code and
not being a C-programmer, the short explanation below doesn't clarify it
to me. Would welcome some directions on how to proceed with this (and
how to become a good patch tester)

Thanks,
Sander



> --- 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 <lha_internal.h>
>  
>  #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 <ENTER> 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 <ENTER> " or "Enter 'YES'" (if confirmation turned on) */
> -	retry:
> -	switch (StonithLookFor(ms->rdfd, Processing, 5)) {
> -		case 0: /* Got "Press <ENTER>" 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 <ENTER> " or "Enter 'YES'" (if confirmation turned on) */
> -	retry:
> -	switch (StonithLookFor(ms->rdfd, Processing, 5)) {
> -		case 0: /* Got "Press <ENTER>" 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. 
> 
> 
> _______________________________________________
> Pacemaker mailing list
> Pacemaker at oss.clusterlabs.org
> http://oss.clusterlabs.org/mailman/listinfo/pacemaker






More information about the Pacemaker mailing list