github.com/vmware/govmomi@v0.51.0/toolbox/power.go (about) 1 // © Broadcom. All Rights Reserved. 2 // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 3 // SPDX-License-Identifier: Apache-2.0 4 5 package toolbox 6 7 import ( 8 "fmt" 9 "log" 10 "os/exec" 11 ) 12 13 // GuestOsState enum as defined in open-vm-tools/lib/include/vmware/guestrpc/powerops.h 14 const ( 15 _ = iota 16 powerStateHalt 17 powerStateReboot 18 powerStatePowerOn 19 powerStateResume 20 powerStateSuspend 21 ) 22 23 var ( 24 shutdown = "/sbin/shutdown" 25 ) 26 27 type PowerCommand struct { 28 Handler func() error 29 30 out *ChannelOut 31 state int 32 name string 33 } 34 35 type PowerCommandHandler struct { 36 Halt PowerCommand 37 Reboot PowerCommand 38 PowerOn PowerCommand 39 Resume PowerCommand 40 Suspend PowerCommand 41 } 42 43 func registerPowerCommandHandler(service *Service) *PowerCommandHandler { 44 handler := new(PowerCommandHandler) 45 46 handlers := map[string]struct { 47 cmd *PowerCommand 48 state int 49 }{ 50 "OS_Halt": {&handler.Halt, powerStateHalt}, 51 "OS_Reboot": {&handler.Reboot, powerStateReboot}, 52 "OS_PowerOn": {&handler.PowerOn, powerStatePowerOn}, 53 "OS_Resume": {&handler.Resume, powerStateResume}, 54 "OS_Suspend": {&handler.Suspend, powerStateSuspend}, 55 } 56 57 for name, h := range handlers { 58 *h.cmd = PowerCommand{ 59 name: name, 60 state: h.state, 61 out: service.out, 62 } 63 64 service.RegisterHandler(name, h.cmd.Dispatch) 65 } 66 67 return handler 68 } 69 70 func (c *PowerCommand) Dispatch([]byte) ([]byte, error) { 71 rc := rpciOK 72 73 log.Printf("dispatching power op %q", c.name) 74 75 if c.Handler == nil { 76 if c.state == powerStateHalt || c.state == powerStateReboot { 77 rc = rpciERR 78 } 79 } 80 81 msg := fmt.Sprintf("tools.os.statechange.status %s%d\x00", rc, c.state) 82 83 if _, err := c.out.Request([]byte(msg)); err != nil { 84 log.Printf("unable to send %q: %q", msg, err) 85 } 86 87 if c.Handler != nil { 88 if err := c.Handler(); err != nil { 89 log.Printf("%s: %s", c.name, err) 90 } 91 } 92 93 return nil, nil 94 } 95 96 func Halt() error { 97 log.Printf("Halting system...") 98 // #nosec: Subprocess launching with variable 99 return exec.Command(shutdown, "-h", "now").Run() 100 } 101 102 func Reboot() error { 103 log.Printf("Rebooting system...") 104 // #nosec: Subprocess launching with variable 105 return exec.Command(shutdown, "-r", "now").Run() 106 }