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

📄 nw_rpc100s.c

📁 在LINUX下实现HA的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 *  *               This type of device is configured from the config file, *                 so we don't actually have to connect to figure this *                 out, just peruse the 'ctx' structure. * Returns: *     NULL on error *     a malloced array, terminated with a NULL, *         of null-terminated malloc'ed strings. */static char **nw_rpc100s_hostlist(Stonith  *s){	char **		ret = NULL;	/* list to return */	struct NW_RPC100S*	ctx;	if (gbl_debug) printf ("Calling nw_rpc100s_hostlist (%s)\n", RPCid);		if (!ISNWRPC100S(s)) {		syslog(LOG_ERR, "invalid argument to RPC_list_hosts");		return(NULL);	}	if (!ISCONFIGED(s)) {		syslog(LOG_ERR		,	"unconfigured stonith object in RPC_list_hosts");		return(NULL);	}	ctx = (struct NW_RPC100S*) s->pinfo;	ret = (char **)MALLOC(2*sizeof(char*));	if (ret == NULL) {		syslog(LOG_ERR, "out of memory");	} else {		ret[1]=NULL;		ret[0]=STRDUP(ctx->node);		if (ret[0] == NULL) {			syslog(LOG_ERR, "out of memory");			FREE(ret);			ret = NULL;		} else {			g_strdown(ret[0]);		}	}	return(ret);} /* end si_hostlist() *//* * nw_rpc100s_free_hostlist - free the result from nw_rpc100s_hostlist()  */static voidnw_rpc100s_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... * *      <info> contains the parameters specific to this type of object * *         The format of <parameters> 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) * *      stonith nodea NW_RPC100S /dev/ttyS0 nodeb 0  *      stonith nodeb NW_RPC100S /dev/ttyS0 nodea 0 nodec 1 * *      Another possible configuration is for 2 stonith devices accessible *         through 2 different serial ports on nodeb: * *      stonith nodeb NW_RPC100S /dev/ttyS0 nodea 0  *      stonith nodeb NW_RPC100S /dev/ttyS1 nodec 0 */static intRPC_parse_config_info(struct NW_RPC100S* ctx, const char * info){	char *copy;	char *token;	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'",		       RPCid, info);		goto token_error;			}	ctx->device = STRDUP(token);	if (!ctx->device) {		syslog(LOG_ERR, "out of memory");		goto token_error;	}	/* Grab <nodename>  */	token = strtok (NULL, " \t");	if (!token) {		syslog(LOG_ERR, "%s: Can't find node name on config line '%s'",		       RPCid, info);		goto token_error;			}	ctx->node = STRDUP(token);	if (!ctx->node) {		syslog(LOG_ERR, "out of memory");		goto token_error;	}				/* free our private copy of the string we've been destructively 	   parsing with strtok()	*/	FREE(copy);	ctx->config = 1;	return S_OK;token_error:	FREE(copy);	return(S_BADCONFIG);}/* * RPCConnect - * * Connect to the given NW_RPC100S device.   * Side Effects *    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 intRPCConnect(struct NW_RPC100S * 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",				RPCid, 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",				RPCid, 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",				RPCid, ctx->device, strerror(errno));			close (ctx->fd);			ctx->fd=-1;			return S_OOPS;				}			}	/* Send a BOGUS string */	SEND("//0,0,BOGUS;\r\n", 10);		/* Should reply with "Invalid Command" */	if (gbl_debug) printf ("Waiting for \"Invalid Entry\"n");	EXPECT(NWtokInvalidEntry, 12);	if (gbl_debug) printf ("Got Invalid Entry\n");	EXPECT(NWtokCRNL, 2);	if (gbl_debug) printf ("Got NL\n");	     return(S_OK);}static intRPCDisconnect(struct NW_RPC100S * 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;} /* * RPCNametoOutlet - Map a hostname to an outlet number on this stonith device. * * Returns: *     0 on success ( the outlet number on the RPS10 - there is only one ) *     -1 on failure (host not found in the config file) *  */static intRPCNametoOutlet ( struct NW_RPC100S * ctx, const char * host ){	char *shost;	int rc = -1;		if ( (shost = strdup(host)) == NULL) {		syslog(LOG_ERR, "strdup failed in RPCNametoOutlet");		return -1;	}	if (!strcmp(ctx->node, host))		rc = 0;	free(shost);	return rc;}/* *	nw_rpc100s_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 intnw_rpc100s_reset_req(Stonith * s, int request, const char * host){	int	rc = S_OK;	int	lorc = S_OK;	int outletnum = -1;	struct NW_RPC100S*	ctx;		if (gbl_debug) printf ("Calling nw_rpc100s_reset (%s)\n", RPCid);		if (!ISNWRPC100S(s)) {		syslog(LOG_ERR, "invalid argument to RPC_reset_host");		return(S_OOPS);	}	if (!ISCONFIGED(s)) {		syslog(LOG_ERR		,	"unconfigured stonith object in RPC_reset_host");		return(S_OOPS);	}	ctx = (struct NW_RPC100S*) s->pinfo;	if ((rc = RPCConnect(ctx)) != S_OK) {		return(rc);	}	outletnum = RPCNametoOutlet(ctx, host);	if (outletnum < 0) {		syslog(LOG_WARNING, _("%s %s "				      "doesn't control host [%s]."), 		       ctx->idinfo, ctx->unitid, host);		RPCDisconnect(ctx);		return(S_BADHOST);	}	switch(request) {#if defined(ST_POWERON) 		case ST_POWERON:			rc = RPCOn(ctx, outletnum, host);			break;#endif#if defined(ST_POWEROFF)		case ST_POWEROFF:			rc = RPCOff(ctx, outletnum, host);			break;#endif	case ST_GENERIC_RESET:		rc = RPCReset(ctx, outletnum, host);		break;	default:		rc = S_INVAL;		break;	}	lorc = RPCDisconnect(ctx);	return(rc != S_OK ? rc : lorc);}/* *	Parse the information in the given configuration file, *	and stash it away... */static intnw_rpc100s_set_config_file(Stonith* s, const char * configname){	FILE *	cfgfile;	char	cfgline[256];	struct NW_RPC100S*	ctx;	if (!ISNWRPC100S(s)) {		syslog(LOG_ERR, "invalid argument to RPC_set_configfile");		return(S_OOPS);	}	ctx = (struct NW_RPC100S*) s->pinfo;	if ((cfgfile = fopen(configname, "r")) == NULL)  {		syslog(LOG_ERR, _("Cannot open %s"), configname);		return(S_BADCONFIG);	}	while (fgets(cfgline, sizeof(cfgline), cfgfile) != NULL){		RPC_parse_config_info(ctx, cfgline);	}	return(S_BADCONFIG);}/* *	nw_rpc100s_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 intnw_rpc100s_set_config_info(Stonith* s, const char * info){	struct NW_RPC100S* ctx;	if (!ISNWRPC100S(s)) {		syslog(LOG_ERR, "RPC_provide_config_info: invalid argument");		return(S_OOPS);	}	ctx = (struct NW_RPC100S *)s->pinfo;	return(RPC_parse_config_info(ctx, info));}/* * nw_rpc100s_getinfo - API entry point to retrieve something from the handle */static const char *nw_rpc100s_getinfo(Stonith * s, int reqtype){	struct NW_RPC100S* ctx;	const char *		ret;	if (!ISNWRPC100S(s)) {		syslog(LOG_ERR, "RPC_idinfo: invalid argument");		return NULL;	}	/*	 *	We look in the ST_TEXTDOMAIN catalog for our messages	 */	ctx = (struct NW_RPC100S *)s->pinfo;	switch (reqtype) {		case ST_DEVICEID:			ret = ctx->idinfo;			break;		case ST_CONF_INFO_SYNTAX:			ret = _("<serial_device> <node>\n"			"All tokens are white-space delimited.\n");			break;		case ST_CONF_FILE_SYNTAX:			ret = _("<serial_device> <node>\n"			"All tokens are white-space delimited.\n"			"Blank lines and lines beginning with # are ignored");			break;		case ST_DEVICEDESCR:			ret = _("Micro Energetics Night/Ware RPC100S");			break;		case ST_DEVICEURL:			ret = "http://microenergeticscorp.com/";			break;		default:			ret = NULL;			break;	}	return ret;}/* * nw_rpc100s_destroy - API entry point to destroy a NW_RPC100S Stonith object. */static voidnw_rpc100s_destroy(Stonith *s){	struct NW_RPC100S* ctx;	if (!ISNWRPC100S(s)) {		syslog(LOG_ERR, "nw_rpc100s_del: invalid argument");		return;	}	ctx = (struct NW_RPC100S *)s->pinfo;	ctx->RPCid = NOTrpcid;	/*  close the fd if open and set ctx->fd to invalid */	RPCDisconnect(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;	}}/*  * nw_rpc100s_new - API entry point called to create a new NW_RPC100S Stonith device *          object.  */static void *nw_rpc100s_new(void){	struct NW_RPC100S*	ctx = MALLOCT(struct NW_RPC100S);	if (ctx == NULL) {		syslog(LOG_ERR, "out of memory");		return(NULL);	}	memset(ctx, 0, sizeof(*ctx));	ctx->RPCid = RPCid;	ctx->fd = -1;	ctx->config = 0;	ctx->device = NULL;	ctx->node = 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 + -