⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wti_nps.c

📁 linux集群服务器软件代码包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: wti_nps.c,v 1.21 2005/02/18 07:32:09 zhaokai Exp $ *//* * *  Copyright 2001 Mission Critical Linux, Inc. * *  All Rights Reserved. *//* *	Stonith module for WTI Network Power Switch Devices (NPS-xxx) *	Also supports the WTI Telnet Power Switch Devices (TPS-xxx) * *  Copyright 2001 Mission Critical Linux, Inc. *  author: mike ledoux <mwl@mclinux.com> *  author: Todd Wheeling <wheeling@mclinux.com> *  Mangled by Zhaokai <zhaokai@cn.ibm.com>, IBM, 2005 * *  Based strongly on original code from baytech.c by Alan Robertson. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. *  * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. *  * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * *//*                          Observations/Notes *  * 1. The WTI Network Power Switch, unlike the BayTech network power switch, *    accpets only one (telnet) connection/session at a time. When one *    session is active, any subsequent attempt to connect to the NPS will *    result in a connection refused/closed failure. In a cluster environment *    or other environment utilizing polling/monitoring of the NPS *    (from multiple nodes), this can clearly cause problems. Obviously the *    more nodes and the shorter the polling interval, the more frequently such *    errors/collisions may occur. * * 2. We observed that on busy networks where there may be high occurances *    of broadcasts, the NPS became unresponsive.  In some  *    configurations this necessitated placing the power switch onto a  *    private subnet. */#define	DEVICE	"WTI Network Power Switch"#include "stonith_plugin_common.h"#define PIL_PLUGIN              wti_nps#define PIL_PLUGIN_S            "wti_nps"#define PIL_PLUGINLICENSE 	LICENSE_LGPL#define PIL_PLUGINLICENSEURL 	URL_LGPL#define MAX_WTIPLUGINID		256#include <pils/plugin.h>#include "stonith_signal.h"static StonithPlugin *	wti_nps_new(void);static void		wti_nps_destroy(StonithPlugin *);static const char**	wti_nps_get_confignames(StonithPlugin *);static int		wti_nps_set_config(StonithPlugin * , StonithNVpair * );static const char *	wti_nps_get_info(StonithPlugin * s, int InfoType);static int		wti_nps_status(StonithPlugin * );static int		wti_nps_reset_req(StonithPlugin * s, int request, const char * host);static char **		wti_nps_hostlist(StonithPlugin  *);static struct stonith_ops wti_npsOps ={	wti_nps_new,			/* Create new STONITH object		*/	wti_nps_destroy,		/* Destroy STONITH object		*/	wti_nps_get_info,		/* Return STONITH info string		*/	wti_nps_get_confignames,	/* Return configration parameters	*/	wti_nps_set_config,		/* set configration			*/	wti_nps_status,			/* Return STONITH device status		*/	wti_nps_reset_req,		/* Request a reset 			*/	wti_nps_hostlist,		/* Return list of supported hosts 	*/};PIL_PLUGIN_BOILERPLATE2("1.0", Debug)static const PILPluginImports*  PluginImports;static PILPlugin*               OurPlugin;static PILInterface*		OurInterface;static StonithImports*		OurImports;static void*			interfprivate;#include "stonith_expect_helpers.h"PIL_rcPIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports);PIL_rcPIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports){	/* Force the compiler to do a little type checking */	(void)(PILPluginInitFun)PIL_PLUGIN_INIT;	PluginImports = imports;	OurPlugin = us;	/* Register ourself as a plugin */	imports->register_plugin(us, &OurPIExports);  	/*  Register our interface implementation */ 	return imports->register_interface(us, PIL_PLUGINTYPE_S	,	PIL_PLUGIN_S	,	&wti_npsOps	,	NULL		/*close */	,	&OurInterface	,	(void*)&OurImports	,	&interfprivate); }/* *	I have a NPS-110.  This code has been tested with this switch. *	(Tested with NPS-230 and TPS-2 by lmb) */struct pluginDevice {	StonithPlugin	sp;	const char *	pluginid;	char *		idinfo;	char *		unitid;	pid_t		pid;	int		rdfd;	int		wrfd;	int		config;	char *		device;	char *		passwd;};static const char * pluginid = "WTINPS-Stonith";static const char * NOTnpsid = "Hey, dummy this has been destroyed (WTINPS)";/* *	Different expect strings that we get from the WTI *	Network Power Switch */#define WTINPSSTR	" Power Switch"static struct Etoken EscapeChar[] =	{ {"Escape character is '^]'.", 0, 0}					,	{NULL,0,0}};static struct Etoken password[] =	{ {"Password:", 0, 0},						{NULL,0,0}};static struct Etoken Prompt[] =	{ {"PS>", 0, 0} ,{NULL,0,0}};static struct Etoken LoginOK[] =	{ {WTINPSSTR, 0, 0}                    , {"Invalid password", 1, 0} ,{NULL,0,0}};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[] =	{ {"rocessing - please wait", 0, 0}				,	{"(Y/N):", 1, 0}				,	{NULL,0,0}};static int	NPS_connect_device(struct pluginDevice * nps);static int	NPSLogin(struct pluginDevice * nps);static int	NPSNametoOutlet(struct pluginDevice*, const char * name, char **outlets);static int	NPSReset(struct pluginDevice*, char * outlets, const char * rebootid);static int	NPSLogout(struct pluginDevice * nps);static int	NPS_parse_config_info(struct pluginDevice* nps, const char * info);#if defined(ST_POWERON) && defined(ST_POWEROFF)static int	NPS_onoff(struct pluginDevice*, const char * outlets, const char * unitid,		int request);#endif/* Attempt to login up to 20 times... */static intNPSRobustLogin(struct pluginDevice * nps){	int rc = S_OOPS;	int j = 0;	if (Debug) {		LOG(PIL_DEBUG, "%s:called.", __FUNCTION__);	}	for ( ; ; ) {		if (nps->pid > 0) {			Stonithkillcomm(&nps->rdfd, &nps->wrfd, &nps->pid);		}		if (NPS_connect_device(nps) != S_OK) {				Stonithkillcomm(&nps->rdfd, &nps->wrfd, &nps->pid);		}		else {			rc = NPSLogin(nps);			if (rc == S_OK) { 				break;			}		}		if ((++j) == 20) { 			break;		}		else {			sleep(1);		}	}	return rc;}/* Login to the WTI Network Power Switch (NPS) */static intNPSLogin(struct pluginDevice * nps){	char		IDinfo[128];	char *		idptr = IDinfo;	if (Debug) {		LOG(PIL_DEBUG, "%s:called.", __FUNCTION__);	}	/*EXPECT(nps->rdfd, EscapeChar, 10);*/	if (StonithLookFor(nps->rdfd, EscapeChar, 10) < 0) {		sleep(1);		return (errno == ETIMEDOUT ? S_TIMEOUT : S_OOPS);	}	/* Look for the unit type info */	if (EXPECT_TOK(nps->rdfd, password, 2, IDinfo	,	sizeof(IDinfo), Debug) < 0) {		LOG(PIL_CRIT, "%s", _("No initial response from " DEVICE "."));		Stonithkillcomm(&nps->rdfd, &nps->wrfd, &nps->pid); 		return(errno == ETIMEDOUT ? S_TIMEOUT : S_OOPS);	}	idptr += strspn(idptr, WHITESPACE);	/*	 * We should be looking at something like this:	 *	Enter Password: 	 */	SEND(nps->wrfd, nps->passwd);	SEND(nps->wrfd, "\r");	/* Expect "Network Power Switch vX.YY" */	switch (StonithLookFor(nps->rdfd, LoginOK, 5)) {		case 0:	/* Good! */			LOG(PIL_INFO, "%s", _("Successful login to " DEVICE "."));			break;		case 1:	/* Uh-oh - bad password */			LOG(PIL_CRIT, "%s", _("Invalid password for " DEVICE "."));			return(S_ACCESS);		default:			Stonithkillcomm(&nps->rdfd, &nps->wrfd, &nps->pid);			return(errno == ETIMEDOUT ? S_TIMEOUT : S_OOPS);	}	return(S_OK);}/* Log out of the WTI NPS */static intNPSLogout(struct pluginDevice* nps){	int	rc;	if (Debug) {		LOG(PIL_DEBUG, "%s:called.", __FUNCTION__);	}	/* Send "/h" help command and expect back prompt */	/*	SEND(nps->wrfd, "/h\r");	*/	/* Expect "PS>" */	rc = StonithLookFor(nps->rdfd, Prompt, 5);	/* "/x" is Logout, "/x,y" auto-confirms */	SEND(nps->wrfd, "/x,y\r");	Stonithkillcomm(&nps->rdfd, &nps->wrfd, &nps->pid);	return(rc >= 0 ? S_OK : (errno == ETIMEDOUT ? S_TIMEOUT : S_OOPS));}/* Reset (power-cycle) the given outlets */static intNPSReset(struct pluginDevice* nps, char * outlets, const char * rebootid){	char		unum[32];	if (Debug) {		LOG(PIL_DEBUG, "%s:called.", __FUNCTION__);	}	/* Send "/h" help command and expect back prompt */	SEND(nps->wrfd, "/h\r");	/* Expect "PS>" */	EXPECT(nps->rdfd, Prompt, 5);		/* Send REBOOT command for given outlets */	snprintf(unum, sizeof(unum), "/BOOT %s,y\r", outlets);	SEND(nps->wrfd, unum);		/* Expect "Processing "... or "(Y/N)" (if confirmation turned on) */	retry:	switch (StonithLookFor(nps->rdfd, Processing, 5)) {		case 0: /* Got "Processing" Do nothing */			break;		case 1: /* Got that annoying command confirmation :-( */			SEND(nps->wrfd, "Y\r");			goto retry;		default: 			return(errno == ETIMEDOUT ? S_RESETFAIL : S_OOPS);	}	LOG(PIL_INFO, "%s: %s", _("Host is being rebooted"), rebootid);	/* Expect "PS>" */	if (StonithLookFor(nps->rdfd, Prompt, 60) < 0) {		return(errno == ETIMEDOUT ? S_RESETFAIL : S_OOPS);	}	/* All Right!  Power is back on.  Life is Good! */	LOG(PIL_INFO, "%s: %s", _("Power restored to host"), rebootid);	SEND(nps->wrfd, "/h\r");	return(S_OK);}#if defined(ST_POWERON) && defined(ST_POWEROFF)static intNPS_onoff(struct pluginDevice* nps, const char * outlets, const char * unitid, int req){	char		unum[32];	const char *	onoff = (req == ST_POWERON ? "/On" : "/Off");	int	rc;	if (Debug) {		LOG(PIL_DEBUG, "%s:called.", __FUNCTION__);	}	if ((rc = NPSRobustLogin(nps) != S_OK)) {		LOG(PIL_CRIT, "%s", _("Cannot log into " DEVICE "."));		return(rc);	}       	/* Send "/h" help command and expect prompt back */	SEND(nps->wrfd, "/h\r");	/* Expect "PS>" */	EXPECT(nps->rdfd, Prompt, 5);	/* Send ON/OFF command for given outlet */	snprintf(unum, sizeof(unum), "%s %s,y\r", onoff, outlets);	SEND(nps->wrfd, unum);	/* Expect "Processing"... or "(Y/N)" (if confirmation turned on) */	if (StonithLookFor(nps->rdfd, Processing, 5) == 1) {		/* They've turned on that annoying command confirmation :-( */		SEND(nps->wrfd, "Y\r");	}	EXPECT(nps->rdfd, Prompt, 60);	/* All Right!  Command done. Life is Good! */	LOG(PIL_INFO, "%s %s %s %s", _("Power to NPS outlet(s)"), outlets, _("turned"), onoff);	return(S_OK);}#endif /* defined(ST_POWERON) && defined(ST_POWEROFF) *//* *	Map the given host name into an (AC) Outlet number on the power strip */static intNPSNametoOutlet(struct pluginDevice* nps, const char * name, char **outlets){  	char	NameMapping[128];  	int	sockno;  	char	sockname[32];        char buf[32];        int left = 17;  	int ret = -1;		if (Debug) {		LOG(PIL_DEBUG, "%s:called.", __FUNCTION__);	}                if ((*outlets = (char *)MALLOC(left*sizeof(char))) == NULL) {                LOG(PIL_CRIT, "out of memory");                return(-1);        }	        strncpy(*outlets, "", left);        left = left - 1;        /* ensure terminating '\0' */  	/* Expect "PS>" */  	EXPECT(nps->rdfd, Prompt, 5);	  	/* The status command output contains mapping of hosts to outlets */     	SEND(nps->wrfd, "/s\r"); 	/* Expect: "-----+" so we can skip over it... */    	EXPECT(nps->rdfd, Separator, 5); 	  	do {  		NameMapping[0] = EOS;  		SNARF(nps->rdfd, NameMapping, 5);  		  		if (sscanf(NameMapping  		,	"%d | %16c",&sockno, sockname) == 2) {    			char *	last = sockname+16;  			*last = EOS;  			--last;			/* Strip off trailing blanks */  			for(; last > sockname; --last) {  				if (*last == ' ') {  					*last = EOS;  				}else{  					break;  				}  			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -