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 }