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