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:
- libacuta4 - the core library to communicate with the device
- check_acuta4 - a nagios plugin that checks the status of the array, and reports on the disk health
- acuta4_info - a command line program that provides verbose details of the array
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
- libacuta4 - make less use of err() functions, instead let the caller decide what to do
- Fix the fan rpm - possibly truncated field? Maybe the spec expects me to multiply by 1000?
- Total sectors for the controller reports 0
- Priv-sep or privelege dropping, since we only need root to open the serial device, and nothing else.
- Makefile for linux / non-BSD systems - as needed / requested
- More testing - my unit is in production, so I can't hose it to better my software
- Better labels for some fields (disklabel provides better insight than the docs (max multiple sectors? what does that mean?)
- check_acuta4 should look at more fields, like temperature / fan sensors values
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:
- CMD_STATUS - queries for basic array status. This command returns the most commonly sought information. Raid level, status, disk status, etc.
- CMD_RAID_INFO - queries for metadata about the raid volume. Total volume size, total sectors, etc.
- CMD_CONTROLLER_INFO - queries for specified details on the controller. Currently on the serial number is returned by this command.
- CMD_DISK1_INFO - specific details about this disk. Total size, sectors, etc.
- CMD_DISK2_INFO
- CMD_DISK3_INFO
- CMD_DISK4_INFO
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.