github.com/vmware/govmomi@v0.43.0/toolbox/power.go (about) 1 /* 2 Copyright (c) 2017 VMware, Inc. All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package toolbox 18 19 import ( 20 "fmt" 21 "log" 22 "os/exec" 23 ) 24 25 // GuestOsState enum as defined in open-vm-tools/lib/include/vmware/guestrpc/powerops.h 26 const ( 27 _ = iota 28 powerStateHalt 29 powerStateReboot 30 powerStatePowerOn 31 powerStateResume 32 powerStateSuspend 33 ) 34 35 var ( 36 shutdown = "/sbin/shutdown" 37 ) 38 39 type PowerCommand struct { 40 Handler func() error 41 42 out *ChannelOut 43 state int 44 name string 45 } 46 47 type PowerCommandHandler struct { 48 Halt PowerCommand 49 Reboot PowerCommand 50 PowerOn PowerCommand 51 Resume PowerCommand 52 Suspend PowerCommand 53 } 54 55 func registerPowerCommandHandler(service *Service) *PowerCommandHandler { 56 handler := new(PowerCommandHandler) 57 58 handlers := map[string]struct { 59 cmd *PowerCommand 60 state int 61 }{ 62 "OS_Halt": {&handler.Halt, powerStateHalt}, 63 "OS_Reboot": {&handler.Reboot, powerStateReboot}, 64 "OS_PowerOn": {&handler.PowerOn, powerStatePowerOn}, 65 "OS_Resume": {&handler.Resume, powerStateResume}, 66 "OS_Suspend": {&handler.Suspend, powerStateSuspend}, 67 } 68 69 for name, h := range handlers { 70 *h.cmd = PowerCommand{ 71 name: name, 72 state: h.state, 73 out: service.out, 74 } 75 76 service.RegisterHandler(name, h.cmd.Dispatch) 77 } 78 79 return handler 80 } 81 82 func (c *PowerCommand) Dispatch([]byte) ([]byte, error) { 83 rc := rpciOK 84 85 log.Printf("dispatching power op %q", c.name) 86 87 if c.Handler == nil { 88 if c.state == powerStateHalt || c.state == powerStateReboot { 89 rc = rpciERR 90 } 91 } 92 93 msg := fmt.Sprintf("tools.os.statechange.status %s%d\x00", rc, c.state) 94 95 if _, err := c.out.Request([]byte(msg)); err != nil { 96 log.Printf("unable to send %q: %q", msg, err) 97 } 98 99 if c.Handler != nil { 100 if err := c.Handler(); err != nil { 101 log.Printf("%s: %s", c.name, err) 102 } 103 } 104 105 return nil, nil 106 } 107 108 func Halt() error { 109 log.Printf("Halting system...") 110 // #nosec: Subprocess launching with variable 111 return exec.Command(shutdown, "-h", "now").Run() 112 } 113 114 func Reboot() error { 115 log.Printf("Rebooting system...") 116 // #nosec: Subprocess launching with variable 117 return exec.Command(shutdown, "-r", "now").Run() 118 }