github.com/vmware/govmomi@v0.51.0/simulator/resource_pool_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  	"reflect"
    10  	"testing"
    11  
    12  	"github.com/google/uuid"
    13  
    14  	"github.com/vmware/govmomi/find"
    15  	"github.com/vmware/govmomi/object"
    16  	"github.com/vmware/govmomi/property"
    17  	"github.com/vmware/govmomi/simulator/esx"
    18  	"github.com/vmware/govmomi/vim25/mo"
    19  	"github.com/vmware/govmomi/vim25/soap"
    20  	"github.com/vmware/govmomi/vim25/types"
    21  )
    22  
    23  func TestResourcePool(t *testing.T) {
    24  	ctx := context.Background()
    25  
    26  	m := &Model{
    27  		ServiceContent: esx.ServiceContent,
    28  		RootFolder:     esx.RootFolder,
    29  	}
    30  
    31  	err := m.Create()
    32  	if err != nil {
    33  		t.Fatal(err)
    34  	}
    35  
    36  	c := m.Service.client()
    37  
    38  	finder := find.NewFinder(c, false)
    39  	finder.SetDatacenter(object.NewDatacenter(c, esx.Datacenter.Reference()))
    40  
    41  	spec := types.DefaultResourceConfigSpec()
    42  
    43  	parent := object.NewResourcePool(c, esx.ResourcePool.Self)
    44  
    45  	spec.CpuAllocation.Reservation = nil
    46  	// missing required field (Reservation) for create
    47  	_, err = parent.Create(ctx, "fail", spec)
    48  	if err == nil {
    49  		t.Error("expected error")
    50  	}
    51  	spec = types.DefaultResourceConfigSpec()
    52  
    53  	// can't destroy a root pool
    54  	task, err := parent.Destroy(ctx)
    55  	if err != nil {
    56  		t.Fatal(err)
    57  	}
    58  	if err = task.Wait(ctx); err == nil {
    59  		t.Fatal("expected error destroying a root pool")
    60  	}
    61  
    62  	// create a child pool
    63  	childName := uuid.New().String()
    64  
    65  	child, err := parent.Create(ctx, childName, spec)
    66  	if err != nil {
    67  		t.Fatal(err)
    68  	}
    69  
    70  	if child.Reference() == esx.ResourcePool.Self {
    71  		t.Error("expected new pool Self reference")
    72  	}
    73  
    74  	*spec.CpuAllocation.Reservation = -1
    75  	// invalid field value (Reservation) for update
    76  	err = child.UpdateConfig(ctx, "", &spec)
    77  	if err == nil {
    78  		t.Error("expected error")
    79  	}
    80  
    81  	// valid config update
    82  	*spec.CpuAllocation.Reservation = 10
    83  	err = child.UpdateConfig(ctx, "", &spec)
    84  	if err != nil {
    85  		t.Error(err)
    86  	}
    87  
    88  	var p mo.ResourcePool
    89  	err = child.Properties(ctx, child.Reference(), []string{"config.cpuAllocation"}, &p)
    90  	if err != nil {
    91  		t.Error(err)
    92  	}
    93  
    94  	if *p.Config.CpuAllocation.Reservation != 10 {
    95  		t.Error("config not updated")
    96  	}
    97  
    98  	// duplicate name
    99  	_, err = parent.Create(ctx, childName, spec)
   100  	if err == nil {
   101  		t.Error("expected error")
   102  	}
   103  
   104  	// create a grandchild pool
   105  	grandChildName := uuid.New().String()
   106  	_, err = child.Create(ctx, grandChildName, spec)
   107  	if err != nil {
   108  		t.Fatal(err)
   109  	}
   110  
   111  	// create sibling (of the grand child) pool
   112  	siblingName := uuid.New().String()
   113  	_, err = child.Create(ctx, siblingName, spec)
   114  	if err != nil {
   115  		t.Fatal(err)
   116  	}
   117  
   118  	// finder should return the 2 grand children
   119  	pools, err := finder.ResourcePoolList(ctx, "*/Resources/"+childName+"/*")
   120  	if err != nil {
   121  		t.Fatal(err)
   122  	}
   123  	if len(pools) != 2 {
   124  		t.Fatalf("len(pools) == %d", len(pools))
   125  	}
   126  
   127  	// destroy the child
   128  	task, err = child.Destroy(ctx)
   129  	if err != nil {
   130  		t.Fatal(err)
   131  	}
   132  	err = task.Wait(ctx)
   133  	if err != nil {
   134  		t.Fatal(err)
   135  	}
   136  
   137  	// finder should error not found after destroying the child
   138  	_, err = finder.ResourcePoolList(ctx, "*/Resources/"+childName+"/*")
   139  	if err == nil {
   140  		t.Fatal("expected not found error")
   141  	}
   142  
   143  	// since the child was destroyed, grand child pools should now be children of the root pool
   144  	pools, err = finder.ResourcePoolList(ctx, "*/Resources/*")
   145  	if err != nil {
   146  		t.Fatal(err)
   147  	}
   148  
   149  	if len(pools) != 2 {
   150  		t.Fatalf("len(pools) == %d", len(pools))
   151  	}
   152  }
   153  
   154  func TestCreateVAppESX(t *testing.T) {
   155  	ctx := context.Background()
   156  
   157  	m := ESX()
   158  	m.Datastore = 0
   159  	m.Machine = 0
   160  
   161  	err := m.Create()
   162  	if err != nil {
   163  		t.Fatal(err)
   164  	}
   165  
   166  	c := m.Service.client()
   167  
   168  	parent := object.NewResourcePool(c, esx.ResourcePool.Self)
   169  
   170  	rspec := types.DefaultResourceConfigSpec()
   171  	vspec := NewVAppConfigSpec()
   172  
   173  	_, err = parent.CreateVApp(ctx, "myapp", rspec, vspec, nil)
   174  	if err == nil {
   175  		t.Fatal("expected error")
   176  	}
   177  
   178  	fault := soap.ToSoapFault(err).Detail.Fault
   179  
   180  	if reflect.TypeOf(fault) != reflect.TypeOf(&types.MethodDisabled{}) {
   181  		t.Errorf("fault=%#v", fault)
   182  	}
   183  }
   184  
   185  func TestCreateVAppVPX(t *testing.T) {
   186  	ctx := context.Background()
   187  
   188  	m := VPX()
   189  
   190  	err := m.Create()
   191  	if err != nil {
   192  		t.Fatal(err)
   193  	}
   194  
   195  	defer m.Remove()
   196  
   197  	c := m.Service.client()
   198  
   199  	pool := m.Map().Any("ResourcePool")
   200  	parent := object.NewResourcePool(c, pool.Reference())
   201  	rspec := types.DefaultResourceConfigSpec()
   202  	vspec := NewVAppConfigSpec()
   203  
   204  	vapp, err := parent.CreateVApp(ctx, "myapp", rspec, vspec, nil)
   205  	if err != nil {
   206  		t.Fatal(err)
   207  	}
   208  
   209  	_, err = parent.CreateVApp(ctx, "myapp", rspec, vspec, nil)
   210  	if err == nil {
   211  		t.Error("expected error")
   212  	}
   213  
   214  	spec := types.VirtualMachineConfigSpec{
   215  		GuestId: string(types.VirtualMachineGuestOsIdentifierOtherGuest),
   216  		Files: &types.VirtualMachineFileInfo{
   217  			VmPathName: "[LocalDS_0]",
   218  		},
   219  	}
   220  
   221  	for _, fail := range []bool{true, false} {
   222  		task, cerr := vapp.CreateChildVM(ctx, spec, nil)
   223  		if cerr != nil {
   224  			t.Fatal(err)
   225  		}
   226  
   227  		cerr = task.Wait(ctx)
   228  		if fail {
   229  			if cerr == nil {
   230  				t.Error("expected error")
   231  			}
   232  		} else {
   233  			if cerr != nil {
   234  				t.Error(err)
   235  			}
   236  		}
   237  
   238  		spec.Name = "test"
   239  	}
   240  
   241  	si := object.NewSearchIndex(c)
   242  	vm, err := si.FindChild(ctx, vapp, spec.Name)
   243  	if err != nil {
   244  		t.Fatal(err)
   245  	}
   246  
   247  	if vm == nil {
   248  		t.Errorf("FindChild(%s)==nil", spec.Name)
   249  	}
   250  
   251  	ref := m.Map().Get(m.Map().getEntityDatacenter(pool).VmFolder).Reference()
   252  	folder, err := object.NewFolder(c, ref).CreateFolder(ctx, "myapp-clone")
   253  	if err != nil {
   254  		t.Fatal(err)
   255  	}
   256  
   257  	cspec := types.VAppCloneSpec{
   258  		VmFolder: types.NewReference(folder.Reference()),
   259  	}
   260  
   261  	task, err := vapp.Clone(ctx, "myapp-clone", parent.Reference(), cspec)
   262  	if err != nil {
   263  		t.Fatal(err)
   264  	}
   265  
   266  	res, err := task.WaitForResult(ctx, nil)
   267  	if err != nil {
   268  		t.Fatal(err)
   269  	}
   270  
   271  	var apps []mo.VirtualApp
   272  	refs := []types.ManagedObjectReference{vapp.Reference(), res.Result.(types.ManagedObjectReference)}
   273  	err = property.DefaultCollector(c).Retrieve(ctx, refs, []string{"vm"}, &apps)
   274  	if err != nil {
   275  		t.Fatal(err)
   276  	}
   277  
   278  	if len(apps) != 2 {
   279  		t.Errorf("apps=%d", len(apps))
   280  	}
   281  
   282  	for _, app := range apps {
   283  		if len(app.Vm) != 1 {
   284  			t.Errorf("app %s vm=%d", app.Reference(), len(app.Vm))
   285  		}
   286  	}
   287  
   288  	task, err = vapp.Destroy(ctx)
   289  	if err != nil {
   290  		t.Fatal(err)
   291  	}
   292  
   293  	err = task.Wait(ctx)
   294  	if err != nil {
   295  		t.Fatal(err)
   296  	}
   297  }
   298  
   299  func TestResourcePoolValidation(t *testing.T) {
   300  	tests := []func() bool{
   301  		func() bool {
   302  			return allResourceFieldsSet(&types.ResourceAllocationInfo{})
   303  		},
   304  		func() bool {
   305  			spec := types.DefaultResourceConfigSpec()
   306  			spec.CpuAllocation.Limit = nil
   307  			return allResourceFieldsSet(&spec.CpuAllocation)
   308  		},
   309  		func() bool {
   310  			spec := types.DefaultResourceConfigSpec()
   311  			spec.CpuAllocation.Reservation = nil
   312  			return allResourceFieldsSet(&spec.CpuAllocation)
   313  		},
   314  		func() bool {
   315  			spec := types.DefaultResourceConfigSpec()
   316  			spec.CpuAllocation.ExpandableReservation = nil
   317  			return allResourceFieldsSet(&spec.CpuAllocation)
   318  		},
   319  		func() bool {
   320  			spec := types.DefaultResourceConfigSpec()
   321  			spec.CpuAllocation.Shares = nil
   322  			return allResourceFieldsSet(&spec.CpuAllocation)
   323  		},
   324  		func() bool {
   325  			spec := types.DefaultResourceConfigSpec()
   326  			spec.CpuAllocation.Reservation = types.NewInt64(-1)
   327  			return allResourceFieldsValid(&spec.CpuAllocation)
   328  		},
   329  		func() bool {
   330  			spec := types.DefaultResourceConfigSpec()
   331  			spec.CpuAllocation.Limit = types.NewInt64(-100)
   332  			return allResourceFieldsValid(&spec.CpuAllocation)
   333  		},
   334  		func() bool {
   335  			spec := types.DefaultResourceConfigSpec()
   336  			shares := spec.CpuAllocation.Shares
   337  			shares.Level = types.SharesLevelCustom
   338  			shares.Shares = -1
   339  			return allResourceFieldsValid(&spec.CpuAllocation)
   340  		},
   341  	}
   342  
   343  	for i, test := range tests {
   344  		ok := test()
   345  		if ok {
   346  			t.Errorf("%d: expected false", i)
   347  		}
   348  	}
   349  }