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  }