📄 nw_rpc100s.c
字号:
ret[0]=STRDUP(ctx->node); if (ret[0] == NULL) { LOG(PIL_CRIT, "out of memory"); FREE(ret); ret = NULL; } else { g_strdown(ret[0]); } } return(ret);} /* end si_hostlist() *//* * 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 pluginDevice* 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) { LOG(PIL_CRIT, "out of memory"); return S_OOPS; } /* Grab the serial device */ token = strtok (copy, " \t"); if (!token) { LOG(PIL_CRIT, "%s: Can't find serial device on config line '%s'", pluginid, info); goto token_error; } ctx->device = STRDUP(token); if (!ctx->device) { LOG(PIL_CRIT, "out of memory"); goto token_error; } /* Grab <nodename> */ token = strtok (NULL, " \t"); if (!token) { LOG(PIL_CRIT, "%s: Can't find node name on config line '%s'", pluginid, info); goto token_error; } ctx->node = STRDUP(token); if (!ctx->node) { LOG(PIL_CRIT, "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 pluginDevice * 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) { LOG(PIL_CRIT, "%s: Can't open %s : %s", pluginid, 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) { LOG(PIL_CRIT, "%s: Can't set attributes %s : %s", pluginid, 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) { LOG(PIL_CRIT, "%s: Can't flush %s : %s", pluginid, ctx->device, strerror(errno)); close (ctx->fd); ctx->fd=-1; return S_OOPS; } } /* Send a BOGUS string */ SENDCMD("//0,0,BOGUS;\r\n", 10); /* Should reply with "Invalid Command" */ if (gbl_debug) { printf ("Waiting for \"Invalid Entry\"n"); } EXPECT(ctx->fd, NWtokInvalidEntry, 12); if (gbl_debug) { printf ("Got Invalid Entry\n"); } EXPECT(ctx->fd, NWtokCRNL, 2); if (gbl_debug) { printf ("Got NL\n"); } return(S_OK);}static intRPCDisconnect(struct pluginDevice * 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 pluginDevice * ctx, const char * host ){ char *shost; int rc = -1; if ( (shost = strdup(host)) == NULL) { LOG(PIL_CRIT, "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(StonithPlugin * s, int request, const char * host){ int rc = S_OK; int lorc = S_OK; int outletnum = -1; struct pluginDevice* ctx; if (gbl_debug) { printf ("Calling nw_rpc100s_reset (%s)\n", pluginid); } ERRIFNOTCONFIGED(s,S_OOPS); ctx = (struct pluginDevice*) s; if ((rc = RPCConnect(ctx)) != S_OK) { return(rc); } outletnum = RPCNametoOutlet(ctx, host); LOG(PIL_DEBUG, "zk:outletname=%d", outletnum); if (outletnum < 0) { LOG(PIL_WARN, "%s %s %s[%s]", ctx->idinfo, ctx->unitid, _("doesn't control host"), 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 string * and stash it away... */static intnw_rpc100s_set_config(StonithPlugin* s, StonithNVpair *list){ char cfgline[MAX_CFGLINE]; struct pluginDevice* ctx; StonithNamesToGet namestoget [] = { {ST_TTYDEV, NULL} , {ST_HOSTLIST, NULL} , {NULL, NULL} }; int rc = 0; ERRIFWRONGDEV(s,S_OOPS); ctx = (struct pluginDevice*) s; if ((rc = OurImports->GetAllValues(namestoget , list)) != S_OK) { return rc; } if ((snprintf(cfgline,MAX_CFGLINE , "%s %s" , namestoget[0].s_value , namestoget[1].s_value)) <= 0){ LOG(PIL_CRIT, "Can not copy parameter to cfgline"); } return (RPC_parse_config_info(ctx, cfgline));}/* * Return STONITH config vars */static const char **nw_rpc100s_get_confignames(StonithPlugin* p){ static const char * RpcParams[] = {ST_TTYDEV , ST_HOSTLIST, NULL }; return RpcParams;}/* * nw_rpc100s_getinfo - API entry point to retrieve something from the handle */static const char *nw_rpc100s_getinfo(StonithPlugin * s, int reqtype){ struct pluginDevice* ctx; const char * ret; ERRIFWRONGDEV(s,NULL); /* * We look in the ST_TEXTDOMAIN catalog for our messages */ ctx = (struct pluginDevice *)s; switch (reqtype) { case ST_DEVICEID: ret = ctx->idinfo; break; case ST_DEVICEDESCR: ret = _("Micro Energetics Night/Ware RPC100S"); break; default: ret = NULL; break; } return ret;}/* * nw_rpc100s_destroy - API entry point to destroy a NW_RPC100S Stonith object. */static voidnw_rpc100s_destroy(StonithPlugin *s){ struct pluginDevice* ctx; VOIDERRIFWRONGDEV(s); ctx = (struct pluginDevice *)s; ctx->pluginid = 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 StonithPlugin *nw_rpc100s_new(void){ struct pluginDevice* ctx = MALLOCT(struct pluginDevice); if (ctx == NULL) { LOG(PIL_CRIT, "out of memory"); return(NULL); } memset(ctx, 0, sizeof(*ctx)); ctx->pluginid = pluginid; 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"); ctx->sp.s_ops = &nw_rpc100sOps; return &(ctx->sp);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -