tests: upload & test in vCenter. Closes #338

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

187
vendor/github.com/vmware/govmomi/govc/vm/change.go generated vendored Normal file
View file

@ -0,0 +1,187 @@
/*
Copyright (c) 2015-2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package vm
import (
"context"
"flag"
"fmt"
"reflect"
"strings"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/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 change struct {
*flags.VirtualMachineFlag
*flags.ResourceAllocationFlag
types.VirtualMachineConfigSpec
extraConfig extraConfig
Latency string
}
func init() {
cli.Register("vm.change", &change{})
}
var latencyLevels = []string{
string(types.LatencySensitivitySensitivityLevelLow),
string(types.LatencySensitivitySensitivityLevelNormal),
string(types.LatencySensitivitySensitivityLevelHigh),
}
// 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, "|"))
}
// 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.Var(&cmd.extraConfig, "e", "ExtraConfig. <key>=<value>")
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")
}
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 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`
}
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
}
if len(cmd.extraConfig) > 0 {
cmd.VirtualMachineConfigSpec.ExtraConfig = cmd.extraConfig
}
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 err = cmd.setLatency(); err != nil {
return err
}
task, err := vm.Reconfigure(ctx, cmd.VirtualMachineConfigSpec)
if err != nil {
return err
}
return task.Wait(ctx)
}

484
vendor/github.com/vmware/govmomi/govc/vm/clone.go generated vendored Normal file
View file

@ -0,0 +1,484 @@
/*
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/govc/cli"
"github.com/vmware/govmomi/govc/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
}
}
}
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.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 := cmd.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
}
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
}

173
vendor/github.com/vmware/govmomi/govc/vm/console.go generated vendored Normal file
View file

@ -0,0 +1,173 @@
/*
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/govc/cli"
"github.com/vmware/govmomi/govc/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
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.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 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, &param)
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, &param)
}
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(os.Stdout, link)
return nil
}

611
vendor/github.com/vmware/govmomi/govc/vm/create.go generated vendored Normal file
View file

@ -0,0 +1,611 @@
/*
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"
"strings"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/units"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
var hardwareVersions = []struct {
esx, vmx string
}{
{"5.0", "vmx-8"},
{"5.5", "vmx-10"},
{"6.0", "vmx-11"},
{"6.5", "vmx-13"},
{"6.7", "vmx-14"},
{"7.0", "vmx-17"},
}
type create struct {
*flags.ClientFlag
*flags.ClusterFlag
*flags.DatacenterFlag
*flags.DatastoreFlag
*flags.StoragePodFlag
*flags.ResourcePoolFlag
*flags.HostSystemFlag
*flags.NetworkFlag
*flags.FolderFlag
name string
memory int
cpus int
guestID string
link bool
on bool
force bool
controller string
annotation string
firmware string
version string
iso string
isoDatastoreFlag *flags.DatastoreFlag
isoDatastore *object.Datastore
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)
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.StringVar(&cmd.annotation, "annotation", "", "VM description")
firmwareTypes := []string{
string(types.GuestOsDescriptorFirmwareTypeBios),
string(types.GuestOsDescriptorFirmwareTypeEfi),
}
f.StringVar(&cmd.firmware, "firmware", firmwareTypes[0],
fmt.Sprintf("Firmware type [%s]", strings.Join(firmwareTypes, "|")))
var versions []string
for i := range hardwareVersions {
versions = append(versions, hardwareVersions[i].esx)
}
f.StringVar(&cmd.version, "version", "",
fmt.Sprintf("ESXi hardware version [%s]", strings.Join(versions, "|")))
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
}
// 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 -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 != "" {
_, err = cmd.isoDatastoreFlag.Stat(ctx, cmd.iso)
if err != nil {
return err
}
cmd.isoDatastore, err = cmd.isoDatastoreFlag.Datastore()
if err != nil {
return err
}
}
// 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
}
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
}
func (cmd *create) createVM(ctx context.Context) (*object.Task, error) {
var devices object.VirtualDeviceList
var err error
if cmd.version != "" {
for i := range hardwareVersions {
if hardwareVersions[i].esx == cmd.version {
cmd.version = hardwareVersions[i].vmx
break
}
}
}
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,
}
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 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 {
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()),
}
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 {
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
}
disk := &types.VirtualDisk{
VirtualDevice: types.VirtualDevice{
Key: devices.NewKey(),
Backing: &types.VirtualDiskFlatVer2BackingInfo{
DiskMode: string(types.VirtualDiskModePersistent),
ThinProvisioned: types.NewBool(true),
},
},
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.isoDatastore.Path(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
}

243
vendor/github.com/vmware/govmomi/govc/vm/customize.go generated vendored Normal file
View file

@ -0,0 +1,243 @@
/*
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/govc/cli"
"github.com/vmware/govmomi/govc/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
gateway flags.StringList
netmask flags.StringList
dnsserver flags.StringList
kind 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", "IP address")
cmd.ip = 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")
cmd.dnsserver = nil
f.StringVar(&cmd.kind, "type", "Linux", "Customization type if spec NAME is not specified (Linux|Windows)")
}
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.
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
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`
}
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 cmd.domain != "" {
if isWindows {
sysprep.Identification.JoinDomain = cmd.domain
} 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, ",")...)
}
}
}
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], ",")
}
}
}
task, err := vm.Customize(ctx, *spec)
if err != nil {
return err
}
return task.Wait(ctx)
}

97
vendor/github.com/vmware/govmomi/govc/vm/destroy.go generated vendored Normal file
View file

@ -0,0 +1,97 @@
/*
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/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
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 {
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
}
err = task.Wait(ctx)
if err != nil {
return err
}
}
return nil
}

74
vendor/github.com/vmware/govmomi/govc/vm/guest/auth.go generated vendored Normal file
View file

@ -0,0 +1,74 @@
/*
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("couldn't set guest login values: %v", err)
}
usage := fmt.Sprintf("Guest VM credentials [%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 {
return nil
}
func (flag *AuthFlag) Auth() types.BaseGuestAuthentication {
return &flag.auth
}

View 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/govc/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)
}

View 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/govc/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/govc/vm/guest/df.go generated vendored Normal file
View 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/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/units"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type 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))
}

View 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/govc/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()
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)
}

View 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/govc/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
}

View 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/govc/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
}

157
vendor/github.com/vmware/govmomi/govc/vm/guest/guest.go generated vendored Normal file
View file

@ -0,0 +1,157 @@
/*
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/govc/flags"
"github.com/vmware/govmomi/guest"
"github.com/vmware/govmomi/guest/toolbox"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
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() (*toolbox.Client, error) {
pm, err := flag.ProcessManager()
if err != nil {
return nil, err
}
fm, err := flag.FileManager()
if err != nil {
return nil, err
}
vm, err := flag.VirtualMachine()
if err != nil {
return nil, err
}
family := ""
var props mo.VirtualMachine
err = vm.Properties(context.Background(), vm.Reference(), []string{"guest.guestFamily"}, &props)
if err != nil {
return nil, err
}
if props.Guest != nil {
family = props.Guest.GuestFamily
}
return &toolbox.Client{
ProcessManager: pm,
FileManager: fm,
Authentication: flag.Auth(),
GuestFamily: types.VirtualMachineGuestOsFamily(family),
}, nil
}
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/govc/vm/guest/kill.go generated vendored Normal file
View 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/govc/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/govc/vm/guest/ls.go generated vendored Normal file
View 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/govc/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
}

View file

@ -0,0 +1,83 @@
/*
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/govc/cli"
"github.com/vmware/govmomi/vim25/soap"
"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 soap.IsSoapFault(err) {
soapFault := soap.ToSoapFault(err)
if _, ok := soapFault.VimFault().(types.FileAlreadyExists); ok {
return nil
}
}
}
return err
}

View 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/govc/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
}

85
vendor/github.com/vmware/govmomi/govc/vm/guest/mv.go generated vendored Normal file
View file

@ -0,0 +1,85 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package guest
import (
"context"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/vim25/soap"
"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 soap.IsSoapFault(err) {
soapFault := soap.ToSoapFault(err)
if _, ok := soapFault.VimFault().(types.NotAFile); ok {
err = m.MoveDirectory(ctx, cmd.Auth(), src, dst)
}
}
}
return err
}

199
vendor/github.com/vmware/govmomi/govc/vm/guest/ps.go generated vendored Normal file
View file

@ -0,0 +1,199 @@
/*
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"
"io"
"strconv"
"strings"
"text/tabwriter"
"time"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/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
}
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/govc/vm/guest/rm.go generated vendored Normal file
View 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/govc/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))
}

View 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/govc/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)
}

100
vendor/github.com/vmware/govmomi/govc/vm/guest/run.go generated vendored Normal file
View file

@ -0,0 +1,100 @@
/*
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/govc/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.
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 -l root:'mypassword' -vm my_vm_hostname "ntpdate -u pool.ntp.org"`
}
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()
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/govc/vm/guest/start.go generated vendored Normal file
View 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/govc/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/govc/vm/guest/tools.go generated vendored Normal file
View 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/govc/cli"
"github.com/vmware/govmomi/govc/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/govc/vm/guest/touch.go generated vendored Normal file
View file

@ -0,0 +1,126 @@
/*
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"
"time"
"github.com/vmware/govmomi/govc/cli"
"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 && soap.IsSoapFault(err) {
fault := soap.ToSoapFault(err)
if _, ok := fault.VimFault().(types.FileNotFound); ok {
// 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
}

View 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/govc/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()
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/govc/vm/info.go generated vendored Normal file
View file

@ -0,0 +1,361 @@
/*
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"
"fmt"
"io"
"os"
"strings"
"text/tabwriter"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/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
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()
}

192
vendor/github.com/vmware/govmomi/govc/vm/ip.go generated vendored Normal file
View file

@ -0,0 +1,192 @@
/*
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"
"fmt"
"strings"
"time"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/govc/host/esxcli"
"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 := esxcli.NewGuestInfo(c)
ticker := time.NewTicker(time.Millisecond * 500)
defer ticker.Stop()
for {
select {
case <-ticker.C:
ip, err := guest.IpAddress(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/govc/vm/keystrokes.go generated vendored Normal file
View 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/govc/cli"
"github.com/vmware/govmomi/govc/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 != ""
}

View 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/govc/cli"
"github.com/vmware/govmomi/govc/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/govc/vm/markasvm.go generated vendored Normal file
View 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/govc/cli"
"github.com/vmware/govmomi/govc/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 $name -host host1
govc vm.markasvm $name -pool cluster1/Resources`
}
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
}

172
vendor/github.com/vmware/govmomi/govc/vm/migrate.go generated vendored Normal file
View file

@ -0,0 +1,172 @@
/*
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"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
)
type migrate struct {
*flags.FolderFlag
*flags.ResourcePoolFlag
*flags.HostSystemFlag
*flags.DatastoreFlag
*flags.SearchFlag
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.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)
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.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.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
}
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 {
task, err := vm.Relocate(ctx, cmd.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.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
}

214
vendor/github.com/vmware/govmomi/govc/vm/power.go generated vendored Normal file
View file

@ -0,0 +1,214 @@
/*
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/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type power struct {
*flags.ClientFlag
*flags.SearchFlag
On bool
Off bool
Reset bool
Reboot bool
Shutdown 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.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}
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 {
if soap.IsSoapFault(err) {
soapFault := soap.ToSoapFault(err)
if _, ok := soapFault.VimFault().(types.ToolsUnavailable); ok {
return ok
}
}
return false
}
// 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)
}
}
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/govc/vm/question.go generated vendored Normal file
View 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/govc/cli"
"github.com/vmware/govmomi/govc/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/govc/vm/register.go generated vendored Normal file
View 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/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type register struct {
*flags.DatastoreFlag
*flags.ResourcePoolFlag
*flags.HostSystemFlag
*flags.FolderFlag
name string
template bool
}
func init() {
cli.Register("vm.register", &register{})
}
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/govc/vm/unregister.go generated vendored Normal file
View 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/govc/cli"
"github.com/vmware/govmomi/govc/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
}

80
vendor/github.com/vmware/govmomi/govc/vm/upgrade.go generated vendored Normal file
View file

@ -0,0 +1,80 @@
package vm
import (
"context"
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/task"
"github.com/vmware/govmomi/vim25/types"
)
type upgrade struct {
*flags.VirtualMachineFlag
version int
}
func init() {
cli.Register("vm.upgrade", &upgrade{})
}
func isAlreadyUpgraded(err error) bool {
if fault, ok := err.(task.Error); ok {
_, ok = fault.Fault().(*types.AlreadyUpgraded)
return ok
}
return false
}
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 isAlreadyUpgraded(err) {
fmt.Println(err.Error())
} else {
return err
}
}
return nil
}

504
vendor/github.com/vmware/govmomi/govc/vm/vnc.go generated vendored Normal file
View 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/govc/cli"
"github.com/vmware/govmomi/govc/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
}