github.com/vmware/govmomi@v0.51.0/cli/vm/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 vm 6 7 import ( 8 "context" 9 "flag" 10 "fmt" 11 12 "github.com/vmware/govmomi/cli" 13 "github.com/vmware/govmomi/cli/flags" 14 "github.com/vmware/govmomi/fault" 15 "github.com/vmware/govmomi/object" 16 "github.com/vmware/govmomi/vim25/types" 17 ) 18 19 type power struct { 20 *flags.ClientFlag 21 *flags.SearchFlag 22 23 On bool 24 Off bool 25 Reset bool 26 Reboot bool 27 Shutdown bool 28 Standby bool 29 Suspend bool 30 Force bool 31 Multi bool 32 Wait bool 33 } 34 35 func init() { 36 cli.Register("vm.power", &power{}) 37 } 38 39 func (cmd *power) Register(ctx context.Context, f *flag.FlagSet) { 40 cmd.ClientFlag, ctx = flags.NewClientFlag(ctx) 41 cmd.ClientFlag.Register(ctx, f) 42 43 cmd.SearchFlag, ctx = flags.NewSearchFlag(ctx, flags.SearchVirtualMachines) 44 cmd.SearchFlag.Register(ctx, f) 45 46 f.BoolVar(&cmd.On, "on", false, "Power on") 47 f.BoolVar(&cmd.Off, "off", false, "Power off") 48 f.BoolVar(&cmd.Reset, "reset", false, "Power reset") 49 f.BoolVar(&cmd.Suspend, "suspend", false, "Power suspend") 50 f.BoolVar(&cmd.Reboot, "r", false, "Reboot guest") 51 f.BoolVar(&cmd.Shutdown, "s", false, "Shutdown guest") 52 f.BoolVar(&cmd.Standby, "standby", false, "Standby guest") 53 f.BoolVar(&cmd.Force, "force", false, "Force (ignore state error and hard shutdown/reboot if tools unavailable)") 54 f.BoolVar(&cmd.Multi, "M", false, "Use Datacenter.PowerOnMultiVM method instead of VirtualMachine.PowerOnVM") 55 f.BoolVar(&cmd.Wait, "wait", true, "Wait for the operation to complete") 56 } 57 58 func (cmd *power) Usage() string { 59 return "NAME..." 60 } 61 62 func (cmd *power) Description() string { 63 return `Invoke VM power operations. 64 65 Examples: 66 govc vm.power -on VM1 VM2 VM3 67 govc vm.power -on -M VM1 VM2 VM3 68 govc vm.power -off -force VM1` 69 } 70 71 func (cmd *power) Process(ctx context.Context) error { 72 if err := cmd.ClientFlag.Process(ctx); err != nil { 73 return err 74 } 75 if err := cmd.SearchFlag.Process(ctx); err != nil { 76 return err 77 } 78 opts := []bool{cmd.On, cmd.Off, cmd.Reset, cmd.Suspend, cmd.Reboot, cmd.Shutdown, cmd.Standby} 79 selected := false 80 81 for _, opt := range opts { 82 if opt { 83 if selected { 84 return flag.ErrHelp 85 } 86 selected = opt 87 } 88 } 89 90 if !selected { 91 return flag.ErrHelp 92 } 93 94 return nil 95 } 96 97 func isToolsUnavailable(err error) bool { 98 return fault.Is(err, &types.ToolsUnavailable{}) 99 } 100 101 // this is annoying, but the likely use cases for Datacenter.PowerOnVM outside of this command would 102 // use []types.ManagedObjectReference via ContainerView or field such as ResourcePool.Vm rather than the Finder. 103 func vmReferences(vms []*object.VirtualMachine) []types.ManagedObjectReference { 104 refs := make([]types.ManagedObjectReference, len(vms)) 105 for i, vm := range vms { 106 refs[i] = vm.Reference() 107 } 108 return refs 109 } 110 111 func (cmd *power) Run(ctx context.Context, f *flag.FlagSet) error { 112 vms, err := cmd.VirtualMachines(f.Args()) 113 if err != nil { 114 return err 115 } 116 117 if cmd.On && cmd.Multi { 118 dc, derr := cmd.Datacenter() 119 if derr != nil { 120 return derr 121 } 122 123 task, derr := dc.PowerOnVM(ctx, vmReferences(vms)) 124 if derr != nil { 125 return derr 126 } 127 128 msg := fmt.Sprintf("Powering on %d VMs...", len(vms)) 129 if task == nil { 130 // running against ESX 131 fmt.Fprintf(cmd, "%s OK\n", msg) 132 return nil 133 } 134 135 if cmd.Wait { 136 logger := cmd.ProgressLogger(msg) 137 defer logger.Wait() 138 139 _, err = task.WaitForResult(ctx, logger) 140 return err 141 } 142 } 143 144 for _, vm := range vms { 145 var task *object.Task 146 147 switch { 148 case cmd.On: 149 fmt.Fprintf(cmd, "Powering on %s... ", vm.Reference()) 150 task, err = vm.PowerOn(ctx) 151 case cmd.Off: 152 fmt.Fprintf(cmd, "Powering off %s... ", vm.Reference()) 153 task, err = vm.PowerOff(ctx) 154 case cmd.Reset: 155 fmt.Fprintf(cmd, "Reset %s... ", vm.Reference()) 156 task, err = vm.Reset(ctx) 157 case cmd.Suspend: 158 fmt.Fprintf(cmd, "Suspend %s... ", vm.Reference()) 159 task, err = vm.Suspend(ctx) 160 case cmd.Reboot: 161 fmt.Fprintf(cmd, "Reboot guest %s... ", vm.Reference()) 162 err = vm.RebootGuest(ctx) 163 164 if err != nil && cmd.Force && isToolsUnavailable(err) { 165 task, err = vm.Reset(ctx) 166 } 167 case cmd.Shutdown: 168 fmt.Fprintf(cmd, "Shutdown guest %s... ", vm.Reference()) 169 err = vm.ShutdownGuest(ctx) 170 171 if err != nil && cmd.Force && isToolsUnavailable(err) { 172 task, err = vm.PowerOff(ctx) 173 } 174 case cmd.Standby: 175 fmt.Fprintf(cmd, "Standby guest %s... ", vm.Reference()) 176 err = vm.StandbyGuest(ctx) 177 178 if err != nil && cmd.Force && isToolsUnavailable(err) { 179 task, err = vm.Suspend(ctx) 180 } 181 } 182 183 if err != nil { 184 return err 185 } 186 187 if cmd.Wait && task != nil { 188 err = task.Wait(ctx) 189 } 190 if err == nil { 191 fmt.Fprintf(cmd, "OK\n") 192 continue 193 } 194 195 if cmd.Force { 196 fmt.Fprintf(cmd, "Error: %s\n", err) 197 continue 198 } 199 200 return err 201 } 202 203 return nil 204 }