As an intermezzo to all my OpenStack woes, I’ve built an out-of-band management device to control the OpenStack machine, based on a Raspberry Pi 2 I had laying around.
The problem I’m trying to solve is twofold: In order to conserve some energy consumption of the server, I’ve removed the graphics card, and I turn the machine off when I’m not using it. But that means that the times I do need it, I need to physically be at the machine and push the power button. When I’m not at home, I’m out of luck. Secondly removing the graphics card means that when I screw up the boot process of the machine (as I’ve done a couple of times when playing with the LVM partitions), I need to pull the machine out from under the desk, open it up, install the graphics card, attach screen and keyboard, debug and when done, undo it all again.
Normally the Core i7 CPU comes with a feature called vPro (link), which should allow remote access to basic functionality, even with the machine powered down (there is always a 5V standby available in a standard ATX power supply, which is used for USB, keyboard, network cards to allow a wake up of the machine via WoL/keyboard shortcut), but the BIOS on my motherboard doesn’t support this.
So I built my own: the Raspberry Pi will control a relay switch to simulate the power button being pushed, and it will connect to the server via serial connection (set up as a console) to be able to debug and fix issues in the grub bootloader, linux OS, network, etc…
The Raspberry Pi is powered via USB, directly connected to the motherboard on one of the connections meant for the front panel USB connector and card readers.
Hardware:
- Raspberry Pi 2: with Debian Jessie
- RSR232 to TTL, female serial convertor, based on the MAX3232
- 2 channel relay module for arduino
- DB9 to 10 pin header cable (those who’ve tried this before might have noticed already that this is exactly the wrong cable for the job)
- Pin header to USB (female) cable
- Pin header to pin header
Connecting all the hardware
I connect the serial convertor like this: TX is connected to GPIO14 on pin 8, RX is connected to GPIO15 on pin 10, VCC is connected to 3.3V on pin 1 and GND is connected to ground on pin 14.
The relay module is connected to ground on pin 9, VCC to 5V on pin 2 and I’m using GPIO4 on pin 7 to control IN1.
I also have a double pin header where I soldered all the rows together. This way I can plug in the cable to the front panel switch, the cable to the relay and the cable to the motherboard power button input, all in parallel. This way, either a connection made by the relay, or by the front panel power switch will turn on the computer.
Configuration on the Raspberry Pi:
- The GPIO serial is disabled by default, to enable it edit /boot/config.txt and add a line at the end:
enable_uart=1
- By default the Raspberry Pi is configured to have a console output on the serial interface. to disable the console:
$ sudo systemctl stop serial-getty@ttyAMA0.service
$ sudo systemctl disable serial-getty#ttyAMA0.service
- Remove the console from the kernel command line: edit the file /boot/cmdline.txt and remove the part “console=serial0,115200”
- Reboot for the changes to take effect
Information has been found here: Link.
Configuration on the server
The machine I’m using as an OpenStack server will need to be configured to use the serial output port as a console:
- Configure grub to use ttyS0 as console. For this edit /etc/default/grub and append or modify:
GRUB_CMDLINE_LINUX='console=tty0 console=ttyS0,19200n8'
GRUB_TERMINAL=serial
GRUB_SERIAL_COMMAND="serial --speed=19200 --unit=0 --word=8 --parity=no --stop=1"
update-grub
- List the working serial port in Linux
# setserial -g /dev/ttyS[0123]
sample output:
/dev/ttyS0, UART: 16550A, Port: 0x03f8, IRQ: 4
/dev/ttyS1, UART: unknown, Port: 0x02f8, IRQ: 3
/dev/ttyS2, UART: unknown, Port: 0x03e8, IRQ: 4
/dev/ttyS3, UART: unknown, Port: 0x02e8, IRQ: 3
This means the serial port is at /dev/ttyS0
- Start the serial-getty serial at /dev/ttyS0:
sudo systemctl enable serial-getty@ttyS0.service
sudo systemctl start serial-getty@ttyS0.service
Triggering power ON
The relay comes with three connections, making up two contacts which are triggered together when the relay is activated: one normal open (NO) and one (normal closed). I’m using the NO contact to simulate a power button press. However it is important to note that the input is stated to be active low, this means that a 0 will activate the relay and a 1 will deactivate it.
Controlling the GPIO pins is pretty easy on the command line:
- echo 4 > /sys/class/gpio/export
This will enable GPIO to enable that pin, by default the direction will be an input.
- echo out > /sys/class/gpio/gpio4/direction
This will set the GPIO to an output pin, default value will be 0. As I said before, since the input on the relay os active low, this will activate the relay! I tried several things to change this, setting the value to 1 before setting the direction is not possible, because the value is not writable when the GPIO is configured as an input.
- Wait for half a second, so that is would seem like the power button has been pressed.
- echo 1 > /sys/class/gpio/gpio4/value
This will deactivate the relay again, the server is now starting up.
Script:
#! /bin/bash
GPIO_NUM=4
# the relay to power on the server is controller bu gpio 4
echo ${GPIO_NUM} > /sys/class/gpio/export
sleep 0.5
# trigger the relay (note that the relay is active LOW, and the gpio will always be LOW when you set the direction to "out"
echo out > /sys/class/gpio/gpio4/direction
echo 0 > /sys/class/gpio/gpio${GPIO_NUM}/value
sleep 0.5
# release the relay
echo 1 > /sys/class/gpio/gpio${GPIO_NUM}/value
# cleanup
echo in > /sys/class/gpio/gpio${GPIO_NUM}/direction
echo ${GPIO_NUM} > /sys/class/gpio/unexport
Problems encountered during setting up the serial connection
It took a while to set up the serial connection. This was because the serial cable I ordered was of the wrong type. The proper pinout:
While in the cable I received it was something like 1-6-2-7-3-8-4-9-5. I had a spare DB-9 connector in my stash, and I soldered it on the correct way.
Also, connect the Rx of the convertor to the Rx pin on the Raspberry PI, and the Tx of the convertor to the Tx pin on the Pi… Some sources claim you need to cross the Tx and Rx, but in my case this wasn’t necessary.