github.com/vmware/govmomi@v0.51.0/simulator/storage_resource_manager.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 simulator 6 7 import ( 8 "strconv" 9 "time" 10 11 "github.com/vmware/govmomi/object" 12 "github.com/vmware/govmomi/vim25/methods" 13 "github.com/vmware/govmomi/vim25/mo" 14 "github.com/vmware/govmomi/vim25/soap" 15 "github.com/vmware/govmomi/vim25/types" 16 ) 17 18 type StorageResourceManager struct { 19 mo.StorageResourceManager 20 } 21 22 func (m *StorageResourceManager) ConfigureStorageDrsForPodTask(ctx *Context, req *types.ConfigureStorageDrsForPod_Task) soap.HasFault { 23 task := CreateTask(m, "configureStorageDrsForPod", func(*Task) (types.AnyType, types.BaseMethodFault) { 24 cluster := ctx.Map.Get(req.Pod).(*StoragePod) 25 26 if s := req.Spec.PodConfigSpec; s != nil { 27 config := &cluster.PodStorageDrsEntry.StorageDrsConfig.PodConfig 28 29 if s.Enabled != nil { 30 config.Enabled = *s.Enabled 31 } 32 if s.DefaultVmBehavior != "" { 33 config.DefaultVmBehavior = s.DefaultVmBehavior 34 } 35 } 36 37 return nil, nil 38 }) 39 40 return &methods.ConfigureStorageDrsForPod_TaskBody{ 41 Res: &types.ConfigureStorageDrsForPod_TaskResponse{ 42 Returnval: task.Run(ctx), 43 }, 44 } 45 } 46 47 func (m *StorageResourceManager) pod(ctx *Context, ref *types.ManagedObjectReference) *StoragePod { 48 if ref == nil { 49 return nil 50 } 51 cluster := ctx.Map.Get(*ref).(*StoragePod) 52 config := &cluster.PodStorageDrsEntry.StorageDrsConfig.PodConfig 53 54 if !config.Enabled { 55 return nil 56 } 57 58 if len(cluster.ChildEntity) == 0 { 59 return nil 60 } 61 62 return cluster 63 } 64 65 func (m *StorageResourceManager) RecommendDatastores(ctx *Context, req *types.RecommendDatastores) soap.HasFault { 66 spec := req.StorageSpec.PodSelectionSpec 67 body := new(methods.RecommendDatastoresBody) 68 res := new(types.RecommendDatastoresResponse) 69 key := 0 70 invalid := func(prop string) soap.HasFault { 71 body.Fault_ = Fault("", &types.InvalidArgument{ 72 InvalidProperty: prop, 73 }) 74 return body 75 } 76 add := func(cluster *StoragePod, ds types.ManagedObjectReference) { 77 key++ 78 res.Returnval.Recommendations = append(res.Returnval.Recommendations, types.ClusterRecommendation{ 79 Key: strconv.Itoa(key), 80 Type: "V1", 81 Time: time.Now(), 82 Rating: 1, 83 Reason: "storagePlacement", 84 ReasonText: "Satisfy storage initial placement requests", 85 WarningText: "", 86 WarningDetails: (*types.LocalizableMessage)(nil), 87 Prerequisite: nil, 88 Action: []types.BaseClusterAction{ 89 &types.StoragePlacementAction{ 90 ClusterAction: types.ClusterAction{ 91 Type: "StoragePlacementV1", 92 Target: (*types.ManagedObjectReference)(nil), 93 }, 94 Vm: (*types.ManagedObjectReference)(nil), 95 RelocateSpec: types.VirtualMachineRelocateSpec{ 96 Service: (*types.ServiceLocator)(nil), 97 Folder: (*types.ManagedObjectReference)(nil), 98 Datastore: &ds, 99 DiskMoveType: "moveAllDiskBackingsAndAllowSharing", 100 Pool: (*types.ManagedObjectReference)(nil), 101 Host: (*types.ManagedObjectReference)(nil), 102 Disk: nil, 103 Transform: "", 104 DeviceChange: nil, 105 Profile: nil, 106 }, 107 Destination: ds, 108 SpaceUtilBefore: 5.00297212600708, 109 SpaceDemandBefore: 5.00297212600708, 110 SpaceUtilAfter: 5.16835880279541, 111 SpaceDemandAfter: 5.894514083862305, 112 IoLatencyBefore: 0, 113 }, 114 }, 115 Target: &cluster.Self, 116 }) 117 } 118 119 var devices object.VirtualDeviceList 120 121 switch types.StoragePlacementSpecPlacementType(req.StorageSpec.Type) { 122 case types.StoragePlacementSpecPlacementTypeCreate: 123 if req.StorageSpec.ResourcePool == nil { 124 return invalid("resourcePool") 125 } 126 if req.StorageSpec.ConfigSpec == nil { 127 return invalid("configSpec") 128 } 129 for _, d := range req.StorageSpec.ConfigSpec.DeviceChange { 130 devices = append(devices, d.GetVirtualDeviceConfigSpec().Device) 131 } 132 cluster := m.pod(ctx, spec.StoragePod) 133 if cluster == nil { 134 if f := req.StorageSpec.ConfigSpec.Files; f == nil || f.VmPathName == "" { 135 return invalid("configSpec.files") 136 } 137 } 138 case types.StoragePlacementSpecPlacementTypeClone: 139 if req.StorageSpec.Folder == nil { 140 return invalid("folder") 141 } 142 if req.StorageSpec.Vm == nil { 143 return invalid("vm") 144 } 145 if req.StorageSpec.CloneName == "" { 146 return invalid("cloneName") 147 } 148 if req.StorageSpec.CloneSpec == nil { 149 return invalid("cloneSpec") 150 } 151 } 152 153 for _, placement := range spec.InitialVmConfig { 154 cluster := m.pod(ctx, &placement.StoragePod) 155 if cluster == nil { 156 return invalid("podSelectionSpec.storagePod") 157 } 158 159 for _, disk := range placement.Disk { 160 if devices.FindByKey(disk.DiskId) == nil { 161 return invalid("podSelectionSpec.initialVmConfig.disk.fileBacking") 162 } 163 } 164 165 for _, ds := range cluster.ChildEntity { 166 add(cluster, ds) 167 } 168 } 169 170 body.Res = res 171 return body 172 }