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

📄 rps10.c

📁 在LINUX下实现HA的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (gbl_debug) printf ("Calling rps10_hostlist (%s)\n", WTIid);		if (!ISWTIRPS10(s)) {		syslog(LOG_ERR, "invalid argument to RPS_list_hosts");		return(NULL);	}	if (!ISCONFIGED(s)) {		syslog(LOG_ERR		,	"unconfigured stonith object in RPS_list_hosts");		return(NULL);	}	ctx = (struct WTI_RPS10*) s->pinfo;	if (ctx->unit_count >= 1) {		ret = (char **)MALLOC((ctx->unit_count+1)*sizeof(char*));		if (ret == NULL) {			syslog(LOG_ERR, "out of memory");			return NULL;		}		ret[ctx->unit_count]=NULL; /* null terminate the array */		for (i=0; i<ctx->unit_count; i++) {			ret[i] = STRDUP(ctx->controllers[i].node);			if (ret[i] == NULL) {				for(j=0; j<i; j++) {					FREE(ret[j]);				}				FREE(ret); ret = NULL;				break;			}		} /* end for each possible outlet */	} /* end if any outlets are configured */	return(ret);} /* end si_hostlist() *//* * rps10_free_hostlist - free the result from rps10_hostlist()  */static voidrps10_free_hostlist (char ** hlist){	char **	hl = hlist;	if (hl == NULL) {		return;	}	while (*hl) {		FREE(*hl);		*hl = NULL;		++hl;	}	FREE(hlist);}/* *	Parse the given configuration information, and stash *      it away... * *         The format of <info> for this module is: *            <serial device> <remotenode> <outlet> [<remotenode> <outlet>] ... * *      e.g. A machine named 'nodea' can kill a machine named 'nodeb' through *           a device attached to serial port /dev/ttyS0. *           A machine named 'nodeb' can kill machines 'nodea' and 'nodec' *           through a device attached to serial port /dev/ttyS1 (outlets 0  *             and 1 respectively) * *      <assuming this is the heartbeat configuration syntax:> *  *      stonith nodea rps10 /dev/ttyS0 nodeb 0  *      stonith nodeb rps10 /dev/ttyS0 nodea 0 nodec 1 * *      Another possible configuration is for 2 stonith devices *         accessible through 2 different serial ports on nodeb: * *      stonith nodeb rps10 /dev/ttyS0 nodea 0  *      stonith nodeb rps10 /dev/ttyS1 nodec 0 *//* * 	OOPS! * * 	Most of the large block of comments above is incorrect as far as this * 	module is concerned.  It is somewhat applicable to the heartbeat code, * 	but not to this Stonith module. * * 	The format of parameter string for this module is: *            <serial device> <remotenode> <outlet> [<remotenode> <outlet>] ... */static intRPS_parse_config_info(struct WTI_RPS10* ctx, const char * info){	char *copy;	char *token;	char *outlet, *node;	if (ctx->config) {		/* The module is already configured. */		return(S_OOPS);	}	/* strtok() is nice to use to parse a string with 	   (other than it isn't threadsafe), but it is destructive, so	   we're going to alloc our own private little copy for the	   duration of this function.	*/	copy = STRDUP(info);	if (!copy) {		syslog(LOG_ERR, "out of memory");		return S_OOPS;	}	/* Grab the serial device */	token = strtok (copy, " \t");	if (!token) {		syslog(LOG_ERR, "%s: Can't find serial device on config line '%s'",		       WTIid, info);		goto token_error;			}	ctx->device = STRDUP(token);	if (!ctx->device) {		syslog(LOG_ERR, "out of memory");		goto token_error;	}	/* Loop through the rest of the command line which should consist of */	/* <nodename> <outlet> pairs */	while ((node = strtok (NULL, " \t"))	       && (outlet = strtok (NULL, " \t\n"))) {		char outlet_id;		/* validate the outlet token */		if ((sscanf (outlet, "%c", &outlet_id) != 1)		    || !( ((outlet_id >= '0') && (outlet_id <= '9'))			|| (outlet_id == '*') || (outlet_id == 'A') )		   ) {			syslog(LOG_ERR			, "%s: the outlet_id %s must be between"			" 0 and 9 or '*' / 'A'",			       WTIid, outlet);			goto token_error;		}				if (outlet_id == 'A') {			/* Remap 'A' to '*'; in some configurations,			 * a '*' can't be configured because it breaks			 * scripts -- lmb */			outlet_id = '*';		}				if (ctx->unit_count >= WTI_NUM_CONTROLLERS) {			syslog(LOG_ERR, 				"%s: Tried to configure too many controllers",				WTIid);			goto token_error;		}				ctx->controllers[ctx->unit_count].node = STRDUP(node);		g_strdown(ctx->controllers[ctx->unit_count].node);		ctx->controllers[ctx->unit_count].outlet_id = outlet_id;		ctx->unit_count++;	} 	/* free our private copy of the string we've been destructively 	 * parsing with strtok()	 */	FREE(copy);	ctx->config = 1;	return ((ctx->unit_count > 0) ? S_OK : S_BADCONFIG);token_error:	FREE(copy);	return(S_BADCONFIG);}/*  * dtrtoggle - toggle DTR on the serial port *  * snarfed from minicom, sysdep1.c, a well known POSIX trick. * */static void dtrtoggle(int fd) {    struct termios tty, old;    int sec = 2;        if (gbl_debug) printf ("Calling dtrtoggle (%s)\n", WTIid);        tcgetattr(fd, &tty);    tcgetattr(fd, &old);    cfsetospeed(&tty, B0);    cfsetispeed(&tty, B0);    tcsetattr(fd, TCSANOW, &tty);    if (sec>0) {      sleep(sec);      tcsetattr(fd, TCSANOW, &old);    }        if (gbl_debug) printf ("dtrtoggle Complete (%s)\n", WTIid);}/* * RPSConnect - * * Connect to the given WTI_RPS10 device.   * Side Effects *    DTR on the serial port is toggled *    ctx->fd now contains a valid file descriptor to the serial port *    ??? LOCK THE SERIAL PORT ??? *   * Returns  *    S_OK on success *    S_OOPS on error *    S_TIMEOUT if the device did not respond * */static intRPSConnect(struct WTI_RPS10 * ctx){  	  	/* Open the serial port if it isn't already open */	if (ctx->fd < 0) {		struct termios tio;		ctx->fd = open (ctx->device, O_RDWR);		if (ctx->fd <0) {			syslog (LOG_ERR, "%s: Can't open %s : %s",				WTIid, ctx->device, strerror(errno));			return S_OOPS;		}		/* set the baudrate to 9600 8 - N - 1 */		memset (&tio, 0, sizeof(tio));		/* ??? ALAN - the -tradtitional flag on gcc causes the 		   CRTSCTS constant to generate a warning, and warnings                    are treated as errors, so I can't set this flag! - EZA ???		                      Hmmm. now that I look at the documentation, RTS		   is just wired high on this device! we don't need it.		*/		/* tio.c_cflag = B9600 | CS8 | CLOCAL | CREAD | CRTSCTS ;*/		tio.c_cflag = B9600 | CS8 | CLOCAL | CREAD ;		tio.c_lflag = ICANON;		if (tcsetattr (ctx->fd, TCSANOW, &tio) < 0) {			syslog (LOG_ERR, "%s: Can't set attributes %s : %s",				WTIid, ctx->device, strerror(errno));			close (ctx->fd);			ctx->fd=-1;			return S_OOPS;		}		/* flush all data to and fro the serial port before we start */		if (tcflush (ctx->fd, TCIOFLUSH) < 0) {			syslog (LOG_ERR, "%s: Can't flush %s : %s",				WTIid, ctx->device, strerror(errno));			close (ctx->fd);			ctx->fd=-1;			return S_OOPS;				}			}	/* Toggle DTR - this 'resets' the controller serial port interface            In minicom, try CTRL-A H to hangup and you can see this behavior.         */	dtrtoggle(ctx->fd);	/* Wait for the switch to respond with "RPS-10 Ready".  	   Emperically, this usually takes 5-10 seconds... 	   ... If this fails, this may be a hint that you got	   a broken serial cable, which doesn't connect hardware	   flow control.	*/	if (gbl_debug) printf ("Waiting for READY\n");	EXPECT(WTItokReady, 12);	if (gbl_debug) printf ("Got READY\n");	EXPECT(WTItokCRNL, 2);	if (gbl_debug) printf ("Got NL\n");  return(S_OK);}static intRPSDisconnect(struct WTI_RPS10 * ctx){  if (ctx->fd >= 0) {    /* Flush the serial port, we don't care what happens to the characters       and failing to do this can cause close to hang.    */    tcflush(ctx->fd, TCIOFLUSH);    close (ctx->fd);  }  ctx->fd = -1;  return S_OK;} /* * RPSNametoOutlet - Map a hostname to an outlet on this stonith device. * * Returns: *     0-9, * on success ( the outlet id on the RPS10 ) *     -1 on failure (host not found in the config file) *  */static signed charRPSNametoOutlet ( struct WTI_RPS10 * ctx, const char * host ){	int i=0;	char *shost;	if ( (shost = STRDUP(host)) == NULL) {		syslog(LOG_ERR, "strdup failed in RPSNametoOutlet");		return -1;	}	g_strdown(shost);			/* scan the controllers[] array to see if this host is there */	for (i=0;i<ctx->unit_count;i++) {		/* return the outlet id */		if ( ctx->controllers[i].node 		    && !strcmp(host, ctx->controllers[i].node)) {			/* found it! */			break;		}	}		free(shost);	if (i == ctx->unit_count) {		return -1;	} else {		return ctx->controllers[i].outlet_id;	}}/* *	rps10_reset - API call to Reset (reboot) the given host on  *          this Stonith device.  This involves toggling the power off  *          and then on again, OR just calling the builtin reset command *          on the stonith device. */static intrps10_reset_req(Stonith * s, int request, const char * host){	int	rc = S_OK;	int	lorc = S_OK;	signed char outlet_id = -1;	struct WTI_RPS10*	ctx;		if (gbl_debug) printf ("Calling rps10_reset (%s)\n", WTIid);		if (!ISWTIRPS10(s)) {		syslog(LOG_ERR, "invalid argument to RPS_reset_host");		return(S_OOPS);	}	if (!ISCONFIGED(s)) {		syslog(LOG_ERR		,	"unconfigured stonith object in RPS_reset_host");		return(S_OOPS);	}	ctx = (struct WTI_RPS10*) s->pinfo;	if ((rc = RPSConnect(ctx)) != S_OK) {		return(rc);	}	outlet_id = RPSNametoOutlet(ctx, host);	if (outlet_id < 0) {		syslog(LOG_WARNING, _("%s %s "				      "doesn't control host [%s]."), 		       ctx->idinfo, ctx->unitid, host);		RPSDisconnect(ctx);		return(S_BADHOST);	}	switch(request) {#if defined(ST_POWERON) 		case ST_POWERON:			rc = RPSOn(ctx, outlet_id, host);			break;#endif#if defined(ST_POWEROFF)		case ST_POWEROFF:			rc = RPSOff(ctx, outlet_id, host);			break;#endif	case ST_GENERIC_RESET:		rc = RPSReset(ctx, outlet_id, host);		break;	default:		rc = S_INVAL;		break;	}	lorc = RPSDisconnect(ctx);	return(rc != S_OK ? rc : lorc);}/* *	Parse the information in the given configuration file, *	and stash it away... */static intrps10_set_config_file(Stonith* s, const char * configname){	FILE *	cfgfile;	char	RPSid[256];	struct WTI_RPS10*	ctx;	if (!ISWTIRPS10(s)) {		syslog(LOG_ERR, "invalid argument to RPS_set_configfile");		return(S_OOPS);	}	ctx = (struct WTI_RPS10*) s->pinfo;	if ((cfgfile = fopen(configname, "r")) == NULL)  {		syslog(LOG_ERR, _("Cannot open %s"), configname);		return(S_BADCONFIG);	}	while (fgets(RPSid, sizeof(RPSid), cfgfile) != NULL){		switch (RPSid[0]){			case '\0': case '\n': case '\r': case '#':			continue;		}		/* We can really only handle one line. Wimpy. */		return RPS_parse_config_info(ctx, RPSid);	}	return(S_BADCONFIG);}/* *	rps10_set_config_info - API entry point to process one line of config info  *       for this particular device. * *      Parse the config information in the given string, and stash it away... * */static intrps10_set_config_info(Stonith* s, const char * info){	struct WTI_RPS10* ctx;	if (!ISWTIRPS10(s)) {		syslog(LOG_ERR, "RPS_provide_config_info: invalid argument");		return(S_OOPS);	}	ctx = (struct WTI_RPS10 *)s->pinfo;	return(RPS_parse_config_info(ctx, info));}/* * rps10_getinfo - API entry point to retrieve something from the handle */static const char *rps10_getinfo(Stonith * s, int reqtype){	struct WTI_RPS10* ctx;	const char *	ret;	if (!ISWTIRPS10(s)) {		syslog(LOG_ERR, "RPS_idinfo: invalid argument");		return NULL;	}	/*	 *	We look in the ST_TEXTDOMAIN catalog for our messages	 */	ctx = (struct WTI_RPS10 *)s->pinfo;	switch (reqtype) {		case ST_DEVICEID:			ret = ctx->idinfo;			break;		case ST_CONF_INFO_SYNTAX:			ret = _("<serial_device> <node> <outlet> "			"[ <node> <outlet> [...] ]\n"			"All tokens are white-space delimited.\n");			break;		case ST_CONF_FILE_SYNTAX:			ret = _("<serial_device> <node> <outlet> "			"[ <node> <outlet> [...] ]\n"			"All tokens are white-space delimited.\n"			"Blank lines and lines beginning with # are ignored");			break;		case ST_DEVICEDESCR:			ret = _("Western Telematic Inc. (WTI) "			"Remote Power Switch - RPS-10M.\n");			break;		case ST_DEVICEURL:			ret = "http://www.wti.com/";			break;		default:			ret = NULL;			break;	}	return ret;}/* * rps10_destroy - API entry point to destroy a WTI_RPS10 Stonith object. */static voidrps10_destroy(Stonith *s){	struct WTI_RPS10* ctx;	if (!ISWTIRPS10(s)) {		syslog(LOG_ERR, "wti_rps10_del: invalid argument");		return;	}	ctx = (struct WTI_RPS10 *)s->pinfo;	ctx->WTIid = NOTwtiid;	/*  close the fd if open and set ctx->fd to invalid */	RPSDisconnect(ctx);		if (ctx->device != NULL) {		FREE(ctx->device);		ctx->device = NULL;	}	if (ctx->idinfo != NULL) {		FREE(ctx->idinfo);		ctx->idinfo = NULL;	}	if (ctx->unitid != NULL) {		FREE(ctx->unitid);		ctx->unitid = NULL;	}}/*  * rps10_new - API entry point called to create a new WTI_RPS10 Stonith device *          object.  */static void *rps10_new(void){	struct WTI_RPS10*	ctx = MALLOCT(struct WTI_RPS10);	if (ctx == NULL) {		syslog(LOG_ERR, "out of memory");		return(NULL);	}	memset(ctx, 0, sizeof(*ctx));	ctx->WTIid = WTIid;	ctx->fd = -1;	ctx->config = 0;	ctx->unit_count = 0;	ctx->device = NULL;	ctx->idinfo = NULL;	ctx->unitid = NULL;	REPLSTR(ctx->idinfo, DEVICE);	REPLSTR(ctx->unitid, "unknown");	return((void *)ctx);}

⌨️ 快捷键说明

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