Skip to content

Commit

Permalink
Merge pull request #231 from pietern/move
Browse files Browse the repository at this point in the history
Misc
  • Loading branch information
pietern committed Mar 17, 2015
2 parents fff8fbc + 27bf35d commit 699036c
Show file tree
Hide file tree
Showing 148 changed files with 3,074 additions and 2,107 deletions.
296 changes: 35 additions & 261 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Loading

0 comments on commit 699036c

Please sign in to comment.