github.com/vmware/govmomi@v0.43.0/simulator/folder_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/vmware/govmomi" 25 "github.com/vmware/govmomi/find" 26 "github.com/vmware/govmomi/object" 27 "github.com/vmware/govmomi/simulator/esx" 28 "github.com/vmware/govmomi/simulator/vpx" 29 "github.com/vmware/govmomi/vim25" 30 "github.com/vmware/govmomi/vim25/methods" 31 "github.com/vmware/govmomi/vim25/mo" 32 "github.com/vmware/govmomi/vim25/soap" 33 "github.com/vmware/govmomi/vim25/types" 34 ) 35 36 func addStandaloneHostTask(folder *object.Folder, spec types.HostConnectSpec) (*object.Task, error) { 37 // TODO: add govmomi wrapper 38 req := types.AddStandaloneHost_Task{ 39 This: folder.Reference(), 40 Spec: spec, 41 AddConnected: true, 42 } 43 44 res, err := methods.AddStandaloneHost_Task(context.TODO(), folder.Client(), &req) 45 if err != nil { 46 return nil, err 47 } 48 49 task := object.NewTask(folder.Client(), res.Returnval) 50 return task, nil 51 } 52 53 func TestFolderESX(t *testing.T) { 54 content := esx.ServiceContent 55 s := New(NewServiceInstance(SpoofContext(), content, esx.RootFolder)) 56 57 ts := s.NewServer() 58 defer ts.Close() 59 60 ctx := context.Background() 61 c, err := govmomi.NewClient(ctx, ts.URL, true) 62 if err != nil { 63 t.Fatal(err) 64 } 65 66 f := object.NewRootFolder(c.Client) 67 68 _, err = f.CreateFolder(ctx, "foo") 69 if err == nil { 70 t.Error("expected error") 71 } 72 73 _, err = f.CreateDatacenter(ctx, "foo") 74 if err == nil { 75 t.Error("expected error") 76 } 77 78 finder := find.NewFinder(c.Client, false) 79 dc, err := finder.DatacenterOrDefault(ctx, "") 80 if err != nil { 81 t.Fatal(err) 82 } 83 84 folders, err := dc.Folders(ctx) 85 if err != nil { 86 t.Fatal(err) 87 } 88 89 spec := types.HostConnectSpec{} 90 _, err = addStandaloneHostTask(folders.HostFolder, spec) 91 if err == nil { 92 t.Fatal("expected error") 93 } 94 95 _, err = folders.DatastoreFolder.CreateStoragePod(ctx, "pod") 96 if err == nil { 97 t.Fatal("expected error") 98 } 99 } 100 101 func TestFolderVC(t *testing.T) { 102 content := vpx.ServiceContent 103 s := New(NewServiceInstance(SpoofContext(), content, vpx.RootFolder)) 104 105 ts := s.NewServer() 106 defer ts.Close() 107 108 ctx := context.Background() 109 c, err := govmomi.NewClient(ctx, ts.URL, true) 110 if err != nil { 111 t.Fatal(err) 112 } 113 114 f := object.NewRootFolder(c.Client) 115 116 ff, err := f.CreateFolder(ctx, "foo") 117 if err != nil { 118 t.Error(err) 119 } 120 121 dc, err := f.CreateDatacenter(ctx, "bar") 122 if err != nil { 123 t.Error(err) 124 } 125 126 for _, ref := range []object.Reference{ff, dc} { 127 o := Map.Get(ref.Reference()) 128 if o == nil { 129 t.Fatalf("failed to find %#v", ref) 130 } 131 132 e := o.(mo.Entity).Entity() 133 if *e.Parent != f.Reference() { 134 t.Fail() 135 } 136 } 137 138 dc, err = ff.CreateDatacenter(ctx, "biz") 139 if err != nil { 140 t.Error(err) 141 } 142 143 folders, err := dc.Folders(ctx) 144 if err != nil { 145 t.Fatal(err) 146 } 147 148 _, err = folders.VmFolder.CreateStoragePod(ctx, "pod") 149 if err == nil { 150 t.Error("expected error") 151 } 152 153 _, err = folders.DatastoreFolder.CreateStoragePod(ctx, "pod") 154 if err != nil { 155 t.Error(err) 156 } 157 158 tests := []struct { 159 name string 160 state types.TaskInfoState 161 }{ 162 {"", types.TaskInfoStateError}, 163 {"foo.local", types.TaskInfoStateSuccess}, 164 } 165 166 for _, test := range tests { 167 spec := types.HostConnectSpec{ 168 HostName: test.name, 169 } 170 171 task, err := addStandaloneHostTask(folders.HostFolder, spec) 172 if err != nil { 173 t.Fatal(err) 174 } 175 176 res, err := task.WaitForResult(ctx, nil) 177 if test.state == types.TaskInfoStateError { 178 if err == nil { 179 t.Error("expected error") 180 } 181 182 if res.Result != nil { 183 t.Error("expected nil") 184 } 185 } else { 186 if err != nil { 187 t.Fatal(err) 188 } 189 190 ref, ok := res.Result.(types.ManagedObjectReference) 191 if !ok { 192 t.Errorf("expected moref, got type=%T", res.Result) 193 } 194 host := Map.Get(ref).(*HostSystem) 195 if host.Name != test.name { 196 t.Fail() 197 } 198 199 if ref == esx.HostSystem.Self { 200 t.Error("expected new host Self reference") 201 } 202 if *host.Summary.Host == esx.HostSystem.Self { 203 t.Error("expected new host summary Self reference") 204 } 205 206 pool := Map.Get(*host.Parent).(*mo.ComputeResource).ResourcePool 207 if *pool == esx.ResourcePool.Self { 208 t.Error("expected new pool Self reference") 209 } 210 } 211 212 if res.State != test.state { 213 t.Fatalf("%s", res.State) 214 } 215 } 216 } 217 218 func TestFolderSpecialCharaters(t *testing.T) { 219 content := vpx.ServiceContent 220 s := New(NewServiceInstance(SpoofContext(), content, vpx.RootFolder)) 221 222 ts := s.NewServer() 223 defer ts.Close() 224 225 ctx := context.Background() 226 c, err := govmomi.NewClient(ctx, ts.URL, true) 227 if err != nil { 228 t.Fatal(err) 229 } 230 231 f := object.NewRootFolder(c.Client) 232 233 tests := []struct { 234 name string 235 expected string 236 }{ 237 {`/`, `%2f`}, 238 {`\`, `%5c`}, 239 {`%`, `%25`}, 240 // multiple special characters 241 {`%%`, `%25%25`}, 242 } 243 244 for _, test := range tests { 245 ff, err := f.CreateFolder(ctx, test.name) 246 if err != nil { 247 t.Fatal(err) 248 } 249 250 o := Map.Get(ff.Reference()) 251 if o == nil { 252 t.Fatalf("failed to find %#v", ff) 253 } 254 255 e := o.(mo.Entity).Entity() 256 if e.Name != test.expected { 257 t.Errorf("expected %s, got %s", test.expected, e.Name) 258 } 259 } 260 } 261 262 func TestFolderFaults(t *testing.T) { 263 f := Folder{} 264 f.ChildType = []string{"VirtualMachine"} 265 266 if f.CreateFolder(nil, nil).Fault() == nil { 267 t.Error("expected fault") 268 } 269 270 if f.CreateDatacenter(nil, nil).Fault() == nil { 271 t.Error("expected fault") 272 } 273 } 274 275 func TestRegisterVm(t *testing.T) { 276 ctx := context.Background() 277 278 for i, model := range []*Model{ESX(), VPX()} { 279 match := "*" 280 if i == 1 { 281 model.App = 1 282 match = "*APP*" 283 } 284 defer model.Remove() 285 err := model.Create() 286 if err != nil { 287 t.Fatal(err) 288 } 289 290 s := model.Service.NewServer() 291 defer s.Close() 292 293 c, err := govmomi.NewClient(ctx, s.URL, true) 294 if err != nil { 295 t.Fatal(err) 296 } 297 298 finder := find.NewFinder(c.Client, false) 299 dc, err := finder.DefaultDatacenter(ctx) 300 if err != nil { 301 t.Fatal(err) 302 } 303 304 finder.SetDatacenter(dc) 305 306 folders, err := dc.Folders(ctx) 307 if err != nil { 308 t.Fatal(err) 309 } 310 311 vmFolder := folders.VmFolder 312 313 vms, err := finder.VirtualMachineList(ctx, match) 314 if err != nil { 315 t.Fatal(err) 316 } 317 318 vm := Map.Get(vms[0].Reference()).(*VirtualMachine) 319 320 req := types.RegisterVM_Task{ 321 This: vmFolder.Reference(), 322 AsTemplate: true, 323 } 324 325 steps := []struct { 326 e interface{} 327 f func() 328 }{ 329 { 330 new(types.InvalidArgument), func() { req.AsTemplate = false }, 331 }, 332 { 333 new(types.InvalidArgument), func() { req.Pool = vm.ResourcePool }, 334 }, 335 { 336 new(types.InvalidArgument), func() { req.Path = "enoent" }, 337 }, 338 { 339 new(types.InvalidDatastorePath), func() { req.Path = vm.Config.Files.VmPathName + "-enoent" }, 340 }, 341 { 342 new(types.NotFound), func() { req.Path = vm.Config.Files.VmPathName }, 343 }, 344 { 345 new(types.AlreadyExists), func() { Map.Remove(SpoofContext(), vm.Reference()) }, 346 }, 347 { 348 nil, func() {}, 349 }, 350 } 351 352 for _, step := range steps { 353 res, err := methods.RegisterVM_Task(ctx, c.Client, &req) 354 if err != nil { 355 t.Fatal(err) 356 } 357 358 ct := object.NewTask(c.Client, res.Returnval) 359 _ = ct.Wait(ctx) 360 361 rt := Map.Get(res.Returnval).(*Task) 362 363 if step.e != nil { 364 fault := rt.Info.Error.Fault 365 if reflect.TypeOf(fault) != reflect.TypeOf(step.e) { 366 t.Errorf("%T != %T", fault, step.e) 367 } 368 } else { 369 if rt.Info.Error != nil { 370 t.Errorf("unexpected error: %#v", rt.Info.Error) 371 } 372 } 373 374 step.f() 375 } 376 377 nvm, err := finder.VirtualMachine(ctx, vm.Name) 378 if err != nil { 379 t.Fatal(err) 380 } 381 382 if nvm.Reference() == vm.Reference() { 383 t.Error("expected new moref") 384 } 385 386 onTask, _ := nvm.PowerOn(ctx) 387 _ = onTask.Wait(ctx) 388 389 steps = []struct { 390 e interface{} 391 f func() 392 }{ 393 { 394 types.InvalidPowerState{}, func() { offTask, _ := nvm.PowerOff(ctx); _ = offTask.Wait(ctx) }, 395 }, 396 { 397 nil, func() {}, 398 }, 399 { 400 types.ManagedObjectNotFound{}, func() {}, 401 }, 402 } 403 404 for _, step := range steps { 405 err = nvm.Unregister(ctx) 406 407 if step.e != nil { 408 fault := soap.ToSoapFault(err).VimFault() 409 if reflect.TypeOf(fault) != reflect.TypeOf(step.e) { 410 t.Errorf("%T != %T", fault, step.e) 411 } 412 } else { 413 if err != nil { 414 t.Errorf("unexpected error: %#v", err) 415 } 416 } 417 418 step.f() 419 } 420 } 421 } 422 423 func TestFolderMoveInto(t *testing.T) { 424 ctx := context.Background() 425 model := VPX() 426 defer model.Remove() 427 err := model.Create() 428 if err != nil { 429 t.Fatal(err) 430 } 431 432 s := model.Service.NewServer() 433 defer s.Close() 434 435 c, err := govmomi.NewClient(ctx, s.URL, true) 436 if err != nil { 437 t.Fatal(err) 438 } 439 440 finder := find.NewFinder(c.Client, false) 441 442 dc, err := finder.DefaultDatacenter(ctx) 443 if err != nil { 444 t.Fatal(err) 445 } 446 447 finder.SetDatacenter(dc) 448 449 folders, err := dc.Folders(ctx) 450 if err != nil { 451 t.Fatal(err) 452 } 453 454 ds, err := finder.DefaultDatastore(ctx) 455 if err != nil { 456 t.Fatal(err) 457 } 458 459 // Move Datastore into a vm folder should fail 460 task, err := folders.VmFolder.MoveInto(ctx, []types.ManagedObjectReference{ds.Reference()}) 461 if err != nil { 462 t.Fatal(err) 463 } 464 465 err = task.Wait(ctx) 466 if err == nil { 467 t.Errorf("expected error") 468 } 469 470 // Move Datacenter into a sub folder should pass 471 f, err := object.NewRootFolder(c.Client).CreateFolder(ctx, "foo") 472 if err != nil { 473 t.Error(err) 474 } 475 476 task, _ = f.MoveInto(ctx, []types.ManagedObjectReference{dc.Reference()}) 477 err = task.Wait(ctx) 478 if err != nil { 479 t.Error(err) 480 } 481 482 pod, err := folders.DatastoreFolder.CreateStoragePod(ctx, "pod") 483 if err != nil { 484 t.Error(err) 485 } 486 487 // Moving any type other than Datastore into a StoragePod should fail 488 task, _ = pod.MoveInto(ctx, []types.ManagedObjectReference{dc.Reference()}) 489 err = task.Wait(ctx) 490 if err == nil { 491 t.Error("expected error") 492 } 493 494 // Move DS into a StoragePod 495 task, _ = pod.MoveInto(ctx, []types.ManagedObjectReference{ds.Reference()}) 496 err = task.Wait(ctx) 497 if err != nil { 498 t.Error(err) 499 } 500 } 501 502 func TestFolderCreateDVS(t *testing.T) { 503 ctx := context.Background() 504 model := VPX() 505 defer model.Remove() 506 err := model.Create() 507 if err != nil { 508 t.Fatal(err) 509 } 510 511 s := model.Service.NewServer() 512 defer s.Close() 513 514 c, err := govmomi.NewClient(ctx, s.URL, true) 515 if err != nil { 516 t.Fatal(err) 517 } 518 519 finder := find.NewFinder(c.Client, false) 520 521 dc, err := finder.DefaultDatacenter(ctx) 522 if err != nil { 523 t.Fatal(err) 524 } 525 526 finder.SetDatacenter(dc) 527 528 folders, err := dc.Folders(ctx) 529 if err != nil { 530 t.Fatal(err) 531 } 532 533 var spec types.DVSCreateSpec 534 spec.ConfigSpec = &types.VMwareDVSConfigSpec{} 535 spec.ConfigSpec.GetDVSConfigSpec().Name = "foo" 536 537 task, err := folders.NetworkFolder.CreateDVS(ctx, spec) 538 if err != nil { 539 t.Fatal(err) 540 } 541 542 err = task.Wait(ctx) 543 if err != nil { 544 t.Error(err) 545 } 546 547 net, err := finder.Network(ctx, "foo") 548 if err != nil { 549 t.Error(err) 550 } 551 552 dvs, ok := net.(*object.DistributedVirtualSwitch) 553 if !ok { 554 t.Fatalf("%T is not of type %T", net, dvs) 555 } 556 557 task, err = folders.NetworkFolder.CreateDVS(ctx, spec) 558 if err != nil { 559 t.Fatal(err) 560 } 561 562 err = task.Wait(ctx) 563 if err == nil { 564 t.Error("expected error") 565 } 566 567 pspec := types.DVPortgroupConfigSpec{Name: "xnet"} 568 task, err = dvs.AddPortgroup(ctx, []types.DVPortgroupConfigSpec{pspec}) 569 if err != nil { 570 t.Fatal(err) 571 } 572 573 err = task.Wait(ctx) 574 if err != nil { 575 t.Error(err) 576 } 577 578 net, err = finder.Network(ctx, "xnet") 579 if err != nil { 580 t.Error(err) 581 } 582 583 pg, ok := net.(*object.DistributedVirtualPortgroup) 584 if !ok { 585 t.Fatalf("%T is not of type %T", net, pg) 586 } 587 588 backing, err := net.EthernetCardBackingInfo(ctx) 589 if err != nil { 590 t.Fatal(err) 591 } 592 593 info, ok := backing.(*types.VirtualEthernetCardDistributedVirtualPortBackingInfo) 594 if ok { 595 if info.Port.SwitchUuid == "" || info.Port.PortgroupKey == "" { 596 t.Errorf("invalid port: %#v", info.Port) 597 } 598 } else { 599 t.Fatalf("%T is not of type %T", net, info) 600 } 601 602 task, err = dvs.AddPortgroup(ctx, []types.DVPortgroupConfigSpec{pspec}) 603 if err != nil { 604 t.Fatal(err) 605 } 606 607 err = task.Wait(ctx) 608 if err == nil { 609 t.Error("expected error") 610 } 611 } 612 613 func TestPlaceVmsXCluster(t *testing.T) { 614 vpx := VPX() 615 vpx.Cluster = 3 616 617 Test(func(ctx context.Context, c *vim25.Client) { 618 finder := find.NewFinder(c, false) 619 620 spec := types.PlaceVmsXClusterSpec{} 621 622 pools, err := finder.ResourcePoolList(ctx, "/DC0/host/DC0_C*/*") 623 if err != nil { 624 t.Fatal(err) 625 } 626 627 for _, pool := range pools { 628 spec.ResourcePools = append(spec.ResourcePools, pool.Reference()) 629 } 630 631 spec.VmPlacementSpecs = []types.PlaceVmsXClusterSpecVmPlacementSpec{{ 632 ConfigSpec: types.VirtualMachineConfigSpec{ 633 Name: "test-vm", 634 }, 635 }} 636 637 folder := object.NewRootFolder(c) 638 res, err := folder.PlaceVmsXCluster(ctx, spec) 639 if err != nil { 640 t.Fatal(err) 641 } 642 643 if len(res.PlacementInfos) != len(spec.VmPlacementSpecs) { 644 t.Errorf("%d PlacementInfos vs %d VmPlacementSpecs", len(res.PlacementInfos), len(spec.VmPlacementSpecs)) 645 } 646 }, vpx) 647 }