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

📄 apcsmart.c

📁 在LINUX下实现HA的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
intAPC_get_smallest_delay(int upsfd, const char *cmd, char *smdelay){	char resp[MAX_DELAY_STRING];	char orig[MAX_DELAY_STRING];	int delay, smallest;	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);	}	smallest = atoi(orig);	strcpy(smdelay, orig);	*resp = '\0';	/* search for smallest delay; need to loop through all possible	 * values so that we leave delay the way we found it */	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 ((delay = atoi(resp)) < smallest) {			smallest = delay;			strcpy(smdelay, resp);		}	}	return (S_OK);}/* * Initialize the ups */intAPC_init( struct APCDevice *ad ){  int upsfd;  char value[MAX_DELAY_STRING];#ifdef APC_DEBUG  syslog(LOG_DEBUG, "%s: called.", __FUNCTION__);#endif  /* if ad->upsfd != -1 device has already been configured. */  /* Just enter smart mode again because otherwise a SmartUPS-1000 */  /*   has been observed to sometimes not respond. */  if(ad->upsfd != -1) {      if(APC_enter_smartmode(ad->upsfd) != S_OK)	  return(S_OOPS);      return( S_OK );  }  /* open serial port and store the fd in ad->upsfd */  if ((upsfd = APC_open_serialport(ad->upsdev, B2400)) == -1) {    return (S_OOPS);  }  /* switch into smart mode */  if(APC_enter_smartmode(upsfd) != S_OK) {    APC_close_serialport(upsfd);    return( S_OOPS );  }  /* get the smallest possible delays for this particular hardware */  if (APC_get_smallest_delay(upsfd, CMD_SHUTDOWN_DELAY    , ad->shutdown_delay) != S_OK  || APC_get_smallest_delay(upsfd, CMD_WAKEUP_DELAY    , ad->wakeup_delay) != S_OK) {    APC_close_serialport(upsfd);    return S_OOPS;  }  /* get the old settings and store them */  strcpy(value, ad->shutdown_delay);  if (APC_set_ups_var(upsfd, CMD_SHUTDOWN_DELAY, value) != S_OK) {    APC_close_serialport(upsfd);    return (S_OOPS);    }  strcpy(ad->old_shutdown_delay, value);  strcpy(value, ad->wakeup_delay);  if (APC_set_ups_var(upsfd, CMD_WAKEUP_DELAY, value) != S_OK) {    APC_close_serialport(upsfd);    return (S_OOPS);  }  strcpy(ad->old_wakeup_delay, value);  ad->upsfd = upsfd;  return( S_OK );}/* * Restore original settings and close the port */voidAPC_deinit( struct APCDevice *ad ){      APC_enter_smartmode( ad->upsfd );      APC_set_ups_var(ad->upsfd, CMD_SHUTDOWN_DELAY, ad->old_shutdown_delay);      APC_set_ups_var(ad->upsfd, CMD_WAKEUP_DELAY, ad->old_wakeup_delay);      /* close serial port */      APC_close_serialport(ad->upsfd);}/* * Parse config */intAPC_parse_config_info(struct APCDevice *ad, const char *info ){  char hostname[MAX_STRING];  static char devicename[MAX_STRING];  char **hl;#ifdef APC_DEBUG  syslog(LOG_DEBUG, "%s: called.", __FUNCTION__);#endif  if (ad->hostcount >= 0) {    return(S_OOPS);  }  if ((hl = (char **)MALLOC((MAX_DEVICES+1)*sizeof(char*))) == NULL) {    syslog(LOG_ERR, "%s: out of memory!", __FUNCTION__);    return S_OOPS;  }  memset(hl, 0, (MAX_DEVICES+1)*sizeof(char*));  if (sscanf(info, "%s %s", devicename, hostname) == 2) {    g_strdown(hostname);    if(( hl[0] = STRDUP(hostname)) == NULL ) {      apcsmart_free_hostlist(hl);      hl = NULL;      return( S_OOPS );    }    ad->hostlist = hl;    ad->hostcount = MAX_DEVICES+1;    ad->upsdev = devicename;    return(S_OK);  }  return(S_BADCONFIG);}                                /* * return the status for this device  */static intapcsmart_status(Stonith * s){    struct APCDevice *ad;    char resp[MAX_STRING];    int rc;#ifdef APC_DEBUG    syslog(LOG_DEBUG, "%s: called.", __FUNCTION__);#endif    if (!ISAPCDEV(s)) {	syslog(LOG_ERR, "%s: invalid argument.", __FUNCTION__);	return (S_INVAL);    }    if( !ISCONFIGED(s)) {        syslog(LOG_ERR, "%s: device is UNCONFIGURED!", __FUNCTION__ );        return( S_OOPS );    }    ad = (struct APCDevice *) s->pinfo;    rc = APC_init(ad);    /* 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. */#ifdef APC_DEBUG    syslog(LOG_DEBUG, "%s: failed, rc=%d.", __FUNCTION__, rc);#endif    return (rc);}/* * return the list of hosts configured for this device  */static char **apcsmart_hostlist(Stonith * s){    int numhosts;    char **hl;    struct APCDevice *ad;    int j;#ifdef APC_DEBUG    syslog(LOG_DEBUG, "%s: called.", __FUNCTION__);#endif    if (!ISAPCDEV(s)) {	syslog(LOG_ERR, "%s: invalid argument.", __FUNCTION__);	return (NULL);    }    if( !ISCONFIGED(s)) {        syslog(LOG_ERR, "%s: device is UNCONFIGURED!", __FUNCTION__ );        return( NULL );    }    ad = (struct APCDevice *) s->pinfo;    numhosts = ad->hostcount;    if (( hl = (char **)MALLOC(numhosts * sizeof(char *))) == NULL) {	syslog(LOG_ERR, "%s: out of memory.", __FUNCTION__);	return (hl);    }    memset(hl, 0, numhosts * sizeof(char *));    for (j = 0; j < numhosts -1; ++j) {	if ((hl[j] = STRDUP(ad->hostlist[j])) == NULL) {	    apcsmart_free_hostlist(hl);	    hl = NULL;	    return (hl);	}    }    return (hl);}/* * free the hostlist  */static voidapcsmart_free_hostlist(char **hlist){    char **hl = hlist;#ifdef APC_DEBUG    syslog(LOG_DEBUG, "%s: called.", __FUNCTION__);#endif    if (hl == NULL)	return;    while (*hl) {	FREE(*hl);	*hl = NULL;	++hl;    }    FREE(hlist);    hlist = NULL;}static gbooleanapcsmart_RegisterBitsSet(struct APCDevice * 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", &regval) != 1)) {		if (waserr){			*waserr = TRUE;		}		return FALSE;	}	if (waserr){		*waserr = FALSE;	}	return ((regval & bits) == bits);}#define	apcsmart_ResetHappening(ad,err) apcsmart_RegisterBitsSet(ad,3,0x08,err)/* * reset the host  */static intapcsmart_reset_req(Stonith * s, int request, const char *host){    struct APCDevice *ad;    char resp[MAX_STRING];    int rc;    int i;    char **hl;    char *shost;    int b_found=FALSE;#ifdef APC_DEBUG    syslog(LOG_DEBUG, "%s: called.", __FUNCTION__);#endif    if (!ISAPCDEV(s)) {	syslog(LOG_ERR, "%s: invalid argument.", __FUNCTION__);	return (S_INVAL);    }    if( !ISCONFIGED(s)) {        syslog(LOG_ERR, "%s: device is UNCONFIGURED!", __FUNCTION__ );        return( S_OOPS );    }    if (host == NULL) {	syslog(LOG_ERR, "%s: invalid hostname argument.", __FUNCTION__);	return (S_INVAL);    }    shost = strdup(host);    if (shost == NULL) {	syslog(LOG_ERR, "%s: strdup failed.", __FUNCTION__);	return (S_INVAL);    }    g_strdown(shost);        ad = (struct APCDevice *) s->pinfo;    /* look through the hostlist */    hl = ad->hostlist;    while (*hl && !b_found ) {      if( strcmp( *hl, shost ) == 0 ) {        b_found = TRUE;        break;      } else        ++hl;    }    /* host not found in hostlist */    if( !b_found ) {      syslog(LOG_ERR, "%s: host '%s' not in hostlist.", __FUNCTION__, host);      rc = S_BADHOST;      goto out;    }    /* send reset command(s) */    if (((rc = APC_init(ad)) == S_OK)        && ((rc = APC_send_cmd(ad->upsfd, CMD_RESET)) == S_OK)) {	if (((rc = APC_recv_rsp(ad->upsfd, resp)) == S_OK) &&	    (strcmp(resp, RSP_RESET) == 0 || strcmp(resp, RSP_RESET2) == 0)) {	    /* first kind of reset command was accepted */	} else if (((rc = APC_send_cmd(ad->upsfd, CMD_RESET2)) == S_OK)	    && ((rc = APC_recv_rsp(ad->upsfd, resp)) == S_OK) &&	    (strcmp(resp, RSP_RESET) == 0 || strcmp(resp, RSP_RESET2) == 0)) {	    /* second kind of command was accepted */	} else {	    rc = S_RESETFAIL;	}    }    if (rc == S_OK) {	/* we wait grace period + up to 10 seconds after shutdown */	int	maxdelay = atoi(ad->shutdown_delay)+10;	for (i=0; i < maxdelay; ++i) {	    gboolean	err;	    if (apcsmart_ResetHappening(ad, &err)) {	        if (err) {	            break;	        }else{	            rc = S_OK;	            goto out;	        }	    }	    sleep(1);	}	rc = S_RESETFAIL;    }    /* reset failed */    syslog(LOG_ERR, "%s: resetting host '%s' failed.", __FUNCTION__, host);    rc = S_RESETFAIL;out:    free(shost);    return rc;}/* * parse the information in the given configuration file, * and stash it away...  */static intapcsmart_set_config_file(Stonith * s, const char *configname){    FILE *cfgfile;    char confline[MAX_STRING];    struct APCDevice *ad;                #ifdef APC_DEBUG    syslog(LOG_DEBUG, "%s: called.", __FUNCTION__);#endif    if (!ISAPCDEV(s)) {	syslog(LOG_ERR, "%s: invalid argument.", __FUNCTION__);	return (S_INVAL);    }    ad = (struct APCDevice *) s->pinfo;    if ((cfgfile = fopen(configname, "r")) == NULL)  {      syslog(LOG_ERR, "Cannot open %s", configname);      return(S_BADCONFIG);    }    while (fgets(confline, sizeof(confline), cfgfile) != NULL) {      if (*confline == '#' || *confline == '\n' || *confline == EOS)        continue;      return(APC_parse_config_info(ad, confline));    }    return(S_BADCONFIG);}/* * Parse the config information in the given string, and stash it away...  */static intapcsmart_set_config_info(Stonith * s, const char *info){    struct APCDevice *ad;#ifdef APC_DEBUG    syslog(LOG_DEBUG, "%s: called.", __FUNCTION__);#endif#ifdef APC_DEBUG    syslog(LOG_DEBUG, "%s: info: '%s'.", __FUNCTION__, info );#endif    if (!ISAPCDEV(s)) {	syslog(LOG_ERR, "%s: invalid argument.", __FUNCTION__);	return (S_INVAL);    }    ad = (struct APCDevice *) s->pinfo;            return(APC_parse_config_info(ad, info));}/* * get info about the stonith device  */static const char *apcsmart_getinfo(Stonith * s, int reqtype){    struct APCDevice *ad;    const char *ret;#ifdef APC_DEBUG    syslog(LOG_DEBUG, "%s: called.", __FUNCTION__);#endif    if (!ISAPCDEV(s)) {	syslog(LOG_ERR, "%s: invalid argument.", __FUNCTION__);	return NULL;    }       ad = (struct APCDevice *) s->pinfo;    switch (reqtype) {    	case ST_DEVICEID:		ret = ad->APCid;		break;    	case ST_CONF_INFO_SYNTAX:        	ret = _("devicename hostname\n"                	"The hostname and devicename are white-space delimited.");        	break;    	case ST_CONF_FILE_SYNTAX:        	ret = _("devicename hostname\n"                	"The hostname and devicename are white-space delimited.\n"                	"Both items must be on one line.\n"                	"Blank lines and lines beginning with # are ignored.");		break;	case ST_DEVICEDESCR:		ret = _("APC Smart UPS (via serial port - model must be >= Smart-UPS 750)");		break;	case ST_DEVICEURL:		ret = "http://www.apc.com/";		break;    default:	ret = NULL;	break;    }    return (ret);}/* * APC Stonith destructor...  */static voidapcsmart_destroy(Stonith * s){    struct APCDevice *ad;#ifdef APC_DEBUG    syslog(LOG_DEBUG, "%s: called.", __FUNCTION__);#endif    if (!ISAPCDEV(s)) {	syslog(LOG_ERR, "%s: invalid argument.", __FUNCTION__);	return;    }    ad = (struct APCDevice *) s->pinfo;    APC_deinit( ad );    ad->APCid = NOTapcID;    if (ad->hostlist) {	apcsmart_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 void *apcsmart_new(void){    struct APCDevice *ad = MALLOCT(struct APCDevice);#ifdef APC_DEBUG    syslog(LOG_DEBUG, "%s: called.", __FUNCTION__);#endif    if (ad == NULL) {	syslog(LOG_ERR, "%s: out of memory.", __FUNCTION__);	return (NULL);    }    memset(ad, 0, sizeof(*ad));    ad->APCid = APCid;    ad->hostlist = NULL;    ad->hostcount = -1;    ad->upsfd = -1;    return ((void *) ad);}

⌨️ 快捷键说明

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