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  }