diff --git a/client.go b/client.go index b756e7dac..ae1f925ac 100644 --- a/client.go +++ b/client.go @@ -17,301 +17,75 @@ limitations under the License. package govmomi import ( - "errors" "net/url" - "github.com/vmware/govmomi/vim25/methods" - "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/property" + "github.com/vmware/govmomi/session" + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/soap" "github.com/vmware/govmomi/vim25/types" "golang.org/x/net/context" ) -var serviceInstance = types.ManagedObjectReference{ - Type: "ServiceInstance", - Value: "ServiceInstance", -} - type Client struct { - Client *soap.Client - ServiceContent types.ServiceContent - Session SessionManager -} + *vim25.Client -func getServiceContent(r soap.RoundTripper) (types.ServiceContent, error) { - req := types.RetrieveServiceContent{ - This: serviceInstance, - } - - res, err := methods.RetrieveServiceContent(context.TODO(), r, &req) - if err != nil { - return types.ServiceContent{}, err - } - - return res.Returnval, nil + SessionManager *session.Manager } -func NewClient(u url.URL, insecure bool) (*Client, error) { +// NewClient creates a new client from a URL. The client authenticates with the +// server before returning if the URL contains user information. +func NewClient(ctx context.Context, u *url.URL, insecure bool) (*Client, error) { soapClient := soap.NewClient(u, insecure) - serviceContent, err := getServiceContent(soapClient) + vimClient, err := vim25.NewClient(ctx, soapClient) if err != nil { return nil, err } - c := Client{ - Client: soapClient, - ServiceContent: serviceContent, + c := &Client{ + Client: vimClient, + SessionManager: session.NewManager(vimClient), } - // automatically create a new SessionManager - c.Session = NewSessionManager(&c, *c.ServiceContent.SessionManager) + // Only login if the URL contains user information. if u.User != nil { - err = c.Session.Login(*u.User) + err = c.Login(ctx, u.User) if err != nil { return nil, err } } - return &c, nil -} - -// convience method for logout via SessionManager -func (c *Client) Logout() error { - return c.Session.Logout() -} - -// RoundTrip dispatches to the client's SOAP client RoundTrip function. -func (c *Client) RoundTrip(ctx context.Context, req, res soap.HasFault) error { - return c.Client.RoundTrip(ctx, req, res) -} - -func (c *Client) Properties(obj types.ManagedObjectReference, p []string, dst interface{}) error { - var objs = []types.ManagedObjectReference{obj} - return c.PropertiesN(objs, p, dst) -} - -func (c *Client) PropertiesN(objs []types.ManagedObjectReference, p []string, dst interface{}) error { - var propSpec *types.PropertySpec - var objectSet []types.ObjectSpec - - for _, obj := range objs { - // Ensure that all object reference types are the same - if propSpec == nil { - propSpec = &types.PropertySpec{ - Type: obj.Type, - } - - if p == nil { - propSpec.All = true - } else { - propSpec.PathSet = p - } - } else { - if obj.Type != propSpec.Type { - return errors.New("object references must have the same type") - } - } - - objectSpec := types.ObjectSpec{ - Obj: obj, - Skip: false, - } - - objectSet = append(objectSet, objectSpec) - } - - req := types.RetrieveProperties{ - This: c.ServiceContent.PropertyCollector, - SpecSet: []types.PropertyFilterSpec{ - { - ObjectSet: objectSet, - PropSet: []types.PropertySpec{*propSpec}, - }, - }, - } - - return mo.RetrievePropertiesForRequest(context.TODO(), c, req, dst) -} - -func (c *Client) WaitForProperties(obj types.ManagedObjectReference, ps []string, f func([]types.PropertyChange) bool) error { - p, err := c.NewPropertyCollector() - if err != nil { - return err - } - - defer p.Destroy() - - req := types.CreateFilter{ - Spec: types.PropertyFilterSpec{ - ObjectSet: []types.ObjectSpec{ - { - Obj: obj, - }, - }, - PropSet: []types.PropertySpec{ - { - PathSet: ps, - Type: obj.Type, - }, - }, - }, - } - - err = p.CreateFilter(req) - if err != nil { - return err - } - - for version := ""; ; { - res, err := p.WaitForUpdates(version) - if err != nil { - return err - } - - version = res.Version - - for _, fs := range res.FilterSet { - for _, os := range fs.ObjectSet { - if os.Obj == obj { - if f(os.ChangeSet) { - return nil - } - } - } - } - } -} - -// Ancestors returns the entire ancestry tree of a specified managed object. -// The return value includes the root node and the specified object itself. -func (c *Client) Ancestors(r Reference) ([]mo.ManagedEntity, error) { - ospec := types.ObjectSpec{ - Obj: r.Reference(), - SelectSet: []types.BaseSelectionSpec{ - &types.TraversalSpec{ - SelectionSpec: types.SelectionSpec{Name: "traverseParent"}, - Type: "ManagedEntity", - Path: "parent", - Skip: false, - SelectSet: []types.BaseSelectionSpec{ - &types.SelectionSpec{Name: "traverseParent"}, - }, - }, - }, - Skip: false, - } - - pspec := types.PropertySpec{ - Type: "ManagedEntity", - PathSet: []string{"name", "parent"}, - } - - req := types.RetrieveProperties{ - This: c.ServiceContent.PropertyCollector, - SpecSet: []types.PropertyFilterSpec{ - { - ObjectSet: []types.ObjectSpec{ospec}, - PropSet: []types.PropertySpec{pspec}, - }, - }, - } - - var ifaces []interface{} - - err := mo.RetrievePropertiesForRequest(context.TODO(), c, req, &ifaces) - if err != nil { - return nil, err - } - - var out []mo.ManagedEntity - - // Build ancestry tree by iteratively finding a new child. - for len(out) < len(ifaces) { - var find types.ManagedObjectReference - - if len(out) > 0 { - find = out[len(out)-1].Self - } - - // Find entity we're looking for given the last entity in the current tree. - for _, iface := range ifaces { - me := iface.(mo.IsManagedEntity).GetManagedEntity() - if me.Parent == nil { - out = append(out, me) - break - } - - if *me.Parent == find { - out = append(out, me) - break - } - } - } - - return out, nil -} - -func (c *Client) FileManager() FileManager { - return FileManager{c} -} - -func (c *Client) GuestOperationsManager() GuestOperationsManager { - return GuestOperationsManager{c} + return c, nil } -func (c *Client) OvfManager() OvfManager { - return OvfManager{c} +// Login dispatches to the SessionManager. +func (c *Client) Login(ctx context.Context, u *url.Userinfo) error { + return c.SessionManager.Login(ctx, u) } -func (c *Client) RootFolder() *Folder { - return NewFolder(c, c.ServiceContent.RootFolder) +// Logout dispatches to the SessionManager. +func (c *Client) Logout(ctx context.Context) error { + // Close any idle connections after logging out. + defer c.Client.CloseIdleConnections() + return c.SessionManager.Logout(ctx) } -func (c *Client) SearchIndex() SearchIndex { - return SearchIndex{c} +// PropertyCollector returns the session's default property collector. +func (c *Client) PropertyCollector() *property.Collector { + return property.DefaultCollector(c.Client) } -func (c *Client) VirtualDiskManager() VirtualDiskManager { - return VirtualDiskManager{c} +// RetrieveOne dispatches to the Retrieve function on the default property collector. +func (c *Client) RetrieveOne(ctx context.Context, obj types.ManagedObjectReference, p []string, dst interface{}) error { + return c.PropertyCollector().RetrieveOne(ctx, obj, p, dst) } -func (c *Client) LicenseManager() LicenseManager { - return NewLicenseManager(c, *c.ServiceContent.LicenseManager) +// Retrieve dispatches to the Retrieve function on the default property collector. +func (c *Client) Retrieve(ctx context.Context, objs []types.ManagedObjectReference, p []string, dst interface{}) error { + return c.PropertyCollector().Retrieve(ctx, objs, p, dst) } -func (c *Client) StorageResourceManager() StorageResourceManager { - return StorageResourceManager{c} -} - -func (c *Client) CustomizationSpecManager() CustomizationSpecManager { - return CustomizationSpecManager{c} -} - -func (c *Client) EventManager() EventManager { - return EventManager{c} -} - -// func (c *Client) SessionManager() SessionManager { -// return NewSessionManager(c, *c.ServiceContent.SessionManager) -// } - -// NewPropertyCollector creates a new property collector based on the -// root property collector. It is the responsibility of the caller to -// clean up the property collector when done. -func (c *Client) NewPropertyCollector() (*PropertyCollector, error) { - req := types.CreatePropertyCollector{ - This: c.ServiceContent.PropertyCollector, - } - - res, err := methods.CreatePropertyCollector(context.TODO(), c, &req) - if err != nil { - return nil, err - } - - p := PropertyCollector{ - c: c, - r: res.Returnval, - } - - return &p, nil +// Wait dispatches to property.Wait. +func (c *Client) Wait(ctx context.Context, obj types.ManagedObjectReference, ps []string, f func([]types.PropertyChange) bool) error { + return property.Wait(ctx, c.PropertyCollector(), obj, ps, f) } diff --git a/client_test.go b/client_test.go index 2bfefb367..c6aa7e25c 100644 --- a/client_test.go +++ b/client_test.go @@ -30,24 +30,23 @@ import ( func TestNewClient(t *testing.T) { u := test.URL() - if u == nil { t.SkipNow() } - c, err := NewClient(*u, true) + c, err := NewClient(context.Background(), u, true) if err != nil { t.Error(err) } f := func() error { var x mo.Folder - err = mo.RetrieveProperties(context.TODO(), c, c.ServiceContent.PropertyCollector, c.ServiceContent.RootFolder, &x) + err = mo.RetrieveProperties(context.Background(), c, c.ServiceContent.PropertyCollector, c.ServiceContent.RootFolder, &x) if err != nil { return err } if len(x.Name) == 0 { - return errors.New("invalid response") // TODO: RetrieveProperties should propagate fault + return errors.New("empty response") } return nil } @@ -77,7 +76,7 @@ func TestNewClient(t *testing.T) { // invalid login u.Path = "/sdk" u.User = url.UserPassword("ENOENT", "EINVAL") - _, err = NewClient(*u, true) + _, err = NewClient(context.Background(), u, true) if err == nil { t.Error("should fail") } @@ -91,7 +90,7 @@ func TestInvalidSdk(t *testing.T) { // a URL other than a valid /sdk should error, not panic u.Path = "/mob" - _, err := NewClient(*u, true) + _, err := NewClient(context.Background(), u, true) if err == nil { t.Error("should fail") } @@ -103,19 +102,19 @@ func TestPropertiesN(t *testing.T) { t.SkipNow() } - c, err := NewClient(*u, true) + c, err := NewClient(context.Background(), u, true) if err != nil { t.Error(err) } var f mo.Folder - err = c.Properties(c.ServiceContent.RootFolder, nil, &f) + err = c.RetrieveOne(context.Background(), c.ServiceContent.RootFolder, nil, &f) if err != nil { t.Error(err) } var dc mo.Datacenter - err = c.Properties(f.ChildEntity[0], nil, &dc) + err = c.RetrieveOne(context.Background(), f.ChildEntity[0], nil, &dc) if err != nil { t.Error(err) } @@ -128,7 +127,7 @@ func TestPropertiesN(t *testing.T) { } var folders []mo.Folder - err = c.PropertiesN(folderReferences, []string{"name"}, &folders) + err = c.Retrieve(context.Background(), folderReferences, []string{"name"}, &folders) if err != nil { t.Error(err) } diff --git a/customization_spec_manager.go b/customization_spec_manager.go deleted file mode 100644 index a0b2725e1..000000000 --- a/customization_spec_manager.go +++ /dev/null @@ -1,156 +0,0 @@ -/* -Copyright (c) 2014 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 govmomi - -import ( - "github.com/vmware/govmomi/vim25/methods" - "github.com/vmware/govmomi/vim25/types" - "golang.org/x/net/context" -) - -type CustomizationSpecManager struct { - c *Client -} - -func (cs CustomizationSpecManager) DoesCustomizationSpecExist(name string) (bool, error) { - req := types.DoesCustomizationSpecExist{ - This: *cs.c.ServiceContent.CustomizationSpecManager, - Name: name, - } - - res, err := methods.DoesCustomizationSpecExist(context.TODO(), cs.c, &req) - - if err != nil { - return false, err - } - - return res.Returnval, nil -} - -func (cs CustomizationSpecManager) GetCustomizationSpec(name string) (*types.CustomizationSpecItem, error) { - req := types.GetCustomizationSpec{ - This: *cs.c.ServiceContent.CustomizationSpecManager, - Name: name, - } - - res, err := methods.GetCustomizationSpec(context.TODO(), cs.c, &req) - - if err != nil { - return nil, err - } - - return &res.Returnval, nil -} - -func (cs CustomizationSpecManager) CreateCustomizationSpec(item types.CustomizationSpecItem) error { - req := types.CreateCustomizationSpec{ - This: *cs.c.ServiceContent.CustomizationSpecManager, - Item: item, - } - - _, err := methods.CreateCustomizationSpec(context.TODO(), cs.c, &req) - if err != nil { - return err - } - - return nil -} - -func (cs CustomizationSpecManager) OverwriteCustomizationSpec(item types.CustomizationSpecItem) error { - req := types.OverwriteCustomizationSpec{ - This: *cs.c.ServiceContent.CustomizationSpecManager, - Item: item, - } - - _, err := methods.OverwriteCustomizationSpec(context.TODO(), cs.c, &req) - if err != nil { - return err - } - - return nil -} - -func (cs CustomizationSpecManager) DeleteCustomizationSpec(name string) error { - req := types.DeleteCustomizationSpec{ - This: *cs.c.ServiceContent.CustomizationSpecManager, - Name: name, - } - - _, err := methods.DeleteCustomizationSpec(context.TODO(), cs.c, &req) - if err != nil { - return err - } - - return nil -} - -func (cs CustomizationSpecManager) DuplicateCustomizationSpec(name string, newName string) error { - req := types.DuplicateCustomizationSpec{ - This: *cs.c.ServiceContent.CustomizationSpecManager, - Name: name, - NewName: newName, - } - - _, err := methods.DuplicateCustomizationSpec(context.TODO(), cs.c, &req) - if err != nil { - return err - } - - return nil -} - -func (cs CustomizationSpecManager) RenameCustomizationSpec(name string, newName string) error { - req := types.RenameCustomizationSpec{ - This: *cs.c.ServiceContent.CustomizationSpecManager, - Name: name, - NewName: newName, - } - - _, err := methods.RenameCustomizationSpec(context.TODO(), cs.c, &req) - if err != nil { - return err - } - - return nil -} - -func (cs CustomizationSpecManager) CustomizationSpecItemToXml(item types.CustomizationSpecItem) (string, error) { - req := types.CustomizationSpecItemToXml{ - This: *cs.c.ServiceContent.CustomizationSpecManager, - Item: item, - } - - res, err := methods.CustomizationSpecItemToXml(context.TODO(), cs.c, &req) - if err != nil { - return "", err - } - - return res.Returnval, nil -} - -func (cs CustomizationSpecManager) XmlToCustomizationSpecItem(xml string) (*types.CustomizationSpecItem, error) { - req := types.XmlToCustomizationSpecItem{ - This: *cs.c.ServiceContent.CustomizationSpecManager, - SpecItemXml: xml, - } - - res, err := methods.XmlToCustomizationSpecItem(context.TODO(), cs.c, &req) - if err != nil { - return nil, err - } - return &res.Returnval, nil -} diff --git a/event_manager.go b/event/manager.go similarity index 52% rename from event_manager.go rename to event/manager.go index 67af698a1..82e7d51a7 100644 --- a/event_manager.go +++ b/event/manager.go @@ -14,39 +14,53 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package event import ( + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/types" "golang.org/x/net/context" ) -type EventManager struct { - c *Client +type Manager struct { + reference types.ManagedObjectReference + + c *vim25.Client +} + +func NewManager(c *vim25.Client) *Manager { + m := Manager{ + reference: *c.ServiceContent.EventManager, + + c: c, + } + + return &m } -func (em EventManager) CreateCollectorForEvents(filter types.EventFilterSpec) (*types.ManagedObjectReference, error) { +func (m Manager) CreateCollectorForEvents(ctx context.Context, filter types.EventFilterSpec) (*types.ManagedObjectReference, error) { req := types.CreateCollectorForEvents{ - This: *em.c.ServiceContent.EventManager, + This: m.reference, Filter: filter, } - res, err := methods.CreateCollectorForEvents(context.TODO(), em.c, &req) + res, err := methods.CreateCollectorForEvents(ctx, m.c, &req) if err != nil { return nil, err } + return &res.Returnval, nil } -func (em EventManager) LogUserEvent(entity types.ManagedObjectReference, msg string) error { +func (m Manager) LogUserEvent(ctx context.Context, entity types.ManagedObjectReference, msg string) error { req := types.LogUserEvent{ - This: *em.c.ServiceContent.EventManager, + This: m.reference, Entity: entity, Msg: msg, } - _, err := methods.LogUserEvent(context.TODO(), em.c, &req) + _, err := methods.LogUserEvent(ctx, m.c, &req) if err != nil { return err } @@ -54,14 +68,14 @@ func (em EventManager) LogUserEvent(entity types.ManagedObjectReference, msg str return nil } -func (em EventManager) PostEvent(eventToPost types.BaseEvent, taskInfo types.TaskInfo) error { +func (m Manager) PostEvent(ctx context.Context, eventToPost types.BaseEvent, taskInfo types.TaskInfo) error { req := types.PostEvent{ - This: *em.c.ServiceContent.EventManager, + This: m.reference, EventToPost: eventToPost, TaskInfo: &taskInfo, } - _, err := methods.PostEvent(context.TODO(), em.c, &req) + _, err := methods.PostEvent(ctx, m.c, &req) if err != nil { return err } @@ -69,29 +83,30 @@ func (em EventManager) PostEvent(eventToPost types.BaseEvent, taskInfo types.Tas return nil } -func (em EventManager) QueryEvents(filter types.EventFilterSpec) ([]types.BaseEvent, error) { +func (m Manager) QueryEvents(ctx context.Context, filter types.EventFilterSpec) ([]types.BaseEvent, error) { req := types.QueryEvents{ - This: *em.c.ServiceContent.EventManager, + This: m.reference, Filter: filter, } - res, err := methods.QueryEvents(context.TODO(), em.c, &req) + res, err := methods.QueryEvents(ctx, m.c, &req) if err != nil { return nil, err } + return res.Returnval, nil } -func (em EventManager) RetrieveArgumentDescription(eventTypeID string) ([]types.EventArgDesc, error) { +func (m Manager) RetrieveArgumentDescription(ctx context.Context, eventTypeID string) ([]types.EventArgDesc, error) { req := types.RetrieveArgumentDescription{ - This: *em.c.ServiceContent.EventManager, + This: m.reference, EventTypeId: eventTypeID, } - res, err := methods.RetrieveArgumentDescription(context.TODO(), em.c, &req) + res, err := methods.RetrieveArgumentDescription(ctx, m.c, &req) if err != nil { return nil, err } - return res.Returnval, nil + return res.Returnval, nil } diff --git a/find/finder.go b/find/finder.go index 3dc111236..deb33bfec 100644 --- a/find/finder.go +++ b/find/finder.go @@ -20,39 +20,47 @@ import ( "errors" "path" - "github.com/vmware/govmomi" "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" + "golang.org/x/net/context" ) type Finder struct { - list.Recurser - dc *govmomi.Datacenter - folders *govmomi.DatacenterFolders + client *vim25.Client + recurser list.Recurser + + dc *object.Datacenter + folders *object.DatacenterFolders } -func NewFinder(c *govmomi.Client, all bool) *Finder { - return &Finder{ - Recurser: list.Recurser{ - Client: c, - All: all, +func NewFinder(client *vim25.Client, all bool) *Finder { + f := &Finder{ + client: client, + recurser: list.Recurser{ + Collector: property.DefaultCollector(client), + All: all, }, } + + return f } -func (f *Finder) SetDatacenter(dc *govmomi.Datacenter) *Finder { +func (f *Finder) SetDatacenter(dc *object.Datacenter) *Finder { f.dc = dc f.folders = nil return f } -type findRelativeFunc func() (govmomi.Reference, error) +type findRelativeFunc func(ctx context.Context) (object.Reference, error) -func (f *Finder) find(fn findRelativeFunc, tl bool, path ...string) ([]list.Element, error) { +func (f *Finder) find(ctx context.Context, fn findRelativeFunc, tl bool, path ...string) ([]list.Element, error) { var out []list.Element for _, arg := range path { - es, err := f.list(fn, tl, arg) + es, err := f.list(ctx, fn, tl, arg) if err != nil { return nil, err } @@ -63,10 +71,10 @@ func (f *Finder) find(fn findRelativeFunc, tl bool, path ...string) ([]list.Elem return out, nil } -func (f *Finder) list(fn findRelativeFunc, tl bool, arg string) ([]list.Element, error) { +func (f *Finder) list(ctx context.Context, fn findRelativeFunc, tl bool, arg string) ([]list.Element, error) { root := list.Element{ Path: "/", - Object: f.Client.RootFolder(), + Object: object.NewRootFolder(f.client), } parts := list.ToParts(arg) @@ -76,12 +84,12 @@ func (f *Finder) list(fn findRelativeFunc, tl bool, arg string) ([]list.Element, case "..": // Not supported; many edge case, little value return nil, errors.New("cannot traverse up a tree") case ".": // Relative to whatever - pivot, err := fn() + pivot, err := fn(ctx) if err != nil { return nil, err } - mes, err := f.Client.Ancestors(pivot) + mes, err := mo.Ancestors(ctx, f.client, f.client.ServiceContent.PropertyCollector, pivot.Reference()) if err != nil { return nil, err } @@ -99,8 +107,8 @@ func (f *Finder) list(fn findRelativeFunc, tl bool, arg string) ([]list.Element, } } - f.TraverseLeafs = tl - es, err := f.Recurse(root, parts) + f.recurser.TraverseLeafs = tl + es, err := f.recurser.Recurse(ctx, root, parts) if err != nil { return nil, err } @@ -108,7 +116,7 @@ func (f *Finder) list(fn findRelativeFunc, tl bool, arg string) ([]list.Element, return es, nil } -func (f *Finder) datacenter() (*govmomi.Datacenter, error) { +func (f *Finder) datacenter() (*object.Datacenter, error) { if f.dc == nil { return nil, errors.New("please specify a datacenter") } @@ -116,7 +124,7 @@ func (f *Finder) datacenter() (*govmomi.Datacenter, error) { return f.dc, nil } -func (f *Finder) dcFolders() (*govmomi.DatacenterFolders, error) { +func (f *Finder) dcFolders(ctx context.Context) (*object.DatacenterFolders, error) { if f.folders != nil { return f.folders, nil } @@ -126,7 +134,7 @@ func (f *Finder) dcFolders() (*govmomi.DatacenterFolders, error) { return nil, err } - folders, err := dc.Folders() + folders, err := dc.Folders(ctx) if err != nil { return nil, err } @@ -136,7 +144,7 @@ func (f *Finder) dcFolders() (*govmomi.DatacenterFolders, error) { return f.folders, nil } -func (f *Finder) dcReference() (govmomi.Reference, error) { +func (f *Finder) dcReference(_ context.Context) (object.Reference, error) { dc, err := f.datacenter() if err != nil { return nil, err @@ -145,8 +153,8 @@ func (f *Finder) dcReference() (govmomi.Reference, error) { return dc, nil } -func (f *Finder) vmFolder() (govmomi.Reference, error) { - folders, err := f.dcFolders() +func (f *Finder) vmFolder(ctx context.Context) (object.Reference, error) { + folders, err := f.dcFolders(ctx) if err != nil { return nil, err } @@ -154,8 +162,8 @@ func (f *Finder) vmFolder() (govmomi.Reference, error) { return folders.VmFolder, nil } -func (f *Finder) hostFolder() (govmomi.Reference, error) { - folders, err := f.dcFolders() +func (f *Finder) hostFolder(ctx context.Context) (object.Reference, error) { + folders, err := f.dcFolders(ctx) if err != nil { return nil, err } @@ -163,8 +171,8 @@ func (f *Finder) hostFolder() (govmomi.Reference, error) { return folders.HostFolder, nil } -func (f *Finder) datastoreFolder() (govmomi.Reference, error) { - folders, err := f.dcFolders() +func (f *Finder) datastoreFolder(ctx context.Context) (object.Reference, error) { + folders, err := f.dcFolders(ctx) if err != nil { return nil, err } @@ -172,8 +180,8 @@ func (f *Finder) datastoreFolder() (govmomi.Reference, error) { return folders.DatastoreFolder, nil } -func (f *Finder) networkFolder() (govmomi.Reference, error) { - folders, err := f.dcFolders() +func (f *Finder) networkFolder(ctx context.Context) (object.Reference, error) { + folders, err := f.dcFolders(ctx) if err != nil { return nil, err } @@ -181,11 +189,11 @@ func (f *Finder) networkFolder() (govmomi.Reference, error) { return folders.NetworkFolder, nil } -func (f *Finder) rootFolder() (govmomi.Reference, error) { - return f.Client.RootFolder(), nil +func (f *Finder) rootFolder(_ context.Context) (object.Reference, error) { + return object.NewRootFolder(f.client), nil } -func (f *Finder) ManagedObjectList(path ...string) ([]list.Element, error) { +func (f *Finder) ManagedObjectList(ctx context.Context, path ...string) ([]list.Element, error) { fn := f.rootFolder if f.dc != nil { @@ -196,28 +204,28 @@ func (f *Finder) ManagedObjectList(path ...string) ([]list.Element, error) { path = []string{"."} } - return f.find(fn, true, path...) + return f.find(ctx, fn, true, path...) } -func (f *Finder) DatacenterList(path ...string) ([]*govmomi.Datacenter, error) { - es, err := f.find(f.rootFolder, false, path...) +func (f *Finder) DatacenterList(ctx context.Context, path ...string) ([]*object.Datacenter, error) { + es, err := f.find(ctx, f.rootFolder, false, path...) if err != nil { return nil, err } - var dcs []*govmomi.Datacenter + var dcs []*object.Datacenter for _, e := range es { ref := e.Object.Reference() if ref.Type == "Datacenter" { - dcs = append(dcs, govmomi.NewDatacenter(f.Client, ref)) + dcs = append(dcs, object.NewDatacenter(f.client, ref)) } } return dcs, nil } -func (f *Finder) Datacenter(path string) (*govmomi.Datacenter, error) { - dcs, err := f.DatacenterList(path) +func (f *Finder) Datacenter(ctx context.Context, path string) (*object.Datacenter, error) { + dcs, err := f.DatacenterList(ctx, path) if err != nil { return nil, err } @@ -233,8 +241,8 @@ func (f *Finder) Datacenter(path string) (*govmomi.Datacenter, error) { return dcs[0], nil } -func (f *Finder) DefaultDatacenter() (*govmomi.Datacenter, error) { - dc, err := f.Datacenter("*") +func (f *Finder) DefaultDatacenter(ctx context.Context) (*object.Datacenter, error) { + dc, err := f.Datacenter(ctx, "*") if err != nil { return nil, toDefaultError(err) } @@ -242,17 +250,17 @@ func (f *Finder) DefaultDatacenter() (*govmomi.Datacenter, error) { return dc, nil } -func (f *Finder) DatastoreList(path ...string) ([]*govmomi.Datastore, error) { - es, err := f.find(f.datastoreFolder, false, path...) +func (f *Finder) DatastoreList(ctx context.Context, path ...string) ([]*object.Datastore, error) { + es, err := f.find(ctx, f.datastoreFolder, false, path...) if err != nil { return nil, err } - var dss []*govmomi.Datastore + var dss []*object.Datastore for _, e := range es { ref := e.Object.Reference() if ref.Type == "Datastore" { - ds := govmomi.NewDatastore(f.Client, ref) + ds := object.NewDatastore(f.client, ref) ds.InventoryPath = e.Path dss = append(dss, ds) @@ -262,8 +270,8 @@ func (f *Finder) DatastoreList(path ...string) ([]*govmomi.Datastore, error) { return dss, nil } -func (f *Finder) Datastore(path string) (*govmomi.Datastore, error) { - dss, err := f.DatastoreList(path) +func (f *Finder) Datastore(ctx context.Context, path string) (*object.Datastore, error) { + dss, err := f.DatastoreList(ctx, path) if err != nil { return nil, err } @@ -279,8 +287,8 @@ func (f *Finder) Datastore(path string) (*govmomi.Datastore, error) { return dss[0], nil } -func (f *Finder) DefaultDatastore() (*govmomi.Datastore, error) { - ds, err := f.Datastore("*") +func (f *Finder) DefaultDatastore(ctx context.Context) (*object.Datastore, error) { + ds, err := f.Datastore(ctx, "*") if err != nil { return nil, toDefaultError(err) } @@ -288,26 +296,26 @@ func (f *Finder) DefaultDatastore() (*govmomi.Datastore, error) { return ds, nil } -func (f *Finder) HostSystemList(path ...string) ([]*govmomi.HostSystem, error) { - es, err := f.find(f.hostFolder, false, path...) +func (f *Finder) HostSystemList(ctx context.Context, path ...string) ([]*object.HostSystem, error) { + es, err := f.find(ctx, f.hostFolder, false, path...) if err != nil { return nil, err } - var hss []*govmomi.HostSystem + var hss []*object.HostSystem for _, e := range es { - var hs *govmomi.HostSystem + var hs *object.HostSystem switch o := e.Object.(type) { case mo.HostSystem: - hs = govmomi.NewHostSystem(f.Client, o.Reference()) + hs = object.NewHostSystem(f.client, o.Reference()) case mo.ComputeResource: - cr := govmomi.NewComputeResource(f.Client, o.Reference()) - hosts, err := cr.Hosts() + cr := object.NewComputeResource(f.client, o.Reference()) + hosts, err := cr.Hosts(ctx) if err != nil { return nil, err } - hs = govmomi.NewHostSystem(f.Client, hosts[0]) + hs = object.NewHostSystem(f.client, hosts[0]) default: continue } @@ -319,8 +327,8 @@ func (f *Finder) HostSystemList(path ...string) ([]*govmomi.HostSystem, error) { return hss, nil } -func (f *Finder) HostSystem(path string) (*govmomi.HostSystem, error) { - hss, err := f.HostSystemList(path) +func (f *Finder) HostSystem(ctx context.Context, path string) (*object.HostSystem, error) { + hss, err := f.HostSystemList(ctx, path) if err != nil { return nil, err } @@ -336,8 +344,8 @@ func (f *Finder) HostSystem(path string) (*govmomi.HostSystem, error) { return hss[0], nil } -func (f *Finder) DefaultHostSystem() (*govmomi.HostSystem, error) { - hs, err := f.HostSystem("*/*") +func (f *Finder) DefaultHostSystem(ctx context.Context) (*object.HostSystem, error) { + hs, err := f.HostSystem(ctx, "*/*") if err != nil { return nil, toDefaultError(err) } @@ -345,22 +353,22 @@ func (f *Finder) DefaultHostSystem() (*govmomi.HostSystem, error) { return hs, nil } -func (f *Finder) NetworkList(path ...string) ([]govmomi.NetworkReference, error) { - es, err := f.find(f.networkFolder, false, path...) +func (f *Finder) NetworkList(ctx context.Context, path ...string) ([]object.NetworkReference, error) { + es, err := f.find(ctx, f.networkFolder, false, path...) if err != nil { return nil, err } - var ns []govmomi.NetworkReference + var ns []object.NetworkReference for _, e := range es { ref := e.Object.Reference() switch ref.Type { case "Network": - r := govmomi.NewNetwork(f.Client, ref) + r := object.NewNetwork(f.client, ref) r.InventoryPath = e.Path ns = append(ns, r) case "DistributedVirtualPortgroup": - r := govmomi.NewDistributedVirtualPortgroup(f.Client, ref) + r := object.NewDistributedVirtualPortgroup(f.client, ref) r.InventoryPath = e.Path ns = append(ns, r) } @@ -369,8 +377,8 @@ func (f *Finder) NetworkList(path ...string) ([]govmomi.NetworkReference, error) return ns, nil } -func (f *Finder) Network(path string) (govmomi.NetworkReference, error) { - networks, err := f.NetworkList(path) +func (f *Finder) Network(ctx context.Context, path string) (object.NetworkReference, error) { + networks, err := f.NetworkList(ctx, path) if err != nil { return nil, err } @@ -386,8 +394,8 @@ func (f *Finder) Network(path string) (govmomi.NetworkReference, error) { return networks[0], nil } -func (f *Finder) DefaultNetwork() (govmomi.NetworkReference, error) { - network, err := f.Network("*") +func (f *Finder) DefaultNetwork(ctx context.Context) (object.NetworkReference, error) { + network, err := f.Network(ctx, "*") if err != nil { return nil, toDefaultError(err) } @@ -395,19 +403,19 @@ func (f *Finder) DefaultNetwork() (govmomi.NetworkReference, error) { return network, nil } -func (f *Finder) ResourcePoolList(path ...string) ([]*govmomi.ResourcePool, error) { - es, err := f.find(f.hostFolder, true, path...) +func (f *Finder) ResourcePoolList(ctx context.Context, path ...string) ([]*object.ResourcePool, error) { + es, err := f.find(ctx, f.hostFolder, true, path...) if err != nil { return nil, err } - var rps []*govmomi.ResourcePool + var rps []*object.ResourcePool for _, e := range es { - var rp *govmomi.ResourcePool + var rp *object.ResourcePool switch o := e.Object.(type) { case mo.ResourcePool: - rp = govmomi.NewResourcePool(f.Client, o.Reference()) + rp = object.NewResourcePool(f.client, o.Reference()) rp.InventoryPath = e.Path rps = append(rps, rp) } @@ -416,8 +424,8 @@ func (f *Finder) ResourcePoolList(path ...string) ([]*govmomi.ResourcePool, erro return rps, nil } -func (f *Finder) ResourcePool(path string) (*govmomi.ResourcePool, error) { - rps, err := f.ResourcePoolList(path) +func (f *Finder) ResourcePool(ctx context.Context, path string) (*object.ResourcePool, error) { + rps, err := f.ResourcePoolList(ctx, path) if err != nil { return nil, err } @@ -433,8 +441,8 @@ func (f *Finder) ResourcePool(path string) (*govmomi.ResourcePool, error) { return rps[0], nil } -func (f *Finder) DefaultResourcePool() (*govmomi.ResourcePool, error) { - rp, err := f.ResourcePool("*/Resources") +func (f *Finder) DefaultResourcePool(ctx context.Context) (*object.ResourcePool, error) { + rp, err := f.ResourcePool(ctx, "*/Resources") if err != nil { return nil, toDefaultError(err) } @@ -442,17 +450,17 @@ func (f *Finder) DefaultResourcePool() (*govmomi.ResourcePool, error) { return rp, nil } -func (f *Finder) VirtualMachineList(path ...string) ([]*govmomi.VirtualMachine, error) { - es, err := f.find(f.vmFolder, false, path...) +func (f *Finder) VirtualMachineList(ctx context.Context, path ...string) ([]*object.VirtualMachine, error) { + es, err := f.find(ctx, f.vmFolder, false, path...) if err != nil { return nil, err } - var vms []*govmomi.VirtualMachine + var vms []*object.VirtualMachine for _, e := range es { switch o := e.Object.(type) { case mo.VirtualMachine: - vm := govmomi.NewVirtualMachine(f.Client, o.Reference()) + vm := object.NewVirtualMachine(f.client, o.Reference()) vm.InventoryPath = e.Path vms = append(vms, vm) } @@ -461,8 +469,8 @@ func (f *Finder) VirtualMachineList(path ...string) ([]*govmomi.VirtualMachine, return vms, nil } -func (f *Finder) VirtualMachine(path string) (*govmomi.VirtualMachine, error) { - vms, err := f.VirtualMachineList(path) +func (f *Finder) VirtualMachine(ctx context.Context, path string) (*object.VirtualMachine, error) { + vms, err := f.VirtualMachineList(ctx, path) if err != nil { return nil, err } diff --git a/govc/datacenter/create.go b/govc/datacenter/create.go index eeea1ca90..bf87dae42 100644 --- a/govc/datacenter/create.go +++ b/govc/datacenter/create.go @@ -22,6 +22,8 @@ import ( "github.com/vmware/govmomi/find" "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/object" + "golang.org/x/net/context" ) type create struct { @@ -52,15 +54,15 @@ func (cmd *create) Run(f *flag.FlagSet) error { } finder := find.NewFinder(client, false) - rootFolder := client.RootFolder() + rootFolder := object.NewRootFolder(client) for _, datacenterToCreate := range datacenters { - foundDatacenters, err := finder.DatacenterList(datacenterToCreate) + foundDatacenters, err := finder.DatacenterList(context.TODO(), datacenterToCreate) if err != nil { return err } if foundDatacenters == nil { - _, err = rootFolder.CreateDatacenter(datacenterToCreate) + _, err = rootFolder.CreateDatacenter(context.TODO(), datacenterToCreate) if err != nil { return err } diff --git a/govc/datacenter/destroy.go b/govc/datacenter/destroy.go index 9fef018de..12362ede4 100644 --- a/govc/datacenter/destroy.go +++ b/govc/datacenter/destroy.go @@ -22,6 +22,7 @@ import ( "github.com/vmware/govmomi/find" "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type destroy struct { @@ -53,17 +54,17 @@ func (cmd *destroy) Run(f *flag.FlagSet) error { finder := find.NewFinder(client, false) for _, datacenterToDestroy := range datacentersToDestroy { - foundDatacenters, err := finder.DatacenterList(datacenterToDestroy) + foundDatacenters, err := finder.DatacenterList(context.TODO(), datacenterToDestroy) if err != nil { return err } for _, foundDatacenter := range foundDatacenters { - task, err := foundDatacenter.Destroy() + task, err := foundDatacenter.Destroy(context.TODO()) if err != nil { return err } - if err := task.Wait(); err != nil { + if err := task.Wait(context.TODO()); err != nil { return err } } diff --git a/govc/datastore/cp.go b/govc/datastore/cp.go index 6ab20eac5..d289fb64f 100644 --- a/govc/datastore/cp.go +++ b/govc/datastore/cp.go @@ -22,6 +22,8 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/object" + "golang.org/x/net/context" ) type cp struct { @@ -73,10 +75,11 @@ func (cmd *cp) Run(f *flag.FlagSet) error { return err } - task, err := c.FileManager().CopyDatastoreFile(src, dc, dst, dc, cmd.force) + m := object.NewFileManager(c) + task, err := m.CopyDatastoreFile(context.TODO(), src, dc, dst, dc, cmd.force) if err != nil { return err } - return task.Wait() + return task.Wait(context.TODO()) } diff --git a/govc/datastore/ls.go b/govc/datastore/ls.go index 1442bdeae..35f55df52 100644 --- a/govc/datastore/ls.go +++ b/govc/datastore/ls.go @@ -24,10 +24,11 @@ import ( "path" "text/tabwriter" - "github.com/vmware/govmomi" "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/object" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type ls struct { @@ -57,7 +58,7 @@ func (cmd *ls) Run(f *flag.FlagSet) error { return err } - b, err := ds.Browser() + b, err := ds.Browser(context.TODO()) if err != nil { return err } @@ -90,7 +91,7 @@ func (cmd *ls) Run(f *flag.FlagSet) error { r, err := cmd.ListPath(b, arg, spec) if err != nil { // Treat the argument as a match pattern if not found as directory - if i == 0 && govmomi.IsFileNotFound(err) { + if i == 0 && types.IsFileNotFound(err) { spec.MatchPattern[0] = path.Base(arg) arg = path.Dir(arg) continue @@ -112,7 +113,7 @@ func (cmd *ls) Run(f *flag.FlagSet) error { return cmd.WriteResult(result) } -func (cmd *ls) ListPath(b *govmomi.HostDatastoreBrowser, path string, spec types.HostDatastoreBrowserSearchSpec) (types.HostDatastoreBrowserSearchResults, error) { +func (cmd *ls) ListPath(b *object.HostDatastoreBrowser, path string, spec types.HostDatastoreBrowserSearchSpec) (types.HostDatastoreBrowserSearchResults, error) { var res types.HostDatastoreBrowserSearchResults path, err := cmd.DatastorePath(path) @@ -120,12 +121,12 @@ func (cmd *ls) ListPath(b *govmomi.HostDatastoreBrowser, path string, spec types return res, err } - task, err := b.SearchDatastore(path, &spec) + task, err := b.SearchDatastore(context.TODO(), path, &spec) if err != nil { return res, err } - info, err := task.WaitForResult(nil) + info, err := task.WaitForResult(context.TODO(), nil) if err != nil { return res, err } diff --git a/govc/datastore/mkdir.go b/govc/datastore/mkdir.go index 851e6c8d5..3ee546f54 100644 --- a/govc/datastore/mkdir.go +++ b/govc/datastore/mkdir.go @@ -22,8 +22,10 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/object" "github.com/vmware/govmomi/vim25/soap" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type mkdir struct { @@ -68,7 +70,8 @@ func (cmd *mkdir) Run(f *flag.FlagSet) error { return err } - err = c.FileManager().MakeDirectory(path, dc, cmd.createParents) + m := object.NewFileManager(c) + err = m.MakeDirectory(context.TODO(), path, dc, cmd.createParents) // ignore EEXIST if -p flag is given if err != nil && cmd.createParents { diff --git a/govc/datastore/mv.go b/govc/datastore/mv.go index 59a2583ce..0e5f2ad01 100644 --- a/govc/datastore/mv.go +++ b/govc/datastore/mv.go @@ -22,6 +22,8 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/object" + "golang.org/x/net/context" ) type mv struct { @@ -72,10 +74,11 @@ func (cmd *mv) Run(f *flag.FlagSet) error { return err } - task, err := c.FileManager().MoveDatastoreFile(src, dc, dst, dc, cmd.force) + m := object.NewFileManager(c) + task, err := m.MoveDatastoreFile(context.TODO(), src, dc, dst, dc, cmd.force) if err != nil { return err } - return task.Wait() + return task.Wait(context.TODO()) } diff --git a/govc/datastore/rm.go b/govc/datastore/rm.go index 1983d673e..1207f7cc9 100644 --- a/govc/datastore/rm.go +++ b/govc/datastore/rm.go @@ -20,9 +20,11 @@ import ( "errors" "flag" - "github.com/vmware/govmomi" "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type rm struct { @@ -68,14 +70,15 @@ func (cmd *rm) Run(f *flag.FlagSet) error { return err } - task, err := c.FileManager().DeleteDatastoreFile(path, dc) + m := object.NewFileManager(c) + task, err := m.DeleteDatastoreFile(context.TODO(), path, dc) if err != nil { return err } - err = task.Wait() + err = task.Wait(context.TODO()) if err != nil { - if govmomi.IsFileNotFound(err) && cmd.force { + if types.IsFileNotFound(err) && cmd.force { // Ignore error return nil } diff --git a/govc/device/boot.go b/govc/device/boot.go index 81ae8a508..aea42e7a9 100644 --- a/govc/device/boot.go +++ b/govc/device/boot.go @@ -23,6 +23,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type boot struct { @@ -56,7 +57,7 @@ func (cmd *boot) Run(f *flag.FlagSet) error { return flag.ErrHelp } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -66,5 +67,5 @@ func (cmd *boot) Run(f *flag.FlagSet) error { cmd.BootOrder = devices.BootOrder(o) } - return vm.SetBootOptions(&cmd.VirtualMachineBootOptions) + return vm.SetBootOptions(context.TODO(), &cmd.VirtualMachineBootOptions) } diff --git a/govc/device/cdrom/add.go b/govc/device/cdrom/add.go index 2dd4974fd..6d18cb096 100644 --- a/govc/device/cdrom/add.go +++ b/govc/device/cdrom/add.go @@ -22,6 +22,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type add struct { @@ -50,7 +51,7 @@ func (cmd *add) Run(f *flag.FlagSet) error { return flag.ErrHelp } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -65,13 +66,13 @@ func (cmd *add) Run(f *flag.FlagSet) error { return err } - err = vm.AddDevice(d) + err = vm.AddDevice(context.TODO(), d) if err != nil { return err } // output name of device we just created - devices, err = vm.Device() + devices, err = vm.Device(context.TODO()) if err != nil { return err } diff --git a/govc/device/cdrom/eject.go b/govc/device/cdrom/eject.go index 3f63c8c7c..edbd29107 100644 --- a/govc/device/cdrom/eject.go +++ b/govc/device/cdrom/eject.go @@ -21,6 +21,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type eject struct { @@ -55,7 +56,7 @@ func (cmd *eject) Run(f *flag.FlagSet) error { return flag.ErrHelp } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -65,5 +66,5 @@ func (cmd *eject) Run(f *flag.FlagSet) error { return err } - return vm.EditDevice(devices.EjectIso(c)) + return vm.EditDevice(context.TODO(), devices.EjectIso(c)) } diff --git a/govc/device/cdrom/insert.go b/govc/device/cdrom/insert.go index cfaab91e6..018c13582 100644 --- a/govc/device/cdrom/insert.go +++ b/govc/device/cdrom/insert.go @@ -21,6 +21,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type insert struct { @@ -60,7 +61,7 @@ func (cmd *insert) Run(f *flag.FlagSet) error { return flag.ErrHelp } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -75,5 +76,5 @@ func (cmd *insert) Run(f *flag.FlagSet) error { return nil } - return vm.EditDevice(devices.InsertIso(c, iso)) + return vm.EditDevice(context.TODO(), devices.InsertIso(c, iso)) } diff --git a/govc/device/connect.go b/govc/device/connect.go index 695d087f4..f6a8a19a9 100644 --- a/govc/device/connect.go +++ b/govc/device/connect.go @@ -22,6 +22,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type connect struct { @@ -50,7 +51,7 @@ func (cmd *connect) Run(f *flag.FlagSet) error { return flag.ErrHelp } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -65,7 +66,7 @@ func (cmd *connect) Run(f *flag.FlagSet) error { return err } - if err = vm.EditDevice(device); err != nil { + if err = vm.EditDevice(context.TODO(), device); err != nil { return err } } diff --git a/govc/device/disconnect.go b/govc/device/disconnect.go index a6a55554e..9fd95fb75 100644 --- a/govc/device/disconnect.go +++ b/govc/device/disconnect.go @@ -22,6 +22,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type disconnect struct { @@ -50,7 +51,7 @@ func (cmd *disconnect) Run(f *flag.FlagSet) error { return flag.ErrHelp } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -65,7 +66,7 @@ func (cmd *disconnect) Run(f *flag.FlagSet) error { return err } - if err = vm.EditDevice(device); err != nil { + if err = vm.EditDevice(context.TODO(), device); err != nil { return err } } diff --git a/govc/device/floppy/add.go b/govc/device/floppy/add.go index 4bb27e192..660fa3cbd 100644 --- a/govc/device/floppy/add.go +++ b/govc/device/floppy/add.go @@ -22,6 +22,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type add struct { @@ -46,7 +47,7 @@ func (cmd *add) Run(f *flag.FlagSet) error { return flag.ErrHelp } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -56,13 +57,13 @@ func (cmd *add) Run(f *flag.FlagSet) error { return err } - err = vm.AddDevice(d) + err = vm.AddDevice(context.TODO(), d) if err != nil { return err } // output name of device we just created - devices, err = vm.Device() + devices, err = vm.Device(context.TODO()) if err != nil { return err } diff --git a/govc/device/floppy/eject.go b/govc/device/floppy/eject.go index c553de7c8..dd9541adf 100644 --- a/govc/device/floppy/eject.go +++ b/govc/device/floppy/eject.go @@ -21,6 +21,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type eject struct { @@ -55,7 +56,7 @@ func (cmd *eject) Run(f *flag.FlagSet) error { return flag.ErrHelp } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -65,5 +66,5 @@ func (cmd *eject) Run(f *flag.FlagSet) error { return err } - return vm.EditDevice(devices.EjectImg(c)) + return vm.EditDevice(context.TODO(), devices.EjectImg(c)) } diff --git a/govc/device/floppy/insert.go b/govc/device/floppy/insert.go index 36f65e3c1..62160f89e 100644 --- a/govc/device/floppy/insert.go +++ b/govc/device/floppy/insert.go @@ -21,6 +21,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type insert struct { @@ -60,7 +61,7 @@ func (cmd *insert) Run(f *flag.FlagSet) error { return flag.ErrHelp } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -75,5 +76,5 @@ func (cmd *insert) Run(f *flag.FlagSet) error { return nil } - return vm.EditDevice(devices.InsertImg(c, img)) + return vm.EditDevice(context.TODO(), devices.InsertImg(c, img)) } diff --git a/govc/device/info.go b/govc/device/info.go index b1fab0b18..6423261ef 100644 --- a/govc/device/info.go +++ b/govc/device/info.go @@ -26,6 +26,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type info struct { @@ -54,7 +55,7 @@ func (cmd *info) Run(f *flag.FlagSet) error { return flag.ErrHelp } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } diff --git a/govc/device/ls.go b/govc/device/ls.go index f1aec87d6..c88591ed1 100644 --- a/govc/device/ls.go +++ b/govc/device/ls.go @@ -24,6 +24,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type ls struct { @@ -52,13 +53,13 @@ func (cmd *ls) Run(f *flag.FlagSet) error { return flag.ErrHelp } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } if cmd.boot { - options, err := vm.BootOptions() + options, err := vm.BootOptions(context.TODO()) if err != nil { return err } diff --git a/govc/device/remove.go b/govc/device/remove.go index b8db1d3b2..8589b1ed0 100644 --- a/govc/device/remove.go +++ b/govc/device/remove.go @@ -22,6 +22,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type remove struct { @@ -50,7 +51,7 @@ func (cmd *remove) Run(f *flag.FlagSet) error { return flag.ErrHelp } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -61,7 +62,7 @@ func (cmd *remove) Run(f *flag.FlagSet) error { return fmt.Errorf("device '%s' not found", name) } - if err = vm.RemoveDevice(device); err != nil { + if err = vm.RemoveDevice(context.TODO(), device); err != nil { return err } } diff --git a/govc/device/scsi/add.go b/govc/device/scsi/add.go index 2d5214bba..7e1dd6b12 100644 --- a/govc/device/scsi/add.go +++ b/govc/device/scsi/add.go @@ -21,10 +21,11 @@ import ( "fmt" "strings" - "github.com/vmware/govmomi" "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/object" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type add struct { @@ -41,7 +42,7 @@ func init() { func (cmd *add) Register(f *flag.FlagSet) { var ctypes []string - ct := govmomi.SCSIControllerTypes() + ct := object.SCSIControllerTypes() for _, t := range ct { ctypes = append(ctypes, ct.Type(t)) } @@ -63,7 +64,7 @@ func (cmd *add) Run(f *flag.FlagSet) error { return flag.ErrHelp } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -77,13 +78,13 @@ func (cmd *add) Run(f *flag.FlagSet) error { c.HotAddRemove = cmd.hotAddRemove c.SharedBus = types.VirtualSCSISharing(cmd.sharedBus) - err = vm.AddDevice(d) + err = vm.AddDevice(context.TODO(), d) if err != nil { return err } // output name of device we just created - devices, err = vm.Device() + devices, err = vm.Device(context.TODO()) if err != nil { return err } diff --git a/govc/device/serial/add.go b/govc/device/serial/add.go index 4a7b23c06..172360097 100644 --- a/govc/device/serial/add.go +++ b/govc/device/serial/add.go @@ -22,6 +22,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type add struct { @@ -46,7 +47,7 @@ func (cmd *add) Run(f *flag.FlagSet) error { return flag.ErrHelp } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -56,13 +57,13 @@ func (cmd *add) Run(f *flag.FlagSet) error { return err } - err = vm.AddDevice(d) + err = vm.AddDevice(context.TODO(), d) if err != nil { return err } // output name of device we just created - devices, err = vm.Device() + devices, err = vm.Device(context.TODO()) if err != nil { return err } diff --git a/govc/device/serial/connect.go b/govc/device/serial/connect.go index 00cae9e26..73278256a 100644 --- a/govc/device/serial/connect.go +++ b/govc/device/serial/connect.go @@ -21,6 +21,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type connect struct { @@ -51,7 +52,7 @@ func (cmd *connect) Run(f *flag.FlagSet) error { return flag.ErrHelp } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -61,5 +62,5 @@ func (cmd *connect) Run(f *flag.FlagSet) error { return err } - return vm.EditDevice(devices.ConnectSerialPort(d, f.Arg(0), cmd.client)) + return vm.EditDevice(context.TODO(), devices.ConnectSerialPort(d, f.Arg(0), cmd.client)) } diff --git a/govc/device/serial/disconnect.go b/govc/device/serial/disconnect.go index a836ad27d..706def9e3 100644 --- a/govc/device/serial/disconnect.go +++ b/govc/device/serial/disconnect.go @@ -21,6 +21,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type disconnect struct { @@ -49,7 +50,7 @@ func (cmd *disconnect) Run(f *flag.FlagSet) error { return flag.ErrHelp } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -59,5 +60,5 @@ func (cmd *disconnect) Run(f *flag.FlagSet) error { return err } - return vm.EditDevice(devices.DisconnectSerialPort(d)) + return vm.EditDevice(context.TODO(), devices.DisconnectSerialPort(d)) } diff --git a/govc/flags/client.go b/govc/flags/client.go index afa538418..8177ff96e 100644 --- a/govc/flags/client.go +++ b/govc/flags/client.go @@ -29,8 +29,10 @@ import ( "strings" "sync" - "github.com/vmware/govmomi" - "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/session" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/soap" + "golang.org/x/net/context" ) const ( @@ -50,7 +52,7 @@ type ClientFlag struct { insecure bool minAPIVersion string - client *govmomi.Client + client *vim25.Client } func (flag *ClientFlag) URLWithoutPassword() *url.URL { @@ -149,79 +151,99 @@ func (flag *ClientFlag) sessionFile() string { return filepath.Join(os.Getenv("HOME"), ".govmomi", "sessions", name) } -func (flag *ClientFlag) loadClient() (*govmomi.Client, error) { - var c govmomi.Client +func (flag *ClientFlag) saveClient(c *vim25.Client) error { + p := flag.sessionFile() + err := os.MkdirAll(filepath.Dir(p), 0700) + if err != nil { + return err + } + f, err := os.OpenFile(p, os.O_CREATE|os.O_WRONLY, 0600) + if err != nil { + return err + } + + defer f.Close() + + enc := json.NewEncoder(f) + err = enc.Encode(c) + if err != nil { + return err + } + + return nil +} + +func (flag *ClientFlag) restoreClient(c *vim25.Client) (bool, error) { f, err := os.Open(flag.sessionFile()) if err != nil { if os.IsNotExist(err) { - return nil, nil + return false, nil } - return nil, err + return false, err } defer f.Close() dec := json.NewDecoder(f) - err = dec.Decode(&c) + err = dec.Decode(c) if err != nil { - return nil, err + return false, err } - return &c, nil + return true, nil } -func (flag *ClientFlag) newClient() (*govmomi.Client, error) { - c, err := govmomi.NewClient(*flag.url, flag.insecure) +func (flag *ClientFlag) loadClient() (*vim25.Client, error) { + c := new(vim25.Client) + ok, err := flag.restoreClient(c) if err != nil { return nil, err } - p := flag.sessionFile() - err = os.MkdirAll(filepath.Dir(p), 0700) - if err != nil { - return nil, err + if !ok || !c.Valid() { + return nil, nil } - f, err := os.OpenFile(p, os.O_CREATE|os.O_WRONLY, 0600) + m := session.NewManager(c) + u, err := m.UserSession(context.TODO()) if err != nil { return nil, err } - defer f.Close() - - enc := json.NewEncoder(f) - err = enc.Encode(c) - if err != nil { - return nil, err + // If the session is nil, the client is not authenticated + if u == nil { + return nil, nil } return c, nil } -// currentSessionValid returns whether or not the current session is valid. It -// is valid if the "currentSession" field of the SessionManager managed object -// can be retrieved. It is not valid it cannot be retrieved, but no error -// occurs. An error is returned otherwise. -func currentSessionValid(c *govmomi.Client) (bool, error) { - var sm mo.SessionManager +func (flag *ClientFlag) newClient() (*vim25.Client, error) { + sc := soap.NewClient(flag.url, flag.insecure) + c, err := vim25.NewClient(context.TODO(), sc) + if err != nil { + return nil, err + } - err := c.Properties(*c.ServiceContent.SessionManager, []string{"currentSession"}, &sm) + m := session.NewManager(c) + err = m.Login(context.TODO(), flag.url.User) if err != nil { - return false, err + return nil, err } - if sm.CurrentSession == nil { - return false, nil + err = flag.saveClient(c) + if err != nil { + return nil, err } - return true, nil + return c, nil } // apiVersionValid returns whether or not the API version supported by the // server the client is connected to is not recent enough. -func apiVersionValid(c *govmomi.Client, minVersionString string) error { +func apiVersionValid(c *vim25.Client, minVersionString string) error { realVersion, err := ParseVersion(c.ServiceContent.About.ApiVersion) if err != nil { return err @@ -243,26 +265,18 @@ func apiVersionValid(c *govmomi.Client, minVersionString string) error { return nil } -func (flag *ClientFlag) Client() (*govmomi.Client, error) { +func (flag *ClientFlag) Client() (*vim25.Client, error) { if flag.client != nil { return flag.client, nil } - var ok = false - c, err := flag.loadClient() if err != nil { return nil, err } - if c != nil { - ok, err = currentSessionValid(c) - if err != nil { - return nil, err - } - } - - if !ok { + // loadClient returns nil if it was unable to load a session from disk + if c == nil { c, err = flag.newClient() if err != nil { return nil, err diff --git a/govc/flags/datacenter.go b/govc/flags/datacenter.go index a5dc04340..93179ffdf 100644 --- a/govc/flags/datacenter.go +++ b/govc/flags/datacenter.go @@ -22,8 +22,9 @@ import ( "os" "sync" - "github.com/vmware/govmomi" "github.com/vmware/govmomi/find" + "github.com/vmware/govmomi/object" + "golang.org/x/net/context" ) type DatacenterFlag struct { @@ -32,7 +33,7 @@ type DatacenterFlag struct { register sync.Once path string - dc *govmomi.Datacenter + dc *object.Datacenter finder *find.Finder err error } @@ -66,9 +67,9 @@ func (flag *DatacenterFlag) Finder() (*find.Finder, error) { // Set for relative func if dc flag is given or // if there is a single (default) Datacenter if flag.path == "" { - flag.dc, flag.err = finder.DefaultDatacenter() + flag.dc, flag.err = finder.DefaultDatacenter(context.TODO()) } else { - if flag.dc, err = finder.Datacenter(flag.path); err != nil { + if flag.dc, err = finder.Datacenter(context.TODO(), flag.path); err != nil { return nil, err } } @@ -80,7 +81,7 @@ func (flag *DatacenterFlag) Finder() (*find.Finder, error) { return flag.finder, nil } -func (flag *DatacenterFlag) Datacenter() (*govmomi.Datacenter, error) { +func (flag *DatacenterFlag) Datacenter() (*object.Datacenter, error) { if flag.dc != nil { return flag.dc, nil } diff --git a/govc/flags/datastore.go b/govc/flags/datastore.go index e8f23c145..1cb765e56 100644 --- a/govc/flags/datastore.go +++ b/govc/flags/datastore.go @@ -25,8 +25,9 @@ import ( "path" "sync" - "github.com/vmware/govmomi" + "github.com/vmware/govmomi/object" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) var ( @@ -39,7 +40,7 @@ type DatastoreFlag struct { register sync.Once name string - ds *govmomi.Datastore + ds *object.Datastore } func (flag *DatastoreFlag) Register(f *flag.FlagSet) { @@ -55,7 +56,7 @@ func (flag *DatastoreFlag) Process() error { return nil } -func (flag *DatastoreFlag) Datastore() (*govmomi.Datastore, error) { +func (flag *DatastoreFlag) Datastore() (*object.Datastore, error) { if flag.ds != nil { return flag.ds, nil } @@ -66,9 +67,9 @@ func (flag *DatastoreFlag) Datastore() (*govmomi.Datastore, error) { } if flag.name == "" { - flag.ds, err = finder.DefaultDatastore() + flag.ds, err = finder.DefaultDatastore(context.TODO()) } else { - flag.ds, err = finder.Datastore(flag.name) + flag.ds, err = finder.Datastore(context.TODO(), flag.name) } return flag.ds, err @@ -94,7 +95,7 @@ func (flag *DatastoreFlag) DatastoreURL(path string) (*url.URL, error) { return nil, err } - u, err := ds.URL(dc, path) + u, err := ds.URL(context.TODO(), dc, path) if err != nil { return nil, err } @@ -108,7 +109,7 @@ func (flag *DatastoreFlag) Stat(file string) (types.BaseFileInfo, error) { return nil, err } - b, err := ds.Browser() + b, err := ds.Browser(context.TODO()) if err != nil { return nil, err } @@ -122,12 +123,12 @@ func (flag *DatastoreFlag) Stat(file string) (types.BaseFileInfo, error) { } dsPath := ds.Path(path.Dir(file)) - task, err := b.SearchDatastore(dsPath, &spec) + task, err := b.SearchDatastore(context.TODO(), dsPath, &spec) if err != nil { return nil, err } - info, err := task.WaitForResult(nil) + info, err := task.WaitForResult(context.TODO(), nil) if err != nil { if info != nil && info.Error != nil { _, ok := info.Error.Fault.(*types.FileNotFound) diff --git a/govc/flags/host_system.go b/govc/flags/host_system.go index 8bc657727..40e787798 100644 --- a/govc/flags/host_system.go +++ b/govc/flags/host_system.go @@ -22,7 +22,8 @@ import ( "os" "sync" - "github.com/vmware/govmomi" + "github.com/vmware/govmomi/object" + "golang.org/x/net/context" ) type HostSystemFlag struct { @@ -32,8 +33,8 @@ type HostSystemFlag struct { register sync.Once name string - host *govmomi.HostSystem - pool *govmomi.ResourcePool + host *object.HostSystem + pool *object.ResourcePool } func (flag *HostSystemFlag) Register(f *flag.FlagSet) { @@ -51,7 +52,7 @@ func (flag *HostSystemFlag) Process() error { return nil } -func (flag *HostSystemFlag) HostSystemIfSpecified() (*govmomi.HostSystem, error) { +func (flag *HostSystemFlag) HostSystemIfSpecified() (*object.HostSystem, error) { if flag.host != nil { return flag.host, nil } @@ -79,11 +80,11 @@ func (flag *HostSystemFlag) HostSystemIfSpecified() (*govmomi.HostSystem, error) return nil, err } - flag.host, err = finder.HostSystem(flag.name) + flag.host, err = finder.HostSystem(context.TODO(), flag.name) return flag.host, err } -func (flag *HostSystemFlag) HostSystem() (*govmomi.HostSystem, error) { +func (flag *HostSystemFlag) HostSystem() (*object.HostSystem, error) { host, err := flag.HostSystemIfSpecified() if err != nil { return nil, err @@ -98,15 +99,15 @@ func (flag *HostSystemFlag) HostSystem() (*govmomi.HostSystem, error) { return nil, err } - flag.host, err = finder.DefaultHostSystem() + flag.host, err = finder.DefaultHostSystem(context.TODO()) return flag.host, err } -func (flag *HostSystemFlag) HostNetworkSystem() (*govmomi.HostNetworkSystem, error) { +func (flag *HostSystemFlag) HostNetworkSystem() (*object.HostNetworkSystem, error) { host, err := flag.HostSystem() if err != nil { return nil, err } - return host.ConfigManager().NetworkSystem() + return host.ConfigManager().NetworkSystem(context.TODO()) } diff --git a/govc/flags/network.go b/govc/flags/network.go index 4f65c9b6a..572dafd46 100644 --- a/govc/flags/network.go +++ b/govc/flags/network.go @@ -22,8 +22,9 @@ import ( "os" "sync" - "github.com/vmware/govmomi" + "github.com/vmware/govmomi/object" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type NetworkFlag struct { @@ -31,7 +32,7 @@ type NetworkFlag struct { register sync.Once name string - net govmomi.NetworkReference + net object.NetworkReference adapter string } @@ -63,7 +64,7 @@ func (flag *NetworkFlag) Set(name string) error { return nil } -func (flag *NetworkFlag) Network() (govmomi.NetworkReference, error) { +func (flag *NetworkFlag) Network() (object.NetworkReference, error) { if flag.net != nil { return flag.net, nil } @@ -74,9 +75,9 @@ func (flag *NetworkFlag) Network() (govmomi.NetworkReference, error) { } if flag.name == "" { - flag.net, err = finder.DefaultNetwork() + flag.net, err = finder.DefaultNetwork(context.TODO()) } else { - flag.net, err = finder.Network(flag.name) + flag.net, err = finder.Network(context.TODO(), flag.name) } return flag.net, err @@ -88,12 +89,12 @@ func (flag *NetworkFlag) Device() (types.BaseVirtualDevice, error) { return nil, err } - backing, err := net.EthernetCardBackingInfo() + backing, err := net.EthernetCardBackingInfo(context.TODO()) if err != nil { return nil, err } - device, err := govmomi.EthernetCardTypes().CreateEthernetCard(flag.adapter, backing) + device, err := object.EthernetCardTypes().CreateEthernetCard(flag.adapter, backing) if err != nil { return nil, err } diff --git a/govc/flags/resource_pool.go b/govc/flags/resource_pool.go index c26039e7c..a3b8877ce 100644 --- a/govc/flags/resource_pool.go +++ b/govc/flags/resource_pool.go @@ -22,7 +22,8 @@ import ( "os" "sync" - "github.com/vmware/govmomi" + "github.com/vmware/govmomi/object" + "golang.org/x/net/context" ) type ResourcePoolFlag struct { @@ -30,7 +31,7 @@ type ResourcePoolFlag struct { register sync.Once name string - pool *govmomi.ResourcePool + pool *object.ResourcePool } func (flag *ResourcePoolFlag) Register(f *flag.FlagSet) { @@ -46,7 +47,7 @@ func (flag *ResourcePoolFlag) Process() error { return nil } -func (flag *ResourcePoolFlag) ResourcePool() (*govmomi.ResourcePool, error) { +func (flag *ResourcePoolFlag) ResourcePool() (*object.ResourcePool, error) { if flag.pool != nil { return flag.pool, nil } @@ -57,9 +58,9 @@ func (flag *ResourcePoolFlag) ResourcePool() (*govmomi.ResourcePool, error) { } if flag.name == "" { - flag.pool, err = finder.DefaultResourcePool() + flag.pool, err = finder.DefaultResourcePool(context.TODO()) } else { - flag.pool, err = finder.ResourcePool(flag.name) + flag.pool, err = finder.ResourcePool(context.TODO(), flag.name) } return flag.pool, err diff --git a/govc/flags/search.go b/govc/flags/search.go index aa410baac..50846fd69 100644 --- a/govc/flags/search.go +++ b/govc/flags/search.go @@ -22,7 +22,9 @@ import ( "fmt" "strings" - "github.com/vmware/govmomi" + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/vim25" + "golang.org/x/net/context" ) const ( @@ -111,55 +113,59 @@ func (flag *SearchFlag) IsSet() bool { return flag.isset } -func (flag *SearchFlag) searchByDatastorePath(c *govmomi.Client, dc *govmomi.Datacenter) (govmomi.Reference, error) { +func (flag *SearchFlag) searchIndex(c *vim25.Client) *object.SearchIndex { + return object.NewSearchIndex(c) +} + +func (flag *SearchFlag) searchByDatastorePath(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) { switch flag.t { case SearchVirtualMachines: - return c.SearchIndex().FindByDatastorePath(dc, flag.byDatastorePath) + return flag.searchIndex(c).FindByDatastorePath(context.TODO(), dc, flag.byDatastorePath) default: panic("unsupported type") } } -func (flag *SearchFlag) searchByDNSName(c *govmomi.Client, dc *govmomi.Datacenter) (govmomi.Reference, error) { +func (flag *SearchFlag) searchByDNSName(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) { switch flag.t { case SearchVirtualMachines: - return c.SearchIndex().FindByDnsName(dc, flag.byDNSName, true) + return flag.searchIndex(c).FindByDnsName(context.TODO(), dc, flag.byDNSName, true) case SearchHosts: - return c.SearchIndex().FindByDnsName(dc, flag.byDNSName, false) + return flag.searchIndex(c).FindByDnsName(context.TODO(), dc, flag.byDNSName, false) default: panic("unsupported type") } } -func (flag *SearchFlag) searchByInventoryPath(c *govmomi.Client, dc *govmomi.Datacenter) (govmomi.Reference, error) { +func (flag *SearchFlag) searchByInventoryPath(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) { // TODO(PN): The datacenter flag should not be set because it is ignored. - return c.SearchIndex().FindByInventoryPath(flag.byInventoryPath) + return flag.searchIndex(c).FindByInventoryPath(context.TODO(), flag.byInventoryPath) } -func (flag *SearchFlag) searchByIP(c *govmomi.Client, dc *govmomi.Datacenter) (govmomi.Reference, error) { +func (flag *SearchFlag) searchByIP(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) { switch flag.t { case SearchVirtualMachines: - return c.SearchIndex().FindByIp(dc, flag.byIP, true) + return flag.searchIndex(c).FindByIp(context.TODO(), dc, flag.byIP, true) case SearchHosts: - return c.SearchIndex().FindByIp(dc, flag.byIP, false) + return flag.searchIndex(c).FindByIp(context.TODO(), dc, flag.byIP, false) default: panic("unsupported type") } } -func (flag *SearchFlag) searchByUUID(c *govmomi.Client, dc *govmomi.Datacenter) (govmomi.Reference, error) { +func (flag *SearchFlag) searchByUUID(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) { switch flag.t { case SearchVirtualMachines: - return c.SearchIndex().FindByUuid(dc, flag.byUUID, true) + return flag.searchIndex(c).FindByUuid(context.TODO(), dc, flag.byUUID, true) case SearchHosts: - return c.SearchIndex().FindByUuid(dc, flag.byUUID, false) + return flag.searchIndex(c).FindByUuid(context.TODO(), dc, flag.byUUID, false) default: panic("unsupported type") } } -func (flag *SearchFlag) search() (govmomi.Reference, error) { - var ref govmomi.Reference +func (flag *SearchFlag) search() (object.Reference, error) { + var ref object.Reference var err error c, err := flag.Client() @@ -198,13 +204,13 @@ func (flag *SearchFlag) search() (govmomi.Reference, error) { return ref, nil } -func (flag *SearchFlag) VirtualMachine() (*govmomi.VirtualMachine, error) { +func (flag *SearchFlag) VirtualMachine() (*object.VirtualMachine, error) { ref, err := flag.search() if err != nil { return nil, err } - vm, ok := ref.(*govmomi.VirtualMachine) + vm, ok := ref.(*object.VirtualMachine) if !ok { return nil, fmt.Errorf("expected VirtualMachine entity, got %s", ref.Reference().Type) } @@ -212,8 +218,8 @@ func (flag *SearchFlag) VirtualMachine() (*govmomi.VirtualMachine, error) { return vm, nil } -func (flag *SearchFlag) VirtualMachines(args []string) ([]*govmomi.VirtualMachine, error) { - var out []*govmomi.VirtualMachine +func (flag *SearchFlag) VirtualMachines(args []string) ([]*object.VirtualMachine, error) { + var out []*object.VirtualMachine if flag.IsSet() { vm, err := flag.VirtualMachine() @@ -235,16 +241,16 @@ func (flag *SearchFlag) VirtualMachines(args []string) ([]*govmomi.VirtualMachin return nil, err } - return finder.VirtualMachineList(args...) + return finder.VirtualMachineList(context.TODO(), args...) } -func (flag *SearchFlag) HostSystem() (*govmomi.HostSystem, error) { +func (flag *SearchFlag) HostSystem() (*object.HostSystem, error) { ref, err := flag.search() if err != nil { return nil, err } - host, ok := ref.(*govmomi.HostSystem) + host, ok := ref.(*object.HostSystem) if !ok { return nil, fmt.Errorf("expected HostSystem entity, got %s", ref.Reference().Type) } @@ -252,8 +258,8 @@ func (flag *SearchFlag) HostSystem() (*govmomi.HostSystem, error) { return host, nil } -func (flag *SearchFlag) HostSystems(args []string) ([]*govmomi.HostSystem, error) { - var out []*govmomi.HostSystem +func (flag *SearchFlag) HostSystems(args []string) ([]*object.HostSystem, error) { + var out []*object.HostSystem if flag.IsSet() { host, err := flag.HostSystem() @@ -275,5 +281,5 @@ func (flag *SearchFlag) HostSystems(args []string) ([]*govmomi.HostSystem, error return nil, err } - return finder.HostSystemList(args...) + return finder.HostSystemList(context.TODO(), args...) } diff --git a/govc/flags/virtual_machine.go b/govc/flags/virtual_machine.go index c75d042bc..87fa31995 100644 --- a/govc/flags/virtual_machine.go +++ b/govc/flags/virtual_machine.go @@ -22,7 +22,8 @@ import ( "os" "sync" - "github.com/vmware/govmomi" + "github.com/vmware/govmomi/object" + "golang.org/x/net/context" ) type VirtualMachineFlag struct { @@ -32,7 +33,7 @@ type VirtualMachineFlag struct { register sync.Once name string - vm *govmomi.VirtualMachine + vm *object.VirtualMachine } func (flag *VirtualMachineFlag) Register(f *flag.FlagSet) { @@ -50,7 +51,7 @@ func (flag *VirtualMachineFlag) Process() error { return nil } -func (flag *VirtualMachineFlag) VirtualMachine() (*govmomi.VirtualMachine, error) { +func (flag *VirtualMachineFlag) VirtualMachine() (*object.VirtualMachine, error) { if flag.vm != nil { return flag.vm, nil } @@ -76,6 +77,6 @@ func (flag *VirtualMachineFlag) VirtualMachine() (*govmomi.VirtualMachine, error return nil, err } - flag.vm, err = finder.VirtualMachine(flag.name) + flag.vm, err = finder.VirtualMachine(context.TODO(), flag.name) return flag.vm, err } diff --git a/govc/host/esxcli/executor.go b/govc/host/esxcli/executor.go index 4cafd7611..5bcc18012 100644 --- a/govc/host/esxcli/executor.go +++ b/govc/host/esxcli/executor.go @@ -20,7 +20,8 @@ import ( "errors" "fmt" - "github.com/vmware/govmomi" + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/types" "github.com/vmware/govmomi/vim25/xml" @@ -28,14 +29,14 @@ import ( ) type Executor struct { - c *govmomi.Client - host *govmomi.HostSystem + c *vim25.Client + host *object.HostSystem mme *types.ReflectManagedMethodExecuter dtm *types.InternalDynamicTypeManager info map[string]*CommandInfo } -func NewExecutor(c *govmomi.Client, host *govmomi.HostSystem) (*Executor, error) { +func NewExecutor(c *vim25.Client, host *object.HostSystem) (*Executor, error) { e := &Executor{ c: c, host: host, diff --git a/govc/host/esxcli/guest_info.go b/govc/host/esxcli/guest_info.go index 2256efd69..2cdc9babb 100644 --- a/govc/host/esxcli/guest_info.go +++ b/govc/host/esxcli/guest_info.go @@ -19,9 +19,12 @@ package esxcli import ( "strings" - "github.com/vmware/govmomi" + "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" + "golang.org/x/net/context" ) type hostInfo struct { @@ -30,11 +33,11 @@ type hostInfo struct { } type GuestInfo struct { - c *govmomi.Client + c *vim25.Client hosts map[string]*hostInfo } -func NewGuestInfo(c *govmomi.Client) *GuestInfo { +func NewGuestInfo(c *vim25.Client) *GuestInfo { return &GuestInfo{ c: c, hosts: make(map[string]*hostInfo), @@ -47,7 +50,7 @@ func (g *GuestInfo) hostInfo(ref *types.ManagedObjectReference) (*hostInfo, erro return h, nil } - host := govmomi.NewHostSystem(g.c, *ref) + host := object.NewHostSystem(g.c, *ref) e, err := NewExecutor(g.c, host) if err != nil { @@ -79,9 +82,11 @@ func (g *GuestInfo) hostInfo(ref *types.ManagedObjectReference) (*hostInfo, erro // ESX hosts must be configured with the /Net/GuestIPHack enabled. // For example: // $ govc host.esxcli -- system settings advanced set -o /Net/GuestIPHack -i 1 -func (g *GuestInfo) IpAddress(vm *govmomi.VirtualMachine) (string, error) { +func (g *GuestInfo) IpAddress(vm *object.VirtualMachine) (string, error) { var mvm mo.VirtualMachine - err := g.c.Properties(vm.ManagedObjectReference, []string{"runtime.host", "config.uuid"}, &mvm) + + pc := property.DefaultCollector(g.c) + err := pc.RetrieveOne(context.TODO(), vm.Reference(), []string{"runtime.host", "config.uuid"}, &mvm) if err != nil { return "", err } diff --git a/govc/host/info.go b/govc/host/info.go index 0cefa68cd..f5d3c8b43 100644 --- a/govc/host/info.go +++ b/govc/host/info.go @@ -23,10 +23,12 @@ import ( "os" "text/tabwriter" - "github.com/vmware/govmomi" "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/property" "github.com/vmware/govmomi/vim25/mo" + "golang.org/x/net/context" ) type info struct { @@ -49,7 +51,7 @@ func (c *info) Run(f *flag.FlagSet) error { return err } - var hosts []*govmomi.HostSystem + var hosts []*object.HostSystem // We could do without the -host flag, leaving it for compat host, err := c.HostSystemIfSpecified() @@ -85,7 +87,9 @@ func (c *info) Run(f *flag.FlagSet) error { for _, host := range hosts { var h mo.HostSystem - err = client.Properties(host.Reference(), props, &h) + + pc := property.DefaultCollector(client) + err = pc.RetrieveOne(context.TODO(), host.Reference(), props, &h) if err != nil { return err } diff --git a/govc/host/portgroup/add.go b/govc/host/portgroup/add.go index bf8cc4607..811e1f5f5 100644 --- a/govc/host/portgroup/add.go +++ b/govc/host/portgroup/add.go @@ -22,6 +22,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type add struct { @@ -53,5 +54,5 @@ func (cmd *add) Run(f *flag.FlagSet) error { cmd.spec.Name = f.Arg(0) - return ns.AddPortGroup(cmd.spec) + return ns.AddPortGroup(context.TODO(), cmd.spec) } diff --git a/govc/host/portgroup/remove.go b/govc/host/portgroup/remove.go index abad024bf..bb6e98d8c 100644 --- a/govc/host/portgroup/remove.go +++ b/govc/host/portgroup/remove.go @@ -21,6 +21,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type remove struct { @@ -45,5 +46,5 @@ func (cmd *remove) Run(f *flag.FlagSet) error { return err } - return ns.RemovePortGroup(f.Arg(0)) + return ns.RemovePortGroup(context.TODO(), f.Arg(0)) } diff --git a/govc/host/vswitch/add.go b/govc/host/vswitch/add.go index f4dbfcb24..44a61819d 100644 --- a/govc/host/vswitch/add.go +++ b/govc/host/vswitch/add.go @@ -22,6 +22,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type add struct { @@ -59,5 +60,5 @@ func (cmd *add) Run(f *flag.FlagSet) error { } } - return ns.AddVirtualSwitch(f.Arg(0), &cmd.spec) + return ns.AddVirtualSwitch(context.TODO(), f.Arg(0), &cmd.spec) } diff --git a/govc/host/vswitch/info.go b/govc/host/vswitch/info.go index 7f919458f..7dfe2484f 100644 --- a/govc/host/vswitch/info.go +++ b/govc/host/vswitch/info.go @@ -25,6 +25,9 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/property" + "github.com/vmware/govmomi/vim25/mo" + "golang.org/x/net/context" ) type info struct { @@ -42,18 +45,27 @@ func (cmd *info) Register(f *flag.FlagSet) {} func (cmd *info) Process() error { return nil } func (cmd *info) Run(f *flag.FlagSet) error { + client, err := cmd.Client() + if err != nil { + return err + } + ns, err := cmd.HostNetworkSystem() if err != nil { return err } - if err = ns.Properties([]string{"networkInfo.vswitch"}); err != nil { + var mns mo.HostNetworkSystem + + pc := property.DefaultCollector(client) + err = pc.RetrieveOne(context.TODO(), ns.Reference(), []string{"networkInfo.vswitch"}, &mns) + if err != nil { return err } tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0) - for i, s := range ns.NetworkInfo.Vswitch { + for i, s := range mns.NetworkInfo.Vswitch { if i > 0 { fmt.Fprintln(tw) } diff --git a/govc/host/vswitch/remove.go b/govc/host/vswitch/remove.go index 55ec85b1a..26e41396f 100644 --- a/govc/host/vswitch/remove.go +++ b/govc/host/vswitch/remove.go @@ -21,6 +21,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type remove struct { @@ -45,5 +46,5 @@ func (cmd *remove) Run(f *flag.FlagSet) error { return err } - return ns.RemoveVirtualSwitch(f.Arg(0)) + return ns.RemoveVirtualSwitch(context.TODO(), f.Arg(0)) } diff --git a/govc/importx/lease_updater.go b/govc/importx/lease_updater.go index c6a1f7253..236e8c629 100644 --- a/govc/importx/lease_updater.go +++ b/govc/importx/lease_updater.go @@ -23,9 +23,11 @@ import ( "sync/atomic" "time" - "github.com/vmware/govmomi" + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/progress" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type ovfFileItem struct { @@ -39,8 +41,8 @@ func (o ovfFileItem) Sink() chan<- progress.Report { } type leaseUpdater struct { - client *govmomi.Client - lease *govmomi.HttpNfcLease + client *vim25.Client + lease *object.HttpNfcLease pos int64 // Number of bytes total int64 // Total number of bytes @@ -50,7 +52,7 @@ type leaseUpdater struct { wg sync.WaitGroup // Track when update loop is done } -func newLeaseUpdater(client *govmomi.Client, lease *govmomi.HttpNfcLease, items []ovfFileItem) *leaseUpdater { +func newLeaseUpdater(client *vim25.Client, lease *object.HttpNfcLease, items []ovfFileItem) *leaseUpdater { l := leaseUpdater{ client: client, lease: lease, @@ -115,7 +117,7 @@ func (l *leaseUpdater) run() { // Always report the current value of percent, as it will renew the // lease even if the value hasn't changed or is 0. percent := int(float32(100*atomic.LoadInt64(&l.pos)) / float32(l.total)) - err := l.lease.HttpNfcLeaseProgress(percent) + err := l.lease.HttpNfcLeaseProgress(context.TODO(), percent) if err != nil { fmt.Printf("from lease updater: %s\n", err) } diff --git a/govc/importx/ovf.go b/govc/importx/ovf.go index 4051a9a49..d3149cb7d 100644 --- a/govc/importx/ovf.go +++ b/govc/importx/ovf.go @@ -24,12 +24,14 @@ import ( "io/ioutil" "path" - "github.com/vmware/govmomi" "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/progress" "github.com/vmware/govmomi/vim25/soap" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type ovf struct { @@ -38,10 +40,10 @@ type ovf struct { *flags.HostSystemFlag *flags.OutputFlag - Client *govmomi.Client - Datacenter *govmomi.Datacenter - Datastore *govmomi.Datastore - ResourcePool *govmomi.ResourcePool + Client *vim25.Client + Datacenter *object.Datacenter + Datastore *object.Datastore + ResourcePool *object.ResourcePool Archive } @@ -137,7 +139,8 @@ func (cmd *ovf) Import(fpath string) error { }, } - spec, err := c.OvfManager().CreateImportSpec(string(desc), cmd.ResourcePool, cmd.Datastore, cisp) + m := object.NewOvfManager(c) + spec, err := m.CreateImportSpec(context.TODO(), string(desc), cmd.ResourcePool, cmd.Datastore, cisp) if err != nil { return err } @@ -162,7 +165,7 @@ func (cmd *ovf) Import(fpath string) error { } } - var host *govmomi.HostSystem + var host *object.HostSystem if cmd.SearchFlag.IsSet() { if host, err = cmd.HostSystem(); err != nil { return err @@ -170,17 +173,17 @@ func (cmd *ovf) Import(fpath string) error { } // TODO: need a folder option - folders, err := cmd.Datacenter.Folders() + folders, err := cmd.Datacenter.Folders(context.TODO()) if err != nil { return err } - lease, err := cmd.ResourcePool.ImportVApp(spec.ImportSpec, folders.VmFolder, host) + lease, err := cmd.ResourcePool.ImportVApp(context.TODO(), spec.ImportSpec, folders.VmFolder, host) if err != nil { return err } - info, err := lease.Wait() + info, err := lease.Wait(context.TODO()) if err != nil { return err } @@ -220,10 +223,10 @@ func (cmd *ovf) Import(fpath string) error { } } - return lease.HttpNfcLeaseComplete() + return lease.HttpNfcLeaseComplete(context.TODO()) } -func (cmd *ovf) Upload(lease *govmomi.HttpNfcLease, ofi ovfFileItem) error { +func (cmd *ovf) Upload(lease *object.HttpNfcLease, ofi ovfFileItem) error { item := ofi.item file := item.Path diff --git a/govc/importx/vmdk.go b/govc/importx/vmdk.go index 7606169bc..f8f84c9b5 100644 --- a/govc/importx/vmdk.go +++ b/govc/importx/vmdk.go @@ -24,13 +24,16 @@ import ( "reflect" "regexp" - "github.com/vmware/govmomi" "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "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/progress" "github.com/vmware/govmomi/vim25/soap" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type vmdk struct { @@ -42,10 +45,10 @@ type vmdk struct { force bool keep bool - Client *govmomi.Client - Datacenter *govmomi.Datacenter - Datastore *govmomi.Datastore - ResourcePool *govmomi.ResourcePool + Client *vim25.Client + Datacenter *object.Datacenter + Datastore *object.Datastore + ResourcePool *object.ResourcePool } func init() { @@ -132,7 +135,8 @@ func (cmd *vmdk) PrepareDestination(i importable) error { case flags.ErrDatastoreDirNotExist: // The base path doesn't exist. Create it. dsPath := cmd.Datastore.Path(path.Dir(vmdkPath)) - return cmd.Client.FileManager().MakeDirectory(dsPath, cmd.Datacenter, true) + m := object.NewFileManager(cmd.Client) + return m.MakeDirectory(context.TODO(), dsPath, cmd.Datacenter, true) case flags.ErrDatastoreFileNotExist: // Destination path doesn't exist; all good to continue with import. return nil @@ -166,7 +170,7 @@ func (cmd *vmdk) PrepareDestination(i importable) error { } func (cmd *vmdk) Upload(i importable) error { - u, err := cmd.Datastore.URL(cmd.Datacenter, i.RemoteSrcVMDK()) + u, err := cmd.Datastore.URL(context.TODO(), cmd.Datacenter, i.RemoteSrcVMDK()) if err != nil { return err } @@ -227,14 +231,14 @@ func (cmd *vmdk) CopyHostAgent(i importable, s progress.Sinker) error { dc := cmd.Datacenter src := cmd.Datastore.Path(i.RemoteSrcVMDK()) dst := cmd.Datastore.Path(i.RemoteDstVMDK()) - vdm := cmd.Client.VirtualDiskManager() - task, err := vdm.CopyVirtualDisk(src, dc, dst, dc, spec, false) + vdm := object.NewVirtualDiskManager(cmd.Client) + task, err := vdm.CopyVirtualDisk(context.TODO(), src, dc, dst, dc, spec, false) if err != nil { return err } ps := progress.Prefix(s, "copying disk") - _, err = task.WaitForResult(ps) + _, err = task.WaitForResult(context.TODO(), ps) if err != nil { return err } @@ -294,29 +298,30 @@ func (cmd *vmdk) CopyVirtualCenter(i importable, s progress.Sinker) error { func (cmd *vmdk) MoveDisk(src, dst string) error { dsSrc := cmd.Datastore.Path(src) dsDst := cmd.Datastore.Path(dst) - vdm := cmd.Client.VirtualDiskManager() - task, err := vdm.MoveVirtualDisk(dsSrc, cmd.Datacenter, dsDst, cmd.Datacenter, true) + vdm := object.NewVirtualDiskManager(cmd.Client) + task, err := vdm.MoveVirtualDisk(context.TODO(), dsSrc, cmd.Datacenter, dsDst, cmd.Datacenter, true) if err != nil { return err } - return task.Wait() + return task.Wait(context.TODO()) } func (cmd *vmdk) DeleteDisk(path string) error { - vdm := cmd.Client.VirtualDiskManager() - task, err := vdm.DeleteVirtualDisk(cmd.Datastore.Path(path), cmd.Datacenter) + vdm := object.NewVirtualDiskManager(cmd.Client) + task, err := vdm.DeleteVirtualDisk(context.TODO(), cmd.Datastore.Path(path), cmd.Datacenter) if err != nil { return err } - return task.Wait() + return task.Wait(context.TODO()) } -func (cmd *vmdk) DetachDisk(vm *govmomi.VirtualMachine) (string, error) { +func (cmd *vmdk) DetachDisk(vm *object.VirtualMachine) (string, error) { var mvm mo.VirtualMachine - err := cmd.Client.Properties(vm.Reference(), []string{"config.hardware"}, &mvm) + pc := property.DefaultCollector(cmd.Client) + err := pc.RetrieveOne(context.TODO(), vm.Reference(), []string{"config.hardware"}, &mvm) if err != nil { return "", err } @@ -324,12 +329,12 @@ func (cmd *vmdk) DetachDisk(vm *govmomi.VirtualMachine) (string, error) { spec := new(configSpec) dsFile := spec.RemoveDisk(&mvm) - task, err := vm.Reconfigure(spec.ToSpec()) + task, err := vm.Reconfigure(context.TODO(), spec.ToSpec()) if err != nil { return "", err } - err = task.Wait() + err = task.Wait(context.TODO()) if err != nil { return "", err } @@ -337,27 +342,27 @@ func (cmd *vmdk) DetachDisk(vm *govmomi.VirtualMachine) (string, error) { return dsFile, nil } -func (cmd *vmdk) CreateVM(spec *configSpec) (*govmomi.VirtualMachine, error) { - folders, err := cmd.Datacenter.Folders() +func (cmd *vmdk) CreateVM(spec *configSpec) (*object.VirtualMachine, error) { + folders, err := cmd.Datacenter.Folders(context.TODO()) if err != nil { return nil, err } - task, err := folders.VmFolder.CreateVM(spec.ToSpec(), cmd.ResourcePool, nil) + task, err := folders.VmFolder.CreateVM(context.TODO(), spec.ToSpec(), cmd.ResourcePool, nil) if err != nil { return nil, err } - info, err := task.WaitForResult(nil) + info, err := task.WaitForResult(context.TODO(), nil) if err != nil { return nil, err } - return govmomi.NewVirtualMachine(cmd.Client, info.Result.(types.ManagedObjectReference)), nil + return object.NewVirtualMachine(cmd.Client, info.Result.(types.ManagedObjectReference)), nil } -func (cmd *vmdk) CloneVM(vm *govmomi.VirtualMachine, name string) (*govmomi.VirtualMachine, error) { - folders, err := cmd.Datacenter.Folders() +func (cmd *vmdk) CloneVM(vm *object.VirtualMachine, name string) (*object.VirtualMachine, error) { + folders, err := cmd.Datacenter.Folders(context.TODO()) if err != nil { return nil, err } @@ -367,31 +372,31 @@ func (cmd *vmdk) CloneVM(vm *govmomi.VirtualMachine, name string) (*govmomi.Virt Location: types.VirtualMachineRelocateSpec{}, } - task, err := vm.Clone(folders.VmFolder, name, spec) + task, err := vm.Clone(context.TODO(), folders.VmFolder, name, spec) if err != nil { return nil, err } - info, err := task.WaitForResult(nil) + info, err := task.WaitForResult(context.TODO(), nil) if err != nil { return nil, err } - return govmomi.NewVirtualMachine(cmd.Client, info.Result.(types.ManagedObjectReference)), nil + return object.NewVirtualMachine(cmd.Client, info.Result.(types.ManagedObjectReference)), nil } -func (cmd *vmdk) DestroyVM(vm *govmomi.VirtualMachine) error { +func (cmd *vmdk) DestroyVM(vm *object.VirtualMachine) error { _, err := cmd.DetachDisk(vm) if err != nil { return err } - task, err := vm.Destroy() + task, err := vm.Destroy(context.TODO()) if err != nil { return err } - err = task.Wait() + err = task.Wait(context.TODO()) if err != nil { return err } @@ -409,7 +414,7 @@ func (c *configSpec) AddChange(d types.BaseVirtualDeviceConfigSpec) { c.DeviceChange = append(c.DeviceChange, d) } -func (c *configSpec) AddDisk(ds *govmomi.Datastore, path string) { +func (c *configSpec) AddDisk(ds *object.Datastore, path string) { controller := &types.VirtualLsiLogicController{ VirtualSCSIController: types.VirtualSCSIController{ SharedBus: types.VirtualSCSISharingNoSharing, diff --git a/govc/license/add.go b/govc/license/add.go index 499e25dca..f6e7df626 100644 --- a/govc/license/add.go +++ b/govc/license/add.go @@ -22,7 +22,9 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/license" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type add struct { @@ -48,7 +50,7 @@ func (cmd *add) Run(f *flag.FlagSet) error { return err } - m := client.LicenseManager() + m := license.NewManager(client) // From the vSphere 5.5 documentation: // @@ -56,19 +58,19 @@ func (cmd *add) Run(f *flag.FlagSet) error { // updateLicense for ESX Server and addLicense follow by // LicenseAssingmentManager.updateAssignedLicense for VirtualCenter. // - var addFunc func(key string, labels map[string]string) (types.LicenseManagerLicenseInfo, error) + var addFunc func(ctx context.Context, key string, labels map[string]string) (types.LicenseManagerLicenseInfo, error) switch t := client.ServiceContent.About.ApiType; t { case "HostAgent": - addFunc = m.UpdateLicense + addFunc = m.Update case "VirtualCenter": - addFunc = m.AddLicense + addFunc = m.Add default: return fmt.Errorf("unsupported ApiType: %s", t) } result := make(licenseOutput, 0) for _, v := range f.Args() { - license, err := addFunc(v, nil) + license, err := addFunc(context.TODO(), v, nil) if err != nil { return err } diff --git a/govc/license/list.go b/govc/license/list.go index 504abb6d0..9f8837a89 100644 --- a/govc/license/list.go +++ b/govc/license/list.go @@ -21,6 +21,8 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/license" + "golang.org/x/net/context" ) type list struct { @@ -42,8 +44,8 @@ func (cmd *list) Run(f *flag.FlagSet) error { return err } - m := client.LicenseManager() - result, err := m.ListLicenses() + m := license.NewManager(client) + result, err := m.List(context.TODO()) if err != nil { return err } diff --git a/govc/license/remove.go b/govc/license/remove.go index a38e125b1..634641652 100644 --- a/govc/license/remove.go +++ b/govc/license/remove.go @@ -21,6 +21,8 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/license" + "golang.org/x/net/context" ) type remove struct { @@ -46,9 +48,9 @@ func (cmd *remove) Run(f *flag.FlagSet) error { return err } - m := client.LicenseManager() + m := license.NewManager(client) for _, v := range f.Args() { - err = m.RemoveLicense(v) + err = m.Remove(context.TODO(), v) if err != nil { return err } diff --git a/govc/ls/command.go b/govc/ls/command.go index e829b1c85..79bd84b86 100644 --- a/govc/ls/command.go +++ b/govc/ls/command.go @@ -25,6 +25,7 @@ import ( "github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/list" "github.com/vmware/govmomi/vim25/mo" + "golang.org/x/net/context" ) type ls struct { @@ -53,7 +54,7 @@ func (cmd *ls) Run(f *flag.FlagSet) error { return err } - es, err := finder.ManagedObjectList(f.Args()...) + es, err := finder.ManagedObjectList(context.TODO(), f.Args()...) if err != nil { return err } diff --git a/govc/pool/change.go b/govc/pool/change.go index a7dcbe073..bc7b41cd2 100644 --- a/govc/pool/change.go +++ b/govc/pool/change.go @@ -22,6 +22,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type change struct { @@ -65,13 +66,13 @@ func (cmd *change) Run(f *flag.FlagSet) error { } }) - pools, err := finder.ResourcePoolList(f.Args()...) + pools, err := finder.ResourcePoolList(context.TODO(), f.Args()...) if err != nil { return err } for _, pool := range pools { - err := pool.UpdateConfig(cmd.name, &cmd.ResourceConfigSpec) + err := pool.UpdateConfig(context.TODO(), cmd.name, &cmd.ResourceConfigSpec) if err != nil { return err } diff --git a/govc/pool/create.go b/govc/pool/create.go index 5c7b023ce..b4086afab 100644 --- a/govc/pool/create.go +++ b/govc/pool/create.go @@ -24,6 +24,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type create struct { @@ -66,7 +67,7 @@ func (cmd *create) Run(f *flag.FlagSet) error { for _, arg := range f.Args() { dir := path.Dir(arg) base := path.Base(arg) - parents, err := finder.ResourcePoolList(dir) + parents, err := finder.ResourcePoolList(context.TODO(), dir) if err != nil { return err } @@ -76,7 +77,7 @@ func (cmd *create) Run(f *flag.FlagSet) error { } for _, parent := range parents { - _, err = parent.Create(base, cmd.ResourceConfigSpec) + _, err = parent.Create(context.TODO(), base, cmd.ResourceConfigSpec) if err != nil { return err } diff --git a/govc/pool/destroy.go b/govc/pool/destroy.go index 8f966316f..8f36fa0ba 100644 --- a/govc/pool/destroy.go +++ b/govc/pool/destroy.go @@ -21,6 +21,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type destroy struct { @@ -56,24 +57,24 @@ func (cmd *destroy) Run(f *flag.FlagSet) error { return err } - pools, err := finder.ResourcePoolList(f.Args()...) + pools, err := finder.ResourcePoolList(context.TODO(), f.Args()...) if err != nil { return err } for _, pool := range pools { if cmd.recursive { - err = pool.DestroyChildren() + err = pool.DestroyChildren(context.TODO()) if err != nil { return err } } - task, err := pool.Destroy() + task, err := pool.Destroy(context.TODO()) if err != nil { return err } - err = task.Wait() + err = task.Wait(context.TODO()) if err != nil { return err } diff --git a/govc/pool/info.go b/govc/pool/info.go index de39c43e1..b52841057 100644 --- a/govc/pool/info.go +++ b/govc/pool/info.go @@ -24,8 +24,10 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/property" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type info struct { @@ -64,7 +66,7 @@ func (cmd *info) Run(f *flag.FlagSet) error { return err } - pools, err := finder.ResourcePoolList(f.Args()...) + pools, err := finder.ResourcePoolList(context.TODO(), f.Args()...) if err != nil { return err } @@ -86,7 +88,9 @@ func (cmd *info) Run(f *flag.FlagSet) error { for _, pool := range pools { var p mo.ResourcePool - err = c.Properties(pool.Reference(), props, &p) + + pc := property.DefaultCollector(c) + err = pc.RetrieveOne(context.TODO(), pool.Reference(), props, &p) if err != nil { return err } diff --git a/govc/vm/change.go b/govc/vm/change.go index ab4351ee6..221a810f4 100644 --- a/govc/vm/change.go +++ b/govc/vm/change.go @@ -22,6 +22,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type change struct { @@ -53,10 +54,10 @@ func (cmd *change) Run(f *flag.FlagSet) error { return flag.ErrHelp } - task, err := vm.Reconfigure(cmd.VirtualMachineConfigSpec) + task, err := vm.Reconfigure(context.TODO(), cmd.VirtualMachineConfigSpec) if err != nil { return err } - return task.Wait() + return task.Wait(context.TODO()) } diff --git a/govc/vm/create.go b/govc/vm/create.go index 257050fe3..1aa6185b9 100644 --- a/govc/vm/create.go +++ b/govc/vm/create.go @@ -20,10 +20,12 @@ import ( "flag" "fmt" - "github.com/vmware/govmomi" "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type create struct { @@ -44,11 +46,11 @@ type create struct { disk string controller string - Client *govmomi.Client - Datacenter *govmomi.Datacenter - Datastore *govmomi.Datastore - ResourcePool *govmomi.ResourcePool - HostSystem *govmomi.HostSystem + Client *vim25.Client + Datacenter *object.Datacenter + Datastore *object.Datastore + ResourcePool *object.ResourcePool + HostSystem *object.HostSystem } func init() { @@ -97,7 +99,7 @@ func (cmd *create) Run(f *flag.FlagSet) error { } if cmd.HostSystem != nil { - if cmd.ResourcePool, err = cmd.HostSystem.ResourcePool(); err != nil { + if cmd.ResourcePool, err = cmd.HostSystem.ResourcePool(context.TODO()); err != nil { return err } } else { @@ -121,24 +123,24 @@ func (cmd *create) Run(f *flag.FlagSet) error { return err } - info, err := task.WaitForResult(nil) + info, err := task.WaitForResult(context.TODO(), nil) if err != nil { return err } - vm := govmomi.NewVirtualMachine(cmd.Client, info.Result.(types.ManagedObjectReference)) + vm := object.NewVirtualMachine(cmd.Client, info.Result.(types.ManagedObjectReference)) if err := cmd.addDevices(vm); err != nil { return err } if cmd.on { - task, err := vm.PowerOn() + task, err := vm.PowerOn(context.TODO()) if err != nil { return err } - _, err = task.WaitForResult(nil) + _, err = task.WaitForResult(context.TODO(), nil) if err != nil { return err } @@ -147,8 +149,8 @@ func (cmd *create) Run(f *flag.FlagSet) error { return nil } -func (cmd *create) addDevices(vm *govmomi.VirtualMachine) error { - devices, err := vm.Device() +func (cmd *create) addDevices(vm *object.VirtualMachine) error { + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -191,10 +193,10 @@ func (cmd *create) addDevices(vm *govmomi.VirtualMachine) error { add = append(add, netdev) - return vm.AddDevice(add...) + return vm.AddDevice(context.TODO(), add...) } -func (cmd *create) createVM(name string) (*govmomi.Task, error) { +func (cmd *create) createVM(name string) (*object.Task, error) { spec := types.VirtualMachineConfigSpec{ Name: name, GuestId: cmd.guestID, @@ -214,7 +216,7 @@ func (cmd *create) createVM(name string) (*govmomi.Task, error) { } if cmd.controller != "ide" { - scsi, err := govmomi.SCSIControllerTypes().CreateSCSIController(cmd.controller) + scsi, err := object.SCSIControllerTypes().CreateSCSIController(cmd.controller) if err != nil { return nil, err } @@ -225,10 +227,10 @@ func (cmd *create) createVM(name string) (*govmomi.Task, error) { }) } - folders, err := cmd.Datacenter.Folders() + folders, err := cmd.Datacenter.Folders(context.TODO()) if err != nil { return nil, err } - return folders.VmFolder.CreateVM(spec, cmd.ResourcePool, cmd.HostSystem) + return folders.VmFolder.CreateVM(context.TODO(), spec, cmd.ResourcePool, cmd.HostSystem) } diff --git a/govc/vm/destroy.go b/govc/vm/destroy.go index aee33a9f6..dbef53d1a 100644 --- a/govc/vm/destroy.go +++ b/govc/vm/destroy.go @@ -21,6 +21,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type destroy struct { @@ -45,21 +46,21 @@ func (cmd *destroy) Run(f *flag.FlagSet) error { } for _, vm := range vms { - task, err := vm.PowerOff() + task, err := vm.PowerOff(context.TODO()) if err != nil { return err } // Ignore error since the VM may already been in powered off state. // vm.Destroy will fail if the VM is still powered on. - _ = task.Wait() + _ = task.Wait(context.TODO()) - task, err = vm.Destroy() + task, err = vm.Destroy(context.TODO()) if err != nil { return err } - err = task.Wait() + err = task.Wait(context.TODO()) if err != nil { return err } diff --git a/govc/vm/disk/attach.go b/govc/vm/disk/attach.go index d8246d4ef..79058b46b 100644 --- a/govc/vm/disk/attach.go +++ b/govc/vm/disk/attach.go @@ -22,6 +22,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type attach struct { @@ -62,7 +63,7 @@ func (cmd *attach) Run(f *flag.FlagSet) error { return err } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -83,7 +84,7 @@ func (cmd *attach) Run(f *flag.FlagSet) error { } disk = devices.ChildDisk(disk) - return vm.AddDevice(disk) + return vm.AddDevice(context.TODO(), disk) } if cmd.persist { @@ -92,5 +93,5 @@ func (cmd *attach) Run(f *flag.FlagSet) error { backing.DiskMode = string(types.VirtualDiskModeNonpersistent) } - return vm.AddDevice(disk) + return vm.AddDevice(context.TODO(), disk) } diff --git a/govc/vm/disk/create.go b/govc/vm/disk/create.go index bf45d2f70..0e33a07b8 100644 --- a/govc/vm/disk/create.go +++ b/govc/vm/disk/create.go @@ -22,6 +22,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type create struct { @@ -68,7 +69,7 @@ func (cmd *create) Run(f *flag.FlagSet) error { return err } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -87,7 +88,7 @@ func (cmd *create) Run(f *flag.FlagSet) error { disk.CapacityInKB = cmd.Bytes.Bytes / 1024 - return vm.AddDevice(disk) + return vm.AddDevice(context.TODO(), disk) } else { cmd.Log("Disk already present\n") } diff --git a/govc/vm/guest/chmod.go b/govc/vm/guest/chmod.go index 137b41173..bd3f53d4c 100644 --- a/govc/vm/guest/chmod.go +++ b/govc/vm/guest/chmod.go @@ -20,6 +20,7 @@ import ( "flag" "github.com/vmware/govmomi/govc/cli" + "golang.org/x/net/context" ) type chmod struct { @@ -41,10 +42,5 @@ func (cmd *chmod) Run(f *flag.FlagSet) error { return err } - vm, err := cmd.VirtualMachine() - if err != nil { - return err - } - - return m.ChangeFileAttributesInGuest(vm, cmd.Auth(), f.Arg(0), cmd.Attr()) + return m.ChangeFileAttributes(context.TODO(), cmd.Auth(), f.Arg(0), cmd.Attr()) } diff --git a/govc/vm/guest/download.go b/govc/vm/guest/download.go index 8c5e0edd2..e0143feb2 100644 --- a/govc/vm/guest/download.go +++ b/govc/vm/guest/download.go @@ -22,6 +22,7 @@ import ( "os" "github.com/vmware/govmomi/govc/cli" + "golang.org/x/net/context" ) type download struct { @@ -48,11 +49,6 @@ func (cmd *download) Run(f *flag.FlagSet) error { return err } - vm, err := cmd.VirtualMachine() - if err != nil { - return err - } - src := f.Arg(0) dst := f.Arg(1) @@ -61,7 +57,7 @@ func (cmd *download) Run(f *flag.FlagSet) error { return os.ErrExist } - info, err := m.InitiateFileTransferFromGuest(vm, cmd.Auth(), src) + info, err := m.InitiateFileTransferFromGuest(context.TODO(), cmd.Auth(), src) if err != nil { return err } diff --git a/govc/vm/guest/getenv.go b/govc/vm/guest/getenv.go index e43292fe3..2d84d966b 100644 --- a/govc/vm/guest/getenv.go +++ b/govc/vm/guest/getenv.go @@ -21,6 +21,7 @@ import ( "fmt" "github.com/vmware/govmomi/govc/cli" + "golang.org/x/net/context" ) type getenv struct { @@ -41,12 +42,7 @@ func (cmd *getenv) Run(f *flag.FlagSet) error { return err } - vm, err := cmd.VirtualMachine() - if err != nil { - return err - } - - vars, err := m.ReadEnvironmentVariableInGuest(vm, cmd.Auth(), f.Args()) + vars, err := m.ReadEnvironmentVariable(context.TODO(), cmd.Auth(), f.Args()) if err != nil { return err } diff --git a/govc/vm/guest/guest.go b/govc/vm/guest/guest.go index c2fdca397..6ffe9873c 100644 --- a/govc/vm/guest/guest.go +++ b/govc/vm/guest/guest.go @@ -22,8 +22,10 @@ import ( "net/url" - "github.com/vmware/govmomi" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/guest" + "github.com/vmware/govmomi/object" + "golang.org/x/net/context" ) type GuestFlag struct { @@ -37,20 +39,34 @@ func (flag *GuestFlag) Register(f *flag.FlagSet) {} func (flag *GuestFlag) Process() error { return nil } -func (flag *GuestFlag) FileManager() (*govmomi.GuestFileManager, error) { +func (flag *GuestFlag) FileManager() (*guest.FileManager, error) { c, err := flag.Client() if err != nil { return nil, err } - return c.GuestOperationsManager().FileManager() + + vm, err := flag.VirtualMachine() + if err != nil { + return nil, err + } + + o := guest.NewOperationsManager(c, vm.Reference()) + return o.FileManager(context.TODO()) } -func (flag *GuestFlag) ProcessManager() (*govmomi.GuestProcessManager, error) { +func (flag *GuestFlag) ProcessManager() (*guest.ProcessManager, error) { c, err := flag.Client() if err != nil { return nil, err } - return c.GuestOperationsManager().ProcessManager() + + vm, err := flag.VirtualMachine() + if err != nil { + return nil, err + } + + o := guest.NewOperationsManager(c, vm.Reference()) + return o.ProcessManager(context.TODO()) } func (flag *GuestFlag) ParseURL(urlStr string) (*url.URL, error) { @@ -62,7 +78,7 @@ func (flag *GuestFlag) ParseURL(urlStr string) (*url.URL, error) { return c.Client.ParseURL(urlStr) } -func (flag *GuestFlag) VirtualMachine() (*govmomi.VirtualMachine, error) { +func (flag *GuestFlag) VirtualMachine() (*object.VirtualMachine, error) { vm, err := flag.VirtualMachineFlag.VirtualMachine() if err != nil { return nil, err diff --git a/govc/vm/guest/kill.go b/govc/vm/guest/kill.go index 29eed64f2..c2478ef60 100644 --- a/govc/vm/guest/kill.go +++ b/govc/vm/guest/kill.go @@ -20,6 +20,7 @@ import ( "flag" "github.com/vmware/govmomi/govc/cli" + "golang.org/x/net/context" ) type kill struct { @@ -44,13 +45,8 @@ func (cmd *kill) Run(f *flag.FlagSet) error { return err } - vm, err := cmd.VirtualMachine() - if err != nil { - return err - } - for _, pid := range cmd.pids { - if err := m.TerminateProcessInGuest(vm, cmd.Auth(), pid); err != nil { + if err := m.TerminateProcess(context.TODO(), cmd.Auth(), pid); err != nil { return err } } diff --git a/govc/vm/guest/ls.go b/govc/vm/guest/ls.go index 654f9b47a..005023e88 100644 --- a/govc/vm/guest/ls.go +++ b/govc/vm/guest/ls.go @@ -23,6 +23,7 @@ import ( "text/tabwriter" "github.com/vmware/govmomi/govc/cli" + "golang.org/x/net/context" ) type ls struct { @@ -43,16 +44,11 @@ func (cmd *ls) Run(f *flag.FlagSet) error { return err } - vm, err := cmd.VirtualMachine() - if err != nil { - return err - } - offset := 0 tw := tabwriter.NewWriter(os.Stdout, 3, 0, 2, ' ', 0) for { - info, err := m.ListFilesInGuest(vm, cmd.Auth(), f.Arg(0), offset, 0, f.Arg(1)) + info, err := m.ListFiles(context.TODO(), cmd.Auth(), f.Arg(0), offset, 0, f.Arg(1)) if err != nil { return err } diff --git a/govc/vm/guest/mkdir.go b/govc/vm/guest/mkdir.go index 46112eddc..b05e62ec4 100644 --- a/govc/vm/guest/mkdir.go +++ b/govc/vm/guest/mkdir.go @@ -22,6 +22,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/vim25/soap" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type mkdir struct { @@ -46,12 +47,7 @@ func (cmd *mkdir) Run(f *flag.FlagSet) error { return err } - vm, err := cmd.VirtualMachine() - if err != nil { - return err - } - - err = m.MakeDirectoryInGuest(vm, cmd.Auth(), f.Arg(0), cmd.createParents) + err = m.MakeDirectory(context.TODO(), cmd.Auth(), f.Arg(0), cmd.createParents) // ignore EEXIST if -p flag is given if err != nil && cmd.createParents { diff --git a/govc/vm/guest/mktemp.go b/govc/vm/guest/mktemp.go index 22b558ebd..56fbde879 100644 --- a/govc/vm/guest/mktemp.go +++ b/govc/vm/guest/mktemp.go @@ -21,6 +21,7 @@ import ( "fmt" "github.com/vmware/govmomi/govc/cli" + "golang.org/x/net/context" ) type mktemp struct { @@ -49,18 +50,12 @@ func (cmd *mktemp) Run(f *flag.FlagSet) error { return err } - vm, err := cmd.VirtualMachine() - if err != nil { - return err - } - - mk := m.CreateTemporaryFileInGuest - + mk := m.CreateTemporaryFile if cmd.dir { - mk = m.CreateTemporaryDirectoryInGuest + mk = m.CreateTemporaryDirectory } - name, err := mk(vm, cmd.Auth(), cmd.prefix, cmd.suffix) + name, err := mk(context.TODO(), cmd.Auth(), cmd.prefix, cmd.suffix) if err != nil { return err } diff --git a/govc/vm/guest/ps.go b/govc/vm/guest/ps.go index d3e46da76..6c92eb3b8 100644 --- a/govc/vm/guest/ps.go +++ b/govc/vm/guest/ps.go @@ -24,6 +24,7 @@ import ( "text/tabwriter" "github.com/vmware/govmomi/govc/cli" + "golang.org/x/net/context" ) type ps struct { @@ -80,16 +81,11 @@ func (cmd *ps) Run(f *flag.FlagSet) error { return err } - vm, err := cmd.VirtualMachine() - if err != nil { - return err - } - if !cmd.every && len(cmd.uids) == 0 { cmd.uids[cmd.auth.Username] = true } - procs, err := m.ListProcessesInGuest(vm, cmd.Auth(), cmd.pids) + procs, err := m.ListProcesses(context.TODO(), cmd.Auth(), cmd.pids) if err != nil { return err } diff --git a/govc/vm/guest/rm.go b/govc/vm/guest/rm.go index dc3d98371..23920004b 100644 --- a/govc/vm/guest/rm.go +++ b/govc/vm/guest/rm.go @@ -20,6 +20,7 @@ import ( "flag" "github.com/vmware/govmomi/govc/cli" + "golang.org/x/net/context" ) type rm struct { @@ -41,10 +42,5 @@ func (cmd *rm) Run(f *flag.FlagSet) error { return err } - vm, err := cmd.VirtualMachine() - if err != nil { - return err - } - - return m.DeleteFileInGuest(vm, cmd.Auth(), f.Arg(0)) + return m.DeleteFile(context.TODO(), cmd.Auth(), f.Arg(0)) } diff --git a/govc/vm/guest/rmdir.go b/govc/vm/guest/rmdir.go index c5a113833..7938592d3 100644 --- a/govc/vm/guest/rmdir.go +++ b/govc/vm/guest/rmdir.go @@ -20,6 +20,7 @@ import ( "flag" "github.com/vmware/govmomi/govc/cli" + "golang.org/x/net/context" ) type rmdir struct { @@ -44,10 +45,5 @@ func (cmd *rmdir) Run(f *flag.FlagSet) error { return err } - vm, err := cmd.VirtualMachine() - if err != nil { - return err - } - - return m.DeleteDirectoryInGuest(vm, cmd.Auth(), f.Arg(0), cmd.recursive) + return m.DeleteDirectory(context.TODO(), cmd.Auth(), f.Arg(0), cmd.recursive) } diff --git a/govc/vm/guest/start.go b/govc/vm/guest/start.go index 1b7aa0f46..e6d8f9edd 100644 --- a/govc/vm/guest/start.go +++ b/govc/vm/guest/start.go @@ -23,6 +23,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type start struct { @@ -60,11 +61,6 @@ func (cmd *start) Run(f *flag.FlagSet) error { return err } - vm, err := cmd.VirtualMachine() - if err != nil { - return err - } - spec := types.GuestProgramSpec{ ProgramPath: f.Arg(0), Arguments: strings.Join(f.Args()[1:], " "), @@ -72,7 +68,7 @@ func (cmd *start) Run(f *flag.FlagSet) error { EnvVariables: cmd.vars, } - pid, err := m.StartProgramInGuest(vm, cmd.Auth(), &spec) + pid, err := m.StartProgram(context.TODO(), cmd.Auth(), &spec) if err != nil { return err } diff --git a/govc/vm/guest/upload.go b/govc/vm/guest/upload.go index d6ba1373f..ab8e1bd5a 100644 --- a/govc/vm/guest/upload.go +++ b/govc/vm/guest/upload.go @@ -21,6 +21,7 @@ import ( "os" "github.com/vmware/govmomi/govc/cli" + "golang.org/x/net/context" ) type upload struct { @@ -46,11 +47,6 @@ func (cmd *upload) Run(f *flag.FlagSet) error { return err } - vm, err := cmd.VirtualMachine() - if err != nil { - return err - } - src := f.Arg(0) dst := f.Arg(1) @@ -59,7 +55,7 @@ func (cmd *upload) Run(f *flag.FlagSet) error { return err } - url, err := m.InitiateFileTransferToGuest(vm, cmd.Auth(), dst, cmd.Attr(), s.Size(), cmd.overwrite) + url, err := m.InitiateFileTransferToGuest(context.TODO(), cmd.Auth(), dst, cmd.Attr(), s.Size(), cmd.overwrite) if err != nil { return err } diff --git a/govc/vm/info.go b/govc/vm/info.go index 1ce10fbc4..eca49085c 100644 --- a/govc/vm/info.go +++ b/govc/vm/info.go @@ -25,7 +25,9 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/property" "github.com/vmware/govmomi/vim25/mo" + "golang.org/x/net/context" ) type info struct { @@ -72,13 +74,14 @@ func (cmd *info) Run(f *flag.FlagSet) error { for { var mvm mo.VirtualMachine - err = c.Properties(vm.Reference(), props, &mvm) + pc := property.DefaultCollector(c) + err = pc.RetrieveOne(context.TODO(), vm.Reference(), props, &mvm) if err != nil { return err } if cmd.WaitForIP && mvm.Guest.IpAddress == "" { - _, err = vm.WaitForIP() + _, err = vm.WaitForIP(context.TODO()) if err != nil { return err } diff --git a/govc/vm/ip.go b/govc/vm/ip.go index 276e8cf1e..580026f91 100644 --- a/govc/vm/ip.go +++ b/govc/vm/ip.go @@ -21,10 +21,11 @@ import ( "fmt" "time" - "github.com/vmware/govmomi" "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/govc/host/esxcli" + "github.com/vmware/govmomi/object" + "golang.org/x/net/context" ) type ip struct { @@ -56,10 +57,10 @@ func (cmd *ip) Run(f *flag.FlagSet) error { return err } - var get func(*govmomi.VirtualMachine) (string, error) + var get func(*object.VirtualMachine) (string, error) if cmd.esx { - get = func(vm *govmomi.VirtualMachine) (string, error) { + get = func(vm *object.VirtualMachine) (string, error) { guest := esxcli.NewGuestInfo(c) ticker := time.NewTicker(time.Millisecond * 500) @@ -80,8 +81,8 @@ func (cmd *ip) Run(f *flag.FlagSet) error { } } } else { - get = func(vm *govmomi.VirtualMachine) (string, error) { - return vm.WaitForIP() + get = func(vm *object.VirtualMachine) (string, error) { + return vm.WaitForIP(context.TODO()) } } diff --git a/govc/vm/network/add.go b/govc/vm/network/add.go index 842cd9ca7..cee82c8b7 100644 --- a/govc/vm/network/add.go +++ b/govc/vm/network/add.go @@ -22,6 +22,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type add struct { @@ -57,5 +58,5 @@ func (cmd *add) Run(f *flag.FlagSet) error { return err } - return vm.AddDevice(net) + return vm.AddDevice(context.TODO(), net) } diff --git a/govc/vm/network/change.go b/govc/vm/network/change.go index e2da85b4f..35c1f0d4a 100644 --- a/govc/vm/network/change.go +++ b/govc/vm/network/change.go @@ -23,6 +23,7 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "golang.org/x/net/context" ) type change struct { @@ -59,7 +60,7 @@ func (cmd *change) Run(f *flag.FlagSet) error { _ = cmd.NetworkFlag.Set(f.Arg(1)) } - devices, err := vm.Device() + devices, err := vm.Device(context.TODO()) if err != nil { return err } @@ -77,5 +78,5 @@ func (cmd *change) Run(f *flag.FlagSet) error { net.GetVirtualDevice().Backing = backing.GetVirtualDevice().Backing - return vm.EditDevice(net) + return vm.EditDevice(context.TODO(), net) } diff --git a/govc/vm/power.go b/govc/vm/power.go index 70a8655da..e34d189cf 100644 --- a/govc/vm/power.go +++ b/govc/vm/power.go @@ -20,9 +20,10 @@ import ( "flag" "fmt" - "github.com/vmware/govmomi" "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/object" + "golang.org/x/net/context" ) type power struct { @@ -81,27 +82,27 @@ func (cmd *power) Run(f *flag.FlagSet) error { } for _, vm := range vms { - var task *govmomi.Task + var task *object.Task switch { case cmd.On: fmt.Fprintf(cmd, "Powering on %s... ", vm.Reference()) - task, err = vm.PowerOn() + task, err = vm.PowerOn(context.TODO()) case cmd.Off: fmt.Fprintf(cmd, "Powering off %s... ", vm.Reference()) - task, err = vm.PowerOff() + task, err = vm.PowerOff(context.TODO()) case cmd.Reset: fmt.Fprintf(cmd, "Reset %s... ", vm.Reference()) - task, err = vm.Reset() + task, err = vm.Reset(context.TODO()) case cmd.Suspend: fmt.Fprintf(cmd, "Suspend %s... ", vm.Reference()) - task, err = vm.Suspend() + task, err = vm.Suspend(context.TODO()) case cmd.Reboot: fmt.Fprintf(cmd, "Reboot guest %s... ", vm.Reference()) - err = vm.RebootGuest() + err = vm.RebootGuest(context.TODO()) case cmd.Shutdown: fmt.Fprintf(cmd, "Shutdown guest %s... ", vm.Reference()) - err = vm.ShutdownGuest() + err = vm.ShutdownGuest(context.TODO()) } if err != nil { @@ -109,7 +110,7 @@ func (cmd *power) Run(f *flag.FlagSet) error { } if task != nil { - err = task.Wait() + err = task.Wait(context.TODO()) } if err == nil { fmt.Fprintf(cmd, "OK\n") diff --git a/govc/vm/question.go b/govc/vm/question.go index 69330c473..59268533d 100644 --- a/govc/vm/question.go +++ b/govc/vm/question.go @@ -23,8 +23,10 @@ import ( "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/property" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type question struct { @@ -61,7 +63,9 @@ func (cmd *question) Run(f *flag.FlagSet) error { } var mvm mo.VirtualMachine - err = c.Properties(vm.ManagedObjectReference, []string{"runtime.question"}, &mvm) + + pc := property.DefaultCollector(c) + err = pc.RetrieveOne(context.TODO(), vm.Reference(), []string{"runtime.question"}, &mvm) if err != nil { return err } @@ -84,5 +88,5 @@ func (cmd *question) Run(f *flag.FlagSet) error { } // Answer question - return vm.Answer(q.Id, cmd.answer) + return vm.Answer(context.TODO(), q.Id, cmd.answer) } diff --git a/govc/vm/vnc.go b/govc/vm/vnc.go index b16ee0c5a..f1101d4f8 100644 --- a/govc/vm/vnc.go +++ b/govc/vm/vnc.go @@ -26,9 +26,11 @@ import ( "strconv" "strings" - "github.com/vmware/govmomi" "github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/flags" + "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" "golang.org/x/net/context" @@ -163,7 +165,7 @@ func (cmd *vnc) loadVMs(args []string) ([]*vncVM, error) { continue } - hs := govmomi.NewHostSystem(c, vm.hostReference()) + hs := object.NewHostSystem(c, vm.hostReference()) h, err := newVNCHost(c, hs, cmd.PortRange.low, cmd.PortRange.high) if err != nil { return nil, err @@ -177,8 +179,8 @@ func (cmd *vnc) loadVMs(args []string) ([]*vncVM, error) { } type vncVM struct { - c *govmomi.Client - vm *govmomi.VirtualMachine + c *vim25.Client + vm *object.VirtualMachine mvm mo.VirtualMachine host *vncHost @@ -186,7 +188,7 @@ type vncVM struct { newOptions vncOptions } -func newVNCVM(c *govmomi.Client, vm *govmomi.VirtualMachine) (*vncVM, error) { +func newVNCVM(c *vim25.Client, vm *object.VirtualMachine) (*vncVM, error) { v := &vncVM{ c: c, vm: vm, @@ -198,7 +200,8 @@ func newVNCVM(c *govmomi.Client, vm *govmomi.VirtualMachine) (*vncVM, error) { "runtime.host", } - err := c.Properties(vm.Reference(), virtualMachineProperties, &v.mvm) + pc := property.DefaultCollector(c) + err := pc.RetrieveOne(context.TODO(), vm.Reference(), virtualMachineProperties, &v.mvm) if err != nil { return nil, err } @@ -252,12 +255,12 @@ func (v *vncVM) reconfigure() error { ExtraConfig: v.newOptions.ToExtraConfig(), } - task, err := v.vm.Reconfigure(spec) + task, err := v.vm.Reconfigure(context.TODO(), spec) if err != nil { return err } - return task.Wait() + return task.Wait(context.TODO()) } func (v *vncVM) uri() (string, error) { @@ -288,13 +291,13 @@ func (v *vncVM) write(w io.Writer) error { } type vncHost struct { - c *govmomi.Client - host *govmomi.HostSystem + c *vim25.Client + host *object.HostSystem ports map[int]struct{} ip string // This field is populated by `managementIP` } -func newVNCHost(c *govmomi.Client, host *govmomi.HostSystem, low, high int) (*vncHost, error) { +func newVNCHost(c *vim25.Client, host *object.HostSystem, low, high int) (*vncHost, error) { ports := make(map[int]struct{}) for i := low; i <= high; i++ { ports[i] = struct{}{} @@ -319,7 +322,7 @@ func newVNCHost(c *govmomi.Client, host *govmomi.HostSystem, low, high int) (*vn return h, nil } -func loadUsedPorts(c *govmomi.Client, host types.ManagedObjectReference) ([]int, error) { +func loadUsedPorts(c *vim25.Client, host types.ManagedObjectReference) ([]int, error) { ospec := types.ObjectSpec{ Obj: host, SelectSet: []types.BaseSelectionSpec{ @@ -390,7 +393,7 @@ func (h *vncHost) managementIP() (string, error) { return h.ip, nil } - ips, err := h.host.ManagementIPs() + ips, err := h.host.ManagementIPs(context.TODO()) if err != nil { return "", err } diff --git a/guest_auth_manager.go b/guest/auth_manager.go similarity index 59% rename from guest_auth_manager.go rename to guest/auth_manager.go index ad5ae5639..93911279d 100644 --- a/guest_auth_manager.go +++ b/guest/auth_manager.go @@ -14,33 +14,36 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package guest import ( + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/types" "golang.org/x/net/context" ) -type GuestAuthManager struct { +type AuthManager struct { types.ManagedObjectReference - c *Client + vm types.ManagedObjectReference + + c *vim25.Client } -func (m GuestAuthManager) Reference() types.ManagedObjectReference { +func (m AuthManager) Reference() types.ManagedObjectReference { return m.ManagedObjectReference } -func (m GuestAuthManager) AcquireCredentialsInGuest(vm *VirtualMachine, requestedAuth types.BaseGuestAuthentication, sessionID int64) (types.BaseGuestAuthentication, error) { +func (m AuthManager) AcquireCredentials(ctx context.Context, requestedAuth types.BaseGuestAuthentication, sessionID int64) (types.BaseGuestAuthentication, error) { req := types.AcquireCredentialsInGuest{ This: m.Reference(), - Vm: vm.Reference(), + Vm: m.vm, RequestedAuth: requestedAuth, SessionID: sessionID, } - res, err := methods.AcquireCredentialsInGuest(context.TODO(), m.c, &req) + res, err := methods.AcquireCredentialsInGuest(ctx, m.c, &req) if err != nil { return nil, err } @@ -48,26 +51,26 @@ func (m GuestAuthManager) AcquireCredentialsInGuest(vm *VirtualMachine, requeste return res.Returnval, nil } -func (m GuestAuthManager) ReleaseCredentialsInGuest(vm *VirtualMachine, auth types.BaseGuestAuthentication) error { +func (m AuthManager) ReleaseCredentials(ctx context.Context, auth types.BaseGuestAuthentication) error { req := types.ReleaseCredentialsInGuest{ This: m.Reference(), - Vm: vm.Reference(), + Vm: m.vm, Auth: auth, } - _, err := methods.ReleaseCredentialsInGuest(context.TODO(), m.c, &req) + _, err := methods.ReleaseCredentialsInGuest(ctx, m.c, &req) return err } -func (m GuestAuthManager) ValidateCredentialsInGuest(vm *VirtualMachine, auth types.BaseGuestAuthentication) error { +func (m AuthManager) ValidateCredentials(ctx context.Context, auth types.BaseGuestAuthentication) error { req := types.ValidateCredentialsInGuest{ This: m.Reference(), - Vm: vm.Reference(), + Vm: m.vm, Auth: auth, } - _, err := methods.ValidateCredentialsInGuest(context.TODO(), m.c, &req) + _, err := methods.ValidateCredentialsInGuest(ctx, m.c, &req) if err != nil { return err } diff --git a/guest/file_manager.go b/guest/file_manager.go new file mode 100644 index 000000000..04b5e956f --- /dev/null +++ b/guest/file_manager.go @@ -0,0 +1,202 @@ +/* +Copyright (c) 2014 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 guest + +import ( + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" +) + +type FileManager struct { + types.ManagedObjectReference + + vm types.ManagedObjectReference + + c *vim25.Client +} + +func (m FileManager) Reference() types.ManagedObjectReference { + return m.ManagedObjectReference +} + +func (m FileManager) ChangeFileAttributes(ctx context.Context, auth types.BaseGuestAuthentication, guestFilePath string, fileAttributes types.BaseGuestFileAttributes) error { + req := types.ChangeFileAttributesInGuest{ + This: m.Reference(), + Vm: m.vm, + Auth: auth, + GuestFilePath: guestFilePath, + FileAttributes: fileAttributes, + } + + _, err := methods.ChangeFileAttributesInGuest(ctx, m.c, &req) + return err +} + +func (m FileManager) CreateTemporaryDirectory(ctx context.Context, auth types.BaseGuestAuthentication, prefix, suffix string) (string, error) { + req := types.CreateTemporaryDirectoryInGuest{ + This: m.Reference(), + Vm: m.vm, + Auth: auth, + Prefix: prefix, + Suffix: suffix, + } + + res, err := methods.CreateTemporaryDirectoryInGuest(ctx, m.c, &req) + if err != nil { + return "", err + } + + return res.Returnval, nil +} + +func (m FileManager) CreateTemporaryFile(ctx context.Context, auth types.BaseGuestAuthentication, prefix, suffix string) (string, error) { + req := types.CreateTemporaryFileInGuest{ + This: m.Reference(), + Vm: m.vm, + Auth: auth, + Prefix: prefix, + Suffix: suffix, + } + + res, err := methods.CreateTemporaryFileInGuest(ctx, m.c, &req) + if err != nil { + return "", err + } + + return res.Returnval, nil +} + +func (m FileManager) DeleteDirectory(ctx context.Context, auth types.BaseGuestAuthentication, directoryPath string, recursive bool) error { + req := types.DeleteDirectoryInGuest{ + This: m.Reference(), + Vm: m.vm, + Auth: auth, + DirectoryPath: directoryPath, + Recursive: recursive, + } + + _, err := methods.DeleteDirectoryInGuest(ctx, m.c, &req) + return err +} + +func (m FileManager) DeleteFile(ctx context.Context, auth types.BaseGuestAuthentication, filePath string) error { + req := types.DeleteFileInGuest{ + This: m.Reference(), + Vm: m.vm, + Auth: auth, + FilePath: filePath, + } + + _, err := methods.DeleteFileInGuest(ctx, m.c, &req) + return err +} + +func (m FileManager) InitiateFileTransferFromGuest(ctx context.Context, auth types.BaseGuestAuthentication, guestFilePath string) (*types.FileTransferInformation, error) { + req := types.InitiateFileTransferFromGuest{ + This: m.Reference(), + Vm: m.vm, + Auth: auth, + GuestFilePath: guestFilePath, + } + + res, err := methods.InitiateFileTransferFromGuest(ctx, m.c, &req) + if err != nil { + return nil, err + } + + return &res.Returnval, nil +} + +func (m FileManager) InitiateFileTransferToGuest(ctx context.Context, auth types.BaseGuestAuthentication, guestFilePath string, fileAttributes types.BaseGuestFileAttributes, fileSize int64, overwrite bool) (string, error) { + req := types.InitiateFileTransferToGuest{ + This: m.Reference(), + Vm: m.vm, + Auth: auth, + GuestFilePath: guestFilePath, + FileAttributes: fileAttributes, + FileSize: fileSize, + Overwrite: overwrite, + } + + res, err := methods.InitiateFileTransferToGuest(ctx, m.c, &req) + if err != nil { + return "", err + } + + return res.Returnval, nil +} + +func (m FileManager) ListFiles(ctx context.Context, auth types.BaseGuestAuthentication, filePath string, index int, maxResults int, matchPattern string) (*types.GuestListFileInfo, error) { + req := types.ListFilesInGuest{ + This: m.Reference(), + Vm: m.vm, + Auth: auth, + FilePath: filePath, + Index: index, + MaxResults: maxResults, + MatchPattern: matchPattern, + } + + res, err := methods.ListFilesInGuest(ctx, m.c, &req) + if err != nil { + return nil, err + } + + return &res.Returnval, nil +} + +func (m FileManager) MakeDirectory(ctx context.Context, auth types.BaseGuestAuthentication, directoryPath string, createParentDirectories bool) error { + req := types.MakeDirectoryInGuest{ + This: m.Reference(), + Vm: m.vm, + Auth: auth, + DirectoryPath: directoryPath, + CreateParentDirectories: createParentDirectories, + } + + _, err := methods.MakeDirectoryInGuest(ctx, m.c, &req) + return err +} + +func (m FileManager) MoveDirectory(ctx context.Context, auth types.BaseGuestAuthentication, srcDirectoryPath string, dstDirectoryPath string) error { + req := types.MoveDirectoryInGuest{ + This: m.Reference(), + Vm: m.vm, + Auth: auth, + SrcDirectoryPath: srcDirectoryPath, + DstDirectoryPath: dstDirectoryPath, + } + + _, err := methods.MoveDirectoryInGuest(ctx, m.c, &req) + return err +} + +func (m FileManager) MoveFile(ctx context.Context, auth types.BaseGuestAuthentication, srcFilePath string, dstFilePath string, overwrite bool) error { + req := types.MoveFileInGuest{ + This: m.Reference(), + Vm: m.vm, + Auth: auth, + SrcFilePath: srcFilePath, + DstFilePath: dstFilePath, + Overwrite: overwrite, + } + + _, err := methods.MoveFileInGuest(ctx, m.c, &req) + return err +} diff --git a/guest/operations_manager.go b/guest/operations_manager.go new file mode 100644 index 000000000..4db6e8959 --- /dev/null +++ b/guest/operations_manager.go @@ -0,0 +1,72 @@ +/* +Copyright (c) 2014 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 guest + +import ( + "github.com/vmware/govmomi/property" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" +) + +type OperationsManager struct { + c *vim25.Client + vm types.ManagedObjectReference +} + +func NewOperationsManager(c *vim25.Client, vm types.ManagedObjectReference) *OperationsManager { + return &OperationsManager{c, vm} +} + +func (m OperationsManager) retrieveOne(ctx context.Context, p string, dst *mo.GuestOperationsManager) error { + pc := property.DefaultCollector(m.c) + return pc.RetrieveOne(ctx, *m.c.ServiceContent.GuestOperationsManager, []string{p}, dst) +} + +func (m OperationsManager) AuthManager(ctx context.Context) (*AuthManager, error) { + var g mo.GuestOperationsManager + + err := m.retrieveOne(ctx, "authManager", &g) + if err != nil { + return nil, err + } + + return &AuthManager{*g.AuthManager, m.vm, m.c}, nil +} + +func (m OperationsManager) FileManager(ctx context.Context) (*FileManager, error) { + var g mo.GuestOperationsManager + + err := m.retrieveOne(ctx, "fileManager", &g) + if err != nil { + return nil, err + } + + return &FileManager{*g.FileManager, m.vm, m.c}, nil +} + +func (m OperationsManager) ProcessManager(ctx context.Context) (*ProcessManager, error) { + var g mo.GuestOperationsManager + + err := m.retrieveOne(ctx, "processManager", &g) + if err != nil { + return nil, err + } + + return &ProcessManager{*g.ProcessManager, m.vm, m.c}, nil +} diff --git a/guest_process_manager.go b/guest/process_manager.go similarity index 55% rename from guest_process_manager.go rename to guest/process_manager.go index da2159f71..efee2420a 100644 --- a/guest_process_manager.go +++ b/guest/process_manager.go @@ -14,33 +14,36 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package guest import ( + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/types" "golang.org/x/net/context" ) -type GuestProcessManager struct { +type ProcessManager struct { types.ManagedObjectReference - c *Client + vm types.ManagedObjectReference + + c *vim25.Client } -func (m GuestProcessManager) Reference() types.ManagedObjectReference { +func (m ProcessManager) Reference() types.ManagedObjectReference { return m.ManagedObjectReference } -func (m GuestProcessManager) ListProcessesInGuest(vm *VirtualMachine, auth types.BaseGuestAuthentication, pids []int64) ([]types.GuestProcessInfo, error) { +func (m ProcessManager) ListProcesses(ctx context.Context, auth types.BaseGuestAuthentication, pids []int64) ([]types.GuestProcessInfo, error) { req := types.ListProcessesInGuest{ This: m.Reference(), - Vm: vm.Reference(), + Vm: m.vm, Auth: auth, Pids: pids, } - res, err := methods.ListProcessesInGuest(context.TODO(), m.c, &req) + res, err := methods.ListProcessesInGuest(ctx, m.c, &req) if err != nil { return nil, err } @@ -48,15 +51,15 @@ func (m GuestProcessManager) ListProcessesInGuest(vm *VirtualMachine, auth types return res.Returnval, err } -func (m GuestProcessManager) ReadEnvironmentVariableInGuest(vm *VirtualMachine, auth types.BaseGuestAuthentication, names []string) ([]string, error) { +func (m ProcessManager) ReadEnvironmentVariable(ctx context.Context, auth types.BaseGuestAuthentication, names []string) ([]string, error) { req := types.ReadEnvironmentVariableInGuest{ This: m.Reference(), - Vm: vm.Reference(), + Vm: m.vm, Auth: auth, Names: names, } - res, err := methods.ReadEnvironmentVariableInGuest(context.TODO(), m.c, &req) + res, err := methods.ReadEnvironmentVariableInGuest(ctx, m.c, &req) if err != nil { return nil, err } @@ -64,15 +67,15 @@ func (m GuestProcessManager) ReadEnvironmentVariableInGuest(vm *VirtualMachine, return res.Returnval, err } -func (m GuestProcessManager) StartProgramInGuest(vm *VirtualMachine, auth types.BaseGuestAuthentication, spec types.BaseGuestProgramSpec) (int64, error) { +func (m ProcessManager) StartProgram(ctx context.Context, auth types.BaseGuestAuthentication, spec types.BaseGuestProgramSpec) (int64, error) { req := types.StartProgramInGuest{ This: m.Reference(), - Vm: vm.Reference(), + Vm: m.vm, Auth: auth, Spec: spec, } - res, err := methods.StartProgramInGuest(context.TODO(), m.c, &req) + res, err := methods.StartProgramInGuest(ctx, m.c, &req) if err != nil { return 0, err } @@ -80,14 +83,14 @@ func (m GuestProcessManager) StartProgramInGuest(vm *VirtualMachine, auth types. return res.Returnval, err } -func (m GuestProcessManager) TerminateProcessInGuest(vm *VirtualMachine, auth types.BaseGuestAuthentication, pid int64) error { +func (m ProcessManager) TerminateProcess(ctx context.Context, auth types.BaseGuestAuthentication, pid int64) error { req := types.TerminateProcessInGuest{ This: m.Reference(), - Vm: vm.Reference(), + Vm: m.vm, Auth: auth, Pid: pid, } - _, err := methods.TerminateProcessInGuest(context.TODO(), m.c, &req) + _, err := methods.TerminateProcessInGuest(ctx, m.c, &req) return err } diff --git a/guest_file_manager.go b/guest_file_manager.go deleted file mode 100644 index 8df730b6a..000000000 --- a/guest_file_manager.go +++ /dev/null @@ -1,199 +0,0 @@ -/* -Copyright (c) 2014 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 govmomi - -import ( - "github.com/vmware/govmomi/vim25/methods" - "github.com/vmware/govmomi/vim25/types" - "golang.org/x/net/context" -) - -type GuestFileManager struct { - types.ManagedObjectReference - - c *Client -} - -func (m GuestFileManager) Reference() types.ManagedObjectReference { - return m.ManagedObjectReference -} - -func (m GuestFileManager) ChangeFileAttributesInGuest(vm *VirtualMachine, auth types.BaseGuestAuthentication, guestFilePath string, fileAttributes types.BaseGuestFileAttributes) error { - req := types.ChangeFileAttributesInGuest{ - This: m.Reference(), - Vm: vm.Reference(), - Auth: auth, - GuestFilePath: guestFilePath, - FileAttributes: fileAttributes, - } - - _, err := methods.ChangeFileAttributesInGuest(context.TODO(), m.c, &req) - return err -} - -func (m GuestFileManager) CreateTemporaryDirectoryInGuest(vm *VirtualMachine, auth types.BaseGuestAuthentication, prefix, suffix string) (string, error) { - req := types.CreateTemporaryDirectoryInGuest{ - This: m.Reference(), - Vm: vm.Reference(), - Auth: auth, - Prefix: prefix, - Suffix: suffix, - } - - res, err := methods.CreateTemporaryDirectoryInGuest(context.TODO(), m.c, &req) - if err != nil { - return "", err - } - - return res.Returnval, nil -} - -func (m GuestFileManager) CreateTemporaryFileInGuest(vm *VirtualMachine, auth types.BaseGuestAuthentication, prefix, suffix string) (string, error) { - req := types.CreateTemporaryFileInGuest{ - This: m.Reference(), - Vm: vm.Reference(), - Auth: auth, - Prefix: prefix, - Suffix: suffix, - } - - res, err := methods.CreateTemporaryFileInGuest(context.TODO(), m.c, &req) - if err != nil { - return "", err - } - - return res.Returnval, nil -} - -func (m GuestFileManager) DeleteDirectoryInGuest(vm *VirtualMachine, auth types.BaseGuestAuthentication, directoryPath string, recursive bool) error { - req := types.DeleteDirectoryInGuest{ - This: m.Reference(), - Vm: vm.Reference(), - Auth: auth, - DirectoryPath: directoryPath, - Recursive: recursive, - } - - _, err := methods.DeleteDirectoryInGuest(context.TODO(), m.c, &req) - return err -} - -func (m GuestFileManager) DeleteFileInGuest(vm *VirtualMachine, auth types.BaseGuestAuthentication, filePath string) error { - req := types.DeleteFileInGuest{ - This: m.Reference(), - Vm: vm.Reference(), - Auth: auth, - FilePath: filePath, - } - - _, err := methods.DeleteFileInGuest(context.TODO(), m.c, &req) - return err -} - -func (m GuestFileManager) InitiateFileTransferFromGuest(vm *VirtualMachine, auth types.BaseGuestAuthentication, guestFilePath string) (*types.FileTransferInformation, error) { - req := types.InitiateFileTransferFromGuest{ - This: m.Reference(), - Vm: vm.Reference(), - Auth: auth, - GuestFilePath: guestFilePath, - } - - res, err := methods.InitiateFileTransferFromGuest(context.TODO(), m.c, &req) - if err != nil { - return nil, err - } - - return &res.Returnval, nil -} - -func (m GuestFileManager) InitiateFileTransferToGuest(vm *VirtualMachine, auth types.BaseGuestAuthentication, guestFilePath string, fileAttributes types.BaseGuestFileAttributes, fileSize int64, overwrite bool) (string, error) { - req := types.InitiateFileTransferToGuest{ - This: m.Reference(), - Vm: vm.Reference(), - Auth: auth, - GuestFilePath: guestFilePath, - FileAttributes: fileAttributes, - FileSize: fileSize, - Overwrite: overwrite, - } - - res, err := methods.InitiateFileTransferToGuest(context.TODO(), m.c, &req) - if err != nil { - return "", err - } - - return res.Returnval, nil -} - -func (m GuestFileManager) ListFilesInGuest(vm *VirtualMachine, auth types.BaseGuestAuthentication, filePath string, index int, maxResults int, matchPattern string) (*types.GuestListFileInfo, error) { - req := types.ListFilesInGuest{ - This: m.Reference(), - Vm: vm.Reference(), - Auth: auth, - FilePath: filePath, - Index: index, - MaxResults: maxResults, - MatchPattern: matchPattern, - } - - res, err := methods.ListFilesInGuest(context.TODO(), m.c, &req) - if err != nil { - return nil, err - } - - return &res.Returnval, nil -} - -func (m GuestFileManager) MakeDirectoryInGuest(vm *VirtualMachine, auth types.BaseGuestAuthentication, directoryPath string, createParentDirectories bool) error { - req := types.MakeDirectoryInGuest{ - This: m.Reference(), - Vm: vm.Reference(), - Auth: auth, - DirectoryPath: directoryPath, - CreateParentDirectories: createParentDirectories, - } - - _, err := methods.MakeDirectoryInGuest(context.TODO(), m.c, &req) - return err -} - -func (m GuestFileManager) MoveDirectoryInGuest(vm *VirtualMachine, auth types.BaseGuestAuthentication, srcDirectoryPath string, dstDirectoryPath string) error { - req := types.MoveDirectoryInGuest{ - This: m.Reference(), - Vm: vm.Reference(), - Auth: auth, - SrcDirectoryPath: srcDirectoryPath, - DstDirectoryPath: dstDirectoryPath, - } - - _, err := methods.MoveDirectoryInGuest(context.TODO(), m.c, &req) - return err -} - -func (m GuestFileManager) MoveFileInGuest(vm *VirtualMachine, auth types.BaseGuestAuthentication, srcFilePath string, dstFilePath string, overwrite bool) error { - req := types.MoveFileInGuest{ - This: m.Reference(), - Vm: vm.Reference(), - Auth: auth, - SrcFilePath: srcFilePath, - DstFilePath: dstFilePath, - Overwrite: overwrite, - } - - _, err := methods.MoveFileInGuest(context.TODO(), m.c, &req) - return err -} diff --git a/guest_operations_manager.go b/guest_operations_manager.go deleted file mode 100644 index ce5e69c97..000000000 --- a/guest_operations_manager.go +++ /dev/null @@ -1,56 +0,0 @@ -/* -Copyright (c) 2014 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 govmomi - -import "github.com/vmware/govmomi/vim25/mo" - -type GuestOperationsManager struct { - c *Client -} - -func (m GuestOperationsManager) AuthManager() (*GuestAuthManager, error) { - var g mo.GuestOperationsManager - - err := m.c.Properties(*m.c.ServiceContent.GuestOperationsManager, []string{"authManager"}, &g) - if err != nil { - return nil, err - } - - return &GuestAuthManager{*g.AuthManager, m.c}, nil -} - -func (m GuestOperationsManager) FileManager() (*GuestFileManager, error) { - var g mo.GuestOperationsManager - - err := m.c.Properties(*m.c.ServiceContent.GuestOperationsManager, []string{"fileManager"}, &g) - if err != nil { - return nil, err - } - - return &GuestFileManager{*g.FileManager, m.c}, nil -} - -func (m GuestOperationsManager) ProcessManager() (*GuestProcessManager, error) { - var g mo.GuestOperationsManager - - err := m.c.Properties(*m.c.ServiceContent.GuestOperationsManager, []string{"processManager"}, &g) - if err != nil { - return nil, err - } - - return &GuestProcessManager{*g.ProcessManager, m.c}, nil -} diff --git a/http_nfc_lease.go b/http_nfc_lease.go deleted file mode 100644 index db8301120..000000000 --- a/http_nfc_lease.go +++ /dev/null @@ -1,70 +0,0 @@ -/* -Copyright (c) 2014 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 govmomi - -import ( - "errors" - "fmt" - - "github.com/vmware/govmomi/vim25/mo" - "github.com/vmware/govmomi/vim25/types" -) - -func (o HttpNfcLease) Wait() (*types.HttpNfcLeaseInfo, error) { - var lease mo.HttpNfcLease - - err := o.c.WaitForProperties(o.Reference(), []string{"state", "info", "error"}, func(pc []types.PropertyChange) bool { - done := false - - for _, c := range pc { - if c.Val == nil { - continue - } - - switch c.Name { - case "error": - val := c.Val.(types.LocalizedMethodFault) - lease.Error = &val - done = true - case "info": - val := c.Val.(types.HttpNfcLeaseInfo) - lease.Info = &val - case "state": - lease.State = c.Val.(types.HttpNfcLeaseState) - if lease.State != types.HttpNfcLeaseStateInitializing { - done = true - } - } - } - - return done - }) - - if err != nil { - return nil, err - } - - if lease.State == types.HttpNfcLeaseStateReady { - return lease.Info, nil - } - - if lease.Error != nil { - return nil, errors.New(lease.Error.LocalizedMessage) - } - - return nil, fmt.Errorf("unexpected nfc lease state: %s", lease.State) -} diff --git a/http_nfc_lease_gen.go b/http_nfc_lease_gen.go deleted file mode 100644 index cf331a284..000000000 --- a/http_nfc_lease_gen.go +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright (c) 2014 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 govmomi - -import ( - "github.com/vmware/govmomi/vim25/methods" - "github.com/vmware/govmomi/vim25/types" - "golang.org/x/net/context" -) - -type HttpNfcLease struct { - types.ManagedObjectReference - - c *Client -} - -func NewHttpNfcLease(c *Client, ref types.ManagedObjectReference) *HttpNfcLease { - return &HttpNfcLease{ - ManagedObjectReference: ref, - c: c, - } -} - -func (o HttpNfcLease) Reference() types.ManagedObjectReference { - return o.ManagedObjectReference -} - -// HttpNfcLeaseAbort wraps methods.HttpNfcLeaseAbort -func (o HttpNfcLease) HttpNfcLeaseAbort(fault *types.LocalizedMethodFault) error { - req := types.HttpNfcLeaseAbort{ - This: o.Reference(), - Fault: fault, - } - - _, err := methods.HttpNfcLeaseAbort(context.TODO(), o.c, &req) - if err != nil { - return err - } - - return nil -} - -// HttpNfcLeaseComplete wraps methods.HttpNfcLeaseComplete -func (o HttpNfcLease) HttpNfcLeaseComplete() error { - req := types.HttpNfcLeaseComplete{ - This: o.Reference(), - } - - _, err := methods.HttpNfcLeaseComplete(context.TODO(), o.c, &req) - if err != nil { - return err - } - - return nil -} - -// HttpNfcLeaseGetManifest wraps methods.HttpNfcLeaseGetManifest -func (o HttpNfcLease) HttpNfcLeaseGetManifest() error { - req := types.HttpNfcLeaseGetManifest{ - This: o.Reference(), - } - - _, err := methods.HttpNfcLeaseGetManifest(context.TODO(), o.c, &req) - if err != nil { - return err - } - - return nil -} - -// HttpNfcLeaseProgress wraps methods.HttpNfcLeaseProgress -func (o HttpNfcLease) HttpNfcLeaseProgress(percent int) error { - req := types.HttpNfcLeaseProgress{ - This: o.Reference(), - Percent: percent, - } - - _, err := methods.HttpNfcLeaseProgress(context.TODO(), o.c, &req) - if err != nil { - return err - } - - return nil -} diff --git a/license_manager.go b/license/manager.go similarity index 57% rename from license_manager.go rename to license/manager.go index 4329da5c2..7dadcb964 100644 --- a/license_manager.go +++ b/license/manager.go @@ -14,30 +14,35 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package license import ( + "github.com/vmware/govmomi/property" + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" "golang.org/x/net/context" ) -type LicenseManager struct { - types.ManagedObjectReference +type Manager struct { + reference types.ManagedObjectReference - c *Client + c *vim25.Client } -func NewLicenseManager(c *Client, ref types.ManagedObjectReference) LicenseManager { - return LicenseManager{ - ManagedObjectReference: ref, +func NewManager(c *vim25.Client) *Manager { + m := Manager{ + reference: *c.ServiceContent.LicenseManager, + c: c, } + + return &m } -func (l LicenseManager) Reference() types.ManagedObjectReference { - return l.ManagedObjectReference +func (m Manager) Reference() types.ManagedObjectReference { + return m.reference } func mapToKeyValueSlice(m map[string]string) []types.KeyValue { @@ -48,14 +53,14 @@ func mapToKeyValueSlice(m map[string]string) []types.KeyValue { return r } -func (l LicenseManager) AddLicense(key string, labels map[string]string) (types.LicenseManagerLicenseInfo, error) { +func (m Manager) Add(ctx context.Context, key string, labels map[string]string) (types.LicenseManagerLicenseInfo, error) { req := types.AddLicense{ - This: l.Reference(), + This: m.Reference(), LicenseKey: key, Labels: mapToKeyValueSlice(labels), } - res, err := methods.AddLicense(context.TODO(), l.c, &req) + res, err := methods.AddLicense(ctx, m.c, &req) if err != nil { return types.LicenseManagerLicenseInfo{}, err } @@ -63,24 +68,24 @@ func (l LicenseManager) AddLicense(key string, labels map[string]string) (types. return res.Returnval, nil } -func (l LicenseManager) RemoveLicense(key string) error { +func (m Manager) Remove(ctx context.Context, key string) error { req := types.RemoveLicense{ - This: l.Reference(), + This: m.Reference(), LicenseKey: key, } - _, err := methods.RemoveLicense(context.TODO(), l.c, &req) + _, err := methods.RemoveLicense(ctx, m.c, &req) return err } -func (l LicenseManager) UpdateLicense(key string, labels map[string]string) (types.LicenseManagerLicenseInfo, error) { +func (m Manager) Update(ctx context.Context, key string, labels map[string]string) (types.LicenseManagerLicenseInfo, error) { req := types.UpdateLicense{ - This: l.Reference(), + This: m.Reference(), LicenseKey: key, Labels: mapToKeyValueSlice(labels), } - res, err := methods.UpdateLicense(context.TODO(), l.c, &req) + res, err := methods.UpdateLicense(ctx, m.c, &req) if err != nil { return types.LicenseManagerLicenseInfo{}, err } @@ -88,10 +93,10 @@ func (l LicenseManager) UpdateLicense(key string, labels map[string]string) (typ return res.Returnval, nil } -func (l LicenseManager) ListLicenses() ([]types.LicenseManagerLicenseInfo, error) { +func (m Manager) List(ctx context.Context) ([]types.LicenseManagerLicenseInfo, error) { var mlm mo.LicenseManager - err := l.c.Properties(l.Reference(), []string{"licenses"}, &mlm) + err := property.DefaultCollector(m.c).RetrieveOne(ctx, m.Reference(), []string{"licenses"}, &mlm) if err != nil { return nil, err } diff --git a/list/lister.go b/list/lister.go index 6b624437a..f902239fa 100644 --- a/list/lister.go +++ b/list/lister.go @@ -21,7 +21,7 @@ import ( "path" "reflect" - "github.com/vmware/govmomi" + "github.com/vmware/govmomi/property" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" "golang.org/x/net/context" @@ -29,10 +29,10 @@ import ( type Element struct { Path string - Object govmomi.Reference + Object mo.Reference } -func ToElement(r govmomi.Reference, prefix string) Element { +func ToElement(r mo.Reference, prefix string) Element { var name string switch m := r.(type) { @@ -71,7 +71,7 @@ func ToElement(r govmomi.Reference, prefix string) Element { } type Lister struct { - Client *govmomi.Client + Collector *property.Collector Reference types.ManagedObjectReference Prefix string All bool @@ -91,24 +91,38 @@ func traversable(ref types.ManagedObjectReference) bool { return true } -func (l Lister) List() ([]Element, error) { +func (l Lister) retrieveProperties(ctx context.Context, req types.RetrieveProperties, dst interface{}) error { + res, err := l.Collector.RetrieveProperties(ctx, req) + if err != nil { + return err + } + + err = mo.LoadRetrievePropertiesResponse(res, dst) + if err != nil { + return err + } + + return nil +} + +func (l Lister) List(ctx context.Context) ([]Element, error) { switch l.Reference.Type { case "Folder": - return l.ListFolder() + return l.ListFolder(ctx) case "Datacenter": - return l.ListDatacenter() + return l.ListDatacenter(ctx) case "ComputeResource", "ClusterComputeResource": // Treat ComputeResource and ClusterComputeResource as one and the same. // It doesn't matter from the perspective of the lister. - return l.ListComputeResource() + return l.ListComputeResource(ctx) case "ResourcePool": - return l.ListResourcePool() + return l.ListResourcePool(ctx) default: return nil, fmt.Errorf("cannot traverse type " + l.Reference.Type) } } -func (l Lister) ListFolder() ([]Element, error) { +func (l Lister) ListFolder(ctx context.Context) ([]Element, error) { spec := types.PropertyFilterSpec{ ObjectSet: []types.ObjectSpec{ { @@ -160,26 +174,25 @@ func (l Lister) ListFolder() ([]Element, error) { } req := types.RetrieveProperties{ - This: l.Client.ServiceContent.PropertyCollector, SpecSet: []types.PropertyFilterSpec{spec}, } var dst []interface{} - err := mo.RetrievePropertiesForRequest(context.TODO(), l.Client, req, &dst) + err := l.retrieveProperties(ctx, req, &dst) if err != nil { return nil, err } es := []Element{} for _, v := range dst { - es = append(es, ToElement(v.(govmomi.Reference), l.Prefix)) + es = append(es, ToElement(v.(mo.Reference), l.Prefix)) } return es, nil } -func (l Lister) ListDatacenter() ([]Element, error) { +func (l Lister) ListDatacenter(ctx context.Context) ([]Element, error) { ospec := types.ObjectSpec{ Obj: l.Reference, Skip: true, @@ -214,7 +227,6 @@ func (l Lister) ListDatacenter() ([]Element, error) { } req := types.RetrieveProperties{ - This: l.Client.ServiceContent.PropertyCollector, SpecSet: []types.PropertyFilterSpec{ { ObjectSet: []types.ObjectSpec{ospec}, @@ -225,20 +237,20 @@ func (l Lister) ListDatacenter() ([]Element, error) { var dst []interface{} - err := mo.RetrievePropertiesForRequest(context.TODO(), l.Client, req, &dst) + err := l.retrieveProperties(ctx, req, &dst) if err != nil { return nil, err } es := []Element{} for _, v := range dst { - es = append(es, ToElement(v.(govmomi.Reference), l.Prefix)) + es = append(es, ToElement(v.(mo.Reference), l.Prefix)) } return es, nil } -func (l Lister) ListComputeResource() ([]Element, error) { +func (l Lister) ListComputeResource(ctx context.Context) ([]Element, error) { ospec := types.ObjectSpec{ Obj: l.Reference, Skip: true, @@ -280,7 +292,6 @@ func (l Lister) ListComputeResource() ([]Element, error) { } req := types.RetrieveProperties{ - This: l.Client.ServiceContent.PropertyCollector, SpecSet: []types.PropertyFilterSpec{ { ObjectSet: []types.ObjectSpec{ospec}, @@ -291,20 +302,20 @@ func (l Lister) ListComputeResource() ([]Element, error) { var dst []interface{} - err := mo.RetrievePropertiesForRequest(context.TODO(), l.Client, req, &dst) + err := l.retrieveProperties(ctx, req, &dst) if err != nil { return nil, err } es := []Element{} for _, v := range dst { - es = append(es, ToElement(v.(govmomi.Reference), l.Prefix)) + es = append(es, ToElement(v.(mo.Reference), l.Prefix)) } return es, nil } -func (l Lister) ListResourcePool() ([]Element, error) { +func (l Lister) ListResourcePool(ctx context.Context) ([]Element, error) { ospec := types.ObjectSpec{ Obj: l.Reference, Skip: true, @@ -344,7 +355,6 @@ func (l Lister) ListResourcePool() ([]Element, error) { } req := types.RetrieveProperties{ - This: l.Client.ServiceContent.PropertyCollector, SpecSet: []types.PropertyFilterSpec{ { ObjectSet: []types.ObjectSpec{ospec}, @@ -355,14 +365,14 @@ func (l Lister) ListResourcePool() ([]Element, error) { var dst []interface{} - err := mo.RetrievePropertiesForRequest(context.TODO(), l.Client, req, &dst) + err := l.retrieveProperties(ctx, req, &dst) if err != nil { return nil, err } es := []Element{} for _, v := range dst { - es = append(es, ToElement(v.(govmomi.Reference), l.Prefix)) + es = append(es, ToElement(v.(mo.Reference), l.Prefix)) } return es, nil diff --git a/list/recurser.go b/list/recurser.go index 22ecd1747..c91c20f78 100644 --- a/list/recurser.go +++ b/list/recurser.go @@ -20,11 +20,12 @@ import ( "path" "path/filepath" - "github.com/vmware/govmomi" + "github.com/vmware/govmomi/property" + "golang.org/x/net/context" ) type Recurser struct { - Client *govmomi.Client + Collector *property.Collector // All configures the recurses to fetch complete objects for leaf nodes. All bool @@ -36,7 +37,7 @@ type Recurser struct { TraverseLeafs bool } -func (r Recurser) Recurse(root Element, parts []string) ([]Element, error) { +func (r Recurser) Recurse(ctx context.Context, root Element, parts []string) ([]Element, error) { if len(parts) == 0 { // Include non-traversable leaf elements in result. For example, consider // the pattern "./vm/my-vm-*", where the pattern should match the VMs and @@ -51,7 +52,7 @@ func (r Recurser) Recurse(root Element, parts []string) ([]Element, error) { } k := Lister{ - Client: r.Client, + Collector: r.Collector, Reference: root.Object.Reference(), Prefix: root.Path, } @@ -60,7 +61,7 @@ func (r Recurser) Recurse(root Element, parts []string) ([]Element, error) { k.All = true } - in, err := k.List() + in, err := k.List(ctx) if err != nil { return nil, err } @@ -84,7 +85,7 @@ func (r Recurser) Recurse(root Element, parts []string) ([]Element, error) { continue } - nres, err := r.Recurse(e, parts) + nres, err := r.Recurse(ctx, e, parts) if err != nil { return nil, err } diff --git a/cluster_compute_resource.go b/object/cluster_compute_resource.go similarity index 97% rename from cluster_compute_resource.go rename to object/cluster_compute_resource.go index 10fc12541..6aa57c783 100644 --- a/cluster_compute_resource.go +++ b/object/cluster_compute_resource.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object type ClusterComputeResource struct { ComputeResource diff --git a/object/common.go b/object/common.go new file mode 100644 index 000000000..6f7c8f70e --- /dev/null +++ b/object/common.go @@ -0,0 +1,42 @@ +/* +Copyright (c) 2015 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 object + +import ( + "github.com/vmware/govmomi/property" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" +) + +// Common contains the fields and functions common to all objects. +type Common struct { + c *vim25.Client + r types.ManagedObjectReference +} + +func NewCommon(c *vim25.Client, r types.ManagedObjectReference) Common { + return Common{c: c, r: r} +} + +func (c Common) Reference() types.ManagedObjectReference { + return c.r +} + +func (c Common) Properties(ctx context.Context, r types.ManagedObjectReference, ps []string, dst interface{}) error { + return property.DefaultCollector(c.c).RetrieveOne(ctx, r, ps, dst) +} diff --git a/compute_resource.go b/object/compute_resource.go similarity index 65% rename from compute_resource.go rename to object/compute_resource.go index 434009cbc..ea63e3c7a 100644 --- a/compute_resource.go +++ b/object/compute_resource.go @@ -14,37 +14,32 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type ComputeResource struct { - types.ManagedObjectReference - - c *Client + Common } -func NewComputeResource(c *Client, ref types.ManagedObjectReference) *ComputeResource { +func NewComputeResource(c *vim25.Client, ref types.ManagedObjectReference) *ComputeResource { return &ComputeResource{ - ManagedObjectReference: ref, - c: c, + Common: NewCommon(c, ref), } } -func (c ComputeResource) Reference() types.ManagedObjectReference { - return c.ManagedObjectReference -} - -func (c ComputeResource) Hosts() ([]types.ManagedObjectReference, error) { +func (c ComputeResource) Hosts(ctx context.Context) ([]types.ManagedObjectReference, error) { var cr mo.ComputeResource - ps := []string{"host"} - err := c.c.Properties(c.Reference(), ps, &cr) + err := c.Properties(ctx, c.Reference(), []string{"host"}, &cr) if err != nil { return nil, err } + return cr.Host, nil } diff --git a/compute_resource_test.go b/object/compute_resource_test.go similarity index 97% rename from compute_resource_test.go rename to object/compute_resource_test.go index 5ec576680..8c4c94035 100644 --- a/compute_resource_test.go +++ b/object/compute_resource_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object // ComputeResource should implement the Reference interface. var _ Reference = ComputeResource{} diff --git a/object/customization_spec_manager.go b/object/customization_spec_manager.go new file mode 100644 index 000000000..c9cff6161 --- /dev/null +++ b/object/customization_spec_manager.go @@ -0,0 +1,165 @@ +/* +Copyright (c) 2014 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 object + +import ( + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" +) + +type CustomizationSpecManager struct { + Common +} + +func NewCustomizationSpecManager(c *vim25.Client) *CustomizationSpecManager { + cs := CustomizationSpecManager{ + Common: NewCommon(c, *c.ServiceContent.CustomizationSpecManager), + } + + return &cs +} + +func (cs CustomizationSpecManager) DoesCustomizationSpecExist(ctx context.Context, name string) (bool, error) { + req := types.DoesCustomizationSpecExist{ + This: cs.Reference(), + Name: name, + } + + res, err := methods.DoesCustomizationSpecExist(ctx, cs.c, &req) + + if err != nil { + return false, err + } + + return res.Returnval, nil +} + +func (cs CustomizationSpecManager) GetCustomizationSpec(ctx context.Context, name string) (*types.CustomizationSpecItem, error) { + req := types.GetCustomizationSpec{ + This: cs.Reference(), + Name: name, + } + + res, err := methods.GetCustomizationSpec(ctx, cs.c, &req) + + if err != nil { + return nil, err + } + + return &res.Returnval, nil +} + +func (cs CustomizationSpecManager) CreateCustomizationSpec(ctx context.Context, item types.CustomizationSpecItem) error { + req := types.CreateCustomizationSpec{ + This: cs.Reference(), + Item: item, + } + + _, err := methods.CreateCustomizationSpec(ctx, cs.c, &req) + if err != nil { + return err + } + + return nil +} + +func (cs CustomizationSpecManager) OverwriteCustomizationSpec(ctx context.Context, item types.CustomizationSpecItem) error { + req := types.OverwriteCustomizationSpec{ + This: cs.Reference(), + Item: item, + } + + _, err := methods.OverwriteCustomizationSpec(ctx, cs.c, &req) + if err != nil { + return err + } + + return nil +} + +func (cs CustomizationSpecManager) DeleteCustomizationSpec(ctx context.Context, name string) error { + req := types.DeleteCustomizationSpec{ + This: cs.Reference(), + Name: name, + } + + _, err := methods.DeleteCustomizationSpec(ctx, cs.c, &req) + if err != nil { + return err + } + + return nil +} + +func (cs CustomizationSpecManager) DuplicateCustomizationSpec(ctx context.Context, name string, newName string) error { + req := types.DuplicateCustomizationSpec{ + This: cs.Reference(), + Name: name, + NewName: newName, + } + + _, err := methods.DuplicateCustomizationSpec(ctx, cs.c, &req) + if err != nil { + return err + } + + return nil +} + +func (cs CustomizationSpecManager) RenameCustomizationSpec(ctx context.Context, name string, newName string) error { + req := types.RenameCustomizationSpec{ + This: cs.Reference(), + Name: name, + NewName: newName, + } + + _, err := methods.RenameCustomizationSpec(ctx, cs.c, &req) + if err != nil { + return err + } + + return nil +} + +func (cs CustomizationSpecManager) CustomizationSpecItemToXml(ctx context.Context, item types.CustomizationSpecItem) (string, error) { + req := types.CustomizationSpecItemToXml{ + This: cs.Reference(), + Item: item, + } + + res, err := methods.CustomizationSpecItemToXml(ctx, cs.c, &req) + if err != nil { + return "", err + } + + return res.Returnval, nil +} + +func (cs CustomizationSpecManager) XmlToCustomizationSpecItem(ctx context.Context, xml string) (*types.CustomizationSpecItem, error) { + req := types.XmlToCustomizationSpecItem{ + This: cs.Reference(), + SpecItemXml: xml, + } + + res, err := methods.XmlToCustomizationSpecItem(ctx, cs.c, &req) + if err != nil { + return nil, err + } + return &res.Returnval, nil +} diff --git a/datacenter.go b/object/datacenter.go similarity index 75% rename from datacenter.go rename to object/datacenter.go index 76768a8f2..12efcee36 100644 --- a/datacenter.go +++ b/object/datacenter.go @@ -14,9 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" @@ -31,27 +32,20 @@ type DatacenterFolders struct { } type Datacenter struct { - types.ManagedObjectReference - - c *Client + Common } -func NewDatacenter(c *Client, ref types.ManagedObjectReference) *Datacenter { +func NewDatacenter(c *vim25.Client, ref types.ManagedObjectReference) *Datacenter { return &Datacenter{ - ManagedObjectReference: ref, - c: c, + Common: NewCommon(c, ref), } } -func (d Datacenter) Reference() types.ManagedObjectReference { - return d.ManagedObjectReference -} - -func (d *Datacenter) Folders() (*DatacenterFolders, error) { +func (d *Datacenter) Folders(ctx context.Context) (*DatacenterFolders, error) { var md mo.Datacenter ps := []string{"vmFolder", "hostFolder", "datastoreFolder", "networkFolder"} - err := d.c.Properties(d.Reference(), ps, &md) + err := d.Properties(ctx, d.Reference(), ps, &md) if err != nil { return nil, err } @@ -66,12 +60,12 @@ func (d *Datacenter) Folders() (*DatacenterFolders, error) { return df, nil } -func (d Datacenter) Destroy() (*Task, error) { +func (d Datacenter) Destroy(ctx context.Context) (*Task, error) { req := types.Destroy_Task{ This: d.Reference(), } - res, err := methods.Destroy_Task(context.TODO(), d.c, &req) + res, err := methods.Destroy_Task(ctx, d.c, &req) if err != nil { return nil, err } diff --git a/datacenter_test.go b/object/datacenter_test.go similarity index 97% rename from datacenter_test.go rename to object/datacenter_test.go index 9760567f1..a31e75a49 100644 --- a/datacenter_test.go +++ b/object/datacenter_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object // Datacenter should implement the Reference interface. var _ Reference = Datacenter{} diff --git a/datastore.go b/object/datastore.go similarity index 69% rename from datastore.go rename to object/datastore.go index a8241328a..279e90ffc 100644 --- a/datastore.go +++ b/object/datastore.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( "fmt" @@ -22,29 +22,24 @@ import ( "net/url" + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type Datastore struct { - types.ManagedObjectReference + Common InventoryPath string - - c *Client } -func NewDatastore(c *Client, ref types.ManagedObjectReference) *Datastore { +func NewDatastore(c *vim25.Client, ref types.ManagedObjectReference) *Datastore { return &Datastore{ - ManagedObjectReference: ref, - c: c, + Common: NewCommon(c, ref), } } -func (d Datastore) Reference() types.ManagedObjectReference { - return d.ManagedObjectReference -} - func (d Datastore) Name() string { return path.Base(d.InventoryPath) } @@ -59,18 +54,18 @@ func (d Datastore) Path(path string) string { } // URL for datastore access over HTTP -func (d Datastore) URL(dc *Datacenter, path string) (*url.URL, error) { +func (d Datastore) URL(ctx context.Context, dc *Datacenter, path string) (*url.URL, error) { var mdc mo.Datacenter - if err := d.c.Properties(dc.Reference(), []string{"name"}, &mdc); err != nil { + if err := dc.Properties(ctx, dc.Reference(), []string{"name"}, &mdc); err != nil { return nil, err } var mds mo.Datastore - if err := d.c.Properties(d.Reference(), []string{"name"}, &mds); err != nil { + if err := d.Properties(ctx, d.Reference(), []string{"name"}, &mds); err != nil { return nil, err } - u := d.c.Client.URL() + u := d.c.URL() return &url.URL{ Scheme: u.Scheme, @@ -83,10 +78,10 @@ func (d Datastore) URL(dc *Datacenter, path string) (*url.URL, error) { }, nil } -func (d Datastore) Browser() (*HostDatastoreBrowser, error) { +func (d Datastore) Browser(ctx context.Context) (*HostDatastoreBrowser, error) { var do mo.Datastore - err := d.c.Properties(d.Reference(), []string{"browser"}, &do) + err := d.Properties(ctx, d.Reference(), []string{"browser"}, &do) if err != nil { return nil, err } diff --git a/datastore_test.go b/object/datastore_test.go similarity index 97% rename from datastore_test.go rename to object/datastore_test.go index 8660cbd66..583962c1c 100644 --- a/datastore_test.go +++ b/object/datastore_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object // Datastore should implement the Reference interface. var _ Reference = Datastore{} diff --git a/distributed_virtual_portgroup.go b/object/distributed_virtual_portgroup.go similarity index 67% rename from distributed_virtual_portgroup.go rename to object/distributed_virtual_portgroup.go index 97435640e..150eaa87b 100644 --- a/distributed_virtual_portgroup.go +++ b/object/distributed_virtual_portgroup.go @@ -14,48 +14,42 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( "path" + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type DistributedVirtualPortgroup struct { - types.ManagedObjectReference + Common InventoryPath string - - c *Client } -func NewDistributedVirtualPortgroup(c *Client, ref types.ManagedObjectReference) *DistributedVirtualPortgroup { +func NewDistributedVirtualPortgroup(c *vim25.Client, ref types.ManagedObjectReference) *DistributedVirtualPortgroup { return &DistributedVirtualPortgroup{ - ManagedObjectReference: ref, - c: c, + Common: NewCommon(c, ref), } } - -func (p DistributedVirtualPortgroup) Reference() types.ManagedObjectReference { - return p.ManagedObjectReference -} - func (p DistributedVirtualPortgroup) Name() string { return path.Base(p.InventoryPath) } // EthernetCardBackingInfo returns the VirtualDeviceBackingInfo for this DistributedVirtualPortgroup -func (p DistributedVirtualPortgroup) EthernetCardBackingInfo() (types.BaseVirtualDeviceBackingInfo, error) { +func (p DistributedVirtualPortgroup) EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) { var dvp mo.DistributedVirtualPortgroup var dvs mo.VmwareDistributedVirtualSwitch // TODO: should be mo.BaseDistributedVirtualSwitch - if err := p.c.Properties(p.Reference(), []string{"key", "config.distributedVirtualSwitch"}, &dvp); err != nil { + if err := p.Properties(ctx, p.Reference(), []string{"key", "config.distributedVirtualSwitch"}, &dvp); err != nil { return nil, err } - if err := p.c.Properties(*dvp.Config.DistributedVirtualSwitch, []string{"uuid"}, &dvs); err != nil { + if err := p.Properties(ctx, *dvp.Config.DistributedVirtualSwitch, []string{"uuid"}, &dvs); err != nil { return nil, err } diff --git a/distributed_virtual_portgroup_test.go b/object/distributed_virtual_portgroup_test.go similarity index 98% rename from distributed_virtual_portgroup_test.go rename to object/distributed_virtual_portgroup_test.go index fb2753ff7..f3ae1561d 100644 --- a/distributed_virtual_portgroup_test.go +++ b/object/distributed_virtual_portgroup_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object // DistributedVirtualPortgroup should implement the Reference interface. var _ Reference = DistributedVirtualPortgroup{} diff --git a/host_config_manager.go b/object/distributed_virtual_switch.go similarity index 58% rename from host_config_manager.go rename to object/distributed_virtual_switch.go index f9015e1be..987c59818 100644 --- a/host_config_manager.go +++ b/object/distributed_virtual_switch.go @@ -14,27 +14,19 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( - "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/types" ) -type HostConfigManager struct { - c *Client - h HostSystem +type DistributedVirtualSwitch struct { + Common } -func (m HostConfigManager) NetworkSystem() (*HostNetworkSystem, error) { - var h mo.HostSystem - - err := m.c.Properties(m.h.Reference(), []string{"configManager.networkSystem"}, &h) - if err != nil { - return nil, err +func NewDistributedVirtualSwitch(c *vim25.Client, ref types.ManagedObjectReference) *DistributedVirtualSwitch { + return &DistributedVirtualSwitch{ + Common: NewCommon(c, ref), } - - return &HostNetworkSystem{ - ManagedObjectReference: *h.ConfigManager.NetworkSystem, - c: m.c, - }, nil } diff --git a/file_manager.go b/object/file_manager.go similarity index 64% rename from file_manager.go rename to object/file_manager.go index 9e22e4c12..47f3e38a5 100644 --- a/file_manager.go +++ b/object/file_manager.go @@ -14,21 +14,30 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/types" "golang.org/x/net/context" ) type FileManager struct { - c *Client + Common } -func (f FileManager) CopyDatastoreFile(sourceName string, sourceDatacenter *Datacenter, destinationName string, destinationDatacenter *Datacenter, force bool) (*Task, error) { +func NewFileManager(c *vim25.Client) *FileManager { + f := FileManager{ + Common: NewCommon(c, *c.ServiceContent.FileManager), + } + + return &f +} + +func (f FileManager) CopyDatastoreFile(ctx context.Context, sourceName string, sourceDatacenter *Datacenter, destinationName string, destinationDatacenter *Datacenter, force bool) (*Task, error) { req := types.CopyDatastoreFile_Task{ - This: *f.c.ServiceContent.FileManager, + This: f.Reference(), SourceName: sourceName, DestinationName: destinationName, Force: force, @@ -44,7 +53,7 @@ func (f FileManager) CopyDatastoreFile(sourceName string, sourceDatacenter *Data req.DestinationDatacenter = &ref } - res, err := methods.CopyDatastoreFile_Task(context.TODO(), f.c, &req) + res, err := methods.CopyDatastoreFile_Task(ctx, f.c, &req) if err != nil { return nil, err } @@ -53,9 +62,9 @@ func (f FileManager) CopyDatastoreFile(sourceName string, sourceDatacenter *Data } // DeleteDatastoreFile deletes the specified file or folder from the datastore. -func (f FileManager) DeleteDatastoreFile(name string, dc *Datacenter) (*Task, error) { +func (f FileManager) DeleteDatastoreFile(ctx context.Context, name string, dc *Datacenter) (*Task, error) { req := types.DeleteDatastoreFile_Task{ - This: *f.c.ServiceContent.FileManager, + This: f.Reference(), Name: name, } @@ -64,7 +73,7 @@ func (f FileManager) DeleteDatastoreFile(name string, dc *Datacenter) (*Task, er req.Datacenter = &ref } - res, err := methods.DeleteDatastoreFile_Task(context.TODO(), f.c, &req) + res, err := methods.DeleteDatastoreFile_Task(ctx, f.c, &req) if err != nil { return nil, err } @@ -73,9 +82,9 @@ func (f FileManager) DeleteDatastoreFile(name string, dc *Datacenter) (*Task, er } // MakeDirectory creates a folder using the specified name. -func (f FileManager) MakeDirectory(name string, dc *Datacenter, createParentDirectories bool) error { +func (f FileManager) MakeDirectory(ctx context.Context, name string, dc *Datacenter, createParentDirectories bool) error { req := types.MakeDirectory{ - This: *f.c.ServiceContent.FileManager, + This: f.Reference(), Name: name, CreateParentDirectories: createParentDirectories, } @@ -85,13 +94,13 @@ func (f FileManager) MakeDirectory(name string, dc *Datacenter, createParentDire req.Datacenter = &ref } - _, err := methods.MakeDirectory(context.TODO(), f.c, &req) + _, err := methods.MakeDirectory(ctx, f.c, &req) return err } -func (f FileManager) MoveDatastoreFile(sourceName string, sourceDatacenter *Datacenter, destinationName string, destinationDatacenter *Datacenter, force bool) (*Task, error) { +func (f FileManager) MoveDatastoreFile(ctx context.Context, sourceName string, sourceDatacenter *Datacenter, destinationName string, destinationDatacenter *Datacenter, force bool) (*Task, error) { req := types.MoveDatastoreFile_Task{ - This: *f.c.ServiceContent.FileManager, + This: f.Reference(), SourceName: sourceName, DestinationName: destinationName, Force: force, @@ -107,7 +116,7 @@ func (f FileManager) MoveDatastoreFile(sourceName string, sourceDatacenter *Data req.DestinationDatacenter = &ref } - res, err := methods.MoveDatastoreFile_Task(context.TODO(), f.c, &req) + res, err := methods.MoveDatastoreFile_Task(ctx, f.c, &req) if err != nil { return nil, err } diff --git a/folder.go b/object/folder.go similarity index 65% rename from folder.go rename to object/folder.go index 7589a2869..06a4d71e0 100644 --- a/folder.go +++ b/object/folder.go @@ -14,9 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" @@ -24,32 +25,28 @@ import ( ) type Folder struct { - types.ManagedObjectReference - - c *Client + Common } -func NewFolder(c *Client, ref types.ManagedObjectReference) *Folder { +func NewFolder(c *vim25.Client, ref types.ManagedObjectReference) *Folder { return &Folder{ - ManagedObjectReference: ref, - c: c, + Common: NewCommon(c, ref), } } -func (f Folder) Reference() types.ManagedObjectReference { - return f.ManagedObjectReference +func NewRootFolder(c *vim25.Client) *Folder { + return NewFolder(c, c.ServiceContent.RootFolder) } -func (f Folder) Children() ([]Reference, error) { +func (f Folder) Children(ctx context.Context) ([]Reference, error) { var mf mo.Folder - err := f.c.Properties(f.Reference(), []string{"childEntity"}, &mf) + err := f.Properties(ctx, f.Reference(), []string{"childEntity"}, &mf) if err != nil { return nil, err } var rs []Reference - for _, e := range mf.ChildEntity { if r := NewReference(f.c, e); r != nil { rs = append(rs, r) @@ -59,13 +56,13 @@ func (f Folder) Children() ([]Reference, error) { return rs, nil } -func (f Folder) CreateDatacenter(datacenter string) (*Datacenter, error) { +func (f Folder) CreateDatacenter(ctx context.Context, datacenter string) (*Datacenter, error) { req := types.CreateDatacenter{ This: f.Reference(), Name: datacenter, } - res, err := methods.CreateDatacenter(context.TODO(), f.c, &req) + res, err := methods.CreateDatacenter(ctx, f.c, &req) if err != nil { return nil, err } @@ -78,13 +75,13 @@ func (f Folder) CreateDatacenter(datacenter string) (*Datacenter, error) { return NewDatacenter(f.c, res.Returnval), nil } -func (f Folder) CreateFolder(name string) (*Folder, error) { +func (f Folder) CreateFolder(ctx context.Context, name string) (*Folder, error) { req := types.CreateFolder{ This: f.Reference(), Name: name, } - res, err := methods.CreateFolder(context.TODO(), f.c, &req) + res, err := methods.CreateFolder(ctx, f.c, &req) if err != nil { return nil, err } @@ -92,7 +89,7 @@ func (f Folder) CreateFolder(name string) (*Folder, error) { return NewFolder(f.c, res.Returnval), err } -func (f Folder) CreateVM(config types.VirtualMachineConfigSpec, pool *ResourcePool, host *HostSystem) (*Task, error) { +func (f Folder) CreateVM(ctx context.Context, config types.VirtualMachineConfigSpec, pool *ResourcePool, host *HostSystem) (*Task, error) { req := types.CreateVM_Task{ This: f.Reference(), Config: config, @@ -104,7 +101,7 @@ func (f Folder) CreateVM(config types.VirtualMachineConfigSpec, pool *ResourcePo req.Host = &ref } - res, err := methods.CreateVM_Task(context.TODO(), f.c, &req) + res, err := methods.CreateVM_Task(ctx, f.c, &req) if err != nil { return nil, err } @@ -112,7 +109,7 @@ func (f Folder) CreateVM(config types.VirtualMachineConfigSpec, pool *ResourcePo return NewTask(f.c, res.Returnval), nil } -func (f Folder) RegisterVM(path string, name string, asTemplate bool, pool *ResourcePool, host *HostSystem) (*Task, error) { +func (f Folder) RegisterVM(ctx context.Context, path string, name string, asTemplate bool, pool *ResourcePool, host *HostSystem) (*Task, error) { req := types.RegisterVM_Task{ This: f.Reference(), Path: path, @@ -133,7 +130,7 @@ func (f Folder) RegisterVM(path string, name string, asTemplate bool, pool *Reso req.Pool = &ref } - res, err := methods.RegisterVM_Task(context.TODO(), f.c, &req) + res, err := methods.RegisterVM_Task(ctx, f.c, &req) if err != nil { return nil, err } diff --git a/folder_test.go b/object/folder_test.go similarity index 97% rename from folder_test.go rename to object/folder_test.go index 27fb08e65..fa721463a 100644 --- a/folder_test.go +++ b/object/folder_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object // Folder should implement the Reference interface. var _ Reference = Folder{} diff --git a/object/host_config_manager.go b/object/host_config_manager.go new file mode 100644 index 000000000..606bb3946 --- /dev/null +++ b/object/host_config_manager.go @@ -0,0 +1,45 @@ +/* +Copyright (c) 2014 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 object + +import ( + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" +) + +type HostConfigManager struct { + Common +} + +func NewHostConfigManager(c *vim25.Client, ref types.ManagedObjectReference) *HostConfigManager { + return &HostConfigManager{ + Common: NewCommon(c, ref), + } +} + +func (m HostConfigManager) NetworkSystem(ctx context.Context) (*HostNetworkSystem, error) { + var h mo.HostSystem + + err := m.Properties(ctx, m.Reference(), []string{"configManager.networkSystem"}, &h) + if err != nil { + return nil, err + } + + return NewHostNetworkSystem(m.c, *h.ConfigManager.NetworkSystem), nil +} diff --git a/host_datastore_browser.go b/object/host_datastore_browser.go similarity index 62% rename from host_datastore_browser.go rename to object/host_datastore_browser.go index 775d91a5b..e243b0fcc 100644 --- a/host_datastore_browser.go +++ b/object/host_datastore_browser.go @@ -14,39 +14,33 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/types" "golang.org/x/net/context" ) type HostDatastoreBrowser struct { - types.ManagedObjectReference - - c *Client + Common } -func NewHostDatastoreBrowser(c *Client, ref types.ManagedObjectReference) *HostDatastoreBrowser { +func NewHostDatastoreBrowser(c *vim25.Client, ref types.ManagedObjectReference) *HostDatastoreBrowser { return &HostDatastoreBrowser{ - ManagedObjectReference: ref, - c: c, + Common: NewCommon(c, ref), } } -func (b HostDatastoreBrowser) Reference() types.ManagedObjectReference { - return b.ManagedObjectReference -} - -func (b HostDatastoreBrowser) SearchDatastore(datastorePath string, searchSpec *types.HostDatastoreBrowserSearchSpec) (*Task, error) { +func (b HostDatastoreBrowser) SearchDatastore(ctx context.Context, datastorePath string, searchSpec *types.HostDatastoreBrowserSearchSpec) (*Task, error) { req := types.SearchDatastore_Task{ This: b.Reference(), DatastorePath: datastorePath, SearchSpec: searchSpec, } - res, err := methods.SearchDatastore_Task(context.TODO(), b.c, &req) + res, err := methods.SearchDatastore_Task(ctx, b.c, &req) if err != nil { return nil, err } @@ -54,14 +48,14 @@ func (b HostDatastoreBrowser) SearchDatastore(datastorePath string, searchSpec * return NewTask(b.c, res.Returnval), nil } -func (b HostDatastoreBrowser) SearchDatastoreSubFolders(datastorePath string, searchSpec *types.HostDatastoreBrowserSearchSpec) (*Task, error) { +func (b HostDatastoreBrowser) SearchDatastoreSubFolders(ctx context.Context, datastorePath string, searchSpec *types.HostDatastoreBrowserSearchSpec) (*Task, error) { req := types.SearchDatastoreSubFolders_Task{ This: b.Reference(), DatastorePath: datastorePath, SearchSpec: searchSpec, } - res, err := methods.SearchDatastoreSubFolders_Task(context.TODO(), b.c, &req) + res, err := methods.SearchDatastoreSubFolders_Task(ctx, b.c, &req) if err != nil { return nil, err } diff --git a/host_network_system_gen.go b/object/host_network_system.go similarity index 57% rename from host_network_system_gen.go rename to object/host_network_system.go index 07b52cce1..19727b3e4 100644 --- a/host_network_system_gen.go +++ b/object/host_network_system.go @@ -14,37 +14,33 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" - "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" "golang.org/x/net/context" ) type HostNetworkSystem struct { - types.ManagedObjectReference - mo.HostNetworkSystem - c *Client + Common } -func (o *HostNetworkSystem) Reference() types.ManagedObjectReference { - return o.ManagedObjectReference -} - -func (o *HostNetworkSystem) Properties(props []string) error { - return o.c.Properties(o.Reference(), props, &o.HostNetworkSystem) +func NewHostNetworkSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostNetworkSystem { + return &HostNetworkSystem{ + Common: NewCommon(c, ref), + } } // AddPortGroup wraps methods.AddPortGroup -func (o HostNetworkSystem) AddPortGroup(portgrp types.HostPortGroupSpec) error { +func (o HostNetworkSystem) AddPortGroup(ctx context.Context, portgrp types.HostPortGroupSpec) error { req := types.AddPortGroup{ This: o.Reference(), Portgrp: portgrp, } - _, err := methods.AddPortGroup(context.TODO(), o.c, &req) + _, err := methods.AddPortGroup(ctx, o.c, &req) if err != nil { return err } @@ -53,14 +49,14 @@ func (o HostNetworkSystem) AddPortGroup(portgrp types.HostPortGroupSpec) error { } // AddServiceConsoleVirtualNic wraps methods.AddServiceConsoleVirtualNic -func (o HostNetworkSystem) AddServiceConsoleVirtualNic(portgroup string, nic types.HostVirtualNicSpec) (string, error) { +func (o HostNetworkSystem) AddServiceConsoleVirtualNic(ctx context.Context, portgroup string, nic types.HostVirtualNicSpec) (string, error) { req := types.AddServiceConsoleVirtualNic{ This: o.Reference(), Portgroup: portgroup, Nic: nic, } - res, err := methods.AddServiceConsoleVirtualNic(context.TODO(), o.c, &req) + res, err := methods.AddServiceConsoleVirtualNic(ctx, o.c, &req) if err != nil { return "", err } @@ -69,14 +65,14 @@ func (o HostNetworkSystem) AddServiceConsoleVirtualNic(portgroup string, nic typ } // AddVirtualNic wraps methods.AddVirtualNic -func (o HostNetworkSystem) AddVirtualNic(portgroup string, nic types.HostVirtualNicSpec) (string, error) { +func (o HostNetworkSystem) AddVirtualNic(ctx context.Context, portgroup string, nic types.HostVirtualNicSpec) (string, error) { req := types.AddVirtualNic{ This: o.Reference(), Portgroup: portgroup, Nic: nic, } - res, err := methods.AddVirtualNic(context.TODO(), o.c, &req) + res, err := methods.AddVirtualNic(ctx, o.c, &req) if err != nil { return "", err } @@ -85,14 +81,14 @@ func (o HostNetworkSystem) AddVirtualNic(portgroup string, nic types.HostVirtual } // AddVirtualSwitch wraps methods.AddVirtualSwitch -func (o HostNetworkSystem) AddVirtualSwitch(vswitchName string, spec *types.HostVirtualSwitchSpec) error { +func (o HostNetworkSystem) AddVirtualSwitch(ctx context.Context, vswitchName string, spec *types.HostVirtualSwitchSpec) error { req := types.AddVirtualSwitch{ This: o.Reference(), VswitchName: vswitchName, Spec: spec, } - _, err := methods.AddVirtualSwitch(context.TODO(), o.c, &req) + _, err := methods.AddVirtualSwitch(ctx, o.c, &req) if err != nil { return err } @@ -101,13 +97,13 @@ func (o HostNetworkSystem) AddVirtualSwitch(vswitchName string, spec *types.Host } // QueryNetworkHint wraps methods.QueryNetworkHint -func (o HostNetworkSystem) QueryNetworkHint(device []string) error { +func (o HostNetworkSystem) QueryNetworkHint(ctx context.Context, device []string) error { req := types.QueryNetworkHint{ This: o.Reference(), Device: device, } - _, err := methods.QueryNetworkHint(context.TODO(), o.c, &req) + _, err := methods.QueryNetworkHint(ctx, o.c, &req) if err != nil { return err } @@ -116,12 +112,12 @@ func (o HostNetworkSystem) QueryNetworkHint(device []string) error { } // RefreshNetworkSystem wraps methods.RefreshNetworkSystem -func (o HostNetworkSystem) RefreshNetworkSystem() error { +func (o HostNetworkSystem) RefreshNetworkSystem(ctx context.Context) error { req := types.RefreshNetworkSystem{ This: o.Reference(), } - _, err := methods.RefreshNetworkSystem(context.TODO(), o.c, &req) + _, err := methods.RefreshNetworkSystem(ctx, o.c, &req) if err != nil { return err } @@ -130,13 +126,13 @@ func (o HostNetworkSystem) RefreshNetworkSystem() error { } // RemovePortGroup wraps methods.RemovePortGroup -func (o HostNetworkSystem) RemovePortGroup(pgName string) error { +func (o HostNetworkSystem) RemovePortGroup(ctx context.Context, pgName string) error { req := types.RemovePortGroup{ This: o.Reference(), PgName: pgName, } - _, err := methods.RemovePortGroup(context.TODO(), o.c, &req) + _, err := methods.RemovePortGroup(ctx, o.c, &req) if err != nil { return err } @@ -145,13 +141,13 @@ func (o HostNetworkSystem) RemovePortGroup(pgName string) error { } // RemoveServiceConsoleVirtualNic wraps methods.RemoveServiceConsoleVirtualNic -func (o HostNetworkSystem) RemoveServiceConsoleVirtualNic(device string) error { +func (o HostNetworkSystem) RemoveServiceConsoleVirtualNic(ctx context.Context, device string) error { req := types.RemoveServiceConsoleVirtualNic{ This: o.Reference(), Device: device, } - _, err := methods.RemoveServiceConsoleVirtualNic(context.TODO(), o.c, &req) + _, err := methods.RemoveServiceConsoleVirtualNic(ctx, o.c, &req) if err != nil { return err } @@ -160,13 +156,13 @@ func (o HostNetworkSystem) RemoveServiceConsoleVirtualNic(device string) error { } // RemoveVirtualNic wraps methods.RemoveVirtualNic -func (o HostNetworkSystem) RemoveVirtualNic(device string) error { +func (o HostNetworkSystem) RemoveVirtualNic(ctx context.Context, device string) error { req := types.RemoveVirtualNic{ This: o.Reference(), Device: device, } - _, err := methods.RemoveVirtualNic(context.TODO(), o.c, &req) + _, err := methods.RemoveVirtualNic(ctx, o.c, &req) if err != nil { return err } @@ -175,13 +171,13 @@ func (o HostNetworkSystem) RemoveVirtualNic(device string) error { } // RemoveVirtualSwitch wraps methods.RemoveVirtualSwitch -func (o HostNetworkSystem) RemoveVirtualSwitch(vswitchName string) error { +func (o HostNetworkSystem) RemoveVirtualSwitch(ctx context.Context, vswitchName string) error { req := types.RemoveVirtualSwitch{ This: o.Reference(), VswitchName: vswitchName, } - _, err := methods.RemoveVirtualSwitch(context.TODO(), o.c, &req) + _, err := methods.RemoveVirtualSwitch(ctx, o.c, &req) if err != nil { return err } @@ -190,13 +186,13 @@ func (o HostNetworkSystem) RemoveVirtualSwitch(vswitchName string) error { } // RestartServiceConsoleVirtualNic wraps methods.RestartServiceConsoleVirtualNic -func (o HostNetworkSystem) RestartServiceConsoleVirtualNic(device string) error { +func (o HostNetworkSystem) RestartServiceConsoleVirtualNic(ctx context.Context, device string) error { req := types.RestartServiceConsoleVirtualNic{ This: o.Reference(), Device: device, } - _, err := methods.RestartServiceConsoleVirtualNic(context.TODO(), o.c, &req) + _, err := methods.RestartServiceConsoleVirtualNic(ctx, o.c, &req) if err != nil { return err } @@ -205,13 +201,13 @@ func (o HostNetworkSystem) RestartServiceConsoleVirtualNic(device string) error } // UpdateConsoleIpRouteConfig wraps methods.UpdateConsoleIpRouteConfig -func (o HostNetworkSystem) UpdateConsoleIpRouteConfig(config types.BaseHostIpRouteConfig) error { +func (o HostNetworkSystem) UpdateConsoleIpRouteConfig(ctx context.Context, config types.BaseHostIpRouteConfig) error { req := types.UpdateConsoleIpRouteConfig{ This: o.Reference(), Config: config, } - _, err := methods.UpdateConsoleIpRouteConfig(context.TODO(), o.c, &req) + _, err := methods.UpdateConsoleIpRouteConfig(ctx, o.c, &req) if err != nil { return err } @@ -220,13 +216,13 @@ func (o HostNetworkSystem) UpdateConsoleIpRouteConfig(config types.BaseHostIpRou } // UpdateDnsConfig wraps methods.UpdateDnsConfig -func (o HostNetworkSystem) UpdateDnsConfig(config types.BaseHostDnsConfig) error { +func (o HostNetworkSystem) UpdateDnsConfig(ctx context.Context, config types.BaseHostDnsConfig) error { req := types.UpdateDnsConfig{ This: o.Reference(), Config: config, } - _, err := methods.UpdateDnsConfig(context.TODO(), o.c, &req) + _, err := methods.UpdateDnsConfig(ctx, o.c, &req) if err != nil { return err } @@ -235,13 +231,13 @@ func (o HostNetworkSystem) UpdateDnsConfig(config types.BaseHostDnsConfig) error } // UpdateIpRouteConfig wraps methods.UpdateIpRouteConfig -func (o HostNetworkSystem) UpdateIpRouteConfig(config types.BaseHostIpRouteConfig) error { +func (o HostNetworkSystem) UpdateIpRouteConfig(ctx context.Context, config types.BaseHostIpRouteConfig) error { req := types.UpdateIpRouteConfig{ This: o.Reference(), Config: config, } - _, err := methods.UpdateIpRouteConfig(context.TODO(), o.c, &req) + _, err := methods.UpdateIpRouteConfig(ctx, o.c, &req) if err != nil { return err } @@ -250,13 +246,13 @@ func (o HostNetworkSystem) UpdateIpRouteConfig(config types.BaseHostIpRouteConfi } // UpdateIpRouteTableConfig wraps methods.UpdateIpRouteTableConfig -func (o HostNetworkSystem) UpdateIpRouteTableConfig(config types.HostIpRouteTableConfig) error { +func (o HostNetworkSystem) UpdateIpRouteTableConfig(ctx context.Context, config types.HostIpRouteTableConfig) error { req := types.UpdateIpRouteTableConfig{ This: o.Reference(), Config: config, } - _, err := methods.UpdateIpRouteTableConfig(context.TODO(), o.c, &req) + _, err := methods.UpdateIpRouteTableConfig(ctx, o.c, &req) if err != nil { return err } @@ -265,14 +261,14 @@ func (o HostNetworkSystem) UpdateIpRouteTableConfig(config types.HostIpRouteTabl } // UpdateNetworkConfig wraps methods.UpdateNetworkConfig -func (o HostNetworkSystem) UpdateNetworkConfig(config types.HostNetworkConfig, changeMode string) (*types.HostNetworkConfigResult, error) { +func (o HostNetworkSystem) UpdateNetworkConfig(ctx context.Context, config types.HostNetworkConfig, changeMode string) (*types.HostNetworkConfigResult, error) { req := types.UpdateNetworkConfig{ This: o.Reference(), Config: config, ChangeMode: changeMode, } - res, err := methods.UpdateNetworkConfig(context.TODO(), o.c, &req) + res, err := methods.UpdateNetworkConfig(ctx, o.c, &req) if err != nil { return nil, err } @@ -281,14 +277,14 @@ func (o HostNetworkSystem) UpdateNetworkConfig(config types.HostNetworkConfig, c } // UpdatePhysicalNicLinkSpeed wraps methods.UpdatePhysicalNicLinkSpeed -func (o HostNetworkSystem) UpdatePhysicalNicLinkSpeed(device string, linkSpeed *types.PhysicalNicLinkInfo) error { +func (o HostNetworkSystem) UpdatePhysicalNicLinkSpeed(ctx context.Context, device string, linkSpeed *types.PhysicalNicLinkInfo) error { req := types.UpdatePhysicalNicLinkSpeed{ This: o.Reference(), Device: device, LinkSpeed: linkSpeed, } - _, err := methods.UpdatePhysicalNicLinkSpeed(context.TODO(), o.c, &req) + _, err := methods.UpdatePhysicalNicLinkSpeed(ctx, o.c, &req) if err != nil { return err } @@ -297,14 +293,14 @@ func (o HostNetworkSystem) UpdatePhysicalNicLinkSpeed(device string, linkSpeed * } // UpdatePortGroup wraps methods.UpdatePortGroup -func (o HostNetworkSystem) UpdatePortGroup(pgName string, portgrp types.HostPortGroupSpec) error { +func (o HostNetworkSystem) UpdatePortGroup(ctx context.Context, pgName string, portgrp types.HostPortGroupSpec) error { req := types.UpdatePortGroup{ This: o.Reference(), PgName: pgName, Portgrp: portgrp, } - _, err := methods.UpdatePortGroup(context.TODO(), o.c, &req) + _, err := methods.UpdatePortGroup(ctx, o.c, &req) if err != nil { return err } @@ -313,14 +309,14 @@ func (o HostNetworkSystem) UpdatePortGroup(pgName string, portgrp types.HostPort } // UpdateServiceConsoleVirtualNic wraps methods.UpdateServiceConsoleVirtualNic -func (o HostNetworkSystem) UpdateServiceConsoleVirtualNic(device string, nic types.HostVirtualNicSpec) error { +func (o HostNetworkSystem) UpdateServiceConsoleVirtualNic(ctx context.Context, device string, nic types.HostVirtualNicSpec) error { req := types.UpdateServiceConsoleVirtualNic{ This: o.Reference(), Device: device, Nic: nic, } - _, err := methods.UpdateServiceConsoleVirtualNic(context.TODO(), o.c, &req) + _, err := methods.UpdateServiceConsoleVirtualNic(ctx, o.c, &req) if err != nil { return err } @@ -329,14 +325,14 @@ func (o HostNetworkSystem) UpdateServiceConsoleVirtualNic(device string, nic typ } // UpdateVirtualNic wraps methods.UpdateVirtualNic -func (o HostNetworkSystem) UpdateVirtualNic(device string, nic types.HostVirtualNicSpec) error { +func (o HostNetworkSystem) UpdateVirtualNic(ctx context.Context, device string, nic types.HostVirtualNicSpec) error { req := types.UpdateVirtualNic{ This: o.Reference(), Device: device, Nic: nic, } - _, err := methods.UpdateVirtualNic(context.TODO(), o.c, &req) + _, err := methods.UpdateVirtualNic(ctx, o.c, &req) if err != nil { return err } @@ -345,14 +341,14 @@ func (o HostNetworkSystem) UpdateVirtualNic(device string, nic types.HostVirtual } // UpdateVirtualSwitch wraps methods.UpdateVirtualSwitch -func (o HostNetworkSystem) UpdateVirtualSwitch(vswitchName string, spec types.HostVirtualSwitchSpec) error { +func (o HostNetworkSystem) UpdateVirtualSwitch(ctx context.Context, vswitchName string, spec types.HostVirtualSwitchSpec) error { req := types.UpdateVirtualSwitch{ This: o.Reference(), VswitchName: vswitchName, Spec: spec, } - _, err := methods.UpdateVirtualSwitch(context.TODO(), o.c, &req) + _, err := methods.UpdateVirtualSwitch(ctx, o.c, &req) if err != nil { return err } diff --git a/host_system.go b/object/host_system.go similarity index 72% rename from host_system.go rename to object/host_system.go index 043e68f9c..b227be29c 100644 --- a/host_system.go +++ b/object/host_system.go @@ -14,42 +14,38 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( "fmt" "net" + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type HostSystem struct { - types.ManagedObjectReference + Common InventoryPath string - - c *Client } -func NewHostSystem(c *Client, ref types.ManagedObjectReference) *HostSystem { +func NewHostSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostSystem { return &HostSystem{ - ManagedObjectReference: ref, - c: c, + Common: NewCommon(c, ref), } } -func (h HostSystem) Reference() types.ManagedObjectReference { - return h.ManagedObjectReference -} - func (h HostSystem) ConfigManager() *HostConfigManager { - return &HostConfigManager{h.c, h} + return NewHostConfigManager(h.c, h.Reference()) } -func (h HostSystem) ResourcePool() (*ResourcePool, error) { +func (h HostSystem) ResourcePool(ctx context.Context) (*ResourcePool, error) { var mh mo.HostSystem - err := h.c.Properties(h.Reference(), []string{"parent"}, &mh) + + err := h.Properties(ctx, h.Reference(), []string{"parent"}, &mh) if err != nil { return nil, err } @@ -69,7 +65,7 @@ func (h HostSystem) ResourcePool() (*ResourcePool, error) { return nil, fmt.Errorf("unknown host parent type: %s", mh.Parent.Type) } - err = h.c.Properties(*mh.Parent, []string{"resourcePool"}, parent) + err = h.Properties(ctx, *mh.Parent, []string{"resourcePool"}, parent) if err != nil { return nil, err } @@ -78,10 +74,10 @@ func (h HostSystem) ResourcePool() (*ResourcePool, error) { return pool, nil } -func (h HostSystem) ManagementIPs() ([]net.IP, error) { +func (h HostSystem) ManagementIPs(ctx context.Context) ([]net.IP, error) { var mh mo.HostSystem - err := h.c.Properties(h.Reference(), []string{"config.virtualNicManagerInfo.netConfig"}, &mh) + err := h.Properties(ctx, h.Reference(), []string{"config.virtualNicManagerInfo.netConfig"}, &mh) if err != nil { return nil, err } diff --git a/object/http_nfc_lease.go b/object/http_nfc_lease.go new file mode 100644 index 000000000..c0dd334e7 --- /dev/null +++ b/object/http_nfc_lease.go @@ -0,0 +1,143 @@ +/* +Copyright (c) 2014 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 object + +import ( + "errors" + "fmt" + + "github.com/vmware/govmomi/property" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" +) + +type HttpNfcLease struct { + Common +} + +func NewHttpNfcLease(c *vim25.Client, ref types.ManagedObjectReference) *HttpNfcLease { + return &HttpNfcLease{ + Common: NewCommon(c, ref), + } +} + +// HttpNfcLeaseAbort wraps methods.HttpNfcLeaseAbort +func (o HttpNfcLease) HttpNfcLeaseAbort(ctx context.Context, fault *types.LocalizedMethodFault) error { + req := types.HttpNfcLeaseAbort{ + This: o.Reference(), + Fault: fault, + } + + _, err := methods.HttpNfcLeaseAbort(ctx, o.c, &req) + if err != nil { + return err + } + + return nil +} + +// HttpNfcLeaseComplete wraps methods.HttpNfcLeaseComplete +func (o HttpNfcLease) HttpNfcLeaseComplete(ctx context.Context) error { + req := types.HttpNfcLeaseComplete{ + This: o.Reference(), + } + + _, err := methods.HttpNfcLeaseComplete(ctx, o.c, &req) + if err != nil { + return err + } + + return nil +} + +// HttpNfcLeaseGetManifest wraps methods.HttpNfcLeaseGetManifest +func (o HttpNfcLease) HttpNfcLeaseGetManifest(ctx context.Context) error { + req := types.HttpNfcLeaseGetManifest{ + This: o.Reference(), + } + + _, err := methods.HttpNfcLeaseGetManifest(ctx, o.c, &req) + if err != nil { + return err + } + + return nil +} + +// HttpNfcLeaseProgress wraps methods.HttpNfcLeaseProgress +func (o HttpNfcLease) HttpNfcLeaseProgress(ctx context.Context, percent int) error { + req := types.HttpNfcLeaseProgress{ + This: o.Reference(), + Percent: percent, + } + + _, err := methods.HttpNfcLeaseProgress(ctx, o.c, &req) + if err != nil { + return err + } + + return nil +} + +func (o HttpNfcLease) Wait(ctx context.Context) (*types.HttpNfcLeaseInfo, error) { + var lease mo.HttpNfcLease + + pc := property.DefaultCollector(o.c) + err := property.Wait(ctx, pc, o.Reference(), []string{"state", "info", "error"}, func(pc []types.PropertyChange) bool { + done := false + + for _, c := range pc { + if c.Val == nil { + continue + } + + switch c.Name { + case "error": + val := c.Val.(types.LocalizedMethodFault) + lease.Error = &val + done = true + case "info": + val := c.Val.(types.HttpNfcLeaseInfo) + lease.Info = &val + case "state": + lease.State = c.Val.(types.HttpNfcLeaseState) + if lease.State != types.HttpNfcLeaseStateInitializing { + done = true + } + } + } + + return done + }) + + if err != nil { + return nil, err + } + + if lease.State == types.HttpNfcLeaseStateReady { + return lease.Info, nil + } + + if lease.Error != nil { + return nil, errors.New(lease.Error.LocalizedMessage) + } + + return nil, fmt.Errorf("unexpected nfc lease state: %s", lease.State) +} diff --git a/network.go b/object/network.go similarity index 75% rename from network.go rename to object/network.go index 3dbe1f24a..59e7048af 100644 --- a/network.go +++ b/object/network.go @@ -14,39 +14,34 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( "path" + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) type Network struct { - types.ManagedObjectReference + Common InventoryPath string - - c *Client } -func NewNetwork(c *Client, ref types.ManagedObjectReference) *Network { +func NewNetwork(c *vim25.Client, ref types.ManagedObjectReference) *Network { return &Network{ - ManagedObjectReference: ref, - c: c, + Common: NewCommon(c, ref), } } -func (n Network) Reference() types.ManagedObjectReference { - return n.ManagedObjectReference -} - func (n Network) Name() string { return path.Base(n.InventoryPath) } // EthernetCardBackingInfo returns the VirtualDeviceBackingInfo for this Network -func (n Network) EthernetCardBackingInfo() (types.BaseVirtualDeviceBackingInfo, error) { +func (n Network) EthernetCardBackingInfo(_ context.Context) (types.BaseVirtualDeviceBackingInfo, error) { name := n.Name() backing := &types.VirtualEthernetCardNetworkBackingInfo{ diff --git a/network_reference.go b/object/network_reference.go similarity index 80% rename from network_reference.go rename to object/network_reference.go index 0bebd1a17..9b8b7ebe8 100644 --- a/network_reference.go +++ b/object/network_reference.go @@ -14,12 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object -import "github.com/vmware/govmomi/vim25/types" +import ( + "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" +) // The NetworkReference interface is implemented by managed objects // which can be used as the backing for a VirtualEthernetCard. type NetworkReference interface { - EthernetCardBackingInfo() (types.BaseVirtualDeviceBackingInfo, error) + EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) } diff --git a/network_test.go b/object/network_test.go similarity index 97% rename from network_test.go rename to object/network_test.go index 4e854bbe6..faa42f2fd 100644 --- a/network_test.go +++ b/object/network_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object // Network should implement the Reference interface. var _ Reference = Network{} diff --git a/ovf_manager_gen.go b/object/ovf_manager.go similarity index 58% rename from ovf_manager_gen.go rename to object/ovf_manager.go index af4cf6e33..aa20388ea 100644 --- a/ovf_manager_gen.go +++ b/object/ovf_manager.go @@ -14,27 +14,36 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/types" "golang.org/x/net/context" ) type OvfManager struct { - c *Client + Common +} + +func NewOvfManager(c *vim25.Client) *OvfManager { + o := OvfManager{ + Common: NewCommon(c, *c.ServiceContent.OvfManager), + } + + return &o } // CreateDescriptor wraps methods.CreateDescriptor -func (o OvfManager) CreateDescriptor(obj Reference, cdp types.OvfCreateDescriptorParams) (*types.OvfCreateDescriptorResult, error) { +func (o OvfManager) CreateDescriptor(ctx context.Context, obj Reference, cdp types.OvfCreateDescriptorParams) (*types.OvfCreateDescriptorResult, error) { req := types.CreateDescriptor{ - This: *o.c.ServiceContent.OvfManager, + This: o.Reference(), Obj: obj.Reference(), Cdp: cdp, } - res, err := methods.CreateDescriptor(context.TODO(), o.c, &req) + res, err := methods.CreateDescriptor(ctx, o.c, &req) if err != nil { return nil, err } @@ -43,16 +52,16 @@ func (o OvfManager) CreateDescriptor(obj Reference, cdp types.OvfCreateDescripto } // CreateImportSpec wraps methods.CreateImportSpec -func (o OvfManager) CreateImportSpec(ovfDescriptor string, resourcePool Reference, datastore Reference, cisp types.OvfCreateImportSpecParams) (*types.OvfCreateImportSpecResult, error) { +func (o OvfManager) CreateImportSpec(ctx context.Context, ovfDescriptor string, resourcePool Reference, datastore Reference, cisp types.OvfCreateImportSpecParams) (*types.OvfCreateImportSpecResult, error) { req := types.CreateImportSpec{ - This: *o.c.ServiceContent.OvfManager, + This: o.Reference(), OvfDescriptor: ovfDescriptor, ResourcePool: resourcePool.Reference(), Datastore: datastore.Reference(), Cisp: cisp, } - res, err := methods.CreateImportSpec(context.TODO(), o.c, &req) + res, err := methods.CreateImportSpec(ctx, o.c, &req) if err != nil { return nil, err } @@ -61,14 +70,14 @@ func (o OvfManager) CreateImportSpec(ovfDescriptor string, resourcePool Referenc } // ParseDescriptor wraps methods.ParseDescriptor -func (o OvfManager) ParseDescriptor(ovfDescriptor string, pdp types.OvfParseDescriptorParams) (*types.OvfParseDescriptorResult, error) { +func (o OvfManager) ParseDescriptor(ctx context.Context, ovfDescriptor string, pdp types.OvfParseDescriptorParams) (*types.OvfParseDescriptorResult, error) { req := types.ParseDescriptor{ - This: *o.c.ServiceContent.OvfManager, + This: o.Reference(), OvfDescriptor: ovfDescriptor, Pdp: pdp, } - res, err := methods.ParseDescriptor(context.TODO(), o.c, &req) + res, err := methods.ParseDescriptor(ctx, o.c, &req) if err != nil { return nil, err } @@ -77,15 +86,15 @@ func (o OvfManager) ParseDescriptor(ovfDescriptor string, pdp types.OvfParseDesc } // ValidateHost wraps methods.ValidateHost -func (o OvfManager) ValidateHost(ovfDescriptor string, host Reference, vhp types.OvfValidateHostParams) (*types.OvfValidateHostResult, error) { +func (o OvfManager) ValidateHost(ctx context.Context, ovfDescriptor string, host Reference, vhp types.OvfValidateHostParams) (*types.OvfValidateHostResult, error) { req := types.ValidateHost{ - This: *o.c.ServiceContent.OvfManager, + This: o.Reference(), OvfDescriptor: ovfDescriptor, Host: host.Reference(), Vhp: vhp, } - res, err := methods.ValidateHost(context.TODO(), o.c, &req) + res, err := methods.ValidateHost(ctx, o.c, &req) if err != nil { return nil, err } diff --git a/resource_pool.go b/object/resource_pool.go similarity index 64% rename from resource_pool.go rename to object/resource_pool.go index ae232c395..f45a59549 100644 --- a/resource_pool.go +++ b/object/resource_pool.go @@ -14,34 +14,28 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/types" "golang.org/x/net/context" ) type ResourcePool struct { - types.ManagedObjectReference + Common InventoryPath string - - c *Client } -func NewResourcePool(c *Client, ref types.ManagedObjectReference) *ResourcePool { +func NewResourcePool(c *vim25.Client, ref types.ManagedObjectReference) *ResourcePool { return &ResourcePool{ - ManagedObjectReference: ref, - c: c, + Common: NewCommon(c, ref), } } -func (p ResourcePool) Reference() types.ManagedObjectReference { - return p.ManagedObjectReference -} - -func (p ResourcePool) ImportVApp(spec types.BaseImportSpec, folder *Folder, host *HostSystem) (*HttpNfcLease, error) { +func (p ResourcePool) ImportVApp(ctx context.Context, spec types.BaseImportSpec, folder *Folder, host *HostSystem) (*HttpNfcLease, error) { req := types.ImportVApp{ This: p.Reference(), Spec: spec, @@ -57,7 +51,7 @@ func (p ResourcePool) ImportVApp(spec types.BaseImportSpec, folder *Folder, host req.Host = &ref } - res, err := methods.ImportVApp(context.TODO(), p.c, &req) + res, err := methods.ImportVApp(ctx, p.c, &req) if err != nil { return nil, err } @@ -65,14 +59,14 @@ func (p ResourcePool) ImportVApp(spec types.BaseImportSpec, folder *Folder, host return NewHttpNfcLease(p.c, res.Returnval), nil } -func (p ResourcePool) Create(name string, spec types.ResourceConfigSpec) (*ResourcePool, error) { +func (p ResourcePool) Create(ctx context.Context, name string, spec types.ResourceConfigSpec) (*ResourcePool, error) { req := types.CreateResourcePool{ This: p.Reference(), Name: name, Spec: spec, } - res, err := methods.CreateResourcePool(context.TODO(), p.c, &req) + res, err := methods.CreateResourcePool(ctx, p.c, &req) if err != nil { return nil, err } @@ -80,7 +74,7 @@ func (p ResourcePool) Create(name string, spec types.ResourceConfigSpec) (*Resou return NewResourcePool(p.c, res.Returnval), nil } -func (p ResourcePool) UpdateConfig(name string, config *types.ResourceConfigSpec) error { +func (p ResourcePool) UpdateConfig(ctx context.Context, name string, config *types.ResourceConfigSpec) error { req := types.UpdateConfig{ This: p.Reference(), Name: name, @@ -96,25 +90,25 @@ func (p ResourcePool) UpdateConfig(name string, config *types.ResourceConfigSpec req.Config = &newConfig } - _, err := methods.UpdateConfig(context.TODO(), p.c, &req) + _, err := methods.UpdateConfig(ctx, p.c, &req) return err } -func (p ResourcePool) DestroyChildren() error { +func (p ResourcePool) DestroyChildren(ctx context.Context) error { req := types.DestroyChildren{ This: p.Reference(), } - _, err := methods.DestroyChildren(context.TODO(), p.c, &req) + _, err := methods.DestroyChildren(ctx, p.c, &req) return err } -func (p ResourcePool) Destroy() (*Task, error) { +func (p ResourcePool) Destroy(ctx context.Context) (*Task, error) { req := types.Destroy_Task{ This: p.Reference(), } - res, err := methods.Destroy_Task(context.TODO(), p.c, &req) + res, err := methods.Destroy_Task(ctx, p.c, &req) if err != nil { return nil, err } diff --git a/search_index.go b/object/search_index.go similarity index 66% rename from search_index.go rename to object/search_index.go index c41844a73..f44897dbe 100644 --- a/search_index.go +++ b/object/search_index.go @@ -14,27 +14,36 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/types" "golang.org/x/net/context" ) type SearchIndex struct { - c *Client + Common +} + +func NewSearchIndex(c *vim25.Client) *SearchIndex { + s := SearchIndex{ + Common: NewCommon(c, *c.ServiceContent.SearchIndex), + } + + return &s } // FindByDatastorePath finds a virtual machine by its location on a datastore. -func (s SearchIndex) FindByDatastorePath(dc *Datacenter, path string) (Reference, error) { +func (s SearchIndex) FindByDatastorePath(ctx context.Context, dc *Datacenter, path string) (Reference, error) { req := types.FindByDatastorePath{ - This: *s.c.ServiceContent.SearchIndex, + This: s.Reference(), Datacenter: dc.Reference(), Path: path, } - res, err := methods.FindByDatastorePath(context.TODO(), s.c, &req) + res, err := methods.FindByDatastorePath(ctx, s.c, &req) if err != nil { return nil, err } @@ -46,9 +55,9 @@ func (s SearchIndex) FindByDatastorePath(dc *Datacenter, path string) (Reference } // FindByDnsName finds a virtual machine or host by DNS name. -func (s SearchIndex) FindByDnsName(dc *Datacenter, dnsName string, vmSearch bool) (Reference, error) { +func (s SearchIndex) FindByDnsName(ctx context.Context, dc *Datacenter, dnsName string, vmSearch bool) (Reference, error) { req := types.FindByDnsName{ - This: *s.c.ServiceContent.SearchIndex, + This: s.Reference(), DnsName: dnsName, VmSearch: vmSearch, } @@ -57,7 +66,7 @@ func (s SearchIndex) FindByDnsName(dc *Datacenter, dnsName string, vmSearch bool req.Datacenter = &ref } - res, err := methods.FindByDnsName(context.TODO(), s.c, &req) + res, err := methods.FindByDnsName(ctx, s.c, &req) if err != nil { return nil, err } @@ -69,13 +78,13 @@ func (s SearchIndex) FindByDnsName(dc *Datacenter, dnsName string, vmSearch bool } // FindByInventoryPath finds a managed entity based on its location in the inventory. -func (s SearchIndex) FindByInventoryPath(path string) (Reference, error) { +func (s SearchIndex) FindByInventoryPath(ctx context.Context, path string) (Reference, error) { req := types.FindByInventoryPath{ - This: *s.c.ServiceContent.SearchIndex, + This: s.Reference(), InventoryPath: path, } - res, err := methods.FindByInventoryPath(context.TODO(), s.c, &req) + res, err := methods.FindByInventoryPath(ctx, s.c, &req) if err != nil { return nil, err } @@ -87,9 +96,9 @@ func (s SearchIndex) FindByInventoryPath(path string) (Reference, error) { } // FindByIp finds a virtual machine or host by IP address. -func (s SearchIndex) FindByIp(dc *Datacenter, ip string, vmSearch bool) (Reference, error) { +func (s SearchIndex) FindByIp(ctx context.Context, dc *Datacenter, ip string, vmSearch bool) (Reference, error) { req := types.FindByIp{ - This: *s.c.ServiceContent.SearchIndex, + This: s.Reference(), Ip: ip, VmSearch: vmSearch, } @@ -98,7 +107,7 @@ func (s SearchIndex) FindByIp(dc *Datacenter, ip string, vmSearch bool) (Referen req.Datacenter = &ref } - res, err := methods.FindByIp(context.TODO(), s.c, &req) + res, err := methods.FindByIp(ctx, s.c, &req) if err != nil { return nil, err } @@ -110,9 +119,9 @@ func (s SearchIndex) FindByIp(dc *Datacenter, ip string, vmSearch bool) (Referen } // FindByUuid finds a virtual machine or host by UUID. -func (s SearchIndex) FindByUuid(dc *Datacenter, uuid string, vmSearch bool) (Reference, error) { +func (s SearchIndex) FindByUuid(ctx context.Context, dc *Datacenter, uuid string, vmSearch bool) (Reference, error) { req := types.FindByUuid{ - This: *s.c.ServiceContent.SearchIndex, + This: s.Reference(), Uuid: uuid, VmSearch: vmSearch, } @@ -121,7 +130,7 @@ func (s SearchIndex) FindByUuid(dc *Datacenter, uuid string, vmSearch bool) (Ref req.Datacenter = &ref } - res, err := methods.FindByUuid(context.TODO(), s.c, &req) + res, err := methods.FindByUuid(ctx, s.c, &req) if err != nil { return nil, err } @@ -133,14 +142,14 @@ func (s SearchIndex) FindByUuid(dc *Datacenter, uuid string, vmSearch bool) (Ref } // FindChild finds a particular child based on a managed entity name. -func (s SearchIndex) FindChild(entity Reference, name string) (Reference, error) { +func (s SearchIndex) FindChild(ctx context.Context, entity Reference, name string) (Reference, error) { req := types.FindChild{ - This: *s.c.ServiceContent.SearchIndex, + This: s.Reference(), Entity: entity.Reference(), Name: name, } - res, err := methods.FindChild(context.TODO(), s.c, &req) + res, err := methods.FindChild(ctx, s.c, &req) if err != nil { return nil, err } diff --git a/search_index_test.go b/object/search_index_test.go similarity index 55% rename from search_index_test.go rename to object/search_index_test.go index ce6812198..9581f6ed5 100644 --- a/search_index_test.go +++ b/object/search_index_test.go @@ -14,30 +14,22 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( "reflect" "testing" - "github.com/vmware/govmomi/test" + "github.com/vmware/govmomi/test/client" "github.com/vmware/govmomi/vim25/mo" + "golang.org/x/net/context" ) func TestSearch(t *testing.T) { - u := test.URL() - if u == nil { - t.SkipNow() - } - - c, err := NewClient(*u, true) - if err != nil { - t.Error(err) - } - - s := c.SearchIndex() + c := client.NewAuthenticatedClient(t) + s := NewSearchIndex(c) - ref, err := s.FindChild(c.RootFolder(), "ha-datacenter") + ref, err := s.FindChild(context.Background(), NewRootFolder(c), "ha-datacenter") if err != nil { t.Fatal(err) } @@ -47,12 +39,12 @@ func TestSearch(t *testing.T) { t.Errorf("Expected Datacenter: %#v", ref) } - folders, err := dc.Folders() + folders, err := dc.Folders(context.Background()) if err != nil { t.Fatal(err) } - ref, err = s.FindChild(folders.DatastoreFolder, "datastore1") + ref, err = s.FindChild(context.Background(), folders.DatastoreFolder, "datastore1") if err != nil { t.Fatal(err) } @@ -62,7 +54,7 @@ func TestSearch(t *testing.T) { t.Errorf("Expected Datastore: %#v", ref) } - ref, err = s.FindByInventoryPath("/ha-datacenter/network/VM Network") + ref, err = s.FindByInventoryPath(context.Background(), "/ha-datacenter/network/VM Network") if err != nil { t.Fatal(err) } @@ -72,7 +64,7 @@ func TestSearch(t *testing.T) { t.Errorf("Expected Network: %#v", ref) } - crs, err := folders.HostFolder.Children() + crs, err := folders.HostFolder.Children(context.Background()) if err != nil { if err != nil { t.Fatal(err) @@ -81,27 +73,31 @@ func TestSearch(t *testing.T) { if len(crs) != 0 { var cr mo.ComputeResource ref = crs[0] - err = c.Properties(ref.Reference(), []string{"host"}, &cr) + err = s.Properties(context.Background(), ref.Reference(), []string{"host"}, &cr) if err != nil { t.Fatal(err) } var host mo.HostSystem ref = NewHostSystem(c, cr.Host[0]) - err = c.Properties(ref.Reference(), []string{"name", "hardware"}, &host) - if err != nil { - t.Fatal(err) - } - - shost, err := s.FindByDnsName(dc, host.Name, false) // TODO: get name/ip from nic manager + err = s.Properties(context.Background(), ref.Reference(), []string{"name", "hardware"}, &host) if err != nil { t.Fatal(err) } - if !reflect.DeepEqual(ref, shost) { - t.Errorf("%#v != %#v\n", ref, shost) - } - shost, err = s.FindByUuid(dc, host.Hardware.SystemInfo.Uuid, false) + // The test below doesn't work on a fresh esxbox (see govc/test/esxbox). + // This should use a different way to figure out the machine's hostname, + // such that FindByDnsName returns it. + // + //shost, err := s.FindByDnsName(context.Background(), dc, host.Name, false) // TODO: get name/ip from nic manager + //if err != nil { + // t.Fatal(err) + //} + //if !reflect.DeepEqual(ref, shost) { + // t.Errorf("%#v != %#v\n", ref, shost) + //} + + shost, err := s.FindByUuid(context.Background(), dc, host.Hardware.SystemInfo.Uuid, false) if err != nil { t.Fatal(err) } @@ -110,18 +106,18 @@ func TestSearch(t *testing.T) { } } - vms, err := folders.VmFolder.Children() + vms, err := folders.VmFolder.Children(context.Background()) if err != nil { t.Fatal(err) } if len(vms) != 0 { var vm mo.VirtualMachine ref = vms[0] - err = c.Properties(ref.Reference(), []string{"config", "guest"}, &vm) + err = s.Properties(context.Background(), ref.Reference(), []string{"config", "guest"}, &vm) if err != nil { t.Fatal(err) } - svm, err := s.FindByDatastorePath(dc, vm.Config.Files.VmPathName) + svm, err := s.FindByDatastorePath(context.Background(), dc, vm.Config.Files.VmPathName) if err != nil { t.Fatal(err) } @@ -129,7 +125,7 @@ func TestSearch(t *testing.T) { t.Errorf("%#v != %#v\n", ref, svm) } - svm, err = s.FindByUuid(dc, vm.Config.Uuid, true) + svm, err = s.FindByUuid(context.Background(), dc, vm.Config.Uuid, true) if err != nil { t.Fatal(err) } @@ -138,7 +134,7 @@ func TestSearch(t *testing.T) { } if vm.Guest.HostName != "" { - svm, err := s.FindByDnsName(dc, vm.Guest.HostName, true) + svm, err := s.FindByDnsName(context.Background(), dc, vm.Guest.HostName, true) if err != nil { t.Fatal(err) } @@ -148,7 +144,7 @@ func TestSearch(t *testing.T) { } if vm.Guest.IpAddress != "" { - svm, err := s.FindByIp(dc, vm.Guest.IpAddress, true) + svm, err := s.FindByIp(context.Background(), dc, vm.Guest.IpAddress, true) if err != nil { t.Fatal(err) } diff --git a/storage_pod.go b/object/storage_pod.go similarity index 97% rename from storage_pod.go rename to object/storage_pod.go index 811cb7c3a..dfb66625d 100644 --- a/storage_pod.go +++ b/object/storage_pod.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object type StoragePod struct { *Folder diff --git a/storage_resource_manager.go b/object/storage_resource_manager.go similarity index 55% rename from storage_resource_manager.go rename to object/storage_resource_manager.go index 2149b6fef..dab9d2549 100644 --- a/storage_resource_manager.go +++ b/object/storage_resource_manager.go @@ -14,25 +14,34 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/types" "golang.org/x/net/context" ) type StorageResourceManager struct { - c *Client + Common } -func (sr StorageResourceManager) ApplyStorageDrsRecommendation(key []string) (*Task, error) { +func NewStorageResourceManager(c *vim25.Client) *StorageResourceManager { + sr := StorageResourceManager{ + Common: NewCommon(c, *c.ServiceContent.StorageResourceManager), + } + + return &sr +} + +func (sr StorageResourceManager) ApplyStorageDrsRecommendation(ctx context.Context, key []string) (*Task, error) { req := types.ApplyStorageDrsRecommendation_Task{ - This: *sr.c.ServiceContent.StorageResourceManager, + This: sr.Reference(), Key: key, } - res, err := methods.ApplyStorageDrsRecommendation_Task(context.TODO(), sr.c, &req) + res, err := methods.ApplyStorageDrsRecommendation_Task(ctx, sr.c, &req) if err != nil { return nil, err } @@ -40,9 +49,9 @@ func (sr StorageResourceManager) ApplyStorageDrsRecommendation(key []string) (*T return NewTask(sr.c, res.Returnval), nil } -func (sr StorageResourceManager) ApplyStorageDrsRecommendationToPod(pod *StoragePod, key string) (*Task, error) { +func (sr StorageResourceManager) ApplyStorageDrsRecommendationToPod(ctx context.Context, pod *StoragePod, key string) (*Task, error) { req := types.ApplyStorageDrsRecommendationToPod_Task{ - This: *sr.c.ServiceContent.StorageResourceManager, + This: sr.Reference(), Key: key, } @@ -50,7 +59,7 @@ func (sr StorageResourceManager) ApplyStorageDrsRecommendationToPod(pod *Storage req.Pod = pod.Reference() } - res, err := methods.ApplyStorageDrsRecommendationToPod_Task(context.TODO(), sr.c, &req) + res, err := methods.ApplyStorageDrsRecommendationToPod_Task(ctx, sr.c, &req) if err != nil { return nil, err } @@ -58,20 +67,20 @@ func (sr StorageResourceManager) ApplyStorageDrsRecommendationToPod(pod *Storage return NewTask(sr.c, res.Returnval), nil } -func (sr StorageResourceManager) CancelStorageDrsRecommendation(key []string) error { +func (sr StorageResourceManager) CancelStorageDrsRecommendation(ctx context.Context, key []string) error { req := types.CancelStorageDrsRecommendation{ - This: *sr.c.ServiceContent.StorageResourceManager, + This: sr.Reference(), Key: key, } - _, err := methods.CancelStorageDrsRecommendation(context.TODO(), sr.c, &req) + _, err := methods.CancelStorageDrsRecommendation(ctx, sr.c, &req) return err } -func (sr StorageResourceManager) ConfigureDatastoreIORM(datastore *Datastore, spec types.StorageIORMConfigSpec, key string) (*Task, error) { +func (sr StorageResourceManager) ConfigureDatastoreIORM(ctx context.Context, datastore *Datastore, spec types.StorageIORMConfigSpec, key string) (*Task, error) { req := types.ConfigureDatastoreIORM_Task{ - This: *sr.c.ServiceContent.StorageResourceManager, + This: sr.Reference(), Spec: spec, } @@ -79,7 +88,7 @@ func (sr StorageResourceManager) ConfigureDatastoreIORM(datastore *Datastore, sp req.Datastore = datastore.Reference() } - res, err := methods.ConfigureDatastoreIORM_Task(context.TODO(), sr.c, &req) + res, err := methods.ConfigureDatastoreIORM_Task(ctx, sr.c, &req) if err != nil { return nil, err } @@ -87,9 +96,9 @@ func (sr StorageResourceManager) ConfigureDatastoreIORM(datastore *Datastore, sp return NewTask(sr.c, res.Returnval), nil } -func (sr StorageResourceManager) ConfigureStorageDrsForPod(pod *StoragePod, spec types.StorageDrsConfigSpec, modify bool) (*Task, error) { +func (sr StorageResourceManager) ConfigureStorageDrsForPod(ctx context.Context, pod *StoragePod, spec types.StorageDrsConfigSpec, modify bool) (*Task, error) { req := types.ConfigureStorageDrsForPod_Task{ - This: *sr.c.ServiceContent.StorageResourceManager, + This: sr.Reference(), Spec: spec, Modify: modify, } @@ -98,7 +107,7 @@ func (sr StorageResourceManager) ConfigureStorageDrsForPod(pod *StoragePod, spec req.Pod = pod.Reference() } - res, err := methods.ConfigureStorageDrsForPod_Task(context.TODO(), sr.c, &req) + res, err := methods.ConfigureStorageDrsForPod_Task(ctx, sr.c, &req) if err != nil { return nil, err } @@ -106,16 +115,16 @@ func (sr StorageResourceManager) ConfigureStorageDrsForPod(pod *StoragePod, spec return NewTask(sr.c, res.Returnval), nil } -func (sr StorageResourceManager) QueryDatastorePerformanceSummary(datastore *Datastore) ([]types.StoragePerformanceSummary, error) { +func (sr StorageResourceManager) QueryDatastorePerformanceSummary(ctx context.Context, datastore *Datastore) ([]types.StoragePerformanceSummary, error) { req := types.QueryDatastorePerformanceSummary{ - This: *sr.c.ServiceContent.StorageResourceManager, + This: sr.Reference(), } if datastore != nil { req.Datastore = datastore.Reference() } - res, err := methods.QueryDatastorePerformanceSummary(context.TODO(), sr.c, &req) + res, err := methods.QueryDatastorePerformanceSummary(ctx, sr.c, &req) if err != nil { return nil, err } @@ -123,16 +132,16 @@ func (sr StorageResourceManager) QueryDatastorePerformanceSummary(datastore *Dat return res.Returnval, nil } -func (sr StorageResourceManager) QueryIORMConfigOption(host *HostSystem) (*types.StorageIORMConfigOption, error) { +func (sr StorageResourceManager) QueryIORMConfigOption(ctx context.Context, host *HostSystem) (*types.StorageIORMConfigOption, error) { req := types.QueryIORMConfigOption{ - This: *sr.c.ServiceContent.StorageResourceManager, + This: sr.Reference(), } if host != nil { req.Host = host.Reference() } - res, err := methods.QueryIORMConfigOption(context.TODO(), sr.c, &req) + res, err := methods.QueryIORMConfigOption(ctx, sr.c, &req) if err != nil { return nil, err } @@ -140,13 +149,13 @@ func (sr StorageResourceManager) QueryIORMConfigOption(host *HostSystem) (*types return &res.Returnval, nil } -func (sr StorageResourceManager) RecommendDatastores(storageSpec types.StoragePlacementSpec) (*types.StoragePlacementResult, error) { +func (sr StorageResourceManager) RecommendDatastores(ctx context.Context, storageSpec types.StoragePlacementSpec) (*types.StoragePlacementResult, error) { req := types.RecommendDatastores{ - This: *sr.c.ServiceContent.StorageResourceManager, + This: sr.Reference(), StorageSpec: storageSpec, } - res, err := methods.RecommendDatastores(context.TODO(), sr.c, &req) + res, err := methods.RecommendDatastores(ctx, sr.c, &req) if err != nil { return nil, err } @@ -154,16 +163,16 @@ func (sr StorageResourceManager) RecommendDatastores(storageSpec types.StoragePl return &res.Returnval, nil } -func (sr StorageResourceManager) RefreshStorageDrsRecommendation(pod *StoragePod) error { +func (sr StorageResourceManager) RefreshStorageDrsRecommendation(ctx context.Context, pod *StoragePod) error { req := types.RefreshStorageDrsRecommendation{ - This: *sr.c.ServiceContent.StorageResourceManager, + This: sr.Reference(), } if pod != nil { req.Pod = pod.Reference() } - _, err := methods.RefreshStorageDrsRecommendation(context.TODO(), sr.c, &req) + _, err := methods.RefreshStorageDrsRecommendation(ctx, sr.c, &req) return err } diff --git a/object/task.go b/object/task.go new file mode 100644 index 000000000..81834854a --- /dev/null +++ b/object/task.go @@ -0,0 +1,52 @@ +/* +Copyright (c) 2014 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 object + +import ( + "github.com/vmware/govmomi/property" + "github.com/vmware/govmomi/task" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/progress" + "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" +) + +// Task is a convenience wrapper around task.Task that keeps a reference to +// the client that was used to create it. This allows users to call the Wait() +// function with only a context parameter, instead of a context parameter, a +// soap.RoundTripper, and reference to the root property collector. +type Task struct { + Common +} + +func NewTask(c *vim25.Client, ref types.ManagedObjectReference) *Task { + t := Task{ + Common: NewCommon(c, ref), + } + + return &t +} + +func (t *Task) Wait(ctx context.Context) error { + _, err := t.WaitForResult(ctx, nil) + return err +} + +func (t *Task) WaitForResult(ctx context.Context, s progress.Sinker) (*types.TaskInfo, error) { + p := property.DefaultCollector(t.c) + return task.Wait(ctx, t.Reference(), p, s) +} diff --git a/types.go b/object/types.go similarity index 76% rename from types.go rename to object/types.go index 6ea4138e8..c94543745 100644 --- a/types.go +++ b/object/types.go @@ -14,15 +14,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object -import "github.com/vmware/govmomi/vim25/types" +import ( + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/types" +) type Reference interface { Reference() types.ManagedObjectReference } -func NewReference(c *Client, e types.ManagedObjectReference) Reference { +func NewReference(c *vim25.Client, e types.ManagedObjectReference) Reference { switch e.Type { case "Folder": return NewFolder(c, e) @@ -39,11 +42,9 @@ func NewReference(c *Client, e types.ManagedObjectReference) Reference { NewResourcePool(c, e), } case "ComputeResource": - return &ComputeResource{ManagedObjectReference: e} + return NewComputeResource(c, e) case "ClusterComputeResource": - return &ClusterComputeResource{ - ComputeResource{ManagedObjectReference: e}, - } + return &ClusterComputeResource{*NewComputeResource(c, e)} case "HostSystem": return NewHostSystem(c, e) case "Network": @@ -51,11 +52,9 @@ func NewReference(c *Client, e types.ManagedObjectReference) Reference { case "ResourcePool": return NewResourcePool(c, e) case "DistributedVirtualSwitch": - return &DistributedVirtualSwitch{ManagedObjectReference: e} + return NewDistributedVirtualSwitch(c, e) case "VmwareDistributedVirtualSwitch": - return &VmwareDistributedVirtualSwitch{ - DistributedVirtualSwitch{ManagedObjectReference: e}, - } + return &VmwareDistributedVirtualSwitch{*NewDistributedVirtualSwitch(c, e)} case "DistributedVirtualPortgroup": return NewDistributedVirtualPortgroup(c, e) case "Datastore": diff --git a/virtual_app.go b/object/virtual_app.go similarity index 97% rename from virtual_app.go rename to object/virtual_app.go index 85a2807c8..63f63a923 100644 --- a/virtual_app.go +++ b/object/virtual_app.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object type VirtualApp struct { *ResourcePool diff --git a/virtual_device_list.go b/object/virtual_device_list.go similarity index 99% rename from virtual_device_list.go rename to object/virtual_device_list.go index c19f44284..6da90319e 100644 --- a/virtual_device_list.go +++ b/object/virtual_device_list.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( "errors" diff --git a/virtual_device_list_test.go b/object/virtual_device_list_test.go similarity index 99% rename from virtual_device_list_test.go rename to object/virtual_device_list_test.go index eae0e0ee3..5f7407824 100644 --- a/virtual_device_list_test.go +++ b/object/virtual_device_list_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( "math/rand" diff --git a/virtual_disk_manager.go b/object/virtual_disk_manager.go similarity index 78% rename from virtual_disk_manager.go rename to object/virtual_disk_manager.go index 79247ed56..36d1b5820 100644 --- a/virtual_disk_manager.go +++ b/object/virtual_disk_manager.go @@ -14,26 +14,36 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/types" "golang.org/x/net/context" ) type VirtualDiskManager struct { - c *Client + Common +} + +func NewVirtualDiskManager(c *vim25.Client) *VirtualDiskManager { + m := VirtualDiskManager{ + Common: NewCommon(c, *c.ServiceContent.VirtualDiskManager), + } + + return &m } // CopyVirtualDisk copies a virtual disk, performing conversions as specified in the spec. func (m VirtualDiskManager) CopyVirtualDisk( + ctx context.Context, sourceName string, sourceDatacenter *Datacenter, destName string, destDatacenter *Datacenter, destSpec *types.VirtualDiskSpec, force bool) (*Task, error) { req := types.CopyVirtualDisk_Task{ - This: *m.c.ServiceContent.VirtualDiskManager, + This: m.Reference(), SourceName: sourceName, DestName: destName, DestSpec: destSpec, @@ -50,7 +60,7 @@ func (m VirtualDiskManager) CopyVirtualDisk( req.DestDatacenter = &ref } - res, err := methods.CopyVirtualDisk_Task(context.TODO(), m.c, &req) + res, err := methods.CopyVirtualDisk_Task(ctx, m.c, &req) if err != nil { return nil, err } @@ -60,11 +70,12 @@ func (m VirtualDiskManager) CopyVirtualDisk( // MoveVirtualDisk moves a virtual disk. func (m VirtualDiskManager) MoveVirtualDisk( + ctx context.Context, sourceName string, sourceDatacenter *Datacenter, destName string, destDatacenter *Datacenter, force bool) (*Task, error) { req := types.MoveVirtualDisk_Task{ - This: *m.c.ServiceContent.VirtualDiskManager, + This: m.Reference(), SourceName: sourceName, DestName: destName, Force: force, @@ -80,7 +91,7 @@ func (m VirtualDiskManager) MoveVirtualDisk( req.DestDatacenter = &ref } - res, err := methods.MoveVirtualDisk_Task(context.TODO(), m.c, &req) + res, err := methods.MoveVirtualDisk_Task(ctx, m.c, &req) if err != nil { return nil, err } @@ -89,9 +100,9 @@ func (m VirtualDiskManager) MoveVirtualDisk( } // DeleteVirtualDisk deletes a virtual disk. -func (m VirtualDiskManager) DeleteVirtualDisk(name string, dc *Datacenter) (*Task, error) { +func (m VirtualDiskManager) DeleteVirtualDisk(ctx context.Context, name string, dc *Datacenter) (*Task, error) { req := types.DeleteVirtualDisk_Task{ - This: *m.c.ServiceContent.VirtualDiskManager, + This: m.Reference(), Name: name, } @@ -100,7 +111,7 @@ func (m VirtualDiskManager) DeleteVirtualDisk(name string, dc *Datacenter) (*Tas req.Datacenter = &ref } - res, err := methods.DeleteVirtualDisk_Task(context.TODO(), m.c, &req) + res, err := methods.DeleteVirtualDisk_Task(ctx, m.c, &req) if err != nil { return nil, err } diff --git a/virtual_machine.go b/object/virtual_machine.go similarity index 55% rename from virtual_machine.go rename to object/virtual_machine.go index ccd061326..a741f7cd6 100644 --- a/virtual_machine.go +++ b/object/virtual_machine.go @@ -14,9 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object import ( + "github.com/vmware/govmomi/property" + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" @@ -24,30 +26,23 @@ import ( ) type VirtualMachine struct { - types.ManagedObjectReference + Common InventoryPath string - - c *Client } -func NewVirtualMachine(c *Client, ref types.ManagedObjectReference) *VirtualMachine { +func NewVirtualMachine(c *vim25.Client, ref types.ManagedObjectReference) *VirtualMachine { return &VirtualMachine{ - ManagedObjectReference: ref, - c: c, + Common: NewCommon(c, ref), } } -func (v VirtualMachine) Reference() types.ManagedObjectReference { - return v.ManagedObjectReference -} - -func (v VirtualMachine) PowerOn() (*Task, error) { +func (v VirtualMachine) PowerOn(ctx context.Context) (*Task, error) { req := types.PowerOnVM_Task{ This: v.Reference(), } - res, err := methods.PowerOnVM_Task(context.TODO(), v.c, &req) + res, err := methods.PowerOnVM_Task(ctx, v.c, &req) if err != nil { return nil, err } @@ -55,12 +50,12 @@ func (v VirtualMachine) PowerOn() (*Task, error) { return NewTask(v.c, res.Returnval), nil } -func (v VirtualMachine) PowerOff() (*Task, error) { +func (v VirtualMachine) PowerOff(ctx context.Context) (*Task, error) { req := types.PowerOffVM_Task{ This: v.Reference(), } - res, err := methods.PowerOffVM_Task(context.TODO(), v.c, &req) + res, err := methods.PowerOffVM_Task(ctx, v.c, &req) if err != nil { return nil, err } @@ -68,12 +63,12 @@ func (v VirtualMachine) PowerOff() (*Task, error) { return NewTask(v.c, res.Returnval), nil } -func (v VirtualMachine) Reset() (*Task, error) { +func (v VirtualMachine) Reset(ctx context.Context) (*Task, error) { req := types.ResetVM_Task{ This: v.Reference(), } - res, err := methods.ResetVM_Task(context.TODO(), v.c, &req) + res, err := methods.ResetVM_Task(ctx, v.c, &req) if err != nil { return nil, err } @@ -81,12 +76,12 @@ func (v VirtualMachine) Reset() (*Task, error) { return NewTask(v.c, res.Returnval), nil } -func (v VirtualMachine) Suspend() (*Task, error) { +func (v VirtualMachine) Suspend(ctx context.Context) (*Task, error) { req := types.SuspendVM_Task{ This: v.Reference(), } - res, err := methods.SuspendVM_Task(context.TODO(), v.c, &req) + res, err := methods.SuspendVM_Task(ctx, v.c, &req) if err != nil { return nil, err } @@ -94,30 +89,30 @@ func (v VirtualMachine) Suspend() (*Task, error) { return NewTask(v.c, res.Returnval), nil } -func (v VirtualMachine) ShutdownGuest() error { +func (v VirtualMachine) ShutdownGuest(ctx context.Context) error { req := types.ShutdownGuest{ This: v.Reference(), } - _, err := methods.ShutdownGuest(context.TODO(), v.c, &req) + _, err := methods.ShutdownGuest(ctx, v.c, &req) return err } -func (v VirtualMachine) RebootGuest() error { +func (v VirtualMachine) RebootGuest(ctx context.Context) error { req := types.RebootGuest{ This: v.Reference(), } - _, err := methods.RebootGuest(context.TODO(), v.c, &req) + _, err := methods.RebootGuest(ctx, v.c, &req) return err } -func (v VirtualMachine) Destroy() (*Task, error) { +func (v VirtualMachine) Destroy(ctx context.Context) (*Task, error) { req := types.Destroy_Task{ This: v.Reference(), } - res, err := methods.Destroy_Task(context.TODO(), v.c, &req) + res, err := methods.Destroy_Task(ctx, v.c, &req) if err != nil { return nil, err } @@ -125,7 +120,7 @@ func (v VirtualMachine) Destroy() (*Task, error) { return NewTask(v.c, res.Returnval), nil } -func (v VirtualMachine) Clone(folder *Folder, name string, config types.VirtualMachineCloneSpec) (*Task, error) { +func (v VirtualMachine) Clone(ctx context.Context, folder *Folder, name string, config types.VirtualMachineCloneSpec) (*Task, error) { req := types.CloneVM_Task{ This: v.Reference(), Folder: folder.Reference(), @@ -133,7 +128,7 @@ func (v VirtualMachine) Clone(folder *Folder, name string, config types.VirtualM Spec: config, } - res, err := methods.CloneVM_Task(context.TODO(), v.c, &req) + res, err := methods.CloneVM_Task(ctx, v.c, &req) if err != nil { return nil, err } @@ -141,13 +136,13 @@ func (v VirtualMachine) Clone(folder *Folder, name string, config types.VirtualM return NewTask(v.c, res.Returnval), nil } -func (v VirtualMachine) Reconfigure(config types.VirtualMachineConfigSpec) (*Task, error) { +func (v VirtualMachine) Reconfigure(ctx context.Context, config types.VirtualMachineConfigSpec) (*Task, error) { req := types.ReconfigVM_Task{ This: v.Reference(), Spec: config, } - res, err := methods.ReconfigVM_Task(context.TODO(), v.c, &req) + res, err := methods.ReconfigVM_Task(ctx, v.c, &req) if err != nil { return nil, err } @@ -155,10 +150,11 @@ func (v VirtualMachine) Reconfigure(config types.VirtualMachineConfigSpec) (*Tas return NewTask(v.c, res.Returnval), nil } -func (v VirtualMachine) WaitForIP() (string, error) { +func (v VirtualMachine) WaitForIP(ctx context.Context) (string, error) { var ip string - err := v.c.WaitForProperties(v.Reference(), []string{"guest.ipAddress"}, func(pc []types.PropertyChange) bool { + p := property.DefaultCollector(v.c) + err := property.Wait(ctx, p, v.Reference(), []string{"guest.ipAddress"}, func(pc []types.PropertyChange) bool { for _, c := range pc { if c.Name != "guest.ipAddress" { continue @@ -185,10 +181,10 @@ func (v VirtualMachine) WaitForIP() (string, error) { } // Device returns the VirtualMachine's config.hardware.device property. -func (v VirtualMachine) Device() (VirtualDeviceList, error) { +func (v VirtualMachine) Device(ctx context.Context) (VirtualDeviceList, error) { var o mo.VirtualMachine - err := v.c.Properties(v.Reference(), []string{"config.hardware.device"}, &o) + err := v.Properties(ctx, v.Reference(), []string{"config.hardware.device"}, &o) if err != nil { return nil, err } @@ -196,7 +192,7 @@ func (v VirtualMachine) Device() (VirtualDeviceList, error) { return VirtualDeviceList(o.Config.Hardware.Device), nil } -func (v VirtualMachine) configureDevice(op types.VirtualDeviceConfigSpecOperation, fop types.VirtualDeviceConfigSpecFileOperation, devices ...types.BaseVirtualDevice) error { +func (v VirtualMachine) configureDevice(ctx context.Context, op types.VirtualDeviceConfigSpecOperation, fop types.VirtualDeviceConfigSpecFileOperation, devices ...types.BaseVirtualDevice) error { spec := types.VirtualMachineConfigSpec{} for _, device := range devices { @@ -224,34 +220,34 @@ func (v VirtualMachine) configureDevice(op types.VirtualDeviceConfigSpecOperatio spec.DeviceChange = append(spec.DeviceChange, config) } - task, err := v.Reconfigure(spec) + task, err := v.Reconfigure(ctx, spec) if err != nil { return err } - return task.Wait() + return task.Wait(ctx) } // AddDevice adds the given devices to the VirtualMachine -func (v VirtualMachine) AddDevice(device ...types.BaseVirtualDevice) error { - return v.configureDevice(types.VirtualDeviceConfigSpecOperationAdd, types.VirtualDeviceConfigSpecFileOperationCreate, device...) +func (v VirtualMachine) AddDevice(ctx context.Context, device ...types.BaseVirtualDevice) error { + return v.configureDevice(ctx, types.VirtualDeviceConfigSpecOperationAdd, types.VirtualDeviceConfigSpecFileOperationCreate, device...) } // EditDevice edits the given (existing) devices on the VirtualMachine -func (v VirtualMachine) EditDevice(device ...types.BaseVirtualDevice) error { - return v.configureDevice(types.VirtualDeviceConfigSpecOperationEdit, types.VirtualDeviceConfigSpecFileOperationReplace, device...) +func (v VirtualMachine) EditDevice(ctx context.Context, device ...types.BaseVirtualDevice) error { + return v.configureDevice(ctx, types.VirtualDeviceConfigSpecOperationEdit, types.VirtualDeviceConfigSpecFileOperationReplace, device...) } // RemoveDevice removes the given devices on the VirtualMachine -func (v VirtualMachine) RemoveDevice(device ...types.BaseVirtualDevice) error { - return v.configureDevice(types.VirtualDeviceConfigSpecOperationRemove, types.VirtualDeviceConfigSpecFileOperationDestroy, device...) +func (v VirtualMachine) RemoveDevice(ctx context.Context, device ...types.BaseVirtualDevice) error { + return v.configureDevice(ctx, types.VirtualDeviceConfigSpecOperationRemove, types.VirtualDeviceConfigSpecFileOperationDestroy, device...) } // BootOptions returns the VirtualMachine's config.bootOptions property. -func (v VirtualMachine) BootOptions() (*types.VirtualMachineBootOptions, error) { +func (v VirtualMachine) BootOptions(ctx context.Context) (*types.VirtualMachineBootOptions, error) { var o mo.VirtualMachine - err := v.c.Properties(v.Reference(), []string{"config.bootOptions"}, &o) + err := v.Properties(ctx, v.Reference(), []string{"config.bootOptions"}, &o) if err != nil { return nil, err } @@ -260,28 +256,28 @@ func (v VirtualMachine) BootOptions() (*types.VirtualMachineBootOptions, error) } // SetBootOptions reconfigures the VirtualMachine with the given options. -func (v VirtualMachine) SetBootOptions(options *types.VirtualMachineBootOptions) error { +func (v VirtualMachine) SetBootOptions(ctx context.Context, options *types.VirtualMachineBootOptions) error { spec := types.VirtualMachineConfigSpec{} spec.BootOptions = options - task, err := v.Reconfigure(spec) + task, err := v.Reconfigure(ctx, spec) if err != nil { return err } - return task.Wait() + return task.Wait(ctx) } // Answer answers a pending question. -func (v VirtualMachine) Answer(id, answer string) error { +func (v VirtualMachine) Answer(ctx context.Context, id, answer string) error { req := types.AnswerVM{ This: v.Reference(), QuestionId: id, AnswerChoice: answer, } - _, err := methods.AnswerVM(context.TODO(), v.c, &req) + _, err := methods.AnswerVM(ctx, v.c, &req) if err != nil { return err } @@ -289,12 +285,12 @@ func (v VirtualMachine) Answer(id, answer string) error { return nil } -func (v VirtualMachine) MarkAsTemplate() error { +func (v VirtualMachine) MarkAsTemplate(ctx context.Context) error { req := types.MarkAsTemplate{ This: v.Reference(), } - _, err := methods.MarkAsTemplate(context.TODO(), v.c, &req) + _, err := methods.MarkAsTemplate(ctx, v.c, &req) if err != nil { return err } @@ -302,7 +298,7 @@ func (v VirtualMachine) MarkAsTemplate() error { return nil } -func (v VirtualMachine) MarkAsVirtualMachine(pool ResourcePool, host *HostSystem) error { +func (v VirtualMachine) MarkAsVirtualMachine(ctx context.Context, pool ResourcePool, host *HostSystem) error { req := types.MarkAsVirtualMachine{ This: v.Reference(), Pool: pool.Reference(), @@ -313,7 +309,7 @@ func (v VirtualMachine) MarkAsVirtualMachine(pool ResourcePool, host *HostSystem req.Host = &ref } - _, err := methods.MarkAsVirtualMachine(context.TODO(), v.c, &req) + _, err := methods.MarkAsVirtualMachine(ctx, v.c, &req) if err != nil { return err } diff --git a/virtual_machine_test.go b/object/virtual_machine_test.go similarity index 97% rename from virtual_machine_test.go rename to object/virtual_machine_test.go index 87b3ece97..ba1949028 100644 --- a/virtual_machine_test.go +++ b/object/virtual_machine_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object // VirtualMachine should implement the Reference interface. var _ Reference = VirtualMachine{} diff --git a/vmware_distributed_virtual_switch.go b/object/vmware_distributed_virtual_switch.go similarity index 97% rename from vmware_distributed_virtual_switch.go rename to object/vmware_distributed_virtual_switch.go index d44bc19c3..180a58385 100644 --- a/vmware_distributed_virtual_switch.go +++ b/object/vmware_distributed_virtual_switch.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package object type VmwareDistributedVirtualSwitch struct { DistributedVirtualSwitch diff --git a/property/collector.go b/property/collector.go new file mode 100644 index 000000000..f174fe588 --- /dev/null +++ b/property/collector.go @@ -0,0 +1,174 @@ +/* +Copyright (c) 2014 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 property + +import ( + "errors" + + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/vim25/soap" + "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" +) + +// Collector models the PropertyCollector managed object. +// +// For more information, see: +// http://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vmodl.query.PropertyCollector.html +// +type Collector struct { + roundTripper soap.RoundTripper + reference types.ManagedObjectReference +} + +// DefaultCollector returns the session's default property collector. +func DefaultCollector(c *vim25.Client) *Collector { + p := Collector{ + roundTripper: c, + reference: c.ServiceContent.PropertyCollector, + } + + return &p +} + +func (p Collector) Reference() types.ManagedObjectReference { + return p.reference +} + +// Create creates a new session-specific Collector that can be used to +// retrieve property updates independent of any other Collector. +func (p *Collector) Create(ctx context.Context) (*Collector, error) { + req := types.CreatePropertyCollector{ + This: p.Reference(), + } + + res, err := methods.CreatePropertyCollector(ctx, p.roundTripper, &req) + if err != nil { + return nil, err + } + + newp := Collector{ + roundTripper: p.roundTripper, + reference: res.Returnval, + } + + return &newp, nil +} + +// Destroy destroys this Collector. +func (p *Collector) Destroy(ctx context.Context) error { + req := types.DestroyPropertyCollector{ + This: p.Reference(), + } + + _, err := methods.DestroyPropertyCollector(ctx, p.roundTripper, &req) + if err != nil { + return err + } + + p.reference = types.ManagedObjectReference{} + return nil +} + +func (p *Collector) CreateFilter(ctx context.Context, req types.CreateFilter) error { + req.This = p.Reference() + + _, err := methods.CreateFilter(ctx, p.roundTripper, &req) + if err != nil { + return err + } + + return nil +} + +func (p *Collector) WaitForUpdates(ctx context.Context, v string) (*types.UpdateSet, error) { + req := types.WaitForUpdatesEx{ + This: p.Reference(), + Version: v, + } + + res, err := methods.WaitForUpdatesEx(ctx, p.roundTripper, &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} + +func (p *Collector) RetrieveProperties(ctx context.Context, req types.RetrieveProperties) (*types.RetrievePropertiesResponse, error) { + req.This = p.Reference() + return methods.RetrieveProperties(ctx, p.roundTripper, &req) +} + +// Retrieve loads properties for a slice of managed objects. The dst argument +// must be a pointer to a []interface{}, which is populated with the instances +// of the specified managed objects, with the relevant properties filled in. If +// the properties slice is nil, all properties are loaded. +func (p *Collector) Retrieve(ctx context.Context, objs []types.ManagedObjectReference, ps []string, dst interface{}) error { + var propSpec *types.PropertySpec + var objectSet []types.ObjectSpec + + for _, obj := range objs { + // Ensure that all object reference types are the same + if propSpec == nil { + propSpec = &types.PropertySpec{ + Type: obj.Type, + } + + if ps == nil { + propSpec.All = true + } else { + propSpec.PathSet = ps + } + } else { + if obj.Type != propSpec.Type { + return errors.New("object references must have the same type") + } + } + + objectSpec := types.ObjectSpec{ + Obj: obj, + Skip: false, + } + + objectSet = append(objectSet, objectSpec) + } + + req := types.RetrieveProperties{ + SpecSet: []types.PropertyFilterSpec{ + { + ObjectSet: objectSet, + PropSet: []types.PropertySpec{*propSpec}, + }, + }, + } + + res, err := p.RetrieveProperties(ctx, req) + if err != nil { + return err + } + + return mo.LoadRetrievePropertiesResponse(res, dst) +} + +// RetrieveOne calls Retrieve with a single managed object reference. +func (p *Collector) RetrieveOne(ctx context.Context, obj types.ManagedObjectReference, ps []string, dst interface{}) error { + var objs = []types.ManagedObjectReference{obj} + return p.Retrieve(ctx, objs, ps, dst) +} diff --git a/property/wait.go b/property/wait.go new file mode 100644 index 000000000..7b99b0eb7 --- /dev/null +++ b/property/wait.go @@ -0,0 +1,86 @@ +/* +Copyright (c) 2014 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 property + +import ( + "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" +) + +// Wait waits for any of the specified properties of the specified managed +// object to change. It calls the specified function for every update it +// receives. If this function returns false, it continues waiting for +// subsequent updates. If this function returns true, it stops waiting and +// returns. +// +// To only receive updates for the specified managed object, the function +// creates a new property collector and calls CreateFilter. A new property +// collector is required because filters can only be added, not removed. +// +// The newly created collector is destroyed before this function returns (both +// in case of success or error). +// +func Wait(ctx context.Context, c *Collector, obj types.ManagedObjectReference, ps []string, f func([]types.PropertyChange) bool) error { + p, err := c.Create(ctx) + if err != nil { + return err + } + + // Attempt to destroy the collector using the background context, as the + // specified context may have timed out or have been cancelled. + defer p.Destroy(context.Background()) + + req := types.CreateFilter{ + Spec: types.PropertyFilterSpec{ + ObjectSet: []types.ObjectSpec{ + { + Obj: obj, + }, + }, + PropSet: []types.PropertySpec{ + { + PathSet: ps, + Type: obj.Type, + }, + }, + }, + } + + err = p.CreateFilter(ctx, req) + if err != nil { + return err + } + + for version := ""; ; { + res, err := p.WaitForUpdates(ctx, version) + if err != nil { + return err + } + + version = res.Version + + for _, fs := range res.FilterSet { + for _, os := range fs.ObjectSet { + if os.Obj == obj { + if f(os.ChangeSet) { + return nil + } + } + } + } + } +} diff --git a/property_collector.go b/property_collector.go deleted file mode 100644 index be00d7249..000000000 --- a/property_collector.go +++ /dev/null @@ -1,67 +0,0 @@ -/* -Copyright (c) 2014 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 govmomi - -import ( - "github.com/vmware/govmomi/vim25/methods" - "github.com/vmware/govmomi/vim25/types" - "golang.org/x/net/context" -) - -type PropertyCollector struct { - c *Client - r types.ManagedObjectReference -} - -func (p *PropertyCollector) Destroy() error { - req := types.DestroyPropertyCollector{ - This: p.r, - } - - _, err := methods.DestroyPropertyCollector(context.TODO(), p.c, &req) - if err != nil { - return err - } - - p.r = types.ManagedObjectReference{} - return nil -} - -func (p *PropertyCollector) CreateFilter(req types.CreateFilter) error { - req.This = p.r - - _, err := methods.CreateFilter(context.TODO(), p.c, &req) - if err != nil { - return err - } - - return nil -} - -func (p *PropertyCollector) WaitForUpdates(v string) (*types.UpdateSet, error) { - req := types.WaitForUpdatesEx{ - This: p.r, - Version: v, - } - - res, err := methods.WaitForUpdatesEx(context.TODO(), p.c, &req) - if err != nil { - return nil, err - } - - return res.Returnval, nil -} diff --git a/session/keep_alive.go b/session/keep_alive.go new file mode 100644 index 000000000..82b488172 --- /dev/null +++ b/session/keep_alive.go @@ -0,0 +1,117 @@ +/* +Copyright (c) 2014 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 session + +import ( + "sync" + "time" + + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/soap" + "golang.org/x/net/context" +) + +type keepAlive struct { + sync.Mutex + + roundTripper soap.RoundTripper + idleTime time.Duration + notifyRequest chan struct{} + notifyStop chan struct{} + notifyWaitGroup sync.WaitGroup + + // keepAlive executes a request in the background with the purpose of + // keeping the session active. The response for this request is discarded. + keepAlive func(soap.RoundTripper) +} + +func defaultKeepAlive(roundTripper soap.RoundTripper) { + methods.GetServiceContent(context.Background(), roundTripper) +} + +// KeepAlive wraps the specified soap.RoundTripper and executes a meaningless +// API request in the background after the RoundTripper has been idle for the +// specified amount of idle time. The keep alive process only starts once a +// user logs in and runs until the user logs out again. +func KeepAlive(roundTripper soap.RoundTripper, idleTime time.Duration) soap.RoundTripper { + k := &keepAlive{ + roundTripper: roundTripper, + idleTime: idleTime, + notifyRequest: make(chan struct{}), + } + + k.keepAlive = defaultKeepAlive + + return k +} + +func (k *keepAlive) start() { + k.Lock() + defer k.Unlock() + + if k.notifyStop != nil { + return + } + + // This channel must be closed to terminate idle timer. + k.notifyStop = make(chan struct{}) + k.notifyWaitGroup.Add(1) + + go func() { + defer k.notifyWaitGroup.Done() + + for t := time.NewTimer(k.idleTime); ; { + select { + case <-k.notifyStop: + return + case <-k.notifyRequest: + t.Reset(k.idleTime) + case <-t.C: + k.keepAlive(k.roundTripper) + t = time.NewTimer(k.idleTime) + } + } + }() +} + +func (k *keepAlive) stop() { + k.Lock() + defer k.Unlock() + + if k.notifyStop != nil { + close(k.notifyStop) + k.notifyWaitGroup.Wait() + k.notifyStop = nil + } +} + +func (k *keepAlive) RoundTrip(ctx context.Context, req, res soap.HasFault) error { + err := k.roundTripper.RoundTrip(ctx, req, res) + if err != nil { + return err + } + + // Start ticker on login, stop ticker on logout. + switch req.(type) { + case *methods.LoginBody: + k.start() + case *methods.LogoutBody: + k.stop() + } + + return nil +} diff --git a/session/keep_alive_test.go b/session/keep_alive_test.go new file mode 100644 index 000000000..917f51c36 --- /dev/null +++ b/session/keep_alive_test.go @@ -0,0 +1,162 @@ +/* +Copyright (c) 2014 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 session + +import ( + "fmt" + "net/url" + "os" + "runtime" + "testing" + "time" + + "github.com/vmware/govmomi/test" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/soap" + "golang.org/x/net/context" +) + +type testKeepAlive int + +func (t *testKeepAlive) Func(soap.RoundTripper) { + *t++ +} + +func newManager(t *testing.T) (*Manager, *url.URL) { + u := test.URL() + if u == nil { + t.SkipNow() + } + + soapClient := soap.NewClient(u, true) + vimClient, err := vim25.NewClient(context.Background(), soapClient) + if err != nil { + t.Fatal(err) + } + + return NewManager(vimClient), u +} + +func TestKeepAlive(t *testing.T) { + var i testKeepAlive + var j int + + m, u := newManager(t) + k := KeepAlive(m.client.RoundTripper, time.Millisecond) + k.(*keepAlive).keepAlive = i.Func + m.client.RoundTripper = k + + // Expect keep alive to not have triggered yet + if i != 0 { + t.Errorf("Expected i == 0, got i: %d", i) + } + + // Logging in starts keep alive + err := m.Login(context.Background(), u.User) + if err != nil { + t.Error(err) + } + + time.Sleep(2 * time.Millisecond) + + // Expect keep alive to triggered at least once + if i == 0 { + t.Errorf("Expected i != 0, got i: %d", i) + } + + j = int(i) + time.Sleep(2 * time.Millisecond) + + // Expect keep alive to triggered at least once more + if int(i) <= j { + t.Errorf("Expected i > j, got i: %d, j: %d", i, j) + } + + // Logging out stops keep alive + err = m.Logout(context.Background()) + if err != nil { + t.Error(err) + } + + j = int(i) + time.Sleep(2 * time.Millisecond) + + // Expect keep alive to have stopped + if int(i) != j { + t.Errorf("Expected i == j, got i: %d, j: %d", i, j) + } +} + +func testSessionOK(t *testing.T, m *Manager, ok bool) { + s, err := m.UserSession(context.Background()) + if err != nil { + t.Fatal(err) + } + + _, file, line, _ := runtime.Caller(1) + prefix := fmt.Sprintf("%s:%d", file, line) + + if ok && s == nil { + t.Fatalf("%s: Expected session to be OK, but is invalid", prefix) + } + + if !ok && s != nil { + t.Fatalf("%s: Expected session to be invalid, but is OK", prefix) + } +} + +// Run with: +// +// env GOVMOMI_KEEPALIVE_TEST=1 go test -timeout=60m -run TestRealKeepAlive +// +func TestRealKeepAlive(t *testing.T) { + if os.Getenv("GOVMOMI_KEEPALIVE_TEST") != "1" { + t.SkipNow() + } + + m1, u1 := newManager(t) + m2, u2 := newManager(t) + + // Enable keepalive on m2 + k := KeepAlive(m2.client.RoundTripper, 10*time.Minute) + m2.client.RoundTripper = k + + // Expect both sessions to be invalid + testSessionOK(t, m1, false) + testSessionOK(t, m2, false) + + // Logging in starts keep alive + if err := m1.Login(context.Background(), u1.User); err != nil { + t.Error(err) + } + if err := m2.Login(context.Background(), u2.User); err != nil { + t.Error(err) + } + + // Expect both sessions to be valid + testSessionOK(t, m1, true) + testSessionOK(t, m2, true) + + // Wait for m1 to time out + delay := 31 * time.Minute + fmt.Printf("%s: Waiting %d minutes for session to time out...\n", time.Now(), int(delay.Minutes())) + time.Sleep(delay) + + // Expect m1's session to be invalid, m2's session to be valid + testSessionOK(t, m1, false) + testSessionOK(t, m2, true) +} diff --git a/session/manager.go b/session/manager.go new file mode 100644 index 000000000..d4e3943e1 --- /dev/null +++ b/session/manager.go @@ -0,0 +1,121 @@ +/* +Copyright (c) 2014 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 session + +import ( + "net/url" + + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" +) + +type Manager struct { + client *vim25.Client + userSession *types.UserSession +} + +func NewManager(client *vim25.Client) *Manager { + m := Manager{ + client: client, + } + + return &m +} + +func (sm Manager) Reference() types.ManagedObjectReference { + return *sm.client.ServiceContent.SessionManager +} + +func (sm *Manager) Login(ctx context.Context, u *url.Userinfo) error { + req := types.Login{ + This: sm.Reference(), + } + + if u != nil { + req.UserName = u.Username() + if pw, ok := u.Password(); ok { + req.Password = pw + } + } + + login, err := methods.Login(ctx, sm.client, &req) + if err != nil { + return err + } + + sm.userSession = &login.Returnval + return nil +} + +func (sm *Manager) Logout(ctx context.Context) error { + req := types.Logout{ + This: sm.Reference(), + } + + _, err := methods.Logout(ctx, sm.client, &req) + if err != nil { + return err + } + + sm.userSession = nil + return nil +} + +// UserSession retrieves and returns the SessionManager's CurrentSession field. +// Nil is returned if the session is not authenticated. +func (sm *Manager) UserSession(ctx context.Context) (*types.UserSession, error) { + var mgr mo.SessionManager + + err := mo.RetrieveProperties(ctx, sm.client, sm.client.ServiceContent.PropertyCollector, sm.Reference(), &mgr) + if err != nil { + // It's OK if we can't retrieve properties because we're not authenticated + if f, ok := err.(types.HasFault); ok { + switch f.Fault().(type) { + case *types.NotAuthenticated: + return nil, nil + } + } + + return nil, err + } + + return mgr.CurrentSession, nil +} + +// SessionIsActive checks whether the session that was created at login is +// still valid. This function only works against vCenter. +func (sm *Manager) SessionIsActive(ctx context.Context) (bool, error) { + if sm.userSession == nil { + return false, nil + } + + req := types.SessionIsActive{ + This: sm.Reference(), + SessionID: sm.userSession.Key, + UserName: sm.userSession.UserName, + } + + active, err := methods.SessionIsActive(ctx, sm.client, &req) + if err != nil { + return false, err + } + + return active.Returnval, err +} diff --git a/session_manager_test.go b/session/manager_test.go similarity index 61% rename from session_manager_test.go rename to session/manager_test.go index 5a06c8e66..98b9230a9 100644 --- a/session_manager_test.go +++ b/session/manager_test.go @@ -14,29 +14,26 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package session import ( "net/url" "testing" "github.com/vmware/govmomi/test" + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/soap" + "golang.org/x/net/context" ) -func sessionClient(u url.URL, t *testing.T) SessionManager { +func sessionClient(u *url.URL, t *testing.T) *Manager { soapClient := soap.NewClient(u, true) - serviceContent, err := getServiceContent(soapClient) + vimClient, err := vim25.NewClient(context.Background(), soapClient) if err != nil { - t.Error(err) + t.Fatal(err) } - c := Client{ - Client: soapClient, - ServiceContent: serviceContent, - } - - return NewSessionManager(&c, *c.ServiceContent.SessionManager) + return NewManager(vimClient) } func TestLogin(t *testing.T) { @@ -44,64 +41,66 @@ func TestLogin(t *testing.T) { if u == nil { t.SkipNow() } - session := sessionClient(*u, t) - err := session.Login(*u.User) + + session := sessionClient(u, t) + err := session.Login(context.Background(), u.User) if err != nil { t.Errorf("Expected no error, got %v", err) } - } func TestLogout(t *testing.T) { u := test.URL() - if u == nil { t.SkipNow() } - session := sessionClient(*u, t) - err := session.Login(*u.User) + session := sessionClient(u, t) + err := session.Login(context.Background(), u.User) if err != nil { t.Error("Login Error: ", err) } - err = session.Logout() + err = session.Logout(context.Background()) if err != nil { t.Errorf("Expected nil, got %v", err) } - err = session.Logout() + err = session.Logout(context.Background()) if err == nil { t.Errorf("Expected NotAuthenticated, got nil") } - } func TestSessionIsActive(t *testing.T) { u := test.URL() - if u == nil { t.SkipNow() } - session := sessionClient(*u, t) - err := session.Login(*u.User) + session := sessionClient(u, t) + + // Skip test against ESXi -- SessionIsActive is not implemented + if session.client.ServiceContent.About.ApiType != "VirtualCenter" { + t.Skipf("Talking to %s instead of %s", session.client.ServiceContent.About.ApiType, "VirtualCenter") + } + + err := session.Login(context.Background(), u.User) if err != nil { t.Error("Login Error: ", err) } - active, err := session.SessionIsActive() + active, err := session.SessionIsActive(context.Background()) if err != nil || !active { t.Errorf("Expected %t, got %t", true, active) t.Errorf("Expected nil, got %v", err) } - session.Logout() + session.Logout(context.Background()) - active, err = session.SessionIsActive() + active, err = session.SessionIsActive(context.Background()) if err == nil || active { t.Errorf("Expected %t, got %t", false, active) t.Errorf("Expected NotAuthenticated, got %v", err) } - } diff --git a/session_manager.go b/session_manager.go deleted file mode 100644 index ea8246468..000000000 --- a/session_manager.go +++ /dev/null @@ -1,106 +0,0 @@ -/* -Copyright (c) 2014 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 govmomi - -import ( - "net/http" - "net/url" - - "github.com/vmware/govmomi/vim25/methods" - "github.com/vmware/govmomi/vim25/mo" - "github.com/vmware/govmomi/vim25/types" - "golang.org/x/net/context" -) - -type SessionManager struct { - types.ManagedObjectReference - c *Client - userSession *types.UserSession -} - -func NewSessionManager(c *Client, ref types.ManagedObjectReference) SessionManager { - return SessionManager{ - ManagedObjectReference: ref, - c: c, - } -} - -func (sm SessionManager) Reference() types.ManagedObjectReference { - return sm.ManagedObjectReference -} - -func (sm *SessionManager) Login(u url.Userinfo) error { - req := types.Login{ - This: sm.Reference(), - } - - req.UserName = u.Username() - if pw, ok := u.Password(); ok { - req.Password = pw - } - - login, err := methods.Login(context.TODO(), sm.c, &req) - sm.userSession = &login.Returnval - return err -} - -func (sm *SessionManager) Logout() error { - req := types.Logout{ - This: sm.Reference(), - } - - _, err := methods.Logout(context.TODO(), sm.c, &req) - // we've logged out - lets close any idle connections - t := sm.c.Client.Transport.(*http.Transport) - t.CloseIdleConnections() - - return err -} - -func (sm *SessionManager) UserSession() (*types.UserSession, error) { - - if sm.userSession == nil { - var mgr mo.SessionManager - err := mo.RetrieveProperties(context.TODO(), sm.c, sm.c.ServiceContent.PropertyCollector, sm.Reference(), &mgr) - if err != nil { - return nil, err - } - sm.userSession = mgr.CurrentSession - } - - return sm.userSession, nil -} - -func (sm *SessionManager) SessionIsActive() (bool, error) { - user, err := sm.UserSession() - if err != nil { - return false, err - } - - req := types.SessionIsActive{ - This: sm.Reference(), - SessionID: user.Key, - UserName: user.UserName, - } - - active, err := methods.SessionIsActive(context.TODO(), sm.c, &req) - if err != nil { - return false, err - } - - return active.Returnval, err -} diff --git a/distributed_virtual_switch.go b/task/error.go similarity index 69% rename from distributed_virtual_switch.go rename to task/error.go index 4cd608d53..81149a80d 100644 --- a/distributed_virtual_switch.go +++ b/task/error.go @@ -14,14 +14,19 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package task import "github.com/vmware/govmomi/vim25/types" -type DistributedVirtualSwitch struct { - types.ManagedObjectReference +type Error struct { + *types.LocalizedMethodFault } -func (s DistributedVirtualSwitch) Reference() types.ManagedObjectReference { - return s.ManagedObjectReference +// Error returns the task's localized fault message. +func (e Error) Error() string { + return e.LocalizedMethodFault.LocalizedMessage +} + +func (e Error) Fault() types.BaseMethodFault { + return e.LocalizedMethodFault.Fault } diff --git a/task.go b/task/wait.go similarity index 62% rename from task.go rename to task/wait.go index b7ed6ed88..b247fa2ea 100644 --- a/task.go +++ b/task/wait.go @@ -14,40 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi +package task import ( + "github.com/vmware/govmomi/property" "github.com/vmware/govmomi/vim25/progress" "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" ) -// Task adds functionality for the Task managed object. -type Task struct { - c *Client - ref types.ManagedObjectReference -} - -func NewTask(c *Client, ref types.ManagedObjectReference) *Task { - t := Task{ - c: c, - ref: ref, - } - - return &t -} - -type taskError struct { - *types.LocalizedMethodFault -} - -func (e taskError) Error() string { - return e.LocalizedMethodFault.LocalizedMessage -} - -func (e taskError) Fault() types.BaseMethodFault { - return e.LocalizedMethodFault.Fault -} - type taskProgress struct { info *types.TaskInfo } @@ -62,7 +37,7 @@ func (t taskProgress) Detail() string { func (t taskProgress) Error() error { if t.info.Error != nil { - return taskError{t.info.Error} + return Error{t.info.Error} } return nil @@ -118,12 +93,22 @@ func (t *taskCallback) fn(pc []types.PropertyChange) bool { } } -func (t *Task) Wait() error { - _, err := t.WaitForResult(nil) - return err -} - -func (t *Task) WaitForResult(s progress.Sinker) (*types.TaskInfo, error) { +// Wait waits for a task to finish with either success or failure. It does so +// by waiting for the "info" property of task managed object to change. The +// function returns when it finds the task in the "success" or "error" state. +// In the former case, the return value is nil. In the latter case the return +// value is an instance of this package's Error struct. +// +// Any error returned while waiting for property changes causes the function to +// return immediately and propagate the error. +// +// If the progress.Sinker argument is specified, any progress updates for the +// task are sent here. The completion percentage is passed through directly. +// The detail for the progress update is set to an empty string. If the task +// finishes in the error state, the error instance is passed through as well. +// Note that this error is the same error that is returned by this function. +// +func Wait(ctx context.Context, ref types.ManagedObjectReference, pc *property.Collector, s progress.Sinker) (*types.TaskInfo, error) { cb := &taskCallback{} // Include progress sink if specified @@ -132,7 +117,7 @@ func (t *Task) WaitForResult(s progress.Sinker) (*types.TaskInfo, error) { defer close(cb.ch) } - err := t.c.WaitForProperties(t.ref, []string{"info"}, cb.fn) + err := property.Wait(ctx, pc, ref, []string{"info"}, cb.fn) if err != nil { return nil, err } diff --git a/test/client/client.go b/test/client/client.go new file mode 100644 index 000000000..a2a336596 --- /dev/null +++ b/test/client/client.go @@ -0,0 +1,48 @@ +/* +Copyright (c) 2015 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 client + +import ( + "testing" + + "github.com/vmware/govmomi/session" + "github.com/vmware/govmomi/test" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/soap" + "golang.org/x/net/context" +) + +func NewAuthenticatedClient(t *testing.T) *vim25.Client { + u := test.URL() + if u == nil { + t.SkipNow() + } + + soapClient := soap.NewClient(u, true) + vimClient, err := vim25.NewClient(context.Background(), soapClient) + if err != nil { + t.Fatal(err) + } + + m := session.NewManager(vimClient) + err = m.Login(context.Background(), u.User) + if err != nil { + t.Fatal(err) + } + + return vimClient +} diff --git a/vim25/client.go b/vim25/client.go new file mode 100644 index 000000000..8345296ea --- /dev/null +++ b/vim25/client.go @@ -0,0 +1,114 @@ +/* +Copyright (c) 2015 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 vim25 + +import ( + "encoding/json" + + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/soap" + "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" +) + +// Client is a tiny wrapper around the vim25/soap Client that stores session +// specific state (i.e. state that only needs to be retrieved once after the +// client has been created). This means the client can be reused after +// serialization without performing additional requests for initialization. +type Client struct { + *soap.Client + + ServiceContent types.ServiceContent + + // RoundTripper is a separate field such that the client's implementation of + // the RoundTripper interface can be wrapped by separate implementations for + // extra functionality (for example, reauthentication on session timeout). + RoundTripper soap.RoundTripper +} + +// NewClient creates and returns a new client wirh the ServiceContent field +// filled in. +func NewClient(ctx context.Context, soapClient *soap.Client) (*Client, error) { + serviceContent, err := methods.GetServiceContent(ctx, soapClient) + if err != nil { + return nil, err + } + + c := Client{ + Client: soapClient, + ServiceContent: serviceContent, + RoundTripper: soapClient, + } + + return &c, nil +} + +// RoundTrip dispatches to the RoundTripper field. +func (c *Client) RoundTrip(ctx context.Context, req, res soap.HasFault) error { + return c.RoundTripper.RoundTrip(ctx, req, res) +} + +type marshaledClient struct { + SoapClient *soap.Client + ServiceContent types.ServiceContent +} + +func (c *Client) MarshalJSON() ([]byte, error) { + m := marshaledClient{ + SoapClient: c.Client, + ServiceContent: c.ServiceContent, + } + + return json.Marshal(m) +} + +func (c *Client) UnmarshalJSON(b []byte) error { + var m marshaledClient + + err := json.Unmarshal(b, &m) + if err != nil { + return err + } + + *c = Client{ + Client: m.SoapClient, + ServiceContent: m.ServiceContent, + RoundTripper: m.SoapClient, + } + + return nil +} + +// Valid returns whether or not the client is valid and ready for use. +// This should be called after unmarshalling the client. +func (c *Client) Valid() bool { + if c == nil { + return false + } + + if c.Client == nil { + return false + } + + // Use arbitrary pointer field in the service content. + // Doesn't matter which one, as long as it is populated by default. + if c.ServiceContent.SessionManager == nil { + return false + } + + return true +} diff --git a/vim25/client_test.go b/vim25/client_test.go new file mode 100644 index 000000000..c843f07a2 --- /dev/null +++ b/vim25/client_test.go @@ -0,0 +1,97 @@ +/* +Copyright (c) 2015 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 vim25 + +import ( + "encoding/json" + "net/url" + "os" + "testing" + + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/vim25/soap" + "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" +) + +// Duplicated to prevent cyclic dependency... +func testURL(t *testing.T) *url.URL { + s := os.Getenv("GOVMOMI_TEST_URL") + if s == "" { + t.SkipNow() + } + u, err := url.Parse(s) + if err != nil { + panic(err) + } + return u +} + +func sessionLogin(t *testing.T, c *Client) { + req := types.Login{ + This: *c.ServiceContent.SessionManager, + } + + u := testURL(t).User + req.UserName = u.Username() + if pw, ok := u.Password(); ok { + req.Password = pw + } + + _, err := methods.Login(context.Background(), c, &req) + if err != nil { + t.Fatal(err) + } +} + +func sessionCheck(t *testing.T, c *Client) { + var mgr mo.SessionManager + + err := mo.RetrieveProperties(context.Background(), c, c.ServiceContent.PropertyCollector, *c.ServiceContent.SessionManager, &mgr) + if err != nil { + t.Fatal(err) + } +} + +func TestClientSerialization(t *testing.T) { + var c1, c2 *Client + + soapClient := soap.NewClient(testURL(t), true) + c1, err := NewClient(context.Background(), soapClient) + if err != nil { + t.Fatal(err) + } + + // Login + sessionLogin(t, c1) + sessionCheck(t, c1) + + // Serialize/deserialize + b, err := json.Marshal(c1) + if err != nil { + t.Fatal(err) + } + c2 = &Client{} + err = json.Unmarshal(b, c2) + if err != nil { + t.Fatal(err) + } + + // Check the session is still valid + sessionCheck(t, c2) +} diff --git a/vim25/doc.go b/vim25/doc.go new file mode 100644 index 000000000..acb2c9f64 --- /dev/null +++ b/vim25/doc.go @@ -0,0 +1,29 @@ +/* +Copyright (c) 2015 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 vim25 provides a minimal client implementation to use with other +packages in the vim25 tree. The code in this package intentionally does not +take any dependendies outside the vim25 tree. + +The client implementation in this package embeds the soap.Client structure. +Additionally, it stores the value of the session's ServiceContent object. This +object stores references to a variety of subsystems, such as the root property +collector, the session manager, and the search index. The client is fully +functional after serialization and deserialization, without the need for +additional requests for initialization. +*/ +package vim25 diff --git a/vim25/methods/service_content.go b/vim25/methods/service_content.go new file mode 100644 index 000000000..cfcc48f72 --- /dev/null +++ b/vim25/methods/service_content.go @@ -0,0 +1,41 @@ +/* +Copyright (c) 2014 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 methods + +import ( + "github.com/vmware/govmomi/vim25/soap" + "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" +) + +var serviceInstance = types.ManagedObjectReference{ + Type: "ServiceInstance", + Value: "ServiceInstance", +} + +func GetServiceContent(ctx context.Context, r soap.RoundTripper) (types.ServiceContent, error) { + req := types.RetrieveServiceContent{ + This: serviceInstance, + } + + res, err := RetrieveServiceContent(ctx, r, &req) + if err != nil { + return types.ServiceContent{}, err + } + + return res.Returnval, nil +} diff --git a/vim25/mo/ancestors.go b/vim25/mo/ancestors.go new file mode 100644 index 000000000..4b948e573 --- /dev/null +++ b/vim25/mo/ancestors.go @@ -0,0 +1,92 @@ +/* +Copyright (c) 2014 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 mo + +import ( + "github.com/vmware/govmomi/vim25/soap" + "github.com/vmware/govmomi/vim25/types" + "golang.org/x/net/context" +) + +// Ancestors returns the entire ancestry tree of a specified managed object. +// The return value includes the root node and the specified object itself. +func Ancestors(ctx context.Context, rt soap.RoundTripper, pc, obj types.ManagedObjectReference) ([]ManagedEntity, error) { + ospec := types.ObjectSpec{ + Obj: obj, + SelectSet: []types.BaseSelectionSpec{ + &types.TraversalSpec{ + SelectionSpec: types.SelectionSpec{Name: "traverseParent"}, + Type: "ManagedEntity", + Path: "parent", + Skip: false, + SelectSet: []types.BaseSelectionSpec{ + &types.SelectionSpec{Name: "traverseParent"}, + }, + }, + }, + Skip: false, + } + + pspec := types.PropertySpec{ + Type: "ManagedEntity", + PathSet: []string{"name", "parent"}, + } + + req := types.RetrieveProperties{ + This: pc, + SpecSet: []types.PropertyFilterSpec{ + { + ObjectSet: []types.ObjectSpec{ospec}, + PropSet: []types.PropertySpec{pspec}, + }, + }, + } + + var ifaces []interface{} + + err := RetrievePropertiesForRequest(ctx, rt, req, &ifaces) + if err != nil { + return nil, err + } + + var out []ManagedEntity + + // Build ancestry tree by iteratively finding a new child. + for len(out) < len(ifaces) { + var find types.ManagedObjectReference + + if len(out) > 0 { + find = out[len(out)-1].Self + } + + // Find entity we're looking for given the last entity in the current tree. + for _, iface := range ifaces { + me := iface.(IsManagedEntity).GetManagedEntity() + if me.Parent == nil { + out = append(out, me) + break + } + + if *me.Parent == find { + out = append(out, me) + break + } + } + } + + return out, nil +} diff --git a/vim25/mo/reference.go b/vim25/mo/reference.go new file mode 100644 index 000000000..1afe07f6b --- /dev/null +++ b/vim25/mo/reference.go @@ -0,0 +1,26 @@ +/* +Copyright (c) 2014 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 mo + +import "github.com/vmware/govmomi/vim25/types" + +// Reference is the interface that is implemented by all the managed objects +// defined in this package. It specifies that these managed objects have a +// function that returns the managed object reference to themselves. +type Reference interface { + Reference() types.ManagedObjectReference +} diff --git a/vim25/soap/client.go b/vim25/soap/client.go index ffacad72c..d1753b448 100644 --- a/vim25/soap/client.go +++ b/vim25/soap/client.go @@ -47,13 +47,13 @@ type RoundTripper interface { type Client struct { http.Client - u url.URL + u *url.URL k bool // Named after curl's -k flag d *debugContainer t *http.Transport } -func NewClient(u url.URL, insecure bool) *Client { +func NewClient(u *url.URL, insecure bool) *Client { c := Client{ u: u, k: insecure, @@ -76,13 +76,17 @@ func NewClient(u url.URL, insecure bool) *Client { c.Client.Transport = c.t c.Client.Jar, _ = cookiejar.New(nil) + + // Remove user information from a copy of the URL + c.u = c.URL() c.u.User = nil return &c } -func (c *Client) URL() url.URL { - return c.u +func (c *Client) URL() *url.URL { + urlCopy := *c.u + return &urlCopy } type marshaledClient struct { @@ -93,8 +97,8 @@ type marshaledClient struct { func (c *Client) MarshalJSON() ([]byte, error) { m := marshaledClient{ - Cookies: c.Jar.Cookies(&c.u), - URL: &c.u, + Cookies: c.Jar.Cookies(c.u), + URL: c.u, Insecure: c.k, } @@ -109,7 +113,7 @@ func (c *Client) UnmarshalJSON(b []byte) error { return err } - *c = *NewClient(*m.URL, m.Insecure) + *c = *NewClient(m.URL, m.Insecure) c.Jar.SetCookies(m.URL, m.Cookies) return nil @@ -204,6 +208,10 @@ func (c *Client) RoundTrip(ctx context.Context, reqBody, resBody HasFault) error return err } +func (c *Client) CloseIdleConnections() { + c.t.CloseIdleConnections() +} + // ParseURL wraps url.Parse to rewrite the URL.Host field // In the case of VM guest uploads or NFC lease URLs, a Host // field with a value of "*" is rewritten to the Client's URL.Host. diff --git a/fault.go b/vim25/types/fault.go similarity index 85% rename from fault.go rename to vim25/types/fault.go index 93cec7ab7..72ae944ec 100644 --- a/fault.go +++ b/vim25/types/fault.go @@ -14,18 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. */ -package govmomi - -import "github.com/vmware/govmomi/vim25/types" +package types type HasFault interface { - Fault() types.BaseMethodFault + Fault() BaseMethodFault } func IsFileNotFound(err error) bool { if f, ok := err.(HasFault); ok { switch f.Fault().(type) { - case *types.FileNotFound: + case *FileNotFound: return true } }