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  }