github.com/vmware/govmomi@v0.43.0/govc/vm/migrate.go (about) 1 /* 2 Copyright (c) 2016-2024 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 vm 18 19 import ( 20 "context" 21 "flag" 22 "fmt" 23 24 "github.com/vmware/govmomi/govc/cli" 25 "github.com/vmware/govmomi/govc/flags" 26 "github.com/vmware/govmomi/object" 27 "github.com/vmware/govmomi/vim25/types" 28 ) 29 30 type migrate struct { 31 *flags.FolderFlag 32 *flags.ResourcePoolFlag 33 *flags.HostSystemFlag 34 *flags.DatastoreFlag 35 *flags.NetworkFlag 36 *flags.VirtualMachineFlag 37 38 priority types.VirtualMachineMovePriority 39 spec types.VirtualMachineRelocateSpec 40 } 41 42 func init() { 43 cli.Register("vm.migrate", &migrate{}) 44 } 45 46 func (cmd *migrate) Register(ctx context.Context, f *flag.FlagSet) { 47 cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx) 48 cmd.FolderFlag.Register(ctx, f) 49 50 cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx) 51 cmd.VirtualMachineFlag.Register(ctx, f) 52 53 cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx) 54 cmd.ResourcePoolFlag.Register(ctx, f) 55 56 cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx) 57 cmd.HostSystemFlag.Register(ctx, f) 58 59 cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx) 60 cmd.DatastoreFlag.Register(ctx, f) 61 62 cmd.NetworkFlag, ctx = flags.NewNetworkFlag(ctx) 63 cmd.NetworkFlag.Register(ctx, f) 64 65 f.StringVar((*string)(&cmd.priority), "priority", string(types.VirtualMachineMovePriorityDefaultPriority), "The task priority") 66 } 67 68 func (cmd *migrate) Process(ctx context.Context) error { 69 if err := cmd.FolderFlag.Process(ctx); err != nil { 70 return err 71 } 72 if err := cmd.VirtualMachineFlag.Process(ctx); err != nil { 73 return err 74 } 75 if err := cmd.ResourcePoolFlag.Process(ctx); err != nil { 76 return err 77 } 78 if err := cmd.HostSystemFlag.Process(ctx); err != nil { 79 return err 80 } 81 if err := cmd.DatastoreFlag.Process(ctx); err != nil { 82 return err 83 } 84 if err := cmd.NetworkFlag.Process(ctx); err != nil { 85 return err 86 } 87 88 return nil 89 } 90 91 func (cmd *migrate) Usage() string { 92 return "VM..." 93 } 94 95 func (cmd *migrate) Description() string { 96 return `Migrates VM to a specific resource pool, host or datastore. 97 98 Examples: 99 govc vm.migrate -host another-host vm-1 vm-2 vm-3 100 govc vm.migrate -pool another-pool vm-1 vm-2 vm-3 101 govc vm.migrate -ds another-ds vm-1 vm-2 vm-3` 102 } 103 104 func (cmd *migrate) relocate(ctx context.Context, vm *object.VirtualMachine) error { 105 spec := cmd.spec 106 107 if cmd.NetworkFlag.IsSet() { 108 dev, err := cmd.NetworkFlag.Device() 109 if err != nil { 110 return err 111 } 112 113 devices, err := vm.Device(ctx) 114 if err != nil { 115 return err 116 } 117 118 net := devices.SelectByType((*types.VirtualEthernetCard)(nil)) 119 if len(net) != 1 { 120 return fmt.Errorf("-net specified, but %s has %d nics", vm.Name(), len(net)) 121 } 122 cmd.NetworkFlag.Change(net[0], dev) 123 124 spec.DeviceChange = append(spec.DeviceChange, &types.VirtualDeviceConfigSpec{ 125 Device: net[0], 126 Operation: types.VirtualDeviceConfigSpecOperationEdit, 127 }) 128 } 129 130 if cmd.VirtualMachineFlag.Spec { 131 return cmd.VirtualMachineFlag.WriteAny(spec) 132 } 133 134 task, err := vm.Relocate(ctx, spec, cmd.priority) 135 if err != nil { 136 return err 137 } 138 139 logger := cmd.DatastoreFlag.ProgressLogger(fmt.Sprintf("migrating %s... ", vm.Reference())) 140 _, err = task.WaitForResult(ctx, logger) 141 if err != nil { 142 return err 143 } 144 145 logger.Wait() 146 147 return nil 148 } 149 150 func (cmd *migrate) Run(ctx context.Context, f *flag.FlagSet) error { 151 vms, err := cmd.VirtualMachineFlag.VirtualMachines(f.Args()) 152 if err != nil { 153 return err 154 } 155 156 folder, err := cmd.FolderIfSpecified() 157 if err != nil { 158 return err 159 } 160 161 if folder != nil { 162 ref := folder.Reference() 163 cmd.spec.Folder = &ref 164 } 165 166 host, err := cmd.HostSystemFlag.HostSystemIfSpecified() 167 if err != nil { 168 return err 169 } 170 171 if host != nil { 172 ref := host.Reference() 173 cmd.spec.Host = &ref 174 } 175 176 pool, err := cmd.ResourcePoolFlag.ResourcePoolIfSpecified() 177 if err != nil { 178 return err 179 } 180 181 if pool == nil && host != nil { 182 pool, err = host.ResourcePool(ctx) 183 if err != nil { 184 return err 185 } 186 } 187 188 if pool != nil { 189 ref := pool.Reference() 190 cmd.spec.Pool = &ref 191 } 192 193 ds, err := cmd.DatastoreFlag.DatastoreIfSpecified() 194 if err != nil { 195 return err 196 } 197 198 if ds != nil { 199 ref := ds.Reference() 200 cmd.spec.Datastore = &ref 201 } 202 203 for _, vm := range vms { 204 err = cmd.relocate(ctx, vm) 205 if err != nil { 206 return err 207 } 208 } 209 210 return nil 211 }