mirror of https://github.com/docker/docs.git
[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:
parent
7f708edcec
commit
0aedfd201d
|
@ -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",
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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")
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
|
@ -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", ®ister{})
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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}
|
||||||
|
}
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
45
vendor/github.com/vmware/govmomi/govc/host/esxcli/firewall_info.go
generated
vendored
Normal file
45
vendor/github.com/vmware/govmomi/govc/host/esxcli/firewall_info.go
generated
vendored
Normal 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
|
||||||
|
}
|
|
@ -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.
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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()
|
||||||
|
}
|
|
@ -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
Loading…
Reference in New Issue