talos/internal/app/init/shutdown.go
Andrew Rynhard 2e9a7ec0c5
feat: add power off functionality (#462)
Signed-off-by: Andrew Rynhard <andrew@andrewrynhard.com>
2019-03-24 20:21:41 -07:00

67 lines
1.5 KiB
Go

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package main
import (
"os"
"github.com/mdlayher/genetlink"
"github.com/mdlayher/netlink"
"github.com/pkg/errors"
"golang.org/x/sys/unix"
)
const (
// See https://github.com/torvalds/linux/blob/master/drivers/acpi/event.c
acpiGenlFamilyName = "acpi_event"
acpiGenlMcastGroupName = "acpi_mc_group"
)
func listenForPowerButton() (err error) {
// Get the acpi_event family.
genconn, err := genetlink.Dial(nil)
if err != nil {
return err
}
// nolint: errcheck
defer genconn.Close()
var f genetlink.Family
if f, err = genconn.GetFamily(acpiGenlFamilyName); os.IsNotExist(err) {
return errors.Wrap(err, acpiGenlFamilyName+" not available")
}
// Listen for ACPI event.
conn, err := netlink.Dial(unix.NETLINK_GENERIC, nil)
if err != nil {
return err
}
// nolint: errcheck
defer conn.Close()
var id uint32
for _, group := range f.Groups {
if group.Name == acpiGenlMcastGroupName {
id = group.ID
}
}
if err = conn.JoinGroup(id); err != nil {
return err
}
msgs, err := conn.Receive()
if err != nil {
return err
}
if len(msgs) > 0 {
// TODO(andrewrynhard): Stop all running containerd tasks.
// See http://man7.org/linux/man-pages/man2/reboot.2.html.
unix.Sync()
// nolint: errcheck
unix.Reboot(unix.LINUX_REBOOT_CMD_POWER_OFF)
}
return nil
}