github.com/vmware/govmomi@v0.51.0/cli/vm/disk/change.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 disk
     6  
     7  import (
     8  	"context"
     9  	"errors"
    10  	"flag"
    11  	"fmt"
    12  	"strings"
    13  
    14  	"github.com/vmware/govmomi/cli"
    15  	"github.com/vmware/govmomi/cli/flags"
    16  	"github.com/vmware/govmomi/object"
    17  	"github.com/vmware/govmomi/units"
    18  	"github.com/vmware/govmomi/vim25/types"
    19  )
    20  
    21  type change struct {
    22  	*flags.VirtualMachineFlag
    23  
    24  	name     string
    25  	key      int
    26  	label    string
    27  	filePath string
    28  	sharing  string
    29  
    30  	bytes units.ByteSize
    31  	mode  string
    32  
    33  	// 	SIOC
    34  	limit *int64
    35  }
    36  
    37  func init() {
    38  	cli.Register("vm.disk.change", &change{})
    39  }
    40  
    41  func (cmd *change) Description() string {
    42  	return `Change some properties of a VM's DISK
    43  
    44  In particular, you can change the DISK mode, and the size (as long as it is bigger)
    45  
    46  Examples:
    47    govc vm.disk.change -vm VM -disk.key 2001 -size 10G
    48    govc vm.disk.change -vm VM -disk.label "BDD disk" -size 10G
    49    govc vm.disk.change -vm VM -disk.name "hard-1000-0" -size 12G
    50    govc vm.disk.change -vm VM -disk.filePath "[DS] VM/VM-1.vmdk" -mode nonpersistent`
    51  }
    52  
    53  func (cmd *change) Register(ctx context.Context, f *flag.FlagSet) {
    54  	cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
    55  	cmd.VirtualMachineFlag.Register(ctx, f)
    56  	err := (&cmd.bytes).Set("0G")
    57  	if err != nil {
    58  		panic(err)
    59  	}
    60  	f.Var(&cmd.bytes, "size", "New disk size")
    61  	f.StringVar(&cmd.name, "disk.name", "", "Disk name")
    62  	f.StringVar(&cmd.label, "disk.label", "", "Disk label")
    63  	f.StringVar(&cmd.filePath, "disk.filePath", "", "Disk file name")
    64  	f.IntVar(&cmd.key, "disk.key", 0, "Disk unique key")
    65  	f.StringVar(&cmd.mode, "mode", "", fmt.Sprintf("Disk mode (%s)", strings.Join(vdmTypes, "|")))
    66  	f.StringVar(&cmd.sharing, "sharing", "", fmt.Sprintf("Sharing (%s)", strings.Join(sharing, "|")))
    67  	f.Var(flags.NewOptionalInt64(&cmd.limit), "disk.io.limit", "Disk storage IO per seconds limit (-1 for unlimited)")
    68  }
    69  
    70  func (cmd *change) Process(ctx context.Context) error {
    71  	if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
    72  		return err
    73  	}
    74  	return nil
    75  }
    76  
    77  func (cmd *change) FindDisk(ctx context.Context, list object.VirtualDeviceList) (*types.VirtualDisk, error) {
    78  	var disks []*types.VirtualDisk
    79  	for _, device := range list {
    80  		switch md := device.(type) {
    81  		case *types.VirtualDisk:
    82  			if cmd.CheckDiskProperties(ctx, list.Name(device), md) {
    83  				disks = append(disks, md)
    84  			}
    85  		default:
    86  			continue
    87  		}
    88  	}
    89  
    90  	switch len(disks) {
    91  	case 0:
    92  		return nil, errors.New("no disk found using the given values")
    93  	case 1:
    94  		return disks[0], nil
    95  	}
    96  	return nil, errors.New("the given disk values match multiple disks")
    97  }
    98  
    99  func (cmd *change) CheckDiskProperties(ctx context.Context, name string, disk *types.VirtualDisk) bool {
   100  	switch {
   101  	case cmd.key != 0 && disk.Key != int32(cmd.key):
   102  		fallthrough
   103  	case cmd.name != "" && name != cmd.name:
   104  		fallthrough
   105  	case cmd.label != "" && disk.DeviceInfo.GetDescription().Label != cmd.label:
   106  		return false
   107  	case cmd.filePath != "":
   108  		if b, ok := disk.Backing.(types.BaseVirtualDeviceFileBackingInfo); ok {
   109  			if b.GetVirtualDeviceFileBackingInfo().FileName != cmd.filePath {
   110  				return false
   111  			}
   112  		}
   113  	}
   114  	return true
   115  }
   116  
   117  func (cmd *change) setMode(mode *string) {
   118  	if cmd.mode != "" {
   119  		*mode = cmd.mode
   120  	}
   121  }
   122  
   123  func (cmd *change) Run(ctx context.Context, f *flag.FlagSet) error {
   124  	vm, err := cmd.VirtualMachine()
   125  	if err != nil {
   126  		return err
   127  	}
   128  
   129  	if vm == nil {
   130  		return flag.ErrHelp
   131  	}
   132  
   133  	devices, err := vm.Device(ctx)
   134  	if err != nil {
   135  		return err
   136  	}
   137  
   138  	editdisk, err := cmd.FindDisk(ctx, devices)
   139  	if err != nil {
   140  		return err
   141  	}
   142  
   143  	if int64(cmd.bytes) != 0 {
   144  		editdisk.CapacityInBytes = int64(cmd.bytes)
   145  	}
   146  
   147  	if editdisk.StorageIOAllocation == nil {
   148  		editdisk.StorageIOAllocation = new(types.StorageIOAllocationInfo)
   149  	}
   150  	editdisk.StorageIOAllocation.Limit = cmd.limit
   151  
   152  	switch backing := editdisk.Backing.(type) {
   153  	case *types.VirtualDiskFlatVer2BackingInfo:
   154  		backing.Sharing = cmd.sharing
   155  		cmd.setMode(&backing.DiskMode)
   156  	case *types.VirtualDiskSeSparseBackingInfo:
   157  		cmd.setMode(&backing.DiskMode)
   158  	}
   159  
   160  	spec := types.VirtualMachineConfigSpec{}
   161  
   162  	config := &types.VirtualDeviceConfigSpec{
   163  		Device:    editdisk,
   164  		Operation: types.VirtualDeviceConfigSpecOperationEdit,
   165  	}
   166  
   167  	config.FileOperation = ""
   168  
   169  	spec.DeviceChange = append(spec.DeviceChange, config)
   170  
   171  	task, err := vm.Reconfigure(ctx, spec)
   172  	if err != nil {
   173  		return err
   174  	}
   175  
   176  	err = task.Wait(ctx)
   177  	if err != nil {
   178  		return fmt.Errorf("error resizing main disk\nLogged Item:  %s", err)
   179  	}
   180  	return nil
   181  }