137 lines
3.2 KiB
Go
137 lines
3.2 KiB
Go
package bmc
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path"
|
|
"strings"
|
|
"text/template"
|
|
|
|
"github.com/Masterminds/sprig/v3"
|
|
|
|
warewulfconf "github.com/warewulf/warewulf/internal/pkg/config"
|
|
"github.com/warewulf/warewulf/internal/pkg/node"
|
|
"github.com/warewulf/warewulf/internal/pkg/wwlog"
|
|
)
|
|
|
|
type Result struct {
|
|
err error
|
|
out string
|
|
}
|
|
|
|
type TemplateStruct struct {
|
|
node.IpmiConf
|
|
ShowOnly bool
|
|
Cmd string
|
|
result Result
|
|
}
|
|
|
|
func (tstruct *TemplateStruct) Result() (string, error) {
|
|
return tstruct.result.out, tstruct.result.err
|
|
}
|
|
|
|
func (tstruct *TemplateStruct) getCommand() (cmdStr string, err error) {
|
|
if tstruct.Template == "" {
|
|
return "", fmt.Errorf("no bmc template specified")
|
|
}
|
|
if !strings.HasPrefix(tstruct.Template, "/") {
|
|
conf := warewulfconf.Get()
|
|
tstruct.Template = path.Join(conf.Paths.Datadir, "warewulf/bmc", tstruct.Template)
|
|
}
|
|
fbuf, err := os.ReadFile(tstruct.Template)
|
|
if err != nil {
|
|
return "", fmt.Errorf("couldn't find the template which defines the bmc command: %s", err)
|
|
}
|
|
cmdTmpl, err := template.New("bmc command").Funcs(sprig.TxtFuncMap()).Parse(string(fbuf))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var tbuffer bytes.Buffer
|
|
err = cmdTmpl.Execute(&tbuffer, *tstruct)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
cmdStr = strings.TrimSpace(tbuffer.String())
|
|
wwlog.Debug("bmc command: %s", cmdStr)
|
|
return cmdStr, nil
|
|
|
|
}
|
|
|
|
func (tstruct *TemplateStruct) runCommand() ([]byte, error) {
|
|
cmdStr, err := tstruct.getCommand()
|
|
if err != nil {
|
|
return []byte{}, err
|
|
}
|
|
if tstruct.ShowOnly {
|
|
return []byte(cmdStr), nil
|
|
}
|
|
return exec.Command("/bin/sh", "-c", cmdStr).CombinedOutput()
|
|
}
|
|
|
|
func (tstruct *TemplateStruct) runInteractiveCommand() (err error) {
|
|
cmdStr, err := tstruct.getCommand()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
cmd := exec.Command("/bin/sh", "-c", cmdStr)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stdin = os.Stdin
|
|
cmd.Stderr = os.Stderr
|
|
return cmd.Run()
|
|
}
|
|
|
|
func (tstruct *TemplateStruct) InteractiveCommand(cmd string) error {
|
|
tstruct.Cmd = cmd
|
|
return tstruct.runInteractiveCommand()
|
|
}
|
|
|
|
func (tstruct *TemplateStruct) Command(cmd string) (string, error) {
|
|
tstruct.Cmd = cmd
|
|
out, err := tstruct.runCommand()
|
|
tstruct.result.out = strings.TrimSpace(string(out))
|
|
tstruct.result.err = err
|
|
return tstruct.result.out, tstruct.result.err
|
|
}
|
|
|
|
/*
|
|
Just define meta commands here, implementation is in the template
|
|
*/
|
|
|
|
func (tstruct *TemplateStruct) PowerOn() (string, error) {
|
|
return tstruct.Command("PowerOn")
|
|
}
|
|
|
|
func (tstruct *TemplateStruct) PowerOff() (string, error) {
|
|
return tstruct.Command("PowerOff")
|
|
}
|
|
|
|
func (tstruct *TemplateStruct) PowerCycle() (string, error) {
|
|
return tstruct.Command("PowerCycle")
|
|
}
|
|
|
|
func (tstruct *TemplateStruct) PowerReset() (string, error) {
|
|
return tstruct.Command("PowerReset")
|
|
}
|
|
|
|
func (tstruct *TemplateStruct) PowerSoft() (string, error) {
|
|
return tstruct.Command("PowerSoft")
|
|
}
|
|
|
|
func (tstruct *TemplateStruct) PowerStatus() (string, error) {
|
|
return tstruct.Command("PowerStatus")
|
|
}
|
|
|
|
func (tstruct *TemplateStruct) SDRList() (string, error) {
|
|
return tstruct.Command("SDRList")
|
|
}
|
|
|
|
func (tstruct *TemplateStruct) SensorList() (string, error) {
|
|
return tstruct.Command("SensorList")
|
|
}
|
|
|
|
func (tstruct *TemplateStruct) Console() error {
|
|
return tstruct.InteractiveCommand("Console")
|
|
}
|