Syncing Time Zone via IPMI

After using UTC time zone exclusively on my servers for a while, I decided to give local time a try for the next 6 months or so. In addition to "normal" shenanigans time zones bring, I got another interesting one - my IPMI servers required me to manually tell them whether daylight saving is in effect or not. What that meant is that, even with time zone set correctly, every daylight saving time change my server's BMC will be 1 hour off.

As all my servers were Supermicro (M11SDV-4CT-LN4F and A1SRi-2558F) I decided to use Supermicro's powerful IPMI to programmatically deal with that issue.

My thoughts were going in the following direction. As long as I keep script on my main server that will update time zone information (if needed) twice a day (at 02:00 and 03:00), it should be enough to keep me happy. As retrieving time zone information via IPMI is not something that's standardized, I contacted Supermicro's support to get the details. While they didn't really provide those details, they did point me toward their SMCIPMITool utility.

Unfortunately this didn't fully solve it for me as it didn't support FreeBSD. However, it did have debug mode (in set debug_level=1) and this really helped.

./SMCIPMITool admin password ipmi oem x10cfg ntp timezone

[ YOU -> BMC : 30 68 01 00 00 ]
[ YOU <- BMC : 00 01 2D 30 37 30 30 01 ]

With these response bytes it was easy enough to construct ipmitool raw bytes:

ipmitool -I lanplus -H -U admin -P password raw 0x30 0x68 0x01 0x00 0x00
01 2d 30 30 30 30 00

The first byte tells us if NTP is enabled or not, next 5 bytes tells time zone in ASCII (+0000), while the last byte says if daylight saving is on or not.

Using the same principle, it's easy enough to update IPMI:

ipmitool -I lanplus -H -U admin -P password raw 0x30 0x68 0x01 0x
01 0x00 0x01 0x2d 0x30 0x37 0x30 0x30 0x00

Trying to script this change is a bit tricky. There isn't really easy and fireproof method of determining if daylight savings is active. However, I decided to ignore that field and just set offset every time as that's really easy to determine (date +%z).

The final script was looking something like this:



CURR_STATE=`ipmitool -I lanplus -H $IP -U $USER -P $PASSWORD raw 0x30 0x68 0x01 0x00 0x00 | xargs | tr ' ' '\n' | awk '{printf " 0x" $1}' | xargs`
NEXT_STATE="0x01 `date +%z | hexdump -C | head -1 | cut -d' ' -f3-7 | tr ' ' '\n' | awk '{printf " 0x" $1}'| xargs` 0x00"

if [[ "$CURR_STATE" != "$NEXT_STATE" ]]; then
ipmitool -I lanplus -H $IP -U $USER -P $PASSWORD raw 0x30 0x68 0x01 0x01 0x00 $NEXT_STATE 2>/dev/null

Leave a Reply

Your email address will not be published. Required fields are marked *