github.com/vmware/govmomi@v0.51.0/simulator/cluster_compute_resource_test.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 "context" 9 "path" 10 "strings" 11 "testing" 12 13 "github.com/stretchr/testify/require" 14 15 "github.com/vmware/govmomi" 16 "github.com/vmware/govmomi/find" 17 "github.com/vmware/govmomi/object" 18 "github.com/vmware/govmomi/simulator/esx" 19 "github.com/vmware/govmomi/simulator/vpx" 20 "github.com/vmware/govmomi/vim25" 21 "github.com/vmware/govmomi/vim25/types" 22 ) 23 24 func TestClusterESX(t *testing.T) { 25 content := esx.ServiceContent 26 s := New(NewServiceInstance(NewContext(), content, esx.RootFolder)) 27 28 ts := s.NewServer() 29 defer ts.Close() 30 31 ctx := context.Background() 32 c, err := govmomi.NewClient(ctx, ts.URL, true) 33 if err != nil { 34 t.Fatal(err) 35 } 36 37 dc := object.NewDatacenter(c.Client, esx.Datacenter.Reference()) 38 39 folders, err := dc.Folders(ctx) 40 if err != nil { 41 t.Fatal(err) 42 } 43 44 _, err = folders.HostFolder.CreateCluster(ctx, "cluster1", types.ClusterConfigSpecEx{}) 45 if err == nil { 46 t.Fatal("expected error") 47 } 48 } 49 50 func TestClusterVC(t *testing.T) { 51 content := vpx.ServiceContent 52 s := New(NewServiceInstance(NewContext(), content, vpx.RootFolder)) 53 54 ts := s.NewServer() 55 defer ts.Close() 56 57 ctx := context.Background() 58 c, err := govmomi.NewClient(ctx, ts.URL, true) 59 if err != nil { 60 t.Fatal(err) 61 } 62 63 f := object.NewRootFolder(c.Client) 64 65 dc, err := f.CreateDatacenter(ctx, "foo") 66 if err != nil { 67 t.Error(err) 68 } 69 70 folders, err := dc.Folders(ctx) 71 if err != nil { 72 t.Fatal(err) 73 } 74 75 cluster, err := folders.HostFolder.CreateCluster(ctx, "cluster1", types.ClusterConfigSpecEx{}) 76 if err != nil { 77 t.Fatal(err) 78 } 79 80 // Enable DRS and HA for the cluster 81 clusterSpec := types.ClusterConfigSpecEx{ 82 DrsConfig: &types.ClusterDrsConfigInfo{ 83 Enabled: types.NewBool(true), 84 DefaultVmBehavior: types.DrsBehaviorFullyAutomated, // Set DRS to fully automated 85 }, 86 DasConfig: &types.ClusterDasConfigInfo{ 87 Enabled: types.NewBool(true), 88 }, 89 } 90 91 task, err := cluster.Reconfigure(ctx, &clusterSpec, true) 92 require.NoError(t, err) 93 err = task.Wait(ctx) 94 require.NoError(t, err) 95 96 // Check if DRS and HA is set 97 98 finder := find.NewFinder(c.Client, false).SetDatacenter(dc) 99 pathname := path.Join(dc.InventoryPath, "host", "cluster1") 100 clusterComputeResource, err := finder.ClusterComputeResource(ctx, pathname) 101 require.NoError(t, err) 102 clusterComputeInfo, err := clusterComputeResource.Configuration(ctx) 103 require.NoError(t, err) 104 require.NotNil(t, clusterComputeInfo.DrsConfig.Enabled) 105 require.NotNil(t, clusterComputeInfo.DasConfig.Enabled) 106 require.True(t, *clusterComputeInfo.DrsConfig.Enabled) 107 require.True(t, *clusterComputeInfo.DasConfig.Enabled) 108 require.True(t, clusterComputeInfo.DrsConfig.DefaultVmBehavior == types.DrsBehaviorFullyAutomated) 109 _, err = folders.HostFolder.CreateCluster(ctx, "cluster1", types.ClusterConfigSpecEx{}) 110 if err == nil { 111 t.Error("expected DuplicateName error") 112 } 113 114 spec := types.HostConnectSpec{} 115 116 for _, fail := range []bool{true, false} { 117 task, err := cluster.AddHost(ctx, spec, true, nil, nil) 118 if err != nil { 119 t.Fatal(err) 120 } 121 122 _, err = task.WaitForResult(ctx, nil) 123 124 if fail { 125 if err == nil { 126 t.Error("expected error") 127 } 128 spec.HostName = "localhost" 129 } else { 130 if err != nil { 131 t.Error(err) 132 } 133 } 134 } 135 } 136 137 func TestPlaceVmReconfigure(t *testing.T) { 138 tests := []struct { 139 name string 140 configSpec *types.VirtualMachineConfigSpec 141 placementType types.PlacementSpecPlacementType 142 expectedErr string 143 }{ 144 { 145 "unsupported placement type", 146 nil, 147 types.PlacementSpecPlacementType("unsupported"), 148 "NotSupported", 149 }, 150 { 151 "create", 152 nil, 153 types.PlacementSpecPlacementTypeCreate, 154 "", 155 }, 156 { 157 "reconfigure with nil config spec", 158 nil, 159 types.PlacementSpecPlacementTypeReconfigure, 160 "InvalidArgument", 161 }, 162 { 163 "reconfigure with an empty config spec", 164 &types.VirtualMachineConfigSpec{}, 165 types.PlacementSpecPlacementTypeReconfigure, 166 "", 167 }, 168 } 169 170 for _, test := range tests { 171 test := test // assign to local var since loop var is reused 172 Test(func(ctx context.Context, c *vim25.Client) { 173 // Test env setup. 174 finder := find.NewFinder(c, true) 175 datacenter, err := finder.DefaultDatacenter(ctx) 176 if err != nil { 177 t.Fatalf("failed to get default datacenter: %v", err) 178 } 179 finder.SetDatacenter(datacenter) 180 vmMoRef := Map(ctx).Any("VirtualMachine").(*VirtualMachine).Reference() 181 clusterMoRef := Map(ctx).Any("ClusterComputeResource").(*ClusterComputeResource).Reference() 182 clusterObj := object.NewClusterComputeResource(c, clusterMoRef) 183 184 // PlaceVm. 185 placementSpec := types.PlacementSpec{ 186 Vm: &vmMoRef, 187 ConfigSpec: test.configSpec, 188 PlacementType: string(test.placementType), 189 } 190 _, err = clusterObj.PlaceVm(ctx, placementSpec) 191 if err != nil && !strings.Contains(err.Error(), test.expectedErr) { 192 t.Fatalf("expected error %q, got %v", test.expectedErr, err) 193 } 194 }) 195 } 196 } 197 198 func TestPlaceVmRelocate(t *testing.T) { 199 Test(func(ctx context.Context, c *vim25.Client) { 200 // Test env setup. 201 finder := find.NewFinder(c, true) 202 datacenter, err := finder.DefaultDatacenter(ctx) 203 if err != nil { 204 t.Fatalf("failed to get default datacenter: %v", err) 205 } 206 finder.SetDatacenter(datacenter) 207 208 vmMoRef := Map(ctx).Any("VirtualMachine").(*VirtualMachine).Reference() 209 hostMoRef := Map(ctx).Any("HostSystem").(*HostSystem).Reference() 210 dsMoRef := Map(ctx).Any("Datastore").(*Datastore).Reference() 211 212 tests := []struct { 213 name string 214 relocateSpec *types.VirtualMachineRelocateSpec 215 vmMoRef *types.ManagedObjectReference 216 expectedErr string 217 }{ 218 { 219 "relocate without a spec", 220 nil, 221 &vmMoRef, 222 "", 223 }, 224 { 225 "relocate with an empty spec", 226 &types.VirtualMachineRelocateSpec{}, 227 &vmMoRef, 228 "", 229 }, 230 { 231 "relocate without a vm in spec", 232 &types.VirtualMachineRelocateSpec{ 233 Host: &hostMoRef, 234 }, 235 nil, 236 "InvalidArgument", 237 }, 238 { 239 "relocate with a non-existing vm in spec", 240 &types.VirtualMachineRelocateSpec{ 241 Host: &hostMoRef, 242 }, 243 &types.ManagedObjectReference{ 244 Type: "VirtualMachine", 245 Value: "fake-vm-999", 246 }, 247 "InvalidArgument", 248 }, 249 { 250 "relocate with a diskId in spec.disk that does not exist in the vm", 251 &types.VirtualMachineRelocateSpec{ 252 Host: &hostMoRef, 253 Disk: []types.VirtualMachineRelocateSpecDiskLocator{ 254 { 255 DiskId: 1, 256 Datastore: dsMoRef, 257 }, 258 }, 259 }, 260 &vmMoRef, 261 "InvalidArgument", 262 }, 263 { 264 "relocate with a non-existing datastore in spec.disk", 265 &types.VirtualMachineRelocateSpec{ 266 Host: &hostMoRef, 267 Disk: []types.VirtualMachineRelocateSpecDiskLocator{ 268 { 269 DiskId: 204, // The default diskId in simulator. 270 Datastore: types.ManagedObjectReference{ 271 Type: "Datastore", 272 Value: "fake-datastore-999", 273 }, 274 }, 275 }, 276 }, 277 &vmMoRef, 278 "InvalidArgument", 279 }, 280 { 281 "relocate with a valid spec.disk", 282 &types.VirtualMachineRelocateSpec{ 283 Host: &hostMoRef, 284 Disk: []types.VirtualMachineRelocateSpecDiskLocator{ 285 { 286 DiskId: 204, // The default diskId in simulator. 287 Datastore: dsMoRef, 288 }, 289 }, 290 }, 291 &vmMoRef, 292 "", 293 }, 294 { 295 "relocate with a valid host in spec", 296 &types.VirtualMachineRelocateSpec{ 297 Host: &hostMoRef, 298 }, 299 &vmMoRef, 300 "", 301 }, 302 { 303 "relocate with a non-existing host in spec", 304 &types.VirtualMachineRelocateSpec{ 305 Host: &types.ManagedObjectReference{ 306 Type: "HostSystem", 307 Value: "fake-host-999", 308 }, 309 }, 310 &vmMoRef, 311 "ManagedObjectNotFound", 312 }, 313 { 314 "relocate with a non-existing datastore in spec", 315 &types.VirtualMachineRelocateSpec{ 316 Datastore: &types.ManagedObjectReference{ 317 Type: "Datastore", 318 Value: "fake-datastore-999", 319 }, 320 }, 321 &vmMoRef, 322 "ManagedObjectNotFound", 323 }, 324 { 325 "relocate with a non-existing resource pool in spec", 326 &types.VirtualMachineRelocateSpec{ 327 Pool: &types.ManagedObjectReference{ 328 Type: "ResourcePool", 329 Value: "fake-resource-pool-999", 330 }, 331 }, 332 &vmMoRef, 333 "ManagedObjectNotFound", 334 }, 335 } 336 337 for _, test := range tests { 338 test := test // assign to local var since loop var is reused 339 // PlaceVm. 340 placementSpec := types.PlacementSpec{ 341 Vm: test.vmMoRef, 342 RelocateSpec: test.relocateSpec, 343 PlacementType: string(types.PlacementSpecPlacementTypeRelocate), 344 } 345 346 clusterMoRef := Map(ctx).Any("ClusterComputeResource").(*ClusterComputeResource).Reference() 347 clusterObj := object.NewClusterComputeResource(c, clusterMoRef) 348 _, err = clusterObj.PlaceVm(ctx, placementSpec) 349 if err == nil && test.expectedErr != "" { 350 t.Fatalf("expected error %q, got nil", test.expectedErr) 351 } else if err != nil && !strings.Contains(err.Error(), test.expectedErr) { 352 t.Fatalf("expected error %q, got %v", test.expectedErr, err) 353 } 354 } 355 }) 356 }