go.mod: update github.com/vmware/govmomi to v0.48.0
Needs manual change of import paths.
This commit is contained in:
parent
3a6bea380e
commit
bec893e37c
170 changed files with 7474 additions and 1604 deletions
249
vendor/github.com/vmware/govmomi/cli/command.go
generated
vendored
Normal file
249
vendor/github.com/vmware/govmomi/cli/command.go
generated
vendored
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
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"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"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, filter string) {
|
||||
var cmds, matches []string
|
||||
for name := range commands {
|
||||
cmds = append(cmds, name)
|
||||
|
||||
if filter != "" && strings.Contains(name, filter) {
|
||||
matches = append(matches, name)
|
||||
}
|
||||
}
|
||||
|
||||
if len(matches) == 0 {
|
||||
fmt.Fprintf(w, `Usage: %[1]s <COMMAND> [COMMON OPTIONS] [PATH]...
|
||||
|
||||
govmomi is a Go library for interacting with VMware vSphere APIs (ESXi and/or
|
||||
vCenter Server).
|
||||
It is licensed under the Apache License, Version 2.0
|
||||
|
||||
%[1]s is the CLI for govmomi.
|
||||
|
||||
The available commands are listed below. A detailed description of each
|
||||
command can be displayed with "govc <COMMAND> -h". The description of all
|
||||
commands can be also found at https://github.com/vmware/govmomi/blob/main/govc/USAGE.md.
|
||||
|
||||
Examples:
|
||||
show usage of a command: govc <COMMAND> -h
|
||||
show toplevel structure: govc ls
|
||||
show datacenter summary: govc datacenter.info
|
||||
show all VMs: govc find -type m
|
||||
upload a ISO file: govc datastore.upload -ds datastore1 ./config.iso vm-name/config.iso
|
||||
|
||||
Common options:
|
||||
-h Show this message
|
||||
-cert= Certificate [GOVC_CERTIFICATE]
|
||||
-debug=false Store debug logs [GOVC_DEBUG]
|
||||
-trace=false Write SOAP/REST traffic to stderr
|
||||
-verbose=false Write request/response data to stderr
|
||||
-dump=false Enable output dump
|
||||
-json=false Enable JSON output
|
||||
-xml=false Enable XML output
|
||||
-k=false Skip verification of server certificate [GOVC_INSECURE]
|
||||
-key= Private key [GOVC_PRIVATE_KEY]
|
||||
-persist-session=true Persist session to disk [GOVC_PERSIST_SESSION]
|
||||
-tls-ca-certs= TLS CA certificates file [GOVC_TLS_CA_CERTS]
|
||||
-tls-known-hosts= TLS known hosts file [GOVC_TLS_KNOWN_HOSTS]
|
||||
-u= ESX or vCenter URL [GOVC_URL]
|
||||
-vim-namespace=urn:vim25 Vim namespace [GOVC_VIM_NAMESPACE]
|
||||
-vim-version=6.0 Vim version [GOVC_VIM_VERSION]
|
||||
-dc= Datacenter [GOVC_DATACENTER]
|
||||
-host.dns= Find host by FQDN
|
||||
-host.ip= Find host by IP address
|
||||
-host.ipath= Find host by inventory path
|
||||
-host.uuid= Find host by UUID
|
||||
-vm.dns= Find VM by FQDN
|
||||
-vm.ip= Find VM by IP address
|
||||
-vm.ipath= Find VM by inventory path
|
||||
-vm.path= Find VM by path to .vmx file
|
||||
-vm.uuid= Find VM by UUID
|
||||
|
||||
Available commands:
|
||||
`, filepath.Base(os.Args[0]))
|
||||
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s: command '%s' not found, did you mean:\n", os.Args[0], filter)
|
||||
cmds = matches
|
||||
}
|
||||
|
||||
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) {
|
||||
arg = strings.TrimLeft(arg, "-")
|
||||
if arg == "h" || arg == "help" {
|
||||
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, name)
|
||||
return rc
|
||||
}
|
||||
|
||||
fs := flag.NewFlagSet("", flag.ContinueOnError)
|
||||
fs.SetOutput(io.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 {
|
||||
if x, ok := err.(interface{ ExitCode() int }); ok {
|
||||
// propagate exit code, e.g. from guest.run
|
||||
rc = x.ExitCode()
|
||||
} else {
|
||||
w, ok := cmd.(interface{ WriteError(error) bool })
|
||||
if ok {
|
||||
ok = w.WriteError(err)
|
||||
}
|
||||
if !ok {
|
||||
fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ = clientLogout(ctx, cmd)
|
||||
|
||||
return rc
|
||||
}
|
||||
152
vendor/github.com/vmware/govmomi/cli/datastore/cp.go
generated
vendored
Normal file
152
vendor/github.com/vmware/govmomi/cli/datastore/cp.go
generated
vendored
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
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/cli"
|
||||
"github.com/vmware/govmomi/cli/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)
|
||||
}
|
||||
349
vendor/github.com/vmware/govmomi/cli/datastore/create.go
generated
vendored
Normal file
349
vendor/github.com/vmware/govmomi/cli/datastore/create.go
generated
vendored
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
/*
|
||||
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/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/units"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
const (
|
||||
sectorSize = 512 // Sector size in bytes
|
||||
startSector = 2048 // Start sector (typically fixed)
|
||||
)
|
||||
|
||||
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
|
||||
Version *int32
|
||||
Size units.ByteSize
|
||||
|
||||
// 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)")
|
||||
f.Var(flags.NewOptionalInt32(&cmd.Version), "version", "VMFS major version")
|
||||
f.Var(&cmd.Size, "size", "Size of new disk. Default is to use entire disk")
|
||||
|
||||
// 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 # use entire disk
|
||||
govc datastore.create -type vmfs -name vmfsDatastore -disk=mpx.vmhba0:C0:T0:L0 -size 20G cluster1 # use 20G of disk
|
||||
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
|
||||
if cmd.Size > 0 {
|
||||
endSector := CalculateSectors(int64(cmd.Size))
|
||||
// set values for Sectors
|
||||
spec.Partition.Partition[0].StartSector = startSector
|
||||
spec.Partition.Partition[0].EndSector = endSector
|
||||
}
|
||||
if cmd.Version != nil {
|
||||
spec.Vmfs.MajorVersion = *cmd.Version
|
||||
}
|
||||
_, err = ds.CreateVmfsDatastore(ctx, spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CalculateSectors calculates the start and end sectors based on the given size.
|
||||
func CalculateSectors(sizeInBytes int64) (endSector int64) {
|
||||
totalSectors := sizeInBytes / sectorSize
|
||||
endSector = startSector + totalSectors - 1
|
||||
|
||||
return endSector
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
137
vendor/github.com/vmware/govmomi/cli/datastore/download.go
generated
vendored
Normal file
137
vendor/github.com/vmware/govmomi/cli/datastore/download.go
generated
vendored
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
// © Broadcom. All Rights Reserved.
|
||||
// The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package datastore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/ovf"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vmdk"
|
||||
)
|
||||
|
||||
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
|
||||
govc datastore.download -json vm-name/vm-name.vmdk - | jq .ddb
|
||||
ovf=$(govc library.info -l -L vmservice/photon-5.0/*.ovf)
|
||||
govc datastore.download -json "$ovf" - | jq -r .diskSection.disk[].capacity`
|
||||
}
|
||||
|
||||
func (cmd *download) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
args := f.Args()
|
||||
if len(args) != 2 {
|
||||
return errors.New("invalid arguments")
|
||||
}
|
||||
|
||||
src := args[0]
|
||||
dst := args[1]
|
||||
|
||||
var dp object.DatastorePath
|
||||
if dp.FromString(src) {
|
||||
// e.g. `govc library.info -l -L ...`
|
||||
cmd.DatastoreFlag.Name = dp.Datastore
|
||||
src = dp.Path
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
if dst == "-" {
|
||||
f, _, err := ds.Download(ctx, src, &p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.DatastoreFlag.All() {
|
||||
switch path.Ext(src) {
|
||||
case ".vmdk":
|
||||
data, err := vmdk.ParseDescriptor(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return cmd.DatastoreFlag.WriteResult(data)
|
||||
case ".ovf":
|
||||
data, err := ovf.Unmarshal(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return cmd.DatastoreFlag.WriteResult(data)
|
||||
}
|
||||
}
|
||||
|
||||
_, 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)
|
||||
}
|
||||
213
vendor/github.com/vmware/govmomi/cli/datastore/info.go
generated
vendored
Normal file
213
vendor/github.com/vmware/govmomi/cli/datastore/info.go
generated
vendored
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
Copyright (c) 2015-2024 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/cli"
|
||||
"github.com/vmware/govmomi/cli/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
|
||||
|
||||
host bool
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
f.BoolVar(&cmd.host, "H", false, "Display info for Datastores shared between hosts")
|
||||
}
|
||||
|
||||
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) Description() string {
|
||||
return `Display info for Datastores.
|
||||
|
||||
Examples:
|
||||
govc datastore.info
|
||||
govc datastore.info vsanDatastore
|
||||
# info on Datastores shared between cluster hosts:
|
||||
govc collect -s -d " " /dc1/host/k8s-cluster host | xargs govc datastore.info -H
|
||||
# info on Datastores shared between VM hosts:
|
||||
govc ls /dc1/vm/*k8s* | xargs -n1 -I% govc collect -s % summary.runtime.host | xargs govc datastore.info -H`
|
||||
}
|
||||
|
||||
func intersect(common []types.ManagedObjectReference, refs []types.ManagedObjectReference) []types.ManagedObjectReference {
|
||||
var shared []types.ManagedObjectReference
|
||||
for i := range common {
|
||||
for j := range refs {
|
||||
if common[i] == refs[j] {
|
||||
shared = append(shared, common[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return shared
|
||||
}
|
||||
|
||||
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
c, err := cmd.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pc := property.DefaultCollector(c)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
if cmd.host {
|
||||
if f.NArg() == 0 {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
refs, err := cmd.ManagedObjects(ctx, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var hosts []mo.HostSystem
|
||||
err = pc.Retrieve(ctx, refs, []string{"name", "datastore"}, &hosts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
refs = hosts[0].Datastore
|
||||
for _, host := range hosts[1:] {
|
||||
refs = intersect(refs, host.Datastore)
|
||||
if len(refs) == 0 {
|
||||
return fmt.Errorf("host %s (%s) has no shared datastores", host.Name, host.Reference())
|
||||
}
|
||||
}
|
||||
for i := range refs {
|
||||
ds, err := finder.ObjectReference(ctx, refs[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
res.objects = append(res.objects, ds.(*object.Datastore))
|
||||
}
|
||||
} else {
|
||||
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())
|
||||
}
|
||||
|
||||
err = pc.Retrieve(ctx, refs, props, &res.Datastores)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return cmd.WriteResult(&res)
|
||||
}
|
||||
|
||||
type infoResult struct {
|
||||
Datastores []mo.Datastore `json:"datastores"`
|
||||
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()
|
||||
}
|
||||
283
vendor/github.com/vmware/govmomi/cli/datastore/ls.go
generated
vendored
Normal file
283
vendor/github.com/vmware/govmomi/cli/datastore/ls.go
generated
vendored
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
Copyright (c) 2014-2024 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/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/fault"
|
||||
"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
|
||||
human 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.human, "H", true, "Display human friendly name") // vSAN top-level dirs are ID by default
|
||||
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 {
|
||||
return fault.Is(err, &types.InvalidArgument{})
|
||||
}
|
||||
|
||||
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 p != "" && p[0] == '.' {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res := r
|
||||
res.File = nil
|
||||
|
||||
for _, f := range r.File {
|
||||
info := f.GetFileInfo()
|
||||
if info.Path[0] == '.' && !o.cmd.all {
|
||||
continue
|
||||
}
|
||||
|
||||
if o.cmd.human {
|
||||
if info.FriendlyName != "" {
|
||||
info.Path = info.FriendlyName
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
115
vendor/github.com/vmware/govmomi/cli/datastore/mkdir.go
generated
vendored
Normal file
115
vendor/github.com/vmware/govmomi/cli/datastore/mkdir.go
generated
vendored
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
Copyright (c) 2014-2024 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/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/fault"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"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 fault.Is(err, &types.FileAlreadyExists{}) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
77
vendor/github.com/vmware/govmomi/cli/datastore/mv.go
generated
vendored
Normal file
77
vendor/github.com/vmware/govmomi/cli/datastore/mv.go
generated
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
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/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)
|
||||
}
|
||||
90
vendor/github.com/vmware/govmomi/cli/datastore/remove.go
generated
vendored
Normal file
90
vendor/github.com/vmware/govmomi/cli/datastore/remove.go
generated
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package datastore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/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
|
||||
}
|
||||
117
vendor/github.com/vmware/govmomi/cli/datastore/rm.go
generated
vendored
Normal file
117
vendor/github.com/vmware/govmomi/cli/datastore/rm.go
generated
vendored
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
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/cli"
|
||||
"github.com/vmware/govmomi/cli/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
|
||||
}
|
||||
137
vendor/github.com/vmware/govmomi/cli/datastore/tail.go
generated
vendored
Normal file
137
vendor/github.com/vmware/govmomi/cli/datastore/tail.go
generated
vendored
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
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/cli"
|
||||
"github.com/vmware/govmomi/cli/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
|
||||
}
|
||||
98
vendor/github.com/vmware/govmomi/cli/datastore/upload.go
generated
vendored
Normal file
98
vendor/github.com/vmware/govmomi/cli/datastore/upload.go
generated
vendored
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
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/cli"
|
||||
"github.com/vmware/govmomi/cli/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)
|
||||
}
|
||||
163
vendor/github.com/vmware/govmomi/cli/esx/command.go
generated
vendored
Normal file
163
vendor/github.com/vmware/govmomi/cli/esx/command.go
generated
vendored
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
Copyright (c) 2014-2024 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 esx
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/internal"
|
||||
)
|
||||
|
||||
type Command struct {
|
||||
name []string
|
||||
args []string
|
||||
}
|
||||
|
||||
type CommandInfoItem struct {
|
||||
Name string `xml:"name" json:"name"`
|
||||
DisplayName string `xml:"displayName" json:"displayName"`
|
||||
Help string `xml:"help" json:"help"`
|
||||
}
|
||||
|
||||
type CommandInfoParam struct {
|
||||
CommandInfoItem
|
||||
Aliases []string `xml:"aliases" json:"aliases"`
|
||||
Flag bool `xml:"flag" json:"flag"`
|
||||
}
|
||||
|
||||
type CommandInfoHint struct {
|
||||
Key string `xml:"key" json:"key"`
|
||||
Value string `xml:"value" json:"value"`
|
||||
}
|
||||
|
||||
type CommandInfoHints []CommandInfoHint
|
||||
|
||||
type CommandInfoMethod struct {
|
||||
CommandInfoItem
|
||||
Param []CommandInfoParam `xml:"param" json:"param"`
|
||||
Hints CommandInfoHints `xml:"hints" json:"hints"`
|
||||
}
|
||||
|
||||
type CommandInfo struct {
|
||||
CommandInfoItem
|
||||
Method []CommandInfoMethod `xml:"method" json:"method"`
|
||||
}
|
||||
|
||||
func NewCommand(args []string) *Command {
|
||||
c := &Command{}
|
||||
|
||||
for i, arg := range args {
|
||||
if strings.HasPrefix(arg, "-") {
|
||||
c.args = args[i:]
|
||||
break
|
||||
} else {
|
||||
c.name = append(c.name, arg)
|
||||
}
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Command) Namespace() string {
|
||||
return strings.Join(c.name[:len(c.name)-1], ".")
|
||||
}
|
||||
|
||||
func (c *Command) Name() string {
|
||||
return c.name[len(c.name)-1]
|
||||
}
|
||||
|
||||
func (c *Command) Method() string {
|
||||
return "vim.EsxCLI." + strings.Join(c.name, ".")
|
||||
}
|
||||
|
||||
func (c *Command) Moid() string {
|
||||
return "ha-cli-handler-" + strings.Join(c.name[:len(c.name)-1], "-")
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// Parse generates a flag.FlagSet based on the given []CommandInfoParam and
|
||||
// returns arguments for use with methods.ExecuteSoap
|
||||
func (c *Command) Parse(params []CommandInfoParam) ([]internal.ReflectManagedMethodExecuterSoapArgument, error) {
|
||||
fs := flag.NewFlagSet(strings.Join(c.name, " "), flag.ExitOnError)
|
||||
vals := make([]stringList, len(params))
|
||||
|
||||
for i, p := range params {
|
||||
v := &vals[i]
|
||||
for _, a := range p.Aliases {
|
||||
a = strings.TrimPrefix(a[1:], "-")
|
||||
fs.Var(v, a, p.Help)
|
||||
}
|
||||
}
|
||||
|
||||
err := fs.Parse(c.args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
args := []internal.ReflectManagedMethodExecuterSoapArgument{}
|
||||
|
||||
for i, p := range params {
|
||||
if len(vals[i]) != 0 {
|
||||
args = append(args, c.Argument(p.Name, vals[i]...))
|
||||
}
|
||||
}
|
||||
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (c *Command) Argument(name string, args ...string) internal.ReflectManagedMethodExecuterSoapArgument {
|
||||
var vars []string
|
||||
for _, arg := range args {
|
||||
vars = append(vars, fmt.Sprintf("<%s>%s</%s>", name, arg, name))
|
||||
}
|
||||
return internal.ReflectManagedMethodExecuterSoapArgument{
|
||||
Name: name,
|
||||
Val: strings.Join(vars, ""),
|
||||
}
|
||||
}
|
||||
|
||||
func (h CommandInfoHints) Formatter() string {
|
||||
for _, hint := range h {
|
||||
if hint.Key == "formatter" {
|
||||
return hint.Value
|
||||
}
|
||||
}
|
||||
|
||||
return "simple"
|
||||
}
|
||||
|
||||
func (h CommandInfoHints) Fields() []string {
|
||||
for _, hint := range h {
|
||||
if strings.HasPrefix(hint.Key, "fields:") {
|
||||
return strings.Split(hint.Value, ",")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
209
vendor/github.com/vmware/govmomi/cli/esx/executor.go
generated
vendored
Normal file
209
vendor/github.com/vmware/govmomi/cli/esx/executor.go
generated
vendored
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
Copyright (c) 2014-2024 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 esx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/govmomi/internal"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"github.com/vmware/govmomi/vim25/xml"
|
||||
)
|
||||
|
||||
type Fault struct {
|
||||
Message string `json:"message"`
|
||||
Detail string `json:"detail"`
|
||||
}
|
||||
|
||||
func (f Fault) Error() string {
|
||||
return f.Message
|
||||
}
|
||||
|
||||
func (f Fault) MessageDetail() string {
|
||||
if f.Detail != "" {
|
||||
return fmt.Sprintf("%s %s", f.Message, f.Detail)
|
||||
}
|
||||
|
||||
return f.Message
|
||||
}
|
||||
|
||||
type Executor struct {
|
||||
c *vim25.Client
|
||||
host mo.Reference
|
||||
mme *internal.ReflectManagedMethodExecuter
|
||||
dtm *internal.InternalDynamicTypeManager
|
||||
info map[string]*CommandInfo
|
||||
|
||||
Trace func(*internal.ExecuteSoapRequest, *internal.ExecuteSoapResponse)
|
||||
}
|
||||
|
||||
func NewExecutor(ctx context.Context, c *vim25.Client, host mo.Reference) (*Executor, error) {
|
||||
e := &Executor{
|
||||
c: c,
|
||||
host: host,
|
||||
info: make(map[string]*CommandInfo),
|
||||
}
|
||||
|
||||
{
|
||||
req := internal.RetrieveManagedMethodExecuterRequest{
|
||||
This: host.Reference(),
|
||||
}
|
||||
|
||||
res, err := internal.RetrieveManagedMethodExecuter(ctx, c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
e.mme = res.Returnval
|
||||
}
|
||||
|
||||
{
|
||||
req := internal.RetrieveDynamicTypeManagerRequest{
|
||||
This: host.Reference(),
|
||||
}
|
||||
|
||||
res, err := internal.RetrieveDynamicTypeManager(ctx, c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
e.dtm = res.Returnval
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
||||
|
||||
func (e *Executor) Client() *vim25.Client {
|
||||
return e.c
|
||||
}
|
||||
|
||||
func (e *Executor) DynamicTypeManager() types.ManagedObjectReference {
|
||||
return e.dtm.ManagedObjectReference
|
||||
}
|
||||
|
||||
func (e *Executor) CommandInfo(ctx context.Context, ns string) (*CommandInfo, error) {
|
||||
info, ok := e.info[ns]
|
||||
if ok {
|
||||
return info, nil
|
||||
}
|
||||
|
||||
req := internal.ExecuteSoapRequest{
|
||||
Moid: "ha-dynamic-type-manager-local-cli-cliinfo",
|
||||
Method: "vim.CLIInfo.FetchCLIInfo",
|
||||
Argument: []internal.ReflectManagedMethodExecuterSoapArgument{
|
||||
NewCommand(nil).Argument("typeName", "vim.EsxCLI."+ns),
|
||||
},
|
||||
}
|
||||
|
||||
info = new(CommandInfo)
|
||||
if err := e.Execute(ctx, &req, info); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
e.info[ns] = info
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func (e *Executor) CommandInfoMethod(ctx context.Context, c *Command) (*CommandInfoMethod, error) {
|
||||
ns := c.Namespace()
|
||||
|
||||
info, err := e.CommandInfo(ctx, ns)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
name := c.Name()
|
||||
for _, method := range info.Method {
|
||||
if method.Name == name {
|
||||
return &method, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("method '%s' not found in name space '%s'", name, c.Namespace())
|
||||
}
|
||||
|
||||
func (e *Executor) NewRequest(ctx context.Context, args []string) (*internal.ExecuteSoapRequest, *CommandInfoMethod, error) {
|
||||
c := NewCommand(args)
|
||||
|
||||
info, err := e.CommandInfoMethod(ctx, c)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
sargs, err := c.Parse(info.Param)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
sreq := internal.ExecuteSoapRequest{
|
||||
Moid: c.Moid(),
|
||||
Method: c.Method(),
|
||||
Argument: sargs,
|
||||
}
|
||||
|
||||
return &sreq, info, nil
|
||||
}
|
||||
|
||||
func (e *Executor) Execute(ctx context.Context, req *internal.ExecuteSoapRequest, res interface{}) error {
|
||||
req.This = e.mme.ManagedObjectReference
|
||||
req.Version = "urn:vim25/5.0"
|
||||
|
||||
x, err := internal.ExecuteSoap(ctx, e.c, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if e.Trace != nil {
|
||||
e.Trace(req, x)
|
||||
}
|
||||
|
||||
if x.Returnval != nil {
|
||||
if x.Returnval.Fault != nil {
|
||||
return &Fault{
|
||||
x.Returnval.Fault.FaultMsg,
|
||||
x.Returnval.Fault.FaultDetail,
|
||||
}
|
||||
}
|
||||
|
||||
if err := xml.Unmarshal([]byte(x.Returnval.Response), res); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Executor) Run(ctx context.Context, args []string) (*Response, error) {
|
||||
req, info, err := e.NewRequest(ctx, args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := &Response{
|
||||
Info: info,
|
||||
}
|
||||
|
||||
if err := e.Execute(ctx, req, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
43
vendor/github.com/vmware/govmomi/cli/esx/firewall_info.go
generated
vendored
Normal file
43
vendor/github.com/vmware/govmomi/cli/esx/firewall_info.go
generated
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
Copyright (c) 2015-2024 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 esx
|
||||
|
||||
import "context"
|
||||
|
||||
type FirewallInfo struct {
|
||||
Loaded bool `json:"loaded"`
|
||||
Enabled bool `json:"enabled"`
|
||||
DefaultAction string `json:"defaultAction"`
|
||||
}
|
||||
|
||||
// GetFirewallInfo via 'esxcli network firewall get'
|
||||
// The HostFirewallSystem type does not expose this data.
|
||||
// This helper can be useful in particular to determine if the firewall is enabled or disabled.
|
||||
func (x *Executor) GetFirewallInfo(ctx context.Context) (*FirewallInfo, error) {
|
||||
res, err := x.Run(ctx, []string{"network", "firewall", "get"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := &FirewallInfo{
|
||||
Loaded: res.Values[0]["Loaded"][0] == "true",
|
||||
Enabled: res.Values[0]["Enabled"][0] == "true",
|
||||
DefaultAction: res.Values[0]["DefaultAction"][0],
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
116
vendor/github.com/vmware/govmomi/cli/esx/guest_info.go
generated
vendored
Normal file
116
vendor/github.com/vmware/govmomi/cli/esx/guest_info.go
generated
vendored
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
Copyright (c) 2014-2024 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 esx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type hostInfo struct {
|
||||
*Executor
|
||||
wids map[string]string
|
||||
}
|
||||
|
||||
type GuestInfo struct {
|
||||
c *vim25.Client
|
||||
hosts map[string]*hostInfo
|
||||
}
|
||||
|
||||
func NewGuestInfo(c *vim25.Client) *GuestInfo {
|
||||
return &GuestInfo{
|
||||
c: c,
|
||||
hosts: make(map[string]*hostInfo),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GuestInfo) hostInfo(ctx context.Context, ref *types.ManagedObjectReference) (*hostInfo, error) {
|
||||
// cache exectuor and uuid -> worldid map
|
||||
if h, ok := g.hosts[ref.Value]; ok {
|
||||
return h, nil
|
||||
}
|
||||
|
||||
e, err := NewExecutor(ctx, g.c, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := e.Run(ctx, []string{"vm", "process", "list"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ids := make(map[string]string, len(res.Values))
|
||||
|
||||
for _, process := range res.Values {
|
||||
// Normalize uuid, esxcli and mo.VirtualMachine have different formats
|
||||
uuid := strings.Replace(process["UUID"][0], " ", "", -1)
|
||||
uuid = strings.Replace(uuid, "-", "", -1)
|
||||
|
||||
ids[uuid] = process["WorldID"][0]
|
||||
}
|
||||
|
||||
h := &hostInfo{e, ids}
|
||||
g.hosts[ref.Value] = h
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// IpAddress attempts to find the guest IP address using esxcli.
|
||||
// ESX hosts must be configured with the /Net/GuestIPHack enabled.
|
||||
// For example:
|
||||
// $ govc host.esxcli -- system settings advanced set -o /Net/GuestIPHack -i 1
|
||||
func (g *GuestInfo) IpAddress(ctx context.Context, vm mo.Reference) (string, error) {
|
||||
const any = "0.0.0.0"
|
||||
var mvm mo.VirtualMachine
|
||||
|
||||
pc := property.DefaultCollector(g.c)
|
||||
err := pc.RetrieveOne(ctx, vm.Reference(), []string{"runtime.host", "config.uuid"}, &mvm)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
h, err := g.hostInfo(ctx, mvm.Runtime.Host)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Normalize uuid, esxcli and mo.VirtualMachine have different formats
|
||||
uuid := strings.Replace(mvm.Config.Uuid, "-", "", -1)
|
||||
|
||||
if wid, ok := h.wids[uuid]; ok {
|
||||
res, err := h.Run(ctx, []string{"network", "vm", "port", "list", "--world-id", wid})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
for _, val := range res.Values {
|
||||
if ip, ok := val["IPAddress"]; ok {
|
||||
if ip[0] != any {
|
||||
return ip[0], nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return any, nil
|
||||
}
|
||||
188
vendor/github.com/vmware/govmomi/cli/esx/response.go
generated
vendored
Normal file
188
vendor/github.com/vmware/govmomi/cli/esx/response.go
generated
vendored
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
Copyright (c) 2014-2024 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 esx
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/xml"
|
||||
)
|
||||
|
||||
type Values map[string][]string
|
||||
|
||||
type Response struct {
|
||||
Info *CommandInfoMethod `json:"info"`
|
||||
Values []Values `json:"values"`
|
||||
String string `json:"string"`
|
||||
Kind string `json:"-"`
|
||||
}
|
||||
|
||||
func (v Values) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
for {
|
||||
t, err := d.Token()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if s, ok := t.(xml.StartElement); ok {
|
||||
t, err = d.Token()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
key := s.Name.Local
|
||||
var val string
|
||||
if c, ok := t.(xml.CharData); ok {
|
||||
val = string(c)
|
||||
}
|
||||
v[key] = append(v[key], val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s Values) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
||||
tokens := []xml.Token{start}
|
||||
|
||||
for key, val := range s {
|
||||
field := xml.StartElement{Name: xml.Name{Local: key}}
|
||||
for _, v := range val {
|
||||
tokens = append(tokens, field, xml.CharData(v), field.End())
|
||||
}
|
||||
}
|
||||
|
||||
tokens = append(tokens, start.End())
|
||||
|
||||
for _, t := range tokens {
|
||||
err := e.EncodeToken(t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v Values) Value(name string) string {
|
||||
if val, ok := v[name]; ok {
|
||||
if len(val) != 0 {
|
||||
return val[0]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *Response) Type(start xml.StartElement) string {
|
||||
for _, a := range start.Attr {
|
||||
if a.Name.Local == "type" {
|
||||
return a.Value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *Response) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
stype := r.Type(start)
|
||||
|
||||
if stype != "ArrayOfDataObject" {
|
||||
switch stype {
|
||||
case "xsd:string", "xsd:boolean", "xsd:long":
|
||||
return d.DecodeElement(&r.String, &start)
|
||||
}
|
||||
v := Values{}
|
||||
if err := d.DecodeElement(&v, &start); err != nil {
|
||||
return err
|
||||
}
|
||||
r.Values = append(r.Values, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
for {
|
||||
t, err := d.Token()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if s, ok := t.(xml.StartElement); ok {
|
||||
if s.Name.Local == "DataObject" {
|
||||
v := Values{}
|
||||
if err := d.DecodeElement(&v, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
r.Values = append(r.Values, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Response) MarshalXML(e *xml.Encoder, _ xml.StartElement) error {
|
||||
kind := "ArrayOfDataObject"
|
||||
native := r.String != ""
|
||||
if native {
|
||||
kind = "xsd:" + r.Kind
|
||||
}
|
||||
|
||||
start := xml.StartElement{
|
||||
Name: xml.Name{
|
||||
Space: "urn:vim25",
|
||||
Local: "obj",
|
||||
},
|
||||
Attr: []xml.Attr{
|
||||
{
|
||||
Name: xml.Name{Local: "xmlns:xsd"},
|
||||
Value: "http://www.w3.org/2001/XMLSchema",
|
||||
},
|
||||
{
|
||||
Name: xml.Name{Local: "xmlns:xsi"},
|
||||
Value: "http://www.w3.org/2001/XMLSchema-instance",
|
||||
},
|
||||
{
|
||||
Name: xml.Name{Local: "xsi:type"},
|
||||
Value: kind,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if err := e.EncodeToken(start); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var err error
|
||||
if native {
|
||||
err = e.EncodeToken(xml.CharData(r.String))
|
||||
} else {
|
||||
obj := xml.StartElement{
|
||||
Name: xml.Name{Local: "DataObject"},
|
||||
Attr: []xml.Attr{{
|
||||
Name: xml.Name{Local: "xsi:type"},
|
||||
Value: r.Kind,
|
||||
}},
|
||||
}
|
||||
err = e.EncodeElement(r.Values, obj)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.EncodeToken(start.End())
|
||||
}
|
||||
499
vendor/github.com/vmware/govmomi/cli/flags/client.go
generated
vendored
Normal file
499
vendor/github.com/vmware/govmomi/cli/flags/client.go
generated
vendored
Normal file
|
|
@ -0,0 +1,499 @@
|
|||
/*
|
||||
Copyright (c) 2014-2023 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/cns"
|
||||
"github.com/vmware/govmomi/pbm"
|
||||
"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"
|
||||
)
|
||||
|
||||
const cDescr = "ESX or vCenter URL"
|
||||
|
||||
type ClientFlag struct {
|
||||
common
|
||||
|
||||
*DebugFlag
|
||||
|
||||
username string
|
||||
password string
|
||||
cert string
|
||||
key string
|
||||
persist bool
|
||||
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)
|
||||
}
|
||||
|
||||
{
|
||||
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", strings.TrimPrefix(BuildVersion, "v"))
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
sc.UseJSON(os.Getenv("GOVC_VI_JSON") != "")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) SetRootCAs(c *soap.Client) error {
|
||||
if flag.tlsCaCerts != "" {
|
||||
return c.SetRootCAs(flag.tlsCaCerts)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) RoundTripper(c *soap.Client) soap.RoundTripper {
|
||||
// Retry twice when a temporary I/O error occurs.
|
||||
// This means a maximum of 3 attempts.
|
||||
rt := vim25.Retry(c, vim25.RetryTemporaryNetworkError, 3)
|
||||
|
||||
switch {
|
||||
case flag.dump:
|
||||
rt = &dump{roundTripper: rt}
|
||||
case flag.verbose:
|
||||
rt = &verbose{roundTripper: rt}
|
||||
}
|
||||
|
||||
return rt
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
if flag.vimVersion == "" || flag.vimVersion == "-" {
|
||||
err = c.UseServiceVersion()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
c.RoundTripper = flag.RoundTripper(c.Client)
|
||||
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) PbmClient() (*pbm.Client, error) {
|
||||
vc, err := flag.Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c, err := pbm.NewClient(context.Background(), vc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.RoundTripper = flag.RoundTripper(c.Client)
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) CnsClient() (*cns.Client, error) {
|
||||
vc, err := flag.Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, err := cns.NewClient(context.Background(), vc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.RoundTripper = flag.RoundTripper(c.Client)
|
||||
|
||||
return c, 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/cli/flags/cluster.go
generated
vendored
Normal file
204
vendor/github.com/vmware/govmomi/cli/flags/cluster.go
generated
vendored
Normal 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/cli/flags/common.go
generated
vendored
Normal file
38
vendor/github.com/vmware/govmomi/cli/flags/common.go
generated
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
Copyright (c) 2015-2023 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
|
||||
}
|
||||
219
vendor/github.com/vmware/govmomi/cli/flags/datacenter.go
generated
vendored
Normal file
219
vendor/github.com/vmware/govmomi/cli/flags/datacenter.go
generated
vendored
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
Copyright (c) 2014-2024 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 match %q: %s (unique inventory path required)", 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 {
|
||||
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)
|
||||
}
|
||||
|
||||
if len(elements) > 1 && !strings.Contains(arg, "/") {
|
||||
return nil, fmt.Errorf("%q must be qualified with a path", arg)
|
||||
}
|
||||
|
||||
for _, e := range elements {
|
||||
refs = append(refs, e.Object.Reference())
|
||||
}
|
||||
}
|
||||
|
||||
return refs, nil
|
||||
}
|
||||
209
vendor/github.com/vmware/govmomi/cli/flags/datastore.go
generated
vendored
Normal file
209
vendor/github.com/vmware/govmomi/cli/flags/datastore.go
generated
vendored
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
Copyright (c) 2014-2024 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"
|
||||
"os"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vapi/library"
|
||||
"github.com/vmware/govmomi/vapi/library/finder"
|
||||
"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 (flag *DatastoreFlag) IsSet() bool {
|
||||
return flag.Name != ""
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
}
|
||||
|
||||
func (f *DatastoreFlag) libraryPath(ctx context.Context, p string) (string, error) {
|
||||
vc, err := f.Client()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
rc, err := f.RestClient()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
m := library.NewManager(rc)
|
||||
|
||||
r, err := finder.NewFinder(m).Find(ctx, p)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(r) != 1 {
|
||||
return "", fmt.Errorf("%s: %d found", p, len(r))
|
||||
}
|
||||
|
||||
return finder.NewPathFinder(m, vc).Path(ctx, r[0])
|
||||
}
|
||||
|
||||
// FileBacking converts the given file path for use as VirtualDeviceFileBackingInfo.FileName.
|
||||
func (f *DatastoreFlag) FileBacking(ctx context.Context, file string, stat bool) (string, error) {
|
||||
u, err := url.Parse(file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
switch u.Scheme {
|
||||
case "library":
|
||||
return f.libraryPath(ctx, u.Path)
|
||||
case "ds":
|
||||
// datastore url, e.g. ds:///vmfs/volumes/$uuid/...
|
||||
return file, nil
|
||||
}
|
||||
|
||||
var p object.DatastorePath
|
||||
if p.FromString(file) {
|
||||
// datastore is specified
|
||||
return file, nil
|
||||
}
|
||||
|
||||
if stat {
|
||||
// Verify ISO exists
|
||||
if _, err := f.Stat(ctx, file); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return f.DatastorePath(file)
|
||||
}
|
||||
474
vendor/github.com/vmware/govmomi/cli/flags/debug.go
generated
vendored
Normal file
474
vendor/github.com/vmware/govmomi/cli/flags/debug.go
generated
vendored
Normal file
|
|
@ -0,0 +1,474 @@
|
|||
/*
|
||||
Copyright (c) 2014-2024 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 (
|
||||
"bufio"
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/dougm/pretty"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/debug"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type cmdFormat struct {
|
||||
path string
|
||||
err error
|
||||
args []string
|
||||
}
|
||||
|
||||
func (c *cmdFormat) lookPath(file string, args ...string) {
|
||||
c.args = args
|
||||
c.path, c.err = exec.LookPath(file)
|
||||
}
|
||||
|
||||
func (c *cmdFormat) cmd() (*exec.Cmd, error) {
|
||||
if c.err != nil {
|
||||
return nil, c.err
|
||||
}
|
||||
return exec.Command(c.path, c.args...), nil
|
||||
}
|
||||
|
||||
type DebugFlag struct {
|
||||
common
|
||||
|
||||
enable bool
|
||||
trace bool
|
||||
verbose bool
|
||||
dump bool
|
||||
xml cmdFormat
|
||||
json cmdFormat
|
||||
}
|
||||
|
||||
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) Verbose() bool {
|
||||
return flag.verbose
|
||||
}
|
||||
|
||||
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)
|
||||
f.BoolVar(&flag.trace, "trace", false, "Write SOAP/REST traffic to stderr")
|
||||
f.BoolVar(&flag.verbose, "verbose", false, "Write request/response data to stderr")
|
||||
})
|
||||
}
|
||||
|
||||
type cmdFormatCloser struct {
|
||||
rc io.Closer
|
||||
in io.Closer
|
||||
cmd *exec.Cmd
|
||||
wg *sync.WaitGroup
|
||||
}
|
||||
|
||||
func (c *cmdFormatCloser) Close() error {
|
||||
_ = c.rc.Close()
|
||||
_ = c.in.Close()
|
||||
c.wg.Wait()
|
||||
return c.cmd.Wait()
|
||||
}
|
||||
|
||||
func (flag *DebugFlag) newFormatReader(rc io.ReadCloser, w io.Writer, ext string) (io.ReadCloser, error) {
|
||||
var err error
|
||||
var cmd *exec.Cmd
|
||||
|
||||
switch ext {
|
||||
case "json":
|
||||
cmd, err = flag.json.cmd()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case "xml":
|
||||
cmd, err = flag.xml.cmd()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported type %s", ext)
|
||||
}
|
||||
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
stdin, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
_, _ = io.Copy(w, stdout)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
return debug.ReadCloser{
|
||||
Reader: io.TeeReader(rc, stdin),
|
||||
Closer: &cmdFormatCloser{rc, stdin, cmd, &wg},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (flag *DebugFlag) debugTrace(rc io.ReadCloser, w io.Writer, ext string) io.ReadCloser {
|
||||
fr, err := flag.newFormatReader(rc, w, ext)
|
||||
if err != nil {
|
||||
return debug.NewTeeReader(rc, w)
|
||||
}
|
||||
return fr
|
||||
}
|
||||
|
||||
func (flag *DebugFlag) Process(ctx context.Context) error {
|
||||
// Base path for storing debug logs.
|
||||
r := os.Getenv("GOVC_DEBUG_PATH")
|
||||
|
||||
if flag.trace {
|
||||
if flag.verbose {
|
||||
flag.dump = true // output req/res as Go code
|
||||
return nil
|
||||
}
|
||||
r = "-"
|
||||
flag.enable = true
|
||||
if os.Getenv("GOVC_DEBUG_FORMAT") != "false" {
|
||||
debugXML := os.Getenv("GOVC_DEBUG_XML")
|
||||
if debugXML == "" {
|
||||
debugXML = "xmlstarlet"
|
||||
}
|
||||
flag.xml.lookPath(debugXML, "fo")
|
||||
|
||||
debugJSON := os.Getenv("GOVC_DEBUG_JSON")
|
||||
if debugJSON == "" {
|
||||
debugJSON = "jq"
|
||||
}
|
||||
flag.json.lookPath(debugJSON, ".")
|
||||
|
||||
soap.Trace = flag.debugTrace
|
||||
}
|
||||
}
|
||||
|
||||
if !flag.enable {
|
||||
return nil
|
||||
}
|
||||
|
||||
return flag.ProcessOnce(func() error {
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
type dump struct {
|
||||
roundTripper soap.RoundTripper
|
||||
}
|
||||
|
||||
func (d *dump) RoundTrip(ctx context.Context, req, res soap.HasFault) error {
|
||||
vreq := reflect.ValueOf(req).Elem().FieldByName("Req").Elem()
|
||||
|
||||
pretty.Fprintf(os.Stderr, "%# v\n", vreq.Interface())
|
||||
|
||||
err := d.roundTripper.RoundTrip(ctx, req, res)
|
||||
if err != nil {
|
||||
if fault := res.Fault(); fault != nil {
|
||||
pretty.Fprintf(os.Stderr, "%# v\n", fault)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
vres := reflect.ValueOf(res).Elem().FieldByName("Res").Elem()
|
||||
pretty.Fprintf(os.Stderr, "%# v\n", vres.Interface())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type verbose struct {
|
||||
roundTripper soap.RoundTripper
|
||||
}
|
||||
|
||||
func (*verbose) mor(ref types.ManagedObjectReference) string {
|
||||
if strings.HasPrefix(ref.Value, "session") {
|
||||
ref.Value = "session[...]"
|
||||
return ref.String()
|
||||
}
|
||||
return ref.Value
|
||||
}
|
||||
|
||||
func (*verbose) str(val reflect.Value) string {
|
||||
if !val.IsValid() {
|
||||
return ""
|
||||
}
|
||||
|
||||
switch val.Kind() {
|
||||
case reflect.Ptr, reflect.Interface:
|
||||
if val.IsNil() {
|
||||
return "nil"
|
||||
}
|
||||
}
|
||||
|
||||
p := ""
|
||||
|
||||
switch pval := val.Interface().(type) {
|
||||
case fmt.Stringer:
|
||||
p = pval.String()
|
||||
case string:
|
||||
if len(pval) > 45 {
|
||||
pval = pval[:42] + "..."
|
||||
}
|
||||
p = fmt.Sprintf("%s", pval)
|
||||
case []string:
|
||||
p = fmt.Sprintf("%v", pval)
|
||||
case []types.ManagedObjectReference:
|
||||
refs := make([]string, len(pval))
|
||||
for i := range pval {
|
||||
refs[i] = pval[i].Value
|
||||
}
|
||||
p = fmt.Sprintf("%v", refs)
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (v *verbose) value(val types.AnyType) string {
|
||||
rval := reflect.ValueOf(val)
|
||||
if rval.Kind() == reflect.Ptr && !rval.IsNil() {
|
||||
rval = rval.Elem()
|
||||
}
|
||||
if rval.Kind() == reflect.Struct {
|
||||
if strings.HasPrefix(rval.Type().Name(), "ArrayOf") {
|
||||
rval = rval.Field(0)
|
||||
val = rval.Interface()
|
||||
}
|
||||
}
|
||||
s := v.str(rval)
|
||||
if s != "" {
|
||||
return s
|
||||
}
|
||||
return v.prettyPrint(val)
|
||||
}
|
||||
|
||||
func (v *verbose) propertyValue(obj types.ManagedObjectReference, name string, pval types.AnyType) string {
|
||||
val := v.value(pval)
|
||||
if obj.Type != "Task" && !strings.HasPrefix(obj.Value, "session") {
|
||||
if len(val) > 512 {
|
||||
val = fmt.Sprintf("`govc collect -dump %s %s`", obj, name)
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("%s\t%s:\t%s", v.mor(obj), name, val)
|
||||
}
|
||||
|
||||
func (v *verbose) missingSet(o types.ManagedObjectReference, m []types.MissingProperty) []string {
|
||||
var s []string
|
||||
for _, p := range m {
|
||||
s = append(s, fmt.Sprintf("%s\t%s:\t%s", v.mor(o), p.Path, v.prettyPrint(p.Fault.Fault)))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (v *verbose) updateSet(u *types.UpdateSet) []string {
|
||||
var s []string
|
||||
if u == nil {
|
||||
return s
|
||||
}
|
||||
for _, f := range u.FilterSet {
|
||||
for _, o := range f.ObjectSet {
|
||||
for _, c := range o.ChangeSet {
|
||||
s = append(s, v.propertyValue(o.Obj, c.Name, c.Val))
|
||||
}
|
||||
s = append(s, v.missingSet(o.Obj, o.MissingSet)...)
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (v *verbose) objectContent(content []types.ObjectContent) []string {
|
||||
var s []string
|
||||
for _, o := range content {
|
||||
for _, p := range o.PropSet {
|
||||
s = append(s, v.propertyValue(o.Obj, p.Name, p.Val))
|
||||
}
|
||||
s = append(s, v.missingSet(o.Obj, o.MissingSet)...)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (v *verbose) prettyPrint(val interface{}) string {
|
||||
p := pretty.Sprintf("%# v\n", val)
|
||||
var res []string
|
||||
scanner := bufio.NewScanner(strings.NewReader(p))
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.Contains(line, "nil,") || strings.Contains(line, "(nil),") {
|
||||
continue // nil pointer field
|
||||
}
|
||||
if strings.Contains(line, `"",`) {
|
||||
continue // empty string field
|
||||
}
|
||||
if strings.Contains(line, `{},`) {
|
||||
continue // empty embedded struct
|
||||
}
|
||||
if strings.Contains(line, "[context]") {
|
||||
continue // noisy base64 encoded backtrace
|
||||
}
|
||||
res = append(res, line)
|
||||
}
|
||||
return strings.Join(res, "\n")
|
||||
}
|
||||
|
||||
func (v *verbose) table(vals []string) {
|
||||
tw := tabwriter.NewWriter(os.Stderr, 2, 0, 1, ' ', 0)
|
||||
for _, val := range vals {
|
||||
fmt.Fprintf(tw, "...%s\n", val)
|
||||
}
|
||||
tw.Flush()
|
||||
}
|
||||
|
||||
func (v *verbose) RoundTrip(ctx context.Context, req, res soap.HasFault) error {
|
||||
vreq := reflect.ValueOf(req).Elem().FieldByName("Req").Elem()
|
||||
param := []string{""}
|
||||
switch f := vreq.Field(0).Interface().(type) {
|
||||
case types.ManagedObjectReference:
|
||||
param[0] = v.mor(f)
|
||||
default:
|
||||
param[0] = fmt.Sprintf("%v", f)
|
||||
}
|
||||
|
||||
for i := 1; i < vreq.NumField(); i++ {
|
||||
val := vreq.Field(i)
|
||||
|
||||
if val.Kind() == reflect.Interface {
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
p := v.str(val)
|
||||
if p == "" {
|
||||
switch val.Kind() {
|
||||
case reflect.Ptr, reflect.Slice, reflect.Struct:
|
||||
p = val.Type().String()
|
||||
default:
|
||||
p = fmt.Sprintf("%v", val.Interface())
|
||||
}
|
||||
}
|
||||
|
||||
param = append(param, p)
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "%s(%s)...\n", vreq.Type().Name(), strings.Join(param, ", "))
|
||||
|
||||
err := v.roundTripper.RoundTrip(ctx, req, res)
|
||||
if err != nil {
|
||||
if fault := res.Fault(); fault != nil {
|
||||
fmt.Fprintln(os.Stderr, v.prettyPrint(fault))
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "...%s\n", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
vres := reflect.ValueOf(res).Elem().FieldByName("Res").Elem()
|
||||
ret := vres.FieldByName("Returnval")
|
||||
var s interface{} = "void"
|
||||
|
||||
if ret.IsValid() {
|
||||
switch x := ret.Interface().(type) {
|
||||
case types.ManagedObjectReference:
|
||||
s = v.mor(x)
|
||||
case *types.UpdateSet:
|
||||
s = v.updateSet(x)
|
||||
case []types.ObjectContent:
|
||||
s = v.objectContent(x)
|
||||
case fmt.Stringer:
|
||||
s = x.String()
|
||||
default:
|
||||
s = v.value(x)
|
||||
}
|
||||
}
|
||||
if vals, ok := s.([]string); ok {
|
||||
v.table(vals)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "...%s\n", s)
|
||||
}
|
||||
fmt.Fprintln(os.Stderr)
|
||||
|
||||
return err
|
||||
}
|
||||
31
vendor/github.com/vmware/govmomi/cli/flags/empty.go
generated
vendored
Normal file
31
vendor/github.com/vmware/govmomi/cli/flags/empty.go
generated
vendored
Normal 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
|
||||
}
|
||||
94
vendor/github.com/vmware/govmomi/cli/flags/env.go
generated
vendored
Normal file
94
vendor/github.com/vmware/govmomi/cli/flags/env.go
generated
vendored
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
Copyright (c) 2023-2023 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"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
)
|
||||
|
||||
type EnvBrowser struct {
|
||||
*ClusterFlag
|
||||
*HostSystemFlag
|
||||
*VirtualMachineFlag
|
||||
}
|
||||
|
||||
func (cmd *EnvBrowser) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.ClusterFlag, ctx = NewClusterFlag(ctx)
|
||||
cmd.ClusterFlag.Register(ctx, f)
|
||||
|
||||
cmd.HostSystemFlag, ctx = NewHostSystemFlag(ctx)
|
||||
cmd.HostSystemFlag.Register(ctx, f)
|
||||
|
||||
cmd.VirtualMachineFlag, ctx = NewVirtualMachineFlag(ctx)
|
||||
cmd.VirtualMachineFlag.Register(ctx, f)
|
||||
}
|
||||
|
||||
func (cmd *EnvBrowser) Process(ctx context.Context) error {
|
||||
if err := cmd.ClusterFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return cmd.VirtualMachineFlag.Process(ctx)
|
||||
}
|
||||
|
||||
func (cmd *EnvBrowser) Browser(ctx context.Context) (*object.EnvironmentBrowser, error) {
|
||||
c, err := cmd.VirtualMachineFlag.Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vm, err := cmd.VirtualMachine()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if vm != nil {
|
||||
return vm.EnvironmentBrowser(ctx)
|
||||
}
|
||||
|
||||
host, err := cmd.HostSystemIfSpecified()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if host != nil {
|
||||
var h mo.HostSystem
|
||||
err = host.Properties(ctx, host.Reference(), []string{"parent"}, &h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return object.NewComputeResource(c, *h.Parent).EnvironmentBrowser(ctx)
|
||||
}
|
||||
|
||||
finder, ferr := cmd.ClusterFlag.Finder()
|
||||
if ferr != nil {
|
||||
return nil, ferr
|
||||
}
|
||||
|
||||
cr, ferr := finder.ComputeResourceOrDefault(ctx, cmd.ClusterFlag.Name)
|
||||
if ferr != nil {
|
||||
return nil, ferr
|
||||
}
|
||||
|
||||
return cr.EnvironmentBrowser(ctx)
|
||||
}
|
||||
142
vendor/github.com/vmware/govmomi/cli/flags/folder.go
generated
vendored
Normal file
142
vendor/github.com/vmware/govmomi/cli/flags/folder.go
generated
vendored
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
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) IsSet() bool {
|
||||
return flag.name != ""
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
95
vendor/github.com/vmware/govmomi/cli/flags/host_connect.go
generated
vendored
Normal file
95
vendor/github.com/vmware/govmomi/cli/flags/host_connect.go
generated
vendored
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
Copyright (c) 2015-2024 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/fault"
|
||||
"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 {
|
||||
var verify *types.SSLVerifyFault
|
||||
if _, ok := fault.As(err, &verify); ok {
|
||||
return fmt.Errorf("%s thumbprint=%s", err, verify.Thumbprint)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
141
vendor/github.com/vmware/govmomi/cli/flags/host_system.go
generated
vendored
Normal file
141
vendor/github.com/vmware/govmomi/cli/flags/host_system.go
generated
vendored
Normal 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() && flag.SearchFlag.t == SearchHosts {
|
||||
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/cli/flags/int32.go
generated
vendored
Normal file
72
vendor/github.com/vmware/govmomi/cli/flags/int32.go
generated
vendored
Normal 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/cli/flags/int64.go
generated
vendored
Normal file
72
vendor/github.com/vmware/govmomi/cli/flags/int64.go
generated
vendored
Normal 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/cli/flags/library.go
generated
vendored
Normal file
93
vendor/github.com/vmware/govmomi/cli/flags/library.go
generated
vendored
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
Copyright (c) 2020-2022 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/cli/flags/list.go
generated
vendored
Normal file
30
vendor/github.com/vmware/govmomi/cli/flags/list.go
generated
vendored
Normal 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
|
||||
}
|
||||
165
vendor/github.com/vmware/govmomi/cli/flags/network.go
generated
vendored
Normal file
165
vendor/github.com/vmware/govmomi/cli/flags/network.go
generated
vendored
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
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
|
||||
proto string
|
||||
}
|
||||
|
||||
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")
|
||||
f.StringVar(&flag.proto, "net.protocol", "", fmt.Sprintf("Network device protocol. Applicable to vmxnet3vrdma. Default to '%s'", string(types.VirtualVmxnet3VrdmaOptionDeviceProtocolsRocev2)))
|
||||
})
|
||||
}
|
||||
|
||||
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 a, ok := device.(*types.VirtualVmxnet3Vrdma); ok {
|
||||
if flag.proto != "" {
|
||||
if flag.proto != string(types.VirtualVmxnet3VrdmaOptionDeviceProtocolsRocev2) &&
|
||||
flag.proto != string(types.VirtualVmxnet3VrdmaOptionDeviceProtocolsRocev1) {
|
||||
return nil, fmt.Errorf("invalid device protocol '%s'", flag.proto)
|
||||
}
|
||||
a.DeviceProtocol = flag.proto
|
||||
}
|
||||
} else if flag.proto != "" {
|
||||
return nil, fmt.Errorf("device protocol is only supported for vmxnet3vrdma at the moment")
|
||||
}
|
||||
|
||||
if flag.address == "-" {
|
||||
card := device.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard()
|
||||
card.AddressType = string(types.VirtualEthernetCardMacTypeGenerated)
|
||||
card.MacAddress = ""
|
||||
} else 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
|
||||
}
|
||||
}
|
||||
55
vendor/github.com/vmware/govmomi/cli/flags/optional_bool.go
generated
vendored
Normal file
55
vendor/github.com/vmware/govmomi/cli/flags/optional_bool.go
generated
vendored
Normal 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}
|
||||
}
|
||||
50
vendor/github.com/vmware/govmomi/cli/flags/optional_string.go
generated
vendored
Normal file
50
vendor/github.com/vmware/govmomi/cli/flags/optional_string.go
generated
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
Copyright (c) 2023-2023 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"
|
||||
)
|
||||
|
||||
type optionalString struct {
|
||||
val **string
|
||||
}
|
||||
|
||||
func (s *optionalString) Set(input string) error {
|
||||
*s.val = &input
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *optionalString) Get() interface{} {
|
||||
if *s.val == nil {
|
||||
return nil
|
||||
}
|
||||
return **s.val
|
||||
}
|
||||
|
||||
func (s *optionalString) String() string {
|
||||
if s.val == nil || *s.val == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
return **s.val
|
||||
}
|
||||
|
||||
// NewOptionalString returns a flag.Value implementation where there is no default value.
|
||||
// This avoids sending a default value over the wire as using flag.StringVar() would.
|
||||
func NewOptionalString(v **string) flag.Value {
|
||||
return &optionalString{v}
|
||||
}
|
||||
308
vendor/github.com/vmware/govmomi/cli/flags/output.go
generated
vendored
Normal file
308
vendor/github.com/vmware/govmomi/cli/flags/output.go
generated
vendored
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
Copyright (c) 2014-2024 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"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dougm/pretty"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/task"
|
||||
"github.com/vmware/govmomi/vim25/progress"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"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
|
||||
Spec bool
|
||||
|
||||
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")
|
||||
if cli.ShowUnreleased() {
|
||||
f.BoolVar(&flag.Spec, "spec", false, "Output spec without sending request")
|
||||
}
|
||||
// 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
|
||||
}
|
||||
|
||||
w := flag.Out
|
||||
if w == nil {
|
||||
w = os.Stdout
|
||||
}
|
||||
n, err := w.Write(b)
|
||||
if w == os.Stdout {
|
||||
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
|
||||
}
|
||||
|
||||
type outputAny struct {
|
||||
Value any
|
||||
}
|
||||
|
||||
func (*outputAny) Write(io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *outputAny) Dump() interface{} {
|
||||
return a.Value
|
||||
}
|
||||
|
||||
func (flag *OutputFlag) WriteAny(val any) error {
|
||||
if !flag.All() {
|
||||
flag.XML = true
|
||||
}
|
||||
return flag.WriteResult(&outputAny{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 {
|
||||
reason := e.Error()
|
||||
var messages []string
|
||||
var faults []types.LocalizableMessage
|
||||
|
||||
switch err := e.error.(type) {
|
||||
case task.Error:
|
||||
faults = err.LocalizedMethodFault.Fault.GetMethodFault().FaultMessage
|
||||
if err.Description != nil {
|
||||
reason = fmt.Sprintf("%s (%s)", reason, err.Description.Message)
|
||||
}
|
||||
default:
|
||||
if soap.IsSoapFault(err) {
|
||||
detail := soap.ToSoapFault(err).Detail.Fault
|
||||
if f, ok := detail.(types.BaseMethodFault); ok {
|
||||
faults = f.GetMethodFault().FaultMessage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, m := range faults {
|
||||
if m.Message != "" && !strings.HasPrefix(m.Message, "[context]") {
|
||||
messages = append(messages, fmt.Sprintf("%s (%s)", m.Message, m.Key))
|
||||
}
|
||||
}
|
||||
|
||||
messages = append(messages, reason)
|
||||
|
||||
for _, message := range messages {
|
||||
if _, err := fmt.Fprintf(w, "%s: %s\n", os.Args[0], message); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// errCannotEncode causes cli.Run to output err.Error() as it would without an error format specified
|
||||
var errCannotEncode = 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, errCannotEncode
|
||||
}
|
||||
|
||||
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 errCannotEncode
|
||||
}
|
||||
|
||||
func (flag *OutputFlag) ProgressLogger(prefix string) *progress.ProgressLogger {
|
||||
return progress.NewProgressLogger(flag.Log, prefix)
|
||||
}
|
||||
85
vendor/github.com/vmware/govmomi/cli/flags/resource_allocation_info.go
generated
vendored
Normal file
85
vendor/github.com/vmware/govmomi/cli/flags/resource_allocation_info.go
generated
vendored
Normal 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
|
||||
}
|
||||
106
vendor/github.com/vmware/govmomi/cli/flags/resource_pool.go
generated
vendored
Normal file
106
vendor/github.com/vmware/govmomi/cli/flags/resource_pool.go
generated
vendored
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
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) IsSet() bool {
|
||||
return flag.name != ""
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
435
vendor/github.com/vmware/govmomi/cli/flags/search.go
generated
vendored
Normal file
435
vendor/github.com/vmware/govmomi/cli/flags/search.go
generated
vendored
Normal file
|
|
@ -0,0 +1,435 @@
|
|||
/*
|
||||
Copyright (c) 2014-2024 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/fault"
|
||||
"github.com/vmware/govmomi/find"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"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
|
||||
}
|
||||
|
||||
func NewSearchFlag(ctx context.Context, t int) (*SearchFlag, context.Context) {
|
||||
searchFlagKey := flagKey(fmt.Sprintf("search%d", t))
|
||||
|
||||
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 fault.Is(err, &types.InvalidArgument{}) {
|
||||
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
|
||||
}
|
||||
94
vendor/github.com/vmware/govmomi/cli/flags/storage_pod.go
generated
vendored
Normal file
94
vendor/github.com/vmware/govmomi/cli/flags/storage_pod.go
generated
vendored
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
Copyright (c) 2014-2022 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 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
|
||||
}
|
||||
124
vendor/github.com/vmware/govmomi/cli/flags/storage_profile.go
generated
vendored
Normal file
124
vendor/github.com/vmware/govmomi/cli/flags/storage_profile.go
generated
vendored
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
Copyright (c) 2024-2024 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"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type StorageProfileFlag struct {
|
||||
*ClientFlag
|
||||
|
||||
Name []string
|
||||
|
||||
option string
|
||||
}
|
||||
|
||||
func NewStorageProfileFlag(ctx context.Context, option ...string) (*StorageProfileFlag, context.Context) {
|
||||
v := &StorageProfileFlag{}
|
||||
if len(option) == 1 {
|
||||
v.option = option[0]
|
||||
} else {
|
||||
v.option = "profile"
|
||||
}
|
||||
v.ClientFlag, ctx = NewClientFlag(ctx)
|
||||
return v, ctx
|
||||
}
|
||||
|
||||
func (e *StorageProfileFlag) String() string {
|
||||
return fmt.Sprint(e.Name)
|
||||
}
|
||||
|
||||
func (e *StorageProfileFlag) Set(value string) error {
|
||||
e.Name = append(e.Name, value)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (flag *StorageProfileFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
flag.ClientFlag.Register(ctx, f)
|
||||
|
||||
f.Var(flag, flag.option, "Storage profile name or ID")
|
||||
}
|
||||
|
||||
func (flag *StorageProfileFlag) StorageProfileList(ctx context.Context) ([]string, error) {
|
||||
if len(flag.Name) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
c, err := flag.PbmClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m, err := c.ProfileMap(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
list := make([]string, len(flag.Name))
|
||||
|
||||
for i, name := range flag.Name {
|
||||
p, ok := m.Name[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("storage profile %q not found", name)
|
||||
}
|
||||
|
||||
list[i] = p.GetPbmProfile().ProfileId.UniqueId
|
||||
}
|
||||
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (flag *StorageProfileFlag) StorageProfile(ctx context.Context) (string, error) {
|
||||
switch len(flag.Name) {
|
||||
case 0:
|
||||
return "", nil
|
||||
case 1:
|
||||
default:
|
||||
return "", errors.New("only 1 '-profile' can be specified")
|
||||
}
|
||||
|
||||
list, err := flag.StorageProfileList(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return list[0], nil
|
||||
}
|
||||
|
||||
func (flag *StorageProfileFlag) StorageProfileSpec(ctx context.Context) ([]types.BaseVirtualMachineProfileSpec, error) {
|
||||
if len(flag.Name) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
list, err := flag.StorageProfileList(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
spec := make([]types.BaseVirtualMachineProfileSpec, len(list))
|
||||
for i, name := range list {
|
||||
spec[i] = &types.VirtualMachineDefinedProfileSpec{
|
||||
ProfileId: name,
|
||||
}
|
||||
}
|
||||
return spec, nil
|
||||
}
|
||||
71
vendor/github.com/vmware/govmomi/cli/flags/version.go
generated
vendored
Normal file
71
vendor/github.com/vmware/govmomi/cli/flags/version.go
generated
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
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"
|
||||
)
|
||||
|
||||
var (
|
||||
BuildVersion = "v0.0.0" // govc-test requires an (arbitrary) version set
|
||||
BuildCommit string
|
||||
BuildDate string
|
||||
)
|
||||
|
||||
type version []int
|
||||
|
||||
func ParseVersion(s string) (version, error) {
|
||||
// remove any trailing "v" version identifier
|
||||
s = strings.TrimPrefix(s, "v")
|
||||
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
|
||||
}
|
||||
106
vendor/github.com/vmware/govmomi/cli/flags/virtual_app.go
generated
vendored
Normal file
106
vendor/github.com/vmware/govmomi/cli/flags/virtual_app.go
generated
vendored
Normal 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
|
||||
}
|
||||
112
vendor/github.com/vmware/govmomi/cli/flags/virtual_machine.go
generated
vendored
Normal file
112
vendor/github.com/vmware/govmomi/cli/flags/virtual_machine.go
generated
vendored
Normal 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
|
||||
}
|
||||
170
vendor/github.com/vmware/govmomi/cli/importx/options.go
generated
vendored
Normal file
170
vendor/github.com/vmware/govmomi/cli/importx/options.go
generated
vendored
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
Copyright (c) 2015-2024 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 importx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/ovf"
|
||||
"github.com/vmware/govmomi/ovf/importer"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type OptionsFlag struct {
|
||||
Options importer.Options
|
||||
|
||||
path string
|
||||
}
|
||||
|
||||
func newOptionsFlag(ctx context.Context) (*OptionsFlag, context.Context) {
|
||||
return &OptionsFlag{}, ctx
|
||||
}
|
||||
|
||||
func (flag *OptionsFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
f.StringVar(&flag.path, "options", "", "Options spec file path for VM deployment")
|
||||
}
|
||||
|
||||
func (flag *OptionsFlag) Process(ctx context.Context) error {
|
||||
if len(flag.path) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
in := os.Stdin
|
||||
|
||||
if flag.path != "-" {
|
||||
in, err = os.Open(flag.path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer in.Close()
|
||||
}
|
||||
|
||||
return json.NewDecoder(in).Decode(&flag.Options)
|
||||
}
|
||||
|
||||
func (flag *OptionsFlag) powerOn(vm *object.VirtualMachine, out *flags.OutputFlag) error {
|
||||
if !flag.Options.PowerOn || flag.Options.MarkAsTemplate {
|
||||
return nil
|
||||
}
|
||||
|
||||
out.Log("Powering on VM...\n")
|
||||
|
||||
task, err := vm.PowerOn(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return task.Wait(context.Background())
|
||||
}
|
||||
|
||||
func (flag *OptionsFlag) markAsTemplate(vm *object.VirtualMachine, out *flags.OutputFlag) error {
|
||||
if !flag.Options.MarkAsTemplate {
|
||||
return nil
|
||||
}
|
||||
|
||||
out.Log("Marking VM as template...\n")
|
||||
|
||||
return vm.MarkAsTemplate(context.Background())
|
||||
}
|
||||
|
||||
func (flag *OptionsFlag) injectOvfEnv(vm *object.VirtualMachine, out *flags.OutputFlag) error {
|
||||
if !flag.Options.InjectOvfEnv {
|
||||
return nil
|
||||
}
|
||||
|
||||
out.Log("Injecting OVF environment...\n")
|
||||
|
||||
var opts []types.BaseOptionValue
|
||||
|
||||
a := vm.Client().ServiceContent.About
|
||||
|
||||
// build up Environment in order to marshal to xml
|
||||
var props []ovf.EnvProperty
|
||||
for _, p := range flag.Options.PropertyMapping {
|
||||
props = append(props, ovf.EnvProperty{
|
||||
Key: p.Key,
|
||||
Value: p.Value,
|
||||
})
|
||||
}
|
||||
|
||||
env := ovf.Env{
|
||||
EsxID: vm.Reference().Value,
|
||||
Platform: &ovf.PlatformSection{
|
||||
Kind: a.Name,
|
||||
Version: a.Version,
|
||||
Vendor: a.Vendor,
|
||||
Locale: "US",
|
||||
},
|
||||
Property: &ovf.PropertySection{
|
||||
Properties: props,
|
||||
},
|
||||
}
|
||||
|
||||
opts = append(opts, &types.OptionValue{
|
||||
Key: "guestinfo.ovfEnv",
|
||||
Value: env.MarshalManual(),
|
||||
})
|
||||
|
||||
task, err := vm.Reconfigure(context.Background(), types.VirtualMachineConfigSpec{
|
||||
ExtraConfig: opts,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return task.Wait(context.Background())
|
||||
}
|
||||
|
||||
func (flag *OptionsFlag) waitForIP(vm *object.VirtualMachine, out *flags.OutputFlag) error {
|
||||
if !flag.Options.PowerOn || !flag.Options.WaitForIP || flag.Options.MarkAsTemplate {
|
||||
return nil
|
||||
}
|
||||
|
||||
out.Log("Waiting for IP address...\n")
|
||||
ip, err := vm.WaitForIP(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.Log(fmt.Sprintf("Received IP address: %s\n", ip))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (flag *OptionsFlag) Deploy(vm *object.VirtualMachine, out *flags.OutputFlag) error {
|
||||
deploy := []func(*object.VirtualMachine, *flags.OutputFlag) error{
|
||||
flag.injectOvfEnv,
|
||||
flag.markAsTemplate,
|
||||
flag.powerOn,
|
||||
flag.waitForIP,
|
||||
}
|
||||
|
||||
for _, step := range deploy {
|
||||
if err := step(vm, out); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
64
vendor/github.com/vmware/govmomi/cli/importx/ova.go
generated
vendored
Normal file
64
vendor/github.com/vmware/govmomi/cli/importx/ova.go
generated
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
Copyright (c) 2014-2024 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 importx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/ovf/importer"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type ova struct {
|
||||
*ovfx
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("import.ova", &ova{&ovfx{}})
|
||||
}
|
||||
|
||||
func (cmd *ova) Usage() string {
|
||||
return "PATH_TO_OVA"
|
||||
}
|
||||
|
||||
func (cmd *ova) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
fpath, err := cmd.Prepare(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
archive := &importer.TapeArchive{Path: fpath}
|
||||
archive.Client = cmd.Importer.Client
|
||||
|
||||
cmd.Importer.Archive = archive
|
||||
|
||||
moref, err := cmd.Import(fpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vm := object.NewVirtualMachine(cmd.Importer.Client, *moref)
|
||||
return cmd.Deploy(vm, cmd.OutputFlag)
|
||||
}
|
||||
|
||||
func (cmd *ova) Import(fpath string) (*types.ManagedObjectReference, error) {
|
||||
ovf := "*.ovf"
|
||||
return cmd.Importer.Import(context.TODO(), ovf, cmd.Options)
|
||||
}
|
||||
186
vendor/github.com/vmware/govmomi/cli/importx/ovf.go
generated
vendored
Normal file
186
vendor/github.com/vmware/govmomi/cli/importx/ovf.go
generated
vendored
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
Copyright (c) 2014-2024 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 importx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/ovf/importer"
|
||||
)
|
||||
|
||||
type ovfx struct {
|
||||
*flags.DatastoreFlag
|
||||
*flags.HostSystemFlag
|
||||
*flags.OutputFlag
|
||||
*flags.ResourcePoolFlag
|
||||
*flags.FolderFlag
|
||||
|
||||
*OptionsFlag
|
||||
|
||||
Importer importer.Importer
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("import.ovf", &ovfx{})
|
||||
}
|
||||
|
||||
func (cmd *ovfx) 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)
|
||||
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
|
||||
cmd.OutputFlag.Register(ctx, f)
|
||||
cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx)
|
||||
cmd.ResourcePoolFlag.Register(ctx, f)
|
||||
cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx)
|
||||
cmd.FolderFlag.Register(ctx, f)
|
||||
|
||||
cmd.OptionsFlag, ctx = newOptionsFlag(ctx)
|
||||
cmd.OptionsFlag.Register(ctx, f)
|
||||
|
||||
f.StringVar(&cmd.Importer.Name, "name", "", "Name to use for new entity")
|
||||
f.BoolVar(&cmd.Importer.VerifyManifest, "m", false, "Verify checksum of uploaded files against manifest (.mf)")
|
||||
f.BoolVar(&cmd.Importer.Hidden, "hidden", false, "Enable hidden properties")
|
||||
}
|
||||
|
||||
func (cmd *ovfx) 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
|
||||
}
|
||||
if err := cmd.OutputFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.ResourcePoolFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.OptionsFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.FolderFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *ovfx) Usage() string {
|
||||
return "PATH_TO_OVF"
|
||||
}
|
||||
|
||||
func (cmd *ovfx) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
fpath, err := cmd.Prepare(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
archive := &importer.FileArchive{Path: fpath}
|
||||
archive.Client = cmd.Importer.Client
|
||||
|
||||
cmd.Importer.Archive = archive
|
||||
|
||||
moref, err := cmd.Importer.Import(context.TODO(), fpath, cmd.Options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vm := object.NewVirtualMachine(cmd.Importer.Client, *moref)
|
||||
return cmd.Deploy(vm, cmd.OutputFlag)
|
||||
}
|
||||
|
||||
func (cmd *ovfx) Prepare(f *flag.FlagSet) (string, error) {
|
||||
var err error
|
||||
|
||||
args := f.Args()
|
||||
if len(args) != 1 {
|
||||
return "", errors.New("no file specified")
|
||||
}
|
||||
|
||||
cmd.Importer.Log = cmd.OutputFlag.Log
|
||||
cmd.Importer.Client, err = cmd.DatastoreFlag.Client()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
cmd.Importer.Datacenter, err = cmd.DatastoreFlag.Datacenter()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
cmd.Importer.Datastore, err = cmd.DatastoreFlag.Datastore()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
cmd.Importer.ResourcePool, err = cmd.ResourcePoolIfSpecified()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
host, err := cmd.HostSystemIfSpecified()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if cmd.Importer.ResourcePool == nil {
|
||||
if host == nil {
|
||||
cmd.Importer.ResourcePool, err = cmd.ResourcePoolFlag.ResourcePool()
|
||||
} else {
|
||||
cmd.Importer.ResourcePool, err = host.ResourcePool(context.TODO())
|
||||
}
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
cmd.Importer.Finder, err = cmd.DatastoreFlag.Finder()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
cmd.Importer.Host, err = cmd.HostSystemIfSpecified()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// The folder argument must not be set on a VM in a vApp, otherwise causes
|
||||
// InvalidArgument fault: A specified parameter was not correct: pool
|
||||
if cmd.Importer.ResourcePool.Reference().Type != "VirtualApp" {
|
||||
cmd.Importer.Folder, err = cmd.FolderOrDefault("vm")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.Importer.Name == "" {
|
||||
// Override name from options if specified
|
||||
if cmd.Options.Name != nil {
|
||||
cmd.Importer.Name = *cmd.Options.Name
|
||||
}
|
||||
} else {
|
||||
cmd.Options.Name = &cmd.Importer.Name
|
||||
}
|
||||
|
||||
return f.Arg(0), nil
|
||||
}
|
||||
114
vendor/github.com/vmware/govmomi/cli/importx/spec.go
generated
vendored
Normal file
114
vendor/github.com/vmware/govmomi/cli/importx/spec.go
generated
vendored
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
Copyright (c) 2015-2024 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 importx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"path"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/ovf/importer"
|
||||
)
|
||||
|
||||
type spec struct {
|
||||
*flags.ClientFlag
|
||||
*flags.OutputFlag
|
||||
|
||||
Archive importer.Archive
|
||||
|
||||
hidden bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("import.spec", &spec{})
|
||||
}
|
||||
|
||||
func (cmd *spec) 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.hidden, "hidden", false, "Enable hidden properties")
|
||||
}
|
||||
|
||||
func (cmd *spec) Process(ctx context.Context) error {
|
||||
if err := cmd.ClientFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return cmd.OutputFlag.Process(ctx)
|
||||
}
|
||||
|
||||
func (cmd *spec) Usage() string {
|
||||
return "PATH_TO_OVF_OR_OVA"
|
||||
}
|
||||
|
||||
func (cmd *spec) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
fpath := ""
|
||||
args := f.Args()
|
||||
if len(args) == 1 {
|
||||
fpath = f.Arg(0)
|
||||
}
|
||||
|
||||
if len(fpath) > 0 {
|
||||
switch path.Ext(fpath) {
|
||||
case ".ovf":
|
||||
cmd.Archive = &importer.FileArchive{Path: fpath}
|
||||
case "", ".ova":
|
||||
cmd.Archive = &importer.TapeArchive{Path: fpath}
|
||||
fpath = "*.ovf"
|
||||
default:
|
||||
return fmt.Errorf("invalid file extension %s", path.Ext(fpath))
|
||||
}
|
||||
|
||||
if importer.IsRemotePath(f.Arg(0)) {
|
||||
client, err := cmd.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch archive := cmd.Archive.(type) {
|
||||
case *importer.FileArchive:
|
||||
archive.Client = client
|
||||
case *importer.TapeArchive:
|
||||
archive.Client = client
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
env, err := importer.Spec(fpath, cmd.Archive, cmd.hidden, cmd.Verbose())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !cmd.All() {
|
||||
cmd.JSON = true
|
||||
}
|
||||
return cmd.WriteResult(&specResult{env})
|
||||
}
|
||||
|
||||
type specResult struct {
|
||||
*importer.Options
|
||||
}
|
||||
|
||||
func (*specResult) Write(w io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
132
vendor/github.com/vmware/govmomi/cli/importx/vmdk.go
generated
vendored
Normal file
132
vendor/github.com/vmware/govmomi/cli/importx/vmdk.go
generated
vendored
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
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 importx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/vmdk"
|
||||
)
|
||||
|
||||
type disk struct {
|
||||
*flags.DatastoreFlag
|
||||
*flags.ResourcePoolFlag
|
||||
*flags.FolderFlag
|
||||
*flags.OutputFlag
|
||||
|
||||
force bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("import.vmdk", &disk{})
|
||||
}
|
||||
|
||||
func (cmd *disk) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
|
||||
cmd.DatastoreFlag.Register(ctx, f)
|
||||
cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx)
|
||||
cmd.ResourcePoolFlag.Register(ctx, f)
|
||||
cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx)
|
||||
cmd.FolderFlag.Register(ctx, f)
|
||||
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
|
||||
cmd.OutputFlag.Register(ctx, f)
|
||||
|
||||
f.BoolVar(&cmd.force, "force", false, "Overwrite existing disk")
|
||||
}
|
||||
|
||||
func (cmd *disk) Process(ctx context.Context) error {
|
||||
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.ResourcePoolFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.FolderFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.OutputFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *disk) Usage() string {
|
||||
return "PATH_TO_VMDK [REMOTE_DIRECTORY]"
|
||||
}
|
||||
|
||||
func (cmd *disk) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
args := f.Args()
|
||||
if len(args) < 1 {
|
||||
return errors.New("no file to import")
|
||||
}
|
||||
|
||||
src := f.Arg(0)
|
||||
|
||||
c, err := cmd.DatastoreFlag.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dc, err := cmd.DatastoreFlag.Datacenter()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ds, err := cmd.DatastoreFlag.Datastore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pool, err := cmd.ResourcePoolFlag.ResourcePool()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
folder, err := cmd.FolderOrDefault("vm")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logger := cmd.ProgressLogger(fmt.Sprintf("Uploading %s... ", path.Base(src)))
|
||||
defer logger.Wait()
|
||||
|
||||
p := vmdk.ImportParams{
|
||||
Path: f.Arg(1),
|
||||
Logger: logger,
|
||||
Type: "", // TODO: flag
|
||||
Force: cmd.force,
|
||||
Datacenter: dc,
|
||||
Pool: pool,
|
||||
Folder: folder,
|
||||
}
|
||||
|
||||
err = vmdk.Import(ctx, c, src, ds, p)
|
||||
if err != nil && err == vmdk.ErrInvalidFormat {
|
||||
return fmt.Errorf(`%s
|
||||
The vmdk can be converted using one of:
|
||||
vmware-vdiskmanager -t 5 -r '%s' new.vmdk
|
||||
qemu-img convert -O vmdk -o subformat=streamOptimized '%s' new.vmdk`, err, src, src)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
47
vendor/github.com/vmware/govmomi/cli/register.go
generated
vendored
Normal file
47
vendor/github.com/vmware/govmomi/cli/register.go
generated
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
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
|
||||
|
||||
import "os"
|
||||
|
||||
var commands = map[string]Command{}
|
||||
|
||||
var aliases = map[string]string{}
|
||||
|
||||
// hideUnreleased allows commands to be compiled into the govc binary without being registered by default.
|
||||
// Unreleased commands are omitted from 'govc -h' help text and the generated govc/USAGE.md
|
||||
// Setting the env var GOVC_SHOW_UNRELEASED=true enables any commands registered as unreleased.
|
||||
var hideUnreleased = os.Getenv("GOVC_SHOW_UNRELEASED") != "true"
|
||||
|
||||
func ShowUnreleased() bool {
|
||||
return !hideUnreleased
|
||||
}
|
||||
|
||||
func Register(name string, c Command, unreleased ...bool) {
|
||||
if len(unreleased) != 0 && unreleased[0] && hideUnreleased {
|
||||
return
|
||||
}
|
||||
commands[name] = c
|
||||
}
|
||||
|
||||
func Alias(name string, alias string) {
|
||||
aliases[alias] = name
|
||||
}
|
||||
|
||||
func Commands() map[string]Command {
|
||||
return commands
|
||||
}
|
||||
264
vendor/github.com/vmware/govmomi/cli/vm/change.go
generated
vendored
Normal file
264
vendor/github.com/vmware/govmomi/cli/vm/change.go
generated
vendored
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
Copyright (c) 2015-2024 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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type extraConfig []types.BaseOptionValue
|
||||
|
||||
func (e *extraConfig) String() string {
|
||||
return fmt.Sprintf("%v", *e)
|
||||
}
|
||||
|
||||
func (e *extraConfig) Set(v string) error {
|
||||
r := strings.SplitN(v, "=", 2)
|
||||
if len(r) < 2 {
|
||||
return fmt.Errorf("failed to parse extraConfig: %s", v)
|
||||
}
|
||||
*e = append(*e, &types.OptionValue{Key: r[0], Value: r[1]})
|
||||
return nil
|
||||
}
|
||||
|
||||
type extraConfigFile []types.BaseOptionValue
|
||||
|
||||
func (e *extraConfigFile) String() string {
|
||||
return fmt.Sprintf("%v", *e)
|
||||
}
|
||||
|
||||
func (e *extraConfigFile) Set(v string) error {
|
||||
r := strings.SplitN(v, "=", 2)
|
||||
if len(r) < 2 {
|
||||
return fmt.Errorf("failed to parse extraConfigFile: %s", v)
|
||||
}
|
||||
|
||||
var fileContents = ""
|
||||
if len(r[1]) > 0 {
|
||||
contents, err := os.ReadFile(r[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse extraConfigFile '%s': %w", v, err)
|
||||
}
|
||||
fileContents = string(contents)
|
||||
}
|
||||
|
||||
*e = append(*e, &types.OptionValue{Key: r[0], Value: fileContents})
|
||||
return nil
|
||||
}
|
||||
|
||||
type change struct {
|
||||
*flags.VirtualMachineFlag
|
||||
*flags.ResourceAllocationFlag
|
||||
|
||||
types.VirtualMachineConfigSpec
|
||||
extraConfig extraConfig
|
||||
extraConfigFile extraConfigFile
|
||||
Latency string
|
||||
hwUpgradePolicy string
|
||||
managedBy string
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.change", &change{})
|
||||
}
|
||||
|
||||
var latencyLevels = types.LatencySensitivitySensitivityLevel("").Strings()
|
||||
|
||||
// setLatency validates latency level if set
|
||||
func (cmd *change) setLatency() error {
|
||||
if cmd.Latency == "" {
|
||||
return nil
|
||||
}
|
||||
for _, l := range latencyLevels {
|
||||
if l == cmd.Latency {
|
||||
cmd.LatencySensitivity = &types.LatencySensitivity{
|
||||
Level: types.LatencySensitivitySensitivityLevel(cmd.Latency),
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("latency must be one of: %s", strings.Join(latencyLevels, "|"))
|
||||
}
|
||||
|
||||
var (
|
||||
hwUpgradePolicies = types.ScheduledHardwareUpgradeInfoHardwareUpgradePolicy("").Strings()
|
||||
ftEncryptionModes = types.VirtualMachineConfigSpecEncryptedFtModes("").Strings()
|
||||
migrateEncryptionModes = types.VirtualMachineConfigSpecEncryptedVMotionModes("").Strings()
|
||||
)
|
||||
|
||||
// setHwUpgradePolicy validates hwUpgradePolicy if set
|
||||
func (cmd *change) setHwUpgradePolicy() error {
|
||||
if cmd.hwUpgradePolicy == "" {
|
||||
return nil
|
||||
}
|
||||
for _, l := range hwUpgradePolicies {
|
||||
if l == cmd.hwUpgradePolicy {
|
||||
cmd.ScheduledHardwareUpgradeInfo = &types.ScheduledHardwareUpgradeInfo{
|
||||
UpgradePolicy: string(types.ScheduledHardwareUpgradeInfoHardwareUpgradePolicy(cmd.hwUpgradePolicy)),
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("Hardware upgrade policy must be one of: %s", strings.Join(hwUpgradePolicies, "|"))
|
||||
}
|
||||
|
||||
// setAllocation sets *info=nil if none of the fields have been set.
|
||||
// We need non-nil fields for use with flag.FlagSet, but we want the
|
||||
// VirtualMachineConfigSpec fields to be nil if none of the related flags were given.
|
||||
func setAllocation(info **types.ResourceAllocationInfo) {
|
||||
r := *info
|
||||
|
||||
if r.Shares.Level == "" {
|
||||
r.Shares = nil
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
if r.Limit != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.Reservation != nil {
|
||||
return
|
||||
}
|
||||
|
||||
*info = nil
|
||||
}
|
||||
|
||||
func (cmd *change) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
|
||||
cmd.VirtualMachineFlag.Register(ctx, f)
|
||||
|
||||
cmd.CpuAllocation = &types.ResourceAllocationInfo{Shares: new(types.SharesInfo)}
|
||||
cmd.MemoryAllocation = &types.ResourceAllocationInfo{Shares: new(types.SharesInfo)}
|
||||
cmd.ResourceAllocationFlag = flags.NewResourceAllocationFlag(cmd.CpuAllocation, cmd.MemoryAllocation)
|
||||
cmd.ResourceAllocationFlag.ExpandableReservation = false
|
||||
cmd.ResourceAllocationFlag.Register(ctx, f)
|
||||
|
||||
f.Int64Var(&cmd.MemoryMB, "m", 0, "Size in MB of memory")
|
||||
f.Var(flags.NewInt32(&cmd.NumCPUs), "c", "Number of CPUs")
|
||||
f.StringVar(&cmd.GuestId, "g", "", "Guest OS")
|
||||
f.StringVar(&cmd.Name, "name", "", "Display name")
|
||||
f.StringVar(&cmd.Latency, "latency", "", fmt.Sprintf("Latency sensitivity (%s)", strings.Join(latencyLevels, "|")))
|
||||
f.StringVar(&cmd.Annotation, "annotation", "", "VM description")
|
||||
f.StringVar(&cmd.Uuid, "uuid", "", "BIOS UUID")
|
||||
f.StringVar(&cmd.managedBy, "managed-by", "", "Set or clear managed by VC Extension")
|
||||
f.Var(&cmd.extraConfig, "e", "ExtraConfig. <key>=<value>")
|
||||
f.Var(&cmd.extraConfigFile, "f", "ExtraConfig. <key>=<absolute path to file>")
|
||||
|
||||
f.Var(flags.NewOptionalBool(&cmd.NestedHVEnabled), "nested-hv-enabled", "Enable nested hardware-assisted virtualization")
|
||||
cmd.Tools = &types.ToolsConfigInfo{}
|
||||
f.Var(flags.NewOptionalBool(&cmd.Tools.SyncTimeWithHost), "sync-time-with-host", "Enable SyncTimeWithHost")
|
||||
f.Var(flags.NewOptionalBool(&cmd.VPMCEnabled), "vpmc-enabled", "Enable CPU performance counters")
|
||||
f.Var(flags.NewOptionalBool(&cmd.MemoryHotAddEnabled), "memory-hot-add-enabled", "Enable memory hot add")
|
||||
f.Var(flags.NewOptionalBool(&cmd.MemoryReservationLockedToMax), "memory-pin", "Reserve all guest memory")
|
||||
f.Var(flags.NewOptionalBool(&cmd.CpuHotAddEnabled), "cpu-hot-add-enabled", "Enable CPU hot add")
|
||||
cmd.Flags = &types.VirtualMachineFlagInfo{}
|
||||
f.Var(flags.NewOptionalBool(&cmd.Flags.VvtdEnabled), "iommu-enabled", "Enable IOMMU")
|
||||
|
||||
f.StringVar(&cmd.hwUpgradePolicy, "scheduled-hw-upgrade-policy", "", fmt.Sprintf("Schedule hardware upgrade policy (%s)", strings.Join(hwUpgradePolicies, "|")))
|
||||
|
||||
f.StringVar(&cmd.FtEncryptionMode, "ft-encryption-mode", "", fmt.Sprintf("Encrypted fault tolerance mode (%s)", strings.Join(ftEncryptionModes, "|")))
|
||||
f.StringVar(&cmd.MigrateEncryption, "migrate-encryption", "", fmt.Sprintf("Encrypted vMotion mode (%s)", strings.Join(migrateEncryptionModes, "|")))
|
||||
}
|
||||
|
||||
func (cmd *change) Description() string {
|
||||
return `Change VM configuration.
|
||||
|
||||
To add ExtraConfig variables that can read within the guest, use the 'guestinfo.' prefix.
|
||||
|
||||
Examples:
|
||||
govc vm.change -vm $vm -mem.reservation 2048
|
||||
govc vm.change -vm $vm -e smc.present=TRUE -e ich7m.present=TRUE
|
||||
# Enable both cpu and memory hotplug on a guest:
|
||||
govc vm.change -vm $vm -cpu-hot-add-enabled -memory-hot-add-enabled
|
||||
govc vm.change -vm $vm -e guestinfo.vmname $vm
|
||||
# Read the contents of a file and use them as ExtraConfig value
|
||||
govc vm.change -vm $vm -f guestinfo.data="$(realpath .)/vmdata.config"
|
||||
# Read the variable set above inside the guest:
|
||||
vmware-rpctool "info-get guestinfo.vmname"
|
||||
govc vm.change -vm $vm -latency high
|
||||
govc vm.change -vm $vm -latency normal
|
||||
govc vm.change -vm $vm -uuid 4139c345-7186-4924-a842-36b69a24159b
|
||||
govc vm.change -vm $vm -scheduled-hw-upgrade-policy always`
|
||||
}
|
||||
|
||||
func (cmd *change) Process(ctx context.Context) error {
|
||||
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
cmd.VirtualMachineConfigSpec.ExtraConfig = append(cmd.extraConfig, cmd.extraConfigFile...)
|
||||
|
||||
setAllocation(&cmd.CpuAllocation)
|
||||
setAllocation(&cmd.MemoryAllocation)
|
||||
if reflect.DeepEqual(cmd.Tools, new(types.ToolsConfigInfo)) {
|
||||
cmd.Tools = nil // no flags set, avoid sending <tools/> in the request
|
||||
}
|
||||
|
||||
if reflect.DeepEqual(cmd.Flags, new(types.VirtualMachineFlagInfo)) {
|
||||
cmd.Flags = nil // no flags set, avoid sending <flags/> in the request
|
||||
}
|
||||
|
||||
if err = cmd.setLatency(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = cmd.setHwUpgradePolicy(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.managedBy != "" {
|
||||
// From the VirtualMachineConfigSpec doc:
|
||||
// To unset this field pass a ManagedByInfo object with an empty extensionKey
|
||||
if cmd.managedBy == "-" {
|
||||
cmd.managedBy = ""
|
||||
}
|
||||
cmd.ManagedBy = &types.ManagedByInfo{
|
||||
Type: vm.Reference().Type,
|
||||
ExtensionKey: cmd.managedBy,
|
||||
}
|
||||
}
|
||||
|
||||
task, err := vm.Reconfigure(ctx, cmd.VirtualMachineConfigSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return task.Wait(ctx)
|
||||
}
|
||||
495
vendor/github.com/vmware/govmomi/cli/vm/clone.go
generated
vendored
Normal file
495
vendor/github.com/vmware/govmomi/cli/vm/clone.go
generated
vendored
Normal file
|
|
@ -0,0 +1,495 @@
|
|||
/*
|
||||
Copyright (c) 2016-2024 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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type clone struct {
|
||||
*flags.ClientFlag
|
||||
*flags.ClusterFlag
|
||||
*flags.DatacenterFlag
|
||||
*flags.DatastoreFlag
|
||||
*flags.StoragePodFlag
|
||||
*flags.ResourcePoolFlag
|
||||
*flags.HostSystemFlag
|
||||
*flags.NetworkFlag
|
||||
*flags.FolderFlag
|
||||
*flags.VirtualMachineFlag
|
||||
|
||||
name string
|
||||
memory int
|
||||
cpus int
|
||||
on bool
|
||||
force bool
|
||||
template bool
|
||||
customization string
|
||||
waitForIP bool
|
||||
annotation string
|
||||
snapshot string
|
||||
link bool
|
||||
|
||||
Client *vim25.Client
|
||||
Cluster *object.ClusterComputeResource
|
||||
Datacenter *object.Datacenter
|
||||
Datastore *object.Datastore
|
||||
StoragePod *object.StoragePod
|
||||
ResourcePool *object.ResourcePool
|
||||
HostSystem *object.HostSystem
|
||||
Folder *object.Folder
|
||||
VirtualMachine *object.VirtualMachine
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.clone", &clone{})
|
||||
}
|
||||
|
||||
func (cmd *clone) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
|
||||
cmd.ClientFlag.Register(ctx, f)
|
||||
|
||||
cmd.ClusterFlag, ctx = flags.NewClusterFlag(ctx)
|
||||
cmd.ClusterFlag.RegisterPlacement(ctx, f)
|
||||
|
||||
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
|
||||
cmd.DatacenterFlag.Register(ctx, f)
|
||||
|
||||
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
|
||||
cmd.DatastoreFlag.Register(ctx, f)
|
||||
|
||||
cmd.StoragePodFlag, ctx = flags.NewStoragePodFlag(ctx)
|
||||
cmd.StoragePodFlag.Register(ctx, f)
|
||||
|
||||
cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx)
|
||||
cmd.ResourcePoolFlag.Register(ctx, f)
|
||||
|
||||
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
|
||||
cmd.HostSystemFlag.Register(ctx, f)
|
||||
|
||||
cmd.NetworkFlag, ctx = flags.NewNetworkFlag(ctx)
|
||||
cmd.NetworkFlag.Register(ctx, f)
|
||||
|
||||
cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx)
|
||||
cmd.FolderFlag.Register(ctx, f)
|
||||
|
||||
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
|
||||
cmd.VirtualMachineFlag.Register(ctx, f)
|
||||
|
||||
f.IntVar(&cmd.memory, "m", 0, "Size in MB of memory")
|
||||
f.IntVar(&cmd.cpus, "c", 0, "Number of CPUs")
|
||||
f.BoolVar(&cmd.on, "on", true, "Power on VM")
|
||||
f.BoolVar(&cmd.force, "force", false, "Create VM if vmx already exists")
|
||||
f.BoolVar(&cmd.template, "template", false, "Create a Template")
|
||||
f.StringVar(&cmd.customization, "customization", "", "Customization Specification Name")
|
||||
f.BoolVar(&cmd.waitForIP, "waitip", false, "Wait for VM to acquire IP address")
|
||||
f.StringVar(&cmd.annotation, "annotation", "", "VM description")
|
||||
f.StringVar(&cmd.snapshot, "snapshot", "", "Snapshot name to clone from")
|
||||
f.BoolVar(&cmd.link, "link", false, "Creates a linked clone from snapshot or source VM")
|
||||
}
|
||||
|
||||
func (cmd *clone) Usage() string {
|
||||
return "NAME"
|
||||
}
|
||||
|
||||
func (cmd *clone) Description() string {
|
||||
return `Clone VM or template to NAME.
|
||||
|
||||
Examples:
|
||||
govc vm.clone -vm template-vm new-vm
|
||||
govc vm.clone -vm template-vm -link new-vm
|
||||
govc vm.clone -vm template-vm -snapshot s-name new-vm
|
||||
govc vm.clone -vm template-vm -link -snapshot s-name new-vm
|
||||
govc vm.clone -vm template-vm -cluster cluster1 new-vm # use compute cluster placement
|
||||
govc vm.clone -vm template-vm -datastore-cluster dscluster new-vm # use datastore cluster placement
|
||||
govc vm.clone -vm template-vm -snapshot $(govc snapshot.tree -vm template-vm -C) new-vm
|
||||
govc vm.clone -vm template-vm -template new-template # clone a VM template
|
||||
govc vm.clone -vm=/ClusterName/vm/FolderName/VM_templateName -on=true -host=myesxi01 -ds=datastore01 myVM_name`
|
||||
}
|
||||
|
||||
func (cmd *clone) Process(ctx context.Context) error {
|
||||
if err := cmd.ClientFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.ClusterFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.StoragePodFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.ResourcePoolFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.NetworkFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.FolderFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *clone) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
var err error
|
||||
|
||||
if len(f.Args()) != 1 {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
cmd.name = f.Arg(0)
|
||||
if cmd.name == "" {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
cmd.Client, err = cmd.ClientFlag.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Cluster, err = cmd.ClusterFlag.ClusterIfSpecified()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Datacenter, err = cmd.DatacenterFlag.Datacenter()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.StoragePodFlag.Isset() {
|
||||
cmd.StoragePod, err = cmd.StoragePodFlag.StoragePod()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if cmd.Cluster == nil {
|
||||
cmd.Datastore, err = cmd.DatastoreFlag.Datastore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
cmd.HostSystem, err = cmd.HostSystemFlag.HostSystemIfSpecified()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.HostSystem != nil {
|
||||
if cmd.ResourcePool, err = cmd.HostSystem.ResourcePool(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if cmd.Cluster == nil {
|
||||
// -host is optional
|
||||
if cmd.ResourcePool, err = cmd.ResourcePoolFlag.ResourcePool(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if cmd.ResourcePool, err = cmd.Cluster.ResourcePool(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.Folder, err = cmd.FolderFlag.Folder(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.VirtualMachine, err = cmd.VirtualMachineFlag.VirtualMachine(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.VirtualMachine == nil {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
vm, err := cmd.cloneVM(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if cmd.Spec {
|
||||
return nil
|
||||
}
|
||||
|
||||
if cmd.cpus > 0 || cmd.memory > 0 || cmd.annotation != "" {
|
||||
vmConfigSpec := types.VirtualMachineConfigSpec{}
|
||||
if cmd.cpus > 0 {
|
||||
vmConfigSpec.NumCPUs = int32(cmd.cpus)
|
||||
}
|
||||
if cmd.memory > 0 {
|
||||
vmConfigSpec.MemoryMB = int64(cmd.memory)
|
||||
}
|
||||
vmConfigSpec.Annotation = cmd.annotation
|
||||
task, err := vm.Reconfigure(ctx, vmConfigSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = task.WaitForResult(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.template {
|
||||
return nil
|
||||
}
|
||||
|
||||
if cmd.on {
|
||||
task, err := vm.PowerOn(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = task.WaitForResult(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.waitForIP {
|
||||
_, err = vm.WaitForIP(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *clone) cloneVM(ctx context.Context) (*object.VirtualMachine, error) {
|
||||
devices, err := cmd.VirtualMachine.Device(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// prepare virtual device config spec for network card
|
||||
configSpecs := []types.BaseVirtualDeviceConfigSpec{}
|
||||
|
||||
if cmd.NetworkFlag.IsSet() {
|
||||
op := types.VirtualDeviceConfigSpecOperationAdd
|
||||
card, derr := cmd.NetworkFlag.Device()
|
||||
if derr != nil {
|
||||
return nil, derr
|
||||
}
|
||||
// search for the first network card of the source
|
||||
for _, device := range devices {
|
||||
if _, ok := device.(types.BaseVirtualEthernetCard); ok {
|
||||
op = types.VirtualDeviceConfigSpecOperationEdit
|
||||
// set new backing info
|
||||
cmd.NetworkFlag.Change(device, card)
|
||||
card = device
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
configSpecs = append(configSpecs, &types.VirtualDeviceConfigSpec{
|
||||
Operation: op,
|
||||
Device: card,
|
||||
})
|
||||
}
|
||||
|
||||
folderref := cmd.Folder.Reference()
|
||||
var poolref *types.ManagedObjectReference
|
||||
if cmd.ResourcePool != nil {
|
||||
poolref = types.NewReference(cmd.ResourcePool.Reference())
|
||||
}
|
||||
|
||||
relocateSpec := types.VirtualMachineRelocateSpec{
|
||||
DeviceChange: configSpecs,
|
||||
Folder: &folderref,
|
||||
Pool: poolref,
|
||||
}
|
||||
|
||||
if cmd.HostSystem != nil {
|
||||
hostref := cmd.HostSystem.Reference()
|
||||
relocateSpec.Host = &hostref
|
||||
}
|
||||
|
||||
cloneSpec := &types.VirtualMachineCloneSpec{
|
||||
PowerOn: false,
|
||||
Template: cmd.template,
|
||||
}
|
||||
|
||||
if cmd.snapshot == "" {
|
||||
if cmd.link {
|
||||
relocateSpec.DiskMoveType = string(types.VirtualMachineRelocateDiskMoveOptionsMoveAllDiskBackingsAndAllowSharing)
|
||||
}
|
||||
} else {
|
||||
if cmd.link {
|
||||
relocateSpec.DiskMoveType = string(types.VirtualMachineRelocateDiskMoveOptionsCreateNewChildDiskBacking)
|
||||
}
|
||||
|
||||
ref, ferr := cmd.VirtualMachine.FindSnapshot(ctx, cmd.snapshot)
|
||||
if ferr != nil {
|
||||
return nil, ferr
|
||||
}
|
||||
|
||||
cloneSpec.Snapshot = ref
|
||||
}
|
||||
|
||||
cloneSpec.Location = relocateSpec
|
||||
vmref := cmd.VirtualMachine.Reference()
|
||||
|
||||
// clone to storage pod
|
||||
datastoreref := types.ManagedObjectReference{}
|
||||
if cmd.StoragePod != nil && cmd.Datastore == nil {
|
||||
storagePod := cmd.StoragePod.Reference()
|
||||
|
||||
// Build pod selection spec from config spec
|
||||
podSelectionSpec := types.StorageDrsPodSelectionSpec{
|
||||
StoragePod: &storagePod,
|
||||
}
|
||||
|
||||
// Build the placement spec
|
||||
storagePlacementSpec := types.StoragePlacementSpec{
|
||||
Folder: &folderref,
|
||||
Vm: &vmref,
|
||||
CloneName: cmd.name,
|
||||
CloneSpec: cloneSpec,
|
||||
PodSelectionSpec: podSelectionSpec,
|
||||
Type: string(types.StoragePlacementSpecPlacementTypeClone),
|
||||
}
|
||||
|
||||
// Get the storage placement result
|
||||
storageResourceManager := object.NewStorageResourceManager(cmd.Client)
|
||||
result, err := storageResourceManager.RecommendDatastores(ctx, storagePlacementSpec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get the recommendations
|
||||
recommendations := result.Recommendations
|
||||
if len(recommendations) == 0 {
|
||||
return nil, fmt.Errorf("no datastore-cluster recommendations")
|
||||
}
|
||||
|
||||
// Get the first recommendation
|
||||
datastoreref = recommendations[0].Action[0].(*types.StoragePlacementAction).Destination
|
||||
} else if cmd.StoragePod == nil && cmd.Datastore != nil {
|
||||
datastoreref = cmd.Datastore.Reference()
|
||||
} else if cmd.Cluster != nil {
|
||||
spec := types.PlacementSpec{
|
||||
PlacementType: string(types.PlacementSpecPlacementTypeClone),
|
||||
CloneName: cmd.name,
|
||||
CloneSpec: cloneSpec,
|
||||
RelocateSpec: &cloneSpec.Location,
|
||||
Vm: &vmref,
|
||||
}
|
||||
result, err := cmd.Cluster.PlaceVm(ctx, spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
recs := result.Recommendations
|
||||
if len(recs) == 0 {
|
||||
return nil, fmt.Errorf("no cluster recommendations")
|
||||
}
|
||||
|
||||
rspec := *recs[0].Action[0].(*types.PlacementAction).RelocateSpec
|
||||
cloneSpec.Location.Host = rspec.Host
|
||||
cloneSpec.Location.Datastore = rspec.Datastore
|
||||
datastoreref = *rspec.Datastore
|
||||
} else {
|
||||
return nil, fmt.Errorf("please provide either a cluster, datastore or datastore-cluster")
|
||||
}
|
||||
|
||||
// Set the destination datastore
|
||||
cloneSpec.Location.Datastore = &datastoreref
|
||||
|
||||
// Check if vmx already exists
|
||||
if !cmd.force {
|
||||
vmxPath := fmt.Sprintf("%s/%s.vmx", cmd.name, cmd.name)
|
||||
|
||||
var mds mo.Datastore
|
||||
err = property.DefaultCollector(cmd.Client).RetrieveOne(ctx, datastoreref, []string{"name"}, &mds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
datastore := object.NewDatastore(cmd.Client, datastoreref)
|
||||
datastore.InventoryPath = mds.Name
|
||||
|
||||
_, err := datastore.Stat(ctx, vmxPath)
|
||||
if err == nil {
|
||||
dsPath := datastore.Path(vmxPath)
|
||||
return nil, fmt.Errorf("file %s already exists", dsPath)
|
||||
}
|
||||
}
|
||||
|
||||
// check if customization specification requested
|
||||
if len(cmd.customization) > 0 {
|
||||
// get the customization spec manager
|
||||
customizationSpecManager := object.NewCustomizationSpecManager(cmd.Client)
|
||||
// check if customization specification exists
|
||||
exists, err := customizationSpecManager.DoesCustomizationSpecExist(ctx, cmd.customization)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("customization specification %s does not exists", cmd.customization)
|
||||
}
|
||||
// get the customization specification
|
||||
customSpecItem, err := customizationSpecManager.GetCustomizationSpec(ctx, cmd.customization)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
customSpec := customSpecItem.Spec
|
||||
// set the customization
|
||||
cloneSpec.Customization = &customSpec
|
||||
}
|
||||
|
||||
if cmd.Spec {
|
||||
return nil, cmd.WriteAny(cloneSpec)
|
||||
}
|
||||
|
||||
task, err := cmd.VirtualMachine.Clone(ctx, cmd.Folder, cmd.name, *cloneSpec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logger := cmd.ProgressLogger(fmt.Sprintf("Cloning %s to %s...", cmd.VirtualMachine.InventoryPath, cmd.name))
|
||||
defer logger.Wait()
|
||||
|
||||
info, err := task.WaitForResult(ctx, logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return object.NewVirtualMachine(cmd.Client, info.Result.(types.ManagedObjectReference)), nil
|
||||
}
|
||||
186
vendor/github.com/vmware/govmomi/cli/vm/console.go
generated
vendored
Normal file
186
vendor/github.com/vmware/govmomi/cli/vm/console.go
generated
vendored
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/session"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type console struct {
|
||||
*flags.VirtualMachineFlag
|
||||
|
||||
h5 bool
|
||||
wss bool
|
||||
capture string
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.console", &console{})
|
||||
}
|
||||
|
||||
func (cmd *console) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
|
||||
cmd.VirtualMachineFlag.Register(ctx, f)
|
||||
|
||||
f.BoolVar(&cmd.h5, "h5", false, "Generate HTML5 UI console link")
|
||||
f.BoolVar(&cmd.wss, "wss", false, "Generate WebSocket console link")
|
||||
f.StringVar(&cmd.capture, "capture", "", "Capture console screen shot to file")
|
||||
}
|
||||
|
||||
func (cmd *console) Process(ctx context.Context) error {
|
||||
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *console) Usage() string {
|
||||
return "VM"
|
||||
}
|
||||
|
||||
func (cmd *console) Description() string {
|
||||
return `Generate console URL or screen capture for VM.
|
||||
|
||||
One of VMRC, VMware Player, VMware Fusion or VMware Workstation must be installed to
|
||||
open VMRC console URLs.
|
||||
|
||||
Examples:
|
||||
govc vm.console my-vm
|
||||
govc vm.console -capture screen.png my-vm # screen capture
|
||||
govc vm.console -capture - my-vm | display # screen capture to stdout
|
||||
open $(govc vm.console my-vm) # MacOSX VMRC
|
||||
open $(govc vm.console -h5 my-vm) # MacOSX H5
|
||||
xdg-open $(govc vm.console my-vm) # Linux VMRC
|
||||
xdg-open $(govc vm.console -h5 my-vm) # Linux H5`
|
||||
}
|
||||
|
||||
func (cmd *console) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
vms, err := cmd.VirtualMachines(f.Args())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(vms) != 1 {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
vm := vms[0]
|
||||
|
||||
state, err := vm.PowerState(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if (cmd.capture != "" || cmd.wss) && state != types.VirtualMachinePowerStatePoweredOn {
|
||||
return fmt.Errorf("vm is not powered on (%s)", state)
|
||||
}
|
||||
|
||||
c := vm.Client()
|
||||
|
||||
u := c.URL()
|
||||
|
||||
if cmd.capture != "" {
|
||||
u.Path = "/screen"
|
||||
query := url.Values{"id": []string{vm.Reference().Value}}
|
||||
u.RawQuery = query.Encode()
|
||||
|
||||
param := soap.DefaultDownload
|
||||
|
||||
if cmd.capture == "-" {
|
||||
w, _, derr := c.Download(ctx, u, ¶m)
|
||||
if derr != nil {
|
||||
return derr
|
||||
}
|
||||
|
||||
_, err = io.Copy(os.Stdout, w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return w.Close()
|
||||
}
|
||||
|
||||
return c.DownloadFile(ctx, cmd.capture, u, ¶m)
|
||||
}
|
||||
|
||||
if cmd.wss {
|
||||
ticket, err := vm.AcquireTicket(ctx, string(types.VirtualMachineTicketTypeWebmks))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
link := fmt.Sprintf("wss://%s:%d/ticket/%s", ticket.Host, ticket.Port, ticket.Ticket)
|
||||
fmt.Fprintln(cmd.Out, link)
|
||||
return nil
|
||||
}
|
||||
|
||||
m := session.NewManager(c)
|
||||
ticket, err := m.AcquireCloneTicket(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var link string
|
||||
|
||||
if cmd.h5 {
|
||||
m := object.NewOptionManager(c, *c.ServiceContent.Setting)
|
||||
|
||||
opt, err := m.Query(ctx, "VirtualCenter.FQDN")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fqdn := opt[0].GetOptionValue().Value.(string)
|
||||
|
||||
var info object.HostCertificateInfo
|
||||
err = info.FromURL(u, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u.Path = "/ui/webconsole.html"
|
||||
|
||||
u.RawQuery = url.Values{
|
||||
"vmId": []string{vm.Reference().Value},
|
||||
"vmName": []string{vm.Name()},
|
||||
"serverGuid": []string{c.ServiceContent.About.InstanceUuid},
|
||||
"host": []string{fqdn},
|
||||
"sessionTicket": []string{ticket},
|
||||
"thumbprint": []string{info.ThumbprintSHA1},
|
||||
}.Encode()
|
||||
|
||||
link = u.String()
|
||||
} else {
|
||||
link = fmt.Sprintf("vmrc://clone:%s@%s/?moid=%s", ticket, u.Hostname(), vm.Reference().Value)
|
||||
}
|
||||
|
||||
fmt.Fprintln(cmd.Out, link)
|
||||
|
||||
return nil
|
||||
}
|
||||
697
vendor/github.com/vmware/govmomi/cli/vm/create.go
generated
vendored
Normal file
697
vendor/github.com/vmware/govmomi/cli/vm/create.go
generated
vendored
Normal file
|
|
@ -0,0 +1,697 @@
|
|||
/*
|
||||
Copyright (c) 2014-2024 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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/find"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/units"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
var (
|
||||
FirmwareTypes = types.GuestOsDescriptorFirmwareType("").Strings()
|
||||
|
||||
FirmwareUsage = fmt.Sprintf("Firmware type [%s]", strings.Join(FirmwareTypes, "|"))
|
||||
)
|
||||
|
||||
type create struct {
|
||||
*flags.ClientFlag
|
||||
*flags.ClusterFlag
|
||||
*flags.DatacenterFlag
|
||||
*flags.DatastoreFlag
|
||||
*flags.StoragePodFlag
|
||||
*flags.ResourcePoolFlag
|
||||
*flags.HostSystemFlag
|
||||
*flags.NetworkFlag
|
||||
*flags.FolderFlag
|
||||
*flags.StorageProfileFlag
|
||||
|
||||
name string
|
||||
memory int
|
||||
cpus int
|
||||
guestID string
|
||||
link bool
|
||||
on bool
|
||||
force bool
|
||||
controller string
|
||||
eager bool
|
||||
thick bool
|
||||
annotation string
|
||||
firmware string
|
||||
version string
|
||||
place bool
|
||||
|
||||
iso string
|
||||
isoDatastoreFlag *flags.DatastoreFlag
|
||||
|
||||
disk string
|
||||
diskDatastoreFlag *flags.DatastoreFlag
|
||||
diskDatastore *object.Datastore
|
||||
|
||||
// Only set if the disk argument is a byte size, which means the disk
|
||||
// doesn't exist yet and should be created
|
||||
diskByteSize int64
|
||||
|
||||
Client *vim25.Client
|
||||
Cluster *object.ClusterComputeResource
|
||||
Datacenter *object.Datacenter
|
||||
Datastore *object.Datastore
|
||||
StoragePod *object.StoragePod
|
||||
ResourcePool *object.ResourcePool
|
||||
HostSystem *object.HostSystem
|
||||
Folder *object.Folder
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.create", &create{})
|
||||
}
|
||||
|
||||
func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
|
||||
cmd.ClientFlag.Register(ctx, f)
|
||||
|
||||
cmd.ClusterFlag, ctx = flags.NewClusterFlag(ctx)
|
||||
cmd.ClusterFlag.RegisterPlacement(ctx, f)
|
||||
|
||||
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
|
||||
cmd.DatacenterFlag.Register(ctx, f)
|
||||
|
||||
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
|
||||
cmd.DatastoreFlag.Register(ctx, f)
|
||||
|
||||
cmd.StoragePodFlag, ctx = flags.NewStoragePodFlag(ctx)
|
||||
cmd.StoragePodFlag.Register(ctx, f)
|
||||
|
||||
cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx)
|
||||
cmd.ResourcePoolFlag.Register(ctx, f)
|
||||
|
||||
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
|
||||
cmd.HostSystemFlag.Register(ctx, f)
|
||||
|
||||
cmd.NetworkFlag, ctx = flags.NewNetworkFlag(ctx)
|
||||
cmd.NetworkFlag.Register(ctx, f)
|
||||
|
||||
cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx)
|
||||
cmd.FolderFlag.Register(ctx, f)
|
||||
|
||||
cmd.StorageProfileFlag, ctx = flags.NewStorageProfileFlag(ctx)
|
||||
cmd.StorageProfileFlag.Register(ctx, f)
|
||||
|
||||
f.IntVar(&cmd.memory, "m", 1024, "Size in MB of memory")
|
||||
f.IntVar(&cmd.cpus, "c", 1, "Number of CPUs")
|
||||
f.StringVar(&cmd.guestID, "g", "otherGuest", "Guest OS ID")
|
||||
f.BoolVar(&cmd.link, "link", true, "Link specified disk")
|
||||
f.BoolVar(&cmd.on, "on", true, "Power on VM")
|
||||
f.BoolVar(&cmd.force, "force", false, "Create VM if vmx already exists")
|
||||
f.StringVar(&cmd.controller, "disk.controller", "scsi", "Disk controller type")
|
||||
f.BoolVar(&cmd.eager, "disk.eager", false, "Eagerly scrub new disk")
|
||||
f.BoolVar(&cmd.thick, "disk.thick", false, "Thick provision new disk")
|
||||
f.StringVar(&cmd.annotation, "annotation", "", "VM description")
|
||||
f.StringVar(&cmd.firmware, "firmware", FirmwareTypes[0], FirmwareUsage)
|
||||
if cli.ShowUnreleased() {
|
||||
f.BoolVar(&cmd.place, "place", false, "Place VM without creating")
|
||||
}
|
||||
|
||||
esxiVersions := types.GetESXiVersions()
|
||||
esxiVersionStrings := make([]string, len(esxiVersions))
|
||||
for i := range esxiVersions {
|
||||
esxiVersionStrings[i] = esxiVersions[i].String()
|
||||
}
|
||||
f.StringVar(&cmd.version, "version", "",
|
||||
fmt.Sprintf("ESXi hardware version [%s]", strings.Join(esxiVersionStrings, "|")))
|
||||
|
||||
f.StringVar(&cmd.iso, "iso", "", "ISO path")
|
||||
cmd.isoDatastoreFlag, ctx = flags.NewCustomDatastoreFlag(ctx)
|
||||
f.StringVar(&cmd.isoDatastoreFlag.Name, "iso-datastore", "", "Datastore for ISO file")
|
||||
|
||||
f.StringVar(&cmd.disk, "disk", "", "Disk path (to use existing) OR size (to create new, e.g. 20GB)")
|
||||
cmd.diskDatastoreFlag, _ = flags.NewCustomDatastoreFlag(ctx)
|
||||
f.StringVar(&cmd.diskDatastoreFlag.Name, "disk-datastore", "", "Datastore for disk file")
|
||||
}
|
||||
|
||||
func (cmd *create) Process(ctx context.Context) error {
|
||||
if err := cmd.ClientFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.ClusterFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.StoragePodFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.ResourcePoolFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.NetworkFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.FolderFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.StorageProfileFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Default iso/disk datastores to the VM's datastore
|
||||
if cmd.isoDatastoreFlag.Name == "" {
|
||||
cmd.isoDatastoreFlag = cmd.DatastoreFlag
|
||||
}
|
||||
if cmd.diskDatastoreFlag.Name == "" {
|
||||
cmd.diskDatastoreFlag = cmd.DatastoreFlag
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *create) Usage() string {
|
||||
return "NAME"
|
||||
}
|
||||
|
||||
func (cmd *create) Description() string {
|
||||
return `Create VM.
|
||||
|
||||
For a list of possible '-g' IDs, use 'govc vm.option.info' or see:
|
||||
https://code.vmware.com/apis/358/vsphere/doc/vim.vm.GuestOsDescriptor.GuestOsIdentifier.html
|
||||
|
||||
Examples:
|
||||
govc vm.create -on=false vm-name
|
||||
govc vm.create -iso library:/boot/linux/ubuntu.iso vm-name # Content Library ISO
|
||||
govc vm.create -cluster cluster1 vm-name # use compute cluster placement
|
||||
govc vm.create -datastore-cluster dscluster vm-name # use datastore cluster placement
|
||||
govc vm.create -m 2048 -c 2 -g freebsd64Guest -net.adapter vmxnet3 -disk.controller pvscsi vm-name`
|
||||
}
|
||||
|
||||
func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
var err error
|
||||
|
||||
if len(f.Args()) != 1 {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
cmd.name = f.Arg(0)
|
||||
if cmd.name == "" {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
cmd.Client, err = cmd.ClientFlag.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Cluster, err = cmd.ClusterFlag.ClusterIfSpecified()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Datacenter, err = cmd.DatacenterFlag.Datacenter()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.StoragePodFlag.Isset() {
|
||||
cmd.StoragePod, err = cmd.StoragePodFlag.StoragePod()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if cmd.Cluster == nil {
|
||||
cmd.Datastore, err = cmd.DatastoreFlag.Datastore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
cmd.HostSystem, err = cmd.HostSystemFlag.HostSystemIfSpecified()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.HostSystem != nil {
|
||||
if cmd.ResourcePool, err = cmd.HostSystem.ResourcePool(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if cmd.Cluster == nil {
|
||||
// -host is optional
|
||||
if cmd.ResourcePool, err = cmd.ResourcePoolFlag.ResourcePool(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if cmd.ResourcePool, err = cmd.Cluster.ResourcePool(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.Folder, err = cmd.FolderFlag.Folder(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify ISO exists
|
||||
if cmd.iso != "" {
|
||||
iso, err := cmd.isoDatastoreFlag.FileBacking(ctx, cmd.iso, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.iso = iso
|
||||
}
|
||||
|
||||
// Verify disk exists
|
||||
if cmd.disk != "" {
|
||||
var b units.ByteSize
|
||||
|
||||
// If disk can be parsed as byte units, don't stat
|
||||
err = b.Set(cmd.disk)
|
||||
if err == nil {
|
||||
cmd.diskByteSize = int64(b)
|
||||
} else {
|
||||
_, err = cmd.diskDatastoreFlag.Stat(ctx, cmd.disk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.diskDatastore, err = cmd.diskDatastoreFlag.Datastore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task, err := cmd.createVM(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if cmd.place || cmd.Spec {
|
||||
return nil
|
||||
}
|
||||
info, err := task.WaitForResult(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vm := object.NewVirtualMachine(cmd.Client, info.Result.(types.ManagedObjectReference))
|
||||
|
||||
if cmd.on {
|
||||
task, err := vm.PowerOn(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = task.WaitForResult(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type place struct {
|
||||
Spec types.PlacementSpec `json:"spec"`
|
||||
Recommendations []types.ClusterRecommendation `json:"recommendations"`
|
||||
|
||||
ctx context.Context
|
||||
cmd *create
|
||||
}
|
||||
|
||||
func (p *place) Dump() interface{} {
|
||||
return p.Recommendations
|
||||
}
|
||||
|
||||
func (p *place) action(w io.Writer, r types.ClusterRecommendation, a *types.PlacementAction) error {
|
||||
spec := a.RelocateSpec
|
||||
if spec == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
fields := []struct {
|
||||
name string
|
||||
moid *types.ManagedObjectReference
|
||||
}{
|
||||
{"Target", r.Target},
|
||||
{" Folder", spec.Folder},
|
||||
{" Datastore", spec.Datastore},
|
||||
{" Pool", spec.Pool},
|
||||
{" Host", spec.Host},
|
||||
}
|
||||
|
||||
for _, f := range fields {
|
||||
if f.moid == nil {
|
||||
continue
|
||||
}
|
||||
path, err := find.InventoryPath(p.ctx, p.cmd.Client, *f.moid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(w, "%s:\t%s\n", f.name, path)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *place) Write(w io.Writer) error {
|
||||
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
|
||||
|
||||
for _, r := range p.Recommendations {
|
||||
for _, a := range r.Action {
|
||||
p.action(tw, r, a.(*types.PlacementAction))
|
||||
}
|
||||
}
|
||||
|
||||
return tw.Flush()
|
||||
}
|
||||
|
||||
func (cmd *create) createVM(ctx context.Context) (*object.Task, error) {
|
||||
var devices object.VirtualDeviceList
|
||||
var err error
|
||||
|
||||
if cmd.version != "" {
|
||||
if v, _ := types.ParseESXiVersion(cmd.version); v.IsValid() {
|
||||
cmd.version = v.HardwareVersion().String()
|
||||
} else if v, _ := types.ParseHardwareVersion(cmd.version); v.IsValid() {
|
||||
cmd.version = v.String()
|
||||
} else {
|
||||
return nil, fmt.Errorf("invalid version: %s", cmd.version)
|
||||
}
|
||||
}
|
||||
|
||||
spec := &types.VirtualMachineConfigSpec{
|
||||
Name: cmd.name,
|
||||
GuestId: cmd.guestID,
|
||||
NumCPUs: int32(cmd.cpus),
|
||||
MemoryMB: int64(cmd.memory),
|
||||
Annotation: cmd.annotation,
|
||||
Firmware: cmd.firmware,
|
||||
Version: cmd.version,
|
||||
}
|
||||
|
||||
spec.VmProfile, err = cmd.StorageProfileSpec(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
devices, err = cmd.addStorage(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
devices, err = cmd.addNetwork(devices)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
deviceChange, err := devices.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
spec.DeviceChange = deviceChange
|
||||
|
||||
var datastore *object.Datastore
|
||||
|
||||
// If storage pod is specified, collect placement recommendations
|
||||
if cmd.StoragePod != nil {
|
||||
datastore, err = cmd.recommendDatastore(ctx, spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if cmd.Datastore != nil {
|
||||
datastore = cmd.Datastore
|
||||
} else if cmd.Cluster != nil {
|
||||
pspec := types.PlacementSpec{
|
||||
PlacementType: string(types.PlacementSpecPlacementTypeCreate),
|
||||
ConfigSpec: spec,
|
||||
}
|
||||
result, err := cmd.Cluster.PlaceVm(ctx, pspec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
recs := result.Recommendations
|
||||
if cmd.place {
|
||||
return nil, cmd.WriteResult(&place{pspec, recs, ctx, cmd})
|
||||
}
|
||||
if len(recs) == 0 {
|
||||
return nil, fmt.Errorf("no cluster recommendations")
|
||||
}
|
||||
|
||||
rspec := *recs[0].Action[0].(*types.PlacementAction).RelocateSpec
|
||||
if rspec.Datastore != nil {
|
||||
datastore = object.NewDatastore(cmd.Client, *rspec.Datastore)
|
||||
datastore.InventoryPath, _ = datastore.ObjectName(ctx)
|
||||
cmd.Datastore = datastore
|
||||
}
|
||||
if rspec.Host != nil {
|
||||
cmd.HostSystem = object.NewHostSystem(cmd.Client, *rspec.Host)
|
||||
}
|
||||
if rspec.Pool != nil {
|
||||
cmd.ResourcePool = object.NewResourcePool(cmd.Client, *rspec.Pool)
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("please provide either a cluster, datastore or datastore-cluster")
|
||||
}
|
||||
|
||||
if !cmd.force && !cmd.Spec {
|
||||
vmxPath := fmt.Sprintf("%s/%s.vmx", cmd.name, cmd.name)
|
||||
|
||||
_, err := datastore.Stat(ctx, vmxPath)
|
||||
if err == nil {
|
||||
dsPath := cmd.Datastore.Path(vmxPath)
|
||||
return nil, fmt.Errorf("file %s already exists", dsPath)
|
||||
}
|
||||
}
|
||||
|
||||
folder := cmd.Folder
|
||||
|
||||
spec.Files = &types.VirtualMachineFileInfo{
|
||||
VmPathName: fmt.Sprintf("[%s]", datastore.Name()),
|
||||
}
|
||||
|
||||
if cmd.Spec {
|
||||
return nil, cmd.WriteAny(spec)
|
||||
}
|
||||
|
||||
return folder.CreateVM(ctx, *spec, cmd.ResourcePool, cmd.HostSystem)
|
||||
}
|
||||
|
||||
func (cmd *create) addStorage(devices object.VirtualDeviceList) (object.VirtualDeviceList, error) {
|
||||
if cmd.controller != "ide" {
|
||||
if cmd.controller == "nvme" {
|
||||
nvme, err := devices.CreateNVMEController()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
devices = append(devices, nvme)
|
||||
cmd.controller = devices.Name(nvme)
|
||||
} else if cmd.controller == "sata" {
|
||||
sata, err := devices.CreateSATAController()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
devices = append(devices, sata)
|
||||
cmd.controller = devices.Name(sata)
|
||||
} else {
|
||||
scsi, err := devices.CreateSCSIController(cmd.controller)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
devices = append(devices, scsi)
|
||||
cmd.controller = devices.Name(scsi)
|
||||
}
|
||||
}
|
||||
|
||||
// If controller is specified to be IDE or if an ISO is specified, add IDE controller.
|
||||
if cmd.controller == "ide" || cmd.iso != "" {
|
||||
ide, err := devices.CreateIDEController()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
devices = append(devices, ide)
|
||||
}
|
||||
|
||||
if cmd.diskByteSize != 0 {
|
||||
controller, err := devices.FindDiskController(cmd.controller)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
backing := &types.VirtualDiskFlatVer2BackingInfo{
|
||||
DiskMode: string(types.VirtualDiskModePersistent),
|
||||
ThinProvisioned: types.NewBool(!cmd.thick),
|
||||
}
|
||||
if cmd.thick {
|
||||
backing.EagerlyScrub = &cmd.eager
|
||||
}
|
||||
disk := &types.VirtualDisk{
|
||||
VirtualDevice: types.VirtualDevice{
|
||||
Key: devices.NewKey(),
|
||||
Backing: backing,
|
||||
},
|
||||
CapacityInKB: cmd.diskByteSize / 1024,
|
||||
}
|
||||
|
||||
devices.AssignController(disk, controller)
|
||||
devices = append(devices, disk)
|
||||
} else if cmd.disk != "" {
|
||||
controller, err := devices.FindDiskController(cmd.controller)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ds := cmd.diskDatastore.Reference()
|
||||
path := cmd.diskDatastore.Path(cmd.disk)
|
||||
disk := devices.CreateDisk(controller, ds, path)
|
||||
|
||||
if cmd.link {
|
||||
disk = devices.ChildDisk(disk)
|
||||
}
|
||||
|
||||
devices = append(devices, disk)
|
||||
}
|
||||
|
||||
if cmd.iso != "" {
|
||||
ide, err := devices.FindIDEController("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cdrom, err := devices.CreateCdrom(ide)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cdrom = devices.InsertIso(cdrom, cmd.iso)
|
||||
devices = append(devices, cdrom)
|
||||
}
|
||||
|
||||
return devices, nil
|
||||
}
|
||||
|
||||
func (cmd *create) addNetwork(devices object.VirtualDeviceList) (object.VirtualDeviceList, error) {
|
||||
netdev, err := cmd.NetworkFlag.Device()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
devices = append(devices, netdev)
|
||||
return devices, nil
|
||||
}
|
||||
|
||||
func (cmd *create) recommendDatastore(ctx context.Context, spec *types.VirtualMachineConfigSpec) (*object.Datastore, error) {
|
||||
sp := cmd.StoragePod.Reference()
|
||||
|
||||
// Build pod selection spec from config spec
|
||||
podSelectionSpec := types.StorageDrsPodSelectionSpec{
|
||||
StoragePod: &sp,
|
||||
}
|
||||
|
||||
// Keep list of disks that need to be placed
|
||||
var disks []*types.VirtualDisk
|
||||
|
||||
// Collect disks eligible for placement
|
||||
for _, deviceConfigSpec := range spec.DeviceChange {
|
||||
s := deviceConfigSpec.GetVirtualDeviceConfigSpec()
|
||||
if s.Operation != types.VirtualDeviceConfigSpecOperationAdd {
|
||||
continue
|
||||
}
|
||||
|
||||
if s.FileOperation != types.VirtualDeviceConfigSpecFileOperationCreate {
|
||||
continue
|
||||
}
|
||||
|
||||
d, ok := s.Device.(*types.VirtualDisk)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
podConfigForPlacement := types.VmPodConfigForPlacement{
|
||||
StoragePod: sp,
|
||||
Disk: []types.PodDiskLocator{
|
||||
{
|
||||
DiskId: d.Key,
|
||||
DiskBackingInfo: d.Backing,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
podSelectionSpec.InitialVmConfig = append(podSelectionSpec.InitialVmConfig, podConfigForPlacement)
|
||||
disks = append(disks, d)
|
||||
}
|
||||
|
||||
sps := types.StoragePlacementSpec{
|
||||
Type: string(types.StoragePlacementSpecPlacementTypeCreate),
|
||||
ResourcePool: types.NewReference(cmd.ResourcePool.Reference()),
|
||||
PodSelectionSpec: podSelectionSpec,
|
||||
ConfigSpec: spec,
|
||||
}
|
||||
|
||||
srm := object.NewStorageResourceManager(cmd.Client)
|
||||
result, err := srm.RecommendDatastores(ctx, sps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Use result to pin disks to recommended datastores
|
||||
recs := result.Recommendations
|
||||
if len(recs) == 0 {
|
||||
return nil, fmt.Errorf("no datastore-cluster recommendations")
|
||||
}
|
||||
|
||||
ds := recs[0].Action[0].(*types.StoragePlacementAction).Destination
|
||||
|
||||
var mds mo.Datastore
|
||||
err = property.DefaultCollector(cmd.Client).RetrieveOne(ctx, ds, []string{"name"}, &mds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
datastore := object.NewDatastore(cmd.Client, ds)
|
||||
datastore.InventoryPath = mds.Name
|
||||
|
||||
// Apply recommendation to eligible disks
|
||||
for _, disk := range disks {
|
||||
backing := disk.Backing.(*types.VirtualDiskFlatVer2BackingInfo)
|
||||
backing.Datastore = &ds
|
||||
}
|
||||
|
||||
return datastore, nil
|
||||
}
|
||||
321
vendor/github.com/vmware/govmomi/cli/vm/customize.go
generated
vendored
Normal file
321
vendor/github.com/vmware/govmomi/cli/vm/customize.go
generated
vendored
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
/*
|
||||
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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type customize struct {
|
||||
*flags.VirtualMachineFlag
|
||||
|
||||
alc int
|
||||
prefix types.CustomizationPrefixName
|
||||
tz string
|
||||
domain string
|
||||
host types.CustomizationFixedName
|
||||
mac flags.StringList
|
||||
ip flags.StringList
|
||||
ip6 flags.StringList
|
||||
gateway flags.StringList
|
||||
netmask flags.StringList
|
||||
dnsserver flags.StringList
|
||||
dnssuffix flags.StringList
|
||||
kind string
|
||||
username string
|
||||
org string
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.customize", &customize{})
|
||||
}
|
||||
|
||||
func (cmd *customize) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
|
||||
cmd.VirtualMachineFlag.Register(ctx, f)
|
||||
|
||||
f.IntVar(&cmd.alc, "auto-login", 0, "Number of times the VM should automatically login as an administrator")
|
||||
f.StringVar(&cmd.prefix.Base, "prefix", "", "Host name generator prefix")
|
||||
f.StringVar(&cmd.tz, "tz", "", "Time zone")
|
||||
f.StringVar(&cmd.domain, "domain", "", "Domain name")
|
||||
f.StringVar(&cmd.host.Name, "name", "", "Host name")
|
||||
f.Var(&cmd.mac, "mac", "MAC address")
|
||||
cmd.mac = nil
|
||||
f.Var(&cmd.ip, "ip", "IPv4 address")
|
||||
cmd.ip = nil
|
||||
f.Var(&cmd.ip6, "ip6", "IPv6 addresses with optional netmask (defaults to /64), separated by comma")
|
||||
cmd.ip6 = nil
|
||||
f.Var(&cmd.gateway, "gateway", "Gateway")
|
||||
cmd.gateway = nil
|
||||
f.Var(&cmd.netmask, "netmask", "Netmask")
|
||||
cmd.netmask = nil
|
||||
f.Var(&cmd.dnsserver, "dns-server", "DNS server list")
|
||||
cmd.dnsserver = nil
|
||||
f.Var(&cmd.dnssuffix, "dns-suffix", "DNS suffix list")
|
||||
cmd.dnssuffix = nil
|
||||
f.StringVar(&cmd.kind, "type", "Linux", "Customization type if spec NAME is not specified (Linux|Windows)")
|
||||
f.StringVar(&cmd.username, "username", "", "Windows only : full name of the end user in firstname lastname format")
|
||||
f.StringVar(&cmd.org, "org", "", "Windows only : name of the org that owns the VM")
|
||||
}
|
||||
|
||||
func (cmd *customize) Usage() string {
|
||||
return "[NAME]"
|
||||
}
|
||||
|
||||
func (cmd *customize) Description() string {
|
||||
return `Customize VM.
|
||||
|
||||
Optionally specify a customization spec NAME.
|
||||
|
||||
The '-ip', '-netmask' and '-gateway' flags are for static IP configuration.
|
||||
If the VM has multiple NICs, an '-ip' and '-netmask' must be specified for each.
|
||||
|
||||
The '-dns-server' and '-dns-suffix' flags can be specified multiple times.
|
||||
|
||||
Windows -tz value requires the Index (hex): https://support.microsoft.com/en-us/help/973627/microsoft-time-zone-index-values
|
||||
|
||||
Examples:
|
||||
govc vm.customize -vm VM NAME
|
||||
govc vm.customize -vm VM -name my-hostname -ip dhcp
|
||||
govc vm.customize -vm VM -gateway GATEWAY -ip NEWIP -netmask NETMASK -dns-server DNS1,DNS2 NAME
|
||||
# Multiple -ip without -mac are applied by vCenter in the order in which the NICs appear on the bus
|
||||
govc vm.customize -vm VM -ip 10.0.0.178 -netmask 255.255.255.0 -ip 10.0.0.162 -netmask 255.255.255.0
|
||||
# Multiple -ip with -mac are applied by vCenter to the NIC with the given MAC address
|
||||
govc vm.customize -vm VM -mac 00:50:56:be:dd:f8 -ip 10.0.0.178 -netmask 255.255.255.0 -mac 00:50:56:be:60:cf -ip 10.0.0.162 -netmask 255.255.255.0
|
||||
# Dual stack IPv4/IPv6, single NIC
|
||||
govc vm.customize -vm VM -ip 10.0.0.1 -netmask 255.255.255.0 -ip6 '2001:db8::1/64' -name my-hostname NAME
|
||||
# DHCPv6, single NIC
|
||||
govc vm.customize -vm VM -ip6 dhcp6 NAME
|
||||
# Static IPv6, three NICs, last one with two addresses
|
||||
govc vm.customize -vm VM -ip6 2001:db8::1/64 -ip6 2001:db8::2/64 -ip6 2001:db8::3/64,2001:db8::4/64 NAME
|
||||
govc vm.customize -vm VM -auto-login 3 NAME
|
||||
govc vm.customize -vm VM -prefix demo NAME
|
||||
govc vm.customize -vm VM -tz America/New_York NAME`
|
||||
}
|
||||
|
||||
// Parse a string of multiple IPv6 addresses with optional netmask; separated by comma
|
||||
func parseIPv6Argument(argv string) (ipconf []types.BaseCustomizationIpV6Generator, err error) {
|
||||
for _, substring := range strings.Split(argv, ",") {
|
||||
// remove leading and trailing white space
|
||||
substring = strings.TrimSpace(substring)
|
||||
// handle "dhcp6" and lists of static IPv6 addresses
|
||||
switch substring {
|
||||
case "dhcp6":
|
||||
ipconf = append(
|
||||
ipconf,
|
||||
&types.CustomizationDhcpIpV6Generator{},
|
||||
)
|
||||
default:
|
||||
// check if subnet mask was specified
|
||||
switch strings.Count(substring, "/") {
|
||||
// no mask, set default
|
||||
case 0:
|
||||
ipconf = append(ipconf, &types.CustomizationFixedIpV6{
|
||||
IpAddress: substring,
|
||||
SubnetMask: 64,
|
||||
})
|
||||
// a single forward slash was found: parse and use subnet mask
|
||||
case 1:
|
||||
parts := strings.Split(substring, "/")
|
||||
mask, err := strconv.Atoi(parts[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to convert subnet mask to int: %w", err)
|
||||
}
|
||||
ipconf = append(ipconf, &types.CustomizationFixedIpV6{
|
||||
IpAddress: parts[0],
|
||||
SubnetMask: int32(mask),
|
||||
})
|
||||
// too many forward slashes; return error
|
||||
default:
|
||||
return nil, fmt.Errorf("unable to parse IPv6 address (too many subnet separators): %s", substring)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ipconf, nil
|
||||
}
|
||||
|
||||
func (cmd *customize) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
vm, err := cmd.VirtualMachineFlag.VirtualMachine()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if vm == nil {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
var spec *types.CustomizationSpec
|
||||
|
||||
name := f.Arg(0)
|
||||
if name == "" {
|
||||
spec = &types.CustomizationSpec{
|
||||
NicSettingMap: make([]types.CustomizationAdapterMapping, len(cmd.ip)),
|
||||
}
|
||||
|
||||
switch cmd.kind {
|
||||
case "Linux":
|
||||
spec.Identity = &types.CustomizationLinuxPrep{
|
||||
HostName: new(types.CustomizationVirtualMachineName),
|
||||
}
|
||||
case "Windows":
|
||||
spec.Identity = &types.CustomizationSysprep{
|
||||
UserData: types.CustomizationUserData{
|
||||
ComputerName: new(types.CustomizationVirtualMachineName),
|
||||
},
|
||||
}
|
||||
default:
|
||||
return flag.ErrHelp
|
||||
}
|
||||
} else {
|
||||
m := object.NewCustomizationSpecManager(vm.Client())
|
||||
|
||||
exists, err := m.DoesCustomizationSpecExist(ctx, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
return fmt.Errorf("specification %q does not exist", name)
|
||||
}
|
||||
|
||||
item, err := m.GetCustomizationSpec(ctx, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
spec = &item.Spec
|
||||
}
|
||||
|
||||
if len(cmd.ip) > len(spec.NicSettingMap) {
|
||||
return fmt.Errorf("%d -ip specified, spec %q has %d", len(cmd.ip), name, len(spec.NicSettingMap))
|
||||
}
|
||||
|
||||
sysprep, isWindows := spec.Identity.(*types.CustomizationSysprep)
|
||||
linprep, _ := spec.Identity.(*types.CustomizationLinuxPrep)
|
||||
|
||||
if isWindows {
|
||||
sysprep.Identification.JoinDomain = cmd.domain
|
||||
sysprep.UserData.FullName = cmd.username
|
||||
sysprep.UserData.OrgName = cmd.org
|
||||
} else {
|
||||
linprep.Domain = cmd.domain
|
||||
}
|
||||
|
||||
if len(cmd.dnsserver) != 0 {
|
||||
if !isWindows {
|
||||
for _, s := range cmd.dnsserver {
|
||||
spec.GlobalIPSettings.DnsServerList =
|
||||
append(spec.GlobalIPSettings.DnsServerList, strings.Split(s, ",")...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spec.GlobalIPSettings.DnsSuffixList = cmd.dnssuffix
|
||||
|
||||
if cmd.prefix.Base != "" {
|
||||
if isWindows {
|
||||
sysprep.UserData.ComputerName = &cmd.prefix
|
||||
} else {
|
||||
linprep.HostName = &cmd.prefix
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.host.Name != "" {
|
||||
if isWindows {
|
||||
sysprep.UserData.ComputerName = &cmd.host
|
||||
} else {
|
||||
linprep.HostName = &cmd.host
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.alc != 0 {
|
||||
if !isWindows {
|
||||
return fmt.Errorf("option '-auto-login' is Windows only")
|
||||
}
|
||||
sysprep.GuiUnattended.AutoLogon = true
|
||||
sysprep.GuiUnattended.AutoLogonCount = int32(cmd.alc)
|
||||
}
|
||||
|
||||
if cmd.tz != "" {
|
||||
if isWindows {
|
||||
tz, err := strconv.ParseInt(cmd.tz, 16, 32)
|
||||
if err != nil {
|
||||
return fmt.Errorf("converting -tz=%q: %s", cmd.tz, err)
|
||||
}
|
||||
sysprep.GuiUnattended.TimeZone = int32(tz)
|
||||
} else {
|
||||
linprep.TimeZone = cmd.tz
|
||||
}
|
||||
}
|
||||
|
||||
for i, ip := range cmd.ip {
|
||||
nic := &spec.NicSettingMap[i]
|
||||
switch ip {
|
||||
case "dhcp":
|
||||
nic.Adapter.Ip = new(types.CustomizationDhcpIpGenerator)
|
||||
default:
|
||||
nic.Adapter.Ip = &types.CustomizationFixedIp{IpAddress: ip}
|
||||
}
|
||||
|
||||
if i < len(cmd.netmask) {
|
||||
nic.Adapter.SubnetMask = cmd.netmask[i]
|
||||
}
|
||||
if i < len(cmd.mac) {
|
||||
nic.MacAddress = cmd.mac[i]
|
||||
}
|
||||
if i < len(cmd.gateway) {
|
||||
nic.Adapter.Gateway = strings.Split(cmd.gateway[i], ",")
|
||||
}
|
||||
if isWindows {
|
||||
if i < len(cmd.dnsserver) {
|
||||
nic.Adapter.DnsServerList = strings.Split(cmd.dnsserver[i], ",")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i, ip6 := range cmd.ip6 {
|
||||
ipconfig, err := parseIPv6Argument(ip6)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// use the same logic as the ip switch: the first occurrence of the ip6 switch is assigned to the first nic,
|
||||
// the second to the second nic and so forth.
|
||||
if spec.NicSettingMap == nil || len(spec.NicSettingMap) < i {
|
||||
return fmt.Errorf("unable to find a network adapter for IPv6 settings %d (%s)", i, ip6)
|
||||
}
|
||||
nic := &spec.NicSettingMap[i]
|
||||
if nic.Adapter.IpV6Spec == nil {
|
||||
nic.Adapter.IpV6Spec = new(types.CustomizationIPSettingsIpV6AddressSpec)
|
||||
}
|
||||
nic.Adapter.IpV6Spec.Ip = append(nic.Adapter.IpV6Spec.Ip, ipconfig...)
|
||||
}
|
||||
|
||||
task, err := vm.Customize(ctx, *spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return task.Wait(ctx)
|
||||
}
|
||||
110
vendor/github.com/vmware/govmomi/cli/vm/destroy.go
generated
vendored
Normal file
110
vendor/github.com/vmware/govmomi/cli/vm/destroy.go
generated
vendored
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type destroy struct {
|
||||
*flags.ClientFlag
|
||||
*flags.SearchFlag
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.destroy", &destroy{})
|
||||
}
|
||||
|
||||
func (cmd *destroy) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
|
||||
cmd.ClientFlag.Register(ctx, f)
|
||||
|
||||
cmd.SearchFlag, ctx = flags.NewSearchFlag(ctx, flags.SearchVirtualMachines)
|
||||
cmd.SearchFlag.Register(ctx, f)
|
||||
}
|
||||
|
||||
func (cmd *destroy) Process(ctx context.Context) error {
|
||||
if err := cmd.ClientFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.SearchFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *destroy) Usage() string {
|
||||
return "VM..."
|
||||
}
|
||||
|
||||
func (cmd *destroy) Description() string {
|
||||
return `Power off and delete VM.
|
||||
|
||||
When a VM is destroyed, any attached virtual disks are also deleted.
|
||||
Use the 'device.remove -vm VM -keep disk-*' command to detach and
|
||||
keep disks if needed, prior to calling vm.destroy.
|
||||
|
||||
Examples:
|
||||
govc vm.destroy my-vm`
|
||||
}
|
||||
|
||||
func (cmd *destroy) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
vms, err := cmd.VirtualMachines(f.Args())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, vm := range vms {
|
||||
var (
|
||||
task *object.Task
|
||||
state types.VirtualMachinePowerState
|
||||
)
|
||||
|
||||
state, err = vm.PowerState(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if state == types.VirtualMachinePowerStatePoweredOn {
|
||||
task, err = vm.PowerOff(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ignore error since the VM may already been in powered off state.
|
||||
// vm.Destroy will fail if the VM is still powered on.
|
||||
_ = task.Wait(ctx)
|
||||
}
|
||||
|
||||
task, err = vm.Destroy(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = task.Wait(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
78
vendor/github.com/vmware/govmomi/cli/vm/guest/auth.go
generated
vendored
Normal file
78
vendor/github.com/vmware/govmomi/cli/vm/guest/auth.go
generated
vendored
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type AuthFlag struct {
|
||||
auth types.NamePasswordAuthentication
|
||||
proc bool
|
||||
}
|
||||
|
||||
func newAuthFlag(ctx context.Context) (*AuthFlag, context.Context) {
|
||||
return &AuthFlag{}, ctx
|
||||
}
|
||||
|
||||
func (flag *AuthFlag) String() string {
|
||||
return fmt.Sprintf("%s:%s", flag.auth.Username, strings.Repeat("x", len(flag.auth.Password)))
|
||||
}
|
||||
|
||||
func (flag *AuthFlag) Set(s string) error {
|
||||
c := strings.SplitN(s, ":", 2)
|
||||
if len(c) > 0 {
|
||||
flag.auth.Username = c[0]
|
||||
if len(c) > 1 {
|
||||
flag.auth.Password = c[1]
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (flag *AuthFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
env := "GOVC_GUEST_LOGIN"
|
||||
value := os.Getenv(env)
|
||||
err := flag.Set(value)
|
||||
if err != nil {
|
||||
fmt.Printf("could not set guest login values: %v", err)
|
||||
}
|
||||
usage := fmt.Sprintf("Guest VM credentials (<user>:<password>) [%s]", env)
|
||||
f.Var(flag, "l", usage)
|
||||
if flag.proc {
|
||||
f.BoolVar(&flag.auth.GuestAuthentication.InteractiveSession, "i", false, "Interactive session")
|
||||
}
|
||||
}
|
||||
|
||||
func (flag *AuthFlag) Process(ctx context.Context) error {
|
||||
if flag.auth.Username == "" {
|
||||
return fmt.Errorf("guest login username must not be empty")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (flag *AuthFlag) Auth() types.BaseGuestAuthentication {
|
||||
return &flag.auth
|
||||
}
|
||||
77
vendor/github.com/vmware/govmomi/cli/vm/guest/chmod.go
generated
vendored
Normal file
77
vendor/github.com/vmware/govmomi/cli/vm/guest/chmod.go
generated
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"strconv"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type chmod struct {
|
||||
*GuestFlag
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("guest.chmod", &chmod{})
|
||||
}
|
||||
|
||||
func (cmd *chmod) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.GuestFlag, ctx = newGuestFlag(ctx)
|
||||
cmd.GuestFlag.Register(ctx, f)
|
||||
}
|
||||
|
||||
func (cmd *chmod) Process(ctx context.Context) error {
|
||||
if err := cmd.GuestFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *chmod) Usage() string {
|
||||
return "MODE FILE"
|
||||
}
|
||||
|
||||
func (cmd *chmod) Description() string {
|
||||
return `Change FILE MODE on VM.
|
||||
|
||||
Examples:
|
||||
govc guest.chmod -vm $name 0644 /var/log/foo.log`
|
||||
}
|
||||
|
||||
func (cmd *chmod) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
if f.NArg() != 2 {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
m, err := cmd.FileManager()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var attr types.GuestPosixFileAttributes
|
||||
|
||||
attr.Permissions, err = strconv.ParseInt(f.Arg(0), 0, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return m.ChangeFileAttributes(ctx, cmd.Auth(), f.Arg(1), &attr)
|
||||
}
|
||||
96
vendor/github.com/vmware/govmomi/cli/vm/guest/chown.go
generated
vendored
Normal file
96
vendor/github.com/vmware/govmomi/cli/vm/guest/chown.go
generated
vendored
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type chown struct {
|
||||
*GuestFlag
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("guest.chown", &chown{})
|
||||
}
|
||||
|
||||
func (cmd *chown) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.GuestFlag, ctx = newGuestFlag(ctx)
|
||||
cmd.GuestFlag.Register(ctx, f)
|
||||
}
|
||||
|
||||
func (cmd *chown) Process(ctx context.Context) error {
|
||||
if err := cmd.GuestFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *chown) Usage() string {
|
||||
return "UID[:GID] FILE"
|
||||
}
|
||||
|
||||
func (cmd *chown) Description() string {
|
||||
return `Change FILE UID and GID on VM.
|
||||
|
||||
Examples:
|
||||
govc guest.chown -vm $name UID[:GID] /var/log/foo.log`
|
||||
}
|
||||
|
||||
func (cmd *chown) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
if f.NArg() != 2 {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
m, err := cmd.FileManager()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var attr types.GuestPosixFileAttributes
|
||||
|
||||
ids := strings.SplitN(f.Arg(0), ":", 2)
|
||||
if len(ids) == 0 {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
id, err := strconv.Atoi(ids[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
attr.OwnerId = new(int32)
|
||||
*attr.OwnerId = int32(id)
|
||||
|
||||
if len(ids) == 2 {
|
||||
id, err = strconv.Atoi(ids[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
attr.GroupId = new(int32)
|
||||
*attr.GroupId = int32(id)
|
||||
}
|
||||
|
||||
return m.ChangeFileAttributes(ctx, cmd.Auth(), f.Arg(1), &attr)
|
||||
}
|
||||
80
vendor/github.com/vmware/govmomi/cli/vm/guest/df.go
generated
vendored
Normal file
80
vendor/github.com/vmware/govmomi/cli/vm/guest/df.go
generated
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/units"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type df struct {
|
||||
*flags.VirtualMachineFlag
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("guest.df", &df{})
|
||||
}
|
||||
|
||||
func (cmd *df) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
|
||||
cmd.VirtualMachineFlag.Register(ctx, f)
|
||||
}
|
||||
|
||||
func (cmd *df) Description() string {
|
||||
return `Report file system disk space usage.
|
||||
|
||||
Examples:
|
||||
govc guest.df -vm $name`
|
||||
}
|
||||
|
||||
type dfResult []types.GuestDiskInfo
|
||||
|
||||
func (r dfResult) Write(w io.Writer) error {
|
||||
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
|
||||
_, _ = fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t%s\n", "Filesystem", "Size", "Used", "Avail", "Use%")
|
||||
for _, disk := range r {
|
||||
used := disk.Capacity - disk.FreeSpace
|
||||
use := 100.0 * float32(used) / float32(disk.Capacity)
|
||||
_, _ = fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t%.0f%%\n", disk.DiskPath,
|
||||
units.ByteSize(disk.Capacity), units.ByteSize(used), units.ByteSize(disk.FreeSpace), use)
|
||||
}
|
||||
return tw.Flush()
|
||||
}
|
||||
|
||||
func (cmd *df) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
obj, err := cmd.VirtualMachine()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var vm mo.VirtualMachine
|
||||
err = obj.Properties(ctx, obj.Reference(), []string{"guest.disk"}, &vm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return cmd.WriteResult(dfResult(vm.Guest.Disk))
|
||||
}
|
||||
106
vendor/github.com/vmware/govmomi/cli/vm/guest/download.go
generated
vendored
Normal file
106
vendor/github.com/vmware/govmomi/cli/vm/guest/download.go
generated
vendored
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/vim25/progress"
|
||||
)
|
||||
|
||||
type download struct {
|
||||
*GuestFlag
|
||||
|
||||
overwrite bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("guest.download", &download{})
|
||||
}
|
||||
|
||||
func (cmd *download) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.GuestFlag, ctx = newGuestFlag(ctx)
|
||||
cmd.GuestFlag.Register(ctx, f)
|
||||
|
||||
f.BoolVar(&cmd.overwrite, "f", false, "If set, the local destination file is clobbered")
|
||||
}
|
||||
|
||||
func (cmd *download) Usage() string {
|
||||
return "SOURCE DEST"
|
||||
}
|
||||
|
||||
func (cmd *download) Description() string {
|
||||
return `Copy SOURCE from the guest VM to DEST on the local system.
|
||||
|
||||
If DEST name is "-", source is written to stdout.
|
||||
|
||||
Examples:
|
||||
govc guest.download -l user:pass -vm=my-vm /var/log/my.log ./local.log
|
||||
govc guest.download -l user:pass -vm=my-vm /etc/motd -
|
||||
tar -cf- foo/ | govc guest.run -d - tar -C /tmp -xf-
|
||||
govc guest.run tar -C /tmp -cf- foo/ | tar -C /tmp -xf- # download directory`
|
||||
}
|
||||
|
||||
func (cmd *download) Process(ctx context.Context) error {
|
||||
if err := cmd.GuestFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *download) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
if f.NArg() != 2 {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
src := f.Arg(0)
|
||||
dst := f.Arg(1)
|
||||
|
||||
_, err := os.Stat(dst)
|
||||
if err == nil && !cmd.overwrite {
|
||||
return os.ErrExist
|
||||
}
|
||||
|
||||
c, err := cmd.Toolbox(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s, n, err := c.Download(ctx, src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if dst == "-" {
|
||||
_, err = io.Copy(os.Stdout, s)
|
||||
return err
|
||||
}
|
||||
|
||||
var p progress.Sinker
|
||||
|
||||
if cmd.OutputFlag.TTY {
|
||||
logger := cmd.ProgressLogger("Downloading... ")
|
||||
p = logger
|
||||
defer logger.Wait()
|
||||
}
|
||||
|
||||
return c.ProcessManager.Client().WriteFile(ctx, dst, s, n, p, nil)
|
||||
}
|
||||
47
vendor/github.com/vmware/govmomi/cli/vm/guest/file_attr.go
generated
vendored
Normal file
47
vendor/github.com/vmware/govmomi/cli/vm/guest/file_attr.go
generated
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type FileAttrFlag struct {
|
||||
types.GuestPosixFileAttributes
|
||||
}
|
||||
|
||||
func newFileAttrFlag(ctx context.Context) (*FileAttrFlag, context.Context) {
|
||||
return &FileAttrFlag{}, ctx
|
||||
}
|
||||
|
||||
func (flag *FileAttrFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
f.Var(flags.NewOptionalInt32(&flag.OwnerId), "uid", "User ID")
|
||||
f.Var(flags.NewOptionalInt32(&flag.GroupId), "gid", "Group ID")
|
||||
f.Int64Var(&flag.Permissions, "perm", 0, "File permissions")
|
||||
}
|
||||
|
||||
func (flag *FileAttrFlag) Process(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (flag *FileAttrFlag) Attr() types.BaseGuestFileAttributes {
|
||||
return &flag.GuestPosixFileAttributes
|
||||
}
|
||||
75
vendor/github.com/vmware/govmomi/cli/vm/guest/getenv.go
generated
vendored
Normal file
75
vendor/github.com/vmware/govmomi/cli/vm/guest/getenv.go
generated
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
)
|
||||
|
||||
type getenv struct {
|
||||
*GuestFlag
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("guest.getenv", &getenv{})
|
||||
}
|
||||
|
||||
func (cmd *getenv) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.GuestFlag, ctx = newGuestProcessFlag(ctx)
|
||||
cmd.GuestFlag.Register(ctx, f)
|
||||
}
|
||||
|
||||
func (cmd *getenv) Process(ctx context.Context) error {
|
||||
if err := cmd.GuestFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *getenv) Usage() string {
|
||||
return "[NAME]..."
|
||||
}
|
||||
|
||||
func (cmd *getenv) Description() string {
|
||||
return `Read NAME environment variables from VM.
|
||||
|
||||
Examples:
|
||||
govc guest.getenv -vm $name
|
||||
govc guest.getenv -vm $name HOME`
|
||||
}
|
||||
|
||||
func (cmd *getenv) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
m, err := cmd.ProcessManager()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vars, err := m.ReadEnvironmentVariable(ctx, cmd.Auth(), f.Args())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, v := range vars {
|
||||
fmt.Printf("%s\n", v)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
135
vendor/github.com/vmware/govmomi/cli/vm/guest/guest.go
generated
vendored
Normal file
135
vendor/github.com/vmware/govmomi/cli/vm/guest/guest.go
generated
vendored
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"net/url"
|
||||
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/guest"
|
||||
"github.com/vmware/govmomi/guest/toolbox"
|
||||
"github.com/vmware/govmomi/object"
|
||||
)
|
||||
|
||||
type GuestFlag struct {
|
||||
*flags.ClientFlag
|
||||
*flags.VirtualMachineFlag
|
||||
|
||||
*AuthFlag
|
||||
}
|
||||
|
||||
func newGuestFlag(ctx context.Context) (*GuestFlag, context.Context) {
|
||||
f := &GuestFlag{}
|
||||
f.ClientFlag, ctx = flags.NewClientFlag(ctx)
|
||||
f.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
|
||||
f.AuthFlag, ctx = newAuthFlag(ctx)
|
||||
return f, ctx
|
||||
}
|
||||
|
||||
func newGuestProcessFlag(ctx context.Context) (*GuestFlag, context.Context) {
|
||||
f, gctx := newGuestFlag(ctx)
|
||||
f.proc = true
|
||||
return f, gctx
|
||||
}
|
||||
|
||||
func (flag *GuestFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
flag.ClientFlag.Register(ctx, f)
|
||||
flag.VirtualMachineFlag.Register(ctx, f)
|
||||
flag.AuthFlag.Register(ctx, f)
|
||||
}
|
||||
|
||||
func (flag *GuestFlag) Process(ctx context.Context) error {
|
||||
if err := flag.ClientFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := flag.VirtualMachineFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := flag.AuthFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (flag *GuestFlag) Toolbox(ctx context.Context) (*toolbox.Client, error) {
|
||||
vm, err := flag.VirtualMachine()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, err := flag.Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return toolbox.NewClient(ctx, c, vm, flag.Auth())
|
||||
}
|
||||
|
||||
func (flag *GuestFlag) FileManager() (*guest.FileManager, error) {
|
||||
ctx := context.TODO()
|
||||
c, err := flag.Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vm, err := flag.VirtualMachine()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
o := guest.NewOperationsManager(c, vm.Reference())
|
||||
return o.FileManager(ctx)
|
||||
}
|
||||
|
||||
func (flag *GuestFlag) ProcessManager() (*guest.ProcessManager, error) {
|
||||
ctx := context.TODO()
|
||||
c, err := flag.Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vm, err := flag.VirtualMachine()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
o := guest.NewOperationsManager(c, vm.Reference())
|
||||
return o.ProcessManager(ctx)
|
||||
}
|
||||
|
||||
func (flag *GuestFlag) ParseURL(urlStr string) (*url.URL, error) {
|
||||
c, err := flag.Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.Client.ParseURL(urlStr)
|
||||
}
|
||||
|
||||
func (flag *GuestFlag) VirtualMachine() (*object.VirtualMachine, error) {
|
||||
vm, err := flag.VirtualMachineFlag.VirtualMachine()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if vm == nil {
|
||||
return nil, errors.New("no vm specified")
|
||||
}
|
||||
return vm, nil
|
||||
}
|
||||
70
vendor/github.com/vmware/govmomi/cli/vm/guest/kill.go
generated
vendored
Normal file
70
vendor/github.com/vmware/govmomi/cli/vm/guest/kill.go
generated
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
)
|
||||
|
||||
type kill struct {
|
||||
*GuestFlag
|
||||
|
||||
pids pidSelector
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("guest.kill", &kill{})
|
||||
}
|
||||
|
||||
func (cmd *kill) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.GuestFlag, ctx = newGuestProcessFlag(ctx)
|
||||
cmd.GuestFlag.Register(ctx, f)
|
||||
|
||||
f.Var(&cmd.pids, "p", "Process ID")
|
||||
}
|
||||
|
||||
func (cmd *kill) Process(ctx context.Context) error {
|
||||
if err := cmd.GuestFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *kill) Description() string {
|
||||
return `Kill process ID on VM.
|
||||
|
||||
Examples:
|
||||
govc guest.kill -vm $name -p 12345`
|
||||
}
|
||||
|
||||
func (cmd *kill) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
m, err := cmd.ProcessManager()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, pid := range cmd.pids {
|
||||
if err := m.TerminateProcess(ctx, cmd.Auth(), pid); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
128
vendor/github.com/vmware/govmomi/cli/vm/guest/ls.go
generated
vendored
Normal file
128
vendor/github.com/vmware/govmomi/cli/vm/guest/ls.go
generated
vendored
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/units"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type ls struct {
|
||||
*GuestFlag
|
||||
|
||||
simple bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("guest.ls", &ls{})
|
||||
}
|
||||
|
||||
func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.GuestFlag, ctx = newGuestFlag(ctx)
|
||||
cmd.GuestFlag.Register(ctx, f)
|
||||
|
||||
f.BoolVar(&cmd.simple, "s", false, "Simple path only listing") // sadly we used '-l' for guest login
|
||||
}
|
||||
|
||||
func (cmd *ls) Process(ctx context.Context) error {
|
||||
if err := cmd.GuestFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *ls) Usage() string {
|
||||
return "PATH"
|
||||
}
|
||||
|
||||
func (cmd *ls) Description() string {
|
||||
return `List PATH files in VM.
|
||||
|
||||
Examples:
|
||||
govc guest.ls -vm $name /tmp`
|
||||
}
|
||||
|
||||
func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
m, err := cmd.FileManager()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var offset int32
|
||||
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
|
||||
|
||||
for {
|
||||
info, err := m.ListFiles(ctx, cmd.Auth(), f.Arg(0), offset, 0, f.Arg(1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, f := range info.Files {
|
||||
if cmd.simple {
|
||||
fmt.Fprintln(tw, f.Path)
|
||||
continue
|
||||
}
|
||||
|
||||
var kind byte
|
||||
|
||||
switch types.GuestFileType(f.Type) {
|
||||
case types.GuestFileTypeDirectory:
|
||||
kind = 'd'
|
||||
if f.Size == 0 {
|
||||
f.Size = 4092
|
||||
}
|
||||
case types.GuestFileTypeSymlink:
|
||||
kind = 'l'
|
||||
case types.GuestFileTypeFile:
|
||||
kind = '-'
|
||||
}
|
||||
|
||||
switch x := f.Attributes.(type) {
|
||||
case *types.GuestPosixFileAttributes:
|
||||
perm := os.FileMode(x.Permissions).Perm().String()[1:]
|
||||
fmt.Fprintf(tw, "%c%s\t%d\t%d\t", kind, perm, *x.OwnerId, *x.GroupId)
|
||||
}
|
||||
|
||||
attr := f.Attributes.GetGuestFileAttributes()
|
||||
|
||||
fmt.Fprintf(tw, "%s\t%s\t%s", units.FileSize(f.Size), attr.ModificationTime.Format("Jan 2 15:04 2006"), f.Path)
|
||||
if attr.SymlinkTarget != "" {
|
||||
fmt.Fprintf(tw, " -> %s", attr.SymlinkTarget)
|
||||
}
|
||||
fmt.Fprintln(tw)
|
||||
}
|
||||
|
||||
err = tw.Flush()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if info.Remaining == 0 {
|
||||
break
|
||||
}
|
||||
offset += int32(len(info.Files))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
80
vendor/github.com/vmware/govmomi/cli/vm/guest/mkdir.go
generated
vendored
Normal file
80
vendor/github.com/vmware/govmomi/cli/vm/guest/mkdir.go
generated
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
Copyright (c) 2014-2024 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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/fault"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type mkdir struct {
|
||||
*GuestFlag
|
||||
|
||||
createParents bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("guest.mkdir", &mkdir{})
|
||||
}
|
||||
|
||||
func (cmd *mkdir) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.GuestFlag, ctx = newGuestFlag(ctx)
|
||||
cmd.GuestFlag.Register(ctx, f)
|
||||
|
||||
f.BoolVar(&cmd.createParents, "p", false, "Create intermediate directories as needed")
|
||||
}
|
||||
|
||||
func (cmd *mkdir) Process(ctx context.Context) error {
|
||||
if err := cmd.GuestFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *mkdir) Usage() string {
|
||||
return "PATH"
|
||||
}
|
||||
|
||||
func (cmd *mkdir) Description() string {
|
||||
return `Create directory PATH in VM.
|
||||
|
||||
Examples:
|
||||
govc guest.mkdir -vm $name /tmp/logs
|
||||
govc guest.mkdir -vm $name -p /tmp/logs/foo/bar`
|
||||
}
|
||||
|
||||
func (cmd *mkdir) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
m, err := cmd.FileManager()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = m.MakeDirectory(ctx, cmd.Auth(), f.Arg(0), cmd.createParents)
|
||||
|
||||
// ignore EEXIST if -p flag is given
|
||||
if err != nil && cmd.createParents {
|
||||
if fault.Is(err, &types.FileAlreadyExists{}) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
86
vendor/github.com/vmware/govmomi/cli/vm/guest/mktemp.go
generated
vendored
Normal file
86
vendor/github.com/vmware/govmomi/cli/vm/guest/mktemp.go
generated
vendored
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
)
|
||||
|
||||
type mktemp struct {
|
||||
*GuestFlag
|
||||
|
||||
dir bool
|
||||
path string
|
||||
prefix string
|
||||
suffix string
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("guest.mktemp", &mktemp{})
|
||||
}
|
||||
|
||||
func (cmd *mktemp) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.GuestFlag, ctx = newGuestFlag(ctx)
|
||||
cmd.GuestFlag.Register(ctx, f)
|
||||
|
||||
f.BoolVar(&cmd.dir, "d", false, "Make a directory instead of a file")
|
||||
f.StringVar(&cmd.path, "p", "", "If specified, create relative to this directory")
|
||||
f.StringVar(&cmd.prefix, "t", "", "Prefix")
|
||||
f.StringVar(&cmd.suffix, "s", "", "Suffix")
|
||||
}
|
||||
|
||||
func (cmd *mktemp) Process(ctx context.Context) error {
|
||||
if err := cmd.GuestFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *mktemp) Description() string {
|
||||
return `Create a temporary file or directory in VM.
|
||||
|
||||
Examples:
|
||||
govc guest.mktemp -vm $name
|
||||
govc guest.mktemp -vm $name -d
|
||||
govc guest.mktemp -vm $name -t myprefix
|
||||
govc guest.mktemp -vm $name -p /var/tmp/$USER`
|
||||
}
|
||||
|
||||
func (cmd *mktemp) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
m, err := cmd.FileManager()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mk := m.CreateTemporaryFile
|
||||
if cmd.dir {
|
||||
mk = m.CreateTemporaryDirectory
|
||||
}
|
||||
|
||||
name, err := mk(ctx, cmd.Auth(), cmd.prefix, cmd.suffix, cmd.path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(name)
|
||||
|
||||
return nil
|
||||
}
|
||||
82
vendor/github.com/vmware/govmomi/cli/vm/guest/mv.go
generated
vendored
Normal file
82
vendor/github.com/vmware/govmomi/cli/vm/guest/mv.go
generated
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
Copyright (c) 2017-2024 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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/fault"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type mv struct {
|
||||
*GuestFlag
|
||||
|
||||
noclobber bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("guest.mv", &mv{})
|
||||
}
|
||||
|
||||
func (cmd *mv) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.GuestFlag, ctx = newGuestFlag(ctx)
|
||||
cmd.GuestFlag.Register(ctx, f)
|
||||
|
||||
f.BoolVar(&cmd.noclobber, "n", false, "Do not overwrite an existing file")
|
||||
}
|
||||
|
||||
func (cmd *mv) Process(ctx context.Context) error {
|
||||
if err := cmd.GuestFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *mv) Usage() string {
|
||||
return "SOURCE DEST"
|
||||
}
|
||||
|
||||
func (cmd *mv) Description() string {
|
||||
return `Move (rename) files in VM.
|
||||
|
||||
Examples:
|
||||
govc guest.mv -vm $name /tmp/foo.sh /tmp/bar.sh
|
||||
govc guest.mv -vm $name -n /tmp/baz.sh /tmp/bar.sh`
|
||||
}
|
||||
|
||||
func (cmd *mv) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
m, err := cmd.FileManager()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
src := f.Arg(0)
|
||||
dst := f.Arg(1)
|
||||
|
||||
err = m.MoveFile(ctx, cmd.Auth(), src, dst, !cmd.noclobber)
|
||||
|
||||
if err != nil {
|
||||
if fault.Is(err, &types.NotAFile{}) {
|
||||
err = m.MoveDirectory(ctx, cmd.Auth(), src, dst)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
199
vendor/github.com/vmware/govmomi/cli/vm/guest/ps.go
generated
vendored
Normal file
199
vendor/github.com/vmware/govmomi/cli/vm/guest/ps.go
generated
vendored
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
Copyright (c) 2014-2023 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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type ps struct {
|
||||
*flags.OutputFlag
|
||||
*GuestFlag
|
||||
|
||||
every bool
|
||||
exit bool
|
||||
wait bool
|
||||
|
||||
pids pidSelector
|
||||
uids uidSelector
|
||||
}
|
||||
|
||||
type pidSelector []int64
|
||||
|
||||
func (s *pidSelector) String() string {
|
||||
return fmt.Sprint(*s)
|
||||
}
|
||||
|
||||
func (s *pidSelector) Set(value string) error {
|
||||
v, err := strconv.ParseInt(value, 0, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*s = append(*s, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
type uidSelector map[string]bool
|
||||
|
||||
func (s uidSelector) String() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s uidSelector) Set(value string) error {
|
||||
s[value] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("guest.ps", &ps{})
|
||||
}
|
||||
|
||||
func (cmd *ps) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
|
||||
cmd.OutputFlag.Register(ctx, f)
|
||||
|
||||
cmd.GuestFlag, ctx = newGuestProcessFlag(ctx)
|
||||
cmd.GuestFlag.Register(ctx, f)
|
||||
|
||||
cmd.uids = make(map[string]bool)
|
||||
f.BoolVar(&cmd.every, "e", false, "Select all processes")
|
||||
f.BoolVar(&cmd.exit, "x", false, "Output exit time and code")
|
||||
f.BoolVar(&cmd.wait, "X", false, "Wait for process to exit")
|
||||
f.Var(&cmd.pids, "p", "Select by process ID")
|
||||
f.Var(&cmd.uids, "U", "Select by process UID")
|
||||
}
|
||||
|
||||
func (cmd *ps) Process(ctx context.Context) error {
|
||||
if err := cmd.OutputFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.GuestFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *ps) Description() string {
|
||||
return `List processes in VM.
|
||||
|
||||
By default, unless the '-e', '-p' or '-U' flag is specified, only processes owned
|
||||
by the '-l' flag user are displayed.
|
||||
|
||||
The '-x' and '-X' flags only apply to processes started by vmware-tools,
|
||||
such as those started with the govc guest.start command.
|
||||
|
||||
Examples:
|
||||
govc guest.ps -vm $name
|
||||
govc guest.ps -vm $name -e
|
||||
govc guest.ps -vm $name -p 12345
|
||||
govc guest.ps -vm $name -U root`
|
||||
}
|
||||
|
||||
func running(procs []types.GuestProcessInfo) bool {
|
||||
for _, p := range procs {
|
||||
if p.EndTime == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (cmd *ps) list(ctx context.Context) ([]types.GuestProcessInfo, error) {
|
||||
m, err := cmd.ProcessManager()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
auth := cmd.Auth()
|
||||
|
||||
for {
|
||||
procs, err := m.ListProcesses(ctx, auth, cmd.pids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cmd.wait && running(procs) {
|
||||
<-time.After(time.Second)
|
||||
continue
|
||||
}
|
||||
|
||||
return procs, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (cmd *ps) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
procs, err := cmd.list(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r := &psResult{cmd, procs}
|
||||
|
||||
return cmd.WriteResult(r)
|
||||
}
|
||||
|
||||
type psResult struct {
|
||||
cmd *ps
|
||||
ProcessInfo []types.GuestProcessInfo `json:"processInfo"`
|
||||
}
|
||||
|
||||
func (r *psResult) Write(w io.Writer) error {
|
||||
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
|
||||
|
||||
fmt.Fprintf(tw, "%s\t%s\t%s", "UID", "PID", "STIME")
|
||||
if r.cmd.exit {
|
||||
fmt.Fprintf(tw, "\t%s\t%s", "XTIME", "XCODE")
|
||||
}
|
||||
fmt.Fprint(tw, "\tCMD\n")
|
||||
|
||||
if len(r.cmd.pids) != 0 {
|
||||
r.cmd.every = true
|
||||
}
|
||||
|
||||
if !r.cmd.every && len(r.cmd.uids) == 0 {
|
||||
r.cmd.uids[r.cmd.auth.Username] = true
|
||||
}
|
||||
|
||||
for _, p := range r.ProcessInfo {
|
||||
if r.cmd.every || r.cmd.uids[p.Owner] {
|
||||
fmt.Fprintf(tw, "%s\t%d\t%s", p.Owner, p.Pid, p.StartTime.Format("15:04"))
|
||||
if r.cmd.exit {
|
||||
etime := "-"
|
||||
ecode := "-"
|
||||
if p.EndTime != nil {
|
||||
etime = p.EndTime.Format("15:04")
|
||||
ecode = strconv.Itoa(int(p.ExitCode))
|
||||
}
|
||||
fmt.Fprintf(tw, "\t%s\t%s", etime, ecode)
|
||||
}
|
||||
fmt.Fprintf(tw, "\t%s\n", strings.TrimSpace(p.CmdLine))
|
||||
}
|
||||
}
|
||||
|
||||
return tw.Flush()
|
||||
}
|
||||
64
vendor/github.com/vmware/govmomi/cli/vm/guest/rm.go
generated
vendored
Normal file
64
vendor/github.com/vmware/govmomi/cli/vm/guest/rm.go
generated
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
)
|
||||
|
||||
type rm struct {
|
||||
*GuestFlag
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("guest.rm", &rm{})
|
||||
}
|
||||
|
||||
func (cmd *rm) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.GuestFlag, ctx = newGuestFlag(ctx)
|
||||
cmd.GuestFlag.Register(ctx, f)
|
||||
}
|
||||
|
||||
func (cmd *rm) Process(ctx context.Context) error {
|
||||
if err := cmd.GuestFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *rm) Usage() string {
|
||||
return "PATH"
|
||||
}
|
||||
|
||||
func (cmd *rm) Description() string {
|
||||
return `Remove file PATH in VM.
|
||||
|
||||
Examples:
|
||||
govc guest.rm -vm $name /tmp/foo.log`
|
||||
}
|
||||
|
||||
func (cmd *rm) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
m, err := cmd.FileManager()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return m.DeleteFile(ctx, cmd.Auth(), f.Arg(0))
|
||||
}
|
||||
69
vendor/github.com/vmware/govmomi/cli/vm/guest/rmdir.go
generated
vendored
Normal file
69
vendor/github.com/vmware/govmomi/cli/vm/guest/rmdir.go
generated
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
)
|
||||
|
||||
type rmdir struct {
|
||||
*GuestFlag
|
||||
|
||||
recursive bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("guest.rmdir", &rmdir{})
|
||||
}
|
||||
|
||||
func (cmd *rmdir) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.GuestFlag, ctx = newGuestFlag(ctx)
|
||||
cmd.GuestFlag.Register(ctx, f)
|
||||
|
||||
f.BoolVar(&cmd.recursive, "r", false, "Recursive removal")
|
||||
}
|
||||
|
||||
func (cmd *rmdir) Process(ctx context.Context) error {
|
||||
if err := cmd.GuestFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *rmdir) Usage() string {
|
||||
return "PATH"
|
||||
}
|
||||
|
||||
func (cmd *rmdir) Description() string {
|
||||
return `Remove directory PATH in VM.
|
||||
|
||||
Examples:
|
||||
govc guest.rmdir -vm $name /tmp/empty-dir
|
||||
govc guest.rmdir -vm $name -r /tmp/non-empty-dir`
|
||||
}
|
||||
|
||||
func (cmd *rmdir) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
m, err := cmd.FileManager()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return m.DeleteDirectory(ctx, cmd.Auth(), f.Arg(0), cmd.recursive)
|
||||
}
|
||||
106
vendor/github.com/vmware/govmomi/cli/vm/guest/run.go
generated
vendored
Normal file
106
vendor/github.com/vmware/govmomi/cli/vm/guest/run.go
generated
vendored
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
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 guest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"flag"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
)
|
||||
|
||||
type run struct {
|
||||
*GuestFlag
|
||||
|
||||
data string
|
||||
dir string
|
||||
vars env
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("guest.run", &run{})
|
||||
}
|
||||
|
||||
func (cmd *run) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.GuestFlag, ctx = newGuestProcessFlag(ctx)
|
||||
cmd.GuestFlag.Register(ctx, f)
|
||||
|
||||
f.StringVar(&cmd.data, "d", "", "Input data string. A value of '-' reads from OS stdin")
|
||||
f.StringVar(&cmd.dir, "C", "", "The absolute path of the working directory for the program to start")
|
||||
f.Var(&cmd.vars, "e", "Set environment variables")
|
||||
}
|
||||
|
||||
func (cmd *run) Usage() string {
|
||||
return "PATH [ARG]..."
|
||||
}
|
||||
|
||||
func (cmd *run) Description() string {
|
||||
return `Run program PATH in VM and display output.
|
||||
|
||||
The guest.run command starts a program in the VM with i/o redirected, waits for the process to exit and
|
||||
propagates the exit code to the govc process exit code. Note that stdout and stderr are redirected by default,
|
||||
stdin is only redirected when the '-d' flag is specified.
|
||||
|
||||
Note that vmware-tools requires program PATH to be absolute.
|
||||
If PATH is not absolute and vm guest family is Windows,
|
||||
guest.run changes the command to: 'c:\\Windows\\System32\\cmd.exe /c "PATH [ARG]..."'
|
||||
Otherwise the command is changed to: '/bin/bash -c "PATH [ARG]..."'
|
||||
|
||||
Examples:
|
||||
govc guest.run -vm $name ifconfig
|
||||
govc guest.run -vm $name ifconfig eth0
|
||||
cal | govc guest.run -vm $name -d - cat
|
||||
govc guest.run -vm $name -d "hello $USER" cat
|
||||
govc guest.run -vm $name curl -s :invalid: || echo $? # exit code 6
|
||||
govc guest.run -vm $name -e FOO=bar -e BIZ=baz -C /tmp env
|
||||
govc guest.run -vm $name -l root:mypassword ntpdate -u pool.ntp.org
|
||||
govc guest.run -vm $name powershell C:\\network_refresh.ps1`
|
||||
}
|
||||
|
||||
func (cmd *run) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
if f.NArg() == 0 {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
name := f.Arg(0)
|
||||
|
||||
c, err := cmd.Toolbox(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ecmd := &exec.Cmd{
|
||||
Path: name,
|
||||
Args: f.Args()[1:],
|
||||
Env: cmd.vars,
|
||||
Dir: cmd.dir,
|
||||
Stdout: os.Stdout,
|
||||
Stderr: os.Stderr,
|
||||
}
|
||||
|
||||
switch cmd.data {
|
||||
case "":
|
||||
case "-":
|
||||
ecmd.Stdin = os.Stdin
|
||||
default:
|
||||
ecmd.Stdin = bytes.NewBuffer([]byte(cmd.data))
|
||||
}
|
||||
|
||||
return c.Run(ctx, ecmd)
|
||||
}
|
||||
103
vendor/github.com/vmware/govmomi/cli/vm/guest/start.go
generated
vendored
Normal file
103
vendor/github.com/vmware/govmomi/cli/vm/guest/start.go
generated
vendored
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type start struct {
|
||||
*GuestFlag
|
||||
|
||||
dir string
|
||||
vars env
|
||||
}
|
||||
|
||||
type env []string
|
||||
|
||||
func (e *env) String() string {
|
||||
return fmt.Sprint(*e)
|
||||
}
|
||||
|
||||
func (e *env) Set(value string) error {
|
||||
*e = append(*e, value)
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("guest.start", &start{})
|
||||
}
|
||||
|
||||
func (cmd *start) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.GuestFlag, ctx = newGuestProcessFlag(ctx)
|
||||
cmd.GuestFlag.Register(ctx, f)
|
||||
|
||||
f.StringVar(&cmd.dir, "C", "", "The absolute path of the working directory for the program to start")
|
||||
f.Var(&cmd.vars, "e", "Set environment variable (key=val)")
|
||||
}
|
||||
|
||||
func (cmd *start) Process(ctx context.Context) error {
|
||||
if err := cmd.GuestFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *start) Usage() string {
|
||||
return "PATH [ARG]..."
|
||||
}
|
||||
|
||||
func (cmd *start) Description() string {
|
||||
return `Start program in VM.
|
||||
|
||||
The process can have its status queried with govc guest.ps.
|
||||
When the process completes, its exit code and end time will be available for 5 minutes after completion.
|
||||
|
||||
Examples:
|
||||
govc guest.start -vm $name /bin/mount /dev/hdb1 /data
|
||||
pid=$(govc guest.start -vm $name /bin/long-running-thing)
|
||||
govc guest.ps -vm $name -p $pid -X`
|
||||
}
|
||||
|
||||
func (cmd *start) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
m, err := cmd.ProcessManager()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
spec := types.GuestProgramSpec{
|
||||
ProgramPath: f.Arg(0),
|
||||
Arguments: strings.Join(f.Args()[1:], " "),
|
||||
WorkingDirectory: cmd.dir,
|
||||
EnvVariables: cmd.vars,
|
||||
}
|
||||
|
||||
pid, err := m.StartProgram(ctx, cmd.Auth(), &spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("%d\n", pid)
|
||||
|
||||
return nil
|
||||
}
|
||||
116
vendor/github.com/vmware/govmomi/cli/vm/guest/tools.go
generated
vendored
Normal file
116
vendor/github.com/vmware/govmomi/cli/vm/guest/tools.go
generated
vendored
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/object"
|
||||
)
|
||||
|
||||
type tools struct {
|
||||
*flags.ClientFlag
|
||||
*flags.SearchFlag
|
||||
|
||||
mount bool
|
||||
upgrade bool
|
||||
options string
|
||||
unmount bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.guest.tools", &tools{})
|
||||
}
|
||||
|
||||
func (cmd *tools) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
|
||||
cmd.ClientFlag.Register(ctx, f)
|
||||
|
||||
cmd.SearchFlag, ctx = flags.NewSearchFlag(ctx, flags.SearchVirtualMachines)
|
||||
cmd.SearchFlag.Register(ctx, f)
|
||||
|
||||
f.BoolVar(&cmd.mount, "mount", false, "Mount tools CD installer in the guest")
|
||||
f.BoolVar(&cmd.upgrade, "upgrade", false, "Upgrade tools in the guest")
|
||||
f.StringVar(&cmd.options, "options", "", "Installer options")
|
||||
f.BoolVar(&cmd.unmount, "unmount", false, "Unmount tools CD installer in the guest")
|
||||
}
|
||||
|
||||
func (cmd *tools) Process(ctx context.Context) error {
|
||||
if err := cmd.ClientFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.SearchFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *tools) Usage() string {
|
||||
return "VM..."
|
||||
}
|
||||
|
||||
func (cmd *tools) Description() string {
|
||||
return `Manage guest tools in VM.
|
||||
|
||||
Examples:
|
||||
govc vm.guest.tools -mount VM
|
||||
govc vm.guest.tools -unmount VM
|
||||
govc vm.guest.tools -upgrade -options "opt1 opt2" VM`
|
||||
}
|
||||
|
||||
func (cmd *tools) Upgrade(ctx context.Context, vm *object.VirtualMachine) error {
|
||||
task, err := vm.UpgradeTools(ctx, cmd.options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return task.Wait(ctx)
|
||||
}
|
||||
|
||||
func (cmd *tools) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
vms, err := cmd.VirtualMachines(f.Args())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, vm := range vms {
|
||||
switch {
|
||||
case cmd.mount:
|
||||
err = vm.MountToolsInstaller(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case cmd.upgrade:
|
||||
err = cmd.Upgrade(ctx, vm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case cmd.unmount:
|
||||
err = vm.UnmountToolsInstaller(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return flag.ErrHelp
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
126
vendor/github.com/vmware/govmomi/cli/vm/guest/touch.go
generated
vendored
Normal file
126
vendor/github.com/vmware/govmomi/cli/vm/guest/touch.go
generated
vendored
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
Copyright (c) 2017-2024 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 guest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"flag"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/fault"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type touch struct {
|
||||
*GuestFlag
|
||||
|
||||
nocreate bool
|
||||
atime bool
|
||||
date string
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("guest.touch", &touch{})
|
||||
}
|
||||
|
||||
func (cmd *touch) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.GuestFlag, ctx = newGuestFlag(ctx)
|
||||
cmd.GuestFlag.Register(ctx, f)
|
||||
|
||||
f.BoolVar(&cmd.atime, "a", false, "Change only the access time")
|
||||
f.BoolVar(&cmd.nocreate, "c", false, "Do not create any files")
|
||||
f.StringVar(&cmd.date, "d", "", "Use DATE instead of current time")
|
||||
}
|
||||
|
||||
func (cmd *touch) Process(ctx context.Context) error {
|
||||
if err := cmd.GuestFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *touch) Usage() string {
|
||||
return "FILE"
|
||||
}
|
||||
|
||||
func (cmd *touch) Description() string {
|
||||
return `Change FILE times on VM.
|
||||
|
||||
Examples:
|
||||
govc guest.touch -vm $name /var/log/foo.log
|
||||
govc guest.touch -vm $name -d "$(date -d '1 day ago')" /var/log/foo.log`
|
||||
}
|
||||
|
||||
func (cmd *touch) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
if f.NArg() != 1 {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
m, err := cmd.FileManager()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
name := f.Arg(0)
|
||||
|
||||
var attr types.GuestFileAttributes
|
||||
now := time.Now()
|
||||
|
||||
if cmd.date != "" {
|
||||
now, err = time.Parse(time.UnixDate, cmd.date)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.atime {
|
||||
attr.AccessTime = &now
|
||||
} else {
|
||||
attr.ModificationTime = &now
|
||||
}
|
||||
|
||||
err = m.ChangeFileAttributes(ctx, cmd.Auth(), name, &attr)
|
||||
if err != nil && !cmd.nocreate {
|
||||
if fault.Is(err, &types.FileNotFound{}) {
|
||||
// create a new empty file
|
||||
url, cerr := m.InitiateFileTransferToGuest(ctx, cmd.Auth(), name, &attr, 0, false)
|
||||
if cerr != nil {
|
||||
return cerr
|
||||
}
|
||||
|
||||
u, cerr := cmd.ParseURL(url)
|
||||
if cerr != nil {
|
||||
return cerr
|
||||
}
|
||||
|
||||
c, cerr := cmd.Client()
|
||||
if cerr != nil {
|
||||
return cerr
|
||||
}
|
||||
|
||||
err = c.Client.Upload(ctx, new(bytes.Buffer), u, &soap.DefaultUpload)
|
||||
if err == nil && cmd.date != "" {
|
||||
err = m.ChangeFileAttributes(ctx, cmd.Auth(), name, &attr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
109
vendor/github.com/vmware/govmomi/cli/vm/guest/upload.go
generated
vendored
Normal file
109
vendor/github.com/vmware/govmomi/cli/vm/guest/upload.go
generated
vendored
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
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 guest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
)
|
||||
|
||||
type upload struct {
|
||||
*GuestFlag
|
||||
*FileAttrFlag
|
||||
|
||||
overwrite bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("guest.upload", &upload{})
|
||||
}
|
||||
|
||||
func (cmd *upload) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.GuestFlag, ctx = newGuestFlag(ctx)
|
||||
cmd.GuestFlag.Register(ctx, f)
|
||||
cmd.FileAttrFlag, ctx = newFileAttrFlag(ctx)
|
||||
cmd.FileAttrFlag.Register(ctx, f)
|
||||
|
||||
f.BoolVar(&cmd.overwrite, "f", false, "If set, the guest destination file is clobbered")
|
||||
}
|
||||
|
||||
func (cmd *upload) Usage() string {
|
||||
return "SOURCE DEST"
|
||||
}
|
||||
|
||||
func (cmd *upload) Description() string {
|
||||
return `Copy SOURCE from the local system to DEST in the guest VM.
|
||||
|
||||
If SOURCE name is "-", read source from stdin.
|
||||
|
||||
Examples:
|
||||
govc guest.upload -l user:pass -vm=my-vm ~/.ssh/id_rsa.pub /home/$USER/.ssh/authorized_keys
|
||||
cowsay "have a great day" | govc guest.upload -l user:pass -vm=my-vm - /etc/motd
|
||||
tar -cf- foo/ | govc guest.run -d - tar -C /tmp -xf- # upload a directory`
|
||||
}
|
||||
|
||||
func (cmd *upload) Process(ctx context.Context) error {
|
||||
if err := cmd.GuestFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.FileAttrFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *upload) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
if f.NArg() != 2 {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
c, err := cmd.Toolbox(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
src := f.Arg(0)
|
||||
dst := f.Arg(1)
|
||||
|
||||
p := soap.DefaultUpload
|
||||
|
||||
var r io.Reader = os.Stdin
|
||||
|
||||
if src != "-" {
|
||||
f, err := os.Open(filepath.Clean(src))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
r = f
|
||||
|
||||
if cmd.OutputFlag.TTY {
|
||||
logger := cmd.ProgressLogger("Uploading... ")
|
||||
p.Progress = logger
|
||||
defer logger.Wait()
|
||||
}
|
||||
}
|
||||
|
||||
return c.Upload(ctx, r, dst, p, cmd.Attr(), cmd.overwrite)
|
||||
}
|
||||
361
vendor/github.com/vmware/govmomi/cli/vm/info.go
generated
vendored
Normal file
361
vendor/github.com/vmware/govmomi/cli/vm/info.go
generated
vendored
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
/*
|
||||
Copyright (c) 2014-2023 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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/find"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/units"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type info struct {
|
||||
*flags.ClientFlag
|
||||
*flags.OutputFlag
|
||||
*flags.SearchFlag
|
||||
|
||||
WaitForIP bool
|
||||
General bool
|
||||
ExtraConfig bool
|
||||
Resources bool
|
||||
ToolsConfigInfo bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.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.SearchFlag, ctx = flags.NewSearchFlag(ctx, flags.SearchVirtualMachines)
|
||||
cmd.SearchFlag.Register(ctx, f)
|
||||
|
||||
f.BoolVar(&cmd.WaitForIP, "waitip", false, "Wait for VM to acquire IP address")
|
||||
f.BoolVar(&cmd.General, "g", true, "Show general summary")
|
||||
f.BoolVar(&cmd.ExtraConfig, "e", false, "Show ExtraConfig")
|
||||
f.BoolVar(&cmd.Resources, "r", false, "Show resource summary")
|
||||
f.BoolVar(&cmd.ToolsConfigInfo, "t", false, "Show ToolsConfigInfo")
|
||||
}
|
||||
|
||||
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.SearchFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *info) Usage() string {
|
||||
return `VM...`
|
||||
}
|
||||
|
||||
func (cmd *info) Description() string {
|
||||
return `Display info for VM.
|
||||
|
||||
The '-r' flag displays additional info for CPU, memory and storage usage,
|
||||
along with the VM's Datastores, Networks and PortGroups.
|
||||
|
||||
Examples:
|
||||
govc vm.info $vm
|
||||
govc vm.info -r $vm | grep Network:
|
||||
govc vm.info -json $vm
|
||||
govc find . -type m -runtime.powerState poweredOn | xargs govc vm.info`
|
||||
}
|
||||
|
||||
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
c, err := cmd.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vms, err := cmd.VirtualMachines(f.Args())
|
||||
if err != nil {
|
||||
if _, ok := err.(*find.NotFoundError); ok {
|
||||
// Continue with empty VM slice
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
refs := make([]types.ManagedObjectReference, 0, len(vms))
|
||||
for _, vm := range vms {
|
||||
refs = append(refs, vm.Reference())
|
||||
}
|
||||
|
||||
var res infoResult
|
||||
var props []string
|
||||
|
||||
if cmd.OutputFlag.All() {
|
||||
props = nil // Load everything
|
||||
} else {
|
||||
props = []string{"summary"} // Load summary
|
||||
if cmd.General {
|
||||
props = append(props, "guest.ipAddress")
|
||||
}
|
||||
if cmd.ExtraConfig {
|
||||
props = append(props, "config.extraConfig")
|
||||
}
|
||||
if cmd.Resources {
|
||||
props = append(props, "datastore", "network")
|
||||
}
|
||||
if cmd.ToolsConfigInfo {
|
||||
props = append(props, "config.tools")
|
||||
}
|
||||
}
|
||||
|
||||
pc := property.DefaultCollector(c)
|
||||
if len(refs) != 0 {
|
||||
err = pc.Retrieve(ctx, refs, props, &res.VirtualMachines)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.WaitForIP {
|
||||
for i, vm := range res.VirtualMachines {
|
||||
if vm.Guest == nil || vm.Guest.IpAddress == "" {
|
||||
_, err = vms[i].WaitForIP(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Reload virtual machine object
|
||||
err = pc.RetrieveOne(ctx, vms[i].Reference(), props, &res.VirtualMachines[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !cmd.OutputFlag.All() {
|
||||
res.objects = vms
|
||||
res.cmd = cmd
|
||||
if err = res.collectReferences(pc, ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return cmd.WriteResult(&res)
|
||||
}
|
||||
|
||||
type infoResult struct {
|
||||
VirtualMachines []mo.VirtualMachine `json:"virtualMachines"`
|
||||
objects []*object.VirtualMachine
|
||||
entities map[types.ManagedObjectReference]string
|
||||
cmd *info
|
||||
}
|
||||
|
||||
// collectReferences builds a unique set of MORs to the set of VirtualMachines,
|
||||
// so we can collect properties in a single call for each reference type {host,datastore,network}.
|
||||
func (r *infoResult) collectReferences(pc *property.Collector, ctx context.Context) error {
|
||||
// MOR -> Name map
|
||||
r.entities = make(map[types.ManagedObjectReference]string)
|
||||
|
||||
var host []mo.HostSystem
|
||||
var network []mo.Network
|
||||
var opaque []mo.OpaqueNetwork
|
||||
var dvp []mo.DistributedVirtualPortgroup
|
||||
var datastore []mo.Datastore
|
||||
// Table to drive inflating refs to their mo.* counterparts (dest)
|
||||
// and save() the Name to r.entities w/o using reflection here.
|
||||
// Note that we cannot use a []mo.ManagedEntity here, since mo.Network has its own 'Name' field,
|
||||
// the mo.Network.ManagedEntity.Name field will not be set.
|
||||
vrefs := map[string]*struct {
|
||||
dest interface{}
|
||||
refs []types.ManagedObjectReference
|
||||
save func()
|
||||
}{
|
||||
"HostSystem": {
|
||||
&host, nil, func() {
|
||||
for _, e := range host {
|
||||
r.entities[e.Reference()] = e.Name
|
||||
}
|
||||
},
|
||||
},
|
||||
"Network": {
|
||||
&network, nil, func() {
|
||||
for _, e := range network {
|
||||
r.entities[e.Reference()] = e.Name
|
||||
}
|
||||
},
|
||||
},
|
||||
"OpaqueNetwork": {
|
||||
&opaque, nil, func() {
|
||||
for _, e := range opaque {
|
||||
r.entities[e.Reference()] = e.Name
|
||||
}
|
||||
},
|
||||
},
|
||||
"DistributedVirtualPortgroup": {
|
||||
&dvp, nil, func() {
|
||||
for _, e := range dvp {
|
||||
r.entities[e.Reference()] = e.Name
|
||||
}
|
||||
},
|
||||
},
|
||||
"Datastore": {
|
||||
&datastore, nil, func() {
|
||||
for _, e := range datastore {
|
||||
r.entities[e.Reference()] = e.Name
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
xrefs := make(map[types.ManagedObjectReference]bool)
|
||||
// Add MOR to vrefs[kind].refs avoiding any duplicates.
|
||||
addRef := func(refs ...types.ManagedObjectReference) {
|
||||
for _, ref := range refs {
|
||||
if _, exists := xrefs[ref]; exists {
|
||||
return
|
||||
}
|
||||
xrefs[ref] = true
|
||||
vref := vrefs[ref.Type]
|
||||
vref.refs = append(vref.refs, ref)
|
||||
}
|
||||
}
|
||||
|
||||
for _, vm := range r.VirtualMachines {
|
||||
if r.cmd.General {
|
||||
if ref := vm.Summary.Runtime.Host; ref != nil {
|
||||
addRef(*ref)
|
||||
}
|
||||
}
|
||||
|
||||
if r.cmd.Resources {
|
||||
addRef(vm.Datastore...)
|
||||
addRef(vm.Network...)
|
||||
}
|
||||
}
|
||||
|
||||
for _, vref := range vrefs {
|
||||
if vref.refs == nil {
|
||||
continue
|
||||
}
|
||||
err := pc.Retrieve(ctx, vref.refs, []string{"name"}, vref.dest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vref.save()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *infoResult) entityNames(refs []types.ManagedObjectReference) string {
|
||||
var names []string
|
||||
for _, ref := range refs {
|
||||
names = append(names, r.entities[ref])
|
||||
}
|
||||
return strings.Join(names, ", ")
|
||||
}
|
||||
|
||||
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.VirtualMachine, len(r.VirtualMachines))
|
||||
for _, o := range r.VirtualMachines {
|
||||
objects[o.Reference()] = o
|
||||
}
|
||||
|
||||
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
|
||||
|
||||
for _, o := range r.objects {
|
||||
vm := objects[o.Reference()]
|
||||
s := vm.Summary
|
||||
|
||||
fmt.Fprintf(tw, "Name:\t%s\n", s.Config.Name)
|
||||
|
||||
if r.cmd.General {
|
||||
hostName := "<unavailable>"
|
||||
|
||||
if href := vm.Summary.Runtime.Host; href != nil {
|
||||
if name, ok := r.entities[*href]; ok {
|
||||
hostName = name
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(tw, " Path:\t%s\n", o.InventoryPath)
|
||||
fmt.Fprintf(tw, " UUID:\t%s\n", s.Config.Uuid)
|
||||
fmt.Fprintf(tw, " Guest name:\t%s\n", s.Config.GuestFullName)
|
||||
fmt.Fprintf(tw, " Memory:\t%dMB\n", s.Config.MemorySizeMB)
|
||||
fmt.Fprintf(tw, " CPU:\t%d vCPU(s)\n", s.Config.NumCpu)
|
||||
fmt.Fprintf(tw, " Power state:\t%s\n", s.Runtime.PowerState)
|
||||
fmt.Fprintf(tw, " Boot time:\t%s\n", s.Runtime.BootTime)
|
||||
fmt.Fprintf(tw, " IP address:\t%s\n", s.Guest.IpAddress)
|
||||
fmt.Fprintf(tw, " Host:\t%s\n", hostName)
|
||||
}
|
||||
|
||||
if r.cmd.Resources {
|
||||
if s.Storage == nil {
|
||||
s.Storage = new(types.VirtualMachineStorageSummary)
|
||||
}
|
||||
fmt.Fprintf(tw, " CPU usage:\t%dMHz\n", s.QuickStats.OverallCpuUsage)
|
||||
fmt.Fprintf(tw, " Host memory usage:\t%dMB\n", s.QuickStats.HostMemoryUsage)
|
||||
fmt.Fprintf(tw, " Guest memory usage:\t%dMB\n", s.QuickStats.GuestMemoryUsage)
|
||||
fmt.Fprintf(tw, " Storage uncommitted:\t%s\n", units.ByteSize(s.Storage.Uncommitted))
|
||||
fmt.Fprintf(tw, " Storage committed:\t%s\n", units.ByteSize(s.Storage.Committed))
|
||||
fmt.Fprintf(tw, " Storage unshared:\t%s\n", units.ByteSize(s.Storage.Unshared))
|
||||
fmt.Fprintf(tw, " Storage:\t%s\n", r.entityNames(vm.Datastore))
|
||||
fmt.Fprintf(tw, " Network:\t%s\n", r.entityNames(vm.Network))
|
||||
}
|
||||
|
||||
if r.cmd.ExtraConfig {
|
||||
fmt.Fprintf(tw, " ExtraConfig:\n")
|
||||
for _, v := range vm.Config.ExtraConfig {
|
||||
fmt.Fprintf(tw, " %s:\t%s\n", v.GetOptionValue().Key, v.GetOptionValue().Value)
|
||||
}
|
||||
}
|
||||
|
||||
if r.cmd.ToolsConfigInfo {
|
||||
t := vm.Config.Tools
|
||||
fmt.Fprintf(tw, " ToolsConfigInfo:\n")
|
||||
fmt.Fprintf(tw, " ToolsVersion:\t%d\n", t.ToolsVersion)
|
||||
fmt.Fprintf(tw, " AfterPowerOn:\t%s\n", flags.NewOptionalBool(&t.AfterPowerOn).String())
|
||||
fmt.Fprintf(tw, " AfterResume:\t%s\n", flags.NewOptionalBool(&t.AfterResume).String())
|
||||
fmt.Fprintf(tw, " BeforeGuestStandby:\t%s\n", flags.NewOptionalBool(&t.BeforeGuestStandby).String())
|
||||
fmt.Fprintf(tw, " BeforeGuestShutdown:\t%s\n", flags.NewOptionalBool(&t.BeforeGuestShutdown).String())
|
||||
fmt.Fprintf(tw, " BeforeGuestReboot:\t%s\n", flags.NewOptionalBool(&t.BeforeGuestReboot).String())
|
||||
fmt.Fprintf(tw, " ToolsUpgradePolicy:\t%s\n", t.ToolsUpgradePolicy)
|
||||
fmt.Fprintf(tw, " PendingCustomization:\t%s\n", t.PendingCustomization)
|
||||
fmt.Fprintf(tw, " SyncTimeWithHost:\t%s\n", flags.NewOptionalBool(&t.SyncTimeWithHost).String())
|
||||
}
|
||||
}
|
||||
|
||||
return tw.Flush()
|
||||
}
|
||||
250
vendor/github.com/vmware/govmomi/cli/vm/instantclone.go
generated
vendored
Normal file
250
vendor/github.com/vmware/govmomi/cli/vm/instantclone.go
generated
vendored
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type instantclone struct {
|
||||
*flags.ClientFlag
|
||||
*flags.DatacenterFlag
|
||||
*flags.DatastoreFlag
|
||||
*flags.ResourcePoolFlag
|
||||
*flags.NetworkFlag
|
||||
*flags.FolderFlag
|
||||
*flags.VirtualMachineFlag
|
||||
|
||||
name string
|
||||
extraConfig extraConfig
|
||||
|
||||
Client *vim25.Client
|
||||
Datacenter *object.Datacenter
|
||||
Datastore *object.Datastore
|
||||
ResourcePool *object.ResourcePool
|
||||
Folder *object.Folder
|
||||
VirtualMachine *object.VirtualMachine
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.instantclone", &instantclone{})
|
||||
}
|
||||
|
||||
func (cmd *instantclone) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
|
||||
cmd.ClientFlag.Register(ctx, f)
|
||||
|
||||
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
|
||||
cmd.DatacenterFlag.Register(ctx, f)
|
||||
|
||||
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
|
||||
cmd.DatastoreFlag.Register(ctx, f)
|
||||
|
||||
cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx)
|
||||
cmd.ResourcePoolFlag.Register(ctx, f)
|
||||
|
||||
cmd.NetworkFlag, ctx = flags.NewNetworkFlag(ctx)
|
||||
cmd.NetworkFlag.Register(ctx, f)
|
||||
|
||||
cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx)
|
||||
cmd.FolderFlag.Register(ctx, f)
|
||||
|
||||
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
|
||||
cmd.VirtualMachineFlag.Register(ctx, f)
|
||||
|
||||
f.Var(&cmd.extraConfig, "e", "ExtraConfig. <key>=<value>")
|
||||
}
|
||||
|
||||
func (cmd *instantclone) Usage() string {
|
||||
return "NAME"
|
||||
}
|
||||
|
||||
func (cmd *instantclone) Description() string {
|
||||
return `Instant Clone VM to NAME.
|
||||
|
||||
Examples:
|
||||
govc vm.instantclone -vm source-vm new-vm
|
||||
# Configure ExtraConfig variables on a guest VM:
|
||||
govc vm.instantclone -vm source-vm -e guestinfo.ipaddress=192.168.0.1 -e guestinfo.netmask=255.255.255.0 new-vm
|
||||
# Read the variable set above inside the guest:
|
||||
vmware-rpctool "info-get guestinfo.ipaddress"
|
||||
vmware-rpctool "info-get guestinfo.netmask"`
|
||||
}
|
||||
|
||||
func (cmd *instantclone) Process(ctx context.Context) error {
|
||||
if err := cmd.ClientFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.ResourcePoolFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.NetworkFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.FolderFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *instantclone) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
var err error
|
||||
|
||||
if len(f.Args()) != 1 {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
cmd.name = f.Arg(0)
|
||||
if cmd.name == "" {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
cmd.Client, err = cmd.ClientFlag.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Datacenter, err = cmd.DatacenterFlag.Datacenter()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Datastore, err = cmd.DatastoreFlag.Datastore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Folder, err = cmd.FolderFlag.Folder()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.ResourcePool, err = cmd.ResourcePoolFlag.ResourcePool()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.VirtualMachine, err = cmd.VirtualMachineFlag.VirtualMachine()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.VirtualMachine == nil {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
_, err = cmd.instantcloneVM(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *instantclone) instantcloneVM(ctx context.Context) (*object.VirtualMachine, error) {
|
||||
relocateSpec := types.VirtualMachineRelocateSpec{}
|
||||
|
||||
if cmd.NetworkFlag.IsSet() {
|
||||
devices, err := cmd.VirtualMachine.Device(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// prepare virtual device config spec for network card
|
||||
configSpecs := []types.BaseVirtualDeviceConfigSpec{}
|
||||
|
||||
op := types.VirtualDeviceConfigSpecOperationAdd
|
||||
card, derr := cmd.NetworkFlag.Device()
|
||||
if derr != nil {
|
||||
return nil, derr
|
||||
}
|
||||
// search for the first network card of the source
|
||||
for _, device := range devices {
|
||||
if _, ok := device.(types.BaseVirtualEthernetCard); ok {
|
||||
op = types.VirtualDeviceConfigSpecOperationEdit
|
||||
// set new backing info
|
||||
cmd.NetworkFlag.Change(device, card)
|
||||
card = device
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
configSpecs = append(configSpecs, &types.VirtualDeviceConfigSpec{
|
||||
Operation: op,
|
||||
Device: card,
|
||||
})
|
||||
|
||||
relocateSpec.DeviceChange = configSpecs
|
||||
}
|
||||
|
||||
if cmd.FolderFlag.IsSet() {
|
||||
folderref := cmd.Folder.Reference()
|
||||
relocateSpec.Folder = &folderref
|
||||
}
|
||||
|
||||
if cmd.ResourcePoolFlag.IsSet() {
|
||||
poolref := cmd.ResourcePool.Reference()
|
||||
relocateSpec.Pool = &poolref
|
||||
}
|
||||
|
||||
if cmd.DatastoreFlag.IsSet() {
|
||||
datastoreref := cmd.Datastore.Reference()
|
||||
relocateSpec.Datastore = &datastoreref
|
||||
}
|
||||
|
||||
instantcloneSpec := &types.VirtualMachineInstantCloneSpec{
|
||||
Name: cmd.name,
|
||||
Location: relocateSpec,
|
||||
}
|
||||
|
||||
if len(cmd.extraConfig) > 0 {
|
||||
instantcloneSpec.Config = cmd.extraConfig
|
||||
}
|
||||
|
||||
task, err := cmd.VirtualMachine.InstantClone(ctx, *instantcloneSpec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logger := cmd.ProgressLogger(fmt.Sprintf("Instant Cloning %s to %s...", cmd.VirtualMachine.InventoryPath, cmd.name))
|
||||
defer logger.Wait()
|
||||
|
||||
info, err := task.WaitForResult(ctx, logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return object.NewVirtualMachine(cmd.Client, info.Result.(types.ManagedObjectReference)), nil
|
||||
}
|
||||
192
vendor/github.com/vmware/govmomi/cli/vm/ip.go
generated
vendored
Normal file
192
vendor/github.com/vmware/govmomi/cli/vm/ip.go
generated
vendored
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
Copyright (c) 2014-2023 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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/esx"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/object"
|
||||
)
|
||||
|
||||
type ip struct {
|
||||
*flags.OutputFlag
|
||||
*flags.SearchFlag
|
||||
|
||||
esx bool
|
||||
all bool
|
||||
v4 bool
|
||||
wait time.Duration
|
||||
nic string
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.ip", &ip{})
|
||||
}
|
||||
|
||||
func (cmd *ip) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
|
||||
cmd.OutputFlag.Register(ctx, f)
|
||||
|
||||
cmd.SearchFlag, ctx = flags.NewSearchFlag(ctx, flags.SearchVirtualMachines)
|
||||
cmd.SearchFlag.Register(ctx, f)
|
||||
|
||||
f.BoolVar(&cmd.esx, "esxcli", false, "Use esxcli instead of guest tools")
|
||||
f.BoolVar(&cmd.all, "a", false, "Wait for an IP address on all NICs")
|
||||
f.StringVar(&cmd.nic, "n", "", "Wait for IP address on NIC, specified by device name or MAC")
|
||||
f.BoolVar(&cmd.v4, "v4", false, "Only report IPv4 addresses")
|
||||
f.DurationVar(&cmd.wait, "wait", time.Hour, "Wait time for the VM obtain an IP address")
|
||||
}
|
||||
|
||||
func (cmd *ip) Usage() string {
|
||||
return "VM..."
|
||||
}
|
||||
|
||||
func (cmd *ip) Description() string {
|
||||
return `List IPs for VM.
|
||||
|
||||
By default the vm.ip command depends on vmware-tools to report the 'guest.ipAddress' field and will
|
||||
wait until it has done so. This value can also be obtained using:
|
||||
|
||||
govc vm.info -json $vm | jq -r .virtualMachines[].guest.ipAddress
|
||||
|
||||
When given the '-a' flag, only IP addresses for which there is a corresponding virtual nic are listed.
|
||||
If there are multiple nics, the listed addresses will be comma delimited. The '-a' flag depends on
|
||||
vmware-tools to report the 'guest.net' field and will wait until it has done so for all nics.
|
||||
Note that this list includes IPv6 addresses if any, use '-v4' to filter them out. IP addresses reported
|
||||
by tools for which there is no virtual nic are not included, for example that of the 'docker0' interface.
|
||||
|
||||
These values can also be obtained using:
|
||||
|
||||
govc vm.info -json $vm | jq -r .virtualMachines[].guest.net[].ipConfig.ipAddress[].ipAddress
|
||||
|
||||
When given the '-n' flag, filters '-a' behavior to the nic specified by MAC address or device name.
|
||||
|
||||
The 'esxcli' flag does not require vmware-tools to be installed, but does require the ESX host to
|
||||
have the /Net/GuestIPHack setting enabled.
|
||||
|
||||
The 'wait' flag default to 1hr (original default was infinite). If a VM does not obtain an IP within
|
||||
the wait time, the command will still exit with status 0.
|
||||
|
||||
Examples:
|
||||
govc vm.ip $vm
|
||||
govc vm.ip -wait 5m $vm
|
||||
govc vm.ip -a -v4 $vm
|
||||
govc vm.ip -n 00:0c:29:57:7b:c3 $vm
|
||||
govc vm.ip -n ethernet-0 $vm
|
||||
govc host.esxcli system settings advanced set -o /Net/GuestIPHack -i 1
|
||||
govc vm.ip -esxcli $vm`
|
||||
}
|
||||
|
||||
func (cmd *ip) Process(ctx context.Context) error {
|
||||
if err := cmd.OutputFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.SearchFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *ip) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
c, err := cmd.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vms, err := cmd.VirtualMachines(f.Args())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var get func(*object.VirtualMachine, context.Context) (string, error)
|
||||
|
||||
if cmd.esx {
|
||||
get = func(vm *object.VirtualMachine, deadline context.Context) (string, error) {
|
||||
guest := esx.NewGuestInfo(c)
|
||||
|
||||
ticker := time.NewTicker(time.Millisecond * 500)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
ip, err := guest.IpAddress(ctx, vm)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if ip != "0.0.0.0" {
|
||||
return ip, nil
|
||||
}
|
||||
case <-deadline.Done():
|
||||
return "", nil
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var hwaddr []string
|
||||
if cmd.nic != "" {
|
||||
hwaddr = strings.Split(cmd.nic, ",")
|
||||
}
|
||||
|
||||
get = func(vm *object.VirtualMachine, deadline context.Context) (string, error) {
|
||||
if cmd.all || hwaddr != nil {
|
||||
macs, err := vm.WaitForNetIP(deadline, cmd.v4, hwaddr...)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var ips []string
|
||||
for _, addrs := range macs {
|
||||
ips = append(ips, addrs...)
|
||||
}
|
||||
return strings.Join(ips, ","), nil
|
||||
}
|
||||
return vm.WaitForIP(deadline, cmd.v4)
|
||||
}
|
||||
}
|
||||
|
||||
for _, vm := range vms {
|
||||
deadline, cancel := context.WithDeadline(ctx, time.Now().Add(cmd.wait))
|
||||
|
||||
ip, err := get(vm, deadline)
|
||||
if err != nil {
|
||||
if deadline.Err() != context.DeadlineExceeded {
|
||||
cancel()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
cancel()
|
||||
|
||||
if ip == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// TODO(PN): Display inventory path to VM
|
||||
fmt.Fprintf(cmd, "%s\n", ip)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
710
vendor/github.com/vmware/govmomi/cli/vm/keystrokes.go
generated
vendored
Normal file
710
vendor/github.com/vmware/govmomi/cli/vm/keystrokes.go
generated
vendored
Normal file
|
|
@ -0,0 +1,710 @@
|
|||
/*
|
||||
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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type hidKey struct {
|
||||
Code int32
|
||||
ShiftPressed bool
|
||||
}
|
||||
|
||||
// stolen from
|
||||
// https://gist.github.com/MightyPork/6da26e382a7ad91b5496ee55fdc73db2#file-usb_hid_keys-h-L110
|
||||
const (
|
||||
KEY_MOD_LCTRL = 0x01
|
||||
KEY_MOD_LSHIFT = 0x02
|
||||
KEY_MOD_LALT = 0x04
|
||||
KEY_MOD_LMETA = 0x08
|
||||
KEY_MOD_RCTRL = 0x10
|
||||
KEY_MOD_RSHIFT = 0x20
|
||||
KEY_MOD_RALT = 0x40
|
||||
KEY_MOD_RMETA = 0x80
|
||||
KEY_NONE = 0x00
|
||||
KEY_ERR_OVF = 0x01
|
||||
KEY_A = 0x04
|
||||
KEY_B = 0x05
|
||||
KEY_C = 0x06
|
||||
KEY_D = 0x07
|
||||
KEY_E = 0x08
|
||||
KEY_F = 0x09
|
||||
KEY_G = 0x0a
|
||||
KEY_H = 0x0b
|
||||
KEY_I = 0x0c
|
||||
KEY_J = 0x0d
|
||||
KEY_K = 0x0e
|
||||
KEY_L = 0x0f
|
||||
KEY_M = 0x10
|
||||
KEY_N = 0x11
|
||||
KEY_O = 0x12
|
||||
KEY_P = 0x13
|
||||
KEY_Q = 0x14
|
||||
KEY_R = 0x15
|
||||
KEY_S = 0x16
|
||||
KEY_T = 0x17
|
||||
KEY_U = 0x18
|
||||
KEY_V = 0x19
|
||||
KEY_W = 0x1a
|
||||
KEY_X = 0x1b
|
||||
KEY_Y = 0x1c
|
||||
KEY_Z = 0x1d
|
||||
KEY_1 = 0x1e
|
||||
KEY_2 = 0x1f
|
||||
KEY_3 = 0x20
|
||||
KEY_4 = 0x21
|
||||
KEY_5 = 0x22
|
||||
KEY_6 = 0x23
|
||||
KEY_7 = 0x24
|
||||
KEY_8 = 0x25
|
||||
KEY_9 = 0x26
|
||||
KEY_0 = 0x27
|
||||
KEY_ENTER = 0x28
|
||||
KEY_ESC = 0x29
|
||||
KEY_BACKSPACE = 0x2a
|
||||
KEY_TAB = 0x2b
|
||||
KEY_SPACE = 0x2c
|
||||
KEY_MINUS = 0x2d
|
||||
KEY_EQUAL = 0x2e
|
||||
KEY_LEFTBRACE = 0x2f
|
||||
KEY_RIGHTBRACE = 0x30
|
||||
KEY_BACKSLASH = 0x31
|
||||
KEY_HASHTILDE = 0x32
|
||||
KEY_SEMICOLON = 0x33
|
||||
KEY_APOSTROPHE = 0x34
|
||||
KEY_GRAVE = 0x35
|
||||
KEY_COMMA = 0x36
|
||||
KEY_DOT = 0x37
|
||||
KEY_SLASH = 0x38
|
||||
KEY_CAPSLOCK = 0x39
|
||||
KEY_F1 = 0x3a
|
||||
KEY_F2 = 0x3b
|
||||
KEY_F3 = 0x3c
|
||||
KEY_F4 = 0x3d
|
||||
KEY_F5 = 0x3e
|
||||
KEY_F6 = 0x3f
|
||||
KEY_F7 = 0x40
|
||||
KEY_F8 = 0x41
|
||||
KEY_F9 = 0x42
|
||||
KEY_F10 = 0x43
|
||||
KEY_F11 = 0x44
|
||||
KEY_F12 = 0x45
|
||||
KEY_SYSRQ = 0x46
|
||||
KEY_SCROLLLOCK = 0x47
|
||||
KEY_PAUSE = 0x48
|
||||
KEY_INSERT = 0x49
|
||||
KEY_HOME = 0x4a
|
||||
KEY_PAGEUP = 0x4b
|
||||
KEY_DELETE = 0x4c
|
||||
KEY_END = 0x4d
|
||||
KEY_PAGEDOWN = 0x4e
|
||||
KEY_RIGHT = 0x4f
|
||||
KEY_LEFT = 0x50
|
||||
KEY_DOWN = 0x51
|
||||
KEY_UP = 0x52
|
||||
KEY_NUMLOCK = 0x53
|
||||
KEY_KPSLASH = 0x54
|
||||
KEY_KPASTERISK = 0x55
|
||||
KEY_KPMINUS = 0x56
|
||||
KEY_KPPLUS = 0x57
|
||||
KEY_KPENTER = 0x58
|
||||
KEY_KP1 = 0x59
|
||||
KEY_KP2 = 0x5a
|
||||
KEY_KP3 = 0x5b
|
||||
KEY_KP4 = 0x5c
|
||||
KEY_KP5 = 0x5d
|
||||
KEY_KP6 = 0x5e
|
||||
KEY_KP7 = 0x5f
|
||||
KEY_KP8 = 0x60
|
||||
KEY_KP9 = 0x61
|
||||
KEY_KP0 = 0x62
|
||||
KEY_KPDOT = 0x63
|
||||
KEY_102ND = 0x64
|
||||
KEY_COMPOSE = 0x65
|
||||
KEY_POWER = 0x66
|
||||
KEY_KPEQUAL = 0x67
|
||||
KEY_F13 = 0x68
|
||||
KEY_F14 = 0x69
|
||||
KEY_F15 = 0x6a
|
||||
KEY_F16 = 0x6b
|
||||
KEY_F17 = 0x6c
|
||||
KEY_F18 = 0x6d
|
||||
KEY_F19 = 0x6e
|
||||
KEY_F20 = 0x6f
|
||||
KEY_F21 = 0x70
|
||||
KEY_F22 = 0x71
|
||||
KEY_F23 = 0x72
|
||||
KEY_F24 = 0x73
|
||||
KEY_OPEN = 0x74
|
||||
KEY_HELP = 0x75
|
||||
KEY_PROPS = 0x76
|
||||
KEY_FRONT = 0x77
|
||||
KEY_STOP = 0x78
|
||||
KEY_AGAIN = 0x79
|
||||
KEY_UNDO = 0x7a
|
||||
KEY_CUT = 0x7b
|
||||
KEY_COPY = 0x7c
|
||||
KEY_PASTE = 0x7d
|
||||
KEY_FIND = 0x7e
|
||||
KEY_MUTE = 0x7f
|
||||
KEY_VOLUMEUP = 0x80
|
||||
KEY_VOLUMEDOWN = 0x81
|
||||
KEY_KPCOMMA = 0x85
|
||||
KEY_RO = 0x87
|
||||
KEY_KATAKANAHIRAGANA = 0x88
|
||||
KEY_YEN = 0x89
|
||||
KEY_HENKAN = 0x8a
|
||||
KEY_MUHENKAN = 0x8b
|
||||
KEY_KPJPCOMMA = 0x8c
|
||||
KEY_HANGEUL = 0x90
|
||||
KEY_HANJA = 0x91
|
||||
KEY_KATAKANA = 0x92
|
||||
KEY_HIRAGANA = 0x93
|
||||
KEY_ZENKAKUHANKAKU = 0x94
|
||||
KEY_KPLEFTPAREN = 0xb6
|
||||
KEY_KPRIGHTPAREN = 0xb7
|
||||
KEY_LEFTCTRL = 0xe0
|
||||
KEY_LEFTSHIFT = 0xe1
|
||||
KEY_LEFTALT = 0xe2
|
||||
KEY_LEFTMETA = 0xe3
|
||||
KEY_RIGHTCTRL = 0xe4
|
||||
KEY_RIGHTSHIFT = 0xe5
|
||||
KEY_RIGHTALT = 0xe6
|
||||
KEY_RIGHTMETA = 0xe7
|
||||
KEY_MEDIA_PLAYPAUSE = 0xe8
|
||||
KEY_MEDIA_STOPCD = 0xe9
|
||||
KEY_MEDIA_PREVIOUSSONG = 0xea
|
||||
KEY_MEDIA_NEXTSONG = 0xeb
|
||||
KEY_MEDIA_EJECTCD = 0xec
|
||||
KEY_MEDIA_VOLUMEUP = 0xed
|
||||
KEY_MEDIA_VOLUMEDOWN = 0xee
|
||||
KEY_MEDIA_MUTE = 0xef
|
||||
KEY_MEDIA_WWW = 0xf0
|
||||
KEY_MEDIA_BACK = 0xf1
|
||||
KEY_MEDIA_FORWARD = 0xf2
|
||||
KEY_MEDIA_STOP = 0xf3
|
||||
KEY_MEDIA_FIND = 0xf4
|
||||
KEY_MEDIA_SCROLLUP = 0xf5
|
||||
KEY_MEDIA_SCROLLDOWN = 0xf6
|
||||
KEY_MEDIA_EDIT = 0xf7
|
||||
KEY_MEDIA_SLEEP = 0xf8
|
||||
KEY_MEDIA_COFFEE = 0xf9
|
||||
KEY_MEDIA_REFRESH = 0xfa
|
||||
KEY_MEDIA_CALC = 0xfb
|
||||
)
|
||||
|
||||
var hidKeyMap = map[string]int32{
|
||||
"KEY_MOD_LCTRL": KEY_MOD_LCTRL,
|
||||
"KEY_MOD_LSHIFT": KEY_MOD_LSHIFT,
|
||||
"KEY_MOD_LALT": KEY_MOD_LALT,
|
||||
"KEY_MOD_LMETA": KEY_MOD_LMETA,
|
||||
"KEY_MOD_RCTRL": KEY_MOD_RCTRL,
|
||||
"KEY_MOD_RSHIFT": KEY_MOD_RSHIFT,
|
||||
"KEY_MOD_RALT": KEY_MOD_RALT,
|
||||
"KEY_MOD_RMETA": KEY_MOD_RMETA,
|
||||
"KEY_NONE": KEY_NONE,
|
||||
"KEY_ERR_OVF": KEY_ERR_OVF,
|
||||
"KEY_A": KEY_A,
|
||||
"KEY_B": KEY_B,
|
||||
"KEY_C": KEY_C,
|
||||
"KEY_D": KEY_D,
|
||||
"KEY_E": KEY_E,
|
||||
"KEY_F": KEY_F,
|
||||
"KEY_G": KEY_G,
|
||||
"KEY_H": KEY_H,
|
||||
"KEY_I": KEY_I,
|
||||
"KEY_J": KEY_J,
|
||||
"KEY_K": KEY_K,
|
||||
"KEY_L": KEY_L,
|
||||
"KEY_M": KEY_M,
|
||||
"KEY_N": KEY_N,
|
||||
"KEY_O": KEY_O,
|
||||
"KEY_P": KEY_P,
|
||||
"KEY_Q": KEY_Q,
|
||||
"KEY_R": KEY_R,
|
||||
"KEY_S": KEY_S,
|
||||
"KEY_T": KEY_T,
|
||||
"KEY_U": KEY_U,
|
||||
"KEY_V": KEY_V,
|
||||
"KEY_W": KEY_W,
|
||||
"KEY_X": KEY_X,
|
||||
"KEY_Y": KEY_Y,
|
||||
"KEY_Z": KEY_Z,
|
||||
"KEY_1": KEY_1,
|
||||
"KEY_2": KEY_2,
|
||||
"KEY_3": KEY_3,
|
||||
"KEY_4": KEY_4,
|
||||
"KEY_5": KEY_5,
|
||||
"KEY_6": KEY_6,
|
||||
"KEY_7": KEY_7,
|
||||
"KEY_8": KEY_8,
|
||||
"KEY_9": KEY_9,
|
||||
"KEY_0": KEY_0,
|
||||
"KEY_ENTER": KEY_ENTER,
|
||||
"KEY_ESC": KEY_ESC,
|
||||
"KEY_BACKSPACE": KEY_BACKSPACE,
|
||||
"KEY_TAB": KEY_TAB,
|
||||
"KEY_SPACE": KEY_SPACE,
|
||||
"KEY_MINUS": KEY_MINUS,
|
||||
"KEY_EQUAL": KEY_EQUAL,
|
||||
"KEY_LEFTBRACE": KEY_LEFTBRACE,
|
||||
"KEY_RIGHTBRACE": KEY_RIGHTBRACE,
|
||||
"KEY_BACKSLASH": KEY_BACKSLASH,
|
||||
"KEY_HASHTILDE": KEY_HASHTILDE,
|
||||
"KEY_SEMICOLON": KEY_SEMICOLON,
|
||||
"KEY_APOSTROPHE": KEY_APOSTROPHE,
|
||||
"KEY_GRAVE": KEY_GRAVE,
|
||||
"KEY_COMMA": KEY_COMMA,
|
||||
"KEY_DOT": KEY_DOT,
|
||||
"KEY_SLASH": KEY_SLASH,
|
||||
"KEY_CAPSLOCK": KEY_CAPSLOCK,
|
||||
"KEY_F1": KEY_F1,
|
||||
"KEY_F2": KEY_F2,
|
||||
"KEY_F3": KEY_F3,
|
||||
"KEY_F4": KEY_F4,
|
||||
"KEY_F5": KEY_F5,
|
||||
"KEY_F6": KEY_F6,
|
||||
"KEY_F7": KEY_F7,
|
||||
"KEY_F8": KEY_F8,
|
||||
"KEY_F9": KEY_F9,
|
||||
"KEY_F10": KEY_F10,
|
||||
"KEY_F11": KEY_F11,
|
||||
"KEY_F12": KEY_F12,
|
||||
"KEY_SYSRQ": KEY_SYSRQ,
|
||||
"KEY_SCROLLLOCK": KEY_SCROLLLOCK,
|
||||
"KEY_PAUSE": KEY_PAUSE,
|
||||
"KEY_INSERT": KEY_INSERT,
|
||||
"KEY_HOME": KEY_HOME,
|
||||
"KEY_PAGEUP": KEY_PAGEUP,
|
||||
"KEY_DELETE": KEY_DELETE,
|
||||
"KEY_END": KEY_END,
|
||||
"KEY_PAGEDOWN": KEY_PAGEDOWN,
|
||||
"KEY_RIGHT": KEY_RIGHT,
|
||||
"KEY_LEFT": KEY_LEFT,
|
||||
"KEY_DOWN": KEY_DOWN,
|
||||
"KEY_UP": KEY_UP,
|
||||
"KEY_NUMLOCK": KEY_NUMLOCK,
|
||||
"KEY_KPSLASH": KEY_KPSLASH,
|
||||
"KEY_KPASTERISK": KEY_KPASTERISK,
|
||||
"KEY_KPMINUS": KEY_KPMINUS,
|
||||
"KEY_KPPLUS": KEY_KPPLUS,
|
||||
"KEY_KPENTER": KEY_KPENTER,
|
||||
"KEY_KP1": KEY_KP1,
|
||||
"KEY_KP2": KEY_KP2,
|
||||
"KEY_KP3": KEY_KP3,
|
||||
"KEY_KP4": KEY_KP4,
|
||||
"KEY_KP5": KEY_KP5,
|
||||
"KEY_KP6": KEY_KP6,
|
||||
"KEY_KP7": KEY_KP7,
|
||||
"KEY_KP8": KEY_KP8,
|
||||
"KEY_KP9": KEY_KP9,
|
||||
"KEY_KP0": KEY_KP0,
|
||||
"KEY_KPDOT": KEY_KPDOT,
|
||||
"KEY_102ND": KEY_102ND,
|
||||
"KEY_COMPOSE": KEY_COMPOSE,
|
||||
"KEY_POWER": KEY_POWER,
|
||||
"KEY_KPEQUAL": KEY_KPEQUAL,
|
||||
"KEY_F13": KEY_F13,
|
||||
"KEY_F14": KEY_F14,
|
||||
"KEY_F15": KEY_F15,
|
||||
"KEY_F16": KEY_F16,
|
||||
"KEY_F17": KEY_F17,
|
||||
"KEY_F18": KEY_F18,
|
||||
"KEY_F19": KEY_F19,
|
||||
"KEY_F20": KEY_F20,
|
||||
"KEY_F21": KEY_F21,
|
||||
"KEY_F22": KEY_F22,
|
||||
"KEY_F23": KEY_F23,
|
||||
"KEY_F24": KEY_F24,
|
||||
"KEY_OPEN": KEY_OPEN,
|
||||
"KEY_HELP": KEY_HELP,
|
||||
"KEY_PROPS": KEY_PROPS,
|
||||
"KEY_FRONT": KEY_FRONT,
|
||||
"KEY_STOP": KEY_STOP,
|
||||
"KEY_AGAIN": KEY_AGAIN,
|
||||
"KEY_UNDO": KEY_UNDO,
|
||||
"KEY_CUT": KEY_CUT,
|
||||
"KEY_COPY": KEY_COPY,
|
||||
"KEY_PASTE": KEY_PASTE,
|
||||
"KEY_FIND": KEY_FIND,
|
||||
"KEY_MUTE": KEY_MUTE,
|
||||
"KEY_VOLUMEUP": KEY_VOLUMEUP,
|
||||
"KEY_VOLUMEDOWN": KEY_VOLUMEDOWN,
|
||||
"KEY_KPCOMMA": KEY_KPCOMMA,
|
||||
"KEY_RO": KEY_RO,
|
||||
"KEY_KATAKANAHIRAGANA": KEY_KATAKANAHIRAGANA,
|
||||
"KEY_YEN": KEY_YEN,
|
||||
"KEY_HENKAN": KEY_HENKAN,
|
||||
"KEY_MUHENKAN": KEY_MUHENKAN,
|
||||
"KEY_KPJPCOMMA": KEY_KPJPCOMMA,
|
||||
"KEY_HANGEUL": KEY_HANGEUL,
|
||||
"KEY_HANJA": KEY_HANJA,
|
||||
"KEY_KATAKANA": KEY_KATAKANA,
|
||||
"KEY_HIRAGANA": KEY_HIRAGANA,
|
||||
"KEY_ZENKAKUHANKAKU": KEY_ZENKAKUHANKAKU,
|
||||
"KEY_KPLEFTPAREN": KEY_KPLEFTPAREN,
|
||||
"KEY_KPRIGHTPAREN": KEY_KPRIGHTPAREN,
|
||||
"KEY_LEFTCTRL": KEY_LEFTCTRL,
|
||||
"KEY_LEFTSHIFT": KEY_LEFTSHIFT,
|
||||
"KEY_LEFTALT": KEY_LEFTALT,
|
||||
"KEY_LEFTMETA": KEY_LEFTMETA,
|
||||
"KEY_RIGHTCTRL": KEY_RIGHTCTRL,
|
||||
"KEY_RIGHTSHIFT": KEY_RIGHTSHIFT,
|
||||
"KEY_RIGHTALT": KEY_RIGHTALT,
|
||||
"KEY_RIGHTMETA": KEY_RIGHTMETA,
|
||||
"KEY_MEDIA_PLAYPAUSE": KEY_MEDIA_PLAYPAUSE,
|
||||
"KEY_MEDIA_STOPCD": KEY_MEDIA_STOPCD,
|
||||
"KEY_MEDIA_PREVIOUSSONG": KEY_MEDIA_PREVIOUSSONG,
|
||||
"KEY_MEDIA_NEXTSONG": KEY_MEDIA_NEXTSONG,
|
||||
"KEY_MEDIA_EJECTCD": KEY_MEDIA_EJECTCD,
|
||||
"KEY_MEDIA_VOLUMEUP": KEY_MEDIA_VOLUMEUP,
|
||||
"KEY_MEDIA_VOLUMEDOWN": KEY_MEDIA_VOLUMEDOWN,
|
||||
"KEY_MEDIA_MUTE": KEY_MEDIA_MUTE,
|
||||
"KEY_MEDIA_WWW": KEY_MEDIA_WWW,
|
||||
"KEY_MEDIA_BACK": KEY_MEDIA_BACK,
|
||||
"KEY_MEDIA_FORWARD": KEY_MEDIA_FORWARD,
|
||||
"KEY_MEDIA_STOP": KEY_MEDIA_STOP,
|
||||
"KEY_MEDIA_FIND": KEY_MEDIA_FIND,
|
||||
"KEY_MEDIA_SCROLLUP": KEY_MEDIA_SCROLLUP,
|
||||
"KEY_MEDIA_SCROLLDOWN": KEY_MEDIA_SCROLLDOWN,
|
||||
"KEY_MEDIA_EDIT": KEY_MEDIA_EDIT,
|
||||
"KEY_MEDIA_SLEEP": KEY_MEDIA_SLEEP,
|
||||
"KEY_MEDIA_COFFEE": KEY_MEDIA_COFFEE,
|
||||
"KEY_MEDIA_REFRESH": KEY_MEDIA_REFRESH,
|
||||
"KEY_MEDIA_CALC": KEY_MEDIA_CALC,
|
||||
}
|
||||
|
||||
var hidCharacterMap = map[string]hidKey{
|
||||
"a": {KEY_A, false},
|
||||
"b": {KEY_B, false},
|
||||
"c": {KEY_C, false},
|
||||
"d": {KEY_D, false},
|
||||
"e": {KEY_E, false},
|
||||
"f": {KEY_F, false},
|
||||
"g": {KEY_G, false},
|
||||
"h": {KEY_H, false},
|
||||
"i": {KEY_I, false},
|
||||
"j": {KEY_J, false},
|
||||
"k": {KEY_K, false},
|
||||
"l": {KEY_L, false},
|
||||
"m": {KEY_M, false},
|
||||
"n": {KEY_N, false},
|
||||
"o": {KEY_O, false},
|
||||
"p": {KEY_P, false},
|
||||
"q": {KEY_Q, false},
|
||||
"r": {KEY_R, false},
|
||||
"s": {KEY_S, false},
|
||||
"t": {KEY_T, false},
|
||||
"u": {KEY_U, false},
|
||||
"v": {KEY_V, false},
|
||||
"w": {KEY_W, false},
|
||||
"x": {KEY_X, false},
|
||||
"y": {KEY_Y, false},
|
||||
"z": {KEY_Z, false},
|
||||
"1": {KEY_1, false},
|
||||
"2": {KEY_2, false},
|
||||
"3": {KEY_3, false},
|
||||
"4": {KEY_4, false},
|
||||
"5": {KEY_5, false},
|
||||
"6": {KEY_6, false},
|
||||
"7": {KEY_7, false},
|
||||
"8": {KEY_8, false},
|
||||
"9": {KEY_9, false},
|
||||
"0": {KEY_0, false},
|
||||
"A": {KEY_A, true},
|
||||
"B": {KEY_B, true},
|
||||
"C": {KEY_C, true},
|
||||
"D": {KEY_D, true},
|
||||
"E": {KEY_E, true},
|
||||
"F": {KEY_F, true},
|
||||
"G": {KEY_G, true},
|
||||
"H": {KEY_H, true},
|
||||
"I": {KEY_I, true},
|
||||
"J": {KEY_J, true},
|
||||
"K": {KEY_K, true},
|
||||
"L": {KEY_L, true},
|
||||
"M": {KEY_M, true},
|
||||
"N": {KEY_N, true},
|
||||
"O": {KEY_O, true},
|
||||
"P": {KEY_P, true},
|
||||
"Q": {KEY_Q, true},
|
||||
"R": {KEY_R, true},
|
||||
"S": {KEY_S, true},
|
||||
"T": {KEY_T, true},
|
||||
"U": {KEY_U, true},
|
||||
"V": {KEY_V, true},
|
||||
"W": {KEY_W, true},
|
||||
"X": {KEY_X, true},
|
||||
"Y": {KEY_Y, true},
|
||||
"Z": {KEY_Z, true},
|
||||
"!": {KEY_1, true},
|
||||
"@": {KEY_2, true},
|
||||
"#": {KEY_3, true},
|
||||
"$": {KEY_4, true},
|
||||
"%": {KEY_5, true},
|
||||
"^": {KEY_6, true},
|
||||
"&": {KEY_7, true},
|
||||
"*": {KEY_8, true},
|
||||
"(": {KEY_9, true},
|
||||
")": {KEY_0, true},
|
||||
" ": {KEY_SPACE, false},
|
||||
"-": {KEY_MINUS, false},
|
||||
"_": {KEY_MINUS, true},
|
||||
"=": {KEY_EQUAL, false},
|
||||
"+": {KEY_EQUAL, true},
|
||||
"[": {KEY_LEFTBRACE, false},
|
||||
"{": {KEY_LEFTBRACE, true},
|
||||
"]": {KEY_RIGHTBRACE, false},
|
||||
"}": {KEY_RIGHTBRACE, true},
|
||||
`\`: {KEY_BACKSLASH, false},
|
||||
"|": {KEY_BACKSLASH, true},
|
||||
";": {KEY_SEMICOLON, false},
|
||||
":": {KEY_SEMICOLON, true},
|
||||
"'": {KEY_APOSTROPHE, false},
|
||||
`"`: {KEY_APOSTROPHE, true},
|
||||
"`": {KEY_GRAVE, false},
|
||||
"~": {KEY_GRAVE, true},
|
||||
",": {KEY_COMMA, false},
|
||||
"<": {KEY_COMMA, true},
|
||||
".": {KEY_DOT, false},
|
||||
">": {KEY_DOT, true},
|
||||
"/": {KEY_SLASH, false},
|
||||
"?": {KEY_SLASH, true},
|
||||
}
|
||||
|
||||
type keystrokes struct {
|
||||
*flags.VirtualMachineFlag
|
||||
|
||||
UsbHidCodeValue int32
|
||||
UsbHidCodes string
|
||||
UsbHidString string
|
||||
LeftControl bool
|
||||
LeftShift bool
|
||||
LeftAlt bool
|
||||
LeftGui bool
|
||||
RightControl bool
|
||||
RightShift bool
|
||||
RightAlt bool
|
||||
RightGui bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.keystrokes", &keystrokes{})
|
||||
}
|
||||
|
||||
func (cmd *keystrokes) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
|
||||
cmd.VirtualMachineFlag.Register(ctx, f)
|
||||
|
||||
f.StringVar(&cmd.UsbHidString, "s", "", "Raw String to Send")
|
||||
f.StringVar(&cmd.UsbHidCodes, "c", "", "USB HID Codes (hex) or aliases, comma separated")
|
||||
f.Var(flags.NewInt32(&cmd.UsbHidCodeValue), "r", "Raw USB HID Code Value (int32)")
|
||||
f.BoolVar(&cmd.LeftControl, "lc", false, "Enable/Disable Left Control")
|
||||
f.BoolVar(&cmd.LeftShift, "ls", false, "Enable/Disable Left Shift")
|
||||
f.BoolVar(&cmd.LeftAlt, "la", false, "Enable/Disable Left Alt")
|
||||
f.BoolVar(&cmd.LeftGui, "lg", false, "Enable/Disable Left Gui")
|
||||
f.BoolVar(&cmd.RightControl, "rc", false, "Enable/Disable Right Control")
|
||||
f.BoolVar(&cmd.RightShift, "rs", false, "Enable/Disable Right Shift")
|
||||
f.BoolVar(&cmd.RightAlt, "ra", false, "Enable/Disable Right Alt")
|
||||
f.BoolVar(&cmd.RightGui, "rg", false, "Enable/Disable Right Gui")
|
||||
}
|
||||
|
||||
func (cmd *keystrokes) Usage() string {
|
||||
return "VM"
|
||||
}
|
||||
|
||||
func (cmd *keystrokes) Description() string {
|
||||
description := `Send Keystrokes to VM.
|
||||
|
||||
Examples:
|
||||
Default Scenario
|
||||
govc vm.keystrokes -vm $vm -s "root" # writes 'root' to the console
|
||||
govc vm.keystrokes -vm $vm -c 0x15 # writes an 'r' to the console
|
||||
govc vm.keystrokes -vm $vm -r 1376263 # writes an 'r' to the console
|
||||
govc vm.keystrokes -vm $vm -c 0x28 # presses ENTER on the console
|
||||
govc vm.keystrokes -vm $vm -c 0x4c -la=true -lc=true # sends CTRL+ALT+DEL to console
|
||||
govc vm.keystrokes -vm $vm -c 0x15,KEY_ENTER # writes an 'r' to the console and press ENTER
|
||||
|
||||
List of available aliases:
|
||||
`
|
||||
keys := make([]string, 0)
|
||||
for key, _ := range hidKeyMap {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for i, key := range keys {
|
||||
if i > 0 {
|
||||
description += ", "
|
||||
}
|
||||
description += key
|
||||
}
|
||||
return description + "\n"
|
||||
}
|
||||
|
||||
func (cmd *keystrokes) Process(ctx context.Context) error {
|
||||
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *keystrokes) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
vm, err := cmd.VirtualMachine()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if vm == nil {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
err = cmd.processUserInput(ctx, vm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *keystrokes) processUserInput(ctx context.Context, vm *object.VirtualMachine) error {
|
||||
if err := cmd.checkValidInputs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
codes, err := cmd.processUsbCode()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var keyEventArray []types.UsbScanCodeSpecKeyEvent
|
||||
for _, code := range codes {
|
||||
leftShiftSetting := false
|
||||
if code.ShiftPressed || cmd.LeftShift {
|
||||
leftShiftSetting = true
|
||||
}
|
||||
modifiers := types.UsbScanCodeSpecModifierType{
|
||||
LeftControl: &cmd.LeftControl,
|
||||
LeftShift: &leftShiftSetting,
|
||||
LeftAlt: &cmd.LeftAlt,
|
||||
LeftGui: &cmd.LeftGui,
|
||||
RightControl: &cmd.RightControl,
|
||||
RightShift: &cmd.RightShift,
|
||||
RightAlt: &cmd.RightAlt,
|
||||
RightGui: &cmd.RightGui,
|
||||
}
|
||||
keyEvent := types.UsbScanCodeSpecKeyEvent{
|
||||
UsbHidCode: code.Code,
|
||||
Modifiers: &modifiers,
|
||||
}
|
||||
keyEventArray = append(keyEventArray, keyEvent)
|
||||
}
|
||||
|
||||
spec := types.UsbScanCodeSpec{
|
||||
KeyEvents: keyEventArray,
|
||||
}
|
||||
|
||||
_, err = vm.PutUsbScanCodes(ctx, spec)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (cmd *keystrokes) processUsbCode() ([]hidKey, error) {
|
||||
if cmd.rawCodeProvided() {
|
||||
return []hidKey{{cmd.UsbHidCodeValue, false}}, nil
|
||||
}
|
||||
|
||||
if cmd.hexCodeProvided() {
|
||||
var retKeyArray []hidKey
|
||||
for _, c := range strings.Split(cmd.UsbHidCodes, ",") {
|
||||
var s int32
|
||||
lookupvalue, ok := hidKeyMap[c]
|
||||
if ok {
|
||||
s = intToHidCode(lookupvalue)
|
||||
} else {
|
||||
var err error
|
||||
s, err = hexStringToHidCode(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
retKeyArray = append(retKeyArray, hidKey{s, false})
|
||||
}
|
||||
return retKeyArray, nil
|
||||
}
|
||||
|
||||
if cmd.stringProvided() {
|
||||
var retKeyArray []hidKey
|
||||
for _, c := range cmd.UsbHidString {
|
||||
lookupValue, ok := hidCharacterMap[string(c)]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid Character %s in String: %s", string(c), cmd.UsbHidString)
|
||||
}
|
||||
lookupValue.Code = intToHidCode(lookupValue.Code)
|
||||
retKeyArray = append(retKeyArray, lookupValue)
|
||||
}
|
||||
return retKeyArray, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func hexStringToHidCode(hex string) (int32, error) {
|
||||
s, err := strconv.ParseInt(hex, 0, 32)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return intToHidCode(int32(s)), nil
|
||||
}
|
||||
|
||||
func intToHidCode(v int32) int32 {
|
||||
var s int32 = v << 16
|
||||
s |= 7
|
||||
return s
|
||||
}
|
||||
|
||||
func (cmd *keystrokes) checkValidInputs() error {
|
||||
// poor man's boolean XOR -> A xor B xor C = A'BC' + AB'C' + A'B'C + ABC
|
||||
if (!cmd.rawCodeProvided() && cmd.hexCodeProvided() && !cmd.stringProvided()) || // A'BC'
|
||||
(cmd.rawCodeProvided() && !cmd.hexCodeProvided() && !cmd.stringProvided()) || // AB'C'
|
||||
(!cmd.rawCodeProvided() && !cmd.hexCodeProvided() && cmd.stringProvided()) || // A'B'C
|
||||
(cmd.rawCodeProvided() && cmd.hexCodeProvided() && cmd.stringProvided()) { // ABC
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("specify only 1 argument")
|
||||
}
|
||||
|
||||
func (cmd keystrokes) rawCodeProvided() bool {
|
||||
return cmd.UsbHidCodeValue != 0
|
||||
}
|
||||
|
||||
func (cmd keystrokes) hexCodeProvided() bool {
|
||||
return cmd.UsbHidCodes != ""
|
||||
}
|
||||
|
||||
func (cmd keystrokes) stringProvided() bool {
|
||||
return cmd.UsbHidString != ""
|
||||
}
|
||||
72
vendor/github.com/vmware/govmomi/cli/vm/markastemplate.go
generated
vendored
Normal file
72
vendor/github.com/vmware/govmomi/cli/vm/markastemplate.go
generated
vendored
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
)
|
||||
|
||||
type markastemplate struct {
|
||||
*flags.SearchFlag
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.markastemplate", &markastemplate{})
|
||||
}
|
||||
|
||||
func (cmd *markastemplate) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.SearchFlag, ctx = flags.NewSearchFlag(ctx, flags.SearchVirtualMachines)
|
||||
cmd.SearchFlag.Register(ctx, f)
|
||||
}
|
||||
|
||||
func (cmd *markastemplate) Process(ctx context.Context) error {
|
||||
if err := cmd.SearchFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *markastemplate) Usage() string {
|
||||
return "VM..."
|
||||
}
|
||||
|
||||
func (cmd *markastemplate) Description() string {
|
||||
return `Mark VM as a virtual machine template.
|
||||
|
||||
Examples:
|
||||
govc vm.markastemplate $name`
|
||||
}
|
||||
|
||||
func (cmd *markastemplate) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
vms, err := cmd.VirtualMachines(f.Args())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, vm := range vms {
|
||||
err := vm.MarkAsTemplate(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
106
vendor/github.com/vmware/govmomi/cli/vm/markasvm.go
generated
vendored
Normal file
106
vendor/github.com/vmware/govmomi/cli/vm/markasvm.go
generated
vendored
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
)
|
||||
|
||||
type markasvm struct {
|
||||
*flags.SearchFlag
|
||||
*flags.ResourcePoolFlag
|
||||
*flags.HostSystemFlag
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.markasvm", &markasvm{})
|
||||
}
|
||||
|
||||
func (cmd *markasvm) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.SearchFlag, ctx = flags.NewSearchFlag(ctx, flags.SearchVirtualMachines)
|
||||
cmd.SearchFlag.Register(ctx, f)
|
||||
cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx)
|
||||
cmd.ResourcePoolFlag.Register(ctx, f)
|
||||
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
|
||||
cmd.HostSystemFlag.Register(ctx, f)
|
||||
}
|
||||
|
||||
func (cmd *markasvm) Process(ctx context.Context) error {
|
||||
if err := cmd.SearchFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.ResourcePoolFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *markasvm) Usage() string {
|
||||
return "VM..."
|
||||
}
|
||||
|
||||
func (cmd *markasvm) Description() string {
|
||||
return `Mark VM template as a virtual machine.
|
||||
|
||||
Examples:
|
||||
govc vm.markasvm -host host1 $name
|
||||
govc vm.markasvm -host host1 $name`
|
||||
}
|
||||
|
||||
func (cmd *markasvm) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
vms, err := cmd.VirtualMachines(f.Args())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pool, err := cmd.ResourcePoolIfSpecified()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
host, err := cmd.HostSystemFlag.HostSystemIfSpecified()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if pool == nil {
|
||||
if host == nil {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
pool, err = host.ResourcePool(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, vm := range vms {
|
||||
err := vm.MarkAsVirtualMachine(ctx, *pool, host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
211
vendor/github.com/vmware/govmomi/cli/vm/migrate.go
generated
vendored
Normal file
211
vendor/github.com/vmware/govmomi/cli/vm/migrate.go
generated
vendored
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
Copyright (c) 2016-2024 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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type migrate struct {
|
||||
*flags.FolderFlag
|
||||
*flags.ResourcePoolFlag
|
||||
*flags.HostSystemFlag
|
||||
*flags.DatastoreFlag
|
||||
*flags.NetworkFlag
|
||||
*flags.VirtualMachineFlag
|
||||
|
||||
priority types.VirtualMachineMovePriority
|
||||
spec types.VirtualMachineRelocateSpec
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.migrate", &migrate{})
|
||||
}
|
||||
|
||||
func (cmd *migrate) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx)
|
||||
cmd.FolderFlag.Register(ctx, f)
|
||||
|
||||
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
|
||||
cmd.VirtualMachineFlag.Register(ctx, f)
|
||||
|
||||
cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx)
|
||||
cmd.ResourcePoolFlag.Register(ctx, f)
|
||||
|
||||
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
|
||||
cmd.HostSystemFlag.Register(ctx, f)
|
||||
|
||||
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
|
||||
cmd.DatastoreFlag.Register(ctx, f)
|
||||
|
||||
cmd.NetworkFlag, ctx = flags.NewNetworkFlag(ctx)
|
||||
cmd.NetworkFlag.Register(ctx, f)
|
||||
|
||||
f.StringVar((*string)(&cmd.priority), "priority", string(types.VirtualMachineMovePriorityDefaultPriority), "The task priority")
|
||||
}
|
||||
|
||||
func (cmd *migrate) Process(ctx context.Context) error {
|
||||
if err := cmd.FolderFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.ResourcePoolFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.NetworkFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *migrate) Usage() string {
|
||||
return "VM..."
|
||||
}
|
||||
|
||||
func (cmd *migrate) Description() string {
|
||||
return `Migrates VM to a specific resource pool, host or datastore.
|
||||
|
||||
Examples:
|
||||
govc vm.migrate -host another-host vm-1 vm-2 vm-3
|
||||
govc vm.migrate -pool another-pool vm-1 vm-2 vm-3
|
||||
govc vm.migrate -ds another-ds vm-1 vm-2 vm-3`
|
||||
}
|
||||
|
||||
func (cmd *migrate) relocate(ctx context.Context, vm *object.VirtualMachine) error {
|
||||
spec := cmd.spec
|
||||
|
||||
if cmd.NetworkFlag.IsSet() {
|
||||
dev, err := cmd.NetworkFlag.Device()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
devices, err := vm.Device(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
net := devices.SelectByType((*types.VirtualEthernetCard)(nil))
|
||||
if len(net) != 1 {
|
||||
return fmt.Errorf("-net specified, but %s has %d nics", vm.Name(), len(net))
|
||||
}
|
||||
cmd.NetworkFlag.Change(net[0], dev)
|
||||
|
||||
spec.DeviceChange = append(spec.DeviceChange, &types.VirtualDeviceConfigSpec{
|
||||
Device: net[0],
|
||||
Operation: types.VirtualDeviceConfigSpecOperationEdit,
|
||||
})
|
||||
}
|
||||
|
||||
if cmd.VirtualMachineFlag.Spec {
|
||||
return cmd.VirtualMachineFlag.WriteAny(spec)
|
||||
}
|
||||
|
||||
task, err := vm.Relocate(ctx, spec, cmd.priority)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logger := cmd.DatastoreFlag.ProgressLogger(fmt.Sprintf("migrating %s... ", vm.Reference()))
|
||||
_, err = task.WaitForResult(ctx, logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *migrate) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
vms, err := cmd.VirtualMachineFlag.VirtualMachines(f.Args())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
folder, err := cmd.FolderIfSpecified()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if folder != nil {
|
||||
ref := folder.Reference()
|
||||
cmd.spec.Folder = &ref
|
||||
}
|
||||
|
||||
host, err := cmd.HostSystemFlag.HostSystemIfSpecified()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if host != nil {
|
||||
ref := host.Reference()
|
||||
cmd.spec.Host = &ref
|
||||
}
|
||||
|
||||
pool, err := cmd.ResourcePoolFlag.ResourcePoolIfSpecified()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if pool == nil && host != nil {
|
||||
pool, err = host.ResourcePool(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if pool != nil {
|
||||
ref := pool.Reference()
|
||||
cmd.spec.Pool = &ref
|
||||
}
|
||||
|
||||
ds, err := cmd.DatastoreFlag.DatastoreIfSpecified()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ds != nil {
|
||||
ref := ds.Reference()
|
||||
cmd.spec.Datastore = &ref
|
||||
}
|
||||
|
||||
for _, vm := range vms {
|
||||
err = cmd.relocate(ctx, vm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
216
vendor/github.com/vmware/govmomi/cli/vm/power.go
generated
vendored
Normal file
216
vendor/github.com/vmware/govmomi/cli/vm/power.go
generated
vendored
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
Copyright (c) 2014-2024 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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/fault"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type power struct {
|
||||
*flags.ClientFlag
|
||||
*flags.SearchFlag
|
||||
|
||||
On bool
|
||||
Off bool
|
||||
Reset bool
|
||||
Reboot bool
|
||||
Shutdown bool
|
||||
Standby bool
|
||||
Suspend bool
|
||||
Force bool
|
||||
Multi bool
|
||||
Wait bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.power", &power{})
|
||||
}
|
||||
|
||||
func (cmd *power) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
|
||||
cmd.ClientFlag.Register(ctx, f)
|
||||
|
||||
cmd.SearchFlag, ctx = flags.NewSearchFlag(ctx, flags.SearchVirtualMachines)
|
||||
cmd.SearchFlag.Register(ctx, f)
|
||||
|
||||
f.BoolVar(&cmd.On, "on", false, "Power on")
|
||||
f.BoolVar(&cmd.Off, "off", false, "Power off")
|
||||
f.BoolVar(&cmd.Reset, "reset", false, "Power reset")
|
||||
f.BoolVar(&cmd.Suspend, "suspend", false, "Power suspend")
|
||||
f.BoolVar(&cmd.Reboot, "r", false, "Reboot guest")
|
||||
f.BoolVar(&cmd.Shutdown, "s", false, "Shutdown guest")
|
||||
f.BoolVar(&cmd.Standby, "standby", false, "Standby guest")
|
||||
f.BoolVar(&cmd.Force, "force", false, "Force (ignore state error and hard shutdown/reboot if tools unavailable)")
|
||||
f.BoolVar(&cmd.Multi, "M", false, "Use Datacenter.PowerOnMultiVM method instead of VirtualMachine.PowerOnVM")
|
||||
f.BoolVar(&cmd.Wait, "wait", true, "Wait for the operation to complete")
|
||||
}
|
||||
|
||||
func (cmd *power) Usage() string {
|
||||
return "NAME..."
|
||||
}
|
||||
|
||||
func (cmd *power) Description() string {
|
||||
return `Invoke VM power operations.
|
||||
|
||||
Examples:
|
||||
govc vm.power -on VM1 VM2 VM3
|
||||
govc vm.power -on -M VM1 VM2 VM3
|
||||
govc vm.power -off -force VM1`
|
||||
}
|
||||
|
||||
func (cmd *power) Process(ctx context.Context) error {
|
||||
if err := cmd.ClientFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.SearchFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
opts := []bool{cmd.On, cmd.Off, cmd.Reset, cmd.Suspend, cmd.Reboot, cmd.Shutdown, cmd.Standby}
|
||||
selected := false
|
||||
|
||||
for _, opt := range opts {
|
||||
if opt {
|
||||
if selected {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
selected = opt
|
||||
}
|
||||
}
|
||||
|
||||
if !selected {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func isToolsUnavailable(err error) bool {
|
||||
return fault.Is(err, &types.ToolsUnavailable{})
|
||||
}
|
||||
|
||||
// this is annoying, but the likely use cases for Datacenter.PowerOnVM outside of this command would
|
||||
// use []types.ManagedObjectReference via ContainerView or field such as ResourcePool.Vm rather than the Finder.
|
||||
func vmReferences(vms []*object.VirtualMachine) []types.ManagedObjectReference {
|
||||
refs := make([]types.ManagedObjectReference, len(vms))
|
||||
for i, vm := range vms {
|
||||
refs[i] = vm.Reference()
|
||||
}
|
||||
return refs
|
||||
}
|
||||
|
||||
func (cmd *power) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
vms, err := cmd.VirtualMachines(f.Args())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.On && cmd.Multi {
|
||||
dc, derr := cmd.Datacenter()
|
||||
if derr != nil {
|
||||
return derr
|
||||
}
|
||||
|
||||
task, derr := dc.PowerOnVM(ctx, vmReferences(vms))
|
||||
if derr != nil {
|
||||
return derr
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("Powering on %d VMs...", len(vms))
|
||||
if task == nil {
|
||||
// running against ESX
|
||||
fmt.Fprintf(cmd, "%s OK\n", msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
if cmd.Wait {
|
||||
logger := cmd.ProgressLogger(msg)
|
||||
defer logger.Wait()
|
||||
|
||||
_, err = task.WaitForResult(ctx, logger)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, vm := range vms {
|
||||
var task *object.Task
|
||||
|
||||
switch {
|
||||
case cmd.On:
|
||||
fmt.Fprintf(cmd, "Powering on %s... ", vm.Reference())
|
||||
task, err = vm.PowerOn(ctx)
|
||||
case cmd.Off:
|
||||
fmt.Fprintf(cmd, "Powering off %s... ", vm.Reference())
|
||||
task, err = vm.PowerOff(ctx)
|
||||
case cmd.Reset:
|
||||
fmt.Fprintf(cmd, "Reset %s... ", vm.Reference())
|
||||
task, err = vm.Reset(ctx)
|
||||
case cmd.Suspend:
|
||||
fmt.Fprintf(cmd, "Suspend %s... ", vm.Reference())
|
||||
task, err = vm.Suspend(ctx)
|
||||
case cmd.Reboot:
|
||||
fmt.Fprintf(cmd, "Reboot guest %s... ", vm.Reference())
|
||||
err = vm.RebootGuest(ctx)
|
||||
|
||||
if err != nil && cmd.Force && isToolsUnavailable(err) {
|
||||
task, err = vm.Reset(ctx)
|
||||
}
|
||||
case cmd.Shutdown:
|
||||
fmt.Fprintf(cmd, "Shutdown guest %s... ", vm.Reference())
|
||||
err = vm.ShutdownGuest(ctx)
|
||||
|
||||
if err != nil && cmd.Force && isToolsUnavailable(err) {
|
||||
task, err = vm.PowerOff(ctx)
|
||||
}
|
||||
case cmd.Standby:
|
||||
fmt.Fprintf(cmd, "Standby guest %s... ", vm.Reference())
|
||||
err = vm.StandbyGuest(ctx)
|
||||
|
||||
if err != nil && cmd.Force && isToolsUnavailable(err) {
|
||||
task, err = vm.Suspend(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.Wait && task != nil {
|
||||
err = task.Wait(ctx)
|
||||
}
|
||||
if err == nil {
|
||||
fmt.Fprintf(cmd, "OK\n")
|
||||
continue
|
||||
}
|
||||
|
||||
if cmd.Force {
|
||||
fmt.Fprintf(cmd, "Error: %s\n", err)
|
||||
continue
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
98
vendor/github.com/vmware/govmomi/cli/vm/question.go
generated
vendored
Normal file
98
vendor/github.com/vmware/govmomi/cli/vm/question.go
generated
vendored
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type question struct {
|
||||
*flags.VirtualMachineFlag
|
||||
|
||||
answer string
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.question", &question{})
|
||||
}
|
||||
|
||||
func (cmd *question) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
|
||||
cmd.VirtualMachineFlag.Register(ctx, f)
|
||||
|
||||
f.StringVar(&cmd.answer, "answer", "", "Answer to question")
|
||||
}
|
||||
|
||||
func (cmd *question) Process(ctx context.Context) error {
|
||||
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *question) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
c, err := cmd.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vm, err := cmd.VirtualMachine()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if vm == nil {
|
||||
return errors.New("no VM specified")
|
||||
}
|
||||
|
||||
var mvm mo.VirtualMachine
|
||||
|
||||
pc := property.DefaultCollector(c)
|
||||
err = pc.RetrieveOne(ctx, vm.Reference(), []string{"runtime.question"}, &mvm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
q := mvm.Runtime.Question
|
||||
if q == nil {
|
||||
fmt.Printf("No pending question\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Print question if no answer is specified
|
||||
if cmd.answer == "" {
|
||||
fmt.Printf("Question:\n%s\n\n", q.Text)
|
||||
fmt.Printf("Possible answers:\n")
|
||||
for _, e := range q.Choice.ChoiceInfo {
|
||||
ed := e.(*types.ElementDescription)
|
||||
fmt.Printf("%s) %s\n", ed.Key, ed.Description.Label)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Answer question
|
||||
return vm.Answer(ctx, q.Id, cmd.answer)
|
||||
}
|
||||
139
vendor/github.com/vmware/govmomi/cli/vm/register.go
generated
vendored
Normal file
139
vendor/github.com/vmware/govmomi/cli/vm/register.go
generated
vendored
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
)
|
||||
|
||||
type register struct {
|
||||
*flags.DatastoreFlag
|
||||
*flags.ResourcePoolFlag
|
||||
*flags.HostSystemFlag
|
||||
*flags.FolderFlag
|
||||
|
||||
name string
|
||||
template bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.register", ®ister{})
|
||||
}
|
||||
|
||||
func (cmd *register) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
|
||||
cmd.DatastoreFlag.Register(ctx, f)
|
||||
|
||||
cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx)
|
||||
cmd.ResourcePoolFlag.Register(ctx, f)
|
||||
|
||||
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
|
||||
cmd.HostSystemFlag.Register(ctx, f)
|
||||
|
||||
cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx)
|
||||
cmd.FolderFlag.Register(ctx, f)
|
||||
|
||||
f.StringVar(&cmd.name, "name", "", "Name of the VM")
|
||||
f.BoolVar(&cmd.template, "template", false, "Mark VM as template")
|
||||
}
|
||||
|
||||
func (cmd *register) Process(ctx context.Context) error {
|
||||
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.ResourcePoolFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.FolderFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *register) Usage() string {
|
||||
return "VMX"
|
||||
}
|
||||
|
||||
func (cmd *register) Description() string {
|
||||
return `Add an existing VM to the inventory.
|
||||
|
||||
VMX is a path to the vm config file, relative to DATASTORE.
|
||||
|
||||
Examples:
|
||||
govc vm.register path/name.vmx
|
||||
govc vm.register -template -host $host path/name.vmx`
|
||||
}
|
||||
|
||||
func (cmd *register) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
if len(f.Args()) != 1 {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
pool, err := cmd.ResourcePoolIfSpecified()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
host, err := cmd.HostSystemFlag.HostSystemIfSpecified()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.template {
|
||||
if pool != nil || host == nil {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
} else if pool == nil {
|
||||
if host != nil {
|
||||
pool, err = host.ResourcePool(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// neither -host nor -pool were specified, so use the default pool (ESX)
|
||||
pool, err = cmd.ResourcePool()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
folder, err := cmd.FolderFlag.Folder()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path, err := cmd.DatastorePath(f.Arg(0))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
task, err := folder.RegisterVM(ctx, path, cmd.name, cmd.template, pool, host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return task.Wait(ctx)
|
||||
}
|
||||
76
vendor/github.com/vmware/govmomi/cli/vm/unregister.go
generated
vendored
Normal file
76
vendor/github.com/vmware/govmomi/cli/vm/unregister.go
generated
vendored
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
)
|
||||
|
||||
type unregister struct {
|
||||
*flags.ClientFlag
|
||||
*flags.SearchFlag
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.unregister", &unregister{})
|
||||
}
|
||||
|
||||
func (cmd *unregister) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
|
||||
cmd.ClientFlag.Register(ctx, f)
|
||||
|
||||
cmd.SearchFlag, ctx = flags.NewSearchFlag(ctx, flags.SearchVirtualMachines)
|
||||
cmd.SearchFlag.Register(ctx, f)
|
||||
}
|
||||
|
||||
func (cmd *unregister) Process(ctx context.Context) error {
|
||||
if err := cmd.ClientFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.SearchFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *unregister) Usage() string {
|
||||
return "VM..."
|
||||
}
|
||||
|
||||
func (cmd *unregister) Description() string {
|
||||
return `Remove VM from inventory without removing any of the VM files on disk.`
|
||||
}
|
||||
|
||||
func (cmd *unregister) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
vms, err := cmd.VirtualMachines(f.Args())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, vm := range vms {
|
||||
err := vm.Unregister(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
87
vendor/github.com/vmware/govmomi/cli/vm/upgrade.go
generated
vendored
Normal file
87
vendor/github.com/vmware/govmomi/cli/vm/upgrade.go
generated
vendored
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
Copyright (c) 2017-2024 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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/fault"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type upgrade struct {
|
||||
*flags.VirtualMachineFlag
|
||||
version int
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("vm.upgrade", &upgrade{})
|
||||
}
|
||||
|
||||
func (cmd *upgrade) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
|
||||
cmd.VirtualMachineFlag.Register(ctx, f)
|
||||
|
||||
f.IntVar(&cmd.version, "version", 0, "Target vm hardware version, by default -- latest available")
|
||||
}
|
||||
|
||||
func (cmd *upgrade) Process(ctx context.Context) error {
|
||||
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *upgrade) Description() string {
|
||||
return `Upgrade VMs to latest hardware version
|
||||
|
||||
Examples:
|
||||
govc vm.upgrade -vm $vm_name
|
||||
govc vm.upgrade -version=$version -vm $vm_name
|
||||
govc vm.upgrade -version=$version -vm.uuid $vm_uuid`
|
||||
}
|
||||
|
||||
func (cmd *upgrade) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
vm, err := cmd.VirtualMachine()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var version = ""
|
||||
if cmd.version != 0 {
|
||||
version = fmt.Sprintf("vmx-%02d", cmd.version)
|
||||
}
|
||||
|
||||
task, err := vm.UpgradeVM(ctx, version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = task.Wait(ctx)
|
||||
if err != nil {
|
||||
if fault.Is(err, &types.AlreadyUpgraded{}) {
|
||||
fmt.Println(err.Error())
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
504
vendor/github.com/vmware/govmomi/cli/vm/vnc.go
generated
vendored
Normal file
504
vendor/github.com/vmware/govmomi/cli/vm/vnc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,504 @@
|
|||
/*
|
||||
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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/cli"
|
||||
"github.com/vmware/govmomi/cli/flags"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type intRange struct {
|
||||
low, high int
|
||||
}
|
||||
|
||||
var intRangeRegexp = regexp.MustCompile("^([0-9]+)-([0-9]+)$")
|
||||
|
||||
func (i *intRange) Set(s string) error {
|
||||
m := intRangeRegexp.FindStringSubmatch(s)
|
||||
if m == nil {
|
||||
return fmt.Errorf("invalid range: %s", s)
|
||||
}
|
||||
|
||||
low, err := strconv.Atoi(m[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't convert to integer: %v", err)
|
||||
}
|
||||
|
||||
high, err := strconv.Atoi(m[2])
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't convert to integer: %v", err)
|
||||
}
|
||||
|
||||
if low > high {
|
||||
return fmt.Errorf("invalid range: low > high")
|
||||
}
|
||||
|
||||
i.low = low
|
||||
i.high = high
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *intRange) String() string {
|
||||
return fmt.Sprintf("%d-%d", i.low, i.high)
|
||||
}
|
||||
|
||||
type vnc struct {
|
||||
*flags.SearchFlag
|
||||
|
||||
Enable bool
|
||||
Disable bool
|
||||
Port int
|
||||
PortRange intRange
|
||||
Password string
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmd := &vnc{}
|
||||
err := cmd.PortRange.Set("5900-5999")
|
||||
if err != nil {
|
||||
fmt.Printf("Error setting port range %v", err)
|
||||
}
|
||||
cli.Register("vm.vnc", cmd)
|
||||
}
|
||||
|
||||
func (cmd *vnc) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.SearchFlag, ctx = flags.NewSearchFlag(ctx, flags.SearchVirtualMachines)
|
||||
cmd.SearchFlag.Register(ctx, f)
|
||||
|
||||
f.BoolVar(&cmd.Enable, "enable", false, "Enable VNC")
|
||||
f.BoolVar(&cmd.Disable, "disable", false, "Disable VNC")
|
||||
f.IntVar(&cmd.Port, "port", -1, "VNC port (-1 for auto-select)")
|
||||
f.Var(&cmd.PortRange, "port-range", "VNC port auto-select range")
|
||||
f.StringVar(&cmd.Password, "password", "", "VNC password")
|
||||
}
|
||||
|
||||
func (cmd *vnc) Process(ctx context.Context) error {
|
||||
if err := cmd.SearchFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
// Either may be true or none may be true.
|
||||
if cmd.Enable && cmd.Disable {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *vnc) Usage() string {
|
||||
return "VM..."
|
||||
}
|
||||
|
||||
func (cmd *vnc) Description() string {
|
||||
return `Enable or disable VNC for VM.
|
||||
|
||||
Port numbers are automatically chosen if not specified.
|
||||
|
||||
If neither -enable or -disable is specified, the current state is returned.
|
||||
|
||||
Examples:
|
||||
govc vm.vnc -enable -password 1234 $vm | awk '{print $2}' | xargs open`
|
||||
}
|
||||
|
||||
func (cmd *vnc) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
vms, err := cmd.loadVMs(f.Args())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Actuate settings in VMs
|
||||
for _, vm := range vms {
|
||||
switch {
|
||||
case cmd.Enable:
|
||||
err = vm.enable(cmd.Port, cmd.Password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case cmd.Disable:
|
||||
err = vm.disable()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reconfigure VMs to reflect updates
|
||||
for _, vm := range vms {
|
||||
err = vm.reconfigure()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return cmd.WriteResult(vncResult(vms))
|
||||
}
|
||||
|
||||
func (cmd *vnc) loadVMs(args []string) ([]*vncVM, error) {
|
||||
c, err := cmd.Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vms, err := cmd.VirtualMachines(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var vncVMs []*vncVM
|
||||
for _, vm := range vms {
|
||||
v, err := newVNCVM(c, vm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vncVMs = append(vncVMs, v)
|
||||
}
|
||||
|
||||
// Assign vncHosts to vncVMs
|
||||
hosts := make(map[string]*vncHost)
|
||||
for _, vm := range vncVMs {
|
||||
if h, ok := hosts[vm.hostReference().Value]; ok {
|
||||
vm.host = h
|
||||
continue
|
||||
}
|
||||
|
||||
hs := object.NewHostSystem(c, vm.hostReference())
|
||||
h, err := newVNCHost(c, hs, cmd.PortRange.low, cmd.PortRange.high)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hosts[vm.hostReference().Value] = h
|
||||
vm.host = h
|
||||
}
|
||||
|
||||
return vncVMs, nil
|
||||
}
|
||||
|
||||
type vncVM struct {
|
||||
c *vim25.Client
|
||||
vm *object.VirtualMachine
|
||||
mvm mo.VirtualMachine
|
||||
host *vncHost
|
||||
|
||||
curOptions vncOptions
|
||||
newOptions vncOptions
|
||||
}
|
||||
|
||||
func newVNCVM(c *vim25.Client, vm *object.VirtualMachine) (*vncVM, error) {
|
||||
v := &vncVM{
|
||||
c: c,
|
||||
vm: vm,
|
||||
}
|
||||
|
||||
virtualMachineProperties := []string{
|
||||
"name",
|
||||
"config.extraConfig",
|
||||
"runtime.host",
|
||||
}
|
||||
|
||||
pc := property.DefaultCollector(c)
|
||||
ctx := context.TODO()
|
||||
err := pc.RetrieveOne(ctx, vm.Reference(), virtualMachineProperties, &v.mvm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v.curOptions = vncOptionsFromExtraConfig(v.mvm.Config.ExtraConfig)
|
||||
v.newOptions = vncOptionsFromExtraConfig(v.mvm.Config.ExtraConfig)
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (v *vncVM) hostReference() types.ManagedObjectReference {
|
||||
return *v.mvm.Runtime.Host
|
||||
}
|
||||
|
||||
func (v *vncVM) enable(port int, password string) error {
|
||||
v.newOptions["enabled"] = "true"
|
||||
v.newOptions["port"] = fmt.Sprintf("%d", port)
|
||||
v.newOptions["password"] = password
|
||||
|
||||
// Find port if auto-select
|
||||
if port == -1 {
|
||||
// Reuse port if If VM already has a port, reuse it.
|
||||
// Otherwise, find unused VNC port on host.
|
||||
if p, ok := v.curOptions["port"]; ok && p != "" {
|
||||
v.newOptions["port"] = p
|
||||
} else {
|
||||
port, err := v.host.popUnusedPort()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.newOptions["port"] = fmt.Sprintf("%d", port)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *vncVM) disable() error {
|
||||
v.newOptions["enabled"] = "false"
|
||||
v.newOptions["port"] = ""
|
||||
v.newOptions["password"] = ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *vncVM) reconfigure() error {
|
||||
if reflect.DeepEqual(v.curOptions, v.newOptions) {
|
||||
// No changes to settings
|
||||
return nil
|
||||
}
|
||||
|
||||
spec := types.VirtualMachineConfigSpec{
|
||||
ExtraConfig: v.newOptions.ToExtraConfig(),
|
||||
}
|
||||
|
||||
ctx := context.TODO()
|
||||
task, err := v.vm.Reconfigure(ctx, spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return task.Wait(ctx)
|
||||
}
|
||||
|
||||
func (v *vncVM) uri() (string, error) {
|
||||
ip, err := v.host.managementIP()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("vnc://:%s@%s:%s",
|
||||
v.newOptions["password"],
|
||||
ip,
|
||||
v.newOptions["port"])
|
||||
|
||||
return uri, nil
|
||||
}
|
||||
|
||||
func (v *vncVM) write(w io.Writer) error {
|
||||
if strings.EqualFold(v.newOptions["enabled"], "true") {
|
||||
uri, err := v.uri()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("%s: %s\n", v.mvm.Name, uri)
|
||||
} else {
|
||||
fmt.Printf("%s: disabled\n", v.mvm.Name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type vncHost struct {
|
||||
c *vim25.Client
|
||||
host *object.HostSystem
|
||||
ports map[int]struct{}
|
||||
ip string // This field is populated by `managementIP`
|
||||
}
|
||||
|
||||
func newVNCHost(c *vim25.Client, host *object.HostSystem, low, high int) (*vncHost, error) {
|
||||
ports := make(map[int]struct{})
|
||||
for i := low; i <= high; i++ {
|
||||
ports[i] = struct{}{}
|
||||
}
|
||||
|
||||
used, err := loadUsedPorts(c, host.Reference())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Remove used ports from range
|
||||
for _, u := range used {
|
||||
delete(ports, u)
|
||||
}
|
||||
|
||||
h := &vncHost{
|
||||
c: c,
|
||||
host: host,
|
||||
ports: ports,
|
||||
}
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func loadUsedPorts(c *vim25.Client, host types.ManagedObjectReference) ([]int, error) {
|
||||
ctx := context.TODO()
|
||||
ospec := types.ObjectSpec{
|
||||
Obj: host,
|
||||
SelectSet: []types.BaseSelectionSpec{
|
||||
&types.TraversalSpec{
|
||||
Type: "HostSystem",
|
||||
Path: "vm",
|
||||
Skip: types.NewBool(false),
|
||||
},
|
||||
},
|
||||
Skip: types.NewBool(false),
|
||||
}
|
||||
|
||||
pspec := types.PropertySpec{
|
||||
Type: "VirtualMachine",
|
||||
PathSet: []string{"config.extraConfig"},
|
||||
}
|
||||
|
||||
req := types.RetrieveProperties{
|
||||
This: c.ServiceContent.PropertyCollector,
|
||||
SpecSet: []types.PropertyFilterSpec{
|
||||
{
|
||||
ObjectSet: []types.ObjectSpec{ospec},
|
||||
PropSet: []types.PropertySpec{pspec},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var vms []mo.VirtualMachine
|
||||
err := mo.RetrievePropertiesForRequest(ctx, c, req, &vms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ports []int
|
||||
for _, vm := range vms {
|
||||
if vm.Config == nil || vm.Config.ExtraConfig == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
options := vncOptionsFromExtraConfig(vm.Config.ExtraConfig)
|
||||
if ps, ok := options["port"]; ok && ps != "" {
|
||||
pi, err := strconv.Atoi(ps)
|
||||
if err == nil {
|
||||
ports = append(ports, pi)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ports, nil
|
||||
}
|
||||
|
||||
func (h *vncHost) popUnusedPort() (int, error) {
|
||||
if len(h.ports) == 0 {
|
||||
return 0, fmt.Errorf("no unused ports in range")
|
||||
}
|
||||
|
||||
// Return first port we get when iterating
|
||||
var port int
|
||||
for port = range h.ports {
|
||||
break
|
||||
}
|
||||
delete(h.ports, port)
|
||||
return port, nil
|
||||
}
|
||||
|
||||
func (h *vncHost) managementIP() (string, error) {
|
||||
ctx := context.TODO()
|
||||
if h.ip != "" {
|
||||
return h.ip, nil
|
||||
}
|
||||
|
||||
ips, err := h.host.ManagementIPs(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(ips) > 0 {
|
||||
h.ip = ips[0].String()
|
||||
} else {
|
||||
h.ip = "<unknown>"
|
||||
}
|
||||
|
||||
return h.ip, nil
|
||||
}
|
||||
|
||||
type vncResult []*vncVM
|
||||
|
||||
func (vms vncResult) MarshalJSON() ([]byte, error) {
|
||||
out := make(map[string]string)
|
||||
for _, vm := range vms {
|
||||
uri, err := vm.uri()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out[vm.mvm.Name] = uri
|
||||
}
|
||||
return json.Marshal(out)
|
||||
}
|
||||
|
||||
func (vms vncResult) Write(w io.Writer) error {
|
||||
for _, vm := range vms {
|
||||
err := vm.write(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type vncOptions map[string]string
|
||||
|
||||
var vncPrefix = "RemoteDisplay.vnc."
|
||||
|
||||
func vncOptionsFromExtraConfig(ov []types.BaseOptionValue) vncOptions {
|
||||
vo := make(vncOptions)
|
||||
for _, b := range ov {
|
||||
o := b.GetOptionValue()
|
||||
if strings.HasPrefix(o.Key, vncPrefix) {
|
||||
key := o.Key[len(vncPrefix):]
|
||||
if key != "key" {
|
||||
vo[key] = o.Value.(string)
|
||||
}
|
||||
}
|
||||
}
|
||||
return vo
|
||||
}
|
||||
|
||||
func (vo vncOptions) ToExtraConfig() []types.BaseOptionValue {
|
||||
ov := make([]types.BaseOptionValue, 0)
|
||||
for k, v := range vo {
|
||||
key := vncPrefix + k
|
||||
value := v
|
||||
|
||||
o := types.OptionValue{
|
||||
Key: key,
|
||||
Value: &value, // Pass pointer to avoid omitempty
|
||||
}
|
||||
|
||||
ov = append(ov, &o)
|
||||
}
|
||||
|
||||
// Don't know how to deal with the key option, set it to be empty...
|
||||
o := types.OptionValue{
|
||||
Key: vncPrefix + "key",
|
||||
Value: new(string), // Pass pointer to avoid omitempty
|
||||
}
|
||||
|
||||
ov = append(ov, &o)
|
||||
|
||||
return ov
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue