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  }