Skip to main content

Command Palette

Search for a command to run...

Controlling Server Hardware With Go

Using IPMI and Go to never leave the couch!

Published
3 min read
Controlling Server Hardware With Go
E

Meet the maestro behind the code, the architect of software solutions, and a burgeoning woodworking aficionado: your humble narrator. By day, I'm a Staff Software Engineer at noteable.io, where since September 2020, I've been constructing digital symphonies with Python, a love affair dating back to 2012. But when the screen glow dims and the keyboard clatter fades, you'll find me amidst the whirr of the saw and the scent of fresh-cut lumber, immersed in my latest woodworking project. It's my respite from the pixelated pandemonium, a testament to all good software engineers finding solace in tangible creations after the inevitable burnout. My haven is nestled near Ann Arbor, MI, where I share my life's joys and journeys with my wife, our discerning cat, Miru, and our spirited dog, Penny. Here's to the code we write, the wood we shape, and the stories we continue to carve.

Intelligent Platform Management Interface (IPMI) is built into most servers to allow remote management, generally for use when you're not in the same physical location of the server. In 2020, I purchased 4 used servers off of Craigslist to set up my own home lab. One of these servers runs a plex media server which hosts a variety of media that I can stream to my TV or even my phone when I'm away.

2020-12-16-033603369.jpg

My home lab is less than 100 steps from my couch and TV, where I'm writing this article at, and yet I decided that was too far to walk to turn my server on and off. Enter IPMI. I discovered my Supermicro server had 2 IP addresses, one I knew was used to connect via SSH and exposed the plex media server but the other was a mystery. This second IP address stayed online even when the server was turned off which lead me to investigate what was going on there. Visiting the IP address in the browser showed a login page and after entering some default credentials I discovered it was an IPMI.

image.png image.png

After seeing that I could turn my server on and off through a webpage, I decided that I didn't want to log in and deal with the ancient Java application that was running with many, many iframes. I decided to write a program to be able to do this from the command line and eventually integrate it into my own mobile app. Unsurprisingly, there was already a Go IPMI library written by VMware. After creating an IPMI connection, the code to execute a command against the server is less than 20 lines of code.

package iipmi

import (
    "github.com/cenkalti/backoff/v4"
    "github.com/vmware/goipmi"
)

func Execute(conn *ipmi.Connection, ctl ipmi.ChassisControl) error {
    client, err := ipmi.NewClient(conn)
    if err != nil {
        return err
    }
    if err := client.Open(); err != nil {
        return err
    }
    defer client.Close()

    return backoff.Retry(func() error { return client.Control(ctl) }, backoff.NewExponentialBackOff())
}

I added exponential backoff retry logic to help with spotty connections or IPMI being, well, IPMI. Setting up the IPMI connection is just as simple:

package cmd

import (
    "github.com/spf13/cobra"
    ipmi "github.com/vmware/goipmi"
    "ipmi-grpc/pkg/iipmi"
)

var startupCmd = &cobra.Command{
    Use: "startup",
    RunE: func(cmd *cobra.Command, args []string) error {
        conn := &ipmi.Connection{Interface: "lan"}
        conn.Path, _ = cmd.Flags().GetString("path")
        conn.Hostname, _ = cmd.Flags().GetString("hostname")
        conn.Port, _ = cmd.Flags().GetInt("port")
        conn.Username, _ = cmd.Flags().GetString("username")
        conn.Password, _ = cmd.Flags().GetString("password")

        return iipmi.Execute(conn, ipmi.ControlPowerUp)
    },
}

func init() {
    startupCmd.Flags().String("path", "", "IPMI path")
    startupCmd.Flags().String("hostname", "", "IPMI hostname")
    startupCmd.Flags().Int("port", 623, "IPMI port")
    startupCmd.Flags().String("username", "ADMIN", "IPMI username")
    startupCmd.Flags().String("password", "ADMIN", "IPMI password")

    _ = deviceIdCmd.MarkFlagRequired("hostname")

    rootCmd.AddCommand(startupCmd)
}

This is the cobra command to start up the server with a simple ./ipmi-grpc startup --hostname 192.168.37.113.

I used this as an excuse to write something in Go and learn more about IPMI. Hardware meeting software is one of the most interesting parts of programming to me. When I run this command and the fans start spinning in my office it brings a smile to my face knowing that I did that using code.