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