libacuta4 - a library for monitoring an acuta4 disk array

Intro

libacuta4 is a C library for querying the status of an Accusys Acuta 4 disk array. The Acuta4 is a low-cost, standalone IDE / SATA hardware raid array that can connect to a host computer over SATA, USB, or Firewire. Considering the size of current IDE disks and the throughput of a SATA bus, this small system performs reasonably well for its modest $1000 - $1400 price tag.

The folks at Accusys were kind enough to provide me with a document detailing the serial communication protocol required to talk to their unit. The spec also covered the SMART interface to some of their other products, but since I don't have any of those, I have not written support for it. A copy of the protocol is included with the source distribution and is also available here. The original version of the spec is here. NOTE: This original version contains at least 2 or 3 errors (specifically around the fan speed reporting bits).

In addition, some early notes on my reverse engineering attempts (before I received the spec) are here.

This library was developed on an i386 machine running OpenBSD 3.6. It will likely compile and run fine on other BSDs, since it makes use of the bsd.prog.mk and bsd.lib.mk system makefiles. Non-BSD systems could be supported if there was desire (and if I had access). There probably are hidden endian assumptions in the code, since I read bits directly from the serial port, so big-endian machines may not work. I don't have a spare unit to test against my Ultra 5, so any feedback there would be appreciated. I can whip up a patch if someone will volunteer to test it.

The source tarball includes:

and is available for download here. This code is distributed under a BSD-style license.

Installation should be pretty straight forward, you'll want to do:
$ tar -xzf acuta4-0.1.tar.gz
$ cd acuta4
$ sudo make obj includes all install
Note that check_nagios needs to either be setuid or accessed via sudo since it requires access to a serial port by your nagios user.

To-do / bugs

If you come across other bugs, or have suggestions or patches (!!!), just send me an email at dave@redterror.net.

API docs

The main header file, acuta4.h, is the definitive guide for library. These notes attempt to tie it together and give a bit of a guide through the necessary hoops through which one must jump.

Setup / Getting Going

struct acuta_message * acuta4_init_msg (void)
void acuta4_free_msg (struct acuta_message *)
void acuta4_setCommand (struct acuta_message *, u_int8_t)
u_int8_t acuta4_getCommand (struct acuta_message *)
void acuta4_dump_msg(struct acuta_message *)

These functions all deal with the standard create / destroy / tweak ops on the acuta_message struct. The acuta4_dump_msg function is available for debugging.

The available commands defined as constants in acuta4.h. They are:

Serial Line Ops

int acuta4_setup_serial (char *) - opens the serial port specified and configure line settings to talk to the acuta4. The acuta4 requires a 19200 8N1 connection. A file descriptor is returned.
int acuta4_send_msg (int, struct acuta_message *) - write a acuta_message to the file descriptor specified, and read the reply back from the same spot.

The caller can simply close() the file descriptor when they are done - no special close method is provided.

CMD_STATUS Functions - aka, raid health metrics

int acuta4_raid_level (struct acuta_message *) - checks the raid configuration of the array (i.e. RAID 0, 1, 0+1, 5, 5+spare). Returns one of the RAID_LEVEL_* constants.
int acuta4_raid_status (struct acuta_message *) - checks the health of the array. Returns one of the RAID_STATUS_* constants.
int acuta4_controller_type (struct acuta_message *) - currently only returns the acuta4 constant.
int * acuta4_raid_members (struct acuta_message *) - returns an array of ACUTA4_DISK_QTY integers. Each integer is 1 if it is a member of the raid set, or 0 if not.
int * acuta4_key_status (struct acuta_message *) - similar to the above, but each integer is 1 if the tray is inserted. Accusys docs refer to those as 'keys', not sure why.
int acuta4_disk_status (struct acuta_message *, unsigned int) - return one of the DISK_STATUS_* constants depending on the health of the disk queried. Valid disk numbers are between 0 and ACUTA4_DISK_QTY - 1. int acuta4_disk_error (struct acuta_message *, unsigned int) - like above, but provides a more detailed failure reason in the event of disk failure / mismatch.
int acuta4_fan_status (struct acuta_message *) - checks if the fan is operational, returns FAN_*.
int acuta4_temp_status (struct acuta_message *) - likewise for the temperature sensor, returns TEMP_SENSOR_*.
float acuta4_percent1 (struct acuta_message *) - when the array is initializing or rebuilding a disk, this reports the percentage complete.
float acuta4_percent2 (struct acuta_message *) - like above, but only useful if rebuilding the second pair in raid 0+1.
u_int16_t acuta4_fan_rpm (struct acuta_message *) - the fan rpm.
int acuta4_host_if_type (struct acuta_message *) - the host interface type, on of HOST_IF_*.
u_int8_t acuta4_temperature (struct acuta_message *) - the unit's temperature, in Celsius degrees.

CMD_CONTROLLER_INFO functions

char * acuta4_controller_serial_number (struct acuta_message *) - returns the unit's serial number.

CMD_RAID_INFO / CMD_DISKX_INFO - generic info commands

These functions provide basic descriptive information about the array and the individual disks.

char * acuta4_info_model_name (struct acuta_message *) - returns either Accuta4 or the disk manufacturer's model number.
u_int16_t acuta4_info_cylinders (struct acuta_message *) - the number of cylinders on the disk / array.
char * acuta4_info_header (struct acuta_message *) - No explanation in the documentation.
u_int16_t acuta4_info_sectors (struct acuta_message *) - sectors per track (?).
u_int8_t acuta4_info_max_multiple_sectors (struct acuta_message *) - tracks per cylinder (?).
u_int8_t acuta4_info_udma_mode (struct acuta_message *) - UDMA mode configured.
u_int64_t acuta4_info_total_sectors (struct acuta_message *) - total sectors on the disk / array.