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 }