12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049 |
- /*
- Copyright (c) 2014-2017 VMware, Inc. All Rights Reserved.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package find
- import (
- "context"
- "errors"
- "path"
- "strings"
- "github.com/vmware/govmomi/list"
- "github.com/vmware/govmomi/object"
- "github.com/vmware/govmomi/property"
- "github.com/vmware/govmomi/vim25"
- "github.com/vmware/govmomi/vim25/mo"
- "github.com/vmware/govmomi/vim25/types"
- )
- type Finder struct {
- client *vim25.Client
- r recurser
- dc *object.Datacenter
- si *object.SearchIndex
- folders *object.DatacenterFolders
- }
- func NewFinder(client *vim25.Client, all bool) *Finder {
- f := &Finder{
- client: client,
- si: object.NewSearchIndex(client),
- r: recurser{
- Collector: property.DefaultCollector(client),
- All: all,
- },
- }
- return f
- }
- func (f *Finder) SetDatacenter(dc *object.Datacenter) *Finder {
- f.dc = dc
- f.folders = nil
- return f
- }
- // findRoot makes it possible to use "find" mode with a different root path.
- // Example: ResourcePoolList("/dc1/host/cluster1/...")
- func (f *Finder) findRoot(ctx context.Context, root *list.Element, parts []string) bool {
- if len(parts) == 0 {
- return false
- }
- ix := len(parts) - 1
- if parts[ix] != "..." {
- return false
- }
- if ix == 0 {
- return true // We already have the Object for root.Path
- }
- // Lookup the Object for the new root.Path
- rootPath := path.Join(root.Path, path.Join(parts[:ix]...))
- ref, err := f.si.FindByInventoryPath(ctx, rootPath)
- if err != nil || ref == nil {
- // If we get an error or fail to match, fall through to find() with the original root and path
- return false
- }
- root.Path = rootPath
- root.Object = ref
- return true
- }
- func (f *Finder) find(ctx context.Context, arg string, s *spec) ([]list.Element, error) {
- isPath := strings.Contains(arg, "/")
- 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 := s.Relative(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:]
- }
- }
- if s.listMode(isPath) {
- if f.findRoot(ctx, &root, parts) {
- parts = []string{"*"}
- } else {
- return f.r.List(ctx, s, root, parts)
- }
- }
- s.Parents = append(s.Parents, s.Nested...)
- return f.r.Find(ctx, s, root, parts)
- }
- func (f *Finder) datacenter() (*object.Datacenter, error) {
- if f.dc == nil {
- return nil, errors.New("please specify a datacenter")
- }
- return f.dc, nil
- }
- // datacenterPath returns the absolute path to the Datacenter containing the given ref
- func (f *Finder) datacenterPath(ctx context.Context, ref types.ManagedObjectReference) (string, error) {
- mes, err := mo.Ancestors(ctx, f.client, f.client.ServiceContent.PropertyCollector, ref)
- if err != nil {
- return "", err
- }
- // Chop leaves under the Datacenter
- for i := len(mes) - 1; i > 0; i-- {
- if mes[i].Self.Type == "Datacenter" {
- break
- }
- mes = mes[:i]
- }
- var p string
- for _, me := range mes {
- // Skip root entity in building inventory path.
- if me.Parent == nil {
- continue
- }
- p = p + "/" + me.Name
- }
- return p, nil
- }
- func (f *Finder) dcFolders(ctx context.Context) (*object.DatacenterFolders, error) {
- if f.folders != nil {
- return f.folders, nil
- }
- dc, err := f.datacenter()
- if err != nil {
- return nil, err
- }
- folders, err := dc.Folders(ctx)
- if err != nil {
- return nil, err
- }
- f.folders = folders
- return f.folders, nil
- }
- func (f *Finder) dcReference(_ context.Context) (object.Reference, error) {
- dc, err := f.datacenter()
- if err != nil {
- return nil, err
- }
- return dc, nil
- }
- func (f *Finder) vmFolder(ctx context.Context) (object.Reference, error) {
- folders, err := f.dcFolders(ctx)
- if err != nil {
- return nil, err
- }
- return folders.VmFolder, nil
- }
- func (f *Finder) hostFolder(ctx context.Context) (object.Reference, error) {
- folders, err := f.dcFolders(ctx)
- if err != nil {
- return nil, err
- }
- return folders.HostFolder, nil
- }
- func (f *Finder) datastoreFolder(ctx context.Context) (object.Reference, error) {
- folders, err := f.dcFolders(ctx)
- if err != nil {
- return nil, err
- }
- return folders.DatastoreFolder, nil
- }
- func (f *Finder) networkFolder(ctx context.Context) (object.Reference, error) {
- folders, err := f.dcFolders(ctx)
- if err != nil {
- return nil, err
- }
- return folders.NetworkFolder, nil
- }
- func (f *Finder) rootFolder(_ context.Context) (object.Reference, error) {
- return object.NewRootFolder(f.client), nil
- }
- func (f *Finder) managedObjectList(ctx context.Context, path string, tl bool, include []string) ([]list.Element, error) {
- fn := f.rootFolder
- if f.dc != nil {
- fn = f.dcReference
- }
- if len(path) == 0 {
- path = "."
- }
- s := &spec{
- Relative: fn,
- Parents: []string{"ComputeResource", "ClusterComputeResource", "HostSystem", "VirtualApp", "StoragePod"},
- Include: include,
- }
- if tl {
- s.Contents = true
- s.ListMode = types.NewBool(true)
- }
- return f.find(ctx, path, s)
- }
- // Element returns an Element for the given ManagedObjectReference
- // This method is only useful for looking up the InventoryPath of a ManagedObjectReference.
- func (f *Finder) Element(ctx context.Context, ref types.ManagedObjectReference) (*list.Element, error) {
- rl := func(_ context.Context) (object.Reference, error) {
- return ref, nil
- }
- s := &spec{
- Relative: rl,
- }
- e, err := f.find(ctx, "./", s)
- if err != nil {
- return nil, err
- }
- if len(e) == 0 {
- return nil, &NotFoundError{ref.Type, ref.Value}
- }
- if len(e) > 1 {
- panic("ManagedObjectReference must be unique")
- }
- return &e[0], nil
- }
- // ObjectReference converts the given ManagedObjectReference to a type from the object package via object.NewReference
- // with the object.Common.InventoryPath field set.
- func (f *Finder) ObjectReference(ctx context.Context, ref types.ManagedObjectReference) (object.Reference, error) {
- e, err := f.Element(ctx, ref)
- if err != nil {
- return nil, err
- }
- r := object.NewReference(f.client, ref)
- type common interface {
- SetInventoryPath(string)
- }
- r.(common).SetInventoryPath(e.Path)
- if f.dc != nil {
- if ds, ok := r.(*object.Datastore); ok {
- ds.DatacenterPath = f.dc.InventoryPath
- }
- }
- return r, nil
- }
- func (f *Finder) ManagedObjectList(ctx context.Context, path string, include ...string) ([]list.Element, error) {
- return f.managedObjectList(ctx, path, false, include)
- }
- func (f *Finder) ManagedObjectListChildren(ctx context.Context, path string, include ...string) ([]list.Element, error) {
- return f.managedObjectList(ctx, path, true, include)
- }
- func (f *Finder) DatacenterList(ctx context.Context, path string) ([]*object.Datacenter, error) {
- s := &spec{
- Relative: f.rootFolder,
- Include: []string{"Datacenter"},
- }
- es, err := f.find(ctx, path, s)
- if err != nil {
- return nil, err
- }
- var dcs []*object.Datacenter
- for _, e := range es {
- ref := e.Object.Reference()
- if ref.Type == "Datacenter" {
- dc := object.NewDatacenter(f.client, ref)
- dc.InventoryPath = e.Path
- dcs = append(dcs, dc)
- }
- }
- if len(dcs) == 0 {
- return nil, &NotFoundError{"datacenter", path}
- }
- return dcs, nil
- }
- func (f *Finder) Datacenter(ctx context.Context, path string) (*object.Datacenter, error) {
- dcs, err := f.DatacenterList(ctx, path)
- if err != nil {
- return nil, err
- }
- if len(dcs) > 1 {
- return nil, &MultipleFoundError{"datacenter", path}
- }
- return dcs[0], nil
- }
- func (f *Finder) DefaultDatacenter(ctx context.Context) (*object.Datacenter, error) {
- dc, err := f.Datacenter(ctx, "*")
- if err != nil {
- return nil, toDefaultError(err)
- }
- return dc, nil
- }
- func (f *Finder) DatacenterOrDefault(ctx context.Context, path string) (*object.Datacenter, error) {
- if path != "" {
- dc, err := f.Datacenter(ctx, path)
- if err != nil {
- return nil, err
- }
- return dc, nil
- }
- return f.DefaultDatacenter(ctx)
- }
- func (f *Finder) DatastoreList(ctx context.Context, path string) ([]*object.Datastore, error) {
- s := &spec{
- Relative: f.datastoreFolder,
- Parents: []string{"StoragePod"},
- }
- es, err := f.find(ctx, path, s)
- if err != nil {
- return nil, err
- }
- var dss []*object.Datastore
- for _, e := range es {
- ref := e.Object.Reference()
- if ref.Type == "Datastore" {
- ds := object.NewDatastore(f.client, ref)
- ds.InventoryPath = e.Path
- if f.dc == nil {
- // In this case SetDatacenter was not called and path is absolute
- ds.DatacenterPath, err = f.datacenterPath(ctx, ref)
- if err != nil {
- return nil, err
- }
- } else {
- ds.DatacenterPath = f.dc.InventoryPath
- }
- dss = append(dss, ds)
- }
- }
- if len(dss) == 0 {
- return nil, &NotFoundError{"datastore", path}
- }
- return dss, nil
- }
- func (f *Finder) Datastore(ctx context.Context, path string) (*object.Datastore, error) {
- dss, err := f.DatastoreList(ctx, path)
- if err != nil {
- return nil, err
- }
- if len(dss) > 1 {
- return nil, &MultipleFoundError{"datastore", path}
- }
- return dss[0], nil
- }
- func (f *Finder) DefaultDatastore(ctx context.Context) (*object.Datastore, error) {
- ds, err := f.Datastore(ctx, "*")
- if err != nil {
- return nil, toDefaultError(err)
- }
- return ds, nil
- }
- func (f *Finder) DatastoreOrDefault(ctx context.Context, path string) (*object.Datastore, error) {
- if path != "" {
- ds, err := f.Datastore(ctx, path)
- if err != nil {
- return nil, err
- }
- return ds, nil
- }
- return f.DefaultDatastore(ctx)
- }
- func (f *Finder) DatastoreClusterList(ctx context.Context, path string) ([]*object.StoragePod, error) {
- s := &spec{
- Relative: f.datastoreFolder,
- }
- es, err := f.find(ctx, path, s)
- if err != nil {
- return nil, err
- }
- var sps []*object.StoragePod
- for _, e := range es {
- ref := e.Object.Reference()
- if ref.Type == "StoragePod" {
- sp := object.NewStoragePod(f.client, ref)
- sp.InventoryPath = e.Path
- sps = append(sps, sp)
- }
- }
- if len(sps) == 0 {
- return nil, &NotFoundError{"datastore cluster", path}
- }
- return sps, nil
- }
- func (f *Finder) DatastoreCluster(ctx context.Context, path string) (*object.StoragePod, error) {
- sps, err := f.DatastoreClusterList(ctx, path)
- if err != nil {
- return nil, err
- }
- if len(sps) > 1 {
- return nil, &MultipleFoundError{"datastore cluster", path}
- }
- return sps[0], nil
- }
- func (f *Finder) DefaultDatastoreCluster(ctx context.Context) (*object.StoragePod, error) {
- sp, err := f.DatastoreCluster(ctx, "*")
- if err != nil {
- return nil, toDefaultError(err)
- }
- return sp, nil
- }
- func (f *Finder) DatastoreClusterOrDefault(ctx context.Context, path string) (*object.StoragePod, error) {
- if path != "" {
- sp, err := f.DatastoreCluster(ctx, path)
- if err != nil {
- return nil, err
- }
- return sp, nil
- }
- return f.DefaultDatastoreCluster(ctx)
- }
- func (f *Finder) ComputeResourceList(ctx context.Context, path string) ([]*object.ComputeResource, error) {
- s := &spec{
- Relative: f.hostFolder,
- }
- es, err := f.find(ctx, path, s)
- if err != nil {
- return nil, err
- }
- var crs []*object.ComputeResource
- for _, e := range es {
- var cr *object.ComputeResource
- switch o := e.Object.(type) {
- case mo.ComputeResource, mo.ClusterComputeResource:
- cr = object.NewComputeResource(f.client, o.Reference())
- default:
- continue
- }
- cr.InventoryPath = e.Path
- crs = append(crs, cr)
- }
- if len(crs) == 0 {
- return nil, &NotFoundError{"compute resource", path}
- }
- return crs, nil
- }
- func (f *Finder) ComputeResource(ctx context.Context, path string) (*object.ComputeResource, error) {
- crs, err := f.ComputeResourceList(ctx, path)
- if err != nil {
- return nil, err
- }
- if len(crs) > 1 {
- return nil, &MultipleFoundError{"compute resource", path}
- }
- return crs[0], nil
- }
- func (f *Finder) DefaultComputeResource(ctx context.Context) (*object.ComputeResource, error) {
- cr, err := f.ComputeResource(ctx, "*")
- if err != nil {
- return nil, toDefaultError(err)
- }
- return cr, nil
- }
- func (f *Finder) ComputeResourceOrDefault(ctx context.Context, path string) (*object.ComputeResource, error) {
- if path != "" {
- cr, err := f.ComputeResource(ctx, path)
- if err != nil {
- return nil, err
- }
- return cr, nil
- }
- return f.DefaultComputeResource(ctx)
- }
- func (f *Finder) ClusterComputeResourceList(ctx context.Context, path string) ([]*object.ClusterComputeResource, error) {
- s := &spec{
- Relative: f.hostFolder,
- }
- es, err := f.find(ctx, path, s)
- if err != nil {
- return nil, err
- }
- var ccrs []*object.ClusterComputeResource
- for _, e := range es {
- var ccr *object.ClusterComputeResource
- switch o := e.Object.(type) {
- case mo.ClusterComputeResource:
- ccr = object.NewClusterComputeResource(f.client, o.Reference())
- default:
- continue
- }
- ccr.InventoryPath = e.Path
- ccrs = append(ccrs, ccr)
- }
- if len(ccrs) == 0 {
- return nil, &NotFoundError{"cluster", path}
- }
- return ccrs, nil
- }
- func (f *Finder) DefaultClusterComputeResource(ctx context.Context) (*object.ClusterComputeResource, error) {
- cr, err := f.ClusterComputeResource(ctx, "*")
- if err != nil {
- return nil, toDefaultError(err)
- }
- return cr, nil
- }
- func (f *Finder) ClusterComputeResource(ctx context.Context, path string) (*object.ClusterComputeResource, error) {
- ccrs, err := f.ClusterComputeResourceList(ctx, path)
- if err != nil {
- return nil, err
- }
- if len(ccrs) > 1 {
- return nil, &MultipleFoundError{"cluster", path}
- }
- return ccrs[0], nil
- }
- func (f *Finder) ClusterComputeResourceOrDefault(ctx context.Context, path string) (*object.ClusterComputeResource, error) {
- if path != "" {
- cr, err := f.ClusterComputeResource(ctx, path)
- if err != nil {
- return nil, err
- }
- return cr, nil
- }
- return f.DefaultClusterComputeResource(ctx)
- }
- func (f *Finder) HostSystemList(ctx context.Context, path string) ([]*object.HostSystem, error) {
- s := &spec{
- Relative: f.hostFolder,
- Parents: []string{"ComputeResource", "ClusterComputeResource"},
- Include: []string{"HostSystem"},
- }
- es, err := f.find(ctx, path, s)
- if err != nil {
- return nil, err
- }
- var hss []*object.HostSystem
- for _, e := range es {
- var hs *object.HostSystem
- switch o := e.Object.(type) {
- case mo.HostSystem:
- hs = object.NewHostSystem(f.client, o.Reference())
- hs.InventoryPath = e.Path
- hss = append(hss, hs)
- case mo.ComputeResource, mo.ClusterComputeResource:
- cr := object.NewComputeResource(f.client, o.Reference())
- cr.InventoryPath = e.Path
- hosts, err := cr.Hosts(ctx)
- if err != nil {
- return nil, err
- }
- hss = append(hss, hosts...)
- }
- }
- if len(hss) == 0 {
- return nil, &NotFoundError{"host", path}
- }
- return hss, nil
- }
- func (f *Finder) HostSystem(ctx context.Context, path string) (*object.HostSystem, error) {
- hss, err := f.HostSystemList(ctx, path)
- if err != nil {
- return nil, err
- }
- if len(hss) > 1 {
- return nil, &MultipleFoundError{"host", path}
- }
- return hss[0], nil
- }
- func (f *Finder) DefaultHostSystem(ctx context.Context) (*object.HostSystem, error) {
- hs, err := f.HostSystem(ctx, "*")
- if err != nil {
- return nil, toDefaultError(err)
- }
- return hs, nil
- }
- func (f *Finder) HostSystemOrDefault(ctx context.Context, path string) (*object.HostSystem, error) {
- if path != "" {
- hs, err := f.HostSystem(ctx, path)
- if err != nil {
- return nil, err
- }
- return hs, nil
- }
- return f.DefaultHostSystem(ctx)
- }
- func (f *Finder) NetworkList(ctx context.Context, path string) ([]object.NetworkReference, error) {
- s := &spec{
- Relative: f.networkFolder,
- }
- es, err := f.find(ctx, path, s)
- if err != nil {
- return nil, err
- }
- var ns []object.NetworkReference
- for _, e := range es {
- ref := e.Object.Reference()
- switch ref.Type {
- case "Network":
- r := object.NewNetwork(f.client, ref)
- r.InventoryPath = e.Path
- ns = append(ns, r)
- case "OpaqueNetwork":
- r := object.NewOpaqueNetwork(f.client, ref)
- r.InventoryPath = e.Path
- ns = append(ns, r)
- case "DistributedVirtualPortgroup":
- r := object.NewDistributedVirtualPortgroup(f.client, ref)
- r.InventoryPath = e.Path
- ns = append(ns, r)
- case "DistributedVirtualSwitch", "VmwareDistributedVirtualSwitch":
- r := object.NewDistributedVirtualSwitch(f.client, ref)
- r.InventoryPath = e.Path
- ns = append(ns, r)
- }
- }
- if len(ns) == 0 {
- return nil, &NotFoundError{"network", path}
- }
- return ns, nil
- }
- func (f *Finder) Network(ctx context.Context, path string) (object.NetworkReference, error) {
- networks, err := f.NetworkList(ctx, path)
- if err != nil {
- return nil, err
- }
- if len(networks) > 1 {
- return nil, &MultipleFoundError{"network", path}
- }
- return networks[0], nil
- }
- func (f *Finder) DefaultNetwork(ctx context.Context) (object.NetworkReference, error) {
- network, err := f.Network(ctx, "*")
- if err != nil {
- return nil, toDefaultError(err)
- }
- return network, nil
- }
- func (f *Finder) NetworkOrDefault(ctx context.Context, path string) (object.NetworkReference, error) {
- if path != "" {
- network, err := f.Network(ctx, path)
- if err != nil {
- return nil, err
- }
- return network, nil
- }
- return f.DefaultNetwork(ctx)
- }
- func (f *Finder) ResourcePoolList(ctx context.Context, path string) ([]*object.ResourcePool, error) {
- s := &spec{
- Relative: f.hostFolder,
- Parents: []string{"ComputeResource", "ClusterComputeResource", "VirtualApp"},
- Nested: []string{"ResourcePool"},
- Contents: true,
- }
- es, err := f.find(ctx, path, s)
- if err != nil {
- return nil, err
- }
- var rps []*object.ResourcePool
- for _, e := range es {
- var rp *object.ResourcePool
- switch o := e.Object.(type) {
- case mo.ResourcePool:
- rp = object.NewResourcePool(f.client, o.Reference())
- rp.InventoryPath = e.Path
- rps = append(rps, rp)
- }
- }
- if len(rps) == 0 {
- return nil, &NotFoundError{"resource pool", path}
- }
- return rps, nil
- }
- func (f *Finder) ResourcePool(ctx context.Context, path string) (*object.ResourcePool, error) {
- rps, err := f.ResourcePoolList(ctx, path)
- if err != nil {
- return nil, err
- }
- if len(rps) > 1 {
- return nil, &MultipleFoundError{"resource pool", path}
- }
- return rps[0], nil
- }
- func (f *Finder) DefaultResourcePool(ctx context.Context) (*object.ResourcePool, error) {
- rp, err := f.ResourcePool(ctx, "*/Resources")
- if err != nil {
- return nil, toDefaultError(err)
- }
- return rp, nil
- }
- func (f *Finder) ResourcePoolOrDefault(ctx context.Context, path string) (*object.ResourcePool, error) {
- if path != "" {
- rp, err := f.ResourcePool(ctx, path)
- if err != nil {
- return nil, err
- }
- return rp, nil
- }
- return f.DefaultResourcePool(ctx)
- }
- // ResourcePoolListAll combines ResourcePoolList and VirtualAppList
- // VirtualAppList is only called if ResourcePoolList does not find any pools with the given path.
- func (f *Finder) ResourcePoolListAll(ctx context.Context, path string) ([]*object.ResourcePool, error) {
- pools, err := f.ResourcePoolList(ctx, path)
- if err != nil {
- if _, ok := err.(*NotFoundError); !ok {
- return nil, err
- }
- vapps, _ := f.VirtualAppList(ctx, path)
- if len(vapps) == 0 {
- return nil, err
- }
- for _, vapp := range vapps {
- pools = append(pools, vapp.ResourcePool)
- }
- }
- return pools, nil
- }
- func (f *Finder) DefaultFolder(ctx context.Context) (*object.Folder, error) {
- ref, err := f.vmFolder(ctx)
- if err != nil {
- return nil, toDefaultError(err)
- }
- folder := object.NewFolder(f.client, ref.Reference())
- // Set the InventoryPath of the newly created folder object
- // The default foler becomes the datacenter's "vm" folder.
- // The "vm" folder always exists for a datacenter. It cannot be
- // removed or replaced
- folder.SetInventoryPath(path.Join(f.dc.InventoryPath, "vm"))
- return folder, nil
- }
- func (f *Finder) FolderOrDefault(ctx context.Context, path string) (*object.Folder, error) {
- if path != "" {
- folder, err := f.Folder(ctx, path)
- if err != nil {
- return nil, err
- }
- return folder, nil
- }
- return f.DefaultFolder(ctx)
- }
- func (f *Finder) VirtualMachineList(ctx context.Context, path string) ([]*object.VirtualMachine, error) {
- s := &spec{
- Relative: f.vmFolder,
- Parents: []string{"VirtualApp"},
- }
- es, err := f.find(ctx, path, s)
- if err != nil {
- return nil, err
- }
- var vms []*object.VirtualMachine
- for _, e := range es {
- switch o := e.Object.(type) {
- case mo.VirtualMachine:
- vm := object.NewVirtualMachine(f.client, o.Reference())
- vm.InventoryPath = e.Path
- vms = append(vms, vm)
- }
- }
- if len(vms) == 0 {
- return nil, &NotFoundError{"vm", path}
- }
- return vms, nil
- }
- func (f *Finder) VirtualMachine(ctx context.Context, path string) (*object.VirtualMachine, error) {
- vms, err := f.VirtualMachineList(ctx, path)
- if err != nil {
- return nil, err
- }
- if len(vms) > 1 {
- return nil, &MultipleFoundError{"vm", path}
- }
- return vms[0], nil
- }
- func (f *Finder) VirtualAppList(ctx context.Context, path string) ([]*object.VirtualApp, error) {
- s := &spec{
- Relative: f.vmFolder,
- }
- es, err := f.find(ctx, path, s)
- if err != nil {
- return nil, err
- }
- var apps []*object.VirtualApp
- for _, e := range es {
- switch o := e.Object.(type) {
- case mo.VirtualApp:
- app := object.NewVirtualApp(f.client, o.Reference())
- app.InventoryPath = e.Path
- apps = append(apps, app)
- }
- }
- if len(apps) == 0 {
- return nil, &NotFoundError{"app", path}
- }
- return apps, nil
- }
- func (f *Finder) VirtualApp(ctx context.Context, path string) (*object.VirtualApp, error) {
- apps, err := f.VirtualAppList(ctx, path)
- if err != nil {
- return nil, err
- }
- if len(apps) > 1 {
- return nil, &MultipleFoundError{"app", path}
- }
- return apps[0], nil
- }
- func (f *Finder) FolderList(ctx context.Context, path string) ([]*object.Folder, error) {
- es, err := f.ManagedObjectList(ctx, path)
- if err != nil {
- return nil, err
- }
- var folders []*object.Folder
- for _, e := range es {
- switch o := e.Object.(type) {
- case mo.Folder, mo.StoragePod:
- folder := object.NewFolder(f.client, o.Reference())
- folder.InventoryPath = e.Path
- folders = append(folders, folder)
- case *object.Folder:
- // RootFolder
- folders = append(folders, o)
- }
- }
- if len(folders) == 0 {
- return nil, &NotFoundError{"folder", path}
- }
- return folders, nil
- }
- func (f *Finder) Folder(ctx context.Context, path string) (*object.Folder, error) {
- folders, err := f.FolderList(ctx, path)
- if err != nil {
- return nil, err
- }
- if len(folders) > 1 {
- return nil, &MultipleFoundError{"folder", path}
- }
- return folders[0], nil
- }
|