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  }