[vmwarevsphere] Start using govmomi provided helpers

Also update govmomi to latest revision and call Logout method when needed

Signed-off-by: S.Çağlar Onur <conur@vmware.com>
This commit is contained in:
S.Çağlar Onur 2016-01-26 10:22:20 -08:00
parent 7f708edcec
commit 0aedfd201d
268 changed files with 9881 additions and 1639 deletions

4
Godeps/Godeps.json generated
View File

@ -234,8 +234,8 @@
}, },
{ {
"ImportPath": "github.com/vmware/govmomi", "ImportPath": "github.com/vmware/govmomi",
"Comment": "prerelease-v0.1.0-73-gfc131d4-65-g482cd82", "Comment": "v0.3.0-11-g20c009c",
"Rev": "482cd823716e0fa9bc4e186d262a6ea23d940fbf" "Rev": "20c009ce9c493f0c714a9fffa5bda5fb84df2b6c"
}, },
{ {
"ImportPath": "github.com/docker/go-units", "ImportPath": "github.com/docker/go-units",

View File

@ -225,6 +225,7 @@ func (d *Driver) GetIP() (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
defer c.Logout(ctx)
vm, err := d.fetchVM(c, ctx, d.MachineName) vm, err := d.fetchVM(c, ctx, d.MachineName)
if err != nil { if err != nil {
@ -250,6 +251,7 @@ func (d *Driver) GetState() (state.State, error) {
if err != nil { if err != nil {
return state.None, err return state.None, err
} }
defer c.Logout(ctx)
vm, err := d.fetchVM(c, ctx, d.MachineName) vm, err := d.fetchVM(c, ctx, d.MachineName)
if err != nil { if err != nil {
@ -284,26 +286,27 @@ func (d *Driver) PreCreateCheck() error {
if err != nil { if err != nil {
return err return err
} }
defer c.Logout(ctx)
// Create a new finder // Create a new finder
f := find.NewFinder(c.Client, true) f := find.NewFinder(c.Client, true)
dc, err := d.getDatacenter(f, ctx) dc, err := f.DatacenterOrDefault(ctx, d.Datacenter)
if err != nil { if err != nil {
return err return err
} }
f.SetDatacenter(dc) f.SetDatacenter(dc)
if _, err := d.getDatastore(f, ctx); err != nil { if _, err := f.DatastoreOrDefault(ctx, d.Datastore); err != nil {
return err return err
} }
if _, err := d.getNetwork(f, ctx); err != nil { if _, err := f.NetworkOrDefault(ctx, d.Network); err != nil {
return err return err
} }
hs, err := d.getHostSystem(f, ctx) hs, err := f.HostSystemOrDefault(ctx, d.HostSystem)
if err != nil { if err != nil {
return err return err
} }
@ -348,27 +351,29 @@ func (d *Driver) Create() error {
if err != nil { if err != nil {
return err return err
} }
defer c.Logout(ctx)
// Create a new finder // Create a new finder
f := find.NewFinder(c.Client, true) f := find.NewFinder(c.Client, true)
dc, err := d.getDatacenter(f, ctx) dc, err := f.DatacenterOrDefault(ctx, d.Datacenter)
if err != nil { if err != nil {
return err return err
} }
f.SetDatacenter(dc) f.SetDatacenter(dc)
dss, err := d.getDatastore(f, ctx) dss, err := f.DatastoreOrDefault(ctx, d.Datastore)
if err != nil { if err != nil {
return err return err
} }
net, err := d.getNetwork(f, ctx) net, err := f.NetworkOrDefault(ctx, d.Network)
if err != nil { if err != nil {
return err return err
} }
hs, err := d.getHostSystem(f, ctx) hs, err := f.HostSystemOrDefault(ctx, d.HostSystem)
if err != nil { if err != nil {
return err return err
} }
@ -558,6 +563,7 @@ func (d *Driver) Start() error {
if err != nil { if err != nil {
return err return err
} }
defer c.Logout(ctx)
vm, err := d.fetchVM(c, ctx, d.MachineName) vm, err := d.fetchVM(c, ctx, d.MachineName)
if err != nil { if err != nil {
@ -590,6 +596,7 @@ func (d *Driver) Stop() error {
if err != nil { if err != nil {
return err return err
} }
defer c.Logout(ctx)
vm, err := d.fetchVM(c, ctx, d.MachineName) vm, err := d.fetchVM(c, ctx, d.MachineName)
if err != nil { if err != nil {
@ -645,6 +652,7 @@ func (d *Driver) Kill() error {
if err != nil { if err != nil {
return err return err
} }
defer c.Logout(ctx)
vm, err := d.fetchVM(c, ctx, d.MachineName) vm, err := d.fetchVM(c, ctx, d.MachineName)
if err != nil { if err != nil {
@ -683,18 +691,19 @@ func (d *Driver) Remove() error {
if err != nil { if err != nil {
return err return err
} }
defer c.Logout(ctx)
// Create a new finder // Create a new finder
f := find.NewFinder(c.Client, true) f := find.NewFinder(c.Client, true)
dc, err := d.getDatacenter(f, ctx) dc, err := f.DatacenterOrDefault(ctx, d.Datacenter)
if err != nil { if err != nil {
return err return err
} }
f.SetDatacenter(dc) f.SetDatacenter(dc)
dss, err := d.getDatastore(f, ctx) dss, err := f.DatastoreOrDefault(ctx, d.Datastore)
if err != nil { if err != nil {
return err return err
} }
@ -821,7 +830,7 @@ func (d *Driver) fetchVM(c *govmomi.Client, ctx context.Context, vmname string)
var vm *object.VirtualMachine var vm *object.VirtualMachine
var err error var err error
dc, err := d.getDatacenter(f, ctx) dc, err := f.DatacenterOrDefault(ctx, d.Datacenter)
if err != nil { if err != nil {
return vm, err return vm, err
} }
@ -856,83 +865,3 @@ func (f *FileAttrFlag) SetPerms(owner, group, perms int) {
func (f *FileAttrFlag) Attr() types.BaseGuestFileAttributes { func (f *FileAttrFlag) Attr() types.BaseGuestFileAttributes {
return &f.GuestPosixFileAttributes return &f.GuestPosixFileAttributes
} }
func (d *Driver) getDatacenter(f *find.Finder, ctx context.Context) (dc *object.Datacenter, err error) {
// Datacenter
if d.Datacenter != "" {
// Find specified Datacenter
dc, err = f.Datacenter(ctx, d.Datacenter)
if err != nil {
return dc, err
}
} else {
// Use default Datacenter
dc, err = f.DefaultDatacenter(ctx)
if err != nil {
return dc, err
}
}
log.Debug("Datacenter found: ", dc)
return dc, nil
}
func (d *Driver) getDatastore(f *find.Finder, ctx context.Context) (dss *object.Datastore, err error) {
// Datastore
if d.Datastore != "" {
// Find specified Datastore
dss, err = f.Datastore(ctx, d.Datastore)
if err != nil {
return dss, err
}
} else {
// Find default Datastore
dss, err = f.DefaultDatastore(ctx)
if err != nil {
return dss, err
}
}
log.Debug("Datastore found: ", dss)
return dss, err
}
func (d *Driver) getNetwork(f *find.Finder, ctx context.Context) (net object.NetworkReference, err error) {
// Network
if d.Network != "" {
// Find specified Network
net, err = f.Network(ctx, d.Network)
if err != nil {
return net, err
}
} else {
// Find default Network
net, err = f.DefaultNetwork(ctx)
if err != nil {
return net, err
}
}
log.Debug("Network found: ", net)
return net, nil
}
func (d *Driver) getHostSystem(f *find.Finder, ctx context.Context) (hs *object.HostSystem, err error) {
// HostSystem
if d.HostSystem != "" {
// Find specified HostSystem
hs, err = f.HostSystem(ctx, d.HostSystem)
if err != nil {
return hs, err
}
} else {
// Find default HostSystem
hs, err = f.DefaultHostSystem(ctx)
if err != nil {
return hs, err
}
}
log.Debug("HostSystem found: ", hs)
return hs, nil
}

View File

@ -1,9 +1,35 @@
# changelog # changelog
### (unreleased) ### 0.3.0 (2016-01-16)
* Add object.VirtualNicManager wrapper
* Add object.HostVsanSystem wrapper
* Add object.HostSystem methods: EnterMaintenanceMode, ExitMaintenanceMode, Disconnect, Reconnect
* Add finder.Folder method
* Add object.Common.Destroy method
* Add object.ComputeResource.Reconfigure method
* Add license.AssignmentManager wrapper
* Add object.HostFirewallSystem wrapper
* Add object.DiagnosticManager wrapper
* Add LoginExtensionByCertificate support
* Add object.ExtensionManager
... ...
### 0.2.0 (2015-09-15)
* Update to vim25/6.0 API
* Stop returning children from `ManagedObjectList` * Stop returning children from `ManagedObjectList`
Change the `ManagedObjectList` function in the `find` package to only Change the `ManagedObjectList` function in the `find` package to only

View File

@ -4,19 +4,23 @@
# #
Alvaro Miranda <kikitux@gmail.com> Alvaro Miranda <kikitux@gmail.com>
Amit Bathla <abathla@vmware.com>
Bob Killen <killen.bob@gmail.com> Bob Killen <killen.bob@gmail.com>
Bruce Downs <bdowns@vmware.com> Bruce Downs <bdowns@vmware.com>
Clint Greenwood <cgreenwood@vmware.com> <clint.greenwood@gmail.com> Clint Greenwood <cgreenwood@vmware.com> <clint.greenwood@gmail.com>
Danny Lockard <danny.lockard@banno.com> Danny Lockard <danny.lockard@banno.com>
Doug MacEachern <dougm@vmware.com> Doug MacEachern <dougm@vmware.com>
Eloy Coto <eloy.coto@gmail.com>
Eric Yutao <eric.yutao@gmail.com> Eric Yutao <eric.yutao@gmail.com>
Faiyaz Ahmed <ahmedf@vmware.com> Faiyaz Ahmed <ahmedf@vmware.com>
Gavin Gray <gavin@infinio.com> Gavin Gray <gavin@infinio.com>
Gavrie Philipson <gavrie@philipson.co.il> <gavrie.philipson@elastifile.com> Gavrie Philipson <gavrie@philipson.co.il> <gavrie.philipson@elastifile.com>
Louie Jiang <jiangl@vmware.com>
Mevan Samaratunga <mevansam@gmail.com> Mevan Samaratunga <mevansam@gmail.com>
Pieter Noordhuis <pnoordhuis@vmware.com> <pcnoordhuis@gmail.com> Pieter Noordhuis <pnoordhuis@vmware.com> <pcnoordhuis@gmail.com>
runner.mei <runner.mei@gmail.com>
S.Çağlar Onur <conur@vmware.com> S.Çağlar Onur <conur@vmware.com>
Takaaki Furukawa <takaaki.frkw@gmail.com> Takaaki Furukawa <takaaki.frkw@gmail.com> <takaaki.furukawa@mail.rakuten.com>
Yang Yang <yangy@vmware.com> Yang Yang <yangy@vmware.com>
Yuya Kusakabe <yuya.kusakabe@gmail.com> Yuya Kusakabe <yuya.kusakabe@gmail.com>
Zee Yang <zeey@vmware.com> <zee.yang@gmail.com> Zee Yang <zeey@vmware.com> <zee.yang@gmail.com>

View File

@ -8,7 +8,7 @@ For `govc`, a CLI built on top of govmomi, check out the [govc](./govc) director
## Compatibility ## Compatibility
This library is built for and tested against ESXi and vCenter 5.5. This library is built for and tested against ESXi and vCenter 5.5 and 6.0.
If you're able to use it against older versions of ESXi and/or vCenter, please If you're able to use it against older versions of ESXi and/or vCenter, please
leave a note and we'll include it in this compatibility list. leave a note and we'll include it in this compatibility list.
@ -22,7 +22,7 @@ The code in the `govmomi` package is a wrapper for the code that is generated fr
It primarily provides convenience functions for working with the vSphere API. It primarily provides convenience functions for working with the vSphere API.
See [godoc.org][godoc] for documentation. See [godoc.org][godoc] for documentation.
[apiref]:http://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/right-pane.html [apiref]:http://pubs.vmware.com/vsphere-60/index.jsp#com.vmware.wssdk.apiref.doc/right-pane.html
[godoc]:http://godoc.org/github.com/vmware/govmomi [godoc]:http://godoc.org/github.com/vmware/govmomi
## Status ## Status

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -57,6 +57,7 @@ are kept outside the object package.
package govmomi package govmomi
import ( import (
"crypto/tls"
"net/url" "net/url"
"github.com/vmware/govmomi/property" "github.com/vmware/govmomi/property"
@ -74,7 +75,7 @@ type Client struct {
} }
// NewClient creates a new client from a URL. The client authenticates with the // NewClient creates a new client from a URL. The client authenticates with the
// server before returning if the URL contains user information. // server with username/password before returning if the URL contains user information.
func NewClient(ctx context.Context, u *url.URL, insecure bool) (*Client, error) { func NewClient(ctx context.Context, u *url.URL, insecure bool) (*Client, error) {
soapClient := soap.NewClient(u, insecure) soapClient := soap.NewClient(u, insecure)
vimClient, err := vim25.NewClient(ctx, soapClient) vimClient, err := vim25.NewClient(ctx, soapClient)
@ -98,11 +99,41 @@ func NewClient(ctx context.Context, u *url.URL, insecure bool) (*Client, error)
return c, nil return c, nil
} }
// NewClientWithCertificate creates a new client from a URL. The client authenticates with the
// server with the certificate before returning if the URL contains user information.
func NewClientWithCertificate(ctx context.Context, u *url.URL, insecure bool, cert tls.Certificate) (*Client, error) {
soapClient := soap.NewClient(u, insecure)
soapClient.SetCertificate(cert)
vimClient, err := vim25.NewClient(ctx, soapClient)
if err != nil {
return nil, err
}
c := &Client{
Client: vimClient,
SessionManager: session.NewManager(vimClient),
}
if u.User != nil {
err = c.LoginExtensionByCertificate(ctx, u.User.Username(), "")
if err != nil {
return nil, err
}
}
return c, nil
}
// Login dispatches to the SessionManager. // Login dispatches to the SessionManager.
func (c *Client) Login(ctx context.Context, u *url.Userinfo) error { func (c *Client) Login(ctx context.Context, u *url.Userinfo) error {
return c.SessionManager.Login(ctx, u) return c.SessionManager.Login(ctx, u)
} }
// Login dispatches to the SessionManager.
func (c *Client) LoginExtensionByCertificate(ctx context.Context, key string, locale string) error {
return c.SessionManager.LoginExtensionByCertificate(ctx, key, locale)
}
// Logout dispatches to the SessionManager. // Logout dispatches to the SessionManager.
func (c *Client) Logout(ctx context.Context) error { func (c *Client) Logout(ctx context.Context) error {
// Close any idle connections after logging out. // Close any idle connections after logging out.

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -43,6 +43,7 @@ func NewManager(c *vim25.Client) *Manager {
c: c, c: c,
eventCategory: make(map[string]string),
eventCategoryMu: new(sync.Mutex), eventCategoryMu: new(sync.Mutex),
} }
@ -125,7 +126,7 @@ func (m Manager) eventCategoryMap(ctx context.Context) (map[string]string, error
m.eventCategoryMu.Lock() m.eventCategoryMu.Lock()
defer m.eventCategoryMu.Unlock() defer m.eventCategoryMu.Unlock()
if m.eventCategory != nil { if len(m.eventCategory) != 0 {
return m.eventCategory, nil return m.eventCategory, nil
} }
@ -137,8 +138,6 @@ func (m Manager) eventCategoryMap(ctx context.Context) (map[string]string, error
return nil, err return nil, err
} }
m.eventCategory = make(map[string]string, len(o.Description.EventInfo))
for _, info := range o.Description.EventInfo { for _, info := range o.Description.EventInfo {
m.eventCategory[info.Key] = info.Category m.eventCategory[info.Key] = info.Category
} }

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -243,6 +243,18 @@ func (f *Finder) DefaultDatacenter(ctx context.Context) (*object.Datacenter, err
return dc, nil return dc, nil
} }
func (f *Finder) DatacenterOrDefault(ctx context.Context, path string) (*object.Datacenter, error) {
if path != "" {
dc, err := f.Datacenter(ctx, path)
if err != nil {
return nil, err
}
return dc, nil
}
return f.DefaultDatacenter(ctx)
}
func (f *Finder) DatastoreList(ctx context.Context, path string) ([]*object.Datastore, error) { func (f *Finder) DatastoreList(ctx context.Context, path string) ([]*object.Datastore, error) {
es, err := f.find(ctx, f.datastoreFolder, false, path) es, err := f.find(ctx, f.datastoreFolder, false, path)
if err != nil { if err != nil {
@ -289,6 +301,18 @@ func (f *Finder) DefaultDatastore(ctx context.Context) (*object.Datastore, error
return ds, nil return ds, nil
} }
func (f *Finder) DatastoreOrDefault(ctx context.Context, path string) (*object.Datastore, error) {
if path != "" {
ds, err := f.Datastore(ctx, path)
if err != nil {
return nil, err
}
return ds, nil
}
return f.DefaultDatastore(ctx)
}
func (f *Finder) ComputeResourceList(ctx context.Context, path string) ([]*object.ComputeResource, error) { func (f *Finder) ComputeResourceList(ctx context.Context, path string) ([]*object.ComputeResource, error) {
es, err := f.find(ctx, f.hostFolder, false, path) es, err := f.find(ctx, f.hostFolder, false, path)
if err != nil { if err != nil {
@ -339,6 +363,18 @@ func (f *Finder) DefaultComputeResource(ctx context.Context) (*object.ComputeRes
return cr, nil return cr, nil
} }
func (f *Finder) ComputeResourceOrDefault(ctx context.Context, path string) (*object.ComputeResource, error) {
if path != "" {
cr, err := f.ComputeResource(ctx, path)
if err != nil {
return nil, err
}
return cr, nil
}
return f.DefaultComputeResource(ctx)
}
func (f *Finder) ClusterComputeResourceList(ctx context.Context, path string) ([]*object.ClusterComputeResource, error) { func (f *Finder) ClusterComputeResourceList(ctx context.Context, path string) ([]*object.ClusterComputeResource, error) {
es, err := f.find(ctx, f.hostFolder, false, path) es, err := f.find(ctx, f.hostFolder, false, path)
if err != nil { if err != nil {
@ -393,19 +429,21 @@ func (f *Finder) HostSystemList(ctx context.Context, path string) ([]*object.Hos
switch o := e.Object.(type) { switch o := e.Object.(type) {
case mo.HostSystem: case mo.HostSystem:
hs = object.NewHostSystem(f.client, o.Reference()) hs = object.NewHostSystem(f.client, o.Reference())
case mo.ComputeResource:
hs.InventoryPath = e.Path
hss = append(hss, hs)
case mo.ComputeResource, mo.ClusterComputeResource:
cr := object.NewComputeResource(f.client, o.Reference()) cr := object.NewComputeResource(f.client, o.Reference())
cr.InventoryPath = e.Path
hosts, err := cr.Hosts(ctx) hosts, err := cr.Hosts(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
hs = object.NewHostSystem(f.client, hosts[0])
default:
continue
}
hs.InventoryPath = e.Path hss = append(hss, hosts...)
hss = append(hss, hs) }
} }
if len(hss) == 0 { if len(hss) == 0 {
@ -437,6 +475,18 @@ func (f *Finder) DefaultHostSystem(ctx context.Context) (*object.HostSystem, err
return hs, nil return hs, nil
} }
func (f *Finder) HostSystemOrDefault(ctx context.Context, path string) (*object.HostSystem, error) {
if path != "" {
hs, err := f.HostSystem(ctx, path)
if err != nil {
return nil, err
}
return hs, nil
}
return f.DefaultHostSystem(ctx)
}
func (f *Finder) NetworkList(ctx context.Context, path string) ([]object.NetworkReference, error) { func (f *Finder) NetworkList(ctx context.Context, path string) ([]object.NetworkReference, error) {
es, err := f.find(ctx, f.networkFolder, false, path) es, err := f.find(ctx, f.networkFolder, false, path)
if err != nil { if err != nil {
@ -455,6 +505,10 @@ func (f *Finder) NetworkList(ctx context.Context, path string) ([]object.Network
r := object.NewDistributedVirtualPortgroup(f.client, ref) r := object.NewDistributedVirtualPortgroup(f.client, ref)
r.InventoryPath = e.Path r.InventoryPath = e.Path
ns = append(ns, r) ns = append(ns, r)
case "DistributedVirtualSwitch", "VmwareDistributedVirtualSwitch":
r := object.NewDistributedVirtualSwitch(f.client, ref)
r.InventoryPath = e.Path
ns = append(ns, r)
} }
} }
@ -487,6 +541,18 @@ func (f *Finder) DefaultNetwork(ctx context.Context) (object.NetworkReference, e
return network, nil return network, nil
} }
func (f *Finder) NetworkOrDefault(ctx context.Context, path string) (object.NetworkReference, error) {
if path != "" {
network, err := f.Network(ctx, path)
if err != nil {
return nil, err
}
return network, nil
}
return f.DefaultNetwork(ctx)
}
func (f *Finder) ResourcePoolList(ctx context.Context, path string) ([]*object.ResourcePool, error) { func (f *Finder) ResourcePoolList(ctx context.Context, path string) ([]*object.ResourcePool, error) {
es, err := f.find(ctx, f.hostFolder, true, path) es, err := f.find(ctx, f.hostFolder, true, path)
if err != nil { if err != nil {
@ -534,6 +600,18 @@ func (f *Finder) DefaultResourcePool(ctx context.Context) (*object.ResourcePool,
return rp, nil return rp, nil
} }
func (f *Finder) ResourcePoolOrDefault(ctx context.Context, path string) (*object.ResourcePool, error) {
if path != "" {
rp, err := f.ResourcePool(ctx, path)
if err != nil {
return nil, err
}
return rp, nil
}
return f.DefaultResourcePool(ctx)
}
func (f *Finder) VirtualMachineList(ctx context.Context, path string) ([]*object.VirtualMachine, error) { func (f *Finder) VirtualMachineList(ctx context.Context, path string) ([]*object.VirtualMachine, error) {
es, err := f.find(ctx, f.vmFolder, false, path) es, err := f.find(ctx, f.vmFolder, false, path)
if err != nil { if err != nil {
@ -605,3 +683,29 @@ func (f *Finder) VirtualApp(ctx context.Context, path string) (*object.VirtualAp
return apps[0], nil return apps[0], nil
} }
func (f *Finder) Folder(ctx context.Context, path string) (*object.Folder, error) {
mo, err := f.ManagedObjectList(ctx, path)
if err != nil {
return nil, err
}
if len(mo) == 0 {
return nil, &NotFoundError{"folder", path}
}
if len(mo) > 1 {
return nil, &MultipleFoundError{"folder", path}
}
ref := mo[0].Object.Reference()
if ref.Type != "Folder" {
return nil, &NotFoundError{"folder", path}
}
folder := object.NewFolder(f.client, ref)
folder.InventoryPath = mo[0].Path
return folder, nil
}

12
vendor/github.com/vmware/govmomi/gen/Gemfile.lock generated vendored Normal file
View File

@ -0,0 +1,12 @@
GEM
remote: https://rubygems.org/
specs:
mini_portile (0.6.0)
nokogiri (1.6.3.1)
mini_portile (= 0.6.0)
PLATFORMS
ruby
DEPENDENCIES
nokogiri

View File

@ -1,4 +1,4 @@
# Copyright (c) 2014 VMware, Inc. All Rights Reserved. # Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -738,22 +738,6 @@ class WSDL
def self.header(name) def self.header(name)
return <<EOF return <<EOF
/*
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 #{name} package #{name}
EOF EOF

View File

@ -2,6 +2,39 @@
### (unreleased) ### (unreleased)
* Add `-p` and `-a` options to govc datastore.ls command
### 0.3.0 (2016-01-16)
* Add permissions.{ls,set,remove} commands
* Add datastore.{create,remove} commands.
The new create command supports both creating NAS and VMFS datastores.
* Add dvs.{create,add} and dvs.portgroup.add commands
* Add host.vnic.{service,info} commands
* Add cluster.{create,change,add} commands
* Add host.{disconnect,reconnect,remove,maintenance.enter,maintenance.exit} commands
* Add license.decode, license.assigned.list and license.assign commands
* Add firewall.ruleset.find command
* Add logs, logs.ls and logs.download commands
* Add support for LoginExtensionByCertificate with new `-cert` and `-key` flags
* Add govc extension.{info,register,unregister,setcert} commands
* Add govc vapp.{info,destroy,power} commands
### 0.2.0 (2015-09-15)
* The `vm.power` guest `-s` and `-r` options will fallback to hard `-off` / `-reset` if tools is unavailable and `-force` flag is given
* Add `PowerOn, InjectOvfEnv, WaitForIP` options to `import.ovf` and `import.ova` option spec file * Add `PowerOn, InjectOvfEnv, WaitForIP` options to `import.ovf` and `import.ova` option spec file
* Add `import.spec` to produce an example json document * Add `import.spec` to produce an example json document
@ -10,12 +43,22 @@
* Add `-folder` to `import.ovf` and `import.ova` * Add `-folder` to `import.ovf` and `import.ova`
* Add `fields` command to manage custom fields
* Add `datastore.info` command
* Add `events` command
* Add `-net.address` (Hardware Address) option to `vm.change` and `vm.create`
* Add `host.add` command to add host to datacenter. * Add `host.add` command to add host to datacenter.
* Add `GOVC_USERNAME` and `GOVC_PASSWORD` to allow overriding username and/or * Add `GOVC_USERNAME` and `GOVC_PASSWORD` to allow overriding username and/or
password (used when they contain special characters that prevent them from password (used when they contain special characters that prevent them from
being embedded in the URL). being embedded in the URL).
* Add `-e' (ExtraConfig) option to `vm.change` and `vm.info`
* Retry twice on temporary network errors. * Retry twice on temporary network errors.
* Add `host.autostart` commands to manage VM autostart. * Add `host.autostart` commands to manage VM autostart.

View File

@ -22,6 +22,8 @@ import (
"os" "os"
"text/tabwriter" "text/tabwriter"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/govc/flags"
) )
@ -34,11 +36,19 @@ func init() {
cli.Register("about", &about{}) cli.Register("about", &about{})
} }
func (cmd *about) Register(f *flag.FlagSet) {} func (cmd *about) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
}
func (cmd *about) Process() error { return nil } func (cmd *about) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *about) Run(f *flag.FlagSet) error { func (cmd *about) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client() c, err := cmd.Client()
if err != nil { if err != nil {
return err return err

View File

@ -1,22 +1,32 @@
#!/bin/bash -e #!/bin/bash -e
if ! which gox > /dev/null; then
echo "gox is not installed..."
exit 1
fi
git_version=$(git describe) git_version=$(git describe)
if git_status=$(git status --porcelain 2>/dev/null) && [ -n "${git_status}" ]; then if git_status=$(git status --porcelain 2>/dev/null) && [ -n "${git_status}" ]; then
git_version="${git_version}-dirty" git_version="${git_version}-dirty"
fi fi
ldflags="-X github.com/vmware/govmomi/govc/version.gitVersion ${git_version}" ldflags="-X github.com/vmware/govmomi/govc/version.gitVersion=${git_version}"
BUILD_OS=${BUILD_OS:-darwin linux windows freebsd} BUILD_OS=${BUILD_OS:-darwin linux windows freebsd}
BUILD_ARCH=${BUILD_ARCH:-386 amd64} BUILD_ARCH=${BUILD_ARCH:-386 amd64}
gox \ for os in ${BUILD_OS}; do
-parallel=1 \ export GOOS="${os}"
-ldflags="${ldflags}" \ for arch in ${BUILD_ARCH}; do
-os="${BUILD_OS}" \ export GOARCH="${arch}"
-arch="${BUILD_ARCH}" \
github.com/vmware/govmomi/govc out="govc_${os}_${arch}"
if [ "${os}" == "windows" ]; then
out="${out}.exe"
fi
set -x
go build \
-o="${out}" \
-pkgdir="./_pkg" \
-compiler='gc' \
-ldflags="${ldflags}" \
github.com/vmware/govmomi/govc
set +x
done
done

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -21,50 +21,24 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"reflect"
"sort" "sort"
"text/tabwriter" "text/tabwriter"
"golang.org/x/net/context"
) )
type HasFlags interface { type HasFlags interface {
// Register may be called more than once and should be idempotent. // Register may be called more than once and should be idempotent.
Register(f *flag.FlagSet) Register(ctx context.Context, f *flag.FlagSet)
// Process may be called more than once and should be idempotent. // Process may be called more than once and should be idempotent.
Process() error Process(ctx context.Context) error
} }
type Command interface { type Command interface {
HasFlags HasFlags
Run(f *flag.FlagSet) error Run(ctx context.Context, f *flag.FlagSet) error
}
var hasFlagsType = reflect.TypeOf((*HasFlags)(nil)).Elem()
func RegisterCommand(h HasFlags, f *flag.FlagSet) {
visited := make(map[interface{}]struct{})
Walk(h, hasFlagsType, func(v interface{}) error {
if _, ok := visited[v]; ok {
return nil
}
visited[v] = struct{}{}
v.(HasFlags).Register(f)
return nil
})
}
func ProcessCommand(h HasFlags) error {
visited := make(map[interface{}]struct{})
err := Walk(h, hasFlagsType, func(v interface{}) error {
if _, ok := visited[v]; ok {
return nil
}
visited[v] = struct{}{}
err := v.(HasFlags).Process()
return err
})
return err
} }
func generalHelp() { func generalHelp() {
@ -117,6 +91,8 @@ func commandHelp(name string, cmd Command, f *flag.FlagSet) {
} }
func Run(args []string) int { func Run(args []string) int {
var err error
if len(args) == 0 { if len(args) == 0 {
generalHelp() generalHelp()
return 1 return 1
@ -134,37 +110,33 @@ func Run(args []string) int {
return 1 return 1
} }
f := flag.NewFlagSet("", flag.ContinueOnError) fs := flag.NewFlagSet("", flag.ContinueOnError)
f.SetOutput(ioutil.Discard) fs.SetOutput(ioutil.Discard)
RegisterCommand(cmd, f) ctx := context.Background()
cmd.Register(ctx, fs)
if err := f.Parse(args[1:]); err != nil { if err = fs.Parse(args[1:]); err != nil {
if err == flag.ErrHelp { goto error
commandHelp(args[0], cmd, f)
} else {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
}
return 1
} }
if err := ProcessCommand(cmd); err != nil { if err = cmd.Process(ctx); err != nil {
if err == flag.ErrHelp { goto error
commandHelp(args[0], cmd, f)
} else {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
}
return 1
} }
if err := cmd.Run(f); err != nil { if err = cmd.Run(ctx, fs); err != nil {
if err == flag.ErrHelp { goto error
commandHelp(args[0], cmd, f)
} else {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
}
return 1
} }
return 0 return 0
error:
if err == flag.ErrHelp {
commandHelp(args[0], cmd, fs)
} else {
fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], err)
}
return 1
} }

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -1,108 +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 cli
import (
"fmt"
"reflect"
)
type WalkFn func(c interface{}) error
// Walk recursively walks struct types that implement the specified interface.
// Fields that implement the specified interface are expected to be pointer
// values. This allows the function to cache pointer values on a per-type
// basis. If, during a recursive walk, the same type is encountered twice, the
// function creates a new value of that type the first time, and reuses that
// same value the second time.
//
// This function is used to make sure that a hierarchy of flags where multiple
// structs refer to the `Client` flag will not end up with more than one
// instance of the actual client. Rather, every struct referring to the
// `Client` flag will have a pointer to the same underlying `Client` struct.
//
func Walk(c interface{}, ifaceType reflect.Type, fn WalkFn) error {
var walker WalkFn
visited := make(map[reflect.Type]reflect.Value)
walker = func(c interface{}) error {
v := reflect.ValueOf(c)
if v.Kind() == reflect.Interface {
v = v.Elem()
}
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
t := v.Type()
// Call user specified function.
err := fn(c)
if err != nil {
return err
}
for i := 0; i < t.NumField(); i++ {
ff := t.Field(i)
ft := ff.Type
fv := v.Field(i)
// Check that a pointer to this field's type doesn't implement the
// specified interface. If it does, this field references the type as
// value. This is not allowed because it prohibits a value from being
// shared among multiple structs that reference it.
//
// For example: if a struct has two fields of the same type, they must
// both point to the same value after this routine has executed. If these
// fields are not a pointer type, the value cannot be shared.
//
if reflect.PtrTo(ft).Implements(ifaceType) {
panic(fmt.Sprintf(`field "%s" in struct "%s" must be a pointer`, ff.Name, v.Type()))
}
// Type must implement specified interface.
if !ft.Implements(ifaceType) {
continue
}
// Type must be a pointer.
if ft.Kind() != reflect.Ptr {
panic(fmt.Sprintf(`field "%s" in struct "%s" must be a pointer`, ff.Name, v.Type()))
}
// Have not seen this type before, create a value.
if _, ok := visited[ft]; !ok {
visited[ft] = reflect.New(ft.Elem())
}
// Make sure current field is set.
if fv.IsNil() {
fv.Set(visited[ft])
}
// Recurse.
err := walker(fv.Interface())
if err != nil {
return err
}
}
return nil
}
return walker(c)
}

129
vendor/github.com/vmware/govmomi/govc/cluster/add.go generated vendored Normal file
View File

@ -0,0 +1,129 @@
/*
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 cluster
import (
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type add struct {
*flags.DatacenterFlag
*flags.HostConnectFlag
cluster string
connect bool
license string
}
func init() {
cli.Register("cluster.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
cmd.HostConnectFlag, ctx = flags.NewHostConnectFlag(ctx)
cmd.HostConnectFlag.Register(ctx, f)
f.StringVar(&cmd.cluster, "cluster", "*", "Path to cluster")
f.StringVar(&cmd.license, "license", "", "Assign license key")
f.BoolVar(&cmd.connect, "connect", true, "Immediately connect to host")
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
if err := cmd.HostConnectFlag.Process(ctx); err != nil {
return err
}
if cmd.HostName == "" {
return flag.ErrHelp
}
if cmd.UserName == "" {
return flag.ErrHelp
}
if cmd.Password == "" {
return flag.ErrHelp
}
return nil
}
func (cmd *add) Description() string {
return `Add host to cluster.
The host is added to the cluster specified by the 'cluster' flag.`
}
func (cmd *add) Add(ctx context.Context, cluster *object.ClusterComputeResource) error {
spec := cmd.HostConnectSpec
var license *string
if cmd.license != "" {
license = &cmd.license
}
task, err := cluster.AddHost(ctx, spec, cmd.connect, license, nil)
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("adding %s to cluster %s... ", spec.HostName, cluster.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 0 {
return flag.ErrHelp
}
finder, err := cmd.Finder()
if err != nil {
return err
}
cluster, err := finder.ClusterComputeResource(ctx, cmd.cluster)
if err != nil {
return nil
}
err = cmd.Add(ctx, cluster)
if err == nil {
return nil
}
// Check if we failed due to SSLVerifyFault and -noverify is set
if err := cmd.AcceptThumbprint(err); err != nil {
return err
}
// Accepted unverified thumbprint, try again
return cmd.Add(ctx, cluster)
}

109
vendor/github.com/vmware/govmomi/govc/cluster/change.go generated vendored Normal file
View File

@ -0,0 +1,109 @@
/*
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 cluster
import (
"flag"
"strings"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)
type change struct {
*flags.DatacenterFlag
types.ClusterConfigSpecEx
}
func init() {
cli.Register("cluster.change", &change{})
}
func (cmd *change) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
cmd.DrsConfig = new(types.ClusterDrsConfigInfo)
cmd.DasConfig = new(types.ClusterDasConfigInfo)
cmd.VsanConfig = new(types.VsanClusterConfigInfo)
cmd.VsanConfig.DefaultConfig = new(types.VsanClusterConfigInfoHostDefaultInfo)
// DRS
f.Var(flags.NewOptionalBool(&cmd.DrsConfig.Enabled), "drs-enabled", "Enable DRS")
drsModes := []string{
string(types.DrsBehaviorManual),
string(types.DrsBehaviorPartiallyAutomated),
string(types.DrsBehaviorFullyAutomated),
}
f.StringVar((*string)(&cmd.DrsConfig.DefaultVmBehavior), "drs-mode", "",
"DRS behavior for virtual machines: "+strings.Join(drsModes, ", "))
// HA
f.Var(flags.NewOptionalBool(&cmd.DasConfig.Enabled), "ha-enabled", "Enable HA")
// vSAN
f.Var(flags.NewOptionalBool(&cmd.VsanConfig.Enabled), "vsan-enabled", "Enable vSAN")
f.Var(flags.NewOptionalBool(&cmd.VsanConfig.DefaultConfig.AutoClaimStorage), "vsan-autoclaim", "")
}
func (cmd *change) Process(ctx context.Context) error {
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *change) Usage() string {
return "CLUSTER..."
}
func (cmd *change) Description() string {
return `Change configuration of the given clusters.`
}
func (cmd *change) Run(ctx context.Context, f *flag.FlagSet) error {
finder, err := cmd.Finder()
if err != nil {
return err
}
for _, path := range f.Args() {
clusters, err := finder.ClusterComputeResourceList(ctx, path)
if err != nil {
return err
}
for _, cluster := range clusters {
task, err := cluster.Reconfigure(ctx, &cmd.ClusterConfigSpecEx, true)
if err != nil {
return err
}
_, err = task.WaitForResult(ctx, nil)
if err != nil {
return err
}
}
}
return nil
}

104
vendor/github.com/vmware/govmomi/govc/cluster/create.go generated vendored Normal file
View File

@ -0,0 +1,104 @@
/*
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 cluster
import (
"flag"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
)
type create struct {
*flags.DatacenterFlag
parent string
types.ClusterConfigSpecEx
}
func init() {
cli.Register("cluster.create", &create{})
}
func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
f.StringVar(&cmd.parent, "parent", "", "Path to parent folder for the new cluster")
}
func (cmd *create) Usage() string {
return "CLUSTER"
}
func (cmd *create) Description() string {
return `Create CLUSTER in datacenter.
The cluster is added to the folder specified by the 'parent' flag. If not given,
this defaults to the hosts folder in the specified or default datacenter.`
}
func (cmd *create) Process(ctx context.Context) error {
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
var parent *object.Folder
if f.NArg() != 1 {
return flag.ErrHelp
}
if cmd.parent == "" {
dc, err := cmd.Datacenter()
if err != nil {
return err
}
folders, err := dc.Folders(ctx)
if err != nil {
return err
}
parent = folders.HostFolder
} else {
finder, err := cmd.Finder()
if err != nil {
return err
}
parent, err = finder.Folder(ctx, cmd.parent)
if err != nil {
return err
}
}
_, err := parent.CreateCluster(ctx, f.Arg(0), cmd.ClusterConfigSpecEx)
if err != nil {
return err
}
return nil
}

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -34,15 +34,23 @@ func init() {
cli.Register("datacenter.create", &create{}) cli.Register("datacenter.create", &create{})
} }
func (cmd *create) Register(f *flag.FlagSet) {} func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
}
func (cmd *create) Usage() string { func (cmd *create) Usage() string {
return "[DATACENTER NAME]..." return "[DATACENTER NAME]..."
} }
func (cmd *create) Process() error { return nil } func (cmd *create) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *create) Run(f *flag.FlagSet) error { func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
datacenters := f.Args() datacenters := f.Args()
if len(datacenters) < 1 { if len(datacenters) < 1 {
return flag.ErrHelp return flag.ErrHelp

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -33,15 +33,23 @@ func init() {
cli.Register("datacenter.destroy", &destroy{}) cli.Register("datacenter.destroy", &destroy{})
} }
func (cmd *destroy) Register(f *flag.FlagSet) {} func (cmd *destroy) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
}
func (cmd *destroy) Usage() string { func (cmd *destroy) Usage() string {
return "[DATACENTER NAME]..." return "[DATACENTER NAME]..."
} }
func (cmd *destroy) Process() error { return nil } func (cmd *destroy) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *destroy) Run(f *flag.FlagSet) error { func (cmd *destroy) Run(ctx context.Context, f *flag.FlagSet) error {
if len(f.Args()) < 1 { if len(f.Args()) < 1 {
return flag.ErrHelp return flag.ErrHelp
} }

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -37,17 +37,31 @@ func init() {
cli.Register("datastore.cp", &cp{}) cli.Register("datastore.cp", &cp{})
} }
func (cmd *cp) Register(f *flag.FlagSet) { func (cmd *cp) Register(ctx context.Context, f *flag.FlagSet) {
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
f.BoolVar(&cmd.force, "f", false, "If true, overwrite any identically named file at the destination") f.BoolVar(&cmd.force, "f", false, "If true, overwrite any identically named file at the destination")
} }
func (cmd *cp) Process() error { return nil } func (cmd *cp) Process(ctx context.Context) error {
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *cp) Usage() string { func (cmd *cp) Usage() string {
return "SRC DST" return "SRC DST"
} }
func (cmd *cp) Run(f *flag.FlagSet) error { func (cmd *cp) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args() args := f.Args()
if len(args) != 2 { if len(args) != 2 {
return errors.New("SRC and DST arguments are required") return errors.New("SRC and DST arguments are required")

View File

@ -0,0 +1,273 @@
/*
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 datastore
import (
"errors"
"flag"
"fmt"
"os"
"strings"
"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 create struct {
*flags.HostSystemFlag
// Generic options
Type typeFlag
Name string
Force bool
// Options for NAS
RemoteHost string
RemotePath string
AccessMode string
UserName string
Password string
// Options for VMFS
DiskCanonicalName string
}
func init() {
cli.Register("datastore.create", &create{})
}
var nasTypes = []string{
string(types.HostFileSystemVolumeFileSystemTypeNFS),
string(types.HostFileSystemVolumeFileSystemTypeNFS41),
string(types.HostFileSystemVolumeFileSystemTypeCIFS),
}
var vmfsTypes = []string{
"VMFS",
}
var allTypes = []string{}
func init() {
allTypes = append(allTypes, nasTypes...)
allTypes = append(allTypes, vmfsTypes...)
}
type typeFlag string
func (t *typeFlag) Set(s string) error {
s = strings.ToLower(s)
for _, e := range allTypes {
if s == strings.ToLower(e) {
*t = typeFlag(e)
return nil
}
}
return fmt.Errorf("unknown type")
}
func (t *typeFlag) String() string {
return string(*t)
}
func (t *typeFlag) partOf(m []string) bool {
for _, e := range m {
if t.String() == e {
return true
}
}
return false
}
func (t *typeFlag) IsNasType() bool {
return t.partOf(nasTypes)
}
func (t *typeFlag) IsVmfsType() bool {
return t.partOf(vmfsTypes)
}
func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
modes := []string{
string(types.HostMountModeReadOnly),
string(types.HostMountModeReadWrite),
}
f.StringVar(&cmd.Name, "name", "", "Datastore name")
f.Var(&cmd.Type, "type", fmt.Sprintf("Datastore type (%s)", strings.Join(allTypes, "|")))
f.BoolVar(&cmd.Force, "force", false, "Ignore DuplicateName error if datastore is already mounted on a host")
// Options for NAS
f.StringVar(&cmd.RemoteHost, "remote-host", "", "Remote hostname of the NAS datastore")
f.StringVar(&cmd.RemotePath, "remote-path", "", "Remote path of the NFS mount point")
f.StringVar(&cmd.AccessMode, "mode", modes[0],
fmt.Sprintf("Access mode for the mount point (%s)", strings.Join(modes, "|")))
f.StringVar(&cmd.UserName, "username", "", "Username to use when connecting (CIFS only)")
f.StringVar(&cmd.Password, "password", "", "Password to use when connecting (CIFS only)")
// Options for VMFS
f.StringVar(&cmd.DiskCanonicalName, "disk", "", "Canonical name of disk (VMFS only)")
}
func (cmd *create) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *create) Usage() string {
return "HOST..."
}
func (cmd *create) Description() string {
return `Create datastore on HOST.
Examples:
govc datastore.create -type nfs -name nfsDatastore -remote-host 10.143.2.232 -remote-path /share cluster1
govc datastore.create -type vmfs -name localDatastore -disk=mpx.vmhba0:C0:T0:L0 cluster1`
}
func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
hosts, err := cmd.HostSystems(f.Args())
if err != nil {
return err
}
switch {
case cmd.Type.IsNasType():
return cmd.CreateNasDatastore(ctx, hosts)
case cmd.Type.IsVmfsType():
return cmd.CreateVmfsDatastore(ctx, hosts)
default:
return fmt.Errorf("unhandled type %#v", cmd.Type)
}
}
func (cmd *create) GetHostNasVolumeSpec() types.HostNasVolumeSpec {
s := types.HostNasVolumeSpec{
LocalPath: cmd.Name,
Type: cmd.Type.String(),
RemoteHost: cmd.RemoteHost,
RemotePath: cmd.RemotePath,
AccessMode: cmd.AccessMode,
UserName: cmd.UserName,
Password: cmd.Password,
}
return s
}
func (cmd *create) CreateNasDatastore(ctx context.Context, hosts []*object.HostSystem) error {
object := types.ManagedObjectReference{
Type: "Datastore",
Value: fmt.Sprintf("%s:%s", cmd.RemoteHost, cmd.RemotePath),
}
spec := cmd.GetHostNasVolumeSpec()
for _, host := range hosts {
ds, err := host.ConfigManager().DatastoreSystem(ctx)
if err != nil {
return err
}
_, err = ds.CreateNasDatastore(ctx, spec)
if err != nil {
if soap.IsSoapFault(err) {
switch fault := soap.ToSoapFault(err).VimFault().(type) {
case types.PlatformConfigFault:
if len(fault.FaultMessage) != 0 {
return errors.New(fault.FaultMessage[0].Message)
}
case types.DuplicateName:
if cmd.Force && fault.Object == object {
fmt.Fprintf(os.Stderr, "%s: '%s' already mounted\n",
host.InventoryPath, cmd.Name)
continue
}
}
}
return fmt.Errorf("%s: %s", host.InventoryPath, err)
}
}
return nil
}
func (cmd *create) CreateVmfsDatastore(ctx context.Context, hosts []*object.HostSystem) error {
for _, host := range hosts {
ds, err := host.ConfigManager().DatastoreSystem(ctx)
if err != nil {
return err
}
// Find the specified disk
disks, err := ds.QueryAvailableDisksForVmfs(ctx)
if err != nil {
return err
}
var disk *types.HostScsiDisk
for _, e := range disks {
if e.CanonicalName == cmd.DiskCanonicalName {
disk = &e
break
}
}
if disk == nil {
return fmt.Errorf("no eligible disk found for name %#v", cmd.DiskCanonicalName)
}
// Query for creation options and pick the right one
options, err := ds.QueryVmfsDatastoreCreateOptions(ctx, disk.DevicePath)
if err != nil {
return err
}
var option *types.VmfsDatastoreOption
for _, e := range options {
if _, ok := e.Info.(*types.VmfsDatastoreAllExtentOption); ok {
option = &e
break
}
}
if option == nil {
return fmt.Errorf("cannot use entire disk for datastore for name %#v", cmd.DiskCanonicalName)
}
spec := *option.Spec.(*types.VmfsDatastoreCreateSpec)
spec.Vmfs.VolumeName = cmd.Name
_, err = ds.CreateVmfsDatastore(ctx, spec)
if err != nil {
return err
}
}
return nil
}

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -20,6 +20,8 @@ import (
"errors" "errors"
"flag" "flag"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/soap" "github.com/vmware/govmomi/vim25/soap"
@ -33,26 +35,29 @@ func init() {
cli.Register("datastore.download", &download{}) cli.Register("datastore.download", &download{})
} }
func (cmd *download) Register(f *flag.FlagSet) {} func (cmd *download) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
}
func (cmd *download) Process() error { return nil } func (cmd *download) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *download) Usage() string { func (cmd *download) Usage() string {
return "REMOTE LOCAL" return "REMOTE LOCAL"
} }
func (cmd *download) Run(f *flag.FlagSet) error { func (cmd *download) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args() args := f.Args()
if len(args) != 2 { if len(args) != 2 {
return errors.New("invalid arguments") return errors.New("invalid arguments")
} }
c, err := cmd.Client() ds, err := cmd.Datastore()
if err != nil {
return err
}
u, err := cmd.DatastoreURL(args[0])
if err != nil { if err != nil {
return err return err
} }
@ -64,5 +69,5 @@ func (cmd *download) Run(f *flag.FlagSet) error {
defer logger.Wait() defer logger.Wait()
} }
return c.Client.DownloadFile(args[1], u, &p) return ds.DownloadFile(context.TODO(), args[0], args[1], &p)
} }

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -25,6 +25,7 @@ import (
"github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/property" "github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types" "github.com/vmware/govmomi/vim25/types"
@ -41,22 +42,40 @@ func init() {
cli.Register("datastore.info", &info{}) cli.Register("datastore.info", &info{})
} }
func (cmd *info) Register(f *flag.FlagSet) {} func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
func (cmd *info) Process() error { return nil } cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
}
func (cmd *info) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *info) Usage() string { func (cmd *info) Usage() string {
return "[PATH]..." return "[PATH]..."
} }
func (cmd *info) Run(f *flag.FlagSet) error { func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client() c, err := cmd.Client()
if err != nil { if err != nil {
return err return err
} }
ctx := context.TODO()
finder, err := cmd.Finder() finder, err := cmd.Finder()
if err != nil { if err != nil {
return err return err
@ -67,16 +86,6 @@ func (cmd *info) Run(f *flag.FlagSet) error {
args = []string{"*"} args = []string{"*"}
} }
datastores, err := finder.DatastoreList(ctx, args[0])
if err != nil {
return err
}
refs := make([]types.ManagedObjectReference, 0, len(datastores))
for _, ds := range datastores {
refs = append(refs, ds.Reference())
}
var res infoResult var res infoResult
var props []string var props []string
@ -86,10 +95,25 @@ func (cmd *info) Run(f *flag.FlagSet) error {
props = []string{"info", "summary"} // Load summary props = []string{"info", "summary"} // Load summary
} }
pc := property.DefaultCollector(c) for _, arg := range args {
err = pc.Retrieve(ctx, refs, props, &res.Datastores) objects, err := finder.DatastoreList(ctx, arg)
if err != nil { if err != nil {
return err return err
}
res.objects = append(res.objects, objects...)
}
if len(res.objects) != 0 {
refs := make([]types.ManagedObjectReference, 0, len(res.objects))
for _, o := range res.objects {
refs = append(refs, o.Reference())
}
pc := property.DefaultCollector(c)
err = pc.Retrieve(ctx, refs, props, &res.Datastores)
if err != nil {
return err
}
} }
return cmd.WriteResult(&res) return cmd.WriteResult(&res)
@ -97,14 +121,23 @@ func (cmd *info) Run(f *flag.FlagSet) error {
type infoResult struct { type infoResult struct {
Datastores []mo.Datastore Datastores []mo.Datastore
objects []*object.Datastore
} }
func (r *infoResult) Write(w io.Writer) error { func (r *infoResult) Write(w io.Writer) error {
// Maintain order via r.objects as Property collector does not always return results in order.
objects := make(map[types.ManagedObjectReference]mo.Datastore, len(r.Datastores))
for _, o := range r.Datastores {
objects[o.Reference()] = o
}
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0) tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
for _, ds := range r.Datastores { for _, o := range r.objects {
ds := objects[o.Reference()]
s := ds.Summary s := ds.Summary
fmt.Fprintf(tw, "Name:\t%s\n", s.Name) fmt.Fprintf(tw, "Name:\t%s\n", s.Name)
fmt.Fprintf(tw, " Path:\t%s\n", o.InventoryPath)
fmt.Fprintf(tw, " Type:\t%s\n", s.Type) fmt.Fprintf(tw, " Type:\t%s\n", s.Type)
fmt.Fprintf(tw, " URL:\t%s\n", s.Url) fmt.Fprintf(tw, " URL:\t%s\n", s.Url)
fmt.Fprintf(tw, " Capacity:\t%.1f GB\n", float64(s.Capacity)/(1<<30)) fmt.Fprintf(tw, " Capacity:\t%.1f GB\n", float64(s.Capacity)/(1<<30))

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -36,24 +36,42 @@ type ls struct {
*flags.DatastoreFlag *flags.DatastoreFlag
*flags.OutputFlag *flags.OutputFlag
long bool long bool
slash bool
all bool
} }
func init() { func init() {
cli.Register("datastore.ls", &ls{}) cli.Register("datastore.ls", &ls{})
} }
func (cmd *ls) Register(f *flag.FlagSet) { func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
f.BoolVar(&cmd.long, "l", false, "Long listing format") f.BoolVar(&cmd.long, "l", false, "Long listing format")
f.BoolVar(&cmd.slash, "p", false, "Write a slash (`/') after each filename if that file is a directory")
f.BoolVar(&cmd.all, "a", false, "Include entries whose names begin with a dot (.)")
} }
func (cmd *ls) Process() error { return nil } func (cmd *ls) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *ls) Usage() string { func (cmd *ls) Usage() string {
return "[FILE]..." return "[FILE]..."
} }
func (cmd *ls) Run(f *flag.FlagSet) error { func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
ds, err := cmd.Datastore() ds, err := cmd.Datastore()
if err != nil { if err != nil {
return err return err
@ -70,8 +88,8 @@ func (cmd *ls) Run(f *flag.FlagSet) error {
} }
result := &listOutput{ result := &listOutput{
rs: make([]types.HostDatastoreBrowserSearchResults, 0), rs: make([]types.HostDatastoreBrowserSearchResults, 0),
long: cmd.long, cmd: cmd,
} }
for _, arg := range args { for _, arg := range args {
@ -137,12 +155,29 @@ func (cmd *ls) ListPath(b *object.HostDatastoreBrowser, path string, spec types.
} }
type listOutput struct { type listOutput struct {
rs []types.HostDatastoreBrowserSearchResults rs []types.HostDatastoreBrowserSearchResults
long bool cmd *ls
} }
func (o *listOutput) add(r types.HostDatastoreBrowserSearchResults) { func (o *listOutput) add(r types.HostDatastoreBrowserSearchResults) {
o.rs = append(o.rs, r) res := r
res.File = nil
for _, f := range r.File {
if f.GetFileInfo().Path[0] == '.' && !o.cmd.all {
continue
}
if o.cmd.slash {
if d, ok := f.(*types.FolderFileInfo); ok {
d.Path += "/"
}
}
res.File = append(res.File, f)
}
o.rs = append(o.rs, res)
} }
// hasMultiplePaths returns whether or not the slice of search results contains // hasMultiplePaths returns whether or not the slice of search results contains
@ -185,7 +220,7 @@ func (o *listOutput) Write(w io.Writer) error {
} }
for _, file := range r.File { for _, file := range r.File {
info := file.GetFileInfo() info := file.GetFileInfo()
if o.long { if o.cmd.long {
fmt.Fprintf(tw, "%s\t%s\t%s\n", units.ByteSize(info.FileSize), info.Modification.Format("Mon Jan 2 15:04:05 2006"), info.Path) fmt.Fprintf(tw, "%s\t%s\t%s\n", units.ByteSize(info.FileSize), info.Modification.Format("Mon Jan 2 15:04:05 2006"), info.Path)
} else { } else {
fmt.Fprintf(tw, "%s\n", info.Path) fmt.Fprintf(tw, "%s\n", info.Path)

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -38,17 +38,25 @@ func init() {
cli.Register("datastore.mkdir", &mkdir{}) cli.Register("datastore.mkdir", &mkdir{})
} }
func (cmd *mkdir) Register(f *flag.FlagSet) { func (cmd *mkdir) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
f.BoolVar(&cmd.createParents, "p", false, "Create intermediate directories as needed") f.BoolVar(&cmd.createParents, "p", false, "Create intermediate directories as needed")
} }
func (cmd *mkdir) Process() error { return nil } func (cmd *mkdir) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *mkdir) Usage() string { func (cmd *mkdir) Usage() string {
return "DIRECTORY" return "DIRECTORY"
} }
func (cmd *mkdir) Run(f *flag.FlagSet) error { func (cmd *mkdir) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args() args := f.Args()
if len(args) == 0 { if len(args) == 0 {
return errors.New("missing operand") return errors.New("missing operand")

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -36,17 +36,25 @@ func init() {
cli.Register("datastore.mv", &mv{}) cli.Register("datastore.mv", &mv{})
} }
func (cmd *mv) Register(f *flag.FlagSet) { func (cmd *mv) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
f.BoolVar(&cmd.force, "f", false, "If true, overwrite any identically named file at the destination") f.BoolVar(&cmd.force, "f", false, "If true, overwrite any identically named file at the destination")
} }
func (cmd *mv) Process() error { return nil } func (cmd *mv) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *mv) Usage() string { func (cmd *mv) Usage() string {
return "SRC DST" return "SRC DST"
} }
func (cmd *mv) Run(f *flag.FlagSet) error { func (cmd *mv) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args() args := f.Args()
if len(args) != 2 { if len(args) != 2 {
return errors.New("SRC and DST arguments are required") return errors.New("SRC and DST arguments are required")

View File

@ -0,0 +1,90 @@
/*
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 datastore
import (
"flag"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type remove struct {
*flags.HostSystemFlag
*flags.DatastoreFlag
}
func init() {
cli.Register("datastore.remove", &remove{})
}
func (cmd *remove) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
}
func (cmd *remove) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *remove) Usage() string {
return "HOST..."
}
func (cmd *remove) Description() string {
return `Remove datastore from HOST.
Example:
govc datastore.remove -ds nfsDatastore cluster1
`
}
func (cmd *remove) Run(ctx context.Context, f *flag.FlagSet) error {
ds, err := cmd.Datastore()
if err != nil {
return err
}
hosts, err := cmd.HostSystems(f.Args())
if err != nil {
return err
}
for _, host := range hosts {
hds, err := host.ConfigManager().DatastoreSystem(ctx)
if err != nil {
return err
}
err = hds.Remove(ctx, ds)
if err != nil {
return err
}
}
return nil
}

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -38,17 +38,25 @@ func init() {
cli.Alias("datastore.rm", "datastore.delete") cli.Alias("datastore.rm", "datastore.delete")
} }
func (cmd *rm) Register(f *flag.FlagSet) { func (cmd *rm) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
f.BoolVar(&cmd.force, "f", false, "Force; ignore nonexistent files and arguments") f.BoolVar(&cmd.force, "f", false, "Force; ignore nonexistent files and arguments")
} }
func (cmd *rm) Process() error { return nil } func (cmd *rm) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *rm) Usage() string { func (cmd *rm) Usage() string {
return "FILE" return "FILE"
} }
func (cmd *rm) Run(f *flag.FlagSet) error { func (cmd *rm) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args() args := f.Args()
if len(args) == 0 { if len(args) == 0 {
return errors.New("missing operand") return errors.New("missing operand")

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -20,6 +20,8 @@ import (
"errors" "errors"
"flag" "flag"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/soap" "github.com/vmware/govmomi/vim25/soap"
@ -34,26 +36,35 @@ func init() {
cli.Register("datastore.upload", &upload{}) cli.Register("datastore.upload", &upload{})
} }
func (cmd *upload) Register(f *flag.FlagSet) {} func (cmd *upload) Register(ctx context.Context, f *flag.FlagSet) {
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
func (cmd *upload) Process() error { return nil } cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
}
func (cmd *upload) Process(ctx context.Context) error {
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *upload) Usage() string { func (cmd *upload) Usage() string {
return "LOCAL REMOTE" return "LOCAL REMOTE"
} }
func (cmd *upload) Run(f *flag.FlagSet) error { func (cmd *upload) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args() args := f.Args()
if len(args) != 2 { if len(args) != 2 {
return errors.New("invalid arguments") return errors.New("invalid arguments")
} }
c, err := cmd.Client() ds, err := cmd.Datastore()
if err != nil {
return err
}
u, err := cmd.DatastoreURL(args[1])
if err != nil { if err != nil {
return err return err
} }
@ -65,5 +76,5 @@ func (cmd *upload) Run(f *flag.FlagSet) error {
defer logger.Wait() defer logger.Wait()
} }
return c.Client.UploadFile(args[0], u, &p) return ds.UploadFile(context.TODO(), args[0], args[1], &p)
} }

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -37,7 +37,10 @@ func init() {
cli.Register("device.boot", &boot{}) cli.Register("device.boot", &boot{})
} }
func (cmd *boot) Register(f *flag.FlagSet) { func (cmd *boot) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.Int64Var(&cmd.BootDelay, "delay", 0, "Delay in ms before starting the boot sequence") f.Int64Var(&cmd.BootDelay, "delay", 0, "Delay in ms before starting the boot sequence")
f.StringVar(&cmd.order, "order", "", "Boot device order") f.StringVar(&cmd.order, "order", "", "Boot device order")
f.Int64Var(&cmd.BootRetryDelay, "retry-delay", 0, "Delay in ms before a boot retry") f.Int64Var(&cmd.BootRetryDelay, "retry-delay", 0, "Delay in ms before a boot retry")
@ -49,9 +52,14 @@ func (cmd *boot) Register(f *flag.FlagSet) {
f.BoolVar(cmd.EnterBIOSSetup, "setup", false, "If true, enter BIOS setup on next boot") f.BoolVar(cmd.EnterBIOSSetup, "setup", false, "If true, enter BIOS setup on next boot")
} }
func (cmd *boot) Process() error { return nil } func (cmd *boot) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *boot) Run(f *flag.FlagSet) error { func (cmd *boot) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine() vm, err := cmd.VirtualMachine()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -35,13 +35,21 @@ func init() {
cli.Register("device.cdrom.add", &add{}) cli.Register("device.cdrom.add", &add{})
} }
func (cmd *add) Register(f *flag.FlagSet) { func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.StringVar(&cmd.controller, "controller", "", "IDE controller name") f.StringVar(&cmd.controller, "controller", "", "IDE controller name")
} }
func (cmd *add) Process() error { return nil } func (cmd *add) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Run(f *flag.FlagSet) error { func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine() vm, err := cmd.VirtualMachine()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -34,11 +34,19 @@ func init() {
cli.Register("device.cdrom.eject", &eject{}) cli.Register("device.cdrom.eject", &eject{})
} }
func (cmd *eject) Register(f *flag.FlagSet) { func (cmd *eject) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.StringVar(&cmd.device, "device", "", "CD-ROM device name") f.StringVar(&cmd.device, "device", "", "CD-ROM device name")
} }
func (cmd *eject) Process() error { return nil } func (cmd *eject) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *eject) Description() string { func (cmd *eject) Description() string {
return `Eject media from CD-ROM device. return `Eject media from CD-ROM device.
@ -46,7 +54,7 @@ func (cmd *eject) Description() string {
If device is not specified, the first CD-ROM device is used.` If device is not specified, the first CD-ROM device is used.`
} }
func (cmd *eject) Run(f *flag.FlagSet) error { func (cmd *eject) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine() vm, err := cmd.VirtualMachine()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -35,11 +35,24 @@ func init() {
cli.Register("device.cdrom.insert", &insert{}) cli.Register("device.cdrom.insert", &insert{})
} }
func (cmd *insert) Register(f *flag.FlagSet) { func (cmd *insert) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.StringVar(&cmd.device, "device", "", "CD-ROM device name") f.StringVar(&cmd.device, "device", "", "CD-ROM device name")
} }
func (cmd *insert) Process() error { return nil } func (cmd *insert) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *insert) Usage() string { func (cmd *insert) Usage() string {
return "ISO" return "ISO"
@ -51,7 +64,7 @@ func (cmd *insert) Description() string {
If device is not specified, the first CD-ROM device is used.` If device is not specified, the first CD-ROM device is used.`
} }
func (cmd *insert) Run(f *flag.FlagSet) error { func (cmd *insert) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine() vm, err := cmd.VirtualMachine()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -33,15 +33,23 @@ func init() {
cli.Register("device.connect", &connect{}) cli.Register("device.connect", &connect{})
} }
func (cmd *connect) Register(f *flag.FlagSet) {} func (cmd *connect) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
}
func (cmd *connect) Process() error { return nil } func (cmd *connect) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *connect) Usage() string { func (cmd *connect) Usage() string {
return "DEVICE..." return "DEVICE..."
} }
func (cmd *connect) Run(f *flag.FlagSet) error { func (cmd *connect) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine() vm, err := cmd.VirtualMachine()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -33,15 +33,23 @@ func init() {
cli.Register("device.disconnect", &disconnect{}) cli.Register("device.disconnect", &disconnect{})
} }
func (cmd *disconnect) Register(f *flag.FlagSet) {} func (cmd *disconnect) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
}
func (cmd *disconnect) Process() error { return nil } func (cmd *disconnect) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *disconnect) Usage() string { func (cmd *disconnect) Usage() string {
return "DEVICE..." return "DEVICE..."
} }
func (cmd *disconnect) Run(f *flag.FlagSet) error { func (cmd *disconnect) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine() vm, err := cmd.VirtualMachine()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -33,11 +33,19 @@ func init() {
cli.Register("device.floppy.add", &add{}) cli.Register("device.floppy.add", &add{})
} }
func (cmd *add) Register(f *flag.FlagSet) {} func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
}
func (cmd *add) Process() error { return nil } func (cmd *add) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Run(f *flag.FlagSet) error { func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine() vm, err := cmd.VirtualMachine()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -34,11 +34,19 @@ func init() {
cli.Register("device.floppy.eject", &eject{}) cli.Register("device.floppy.eject", &eject{})
} }
func (cmd *eject) Register(f *flag.FlagSet) { func (cmd *eject) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.StringVar(&cmd.device, "device", "", "Floppy device name") f.StringVar(&cmd.device, "device", "", "Floppy device name")
} }
func (cmd *eject) Process() error { return nil } func (cmd *eject) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *eject) Description() string { func (cmd *eject) Description() string {
return `Eject image from floppy device. return `Eject image from floppy device.
@ -46,7 +54,7 @@ func (cmd *eject) Description() string {
If device is not specified, the first floppy device is used.` If device is not specified, the first floppy device is used.`
} }
func (cmd *eject) Run(f *flag.FlagSet) error { func (cmd *eject) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine() vm, err := cmd.VirtualMachine()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -35,11 +35,24 @@ func init() {
cli.Register("device.floppy.insert", &insert{}) cli.Register("device.floppy.insert", &insert{})
} }
func (cmd *insert) Register(f *flag.FlagSet) { func (cmd *insert) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.StringVar(&cmd.device, "device", "", "Floppy device name") f.StringVar(&cmd.device, "device", "", "Floppy device name")
} }
func (cmd *insert) Process() error { return nil } func (cmd *insert) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *insert) Usage() string { func (cmd *insert) Usage() string {
return "IMG" return "IMG"
@ -51,7 +64,7 @@ func (cmd *insert) Description() string {
If device is not specified, the first floppy device is used.` If device is not specified, the first floppy device is used.`
} }
func (cmd *insert) Run(f *flag.FlagSet) error { func (cmd *insert) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine() vm, err := cmd.VirtualMachine()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -19,33 +19,50 @@ package device
import ( import (
"flag" "flag"
"fmt" "fmt"
"io"
"os" "os"
"strings" "strings"
"text/tabwriter" "text/tabwriter"
"github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types" "github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
type info struct { type info struct {
*flags.VirtualMachineFlag *flags.VirtualMachineFlag
*flags.OutputFlag
} }
func init() { func init() {
cli.Register("device.info", &info{}) cli.Register("device.info", &info{})
} }
func (cmd *info) Register(f *flag.FlagSet) {} func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
func (cmd *info) Process() error { return nil } cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
func (cmd *info) Usage() string {
return "DEVICE..."
} }
func (cmd *info) Run(f *flag.FlagSet) error { func (cmd *info) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *info) Usage() string {
return "[DEVICE]..."
}
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine() vm, err := cmd.VirtualMachine()
if err != nil { if err != nil {
return err return err
@ -60,19 +77,41 @@ func (cmd *info) Run(f *flag.FlagSet) error {
return err return err
} }
res := infoResult{
list: devices,
}
if f.NArg() == 0 {
res.Devices = devices
} else {
for _, name := range f.Args() {
device := devices.Find(name)
if device == nil {
return fmt.Errorf("device '%s' not found", name)
}
res.Devices = append(res.Devices, device)
}
}
return cmd.WriteResult(&res)
}
type infoResult struct {
Devices object.VirtualDeviceList
// need the full list of devices to lookup attached devices and controllers
list object.VirtualDeviceList
}
func (r *infoResult) Write(w io.Writer) error {
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0) tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
for _, name := range f.Args() { for _, device := range r.Devices {
device := devices.Find(name)
if device == nil {
return fmt.Errorf("device '%s' not found", name)
}
d := device.GetVirtualDevice() d := device.GetVirtualDevice()
info := d.DeviceInfo.GetDescription() info := d.DeviceInfo.GetDescription()
fmt.Fprintf(tw, "Name:\t%s\n", name) fmt.Fprintf(tw, "Name:\t%s\n", r.Devices.Name(device))
fmt.Fprintf(tw, " Type:\t%s\n", devices.TypeName(device)) fmt.Fprintf(tw, " Type:\t%s\n", r.Devices.TypeName(device))
fmt.Fprintf(tw, " Label:\t%s\n", info.Label) fmt.Fprintf(tw, " Label:\t%s\n", info.Label)
fmt.Fprintf(tw, " Summary:\t%s\n", info.Summary) fmt.Fprintf(tw, " Summary:\t%s\n", info.Summary)
fmt.Fprintf(tw, " Key:\t%d\n", d.Key) fmt.Fprintf(tw, " Key:\t%d\n", d.Key)
@ -80,12 +119,12 @@ func (cmd *info) Run(f *flag.FlagSet) error {
if c, ok := device.(types.BaseVirtualController); ok { if c, ok := device.(types.BaseVirtualController); ok {
var attached []string var attached []string
for _, key := range c.GetVirtualController().Device { for _, key := range c.GetVirtualController().Device {
attached = append(attached, devices.Name(devices.FindByKey(key))) attached = append(attached, r.Devices.Name(r.list.FindByKey(key)))
} }
fmt.Fprintf(tw, " Devices:\t%s\n", strings.Join(attached, ", ")) fmt.Fprintf(tw, " Devices:\t%s\n", strings.Join(attached, ", "))
} else { } else {
if c := devices.FindByKey(d.ControllerKey); c != nil { if c := r.list.FindByKey(d.ControllerKey); c != nil {
fmt.Fprintf(tw, " Controller:\t%s\n", devices.Name(c)) fmt.Fprintf(tw, " Controller:\t%s\n", r.Devices.Name(c))
fmt.Fprintf(tw, " Unit number:\t%d\n", d.UnitNumber) fmt.Fprintf(tw, " Unit number:\t%d\n", d.UnitNumber)
} }
} }
@ -108,6 +147,12 @@ func (cmd *info) Run(f *flag.FlagSet) error {
if b, ok := md.Backing.(*types.VirtualDiskFlatVer2BackingInfo); ok && b.Parent != nil { if b, ok := md.Backing.(*types.VirtualDiskFlatVer2BackingInfo); ok && b.Parent != nil {
fmt.Fprintf(tw, " Parent:\t%s\n", b.Parent.GetVirtualDeviceFileBackingInfo().FileName) fmt.Fprintf(tw, " Parent:\t%s\n", b.Parent.GetVirtualDeviceFileBackingInfo().FileName)
} }
case *types.VirtualSerialPort:
if b, ok := md.Backing.(*types.VirtualSerialPortURIBackingInfo); ok {
fmt.Fprintf(tw, " Direction:\t%s\n", b.Direction)
fmt.Fprintf(tw, " Service URI:\t%s\n", b.ServiceURI)
fmt.Fprintf(tw, " Proxy URI:\t%s\n", b.ProxyURI)
}
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -37,13 +37,21 @@ func init() {
cli.Register("device.ls", &ls{}) cli.Register("device.ls", &ls{})
} }
func (cmd *ls) Register(f *flag.FlagSet) { func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.BoolVar(&cmd.boot, "boot", false, "List devices configured in the VM's boot options") f.BoolVar(&cmd.boot, "boot", false, "List devices configured in the VM's boot options")
} }
func (cmd *ls) Process() error { return nil } func (cmd *ls) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *ls) Run(f *flag.FlagSet) error { func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine() vm, err := cmd.VirtualMachine()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -33,15 +33,23 @@ func init() {
cli.Register("device.remove", &remove{}) cli.Register("device.remove", &remove{})
} }
func (cmd *remove) Register(f *flag.FlagSet) {} func (cmd *remove) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
}
func (cmd *remove) Process() error { return nil } func (cmd *remove) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *remove) Usage() string { func (cmd *remove) Usage() string {
return "DEVICE..." return "DEVICE..."
} }
func (cmd *remove) Run(f *flag.FlagSet) error { func (cmd *remove) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine() vm, err := cmd.VirtualMachine()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -40,7 +40,10 @@ func init() {
cli.Register("device.scsi.add", &add{}) cli.Register("device.scsi.add", &add{})
} }
func (cmd *add) Register(f *flag.FlagSet) { func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
var ctypes []string var ctypes []string
ct := object.SCSIControllerTypes() ct := object.SCSIControllerTypes()
for _, t := range ct { for _, t := range ct {
@ -52,9 +55,14 @@ func (cmd *add) Register(f *flag.FlagSet) {
f.BoolVar(&cmd.hotAddRemove, "hot", false, "Enable hot-add/remove") f.BoolVar(&cmd.hotAddRemove, "hot", false, "Enable hot-add/remove")
} }
func (cmd *add) Process() error { return nil } func (cmd *add) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Run(f *flag.FlagSet) error { func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine() vm, err := cmd.VirtualMachine()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -33,11 +33,19 @@ func init() {
cli.Register("device.serial.add", &add{}) cli.Register("device.serial.add", &add{})
} }
func (cmd *add) Register(f *flag.FlagSet) {} func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
}
func (cmd *add) Process() error { return nil } func (cmd *add) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Run(f *flag.FlagSet) error { func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine() vm, err := cmd.VirtualMachine()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -11,6 +11,8 @@ Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
@ -35,14 +37,22 @@ func init() {
cli.Register("device.serial.connect", &connect{}) cli.Register("device.serial.connect", &connect{})
} }
func (cmd *connect) Register(f *flag.FlagSet) { func (cmd *connect) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.StringVar(&cmd.device, "device", "", "serial port device name") f.StringVar(&cmd.device, "device", "", "serial port device name")
f.BoolVar(&cmd.client, "client", false, "Use client direction") f.BoolVar(&cmd.client, "client", false, "Use client direction")
} }
func (cmd *connect) Process() error { return nil } func (cmd *connect) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *connect) Run(f *flag.FlagSet) error { func (cmd *connect) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine() vm, err := cmd.VirtualMachine()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -34,13 +34,21 @@ func init() {
cli.Register("device.serial.disconnect", &disconnect{}) cli.Register("device.serial.disconnect", &disconnect{})
} }
func (cmd *disconnect) Register(f *flag.FlagSet) { func (cmd *disconnect) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.StringVar(&cmd.device, "device", "", "serial port device name") f.StringVar(&cmd.device, "device", "", "serial port device name")
} }
func (cmd *disconnect) Process() error { return nil } func (cmd *disconnect) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *disconnect) Run(f *flag.FlagSet) error { func (cmd *disconnect) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine() vm, err := cmd.VirtualMachine()
if err != nil { if err != nil {
return err return err

145
vendor/github.com/vmware/govmomi/govc/dvs/add.go generated vendored Normal file
View File

@ -0,0 +1,145 @@
/*
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 dvs
import (
"flag"
"fmt"
"os"
"strings"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type add struct {
*flags.HostSystemFlag
path string
pnic string
}
func init() {
cli.Register("dvs.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
f.StringVar(&cmd.path, "dvs", "", "DVS path")
f.StringVar(&cmd.pnic, "pnic", "vmnic0", "Name of the host physical NIC")
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Usage() string {
return "HOST..."
}
func (cmd *add) Description() string {
return `Add hosts to DVS.`
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() == 0 {
return flag.ErrHelp
}
finder, err := cmd.Finder()
if err != nil {
return err
}
net, err := finder.Network(ctx, cmd.path)
if err != nil {
return err
}
dvs, ok := net.(*object.DistributedVirtualSwitch)
if !ok {
return fmt.Errorf("%s (%T) is not of type %T", cmd.path, net, dvs)
}
var s mo.VmwareDistributedVirtualSwitch
err = dvs.Properties(ctx, dvs.Reference(), []string{"config"}, &s)
if err != nil {
return err
}
backing := new(types.DistributedVirtualSwitchHostMemberPnicBacking)
for _, vmnic := range strings.Split(cmd.pnic, ",") {
backing.PnicSpec = append(backing.PnicSpec, types.DistributedVirtualSwitchHostMemberPnicSpec{
PnicDevice: strings.TrimSpace(vmnic),
})
}
config := &types.DVSConfigSpec{
ConfigVersion: s.Config.GetDVSConfigInfo().ConfigVersion,
}
hosts, err := cmd.HostSystems(f.Args())
if err != nil {
return err
}
existing := make(map[string]bool)
// TODO: host.pnic.info command
for _, member := range s.Config.GetDVSConfigInfo().Host {
existing[member.Config.Host.Value] = true
}
for _, host := range hosts {
ref := host.Reference()
if existing[ref.Value] {
fmt.Fprintf(os.Stderr, "%s is already a member of %s\n", host.InventoryPath, dvs.InventoryPath)
continue
}
config.Host = append(config.Host, types.DistributedVirtualSwitchHostMemberConfigSpec{
Operation: "add",
Host: ref,
Backing: backing,
})
}
if len(config.Host) == 0 {
return nil
}
task, err := dvs.Reconfigure(ctx, config)
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("adding %d hosts to dvs %s... ", len(config.Host), dvs.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}

119
vendor/github.com/vmware/govmomi/govc/dvs/create.go generated vendored Normal file
View File

@ -0,0 +1,119 @@
/*
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 dvs
import (
"flag"
"fmt"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
)
type create struct {
*flags.DatacenterFlag
types.DVSCreateSpec
configSpec *types.VMwareDVSConfigSpec
parent string
}
func init() {
cli.Register("dvs.create", &create{})
}
func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
cmd.configSpec = new(types.VMwareDVSConfigSpec)
cmd.DVSCreateSpec.ConfigSpec = cmd.configSpec
f.StringVar(&cmd.parent, "parent", "", "Path to parent folder for the new dvs")
}
func (cmd *create) Usage() string {
return "DVS"
}
func (cmd *create) Description() string {
return `Create DVS (DistributedVirtualSwitch) in datacenter.
The dvs is added to the folder specified by the 'parent' flag. If not given,
this defaults to the network folder in the specified or default datacenter.`
}
func (cmd *create) Process(ctx context.Context) error {
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
var parent *object.Folder
if f.NArg() != 1 {
return flag.ErrHelp
}
name := f.Arg(0)
if cmd.parent == "" {
dc, err := cmd.Datacenter()
if err != nil {
return err
}
folders, err := dc.Folders(ctx)
if err != nil {
return err
}
parent = folders.NetworkFolder
} else {
finder, err := cmd.Finder()
if err != nil {
return err
}
parent, err = finder.Folder(ctx, cmd.parent)
if err != nil {
return err
}
}
cmd.configSpec.Name = name
task, err := parent.CreateDVS(ctx, cmd.DVSCreateSpec)
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("adding %s to folder %s... ", name, parent.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}

View File

@ -0,0 +1,107 @@
/*
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 portgroup
import (
"flag"
"fmt"
"strings"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
)
type add struct {
*flags.DatacenterFlag
types.DVPortgroupConfigSpec
path string
}
func init() {
cli.Register("dvs.portgroup.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
f.StringVar(&cmd.path, "dvs", "", "DVS path")
ptypes := []string{
string(types.DistributedVirtualPortgroupPortgroupTypeEarlyBinding),
string(types.DistributedVirtualPortgroupPortgroupTypeLateBinding),
string(types.DistributedVirtualPortgroupPortgroupTypeEphemeral),
}
f.StringVar(&cmd.DVPortgroupConfigSpec.Type, "type", ptypes[0],
fmt.Sprintf("Portgroup type (%s)", strings.Join(ptypes, "|")))
f.IntVar(&cmd.DVPortgroupConfigSpec.NumPorts, "nports", 128, "Number of ports")
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Usage() string {
return "NAME"
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() == 0 {
return flag.ErrHelp
}
name := f.Arg(0)
finder, err := cmd.Finder()
if err != nil {
return err
}
net, err := finder.Network(ctx, cmd.path)
if err != nil {
return err
}
dvs, ok := net.(*object.DistributedVirtualSwitch)
if !ok {
return fmt.Errorf("%s (%T) is not of type %T", cmd.path, net, dvs)
}
cmd.DVPortgroupConfigSpec.Name = name
task, err := dvs.AddPortgroup(ctx, []types.DVPortgroupConfigSpec{cmd.DVPortgroupConfigSpec})
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("adding %s portgroup to dvs %s... ", name, dvs.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -21,13 +21,11 @@ import (
"fmt" "fmt"
"os" "os"
"strings" "strings"
"text/tabwriter"
"time" "time"
"github.com/vmware/govmomi/event" "github.com/vmware/govmomi/event"
"github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/list"
"github.com/vmware/govmomi/vim25/types" "github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
@ -42,24 +40,25 @@ func init() {
cli.Register("events", &events{}) cli.Register("events", &events{})
} }
func (cmd *events) Register(f *flag.FlagSet) { func (cmd *events) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
f.IntVar(&cmd.Max, "n", 25, "Output the last N events") f.IntVar(&cmd.Max, "n", 25, "Output the last N events")
} }
func (cmd *events) Process() error { return nil } func (cmd *events) Process(ctx context.Context) error {
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *events) Usage() string { func (cmd *events) Usage() string {
return "[PATH]..." return "[PATH]..."
} }
func (cmd *events) Run(f *flag.FlagSet) error { func (cmd *events) Run(ctx context.Context, f *flag.FlagSet) error {
ctx := context.TODO()
finder, err := cmd.Finder()
if err != nil {
return err
}
c, err := cmd.Client() c, err := cmd.Client()
if err != nil { if err != nil {
return err return err
@ -67,20 +66,9 @@ func (cmd *events) Run(f *flag.FlagSet) error {
m := event.NewManager(c) m := event.NewManager(c)
var objs []list.Element objs, err := cmd.ManagedObjects(ctx, f.Args())
if err != nil {
args := f.Args() return err
if len(args) == 0 {
args = []string{"."}
}
for _, arg := range args {
es, err := finder.ManagedObjectList(ctx, arg)
if err != nil {
return err
}
objs = append(objs, es...)
} }
var events []types.BaseEvent var events []types.BaseEvent
@ -88,14 +76,14 @@ func (cmd *events) Run(f *flag.FlagSet) error {
for _, o := range objs { for _, o := range objs {
filter := types.EventFilterSpec{ filter := types.EventFilterSpec{
Entity: &types.EventFilterSpecByEntity{ Entity: &types.EventFilterSpecByEntity{
Entity: o.Object.Reference(), Entity: o,
Recursion: types.EventFilterSpecRecursionOptionAll, Recursion: types.EventFilterSpecRecursionOptionAll,
}, },
} }
collector, err := m.CreateCollectorForEvents(ctx, filter) collector, err := m.CreateCollectorForEvents(ctx, filter)
if err != nil { if err != nil {
return fmt.Errorf("[%s] %s", o.Path, err) return fmt.Errorf("[%#v] %s", o, err)
} }
defer collector.Destroy(ctx) defer collector.Destroy(ctx)
@ -114,8 +102,6 @@ func (cmd *events) Run(f *flag.FlagSet) error {
event.Sort(events) event.Sort(events)
tw := tabwriter.NewWriter(os.Stdout, 3, 0, 2, ' ', 0)
for _, e := range events { for _, e := range events {
cat, err := m.EventCategory(ctx, e) cat, err := m.EventCategory(ctx, e)
if err != nil { if err != nil {
@ -129,10 +115,10 @@ func (cmd *events) Run(f *flag.FlagSet) error {
msg = fmt.Sprintf("%s (target=%s %s)", msg, t.Info.Entity.Type, t.Info.EntityName) msg = fmt.Sprintf("%s (target=%s %s)", msg, t.Info.Entity.Type, t.Info.EntityName)
} }
fmt.Fprintf(tw, "[%s]\t[%s]\t%s\n", fmt.Fprintf(os.Stdout, "[%s] [%s] %s\n",
event.CreatedTime.Local().Format(time.ANSIC), event.CreatedTime.Local().Format(time.ANSIC),
cat, msg) cat, msg)
} }
return tw.Flush() return nil
} }

121
vendor/github.com/vmware/govmomi/govc/extension/info.go generated vendored Normal file
View File

@ -0,0 +1,121 @@
/*
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 extension
import (
"flag"
"fmt"
"io"
"os"
"text/tabwriter"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
)
type info struct {
*flags.ClientFlag
*flags.OutputFlag
}
func init() {
cli.Register("extension.info", &info{})
}
func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
}
func (cmd *info) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *info) Usage() string {
return "[KEY]..."
}
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetExtensionManager(c)
if err != nil {
return err
}
list, err := m.List(ctx)
if err != nil {
return err
}
var res infoResult
if f.NArg() == 0 {
res.Extensions = list
} else {
exts := make(map[string]types.Extension)
for _, e := range list {
exts[e.Key] = e
}
for _, key := range f.Args() {
if e, ok := exts[key]; ok {
res.Extensions = append(res.Extensions, e)
} else {
return fmt.Errorf("extension %s not found", key)
}
}
}
return cmd.WriteResult(&res)
}
type infoResult struct {
Extensions []types.Extension
}
func (r *infoResult) Write(w io.Writer) error {
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
for _, e := range r.Extensions {
fmt.Fprintf(tw, "Name:\t%s\n", e.Key)
fmt.Fprintf(tw, " Version:\t%s\n", e.Version)
fmt.Fprintf(tw, " Description:\t%s\n", e.Description.GetDescription().Summary)
fmt.Fprintf(tw, " Company:\t%s\n", e.Company)
fmt.Fprintf(tw, " Last heartbeat time:\t%s\n", e.LastHeartbeatTime)
fmt.Fprintf(tw, " Subject name:\t%s\n", e.SubjectName)
fmt.Fprintf(tw, " Type:\t%s\n", e.Type)
}
return tw.Flush()
}

View File

@ -0,0 +1,81 @@
/*
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 extension
import (
"encoding/json"
"flag"
"os"
"time"
"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 register struct {
*flags.ClientFlag
update bool
}
func init() {
cli.Register("extension.register", &register{})
}
func (cmd *register) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
f.BoolVar(&cmd.update, "update", false, "Update extension")
}
func (cmd *register) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *register) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetExtensionManager(c)
if err != nil {
return err
}
var e types.Extension
e.Description = new(types.Description)
if err = json.NewDecoder(os.Stdin).Decode(&e); err != nil {
return err
}
e.LastHeartbeatTime = time.Now().UTC()
if cmd.update {
return m.Update(ctx, e)
}
return m.Register(ctx, e)
}

View File

@ -0,0 +1,171 @@
/*
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 extension
import (
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"flag"
"fmt"
"io/ioutil"
"math/big"
"os"
"time"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type setcert struct {
*flags.ClientFlag
cert string
org string
encodedCert bytes.Buffer
}
func init() {
cli.Register("extension.setcert", &setcert{})
}
func (cmd *setcert) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
f.StringVar(&cmd.cert, "cert-pem", "-", "PEM encoded certificate")
f.StringVar(&cmd.org, "org", "VMware", "Organization for generated certificate")
}
func (cmd *setcert) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *setcert) Usage() string {
return "ID"
}
func (cmd *setcert) Description() string {
return `The '-cert-pem' option can be one of the following:
'-' : Read the certificate from stdin
'+' : Generate a new key pair and save locally to ID.crt and ID.key
... : Any other value is passed as-is to ExtensionManager.SetCertificate
`
}
func (cmd *setcert) create(id string) error {
certFile, err := os.Create(id + ".crt")
if err != nil {
return err
}
defer certFile.Close()
keyFile, err := os.Create(id + ".key")
if err != nil {
return err
}
defer keyFile.Close()
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return err
}
notBefore := time.Now()
notAfter := notBefore.Add(5 * 365 * 24 * time.Hour) // 5 years
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return err
}
template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{cmd.org},
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
BasicConstraintsValid: true,
}
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
if err != nil {
return err
}
err = pem.Encode(&cmd.encodedCert, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
if err != nil {
return err
}
_, err = certFile.Write(cmd.encodedCert.Bytes())
if err != nil {
return err
}
err = pem.Encode(keyFile, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
if err != nil {
return err
}
return nil
}
func (cmd *setcert) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetExtensionManager(c)
if err != nil {
return err
}
if f.NArg() != 1 {
return flag.ErrHelp
}
key := f.Arg(0)
if cmd.cert == "-" {
b, err := ioutil.ReadAll(os.Stdin)
if err != nil {
return err
}
cmd.cert = string(b)
} else if cmd.cert == "+" {
if err := cmd.create(key); err != nil {
return fmt.Errorf("creating certificate: %s", err)
}
cmd.cert = cmd.encodedCert.String()
}
return m.SetCertificate(ctx, key, cmd.cert)
}

View File

@ -0,0 +1,66 @@
/*
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 extension
import (
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type unregister struct {
*flags.ClientFlag
}
func init() {
cli.Register("extension.unregister", &unregister{})
}
func (cmd *unregister) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
}
func (cmd *unregister) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *unregister) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetExtensionManager(c)
if err != nil {
return err
}
for _, key := range f.Args() {
if err = m.Unregister(ctx, key); err != nil {
return err
}
}
return nil
}

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -34,21 +34,27 @@ func init() {
cli.Register("fields.add", &add{}) cli.Register("fields.add", &add{})
} }
func (cmd *add) Register(f *flag.FlagSet) {} func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
}
func (cmd *add) Process() error { return nil } func (cmd *add) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Usage() string { func (cmd *add) Usage() string {
return "NAME" return "NAME"
} }
func (cmd *add) Run(f *flag.FlagSet) error { func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 1 { if f.NArg() != 1 {
return flag.ErrHelp return flag.ErrHelp
} }
ctx := context.TODO()
c, err := cmd.Client() c, err := cmd.Client()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -36,13 +36,19 @@ func init() {
cli.Register("fields.ls", &ls{}) cli.Register("fields.ls", &ls{})
} }
func (cmd *ls) Register(f *flag.FlagSet) {} func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
}
func (cmd *ls) Process() error { return nil } func (cmd *ls) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
func (cmd *ls) Run(f *flag.FlagSet) error { return err
ctx := context.TODO() }
return nil
}
func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client() c, err := cmd.Client()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -33,21 +33,27 @@ func init() {
cli.Register("fields.rename", &rename{}) cli.Register("fields.rename", &rename{})
} }
func (cmd *rename) Register(f *flag.FlagSet) {} func (cmd *rename) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
}
func (cmd *rename) Process() error { return nil } func (cmd *rename) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *rename) Usage() string { func (cmd *rename) Usage() string {
return "KEY NAME" return "KEY NAME"
} }
func (cmd *rename) Run(f *flag.FlagSet) error { func (cmd *rename) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 2 { if f.NArg() != 2 {
return flag.ErrHelp return flag.ErrHelp
} }
ctx := context.TODO()
c, err := cmd.Client() c, err := cmd.Client()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -33,17 +33,23 @@ func init() {
cli.Register("fields.rm", &rm{}) cli.Register("fields.rm", &rm{})
} }
func (cmd *rm) Register(f *flag.FlagSet) {} func (cmd *rm) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
}
func (cmd *rm) Process() error { return nil } func (cmd *rm) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *rm) Usage() string { func (cmd *rm) Usage() string {
return "KEY..." return "KEY..."
} }
func (cmd *rm) Run(f *flag.FlagSet) error { func (cmd *rm) Run(ctx context.Context, f *flag.FlagSet) error {
ctx := context.TODO()
c, err := cmd.Client() c, err := cmd.Client()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -21,7 +21,6 @@ import (
"github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/list"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
@ -34,26 +33,27 @@ func init() {
cli.Register("fields.set", &set{}) cli.Register("fields.set", &set{})
} }
func (cmd *set) Register(f *flag.FlagSet) {} func (cmd *set) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
}
func (cmd *set) Process() error { return nil } func (cmd *set) Process(ctx context.Context) error {
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *set) Usage() string { func (cmd *set) Usage() string {
return "KEY VALUE PATH..." return "KEY VALUE PATH..."
} }
func (cmd *set) Run(f *flag.FlagSet) error { func (cmd *set) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() < 3 { if f.NArg() < 3 {
return flag.ErrHelp return flag.ErrHelp
} }
ctx := context.TODO()
finder, err := cmd.Finder()
if err != nil {
return err
}
c, err := cmd.Client() c, err := cmd.Client()
if err != nil { if err != nil {
return err return err
@ -64,8 +64,6 @@ func (cmd *set) Run(f *flag.FlagSet) error {
return err return err
} }
var objs []list.Element
args := f.Args() args := f.Args()
key, err := m.FindKey(ctx, args[0]) key, err := m.FindKey(ctx, args[0])
@ -75,17 +73,13 @@ func (cmd *set) Run(f *flag.FlagSet) error {
val := args[1] val := args[1]
for _, arg := range args[2:] { objs, err := cmd.ManagedObjects(ctx, args[2:])
es, err := finder.ManagedObjectList(ctx, arg) if err != nil {
if err != nil { return err
return err
}
objs = append(objs, es...)
} }
for _, ref := range objs { for _, ref := range objs {
err := m.Set(ctx, ref.Object.Reference(), key, val) err := m.Set(ctx, ref, key, val)
if err != nil { if err != nil {
return err return err
} }

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -18,6 +18,7 @@ package flags
import ( import (
"crypto/sha1" "crypto/sha1"
"crypto/tls"
"encoding/json" "encoding/json"
"errors" "errors"
"flag" "flag"
@ -25,9 +26,7 @@ import (
"net/url" "net/url"
"os" "os"
"path/filepath" "path/filepath"
"regexp"
"strings" "strings"
"sync"
"github.com/vmware/govmomi/session" "github.com/vmware/govmomi/session"
"github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25"
@ -39,6 +38,8 @@ const (
envURL = "GOVC_URL" envURL = "GOVC_URL"
envUsername = "GOVC_USERNAME" envUsername = "GOVC_USERNAME"
envPassword = "GOVC_PASSWORD" envPassword = "GOVC_PASSWORD"
envCertificate = "GOVC_CERTIFICATE"
envPrivateKey = "GOVC_PRIVATE_KEY"
envInsecure = "GOVC_INSECURE" envInsecure = "GOVC_INSECURE"
envPersist = "GOVC_PERSIST_SESSION" envPersist = "GOVC_PERSIST_SESSION"
envMinAPIVersion = "GOVC_MIN_API_VERSION" envMinAPIVersion = "GOVC_MIN_API_VERSION"
@ -47,13 +48,15 @@ const (
const cDescr = "ESX or vCenter URL" const cDescr = "ESX or vCenter URL"
type ClientFlag struct { type ClientFlag struct {
*DebugFlag common
register sync.Once *DebugFlag
url *url.URL url *url.URL
username string username string
password string password string
cert string
key string
insecure bool insecure bool
persist bool persist bool
minAPIVersion string minAPIVersion string
@ -61,6 +64,19 @@ type ClientFlag struct {
client *vim25.Client client *vim25.Client
} }
var clientFlagKey = flagKey("client")
func NewClientFlag(ctx context.Context) (*ClientFlag, context.Context) {
if v := ctx.Value(clientFlagKey); v != nil {
return v.(*ClientFlag), ctx
}
v := &ClientFlag{}
v.DebugFlag, ctx = NewDebugFlag(ctx)
ctx = context.WithValue(ctx, clientFlagKey, v)
return v, ctx
}
func (flag *ClientFlag) URLWithoutPassword() *url.URL { func (flag *ClientFlag) URLWithoutPassword() *url.URL {
if flag.url == nil { if flag.url == nil {
return nil return nil
@ -80,37 +96,18 @@ func (flag *ClientFlag) String() string {
return url.String() return url.String()
} }
var schemeMatch = regexp.MustCompile(`^\w+://`)
func (flag *ClientFlag) Set(s string) error { func (flag *ClientFlag) Set(s string) error {
var err error var err error
if s != "" { flag.url, err = soap.ParseURL(s)
// Default the scheme to https
if !schemeMatch.MatchString(s) {
s = "https://" + s
}
flag.url, err = url.Parse(s) return err
if err != nil {
return err
}
// Default the path to /sdk
if flag.url.Path == "" {
flag.url.Path = "/sdk"
}
if flag.url.User == nil {
flag.url.User = url.UserPassword("", "")
}
}
return nil
} }
func (flag *ClientFlag) Register(f *flag.FlagSet) { func (flag *ClientFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.register.Do(func() { flag.RegisterOnce(func() {
flag.DebugFlag.Register(ctx, f)
{ {
flag.Set(os.Getenv(envURL)) flag.Set(os.Getenv(envURL))
usage := fmt.Sprintf("%s [%s]", cDescr, envURL) usage := fmt.Sprintf("%s [%s]", cDescr, envURL)
@ -122,6 +119,18 @@ func (flag *ClientFlag) Register(f *flag.FlagSet) {
flag.password = os.Getenv(envPassword) flag.password = os.Getenv(envPassword)
} }
{
value := os.Getenv(envCertificate)
usage := fmt.Sprintf("Certificate [%s]", envCertificate)
f.StringVar(&flag.cert, "cert", value, usage)
}
{
value := os.Getenv(envPrivateKey)
usage := fmt.Sprintf("Private key [%s]", envPrivateKey)
f.StringVar(&flag.key, "key", value, usage)
}
{ {
insecure := false insecure := false
switch env := strings.ToLower(os.Getenv(envInsecure)); env { switch env := strings.ToLower(os.Getenv(envInsecure)); env {
@ -155,39 +164,45 @@ func (flag *ClientFlag) Register(f *flag.FlagSet) {
}) })
} }
func (flag *ClientFlag) Process() error { func (flag *ClientFlag) Process(ctx context.Context) error {
if flag.url == nil { return flag.ProcessOnce(func() error {
return errors.New("specify an " + cDescr) if err := flag.DebugFlag.Process(ctx); err != nil {
} return err
// Override username if set
if flag.username != "" {
var password string
var ok bool
if flag.url.User != nil {
password, ok = flag.url.User.Password()
} }
if ok { if flag.url == nil {
flag.url.User = url.UserPassword(flag.username, password) return errors.New("specify an " + cDescr)
} else {
flag.url.User = url.User(flag.username)
}
}
// Override password if set
if flag.password != "" {
var username string
if flag.url.User != nil {
username = flag.url.User.Username()
} }
flag.url.User = url.UserPassword(username, flag.password) // Override username if set
} if flag.username != "" {
var password string
var ok bool
return nil if flag.url.User != nil {
password, ok = flag.url.User.Password()
}
if ok {
flag.url.User = url.UserPassword(flag.username, password)
} else {
flag.url.User = url.User(flag.username)
}
}
// Override password if set
if flag.password != "" {
var username string
if flag.url.User != nil {
username = flag.url.User.Username()
}
flag.url.User = url.UserPassword(username, flag.password)
}
return nil
})
} }
// Retry twice when a temporary I/O error occurs. // Retry twice when a temporary I/O error occurs.
@ -221,11 +236,9 @@ func (flag *ClientFlag) saveClient(c *vim25.Client) error {
if err != nil { if err != nil {
return err return err
} }
defer f.Close() defer f.Close()
enc := json.NewEncoder(f) err = json.NewEncoder(f).Encode(c)
err = enc.Encode(c)
if err != nil { if err != nil {
return err return err
} }
@ -288,6 +301,17 @@ func (flag *ClientFlag) loadClient() (*vim25.Client, error) {
func (flag *ClientFlag) newClient() (*vim25.Client, error) { func (flag *ClientFlag) newClient() (*vim25.Client, error) {
sc := soap.NewClient(flag.url, flag.insecure) sc := soap.NewClient(flag.url, flag.insecure)
isTunnel := false
if flag.cert != "" {
isTunnel = true
cert, err := tls.LoadX509KeyPair(flag.cert, flag.key)
if err != nil {
return nil, err
}
sc.SetCertificate(cert)
}
// Add retry functionality before making any calls // Add retry functionality before making any calls
rt := attachRetries(sc) rt := attachRetries(sc)
@ -300,9 +324,17 @@ func (flag *ClientFlag) newClient() (*vim25.Client, error) {
c.Client = sc c.Client = sc
m := session.NewManager(c) m := session.NewManager(c)
err = m.Login(context.TODO(), flag.url.User) u := flag.url.User
if err != nil { if isTunnel {
return nil, err err = m.LoginExtensionByCertificate(context.TODO(), u.Username(), "")
if err != nil {
return nil, err
}
} else {
err = m.Login(context.TODO(), u)
if err != nil {
return nil, err
}
} }
err = flag.saveClient(c) err = flag.saveClient(c)
@ -316,7 +348,18 @@ func (flag *ClientFlag) newClient() (*vim25.Client, error) {
// apiVersionValid returns whether or not the API version supported by the // apiVersionValid returns whether or not the API version supported by the
// server the client is connected to is not recent enough. // server the client is connected to is not recent enough.
func apiVersionValid(c *vim25.Client, minVersionString string) error { func apiVersionValid(c *vim25.Client, minVersionString string) error {
realVersion, err := ParseVersion(c.ServiceContent.About.ApiVersion) if minVersionString == "-" {
// Disable version check
return nil
}
apiVersion := c.ServiceContent.About.ApiVersion
if strings.HasSuffix(apiVersion, ".x") {
// Skip version check for development builds
return nil
}
realVersion, err := ParseVersion(apiVersion)
if err != nil { if err != nil {
return err return err
} }

23
vendor/github.com/vmware/govmomi/govc/flags/common.go generated vendored Normal file
View File

@ -0,0 +1,23 @@
package flags
import "sync"
// Key type for storing flag instances in a context.Context.
type flagKey string
// Type to help flags out with only registering/processing once.
type common struct {
register sync.Once
process sync.Once
}
func (c *common) RegisterOnce(fn func()) {
c.register.Do(fn)
}
func (c *common) ProcessOnce(fn func() error) (err error) {
c.process.Do(func() {
err = fn()
})
return err
}

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -20,26 +20,44 @@ import (
"flag" "flag"
"fmt" "fmt"
"os" "os"
"sync"
"github.com/vmware/govmomi/find" "github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
type DatacenterFlag struct { type DatacenterFlag struct {
common
*ClientFlag *ClientFlag
*OutputFlag *OutputFlag
register sync.Once path string
path string dc *object.Datacenter
dc *object.Datacenter finder *find.Finder
finder *find.Finder err error
err error
} }
func (flag *DatacenterFlag) Register(f *flag.FlagSet) { var datacenterFlagKey = flagKey("datacenter")
flag.register.Do(func() {
func NewDatacenterFlag(ctx context.Context) (*DatacenterFlag, context.Context) {
if v := ctx.Value(datacenterFlagKey); v != nil {
return v.(*DatacenterFlag), ctx
}
v := &DatacenterFlag{}
v.ClientFlag, ctx = NewClientFlag(ctx)
v.OutputFlag, ctx = NewOutputFlag(ctx)
ctx = context.WithValue(ctx, datacenterFlagKey, v)
return v, ctx
}
func (flag *DatacenterFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.ClientFlag.Register(ctx, f)
flag.OutputFlag.Register(ctx, f)
env := "GOVC_DATACENTER" env := "GOVC_DATACENTER"
value := os.Getenv(env) value := os.Getenv(env)
usage := fmt.Sprintf("Datacenter [%s]", env) usage := fmt.Sprintf("Datacenter [%s]", env)
@ -47,7 +65,17 @@ func (flag *DatacenterFlag) Register(f *flag.FlagSet) {
}) })
} }
func (flag *DatacenterFlag) Process() error { return nil } func (flag *DatacenterFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.ClientFlag.Process(ctx); err != nil {
return err
}
if err := flag.OutputFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (flag *DatacenterFlag) Finder() (*find.Finder, error) { func (flag *DatacenterFlag) Finder() (*find.Finder, error) {
if flag.finder != nil { if flag.finder != nil {
@ -64,12 +92,8 @@ func (flag *DatacenterFlag) Finder() (*find.Finder, error) {
// Datacenter is not required (ls command for example). // Datacenter is not required (ls command for example).
// Set for relative func if dc flag is given or // Set for relative func if dc flag is given or
// if there is a single (default) Datacenter // if there is a single (default) Datacenter
if flag.path == "" { if flag.dc, err = finder.DatacenterOrDefault(context.TODO(), flag.path); err != nil {
flag.dc, flag.err = finder.DefaultDatacenter(context.TODO()) return nil, err
} else {
if flag.dc, err = finder.Datacenter(context.TODO(), flag.path); err != nil {
return nil, err
}
} }
finder.SetDatacenter(flag.dc) finder.SetDatacenter(flag.dc)
@ -96,3 +120,35 @@ func (flag *DatacenterFlag) Datacenter() (*object.Datacenter, error) {
return flag.dc, err return flag.dc, err
} }
func (flag *DatacenterFlag) ManagedObjects(ctx context.Context, args []string) ([]types.ManagedObjectReference, error) {
var refs []types.ManagedObjectReference
c, err := flag.Client()
if err != nil {
return nil, err
}
if len(args) == 0 {
refs = append(refs, c.ServiceContent.RootFolder)
return refs, nil
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
for _, arg := range args {
elements, err := finder.ManagedObjectList(ctx, arg)
if err != nil {
return nil, err
}
for _, e := range elements {
refs = append(refs, e.Object.Reference())
}
}
return refs, nil
}

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -17,34 +17,41 @@ limitations under the License.
package flags package flags
import ( import (
"errors"
"flag" "flag"
"fmt" "fmt"
"net/url" "net/url"
"os" "os"
"path"
"sync"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
var (
ErrDatastoreDirNotExist = errors.New("datastore directory does not exist")
ErrDatastoreFileNotExist = errors.New("datastore file does not exist")
)
type DatastoreFlag struct { type DatastoreFlag struct {
common
*DatacenterFlag *DatacenterFlag
register sync.Once name string
name string ds *object.Datastore
ds *object.Datastore
} }
func (flag *DatastoreFlag) Register(f *flag.FlagSet) { var datastoreFlagKey = flagKey("datastore")
flag.register.Do(func() {
func NewDatastoreFlag(ctx context.Context) (*DatastoreFlag, context.Context) {
if v := ctx.Value(datastoreFlagKey); v != nil {
return v.(*DatastoreFlag), ctx
}
v := &DatastoreFlag{}
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
ctx = context.WithValue(ctx, datastoreFlagKey, v)
return v, ctx
}
func (flag *DatastoreFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.DatacenterFlag.Register(ctx, f)
env := "GOVC_DATASTORE" env := "GOVC_DATASTORE"
value := os.Getenv(env) value := os.Getenv(env)
usage := fmt.Sprintf("Datastore [%s]", env) usage := fmt.Sprintf("Datastore [%s]", env)
@ -52,7 +59,14 @@ func (flag *DatastoreFlag) Register(f *flag.FlagSet) {
}) })
} }
func (flag *DatastoreFlag) Process() error { return nil } func (flag *DatastoreFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (flag *DatastoreFlag) Datastore() (*object.Datastore, error) { func (flag *DatastoreFlag) Datastore() (*object.Datastore, error) {
if flag.ds != nil { if flag.ds != nil {
@ -64,13 +78,11 @@ func (flag *DatastoreFlag) Datastore() (*object.Datastore, error) {
return nil, err return nil, err
} }
if flag.name == "" { if flag.ds, err = finder.DatastoreOrDefault(context.TODO(), flag.name); err != nil {
flag.ds, err = finder.DefaultDatastore(context.TODO()) return nil, err
} else {
flag.ds, err = finder.Datastore(context.TODO(), flag.name)
} }
return flag.ds, err return flag.ds, nil
} }
func (flag *DatastoreFlag) DatastorePath(name string) (string, error) { func (flag *DatastoreFlag) DatastorePath(name string) (string, error) {
@ -100,50 +112,3 @@ func (flag *DatastoreFlag) DatastoreURL(path string) (*url.URL, error) {
return u, nil return u, nil
} }
func (flag *DatastoreFlag) Stat(file string) (types.BaseFileInfo, error) {
ds, err := flag.Datastore()
if err != nil {
return nil, err
}
b, err := ds.Browser(context.TODO())
if err != nil {
return nil, err
}
spec := types.HostDatastoreBrowserSearchSpec{
Details: &types.FileQueryFlags{
FileType: true,
FileOwner: types.NewBool(true), // TODO: omitempty is generated, but seems to be required
},
MatchPattern: []string{path.Base(file)},
}
dsPath := ds.Path(path.Dir(file))
task, err := b.SearchDatastore(context.TODO(), dsPath, &spec)
if err != nil {
return nil, err
}
info, err := task.WaitForResult(context.TODO(), nil)
if err != nil {
if info != nil && info.Error != nil {
_, ok := info.Error.Fault.(*types.FileNotFound)
if ok {
// FileNotFound means the base path doesn't exist.
return nil, ErrDatastoreDirNotExist
}
}
return nil, err
}
res := info.Result.(types.HostDatastoreBrowserSearchResults)
if len(res.File) == 0 {
// File doesn't exist
return nil, ErrDatastoreFileNotExist
}
return res.File[0], nil
}

View File

@ -24,27 +24,49 @@ import (
"strings" "strings"
"time" "time"
"golang.org/x/net/context"
"github.com/vmware/govmomi/vim25/debug" "github.com/vmware/govmomi/vim25/debug"
) )
type DebugFlag struct { type DebugFlag struct {
common
enable bool enable bool
} }
func (flag *DebugFlag) Register(f *flag.FlagSet) { var debugFlagKey = flagKey("debug")
env := "GOVC_DEBUG"
enable := false func NewDebugFlag(ctx context.Context) (*DebugFlag, context.Context) {
switch env := strings.ToLower(os.Getenv(env)); env { if v := ctx.Value(debugFlagKey); v != nil {
case "1", "true": return v.(*DebugFlag), ctx
enable = true
} }
usage := fmt.Sprintf("Store debug logs [%s]", env) v := &DebugFlag{}
f.BoolVar(&flag.enable, "debug", enable, usage) ctx = context.WithValue(ctx, debugFlagKey, v)
return v, ctx
} }
func (flag *DebugFlag) Process() error { func (flag *DebugFlag) Register(ctx context.Context, f *flag.FlagSet) {
if flag.enable { flag.RegisterOnce(func() {
env := "GOVC_DEBUG"
enable := false
switch env := strings.ToLower(os.Getenv(env)); env {
case "1", "true":
enable = true
}
usage := fmt.Sprintf("Store debug logs [%s]", env)
f.BoolVar(&flag.enable, "debug", enable, usage)
})
}
func (flag *DebugFlag) Process(ctx context.Context) error {
if !flag.enable {
return nil
}
return flag.ProcessOnce(func() error {
// Base path for storing debug logs. // Base path for storing debug logs.
r := os.Getenv("GOVC_DEBUG_PATH") r := os.Getenv("GOVC_DEBUG_PATH")
if r == "" { if r == "" {
@ -66,7 +88,6 @@ func (flag *DebugFlag) Process() error {
} }
debug.SetProvider(&p) debug.SetProvider(&p)
} return nil
})
return nil
} }

View File

@ -16,10 +16,17 @@ limitations under the License.
package flags package flags
import "flag" import (
"flag"
"golang.org/x/net/context"
)
type EmptyFlag struct{} type EmptyFlag struct{}
func (flag *EmptyFlag) Register(f *flag.FlagSet) {} func (flag *EmptyFlag) Register(ctx context.Context, f *flag.FlagSet) {
}
func (flag *EmptyFlag) Process() error { return nil } func (flag *EmptyFlag) Process(ctx context.Context) error {
return nil
}

View File

@ -0,0 +1,79 @@
/*
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 flags
import (
"flag"
"fmt"
"golang.org/x/net/context"
"github.com/vmware/govmomi/vim25/types"
)
type HostConnectFlag struct {
common
types.HostConnectSpec
noverify bool
}
var hostConnectFlagKey = flagKey("hostConnect")
func NewHostConnectFlag(ctx context.Context) (*HostConnectFlag, context.Context) {
if v := ctx.Value(hostConnectFlagKey); v != nil {
return v.(*HostConnectFlag), ctx
}
v := &HostConnectFlag{}
ctx = context.WithValue(ctx, hostConnectFlagKey, v)
return v, ctx
}
func (flag *HostConnectFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
f.StringVar(&flag.HostName, "hostname", "", "Hostname or IP address of the host")
f.StringVar(&flag.UserName, "username", "", "Username of administration account on the host")
f.StringVar(&flag.Password, "password", "", "Password of administration account on the host")
f.StringVar(&flag.SslThumbprint, "fingerprint", "", "Fingerprint of the host's SSL certificate")
f.BoolVar(&flag.Force, "force", false, "Force when host is managed by another VC")
f.BoolVar(&flag.noverify, "noverify", false, "When true, ignore host SSL certificate verification error")
})
}
func (flag *HostConnectFlag) Process(ctx context.Context) error {
return nil
}
// AcceptThumbprint returns nil if the given error is an SSLVerifyFault and -noverify is true.
// In which case, flag.SslThumbprint is set to fault.Thumbprint and the caller should retry the task.
func (flag *HostConnectFlag) AcceptThumbprint(err error) error {
if f, ok := err.(types.HasFault); ok {
switch fault := f.Fault().(type) {
case *types.SSLVerifyFault:
if flag.noverify {
flag.SslThumbprint = fault.Thumbprint
return nil
}
return fmt.Errorf("%s Fingerprint is %s", err, fault.Thumbprint)
}
}
return err
}

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -20,27 +20,44 @@ import (
"flag" "flag"
"fmt" "fmt"
"os" "os"
"sync"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
type HostSystemFlag struct { type HostSystemFlag struct {
common
*ClientFlag *ClientFlag
*DatacenterFlag *DatacenterFlag
*SearchFlag *SearchFlag
register sync.Once name string
name string host *object.HostSystem
host *object.HostSystem pool *object.ResourcePool
pool *object.ResourcePool
} }
func (flag *HostSystemFlag) Register(f *flag.FlagSet) { var hostSystemFlagKey = flagKey("hostSystem")
flag.SearchFlag = NewSearchFlag(SearchHosts)
func NewHostSystemFlag(ctx context.Context) (*HostSystemFlag, context.Context) {
if v := ctx.Value(hostSystemFlagKey); v != nil {
return v.(*HostSystemFlag), ctx
}
v := &HostSystemFlag{}
v.ClientFlag, ctx = NewClientFlag(ctx)
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
v.SearchFlag, ctx = NewSearchFlag(ctx, SearchHosts)
ctx = context.WithValue(ctx, hostSystemFlagKey, v)
return v, ctx
}
func (flag *HostSystemFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.ClientFlag.Register(ctx, f)
flag.DatacenterFlag.Register(ctx, f)
flag.SearchFlag.Register(ctx, f)
flag.register.Do(func() {
env := "GOVC_HOST" env := "GOVC_HOST"
value := os.Getenv(env) value := os.Getenv(env)
usage := fmt.Sprintf("Host system [%s]", env) usage := fmt.Sprintf("Host system [%s]", env)
@ -48,7 +65,20 @@ func (flag *HostSystemFlag) Register(f *flag.FlagSet) {
}) })
} }
func (flag *HostSystemFlag) Process() error { return nil } func (flag *HostSystemFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.ClientFlag.Process(ctx); err != nil {
return err
}
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
if err := flag.SearchFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (flag *HostSystemFlag) HostSystemIfSpecified() (*object.HostSystem, error) { func (flag *HostSystemFlag) HostSystemIfSpecified() (*object.HostSystem, error) {
if flag.host != nil { if flag.host != nil {

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -20,7 +20,6 @@ import (
"flag" "flag"
"fmt" "fmt"
"os" "os"
"sync"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types" "github.com/vmware/govmomi/vim25/types"
@ -28,21 +27,33 @@ import (
) )
type NetworkFlag struct { type NetworkFlag struct {
common
*DatacenterFlag *DatacenterFlag
register sync.Once name string
name string net object.NetworkReference
net object.NetworkReference adapter string
adapter string address string
address string
} }
func NewNetworkFlag() *NetworkFlag { var networkFlagKey = flagKey("network")
return &NetworkFlag{}
func NewNetworkFlag(ctx context.Context) (*NetworkFlag, context.Context) {
if v := ctx.Value(networkFlagKey); v != nil {
return v.(*NetworkFlag), ctx
}
v := &NetworkFlag{}
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
ctx = context.WithValue(ctx, networkFlagKey, v)
return v, ctx
} }
func (flag *NetworkFlag) Register(f *flag.FlagSet) { func (flag *NetworkFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.register.Do(func() { flag.RegisterOnce(func() {
flag.DatacenterFlag.Register(ctx, f)
env := "GOVC_NETWORK" env := "GOVC_NETWORK"
value := os.Getenv(env) value := os.Getenv(env)
flag.Set(value) flag.Set(value)
@ -53,7 +64,14 @@ func (flag *NetworkFlag) Register(f *flag.FlagSet) {
}) })
} }
func (flag *NetworkFlag) Process() error { return nil } func (flag *NetworkFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (flag *NetworkFlag) String() string { func (flag *NetworkFlag) String() string {
return flag.name return flag.name
@ -74,13 +92,11 @@ func (flag *NetworkFlag) Network() (object.NetworkReference, error) {
return nil, err return nil, err
} }
if flag.name == "" { if flag.net, err = finder.NetworkOrDefault(context.TODO(), flag.name); err != nil {
flag.net, err = finder.DefaultNetwork(context.TODO()) return nil, err
} else {
flag.net, err = finder.Network(context.TODO(), flag.name)
} }
return flag.net, err return flag.net, nil
} }
func (flag *NetworkFlag) Device() (types.BaseVirtualDevice, error) { func (flag *NetworkFlag) Device() (types.BaseVirtualDevice, error) {

View File

@ -0,0 +1,55 @@
/*
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 flags
import (
"flag"
"fmt"
"strconv"
)
type optionalBool struct {
val **bool
}
func (b *optionalBool) Set(s string) error {
v, err := strconv.ParseBool(s)
*b.val = &v
return err
}
func (b *optionalBool) Get() interface{} {
if *b.val == nil {
return nil
}
return **b.val
}
func (b *optionalBool) String() string {
if *b.val == nil {
return "<nil>"
}
return fmt.Sprintf("%v", **b.val)
}
func (b *optionalBool) IsBoolFlag() bool { return true }
// NewOptionalBool returns a flag.Value implementation where there is no default value.
// This avoids sending a default value over the wire as using flag.BoolVar() would.
func NewOptionalBool(v **bool) flag.Value {
return &optionalBool{v}
}

View File

@ -25,6 +25,8 @@ import (
"sync" "sync"
"time" "time"
"golang.org/x/net/context"
"github.com/vmware/govmomi/vim25/progress" "github.com/vmware/govmomi/vim25/progress"
) )
@ -33,21 +35,39 @@ type OutputWriter interface {
} }
type OutputFlag struct { type OutputFlag struct {
common
JSON bool JSON bool
TTY bool TTY bool
} }
func (flag *OutputFlag) Register(f *flag.FlagSet) { var outputFlagKey = flagKey("output")
f.BoolVar(&flag.JSON, "json", false, "Enable JSON output")
}
func (flag *OutputFlag) Process() error { func NewOutputFlag(ctx context.Context) (*OutputFlag, context.Context) {
if !flag.JSON { if v := ctx.Value(outputFlagKey); v != nil {
// Assume we have a tty if not outputting JSON return v.(*OutputFlag), ctx
flag.TTY = true
} }
return nil v := &OutputFlag{}
ctx = context.WithValue(ctx, outputFlagKey, v)
return v, ctx
}
func (flag *OutputFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
f.BoolVar(&flag.JSON, "json", false, "Enable JSON output")
})
}
func (flag *OutputFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if !flag.JSON {
// Assume we have a tty if not outputting JSON
flag.TTY = true
}
return nil
})
} }
// Log outputs the specified string, prefixed with the current time. // Log outputs the specified string, prefixed with the current time.
@ -81,8 +101,7 @@ func (flag *OutputFlag) WriteResult(result OutputWriter) error {
var out = os.Stdout var out = os.Stdout
if flag.JSON { if flag.JSON {
enc := json.NewEncoder(out) err = json.NewEncoder(out).Encode(result)
err = enc.Encode(result)
} else { } else {
err = result.Write(out) err = result.Write(out)
} }

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -20,22 +20,37 @@ import (
"flag" "flag"
"fmt" "fmt"
"os" "os"
"sync"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
type ResourcePoolFlag struct { type ResourcePoolFlag struct {
common
*DatacenterFlag *DatacenterFlag
register sync.Once name string
name string pool *object.ResourcePool
pool *object.ResourcePool
} }
func (flag *ResourcePoolFlag) Register(f *flag.FlagSet) { var resourcePoolFlagKey = flagKey("resourcePool")
flag.register.Do(func() {
func NewResourcePoolFlag(ctx context.Context) (*ResourcePoolFlag, context.Context) {
if v := ctx.Value(resourcePoolFlagKey); v != nil {
return v.(*ResourcePoolFlag), ctx
}
v := &ResourcePoolFlag{}
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
ctx = context.WithValue(ctx, resourcePoolFlagKey, v)
return v, ctx
}
func (flag *ResourcePoolFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.DatacenterFlag.Register(ctx, f)
env := "GOVC_RESOURCE_POOL" env := "GOVC_RESOURCE_POOL"
value := os.Getenv(env) value := os.Getenv(env)
usage := fmt.Sprintf("Resource pool [%s]", env) usage := fmt.Sprintf("Resource pool [%s]", env)
@ -43,7 +58,14 @@ func (flag *ResourcePoolFlag) Register(f *flag.FlagSet) {
}) })
} }
func (flag *ResourcePoolFlag) Process() error { return nil } func (flag *ResourcePoolFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (flag *ResourcePoolFlag) ResourcePool() (*object.ResourcePool, error) { func (flag *ResourcePoolFlag) ResourcePool() (*object.ResourcePool, error) {
if flag.pool != nil { if flag.pool != nil {
@ -55,11 +77,9 @@ func (flag *ResourcePoolFlag) ResourcePool() (*object.ResourcePool, error) {
return nil, err return nil, err
} }
if flag.name == "" { if flag.pool, err = finder.ResourcePoolOrDefault(context.TODO(), flag.name); err != nil {
flag.pool, err = finder.DefaultResourcePool(context.TODO()) return nil, err
} else {
flag.pool, err = finder.ResourcePool(context.TODO(), flag.name)
} }
return flag.pool, err return flag.pool, nil
} }

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -22,6 +22,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25"
"golang.org/x/net/context" "golang.org/x/net/context"
@ -30,9 +31,12 @@ import (
const ( const (
SearchVirtualMachines = iota + 1 SearchVirtualMachines = iota + 1
SearchHosts SearchHosts
SearchVirtualApps
) )
type SearchFlag struct { type SearchFlag struct {
common
*ClientFlag *ClientFlag
*DatacenterFlag *DatacenterFlag
@ -48,65 +52,91 @@ type SearchFlag struct {
isset bool isset bool
} }
func NewSearchFlag(t int) *SearchFlag { var searchFlagKey = flagKey("search")
s := SearchFlag{
func NewSearchFlag(ctx context.Context, t int) (*SearchFlag, context.Context) {
if v := ctx.Value(searchFlagKey); v != nil {
return v.(*SearchFlag), ctx
}
v := &SearchFlag{
t: t, t: t,
} }
v.ClientFlag, ctx = NewClientFlag(ctx)
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
switch t { switch t {
case SearchVirtualMachines: case SearchVirtualMachines:
s.entity = "VM" v.entity = "VM"
case SearchHosts: case SearchHosts:
s.entity = "host" v.entity = "host"
case SearchVirtualApps:
v.entity = "vapp"
default: default:
panic("invalid search type") panic("invalid search type")
} }
return &s ctx = context.WithValue(ctx, searchFlagKey, v)
return v, ctx
} }
func (flag *SearchFlag) Register(fs *flag.FlagSet) { func (flag *SearchFlag) Register(ctx context.Context, fs *flag.FlagSet) {
register := func(v *string, f string, d string) { flag.RegisterOnce(func() {
f = fmt.Sprintf("%s.%s", strings.ToLower(flag.entity), f) flag.ClientFlag.Register(ctx, fs)
d = fmt.Sprintf(d, flag.entity) flag.DatacenterFlag.Register(ctx, fs)
fs.StringVar(v, f, "", d)
}
switch flag.t { register := func(v *string, f string, d string) {
case SearchVirtualMachines: f = fmt.Sprintf("%s.%s", strings.ToLower(flag.entity), f)
register(&flag.byDatastorePath, "path", "Find %s by path to .vmx file") d = fmt.Sprintf(d, flag.entity)
} fs.StringVar(v, f, "", d)
switch flag.t {
case SearchVirtualMachines, SearchHosts:
register(&flag.byDNSName, "dns", "Find %s by FQDN")
register(&flag.byIP, "ip", "Find %s by IP address")
register(&flag.byUUID, "uuid", "Find %s by instance UUID")
}
register(&flag.byInventoryPath, "ipath", "Find %s by inventory path")
}
func (flag *SearchFlag) Process() error {
flags := []string{
flag.byDatastorePath,
flag.byDNSName,
flag.byInventoryPath,
flag.byIP,
flag.byUUID,
}
flag.isset = false
for _, f := range flags {
if f != "" {
if flag.isset {
return errors.New("cannot use more than one search flag")
}
flag.isset = true
} }
}
return nil switch flag.t {
case SearchVirtualMachines:
register(&flag.byDatastorePath, "path", "Find %s by path to .vmx file")
}
switch flag.t {
case SearchVirtualMachines, SearchHosts:
register(&flag.byDNSName, "dns", "Find %s by FQDN")
register(&flag.byIP, "ip", "Find %s by IP address")
register(&flag.byUUID, "uuid", "Find %s by instance UUID")
}
register(&flag.byInventoryPath, "ipath", "Find %s by inventory path")
})
}
func (flag *SearchFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.ClientFlag.Process(ctx); err != nil {
return err
}
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
flags := []string{
flag.byDatastorePath,
flag.byDNSName,
flag.byInventoryPath,
flag.byIP,
flag.byUUID,
}
flag.isset = false
for _, f := range flags {
if f != "" {
if flag.isset {
return errors.New("cannot use more than one search flag")
}
flag.isset = true
}
}
return nil
})
} }
func (flag *SearchFlag) IsSet() bool { func (flag *SearchFlag) IsSet() bool {
@ -156,9 +186,9 @@ func (flag *SearchFlag) searchByIP(c *vim25.Client, dc *object.Datacenter) (obje
func (flag *SearchFlag) searchByUUID(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) { func (flag *SearchFlag) searchByUUID(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) {
switch flag.t { switch flag.t {
case SearchVirtualMachines: case SearchVirtualMachines:
return flag.searchIndex(c).FindByUuid(context.TODO(), dc, flag.byUUID, true) return flag.searchIndex(c).FindByUuid(context.TODO(), dc, flag.byUUID, true, nil)
case SearchHosts: case SearchHosts:
return flag.searchIndex(c).FindByUuid(context.TODO(), dc, flag.byUUID, false) return flag.searchIndex(c).FindByUuid(context.TODO(), dc, flag.byUUID, false, nil)
default: default:
panic("unsupported type") panic("unsupported type")
} }
@ -241,16 +271,73 @@ func (flag *SearchFlag) VirtualMachines(args []string) ([]*object.VirtualMachine
return nil, err return nil, err
} }
var nfe error
// List virtual machines for every argument // List virtual machines for every argument
for _, arg := range args { for _, arg := range args {
vms, err := finder.VirtualMachineList(context.TODO(), arg) vms, err := finder.VirtualMachineList(context.TODO(), arg)
if err != nil { if err != nil {
if _, ok := err.(*find.NotFoundError); ok {
// Let caller decide how to handle NotFoundError
nfe = err
continue
}
return nil, err return nil, err
} }
out = append(out, vms...) out = append(out, vms...)
} }
return out, nfe
}
func (flag *SearchFlag) VirtualApp() (*object.VirtualApp, error) {
ref, err := flag.search()
if err != nil {
return nil, err
}
app, ok := ref.(*object.VirtualApp)
if !ok {
return nil, fmt.Errorf("expected VirtualApp entity, got %s", ref.Reference().Type)
}
return app, nil
}
func (flag *SearchFlag) VirtualApps(args []string) ([]*object.VirtualApp, error) {
var out []*object.VirtualApp
if flag.IsSet() {
app, err := flag.VirtualApp()
if err != nil {
return nil, err
}
out = append(out, app)
return out, nil
}
// List virtual apps
if len(args) == 0 {
return nil, errors.New("no argument")
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
// List virtual apps for every argument
for _, arg := range args {
apps, err := finder.VirtualAppList(context.TODO(), arg)
if err != nil {
return nil, err
}
out = append(out, apps...)
}
return out, nil return out, nil
} }

View File

@ -0,0 +1,104 @@
/*
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 flags
import (
"flag"
"fmt"
"os"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type VirtualAppFlag struct {
common
*DatacenterFlag
*SearchFlag
name string
app *object.VirtualApp
}
var virtualAppFlagKey = flagKey("virtualApp")
func NewVirtualAppFlag(ctx context.Context) (*VirtualAppFlag, context.Context) {
if v := ctx.Value(virtualAppFlagKey); v != nil {
return v.(*VirtualAppFlag), ctx
}
v := &VirtualAppFlag{}
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
v.SearchFlag, ctx = NewSearchFlag(ctx, SearchVirtualApps)
ctx = context.WithValue(ctx, virtualAppFlagKey, v)
return v, ctx
}
func (flag *VirtualAppFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.DatacenterFlag.Register(ctx, f)
flag.SearchFlag.Register(ctx, f)
env := "GOVC_VAPP"
value := os.Getenv(env)
usage := fmt.Sprintf("Virtual App [%s]", env)
f.StringVar(&flag.name, "vapp", value, usage)
})
}
func (flag *VirtualAppFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
if err := flag.SearchFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (flag *VirtualAppFlag) VirtualApp() (*object.VirtualApp, error) {
if flag.app != nil {
return flag.app, nil
}
// Use search flags if specified.
if flag.SearchFlag.IsSet() {
app, err := flag.SearchFlag.VirtualApp()
if err != nil {
return nil, err
}
flag.app = app
return flag.app, nil
}
// Never look for a default virtual app.
if flag.name == "" {
return nil, nil
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
flag.app, err = finder.VirtualApp(context.TODO(), flag.name)
return flag.app, err
}

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -20,26 +20,43 @@ import (
"flag" "flag"
"fmt" "fmt"
"os" "os"
"sync"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
type VirtualMachineFlag struct { type VirtualMachineFlag struct {
common
*ClientFlag *ClientFlag
*DatacenterFlag *DatacenterFlag
*SearchFlag *SearchFlag
register sync.Once name string
name string vm *object.VirtualMachine
vm *object.VirtualMachine
} }
func (flag *VirtualMachineFlag) Register(f *flag.FlagSet) { var virtualMachineFlagKey = flagKey("virtualMachine")
flag.SearchFlag = NewSearchFlag(SearchVirtualMachines)
func NewVirtualMachineFlag(ctx context.Context) (*VirtualMachineFlag, context.Context) {
if v := ctx.Value(virtualMachineFlagKey); v != nil {
return v.(*VirtualMachineFlag), ctx
}
v := &VirtualMachineFlag{}
v.ClientFlag, ctx = NewClientFlag(ctx)
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
v.SearchFlag, ctx = NewSearchFlag(ctx, SearchVirtualMachines)
ctx = context.WithValue(ctx, virtualMachineFlagKey, v)
return v, ctx
}
func (flag *VirtualMachineFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.ClientFlag.Register(ctx, f)
flag.DatacenterFlag.Register(ctx, f)
flag.SearchFlag.Register(ctx, f)
flag.register.Do(func() {
env := "GOVC_VM" env := "GOVC_VM"
value := os.Getenv(env) value := os.Getenv(env)
usage := fmt.Sprintf("Virtual machine [%s]", env) usage := fmt.Sprintf("Virtual machine [%s]", env)
@ -47,7 +64,20 @@ func (flag *VirtualMachineFlag) Register(f *flag.FlagSet) {
}) })
} }
func (flag *VirtualMachineFlag) Process() error { return nil } func (flag *VirtualMachineFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.ClientFlag.Process(ctx); err != nil {
return err
}
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
if err := flag.SearchFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (flag *VirtualMachineFlag) VirtualMachine() (*object.VirtualMachine, error) { func (flag *VirtualMachineFlag) VirtualMachine() (*object.VirtualMachine, error) {
if flag.vm != nil { if flag.vm != nil {

View File

@ -1,6 +1,7 @@
/* /*
Copyright (c) 2015 VMware, Inc. All Rights Reserved. Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
@ -17,7 +18,6 @@ limitations under the License.
package host package host
import ( import (
"errors"
"flag" "flag"
"fmt" "fmt"
@ -32,63 +32,88 @@ import (
type add struct { type add struct {
*flags.ClientFlag *flags.ClientFlag
*flags.DatacenterFlag *flags.DatacenterFlag
*flags.HostConnectFlag
parent string parent string
connect bool
host string
username string
password string
connect bool
fingerprint string
} }
func init() { func init() {
cli.Register("host.add", &add{}) cli.Register("host.add", &add{})
} }
func (cmd *add) Register(f *flag.FlagSet) { func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
f.StringVar(&cmd.parent, "parent", "", "Path to folder to add the host to") cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
f.StringVar(&cmd.host, "host", "", "Hostname or IP address of the host") cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
f.StringVar(&cmd.username, "username", "", "Username of administration account on the host") cmd.DatacenterFlag.Register(ctx, f)
f.StringVar(&cmd.password, "password", "", "Password of administration account on the host")
cmd.HostConnectFlag, ctx = flags.NewHostConnectFlag(ctx)
cmd.HostConnectFlag.Register(ctx, f)
f.StringVar(&cmd.parent, "parent", "", "Path to folder to add the host to")
f.BoolVar(&cmd.connect, "connect", true, "Immediately connect to host") f.BoolVar(&cmd.connect, "connect", true, "Immediately connect to host")
f.StringVar(&cmd.fingerprint, "fingerprint", "", "Fingerprint of the host's SSL certificate")
} }
func (cmd *add) Process() error { func (cmd *add) Process(ctx context.Context) error {
if cmd.host == "" { if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
if err := cmd.HostConnectFlag.Process(ctx); err != nil {
return err
}
if cmd.HostName == "" {
return flag.ErrHelp return flag.ErrHelp
} }
if cmd.username == "" { if cmd.UserName == "" {
return flag.ErrHelp return flag.ErrHelp
} }
if cmd.password == "" { if cmd.Password == "" {
return flag.ErrHelp return flag.ErrHelp
} }
return nil return nil
} }
func (cmd *add) Usage() string {
return "HOST"
}
func (cmd *add) Description() string { func (cmd *add) Description() string {
return `Add HOST to datacenter. return `Add host to datacenter.
The host is added to the folder specified by the 'parent' flag. If not given, The host is added to the folder specified by the 'parent' flag. If not given,
this defaults to the hosts folder in the specified or default datacenter.` this defaults to the hosts folder in the specified or default datacenter.`
} }
func (cmd *add) Run(f *flag.FlagSet) error { func (cmd *add) Add(ctx context.Context, parent *object.Folder) error {
var ctx = context.Background() spec := cmd.HostConnectSpec
var parent *object.Folder
client, err := cmd.Client() req := types.AddStandaloneHost_Task{
This: parent.Reference(),
Spec: spec,
AddConnected: cmd.connect,
}
res, err := methods.AddStandaloneHost_Task(ctx, parent.Client(), &req)
if err != nil { if err != nil {
return err return err
} }
logger := cmd.ProgressLogger(fmt.Sprintf("adding %s to folder %s... ", spec.HostName, parent.InventoryPath))
defer logger.Wait()
task := object.NewTask(parent.Client(), res.Returnval)
_, err = task.WaitForResult(ctx, logger)
return err
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
var parent *object.Folder
if f.NArg() != 0 {
return flag.ErrHelp
}
if cmd.parent == "" { if cmd.parent == "" {
dc, err := cmd.Datacenter() dc, err := cmd.Datacenter()
if err != nil { if err != nil {
@ -107,59 +132,22 @@ func (cmd *add) Run(f *flag.FlagSet) error {
return err return err
} }
mo, err := finder.ManagedObjectList(ctx, cmd.parent) parent, err = finder.Folder(ctx, cmd.parent)
if err != nil { if err != nil {
return err return err
} }
if len(mo) == 0 {
return errors.New("parent does not resolve to object")
}
if len(mo) > 1 {
return errors.New("parent resolves to more than one object")
}
ref := mo[0].Object.Reference()
if ref.Type != "Folder" {
return errors.New("parent does not resolve to folder")
}
parent = object.NewFolder(client, ref)
} }
req := types.AddStandaloneHost_Task{ err := cmd.Add(ctx, parent)
This: parent.Reference(), if err == nil {
Spec: types.HostConnectSpec{ return nil
HostName: cmd.host,
UserName: cmd.username,
Password: cmd.password,
SslThumbprint: cmd.fingerprint,
},
AddConnected: cmd.connect,
} }
res, err := methods.AddStandaloneHost_Task(ctx, client, &req) // Check if we failed due to SSLVerifyFault and -noverify is set
if err != nil { if err := cmd.AcceptThumbprint(err); err != nil {
return err return err
} }
task := object.NewTask(client, res.Returnval) // Accepted unverified thumbprint, try again
_, err = task.WaitForResult(ctx, nil) return cmd.Add(ctx, parent)
if err != nil {
f, ok := err.(types.HasFault)
if !ok {
return err
}
switch fault := f.Fault().(type) {
case *types.SSLVerifyFault:
// Add fingerprint to error message
return fmt.Errorf("%s Fingerprint is %s.", err.Error(), fault.Thumbprint)
default:
return err
}
}
return nil
} }

View File

@ -19,6 +19,8 @@ package autostart
import ( import (
"flag" "flag"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/vim25/types" "github.com/vmware/govmomi/vim25/types"
) )
@ -31,15 +33,23 @@ func init() {
cli.Register("host.autostart.add", &add{}) cli.Register("host.autostart.add", &add{})
} }
func (cmd *add) Register(f *flag.FlagSet) {} func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.AutostartFlag, ctx = newAutostartFlag(ctx)
cmd.AutostartFlag.Register(ctx, f)
}
func (cmd *add) Process() error { return nil } func (cmd *add) Process(ctx context.Context) error {
if err := cmd.AutostartFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Usage() string { func (cmd *add) Usage() string {
return "VM..." return "VM..."
} }
func (cmd *add) Run(f *flag.FlagSet) error { func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
var powerInfo = types.AutoStartPowerInfo{ var powerInfo = types.AutoStartPowerInfo{
StartAction: "powerOn", StartAction: "powerOn",
StartDelay: -1, StartDelay: -1,

View File

@ -34,9 +34,32 @@ type AutostartFlag struct {
*flags.HostSystemFlag *flags.HostSystemFlag
} }
func (f *AutostartFlag) Register(fs *flag.FlagSet) {} func newAutostartFlag(ctx context.Context) (*AutostartFlag, context.Context) {
f := &AutostartFlag{}
f.ClientFlag, ctx = flags.NewClientFlag(ctx)
f.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
f.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
return f, ctx
}
func (f *AutostartFlag) Process() error { return nil } func (f *AutostartFlag) Register(ctx context.Context, fs *flag.FlagSet) {
f.ClientFlag.Register(ctx, fs)
f.DatacenterFlag.Register(ctx, fs)
f.HostSystemFlag.Register(ctx, fs)
}
func (f *AutostartFlag) Process(ctx context.Context) error {
if err := f.ClientFlag.Process(ctx); err != nil {
return err
}
if err := f.DatacenterFlag.Process(ctx); err != nil {
return err
}
if err := f.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
// VirtualMachines returns list of virtual machine objects based on the // VirtualMachines returns list of virtual machine objects based on the
// arguments specified on the command line. This helper is defined in // arguments specified on the command line. This helper is defined in

View File

@ -19,41 +19,45 @@ package autostart
import ( import (
"flag" "flag"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types" "github.com/vmware/govmomi/vim25/types"
) )
type configure struct { type configure struct {
*AutostartFlag *AutostartFlag
defaults types.AutoStartDefaults types.AutoStartDefaults
} }
func init() { func init() {
cli.Register("host.autostart.configure", &configure{}) cli.Register("host.autostart.configure", &configure{})
} }
func (cmd *configure) Register(f *flag.FlagSet) { func (cmd *configure) Register(ctx context.Context, f *flag.FlagSet) {
cmd.defaults.Enabled = types.NewBool(false) cmd.AutostartFlag, ctx = newAutostartFlag(ctx)
f.BoolVar(cmd.defaults.Enabled, "enabled", false, "") cmd.AutostartFlag.Register(ctx, f)
f.IntVar(&cmd.defaults.StartDelay, "start-delay", 0, "") f.Var(flags.NewOptionalBool(&cmd.Enabled), "enabled", "")
f.StringVar(&cmd.defaults.StopAction, "stop-action", "", "") f.IntVar(&cmd.StartDelay, "start-delay", 0, "")
f.IntVar(&cmd.defaults.StopDelay, "stop-delay", 0, "") f.StringVar(&cmd.StopAction, "stop-action", "", "")
f.IntVar(&cmd.StopDelay, "stop-delay", 0, "")
cmd.defaults.WaitForHeartbeat = types.NewBool(false) f.Var(flags.NewOptionalBool(&cmd.WaitForHeartbeat), "wait-for-heartbeat", "")
f.BoolVar(cmd.defaults.WaitForHeartbeat, "wait-for-heartbeat", false, "")
} }
func (cmd *configure) Process() error { return nil } func (cmd *configure) Process(ctx context.Context) error {
if err := cmd.AutostartFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *configure) Usage() string { func (cmd *configure) Usage() string {
return "" return ""
} }
func (cmd *configure) Run(f *flag.FlagSet) error { func (cmd *configure) Run(ctx context.Context, f *flag.FlagSet) error {
// Note: this command cannot DISABLE autostart because the "Enabled" field is return cmd.ReconfigureDefaults(cmd.AutoStartDefaults)
// marked "omitempty", which means that it is not included when it is false.
// Also see: https://github.com/vmware/govmomi/issues/240
return cmd.ReconfigureDefaults(cmd.defaults)
} }

View File

@ -32,8 +32,9 @@ import (
) )
type info struct { type info struct {
*AutostartFlag cli.Command
*AutostartFlag
*flags.OutputFlag *flags.OutputFlag
} }
@ -41,15 +42,28 @@ func init() {
cli.Register("host.autostart.info", &info{}) cli.Register("host.autostart.info", &info{})
} }
func (cmd *info) Register(f *flag.FlagSet) {} func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
cmd.AutostartFlag, ctx = newAutostartFlag(ctx)
cmd.AutostartFlag.Register(ctx, f)
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
}
func (cmd *info) Process() error { return nil } func (cmd *info) Process(ctx context.Context) error {
if err := cmd.AutostartFlag.Process(ctx); err != nil {
return err
}
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *info) Usage() string { func (cmd *info) Usage() string {
return "" return ""
} }
func (cmd *info) Run(f *flag.FlagSet) error { func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
client, err := cmd.Client() client, err := cmd.Client()
if err != nil { if err != nil {
return err return err

View File

@ -19,6 +19,8 @@ package autostart
import ( import (
"flag" "flag"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/vim25/types" "github.com/vmware/govmomi/vim25/types"
) )
@ -31,15 +33,23 @@ func init() {
cli.Register("host.autostart.remove", &remove{}) cli.Register("host.autostart.remove", &remove{})
} }
func (cmd *remove) Register(f *flag.FlagSet) {} func (cmd *remove) Register(ctx context.Context, f *flag.FlagSet) {
cmd.AutostartFlag, ctx = newAutostartFlag(ctx)
cmd.AutostartFlag.Register(ctx, f)
}
func (cmd *remove) Process() error { return nil } func (cmd *remove) Process(ctx context.Context) error {
if err := cmd.AutostartFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *remove) Usage() string { func (cmd *remove) Usage() string {
return "VM..." return "VM..."
} }
func (cmd *remove) Run(f *flag.FlagSet) error { func (cmd *remove) Run(ctx context.Context, f *flag.FlagSet) error {
var powerInfo = types.AutoStartPowerInfo{ var powerInfo = types.AutoStartPowerInfo{
StartAction: "none", StartAction: "none",
StartDelay: -1, StartDelay: -1,

View File

@ -0,0 +1,81 @@
/*
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 host
import (
"flag"
"fmt"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
)
type disconnect struct {
*flags.HostSystemFlag
}
func init() {
cli.Register("host.disconnect", &disconnect{})
}
func (cmd *disconnect) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
}
func (cmd *disconnect) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *disconnect) Description() string {
return `Disconnect host from vCenter and instruct the host to stop sending heartbeats.`
}
func (cmd *disconnect) Disconnect(ctx context.Context, host *object.HostSystem) error {
task, err := host.Disconnect(ctx)
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("%s disconnecting... ", host.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}
func (cmd *disconnect) Run(ctx context.Context, f *flag.FlagSet) error {
hosts, err := cmd.HostSystems(f.Args())
if err != nil {
return err
}
for _, host := range hosts {
err = cmd.Disconnect(ctx, host)
if err != nil {
return err
}
}
return nil
}

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -24,6 +24,8 @@ import (
"strings" "strings"
"text/tabwriter" "text/tabwriter"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/govc/flags"
) )
@ -42,13 +44,21 @@ func (cmd *esxcli) Usage() string {
return "COMMAND [ARG]..." return "COMMAND [ARG]..."
} }
func (cmd *esxcli) Register(f *flag.FlagSet) { func (cmd *esxcli) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
f.BoolVar(&cmd.hints, "hints", true, "Use command info hints when formatting output") f.BoolVar(&cmd.hints, "hints", true, "Use command info hints when formatting output")
} }
func (cmd *esxcli) Process() error { return nil } func (cmd *esxcli) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *esxcli) Run(f *flag.FlagSet) error { func (cmd *esxcli) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client() c, err := cmd.Client()
if err != nil { if err != nil {
return nil return nil

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -0,0 +1,45 @@
/*
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 esxcli
import "github.com/vmware/govmomi/object"
type FirewallInfo struct {
Loaded bool
Enabled bool
DefaultAction string
}
// GetFirewallInfo via 'esxcli network firewall get'
// The HostFirewallSystem type does not expose this data.
// This helper can be useful in particular to determine if the firewall is enabled or disabled.
func GetFirewallInfo(s *object.HostSystem) (*FirewallInfo, error) {
x, err := NewExecutor(s.Client(), s)
res, err := x.Run([]string{"network", "firewall", "get"})
if err != nil {
return nil, err
}
info := &FirewallInfo{
Loaded: res.Values[0]["Loaded"][0] == "true",
Enabled: res.Values[0]["Enabled"][0] == "true",
DefaultAction: res.Values[0]["DefaultAction"][0],
}
return info, nil
}

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -1,3 +1,18 @@
/*
Copyright (c) 2014-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 esxcli package esxcli
import ( import (

View File

@ -0,0 +1,128 @@
/*
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 firewall
import (
"flag"
"fmt"
"os"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/govc/host/esxcli"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
)
type find struct {
*flags.ClientFlag
*flags.OutputFlag
*flags.HostSystemFlag
enabled bool
check bool
types.HostFirewallRule
}
func init() {
cli.Register("firewall.ruleset.find", &find{})
}
func (cmd *find) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
f.BoolVar(&cmd.check, "c", true, "Check if esx firewall is enabled")
f.BoolVar(&cmd.enabled, "enabled", true, "Find enabled rule sets if true, disabled if false")
f.StringVar((*string)(&cmd.Direction), "direction", string(types.HostFirewallRuleDirectionOutbound), "Direction")
f.StringVar((*string)(&cmd.PortType), "type", string(types.HostFirewallRulePortTypeDst), "Port type")
f.StringVar((*string)(&cmd.Protocol), "proto", string(types.HostFirewallRuleProtocolTcp), "Protocol")
f.IntVar(&cmd.Port, "port", 0, "Port")
}
func (cmd *find) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *find) Description() string {
return `Find firewall rulesets matching the given rule.
For a complete list of rulesets: govc host.esxcli network firewall ruleset list
For a complete list of rules: govc host.esxcli network firewall ruleset rule list`
}
func (cmd *find) Run(ctx context.Context, f *flag.FlagSet) error {
host, err := cmd.HostSystem()
if err != nil {
return err
}
fs, err := host.ConfigManager().FirewallSystem(ctx)
if err != nil {
return err
}
if cmd.check {
esxfw, err := esxcli.GetFirewallInfo(host)
if err != nil {
return err
}
if !esxfw.Enabled {
fmt.Fprintln(os.Stderr, "host firewall is disabled")
}
}
info, err := fs.Info(ctx)
if err != nil {
return err
}
if f.NArg() != 0 {
// TODO: f.Args() -> types.HostFirewallRulesetIpList
return flag.ErrHelp
}
rs := object.HostFirewallRulesetList(info.Ruleset)
matched, err := rs.EnabledByRule(cmd.HostFirewallRule, cmd.enabled)
if err != nil {
return err
}
for _, r := range matched {
fmt.Println(r.Key)
}
return nil
}

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -23,12 +23,14 @@ import (
"os" "os"
"text/tabwriter" "text/tabwriter"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli" "github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags" "github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/property" "github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/mo"
"golang.org/x/net/context" "github.com/vmware/govmomi/vim25/types"
) )
type info struct { type info struct {
@ -41,73 +43,100 @@ func init() {
cli.Register("host.info", &info{}) cli.Register("host.info", &info{})
} }
func (c *info) Register(f *flag.FlagSet) {} func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
func (c *info) Process() error { return nil } cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
func (c *info) Run(f *flag.FlagSet) error { cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
client, err := c.Client() cmd.HostSystemFlag.Register(ctx, f)
}
func (cmd *info) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil { if err != nil {
return err return err
} }
var hosts []*object.HostSystem var res infoResult
var props []string
if cmd.OutputFlag.JSON {
props = nil // Load everything
} else {
props = []string{"summary"} // Load summary
}
// We could do without the -host flag, leaving it for compat // We could do without the -host flag, leaving it for compat
host, err := c.HostSystemIfSpecified() host, err := cmd.HostSystemIfSpecified()
if err != nil { if err != nil {
return err return err
} }
// Default only if there is a single host // Default only if there is a single host
if host == nil && f.NArg() == 0 { if host == nil && f.NArg() == 0 {
host, err = c.HostSystem() host, err = cmd.HostSystem()
if err != nil { if err != nil {
return err return err
} }
} }
if host != nil { if host != nil {
hosts = append(hosts, host) res.objects = append(res.objects, host)
} else { } else {
hosts, err = c.HostSystems(f.Args()) res.objects, err = cmd.HostSystems(f.Args())
if err != nil { if err != nil {
return err return err
} }
} }
var res infoResult if len(res.objects) != 0 {
var props []string refs := make([]types.ManagedObjectReference, 0, len(res.objects))
for _, o := range res.objects {
refs = append(refs, o.Reference())
}
if c.OutputFlag.JSON { pc := property.DefaultCollector(c)
props = nil // Load everything err = pc.Retrieve(ctx, refs, props, &res.HostSystems)
} else {
props = []string{"summary"} // Load summary
}
for _, host := range hosts {
var h mo.HostSystem
pc := property.DefaultCollector(client)
err = pc.RetrieveOne(context.TODO(), host.Reference(), props, &h)
if err != nil { if err != nil {
return err return err
} }
res.HostSystems = append(res.HostSystems, h)
} }
return c.WriteResult(&res) return cmd.WriteResult(&res)
} }
type infoResult struct { type infoResult struct {
HostSystems []mo.HostSystem HostSystems []mo.HostSystem
objects []*object.HostSystem
} }
func (r *infoResult) Write(w io.Writer) error { func (r *infoResult) Write(w io.Writer) error {
// Maintain order via r.objects as Property collector does not always return results in order.
objects := make(map[types.ManagedObjectReference]mo.HostSystem, len(r.HostSystems))
for _, o := range r.HostSystems {
objects[o.Reference()] = o
}
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0) tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
for _, host := range r.HostSystems { for _, o := range r.objects {
host := objects[o.Reference()]
s := host.Summary s := host.Summary
h := s.Hardware h := s.Hardware
z := s.QuickStats z := s.QuickStats
@ -116,6 +145,7 @@ func (r *infoResult) Write(w io.Writer) error {
memUsage := 100 * float64(z.OverallMemoryUsage<<20) / float64(h.MemorySize) memUsage := 100 * float64(z.OverallMemoryUsage<<20) / float64(h.MemorySize)
fmt.Fprintf(tw, "Name:\t%s\n", s.Config.Name) fmt.Fprintf(tw, "Name:\t%s\n", s.Config.Name)
fmt.Fprintf(tw, " Path:\t%s\n", o.InventoryPath)
fmt.Fprintf(tw, " Manufacturer:\t%s\n", h.Vendor) fmt.Fprintf(tw, " Manufacturer:\t%s\n", h.Vendor)
fmt.Fprintf(tw, " Logical CPUs:\t%d CPUs @ %dMHz\n", ncpu, h.CpuMhz) fmt.Fprintf(tw, " Logical CPUs:\t%d CPUs @ %dMHz\n", ncpu, h.CpuMhz)
fmt.Fprintf(tw, " Processor type:\t%s\n", h.CpuModel) fmt.Fprintf(tw, " Processor type:\t%s\n", h.CpuModel)

View File

@ -0,0 +1,94 @@
/*
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 maintenancec
import (
"flag"
"fmt"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
)
type enter struct {
*flags.HostSystemFlag
timeout int
evacuate bool
}
func init() {
cli.Register("host.maintenance.enter", &enter{})
}
func (cmd *enter) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
f.IntVar(&cmd.timeout, "timeout", 0, "Timeout")
f.BoolVar(&cmd.evacuate, "evacuate", false, "Evacuate powered off VMs")
}
func (cmd *enter) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *enter) Usage() string {
return "HOST..."
}
func (cmd *enter) Description() string {
return `Put the hosts in maintenance mode.
While this task is running and when the host is in maintenance mode,
no virtual machines can be powered on and no provisioning operations can be performed on the host.`
}
func (cmd *enter) EnterMaintenanceMode(ctx context.Context, host *object.HostSystem) error {
task, err := host.EnterMaintenanceMode(ctx, cmd.timeout, cmd.evacuate, nil) // TODO: spec param
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("%s entering maintenance mode... ", host.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}
func (cmd *enter) Run(ctx context.Context, f *flag.FlagSet) error {
hosts, err := cmd.HostSystems(f.Args())
if err != nil {
return err
}
for _, host := range hosts {
err = cmd.EnterMaintenanceMode(ctx, host)
if err != nil {
return err
}
}
return nil
}

View File

@ -0,0 +1,95 @@
/*
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 maintenancec
import (
"flag"
"fmt"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
)
type exit struct {
*flags.HostSystemFlag
timeout int
}
func init() {
cli.Register("host.maintenance.exit", &exit{})
}
func (cmd *exit) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
f.IntVar(&cmd.timeout, "timeout", 0, "Timeout")
}
func (cmd *exit) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *exit) Usage() string {
return "HOST..."
}
func (cmd *exit) Description() string {
return `Take hosts out of maintenance mode.
This blocks if any concurrent running maintenance-only host configurations operations are being performed.
For example, if VMFS volumes are being upgraded.
The 'timeout' flag is the number of seconds to wait for the exit maintenance mode to succeed.
If the timeout is less than or equal to zero, there is no timeout.`
}
func (cmd *exit) ExitMaintenanceMode(ctx context.Context, host *object.HostSystem) error {
task, err := host.ExitMaintenanceMode(ctx, cmd.timeout)
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("%s exiting maintenance mode... ", host.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}
func (cmd *exit) Run(ctx context.Context, f *flag.FlagSet) error {
hosts, err := cmd.HostSystems(f.Args())
if err != nil {
return err
}
for _, host := range hosts {
err = cmd.ExitMaintenanceMode(ctx, host)
if err != nil {
return err
}
}
return nil
}

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -35,18 +35,26 @@ func init() {
cli.Register("host.portgroup.add", &add{}) cli.Register("host.portgroup.add", &add{})
} }
func (cmd *add) Register(f *flag.FlagSet) { func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
f.StringVar(&cmd.spec.VswitchName, "vswitch", "", "vSwitch Name") f.StringVar(&cmd.spec.VswitchName, "vswitch", "", "vSwitch Name")
f.IntVar(&cmd.spec.VlanId, "vlan", 0, "VLAN ID") f.IntVar(&cmd.spec.VlanId, "vlan", 0, "VLAN ID")
} }
func (cmd *add) Process() error { return nil } func (cmd *add) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Usage() string { func (cmd *add) Usage() string {
return "NAME" return "NAME"
} }
func (cmd *add) Run(f *flag.FlagSet) error { func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
ns, err := cmd.HostNetworkSystem() ns, err := cmd.HostNetworkSystem()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2014 VMware, Inc. All Rights Reserved. Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -32,15 +32,23 @@ func init() {
cli.Register("host.portgroup.remove", &remove{}) cli.Register("host.portgroup.remove", &remove{})
} }
func (cmd *remove) Register(f *flag.FlagSet) {} func (cmd *remove) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
}
func (cmd *remove) Process() error { return nil } func (cmd *remove) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *remove) Usage() string { func (cmd *remove) Usage() string {
return "NAME" return "NAME"
} }
func (cmd *remove) Run(f *flag.FlagSet) error { func (cmd *remove) Run(ctx context.Context, f *flag.FlagSet) error {
ns, err := cmd.HostNetworkSystem() ns, err := cmd.HostNetworkSystem()
if err != nil { if err != nil {
return err return err

View File

@ -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 host
import (
"flag"
"fmt"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
)
type reconnect struct {
*flags.HostSystemFlag
*flags.HostConnectFlag
types.HostSystemReconnectSpec
}
func init() {
cli.Register("host.reconnect", &reconnect{})
}
func (cmd *reconnect) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
cmd.HostConnectFlag, ctx = flags.NewHostConnectFlag(ctx)
cmd.HostConnectFlag.Register(ctx, f)
cmd.HostSystemReconnectSpec.SyncState = types.NewBool(false)
f.BoolVar(cmd.HostSystemReconnectSpec.SyncState, "sync-state", false, "Sync state")
}
func (cmd *reconnect) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
if err := cmd.HostConnectFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *reconnect) Description() string {
return `Reconnect host to vCenter.
This command can also be used to change connection properties (hostname, fingerprint, username, password),
without disconnecting the host.`
}
func (cmd *reconnect) Reconnect(ctx context.Context, host *object.HostSystem) error {
task, err := host.Reconnect(ctx, &cmd.HostConnectSpec, &cmd.HostSystemReconnectSpec)
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("%s reconnecting... ", host.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}
func (cmd *reconnect) Run(ctx context.Context, f *flag.FlagSet) error {
hosts, err := cmd.HostSystems(f.Args())
if err != nil {
return err
}
for _, host := range hosts {
err = cmd.Reconnect(ctx, host)
if err != nil {
return err
}
}
return nil
}

101
vendor/github.com/vmware/govmomi/govc/host/remove.go generated vendored Normal file
View File

@ -0,0 +1,101 @@
/*
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 host
import (
"flag"
"fmt"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
)
type remove struct {
*flags.HostSystemFlag
}
func init() {
cli.Register("host.remove", &remove{})
}
func (cmd *remove) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
}
func (cmd *remove) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *remove) Usage() string {
return "HOST..."
}
func (cmd *remove) Description() string {
return `Remove hosts from vCenter.`
}
func (cmd *remove) Remove(ctx context.Context, host *object.HostSystem) error {
var h mo.HostSystem
err := host.Properties(ctx, host.Reference(), []string{"parent"}, &h)
if err != nil {
return err
}
remove := host.Destroy
if h.Parent.Type == "ComputeResource" {
// Standalone host. From the docs:
// "Invoking remove on a HostSystem of standalone type throws a NotSupported fault.
// A standalone HostSystem can be removeed only by invoking remove on its parent ComputeResource."
remove = object.NewComputeResource(host.Client(), *h.Parent).Destroy
}
task, err := remove(ctx)
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("%s removing... ", host.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}
func (cmd *remove) Run(ctx context.Context, f *flag.FlagSet) error {
hosts, err := cmd.HostSystems(f.Args())
if err != nil {
return err
}
for _, host := range hosts {
err = cmd.Remove(ctx, host)
if err != nil {
return err
}
}
return nil
}

View File

@ -0,0 +1,188 @@
/*
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 storage
import (
"flag"
"fmt"
"io"
"strings"
"text/tabwriter"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/units"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
var infoTypes = []string{"hba", "lun"}
type infoType string
func (t *infoType) Set(s string) error {
s = strings.ToLower(s)
for _, e := range infoTypes {
if s == e {
*t = infoType(s)
return nil
}
}
return fmt.Errorf("invalid type")
}
func (t *infoType) String() string {
return string(*t)
}
func (t *infoType) Result(hss mo.HostStorageSystem) flags.OutputWriter {
switch string(*t) {
case "hba":
return hbaResult(hss)
case "lun":
return lunResult(hss)
default:
panic("unsupported")
}
}
type info struct {
*flags.HostSystemFlag
*flags.OutputFlag
typ infoType
}
func init() {
cli.Register("host.storage.info", &info{})
}
func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
err := cmd.typ.Set("lun")
if err != nil {
panic(err)
}
f.Var(&cmd.typ, "t", fmt.Sprintf("Type (%s)", strings.Join(infoTypes, ",")))
}
func (cmd *info) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *info) Usage() string {
return "[-t TYPE]"
}
func (cmd *info) Description() string {
return `Show information about a host's storage system.`
}
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
host, err := cmd.HostSystem()
if err != nil {
return err
}
ss, err := host.ConfigManager().StorageSystem(ctx)
if err != nil {
return err
}
var hss mo.HostStorageSystem
err = ss.Properties(ctx, ss.Reference(), nil, &hss)
if err != nil {
return nil
}
return cmd.WriteResult(cmd.typ.Result(hss))
}
type hbaResult mo.HostStorageSystem
func (r hbaResult) Write(w io.Writer) error {
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
fmt.Fprintf(tw, "Device\t")
fmt.Fprintf(tw, "PCI\t")
fmt.Fprintf(tw, "Driver\t")
fmt.Fprintf(tw, "Status\t")
fmt.Fprintf(tw, "Model\t")
fmt.Fprintf(tw, "\n")
for _, e := range r.StorageDeviceInfo.HostBusAdapter {
hba := e.GetHostHostBusAdapter()
fmt.Fprintf(tw, "%s\t", hba.Device)
fmt.Fprintf(tw, "%s\t", hba.Pci)
fmt.Fprintf(tw, "%s\t", hba.Driver)
fmt.Fprintf(tw, "%s\t", hba.Status)
fmt.Fprintf(tw, "%s\t", hba.Model)
fmt.Fprintf(tw, "\n")
}
return tw.Flush()
}
type lunResult mo.HostStorageSystem
func (r lunResult) Write(w io.Writer) error {
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
fmt.Fprintf(tw, "Name\t")
fmt.Fprintf(tw, "Type\t")
fmt.Fprintf(tw, "Capacity\t")
fmt.Fprintf(tw, "Model\t")
fmt.Fprintf(tw, "\n")
for _, e := range r.StorageDeviceInfo.ScsiLun {
var capacity int64
lun := e.GetScsiLun()
if disk, ok := e.(*types.HostScsiDisk); ok {
capacity = int64(disk.Capacity.Block) * int64(disk.Capacity.BlockSize)
}
fmt.Fprintf(tw, "%s\t", lun.DeviceName)
fmt.Fprintf(tw, "%s\t", lun.DeviceType)
if capacity == 0 {
fmt.Fprintf(tw, "-\t")
} else {
fmt.Fprintf(tw, "%s\t", units.ByteSize(capacity))
}
fmt.Fprintf(tw, "%s\t", lun.Model)
fmt.Fprintf(tw, "\n")
}
return tw.Flush()
}

View File

@ -0,0 +1,127 @@
/*
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 storage
import (
"flag"
"fmt"
"io"
"text/tabwriter"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/units"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type partition struct {
*flags.HostSystemFlag
*flags.OutputFlag
}
func init() {
cli.Register("host.storage.partition", &partition{})
}
func (cmd *partition) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
}
func (cmd *partition) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *partition) Usage() string {
return "DEVICE_PATH"
}
func (cmd *partition) Description() string {
return `Show partition table for device at DEVICE_PATH.`
}
func (cmd *partition) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 1 {
return fmt.Errorf("specify device path")
}
path := f.Args()[0]
host, err := cmd.HostSystem()
if err != nil {
return err
}
ss, err := host.ConfigManager().StorageSystem(ctx)
if err != nil {
return err
}
var hss mo.HostStorageSystem
err = ss.Properties(ctx, ss.Reference(), nil, &hss)
if err != nil {
return nil
}
info, err := ss.RetrieveDiskPartitionInfo(ctx, path)
if err != nil {
return err
}
return cmd.WriteResult(partitionInfo(*info))
}
type partitionInfo types.HostDiskPartitionInfo
func (p partitionInfo) Write(w io.Writer) error {
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
fmt.Fprintf(tw, "Table format: %s\n", p.Spec.PartitionFormat)
fmt.Fprintf(tw, "Number of sectors: %d\n", p.Spec.TotalSectors)
fmt.Fprintf(tw, "\n")
fmt.Fprintf(tw, "Number\t")
fmt.Fprintf(tw, "Start\t")
fmt.Fprintf(tw, "End\t")
fmt.Fprintf(tw, "Size\t")
fmt.Fprintf(tw, "Type\t")
fmt.Fprintf(tw, "\n")
for _, e := range p.Spec.Partition {
sectors := e.EndSector - e.StartSector
fmt.Fprintf(tw, "%d\t", e.Partition)
fmt.Fprintf(tw, "%d\t", e.StartSector)
fmt.Fprintf(tw, "%d\t", e.EndSector)
fmt.Fprintf(tw, "%s\t", units.ByteSize(sectors*512))
fmt.Fprintf(tw, "%s\t", e.Type)
fmt.Fprintf(tw, "\n")
}
return tw.Flush()
}

Some files were not shown because too many files have changed in this diff Show More