tests: upload & test in vCenter. Closes #338

This commit is contained in:
Alexander Todorov 2020-07-30 09:26:13 -04:00 committed by Tom Gundersen
parent 02346faff8
commit 9cce43d384
255 changed files with 127290 additions and 3 deletions

508
vendor/github.com/vmware/govmomi/govc/flags/client.go generated vendored Normal file
View file

@ -0,0 +1,508 @@
/*
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/tls"
"errors"
"flag"
"fmt"
"net/url"
"os"
"os/signal"
"path/filepath"
"strings"
"syscall"
"time"
"github.com/vmware/govmomi/session"
"github.com/vmware/govmomi/session/cache"
"github.com/vmware/govmomi/session/keepalive"
"github.com/vmware/govmomi/vapi/rest"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/soap"
)
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"
defaultMinVimVersion = "5.5"
)
const cDescr = "ESX or vCenter URL"
type ClientFlag struct {
common
*DebugFlag
username string
password string
cert string
key string
persist bool
minAPIVersion string
vimNamespace string
vimVersion string
tlsCaCerts string
tlsKnownHosts string
client *vim25.Client
restClient *rest.Client
Session cache.Session
}
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.DebugFlag, ctx = NewDebugFlag(ctx)
ctx = context.WithValue(ctx, clientFlagKey, v)
return v, ctx
}
func (flag *ClientFlag) String() string {
url := flag.Session.Endpoint()
if url == nil {
return ""
}
return url.String()
}
func (flag *ClientFlag) Set(s string) error {
var err error
flag.Session.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.Session.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 = defaultMinVimVersion
}
flag.minAPIVersion = env
}
{
value := os.Getenv(envVimNamespace)
if value == "" {
value = vim25.Namespace
}
usage := fmt.Sprintf("Vim namespace [%s]", envVimNamespace)
f.StringVar(&flag.vimNamespace, "vim-namespace", value, usage)
}
{
value := os.Getenv(envVimVersion)
if value == "" {
value = vim25.Version
}
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 {
err := flag.DebugFlag.Process(ctx)
if err != nil {
return err
}
if flag.Session.URL == nil {
return errors.New("specify an " + cDescr)
}
if !flag.persist {
flag.Session.Passthrough = true
}
flag.username, err = session.Secret(flag.username)
if err != nil {
return err
}
flag.password, err = session.Secret(flag.password)
if err != nil {
return err
}
// Override username if set
if flag.username != "" {
var password string
var ok bool
if flag.Session.URL.User != nil {
password, ok = flag.Session.URL.User.Password()
}
if ok {
flag.Session.URL.User = url.UserPassword(flag.username, password)
} else {
flag.Session.URL.User = url.User(flag.username)
}
}
// Override password if set
if flag.password != "" {
var username string
if flag.Session.URL.User != nil {
username = flag.Session.URL.User.Username()
}
flag.Session.URL.User = url.UserPassword(username, flag.password)
}
return nil
})
}
func (flag *ClientFlag) ConfigureTLS(sc *soap.Client) error {
if flag.cert != "" {
cert, err := tls.LoadX509KeyPair(flag.cert, flag.key)
if err != nil {
return fmt.Errorf("%s=%q %s=%q: %s", envCertificate, flag.cert, envPrivateKey, flag.key, err)
}
sc.SetCertificate(cert)
}
// Set namespace and version
sc.Namespace = "urn:" + flag.vimNamespace
sc.Version = flag.vimVersion
sc.UserAgent = fmt.Sprintf("govc/%s", Version)
if err := flag.SetRootCAs(sc); err != nil {
return err
}
if err := sc.LoadThumbprints(flag.tlsKnownHosts); err != nil {
return err
}
t := sc.DefaultTransport()
var err error
value := os.Getenv("GOVC_TLS_HANDSHAKE_TIMEOUT")
if value != "" {
t.TLSHandshakeTimeout, err = time.ParseDuration(value)
if err != nil {
return err
}
}
return nil
}
func (flag *ClientFlag) SetRootCAs(c *soap.Client) error {
if flag.tlsCaCerts != "" {
return c.SetRootCAs(flag.tlsCaCerts)
}
return 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 := new(vim25.Client)
err := flag.Session.Login(context.Background(), c, flag.ConfigureTLS)
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
}
if flag.vimVersion == "" {
err = c.UseServiceVersion()
if err != nil {
return nil, err
}
}
// Retry twice when a temporary I/O error occurs.
// This means a maximum of 3 attempts.
c.RoundTripper = vim25.Retry(c.Client, vim25.TemporaryNetworkError(3))
flag.client = c
return flag.client, nil
}
func (flag *ClientFlag) RestClient() (*rest.Client, error) {
if flag.restClient != nil {
return flag.restClient, nil
}
c := new(rest.Client)
err := flag.Session.Login(context.Background(), c, flag.ConfigureTLS)
if err != nil {
return nil, err
}
flag.restClient = c
return flag.restClient, nil
}
func (flag *ClientFlag) KeepAlive(client cache.Client) {
switch c := client.(type) {
case *vim25.Client:
keepalive.NewHandlerSOAP(c, 0, nil).Start()
case *rest.Client:
keepalive.NewHandlerREST(c, 0, nil).Start()
default:
panic(fmt.Sprintf("unsupported client type=%T", client))
}
}
func (flag *ClientFlag) Logout(ctx context.Context) error {
if flag.client != nil {
_ = flag.Session.Logout(ctx, flag.client)
}
if flag.restClient != nil {
_ = flag.Session.Logout(ctx, flag.restClient)
}
return nil
}
// 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.Session.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 == vim25.Path {
u.Path = ""
}
u.Fragment = ""
u.RawQuery = ""
add(envURL, strings.TrimPrefix(u.String(), "https://"))
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.Session.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.Session.URL.Path)
if f := flag.Session.URL.Fragment; f != "" {
add("GOVC_URL_FRAGMENT", f)
}
if q := flag.Session.URL.RawQuery; q != "" {
add("GOVC_URL_QUERY", q)
}
}
return env
}
// WithCancel calls the given function, returning when complete or canceled via SIGINT.
func (flag *ClientFlag) WithCancel(ctx context.Context, f func(context.Context) error) error {
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT)
wctx, cancel := context.WithCancel(ctx)
defer cancel()
done := make(chan bool)
var werr error
go func() {
defer close(done)
werr = f(wctx)
}()
select {
case <-sig:
cancel()
<-done // Wait for f() to complete
case <-done:
}
return werr
}

204
vendor/github.com/vmware/govmomi/govc/flags/cluster.go generated vendored Normal file
View file

@ -0,0 +1,204 @@
/*
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)
})
}
// RegisterPlacement registers the -cluster flag without using GOVC_CLUSTER env as the default value,
// usage is specific to VM placement.
func (f *ClusterFlag) RegisterPlacement(ctx context.Context, fs *flag.FlagSet) {
f.RegisterOnce(func() {
f.DatacenterFlag.Register(ctx, fs)
fs.StringVar(&f.Name, "cluster", "", "Use cluster for VM placement via DRS")
})
}
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 func() {
_ = 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
}

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

@ -0,0 +1,38 @@
/*
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

@ -0,0 +1,221 @@
/*
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"
"strings"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/property"
"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(all ...bool) (*find.Finder, error) {
if flag.finder != nil {
return flag.finder, nil
}
c, err := flag.Client()
if err != nil {
return nil, err
}
allFlag := false
if len(all) == 1 {
allFlag = all[0]
}
finder := find.NewFinder(c, allFlag)
// 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) ManagedObject(ctx context.Context, arg string) (types.ManagedObjectReference, error) {
var ref types.ManagedObjectReference
finder, err := flag.Finder()
if err != nil {
return ref, err
}
if ref.FromString(arg) {
if strings.HasPrefix(ref.Type, "com.vmware.content.") {
return ref, nil // special case for content library
}
pc := property.DefaultCollector(flag.client)
var content []types.ObjectContent
err = pc.RetrieveOne(ctx, ref, []string{"name"}, &content)
if err == nil {
return ref, nil
}
}
l, err := finder.ManagedObjectList(ctx, arg)
if err != nil {
return ref, err
}
switch len(l) {
case 0:
return ref, fmt.Errorf("%s not found", arg)
case 1:
return l[0].Object.Reference(), nil
default:
var objs []types.ManagedObjectReference
for _, o := range l {
objs = append(objs, o.Object.Reference())
}
return ref, fmt.Errorf("%d objects at path %q: %s", len(l), arg, objs)
}
}
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 {
var ref types.ManagedObjectReference
if ref.FromString(arg) {
// e.g. output from object.collect
refs = append(refs, ref)
continue
}
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

@ -0,0 +1,146 @@
/*
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)
}

103
vendor/github.com/vmware/govmomi/govc/flags/debug.go generated vendored Normal file
View file

@ -0,0 +1,103 @@
/*
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")
switch r {
case "-":
debug.SetProvider(&debug.LogProvider{})
return nil
case "":
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
})
}

31
vendor/github.com/vmware/govmomi/govc/flags/empty.go generated vendored Normal file
View file

@ -0,0 +1,31 @@
/*
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
}

138
vendor/github.com/vmware/govmomi/govc/flags/folder.go generated vendored Normal file
View file

@ -0,0 +1,138 @@
/*
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) FolderIfSpecified() (*object.Folder, error) {
if flag.name == "" {
return nil, nil
}
return flag.Folder()
}
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

@ -0,0 +1,100 @@
/*
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/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.DefaultTransport()
_ = 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

@ -0,0 +1,141 @@
/*
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())
}

72
vendor/github.com/vmware/govmomi/govc/flags/int32.go generated vendored Normal file
View file

@ -0,0 +1,72 @@
/*
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}
}

72
vendor/github.com/vmware/govmomi/govc/flags/int64.go generated vendored Normal file
View file

@ -0,0 +1,72 @@
/*
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}
}

93
vendor/github.com/vmware/govmomi/govc/flags/library.go generated vendored Normal file
View file

@ -0,0 +1,93 @@
/*
Copyright (c) 2020 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"
"fmt"
"github.com/vmware/govmomi/vapi/library"
"github.com/vmware/govmomi/vapi/library/finder"
"github.com/vmware/govmomi/vapi/rest"
)
// errContentLibraryMatch is an error returned when a query returns more than one result.
type errContentLibraryMatch struct {
// Type is the type of object being queried.
Type string
// Key is the key used to perform the query.
Key string
// Val is the value used to perform the query.
Val string
// Count is the number of objects returned.
Count int
}
// Error returns the error string.
func (e errContentLibraryMatch) Error() string {
kind := e.Type
if kind == "" {
kind = "library|item"
}
hint := ""
if e.Count > 1 {
hint = fmt.Sprintf(" (use %q ID instead of NAME)", kind)
}
return fmt.Sprintf("%q=%q matches %d items%s", e.Key, e.Val, e.Count, hint)
}
func ContentLibraryResult(ctx context.Context, c *rest.Client, kind string, path string) (finder.FindResult, error) {
res, err := finder.NewFinder(library.NewManager(c)).Find(ctx, path)
if err != nil {
return nil, err
}
if len(res) != 1 {
return nil, errContentLibraryMatch{Type: kind, Key: "path", Val: path, Count: len(res)}
}
return res[0], nil
}
// ContentLibrary attempts to find a content library with the given path,
// asserting 1 match of type library.Library.
func ContentLibrary(ctx context.Context, c *rest.Client, path string) (*library.Library, error) {
r, err := ContentLibraryResult(ctx, c, "library", path)
if err != nil {
return nil, err
}
lib, ok := r.GetResult().(library.Library)
if !ok {
return nil, fmt.Errorf("%q is a %T", path, r)
}
return &lib, nil
}
// ContentLibraryItem attempts to find a content library with the given path,
// asserting 1 match of type library.Item.
func ContentLibraryItem(ctx context.Context, c *rest.Client, path string) (*library.Item, error) {
r, err := ContentLibraryResult(ctx, c, "item", path)
if err != nil {
return nil, err
}
item, ok := r.GetResult().(library.Item)
if !ok {
return nil, fmt.Errorf("%q is a %T", path, r)
}
return &item, nil
}

30
vendor/github.com/vmware/govmomi/govc/flags/list.go generated vendored Normal file
View file

@ -0,0 +1,30 @@
/*
Copyright (c) 2019 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 "fmt"
type StringList []string
func (l *StringList) String() string {
return fmt.Sprint(*l)
}
func (l *StringList) Set(value string) error {
*l = append(*l, value)
return nil
}

147
vendor/github.com/vmware/govmomi/govc/flags/network.go generated vendored Normal file
View file

@ -0,0 +1,147 @@
/*
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
}
}

View file

@ -0,0 +1,55 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package flags
import (
"flag"
"fmt"
"strconv"
)
type optionalBool struct {
val **bool
}
func (b *optionalBool) Set(s string) error {
v, err := strconv.ParseBool(s)
*b.val = &v
return err
}
func (b *optionalBool) Get() interface{} {
if *b.val == nil {
return nil
}
return **b.val
}
func (b *optionalBool) String() string {
if b.val == nil || *b.val == nil {
return "<nil>"
}
return fmt.Sprintf("%v", **b.val)
}
func (b *optionalBool) IsBoolFlag() bool { return true }
// NewOptionalBool returns a flag.Value implementation where there is no default value.
// This avoids sending a default value over the wire as using flag.BoolVar() would.
func NewOptionalBool(v **bool) flag.Value {
return &optionalBool{v}
}

343
vendor/github.com/vmware/govmomi/govc/flags/output.go generated vendored Normal file
View file

@ -0,0 +1,343 @@
/*
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"
"encoding/json"
"errors"
"flag"
"fmt"
"io"
"os"
"reflect"
"sync"
"time"
"github.com/kr/pretty"
"github.com/vmware/govmomi/task"
"github.com/vmware/govmomi/vim25/progress"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/xml"
)
type OutputWriter interface {
Write(io.Writer) error
}
type OutputFlag struct {
common
JSON bool
XML bool
TTY bool
Dump bool
Out io.Writer
formatError bool
formatIndent bool
}
var outputFlagKey = flagKey("output")
func NewOutputFlag(ctx context.Context) (*OutputFlag, context.Context) {
if v := ctx.Value(outputFlagKey); v != nil {
return v.(*OutputFlag), ctx
}
v := &OutputFlag{Out: os.Stdout}
ctx = context.WithValue(ctx, outputFlagKey, v)
return v, ctx
}
func (flag *OutputFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
f.BoolVar(&flag.JSON, "json", false, "Enable JSON output")
f.BoolVar(&flag.XML, "xml", false, "Enable XML output")
f.BoolVar(&flag.Dump, "dump", false, "Enable Go output")
// Avoid adding more flags for now..
flag.formatIndent = os.Getenv("GOVC_INDENT") != "false" // Default to indented output
flag.formatError = os.Getenv("GOVC_FORMAT_ERROR") != "false" // Default to formatted errors
})
}
func (flag *OutputFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if !flag.All() {
// Assume we have a tty if not outputting JSON
flag.TTY = true
}
return nil
})
}
// Log outputs the specified string, prefixed with the current time.
// A newline is not automatically added. If the specified string
// starts with a '\r', the current line is cleared first.
func (flag *OutputFlag) Log(s string) (int, error) {
if len(s) > 0 && s[0] == '\r' {
flag.Write([]byte{'\r', 033, '[', 'K'})
s = s[1:]
}
return flag.WriteString(time.Now().Format("[02-01-06 15:04:05] ") + s)
}
func (flag *OutputFlag) Write(b []byte) (int, error) {
if !flag.TTY {
return 0, nil
}
n, err := os.Stdout.Write(b)
os.Stdout.Sync()
return n, err
}
func (flag *OutputFlag) WriteString(s string) (int, error) {
return flag.Write([]byte(s))
}
func (flag *OutputFlag) All() bool {
return flag.JSON || flag.XML || flag.Dump
}
func dumpValue(val interface{}) interface{} {
type dumper interface {
Dump() interface{}
}
if d, ok := val.(dumper); ok {
return d.Dump()
}
rval := reflect.ValueOf(val)
if rval.Type().Kind() != reflect.Ptr {
return val
}
rval = rval.Elem()
if rval.Type().Kind() == reflect.Struct {
f := rval.Field(0)
if f.Type().Kind() == reflect.Slice {
// common case for the various 'type infoResult'
if f.Len() == 1 {
return f.Index(0).Interface()
}
return f.Interface()
}
if rval.NumField() == 1 && rval.Type().Field(0).Anonymous {
// common case where govc type wraps govmomi type to implement OutputWriter
return f.Interface()
}
}
return val
}
func (flag *OutputFlag) WriteResult(result OutputWriter) error {
var err error
switch {
case flag.Dump:
format := "%#v\n"
if flag.formatIndent {
format = "%# v\n"
}
_, err = pretty.Fprintf(flag.Out, format, dumpValue(result))
case flag.JSON:
e := json.NewEncoder(flag.Out)
if flag.formatIndent {
e.SetIndent("", " ")
}
err = e.Encode(result)
case flag.XML:
e := xml.NewEncoder(flag.Out)
if flag.formatIndent {
e.Indent("", " ")
}
err = e.Encode(dumpValue(result))
if err == nil {
fmt.Fprintln(flag.Out)
}
default:
err = result.Write(flag.Out)
}
return err
}
func (flag *OutputFlag) WriteError(err error) bool {
if flag.formatError {
flag.Out = os.Stderr
return flag.WriteResult(&errorOutput{err}) == nil
}
return false
}
type errorOutput struct {
error
}
func (e errorOutput) Write(w io.Writer) error {
_, ferr := fmt.Fprintf(w, "%s: %s\n", os.Args[0], e.error)
return ferr
}
func (e errorOutput) Dump() interface{} {
if f, ok := e.error.(task.Error); ok {
return f.LocalizedMethodFault
}
if soap.IsSoapFault(e.error) {
return soap.ToSoapFault(e.error)
}
if soap.IsVimFault(e.error) {
return soap.ToVimFault(e.error)
}
return e
}
func (e errorOutput) canEncode() bool {
switch e.error.(type) {
case task.Error:
return true
}
return soap.IsSoapFault(e.error) || soap.IsVimFault(e.error)
}
// cannotEncode causes cli.Run to output err.Error() as it would without an error format specified
var cannotEncode = errors.New("cannot encode error")
func (e errorOutput) MarshalJSON() ([]byte, error) {
_, ok := e.error.(json.Marshaler)
if ok || e.canEncode() {
return json.Marshal(e.error)
}
return nil, cannotEncode
}
func (e errorOutput) MarshalXML(encoder *xml.Encoder, start xml.StartElement) error {
_, ok := e.error.(xml.Marshaler)
if ok || e.canEncode() {
return encoder.Encode(e.error)
}
return cannotEncode
}
type progressLogger struct {
flag *OutputFlag
prefix string
wg sync.WaitGroup
sink chan chan progress.Report
done chan struct{}
}
func newProgressLogger(flag *OutputFlag, prefix string) *progressLogger {
p := &progressLogger{
flag: flag,
prefix: prefix,
sink: make(chan chan progress.Report),
done: make(chan struct{}),
}
p.wg.Add(1)
go p.loopA()
return p
}
// loopA runs before Sink() has been called.
func (p *progressLogger) loopA() {
var err error
defer p.wg.Done()
tick := time.NewTicker(100 * time.Millisecond)
defer tick.Stop()
called := false
for stop := false; !stop; {
select {
case ch := <-p.sink:
err = p.loopB(tick, ch)
stop = true
called = true
case <-p.done:
stop = true
case <-tick.C:
line := fmt.Sprintf("\r%s", p.prefix)
p.flag.Log(line)
}
}
if err != nil && err != io.EOF {
p.flag.Log(fmt.Sprintf("\r%sError: %s\n", p.prefix, err))
} else if called {
p.flag.Log(fmt.Sprintf("\r%sOK\n", p.prefix))
}
}
// loopA runs after Sink() has been called.
func (p *progressLogger) loopB(tick *time.Ticker, ch <-chan progress.Report) error {
var r progress.Report
var ok bool
var err error
for ok = true; ok; {
select {
case r, ok = <-ch:
if !ok {
break
}
err = r.Error()
case <-tick.C:
line := fmt.Sprintf("\r%s", p.prefix)
if r != nil {
line += fmt.Sprintf("(%.0f%%", r.Percentage())
detail := r.Detail()
if detail != "" {
line += fmt.Sprintf(", %s", detail)
}
line += ")"
}
p.flag.Log(line)
}
}
return err
}
func (p *progressLogger) Sink() chan<- progress.Report {
ch := make(chan progress.Report)
p.sink <- ch
return ch
}
func (p *progressLogger) Wait() {
close(p.done)
p.wg.Wait()
}
func (flag *OutputFlag) ProgressLogger(prefix string) *progressLogger {
return newProgressLogger(flag, prefix)
}

View file

@ -0,0 +1,85 @@
/*
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"
"strconv"
"strings"
"github.com/vmware/govmomi/vim25/types"
)
type sharesInfo types.SharesInfo
func (s *sharesInfo) String() string {
return string(s.Level)
}
func (s *sharesInfo) Set(val string) error {
switch val {
case string(types.SharesLevelNormal), string(types.SharesLevelLow), string(types.SharesLevelHigh):
s.Level = types.SharesLevel(val)
default:
n, err := strconv.Atoi(val)
if err != nil {
return err
}
s.Level = types.SharesLevelCustom
s.Shares = int32(n)
}
return nil
}
type ResourceAllocationFlag struct {
cpu, mem *types.ResourceAllocationInfo
ExpandableReservation bool
}
func NewResourceAllocationFlag(cpu, mem *types.ResourceAllocationInfo) *ResourceAllocationFlag {
return &ResourceAllocationFlag{cpu, mem, true}
}
func (r *ResourceAllocationFlag) Register(ctx context.Context, f *flag.FlagSet) {
opts := []struct {
name string
units string
*types.ResourceAllocationInfo
}{
{"CPU", "MHz", r.cpu},
{"Memory", "MB", r.mem},
}
for _, opt := range opts {
prefix := strings.ToLower(opt.name)[:3]
shares := (*sharesInfo)(opt.Shares)
f.Var(NewOptionalInt64(&opt.Limit), prefix+".limit", opt.name+" limit in "+opt.units)
f.Var(NewOptionalInt64(&opt.Reservation), prefix+".reservation", opt.name+" reservation in "+opt.units)
if r.ExpandableReservation {
f.Var(NewOptionalBool(&opt.ExpandableReservation), prefix+".expandable", opt.name+" expandable reservation")
}
f.Var(shares, prefix+".shares", opt.name+" shares level or number")
}
}
func (s *ResourceAllocationFlag) Process(ctx context.Context) error {
return nil
}

View file

@ -0,0 +1,102 @@
/*
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"
)
type ResourcePoolFlag struct {
common
*DatacenterFlag
name string
pool *object.ResourcePool
}
var resourcePoolFlagKey = flagKey("resourcePool")
func NewResourcePoolFlag(ctx context.Context) (*ResourcePoolFlag, context.Context) {
if v := ctx.Value(resourcePoolFlagKey); v != nil {
return v.(*ResourcePoolFlag), ctx
}
v := &ResourcePoolFlag{}
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
ctx = context.WithValue(ctx, resourcePoolFlagKey, v)
return v, ctx
}
func (flag *ResourcePoolFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.DatacenterFlag.Register(ctx, f)
env := "GOVC_RESOURCE_POOL"
value := os.Getenv(env)
usage := fmt.Sprintf("Resource pool [%s]", env)
f.StringVar(&flag.name, "pool", value, usage)
})
}
func (flag *ResourcePoolFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (flag *ResourcePoolFlag) ResourcePool() (*object.ResourcePool, error) {
if flag.pool != nil {
return flag.pool, nil
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
flag.pool, err = finder.ResourcePoolOrDefault(context.TODO(), flag.name)
if err != nil {
if _, ok := err.(*find.NotFoundError); ok {
vapp, verr := finder.VirtualApp(context.TODO(), flag.name)
if verr != nil {
return nil, err
}
flag.pool = vapp.ResourcePool
} else {
return nil, err
}
}
return flag.pool, nil
}
func (flag *ResourcePoolFlag) ResourcePoolIfSpecified() (*object.ResourcePool, error) {
if flag.name == "" {
return nil, nil
}
return flag.ResourcePool()
}

438
vendor/github.com/vmware/govmomi/govc/flags/search.go generated vendored Normal file
View file

@ -0,0 +1,438 @@
/*
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"
"errors"
"flag"
"fmt"
"strings"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
const (
SearchVirtualMachines = iota + 1
SearchHosts
SearchVirtualApps
)
type SearchFlag struct {
common
*ClientFlag
*DatacenterFlag
t int
entity string
byDatastorePath string
byDNSName string
byInventoryPath string
byIP string
byUUID string
isset bool
}
var searchFlagKey = flagKey("search")
func NewSearchFlag(ctx context.Context, t int) (*SearchFlag, context.Context) {
if v := ctx.Value(searchFlagKey); v != nil {
return v.(*SearchFlag), ctx
}
v := &SearchFlag{
t: t,
}
v.ClientFlag, ctx = NewClientFlag(ctx)
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
switch t {
case SearchVirtualMachines:
v.entity = "VM"
case SearchHosts:
v.entity = "host"
case SearchVirtualApps:
v.entity = "vapp"
default:
panic("invalid search type")
}
ctx = context.WithValue(ctx, searchFlagKey, v)
return v, ctx
}
func (flag *SearchFlag) Register(ctx context.Context, fs *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.ClientFlag.Register(ctx, fs)
flag.DatacenterFlag.Register(ctx, fs)
register := func(v *string, f string, d string) {
f = fmt.Sprintf("%s.%s", strings.ToLower(flag.entity), f)
d = fmt.Sprintf(d, flag.entity)
fs.StringVar(v, f, "", d)
}
switch flag.t {
case SearchVirtualMachines:
register(&flag.byDatastorePath, "path", "Find %s by path to .vmx file")
}
switch flag.t {
case SearchVirtualMachines, SearchHosts:
register(&flag.byDNSName, "dns", "Find %s by FQDN")
register(&flag.byIP, "ip", "Find %s by IP address")
register(&flag.byUUID, "uuid", "Find %s by UUID")
}
register(&flag.byInventoryPath, "ipath", "Find %s by inventory path")
})
}
func (flag *SearchFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.ClientFlag.Process(ctx); err != nil {
return err
}
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
flags := []string{
flag.byDatastorePath,
flag.byDNSName,
flag.byInventoryPath,
flag.byIP,
flag.byUUID,
}
flag.isset = false
for _, f := range flags {
if f != "" {
if flag.isset {
return errors.New("cannot use more than one search flag")
}
flag.isset = true
}
}
return nil
})
}
func (flag *SearchFlag) IsSet() bool {
return flag.isset
}
func (flag *SearchFlag) searchIndex(c *vim25.Client) *object.SearchIndex {
return object.NewSearchIndex(c)
}
func (flag *SearchFlag) searchByDatastorePath(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) {
ctx := context.TODO()
switch flag.t {
case SearchVirtualMachines:
return flag.searchIndex(c).FindByDatastorePath(ctx, dc, flag.byDatastorePath)
default:
panic("unsupported type")
}
}
func (flag *SearchFlag) searchByDNSName(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) {
ctx := context.TODO()
switch flag.t {
case SearchVirtualMachines:
return flag.searchIndex(c).FindByDnsName(ctx, dc, flag.byDNSName, true)
case SearchHosts:
return flag.searchIndex(c).FindByDnsName(ctx, dc, flag.byDNSName, false)
default:
panic("unsupported type")
}
}
func (flag *SearchFlag) searchByInventoryPath(c *vim25.Client) (object.Reference, error) {
ctx := context.TODO()
return flag.searchIndex(c).FindByInventoryPath(ctx, flag.byInventoryPath)
}
func (flag *SearchFlag) searchByIP(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) {
ctx := context.TODO()
switch flag.t {
case SearchVirtualMachines:
return flag.searchIndex(c).FindByIp(ctx, dc, flag.byIP, true)
case SearchHosts:
return flag.searchIndex(c).FindByIp(ctx, dc, flag.byIP, false)
default:
panic("unsupported type")
}
}
func (flag *SearchFlag) searchByUUID(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) {
ctx := context.TODO()
isVM := false
switch flag.t {
case SearchVirtualMachines:
isVM = true
case SearchHosts:
default:
panic("unsupported type")
}
var ref object.Reference
var err error
for _, iu := range []*bool{nil, types.NewBool(true)} {
ref, err = flag.searchIndex(c).FindByUuid(ctx, dc, flag.byUUID, isVM, iu)
if err != nil {
if soap.IsSoapFault(err) {
fault := soap.ToSoapFault(err).VimFault()
if _, ok := fault.(types.InvalidArgument); ok {
continue
}
}
return nil, err
}
if ref != nil {
break
}
}
return ref, nil
}
func (flag *SearchFlag) search() (object.Reference, error) {
ctx := context.TODO()
var ref object.Reference
var err error
var dc *object.Datacenter
c, err := flag.Client()
if err != nil {
return nil, err
}
isPath := flag.byInventoryPath != ""
if !isPath {
// All other SearchIndex methods require a Datacenter param
dc, err = flag.Datacenter()
if err != nil {
return nil, err
}
}
switch {
case isPath:
ref, err = flag.searchByInventoryPath(c)
case flag.byDatastorePath != "":
ref, err = flag.searchByDatastorePath(c, dc)
case flag.byDNSName != "":
ref, err = flag.searchByDNSName(c, dc)
case flag.byIP != "":
ref, err = flag.searchByIP(c, dc)
case flag.byUUID != "":
ref, err = flag.searchByUUID(c, dc)
default:
err = errors.New("no search flag specified")
}
if err != nil {
return nil, err
}
if ref == nil {
return nil, fmt.Errorf("no such %s", flag.entity)
}
// set the InventoryPath field
finder, err := flag.Finder()
if err != nil {
return nil, err
}
ref, err = finder.ObjectReference(ctx, ref.Reference())
if err != nil {
return nil, err
}
return ref, nil
}
func (flag *SearchFlag) VirtualMachine() (*object.VirtualMachine, error) {
ref, err := flag.search()
if err != nil {
return nil, err
}
vm, ok := ref.(*object.VirtualMachine)
if !ok {
return nil, fmt.Errorf("expected VirtualMachine entity, got %s", ref.Reference().Type)
}
return vm, nil
}
func (flag *SearchFlag) VirtualMachines(args []string) ([]*object.VirtualMachine, error) {
ctx := context.TODO()
var out []*object.VirtualMachine
if flag.IsSet() {
vm, err := flag.VirtualMachine()
if err != nil {
return nil, err
}
out = append(out, vm)
return out, nil
}
// List virtual machines
if len(args) == 0 {
return nil, errors.New("no argument")
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
var nfe error
// List virtual machines for every argument
for _, arg := range args {
vms, err := finder.VirtualMachineList(ctx, arg)
if err != nil {
if _, ok := err.(*find.NotFoundError); ok {
// Let caller decide how to handle NotFoundError
nfe = err
continue
}
return nil, err
}
out = append(out, vms...)
}
return out, nfe
}
func (flag *SearchFlag) VirtualApp() (*object.VirtualApp, error) {
ref, err := flag.search()
if err != nil {
return nil, err
}
app, ok := ref.(*object.VirtualApp)
if !ok {
return nil, fmt.Errorf("expected VirtualApp entity, got %s", ref.Reference().Type)
}
return app, nil
}
func (flag *SearchFlag) VirtualApps(args []string) ([]*object.VirtualApp, error) {
ctx := context.TODO()
var out []*object.VirtualApp
if flag.IsSet() {
app, err := flag.VirtualApp()
if err != nil {
return nil, err
}
out = append(out, app)
return out, nil
}
// List virtual apps
if len(args) == 0 {
return nil, errors.New("no argument")
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
// List virtual apps for every argument
for _, arg := range args {
apps, err := finder.VirtualAppList(ctx, arg)
if err != nil {
return nil, err
}
out = append(out, apps...)
}
return out, nil
}
func (flag *SearchFlag) HostSystem() (*object.HostSystem, error) {
ref, err := flag.search()
if err != nil {
return nil, err
}
host, ok := ref.(*object.HostSystem)
if !ok {
return nil, fmt.Errorf("expected HostSystem entity, got %s", ref.Reference().Type)
}
return host, nil
}
func (flag *SearchFlag) HostSystems(args []string) ([]*object.HostSystem, error) {
ctx := context.TODO()
var out []*object.HostSystem
if flag.IsSet() {
host, err := flag.HostSystem()
if err != nil {
return nil, err
}
out = append(out, host)
return out, nil
}
// List host system
if len(args) == 0 {
return nil, errors.New("no argument")
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
// List host systems for every argument
for _, arg := range args {
vms, err := finder.HostSystemList(ctx, arg)
if err != nil {
return nil, err
}
out = append(out, vms...)
}
return out, nil
}

View file

@ -0,0 +1,78 @@
package flags
import (
"context"
"flag"
"fmt"
"os"
"github.com/vmware/govmomi/object"
)
type StoragePodFlag struct {
common
*DatacenterFlag
Name string
sp *object.StoragePod
}
var storagePodFlagKey = flagKey("storagePod")
func NewStoragePodFlag(ctx context.Context) (*StoragePodFlag, context.Context) {
if v := ctx.Value(storagePodFlagKey); v != nil {
return v.(*StoragePodFlag), ctx
}
v := &StoragePodFlag{}
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
ctx = context.WithValue(ctx, storagePodFlagKey, v)
return v, ctx
}
func (f *StoragePodFlag) Register(ctx context.Context, fs *flag.FlagSet) {
f.RegisterOnce(func() {
f.DatacenterFlag.Register(ctx, fs)
env := "GOVC_DATASTORE_CLUSTER"
value := os.Getenv(env)
usage := fmt.Sprintf("Datastore cluster [%s]", env)
fs.StringVar(&f.Name, "datastore-cluster", value, usage)
})
}
func (f *StoragePodFlag) Process(ctx context.Context) error {
return f.DatacenterFlag.Process(ctx)
}
func (f *StoragePodFlag) Isset() bool {
return f.Name != ""
}
func (f *StoragePodFlag) StoragePod() (*object.StoragePod, error) {
ctx := context.TODO()
if f.sp != nil {
return f.sp, nil
}
finder, err := f.Finder()
if err != nil {
return nil, err
}
if f.Isset() {
f.sp, err = finder.DatastoreCluster(ctx, f.Name)
if err != nil {
return nil, err
}
} else {
f.sp, err = finder.DefaultDatastoreCluster(ctx)
if err != nil {
return nil, err
}
}
return f.sp, nil
}

66
vendor/github.com/vmware/govmomi/govc/flags/version.go generated vendored Normal file
View file

@ -0,0 +1,66 @@
/*
Copyright (c) 2014-2020 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 (
"strconv"
"strings"
)
const Version = "0.23.0"
var GitVersion string
type version []int
func ParseVersion(s string) (version, error) {
v := make(version, 0)
ds := strings.Split(s, "-")
ps := strings.Split(ds[0], ".")
for _, p := range ps {
i, err := strconv.Atoi(p)
if err != nil {
return nil, err
}
v = append(v, i)
}
return v, nil
}
func (v version) Lte(u version) bool {
lv := len(v)
lu := len(u)
for i := 0; i < lv; i++ {
// Everything up to here has been equal and v has more elements than u.
if i >= lu {
return false
}
// Move to next digit if equal.
if v[i] == u[i] {
continue
}
return v[i] < u[i]
}
// Equal.
return true
}

View file

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

View file

@ -0,0 +1,112 @@
/*
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 VirtualMachineFlag struct {
common
*ClientFlag
*DatacenterFlag
*SearchFlag
name string
vm *object.VirtualMachine
}
var virtualMachineFlagKey = flagKey("virtualMachine")
func NewVirtualMachineFlag(ctx context.Context) (*VirtualMachineFlag, context.Context) {
if v := ctx.Value(virtualMachineFlagKey); v != nil {
return v.(*VirtualMachineFlag), ctx
}
v := &VirtualMachineFlag{}
v.ClientFlag, ctx = NewClientFlag(ctx)
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
v.SearchFlag, ctx = NewSearchFlag(ctx, SearchVirtualMachines)
ctx = context.WithValue(ctx, virtualMachineFlagKey, v)
return v, ctx
}
func (flag *VirtualMachineFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.ClientFlag.Register(ctx, f)
flag.DatacenterFlag.Register(ctx, f)
flag.SearchFlag.Register(ctx, f)
env := "GOVC_VM"
value := os.Getenv(env)
usage := fmt.Sprintf("Virtual machine [%s]", env)
f.StringVar(&flag.name, "vm", value, usage)
})
}
func (flag *VirtualMachineFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.ClientFlag.Process(ctx); err != nil {
return err
}
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
if err := flag.SearchFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (flag *VirtualMachineFlag) VirtualMachine() (*object.VirtualMachine, error) {
ctx := context.TODO()
if flag.vm != nil {
return flag.vm, nil
}
// Use search flags if specified.
if flag.SearchFlag.IsSet() {
vm, err := flag.SearchFlag.VirtualMachine()
if err != nil {
return nil, err
}
flag.vm = vm
return flag.vm, nil
}
// Never look for a default virtual machine.
if flag.name == "" {
return nil, nil
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
flag.vm, err = finder.VirtualMachine(ctx, flag.name)
return flag.vm, err
}