github.com/vmware/govmomi@v0.43.0/simulator/cluster_compute_resource_test.go (about)

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