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