Fix the dependency issue (#231)

This commit is contained in:
Robbie Zhang
2018-06-21 12:09:42 -07:00
committed by GitHub
parent 027b76651d
commit 6ec1098bb8
16629 changed files with 74837 additions and 4975021 deletions

View File

@@ -1 +0,0 @@
/govc*

View File

@@ -1,346 +0,0 @@
# changelog
### 0.17.1 (2018-03-19)
* Avoid possible panic in QueryVirtualDiskInfo
* Add goreleaser to automate release process
* Fix dvs.portgroup.info filtering
### 0.17.0 (2018-02-28)
* The datastore cp and mv commands can target a different Datacenter and/or Datastore
* The datastore cp and mv commands now use VirtualDiskManager methods by default
* Add '-M' flag to vm.power command to use Datacenter.PowerOnMultiVM
* Add '-cluster' flag to license.assign command
* Add cluster vm override commands
* User server clock in session.ls
* Add session login and logout commands
* Add '-rescan-vmfs' option to host.storage.info
* Add datastore.disk inflate and shrink commands
* Add cluster.group and cluster.rule commands
* Add vm.upgrade command
* Add cpu + mem allocation support to vm.change
* Allow columns in password for guest login.
### 0.16.0 (2017-11-08)
* Add export.ovf command
* Add '-snapshot' and '-link' options to vm.clone
* Add vm.console command
* Add '-refresh' option to host.storage.info
* Add tasks and task.cancel commands
* The import.vmdk command now requires streamOptimized format
* Add view and filter support to object.collect command
* Add reboot option to host.shutdown
### 0.15.0 (2017-06-19)
* Remove FileAttr flags from guest.chmod command,
chown functionality moved to its own command
* Add optional path to guest mktemp file methods
* Add guest.touch and guest.mv commands
* Add host.shutdown command
* Add option flags to host.autostart.add
* Add object.method command
* Add options.{ls,set} commands
### 0.14.0 (2017-04-08)
* Add find command
* Add '-wait' option to vm.ip to allow a non-waiting query
* Add datastore.disk.info command
* Add bash completion script
* Add metric commands: change, ls, info, sample, reset, interval.change, interval.info
### 0.13.0 (2017-03-02)
* Add vm.guest.tools command
* Add datastore.disk.create command
* Add datastore.vsan.dom.ls and datastore.vsan.dom.rm commands
* Add vm.disk.change command
* Add vm.rdm attach and ls commands
* Add '-n' option to vm.ip to wait for a specific NIC
* Add '-annotation' option to vm.create and vm.clone commands
* Add '-sync-time-with-host-' flag to vm.change command
* Add object.collect command (MOB for cli + Emacs)
### 0.12.1 (2016-12-19)
* Add '-f' flag to logs command
* Add storage support to vm.migrate
* Add support for file backed serialport devices
### 0.12.0 (2016-12-01)
* Add optional '-host' flag to datastore download/tail commands
* Support InjectOvfEnv without PowerOn when importing
* Support stdin as import options source
* Add basic NVME controller support
### 0.11.4 (2016-11-15)
* Add role create, remove, update, ls and usage commands
### 0.11.3 (2016-11-08)
* Add `-product-version` flag to dvs.create
* datastore.tail -f will exit without error if the file no longer exists
### 0.11.2 (2016-11-01)
* Add object.reload command
* Add ESX 5.5 support to host.account commands
### 0.11.1 (2016-10-27)
* Add support for VirtualApp in pool.change command
### 0.11.0 (2016-10-25)
* Add object.destroy and object.rename commands
* Remove datacenter.destroy command (use object.destroy instead)
* Remove folder.destroy command (use object.destroy instead)
* Rename folder.move_into -> object.mv
* Add dvs.portgroup.change command
* Add vlan flag to dvs.portgroup.add command
### 0.10.0 (2016-10-20)
* Add generated govc/USAGE.md
* Add host.date info and change commands
* Add session ls and rm commands
* Add `-tls-known-hosts` and `-tls-ca-certs` flags
* Add host.cert commands : info, csr, import
* Add about.cert command (similar to the Chrome Certificate Viewer)
* Add `-vspc-proxy` flag to device.serial.connect command
* Rename license.list -> license.ls, license.assigned.list -> license.assigned.ls
### 0.9.0 (2016-09-09)
* Add `-R` option to datastore.ls
* Add datastore.tail command
* Add vm.migrate command
* Add govc vm.register and vm.unregister commands
* Add govc vm snapshot commands: create, remove, revert, tree
* Add device.usb.add command
* Support stdin/stdout in datastore upload/download
* Add host.portgroup.change command
* Add host.portgroup.info command
* Add HostNetworkPolicy to host.vswitch.info
* Add `-json` support to host.vswitch.info command
* Support instance uuid in SearchFlag
* Add `-json` support to esxcli command
* Add `-unclaimed` flag to host.storage.info command
* Support Network mapping in import.{ova,ovf} commands
### 0.8.0 (2016-06-30)
* If username (`-u` / GOVC_USERNAME) is empty, attempt login via local ticket (Workstation)
* Add StoragePod support to govc folder.create
* Add `-folder` flag to datacenter.create command
* Logout when session persistence is disabled
* Add `-L` flag to ls command for resolving by managed object reference
* Add `-i` flag to ls command for listing the managed object reference
* Add vm.markasvm command
* Add vm.markastemplate command
### 0.7.1 (2016-06-03)
* Fix datastore.{upload,download} against VirtualCenter
### 0.7.0 (2016-06-02)
* Add `-require` flag to version command
* Add support for local type in the datastore.create command
* Add `-namespace` option to datastore.mkdir and datastore.rm to create/remove namespaces on VSANs
* Add host.service command
* Add host.storage.mark command
* Add `-rescan` option to host.storage.info command
### 0.6.0 (2016-04-29)
* Add folder commands: info, create, destroy, rename, moveinto
* Add datastore.info command
* Add `-a` and `-v4` flags to vm.ip command
* Add host.account.{create,update,remove} commands
* Add env command
* Add vm.clone command
### 0.5.0 (2016-03-30)
* Add dvs.portgroup.info command
* Add `-folder` flag to vm.create command
* Add `-dump` flag to OutputFlag
* Add `-f` flag to events command
* Add `-mode` flag to vm.disk.create command
* Add `-net` flag to device.info command
* Add `-eager` and `-thick` options to vm.create command
### 0.4.0 (2016-02-26)
* Add support for placement in datastore cluster to vm.create command
* Add support for creating new disks in vm.create command
* 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 `import.spec` to produce an example json document
* Add `-options` 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 `GOVC_USERNAME` and `GOVC_PASSWORD` to allow overriding username and/or
password (used when they contain special characters that prevent them from
being embedded in the URL).
* Add `-e' (ExtraConfig) option to `vm.change` and `vm.info`
* Retry twice on temporary network errors.
* Add `host.autostart` commands to manage VM autostart.
* Add `-persist-session` flag to control whether or not the session is
persisted to disk (defaults to true).
### 0.1.0 (2015-03-17)
Prior to this version the changes to govc's command set were not documented.

View File

@@ -1,211 +0,0 @@
# govc
govc is a vSphere CLI built on top of govmomi.
The CLI is designed to be a user friendly CLI alternative to the GUI and well suited for automation tasks.
It also acts as a [test harness](test) for the govmomi APIs and provides working examples of how to use the APIs.
## Installation
You can find prebuilt govc binaries on the [releases page](https://github.com/vmware/govmomi/releases).
Download and install a binary locally like this:
``` console
% curl -L $URL_TO_BINARY | gunzip > /usr/local/bin/govc
% chmod +x /usr/local/bin/govc
```
### Source
To build govc from source, first install the [Go toolchain](https://golang.org/dl/).
Make sure to set the environment variable [GOPATH](https://github.com/golang/go/wiki/SettingGOPATH).
You can then install the latest govc from github using:
``` console
% go get -u github.com/vmware/govmomi/govc
```
Make sure `$GOPATH/bin` is in your `PATH` to use the version installed from source.
If you've made local modifications to the repository at `$GOPATH/src/github.com/vmware/govmomi`, you can install using:
``` console
% go install github.com/vmware/govmomi/govc
```
## Usage
For the complete list of commands and flags, refer to the [USAGE](USAGE.md) document.
Common flags include:
* `-u`: ESXi or vCenter URL (ex: `user:pass@host`)
* `-debug`: Trace requests and responses (to `~/.govmomi/debug`)
Managed entities can be referred to by their absolute path or by their relative
path. For example, when specifying a datastore to use for a subcommand, you can
either specify it as `/mydatacenter/datastore/mydatastore`, or as
`mydatastore`. If you're not sure about the name of the datastore, or even the
full path to the datastore, you can specify a pattern to match. Both
`/*center/*/my*` (absolute) and `my*store` (relative) will resolve to the same
datastore, given there are no other datastores that match those globs.
The relative path in this example can only be used if the command can
umambigously resolve a datacenter to use as origin for the query. If no
datacenter is specified, govc defaults to the only datacenter, if there is only
one. The datacenter itself can be specified as a pattern as well, enabling the
following arguments: `-dc='my*' -ds='*store'`. The datastore pattern is looked
up and matched relative to the datacenter which itself is specified as a
pattern.
Besides specifying managed entities as arguments, they can also be specified
using environment variables. The following environment variables are used by govc
to set defaults:
* `GOVC_URL`: URL of ESXi or vCenter instance to connect to.
The URL scheme defaults to `https` and the URL path defaults to `/sdk`.
This means that specifying `user:pass@host` is equivalent to
`https://user:pass@host/sdk`.
If password include special characters like `#` or `:` you can use
`GOVC_USERNAME` and `GOVC_PASSWORD` to have a simple `GOVC_URL`
When using govc against VMware Workstation, GOVC_URL can be set to "localhost"
without a user or pass, in which case local ticket based authentication is used.
* `GOVC_USERNAME`: USERNAME to use if not specified in GOVC_URL.
* `GOVC_PASSWORD`: PASSWORD to use if not specified in GOVC_URL.
* `GOVC_TLS_CA_CERTS`: Override system root certificate authorities.
``` console
$ export GOVC_TLS_CA_CERTS=~/.govc_ca.crt
# Use path separator to specify multiple files:
$ export GOVC_TLS_CA_CERTS=~/ca-certificates/bar.crt:~/ca-certificates/foo.crt
```
* `GOVC_TLS_KNOWN_HOSTS`: File(s) for thumbprint based certificate verification.
Thumbprint based verification can be used in addition to or as an alternative to
`GOVC_TLS_CA_CERTS` for self-signed certificates. Example:
``` console
$ export GOVC_TLS_KNOWN_HOSTS=~/.govc_known_hosts
$ govc about.cert -u host -k -thumbprint | tee -a $GOVC_TLS_KNOWN_HOSTS
$ govc about -u user:pass@host
```
* `GOVC_TLS_HANDSHAKE_TIMEOUT`: Limits the time spent performing the TLS handshake.
* `GOVC_INSECURE`: Disable certificate verification.
This option sets Go's `tls.Config.InsecureSkipVerify` flag and is false by default.
Quoting https://golang.org/pkg/crypto/tls/#Config:
> `InsecureSkipVerify` controls whether a client verifies the
> server's certificate chain and host name.
>
> If `InsecureSkipVerify` is true, TLS accepts any certificate
> presented by the server and any host name in that certificate.
>
> In this mode, TLS is susceptible to man-in-the-middle attacks.
> This should be used only for testing.
* `GOVC_DATACENTER`
* `GOVC_DATASTORE`
* `GOVC_NETWORK`
* `GOVC_RESOURCE_POOL`
* `GOVC_HOST`
* `GOVC_GUEST_LOGIN`: Guest credentials for guest operations
* `GOVC_VIM_NAMESPACE`: Vim namespace defaults to `urn:vim25`
* `GOVC_VIM_VERSION`: Vim version defaults to `6.0`
## Troubleshooting
### Environment variables
If you're using environment variables to set `GOVC_URL`, verify the values are set as expected:
``` console
% govc env
```
### Connection issues
Check your proxy settings:
``` console
% env | grep -i https_proxy
```
Test connection using curl:
``` console
% curl --verbose -k -X POST https://x.x.x.x/sdk
```
### MSYS2 (Windows)
Inventory path arguments with a leading '/' are subject
to [Posix path conversion](http://www.mingw.org/wiki/Posix_path_conversion).
## Examples
Several examples are embedded in the govc command [help](USAGE.md)
* [Upload ssh public key to a VM](examples/lib/ssh.sh)
* [Create a CoreOS VM](https://github.com/vmware/govmomi/blob/master/toolbox/toolbox-test.sh)
* [Create a Debian VM](https://github.com/kubernetes/kubernetes/tree/master/cluster/vsphere)
* [Create a Windows VM](https://github.com/dougm/govc-windows-box/blob/master/provision-esx.sh)
* [Create an ESX VM](../scripts/vcsa/create-esxi-vm.sh)
* [Create a vCenter VM](../scripts/vcsa/create-vcsa-vm.sh)
* [Create a Cluster](../scripts/vcsa/create-cluster.sh)
## Status
Changes to the cli are subject to [semantic versioning](http://semver.org).
Refer to the [CHANGELOG](CHANGELOG.md) for version to version changes.
When new govc commands or flags are added, the PATCH version will be incremented. This enables you to require a minimum
version from within a script, for example:
``` console
% govc version -require 0.14
```
## Projects using govc
* [Emacs govc package](./emacs)
* [Kubernetes vSphere Provider](https://github.com/kubernetes/kubernetes/tree/master/cluster/vsphere)
* [VMware VIC Engine](https://github.com/vmware/vic)
* [vSphere Docker Volume Service](https://github.com/vmware/docker-volume-vsphere)
* [golang/build](https://github.com/golang/build)
## Related projects
* [rvc](https://github.com/vmware/rvc)
## License
govc is available under the [Apache 2 license](../LICENSE).

File diff suppressed because it is too large Load Diff

View File

@@ -1,120 +0,0 @@
/*
Copyright (c) 2016 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 about
import (
"context"
"encoding/pem"
"flag"
"fmt"
"io"
"net/http"
"os"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/soap"
)
type cert struct {
*flags.ClientFlag
*flags.OutputFlag
show bool
thumbprint bool
}
func init() {
cli.Register("about.cert", &cert{})
}
func (cmd *cert) 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)
f.BoolVar(&cmd.show, "show", false, "Show PEM encoded server certificate only")
f.BoolVar(&cmd.thumbprint, "thumbprint", false, "Output host hash and thumbprint only")
}
func (cmd *cert) Description() string {
return `Display TLS certificate info for HOST.
If the HOST certificate cannot be verified, about.cert will return with exit code 60 (as curl does).
If the '-k' flag is provided, about.cert will return with exit code 0 in this case.
The SHA1 thumbprint can also be used as '-thumbprint' for the 'host.add' and 'cluster.add' commands.
Examples:
govc about.cert -k -json | jq -r .ThumbprintSHA1
govc about.cert -k -show | sudo tee /usr/local/share/ca-certificates/host.crt
govc about.cert -k -thumbprint | tee -a ~/.govmomi/known_hosts`
}
func (cmd *cert) 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
}
type certResult struct {
cmd *cert
info object.HostCertificateInfo
}
func (r *certResult) Write(w io.Writer) error {
if r.cmd.show {
return pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: r.info.Certificate.Raw})
}
if r.cmd.thumbprint {
u := r.cmd.URLWithoutPassword()
_, err := fmt.Fprintf(w, "%s %s\n", u.Host, r.info.ThumbprintSHA1)
return err
}
return r.cmd.WriteResult(&r.info)
}
func (cmd *cert) Run(ctx context.Context, f *flag.FlagSet) error {
u := cmd.URLWithoutPassword()
c := soap.NewClient(u, false)
t := c.Client.Transport.(*http.Transport)
r := certResult{cmd: cmd}
if err := cmd.SetRootCAs(c); err != nil {
return err
}
if err := r.info.FromURL(u, t.TLSClientConfig); err != nil {
return err
}
if r.info.Err != nil && r.cmd.IsSecure() {
cmd.Out = os.Stderr
// using same exit code as curl:
defer os.Exit(60)
}
return r.Write(cmd.Out)
}

View File

@@ -1,116 +0,0 @@
/*
Copyright (c) 2014-2016 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 about
import (
"context"
"flag"
"fmt"
"io"
"text/tabwriter"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)
type about struct {
*flags.ClientFlag
*flags.OutputFlag
Long bool
}
func init() {
cli.Register("about", &about{})
}
func (cmd *about) 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)
f.BoolVar(&cmd.Long, "l", false, "Include service content")
}
func (cmd *about) Description() string {
return `Display About info for HOST.
System information including the name, type, version, and build number.
Examples:
govc about
govc about -json | jq -r .About.ProductLineId`
}
func (cmd *about) 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 *about) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
res := infoResult{
a: &c.ServiceContent.About,
}
if cmd.Long {
res.Content = &c.ServiceContent
} else {
res.About = res.a
}
return cmd.WriteResult(&res)
}
type infoResult struct {
Content *types.ServiceContent `json:",omitempty"`
About *types.AboutInfo `json:",omitempty"`
a *types.AboutInfo
}
func (r *infoResult) Write(w io.Writer) error {
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
fmt.Fprintf(tw, "Name:\t%s\n", r.a.Name)
fmt.Fprintf(tw, "Vendor:\t%s\n", r.a.Vendor)
fmt.Fprintf(tw, "Version:\t%s\n", r.a.Version)
fmt.Fprintf(tw, "Build:\t%s\n", r.a.Build)
fmt.Fprintf(tw, "OS type:\t%s\n", r.a.OsType)
fmt.Fprintf(tw, "API type:\t%s\n", r.a.ApiType)
fmt.Fprintf(tw, "API version:\t%s\n", r.a.ApiVersion)
fmt.Fprintf(tw, "Product ID:\t%s\n", r.a.ProductLineId)
fmt.Fprintf(tw, "UUID:\t%s\n", r.a.InstanceUuid)
return tw.Flush()
}
func (r *infoResult) Dump() interface{} {
if r.Content != nil {
return r.Content
}
return r.About
}

View File

@@ -1,37 +0,0 @@
#!/bin/bash -e
git_version=$(git describe --dirty)
if [[ $git_version == *-dirty ]] ; then
echo 'Working tree is dirty.'
echo 'NOTE: This script is meant for building govc releases via release.sh'
echo 'To build govc from source see: https://github.com/vmware/govmomi/blob/master/govc/README.md#source'
exit 1
fi
ldflags="-X github.com/vmware/govmomi/govc/version.gitVersion=${git_version}"
BUILD_OS=${BUILD_OS:-darwin linux windows freebsd}
BUILD_ARCH=${BUILD_ARCH:-386 amd64}
for os in ${BUILD_OS}; do
export GOOS="${os}"
for arch in ${BUILD_ARCH}; do
export GOARCH="${arch}"
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
wait

View File

@@ -1,179 +0,0 @@
/*
Copyright (c) 2014-2016 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 (
"context"
"flag"
"fmt"
"io"
"io/ioutil"
"os"
"sort"
"text/tabwriter"
"github.com/vmware/govmomi/vim25/types"
)
type HasFlags interface {
// Register may be called more than once and should be idempotent.
Register(ctx context.Context, f *flag.FlagSet)
// Process may be called more than once and should be idempotent.
Process(ctx context.Context) error
}
type Command interface {
HasFlags
Run(ctx context.Context, f *flag.FlagSet) error
}
func generalHelp(w io.Writer) {
fmt.Fprintf(w, "Usage of %s:\n", os.Args[0])
cmds := []string{}
for name := range commands {
cmds = append(cmds, name)
}
sort.Strings(cmds)
for _, name := range cmds {
fmt.Fprintf(w, " %s\n", name)
}
}
func commandHelp(w io.Writer, name string, cmd Command, f *flag.FlagSet) {
type HasUsage interface {
Usage() string
}
fmt.Fprintf(w, "Usage: %s %s [OPTIONS]", os.Args[0], name)
if u, ok := cmd.(HasUsage); ok {
fmt.Fprintf(w, " %s", u.Usage())
}
fmt.Fprintf(w, "\n")
type HasDescription interface {
Description() string
}
if u, ok := cmd.(HasDescription); ok {
fmt.Fprintf(w, "\n%s\n", u.Description())
}
n := 0
f.VisitAll(func(_ *flag.Flag) {
n += 1
})
if n > 0 {
fmt.Fprintf(w, "\nOptions:\n")
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
f.VisitAll(func(f *flag.Flag) {
fmt.Fprintf(tw, "\t-%s=%s\t%s\n", f.Name, f.DefValue, f.Usage)
})
tw.Flush()
}
}
func clientLogout(ctx context.Context, cmd Command) error {
type logout interface {
Logout(context.Context) error
}
if l, ok := cmd.(logout); ok {
return l.Logout(ctx)
}
return nil
}
func Run(args []string) int {
hw := os.Stderr
rc := 1
hwrc := func(arg string) {
if arg == "-h" {
hw = os.Stdout
rc = 0
}
}
var err error
if len(args) == 0 {
generalHelp(hw)
return rc
}
// Look up real command name in aliases table.
name, ok := aliases[args[0]]
if !ok {
name = args[0]
}
cmd, ok := commands[name]
if !ok {
hwrc(name)
generalHelp(hw)
return rc
}
fs := flag.NewFlagSet("", flag.ContinueOnError)
fs.SetOutput(ioutil.Discard)
ctx := context.Background()
if id := os.Getenv("GOVC_OPERATION_ID"); id != "" {
ctx = context.WithValue(ctx, types.ID{}, id)
}
cmd.Register(ctx, fs)
if err = fs.Parse(args[1:]); err != nil {
goto error
}
if err = cmd.Process(ctx); err != nil {
goto error
}
if err = cmd.Run(ctx, fs); err != nil {
goto error
}
if err = clientLogout(ctx, cmd); err != nil {
goto error
}
return 0
error:
if err == flag.ErrHelp {
if len(args) == 2 {
hwrc(args[1])
}
commandHelp(hw, args[0], cmd, fs)
} else {
fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], err)
}
_ = clientLogout(ctx, cmd)
return rc
}

View File

@@ -1,33 +0,0 @@
/*
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 cli
var commands = map[string]Command{}
var aliases = map[string]string{}
func Register(name string, c Command) {
commands[name] = c
}
func Alias(name string, alias string) {
aliases[alias] = name
}
func Commands() map[string]Command {
return commands
}

View File

@@ -1,114 +0,0 @@
/*
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 (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
)
type add struct {
*flags.ClusterFlag
*flags.HostConnectFlag
connect bool
license string
}
func init() {
cli.Register("cluster.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClusterFlag, ctx = flags.NewClusterFlag(ctx)
cmd.ClusterFlag.Register(ctx, f)
cmd.HostConnectFlag, ctx = flags.NewHostConnectFlag(ctx)
cmd.HostConnectFlag.Register(ctx, f)
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.ClusterFlag.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.
Examples:
thumbprint=$(govc about.cert -k -u host.example.com -thumbprint | awk '{print $2}')
govc cluster.add -cluster ClusterA -hostname host.example.com -username root -password pass -thumbprint $thumbprint
govc cluster.add -cluster ClusterB -hostname 10.0.6.1 -username root -password pass -noverify`
}
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, cmd.Spec(cluster.Client()), 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
}
cluster, err := cmd.Cluster()
if err != nil {
return err
}
return cmd.Fault(cmd.Add(ctx, cluster))
}

View File

@@ -1,116 +0,0 @@
/*
Copyright (c) 2015-2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cluster
import (
"context"
"flag"
"strings"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)
func DrsBehaviorUsage() string {
drsModes := []string{
string(types.DrsBehaviorManual),
string(types.DrsBehaviorPartiallyAutomated),
string(types.DrsBehaviorFullyAutomated),
}
return "DRS behavior for virtual machines: " + strings.Join(drsModes, ", ")
}
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")
f.StringVar((*string)(&cmd.DrsConfig.DefaultVmBehavior), "drs-mode", "", DrsBehaviorUsage())
// 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", "Autoclaim storage on cluster hosts")
}
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.
Examples:
govc cluster.change -drs-enabled -vsan-enabled -vsan-autoclaim ClusterA
govc cluster.change -drs-enabled=false ClusterB`
}
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
}

View File

@@ -1,78 +0,0 @@
/*
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 (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)
type create struct {
*flags.FolderFlag
types.ClusterConfigSpecEx
}
func init() {
cli.Register("cluster.create", &create{})
}
func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx)
cmd.FolderFlag.Register(ctx, f)
}
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 'folder' flag. If not given,
this defaults to the host folder in the specified or default datacenter.
Examples:
govc cluster.create ClusterA
govc cluster.create -folder /dc2/test-folder ClusterB`
}
func (cmd *create) Process(ctx context.Context) error {
if err := cmd.FolderFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 1 {
return flag.ErrHelp
}
folder, err := cmd.FolderOrDefault("host")
if err != nil {
return err
}
_, err = folder.CreateCluster(ctx, f.Arg(0), cmd.ClusterConfigSpecEx)
return err
}

View File

@@ -1,75 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package group
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/vim25/types"
)
type change struct {
*InfoFlag
}
func init() {
cli.Register("cluster.group.change", &change{})
}
func (cmd *change) Register(ctx context.Context, f *flag.FlagSet) {
cmd.InfoFlag, ctx = NewInfoFlag(ctx)
cmd.InfoFlag.Register(ctx, f)
}
func (cmd *change) Process(ctx context.Context) error {
if cmd.name == "" {
return flag.ErrHelp
}
return cmd.InfoFlag.Process(ctx)
}
func (cmd *change) Usage() string {
return `NAME...`
}
func (cmd *change) Description() string {
return `Set cluster group members.
Examples:
govc cluster.group.change -name my_group vm_a vm_b vm_c # set
govc cluster.group.change -name my_group vm_a vm_b vm_c $(govc cluster.group.ls -name my_group) vm_d # add
govc cluster.group.ls -name my_group | grep -v vm_b | xargs govc cluster.group.change -name my_group vm_a vm_b vm_c # remove`
}
func (cmd *change) Run(ctx context.Context, f *flag.FlagSet) error {
update := types.ArrayUpdateSpec{Operation: types.ArrayUpdateOperationEdit}
group, err := cmd.Group(ctx)
if err != nil {
return err
}
refs, err := cmd.ObjectList(ctx, group.kind, f.Args())
if err != nil {
return err
}
*group.refs = refs
return cmd.Apply(ctx, update, group.info)
}

View File

@@ -1,86 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package group
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/vim25/types"
)
type create struct {
*InfoFlag
vm bool
host bool
}
func init() {
cli.Register("cluster.group.create", &create{})
}
func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
cmd.InfoFlag, ctx = NewInfoFlag(ctx)
cmd.InfoFlag.Register(ctx, f)
f.BoolVar(&cmd.vm, "vm", false, "Create cluster VM group")
f.BoolVar(&cmd.host, "host", false, "Create cluster Host group")
}
func (cmd *create) Process(ctx context.Context) error {
if cmd.name == "" {
return flag.ErrHelp
}
return cmd.InfoFlag.Process(ctx)
}
func (cmd *create) Description() string {
return `Create cluster group.
One of '-vm' or '-host' must be provided to specify the group type.
Examples:
govc cluster.group.create -name my_vm_group -vm vm_a vm_b vm_c
govc cluster.group.create -name my_host_group -host host_a host_b host_c`
}
func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
update := types.ArrayUpdateSpec{Operation: types.ArrayUpdateOperationAdd}
var info types.BaseClusterGroupInfo
var err error
switch {
case cmd.vm:
info = new(types.ClusterVmGroup)
case cmd.host:
info = new(types.ClusterHostGroup)
default:
return flag.ErrHelp
}
info.GetClusterGroupInfo().Name = cmd.name
group := newGroupInfo(info)
*group.refs, err = cmd.ObjectList(ctx, group.kind, f.Args())
if err != nil {
return err
}
return cmd.Apply(ctx, update, info)
}

View File

@@ -1,121 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package group
import (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)
type InfoFlag struct {
*flags.ClusterFlag
groups []types.BaseClusterGroupInfo
name string
}
func NewInfoFlag(ctx context.Context) (*InfoFlag, context.Context) {
f := &InfoFlag{}
f.ClusterFlag, ctx = flags.NewClusterFlag(ctx)
return f, ctx
}
func (f *InfoFlag) Register(ctx context.Context, fs *flag.FlagSet) {
f.ClusterFlag.Register(ctx, fs)
fs.StringVar(&f.name, "name", "", "Cluster group name")
}
func (f *InfoFlag) Process(ctx context.Context) error {
return f.ClusterFlag.Process(ctx)
}
func (f *InfoFlag) Groups(ctx context.Context) ([]types.BaseClusterGroupInfo, error) {
if f.groups != nil {
return f.groups, nil
}
cluster, err := f.Cluster()
if err != nil {
return nil, err
}
config, err := cluster.Configuration(ctx)
if err != nil {
return nil, err
}
f.groups = config.Group
return f.groups, nil
}
type ClusterGroupInfo struct {
info types.BaseClusterGroupInfo
refs *[]types.ManagedObjectReference
kind string
}
func newGroupInfo(info types.BaseClusterGroupInfo) *ClusterGroupInfo {
group := &ClusterGroupInfo{info: info}
switch info := info.(type) {
case *types.ClusterHostGroup:
group.refs = &info.Host
group.kind = "HostSystem"
case *types.ClusterVmGroup:
group.refs = &info.Vm
group.kind = "VirtualMachine"
}
return group
}
func (f *InfoFlag) Group(ctx context.Context) (*ClusterGroupInfo, error) {
groups, err := f.Groups(ctx)
if err != nil {
return nil, err
}
for _, group := range groups {
if group.GetClusterGroupInfo().Name == f.name {
return newGroupInfo(group), nil
}
}
return nil, fmt.Errorf("group %q not found", f.name)
}
func (f *InfoFlag) Apply(ctx context.Context, update types.ArrayUpdateSpec, info types.BaseClusterGroupInfo) error {
spec := &types.ClusterConfigSpecEx{
GroupSpec: []types.ClusterGroupSpec{
{
ArrayUpdateSpec: update,
Info: info,
},
},
}
return f.Reconfigure(ctx, spec)
}

View File

@@ -1,92 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package group
import (
"context"
"flag"
"fmt"
"io"
"github.com/vmware/govmomi/govc/cli"
)
type ls struct {
*InfoFlag
}
func init() {
cli.Register("cluster.group.ls", &ls{})
}
func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
cmd.InfoFlag, ctx = NewInfoFlag(ctx)
cmd.InfoFlag.Register(ctx, f)
}
func (cmd *ls) Process(ctx context.Context) error {
return cmd.InfoFlag.Process(ctx)
}
func (cmd *ls) Description() string {
return `List cluster groups and group members.
Examples:
govc cluster.group.ls -cluster my_cluster
govc cluster.group.ls -cluster my_cluster -name my_group`
}
type groupResult []string
func (r groupResult) Write(w io.Writer) error {
for i := range r {
fmt.Fprintln(w, r[i])
}
return nil
}
func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
var res groupResult
if cmd.name == "" {
groups, err := cmd.Groups(ctx)
if err != nil {
return err
}
for _, g := range groups {
res = append(res, g.GetClusterGroupInfo().Name)
}
} else {
group, err := cmd.Group(ctx)
if err != nil {
return err
}
names, err := cmd.Names(ctx, *group.refs)
if err != nil {
return err
}
for _, ref := range *group.refs {
res = append(res, names[ref])
}
}
return cmd.WriteResult(res)
}

View File

@@ -1,61 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package group
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/vim25/types"
)
type remove struct {
*InfoFlag
}
func init() {
cli.Register("cluster.group.remove", &remove{})
}
func (cmd *remove) Register(ctx context.Context, f *flag.FlagSet) {
cmd.InfoFlag, ctx = NewInfoFlag(ctx)
cmd.InfoFlag.Register(ctx, f)
}
func (cmd *remove) Process(ctx context.Context) error {
if cmd.name == "" {
return flag.ErrHelp
}
return cmd.InfoFlag.Process(ctx)
}
func (cmd *remove) Description() string {
return `Remove cluster group.
Examples:
govc cluster.group.remove -cluster my_cluster -name my_group`
}
func (cmd *remove) Run(ctx context.Context, f *flag.FlagSet) error {
update := types.ArrayUpdateSpec{
Operation: types.ArrayUpdateOperationRemove,
RemoveKey: cmd.name,
}
return cmd.Apply(ctx, update, nil)
}

View File

@@ -1,148 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package override
import (
"context"
"flag"
"strings"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/cluster"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)
type change struct {
*flags.ClusterFlag
*flags.VirtualMachineFlag
drs types.ClusterDrsVmConfigInfo
das types.ClusterDasVmConfigInfo
}
func init() {
cli.Register("cluster.override.change", &change{})
}
func (cmd *change) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClusterFlag, ctx = flags.NewClusterFlag(ctx)
cmd.ClusterFlag.Register(ctx, f)
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
// DRS
f.Var(flags.NewOptionalBool(&cmd.drs.Enabled), "drs-enabled", "Enable DRS")
f.StringVar((*string)(&cmd.drs.Behavior), "drs-mode", "", cluster.DrsBehaviorUsage())
// HA
rp := []string{
string(types.DasVmPriorityDisabled),
string(types.DasVmPriorityLow),
string(types.DasVmPriorityMedium),
string(types.DasVmPriorityHigh),
}
cmd.das.DasSettings = new(types.ClusterDasVmSettings)
f.StringVar((*string)(&cmd.das.DasSettings.RestartPriority), "ha-restart-priority", "", "HA restart priority: "+strings.Join(rp, ", "))
}
func (cmd *change) Description() string {
return `Change cluster VM overrides.
Examples:
govc cluster.override.change -cluster cluster_1 -vm vm_1 -ha-restart-priority high
govc cluster.override.change -cluster cluster_1 -vm vm_2 -drs-enabled=false
govc cluster.override.change -cluster cluster_1 -vm vm_3 -drs-enabled -drs-mode fullyAutomated`
}
func (cmd *change) Process(ctx context.Context) error {
if err := cmd.ClusterFlag.Process(ctx); err != nil {
return err
}
return cmd.VirtualMachineFlag.Process(ctx)
}
func (cmd *change) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
cluster, err := cmd.Cluster()
if err != nil {
return err
}
config, err := cluster.Configuration(ctx)
if err != nil {
return err
}
spec := &types.ClusterConfigSpecEx{}
cmd.drs.Key = vm.Reference()
cmd.das.Key = vm.Reference()
if cmd.drs.Behavior != "" || cmd.drs.Enabled != nil {
op := types.ArrayUpdateOperationAdd
for _, c := range config.DrsVmConfig {
if c.Key == cmd.drs.Key {
op = types.ArrayUpdateOperationEdit
break
}
}
spec.DrsVmConfigSpec = []types.ClusterDrsVmConfigSpec{
{
ArrayUpdateSpec: types.ArrayUpdateSpec{
Operation: op,
},
Info: &cmd.drs,
},
}
}
if cmd.das.DasSettings.RestartPriority != "" {
op := types.ArrayUpdateOperationAdd
for _, c := range config.DasVmConfig {
if c.Key == cmd.das.Key {
op = types.ArrayUpdateOperationEdit
break
}
}
spec.DasVmConfigSpec = []types.ClusterDasVmConfigSpec{
{
ArrayUpdateSpec: types.ArrayUpdateSpec{
Operation: op,
},
Info: &cmd.das,
},
}
}
if spec.DrsVmConfigSpec == nil && spec.DasVmConfigSpec == nil {
return flag.ErrHelp
}
return cmd.Reconfigure(ctx, spec)
}

View File

@@ -1,142 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package override
import (
"context"
"flag"
"fmt"
"io"
"strings"
"text/tabwriter"
"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.ClusterFlag
}
func init() {
cli.Register("cluster.override.info", &info{})
}
func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClusterFlag, ctx = flags.NewClusterFlag(ctx)
cmd.ClusterFlag.Register(ctx, f)
}
func (cmd *info) Description() string {
return `Cluster VM overrides info.
Examples:
govc cluster.override.info
govc cluster.override.info -json`
}
func (cmd *info) Process(ctx context.Context) error {
return cmd.ClusterFlag.Process(ctx)
}
type Override struct {
id types.ManagedObjectReference
Name string
Host string `json:",omitempty"`
DRS *types.ClusterDrsVmConfigInfo `json:",omitempty"`
DAS *types.ClusterDasVmConfigInfo `json:",omitempty"`
}
type infoResult struct {
Overrides map[string]*Override
}
func (r *infoResult) Write(w io.Writer) error {
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
for _, entry := range r.Overrides {
behavior := fmt.Sprintf("Default (%s)", types.DrsBehaviorFullyAutomated)
if entry.DRS != nil {
if *entry.DRS.Enabled {
behavior = string(entry.DRS.Behavior)
}
}
priority := fmt.Sprintf("Default (%s)", types.DasVmPriorityMedium)
if entry.DAS != nil {
priority = entry.DAS.DasSettings.RestartPriority
}
fmt.Fprintf(tw, "Name:\t%s\n", entry.Name)
fmt.Fprintf(tw, " DRS Automation Level:\t%s\n", strings.Title(behavior))
fmt.Fprintf(tw, " HA Restart Priority:\t%s\n", strings.Title(priority))
fmt.Fprintf(tw, " Host:\t%s\n", entry.Host)
}
return tw.Flush()
}
func (r *infoResult) entry(id types.ManagedObjectReference) *Override {
key := id.String()
vm, ok := r.Overrides[key]
if !ok {
r.Overrides[key] = &Override{id: id}
vm = r.Overrides[key]
}
return vm
}
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
cluster, err := cmd.Cluster()
if err != nil {
return err
}
config, err := cluster.Configuration(ctx)
if err != nil {
return err
}
res := &infoResult{
Overrides: make(map[string]*Override),
}
for i := range config.DasVmConfig {
vm := res.entry(config.DasVmConfig[i].Key)
vm.DAS = &config.DasVmConfig[i]
}
for i := range config.DrsVmConfig {
vm := res.entry(config.DrsVmConfig[i].Key)
vm.DRS = &config.DrsVmConfig[i]
}
for _, o := range res.Overrides {
// TODO: can optimize to reduce round trips
vm := object.NewVirtualMachine(cluster.Client(), o.id)
o.Name, _ = vm.ObjectName(ctx)
if h, herr := vm.HostSystem(ctx); herr == nil {
o.Host, _ = h.ObjectName(ctx)
}
}
return cmd.WriteResult(res)
}

View File

@@ -1,110 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package override
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)
type remove struct {
*flags.ClusterFlag
*flags.VirtualMachineFlag
}
func init() {
cli.Register("cluster.override.remove", &remove{})
}
func (cmd *remove) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClusterFlag, ctx = flags.NewClusterFlag(ctx)
cmd.ClusterFlag.Register(ctx, f)
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
}
func (cmd *remove) Description() string {
return `Remove cluster VM overrides.
Examples:
govc cluster.override.remove -cluster cluster_1 -vm vm_1`
}
func (cmd *remove) Process(ctx context.Context) error {
if err := cmd.ClusterFlag.Process(ctx); err != nil {
return err
}
return cmd.VirtualMachineFlag.Process(ctx)
}
func (cmd *remove) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
cluster, err := cmd.Cluster()
if err != nil {
return err
}
config, err := cluster.Configuration(ctx)
if err != nil {
return err
}
spec := &types.ClusterConfigSpecEx{}
ref := vm.Reference()
for _, c := range config.DrsVmConfig {
if c.Key == ref {
spec.DrsVmConfigSpec = []types.ClusterDrsVmConfigSpec{
{
ArrayUpdateSpec: types.ArrayUpdateSpec{
Operation: types.ArrayUpdateOperationRemove,
RemoveKey: ref,
},
},
}
break
}
}
for _, c := range config.DasVmConfig {
if c.Key == ref {
spec.DasVmConfigSpec = []types.ClusterDasVmConfigSpec{
{
ArrayUpdateSpec: types.ArrayUpdateSpec{
Operation: types.ArrayUpdateOperationRemove,
RemoveKey: ref,
},
},
}
break
}
}
return cmd.Reconfigure(ctx, spec)
}

View File

@@ -1,93 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package rule
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/vim25/types"
)
type change struct {
*SpecFlag
*InfoFlag
}
func init() {
cli.Register("cluster.rule.change", &change{})
}
func (cmd *change) Register(ctx context.Context, f *flag.FlagSet) {
cmd.SpecFlag = new(SpecFlag)
cmd.SpecFlag.Register(ctx, f)
cmd.InfoFlag, ctx = NewInfoFlag(ctx)
cmd.InfoFlag.Register(ctx, f)
}
func (cmd *change) Process(ctx context.Context) error {
if cmd.name == "" {
return flag.ErrHelp
}
return cmd.InfoFlag.Process(ctx)
}
func (cmd *change) Usage() string {
return `NAME...`
}
func (cmd *change) Description() string {
return `Change cluster rule.
Examples:
govc cluster.rule.change -cluster my_cluster -name my_rule -enable=false`
}
func (cmd *change) Run(ctx context.Context, f *flag.FlagSet) error {
update := types.ArrayUpdateSpec{Operation: types.ArrayUpdateOperationEdit}
rule, err := cmd.Rule(ctx)
if err != nil {
return err
}
var vms *[]types.ManagedObjectReference
switch r := rule.info.(type) {
case *types.ClusterAffinityRuleSpec:
vms = &r.Vm
case *types.ClusterAntiAffinityRuleSpec:
vms = &r.Vm
}
if vms != nil && f.NArg() != 0 {
refs, err := cmd.ObjectList(ctx, rule.kind, f.Args())
if err != nil {
return err
}
*vms = refs
}
info := rule.info.GetClusterRuleInfo()
info.Name = cmd.name
info.Enabled = cmd.Enabled
info.Mandatory = cmd.Mandatory
return cmd.Apply(ctx, update, rule.info)
}

View File

@@ -1,136 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package rule
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/vim25/types"
)
type create struct {
*SpecFlag
*InfoFlag
vmhost bool
affinity bool
antiaffinity bool
depends bool
}
func init() {
cli.Register("cluster.rule.create", &create{})
}
func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
cmd.SpecFlag = new(SpecFlag)
cmd.SpecFlag.Register(ctx, f)
cmd.InfoFlag, ctx = NewInfoFlag(ctx)
cmd.InfoFlag.Register(ctx, f)
f.BoolVar(&cmd.vmhost, "vm-host", false, "Virtual Machines to Hosts")
f.BoolVar(&cmd.affinity, "affinity", false, "Keep Virtual Machines Together")
f.BoolVar(&cmd.antiaffinity, "anti-affinity", false, "Separate Virtual Machines")
f.BoolVar(&cmd.depends, "depends", false, "Virtual Machines to Virtual Machines")
}
func (cmd *create) Process(ctx context.Context) error {
if cmd.name == "" {
return flag.ErrHelp
}
return cmd.InfoFlag.Process(ctx)
}
func (cmd *create) Usage() string {
return "NAME..."
}
func (cmd *create) Description() string {
return `Create cluster rule.
Rules are not enabled by default, use the 'enable' flag to enable upon creation or cluster.rule.change after creation.
One of '-affinity', '-anti-affinity', '-depends' or '-vm-host' must be provided to specify the rule type.
With '-affinity' or '-anti-affinity', at least 2 vm NAME arguments must be specified.
With '-depends', vm group NAME and vm group dependency NAME arguments must be specified.
With '-vm-host', use the '-vm-group' flag combined with the '-host-affine-group' and/or '-host-anti-affine-group' flags.
Examples:
govc cluster.rule.create -name pod1 -enable -affinity vm_a vm_b vm_c
govc cluster.rule.create -name pod2 -enable -anti-affinity vm_d vm_e vm_f
govc cluster.rule.create -name pod3 -enable -mandatory -vm-host -vm-group my_vms -host-affine-group my_hosts
govc cluster.rule.create -name pod4 -depends vm_group_app vm_group_db`
}
func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args()
update := types.ArrayUpdateSpec{Operation: types.ArrayUpdateOperationAdd}
var rule types.BaseClusterRuleInfo
var err error
switch {
case cmd.vmhost:
rule = &cmd.ClusterVmHostRuleInfo
case cmd.affinity:
rule = &cmd.ClusterAffinityRuleSpec
if len(args) < 2 {
return flag.ErrHelp // can't create this rule without 2 or more hosts
}
cmd.ClusterAffinityRuleSpec.Vm, err = cmd.ObjectList(ctx, "VirtualMachine", args)
if err != nil {
return err
}
case cmd.antiaffinity:
rule = &cmd.ClusterAntiAffinityRuleSpec
if len(args) < 2 {
return flag.ErrHelp // can't create this rule without 2 or more hosts
}
cmd.ClusterAntiAffinityRuleSpec.Vm, err = cmd.ObjectList(ctx, "VirtualMachine", args)
if err != nil {
return err
}
case cmd.depends:
if len(args) != 2 {
return flag.ErrHelp
}
rule = &types.ClusterDependencyRuleInfo{
VmGroup: args[0],
DependsOnVmGroup: args[1],
}
default:
return flag.ErrHelp
}
if cmd.Enabled == nil {
// ClusterDependencyRuleInfo throws InvalidArgument if Enabled == nil
cmd.Enabled = types.NewBool(false)
}
info := rule.GetClusterRuleInfo()
info.Name = cmd.name
info.Enabled = cmd.Enabled
info.Mandatory = cmd.Mandatory
info.UserCreated = types.NewBool(true)
return cmd.Apply(ctx, update, rule)
}

View File

@@ -1,135 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package rule
import (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)
type InfoFlag struct {
*flags.ClusterFlag
rules []types.BaseClusterRuleInfo
name string
}
func NewInfoFlag(ctx context.Context) (*InfoFlag, context.Context) {
f := &InfoFlag{}
f.ClusterFlag, ctx = flags.NewClusterFlag(ctx)
return f, ctx
}
func (f *InfoFlag) Register(ctx context.Context, fs *flag.FlagSet) {
f.ClusterFlag.Register(ctx, fs)
fs.StringVar(&f.name, "name", "", "Cluster rule name")
}
func (f *InfoFlag) Process(ctx context.Context) error {
return f.ClusterFlag.Process(ctx)
}
func (f *InfoFlag) Rules(ctx context.Context) ([]types.BaseClusterRuleInfo, error) {
if f.rules != nil {
return f.rules, nil
}
cluster, err := f.Cluster()
if err != nil {
return nil, err
}
config, err := cluster.Configuration(ctx)
if err != nil {
return nil, err
}
f.rules = config.Rule
return f.rules, nil
}
type ClusterRuleInfo struct {
info types.BaseClusterRuleInfo
refs *[]types.ManagedObjectReference
kind string
}
func (f *InfoFlag) Rule(ctx context.Context) (*ClusterRuleInfo, error) {
rules, err := f.Rules(ctx)
if err != nil {
return nil, err
}
for _, rule := range rules {
if rule.GetClusterRuleInfo().Name != f.name {
continue
}
r := &ClusterRuleInfo{info: rule}
switch info := rule.(type) {
case *types.ClusterAffinityRuleSpec:
r.refs = &info.Vm
r.kind = "VirtualMachine"
case *types.ClusterAntiAffinityRuleSpec:
r.refs = &info.Vm
r.kind = "VirtualMachine"
}
return r, nil
}
return nil, fmt.Errorf("rule %q not found", f.name)
}
func (f *InfoFlag) Apply(ctx context.Context, update types.ArrayUpdateSpec, info types.BaseClusterRuleInfo) error {
spec := &types.ClusterConfigSpecEx{
RulesSpec: []types.ClusterRuleSpec{
{
ArrayUpdateSpec: update,
Info: info,
},
},
}
return f.Reconfigure(ctx, spec)
}
type SpecFlag struct {
types.ClusterRuleInfo
types.ClusterVmHostRuleInfo
types.ClusterAffinityRuleSpec
types.ClusterAntiAffinityRuleSpec
}
func (s *SpecFlag) Register(ctx context.Context, f *flag.FlagSet) {
f.Var(flags.NewOptionalBool(&s.Enabled), "enable", "Enable rule")
f.Var(flags.NewOptionalBool(&s.Mandatory), "mandatory", "Enforce rule compliance")
f.StringVar(&s.VmGroupName, "vm-group", "", "VM group name")
f.StringVar(&s.AffineHostGroupName, "host-affine-group", "", "Host affine group name")
f.StringVar(&s.AntiAffineHostGroupName, "host-anti-affine-group", "", "Host anti-affine group name")
}

View File

@@ -1,96 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package rule
import (
"context"
"flag"
"fmt"
"io"
"github.com/vmware/govmomi/govc/cli"
)
type ls struct {
*InfoFlag
}
func init() {
cli.Register("cluster.rule.ls", &ls{})
}
func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
cmd.InfoFlag, ctx = NewInfoFlag(ctx)
cmd.InfoFlag.Register(ctx, f)
}
func (cmd *ls) Process(ctx context.Context) error {
return cmd.InfoFlag.Process(ctx)
}
func (cmd *ls) Description() string {
return `List cluster rules and rule members.
Examples:
govc cluster.rule.ls -cluster my_cluster
govc cluster.rule.ls -cluster my_cluster -name my_rule`
}
type ruleResult []string
func (r ruleResult) Write(w io.Writer) error {
for i := range r {
fmt.Fprintln(w, r[i])
}
return nil
}
func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
var res ruleResult
if cmd.name == "" {
rules, err := cmd.Rules(ctx)
if err != nil {
return err
}
for _, g := range rules {
res = append(res, g.GetClusterRuleInfo().Name)
}
} else {
rule, err := cmd.Rule(ctx)
if err != nil {
return err
}
if rule.refs == nil {
return nil
}
names, err := cmd.Names(ctx, *rule.refs)
if err != nil {
return err
}
for _, ref := range *rule.refs {
res = append(res, names[ref])
}
}
return cmd.WriteResult(res)
}

View File

@@ -1,66 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package rule
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/vim25/types"
)
type remove struct {
*InfoFlag
}
func init() {
cli.Register("cluster.rule.remove", &remove{})
}
func (cmd *remove) Register(ctx context.Context, f *flag.FlagSet) {
cmd.InfoFlag, ctx = NewInfoFlag(ctx)
cmd.InfoFlag.Register(ctx, f)
}
func (cmd *remove) Process(ctx context.Context) error {
if cmd.name == "" {
return flag.ErrHelp
}
return cmd.InfoFlag.Process(ctx)
}
func (cmd *remove) Description() string {
return `Remove cluster rule.
Examples:
govc cluster.group.remove -cluster my_cluster -name my_rule`
}
func (cmd *remove) Run(ctx context.Context, f *flag.FlagSet) error {
rule, err := cmd.Rule(ctx)
if err != nil {
return err
}
update := types.ArrayUpdateSpec{
Operation: types.ArrayUpdateOperationRemove,
RemoveKey: rule.info.GetClusterRuleInfo().Key,
}
return cmd.Apply(ctx, update, nil)
}

View File

@@ -1,69 +0,0 @@
/*
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 datacenter
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type create struct {
*flags.FolderFlag
}
func init() {
cli.Register("datacenter.create", &create{})
}
func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx)
cmd.FolderFlag.Register(ctx, f)
}
func (cmd *create) Usage() string {
return "NAME..."
}
func (cmd *create) Process(ctx context.Context) error {
if err := cmd.FolderFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
folder, err := cmd.FolderOrDefault("/")
if err != nil {
return err
}
if f.NArg() == 0 {
return flag.ErrHelp
}
for _, name := range f.Args() {
_, err := folder.CreateDatacenter(ctx, name)
if err != nil {
return err
}
}
return nil
}

View File

@@ -1,174 +0,0 @@
/*
Copyright (c) 2016 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 datacenter
import (
"context"
"flag"
"fmt"
"io"
"path"
"text/tabwriter"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type info struct {
*flags.ClientFlag
*flags.OutputFlag
*flags.DatacenterFlag
}
func init() {
cli.Register("datacenter.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)
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 {
return "[PATH]..."
}
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
finder, err := cmd.Finder()
if err != nil {
return err
}
args := f.Args()
if len(args) == 0 {
args = []string{"*"}
}
var props []string
res := infoResult{
finder: finder,
ctx: ctx,
}
if !cmd.OutputFlag.All() {
props = []string{
"name",
"vmFolder",
"hostFolder",
"datastoreFolder",
"networkFolder",
"datastore",
"network",
}
}
for _, arg := range args {
objects, err := finder.DatacenterList(ctx, arg)
if err != nil {
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.Datacenters)
if err != nil {
return err
}
}
return cmd.WriteResult(&res)
}
type infoResult struct {
Datacenters []mo.Datacenter
objects []*object.Datacenter
finder *find.Finder
ctx context.Context
}
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.Datacenter, len(r.Datacenters))
for _, o := range r.Datacenters {
objects[o.Reference()] = o
}
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
for _, o := range r.objects {
dc := objects[o.Reference()]
fmt.Fprintf(tw, "Name:\t%s\n", dc.Name)
fmt.Fprintf(tw, " Path:\t%s\n", o.InventoryPath)
folders, err := o.Folders(r.ctx)
if err != nil {
return err
}
r.finder.SetDatacenter(o)
hosts, _ := r.finder.HostSystemList(r.ctx, path.Join(folders.HostFolder.InventoryPath, "*"))
fmt.Fprintf(tw, " Hosts:\t%d\n", len(hosts))
clusters, _ := r.finder.ClusterComputeResourceList(r.ctx, path.Join(folders.HostFolder.InventoryPath, "*"))
fmt.Fprintf(tw, " Clusters:\t%d\n", len(clusters))
vms, _ := r.finder.VirtualMachineList(r.ctx, path.Join(folders.VmFolder.InventoryPath, "*"))
fmt.Fprintf(tw, " Virtual Machines:\t%d\n", len(vms))
fmt.Fprintf(tw, " Networks:\t%d\n", len(dc.Network))
fmt.Fprintf(tw, " Datastores:\t%d\n", len(dc.Datastore))
}
return tw.Flush()
}

View File

@@ -1,152 +0,0 @@
/*
Copyright (c) 2014-2018 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 (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
)
type cp struct {
target
}
func init() {
cli.Register("datastore.cp", &cp{})
}
type target struct {
*flags.DatastoreFlag // The source Datastore and the default target Datastore
dc *flags.DatacenterFlag // Optionally target a different Datacenter
ds *flags.DatastoreFlag // Optionally target a different Datastore
kind bool
force bool
}
func (cmd *target) FileManager() (*object.DatastoreFileManager, error) {
dc, err := cmd.Datacenter()
if err != nil {
return nil, err
}
ds, err := cmd.Datastore()
if err != nil {
return nil, err
}
m := ds.NewFileManager(dc, cmd.force)
dc, err = cmd.dc.Datacenter()
if err != nil {
return nil, err
}
m.DatacenterTarget = dc
return m, nil
}
func (cmd *target) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
cmd.dc = &flags.DatacenterFlag{
OutputFlag: cmd.OutputFlag,
ClientFlag: cmd.ClientFlag,
}
f.StringVar(&cmd.dc.Name, "dc-target", "", "Datacenter destination (defaults to -dc)")
cmd.ds = &flags.DatastoreFlag{
DatacenterFlag: cmd.dc,
}
f.StringVar(&cmd.ds.Name, "ds-target", "", "Datastore destination (defaults to -ds)")
f.BoolVar(&cmd.kind, "t", true, "Use file type to choose disk or file manager")
f.BoolVar(&cmd.force, "f", false, "If true, overwrite any identically named file at the destination")
}
func (cmd *target) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
if cmd.dc.Name == "" {
// Use source DC as target DC
cmd.dc = cmd.DatacenterFlag
cmd.ds.DatacenterFlag = cmd.dc
}
if cmd.ds.Name == "" {
// Use source DS as target DS
cmd.ds.Name = cmd.DatastoreFlag.Name
}
return nil
}
func (cmd *cp) Usage() string {
return "SRC DST"
}
func (cmd *cp) Description() string {
return `Copy SRC to DST on DATASTORE.
Examples:
govc datastore.cp foo/foo.vmx foo/foo.vmx.old
govc datastore.cp -f my.vmx foo/foo.vmx
govc datastore.cp disks/disk1.vmdk disks/disk2.vmdk
govc datastore.cp disks/disk1.vmdk -dc-target DC2 disks/disk2.vmdk
govc datastore.cp disks/disk1.vmdk -ds-target NFS-2 disks/disk2.vmdk`
}
func (cmd *cp) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args()
if len(args) != 2 {
return flag.ErrHelp
}
m, err := cmd.FileManager()
if err != nil {
return err
}
src, err := cmd.DatastorePath(args[0])
if err != nil {
return err
}
dst, err := cmd.target.ds.DatastorePath(args[1])
if err != nil {
return err
}
cp := m.CopyFile
if cmd.kind {
cp = m.Copy
}
logger := cmd.ProgressLogger(fmt.Sprintf("Copying %s to %s...", src, dst))
defer logger.Wait()
return cp(m.WithProgress(ctx, logger), src, dst)
}

View File

@@ -1,321 +0,0 @@
/*
Copyright (c) 2015-2016 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 (
"context"
"errors"
"flag"
"fmt"
"os"
"path/filepath"
"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"
)
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
// Options for local
Path string
}
func init() {
cli.Register("datastore.create", &create{})
}
var nasTypes = []string{
string(types.HostFileSystemVolumeFileSystemTypeNFS),
string(types.HostFileSystemVolumeFileSystemTypeNFS41),
string(types.HostFileSystemVolumeFileSystemTypeCIFS),
}
var vmfsTypes = []string{
string(types.HostFileSystemVolumeFileSystemTypeVMFS),
}
var localTypes = []string{
"local",
}
var allTypes = []string{}
func init() {
allTypes = append(allTypes, nasTypes...)
allTypes = append(allTypes, vmfsTypes...)
allTypes = append(allTypes, localTypes...)
}
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 (t *typeFlag) IsLocalType() bool {
return t.partOf(localTypes)
}
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)")
// Options for Local
f.StringVar(&cmd.Path, "path", "", "Local directory path for the datastore (local 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 vmfsDatastore -disk=mpx.vmhba0:C0:T0:L0 cluster1
govc datastore.create -type local -name localDatastore -path /var/datastore host1`
}
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)
case cmd.Type.IsLocalType():
return cmd.CreateLocalDatastore(ctx, hosts)
default:
return fmt.Errorf("unhandled type %#v", cmd.Type)
}
}
func (cmd *create) GetHostNasVolumeSpec() types.HostNasVolumeSpec {
localPath := cmd.Path
if localPath == "" {
localPath = cmd.Name
}
s := types.HostNasVolumeSpec{
LocalPath: localPath,
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
}
func (cmd *create) CreateLocalDatastore(ctx context.Context, hosts []*object.HostSystem) error {
for _, host := range hosts {
ds, err := host.ConfigManager().DatastoreSystem(ctx)
if err != nil {
return err
}
if cmd.Path == "" {
cmd.Path = cmd.Name
}
if cmd.Name == "" {
cmd.Name = filepath.Base(cmd.Path)
}
_, err = ds.CreateLocalDatastore(ctx, cmd.Name, cmd.Path)
if err != nil {
return err
}
}
return nil
}

View File

@@ -1,114 +0,0 @@
/*
Copyright (c) 2017-2018 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 disk
import (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/units"
"github.com/vmware/govmomi/vim25/types"
)
type spec struct {
types.FileBackedVirtualDiskSpec
force bool
}
func (s *spec) Register(ctx context.Context, f *flag.FlagSet) {
f.StringVar(&s.AdapterType, "a", string(types.VirtualDiskAdapterTypeLsiLogic), "Disk adapter")
f.StringVar(&s.DiskType, "d", string(types.VirtualDiskTypeThin), "Disk format")
f.BoolVar(&s.force, "f", false, "Force")
}
type create struct {
*flags.DatastoreFlag
Bytes units.ByteSize
spec
}
func init() {
cli.Register("datastore.disk.create", &create{})
}
func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
_ = cmd.Bytes.Set("10G")
f.Var(&cmd.Bytes, "size", "Size of new disk")
cmd.spec.Register(ctx, f)
}
func (cmd *create) Usage() string {
return "VMDK"
}
func (cmd *create) Description() string {
return `Create VMDK on DS.
Examples:
govc datastore.mkdir disks
govc datastore.disk.create -size 24G disks/disk1.vmdk
govc datastore.disk.create disks/parent.vmdk disk/child.vmdk`
}
func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() == 0 {
return flag.ErrHelp
}
dc, err := cmd.Datacenter()
if err != nil {
return err
}
ds, err := cmd.Datastore()
if err != nil {
return err
}
m := object.NewVirtualDiskManager(ds.Client())
var task *object.Task
var dst string
if f.NArg() == 1 {
cmd.spec.CapacityKb = int64(cmd.Bytes) / 1024
dst = ds.Path(f.Arg(0))
task, err = m.CreateVirtualDisk(ctx, dst, dc, &cmd.spec.FileBackedVirtualDiskSpec)
} else {
dst = ds.Path(f.Arg(0))
task, err = m.CreateChildDisk(ctx, ds.Path(f.Arg(0)), dc, dst, dc, cmd.force)
}
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("Creating %s...", dst))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}

View File

@@ -1,80 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package disk
import (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
)
type inflate struct {
*flags.DatastoreFlag
}
func init() {
cli.Register("datastore.disk.inflate", &inflate{})
}
func (cmd *inflate) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
}
func (cmd *inflate) Process(ctx context.Context) error {
return cmd.DatastoreFlag.Process(ctx)
}
func (cmd *inflate) Usage() string {
return "VMDK"
}
func (cmd *inflate) Description() string {
return `Inflate VMDK on DS.
Examples:
govc datastore.disk.inflate disks/disk1.vmdk`
}
func (cmd *inflate) Run(ctx context.Context, f *flag.FlagSet) error {
dc, err := cmd.Datacenter()
if err != nil {
return err
}
ds, err := cmd.Datastore()
if err != nil {
return err
}
m := object.NewVirtualDiskManager(ds.Client())
path := ds.Path(f.Arg(0))
task, err := m.InflateVirtualDisk(ctx, path, dc)
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("Inflating %s...", path))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}

View File

@@ -1,145 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package disk
import (
"context"
"flag"
"fmt"
"io"
"strings"
"text/tabwriter"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
)
type info struct {
*flags.DatastoreFlag
c bool
d bool
p bool
}
func init() {
cli.Register("datastore.disk.info", &info{})
}
func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
f.BoolVar(&cmd.c, "c", false, "Chain format")
f.BoolVar(&cmd.d, "d", false, "Include datastore in output")
f.BoolVar(&cmd.p, "p", true, "Include parents")
}
func (cmd *info) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *info) Usage() string {
return "VMDK"
}
func (cmd *info) Description() string {
return `Query VMDK info on DS.
Examples:
govc datastore.disk.info disks/disk1.vmdk`
}
func fullPath(s string) string {
return s
}
func dsPath(s string) string {
var p object.DatastorePath
if p.FromString(s) {
return p.Path
}
return s
}
var infoPath = dsPath
type infoResult []object.VirtualDiskInfo
func (r infoResult) Write(w io.Writer) error {
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
for _, info := range r {
fmt.Fprintf(tw, "Name:\t%s\n", infoPath(info.Name))
fmt.Fprintf(tw, " Type:\t%s\n", info.DiskType)
fmt.Fprintf(tw, " Parent:\t%s\n", infoPath(info.Parent))
}
return tw.Flush()
}
type chainResult []object.VirtualDiskInfo
func (r chainResult) Write(w io.Writer) error {
for i, info := range r {
fmt.Fprint(w, strings.Repeat(" ", i*2))
fmt.Fprintln(w, infoPath(info.Name))
}
return nil
}
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 1 {
return flag.ErrHelp
}
dc, err := cmd.Datacenter()
if err != nil {
return err
}
ds, err := cmd.Datastore()
if err != nil {
return err
}
m := object.NewVirtualDiskManager(ds.Client())
info, err := m.QueryVirtualDiskInfo(ctx, ds.Path(f.Arg(0)), dc, cmd.p)
if err != nil {
return err
}
if cmd.d {
infoPath = fullPath
}
var r flags.OutputWriter = infoResult(info)
if cmd.c {
r = chainResult(info)
}
return cmd.WriteResult(r)
}

View File

@@ -1,84 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package disk
import (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
)
type shrink struct {
*flags.DatastoreFlag
copy *bool
}
func init() {
cli.Register("datastore.disk.shrink", &shrink{})
}
func (cmd *shrink) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
f.Var(flags.NewOptionalBool(&cmd.copy), "copy", "Perform shrink in-place mode if false, copy-shrink mode otherwise")
}
func (cmd *shrink) Process(ctx context.Context) error {
return cmd.DatastoreFlag.Process(ctx)
}
func (cmd *shrink) Usage() string {
return "VMDK"
}
func (cmd *shrink) Description() string {
return `Shrink VMDK on DS.
Examples:
govc datastore.disk.shrink disks/disk1.vmdk`
}
func (cmd *shrink) Run(ctx context.Context, f *flag.FlagSet) error {
dc, err := cmd.Datacenter()
if err != nil {
return err
}
ds, err := cmd.Datastore()
if err != nil {
return err
}
m := object.NewVirtualDiskManager(ds.Client())
path := ds.Path(f.Arg(0))
task, err := m.ShrinkVirtualDisk(ctx, path, dc, cmd.copy)
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("Shrinking %s...", path))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}

View File

@@ -1,117 +0,0 @@
/*
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 datastore
import (
"context"
"errors"
"flag"
"fmt"
"io"
"os"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/soap"
)
type download struct {
*flags.DatastoreFlag
*flags.HostSystemFlag
}
func init() {
cli.Register("datastore.download", &download{})
}
func (cmd *download) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
}
func (cmd *download) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *download) Usage() string {
return "SOURCE DEST"
}
func (cmd *download) Description() string {
return `Copy SOURCE from DS to DEST on the local system.
If DEST name is "-", source is written to stdout.
Examples:
govc datastore.download vm-name/vmware.log ./local.log
govc datastore.download vm-name/vmware.log - | grep -i error`
}
func (cmd *download) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args()
if len(args) != 2 {
return errors.New("invalid arguments")
}
ds, err := cmd.Datastore()
if err != nil {
return err
}
h, err := cmd.HostSystemIfSpecified()
if err != nil {
return err
}
var via string
if h != nil {
via = fmt.Sprintf(" via %s", h.InventoryPath)
ctx = ds.HostContext(ctx, h)
}
p := soap.DefaultDownload
src := args[0]
dst := args[1]
if dst == "-" {
f, _, err := ds.Download(ctx, src, &p)
if err != nil {
return err
}
_, err = io.Copy(os.Stdout, f)
return err
}
if cmd.DatastoreFlag.OutputFlag.TTY {
logger := cmd.DatastoreFlag.ProgressLogger(fmt.Sprintf("Downloading%s... ", via))
p.Progress = logger
defer logger.Wait()
}
return ds.DownloadFile(ctx, src, dst, &p)
}

View File

@@ -1,153 +0,0 @@
/*
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 (
"context"
"flag"
"fmt"
"io"
"os"
"text/tabwriter"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type info struct {
*flags.ClientFlag
*flags.OutputFlag
*flags.DatacenterFlag
}
func init() {
cli.Register("datastore.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)
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 {
return "[PATH]..."
}
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
finder, err := cmd.Finder()
if err != nil {
return err
}
args := f.Args()
if len(args) == 0 {
args = []string{"*"}
}
var res infoResult
var props []string
if cmd.OutputFlag.All() {
props = nil // Load everything
} else {
props = []string{"info", "summary"} // Load summary
}
for _, arg := range args {
objects, err := finder.DatastoreList(ctx, arg)
if err != nil {
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)
}
type infoResult struct {
Datastores []mo.Datastore
objects []*object.Datastore
}
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)
for _, o := range r.objects {
ds := objects[o.Reference()]
s := ds.Summary
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, " URL:\t%s\n", s.Url)
fmt.Fprintf(tw, " Capacity:\t%.1f GB\n", float64(s.Capacity)/(1<<30))
fmt.Fprintf(tw, " Free:\t%.1f GB\n", float64(s.FreeSpace)/(1<<30))
switch info := ds.Info.(type) {
case *types.NasDatastoreInfo:
fmt.Fprintf(tw, " Remote:\t%s:%s\n", info.Nas.RemoteHost, info.Nas.RemotePath)
}
}
return tw.Flush()
}

View File

@@ -1,280 +0,0 @@
/*
Copyright (c) 2014-2016 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 (
"context"
"encoding/json"
"flag"
"fmt"
"io"
"path"
"strings"
"text/tabwriter"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/units"
"github.com/vmware/govmomi/vim25/types"
)
type ls struct {
*flags.DatastoreFlag
*flags.OutputFlag
long bool
slash bool
all bool
recurse bool
}
func init() {
cli.Register("datastore.ls", &ls{})
}
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.slash, "p", false, "Append / indicator to directories")
f.BoolVar(&cmd.all, "a", false, "Do not ignore entries starting with .")
f.BoolVar(&cmd.recurse, "R", false, "List subdirectories recursively")
}
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 {
return "[FILE]..."
}
func isInvalid(err error) bool {
if f, ok := err.(types.HasFault); ok {
switch f.Fault().(type) {
case *types.InvalidArgument:
return true
}
}
return false
}
func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
args := cmd.Args(f.Args())
ds, err := cmd.Datastore()
if err != nil {
return err
}
b, err := ds.Browser(ctx)
if err != nil {
return err
}
if len(args) == 0 {
args = append(args, object.DatastorePath{})
}
result := &listOutput{
rs: make([]types.HostDatastoreBrowserSearchResults, 0),
cmd: cmd,
}
for _, p := range args {
arg := p.Path
spec := types.HostDatastoreBrowserSearchSpec{
MatchPattern: []string{"*"},
}
if cmd.long {
spec.Details = &types.FileQueryFlags{
FileType: true,
FileSize: true,
FileOwner: types.NewBool(true), // TODO: omitempty is generated, but seems to be required
Modification: true,
}
}
for i := 0; ; i++ {
r, err := cmd.ListPath(b, arg, spec)
if err != nil {
// Treat the argument as a match pattern if not found as directory
if i == 0 && types.IsFileNotFound(err) || isInvalid(err) {
spec.MatchPattern[0] = path.Base(arg)
arg = path.Dir(arg)
continue
}
return err
}
// Treat an empty result against match pattern as file not found
if i == 1 && len(r) == 1 && len(r[0].File) == 0 {
return fmt.Errorf("File %s/%s was not found", r[0].FolderPath, spec.MatchPattern[0])
}
for n := range r {
result.add(r[n])
}
break
}
}
return cmd.WriteResult(result)
}
func (cmd *ls) ListPath(b *object.HostDatastoreBrowser, path string, spec types.HostDatastoreBrowserSearchSpec) ([]types.HostDatastoreBrowserSearchResults, error) {
ctx := context.TODO()
path, err := cmd.DatastorePath(path)
if err != nil {
return nil, err
}
search := b.SearchDatastore
if cmd.recurse {
search = b.SearchDatastoreSubFolders
}
task, err := search(ctx, path, &spec)
if err != nil {
return nil, err
}
info, err := task.WaitForResult(ctx, nil)
if err != nil {
return nil, err
}
switch r := info.Result.(type) {
case types.HostDatastoreBrowserSearchResults:
return []types.HostDatastoreBrowserSearchResults{r}, nil
case types.ArrayOfHostDatastoreBrowserSearchResults:
return r.HostDatastoreBrowserSearchResults, nil
default:
panic(fmt.Sprintf("unknown result type: %T", r))
}
}
type listOutput struct {
rs []types.HostDatastoreBrowserSearchResults
cmd *ls
}
func (o *listOutput) add(r types.HostDatastoreBrowserSearchResults) {
if o.cmd.recurse && !o.cmd.all {
// filter out ".hidden" directories
path := strings.SplitN(r.FolderPath, " ", 2)
if len(path) == 2 {
path = strings.Split(path[1], "/")
if path[0] == "." {
path = path[1:]
}
for _, p := range path {
if len(p) != 0 && p[0] == '.' {
return
}
}
}
}
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
// results from more than one folder path.
func (o *listOutput) hasMultiplePaths() bool {
if len(o.rs) == 0 {
return false
}
p := o.rs[0].FolderPath
// Multiple paths if any entry is not equal to the first one.
for _, e := range o.rs {
if e.FolderPath != p {
return true
}
}
return false
}
func (o *listOutput) MarshalJSON() ([]byte, error) {
return json.Marshal(o.rs)
}
func (o *listOutput) Write(w io.Writer) error {
// Only include path header if we're dealing with more than one path.
includeHeader := false
if o.hasMultiplePaths() {
includeHeader = true
}
tw := tabwriter.NewWriter(w, 3, 0, 2, ' ', 0)
for i, r := range o.rs {
if includeHeader {
if i > 0 {
fmt.Fprintf(tw, "\n")
}
fmt.Fprintf(tw, "%s:\n", r.FolderPath)
}
for _, file := range r.File {
info := file.GetFileInfo()
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)
} else {
fmt.Fprintf(tw, "%s\n", info.Path)
}
}
}
tw.Flush()
return nil
}

View File

@@ -1,118 +0,0 @@
/*
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 datastore
import (
"context"
"errors"
"flag"
"fmt"
"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"
)
type mkdir struct {
*flags.DatastoreFlag
createParents bool
isNamespace bool
}
func init() {
cli.Register("datastore.mkdir", &mkdir{})
}
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.isNamespace, "namespace", false, "Return uuid of namespace created on vsan datastore")
}
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 {
return "DIRECTORY"
}
func (cmd *mkdir) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args()
if len(args) == 0 {
return errors.New("missing operand")
}
c, err := cmd.Client()
if err != nil {
return err
}
if cmd.isNamespace {
var uuid string
var ds *object.Datastore
if ds, err = cmd.Datastore(); err != nil {
return err
}
path := args[0]
nm := object.NewDatastoreNamespaceManager(c)
if uuid, err = nm.CreateDirectory(ctx, ds, path, ""); err != nil {
return err
}
fmt.Println(uuid)
} else {
var dc *object.Datacenter
var path string
dc, err = cmd.Datacenter()
if err != nil {
return err
}
path, err = cmd.DatastorePath(args[0])
if err != nil {
return err
}
m := object.NewFileManager(c)
err = m.MakeDirectory(ctx, path, dc, cmd.createParents)
// ignore EEXIST if -p flag is given
if err != nil && cmd.createParents {
if soap.IsSoapFault(err) {
soapFault := soap.ToSoapFault(err)
if _, ok := soapFault.VimFault().(types.FileAlreadyExists); ok {
return nil
}
}
}
}
return err
}

View File

@@ -1,77 +0,0 @@
/*
Copyright (c) 2014-2018 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 (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
)
type mv struct {
target
}
func init() {
cli.Register("datastore.mv", &mv{})
}
func (cmd *mv) Usage() string {
return "SRC DST"
}
func (cmd *mv) Description() string {
return `Move SRC to DST on DATASTORE.
Examples:
govc datastore.mv foo/foo.vmx foo/foo.vmx.old
govc datastore.mv -f my.vmx foo/foo.vmx`
}
func (cmd *mv) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args()
if len(args) != 2 {
return flag.ErrHelp
}
m, err := cmd.FileManager()
if err != nil {
return err
}
src, err := cmd.DatastorePath(args[0])
if err != nil {
return err
}
dst, err := cmd.target.ds.DatastorePath(args[1])
if err != nil {
return err
}
mv := m.MoveFile
if cmd.kind {
mv = m.Move
}
logger := cmd.ProgressLogger(fmt.Sprintf("Moving %s to %s...", src, dst))
defer logger.Wait()
return mv(m.WithProgress(ctx, logger), src, dst)
}

View File

@@ -1,90 +0,0 @@
/*
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 (
"context"
"flag"
"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.
Examples:
govc datastore.remove -ds nfsDatastore cluster1
govc datastore.remove -ds nasDatastore host1 host2 host3`
}
func (cmd *remove) Run(ctx context.Context, f *flag.FlagSet) error {
ds, err := cmd.Datastore()
if err != nil {
return err
}
hosts, err := cmd.HostSystems(f.Args())
if err != nil {
return err
}
for _, host := range hosts {
hds, err := host.ConfigManager().DatastoreSystem(ctx)
if err != nil {
return err
}
err = hds.Remove(ctx, ds)
if err != nil {
return err
}
}
return nil
}

View File

@@ -1,117 +0,0 @@
/*
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 datastore
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
)
type rm struct {
*flags.DatastoreFlag
kind bool
force bool
isNamespace bool
}
func init() {
cli.Register("datastore.rm", &rm{})
cli.Alias("datastore.rm", "datastore.delete")
}
func (cmd *rm) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
f.BoolVar(&cmd.kind, "t", true, "Use file type to choose disk or file manager")
f.BoolVar(&cmd.force, "f", false, "Force; ignore nonexistent files and arguments")
f.BoolVar(&cmd.isNamespace, "namespace", false, "Path is uuid of namespace on vsan datastore")
}
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 {
return "FILE"
}
func (cmd *rm) Description() string {
return `Remove FILE from DATASTORE.
Examples:
govc datastore.rm vm/vmware.log
govc datastore.rm vm
govc datastore.rm -f images/base.vmdk`
}
func (cmd *rm) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args()
if len(args) == 0 {
return flag.ErrHelp
}
c, err := cmd.Client()
if err != nil {
return err
}
var dc *object.Datacenter
dc, err = cmd.Datacenter()
if err != nil {
return err
}
ds, err := cmd.Datastore()
if err != nil {
return err
}
if cmd.isNamespace {
path := args[0]
nm := object.NewDatastoreNamespaceManager(c)
err = nm.DeleteDirectory(ctx, dc, path)
} else {
fm := ds.NewFileManager(dc, cmd.force)
remove := fm.DeleteFile // File delete
if cmd.kind {
remove = fm.Delete // VirtualDisk or File delete
}
err = remove(ctx, args[0])
}
if err != nil {
if types.IsFileNotFound(err) && cmd.force {
// Ignore error
return nil
}
}
return err
}

View File

@@ -1,137 +0,0 @@
/*
Copyright (c) 2016 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 (
"context"
"flag"
"io"
"os"
"time"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type tail struct {
*flags.DatastoreFlag
*flags.HostSystemFlag
count int64
lines int
follow bool
}
func init() {
cli.Register("datastore.tail", &tail{})
}
func (cmd *tail) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
f.Int64Var(&cmd.count, "c", -1, "Output the last NUM bytes")
f.IntVar(&cmd.lines, "n", 10, "Output the last NUM lines")
f.BoolVar(&cmd.follow, "f", false, "Output appended data as the file grows")
}
func (cmd *tail) Description() string {
return `Output the last part of datastore files.
Examples:
govc datastore.tail -n 100 vm-name/vmware.log
govc datastore.tail -n 0 -f vm-name/vmware.log`
}
func (cmd *tail) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *tail) Usage() string {
return "PATH"
}
func (cmd *tail) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 1 {
return flag.ErrHelp
}
p := cmd.Args(f.Args())[0]
ds, err := cmd.Datastore()
if err != nil {
return err
}
h, err := cmd.HostSystemIfSpecified()
if err != nil {
return err
}
if h != nil {
ctx = ds.HostContext(ctx, h)
}
file, err := ds.Open(ctx, p.Path)
if err != nil {
return err
}
var reader io.ReadCloser = file
var offset int64
if cmd.count >= 0 {
info, serr := file.Stat()
if serr != nil {
return serr
}
if info.Size() > cmd.count {
offset = info.Size() - cmd.count
_, err = file.Seek(offset, io.SeekStart)
if err != nil {
return err
}
}
} else if cmd.lines >= 0 {
err = file.Tail(cmd.lines)
if err != nil {
return err
}
}
if cmd.follow {
reader = file.Follow(time.Second)
}
_, err = io.Copy(os.Stdout, reader)
_ = reader.Close()
return err
}

View File

@@ -1,98 +0,0 @@
/*
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 datastore
import (
"context"
"errors"
"flag"
"os"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/soap"
)
type upload struct {
*flags.OutputFlag
*flags.DatastoreFlag
}
func init() {
cli.Register("datastore.upload", &upload{})
}
func (cmd *upload) 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)
}
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 {
return "SOURCE DEST"
}
func (cmd *upload) Description() string {
return `Copy SOURCE from the local system to DEST on DS.
If SOURCE name is "-", read source from stdin.
Examples:
govc datastore.upload -ds datastore1 ./config.iso vm-name/config.iso
genisoimage ... | govc datastore.upload -ds datastore1 - vm-name/config.iso`
}
func (cmd *upload) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args()
if len(args) != 2 {
return errors.New("invalid arguments")
}
ds, err := cmd.Datastore()
if err != nil {
return err
}
p := soap.DefaultUpload
src := args[0]
dst := args[1]
if src == "-" {
return ds.Upload(ctx, os.Stdin, dst, &p)
}
if cmd.OutputFlag.TTY {
logger := cmd.ProgressLogger("Uploading... ")
p.Progress = logger
defer logger.Wait()
}
return ds.UploadFile(ctx, src, dst, &p)
}

View File

@@ -1,156 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package vsan
import (
"context"
"flag"
"fmt"
"net/url"
"text/tabwriter"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
)
type ls struct {
*flags.DatastoreFlag
long bool
orphan bool
}
func init() {
cli.Register("datastore.vsan.dom.ls", &ls{})
}
func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
f.BoolVar(&cmd.long, "l", false, "Long listing")
f.BoolVar(&cmd.orphan, "o", false, "List orphan objects")
}
func (cmd *ls) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *ls) Usage() string {
return "[UUID]..."
}
func (cmd *ls) Description() string {
return `List vSAN DOM objects in DS.
Examples:
govc datastore.vsan.dom.ls
govc datastore.vsan.dom.ls -ds vsanDatastore -l
govc datastore.vsan.dom.ls -l d85aa758-63f5-500a-3150-0200308e589c`
}
func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
ds, err := cmd.Datastore()
if err != nil {
return err
}
var mds mo.Datastore
err = ds.Properties(ctx, ds.Reference(), []string{"summary"}, &mds)
if err != nil {
return err
}
if mds.Summary.Type != "vsan" {
return flag.ErrHelp
}
hosts, err := ds.AttachedHosts(ctx)
if err != nil {
return err
}
if len(hosts) == 0 {
return flag.ErrHelp
}
m, err := hosts[0].ConfigManager().VsanInternalSystem(ctx)
if err != nil {
return err
}
ids, err := m.QueryVsanObjectUuidsByFilter(ctx, f.Args(), 0, 0)
if err != nil {
return err
}
if len(ids) == 0 {
return nil
}
if !cmd.long && !cmd.orphan {
for _, id := range ids {
fmt.Fprintln(cmd.Out, id)
}
return nil
}
objs, err := m.GetVsanObjExtAttrs(ctx, ids)
if err != nil {
return err
}
u, err := url.Parse(mds.Summary.Url)
if err != nil {
return err
}
tw := tabwriter.NewWriter(cmd.Out, 2, 0, 2, ' ', 0)
cmd.Out = tw
for id, obj := range objs {
path := obj.DatastorePath(u.Path)
if cmd.orphan {
_, err = ds.Stat(ctx, path)
if err == nil {
continue
}
switch err.(type) {
case object.DatastoreNoSuchDirectoryError, object.DatastoreNoSuchFileError:
default:
return err
}
if !cmd.long {
fmt.Fprintln(cmd.Out, id)
continue
}
}
fmt.Fprintf(cmd.Out, "%s\t%s\t%s\n", id, obj.Class, path)
}
return tw.Flush()
}

View File

@@ -1,108 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package vsan
import (
"context"
"flag"
"fmt"
"os"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type rm struct {
*flags.DatastoreFlag
force bool
verbose bool
}
func init() {
cli.Register("datastore.vsan.dom.rm", &rm{})
}
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 delete")
f.BoolVar(&cmd.verbose, "v", false, "Print deleted UUIDs to stdout, failed to stderr")
}
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 {
return "UUID..."
}
func (cmd *rm) Description() string {
return `Remove vSAN DOM objects in DS.
Examples:
govc datastore.vsan.dom.rm d85aa758-63f5-500a-3150-0200308e589c
govc datastore.vsan.dom.rm -f d85aa758-63f5-500a-3150-0200308e589c
govc datastore.vsan.dom.ls -o | xargs govc datastore.vsan.dom.rm`
}
func (cmd *rm) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() == 0 {
return flag.ErrHelp
}
ds, err := cmd.Datastore()
if err != nil {
return err
}
hosts, err := ds.AttachedHosts(ctx)
if err != nil {
return err
}
if len(hosts) == 0 {
return flag.ErrHelp
}
m, err := hosts[0].ConfigManager().VsanInternalSystem(ctx)
if err != nil {
return err
}
res, err := m.DeleteVsanObjects(ctx, f.Args(), &cmd.force)
if err != nil {
return err
}
if cmd.verbose {
for _, r := range res {
if r.Success {
fmt.Fprintln(cmd.Out, r.Uuid)
} else {
fmt.Fprintf(os.Stderr, "%s %s\n", r.Uuid, r.FailureReason[0].Message)
}
}
}
return nil
}

View File

@@ -1,91 +0,0 @@
/*
Copyright (c) 2014-2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package device
import (
"context"
"flag"
"strings"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)
type boot struct {
*flags.VirtualMachineFlag
order string
types.VirtualMachineBootOptions
}
func init() {
cli.Register("device.boot", &boot{})
}
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.StringVar(&cmd.order, "order", "", "Boot device order [-,floppy,cdrom,ethernet,disk]")
f.Int64Var(&cmd.BootRetryDelay, "retry-delay", 0, "Delay in ms before a boot retry")
cmd.BootRetryEnabled = types.NewBool(false)
f.BoolVar(cmd.BootRetryEnabled, "retry", false, "If true, retry boot after retry-delay")
cmd.EnterBIOSSetup = types.NewBool(false)
f.BoolVar(cmd.EnterBIOSSetup, "setup", false, "If true, enter BIOS setup on next boot")
}
func (cmd *boot) Description() string {
return `Configure VM boot settings.
Examples:
govc device.boot -vm $vm -delay 1000 -order floppy,cdrom,ethernet,disk
govc device.boot -vm $vm -order - # reset boot order`
}
func (cmd *boot) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *boot) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(ctx)
if err != nil {
return err
}
if cmd.order != "" {
o := strings.Split(cmd.order, ",")
cmd.BootOrder = devices.BootOrder(o)
}
return vm.SetBootOptions(ctx, &cmd.VirtualMachineBootOptions)
}

View File

@@ -1,105 +0,0 @@
/*
Copyright (c) 2014-2016 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 cdrom
import (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type add struct {
*flags.VirtualMachineFlag
controller string
}
func init() {
cli.Register("device.cdrom.add", &add{})
}
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")
}
func (cmd *add) Description() string {
return `Add CD-ROM device to VM.
Examples:
govc device.cdrom.add -vm $vm
govc device.ls -vm $vm | grep ide-
govc device.cdrom.add -vm $vm -controller ide-200
govc device.info cdrom-*`
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(ctx)
if err != nil {
return err
}
c, err := devices.FindIDEController(cmd.controller)
if err != nil {
return err
}
d, err := devices.CreateCdrom(c)
if err != nil {
return err
}
err = vm.AddDevice(ctx, d)
if err != nil {
return err
}
// output name of device we just created
devices, err = vm.Device(ctx)
if err != nil {
return err
}
devices = devices.SelectByType(d)
name := devices.Name(devices[len(devices)-1])
fmt.Println(name)
return nil
}

View File

@@ -1,82 +0,0 @@
/*
Copyright (c) 2014-2016 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 cdrom
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type eject struct {
*flags.VirtualMachineFlag
device string
}
func init() {
cli.Register("device.cdrom.eject", &eject{})
}
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")
}
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 {
return `Eject media from CD-ROM device.
If device is not specified, the first CD-ROM device is used.
Examples:
govc device.cdrom.eject -vm vm-1
govc device.cdrom.eject -vm vm-1 -device floppy-1`
}
func (cmd *eject) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(ctx)
if err != nil {
return err
}
c, err := devices.FindCdrom(cmd.device)
if err != nil {
return err
}
return vm.EditDevice(ctx, devices.EjectIso(c))
}

View File

@@ -1,96 +0,0 @@
/*
Copyright (c) 2014-2016 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 cdrom
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type insert struct {
*flags.DatastoreFlag
*flags.VirtualMachineFlag
device string
}
func init() {
cli.Register("device.cdrom.insert", &insert{})
}
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")
}
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 {
return "ISO"
}
func (cmd *insert) Description() string {
return `Insert media on datastore into CD-ROM device.
If device is not specified, the first CD-ROM device is used.
Examples:
govc device.cdrom.insert -vm vm-1 -device cdrom-3000 images/boot.iso`
}
func (cmd *insert) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil || f.NArg() != 1 {
return flag.ErrHelp
}
devices, err := vm.Device(ctx)
if err != nil {
return err
}
c, err := devices.FindCdrom(cmd.device)
if err != nil {
return err
}
iso, err := cmd.DatastorePath(f.Arg(0))
if err != nil {
return nil
}
return vm.EditDevice(ctx, devices.InsertIso(c, iso))
}

View File

@@ -1,90 +0,0 @@
/*
Copyright (c) 2014-2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package device
import (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type connect struct {
*flags.VirtualMachineFlag
}
func init() {
cli.Register("device.connect", &connect{})
}
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(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *connect) Usage() string {
return "DEVICE..."
}
func (cmd *connect) Description() string {
return `Connect DEVICE on VM.
Examples:
govc device.connect -vm $name cdrom-3000`
}
func (cmd *connect) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(ctx)
if err != nil {
return err
}
for _, name := range f.Args() {
device := devices.Find(name)
if device == nil {
return fmt.Errorf("device '%s' not found", name)
}
if err = devices.Connect(device); err != nil {
return err
}
if err = vm.EditDevice(ctx, device); err != nil {
return err
}
}
return nil
}

View File

@@ -1,90 +0,0 @@
/*
Copyright (c) 2014-2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package device
import (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type disconnect struct {
*flags.VirtualMachineFlag
}
func init() {
cli.Register("device.disconnect", &disconnect{})
}
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(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *disconnect) Usage() string {
return "DEVICE..."
}
func (cmd *disconnect) Description() string {
return `Disconnect DEVICE on VM.
Examples:
govc device.disconnect -vm $name cdrom-3000`
}
func (cmd *disconnect) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(ctx)
if err != nil {
return err
}
for _, name := range f.Args() {
device := devices.Find(name)
if device == nil {
return fmt.Errorf("device '%s' not found", name)
}
if err = devices.Disconnect(device); err != nil {
return err
}
if err = vm.EditDevice(ctx, device); err != nil {
return err
}
}
return nil
}

View File

@@ -1,94 +0,0 @@
/*
Copyright (c) 2014-2016 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 floppy
import (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type add struct {
*flags.VirtualMachineFlag
}
func init() {
cli.Register("device.floppy.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
}
func (cmd *add) Description() string {
return `Add floppy device to VM.
Examples:
govc device.floppy.add -vm $vm
govc device.info floppy-*`
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(ctx)
if err != nil {
return err
}
d, err := devices.CreateFloppy()
if err != nil {
return err
}
err = vm.AddDevice(ctx, d)
if err != nil {
return err
}
// output name of device we just created
devices, err = vm.Device(ctx)
if err != nil {
return err
}
devices = devices.SelectByType(d)
name := devices.Name(devices[len(devices)-1])
fmt.Println(name)
return nil
}

View File

@@ -1,81 +0,0 @@
/*
Copyright (c) 2014-2016 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 floppy
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type eject struct {
*flags.VirtualMachineFlag
device string
}
func init() {
cli.Register("device.floppy.eject", &eject{})
}
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")
}
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 {
return `Eject image from floppy device.
If device is not specified, the first floppy device is used.
Examples:
govc device.floppy.eject -vm vm-1`
}
func (cmd *eject) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(ctx)
if err != nil {
return err
}
c, err := devices.FindFloppy(cmd.device)
if err != nil {
return err
}
return vm.EditDevice(ctx, devices.EjectImg(c))
}

View File

@@ -1,96 +0,0 @@
/*
Copyright (c) 2014-2016 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 floppy
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type insert struct {
*flags.DatastoreFlag
*flags.VirtualMachineFlag
device string
}
func init() {
cli.Register("device.floppy.insert", &insert{})
}
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")
}
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 {
return "IMG"
}
func (cmd *insert) Description() string {
return `Insert IMG on datastore into floppy device.
If device is not specified, the first floppy device is used.
Examples:
govc device.floppy.insert -vm vm-1 vm-1/config.img`
}
func (cmd *insert) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil || f.NArg() != 1 {
return flag.ErrHelp
}
devices, err := vm.Device(ctx)
if err != nil {
return err
}
c, err := devices.FindFloppy(cmd.device)
if err != nil {
return err
}
img, err := cmd.DatastorePath(f.Arg(0))
if err != nil {
return nil
}
return vm.EditDevice(ctx, devices.InsertImg(c, img))
}

View File

@@ -1,249 +0,0 @@
/*
Copyright (c) 2014-2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package device
import (
"context"
"encoding/json"
"flag"
"fmt"
"io"
"os"
"path"
"strings"
"text/tabwriter"
"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.VirtualMachineFlag
*flags.OutputFlag
*flags.NetworkFlag
}
func init() {
cli.Register("device.info", &info{})
}
func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
cmd.NetworkFlag, ctx = flags.NewNetworkFlag(ctx)
cmd.NetworkFlag.Register(ctx, f)
}
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
}
if err := cmd.NetworkFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *info) Usage() string {
return "[DEVICE]..."
}
func (cmd *info) Description() string {
return `Device info for VM.
Examples:
govc device.info -vm $name
govc device.info -vm $name disk-*
govc device.info -vm $name -json ethernet-0 | jq -r .Devices[].MacAddress`
}
func (cmd *info) match(p string, devices object.VirtualDeviceList) object.VirtualDeviceList {
var matches object.VirtualDeviceList
match := func(name string) bool {
matched, _ := path.Match(p, name)
return matched
}
for _, device := range devices {
name := devices.Name(device)
eq := name == p
if eq || match(name) {
matches = append(matches, device)
}
if eq {
break
}
}
return matches
}
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(ctx)
if err != nil {
return err
}
res := infoResult{
list: devices,
}
if cmd.NetworkFlag.IsSet() {
net, err := cmd.Network()
if err != nil {
return err
}
backing, err := net.EthernetCardBackingInfo(ctx)
if err != nil {
return err
}
devices = devices.SelectByBackingInfo(backing)
}
if f.NArg() == 0 {
res.Devices = toInfoList(devices)
} else {
for _, name := range f.Args() {
matches := cmd.match(name, devices)
if len(matches) == 0 {
return fmt.Errorf("device '%s' not found", name)
}
res.Devices = append(res.Devices, toInfoList(matches)...)
}
}
return cmd.WriteResult(&res)
}
func toInfoList(devices object.VirtualDeviceList) []infoDevice {
var res []infoDevice
for _, device := range devices {
res = append(res, infoDevice{
Name: devices.Name(device),
Type: devices.TypeName(device),
BaseVirtualDevice: device,
})
}
return res
}
type infoDevice struct {
Name string
Type string
types.BaseVirtualDevice
}
func (d *infoDevice) MarshalJSON() ([]byte, error) {
b, err := json.Marshal(d.BaseVirtualDevice)
if err != nil {
return b, err
}
// TODO: make use of "inline" tag if it comes to be: https://github.com/golang/go/issues/6213
return append([]byte(fmt.Sprintf(`{"Name":"%s","Type":"%s",`, d.Name, d.Type)), b[1:]...), err
}
type infoResult struct {
Devices []infoDevice
// 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)
for i := range r.Devices {
device := r.Devices[i].BaseVirtualDevice
d := device.GetVirtualDevice()
info := d.DeviceInfo.GetDescription()
fmt.Fprintf(tw, "Name:\t%s\n", r.Devices[i].Name)
fmt.Fprintf(tw, " Type:\t%s\n", r.list.TypeName(device))
fmt.Fprintf(tw, " Label:\t%s\n", info.Label)
fmt.Fprintf(tw, " Summary:\t%s\n", info.Summary)
fmt.Fprintf(tw, " Key:\t%d\n", d.Key)
if c, ok := device.(types.BaseVirtualController); ok {
var attached []string
for _, key := range c.GetVirtualController().Device {
attached = append(attached, r.list.Name(r.list.FindByKey(key)))
}
fmt.Fprintf(tw, " Devices:\t%s\n", strings.Join(attached, ", "))
} else {
if c := r.list.FindByKey(d.ControllerKey); c != nil {
fmt.Fprintf(tw, " Controller:\t%s\n", r.list.Name(c))
if d.UnitNumber != nil {
fmt.Fprintf(tw, " Unit number:\t%d\n", *d.UnitNumber)
} else {
fmt.Fprintf(tw, " Unit number:\t<nil>\n")
}
}
}
if ca := d.Connectable; ca != nil {
fmt.Fprintf(tw, " Connected:\t%t\n", ca.Connected)
fmt.Fprintf(tw, " Start connected:\t%t\n", ca.StartConnected)
fmt.Fprintf(tw, " Guest control:\t%t\n", ca.AllowGuestControl)
fmt.Fprintf(tw, " Status:\t%s\n", ca.Status)
}
switch md := device.(type) {
case types.BaseVirtualEthernetCard:
fmt.Fprintf(tw, " MAC Address:\t%s\n", md.GetVirtualEthernetCard().MacAddress)
fmt.Fprintf(tw, " Address type:\t%s\n", md.GetVirtualEthernetCard().AddressType)
case *types.VirtualDisk:
if b, ok := md.Backing.(types.BaseVirtualDeviceFileBackingInfo); ok {
fmt.Fprintf(tw, " File:\t%s\n", b.GetVirtualDeviceFileBackingInfo().FileName)
}
if b, ok := md.Backing.(*types.VirtualDiskFlatVer2BackingInfo); ok && b.Parent != nil {
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)
}
}
}
return tw.Flush()
}

View File

@@ -1,93 +0,0 @@
/*
Copyright (c) 2014-2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package device
import (
"context"
"flag"
"fmt"
"os"
"text/tabwriter"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type ls struct {
*flags.VirtualMachineFlag
boot bool
}
func init() {
cli.Register("device.ls", &ls{})
}
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")
}
func (cmd *ls) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *ls) Description() string {
return `List devices for VM.
Examples:
govc device.ls -vm $name`
}
func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(ctx)
if err != nil {
return err
}
if cmd.boot {
options, err := vm.BootOptions(ctx)
if err != nil {
return err
}
devices = devices.SelectBootOrder(options.BootOrder)
}
tw := tabwriter.NewWriter(os.Stdout, 3, 0, 2, ' ', 0)
for _, device := range devices {
fmt.Fprintf(tw, "%s\t%s\t%s\n", devices.Name(device), devices.TypeName(device),
device.GetVirtualDevice().DeviceInfo.GetDescription().Summary)
}
return tw.Flush()
}

View File

@@ -1,89 +0,0 @@
/*
Copyright (c) 2014-2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package device
import (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type remove struct {
*flags.VirtualMachineFlag
keepFiles bool
}
func init() {
cli.Register("device.remove", &remove{})
}
func (cmd *remove) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.BoolVar(&cmd.keepFiles, "keep", false, "Keep files in datastore")
}
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 {
return "DEVICE..."
}
func (cmd *remove) Description() string {
return `Remove DEVICE from VM.
Examples:
govc device.remove -vm $name cdrom-3000
govc device.remove -vm $name -keep disk-1000`
}
func (cmd *remove) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(ctx)
if err != nil {
return err
}
for _, name := range f.Args() {
device := devices.Find(name)
if device == nil {
return fmt.Errorf("device '%s' not found", name)
}
if err = vm.RemoveDevice(ctx, cmd.keepFiles, device); err != nil {
return err
}
}
return nil
}

View File

@@ -1,116 +0,0 @@
/*
Copyright (c) 2014-2016 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 scsi
import (
"context"
"flag"
"fmt"
"strings"
"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.VirtualMachineFlag
controller string
sharedBus string
hotAddRemove bool
}
func init() {
cli.Register("device.scsi.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
var ctypes []string
ct := object.SCSIControllerTypes()
for _, t := range ct {
ctypes = append(ctypes, ct.Type(t))
}
f.StringVar(&cmd.controller, "type", ct.Type(ct[0]),
fmt.Sprintf("SCSI controller type (%s)", strings.Join(ctypes, "|")))
f.StringVar(&cmd.sharedBus, "sharing", string(types.VirtualSCSISharingNoSharing), "SCSI sharing")
f.BoolVar(&cmd.hotAddRemove, "hot", false, "Enable hot-add/remove")
}
func (cmd *add) Description() string {
return `Add SCSI controller to VM.
Examples:
govc device.scsi.add -vm $vm
govc device.scsi.add -vm $vm -type pvscsi
govc device.info -vm $vm {lsi,pv}*`
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(ctx)
if err != nil {
return err
}
d, err := devices.CreateSCSIController(cmd.controller)
if err != nil {
return err
}
c := d.(types.BaseVirtualSCSIController).GetVirtualSCSIController()
c.HotAddRemove = &cmd.hotAddRemove
c.SharedBus = types.VirtualSCSISharing(cmd.sharedBus)
err = vm.AddDevice(ctx, d)
if err != nil {
return err
}
// output name of device we just created
devices, err = vm.Device(ctx)
if err != nil {
return err
}
devices = devices.SelectByType(d)
name := devices.Name(devices[len(devices)-1])
fmt.Println(name)
return nil
}

View File

@@ -1,94 +0,0 @@
/*
Copyright (c) 2014-2016 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 serial
import (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type add struct {
*flags.VirtualMachineFlag
}
func init() {
cli.Register("device.serial.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
}
func (cmd *add) Description() string {
return `Add serial port to VM.
Examples:
govc device.serial.add -vm $vm
govc device.info -vm $vm serialport-*`
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(ctx)
if err != nil {
return err
}
d, err := devices.CreateSerialPort()
if err != nil {
return err
}
err = vm.AddDevice(ctx, d)
if err != nil {
return err
}
// output name of device we just created
devices, err = vm.Device(ctx)
if err != nil {
return err
}
devices = devices.SelectByType(d)
name := devices.Name(devices[len(devices)-1])
fmt.Println(name)
return nil
}

View File

@@ -1,116 +0,0 @@
/*
Copyright (c) 2014-2016 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 serial
import (
"context"
"flag"
"fmt"
"path"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/mo"
)
type connect struct {
*flags.VirtualMachineFlag
proxy string
device string
client bool
}
func init() {
cli.Register("device.serial.connect", &connect{})
}
func (cmd *connect) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.StringVar(&cmd.proxy, "vspc-proxy", "", "vSPC proxy URI")
f.StringVar(&cmd.device, "device", "", "serial port device name")
f.BoolVar(&cmd.client, "client", false, "Use client direction")
}
func (cmd *connect) Usage() string {
return "URI"
}
func (cmd *connect) Description() string {
return `Connect service URI to serial port.
If "-" is given as URI, connects file backed device with file name of
device name + .log suffix in the VM Config.Files.LogDirectory.
Defaults to the first serial port if no DEVICE is given.
Examples:
govc device.ls | grep serialport-
govc device.serial.connect -vm $vm -device serialport-8000 telnet://:33233
govc device.info -vm $vm serialport-*
govc device.serial.connect -vm $vm "[datastore1] $vm/console.log"
govc device.serial.connect -vm $vm -
govc datastore.tail -f $vm/serialport-8000.log`
}
func (cmd *connect) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *connect) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 1 {
return flag.ErrHelp
}
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(ctx)
if err != nil {
return err
}
d, err := devices.FindSerialPort(cmd.device)
if err != nil {
return err
}
uri := f.Arg(0)
if uri == "-" {
var mvm mo.VirtualMachine
err = vm.Properties(ctx, vm.Reference(), []string{"config.files.logDirectory"}, &mvm)
if err != nil {
return err
}
uri = path.Join(mvm.Config.Files.LogDirectory, fmt.Sprintf("%s.log", devices.Name(d)))
}
return vm.EditDevice(ctx, devices.ConnectSerialPort(d, uri, cmd.client, cmd.proxy))
}

View File

@@ -1,81 +0,0 @@
/*
Copyright (c) 2014-2016 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 serial
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type disconnect struct {
*flags.VirtualMachineFlag
device string
}
func init() {
cli.Register("device.serial.disconnect", &disconnect{})
}
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")
}
func (cmd *disconnect) Description() string {
return `Disconnect service URI from serial port.
Examples:
govc device.ls | grep serialport-
govc device.serial.disconnect -vm $vm -device serialport-8000
govc device.info -vm $vm serialport-*`
}
func (cmd *disconnect) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *disconnect) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(ctx)
if err != nil {
return err
}
d, err := devices.FindSerialPort(cmd.device)
if err != nil {
return err
}
return vm.EditDevice(ctx, devices.DisconnectSerialPort(d))
}

View File

@@ -1,114 +0,0 @@
/*
Copyright (c) 2016 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 usb
import (
"context"
"flag"
"fmt"
"strings"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)
type add struct {
*flags.VirtualMachineFlag
controller string
autoConnect bool
ehciEnabled bool
}
func init() {
cli.Register("device.usb.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
ctypes := []string{"usb", "xhci"}
f.StringVar(&cmd.controller, "type", ctypes[0],
fmt.Sprintf("USB controller type (%s)", strings.Join(ctypes, "|")))
f.BoolVar(&cmd.autoConnect, "auto", true, "Enable ability to hot plug devices")
f.BoolVar(&cmd.ehciEnabled, "ehci", true, "Enable enhanced host controller interface (USB 2.0)")
}
func (cmd *add) Description() string {
return `Add USB device to VM.
Examples:
govc device.usb.add -vm $vm
govc device.usb.add -type xhci -vm $vm
govc device.info usb*`
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
var d types.BaseVirtualDevice
switch cmd.controller {
case "usb":
c := new(types.VirtualUSBController)
c.AutoConnectDevices = &cmd.autoConnect
c.EhciEnabled = &cmd.ehciEnabled
d = c
case "xhci":
c := new(types.VirtualUSBXHCIController)
c.AutoConnectDevices = &cmd.autoConnect
d = c
default:
return flag.ErrHelp
}
err = vm.AddDevice(ctx, d)
if err != nil {
return err
}
// output name of device we just created
devices, err := vm.Device(ctx)
if err != nil {
return err
}
devices = devices.SelectByType(d)
name := devices.Name(devices[len(devices)-1])
fmt.Println(name)
return nil
}

View File

@@ -1,147 +0,0 @@
/*
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 (
"context"
"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/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.
Examples:
govc dvs.add -dvs dvsName -pnic vmnic1 hostA hostB hostC`
}
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.DistributedVirtualSwitch
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
}

View File

@@ -1,99 +0,0 @@
/*
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 (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)
type create struct {
*flags.FolderFlag
types.DVSCreateSpec
configSpec *types.VMwareDVSConfigSpec
}
func init() {
cli.Register("dvs.create", &create{})
}
func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx)
cmd.FolderFlag.Register(ctx, f)
cmd.configSpec = new(types.VMwareDVSConfigSpec)
cmd.DVSCreateSpec.ConfigSpec = cmd.configSpec
cmd.DVSCreateSpec.ProductInfo = new(types.DistributedVirtualSwitchProductSpec)
f.StringVar(&cmd.ProductInfo.Version, "product-version", "", "DVS product version")
}
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 'folder' flag. If not given,
this defaults to the network folder in the specified or default datacenter.
Examples:
govc dvs.create DSwitch
govc dvs.create -product-version 5.5.0 DSwitch`
}
func (cmd *create) Process(ctx context.Context) error {
if err := cmd.FolderFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 1 {
return flag.ErrHelp
}
name := f.Arg(0)
cmd.configSpec.Name = name
folder, err := cmd.FolderOrDefault("network")
if err != nil {
return err
}
task, err := folder.CreateDVS(ctx, cmd.DVSCreateSpec)
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("adding %s to folder %s... ", name, folder.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}

View File

@@ -1,107 +0,0 @@
/*
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 (
"context"
"flag"
"fmt"
"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
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")
cmd.DVPortgroupConfigSpec.NumPorts = 128 // default
cmd.DVPortgroupConfigSpec.Register(ctx, f)
}
func (cmd *add) Description() string {
return `Add portgroup to DVS.
Examples:
govc dvs.create DSwitch
govc dvs.portgroup.add -dvs DSwitch -type earlyBinding -nports 16 ExternalNetwork
govc dvs.portgroup.add -dvs DSwitch -type ephemeral InternalNetwork`
}
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.Spec()})
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("adding %s portgroup to dvs %s... ", name, dvs.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}

View File

@@ -1,107 +0,0 @@
/*
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 (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
)
type change struct {
*flags.DatacenterFlag
DVPortgroupConfigSpec
}
func init() {
cli.Register("dvs.portgroup.change", &change{})
}
func (cmd *change) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
cmd.DVPortgroupConfigSpec.Register(ctx, f)
}
func (cmd *change) Description() string {
return `Change DVS portgroup configuration.
Examples:
govc dvs.portgroup.change -nports 26 ExternalNetwork
govc dvs.portgroup.change -vlan 3214 ExternalNetwork`
}
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 "PATH"
}
func (cmd *change) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 1 {
return flag.ErrHelp
}
path := f.Arg(0)
finder, err := cmd.Finder()
if err != nil {
return err
}
net, err := finder.Network(ctx, path)
if err != nil {
return err
}
pg, ok := net.(*object.DistributedVirtualPortgroup)
if !ok {
return fmt.Errorf("%s (%T) is not of type %T", path, net, pg)
}
var s mo.DistributedVirtualPortgroup
err = pg.Properties(ctx, pg.Reference(), []string{"config.configVersion"}, &s)
if err != nil {
return err
}
spec := cmd.Spec()
spec.ConfigVersion = s.Config.ConfigVersion
task, err := pg.Reconfigure(ctx, spec)
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("changing %s portgroup configuration %s... ", pg.Name(), pg.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}

View File

@@ -1,173 +0,0 @@
/*
Copyright (c) 2015-2016 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 (
"context"
"flag"
"fmt"
"io"
"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 info struct {
*flags.DatacenterFlag
pg string
active bool
connected bool
inside bool
uplinkPort bool
vlanID int
count int
}
func init() {
cli.Register("dvs.portgroup.info", &info{})
}
func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
f.StringVar(&cmd.pg, "pg", "", "Distributed Virtual Portgroup")
f.BoolVar(&cmd.active, "active", false, "Filter by port active or inactive status")
f.BoolVar(&cmd.connected, "connected", false, "Filter by port connected or disconnected status")
f.BoolVar(&cmd.inside, "inside", true, "Filter by port inside or outside status")
f.BoolVar(&cmd.uplinkPort, "uplinkPort", false, "Filter for uplink ports")
f.IntVar(&cmd.vlanID, "vlan", 0, "Filter by VLAN ID (0 = unfiltered)")
f.IntVar(&cmd.count, "count", 0, "Number of matches to return (0 = unlimited)")
}
func (cmd *info) Usage() string {
return "DVS"
}
func (cmd *info) Description() string {
return `Portgroup info for DVS.
Examples:
govc dvs.portgroup.info DSwitch
govc dvs.portgroup.info -pg InternalNetwork DSwitch
govc find / -type DistributedVirtualSwitch | xargs -n1 govc dvs.portgroup.info`
}
type infoResult struct {
Port []types.DistributedVirtualPort
cmd *info
}
func (r *infoResult) Write(w io.Writer) error {
for _, port := range r.Port {
var vlanID int32
setting := port.Config.Setting.(*types.VMwareDVSPortSetting)
switch vlan := setting.Vlan.(type) {
case *types.VmwareDistributedVirtualSwitchVlanIdSpec:
vlanID = vlan.VlanId
case *types.VmwareDistributedVirtualSwitchTrunkVlanSpec:
case *types.VmwareDistributedVirtualSwitchPvlanSpec:
vlanID = vlan.PvlanId
}
// Show port info if: VLAN ID is not defined, or VLAN ID matches requested VLAN
if r.cmd.vlanID == 0 || vlanID == int32(r.cmd.vlanID) {
fmt.Printf("PortgroupKey: %s\n", port.PortgroupKey)
fmt.Printf("DvsUuid: %s\n", port.DvsUuid)
fmt.Printf("VlanId: %d\n", vlanID)
fmt.Printf("PortKey: %s\n\n", port.Key)
}
}
return nil
}
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 1 {
return flag.ErrHelp
}
finder, err := cmd.Finder()
if err != nil {
return err
}
// Retrieve DVS reference
net, err := finder.Network(ctx, f.Arg(0))
if err != nil {
return err
}
// Convert to DVS object type
dvs, ok := net.(*object.DistributedVirtualSwitch)
if !ok {
return fmt.Errorf("%s (%s) is not a DVS", f.Arg(0), net.Reference().Type)
}
// Set base search criteria
criteria := types.DistributedVirtualSwitchPortCriteria{
Connected: types.NewBool(cmd.connected),
Active: types.NewBool(cmd.active),
UplinkPort: types.NewBool(cmd.uplinkPort),
Inside: types.NewBool(cmd.inside),
}
// If a distributed virtual portgroup path is set, then add its portgroup key to the base criteria
if len(cmd.pg) > 0 {
// Retrieve distributed virtual portgroup reference
net, err = finder.Network(ctx, cmd.pg)
if err != nil {
return err
}
// Convert distributed virtual portgroup object type
dvpg, ok := net.(*object.DistributedVirtualPortgroup)
if !ok {
return fmt.Errorf("%s (%s) is not a DVPG", cmd.pg, net.Reference().Type)
}
// Obtain portgroup key property
var dvp mo.DistributedVirtualPortgroup
if err := dvpg.Properties(ctx, dvpg.Reference(), []string{"key"}, &dvp); err != nil {
return err
}
// Add portgroup key to port search criteria
criteria.PortgroupKey = []string{dvp.Key}
}
res, err := dvs.FetchDVPorts(ctx, &criteria)
if err != nil {
return err
}
// Truncate output to -count if specified
if cmd.count > 0 && cmd.count < len(res) {
res = res[:cmd.count]
}
info := infoResult{
cmd: cmd,
Port: res,
}
return cmd.WriteResult(&info)
}

View File

@@ -1,55 +0,0 @@
/*
Copyright (c) 2016 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 (
"context"
"flag"
"fmt"
"strings"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)
type DVPortgroupConfigSpec struct {
types.DVPortgroupConfigSpec
}
func (spec *DVPortgroupConfigSpec) Register(ctx context.Context, f *flag.FlagSet) {
ptypes := []string{
string(types.DistributedVirtualPortgroupPortgroupTypeEarlyBinding),
string(types.DistributedVirtualPortgroupPortgroupTypeLateBinding),
string(types.DistributedVirtualPortgroupPortgroupTypeEphemeral),
}
f.StringVar(&spec.Type, "type", ptypes[0],
fmt.Sprintf("Portgroup type (%s)", strings.Join(ptypes, "|")))
f.Var(flags.NewInt32(&spec.NumPorts), "nports", "Number of ports")
config := new(types.VMwareDVSPortSetting)
vlan := new(types.VmwareDistributedVirtualSwitchVlanIdSpec)
spec.DefaultPortConfig = config
config.Vlan = vlan
f.Var(flags.NewInt32(&vlan.VlanId), "vlan", "VLAN ID")
}
func (spec *DVPortgroupConfigSpec) Spec() types.DVPortgroupConfigSpec {
return spec.DVPortgroupConfigSpec
}

View File

@@ -1,3 +0,0 @@
.cask
elpa
*.elc

View File

@@ -1,10 +0,0 @@
(source gnu)
(source melpa)
(package-file "govc.el")
(development
(depends-on "dash")
(depends-on "json-mode")
(depends-on "magit")
(depends-on "s"))

View File

@@ -1,27 +0,0 @@
CASK = cask
EMACS_BIN ?= emacs
EMACS_FLAGS =
EMACS_EXEC = $(CASK) exec $(EMACS_BIN) --no-site-file --no-site-lisp --batch $(EMACS_FLAGS)
OBJECTS = govc.elc
elpa:
$(CASK) install
$(CASK) update
touch $@
.PHONY: build test docs clean
build: elpa $(OBJECTS)
test: build docs
$(EMACS_EXEC) -l test/make.el -f make-test
docs: build
$(EMACS_EXEC) -l test/make.el -f make-docs
clean:
rm -f $(OBJECTS) elpa
rm -rf .cask
%.elc: %.el
$(EMACS_EXEC) -f batch-byte-compile $<

View File

@@ -1,295 +0,0 @@
# govc.el
Interface to govc for managing VMware ESXi and vCenter.
The goal of this package is to provide a simple interface for commonly used
govc commands within Emacs. This includes table based inventory/state modes
for vms, hosts, datastores and pools. The keymap for each mode provides
shortcuts for easily feeding the data in view to other govc commands.
Within the various govc modes, press `?` to see a popup menu of options.
A menu bar is enabled for certain modes, such as `govc-vm-mode` and `govc-host-mode`.
There is also a `govc` menu at all times under the `Tools` menu.
The recommended way to install govc.el is via MELPA (http://melpa.org/).
## govc-mode
Running `govc-global-mode` creates key bindings to the various govc modes.
The default prefix is `C-c ;` and can be changed by setting `govc-keymap-prefix`.
### govc-command-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>h</kbd> | Host info via govc
<kbd>p</kbd> | Pool info via govc
<kbd>v</kbd> | VM info via govc
<kbd>s</kbd> | Datastore info via govc
### govc-urls
List of URLs for use with `govc-session`.
The `govc-session-name` displayed by `govc-mode-line` uses `url-target` (anchor)
if set, otherwise `url-host` is used.
Example:
```
(setq govc-urls `("root:vagrant@localhost:18443#Vagrant-ESXi"
"root:password@192.168.1.192#Intel-NUC"
"Administrator@vsphere.local:password!@vcva-clovervm"))
```
To enter a URL that is not in the list, prefix `universal-argument`, for example:
`C-u M-x govc-vm`
To avoid putting your credentials in a variable, you can use the
auth-source search integration.
```
(setq govc-urls `("myserver-vmware-2"))
```
And then put this line in your `auth-sources` (e.g. `~/.authinfo.gpg`):
```
machine myserver-vmware-2 login tzz password mypass url "myserver-vmware-2.some.domain.here:443?insecure=true"
```
Which will result in the URL "tzz:mypass@myserver-vmware-2.some.domain.here:443?insecure=true".
For more details on `auth-sources`, see Info node `(auth) Help for users`.
When in `govc-vm` or `govc-host` mode, a default URL is composed with the
current session credentials and the IP address of the current vm/host and
the vm/host name as the session name. This makes it easier to connect to
nested ESX/vCenter VMs or directly to an ESX host.
### govc-session-url
ESX or vCenter URL set by `govc-session` via `govc-urls` selection.
### govc-session-insecure
Skip verification of server certificate when true.
This variable is set to the value of the `GOVC_INSECURE` env var by default.
It can also be set per-url via the query string (insecure=true). For example:
```
(setq govc-urls `("root:password@hostname?insecure=true"))
```
### govc-session-datacenter
Datacenter to use for the current `govc-session`.
If the endpoint has a single Datacenter it will be used by default, otherwise
`govc-session` will prompt for selection. It can also be set per-url via the
query string. For example:
```
(setq govc-urls `("root:password@hostname?datacenter=dc1"))
```
### govc-session-datastore
Datastore to use for the current `govc-session`.
If the endpoint has a single Datastore it will be used by default, otherwise
`govc-session` will prompt for selection. It can also be set per-url via the
query string. For example:
```
(setq govc-urls `("root:password@hostname?datastore=vsanDatastore"))
```
### govc-session-network
Network to use for the current `govc-session`.
## govc-tabulated-list-mode
Generic table bindings to mark/unmark rows.
In addition to any hooks its parent mode `tabulated-list-mode` might have run,
this mode runs the hook `govc-tabulated-list-mode-hook`, as the final step
during initialization.
### govc-tabulated-list-mode-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>m</kbd> | Mark and move to the next line
<kbd>u</kbd> | Unmark and move to the next line
<kbd>t</kbd> | Toggle mark
<kbd>U</kbd> | Unmark all
<kbd>M-&</kbd> | Shell CMD in BUFFER with current `govc-session` exported as GOVC_ env vars
<kbd>M-w</kbd> | Copy current selection or region to the kill ring
<kbd>M-E</kbd> | Export session to `process-environment` and `kill-ring`
## govc-host-mode
Major mode for handling a list of govc hosts.
In addition to any hooks its parent mode `govc-tabulated-list-mode` might have run,
this mode runs the hook `govc-host-mode-hook`, as the final step
during initialization.
### govc-host-mode-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>E</kbd> | Events via govc events -n `govc-max-events`
<kbd>L</kbd> | Logs via govc logs -n `govc-max-events`
<kbd>J</kbd> | JSON via govc host
<kbd>M</kbd> | Metrics info
<kbd>N</kbd> | Netstat via `govc-esxcli-netstat-info` with current host id
<kbd>O</kbd> | Object browser via govc object
<kbd>T</kbd> | Tasks via govc tasks
<kbd>c</kbd> | Connect new session for the current govc mode
<kbd>p</kbd> | Pool-mode with current session
<kbd>s</kbd> | Datastore-mode with current session
<kbd>v</kbd> | VM-mode with current session
## govc-pool-mode
Major mode for handling a list of govc pools.
In addition to any hooks its parent mode `govc-tabulated-list-mode` might have run,
this mode runs the hook `govc-pool-mode-hook`, as the final step
during initialization.
### govc-pool-mode-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>D</kbd> | Destroy via `govc-pool-destroy` on the pool selection
<kbd>E</kbd> | Events via govc events -n `govc-max-events`
<kbd>J</kbd> | JSON via govc pool
<kbd>M</kbd> | Metrics info
<kbd>O</kbd> | Object browser via govc object
<kbd>T</kbd> | Tasks via govc tasks
<kbd>c</kbd> | Connect new session for the current govc mode
<kbd>h</kbd> | Host-mode with current session
<kbd>s</kbd> | Datastore-mode with current session
<kbd>v</kbd> | VM-mode with current session
## govc-datastore-mode
Major mode for govc datastore.info.
In addition to any hooks its parent mode `tabulated-list-mode` might have run,
this mode runs the hook `govc-datastore-mode-hook`, as the final step
during initialization.
### govc-datastore-mode-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>J</kbd> | JSON via govc datastore
<kbd>M</kbd> | Metrics info
<kbd>O</kbd> | Object browser via govc object
<kbd>RET</kbd> | Browse datastore
<kbd>c</kbd> | Connect new session for the current govc mode
<kbd>h</kbd> | Host-mode with current session
<kbd>p</kbd> | Pool-mode with current session
<kbd>v</kbd> | VM-mode with current session
## govc-datastore-ls-mode
Major mode govc datastore.ls.
In addition to any hooks its parent mode `govc-tabulated-list-mode` might have run,
this mode runs the hook `govc-datastore-ls-mode-hook`, as the final step
during initialization.
### govc-datastore-ls-mode-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>I</kbd> | Info datastore disk
<kbd>J</kbd> | JSON via govc datastore
<kbd>S</kbd> | Search via govc datastore
<kbd>D</kbd> | Delete selected datastore paths
<kbd>T</kbd> | Tail datastore FILE
<kbd>+</kbd> | Mkdir via govc datastore
<kbd>DEL</kbd> | Up to parent folder
<kbd>RET</kbd> | Open datastore folder or file
## govc-vm-mode
Major mode for handling a list of govc vms.
In addition to any hooks its parent mode `govc-tabulated-list-mode` might have run,
this mode runs the hook `govc-vm-mode-hook`, as the final step
during initialization.
### govc-vm-mode-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>E</kbd> | Events via govc events -n `govc-max-events`
<kbd>L</kbd> | Logs via `govc-datastore-tail` with logDirectory of current selection
<kbd>J</kbd> | JSON via govc vm
<kbd>O</kbd> | Object browser via govc object
<kbd>T</kbd> | Tasks via govc tasks
<kbd>X</kbd> | ExtraConfig via `govc-vm-extra-config` on the current selection
<kbd>RET</kbd> | Devices via `govc-device` on the current selection
<kbd>C</kbd> | Console via `govc-vm-console` on the current selection
<kbd>V</kbd> | VNC via `govc-vm-vnc` on the current selection
<kbd>D</kbd> | Destroy via `govc-vm-destroy` on the current selection
<kbd>^</kbd> | Start via `govc-vm-start` on the current selection
<kbd>!</kbd> | Shutdown via `govc-vm-shutdown` on the current selection
<kbd>@</kbd> | Reboot via `govc-vm-reboot` on the current selection
<kbd>&</kbd> | Suspend via `govc-vm-suspend` on the current selection
<kbd>H</kbd> | Host info via `govc-host` with host(s) of current selection
<kbd>M</kbd> | Metrics info
<kbd>P</kbd> | Ping VM
<kbd>S</kbd> | Datastore via `govc-datastore-ls` with datastore of current selection
<kbd>c</kbd> | Connect new session for the current govc mode
<kbd>h</kbd> | Host-mode with current session
<kbd>p</kbd> | Pool-mode with current session
<kbd>s</kbd> | Datastore-mode with current session
## govc-device-mode
Major mode for handling a govc device.
In addition to any hooks its parent mode `govc-tabulated-list-mode` might have run,
this mode runs the hook `govc-device-mode-hook`, as the final step
during initialization.
### govc-device-mode-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>J</kbd> | JSON via govc device
<kbd>RET</kbd> | Tabulated govc device
## govc-object-mode
Major mode for handling a govc object.
In addition to any hooks its parent mode `govc-tabulated-list-mode` might have run,
this mode runs the hook `govc-object-mode-hook`, as the final step
during initialization.
### govc-object-mode-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>J</kbd> | JSON object selection via govc object
<kbd>N</kbd> | Next managed object reference
<kbd>O</kbd> | Object browser via govc object
<kbd>DEL</kbd> | Parent object selection if reachable, otherwise prompt with `govc-object-history`
<kbd>RET</kbd> | Expand object selection via govc object
## govc-metric-mode
Major mode for handling a govc metric.
In addition to any hooks its parent mode `govc-tabulated-list-mode` might have run,
this mode runs the hook `govc-metric-mode-hook`, as the final step
during initialization.
### govc-metric-mode-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>RET</kbd> | Sample metrics
<kbd>P</kbd> | Plot metric sample
<kbd>s</kbd> | Select metric names

File diff suppressed because it is too large Load Diff

View File

@@ -1,138 +0,0 @@
(defconst testsuite-dir
(if load-file-name
(file-name-directory load-file-name)
;; Fall back to default directory (in case of M-x eval-buffer)
default-directory)
"Directory of the test suite.")
(defconst govc-test-helper-path
(concat (expand-file-name (concat testsuite-dir "/../../test/test_helper.bash"))))
(load (expand-file-name "../govc" testsuite-dir) nil :no-message)
(ert-deftest test-govc-url-parse ()
(dolist (u '("root:vagrant@localhost:18443"
"Administrator@vsphere.local:vagrant@localhost"
"https://root:vagrant@localhost:18443/sdk"
"https://Administrator@vsphere.local:vagrant@localhost/sdk"))
(should (equal u (url-recreate-url (govc-url-parse u))))))
(ert-deftest test-govc-session-set-url ()
(should (equal govc-session-insecure nil))
(should (equal govc-session-datacenter nil))
(with-temp-buffer
(govc-session-set-url "vc.example.com?insecure=true&datacenter=foo&ignored=true")
(should (equal govc-session-insecure "true"))
(should (equal govc-session-datacenter "foo"))
(should (equal govc-session-datastore nil))))
(ert-deftest test-govc-copy-environment ()
(let ((process-environment)
(govc-session-url "vc.example.com")
(govc-session-insecure "false")
(govc-session-datacenter "dc1")
(govc-session-datastore "ds1")
(govc-session-network "net1"))
(govc-export-environment '-)
(dolist (e govc-environment-map)
(should (equal nil (getenv (car e)))))
(govc-export-environment (universal-argument))
(dolist (e govc-environment-map)
(should (not (equal nil (getenv (car e))))))))
(defun govc-test-env ()
(let ((url (getenv "GOVC_TEST_URL")))
(unless url
(ert-skip "env GOVC_TEST_URL not set"))
(setq govc-session-url url
govc-session-insecure "true")))
(defun govc-test-helper (arg)
(shell-command-to-string (format "bash -c \"source %s; %s\"" govc-test-helper-path arg)))
(defun govc-test-new-vm ()
(s-trim-right (govc-test-helper "new_empty_vm")))
(defun govc-test-new-id ()
(s-trim-right (govc-test-helper "new_id")))
(defun govc-test-teardown ()
(ignore-errors
(govc-test-helper "teardown")))
(ert-deftest test-govc-vm-info ()
(govc-test-env)
(unwind-protect
(let ((id (govc-test-new-vm)))
(govc-json-info "vm.info" (list id))
(with-current-buffer "*govc-json*"
(goto-char (point-min))
(let ((data (json-read)))
(should (= (length data) 1))
(should (cdr (assq 'VirtualMachines data)))))
(govc-json-info "vm.info" (list "ENOENT"))
(with-current-buffer "*govc-json*"
(goto-char (point-min))
(let ((data (json-read)))
(should (= (length data) 1))
(should (not (cdr (assq 'VirtualMachines data))))))
(let ((govc-args (list id))
(len1)
(len2))
(setq len1 (length (govc-vm-extra-config)))
(should (>= len1 1))
(govc "vm.change" "-vm" id
"-e" "govc-test-one=1"
"-e" "govc-test-two:2.2=2"
;; test that we don't choke on \n
"-e" "foo=bar
baz")
(setq len2 (length (govc-vm-extra-config)))
(should (= (- len2 len1) 3)))
(let ((govc-filter "*"))
(should (>= (length (govc-vm-info)) 1)))
(let ((govc-filter "ENOENT"))
(should (= (length (govc-vm-info)) 0)))
(govc-vm-screen id))
(govc-test-teardown)))
(ert-deftest test-govc-datastore-ls-entries ()
(govc-test-env)
(unwind-protect
(let ((id (govc-test-new-id)))
(should (>= (length (govc-datastore-ls-entries)) 1))
(let ((govc-filter (concat id "/")))
(should-error (govc-datastore-ls-entries))
(govc "datastore.mkdir" id)
(should (= (length (govc-datastore-ls-entries)) 0))
(dotimes (i 3)
(govc "datastore.mkdir" (format "%s/dir %d" id i)))
(let ((entries (govc-datastore-ls-entries)))
(should (= (length entries) 3))
(should (s-starts-with? (concat id "/dir ") (caar entries))))))
(govc-test-teardown)))
(ert-deftest test-govc-pool-ls ()
(govc-test-env)
(unwind-protect
(let* ((pools (govc-ls-pool))
(num (length pools))
(path (concat (car pools) "/" (govc-test-new-id))))
(should (>= num 1))
(message "%d existing pools [%S]" num pools)
(govc "pool.create" path)
(setq pools (govc-ls-pool))
(govc-pool-destroy path)
(should (= (- (length pools) num) 1)))
(govc-test-teardown)))
(ert-deftest test-govc-about ()
(govc-test-env)
(govc "about"))

View File

@@ -1,59 +0,0 @@
#!/usr/bin/env emacs --script
(let ((current-directory (file-name-directory load-file-name)))
(setq project-test-path (expand-file-name "." current-directory))
(setq project-root-path (expand-file-name ".." current-directory)))
(add-to-list 'load-path project-root-path)
(add-to-list 'load-path project-test-path)
(require 'lisp-mnt)
(require 'govc)
(require 's)
(defun make-test ()
(dolist (test-file (or argv (directory-files project-test-path t "-test.el$")))
(load test-file nil t))
(ert-run-tests-batch-and-exit t))
(defun govc-help ()
"Summary of govc modes in markdown format."
(interactive)
(with-help-window (help-buffer) ; TODO: this turned into a mess, but does the job of generating README.md from govc.el
(dolist (kind '(govc-mode govc-urls
govc-session-url govc-session-insecure govc-session-datacenter govc-session-datastore govc-session-network
tabulated-list host pool datastore datastore-ls vm device object metric))
(let* ((name (if (boundp kind) (symbol-name kind) (format "govc-%s-mode" kind)))
(map (if (equal 'govc-mode kind) 'govc-command-map (intern (concat name "-map"))))
(doc (lambda (f &optional all)
(let* ((txt (if (functionp f) (documentation f t) (documentation-property f 'variable-documentation)))
(ix (if all (length txt) (s-index-of "." txt))))
(s-replace (format "\n\n\\\{%s\}" (concat name "-map")) ""
(s-replace "'" "`" (substring txt 0 ix)))))))
(princ (concat (s-repeat (if (and (boundp kind) (not (fboundp kind))) 3 2) "#") " " name "\n"))
(princ (concat "\n" (funcall doc (intern name) t) "\n\n"))
(when (boundp map)
(princ (concat "### " (symbol-name map) "\n\n"))
(princ "Keybinding | Description\n")
(princ "---------------|------------------------------------------------------------\n")
(dolist (kl (govc-keymap-list (symbol-value map)))
(let ((key (govc-key-description (car kl))))
(princ (format "<kbd>%s</kbd>%s| %s\n" key (s-repeat (- 4 (length key)) " ") (funcall doc (nth 2 kl))))))
(princ "\n"))))))
(defun make-docs ()
(let ((commentary)
(summary))
(with-current-buffer (find-file-noselect (concat project-root-path "/govc.el"))
(setq commentary (s-replace ";;; Commentary:" "" (lm-commentary))
summary (lm-summary)))
(let ((readme (find-file-noselect (concat project-root-path "/README.md"))))
(with-current-buffer readme
(erase-buffer)
(govc-help)
(with-current-buffer (help-buffer)
(copy-to-buffer readme (point-min) (point-max)))
(goto-char (point-min))
(insert (concat "# govc.el\n\n" summary ".\n"))
(insert (s-replace "'" "`" (replace-regexp-in-string ";; ?" "" commentary t t)))
(save-buffer 0)))))

View File

@@ -1,103 +0,0 @@
/*
Copyright (c) 2016 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 env
import (
"context"
"flag"
"fmt"
"io"
"strings"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type env struct {
*flags.OutputFlag
*flags.ClientFlag
extra bool
}
func init() {
cli.Register("env", &env{})
}
func (cmd *env) Register(ctx context.Context, f *flag.FlagSet) {
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
f.BoolVar(&cmd.extra, "x", false, "Output variables for each GOVC_URL component")
}
func (cmd *env) Process(ctx context.Context) error {
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *env) Description() string {
return `Output the environment variables for this client.
If credentials are included in the url, they are split into separate variables.
Useful as bash scripting helper to parse GOVC_URL.`
}
func (cmd *env) Run(ctx context.Context, f *flag.FlagSet) error {
env := envResult(cmd.ClientFlag.Environ(cmd.extra))
if f.NArg() > 1 {
return flag.ErrHelp
}
// Option to just output the value, example use:
// password=$(govc env GOVC_PASSWORD)
if f.NArg() == 1 {
var output []string
prefix := fmt.Sprintf("%s=", f.Arg(0))
for _, e := range env {
if strings.HasPrefix(e, prefix) {
output = append(output, e[len(prefix):])
break
}
}
return cmd.WriteResult(envResult(output))
}
return cmd.WriteResult(env)
}
type envResult []string
func (r envResult) Write(w io.Writer) error {
for _, e := range r {
fmt.Println(e)
}
return nil
}

View File

@@ -1,187 +0,0 @@
/*
Copyright (c) 2015-2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package events
import (
"context"
"flag"
"fmt"
"io"
"os"
"reflect"
"strings"
"time"
"github.com/vmware/govmomi/event"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)
type events struct {
*flags.DatacenterFlag
Max int32
Tail bool
Force bool
Long bool
Kind kinds
}
type kinds []string
func (e *kinds) String() string {
return fmt.Sprint(*e)
}
func (e *kinds) Set(value string) error {
*e = append(*e, value)
return nil
}
func init() {
// initialize with the maximum allowed objects set
cli.Register("events", &events{})
}
func (cmd *events) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
cmd.Max = 25 // default
f.Var(flags.NewInt32(&cmd.Max), "n", "Output the last N events")
f.BoolVar(&cmd.Tail, "f", false, "Follow event stream")
f.BoolVar(&cmd.Force, "force", false, "Disable number objects to monitor limit")
f.BoolVar(&cmd.Long, "l", false, "Long listing format")
f.Var(&cmd.Kind, "type", "Include only the specified event types")
}
func (cmd *events) Description() string {
return `Display events.
Examples:
govc events vm/my-vm1 vm/my-vm2
govc events /dc1/vm/* /dc2/vm/*
govc events -type VmPoweredOffEvent -type VmPoweredOnEvent
govc ls -t HostSystem host/* | xargs govc events | grep -i vsan`
}
func (cmd *events) Usage() string {
return "[PATH]..."
}
func (cmd *events) printEvents(ctx context.Context, obj *types.ManagedObjectReference, page []types.BaseEvent, m *event.Manager) error {
event.Sort(page)
source := ""
if obj != nil {
source = obj.String()
if !cmd.JSON {
// print the object reference
fmt.Fprintf(os.Stdout, "\n==> %s <==\n", source)
}
}
for _, e := range page {
cat, err := m.EventCategory(ctx, e)
if err != nil {
return err
}
event := e.GetEvent()
r := &record{
Object: source,
CreatedTime: event.CreatedTime,
Category: cat,
Message: strings.TrimSpace(event.FullFormattedMessage),
event: e,
}
if cmd.Long {
r.Type = reflect.TypeOf(e).Elem().Name()
}
// if this is a TaskEvent gather a little more information
if t, ok := e.(*types.TaskEvent); ok {
// some tasks won't have this information, so just use the event message
if t.Info.Entity != nil {
r.Message = fmt.Sprintf("%s (target=%s %s)", r.Message, t.Info.Entity.Type, t.Info.EntityName)
}
}
if err = cmd.WriteResult(r); err != nil {
return err
}
}
return nil
}
type record struct {
Object string `json:",omitempty"`
Type string `json:",omitempty"`
CreatedTime time.Time
Category string
Message string
event types.BaseEvent
}
// Dump the raw Event rather than the record struct.
func (r *record) Dump() interface{} {
return r.event
}
func (r *record) Write(w io.Writer) error {
when := r.CreatedTime.Local().Format(time.ANSIC)
var kind string
if r.Type != "" {
kind = fmt.Sprintf(" [%s]", r.Type)
}
_, err := fmt.Fprintf(w, "[%s] [%s]%s %s\n", when, r.Category, kind, r.Message)
return err
}
func (cmd *events) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
objs, err := cmd.ManagedObjects(ctx, f.Args())
if err != nil {
return err
}
if len(objs) > 0 {
// need an event manager
m := event.NewManager(c)
// get the event stream
err = m.Events(ctx, objs, cmd.Max, cmd.Tail, cmd.Force, func(obj types.ManagedObjectReference, ee []types.BaseEvent) error {
var o *types.ManagedObjectReference
if len(objs) > 1 {
o = &obj
}
return cmd.printEvents(ctx, o, ee, m)
}, cmd.Kind...)
if err != nil {
return err
}
}
return nil
}

View File

@@ -1,44 +0,0 @@
function public-key {
local dir=${HOME}/.ssh
for f in $HOME/.ssh/{id_{rsa,dsa},*}.pub; do
if [ -r $f ]; then
echo $f
return
fi
done
echo "Can't find public key file..."
exit 1
}
PUBLIC_KEY_FILE=${PUBLIC_KEY_FILE-$(public-key)}
SSH_OPTS="-oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oLogLevel=quiet"
function upload-public-key {
local vm_name=$1
local dir=$2
if [ -z "$dir" ]
then
uid=$(echo $GOVC_GUEST_LOGIN | awk -F: '{print $1}')
dir=$(govc guest.getenv -vm ${vm_name} HOME | awk -F= '{print $2}')
if [ -z "$dir" ]
then
echo "Can't find ${uid}'s HOME dir..."
exit 1
fi
fi
govc guest.mkdir \
-vm ${vm_name} \
-p \
${dir}/.ssh
govc guest.upload \
-vm ${vm_name} \
-f \
${PUBLIC_KEY_FILE} \
${dir}/.ssh/authorized_keys
}

View File

@@ -1,251 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package export
import (
"bytes"
"context"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"flag"
"fmt"
"hash"
"io"
"os"
"path/filepath"
"strings"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/nfc"
"github.com/vmware/govmomi/ovf"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type ovfx struct {
*flags.VirtualMachineFlag
dest string
name string
force bool
images bool
sha int
mf bytes.Buffer
}
var sha = map[int]func() hash.Hash{
1: sha1.New,
256: sha256.New,
512: sha512.New,
}
func init() {
cli.Register("export.ovf", &ovfx{})
}
func (cmd *ovfx) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.StringVar(&cmd.name, "name", "", "Specifies target name (defaults to source name)")
f.BoolVar(&cmd.force, "f", false, "Overwrite existing")
f.BoolVar(&cmd.images, "i", false, "Include image files (*.{iso,img})")
f.IntVar(&cmd.sha, "sha", 0, "Generate manifest using SHA 1, 256, 512 or 0 to skip")
}
func (cmd *ovfx) Usage() string {
return "DIR"
}
func (cmd *ovfx) Description() string {
return `Export VM.
Examples:
govc export.ovf -vm $vm DIR`
}
func (cmd *ovfx) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *ovfx) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 1 {
// TODO: output summary similar to ovftool's
return flag.ErrHelp
}
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
if cmd.sha != 0 {
if _, ok := sha[cmd.sha]; !ok {
return fmt.Errorf("unknown hash: sha%d", cmd.sha)
}
}
if cmd.name == "" {
cmd.name = vm.Name()
}
cmd.dest = filepath.Join(f.Arg(0), cmd.name)
target := filepath.Join(cmd.dest, cmd.name+".ovf")
if !cmd.force {
if _, err = os.Stat(target); err == nil {
return fmt.Errorf("File already exists: %s", target)
}
}
if err = os.MkdirAll(cmd.dest, 0755); err != nil {
return err
}
lease, err := vm.Export(ctx)
if err != nil {
return err
}
info, err := lease.Wait(ctx, nil)
if err != nil {
return err
}
u := lease.StartUpdater(ctx, info)
defer u.Done()
cdp := types.OvfCreateDescriptorParams{
Name: cmd.name,
}
for _, i := range info.Items {
if !cmd.include(&i) {
continue
}
if !strings.HasPrefix(i.Path, cmd.name) {
i.Path = cmd.name + "-" + i.Path
}
err = cmd.Download(ctx, lease, i)
if err != nil {
return err
}
cdp.OvfFiles = append(cdp.OvfFiles, i.File())
}
if err = lease.Complete(ctx); err != nil {
return err
}
m := ovf.NewManager(vm.Client())
desc, err := m.CreateDescriptor(ctx, vm, cdp)
if err != nil {
return err
}
file, err := os.Create(target)
if err != nil {
return err
}
var w io.Writer = file
h, ok := cmd.newHash()
if ok {
w = io.MultiWriter(file, h)
}
_, err = io.WriteString(w, desc.OvfDescriptor)
if err != nil {
return err
}
if err = file.Close(); err != nil {
return err
}
if cmd.sha == 0 {
return nil
}
cmd.addHash(filepath.Base(target), h)
file, err = os.Create(filepath.Join(cmd.dest, cmd.name+".mf"))
if err != nil {
return err
}
_, err = io.Copy(file, &cmd.mf)
if err != nil {
return err
}
return file.Close()
}
func (cmd *ovfx) include(item *nfc.FileItem) bool {
if cmd.images {
return true
}
return filepath.Ext(item.Path) == ".vmdk"
}
func (cmd *ovfx) newHash() (hash.Hash, bool) {
if h, ok := sha[cmd.sha]; ok {
return h(), true
}
return nil, false
}
func (cmd *ovfx) addHash(p string, h hash.Hash) {
_, _ = fmt.Fprintf(&cmd.mf, "SHA%d(%s)= %x\n", cmd.sha, p, h.Sum(nil))
}
func (cmd *ovfx) Download(ctx context.Context, lease *nfc.Lease, item nfc.FileItem) error {
path := filepath.Join(cmd.dest, item.Path)
logger := cmd.ProgressLogger(fmt.Sprintf("Downloading %s... ", item.Path))
defer logger.Wait()
opts := soap.Download{
Progress: logger,
}
if h, ok := cmd.newHash(); ok {
opts.Writer = h
defer cmd.addHash(item.Path, h)
}
return lease.DownloadFile(ctx, path, item, opts)
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,78 +0,0 @@
/*
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 fields
import (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
)
type add struct {
*flags.ClientFlag
}
func init() {
cli.Register("fields.add", &add{})
}
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(ctx context.Context) error {
if err := cmd.ClientFlag.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() != 1 {
return flag.ErrHelp
}
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetCustomFieldsManager(c)
if err != nil {
return err
}
name := f.Arg(0)
def, err := m.Add(ctx, name, "", nil, nil)
if err != nil {
return err
}
fmt.Printf("%d\n", def.Key)
return nil
}

View File

@@ -1,74 +0,0 @@
/*
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 fields
import (
"context"
"flag"
"fmt"
"os"
"text/tabwriter"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
)
type ls struct {
*flags.ClientFlag
}
func init() {
cli.Register("fields.ls", &ls{})
}
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(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetCustomFieldsManager(c)
if err != nil {
return err
}
field, err := m.Field(ctx)
if err != nil {
return err
}
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
for _, def := range field {
fmt.Fprintf(tw, "%d\t%s\n", def.Key, def.Name)
}
return tw.Flush()
}

View File

@@ -1,75 +0,0 @@
/*
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 fields
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
)
type rename struct {
*flags.ClientFlag
}
func init() {
cli.Register("fields.rename", &rename{})
}
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(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *rename) Usage() string {
return "KEY NAME"
}
func (cmd *rename) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 2 {
return flag.ErrHelp
}
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetCustomFieldsManager(c)
if err != nil {
return err
}
key, err := m.FindKey(ctx, f.Arg(0))
if err != nil {
return err
}
name := f.Arg(1)
return m.Rename(ctx, key, name)
}

View File

@@ -1,75 +0,0 @@
/*
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 fields
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
)
type rm struct {
*flags.ClientFlag
}
func init() {
cli.Register("fields.rm", &rm{})
}
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(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *rm) Usage() string {
return "KEY..."
}
func (cmd *rm) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetCustomFieldsManager(c)
if err != nil {
return err
}
for _, name := range f.Args() {
key, err := m.FindKey(ctx, name)
if err != nil {
return err
}
if err := m.Remove(ctx, key); err != nil {
return err
}
}
return nil
}

View File

@@ -1,89 +0,0 @@
/*
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 fields
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
)
type set struct {
*flags.DatacenterFlag
}
func init() {
cli.Register("fields.set", &set{})
}
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(ctx context.Context) error {
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *set) Usage() string {
return "KEY VALUE PATH..."
}
func (cmd *set) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() < 3 {
return flag.ErrHelp
}
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetCustomFieldsManager(c)
if err != nil {
return err
}
args := f.Args()
key, err := m.FindKey(ctx, args[0])
if err != nil {
return err
}
val := args[1]
objs, err := cmd.ManagedObjects(ctx, args[2:])
if err != nil {
return err
}
for _, ref := range objs {
err := m.Set(ctx, ref, key, val)
if err != nil {
return err
}
}
return nil
}

View File

@@ -1,626 +0,0 @@
/*
Copyright (c) 2014-2018 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 (
"context"
"crypto/sha1"
"crypto/tls"
"encoding/json"
"errors"
"flag"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
"time"
"github.com/vmware/govmomi/session"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
const (
envURL = "GOVC_URL"
envUsername = "GOVC_USERNAME"
envPassword = "GOVC_PASSWORD"
envCertificate = "GOVC_CERTIFICATE"
envPrivateKey = "GOVC_PRIVATE_KEY"
envInsecure = "GOVC_INSECURE"
envPersist = "GOVC_PERSIST_SESSION"
envMinAPIVersion = "GOVC_MIN_API_VERSION"
envVimNamespace = "GOVC_VIM_NAMESPACE"
envVimVersion = "GOVC_VIM_VERSION"
envTLSCaCerts = "GOVC_TLS_CA_CERTS"
envTLSKnownHosts = "GOVC_TLS_KNOWN_HOSTS"
)
const cDescr = "ESX or vCenter URL"
type ClientFlag struct {
common
*DebugFlag
url *url.URL
username string
password string
cert string
key string
insecure bool
persist bool
minAPIVersion string
vimNamespace string
vimVersion string
tlsCaCerts string
tlsKnownHosts string
client *vim25.Client
Login func(context.Context, *vim25.Client) error
}
var (
home = os.Getenv("GOVMOMI_HOME")
clientFlagKey = flagKey("client")
)
func init() {
if home == "" {
home = filepath.Join(os.Getenv("HOME"), ".govmomi")
}
}
func NewClientFlag(ctx context.Context) (*ClientFlag, context.Context) {
if v := ctx.Value(clientFlagKey); v != nil {
return v.(*ClientFlag), ctx
}
v := &ClientFlag{}
v.Login = v.login
v.DebugFlag, ctx = NewDebugFlag(ctx)
ctx = context.WithValue(ctx, clientFlagKey, v)
return v, ctx
}
func (flag *ClientFlag) URLWithoutPassword() *url.URL {
if flag.url == nil {
return nil
}
withoutCredentials := *flag.url
withoutCredentials.User = url.User(flag.url.User.Username())
return &withoutCredentials
}
func (flag *ClientFlag) IsSecure() bool {
return !flag.insecure
}
func (flag *ClientFlag) String() string {
url := flag.URLWithoutPassword()
if url == nil {
return ""
}
return url.String()
}
func (flag *ClientFlag) Set(s string) error {
var err error
flag.url, err = soap.ParseURL(s)
return err
}
func (flag *ClientFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.DebugFlag.Register(ctx, f)
{
flag.Set(os.Getenv(envURL))
usage := fmt.Sprintf("%s [%s]", cDescr, envURL)
f.Var(flag, "u", usage)
}
{
flag.username = os.Getenv(envUsername)
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
switch env := strings.ToLower(os.Getenv(envInsecure)); env {
case "1", "true":
insecure = true
}
usage := fmt.Sprintf("Skip verification of server certificate [%s]", envInsecure)
f.BoolVar(&flag.insecure, "k", insecure, usage)
}
{
persist := true
switch env := strings.ToLower(os.Getenv(envPersist)); env {
case "0", "false":
persist = false
}
usage := fmt.Sprintf("Persist session to disk [%s]", envPersist)
f.BoolVar(&flag.persist, "persist-session", persist, usage)
}
{
env := os.Getenv(envMinAPIVersion)
if env == "" {
env = soap.DefaultMinVimVersion
}
flag.minAPIVersion = env
}
{
value := os.Getenv(envVimNamespace)
if value == "" {
value = soap.DefaultVimNamespace
}
usage := fmt.Sprintf("Vim namespace [%s]", envVimNamespace)
f.StringVar(&flag.vimNamespace, "vim-namespace", value, usage)
}
{
value := os.Getenv(envVimVersion)
if value == "" {
value = soap.DefaultVimVersion
}
usage := fmt.Sprintf("Vim version [%s]", envVimVersion)
f.StringVar(&flag.vimVersion, "vim-version", value, usage)
}
{
value := os.Getenv(envTLSCaCerts)
usage := fmt.Sprintf("TLS CA certificates file [%s]", envTLSCaCerts)
f.StringVar(&flag.tlsCaCerts, "tls-ca-certs", value, usage)
}
{
value := os.Getenv(envTLSKnownHosts)
usage := fmt.Sprintf("TLS known hosts file [%s]", envTLSKnownHosts)
f.StringVar(&flag.tlsKnownHosts, "tls-known-hosts", value, usage)
}
})
}
func (flag *ClientFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.DebugFlag.Process(ctx); err != nil {
return err
}
if flag.url == nil {
return errors.New("specify an " + cDescr)
}
// 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 {
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
})
}
// configure TLS and retry settings before making any connections
func (flag *ClientFlag) configure(sc *soap.Client) (soap.RoundTripper, error) {
// Set namespace and version
sc.Namespace = flag.vimNamespace
sc.Version = flag.vimVersion
sc.UserAgent = fmt.Sprintf("govc/%s", Version)
if err := flag.SetRootCAs(sc); err != nil {
return nil, err
}
if err := sc.LoadThumbprints(flag.tlsKnownHosts); err != nil {
return nil, err
}
if t, ok := sc.Transport.(*http.Transport); ok {
var err error
value := os.Getenv("GOVC_TLS_HANDSHAKE_TIMEOUT")
if value != "" {
t.TLSHandshakeTimeout, err = time.ParseDuration(value)
if err != nil {
return nil, err
}
}
}
// Retry twice when a temporary I/O error occurs.
// This means a maximum of 3 attempts.
return vim25.Retry(sc, vim25.TemporaryNetworkError(3)), nil
}
func (flag *ClientFlag) sessionFile() string {
url := flag.URLWithoutPassword()
// Key session file off of full URI and insecure setting.
// Hash key to get a predictable, canonical format.
key := fmt.Sprintf("%s#insecure=%t", url.String(), flag.insecure)
name := fmt.Sprintf("%040x", sha1.Sum([]byte(key)))
return filepath.Join(home, "sessions", name)
}
func (flag *ClientFlag) saveClient(c *vim25.Client) error {
if !flag.persist {
return nil
}
p := flag.sessionFile()
err := os.MkdirAll(filepath.Dir(p), 0700)
if err != nil {
return err
}
f, err := os.OpenFile(p, os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
return err
}
defer f.Close()
err = json.NewEncoder(f).Encode(c)
if err != nil {
return err
}
return nil
}
func (flag *ClientFlag) restoreClient(c *vim25.Client) (bool, error) {
if !flag.persist {
return false, nil
}
f, err := os.Open(flag.sessionFile())
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
defer f.Close()
dec := json.NewDecoder(f)
err = dec.Decode(c)
if err != nil {
return false, err
}
return true, nil
}
func (flag *ClientFlag) loadClient() (*vim25.Client, error) {
c := new(vim25.Client)
ok, err := flag.restoreClient(c)
if err != nil {
return nil, err
}
if !ok || !c.Valid() {
return nil, nil
}
c.RoundTripper, err = flag.configure(c.Client)
if err != nil {
return nil, err
}
m := session.NewManager(c)
u, err := m.UserSession(context.TODO())
if err != nil {
if soap.IsSoapFault(err) {
fault := soap.ToSoapFault(err).VimFault()
// If the PropertyCollector is not found, the saved session for this URL is not valid
if _, ok := fault.(types.ManagedObjectNotFound); ok {
return nil, nil
}
}
return nil, err
}
// If the session is nil, the client is not authenticated
if u == nil {
return nil, nil
}
return c, nil
}
func (flag *ClientFlag) SetRootCAs(c *soap.Client) error {
if flag.tlsCaCerts != "" {
return c.SetRootCAs(flag.tlsCaCerts)
}
return nil
}
func (flag *ClientFlag) login(ctx context.Context, c *vim25.Client) error {
m := session.NewManager(c)
u := flag.url.User
if u.Username() == "" {
if !c.IsVC() {
// If no username is provided, try to acquire a local ticket.
// When invoked remotely, ESX returns an InvalidRequestFault.
// So, rather than return an error here, fallthrough to Login() with the original User to
// to avoid what would be a confusing error message.
luser, lerr := flag.localTicket(ctx, m)
if lerr == nil {
// We are running directly on an ESX or Workstation host and can use the ticket with Login()
u = luser
} else {
flag.persist = true // Not persisting, but this avoids the call to Logout()
return nil // Avoid SaveSession for non-authenticated session
}
}
}
if flag.cert != "" {
err := m.LoginExtensionByCertificate(ctx, u.Username(), "")
if err != nil {
return err
}
}
return m.Login(ctx, u)
}
func (flag *ClientFlag) newClient() (*vim25.Client, error) {
ctx := context.TODO()
sc := soap.NewClient(flag.url, flag.insecure)
if flag.cert != "" {
cert, err := tls.LoadX509KeyPair(flag.cert, flag.key)
if err != nil {
return nil, err
}
sc.SetCertificate(cert)
}
rt, err := flag.configure(sc)
if err != nil {
return nil, err
}
c, err := vim25.NewClient(ctx, rt)
if err != nil {
return nil, err
}
// Set client, since we didn't pass it in the constructor
c.Client = sc
if err := flag.Login(ctx, c); err != nil {
return nil, err
}
return c, flag.saveClient(c)
}
func (flag *ClientFlag) localTicket(ctx context.Context, m *session.Manager) (*url.Userinfo, error) {
ticket, err := m.AcquireLocalTicket(ctx, os.Getenv("USER"))
if err != nil {
return nil, err
}
password, err := ioutil.ReadFile(ticket.PasswordFilePath)
if err != nil {
return nil, err
}
return url.UserPassword(ticket.UserName, string(password)), nil
}
func isDevelopmentVersion(apiVersion string) bool {
// Skip version check for development builds which can be in the form of "r4A70F" or "6.5.x"
return strings.Count(apiVersion, ".") == 0 || strings.HasSuffix(apiVersion, ".x")
}
// apiVersionValid returns whether or not the API version supported by the
// server the client is connected to is not recent enough.
func apiVersionValid(c *vim25.Client, minVersionString string) error {
if minVersionString == "-" {
// Disable version check
return nil
}
apiVersion := c.ServiceContent.About.ApiVersion
if isDevelopmentVersion(apiVersion) {
return nil
}
realVersion, err := ParseVersion(apiVersion)
if err != nil {
return fmt.Errorf("Error parsing API version %q: %s", apiVersion, err)
}
minVersion, err := ParseVersion(minVersionString)
if err != nil {
return fmt.Errorf("Error parsing %s=%q: %s", envMinAPIVersion, minVersionString, err)
}
if !minVersion.Lte(realVersion) {
err = fmt.Errorf("Require API version %q, connected to API version %q (set %s to override)",
minVersionString,
c.ServiceContent.About.ApiVersion,
envMinAPIVersion)
return err
}
return nil
}
func (flag *ClientFlag) Client() (*vim25.Client, error) {
if flag.client != nil {
return flag.client, nil
}
c, err := flag.loadClient()
if err != nil {
return nil, err
}
// loadClient returns nil if it was unable to load a session from disk
if c == nil {
c, err = flag.newClient()
if err != nil {
return nil, err
}
}
// Check that the endpoint has the right API version
err = apiVersionValid(c, flag.minAPIVersion)
if err != nil {
return nil, err
}
flag.client = c
return flag.client, nil
}
func (flag *ClientFlag) Logout(ctx context.Context) error {
if flag.persist || flag.client == nil {
return nil
}
m := session.NewManager(flag.client)
return m.Logout(ctx)
}
// Environ returns the govc environment variables for this connection
func (flag *ClientFlag) Environ(extra bool) []string {
var env []string
add := func(k, v string) {
env = append(env, fmt.Sprintf("%s=%s", k, v))
}
u := *flag.url
if u.User != nil {
add(envUsername, u.User.Username())
if p, ok := u.User.Password(); ok {
add(envPassword, p)
}
u.User = nil
}
if u.Path == "/sdk" {
u.Path = ""
}
u.Fragment = ""
u.RawQuery = ""
val := u.String()
prefix := "https://"
if strings.HasPrefix(val, prefix) {
val = val[len(prefix):]
}
add(envURL, val)
keys := []string{
envCertificate,
envPrivateKey,
envInsecure,
envPersist,
envMinAPIVersion,
envVimNamespace,
envVimVersion,
}
for _, k := range keys {
if v := os.Getenv(k); v != "" {
add(k, v)
}
}
if extra {
add("GOVC_URL_SCHEME", flag.url.Scheme)
v := strings.SplitN(u.Host, ":", 2)
add("GOVC_URL_HOST", v[0])
if len(v) == 2 {
add("GOVC_URL_PORT", v[1])
}
add("GOVC_URL_PATH", flag.url.Path)
if f := flag.url.Fragment; f != "" {
add("GOVC_URL_FRAGMENT", f)
}
if q := flag.url.RawQuery; q != "" {
add("GOVC_URL_QUERY", q)
}
}
return env
}

View File

@@ -1,191 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package flags
import (
"context"
"flag"
"fmt"
"os"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/view"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type ClusterFlag struct {
common
*DatacenterFlag
Name string
cluster *object.ClusterComputeResource
pc *property.Collector
}
var clusterFlagKey = flagKey("cluster")
func NewClusterFlag(ctx context.Context) (*ClusterFlag, context.Context) {
if v := ctx.Value(clusterFlagKey); v != nil {
return v.(*ClusterFlag), ctx
}
v := &ClusterFlag{}
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
ctx = context.WithValue(ctx, clusterFlagKey, v)
return v, ctx
}
func (f *ClusterFlag) Register(ctx context.Context, fs *flag.FlagSet) {
f.RegisterOnce(func() {
f.DatacenterFlag.Register(ctx, fs)
env := "GOVC_CLUSTER"
value := os.Getenv(env)
usage := fmt.Sprintf("Cluster [%s]", env)
fs.StringVar(&f.Name, "cluster", value, usage)
})
}
func (f *ClusterFlag) Process(ctx context.Context) error {
return f.ProcessOnce(func() error {
if err := f.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (f *ClusterFlag) Cluster() (*object.ClusterComputeResource, error) {
if f.cluster != nil {
return f.cluster, nil
}
finder, err := f.Finder()
if err != nil {
return nil, err
}
if f.cluster, err = finder.ClusterComputeResourceOrDefault(context.TODO(), f.Name); err != nil {
return nil, err
}
f.pc = property.DefaultCollector(f.cluster.Client())
return f.cluster, nil
}
func (f *ClusterFlag) ClusterIfSpecified() (*object.ClusterComputeResource, error) {
if f.Name == "" {
return nil, nil
}
return f.Cluster()
}
func (f *ClusterFlag) Reconfigure(ctx context.Context, spec types.BaseComputeResourceConfigSpec) error {
cluster, err := f.Cluster()
if err != nil {
return err
}
task, err := cluster.Reconfigure(ctx, spec, true)
if err != nil {
return err
}
logger := f.ProgressLogger(fmt.Sprintf("Reconfigure %s...", cluster.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}
func (f *ClusterFlag) objectMap(ctx context.Context, kind string, names []string) (map[string]types.ManagedObjectReference, error) {
cluster, err := f.Cluster()
if err != nil {
return nil, err
}
objects := make(map[string]types.ManagedObjectReference, len(names))
for _, name := range names {
objects[name] = types.ManagedObjectReference{}
}
m := view.NewManager(cluster.Client())
v, err := m.CreateContainerView(ctx, cluster.Reference(), []string{kind}, true)
if err != nil {
return nil, err
}
defer v.Destroy(ctx)
var entities []mo.ManagedEntity
err = v.Retrieve(ctx, []string{"ManagedEntity"}, []string{"name"}, &entities)
if err != nil {
return nil, err
}
for _, e := range entities {
if _, ok := objects[e.Name]; ok {
objects[e.Name] = e.Self
}
}
for name, ref := range objects {
if ref.Value == "" {
return nil, fmt.Errorf("%s %q not found", kind, name)
}
}
return objects, nil
}
func (f *ClusterFlag) ObjectList(ctx context.Context, kind string, names []string) ([]types.ManagedObjectReference, error) {
objs, err := f.objectMap(ctx, kind, names)
if err != nil {
return nil, err
}
var refs []types.ManagedObjectReference
for _, name := range names { // preserve order
refs = append(refs, objs[name])
}
return refs, nil
}
func (f *ClusterFlag) Names(ctx context.Context, refs []types.ManagedObjectReference) (map[types.ManagedObjectReference]string, error) {
names := make(map[types.ManagedObjectReference]string, len(refs))
if len(refs) != 0 {
var objs []mo.ManagedEntity
err := f.pc.Retrieve(ctx, refs, []string{"name"}, &objs)
if err != nil {
return nil, err
}
for _, obj := range objs {
names[obj.Self] = obj.Name
}
}
return names, nil
}

View File

@@ -1,38 +0,0 @@
/*
Copyright (c) 2015-2016 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 "sync"
// Key type for storing flag instances in a context.Context.
type flagKey string
// Type to help flags out with only registering/processing once.
type common struct {
register sync.Once
process sync.Once
}
func (c *common) RegisterOnce(fn func()) {
c.register.Do(fn)
}
func (c *common) ProcessOnce(fn func() error) (err error) {
c.process.Do(func() {
err = fn()
})
return err
}

View File

@@ -1,170 +0,0 @@
/*
Copyright (c) 2014-2016 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 (
"context"
"flag"
"fmt"
"os"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
)
type DatacenterFlag struct {
common
*ClientFlag
*OutputFlag
Name string
dc *object.Datacenter
finder *find.Finder
err error
}
var datacenterFlagKey = flagKey("datacenter")
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"
value := os.Getenv(env)
usage := fmt.Sprintf("Datacenter [%s]", env)
f.StringVar(&flag.Name, "dc", value, usage)
})
}
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) {
if flag.finder != nil {
return flag.finder, nil
}
c, err := flag.Client()
if err != nil {
return nil, err
}
finder := find.NewFinder(c, flag.JSON || flag.Dump)
// Datacenter is not required (ls command for example).
// Set for relative func if dc flag is given or
// if there is a single (default) Datacenter
ctx := context.TODO()
if flag.Name == "" {
flag.dc, flag.err = finder.DefaultDatacenter(ctx)
} else {
if flag.dc, err = finder.Datacenter(ctx, flag.Name); err != nil {
return nil, err
}
}
finder.SetDatacenter(flag.dc)
flag.finder = finder
return flag.finder, nil
}
func (flag *DatacenterFlag) Datacenter() (*object.Datacenter, error) {
if flag.dc != nil {
return flag.dc, nil
}
_, err := flag.Finder()
if err != nil {
return nil, err
}
if flag.err != nil {
// Should only happen if no dc is specified and len(dcs) > 1
return nil, flag.err
}
return flag.dc, err
}
func (flag *DatacenterFlag) DatacenterIfSpecified() (*object.Datacenter, error) {
if flag.Name == "" {
return nil, nil
}
return flag.Datacenter()
}
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
}
if len(elements) == 0 {
return nil, fmt.Errorf("object '%s' not found", arg)
}
for _, e := range elements {
refs = append(refs, e.Object.Reference())
}
}
return refs, nil
}

View File

@@ -1,146 +0,0 @@
/*
Copyright (c) 2014-2016 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 (
"context"
"flag"
"fmt"
"os"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
)
type DatastoreFlag struct {
common
*DatacenterFlag
Name string
ds *object.Datastore
}
var datastoreFlagKey = flagKey("datastore")
// NewCustomDatastoreFlag creates and returns a new DatastoreFlag without
// trying to retrieve an existing one from the specified context.
func NewCustomDatastoreFlag(ctx context.Context) (*DatastoreFlag, context.Context) {
v := &DatastoreFlag{}
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
return v, ctx
}
func NewDatastoreFlag(ctx context.Context) (*DatastoreFlag, context.Context) {
if v := ctx.Value(datastoreFlagKey); v != nil {
return v.(*DatastoreFlag), ctx
}
v, ctx := NewCustomDatastoreFlag(ctx)
ctx = context.WithValue(ctx, datastoreFlagKey, v)
return v, ctx
}
func (f *DatastoreFlag) Register(ctx context.Context, fs *flag.FlagSet) {
f.RegisterOnce(func() {
f.DatacenterFlag.Register(ctx, fs)
env := "GOVC_DATASTORE"
value := os.Getenv(env)
usage := fmt.Sprintf("Datastore [%s]", env)
fs.StringVar(&f.Name, "ds", value, usage)
})
}
func (f *DatastoreFlag) Process(ctx context.Context) error {
return f.ProcessOnce(func() error {
if err := f.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (f *DatastoreFlag) Args(args []string) []object.DatastorePath {
var files []object.DatastorePath
for _, arg := range args {
var p object.DatastorePath
if p.FromString(arg) {
f.Name = p.Datastore
} else {
p.Datastore = f.Name
p.Path = arg
}
files = append(files, p)
}
return files
}
func (f *DatastoreFlag) Datastore() (*object.Datastore, error) {
if f.ds != nil {
return f.ds, nil
}
var p object.DatastorePath
if p.FromString(f.Name) {
// Example use case:
// -ds "$(govc object.collect -s vm/foo config.files.logDirectory)"
f.Name = p.Datastore
}
finder, err := f.Finder()
if err != nil {
return nil, err
}
if f.ds, err = finder.DatastoreOrDefault(context.TODO(), f.Name); err != nil {
return nil, err
}
return f.ds, nil
}
func (flag *DatastoreFlag) DatastoreIfSpecified() (*object.Datastore, error) {
if flag.Name == "" {
return nil, nil
}
return flag.Datastore()
}
func (f *DatastoreFlag) DatastorePath(name string) (string, error) {
ds, err := f.Datastore()
if err != nil {
return "", err
}
return ds.Path(name), nil
}
func (f *DatastoreFlag) Stat(ctx context.Context, file string) (types.BaseFileInfo, error) {
ds, err := f.Datastore()
if err != nil {
return nil, err
}
return ds.Stat(ctx, file)
}

View File

@@ -1,99 +0,0 @@
/*
Copyright (c) 2014-2016 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 (
"context"
"flag"
"fmt"
"os"
"path/filepath"
"strings"
"time"
"github.com/vmware/govmomi/vim25/debug"
)
type DebugFlag struct {
common
enable bool
}
var debugFlagKey = flagKey("debug")
func NewDebugFlag(ctx context.Context) (*DebugFlag, context.Context) {
if v := ctx.Value(debugFlagKey); v != nil {
return v.(*DebugFlag), ctx
}
v := &DebugFlag{}
ctx = context.WithValue(ctx, debugFlagKey, v)
return v, ctx
}
func (flag *DebugFlag) Register(ctx context.Context, f *flag.FlagSet) {
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.
r := os.Getenv("GOVC_DEBUG_PATH")
if r == "" {
r = home
}
r = filepath.Join(r, "debug")
// Path for this particular run.
run := os.Getenv("GOVC_DEBUG_PATH_RUN")
if run == "" {
now := time.Now().Format("2006-01-02T15-04-05.999999999")
r = filepath.Join(r, now)
} else {
// reuse the same path
r = filepath.Join(r, run)
_ = os.RemoveAll(r)
}
err := os.MkdirAll(r, 0700)
if err != nil {
return err
}
p := debug.FileProvider{
Path: r,
}
debug.SetProvider(&p)
return nil
})
}

View File

@@ -1,31 +0,0 @@
/*
Copyright (c) 2014-2016 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 (
"context"
"flag"
)
type EmptyFlag struct{}
func (flag *EmptyFlag) Register(ctx context.Context, f *flag.FlagSet) {
}
func (flag *EmptyFlag) Process(ctx context.Context) error {
return nil
}

View File

@@ -1,131 +0,0 @@
/*
Copyright (c) 2014-2016 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 (
"context"
"flag"
"fmt"
"os"
"github.com/vmware/govmomi/object"
)
type FolderFlag struct {
common
*DatacenterFlag
name string
folder *object.Folder
}
var folderFlagKey = flagKey("folder")
func NewFolderFlag(ctx context.Context) (*FolderFlag, context.Context) {
if v := ctx.Value(folderFlagKey); v != nil {
return v.(*FolderFlag), ctx
}
v := &FolderFlag{}
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
ctx = context.WithValue(ctx, folderFlagKey, v)
return v, ctx
}
func (flag *FolderFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.DatacenterFlag.Register(ctx, f)
env := "GOVC_FOLDER"
value := os.Getenv(env)
usage := fmt.Sprintf("Inventory folder [%s]", env)
f.StringVar(&flag.name, "folder", value, usage)
})
}
func (flag *FolderFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (flag *FolderFlag) Folder() (*object.Folder, error) {
if flag.folder != nil {
return flag.folder, nil
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
if flag.folder, err = finder.FolderOrDefault(context.TODO(), flag.name); err != nil {
return nil, err
}
return flag.folder, nil
}
func (flag *FolderFlag) FolderOrDefault(kind string) (*object.Folder, error) {
if flag.folder != nil {
return flag.folder, nil
}
if flag.name != "" {
return flag.Folder()
}
// RootFolder, no dc required
if kind == "/" {
client, err := flag.Client()
if err != nil {
return nil, err
}
flag.folder = object.NewRootFolder(client)
return flag.folder, nil
}
dc, err := flag.Datacenter()
if err != nil {
return nil, err
}
folders, err := dc.Folders(context.TODO())
if err != nil {
return nil, err
}
switch kind {
case "vm":
flag.folder = folders.VmFolder
case "host":
flag.folder = folders.HostFolder
case "datastore":
flag.folder = folders.DatastoreFolder
case "network":
flag.folder = folders.NetworkFolder
default:
panic(kind)
}
return flag.folder, nil
}

View File

@@ -1,101 +0,0 @@
/*
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 (
"context"
"flag"
"fmt"
"net/http"
"net/url"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25"
"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, "thumbprint", "", "SHA-1 thumbprint 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, "Accept host thumbprint without verification")
})
}
func (flag *HostConnectFlag) Process(ctx context.Context) error {
return nil
}
// Spec attempts to fill in SslThumbprint if empty.
// First checks GOVC_TLS_KNOWN_HOSTS, if not found and noverify=true then
// use object.HostCertificateInfo to get the thumbprint.
func (flag *HostConnectFlag) Spec(c *vim25.Client) types.HostConnectSpec {
spec := flag.HostConnectSpec
if spec.SslThumbprint == "" {
spec.SslThumbprint = c.Thumbprint(spec.HostName)
if spec.SslThumbprint == "" && flag.noverify {
var info object.HostCertificateInfo
t := c.Transport.(*http.Transport)
_ = info.FromURL(&url.URL{Host: spec.HostName}, t.TLSClientConfig)
spec.SslThumbprint = info.ThumbprintSHA1
}
}
return spec
}
// Fault checks if error is SSLVerifyFault, including the thumbprint if so
func (flag *HostConnectFlag) Fault(err error) error {
if err == nil {
return nil
}
if f, ok := err.(types.HasFault); ok {
switch fault := f.Fault().(type) {
case *types.SSLVerifyFault:
return fmt.Errorf("%s thumbprint=%s", err, fault.Thumbprint)
}
}
return err
}

View File

@@ -1,141 +0,0 @@
/*
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 flags
import (
"context"
"flag"
"fmt"
"os"
"github.com/vmware/govmomi/object"
)
type HostSystemFlag struct {
common
*ClientFlag
*DatacenterFlag
*SearchFlag
name string
host *object.HostSystem
pool *object.ResourcePool
}
var hostSystemFlagKey = flagKey("hostSystem")
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)
env := "GOVC_HOST"
value := os.Getenv(env)
usage := fmt.Sprintf("Host system [%s]", env)
f.StringVar(&flag.name, "host", value, usage)
})
}
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) {
if flag.host != nil {
return flag.host, nil
}
// Use search flags if specified.
if flag.SearchFlag.IsSet() {
host, err := flag.SearchFlag.HostSystem()
if err != nil {
return nil, err
}
flag.host = host
return flag.host, nil
}
// Never look for a default host system.
// A host system parameter is optional for vm creation. It uses a mandatory
// resource pool parameter to determine where the vm should be placed.
if flag.name == "" {
return nil, nil
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
flag.host, err = finder.HostSystem(context.TODO(), flag.name)
return flag.host, err
}
func (flag *HostSystemFlag) HostSystem() (*object.HostSystem, error) {
host, err := flag.HostSystemIfSpecified()
if err != nil {
return nil, err
}
if host != nil {
return host, nil
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
flag.host, err = finder.DefaultHostSystem(context.TODO())
return flag.host, err
}
func (flag *HostSystemFlag) HostNetworkSystem() (*object.HostNetworkSystem, error) {
host, err := flag.HostSystem()
if err != nil {
return nil, err
}
return host.ConfigManager().NetworkSystem(context.TODO())
}

View File

@@ -1,72 +0,0 @@
/*
Copyright (c) 2016-2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package flags
import (
"flag"
"fmt"
"strconv"
)
// This flag type is internal to stdlib:
// https://github.com/golang/go/blob/master/src/cmd/internal/obj/flag.go
type int32Value int32
func (i *int32Value) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 32)
*i = int32Value(v)
return err
}
func (i *int32Value) Get() interface{} {
return int32(*i)
}
func (i *int32Value) String() string {
return fmt.Sprintf("%v", *i)
}
// NewInt32 behaves as flag.IntVar, but using an int32 type.
func NewInt32(v *int32) flag.Value {
return (*int32Value)(v)
}
type int32ptrValue struct {
val **int32
}
func (i *int32ptrValue) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 32)
*i.val = new(int32)
**i.val = int32(v)
return err
}
func (i *int32ptrValue) Get() interface{} {
if i.val == nil || *i.val == nil {
return nil
}
return *i.val
}
func (i *int32ptrValue) String() string {
return fmt.Sprintf("%v", i.Get())
}
func NewOptionalInt32(v **int32) flag.Value {
return &int32ptrValue{val: v}
}

View File

@@ -1,72 +0,0 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package flags
import (
"flag"
"fmt"
"strconv"
)
// This flag type is internal to stdlib:
// https://github.com/golang/go/blob/master/src/cmd/internal/obj/flag.go
type int64Value int64
func (i *int64Value) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 64)
*i = int64Value(v)
return err
}
func (i *int64Value) Get() interface{} {
return int64(*i)
}
func (i *int64Value) String() string {
return fmt.Sprintf("%v", *i)
}
// NewInt64 behaves as flag.IntVar, but using an int64 type.
func NewInt64(v *int64) flag.Value {
return (*int64Value)(v)
}
type int64ptrValue struct {
val **int64
}
func (i *int64ptrValue) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 64)
*i.val = new(int64)
**i.val = int64(v)
return err
}
func (i *int64ptrValue) Get() interface{} {
if i.val == nil || *i.val == nil {
return nil
}
return **i.val
}
func (i *int64ptrValue) String() string {
return fmt.Sprintf("%v", i.Get())
}
func NewOptionalInt64(v **int64) flag.Value {
return &int64ptrValue{val: v}
}

View File

@@ -1,147 +0,0 @@
/*
Copyright (c) 2014-2016 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 (
"context"
"flag"
"fmt"
"os"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
)
type NetworkFlag struct {
common
*DatacenterFlag
name string
net object.NetworkReference
adapter string
address string
isset bool
}
var networkFlagKey = flagKey("network")
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(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.DatacenterFlag.Register(ctx, f)
env := "GOVC_NETWORK"
value := os.Getenv(env)
flag.name = value
usage := fmt.Sprintf("Network [%s]", env)
f.Var(flag, "net", usage)
f.StringVar(&flag.adapter, "net.adapter", "e1000", "Network adapter type")
f.StringVar(&flag.address, "net.address", "", "Network hardware address")
})
}
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 {
return flag.name
}
func (flag *NetworkFlag) Set(name string) error {
flag.name = name
flag.isset = true
return nil
}
func (flag *NetworkFlag) IsSet() bool {
return flag.isset
}
func (flag *NetworkFlag) Network() (object.NetworkReference, error) {
if flag.net != nil {
return flag.net, nil
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
if flag.net, err = finder.NetworkOrDefault(context.TODO(), flag.name); err != nil {
return nil, err
}
return flag.net, nil
}
func (flag *NetworkFlag) Device() (types.BaseVirtualDevice, error) {
net, err := flag.Network()
if err != nil {
return nil, err
}
backing, err := net.EthernetCardBackingInfo(context.TODO())
if err != nil {
return nil, err
}
device, err := object.EthernetCardTypes().CreateEthernetCard(flag.adapter, backing)
if err != nil {
return nil, err
}
if flag.address != "" {
card := device.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard()
card.AddressType = string(types.VirtualEthernetCardMacTypeManual)
card.MacAddress = flag.address
}
return device, nil
}
// Change applies update backing and hardware address changes to the given network device.
func (flag *NetworkFlag) Change(device types.BaseVirtualDevice, update types.BaseVirtualDevice) {
current := device.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard()
changed := update.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard()
current.Backing = changed.Backing
if changed.MacAddress != "" {
current.MacAddress = changed.MacAddress
}
if changed.AddressType != "" {
current.AddressType = changed.AddressType
}
}

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