talos/pkg/provision/providers/qemu/controller.go
Utku Ozdemir fe04571527
fix: power on the machine on reboot request in qemu power api
IPMI powers on a machine when a PowerCycle command is sent, making a prior power on call unnecessary. We probably want to do the same thing in our API-based power implementation.

Signed-off-by: Utku Ozdemir <utku.ozdemir@siderolabs.com>
2024-12-11 13:09:17 +01:00

149 lines
2.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 qemu
import (
"sync"
"github.com/siderolabs/talos/pkg/provision/providers/vm"
)
// PowerState is current VM power state.
type PowerState string
// Virtual machine power state.
const (
PoweredOn PowerState = "on"
PoweredOff PowerState = "off"
)
// VMCommand is a translated VM command.
type VMCommand string
// Virtual machine commands.
const (
VMCommandStart VMCommand = "start"
VMCommandStop VMCommand = "stop"
)
// Controller supports IPMI-like machine control.
type Controller struct {
mu sync.Mutex
state PowerState
forcePXEBoot bool
commandsCh chan VMCommand
}
// NewController initializes controller in "powered on" state.
func NewController() *Controller {
return &Controller{
state: PoweredOn,
commandsCh: make(chan VMCommand),
}
}
// PowerOn implements vm.Controller interface.
func (c *Controller) PowerOn() error {
c.mu.Lock()
if c.state == PoweredOn {
c.mu.Unlock()
return nil
}
c.state = PoweredOn
c.mu.Unlock()
c.commandsCh <- VMCommandStart
return nil
}
// PowerOff implements vm.Controller interface.
func (c *Controller) PowerOff() error {
c.mu.Lock()
if c.state == PoweredOff {
c.mu.Unlock()
return nil
}
c.state = PoweredOff
c.mu.Unlock()
c.commandsCh <- VMCommandStop
return nil
}
// Reboot implements vm.Controller interface.
func (c *Controller) Reboot() error {
c.mu.Lock()
if c.state == PoweredOff {
c.state = PoweredOn
c.mu.Unlock()
c.commandsCh <- VMCommandStart
return nil
}
c.mu.Unlock()
c.commandsCh <- VMCommandStop
return nil
}
// PXEBootOnce implements vm.Controller interface.
func (c *Controller) PXEBootOnce() error {
c.mu.Lock()
defer c.mu.Unlock()
c.forcePXEBoot = true
return nil
}
// Status implements vm.Controller interface.
func (c *Controller) Status() vm.Status {
return vm.Status{
PoweredOn: c.PowerState() == PoweredOn,
}
}
// PowerState returns current power state.
func (c *Controller) PowerState() PowerState {
c.mu.Lock()
defer c.mu.Unlock()
return c.state
}
// ForcePXEBoot returns whether next boot should be PXE boot.
func (c *Controller) ForcePXEBoot() bool {
c.mu.Lock()
defer c.mu.Unlock()
if c.forcePXEBoot {
c.forcePXEBoot = false
return true
}
return false
}
// CommandsCh returns channel with commands.
func (c *Controller) CommandsCh() <-chan VMCommand {
return c.commandsCh
}