func (cmd *create) Run(f *flag.FlagSet) error { datacenters := f.Args() if len(datacenters) < 1 { return flag.ErrHelp } client, err := cmd.ClientFlag.Client() if err != nil { return err } finder := find.NewFinder(client, false) rootFolder := object.NewRootFolder(client) for _, datacenterToCreate := range datacenters { _, err := finder.Datacenter(context.TODO(), datacenterToCreate) if err == nil { // The datacenter was found, no need to create it continue } switch err.(type) { case *find.NotFoundError: _, err = rootFolder.CreateDatacenter(context.TODO(), datacenterToCreate) if err != nil { return err } default: return err } } return nil }
func TestClusterVC(t *testing.T) { content := vc.ServiceContent s := New(NewServiceInstance(content, vc.RootFolder)) ts := s.NewServer() defer ts.Close() ctx := context.Background() c, err := govmomi.NewClient(ctx, ts.URL, true) if err != nil { t.Fatal(err) } f := object.NewRootFolder(c.Client) dc, err := f.CreateDatacenter(ctx, "foo") if err != nil { t.Error(err) } folders, err := dc.Folders(ctx) if err != nil { t.Fatal(err) } cluster, err := folders.HostFolder.CreateCluster(ctx, "cluster1", types.ClusterConfigSpecEx{}) if err != nil { t.Fatal(err) } _, err = folders.HostFolder.CreateCluster(ctx, "cluster1", types.ClusterConfigSpecEx{}) if err == nil { t.Error("expected DuplicateName error") } spec := types.HostConnectSpec{} for _, fail := range []bool{true, false} { task, err := cluster.AddHost(ctx, spec, true, nil, nil) if err != nil { t.Fatal(err) } _, err = task.WaitForResult(ctx, nil) if fail { if err == nil { t.Error("expected error") } spec.HostName = "localhost" } else { if err != nil { t.Error(err) } } } }
func (flag *FolderFlag) FolderOrRoot() (*object.Folder, error) { if flag.name == "" { client, err := flag.Client() if err != nil { return nil, err } flag.folder = object.NewRootFolder(client) return flag.folder, nil } return flag.Folder() }
func (flag *FolderFlag) FolderOrDefault(kind string) (*object.Folder, error) { if flag.folder != nil { return flag.folder, nil } if flag.name != "" { return flag.Folder() } // RootFolder, no dc required if kind == "/" { client, err := flag.Client() if err != nil { return nil, err } flag.folder = object.NewRootFolder(client) return flag.folder, nil } dc, err := flag.Datacenter() if err != nil { return nil, err } folders, err := dc.Folders(context.TODO()) if err != nil { return nil, err } switch kind { case "vm": flag.folder = folders.VmFolder case "host": flag.folder = folders.HostFolder case "datastore": flag.folder = folders.DatastoreFolder case "network": flag.folder = folders.NetworkFolder default: panic(kind) } return flag.folder, nil }
func (f *Finder) find(ctx context.Context, fn findRelativeFunc, tl bool, arg string) ([]list.Element, error) { root := list.Element{ Path: "/", Object: object.NewRootFolder(f.client), } parts := list.ToParts(arg) if len(parts) > 0 { switch parts[0] { case "..": // Not supported; many edge case, little value return nil, errors.New("cannot traverse up a tree") case ".": // Relative to whatever pivot, err := fn(ctx) if err != nil { return nil, err } mes, err := mo.Ancestors(ctx, f.client, f.client.ServiceContent.PropertyCollector, pivot.Reference()) if err != nil { return nil, err } for _, me := range mes { // Skip root entity in building inventory path. if me.Parent == nil { continue } root.Path = path.Join(root.Path, me.Name) } root.Object = pivot parts = parts[1:] } } f.recurser.TraverseLeafs = tl es, err := f.recurser.Recurse(ctx, root, parts) if err != nil { return nil, err } return es, nil }
func TestFolderESX(t *testing.T) { content := esx.ServiceContent s := New(NewServiceInstance(content, esx.RootFolder)) ts := s.NewServer() defer ts.Close() ctx := context.Background() c, err := govmomi.NewClient(ctx, ts.URL, true) if err != nil { t.Fatal(err) } f := object.NewRootFolder(c.Client) _, err = f.CreateFolder(ctx, "foo") if err == nil { t.Error("expected error") } _, err = f.CreateDatacenter(ctx, "foo") if err == nil { t.Error("expected error") } finder := find.NewFinder(c.Client, false) dc, err := finder.DatacenterOrDefault(ctx, "") if err != nil { t.Fatal(err) } folders, err := dc.Folders(ctx) if err != nil { t.Fatal(err) } spec := types.HostConnectSpec{} _, err = addStandaloneHost(folders.HostFolder, spec) if err == nil { t.Fatal("expected error") } }
func (f *Finder) rootFolder(_ context.Context) (object.Reference, error) { return object.NewRootFolder(f.client), nil }
// Create populates the Model with the given ModelConfig func (m *Model) Create() error { m.Service = New(NewServiceInstance(m.ServiceContent, m.RootFolder)) ctx := context.Background() client := m.Service.client root := object.NewRootFolder(client) // After all hosts are created, this var is used to mount the host datastores. var hosts []*object.HostSystem // We need to defer VM creation until after the datastores are created. var vms []func() error // addHost adds a cluster host or a stanalone host. addHost := func(name string, f func(types.HostConnectSpec) (*object.Task, error)) (*object.HostSystem, error) { spec := types.HostConnectSpec{ HostName: name, } task, err := f(spec) if err != nil { return nil, err } info, err := task.WaitForResult(context.Background(), nil) if err != nil { return nil, err } host := object.NewHostSystem(client, info.Result.(types.ManagedObjectReference)) hosts = append(hosts, host) return host, nil } // addMachine returns a func to create a VM. addMachine := func(prefix string, host *object.HostSystem, pool *object.ResourcePool, folders *object.DatacenterFolders) { f := func() error { for i := 0; i < m.Machine; i++ { name := m.fmtName(prefix+"_VM", i) config := types.VirtualMachineConfigSpec{ Name: name, GuestId: string(types.VirtualMachineGuestOsIdentifierOtherGuest), Files: &types.VirtualMachineFileInfo{ VmPathName: fmt.Sprintf("[LocalDS_0] %s", name), }, } if pool == nil { pool, _ = host.ResourcePool(ctx) } task, err := folders.VmFolder.CreateVM(ctx, config, pool, host) if err != nil { return err } err = task.Wait(ctx) if err != nil { return err } } return nil } vms = append(vms, f) } for ndc := 0; ndc < m.Datacenter; ndc++ { dcName := m.fmtName("DC", ndc) dc, err := root.CreateDatacenter(ctx, dcName) if err != nil { return err } folders, err := dc.Folders(ctx) if err != nil { return err } for nhost := 0; nhost < m.Host; nhost++ { name := m.fmtName(dcName+"_H", nhost) host, err := addHost(name, func(spec types.HostConnectSpec) (*object.Task, error) { return folders.HostFolder.AddStandaloneHost(ctx, spec, true, nil, nil) }) if err != nil { return err } addMachine(name, host, nil, folders) } for ncluster := 0; ncluster < m.Cluster; ncluster++ { clusterName := m.fmtName(dcName+"_C", ncluster) cluster, err := folders.HostFolder.CreateCluster(ctx, clusterName, types.ClusterConfigSpecEx{}) if err != nil { return err } // TODO: create DistributedVirtualPortgroup for npg := 0; npg < m.Portgroup; npg++ for nhost := 0; nhost < m.ClusterHost; nhost++ { name := m.fmtName(clusterName+"_H", nhost) _, err := addHost(name, func(spec types.HostConnectSpec) (*object.Task, error) { return cluster.AddHost(ctx, spec, true, nil, nil) }) if err != nil { return err } } pool, err := cluster.ResourcePool(ctx) if err != nil { return err } prefix := clusterName + "_RP" addMachine(prefix+"0", nil, pool, folders) for npool := 1; npool <= m.Pool; npool++ { spec := NewResourceConfigSpec() _, err = pool.Create(ctx, m.fmtName(prefix, npool), spec) if err != nil { return err } } } } if m.ServiceContent.RootFolder == esx.RootFolder.Reference() { // ESX model host := object.NewHostSystem(client, esx.HostSystem.Reference()) hosts = append(hosts, host) dc := object.NewDatacenter(client, esx.Datacenter.Reference()) folders, err := dc.Folders(ctx) if err != nil { return err } addMachine(host.Reference().Value, host, nil, folders) } for i := 0; i < m.Datastore; i++ { err := m.createLocalDatastore(m.fmtName("LocalDS_", i), hosts) if err != nil { return err } } for _, createVM := range vms { err := createVM() if err != nil { return err } } return nil }
func TestRetrieveProperties(t *testing.T) { configs := []struct { folder mo.Folder content types.ServiceContent dc *types.ManagedObjectReference }{ {esx.RootFolder, esx.ServiceContent, &esx.Datacenter.Self}, {vc.RootFolder, vc.ServiceContent, nil}, } for _, config := range configs { s := New(NewServiceInstance(config.content, config.folder)) ts := s.NewServer() defer ts.Close() ctx := context.Background() client, err := govmomi.NewClient(ctx, ts.URL, true) if err != nil { t.Fatal(err) } if config.dc == nil { dc, cerr := object.NewRootFolder(client.Client).CreateDatacenter(ctx, "dc1") if cerr != nil { t.Fatal(cerr) } ref := dc.Reference() config.dc = &ref } // Retrieve a specific property f := mo.Folder{} err = client.RetrieveOne(ctx, config.content.RootFolder, []string{"name"}, &f) if err != nil { t.Fatal(err) } if f.Name != config.folder.Name { t.Fail() } // Retrieve all properties f = mo.Folder{} err = client.RetrieveOne(ctx, config.content.RootFolder, nil, &f) if err != nil { t.Fatal(err) } if f.Name != config.folder.Name { t.Fatalf("'%s' vs '%s'", f.Name, config.folder.Name) } // Retrieve an ArrayOf property f = mo.Folder{} err = client.RetrieveOne(ctx, config.content.RootFolder, []string{"childEntity"}, &f) if err != nil { t.Fatal(err) } if len(f.ChildEntity) != 1 { t.Fail() } es, err := mo.Ancestors(ctx, client.Client, config.content.PropertyCollector, config.content.RootFolder) if err != nil { t.Fatal(err) } if len(es) != 1 { t.Fail() } finder := find.NewFinder(client.Client, false) dc, err := finder.DatacenterOrDefault(ctx, "") if err != nil { t.Fatal(err) } if dc.Reference() != *config.dc { t.Fail() } finder.SetDatacenter(dc) es, err = mo.Ancestors(ctx, client.Client, config.content.PropertyCollector, dc.Reference()) if err != nil { t.Fatal(err) } expect := map[string]types.ManagedObjectReference{ "Folder": config.folder.Reference(), "Datacenter": dc.Reference(), } if len(es) != len(expect) { t.Fail() } for _, e := range es { ref := e.Reference() if r, ok := expect[ref.Type]; ok { if r != ref { t.Errorf("%#v vs %#v", r, ref) } } else { t.Errorf("unexpected object %#v", e.Reference()) } } // finder tests ls, err := finder.ManagedObjectListChildren(ctx, ".") if err != nil { t.Error(err) } folders, err := dc.Folders(ctx) if err != nil { t.Fatal(err) } // Validated name properties are recursively retrieved for the datacenter and its folder children ipaths := []string{ folders.VmFolder.InventoryPath, folders.HostFolder.InventoryPath, folders.DatastoreFolder.InventoryPath, folders.NetworkFolder.InventoryPath, } var lpaths []string for _, p := range ls { lpaths = append(lpaths, p.Path) } if !reflect.DeepEqual(ipaths, lpaths) { t.Errorf("%#v != %#v\n", ipaths, lpaths) } // We have no VMs, expect NotFoundError _, err = finder.VirtualMachineList(ctx, "*") if err == nil { t.Error("expected error") } else { if _, ok := err.(*find.NotFoundError); !ok { t.Error(err) } } // Retrieve a missing property mdc := mo.Datacenter{} err = client.RetrieveOne(ctx, dc.Reference(), []string{"enoent"}, &mdc) if err == nil { t.Error("expected error") } else { switch fault := soap.ToVimFault(err).(type) { case *types.InvalidProperty: // ok default: t.Errorf("unexpected fault: %#v", fault) } } // Retrieve a nested property Map.Get(dc.Reference()).(*mo.Datacenter).Configuration.DefaultHardwareVersionKey = "foo" mdc = mo.Datacenter{} err = client.RetrieveOne(ctx, dc.Reference(), []string{"configuration.defaultHardwareVersionKey"}, &mdc) if err != nil { t.Fatal(err) } if mdc.Configuration.DefaultHardwareVersionKey != "foo" { t.Fail() } // Retrieve a missing nested property mdc = mo.Datacenter{} err = client.RetrieveOne(ctx, dc.Reference(), []string{"configuration.enoent"}, &mdc) if err == nil { t.Error("expected error") } else { switch fault := soap.ToVimFault(err).(type) { case *types.InvalidProperty: // ok default: t.Errorf("unexpected fault: %#v", fault) } } // Retrieve an empty property err = client.RetrieveOne(ctx, dc.Reference(), []string{""}, &mdc) if err != nil { t.Error(err) } // Expect ManagedObjectNotFoundError Map.Remove(dc.Reference()) err = client.RetrieveOne(ctx, dc.Reference(), []string{"name"}, &mdc) if err == nil { t.Fatal("expected error") } } }
func TestFolderVC(t *testing.T) { content := vc.ServiceContent s := New(NewServiceInstance(content, vc.RootFolder)) ts := s.NewServer() defer ts.Close() ctx := context.Background() c, err := govmomi.NewClient(ctx, ts.URL, true) if err != nil { t.Fatal(err) } f := object.NewRootFolder(c.Client) ff, err := f.CreateFolder(ctx, "foo") if err != nil { t.Error(err) } dc, err := f.CreateDatacenter(ctx, "bar") if err != nil { t.Error(err) } for _, ref := range []object.Reference{ff, dc} { o := Map.Get(ref.Reference()) if o == nil { t.Fatalf("failed to find %#v", ref) } e := o.(mo.Entity).Entity() if *e.Parent != f.Reference() { t.Fail() } } dc, err = ff.CreateDatacenter(ctx, "biz") if err != nil { t.Error(err) } folders, err := dc.Folders(ctx) if err != nil { t.Fatal(err) } tests := []struct { name string state types.TaskInfoState }{ {"", types.TaskInfoStateError}, {"foo.local", types.TaskInfoStateSuccess}, } for _, test := range tests { spec := types.HostConnectSpec{ HostName: test.name, } task, err := addStandaloneHost(folders.HostFolder, spec) if err != nil { t.Fatal(err) } res, err := task.WaitForResult(ctx, nil) if test.state == types.TaskInfoStateError { if err == nil { t.Error("expected error") } if res.Result != nil { t.Error("expected nil") } } else { if err != nil { t.Fatal(err) } ref, ok := res.Result.(types.ManagedObjectReference) if !ok { t.Errorf("expected moref, got type=%T", res.Result) } host := Map.Get(ref).(*HostSystem) if host.Name != test.name { t.Fail() } if ref == esx.HostSystem.Self { t.Error("expected new host Self reference") } pool := Map.Get(*host.Parent).(*mo.ComputeResource).ResourcePool if *pool == esx.ResourcePool.Self { t.Error("expected new pool Self reference") } } if res.State != test.state { t.Fatalf("%s", res.State) } } }