github.com/vmware/govmomi@v0.43.0/vmdk/disk_info.go (about) 1 /* 2 Copyright (c) 2024-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 vmdk 18 19 import ( 20 "context" 21 "fmt" 22 23 "github.com/vmware/govmomi/object" 24 "github.com/vmware/govmomi/vim25" 25 "github.com/vmware/govmomi/vim25/mo" 26 "github.com/vmware/govmomi/vim25/types" 27 ) 28 29 type VirtualDiskInfo struct { 30 CapacityInBytes int64 31 DeviceKey int32 32 FileName string 33 Size int64 34 UniqueSize int64 35 } 36 37 // GetVirtualDiskInfoByUUID returns information about a virtual disk identified 38 // by the provided UUID. This method is valid for the following backing types: 39 // 40 // - VirtualDiskFlatVer2BackingInfo 41 // - VirtualDiskSeSparseBackingInfo 42 // - VirtualDiskRawDiskMappingVer1BackingInfo 43 // - VirtualDiskSparseVer2BackingInfo 44 // - VirtualDiskRawDiskVer2BackingInfo 45 // 46 // These are the only backing types that have a UUID property for comparing the 47 // provided value. 48 func GetVirtualDiskInfoByUUID( 49 ctx context.Context, 50 client *vim25.Client, 51 mo mo.VirtualMachine, 52 fetchProperties bool, 53 diskUUID string) (VirtualDiskInfo, error) { 54 55 if diskUUID == "" { 56 return VirtualDiskInfo{}, fmt.Errorf("diskUUID is empty") 57 } 58 59 switch { 60 case fetchProperties, 61 mo.Config == nil, 62 mo.Config.Hardware.Device == nil, 63 mo.LayoutEx == nil, 64 mo.LayoutEx.Disk == nil, 65 mo.LayoutEx.File == nil: 66 67 if ctx == nil { 68 return VirtualDiskInfo{}, fmt.Errorf("ctx is nil") 69 } 70 if client == nil { 71 return VirtualDiskInfo{}, fmt.Errorf("client is nil") 72 } 73 74 obj := object.NewVirtualMachine(client, mo.Self) 75 76 if err := obj.Properties( 77 ctx, 78 mo.Self, 79 []string{"config", "layoutEx"}, 80 &mo); err != nil { 81 82 return VirtualDiskInfo{}, 83 fmt.Errorf("failed to retrieve properties: %w", err) 84 } 85 } 86 87 // Find the disk by UUID by inspecting all of the disk backing types that 88 // can have an associated UUID. 89 var ( 90 disk *types.VirtualDisk 91 fileName string 92 ) 93 for i := range mo.Config.Hardware.Device { 94 switch tvd := mo.Config.Hardware.Device[i].(type) { 95 case *types.VirtualDisk: 96 switch tb := tvd.Backing.(type) { 97 case *types.VirtualDiskFlatVer2BackingInfo: 98 if tb.Uuid == diskUUID { 99 disk = tvd 100 fileName = tb.FileName 101 } 102 case *types.VirtualDiskSeSparseBackingInfo: 103 if tb.Uuid == diskUUID { 104 disk = tvd 105 fileName = tb.FileName 106 } 107 case *types.VirtualDiskRawDiskMappingVer1BackingInfo: 108 if tb.Uuid == diskUUID { 109 disk = tvd 110 fileName = tb.FileName 111 } 112 case *types.VirtualDiskSparseVer2BackingInfo: 113 if tb.Uuid == diskUUID { 114 disk = tvd 115 fileName = tb.FileName 116 } 117 case *types.VirtualDiskRawDiskVer2BackingInfo: 118 if tb.Uuid == diskUUID { 119 disk = tvd 120 fileName = tb.DescriptorFileName 121 } 122 } 123 } 124 } 125 126 if disk == nil { 127 return VirtualDiskInfo{}, 128 fmt.Errorf("disk not found with uuid %q", diskUUID) 129 } 130 131 // Build a lookup table for determining if file key belongs to this disk 132 // chain. 133 diskFileKeys := map[int32]struct{}{} 134 for i := range mo.LayoutEx.Disk { 135 if d := mo.LayoutEx.Disk[i]; d.Key == disk.Key { 136 for j := range d.Chain { 137 for k := range d.Chain[j].FileKey { 138 diskFileKeys[d.Chain[j].FileKey[k]] = struct{}{} 139 } 140 } 141 } 142 } 143 144 // Sum the disk's total size and unique size. 145 var ( 146 size int64 147 uniqueSize int64 148 ) 149 for i := range mo.LayoutEx.File { 150 f := mo.LayoutEx.File[i] 151 if _, ok := diskFileKeys[f.Key]; ok { 152 size += f.Size 153 uniqueSize += f.UniqueSize 154 } 155 } 156 157 return VirtualDiskInfo{ 158 CapacityInBytes: disk.CapacityInBytes, 159 DeviceKey: disk.Key, 160 FileName: fileName, 161 Size: size, 162 UniqueSize: uniqueSize, 163 }, nil 164 }