?? apcsmart.c
字號:
intAPC_set_ups_var(int upsfd, const char *cmd, char *newval){ char resp[MAX_STRING]; char orig[MAX_STRING]; int rc; if (Debug) { LOG(PIL_DEBUG, "%s: called.", __FUNCTION__); } if (((rc = APC_enter_smartmode(upsfd)) != S_OK) || ((rc = APC_send_cmd(upsfd, cmd)) != S_OK) || ((rc = APC_recv_rsp(upsfd, orig)) != S_OK)) { return (rc); } if (strcmp(orig, newval) == 0) { return (S_OK); /* already set */ } *resp = '\0'; while (strcmp(resp, orig) != 0) { if (((rc = APC_send_cmd(upsfd, SWITCH_TO_NEXT_VAL)) != S_OK) || ((rc = APC_recv_rsp(upsfd, resp)) != S_OK)) { return (rc); } if (((rc = APC_enter_smartmode(upsfd)) != S_OK) || ((rc = APC_send_cmd(upsfd, cmd)) != S_OK) || ((rc = APC_recv_rsp(upsfd, resp)) != S_OK)) { return (rc); } if (strcmp(resp, newval) == 0) { strcpy(newval, orig); /* return the old value */ return (S_OK); /* got it */ } } LOG(PIL_CRIT, "%s(): Could not set variable '%s' to %s!" , __FUNCTION__, cmd, newval); LOG(PIL_CRIT, "%s(): This UPS may not support STONITH :-(" , __FUNCTION__); return (S_OOPS);}/* * Initialize the ups */intAPC_init(struct pluginDevice *ad){ int upsfd; char value[MAX_STRING]; if (Debug) { LOG(PIL_DEBUG, "%s: called.", __FUNCTION__); } /* if ad->upsfd == -1 -> dev configured! */ if(ad->upsfd >= 0 ) { return S_OK; } /* open serial port and store the fd in ad->upsfd */ if ((upsfd = APC_open_serialport(ad->upsdev, B2400)) == -1) { return -1; } /* switch into smart mode */ if (APC_enter_smartmode(upsfd) != S_OK) { return -1; } /* get the old settings and store them */ strcpy(value, SHUTDOWN_DELAY); if (APC_set_ups_var(upsfd, CMD_SHUTDOWN_DELAY, value) != S_OK) { return -1; } strcpy(old_shutdown_delay, value); strcpy(value, WAKEUP_DELAY); if (APC_set_ups_var(upsfd, CMD_WAKEUP_DELAY, value) != S_OK) { return (-1); } strcpy(old_wakeup_delay, value); ad->upsfd = upsfd; return S_OK;}/* * Restore original settings and close the port */voidAPC_deinit( int upsfd ){ APC_enter_smartmode( upsfd ); APC_set_ups_var(upsfd, CMD_SHUTDOWN_DELAY, old_shutdown_delay); APC_set_ups_var(upsfd, CMD_WAKEUP_DELAY, old_wakeup_delay); /* close serial port */ APC_close_serialport(upsfd);}static const char**apcsmart_get_confignames(StonithPlugin* sp){ static const char * names[] = {ST_TTYDEV, ST_HOSTLIST, NULL}; if (Debug) { LOG(PIL_DEBUG, "%s: called.", __FUNCTION__); } return names;}/* * Stash away the config info we've been given... */static intapcsmart_set_config(StonithPlugin * s, StonithNVpair* list){ struct pluginDevice * ad = (struct pluginDevice*)s; StonithNamesToGet namestoget [] = { {ST_TTYDEV, NULL} , {ST_HOSTLIST, NULL} , {NULL, NULL} }; int rc; if (Debug) { LOG(PIL_DEBUG, "%s: called.", __FUNCTION__); } ERRIFWRONGDEV(s, S_OOPS); if ((rc=OurImports->GetAllValues(namestoget, list)) != S_OK) { return rc; } ad->hostlist = OurImports->StringToHostList(namestoget[1].s_value); if (ad->hostlist == NULL) { LOG(PIL_CRIT,"StringToHostList() failed"); return S_OOPS; } for (ad->hostcount = 0; ad->hostlist[ad->hostcount] ; ad->hostcount++) { /* Just count */ } if (access(namestoget[0].s_value, R_OK|W_OK|F_OK) < 0) { LOG(PIL_CRIT,"Cannot access tty [%s]" , namestoget[0].s_value); return S_BADCONFIG; } ad->upsdev = namestoget[0].s_value; return ad->hostcount ? S_OK : S_BADCONFIG;}/* * return the status for this device */static intapcsmart_status(StonithPlugin * s){ struct pluginDevice *ad = (struct pluginDevice *) s; char resp[MAX_STRING]; int rc; if (Debug) { LOG(PIL_DEBUG, "%s: called.", __FUNCTION__); } ERRIFNOTCONFIGED(s,S_OOPS); /* get status */ if (((rc = APC_init( ad ) == S_OK) && ((rc = APC_send_cmd(ad->upsfd, CMD_GET_STATUS)) == S_OK) && ((rc = APC_recv_rsp(ad->upsfd, resp)) == S_OK))) { return (S_OK); /* everything ok. */ } if (Debug) { LOG(PIL_DEBUG, "%s: failed.", __FUNCTION__); } return (rc);}/* * return the list of hosts configured for this device */static char **apcsmart_hostlist(StonithPlugin * s){ struct pluginDevice *ad = (struct pluginDevice *) s; if (Debug) { LOG(PIL_DEBUG, "%s: called.", __FUNCTION__); } ERRIFNOTCONFIGED(s,NULL); return OurImports->CopyHostList((const char **)ad->hostlist);}static gbooleanapcsmart_RegisterBitsSet(struct pluginDevice * ad, int nreg, unsigned bits, gboolean* waserr){ const char* reqregs[4] = {"?", "~", "'", "8"}; unsigned regval; char resp[MAX_STRING]; if (Debug) { LOG(PIL_DEBUG, "%s: called.", __FUNCTION__); } if (APC_enter_smartmode(ad->upsfd) != S_OK || APC_send_cmd(ad->upsfd, reqregs[nreg]) != S_OK || APC_recv_rsp(ad->upsfd, resp) != S_OK || (sscanf(resp, "%02x", ®val) != 1)) { if (waserr){ *waserr = TRUE; } return FALSE; } if (waserr){ *waserr = FALSE; } return ((regval & bits) == bits);}#define apcsmart_IsPoweredOff(ad, err) apcsmart_RegisterBitsSet(ad,1,0x40,err)#define apcsmart_ResetHappening(ad,err) apcsmart_RegisterBitsSet(ad,3,0x08,err)static intapcsmart_ReqOnOff(struct pluginDevice * ad, int request){ const char * cmdstr; int rc; if (Debug) { LOG(PIL_DEBUG, "%s: called.", __FUNCTION__); } cmdstr = (request == ST_POWEROFF ? CMD_OFF : CMD_ON); /* enter smartmode, send on/off command */ if ((rc =APC_enter_smartmode(ad->upsfd)) != S_OK || (rc = APC_send_cmd(ad->upsfd, cmdstr)) != S_OK) { return rc; } sleep(2); if ((rc = APC_send_cmd(ad->upsfd, cmdstr)) == S_OK) { gboolean ison; gboolean waserr; sleep(1); ison = !apcsmart_IsPoweredOff(ad, &waserr); if (waserr) { return S_RESETFAIL; } if (request == ST_POWEROFF) { return ison ? S_RESETFAIL : S_OK; }else{ return ison ? S_OK : S_RESETFAIL; } } return rc;}/* * reset the host */static intapcsmart_ReqGenericReset(struct pluginDevice *ad){ char resp[MAX_STRING]; int rc = S_RESETFAIL; if (Debug) { LOG(PIL_DEBUG, "%s: called.", __FUNCTION__); } /* enter smartmode, send reset command */ if (((rc = APC_init(ad)) == S_OK) && ((rc = APC_send_cmd(ad->upsfd, CMD_RESET)) == S_OK) && ((rc = APC_recv_rsp(ad->upsfd, resp)) == S_OK) && ( strcmp(resp, RSP_RESET) == 0 || strcmp(resp, RSP_RESET2) == 0)) { int maxdelay = atoi(SHUTDOWN_DELAY)+5; int j; for (j=0; j < maxdelay; ++j) { gboolean err; if (apcsmart_ResetHappening(ad, &err)) { return err ? S_RESETFAIL : S_OK; } sleep(1); } return S_RESETFAIL; }else{ LOG(PIL_DEBUG, "APC: rc = %d resp[%s]" , rc, resp); if (rc == S_OK && strcmp(resp, RSP_NA) == 0){ gboolean iserr; /* This means it's currently powered off */ /* or busy on a previous command... */ if (apcsmart_IsPoweredOff(ad, &iserr)) { if (iserr) { return S_RESETFAIL; } return apcsmart_ReqOnOff(ad, ST_POWERON); } } } strcpy(resp, "?"); /* reset failed */ return S_RESETFAIL;}static intapcsmart_req_reset(StonithPlugin * s, int request, const char *host){ char ** hl; int b_found=FALSE; struct pluginDevice * ad = (struct pluginDevice *) s; int rc; ERRIFNOTCONFIGED(s, S_OOPS); if (host == NULL) { LOG(PIL_CRIT, "%s: invalid hostname argument.", __FUNCTION__); return (S_INVAL); } /* look through the hostlist */ hl = ad->hostlist; while (*hl && !b_found ) { if( strcmp( *hl, host ) == 0 ) { b_found = TRUE; break; }else{ ++hl; } } /* host not found in hostlist */ if( !b_found ) { LOG(PIL_CRIT, "%s: host '%s' not in hostlist." , __FUNCTION__, host); return S_BADHOST; } if ((rc = APC_init(ad)) != S_OK) { return rc; } if (request == ST_POWERON || request == ST_POWEROFF) { return apcsmart_ReqOnOff(ad, request); } return apcsmart_ReqGenericReset(ad);}/* * get info about the stonith device */static const char *apcsmart_get_info(StonithPlugin * s, int reqtype){ struct pluginDevice *ad = (struct pluginDevice *) s; const char *ret; if (Debug) { LOG(PIL_DEBUG, "%s: called.", __FUNCTION__); } ERRIFWRONGDEV(s,NULL); switch (reqtype) { case ST_DEVICEID: ret = ad->pluginid; break; case ST_DEVICEDESCR: ret = "APC Smart UPS" " (via serial port - NOT USB!). " " Works with higher-end APC UPSes, like" " Back-UPS Pro, Smart-UPS, Matrix-UPS, etc. " " (Smart-UPS may have to be >= Smart-UPS 700?)\n" " See http://us1.networkupstools.org/protocols/apcsmart.html" " for protocol compatibility details."; break; case ST_DEVICEURL: ret = "http://www.apc.com/"; break; default: ret = NULL; break; } return (ret);}/* * APC Stonith destructor... */static voidapcsmart_destroy(StonithPlugin * s){ struct pluginDevice *ad = (struct pluginDevice *) s; if (Debug) { LOG(PIL_DEBUG, "%s: called.", __FUNCTION__); } VOIDERRIFWRONGDEV(s); APC_deinit( ad->upsfd ); ad->pluginid = NOTpluginID; if (ad->hostlist) { stonith_free_hostlist(ad->hostlist); ad->hostlist = NULL; } ad->hostcount = -1; ad->upsfd = -1; FREE(ad);}/* * Create a new APC Stonith device. Too bad this function can't be * static */static StonithPlugin *apcsmart_new(void){ struct pluginDevice *ad = MALLOCT(struct pluginDevice); if (Debug) { LOG(PIL_DEBUG, "%s: called.", __FUNCTION__); } if (ad == NULL) { LOG(PIL_CRIT, "%s: out of memory.", __FUNCTION__); return (NULL); } memset(ad, 0, sizeof(*ad)); ad->pluginid = pluginid; ad->hostlist = NULL; ad->hostcount = -1; ad->upsfd = -1; ad->sp.s_ops = &apcsmartOps; if (Debug) { LOG(PIL_DEBUG, "%s: returning successfully.", __FUNCTION__); } return &(ad->sp);}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -