[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[cobalt-developers] APC back UPS 500
- Subject: [cobalt-developers] APC back UPS 500
- From: "Gerald Waugh" <gerald@xxxxxxxxx>
- Date: Tue Jul 10 15:43:24 2001
- List-id: Discussion Forum for developers on Cobalt Networks products <cobalt-developers.list.cobalt.com>
Sorry for this long post!
I have the following problem,
I have six Cobalt Servers mixed RaQ2, RaQ3 and RaQ4 and 2 Intel white boxes all
running Red HatLinux.
I have a manually switched generator backup.
I use APC Back UPS 500, one for each system.
The code that follows controls the UPS for the systems.
I modified inittab to do a reset instead of halt, changed the time to 2 minutes.
I modified halt to "runcmd raqupsd /dev/ttyS1 killpower" just before the reset.
when halt runs and TIOCM_DSR and TIOCM_CD are high the UPS
will shutdown. If line power resumed during shutdown -r the system will reboot.
The Intel white boxes run fine using APC furnished standard serial cable.
(I know there is a Linux Cable, but 8 of them will cost 340.00, not to
mention the issues of ordering, and I think that is nonsense, do it in
software!)
Now the Cobalt RaQ's.
These units shutdown the UPS as soon as line power is removed. Ack!
This problem is driving me crazy!!! the same code is running on all the
systems. WHY does it work on the white boxes and not the blue boxes???
/* raqupsd.c -- Simple Daemon to catch power failure signals from a
* Back-UPS 500 (from APC).
*
* Parts of the code are from Miquel van Smoorenburg's powerd.c
* Other parts are from Christian Holtje <docwhat@xxxxxxxx>
* I believe that it is okay to say that this is Public Domain, just
* give credit, where credit is due.
* Modified on 10 July 2001 Gerald Waugh <gerald@xxxxxxxxx>
* to work with APC furnished cable.
* Disclaimer: We make NO claims to this software, and take no
* resposibility for it's use/misuse.
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <syslog.h>
/* File needed by SysVInit (Reads this file to determine shutcown */
#define PWRSTAT "/etc/powerstatus"
void powerfail(int fail); /* prototype - called by this program */
/* Main program. */
int main(int argc, char **argv)
{
int fd;
int rts_bit = TIOCM_RTS;
int dtr_bit = TIOCM_DTR;
int flags;
int status, oldstat = -1;
int count = 0;
int ups_state = 0;
openlog("raqupsd:", LOG_PID, LOG_DAEMON);
if (argc < 2) { /* requires serial port */
syslog(LOG_ERR, "Usage: %s <device> [killpower]\n", argv[0]);
exit(1);
}
/* Open the the device */
if ((fd = open(argv[1], O_RDWR | O_NOCTTY)) < 0) {
syslog(LOG_NOTICE, "%s: %s: %s", argv[0], argv[1], sys_errlist[errno]);
exit(1);
}
syslog(LOG_NOTICE, "raqupsd is starting up");
ioctl(fd, TIOCMBIS, &dtr_bit); // DTR on, so we get DSR from UPS
ioctl(fd, TIOCMBIC, &rts_bit); // RTS off
if ( argc >= 3 && (strcmp(argv[2], "killpower")==0) ) {
/* Let's kill the power! - system request */
ioctl(fd, TIOCMBIS, &rts_bit);
sleep(1);
close(fd);
exit(0);
}
/* Become a daemon. */
switch(fork()) {
case 0: /* I am the child. */
setsid();
break;
case -1: /* Failed to become daemon. */
syslog(LOG_ERR, "%s: can't fork.\n", argv[0]);
exit(1);
default: /* I am the parent. */
exit(0);
}
openlog("raqupsd:", LOG_PID, LOG_DAEMON);
syslog(LOG_NOTICE, "raqupsd has become a daemon");
/* Now sample the DCD line. */
while(1) {
ioctl(fd, TIOCMGET, &flags);
if(ups_state == 0 && flags & TIOCM_DSR) {
ups_state = 1;
syslog(LOG_WARNING, "UPS detected Line Failure: Running on Battery");
}
if(ups_state == 1 && !(flags & TIOCM_DSR)) {
ups_state = 0;
syslog(LOG_ALERT, "UPS Line Power Restored");
}
status = (flags & TIOCM_CD);
/* Did DCD jumps to high? Then the power has failed. */
if (oldstat == 0 && status != 0) {
count++;
if (count > 3) {
powerfail(0);
syslog(LOG_ALERT, "UPS Low Battery detected sending SIGPWR");
}
else { sleep(2); continue; }
}
/* Did DCD go down again? Then the power is back. */
if (oldstat > 0 && status == 0) {
count++;
if (count > 3) {
powerfail(1);
syslog(LOG_ALERT, "Power restored sending SIGPWR");
ups_state = 0;
}
else { sleep(2); continue; }
}
/* Reset count, remember status and sleep 2 seconds. */
count = 0;
oldstat = status;
sleep(2);
}
/* Error! (shouldn't happen) */
return(1);
}
/* Tell init the power has either gone or is back. */
void powerfail(int ok)
{
int fd;
/* Create an info file needed by init to shutdown/cancel shutdown */
unlink(PWRSTAT);
if ((fd = open(PWRSTAT, O_CREAT|O_WRONLY, 0644)) >= 0) {
if (ok)
write(fd, "OK\n", 3);
else
write(fd, "FAIL\n", 5);
close(fd);
}
kill(1, SIGPWR);
}
/* End of File */