Merge pull request #5114 from bennu/vsphere-tpl

New post-processor vSphere Template for vmware-iso builder
This commit is contained in:
Megan Marsh 2017-09-01 09:23:54 -07:00 committed by GitHub
commit a7c18fc4e7
123 changed files with 99156 additions and 0 deletions

View File

@ -54,6 +54,7 @@ import (
vagrantpostprocessor "github.com/hashicorp/packer/post-processor/vagrant"
vagrantcloudpostprocessor "github.com/hashicorp/packer/post-processor/vagrant-cloud"
vspherepostprocessor "github.com/hashicorp/packer/post-processor/vsphere"
vspheretemplatepostprocessor "github.com/hashicorp/packer/post-processor/vsphere-template"
ansibleprovisioner "github.com/hashicorp/packer/provisioner/ansible"
ansiblelocalprovisioner "github.com/hashicorp/packer/provisioner/ansible-local"
chefclientprovisioner "github.com/hashicorp/packer/provisioner/chef-client"
@ -136,6 +137,7 @@ var PostProcessors = map[string]packer.PostProcessor{
"vagrant": new(vagrantpostprocessor.PostProcessor),
"vagrant-cloud": new(vagrantcloudpostprocessor.PostProcessor),
"vsphere": new(vspherepostprocessor.PostProcessor),
"vsphere-template": new(vspheretemplatepostprocessor.PostProcessor),
}
var pluginRegexp = regexp.MustCompile("packer-(builder|post-processor|provisioner)-(.+)")

View File

@ -0,0 +1,132 @@
package vsphere_template
import (
"context"
"fmt"
"net/url"
"strings"
"time"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
"github.com/mitchellh/multistep"
"github.com/vmware/govmomi"
)
var builtins = map[string]string{
"mitchellh.vmware-esx": "vmware",
}
type Config struct {
common.PackerConfig `mapstructure:",squash"`
Host string `mapstructure:"host"`
Insecure bool `mapstructure:"insecure"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
Datacenter string `mapstructure:"datacenter"`
Folder string `mapstructure:"folder"`
ctx interpolate.Context
}
type PostProcessor struct {
config Config
url *url.URL
}
func (p *PostProcessor) Configure(raws ...interface{}) error {
err := config.Decode(&p.config, &config.DecodeOpts{
Interpolate: true,
InterpolateContext: &p.config.ctx,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{},
},
}, raws...)
if err != nil {
return err
}
errs := new(packer.MultiError)
vc := map[string]*string{
"host": &p.config.Host,
"username": &p.config.Username,
"password": &p.config.Password,
}
for key, ptr := range vc {
if *ptr == "" {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("%s must be set", key))
}
}
if p.config.Folder != "" && !strings.HasPrefix(p.config.Folder, "/") {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("Folder must be bound to the root"))
}
sdk, err := url.Parse(fmt.Sprintf("https://%v/sdk", p.config.Host))
if err != nil {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("Error invalid vSphere sdk endpoint: %s", err))
}
sdk.User = url.UserPassword(p.config.Username, p.config.Password)
p.url = sdk
if len(errs.Errors) > 0 {
return errs
}
return nil
}
func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
if _, ok := builtins[artifact.BuilderId()]; !ok {
return nil, false, fmt.Errorf("Unknown artifact type, can't build box: %s", artifact.BuilderId())
}
source := ""
for _, path := range artifact.Files() {
if strings.HasSuffix(path, ".vmx") {
source = path
break
}
}
// In some occasions the VM state is powered on and if we immediately try to mark as template
// (after the ESXi creates it) it will fail. If vSphere is given a few seconds this behavior doesn't reappear.
ui.Message("Waiting 10s for VMware vSphere to start")
time.Sleep(10 * time.Second)
c, err := govmomi.NewClient(context.Background(), p.url, p.config.Insecure)
if err != nil {
return nil, false, fmt.Errorf("Error connecting to vSphere: %s", err)
}
defer c.Logout(context.Background())
state := new(multistep.BasicStateBag)
state.Put("ui", ui)
state.Put("client", c)
steps := []multistep.Step{
&stepChooseDatacenter{
Datacenter: p.config.Datacenter,
},
&stepCreateFolder{
Folder: p.config.Folder,
},
&stepMarkAsTemplate{
VMName: artifact.Id(),
Source: source,
},
}
runner := common.NewRunnerWithPauseFn(steps, p.config.PackerConfig, ui, state)
runner.Run(state)
if rawErr, ok := state.GetOk("error"); ok {
return nil, false, rawErr.(error)
}
return artifact, true, nil
}

View File

@ -0,0 +1,35 @@
package vsphere_template
import (
"context"
"github.com/hashicorp/packer/packer"
"github.com/mitchellh/multistep"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/find"
)
type stepChooseDatacenter struct {
Datacenter string
}
func (s *stepChooseDatacenter) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
cli := state.Get("client").(*govmomi.Client)
finder := find.NewFinder(cli.Client, false)
ui.Message("Choosing datacenter...")
dc, err := finder.DatacenterOrDefault(context.Background(), s.Datacenter)
if err != nil {
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
state.Put("dcPath", dc.InventoryPath)
return multistep.ActionContinue
}
func (s *stepChooseDatacenter) Cleanup(multistep.StateBag) {}

View File

@ -0,0 +1,86 @@
package vsphere_template
import (
"context"
"fmt"
"path"
"github.com/hashicorp/packer/packer"
"github.com/mitchellh/multistep"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/object"
)
type stepCreateFolder struct {
Folder string
}
func (s *stepCreateFolder) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
cli := state.Get("client").(*govmomi.Client)
dcPath := state.Get("dcPath").(string)
ui.Message("Creating or checking destination folders...")
base := path.Join(dcPath, "vm")
fullPath := path.Join(base, s.Folder)
si := object.NewSearchIndex(cli.Client)
var folders []string
var err error
var ref object.Reference
// We iterate over the path starting with full path
// If we don't find it, we save the folder name and continue with the previous path
// The iteration ends when we find an existing path otherwise it throws error
for {
ref, err = si.FindByInventoryPath(context.Background(), fullPath)
if err != nil {
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
if ref == nil {
dir, folder := path.Split(fullPath)
fullPath = path.Clean(dir)
if fullPath == dcPath {
err = fmt.Errorf("vSphere base path %s not found", base)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
folders = append(folders, folder)
} else {
break
}
}
if root, ok := ref.(*object.Folder); ok {
for i := len(folders) - 1; i >= 0; i-- {
ui.Message(fmt.Sprintf("Creating folder: %v", folders[i]))
root, err = root.CreateFolder(context.Background(), folders[i])
if err != nil {
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
fullPath = path.Join(fullPath, folders[i])
}
root.SetInventoryPath(fullPath)
state.Put("folder", root)
} else {
err = fmt.Errorf("folder not found: '%v'", ref)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
return multistep.ActionContinue
}
func (s *stepCreateFolder) Cleanup(multistep.StateBag) {}

View File

@ -0,0 +1,118 @@
package vsphere_template
import (
"context"
"fmt"
"path"
"strings"
"github.com/hashicorp/packer/packer"
"github.com/mitchellh/multistep"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/object"
)
type stepMarkAsTemplate struct {
VMName string
Source string
}
func (s *stepMarkAsTemplate) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
cli := state.Get("client").(*govmomi.Client)
folder := state.Get("folder").(*object.Folder)
dcPath := state.Get("dcPath").(string)
ui.Message("Marking as a template...")
vm, err := findRuntimeVM(cli, dcPath, s.VMName)
if err != nil {
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
host, err := vm.HostSystem(context.Background())
if err != nil {
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
if err := vm.Unregister(context.Background()); err != nil {
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
source := strings.Split(s.Source, "/vmfs/volumes/")[1]
i := strings.Index(source, "/")
path := (&object.DatastorePath{
Datastore: source[:i],
Path: source[i:],
}).String()
if err := unregisterPreviousVM(cli, folder, s.VMName); err != nil {
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
task, err := folder.RegisterVM(context.Background(), path, s.VMName, true, nil, host)
if err != nil {
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
if err = task.Wait(context.Background()); err != nil {
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
return multistep.ActionContinue
}
// We will use the virtual machine created by vmware-iso builder
func findRuntimeVM(cli *govmomi.Client, dcPath, name string) (*object.VirtualMachine, error) {
si := object.NewSearchIndex(cli.Client)
fullPath := path.Join(dcPath, "vm", "Discovered virtual machine", name)
ref, err := si.FindByInventoryPath(context.Background(), fullPath)
if err != nil {
return nil, err
}
if ref == nil {
return nil, fmt.Errorf("VM at path %s not found", fullPath)
}
return ref.(*object.VirtualMachine), nil
}
// If in the target folder a virtual machine or template already exists
// it will be removed to maintain consistency
func unregisterPreviousVM(cli *govmomi.Client, folder *object.Folder, name string) error {
si := object.NewSearchIndex(cli.Client)
fullPath := path.Join(folder.InventoryPath, name)
ref, err := si.FindByInventoryPath(context.Background(), fullPath)
if err != nil {
return err
}
if ref != nil {
if vm, ok := ref.(*object.VirtualMachine); ok {
return vm.Unregister(context.Background())
} else {
return fmt.Errorf("an object name '%v' already exists", name)
}
}
return nil
}
func (s *stepMarkAsTemplate) Cleanup(multistep.StateBag) {}

263
vendor/github.com/vmware/govmomi/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,263 @@
# changelog
### 0.15.0 (2017-06-19)
* WaitOptions.MaxWaitSeconds is now optional
* Support removal of ExtraConfig entries
* GuestPosixFileAttributes OwnerId and GroupId fields are now pointers,
rather than omitempty ints to allow chown with root uid:gid
* Updated examples/ using view package
* Add DatastoreFile.TailFunc method
* Export VirtualMachine.FindSnapshot method
* Add AuthorizationManager {Enable,Disable}Methods
* Add PBM client
### 0.14.0 (2017-04-08)
* Add view.ContainerView type and methods
* Add Collector.RetrieveWithFilter method
* Add property.Filter type
* Implement EthernetCardBackingInfo for OpaqueNetwork
* Finder: support changing object root in find mode
* Add VirtualDiskManager.QueryVirtualDiskInfo
* Add performance.Manager APIs
### 0.13.0 (2017-03-02)
* Add DatastoreFileManager API wrapper
* Add HostVsanInternalSystem API wrappers
* Add Container support to view package
* Finder supports Folder recursion without specifying a path
* Add VirtualMachine.QueryConfigTarget method
* Add device option to VirtualMachine.WaitForNetIP
* Remove _Task suffix from vapp methods
### 0.12.1 (2016-12-19)
* Add DiagnosticLog helper
* Add DatastorePath helper
### 0.12.0 (2016-12-01)
* Disable use of service ticket for datastore HTTP access by default
* Attach context to HTTP requests for cancellations
* Update to vim25/6.5 API
### 0.11.4 (2016-11-15)
* Add object.AuthorizationManager methods: RetrieveRolePermissions, RetrieveAllPermissions, AddRole, RemoveRole, UpdateRole
### 0.11.3 (2016-11-08)
* Allow DatastoreFile.Follow reader to drain current body after stopping
### 0.11.2 (2016-11-01)
* Avoid possible NPE in VirtualMachine.Device method
* Add support for OpaqueNetwork type to Finder
* Add HostConfigManager.AccountManager support for ESX 5.5
### 0.11.1 (2016-10-27)
* Add Finder.ResourcePoolListAll method
### 0.11.0 (2016-10-25)
* Add object.DistributedVirtualPortgroup.Reconfigure method
### 0.10.0 (2016-10-20)
* Add option to set soap.Client.UserAgent
* Add service ticket thumbprint validation
* Update use of http.DefaultTransport fields to 1.7
* Set default locale to en_US (override with GOVMOMI_LOCALE env var)
* Add object.HostCertificateInfo (types.HostCertificateManagerCertificateInfo helpers)
* Add object.HostCertificateManager type and HostConfigManager.CertificateManager method
* Add soap.Client SetRootCAs and SetDialTLS methods
### 0.9.0 (2016-09-09)
* Add object.DatastoreFile helpers for streaming and tailing datastore files
* Add object VirtualMachine.Unregister method
* Add object.ListView methods: Add, Remove, Reset
* Update to Go 1.7 - using stdlib's context package
### 0.8.0 (2016-06-30)
* Add session.Manager.AcquireLocalTicket
* Include StoragePod in Finder.FolderList
* Add Finder methods for finding by ManagedObjectReference: Element, ObjectReference
* Add mo.ManagedObjectReference methods: Reference, String, FromString
* Add support using SessionManagerGenericServiceTicket.HostName for Datastore HTTP access
### 0.7.1 (2016-06-03)
* Fix object.ObjectName method
### 0.7.0 (2016-06-02)
* Move InventoryPath field to object.Common
* Add HostDatastoreSystem.CreateLocalDatastore method
* Add DatastoreNamespaceManager methods: CreateDirectory, DeleteDirectory
* Add HostServiceSystem
* Add HostStorageSystem methods: MarkAsSdd, MarkAsNonSdd, MarkAsLocal, MarkAsNonLocal
* Add HostStorageSystem.RescanAllHba method
### 0.6.2 (2016-05-11)
* Get complete file details in Datastore.Stat
* SOAP decoding fixes
* Add VirtualMachine.RemoveAllSnapshot
### 0.6.1 (2016-04-30)
* Fix mo.Entity interface
### 0.6.0 (2016-04-29)
* Add Common.Rename method
* Add mo.Entity interface
* Add OptionManager
* Add Finder.FolderList method
* Add VirtualMachine.WaitForNetIP method
* Add VirtualMachine.RevertToSnapshot method
* Add Datastore.Download method
### 0.5.0 (2016-03-30)
Generated fields using xsd type 'int' change to Go type 'int32'
VirtualDevice.UnitNumber field changed to pointer type
### 0.4.0 (2016-02-26)
* Add method to convert virtual device list to array with virtual device
changes that can be used in the VirtualMachineConfigSpec.
* Make datastore cluster traversable in lister
* Add finder.DatastoreCluster methods (also known as storage pods)
* Add Drone CI check
* Add object.Datastore Type and AttachedClusterHosts methods
* Add finder.*OrDefault methods
### 0.3.0 (2016-01-16)
* Add object.VirtualNicManager wrapper
* Add object.HostVsanSystem wrapper
* Add object.HostSystem methods: EnterMaintenanceMode, ExitMaintenanceMode, Disconnect, Reconnect
* Add finder.Folder method
* Add object.Common.Destroy method
* Add object.ComputeResource.Reconfigure method
* Add license.AssignmentManager wrapper
* Add object.HostFirewallSystem wrapper
* Add object.DiagnosticManager wrapper
* Add LoginExtensionByCertificate support
* Add object.ExtensionManager
...
### 0.2.0 (2015-09-15)
* Update to vim25/6.0 API
* Stop returning children from `ManagedObjectList`
Change the `ManagedObjectList` function in the `find` package to only
return the managed objects specified by the path argument and not their
children. The original behavior was used by govc's `ls` command and is
now available in the newly added function `ManagedObjectListChildren`.
* Add retry functionality to vim25 package
* Change finder functions to no longer take varargs
The `find` package had functions to return a list of objects, given a
variable number of patterns. This makes it impossible to distinguish which
patterns produced results and which ones didn't.
In particular for govc, where multiple arguments can be passed from the
command line, it is useful to let the user know which ones produce results
and which ones don't.
To evaluate multiple patterns, the user should call the find functions
multiple times (either serially or in parallel).
* Make optional boolean fields pointers (`vim25/types`).
False is the zero value of a boolean field, which means they are not serialized
if the field is marked "omitempty". If the field is a pointer instead, the zero
value will be the nil pointer, and both true and false values are serialized.
### 0.1.0 (2015-03-17)
Prior to this version the API of this library was in flux.
Notable changes w.r.t. the state of this library before March 2015 are:
* All functions that may execute a request take a `context.Context` parameter.
* The `vim25` package contains a minimal client implementation.
* The property collector and its convenience functions live in the `property` package.

101
vendor/github.com/vmware/govmomi/CONTRIBUTING.md generated vendored Normal file
View File

@ -0,0 +1,101 @@
# Contributing to govmomi
## Getting started
First, fork the repository on GitHub to your personal account.
Note that _GOPATH_ can be any directory, the example below uses _$HOME/govmomi_.
Change _$USER_ below to your github username if they are not the same.
``` shell
export GOPATH=$HOME/govmomi
go get github.com/vmware/govmomi
cd $GOPATH/src/github.com/vmware/govmomi
git config push.default nothing # anything to avoid pushing to vmware/govmomi by default
git remote rename origin vmware
git remote add $USER git@github.com:$USER/govmomi.git
git fetch $USER
```
## Installing from source
Compile the govmomi libraries and install govc using:
``` shell
go install -v github.com/vmware/govmomi/govc
```
Note that **govc/build.sh** is only used for building release binaries.
## Contribution flow
This is a rough outline of what a contributor's workflow looks like:
- Create a topic branch from where you want to base your work.
- Make commits of logical units.
- Make sure your commit messages are in the proper format (see below).
- Update CHANGELOG.md and/or govc/CHANGELOG.md when appropriate.
- Push your changes to a topic branch in your fork of the repository.
- Submit a pull request to vmware/govmomi.
Example:
``` shell
git checkout -b my-new-feature vmware/master
git commit -a
git push $USER my-new-feature
```
### Stay in sync with upstream
When your branch gets out of sync with the vmware/master branch, use the following to update:
``` shell
git checkout my-new-feature
git fetch -a
git rebase vmware/master
git push --force-with-lease $USER my-new-feature
```
### Updating pull requests
If your PR fails to pass CI or needs changes based on code review, you'll most likely want to squash these changes into
existing commits.
If your pull request contains a single commit or your changes are related to the most recent commit, you can simply
amend the commit.
``` shell
git add .
git commit --amend
git push --force-with-lease $USER my-new-feature
```
If you need to squash changes into an earlier commit, you can use:
``` shell
git add .
git commit --fixup <commit>
git rebase -i --autosquash vmware/master
git push --force-with-lease $USER my-new-feature
```
Be sure to add a comment to the PR indicating your new changes are ready to review, as github does not generate a
notification when you git push.
### Code style
The coding style suggested by the Golang community is used in govmomi. See the
[style doc](https://github.com/golang/go/wiki/CodeReviewComments) for details.
Try to limit column width to 120 characters for both code and markdown documents such as this one.
### Format of the Commit Message
We follow the conventions on [How to Write a Git Commit Message](http://chris.beams.io/posts/git-commit/).
Be sure to include any related GitHub issue references in the commit message.
## Reporting Bugs and Creating Issues
When opening a new issue, try to roughly follow the commit message format conventions above.

61
vendor/github.com/vmware/govmomi/CONTRIBUTORS generated vendored Normal file
View File

@ -0,0 +1,61 @@
# People who can (and typically have) contributed to this repository.
#
# This script is generated by contributors.sh
#
abrarshivani <abrarshivani@users.noreply.github.com>
Alvaro Miranda <kikitux@gmail.com>
amandahla <amanda.andrade@serpro.gov.br>
Amit Bathla <abathla@.vmware.com>
Andrew Chin <andrew@andrewtchin.com>
aniketGslab <aniket.shinde@gslab.com>
Arran Walker <arran.walker@zopa.com>
Aryeh Weinreb <aryehweinreb@gmail.com>
Austin Parker <aparker@apprenda.com>
Balu Dontu <bdontu@vmware.com>
bastienbc <bastien.barbe.creuly@gmail.com>
Bob Killen <killen.bob@gmail.com>
Brad Fitzpatrick <bradfitz@golang.org>
Bruce Downs <bruceadowns@gmail.com>
Cédric Blomart <cblomart@gmail.com>
Christian Höltje <docwhat@gerf.org>
Clint Greenwood <cgreenwood@vmware.com>
Danny Lockard <danny.lockard@banno.com>
Dave Tucker <dave@dtucker.co.uk>
Davide Agnello <dagnello@hp.com>
David Stark <dave@davidstark.name>
Doug MacEachern <dougm@vmware.com>
Eloy Coto <eloy.coto@gmail.com>
Eric Gray <egray@vmware.com>
Eric Yutao <eric.yutao@gmail.com>
Fabio Rapposelli <fabio@vmware.com>
Faiyaz Ahmed <ahmedf@vmware.com>
forkbomber <forkbomber@users.noreply.github.com>
Gavin Gray <gavin@infinio.com>
Gavrie Philipson <gavrie.philipson@elastifile.com>
George Hicken <ghicken@vmware.com>
Gerrit Renker <Gerrit.Renker@ctl.io>
gthombare <gthombare@vmware.com>
Hasan Mahmood <mahmoodh@vmware.com>
Henrik Hodne <henrik@travis-ci.com>
Isaac Rodman <isaac@eyz.us>
Ivan Porto Carrero <icarrero@vmware.com>
Jason Kincl <jkincl@gmail.com>
Jeremy Canady <jcanady@jackhenry.com>
Louie Jiang <jiangl@vmware.com>
Marc Carmier <mcarmier@gmail.com>
Mevan Samaratunga <mevansam@gmail.com>
Nicolas Lamirault <nicolas.lamirault@gmail.com>
Pieter Noordhuis <pnoordhuis@vmware.com>
runner.mei <runner.mei@gmail.com>
S.Çağlar Onur <conur@vmware.com>
Sergey Ignatov <sergey.ignatov@jetbrains.com>
Steve Purcell <steve@sanityinc.com>
Takaaki Furukawa <takaaki.frkw@gmail.com>
Ted Zlatanov <tzz@lifelogs.com>
Thibaut Ackermann <thibaut.ackermann@alcatel-lucent.com>
Vadim Egorov <vegorov@vmware.com>
Yang Yang <yangy@vmware.com>
Yuya Kusakabe <yuya.kusakabe@gmail.com>
Zach Tucker <ztucker@vmware.com>
Zee Yang <zeey@vmware.com>

202
vendor/github.com/vmware/govmomi/LICENSE.txt generated vendored Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

24
vendor/github.com/vmware/govmomi/Makefile generated vendored Normal file
View File

@ -0,0 +1,24 @@
.PHONY: test
all: check test
check: goimports govet
goimports:
@echo checking go imports...
@go get golang.org/x/tools/cmd/goimports
@! goimports -d . 2>&1 | egrep -v '^$$'
govet:
@echo checking go vet...
@go tool vet -structtags=false -methods=false $$(find . -mindepth 1 -maxdepth 1 -type d -not -name vendor)
test:
go test -v $(TEST_OPTS) ./...
install:
go install -v github.com/vmware/govmomi/govc
go install -v github.com/vmware/govmomi/vcsim
doc: install
./govc/usage.sh > ./govc/USAGE.md

78
vendor/github.com/vmware/govmomi/README.md generated vendored Normal file
View File

@ -0,0 +1,78 @@
[![Build Status](https://travis-ci.org/vmware/govmomi.png?branch=master)](https://travis-ci.org/vmware/govmomi)
[![Go Report Card](https://goreportcard.com/badge/github.com/vmware/govmomi)](https://goreportcard.com/report/github.com/vmware/govmomi)
# govmomi
A Go library for interacting with VMware vSphere APIs (ESXi and/or vCenter).
For `govc`, a CLI built on top of govmomi, check out the [govc](./govc) directory and [USAGE](./govc/USAGE.md) document.
## Compatibility
This library is built for and tested against ESXi and vCenter 5.5, 6.0 and 6.5.
If you're able to use it against older versions of ESXi and/or vCenter, please
leave a note and we'll include it in this compatibility list.
## Documentation
The APIs exposed by this library very closely follow the API described in the [VMware vSphere API Reference Documentation][apiref].
Refer to this document to become familiar with the upstream API.
The code in the `govmomi` package is a wrapper for the code that is generated from the vSphere API description.
It primarily provides convenience functions for working with the vSphere API.
See [godoc.org][godoc] for documentation.
[apiref]:http://pubs.vmware.com/vsphere-6-5/index.jsp#com.vmware.wssdk.apiref.doc/right-pane.html
[godoc]:http://godoc.org/github.com/vmware/govmomi
[drone]:https://drone.io
[dronesrc]:https://github.com/drone/drone
[dronecli]:http://readme.drone.io/devs/cli/
#### Building with CI
Merges to this repository will trigger builds in both Travis and [Drone][drone].
To build locally with Drone:
- Ensure that you have Docker 1.6 or higher installed.
- Install the [Drone command line tools][dronecli].
- Run `drone exec` from within the root directory of the govmomi repository.
## Discussion
Contributors and users are encouraged to collaborate using GitHub issues and/or
[Slack](https://vmwarecode.slack.com/messages/govmomi).
Access to Slack requires a [VMware {code} membership](https://code.vmware.com/join/).
## Status
Changes to the API are subject to [semantic versioning](http://semver.org).
Refer to the [CHANGELOG](CHANGELOG.md) for version to version changes.
## Projects using govmomi
* [Docker Machine](https://github.com/docker/machine/tree/master/drivers/vmwarevsphere)
* [Kubernetes](https://github.com/kubernetes/kubernetes/tree/master/pkg/cloudprovider/providers/vsphere)
* [Terraform](https://github.com/hashicorp/terraform/tree/master/builtin/providers/vsphere)
* [VMware VIC Engine](https://github.com/vmware/vic)
* [Travis CI](https://github.com/travis-ci/jupiter-brain)
* [collectd-vsphere](https://github.com/travis-ci/collectd-vsphere)
* [Gru](https://github.com/dnaeon/gru)
* [Libretto](https://github.com/apcera/libretto/tree/master/virtualmachine/vsphere)
## Related projects
* [rbvmomi](https://github.com/vmware/rbvmomi)
* [pyvmomi](https://github.com/vmware/pyvmomi)
## License
govmomi is available under the [Apache 2 license](LICENSE).

167
vendor/github.com/vmware/govmomi/client.go generated vendored Normal file
View File

@ -0,0 +1,167 @@
/*
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.
*/
/*
This package is the root package of the govmomi library.
The library is structured as follows:
Package vim25
The minimal usable functionality is available through the vim25 package.
It contains subpackages that contain generated types, managed objects, and all
available methods. The vim25 package is entirely independent of the other
packages in the govmomi tree -- it has no dependencies on its peers.
The vim25 package itself contains a client structure that is
passed around throughout the entire library. It abstracts a session and its
immutable state. See the vim25 package for more information.
Package session
The session package contains an abstraction for the session manager that allows
a user to login and logout. It also provides access to the current session
(i.e. to determine if the user is in fact logged in)
Package object
The object package contains wrappers for a selection of managed objects. The
constructors of these objects all take a *vim25.Client, which they pass along
to derived objects, if applicable.
Package govc
The govc package contains the govc CLI. The code in this tree is not intended
to be used as a library. Any functionality that govc contains that _could_ be
used as a library function but isn't, _should_ live in a root level package.
Other packages
Other packages, such as "event", "guest", or "license", provide wrappers for
the respective subsystems. They are typically not needed in normal workflows so
are kept outside the object package.
*/
package govmomi
import (
"context"
"crypto/tls"
"net/url"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/session"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type Client struct {
*vim25.Client
SessionManager *session.Manager
}
// NewClient creates a new client from a URL. The client authenticates with the
// server with username/password before returning if the URL contains user information.
func NewClient(ctx context.Context, u *url.URL, insecure bool) (*Client, error) {
soapClient := soap.NewClient(u, insecure)
vimClient, err := vim25.NewClient(ctx, soapClient)
if err != nil {
return nil, err
}
c := &Client{
Client: vimClient,
SessionManager: session.NewManager(vimClient),
}
// Only login if the URL contains user information.
if u.User != nil {
err = c.Login(ctx, u.User)
if err != nil {
return nil, err
}
}
return c, nil
}
// NewClientWithCertificate creates a new client from a URL. The client authenticates with the
// server with the certificate before returning if the URL contains user information.
func NewClientWithCertificate(ctx context.Context, u *url.URL, insecure bool, cert tls.Certificate) (*Client, error) {
soapClient := soap.NewClient(u, insecure)
soapClient.SetCertificate(cert)
vimClient, err := vim25.NewClient(ctx, soapClient)
if err != nil {
return nil, err
}
c := &Client{
Client: vimClient,
SessionManager: session.NewManager(vimClient),
}
if u.User != nil {
err = c.LoginExtensionByCertificate(ctx, u.User.Username(), "")
if err != nil {
return nil, err
}
}
return c, nil
}
// Login dispatches to the SessionManager.
func (c *Client) Login(ctx context.Context, u *url.Userinfo) error {
return c.SessionManager.Login(ctx, u)
}
// Login dispatches to the SessionManager.
func (c *Client) LoginExtensionByCertificate(ctx context.Context, key string, locale string) error {
return c.SessionManager.LoginExtensionByCertificate(ctx, key, locale)
}
// Logout dispatches to the SessionManager.
func (c *Client) Logout(ctx context.Context) error {
// Close any idle connections after logging out.
defer c.Client.CloseIdleConnections()
return c.SessionManager.Logout(ctx)
}
// PropertyCollector returns the session's default property collector.
func (c *Client) PropertyCollector() *property.Collector {
return property.DefaultCollector(c.Client)
}
// RetrieveOne dispatches to the Retrieve function on the default property collector.
func (c *Client) RetrieveOne(ctx context.Context, obj types.ManagedObjectReference, p []string, dst interface{}) error {
return c.PropertyCollector().RetrieveOne(ctx, obj, p, dst)
}
// Retrieve dispatches to the Retrieve function on the default property collector.
func (c *Client) Retrieve(ctx context.Context, objs []types.ManagedObjectReference, p []string, dst interface{}) error {
return c.PropertyCollector().Retrieve(ctx, objs, p, dst)
}
// Wait dispatches to property.Wait.
func (c *Client) Wait(ctx context.Context, obj types.ManagedObjectReference, ps []string, f func([]types.PropertyChange) bool) error {
return property.Wait(ctx, c.PropertyCollector(), obj, ps, f)
}
// IsVC returns true if we are connected to a vCenter
func (c *Client) IsVC() bool {
return c.Client.IsVC()
}

37
vendor/github.com/vmware/govmomi/find/doc.go generated vendored Normal file
View File

@ -0,0 +1,37 @@
/*
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 find implements inventory listing and searching.
The Finder is an alternative to the object.SearchIndex FindByInventoryPath() and FindChild() methods.
SearchIndex.FindByInventoryPath requires an absolute path, whereas the Finder also supports relative paths
and patterns via path.Match.
SearchIndex.FindChild requires a parent to find the child, whereas the Finder also supports an ancestor via
recursive object traversal.
The various Finder methods accept a "path" argument, which can absolute or relative to the Folder for the object type.
The Finder supports two modes, "list" and "find". The "list" mode behaves like the "ls" command, only searching within
the immediate path. The "find" mode behaves like the "find" command, with the search starting at the immediate path but
also recursing into sub Folders relative to the Datacenter. The default mode is "list" if the given path contains a "/",
otherwise "find" mode is used.
The exception is to use a "..." wildcard with a path to find all objects recursively underneath any root object.
For example: VirtualMachineList("/DC1/...")
See also: https://github.com/vmware/govmomi/blob/master/govc/README.md#usage
*/
package find

64
vendor/github.com/vmware/govmomi/find/error.go generated vendored Normal file
View File

@ -0,0 +1,64 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package find
import "fmt"
type NotFoundError struct {
kind string
path string
}
func (e *NotFoundError) Error() string {
return fmt.Sprintf("%s '%s' not found", e.kind, e.path)
}
type MultipleFoundError struct {
kind string
path string
}
func (e *MultipleFoundError) Error() string {
return fmt.Sprintf("path '%s' resolves to multiple %ss", e.path, e.kind)
}
type DefaultNotFoundError struct {
kind string
}
func (e *DefaultNotFoundError) Error() string {
return fmt.Sprintf("no default %s found", e.kind)
}
type DefaultMultipleFoundError struct {
kind string
}
func (e DefaultMultipleFoundError) Error() string {
return fmt.Sprintf("default %s resolves to multiple instances, please specify", e.kind)
}
func toDefaultError(err error) error {
switch e := err.(type) {
case *NotFoundError:
return &DefaultNotFoundError{e.kind}
case *MultipleFoundError:
return &DefaultMultipleFoundError{e.kind}
default:
return err
}
}

1021
vendor/github.com/vmware/govmomi/find/finder.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

253
vendor/github.com/vmware/govmomi/find/recurser.go generated vendored Normal file
View File

@ -0,0 +1,253 @@
/*
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 find
import (
"context"
"os"
"path"
"strings"
"github.com/vmware/govmomi/list"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25/mo"
)
// spec is used to specify per-search configuration, independent of the Finder instance.
type spec struct {
// Relative returns the root object to resolve Relative paths (starts with ".")
Relative func(ctx context.Context) (object.Reference, error)
// ListMode can be used to optionally force "ls" behavior, rather than "find" behavior
ListMode *bool
// Contents configures the Recurser to list the Contents of traversable leaf nodes.
// This is typically set to true when used from the ls command, where listing
// a folder means listing its Contents. This is typically set to false for
// commands that take managed entities that are not folders as input.
Contents bool
// Parents specifies the types which can contain the child types being searched for.
// for example, when searching for a HostSystem, parent types can be
// "ComputeResource" or "ClusterComputeResource".
Parents []string
// Include specifies which types to be included in the results, used only in "find" mode.
Include []string
// Nested should be set to types that can be Nested, used only in "find" mode.
Nested []string
// ChildType avoids traversing into folders that can't contain the Include types, used only in "find" mode.
ChildType []string
}
func (s *spec) traversable(o mo.Reference) bool {
ref := o.Reference()
switch ref.Type {
case "Datacenter":
if len(s.Include) == 1 && s.Include[0] == "Datacenter" {
// No point in traversing deeper as Datacenters cannot be nested
return false
}
return true
case "Folder":
if f, ok := o.(mo.Folder); ok {
// TODO: Not making use of this yet, but here we can optimize when searching the entire
// inventory across Datacenters for specific types, for example: 'govc ls -t VirtualMachine /**'
// should not traverse into a Datacenter's host, network or datatore folders.
if !s.traversableChildType(f.ChildType) {
return false
}
}
return true
}
for _, kind := range s.Parents {
if kind == ref.Type {
return true
}
}
return false
}
func (s *spec) traversableChildType(ctypes []string) bool {
if len(s.ChildType) == 0 {
return true
}
for _, t := range ctypes {
for _, c := range s.ChildType {
if t == c {
return true
}
}
}
return false
}
func (s *spec) wanted(e list.Element) bool {
if len(s.Include) == 0 {
return true
}
w := e.Object.Reference().Type
for _, kind := range s.Include {
if w == kind {
return true
}
}
return false
}
// listMode is a global option to revert to the original Finder behavior,
// disabling the newer "find" mode.
var listMode = os.Getenv("GOVMOMI_FINDER_LIST_MODE") == "true"
func (s *spec) listMode(isPath bool) bool {
if listMode {
return true
}
if s.ListMode != nil {
return *s.ListMode
}
return isPath
}
type recurser struct {
Collector *property.Collector
// All configures the recurses to fetch complete objects for leaf nodes.
All bool
}
func (r recurser) List(ctx context.Context, s *spec, root list.Element, parts []string) ([]list.Element, error) {
if len(parts) == 0 {
// Include non-traversable leaf elements in result. For example, consider
// the pattern "./vm/my-vm-*", where the pattern should match the VMs and
// not try to traverse them.
//
// Include traversable leaf elements in result, if the contents
// field is set to false.
//
if !s.Contents || !s.traversable(root.Object.Reference()) {
return []list.Element{root}, nil
}
}
k := list.Lister{
Collector: r.Collector,
Reference: root.Object.Reference(),
Prefix: root.Path,
}
if r.All && len(parts) < 2 {
k.All = true
}
in, err := k.List(ctx)
if err != nil {
return nil, err
}
// This folder is a leaf as far as the glob goes.
if len(parts) == 0 {
return in, nil
}
all := parts
pattern := parts[0]
parts = parts[1:]
var out []list.Element
for _, e := range in {
matched, err := path.Match(pattern, path.Base(e.Path))
if err != nil {
return nil, err
}
if !matched {
matched = strings.HasSuffix(e.Path, path.Join(all...))
if matched {
// name contains a '/'
out = append(out, e)
}
continue
}
nres, err := r.List(ctx, s, e, parts)
if err != nil {
return nil, err
}
out = append(out, nres...)
}
return out, nil
}
func (r recurser) Find(ctx context.Context, s *spec, root list.Element, parts []string) ([]list.Element, error) {
var out []list.Element
if len(parts) > 0 {
pattern := parts[0]
matched, err := path.Match(pattern, path.Base(root.Path))
if err != nil {
return nil, err
}
if matched && s.wanted(root) {
out = append(out, root)
}
}
if !s.traversable(root.Object) {
return out, nil
}
k := list.Lister{
Collector: r.Collector,
Reference: root.Object.Reference(),
Prefix: root.Path,
}
in, err := k.List(ctx)
if err != nil {
return nil, err
}
for _, e := range in {
nres, err := r.Find(ctx, s, e, parts)
if err != nil {
return nil, err
}
out = append(out, nres...)
}
return out, nil
}

563
vendor/github.com/vmware/govmomi/list/lister.go generated vendored Normal file
View File

@ -0,0 +1,563 @@
/*
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 list
import (
"context"
"fmt"
"path"
"reflect"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type Element struct {
Path string
Object mo.Reference
}
func (e Element) String() string {
return fmt.Sprintf("%s @ %s", e.Object.Reference(), e.Path)
}
func ToElement(r mo.Reference, prefix string) Element {
var name string
// Comments about types to be expected in folders copied from the
// documentation of the Folder managed object:
// http://pubs.vmware.com/vsphere-55/topic/com.vmware.wssdk.apiref.doc/vim.Folder.html
switch m := r.(type) {
case mo.Folder:
name = m.Name
case mo.StoragePod:
name = m.Name
// { "vim.Datacenter" } - Identifies the root folder and its descendant
// folders. Data center folders can contain child data center folders and
// Datacenter managed objects. Datacenter objects contain virtual machine,
// compute resource, network entity, and datastore folders.
case mo.Datacenter:
name = m.Name
// { "vim.Virtualmachine", "vim.VirtualApp" } - Identifies a virtual machine
// folder. A virtual machine folder may contain child virtual machine
// folders. It also can contain VirtualMachine managed objects, templates,
// and VirtualApp managed objects.
case mo.VirtualMachine:
name = m.Name
case mo.VirtualApp:
name = m.Name
// { "vim.ComputeResource" } - Identifies a compute resource
// folder, which contains child compute resource folders and ComputeResource
// hierarchies.
case mo.ComputeResource:
name = m.Name
case mo.ClusterComputeResource:
name = m.Name
case mo.HostSystem:
name = m.Name
case mo.ResourcePool:
name = m.Name
// { "vim.Network" } - Identifies a network entity folder.
// Network entity folders on a vCenter Server can contain Network,
// DistributedVirtualSwitch, and DistributedVirtualPortgroup managed objects.
// Network entity folders on an ESXi host can contain only Network objects.
case mo.Network:
name = m.Name
case mo.OpaqueNetwork:
name = m.Name
case mo.DistributedVirtualSwitch:
name = m.Name
case mo.DistributedVirtualPortgroup:
name = m.Name
case mo.VmwareDistributedVirtualSwitch:
name = m.Name
// { "vim.Datastore" } - Identifies a datastore folder. Datastore folders can
// contain child datastore folders and Datastore managed objects.
case mo.Datastore:
name = m.Name
default:
panic("not implemented for type " + reflect.TypeOf(r).String())
}
e := Element{
Path: path.Join(prefix, name),
Object: r,
}
return e
}
type Lister struct {
Collector *property.Collector
Reference types.ManagedObjectReference
Prefix string
All bool
}
func (l Lister) retrieveProperties(ctx context.Context, req types.RetrieveProperties, dst *[]interface{}) error {
res, err := l.Collector.RetrieveProperties(ctx, req)
if err != nil {
return err
}
// Instead of using mo.LoadRetrievePropertiesResponse, use a custom loop to
// iterate over the results and ignore entries that have properties that
// could not be retrieved (a non-empty `missingSet` property). Since the
// returned objects are enumerated by vSphere in the first place, any object
// that has a non-empty `missingSet` property is indicative of a race
// condition in vSphere where the object was enumerated initially, but was
// removed before its properties could be collected.
for _, p := range res.Returnval {
v, err := mo.ObjectContentToType(p)
if err != nil {
// Ignore fault if it is ManagedObjectNotFound
if soap.IsVimFault(err) {
switch soap.ToVimFault(err).(type) {
case *types.ManagedObjectNotFound:
continue
}
}
return err
}
*dst = append(*dst, v)
}
return nil
}
func (l Lister) List(ctx context.Context) ([]Element, error) {
switch l.Reference.Type {
case "Folder", "StoragePod":
return l.ListFolder(ctx)
case "Datacenter":
return l.ListDatacenter(ctx)
case "ComputeResource", "ClusterComputeResource":
// Treat ComputeResource and ClusterComputeResource as one and the same.
// It doesn't matter from the perspective of the lister.
return l.ListComputeResource(ctx)
case "ResourcePool":
return l.ListResourcePool(ctx)
case "HostSystem":
return l.ListHostSystem(ctx)
case "VirtualApp":
return l.ListVirtualApp(ctx)
default:
return nil, fmt.Errorf("cannot traverse type " + l.Reference.Type)
}
}
func (l Lister) ListFolder(ctx context.Context) ([]Element, error) {
spec := types.PropertyFilterSpec{
ObjectSet: []types.ObjectSpec{
{
Obj: l.Reference,
SelectSet: []types.BaseSelectionSpec{
&types.TraversalSpec{
Path: "childEntity",
Skip: types.NewBool(false),
Type: "Folder",
},
},
Skip: types.NewBool(true),
},
},
}
// Retrieve all objects that we can deal with
childTypes := []string{
"Folder",
"Datacenter",
"VirtualApp",
"VirtualMachine",
"Network",
"ComputeResource",
"ClusterComputeResource",
"Datastore",
"DistributedVirtualSwitch",
}
for _, t := range childTypes {
pspec := types.PropertySpec{
Type: t,
}
if l.All {
pspec.All = types.NewBool(true)
} else {
pspec.PathSet = []string{"name"}
// Additional basic properties.
switch t {
case "Folder":
pspec.PathSet = append(pspec.PathSet, "childType")
case "ComputeResource", "ClusterComputeResource":
// The ComputeResource and ClusterComputeResource are dereferenced in
// the ResourcePoolFlag. Make sure they always have their resourcePool
// field populated.
pspec.PathSet = append(pspec.PathSet, "resourcePool")
}
}
spec.PropSet = append(spec.PropSet, pspec)
}
req := types.RetrieveProperties{
SpecSet: []types.PropertyFilterSpec{spec},
}
var dst []interface{}
err := l.retrieveProperties(ctx, req, &dst)
if err != nil {
return nil, err
}
es := []Element{}
for _, v := range dst {
es = append(es, ToElement(v.(mo.Reference), l.Prefix))
}
return es, nil
}
func (l Lister) ListDatacenter(ctx context.Context) ([]Element, error) {
ospec := types.ObjectSpec{
Obj: l.Reference,
Skip: types.NewBool(true),
}
// Include every datastore folder in the select set
fields := []string{
"vmFolder",
"hostFolder",
"datastoreFolder",
"networkFolder",
}
for _, f := range fields {
tspec := types.TraversalSpec{
Path: f,
Skip: types.NewBool(false),
Type: "Datacenter",
}
ospec.SelectSet = append(ospec.SelectSet, &tspec)
}
pspec := types.PropertySpec{
Type: "Folder",
}
if l.All {
pspec.All = types.NewBool(true)
} else {
pspec.PathSet = []string{"name", "childType"}
}
req := types.RetrieveProperties{
SpecSet: []types.PropertyFilterSpec{
{
ObjectSet: []types.ObjectSpec{ospec},
PropSet: []types.PropertySpec{pspec},
},
},
}
var dst []interface{}
err := l.retrieveProperties(ctx, req, &dst)
if err != nil {
return nil, err
}
es := []Element{}
for _, v := range dst {
es = append(es, ToElement(v.(mo.Reference), l.Prefix))
}
return es, nil
}
func (l Lister) ListComputeResource(ctx context.Context) ([]Element, error) {
ospec := types.ObjectSpec{
Obj: l.Reference,
Skip: types.NewBool(true),
}
fields := []string{
"host",
"resourcePool",
}
for _, f := range fields {
tspec := types.TraversalSpec{
Path: f,
Skip: types.NewBool(false),
Type: "ComputeResource",
}
ospec.SelectSet = append(ospec.SelectSet, &tspec)
}
childTypes := []string{
"HostSystem",
"ResourcePool",
}
var pspecs []types.PropertySpec
for _, t := range childTypes {
pspec := types.PropertySpec{
Type: t,
}
if l.All {
pspec.All = types.NewBool(true)
} else {
pspec.PathSet = []string{"name"}
}
pspecs = append(pspecs, pspec)
}
req := types.RetrieveProperties{
SpecSet: []types.PropertyFilterSpec{
{
ObjectSet: []types.ObjectSpec{ospec},
PropSet: pspecs,
},
},
}
var dst []interface{}
err := l.retrieveProperties(ctx, req, &dst)
if err != nil {
return nil, err
}
es := []Element{}
for _, v := range dst {
es = append(es, ToElement(v.(mo.Reference), l.Prefix))
}
return es, nil
}
func (l Lister) ListResourcePool(ctx context.Context) ([]Element, error) {
ospec := types.ObjectSpec{
Obj: l.Reference,
Skip: types.NewBool(true),
}
fields := []string{
"resourcePool",
}
for _, f := range fields {
tspec := types.TraversalSpec{
Path: f,
Skip: types.NewBool(false),
Type: "ResourcePool",
}
ospec.SelectSet = append(ospec.SelectSet, &tspec)
}
childTypes := []string{
"ResourcePool",
}
var pspecs []types.PropertySpec
for _, t := range childTypes {
pspec := types.PropertySpec{
Type: t,
}
if l.All {
pspec.All = types.NewBool(true)
} else {
pspec.PathSet = []string{"name"}
}
pspecs = append(pspecs, pspec)
}
req := types.RetrieveProperties{
SpecSet: []types.PropertyFilterSpec{
{
ObjectSet: []types.ObjectSpec{ospec},
PropSet: pspecs,
},
},
}
var dst []interface{}
err := l.retrieveProperties(ctx, req, &dst)
if err != nil {
return nil, err
}
es := []Element{}
for _, v := range dst {
es = append(es, ToElement(v.(mo.Reference), l.Prefix))
}
return es, nil
}
func (l Lister) ListHostSystem(ctx context.Context) ([]Element, error) {
ospec := types.ObjectSpec{
Obj: l.Reference,
Skip: types.NewBool(true),
}
fields := []string{
"datastore",
"network",
"vm",
}
for _, f := range fields {
tspec := types.TraversalSpec{
Path: f,
Skip: types.NewBool(false),
Type: "HostSystem",
}
ospec.SelectSet = append(ospec.SelectSet, &tspec)
}
childTypes := []string{
"Datastore",
"Network",
"VirtualMachine",
}
var pspecs []types.PropertySpec
for _, t := range childTypes {
pspec := types.PropertySpec{
Type: t,
}
if l.All {
pspec.All = types.NewBool(true)
} else {
pspec.PathSet = []string{"name"}
}
pspecs = append(pspecs, pspec)
}
req := types.RetrieveProperties{
SpecSet: []types.PropertyFilterSpec{
{
ObjectSet: []types.ObjectSpec{ospec},
PropSet: pspecs,
},
},
}
var dst []interface{}
err := l.retrieveProperties(ctx, req, &dst)
if err != nil {
return nil, err
}
es := []Element{}
for _, v := range dst {
es = append(es, ToElement(v.(mo.Reference), l.Prefix))
}
return es, nil
}
func (l Lister) ListVirtualApp(ctx context.Context) ([]Element, error) {
ospec := types.ObjectSpec{
Obj: l.Reference,
Skip: types.NewBool(true),
}
fields := []string{
"resourcePool",
"vm",
}
for _, f := range fields {
tspec := types.TraversalSpec{
Path: f,
Skip: types.NewBool(false),
Type: "VirtualApp",
}
ospec.SelectSet = append(ospec.SelectSet, &tspec)
}
childTypes := []string{
"ResourcePool",
"VirtualMachine",
}
var pspecs []types.PropertySpec
for _, t := range childTypes {
pspec := types.PropertySpec{
Type: t,
}
if l.All {
pspec.All = types.NewBool(true)
} else {
pspec.PathSet = []string{"name"}
}
pspecs = append(pspecs, pspec)
}
req := types.RetrieveProperties{
SpecSet: []types.PropertyFilterSpec{
{
ObjectSet: []types.ObjectSpec{ospec},
PropSet: pspecs,
},
},
}
var dst []interface{}
err := l.retrieveProperties(ctx, req, &dst)
if err != nil {
return nil, err
}
es := []Element{}
for _, v := range dst {
es = append(es, ToElement(v.(mo.Reference), l.Prefix))
}
return es, nil
}

44
vendor/github.com/vmware/govmomi/list/path.go generated vendored Normal file
View File

@ -0,0 +1,44 @@
/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package list
import (
"path"
"strings"
)
func ToParts(p string) []string {
p = path.Clean(p)
if p == "/" {
return []string{}
}
if len(p) > 0 {
// Prefix ./ if relative
if p[0] != '/' && p[0] != '.' {
p = "./" + p
}
}
ps := strings.Split(p, "/")
if ps[0] == "" {
// Start at root
ps = ps[1:]
}
return ps
}

View File

@ -0,0 +1,174 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type AuthorizationManager struct {
Common
}
func NewAuthorizationManager(c *vim25.Client) *AuthorizationManager {
m := AuthorizationManager{
Common: NewCommon(c, *c.ServiceContent.AuthorizationManager),
}
return &m
}
type AuthorizationRoleList []types.AuthorizationRole
func (l AuthorizationRoleList) ById(id int32) *types.AuthorizationRole {
for _, role := range l {
if role.RoleId == id {
return &role
}
}
return nil
}
func (l AuthorizationRoleList) ByName(name string) *types.AuthorizationRole {
for _, role := range l {
if role.Name == name {
return &role
}
}
return nil
}
func (m AuthorizationManager) RoleList(ctx context.Context) (AuthorizationRoleList, error) {
var am mo.AuthorizationManager
err := m.Properties(ctx, m.Reference(), []string{"roleList"}, &am)
if err != nil {
return nil, err
}
return AuthorizationRoleList(am.RoleList), nil
}
func (m AuthorizationManager) RetrieveEntityPermissions(ctx context.Context, entity types.ManagedObjectReference, inherited bool) ([]types.Permission, error) {
req := types.RetrieveEntityPermissions{
This: m.Reference(),
Entity: entity,
Inherited: inherited,
}
res, err := methods.RetrieveEntityPermissions(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (m AuthorizationManager) RemoveEntityPermission(ctx context.Context, entity types.ManagedObjectReference, user string, isGroup bool) error {
req := types.RemoveEntityPermission{
This: m.Reference(),
Entity: entity,
User: user,
IsGroup: isGroup,
}
_, err := methods.RemoveEntityPermission(ctx, m.Client(), &req)
return err
}
func (m AuthorizationManager) SetEntityPermissions(ctx context.Context, entity types.ManagedObjectReference, permission []types.Permission) error {
req := types.SetEntityPermissions{
This: m.Reference(),
Entity: entity,
Permission: permission,
}
_, err := methods.SetEntityPermissions(ctx, m.Client(), &req)
return err
}
func (m AuthorizationManager) RetrieveRolePermissions(ctx context.Context, id int32) ([]types.Permission, error) {
req := types.RetrieveRolePermissions{
This: m.Reference(),
RoleId: id,
}
res, err := methods.RetrieveRolePermissions(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (m AuthorizationManager) RetrieveAllPermissions(ctx context.Context) ([]types.Permission, error) {
req := types.RetrieveAllPermissions{
This: m.Reference(),
}
res, err := methods.RetrieveAllPermissions(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (m AuthorizationManager) AddRole(ctx context.Context, name string, ids []string) (int32, error) {
req := types.AddAuthorizationRole{
This: m.Reference(),
Name: name,
PrivIds: ids,
}
res, err := methods.AddAuthorizationRole(ctx, m.Client(), &req)
if err != nil {
return -1, err
}
return res.Returnval, nil
}
func (m AuthorizationManager) RemoveRole(ctx context.Context, id int32, failIfUsed bool) error {
req := types.RemoveAuthorizationRole{
This: m.Reference(),
RoleId: id,
FailIfUsed: failIfUsed,
}
_, err := methods.RemoveAuthorizationRole(ctx, m.Client(), &req)
return err
}
func (m AuthorizationManager) UpdateRole(ctx context.Context, id int32, name string, ids []string) error {
req := types.UpdateAuthorizationRole{
This: m.Reference(),
RoleId: id,
NewName: name,
PrivIds: ids,
}
_, err := methods.UpdateAuthorizationRole(ctx, m.Client(), &req)
return err
}

View File

@ -0,0 +1,86 @@
/*
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 object
import (
"context"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type DisabledMethodRequest struct {
Method string `xml:"method"`
Reason string `xml:"reasonId"`
}
type disableMethodsRequest struct {
This types.ManagedObjectReference `xml:"_this"`
Entity []types.ManagedObjectReference `xml:"entity"`
Method []DisabledMethodRequest `xml:"method"`
Source string `xml:"sourceId"`
Scope bool `xml:"sessionScope,omitempty"`
}
type disableMethodsBody struct {
Req *disableMethodsRequest `xml:"urn:internalvim25 DisableMethods,omitempty"`
Res interface{} `xml:"urn:vim25 DisableMethodsResponse,omitempty"`
Err *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *disableMethodsBody) Fault() *soap.Fault { return b.Err }
func (m AuthorizationManager) DisableMethods(ctx context.Context, entity []types.ManagedObjectReference, method []DisabledMethodRequest, source string) error {
var reqBody, resBody disableMethodsBody
reqBody.Req = &disableMethodsRequest{
This: m.Reference(),
Entity: entity,
Method: method,
Source: source,
}
return m.Client().RoundTrip(ctx, &reqBody, &resBody)
}
type enableMethodsRequest struct {
This types.ManagedObjectReference `xml:"_this"`
Entity []types.ManagedObjectReference `xml:"entity"`
Method []string `xml:"method"`
Source string `xml:"sourceId"`
}
type enableMethodsBody struct {
Req *enableMethodsRequest `xml:"urn:internalvim25 EnableMethods,omitempty"`
Res interface{} `xml:"urn:vim25 EnableMethodsResponse,omitempty"`
Err *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *enableMethodsBody) Fault() *soap.Fault { return b.Err }
func (m AuthorizationManager) EnableMethods(ctx context.Context, entity []types.ManagedObjectReference, method []string, source string) error {
var reqBody, resBody enableMethodsBody
reqBody.Req = &enableMethodsRequest{
This: m.Reference(),
Entity: entity,
Method: method,
Source: source,
}
return m.Client().RoundTrip(ctx, &reqBody, &resBody)
}

View File

@ -0,0 +1,86 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type ClusterComputeResource struct {
ComputeResource
}
func NewClusterComputeResource(c *vim25.Client, ref types.ManagedObjectReference) *ClusterComputeResource {
return &ClusterComputeResource{
ComputeResource: *NewComputeResource(c, ref),
}
}
func (c ClusterComputeResource) ReconfigureCluster(ctx context.Context, spec types.ClusterConfigSpec) (*Task, error) {
req := types.ReconfigureCluster_Task{
This: c.Reference(),
Spec: spec,
Modify: true,
}
res, err := methods.ReconfigureCluster_Task(ctx, c.c, &req)
if err != nil {
return nil, err
}
return NewTask(c.c, res.Returnval), nil
}
func (c ClusterComputeResource) AddHost(ctx context.Context, spec types.HostConnectSpec, asConnected bool, license *string, resourcePool *types.ManagedObjectReference) (*Task, error) {
req := types.AddHost_Task{
This: c.Reference(),
Spec: spec,
AsConnected: asConnected,
}
if license != nil {
req.License = *license
}
if resourcePool != nil {
req.ResourcePool = resourcePool
}
res, err := methods.AddHost_Task(ctx, c.c, &req)
if err != nil {
return nil, err
}
return NewTask(c.c, res.Returnval), nil
}
func (c ClusterComputeResource) Destroy(ctx context.Context) (*Task, error) {
req := types.Destroy_Task{
This: c.Reference(),
}
res, err := methods.Destroy_Task(ctx, c.c, &req)
if err != nil {
return nil, err
}
return NewTask(c.c, res.Returnval), nil
}

120
vendor/github.com/vmware/govmomi/object/common.go generated vendored Normal file
View File

@ -0,0 +1,120 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"errors"
"fmt"
"path"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
var (
ErrNotSupported = errors.New("product/version specific feature not supported by target")
)
// Common contains the fields and functions common to all objects.
type Common struct {
InventoryPath string
c *vim25.Client
r types.ManagedObjectReference
}
func (c Common) String() string {
ref := fmt.Sprintf("%v", c.Reference())
if c.InventoryPath == "" {
return ref
}
return fmt.Sprintf("%s @ %s", ref, c.InventoryPath)
}
func NewCommon(c *vim25.Client, r types.ManagedObjectReference) Common {
return Common{c: c, r: r}
}
func (c Common) Reference() types.ManagedObjectReference {
return c.r
}
func (c Common) Client() *vim25.Client {
return c.c
}
// Name returns the base name of the InventoryPath field
func (c Common) Name() string {
if c.InventoryPath == "" {
return ""
}
return path.Base(c.InventoryPath)
}
func (c *Common) SetInventoryPath(p string) {
c.InventoryPath = p
}
// ObjectName returns the base name of the InventoryPath field if set,
// otherwise fetches the mo.ManagedEntity.Name field via the property collector.
func (c Common) ObjectName(ctx context.Context) (string, error) {
var o mo.ManagedEntity
err := c.Properties(ctx, c.Reference(), []string{"name"}, &o)
if err != nil {
return "", err
}
return o.Name, nil
}
func (c Common) Properties(ctx context.Context, r types.ManagedObjectReference, ps []string, dst interface{}) error {
return property.DefaultCollector(c.c).RetrieveOne(ctx, r, ps, dst)
}
func (c Common) Destroy(ctx context.Context) (*Task, error) {
req := types.Destroy_Task{
This: c.Reference(),
}
res, err := methods.Destroy_Task(ctx, c.c, &req)
if err != nil {
return nil, err
}
return NewTask(c.c, res.Returnval), nil
}
func (c Common) Rename(ctx context.Context, name string) (*Task, error) {
req := types.Rename_Task{
This: c.Reference(),
NewName: name,
}
res, err := methods.Rename_Task(ctx, c.c, &req)
if err != nil {
return nil, err
}
return NewTask(c.c, res.Returnval), nil
}

View File

@ -0,0 +1,124 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"path"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type ComputeResource struct {
Common
}
func NewComputeResource(c *vim25.Client, ref types.ManagedObjectReference) *ComputeResource {
return &ComputeResource{
Common: NewCommon(c, ref),
}
}
func (c ComputeResource) Hosts(ctx context.Context) ([]*HostSystem, error) {
var cr mo.ComputeResource
err := c.Properties(ctx, c.Reference(), []string{"host"}, &cr)
if err != nil {
return nil, err
}
if len(cr.Host) == 0 {
return nil, nil
}
var hs []mo.HostSystem
pc := property.DefaultCollector(c.Client())
err = pc.Retrieve(ctx, cr.Host, []string{"name"}, &hs)
if err != nil {
return nil, err
}
var hosts []*HostSystem
for _, h := range hs {
host := NewHostSystem(c.Client(), h.Reference())
host.InventoryPath = path.Join(c.InventoryPath, h.Name)
hosts = append(hosts, host)
}
return hosts, nil
}
func (c ComputeResource) Datastores(ctx context.Context) ([]*Datastore, error) {
var cr mo.ComputeResource
err := c.Properties(ctx, c.Reference(), []string{"datastore"}, &cr)
if err != nil {
return nil, err
}
var dss []*Datastore
for _, ref := range cr.Datastore {
ds := NewDatastore(c.c, ref)
dss = append(dss, ds)
}
return dss, nil
}
func (c ComputeResource) ResourcePool(ctx context.Context) (*ResourcePool, error) {
var cr mo.ComputeResource
err := c.Properties(ctx, c.Reference(), []string{"resourcePool"}, &cr)
if err != nil {
return nil, err
}
return NewResourcePool(c.c, *cr.ResourcePool), nil
}
func (c ComputeResource) Reconfigure(ctx context.Context, spec types.BaseComputeResourceConfigSpec, modify bool) (*Task, error) {
req := types.ReconfigureComputeResource_Task{
This: c.Reference(),
Spec: spec,
Modify: modify,
}
res, err := methods.ReconfigureComputeResource_Task(ctx, c.c, &req)
if err != nil {
return nil, err
}
return NewTask(c.c, res.Returnval), nil
}
func (c ComputeResource) Destroy(ctx context.Context) (*Task, error) {
req := types.Destroy_Task{
This: c.Reference(),
}
res, err := methods.Destroy_Task(ctx, c.c, &req)
if err != nil {
return nil, err
}
return NewTask(c.c, res.Returnval), nil
}

View File

@ -0,0 +1,135 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"errors"
"strconv"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
var (
ErrKeyNameNotFound = errors.New("key name not found")
)
type CustomFieldsManager struct {
Common
}
// GetCustomFieldsManager wraps NewCustomFieldsManager, returning ErrNotSupported
// when the client is not connected to a vCenter instance.
func GetCustomFieldsManager(c *vim25.Client) (*CustomFieldsManager, error) {
if c.ServiceContent.CustomFieldsManager == nil {
return nil, ErrNotSupported
}
return NewCustomFieldsManager(c), nil
}
func NewCustomFieldsManager(c *vim25.Client) *CustomFieldsManager {
m := CustomFieldsManager{
Common: NewCommon(c, *c.ServiceContent.CustomFieldsManager),
}
return &m
}
func (m CustomFieldsManager) Add(ctx context.Context, name string, moType string, fieldDefPolicy *types.PrivilegePolicyDef, fieldPolicy *types.PrivilegePolicyDef) (*types.CustomFieldDef, error) {
req := types.AddCustomFieldDef{
This: m.Reference(),
Name: name,
MoType: moType,
FieldDefPolicy: fieldDefPolicy,
FieldPolicy: fieldPolicy,
}
res, err := methods.AddCustomFieldDef(ctx, m.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
func (m CustomFieldsManager) Remove(ctx context.Context, key int32) error {
req := types.RemoveCustomFieldDef{
This: m.Reference(),
Key: key,
}
_, err := methods.RemoveCustomFieldDef(ctx, m.c, &req)
return err
}
func (m CustomFieldsManager) Rename(ctx context.Context, key int32, name string) error {
req := types.RenameCustomFieldDef{
This: m.Reference(),
Key: key,
Name: name,
}
_, err := methods.RenameCustomFieldDef(ctx, m.c, &req)
return err
}
func (m CustomFieldsManager) Set(ctx context.Context, entity types.ManagedObjectReference, key int32, value string) error {
req := types.SetField{
This: m.Reference(),
Entity: entity,
Key: key,
Value: value,
}
_, err := methods.SetField(ctx, m.c, &req)
return err
}
func (m CustomFieldsManager) Field(ctx context.Context) ([]types.CustomFieldDef, error) {
var fm mo.CustomFieldsManager
err := m.Properties(ctx, m.Reference(), []string{"field"}, &fm)
if err != nil {
return nil, err
}
return fm.Field, nil
}
func (m CustomFieldsManager) FindKey(ctx context.Context, key string) (int32, error) {
field, err := m.Field(ctx)
if err != nil {
return -1, err
}
for _, def := range field {
if def.Name == key {
return def.Key, nil
}
}
k, err := strconv.Atoi(key)
if err == nil {
// assume literal int key
return int32(k), nil
}
return -1, ErrKeyNameNotFound
}

View File

@ -0,0 +1,166 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type CustomizationSpecManager struct {
Common
}
func NewCustomizationSpecManager(c *vim25.Client) *CustomizationSpecManager {
cs := CustomizationSpecManager{
Common: NewCommon(c, *c.ServiceContent.CustomizationSpecManager),
}
return &cs
}
func (cs CustomizationSpecManager) DoesCustomizationSpecExist(ctx context.Context, name string) (bool, error) {
req := types.DoesCustomizationSpecExist{
This: cs.Reference(),
Name: name,
}
res, err := methods.DoesCustomizationSpecExist(ctx, cs.c, &req)
if err != nil {
return false, err
}
return res.Returnval, nil
}
func (cs CustomizationSpecManager) GetCustomizationSpec(ctx context.Context, name string) (*types.CustomizationSpecItem, error) {
req := types.GetCustomizationSpec{
This: cs.Reference(),
Name: name,
}
res, err := methods.GetCustomizationSpec(ctx, cs.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
func (cs CustomizationSpecManager) CreateCustomizationSpec(ctx context.Context, item types.CustomizationSpecItem) error {
req := types.CreateCustomizationSpec{
This: cs.Reference(),
Item: item,
}
_, err := methods.CreateCustomizationSpec(ctx, cs.c, &req)
if err != nil {
return err
}
return nil
}
func (cs CustomizationSpecManager) OverwriteCustomizationSpec(ctx context.Context, item types.CustomizationSpecItem) error {
req := types.OverwriteCustomizationSpec{
This: cs.Reference(),
Item: item,
}
_, err := methods.OverwriteCustomizationSpec(ctx, cs.c, &req)
if err != nil {
return err
}
return nil
}
func (cs CustomizationSpecManager) DeleteCustomizationSpec(ctx context.Context, name string) error {
req := types.DeleteCustomizationSpec{
This: cs.Reference(),
Name: name,
}
_, err := methods.DeleteCustomizationSpec(ctx, cs.c, &req)
if err != nil {
return err
}
return nil
}
func (cs CustomizationSpecManager) DuplicateCustomizationSpec(ctx context.Context, name string, newName string) error {
req := types.DuplicateCustomizationSpec{
This: cs.Reference(),
Name: name,
NewName: newName,
}
_, err := methods.DuplicateCustomizationSpec(ctx, cs.c, &req)
if err != nil {
return err
}
return nil
}
func (cs CustomizationSpecManager) RenameCustomizationSpec(ctx context.Context, name string, newName string) error {
req := types.RenameCustomizationSpec{
This: cs.Reference(),
Name: name,
NewName: newName,
}
_, err := methods.RenameCustomizationSpec(ctx, cs.c, &req)
if err != nil {
return err
}
return nil
}
func (cs CustomizationSpecManager) CustomizationSpecItemToXml(ctx context.Context, item types.CustomizationSpecItem) (string, error) {
req := types.CustomizationSpecItemToXml{
This: cs.Reference(),
Item: item,
}
res, err := methods.CustomizationSpecItemToXml(ctx, cs.c, &req)
if err != nil {
return "", err
}
return res.Returnval, nil
}
func (cs CustomizationSpecManager) XmlToCustomizationSpecItem(ctx context.Context, xml string) (*types.CustomizationSpecItem, error) {
req := types.XmlToCustomizationSpecItem{
This: cs.Reference(),
SpecItemXml: xml,
}
res, err := methods.XmlToCustomizationSpecItem(ctx, cs.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}

90
vendor/github.com/vmware/govmomi/object/datacenter.go generated vendored Normal file
View File

@ -0,0 +1,90 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"fmt"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type DatacenterFolders struct {
VmFolder *Folder
HostFolder *Folder
DatastoreFolder *Folder
NetworkFolder *Folder
}
type Datacenter struct {
Common
}
func NewDatacenter(c *vim25.Client, ref types.ManagedObjectReference) *Datacenter {
return &Datacenter{
Common: NewCommon(c, ref),
}
}
func (d *Datacenter) Folders(ctx context.Context) (*DatacenterFolders, error) {
var md mo.Datacenter
ps := []string{"name", "vmFolder", "hostFolder", "datastoreFolder", "networkFolder"}
err := d.Properties(ctx, d.Reference(), ps, &md)
if err != nil {
return nil, err
}
df := &DatacenterFolders{
VmFolder: NewFolder(d.c, md.VmFolder),
HostFolder: NewFolder(d.c, md.HostFolder),
DatastoreFolder: NewFolder(d.c, md.DatastoreFolder),
NetworkFolder: NewFolder(d.c, md.NetworkFolder),
}
paths := []struct {
name string
path *string
}{
{"vm", &df.VmFolder.InventoryPath},
{"host", &df.HostFolder.InventoryPath},
{"datastore", &df.DatastoreFolder.InventoryPath},
{"network", &df.NetworkFolder.InventoryPath},
}
for _, p := range paths {
*p.path = fmt.Sprintf("/%s/%s", md.Name, p.name)
}
return df, nil
}
func (d Datacenter) Destroy(ctx context.Context) (*Task, error) {
req := types.Destroy_Task{
This: d.Reference(),
}
res, err := methods.Destroy_Task(ctx, d.c, &req)
if err != nil {
return nil, err
}
return NewTask(d.c, res.Returnval), nil
}

438
vendor/github.com/vmware/govmomi/object/datastore.go generated vendored Normal file
View File

@ -0,0 +1,438 @@
/*
Copyright (c) 2015-2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"fmt"
"io"
"math/rand"
"os"
"path"
"strings"
"context"
"net/http"
"net/url"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/session"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
// DatastoreNoSuchDirectoryError is returned when a directory could not be found.
type DatastoreNoSuchDirectoryError struct {
verb string
subject string
}
func (e DatastoreNoSuchDirectoryError) Error() string {
return fmt.Sprintf("cannot %s '%s': No such directory", e.verb, e.subject)
}
// DatastoreNoSuchFileError is returned when a file could not be found.
type DatastoreNoSuchFileError struct {
verb string
subject string
}
func (e DatastoreNoSuchFileError) Error() string {
return fmt.Sprintf("cannot %s '%s': No such file", e.verb, e.subject)
}
type Datastore struct {
Common
DatacenterPath string
}
func NewDatastore(c *vim25.Client, ref types.ManagedObjectReference) *Datastore {
return &Datastore{
Common: NewCommon(c, ref),
}
}
func (d Datastore) Path(path string) string {
return (&DatastorePath{
Datastore: d.Name(),
Path: path,
}).String()
}
// NewURL constructs a url.URL with the given file path for datastore access over HTTP.
func (d Datastore) NewURL(path string) *url.URL {
u := d.c.URL()
return &url.URL{
Scheme: u.Scheme,
Host: u.Host,
Path: fmt.Sprintf("/folder/%s", path),
RawQuery: url.Values{
"dcPath": []string{d.DatacenterPath},
"dsName": []string{d.Name()},
}.Encode(),
}
}
// URL is deprecated, use NewURL instead.
func (d Datastore) URL(ctx context.Context, dc *Datacenter, path string) (*url.URL, error) {
return d.NewURL(path), nil
}
func (d Datastore) Browser(ctx context.Context) (*HostDatastoreBrowser, error) {
var do mo.Datastore
err := d.Properties(ctx, d.Reference(), []string{"browser"}, &do)
if err != nil {
return nil, err
}
return NewHostDatastoreBrowser(d.c, do.Browser), nil
}
func (d Datastore) useServiceTicket() bool {
// If connected to workstation, service ticketing not supported
// If connected to ESX, service ticketing not needed
if !d.c.IsVC() {
return false
}
key := "GOVMOMI_USE_SERVICE_TICKET"
val := d.c.URL().Query().Get(key)
if val == "" {
val = os.Getenv(key)
}
if val == "1" || val == "true" {
return true
}
return false
}
func (d Datastore) useServiceTicketHostName(name string) bool {
// No need if talking directly to ESX.
if !d.c.IsVC() {
return false
}
// If version happens to be < 5.1
if name == "" {
return false
}
// If the HostSystem is using DHCP on a network without dynamic DNS,
// HostSystem.Config.Network.DnsConfig.HostName is set to "localhost" by default.
// This resolves to "localhost.localdomain" by default via /etc/hosts on ESX.
// In that case, we will stick with the HostSystem.Name which is the IP address that
// was used to connect the host to VC.
if name == "localhost.localdomain" {
return false
}
// Still possible to have HostName that don't resolve via DNS,
// so we default to false.
key := "GOVMOMI_USE_SERVICE_TICKET_HOSTNAME"
val := d.c.URL().Query().Get(key)
if val == "" {
val = os.Getenv(key)
}
if val == "1" || val == "true" {
return true
}
return false
}
type datastoreServiceTicketHostKey struct{}
// HostContext returns a Context where the given host will be used for datastore HTTP access
// via the ServiceTicket method.
func (d Datastore) HostContext(ctx context.Context, host *HostSystem) context.Context {
return context.WithValue(ctx, datastoreServiceTicketHostKey{}, host)
}
// ServiceTicket obtains a ticket via AcquireGenericServiceTicket and returns it an http.Cookie with the url.URL
// that can be used along with the ticket cookie to access the given path. An host is chosen at random unless the
// the given Context was created with a specific host via the HostContext method.
func (d Datastore) ServiceTicket(ctx context.Context, path string, method string) (*url.URL, *http.Cookie, error) {
u := d.NewURL(path)
host, ok := ctx.Value(datastoreServiceTicketHostKey{}).(*HostSystem)
if !ok {
if !d.useServiceTicket() {
return u, nil, nil
}
hosts, err := d.AttachedHosts(ctx)
if err != nil {
return nil, nil, err
}
if len(hosts) == 0 {
// Fallback to letting vCenter choose a host
return u, nil, nil
}
// Pick a random attached host
host = hosts[rand.Intn(len(hosts))]
}
ips, err := host.ManagementIPs(ctx)
if err != nil {
return nil, nil, err
}
if len(ips) > 0 {
// prefer a ManagementIP
u.Host = ips[0].String()
} else {
// fallback to inventory name
u.Host, err = host.ObjectName(ctx)
if err != nil {
return nil, nil, err
}
}
// VC datacenter path will not be valid against ESX
q := u.Query()
delete(q, "dcPath")
u.RawQuery = q.Encode()
spec := types.SessionManagerHttpServiceRequestSpec{
Url: u.String(),
// See SessionManagerHttpServiceRequestSpecMethod enum
Method: fmt.Sprintf("http%s%s", method[0:1], strings.ToLower(method[1:])),
}
sm := session.NewManager(d.Client())
ticket, err := sm.AcquireGenericServiceTicket(ctx, &spec)
if err != nil {
return nil, nil, err
}
cookie := &http.Cookie{
Name: "vmware_cgi_ticket",
Value: ticket.Id,
}
if d.useServiceTicketHostName(ticket.HostName) {
u.Host = ticket.HostName
}
d.Client().SetThumbprint(u.Host, ticket.SslThumbprint)
return u, cookie, nil
}
func (d Datastore) uploadTicket(ctx context.Context, path string, param *soap.Upload) (*url.URL, *soap.Upload, error) {
p := soap.DefaultUpload
if param != nil {
p = *param // copy
}
u, ticket, err := d.ServiceTicket(ctx, path, p.Method)
if err != nil {
return nil, nil, err
}
p.Ticket = ticket
return u, &p, nil
}
func (d Datastore) downloadTicket(ctx context.Context, path string, param *soap.Download) (*url.URL, *soap.Download, error) {
p := soap.DefaultDownload
if param != nil {
p = *param // copy
}
u, ticket, err := d.ServiceTicket(ctx, path, p.Method)
if err != nil {
return nil, nil, err
}
p.Ticket = ticket
return u, &p, nil
}
// Upload via soap.Upload with an http service ticket
func (d Datastore) Upload(ctx context.Context, f io.Reader, path string, param *soap.Upload) error {
u, p, err := d.uploadTicket(ctx, path, param)
if err != nil {
return err
}
return d.Client().Upload(f, u, p)
}
// UploadFile via soap.Upload with an http service ticket
func (d Datastore) UploadFile(ctx context.Context, file string, path string, param *soap.Upload) error {
u, p, err := d.uploadTicket(ctx, path, param)
if err != nil {
return err
}
return d.Client().UploadFile(file, u, p)
}
// Download via soap.Download with an http service ticket
func (d Datastore) Download(ctx context.Context, path string, param *soap.Download) (io.ReadCloser, int64, error) {
u, p, err := d.downloadTicket(ctx, path, param)
if err != nil {
return nil, 0, err
}
return d.Client().Download(u, p)
}
// DownloadFile via soap.Download with an http service ticket
func (d Datastore) DownloadFile(ctx context.Context, path string, file string, param *soap.Download) error {
u, p, err := d.downloadTicket(ctx, path, param)
if err != nil {
return err
}
return d.Client().DownloadFile(file, u, p)
}
// AttachedHosts returns hosts that have this Datastore attached, accessible and writable.
func (d Datastore) AttachedHosts(ctx context.Context) ([]*HostSystem, error) {
var ds mo.Datastore
var hosts []*HostSystem
pc := property.DefaultCollector(d.Client())
err := pc.RetrieveOne(ctx, d.Reference(), []string{"host"}, &ds)
if err != nil {
return nil, err
}
mounts := make(map[types.ManagedObjectReference]types.DatastoreHostMount)
var refs []types.ManagedObjectReference
for _, host := range ds.Host {
refs = append(refs, host.Key)
mounts[host.Key] = host
}
var hs []mo.HostSystem
err = pc.Retrieve(ctx, refs, []string{"runtime.connectionState", "runtime.powerState"}, &hs)
if err != nil {
return nil, err
}
for _, host := range hs {
if host.Runtime.ConnectionState == types.HostSystemConnectionStateConnected &&
host.Runtime.PowerState == types.HostSystemPowerStatePoweredOn {
mount := mounts[host.Reference()]
info := mount.MountInfo
if *info.Mounted && *info.Accessible && info.AccessMode == string(types.HostMountModeReadWrite) {
hosts = append(hosts, NewHostSystem(d.Client(), mount.Key))
}
}
}
return hosts, nil
}
// AttachedClusterHosts returns hosts that have this Datastore attached, accessible and writable and are members of the given cluster.
func (d Datastore) AttachedClusterHosts(ctx context.Context, cluster *ComputeResource) ([]*HostSystem, error) {
var hosts []*HostSystem
clusterHosts, err := cluster.Hosts(ctx)
if err != nil {
return nil, err
}
attachedHosts, err := d.AttachedHosts(ctx)
if err != nil {
return nil, err
}
refs := make(map[types.ManagedObjectReference]bool)
for _, host := range attachedHosts {
refs[host.Reference()] = true
}
for _, host := range clusterHosts {
if refs[host.Reference()] {
hosts = append(hosts, host)
}
}
return hosts, nil
}
func (d Datastore) Stat(ctx context.Context, file string) (types.BaseFileInfo, error) {
b, err := d.Browser(ctx)
if err != nil {
return nil, err
}
spec := types.HostDatastoreBrowserSearchSpec{
Details: &types.FileQueryFlags{
FileType: true,
FileSize: true,
Modification: true,
FileOwner: types.NewBool(true),
},
MatchPattern: []string{path.Base(file)},
}
dsPath := d.Path(path.Dir(file))
task, err := b.SearchDatastore(ctx, dsPath, &spec)
if err != nil {
return nil, err
}
info, err := task.WaitForResult(ctx, nil)
if err != nil {
if info == nil || info.Error != nil {
_, ok := info.Error.Fault.(*types.FileNotFound)
if ok {
// FileNotFound means the base path doesn't exist.
return nil, DatastoreNoSuchDirectoryError{"stat", dsPath}
}
}
return nil, err
}
res := info.Result.(types.HostDatastoreBrowserSearchResults)
if len(res.File) == 0 {
// File doesn't exist
return nil, DatastoreNoSuchFileError{"stat", d.Path(file)}
}
return res.File[0], nil
}
// Type returns the type of file system volume.
func (d Datastore) Type(ctx context.Context) (types.HostFileSystemVolumeFileSystemType, error) {
var mds mo.Datastore
if err := d.Properties(ctx, d.Reference(), []string{"summary.type"}, &mds); err != nil {
return types.HostFileSystemVolumeFileSystemType(""), err
}
return types.HostFileSystemVolumeFileSystemType(mds.Summary.Type), nil
}

View File

@ -0,0 +1,408 @@
/*
Copyright (c) 2016-2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"net/http"
"os"
"path"
"time"
"github.com/vmware/govmomi/vim25/soap"
)
// DatastoreFile implements io.Reader, io.Seeker and io.Closer interfaces for datastore file access.
type DatastoreFile struct {
d Datastore
ctx context.Context
name string
buf io.Reader
body io.ReadCloser
length int64
offset struct {
read, seek int64
}
}
// Open opens the named file relative to the Datastore.
func (d Datastore) Open(ctx context.Context, name string) (*DatastoreFile, error) {
return &DatastoreFile{
d: d,
name: name,
length: -1,
ctx: ctx,
}, nil
}
// Read reads up to len(b) bytes from the DatastoreFile.
func (f *DatastoreFile) Read(b []byte) (int, error) {
if f.offset.read != f.offset.seek {
// A Seek() call changed the offset, we need to issue a new GET
_ = f.Close()
f.offset.read = f.offset.seek
} else if f.buf != nil {
// f.buf + f behaves like an io.MultiReader
n, err := f.buf.Read(b)
if err == io.EOF {
f.buf = nil // buffer has been drained
}
if n > 0 {
return n, nil
}
}
body, err := f.get()
if err != nil {
return 0, err
}
n, err := body.Read(b)
f.offset.read += int64(n)
f.offset.seek += int64(n)
return n, err
}
// Close closes the DatastoreFile.
func (f *DatastoreFile) Close() error {
var err error
if f.body != nil {
err = f.body.Close()
f.body = nil
}
f.buf = nil
return err
}
// Seek sets the offset for the next Read on the DatastoreFile.
func (f *DatastoreFile) Seek(offset int64, whence int) (int64, error) {
switch whence {
case io.SeekStart:
case io.SeekCurrent:
offset += f.offset.seek
case io.SeekEnd:
if f.length < 0 {
_, err := f.Stat()
if err != nil {
return 0, err
}
}
offset += f.length
default:
return 0, errors.New("Seek: invalid whence")
}
// allow negative SeekStart for initial Range request
if offset < 0 {
return 0, errors.New("Seek: invalid offset")
}
f.offset.seek = offset
return offset, nil
}
type fileStat struct {
file *DatastoreFile
header http.Header
}
func (s *fileStat) Name() string {
return path.Base(s.file.name)
}
func (s *fileStat) Size() int64 {
return s.file.length
}
func (s *fileStat) Mode() os.FileMode {
return 0
}
func (s *fileStat) ModTime() time.Time {
return time.Now() // no Last-Modified
}
func (s *fileStat) IsDir() bool {
return false
}
func (s *fileStat) Sys() interface{} {
return s.header
}
func statusError(res *http.Response) error {
if res.StatusCode == http.StatusNotFound {
return os.ErrNotExist
}
return errors.New(res.Status)
}
// Stat returns the os.FileInfo interface describing file.
func (f *DatastoreFile) Stat() (os.FileInfo, error) {
// TODO: consider using Datastore.Stat() instead
u, p, err := f.d.downloadTicket(f.ctx, f.name, &soap.Download{Method: "HEAD"})
if err != nil {
return nil, err
}
res, err := f.d.Client().DownloadRequest(u, p)
if err != nil {
return nil, err
}
if res.StatusCode != http.StatusOK {
return nil, statusError(res)
}
f.length = res.ContentLength
return &fileStat{f, res.Header}, nil
}
func (f *DatastoreFile) get() (io.Reader, error) {
if f.body != nil {
return f.body, nil
}
u, p, err := f.d.downloadTicket(f.ctx, f.name, nil)
if err != nil {
return nil, err
}
if f.offset.read != 0 {
p.Headers = map[string]string{
"Range": fmt.Sprintf("bytes=%d-", f.offset.read),
}
}
res, err := f.d.Client().DownloadRequest(u, p)
if err != nil {
return nil, err
}
switch res.StatusCode {
case http.StatusOK:
f.length = res.ContentLength
case http.StatusPartialContent:
var start, end int
cr := res.Header.Get("Content-Range")
_, err = fmt.Sscanf(cr, "bytes %d-%d/%d", &start, &end, &f.length)
if err != nil {
f.length = -1
}
case http.StatusRequestedRangeNotSatisfiable:
// ok: Read() will return io.EOF
default:
return nil, statusError(res)
}
if f.length < 0 {
_ = res.Body.Close()
return nil, errors.New("unable to determine file size")
}
f.body = res.Body
return f.body, nil
}
func lastIndexLines(s []byte, line *int, include func(l int, m string) bool) (int64, bool) {
i := len(s) - 1
done := false
for i > 0 {
o := bytes.LastIndexByte(s[:i], '\n')
if o < 0 {
break
}
msg := string(s[o+1 : i+1])
if !include(*line, msg) {
done = true
break
} else {
i = o
*line++
}
}
return int64(i), done
}
// Tail seeks to the position of the last N lines of the file.
func (f *DatastoreFile) Tail(n int) error {
return f.TailFunc(n, func(line int, _ string) bool { return n > line })
}
// TailFunc will seek backwards in the datastore file until it hits a line that does
// not satisfy the supplied `include` function.
func (f *DatastoreFile) TailFunc(lines int, include func(line int, message string) bool) error {
// Read the file in reverse using bsize chunks
const bsize = int64(1024 * 16)
fsize, err := f.Seek(0, io.SeekEnd)
if err != nil {
return err
}
if lines == 0 {
return nil
}
chunk := int64(-1)
buf := bytes.NewBuffer(make([]byte, 0, bsize))
line := 0
for {
var eof bool
var pos int64
nread := bsize
offset := chunk * bsize
remain := fsize + offset
if remain < 0 {
if pos, err = f.Seek(0, io.SeekStart); err != nil {
return err
}
nread = bsize + remain
eof = true
} else {
if pos, err = f.Seek(offset, io.SeekEnd); err != nil {
return err
}
}
if _, err = io.CopyN(buf, f, nread); err != nil {
if err != io.EOF {
return err
}
}
b := buf.Bytes()
idx, done := lastIndexLines(b, &line, include)
if done {
if chunk == -1 {
// We found all N lines in the last chunk of the file.
// The seek offset is also now at the current end of file.
// Save this buffer to avoid another GET request when Read() is called.
buf.Next(int(idx + 1))
f.buf = buf
return nil
}
if _, err = f.Seek(pos+idx+1, io.SeekStart); err != nil {
return err
}
break
}
if eof {
if remain < 0 {
// We found < N lines in the entire file, so seek to the start.
_, _ = f.Seek(0, io.SeekStart)
}
break
}
chunk--
buf.Reset()
}
return nil
}
type followDatastoreFile struct {
r *DatastoreFile
c chan struct{}
i time.Duration
}
// Read reads up to len(b) bytes from the DatastoreFile being followed.
// This method will block until data is read, an error other than io.EOF is returned or Close() is called.
func (f *followDatastoreFile) Read(p []byte) (int, error) {
offset := f.r.offset.seek
stop := false
for {
n, err := f.r.Read(p)
if err != nil && err == io.EOF {
_ = f.r.Close() // GET request body has been drained.
if stop {
return n, err
}
err = nil
}
if n > 0 {
return n, err
}
select {
case <-f.c:
// Wake up and stop polling once the body has been drained
stop = true
case <-time.After(f.i):
}
info, serr := f.r.Stat()
if serr != nil {
// Return EOF rather than 404 if the file goes away
if serr == os.ErrNotExist {
_ = f.r.Close()
return 0, io.EOF
}
return 0, serr
}
if info.Size() < offset {
// assume file has be truncated
offset, err = f.r.Seek(0, io.SeekStart)
if err != nil {
return 0, err
}
}
}
}
// Close will stop Follow polling and close the underlying DatastoreFile.
func (f *followDatastoreFile) Close() error {
close(f.c)
return nil
}
// Follow returns an io.ReadCloser to stream the file contents as data is appended.
func (f *DatastoreFile) Follow(interval time.Duration) io.ReadCloser {
return &followDatastoreFile{f, make(chan struct{}), interval}
}

View File

@ -0,0 +1,145 @@
/*
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 object
import (
"bufio"
"bytes"
"context"
"fmt"
"io"
"log"
"path"
"strings"
"github.com/vmware/govmomi/vim25/soap"
)
// DatastoreFileManager combines FileManager and VirtualDiskManager to manage files on a Datastore
type DatastoreFileManager struct {
Datacenter *Datacenter
Datastore *Datastore
FileManager *FileManager
VirtualDiskManager *VirtualDiskManager
Force bool
}
// NewFileManager creates a new instance of DatastoreFileManager
func (d Datastore) NewFileManager(dc *Datacenter, force bool) *DatastoreFileManager {
c := d.Client()
m := &DatastoreFileManager{
Datacenter: dc,
Datastore: &d,
FileManager: NewFileManager(c),
VirtualDiskManager: NewVirtualDiskManager(c),
Force: force,
}
return m
}
// Delete dispatches to the appropriate Delete method based on file name extension
func (m *DatastoreFileManager) Delete(ctx context.Context, name string) error {
switch path.Ext(name) {
case ".vmdk":
return m.DeleteVirtualDisk(ctx, name)
default:
return m.DeleteFile(ctx, name)
}
}
// DeleteFile calls FileManager.DeleteDatastoreFile
func (m *DatastoreFileManager) DeleteFile(ctx context.Context, name string) error {
p := m.Path(name)
task, err := m.FileManager.DeleteDatastoreFile(ctx, p.String(), m.Datacenter)
if err != nil {
return err
}
return task.Wait(ctx)
}
// DeleteVirtualDisk calls VirtualDiskManager.DeleteVirtualDisk
// Regardless of the Datastore type, DeleteVirtualDisk will fail if 'ddb.deletable=false',
// so if Force=true this method attempts to set 'ddb.deletable=true' before starting the delete task.
func (m *DatastoreFileManager) DeleteVirtualDisk(ctx context.Context, name string) error {
p := m.Path(name)
var merr error
if m.Force {
merr = m.markDiskAsDeletable(ctx, p)
}
task, err := m.VirtualDiskManager.DeleteVirtualDisk(ctx, p.String(), m.Datacenter)
if err != nil {
log.Printf("markDiskAsDeletable(%s): %s", p, merr)
return err
}
return task.Wait(ctx)
}
// Path converts path name to a DatastorePath
func (m *DatastoreFileManager) Path(name string) *DatastorePath {
var p DatastorePath
if !p.FromString(name) {
p.Path = name
p.Datastore = m.Datastore.Name()
}
return &p
}
func (m *DatastoreFileManager) markDiskAsDeletable(ctx context.Context, path *DatastorePath) error {
r, _, err := m.Datastore.Download(ctx, path.Path, &soap.DefaultDownload)
if err != nil {
return err
}
defer r.Close()
hasFlag := false
buf := new(bytes.Buffer)
s := bufio.NewScanner(&io.LimitedReader{R: r, N: 2048}) // should be only a few hundred bytes, limit to be sure
for s.Scan() {
line := s.Text()
if strings.HasPrefix(line, "ddb.deletable") {
hasFlag = true
continue
}
fmt.Fprintln(buf, line)
}
if err := s.Err(); err != nil {
return err // any error other than EOF
}
if !hasFlag {
return nil // already deletable, so leave as-is
}
// rewrite the .vmdk with ddb.deletable flag removed (the default is true)
return m.Datastore.Upload(ctx, buf, path.Path, &soap.DefaultUpload)
}

View File

@ -0,0 +1,65 @@
/*
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 object
import (
"fmt"
"strings"
)
// DatastorePath contains the components of a datastore path.
type DatastorePath struct {
Datastore string
Path string
}
// FromString parses a datastore path.
// Returns true if the path could be parsed, false otherwise.
func (p *DatastorePath) FromString(s string) bool {
if len(s) == 0 {
return false
}
s = strings.TrimSpace(s)
if !strings.HasPrefix(s, "[") {
return false
}
s = s[1:]
ix := strings.Index(s, "]")
if ix < 0 {
return false
}
p.Datastore = s[:ix]
p.Path = strings.TrimSpace(s[ix+1:])
return true
}
// String formats a datastore path.
func (p *DatastorePath) String() string {
s := fmt.Sprintf("[%s]", p.Datastore)
if p.Path == "" {
return s
}
return strings.Join([]string{s, p.Path}, " ")
}

View File

@ -0,0 +1,76 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"fmt"
"io"
"math"
)
// DiagnosticLog wraps DiagnosticManager.BrowseLog
type DiagnosticLog struct {
m DiagnosticManager
Key string
Host *HostSystem
Start int32
}
// Seek to log position starting at the last nlines of the log
func (l *DiagnosticLog) Seek(ctx context.Context, nlines int32) error {
h, err := l.m.BrowseLog(ctx, l.Host, l.Key, math.MaxInt32, 0)
if err != nil {
return err
}
l.Start = h.LineEnd - nlines
return nil
}
// Copy log starting from l.Start to the given io.Writer
// Returns on error or when end of log is reached.
func (l *DiagnosticLog) Copy(ctx context.Context, w io.Writer) (int, error) {
const max = 500 // VC max == 500, ESX max == 1000
written := 0
for {
h, err := l.m.BrowseLog(ctx, l.Host, l.Key, l.Start, max)
if err != nil {
return 0, err
}
for _, line := range h.LineText {
n, err := fmt.Fprintln(w, line)
written += n
if err != nil {
return written, err
}
}
l.Start += int32(len(h.LineText))
if l.Start >= h.LineEnd {
break
}
}
return written, nil
}

View File

@ -0,0 +1,104 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type DiagnosticManager struct {
Common
}
func NewDiagnosticManager(c *vim25.Client) *DiagnosticManager {
m := DiagnosticManager{
Common: NewCommon(c, *c.ServiceContent.DiagnosticManager),
}
return &m
}
func (m DiagnosticManager) Log(ctx context.Context, host *HostSystem, key string) *DiagnosticLog {
return &DiagnosticLog{
m: m,
Key: key,
Host: host,
}
}
func (m DiagnosticManager) BrowseLog(ctx context.Context, host *HostSystem, key string, start, lines int32) (*types.DiagnosticManagerLogHeader, error) {
req := types.BrowseDiagnosticLog{
This: m.Reference(),
Key: key,
Start: start,
Lines: lines,
}
if host != nil {
ref := host.Reference()
req.Host = &ref
}
res, err := methods.BrowseDiagnosticLog(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
func (m DiagnosticManager) GenerateLogBundles(ctx context.Context, includeDefault bool, host []*HostSystem) (*Task, error) {
req := types.GenerateLogBundles_Task{
This: m.Reference(),
IncludeDefault: includeDefault,
}
if host != nil {
for _, h := range host {
req.Host = append(req.Host, h.Reference())
}
}
res, err := methods.GenerateLogBundles_Task(ctx, m.c, &req)
if err != nil {
return nil, err
}
return NewTask(m.c, res.Returnval), nil
}
func (m DiagnosticManager) QueryDescriptions(ctx context.Context, host *HostSystem) ([]types.DiagnosticManagerLogDescriptor, error) {
req := types.QueryDescriptions{
This: m.Reference(),
}
if host != nil {
ref := host.Reference()
req.Host = &ref
}
res, err := methods.QueryDescriptions(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}

View File

@ -0,0 +1,73 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type DistributedVirtualPortgroup struct {
Common
}
func NewDistributedVirtualPortgroup(c *vim25.Client, ref types.ManagedObjectReference) *DistributedVirtualPortgroup {
return &DistributedVirtualPortgroup{
Common: NewCommon(c, ref),
}
}
// EthernetCardBackingInfo returns the VirtualDeviceBackingInfo for this DistributedVirtualPortgroup
func (p DistributedVirtualPortgroup) EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) {
var dvp mo.DistributedVirtualPortgroup
var dvs mo.VmwareDistributedVirtualSwitch // TODO: should be mo.BaseDistributedVirtualSwitch
if err := p.Properties(ctx, p.Reference(), []string{"key", "config.distributedVirtualSwitch"}, &dvp); err != nil {
return nil, err
}
if err := p.Properties(ctx, *dvp.Config.DistributedVirtualSwitch, []string{"uuid"}, &dvs); err != nil {
return nil, err
}
backing := &types.VirtualEthernetCardDistributedVirtualPortBackingInfo{
Port: types.DistributedVirtualSwitchPortConnection{
PortgroupKey: dvp.Key,
SwitchUuid: dvs.Uuid,
},
}
return backing, nil
}
func (p DistributedVirtualPortgroup) Reconfigure(ctx context.Context, spec types.DVPortgroupConfigSpec) (*Task, error) {
req := types.ReconfigureDVPortgroup_Task{
This: p.Reference(),
Spec: spec,
}
res, err := methods.ReconfigureDVPortgroup_Task(ctx, p.Client(), &req)
if err != nil {
return nil, err
}
return NewTask(p.Client(), res.Returnval), nil
}

View File

@ -0,0 +1,67 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type DistributedVirtualSwitch struct {
Common
}
func NewDistributedVirtualSwitch(c *vim25.Client, ref types.ManagedObjectReference) *DistributedVirtualSwitch {
return &DistributedVirtualSwitch{
Common: NewCommon(c, ref),
}
}
func (s DistributedVirtualSwitch) EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) {
return nil, ErrNotSupported // TODO: just to satisfy NetworkReference interface for the finder
}
func (s DistributedVirtualSwitch) Reconfigure(ctx context.Context, spec types.BaseDVSConfigSpec) (*Task, error) {
req := types.ReconfigureDvs_Task{
This: s.Reference(),
Spec: spec,
}
res, err := methods.ReconfigureDvs_Task(ctx, s.Client(), &req)
if err != nil {
return nil, err
}
return NewTask(s.Client(), res.Returnval), nil
}
func (s DistributedVirtualSwitch) AddPortgroup(ctx context.Context, spec []types.DVPortgroupConfigSpec) (*Task, error) {
req := types.AddDVPortgroup_Task{
This: s.Reference(),
Spec: spec,
}
res, err := methods.AddDVPortgroup_Task(ctx, s.Client(), &req)
if err != nil {
return nil, err
}
return NewTask(s.Client(), res.Returnval), nil
}

View File

@ -0,0 +1,113 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type ExtensionManager struct {
Common
}
// GetExtensionManager wraps NewExtensionManager, returning ErrNotSupported
// when the client is not connected to a vCenter instance.
func GetExtensionManager(c *vim25.Client) (*ExtensionManager, error) {
if c.ServiceContent.ExtensionManager == nil {
return nil, ErrNotSupported
}
return NewExtensionManager(c), nil
}
func NewExtensionManager(c *vim25.Client) *ExtensionManager {
o := ExtensionManager{
Common: NewCommon(c, *c.ServiceContent.ExtensionManager),
}
return &o
}
func (m ExtensionManager) List(ctx context.Context) ([]types.Extension, error) {
var em mo.ExtensionManager
err := m.Properties(ctx, m.Reference(), []string{"extensionList"}, &em)
if err != nil {
return nil, err
}
return em.ExtensionList, nil
}
func (m ExtensionManager) Find(ctx context.Context, key string) (*types.Extension, error) {
req := types.FindExtension{
This: m.Reference(),
ExtensionKey: key,
}
res, err := methods.FindExtension(ctx, m.c, &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (m ExtensionManager) Register(ctx context.Context, extension types.Extension) error {
req := types.RegisterExtension{
This: m.Reference(),
Extension: extension,
}
_, err := methods.RegisterExtension(ctx, m.c, &req)
return err
}
func (m ExtensionManager) SetCertificate(ctx context.Context, key string, certificatePem string) error {
req := types.SetExtensionCertificate{
This: m.Reference(),
ExtensionKey: key,
CertificatePem: certificatePem,
}
_, err := methods.SetExtensionCertificate(ctx, m.c, &req)
return err
}
func (m ExtensionManager) Unregister(ctx context.Context, key string) error {
req := types.UnregisterExtension{
This: m.Reference(),
ExtensionKey: key,
}
_, err := methods.UnregisterExtension(ctx, m.c, &req)
return err
}
func (m ExtensionManager) Update(ctx context.Context, extension types.Extension) error {
req := types.UpdateExtension{
This: m.Reference(),
Extension: extension,
}
_, err := methods.UpdateExtension(ctx, m.c, &req)
return err
}

126
vendor/github.com/vmware/govmomi/object/file_manager.go generated vendored Normal file
View File

@ -0,0 +1,126 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type FileManager struct {
Common
}
func NewFileManager(c *vim25.Client) *FileManager {
f := FileManager{
Common: NewCommon(c, *c.ServiceContent.FileManager),
}
return &f
}
func (f FileManager) CopyDatastoreFile(ctx context.Context, sourceName string, sourceDatacenter *Datacenter, destinationName string, destinationDatacenter *Datacenter, force bool) (*Task, error) {
req := types.CopyDatastoreFile_Task{
This: f.Reference(),
SourceName: sourceName,
DestinationName: destinationName,
Force: types.NewBool(force),
}
if sourceDatacenter != nil {
ref := sourceDatacenter.Reference()
req.SourceDatacenter = &ref
}
if destinationDatacenter != nil {
ref := destinationDatacenter.Reference()
req.DestinationDatacenter = &ref
}
res, err := methods.CopyDatastoreFile_Task(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewTask(f.c, res.Returnval), nil
}
// DeleteDatastoreFile deletes the specified file or folder from the datastore.
func (f FileManager) DeleteDatastoreFile(ctx context.Context, name string, dc *Datacenter) (*Task, error) {
req := types.DeleteDatastoreFile_Task{
This: f.Reference(),
Name: name,
}
if dc != nil {
ref := dc.Reference()
req.Datacenter = &ref
}
res, err := methods.DeleteDatastoreFile_Task(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewTask(f.c, res.Returnval), nil
}
// MakeDirectory creates a folder using the specified name.
func (f FileManager) MakeDirectory(ctx context.Context, name string, dc *Datacenter, createParentDirectories bool) error {
req := types.MakeDirectory{
This: f.Reference(),
Name: name,
CreateParentDirectories: types.NewBool(createParentDirectories),
}
if dc != nil {
ref := dc.Reference()
req.Datacenter = &ref
}
_, err := methods.MakeDirectory(ctx, f.c, &req)
return err
}
func (f FileManager) MoveDatastoreFile(ctx context.Context, sourceName string, sourceDatacenter *Datacenter, destinationName string, destinationDatacenter *Datacenter, force bool) (*Task, error) {
req := types.MoveDatastoreFile_Task{
This: f.Reference(),
SourceName: sourceName,
DestinationName: destinationName,
Force: types.NewBool(force),
}
if sourceDatacenter != nil {
ref := sourceDatacenter.Reference()
req.SourceDatacenter = &ref
}
if destinationDatacenter != nil {
ref := destinationDatacenter.Reference()
req.DestinationDatacenter = &ref
}
res, err := methods.MoveDatastoreFile_Task(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewTask(f.c, res.Returnval), nil
}

227
vendor/github.com/vmware/govmomi/object/folder.go generated vendored Normal file
View File

@ -0,0 +1,227 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type Folder struct {
Common
}
func NewFolder(c *vim25.Client, ref types.ManagedObjectReference) *Folder {
return &Folder{
Common: NewCommon(c, ref),
}
}
func NewRootFolder(c *vim25.Client) *Folder {
f := NewFolder(c, c.ServiceContent.RootFolder)
f.InventoryPath = "/"
return f
}
func (f Folder) Children(ctx context.Context) ([]Reference, error) {
var mf mo.Folder
err := f.Properties(ctx, f.Reference(), []string{"childEntity"}, &mf)
if err != nil {
return nil, err
}
var rs []Reference
for _, e := range mf.ChildEntity {
if r := NewReference(f.c, e); r != nil {
rs = append(rs, r)
}
}
return rs, nil
}
func (f Folder) CreateDatacenter(ctx context.Context, datacenter string) (*Datacenter, error) {
req := types.CreateDatacenter{
This: f.Reference(),
Name: datacenter,
}
res, err := methods.CreateDatacenter(ctx, f.c, &req)
if err != nil {
return nil, err
}
// Response will be nil if this is an ESX host that does not belong to a vCenter
if res == nil {
return nil, nil
}
return NewDatacenter(f.c, res.Returnval), nil
}
func (f Folder) CreateCluster(ctx context.Context, cluster string, spec types.ClusterConfigSpecEx) (*ClusterComputeResource, error) {
req := types.CreateClusterEx{
This: f.Reference(),
Name: cluster,
Spec: spec,
}
res, err := methods.CreateClusterEx(ctx, f.c, &req)
if err != nil {
return nil, err
}
// Response will be nil if this is an ESX host that does not belong to a vCenter
if res == nil {
return nil, nil
}
return NewClusterComputeResource(f.c, res.Returnval), nil
}
func (f Folder) CreateFolder(ctx context.Context, name string) (*Folder, error) {
req := types.CreateFolder{
This: f.Reference(),
Name: name,
}
res, err := methods.CreateFolder(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewFolder(f.c, res.Returnval), err
}
func (f Folder) CreateStoragePod(ctx context.Context, name string) (*StoragePod, error) {
req := types.CreateStoragePod{
This: f.Reference(),
Name: name,
}
res, err := methods.CreateStoragePod(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewStoragePod(f.c, res.Returnval), err
}
func (f Folder) AddStandaloneHost(ctx context.Context, spec types.HostConnectSpec, addConnected bool, license *string, compResSpec *types.BaseComputeResourceConfigSpec) (*Task, error) {
req := types.AddStandaloneHost_Task{
This: f.Reference(),
Spec: spec,
AddConnected: addConnected,
}
if license != nil {
req.License = *license
}
if compResSpec != nil {
req.CompResSpec = *compResSpec
}
res, err := methods.AddStandaloneHost_Task(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewTask(f.c, res.Returnval), nil
}
func (f Folder) CreateVM(ctx context.Context, config types.VirtualMachineConfigSpec, pool *ResourcePool, host *HostSystem) (*Task, error) {
req := types.CreateVM_Task{
This: f.Reference(),
Config: config,
Pool: pool.Reference(),
}
if host != nil {
ref := host.Reference()
req.Host = &ref
}
res, err := methods.CreateVM_Task(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewTask(f.c, res.Returnval), nil
}
func (f Folder) RegisterVM(ctx context.Context, path string, name string, asTemplate bool, pool *ResourcePool, host *HostSystem) (*Task, error) {
req := types.RegisterVM_Task{
This: f.Reference(),
Path: path,
AsTemplate: asTemplate,
}
if name != "" {
req.Name = name
}
if host != nil {
ref := host.Reference()
req.Host = &ref
}
if pool != nil {
ref := pool.Reference()
req.Pool = &ref
}
res, err := methods.RegisterVM_Task(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewTask(f.c, res.Returnval), nil
}
func (f Folder) CreateDVS(ctx context.Context, spec types.DVSCreateSpec) (*Task, error) {
req := types.CreateDVS_Task{
This: f.Reference(),
Spec: spec,
}
res, err := methods.CreateDVS_Task(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewTask(f.c, res.Returnval), nil
}
func (f Folder) MoveInto(ctx context.Context, list []types.ManagedObjectReference) (*Task, error) {
req := types.MoveIntoFolder_Task{
This: f.Reference(),
List: list,
}
res, err := methods.MoveIntoFolder_Task(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewTask(f.c, res.Returnval), nil
}

View File

@ -0,0 +1,72 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HistoryCollector struct {
Common
}
func NewHistoryCollector(c *vim25.Client, ref types.ManagedObjectReference) *HistoryCollector {
return &HistoryCollector{
Common: NewCommon(c, ref),
}
}
func (h HistoryCollector) Destroy(ctx context.Context) error {
req := types.DestroyCollector{
This: h.Reference(),
}
_, err := methods.DestroyCollector(ctx, h.c, &req)
return err
}
func (h HistoryCollector) Reset(ctx context.Context) error {
req := types.ResetCollector{
This: h.Reference(),
}
_, err := methods.ResetCollector(ctx, h.c, &req)
return err
}
func (h HistoryCollector) Rewind(ctx context.Context) error {
req := types.RewindCollector{
This: h.Reference(),
}
_, err := methods.RewindCollector(ctx, h.c, &req)
return err
}
func (h HistoryCollector) SetPageSize(ctx context.Context, maxCount int32) error {
req := types.SetCollectorPageSize{
This: h.Reference(),
MaxCount: maxCount,
}
_, err := methods.SetCollectorPageSize(ctx, h.c, &req)
return err
}

View File

@ -0,0 +1,65 @@
/*
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 object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HostAccountManager struct {
Common
}
func NewHostAccountManager(c *vim25.Client, ref types.ManagedObjectReference) *HostAccountManager {
return &HostAccountManager{
Common: NewCommon(c, ref),
}
}
func (m HostAccountManager) Create(ctx context.Context, user *types.HostAccountSpec) error {
req := types.CreateUser{
This: m.Reference(),
User: user,
}
_, err := methods.CreateUser(ctx, m.Client(), &req)
return err
}
func (m HostAccountManager) Update(ctx context.Context, user *types.HostAccountSpec) error {
req := types.UpdateUser{
This: m.Reference(),
User: user,
}
_, err := methods.UpdateUser(ctx, m.Client(), &req)
return err
}
func (m HostAccountManager) Remove(ctx context.Context, userName string) error {
req := types.RemoveUser{
This: m.Reference(),
UserName: userName,
}
_, err := methods.RemoveUser(ctx, m.Client(), &req)
return err
}

View File

@ -0,0 +1,250 @@
/*
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 object
import (
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"fmt"
"io"
"net/url"
"strings"
"text/tabwriter"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
// HostCertificateInfo provides helpers for types.HostCertificateManagerCertificateInfo
type HostCertificateInfo struct {
types.HostCertificateManagerCertificateInfo
ThumbprintSHA1 string
ThumbprintSHA256 string
Err error
Certificate *x509.Certificate `json:"-"`
subjectName *pkix.Name
issuerName *pkix.Name
}
// FromCertificate converts x509.Certificate to HostCertificateInfo
func (info *HostCertificateInfo) FromCertificate(cert *x509.Certificate) *HostCertificateInfo {
info.Certificate = cert
info.subjectName = &cert.Subject
info.issuerName = &cert.Issuer
info.Issuer = info.fromName(info.issuerName)
info.NotBefore = &cert.NotBefore
info.NotAfter = &cert.NotAfter
info.Subject = info.fromName(info.subjectName)
info.ThumbprintSHA1 = soap.ThumbprintSHA1(cert)
// SHA-256 for info purposes only, API fields all use SHA-1
sum := sha256.Sum256(cert.Raw)
hex := make([]string, len(sum))
for i, b := range sum {
hex[i] = fmt.Sprintf("%02X", b)
}
info.ThumbprintSHA256 = strings.Join(hex, ":")
if info.Status == "" {
info.Status = string(types.HostCertificateManagerCertificateInfoCertificateStatusUnknown)
}
return info
}
// FromURL connects to the given URL.Host via tls.Dial with the given tls.Config and populates the HostCertificateInfo
// via tls.ConnectionState. If the certificate was verified with the given tls.Config, the Err field will be nil.
// Otherwise, Err will be set to the x509.UnknownAuthorityError or x509.HostnameError.
// If tls.Dial returns an error of any other type, that error is returned.
func (info *HostCertificateInfo) FromURL(u *url.URL, config *tls.Config) error {
addr := u.Host
if !(strings.LastIndex(addr, ":") > strings.LastIndex(addr, "]")) {
addr += ":443"
}
conn, err := tls.Dial("tcp", addr, config)
if err != nil {
switch err.(type) {
case x509.UnknownAuthorityError:
case x509.HostnameError:
default:
return err
}
info.Err = err
conn, err = tls.Dial("tcp", addr, &tls.Config{InsecureSkipVerify: true})
if err != nil {
return err
}
} else {
info.Status = string(types.HostCertificateManagerCertificateInfoCertificateStatusGood)
}
state := conn.ConnectionState()
_ = conn.Close()
info.FromCertificate(state.PeerCertificates[0])
return nil
}
var emailAddressOID = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}
func (info *HostCertificateInfo) fromName(name *pkix.Name) string {
var attrs []string
oids := map[string]string{
emailAddressOID.String(): "emailAddress",
}
for _, attr := range name.Names {
if key, ok := oids[attr.Type.String()]; ok {
attrs = append(attrs, fmt.Sprintf("%s=%s", key, attr.Value))
}
}
attrs = append(attrs, fmt.Sprintf("CN=%s", name.CommonName))
add := func(key string, vals []string) {
for _, val := range vals {
attrs = append(attrs, fmt.Sprintf("%s=%s", key, val))
}
}
elts := []struct {
key string
val []string
}{
{"OU", name.OrganizationalUnit},
{"O", name.Organization},
{"L", name.Locality},
{"ST", name.Province},
{"C", name.Country},
}
for _, elt := range elts {
add(elt.key, elt.val)
}
return strings.Join(attrs, ",")
}
func (info *HostCertificateInfo) toName(s string) *pkix.Name {
var name pkix.Name
for _, pair := range strings.Split(s, ",") {
attr := strings.SplitN(pair, "=", 2)
if len(attr) != 2 {
continue
}
v := attr[1]
switch strings.ToLower(attr[0]) {
case "cn":
name.CommonName = v
case "ou":
name.OrganizationalUnit = append(name.OrganizationalUnit, v)
case "o":
name.Organization = append(name.Organization, v)
case "l":
name.Locality = append(name.Locality, v)
case "st":
name.Province = append(name.Province, v)
case "c":
name.Country = append(name.Country, v)
case "emailaddress":
name.Names = append(name.Names, pkix.AttributeTypeAndValue{Type: emailAddressOID, Value: v})
}
}
return &name
}
// SubjectName parses Subject into a pkix.Name
func (info *HostCertificateInfo) SubjectName() *pkix.Name {
if info.subjectName != nil {
return info.subjectName
}
return info.toName(info.Subject)
}
// IssuerName parses Issuer into a pkix.Name
func (info *HostCertificateInfo) IssuerName() *pkix.Name {
if info.issuerName != nil {
return info.issuerName
}
return info.toName(info.Issuer)
}
// Write outputs info similar to the Chrome Certificate Viewer.
func (info *HostCertificateInfo) Write(w io.Writer) error {
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
s := func(val string) string {
if val != "" {
return val
}
return "<Not Part Of Certificate>"
}
ss := func(val []string) string {
return s(strings.Join(val, ","))
}
name := func(n *pkix.Name) {
fmt.Fprintf(tw, " Common Name (CN):\t%s\n", s(n.CommonName))
fmt.Fprintf(tw, " Organization (O):\t%s\n", ss(n.Organization))
fmt.Fprintf(tw, " Organizational Unit (OU):\t%s\n", ss(n.OrganizationalUnit))
}
status := info.Status
if info.Err != nil {
status = fmt.Sprintf("ERROR %s", info.Err)
}
fmt.Fprintf(tw, "Certificate Status:\t%s\n", status)
fmt.Fprintln(tw, "Issued To:\t")
name(info.SubjectName())
fmt.Fprintln(tw, "Issued By:\t")
name(info.IssuerName())
fmt.Fprintln(tw, "Validity Period:\t")
fmt.Fprintf(tw, " Issued On:\t%s\n", info.NotBefore)
fmt.Fprintf(tw, " Expires On:\t%s\n", info.NotAfter)
if info.ThumbprintSHA1 != "" {
fmt.Fprintln(tw, "Thumbprints:\t")
if info.ThumbprintSHA256 != "" {
fmt.Fprintf(tw, " SHA-256 Thumbprint:\t%s\n", info.ThumbprintSHA256)
}
fmt.Fprintf(tw, " SHA-1 Thumbprint:\t%s\n", info.ThumbprintSHA1)
}
return tw.Flush()
}

View File

@ -0,0 +1,162 @@
/*
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 object
import (
"context"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
// HostCertificateManager provides helper methods around the HostSystem.ConfigManager.CertificateManager
type HostCertificateManager struct {
Common
Host *HostSystem
}
// NewHostCertificateManager creates a new HostCertificateManager helper
func NewHostCertificateManager(c *vim25.Client, ref types.ManagedObjectReference, host types.ManagedObjectReference) *HostCertificateManager {
return &HostCertificateManager{
Common: NewCommon(c, ref),
Host: NewHostSystem(c, host),
}
}
// CertificateInfo wraps the host CertificateManager certificateInfo property with the HostCertificateInfo helper.
// The ThumbprintSHA1 field is set to HostSystem.Summary.Config.SslThumbprint if the host system is managed by a vCenter.
func (m HostCertificateManager) CertificateInfo(ctx context.Context) (*HostCertificateInfo, error) {
var hs mo.HostSystem
var cm mo.HostCertificateManager
pc := property.DefaultCollector(m.Client())
err := pc.RetrieveOne(ctx, m.Reference(), []string{"certificateInfo"}, &cm)
if err != nil {
return nil, err
}
_ = pc.RetrieveOne(ctx, m.Host.Reference(), []string{"summary.config.sslThumbprint"}, &hs)
return &HostCertificateInfo{
HostCertificateManagerCertificateInfo: cm.CertificateInfo,
ThumbprintSHA1: hs.Summary.Config.SslThumbprint,
}, nil
}
// GenerateCertificateSigningRequest requests the host system to generate a certificate-signing request (CSR) for itself.
// The CSR is then typically provided to a Certificate Authority to sign and issue the SSL certificate for the host system.
// Use InstallServerCertificate to import this certificate.
func (m HostCertificateManager) GenerateCertificateSigningRequest(ctx context.Context, useIPAddressAsCommonName bool) (string, error) {
req := types.GenerateCertificateSigningRequest{
This: m.Reference(),
UseIpAddressAsCommonName: useIPAddressAsCommonName,
}
res, err := methods.GenerateCertificateSigningRequest(ctx, m.Client(), &req)
if err != nil {
return "", err
}
return res.Returnval, nil
}
// GenerateCertificateSigningRequestByDn requests the host system to generate a certificate-signing request (CSR) for itself.
// Alternative version similar to GenerateCertificateSigningRequest but takes a Distinguished Name (DN) as a parameter.
func (m HostCertificateManager) GenerateCertificateSigningRequestByDn(ctx context.Context, distinguishedName string) (string, error) {
req := types.GenerateCertificateSigningRequestByDn{
This: m.Reference(),
DistinguishedName: distinguishedName,
}
res, err := methods.GenerateCertificateSigningRequestByDn(ctx, m.Client(), &req)
if err != nil {
return "", err
}
return res.Returnval, nil
}
// InstallServerCertificate imports the given SSL certificate to the host system.
func (m HostCertificateManager) InstallServerCertificate(ctx context.Context, cert string) error {
req := types.InstallServerCertificate{
This: m.Reference(),
Cert: cert,
}
_, err := methods.InstallServerCertificate(ctx, m.Client(), &req)
if err != nil {
return err
}
// NotifyAffectedService is internal, not exposing as we don't have a use case other than with InstallServerCertificate
// Without this call, hostd needs to be restarted to use the updated certificate
// Note: using Refresh as it has the same struct/signature, we just need to use different xml name tags
body := struct {
Req *types.Refresh `xml:"urn:vim25 NotifyAffectedServices,omitempty"`
Res *types.RefreshResponse `xml:"urn:vim25 NotifyAffectedServicesResponse,omitempty"`
methods.RefreshBody
}{
Req: &types.Refresh{This: m.Reference()},
}
return m.Client().RoundTrip(ctx, &body, &body)
}
// ListCACertificateRevocationLists returns the SSL CRLs of Certificate Authorities that are trusted by the host system.
func (m HostCertificateManager) ListCACertificateRevocationLists(ctx context.Context) ([]string, error) {
req := types.ListCACertificateRevocationLists{
This: m.Reference(),
}
res, err := methods.ListCACertificateRevocationLists(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
// ListCACertificates returns the SSL certificates of Certificate Authorities that are trusted by the host system.
func (m HostCertificateManager) ListCACertificates(ctx context.Context) ([]string, error) {
req := types.ListCACertificates{
This: m.Reference(),
}
res, err := methods.ListCACertificates(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
// ReplaceCACertificatesAndCRLs replaces the trusted CA certificates and CRL used by the host system.
// These determine whether the server can verify the identity of an external entity.
func (m HostCertificateManager) ReplaceCACertificatesAndCRLs(ctx context.Context, caCert []string, caCrl []string) error {
req := types.ReplaceCACertificatesAndCRLs{
This: m.Reference(),
CaCert: caCert,
CaCrl: caCrl,
}
_, err := methods.ReplaceCACertificatesAndCRLs(ctx, m.Client(), &req)
return err
}

View File

@ -0,0 +1,196 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type HostConfigManager struct {
Common
}
func NewHostConfigManager(c *vim25.Client, ref types.ManagedObjectReference) *HostConfigManager {
return &HostConfigManager{
Common: NewCommon(c, ref),
}
}
func (m HostConfigManager) DatastoreSystem(ctx context.Context) (*HostDatastoreSystem, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.datastoreSystem"}, &h)
if err != nil {
return nil, err
}
return NewHostDatastoreSystem(m.c, *h.ConfigManager.DatastoreSystem), nil
}
func (m HostConfigManager) NetworkSystem(ctx context.Context) (*HostNetworkSystem, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.networkSystem"}, &h)
if err != nil {
return nil, err
}
return NewHostNetworkSystem(m.c, *h.ConfigManager.NetworkSystem), nil
}
func (m HostConfigManager) FirewallSystem(ctx context.Context) (*HostFirewallSystem, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.firewallSystem"}, &h)
if err != nil {
return nil, err
}
return NewHostFirewallSystem(m.c, *h.ConfigManager.FirewallSystem), nil
}
func (m HostConfigManager) StorageSystem(ctx context.Context) (*HostStorageSystem, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.storageSystem"}, &h)
if err != nil {
return nil, err
}
return NewHostStorageSystem(m.c, *h.ConfigManager.StorageSystem), nil
}
func (m HostConfigManager) VirtualNicManager(ctx context.Context) (*HostVirtualNicManager, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.virtualNicManager"}, &h)
if err != nil {
return nil, err
}
return NewHostVirtualNicManager(m.c, *h.ConfigManager.VirtualNicManager, m.Reference()), nil
}
func (m HostConfigManager) VsanSystem(ctx context.Context) (*HostVsanSystem, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.vsanSystem"}, &h)
if err != nil {
return nil, err
}
// Added in 5.5
if h.ConfigManager.VsanSystem == nil {
return nil, ErrNotSupported
}
return NewHostVsanSystem(m.c, *h.ConfigManager.VsanSystem), nil
}
func (m HostConfigManager) VsanInternalSystem(ctx context.Context) (*HostVsanInternalSystem, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.vsanInternalSystem"}, &h)
if err != nil {
return nil, err
}
// Added in 5.5
if h.ConfigManager.VsanInternalSystem == nil {
return nil, ErrNotSupported
}
return NewHostVsanInternalSystem(m.c, *h.ConfigManager.VsanInternalSystem), nil
}
func (m HostConfigManager) AccountManager(ctx context.Context) (*HostAccountManager, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.accountManager"}, &h)
if err != nil {
return nil, err
}
ref := h.ConfigManager.AccountManager // Added in 6.0
if ref == nil {
// Versions < 5.5 can use the ServiceContent ref,
// but we can only use it when connected directly to ESX.
c := m.Client()
if !c.IsVC() {
ref = c.ServiceContent.AccountManager
}
if ref == nil {
return nil, ErrNotSupported
}
}
return NewHostAccountManager(m.c, *ref), nil
}
func (m HostConfigManager) OptionManager(ctx context.Context) (*OptionManager, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.advancedOption"}, &h)
if err != nil {
return nil, err
}
return NewOptionManager(m.c, *h.ConfigManager.AdvancedOption), nil
}
func (m HostConfigManager) ServiceSystem(ctx context.Context) (*HostServiceSystem, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.serviceSystem"}, &h)
if err != nil {
return nil, err
}
return NewHostServiceSystem(m.c, *h.ConfigManager.ServiceSystem), nil
}
func (m HostConfigManager) CertificateManager(ctx context.Context) (*HostCertificateManager, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.certificateManager"}, &h)
if err != nil {
return nil, err
}
// Added in 6.0
if h.ConfigManager.CertificateManager == nil {
return nil, ErrNotSupported
}
return NewHostCertificateManager(m.c, *h.ConfigManager.CertificateManager, m.Reference()), nil
}
func (m HostConfigManager) DateTimeSystem(ctx context.Context) (*HostDateTimeSystem, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.dateTimeSystem"}, &h)
if err != nil {
return nil, err
}
return NewHostDateTimeSystem(m.c, *h.ConfigManager.DateTimeSystem), nil
}

View File

@ -0,0 +1,65 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HostDatastoreBrowser struct {
Common
}
func NewHostDatastoreBrowser(c *vim25.Client, ref types.ManagedObjectReference) *HostDatastoreBrowser {
return &HostDatastoreBrowser{
Common: NewCommon(c, ref),
}
}
func (b HostDatastoreBrowser) SearchDatastore(ctx context.Context, datastorePath string, searchSpec *types.HostDatastoreBrowserSearchSpec) (*Task, error) {
req := types.SearchDatastore_Task{
This: b.Reference(),
DatastorePath: datastorePath,
SearchSpec: searchSpec,
}
res, err := methods.SearchDatastore_Task(ctx, b.c, &req)
if err != nil {
return nil, err
}
return NewTask(b.c, res.Returnval), nil
}
func (b HostDatastoreBrowser) SearchDatastoreSubFolders(ctx context.Context, datastorePath string, searchSpec *types.HostDatastoreBrowserSearchSpec) (*Task, error) {
req := types.SearchDatastoreSubFolders_Task{
This: b.Reference(),
DatastorePath: datastorePath,
SearchSpec: searchSpec,
}
res, err := methods.SearchDatastoreSubFolders_Task(ctx, b.c, &req)
if err != nil {
return nil, err
}
return NewTask(b.c, res.Returnval), nil
}

View File

@ -0,0 +1,119 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HostDatastoreSystem struct {
Common
}
func NewHostDatastoreSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostDatastoreSystem {
return &HostDatastoreSystem{
Common: NewCommon(c, ref),
}
}
func (s HostDatastoreSystem) CreateLocalDatastore(ctx context.Context, name string, path string) (*Datastore, error) {
req := types.CreateLocalDatastore{
This: s.Reference(),
Name: name,
Path: path,
}
res, err := methods.CreateLocalDatastore(ctx, s.Client(), &req)
if err != nil {
return nil, err
}
return NewDatastore(s.Client(), res.Returnval), nil
}
func (s HostDatastoreSystem) CreateNasDatastore(ctx context.Context, spec types.HostNasVolumeSpec) (*Datastore, error) {
req := types.CreateNasDatastore{
This: s.Reference(),
Spec: spec,
}
res, err := methods.CreateNasDatastore(ctx, s.Client(), &req)
if err != nil {
return nil, err
}
return NewDatastore(s.Client(), res.Returnval), nil
}
func (s HostDatastoreSystem) CreateVmfsDatastore(ctx context.Context, spec types.VmfsDatastoreCreateSpec) (*Datastore, error) {
req := types.CreateVmfsDatastore{
This: s.Reference(),
Spec: spec,
}
res, err := methods.CreateVmfsDatastore(ctx, s.Client(), &req)
if err != nil {
return nil, err
}
return NewDatastore(s.Client(), res.Returnval), nil
}
func (s HostDatastoreSystem) Remove(ctx context.Context, ds *Datastore) error {
req := types.RemoveDatastore{
This: s.Reference(),
Datastore: ds.Reference(),
}
_, err := methods.RemoveDatastore(ctx, s.Client(), &req)
if err != nil {
return err
}
return nil
}
func (s HostDatastoreSystem) QueryAvailableDisksForVmfs(ctx context.Context) ([]types.HostScsiDisk, error) {
req := types.QueryAvailableDisksForVmfs{
This: s.Reference(),
}
res, err := methods.QueryAvailableDisksForVmfs(ctx, s.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (s HostDatastoreSystem) QueryVmfsDatastoreCreateOptions(ctx context.Context, devicePath string) ([]types.VmfsDatastoreOption, error) {
req := types.QueryVmfsDatastoreCreateOptions{
This: s.Reference(),
DevicePath: devicePath,
}
res, err := methods.QueryVmfsDatastoreCreateOptions(ctx, s.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}

View File

@ -0,0 +1,69 @@
/*
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 object
import (
"context"
"time"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HostDateTimeSystem struct {
Common
}
func NewHostDateTimeSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostDateTimeSystem {
return &HostDateTimeSystem{
Common: NewCommon(c, ref),
}
}
func (s HostDateTimeSystem) UpdateConfig(ctx context.Context, config types.HostDateTimeConfig) error {
req := types.UpdateDateTimeConfig{
This: s.Reference(),
Config: config,
}
_, err := methods.UpdateDateTimeConfig(ctx, s.c, &req)
return err
}
func (s HostDateTimeSystem) Update(ctx context.Context, date time.Time) error {
req := types.UpdateDateTime{
This: s.Reference(),
DateTime: date,
}
_, err := methods.UpdateDateTime(ctx, s.c, &req)
return err
}
func (s HostDateTimeSystem) Query(ctx context.Context) (*time.Time, error) {
req := types.QueryDateTime{
This: s.Reference(),
}
res, err := methods.QueryDateTime(ctx, s.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}

View File

@ -0,0 +1,181 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"errors"
"fmt"
"strings"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type HostFirewallSystem struct {
Common
}
func NewHostFirewallSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostFirewallSystem {
return &HostFirewallSystem{
Common: NewCommon(c, ref),
}
}
func (s HostFirewallSystem) DisableRuleset(ctx context.Context, id string) error {
req := types.DisableRuleset{
This: s.Reference(),
Id: id,
}
_, err := methods.DisableRuleset(ctx, s.c, &req)
return err
}
func (s HostFirewallSystem) EnableRuleset(ctx context.Context, id string) error {
req := types.EnableRuleset{
This: s.Reference(),
Id: id,
}
_, err := methods.EnableRuleset(ctx, s.c, &req)
return err
}
func (s HostFirewallSystem) Refresh(ctx context.Context) error {
req := types.RefreshFirewall{
This: s.Reference(),
}
_, err := methods.RefreshFirewall(ctx, s.c, &req)
return err
}
func (s HostFirewallSystem) Info(ctx context.Context) (*types.HostFirewallInfo, error) {
var fs mo.HostFirewallSystem
err := s.Properties(ctx, s.Reference(), []string{"firewallInfo"}, &fs)
if err != nil {
return nil, err
}
return fs.FirewallInfo, nil
}
// HostFirewallRulesetList provides helpers for a slice of types.HostFirewallRuleset
type HostFirewallRulesetList []types.HostFirewallRuleset
// ByRule returns a HostFirewallRulesetList where Direction, PortType and Protocol are equal and Port is within range
func (l HostFirewallRulesetList) ByRule(rule types.HostFirewallRule) HostFirewallRulesetList {
var matches HostFirewallRulesetList
for _, rs := range l {
for _, r := range rs.Rule {
if r.PortType != rule.PortType ||
r.Protocol != rule.Protocol ||
r.Direction != rule.Direction {
continue
}
if r.EndPort == 0 && rule.Port == r.Port ||
rule.Port >= r.Port && rule.Port <= r.EndPort {
matches = append(matches, rs)
break
}
}
}
return matches
}
// EnabledByRule returns a HostFirewallRulesetList with Match(rule) applied and filtered via Enabled()
// if enabled param is true, otherwise filtered via Disabled().
// An error is returned if the resulting list is empty.
func (l HostFirewallRulesetList) EnabledByRule(rule types.HostFirewallRule, enabled bool) (HostFirewallRulesetList, error) {
var matched, skipped HostFirewallRulesetList
var matchedKind, skippedKind string
l = l.ByRule(rule)
if enabled {
matched = l.Enabled()
matchedKind = "enabled"
skipped = l.Disabled()
skippedKind = "disabled"
} else {
matched = l.Disabled()
matchedKind = "disabled"
skipped = l.Enabled()
skippedKind = "enabled"
}
if len(matched) == 0 {
msg := fmt.Sprintf("%d %s firewall rulesets match %s %s %s %d, %d %s rulesets match",
len(matched), matchedKind,
rule.Direction, rule.Protocol, rule.PortType, rule.Port,
len(skipped), skippedKind)
if len(skipped) != 0 {
msg += fmt.Sprintf(": %s", strings.Join(skipped.Keys(), ", "))
}
return nil, errors.New(msg)
}
return matched, nil
}
// Enabled returns a HostFirewallRulesetList with enabled rules
func (l HostFirewallRulesetList) Enabled() HostFirewallRulesetList {
var matches HostFirewallRulesetList
for _, rs := range l {
if rs.Enabled {
matches = append(matches, rs)
}
}
return matches
}
// Disabled returns a HostFirewallRulesetList with disabled rules
func (l HostFirewallRulesetList) Disabled() HostFirewallRulesetList {
var matches HostFirewallRulesetList
for _, rs := range l {
if !rs.Enabled {
matches = append(matches, rs)
}
}
return matches
}
// Keys returns the HostFirewallRuleset.Key for each ruleset in the list
func (l HostFirewallRulesetList) Keys() []string {
var keys []string
for _, rs := range l {
keys = append(keys, rs.Key)
}
return keys
}

View File

@ -0,0 +1,358 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HostNetworkSystem struct {
Common
}
func NewHostNetworkSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostNetworkSystem {
return &HostNetworkSystem{
Common: NewCommon(c, ref),
}
}
// AddPortGroup wraps methods.AddPortGroup
func (o HostNetworkSystem) AddPortGroup(ctx context.Context, portgrp types.HostPortGroupSpec) error {
req := types.AddPortGroup{
This: o.Reference(),
Portgrp: portgrp,
}
_, err := methods.AddPortGroup(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// AddServiceConsoleVirtualNic wraps methods.AddServiceConsoleVirtualNic
func (o HostNetworkSystem) AddServiceConsoleVirtualNic(ctx context.Context, portgroup string, nic types.HostVirtualNicSpec) (string, error) {
req := types.AddServiceConsoleVirtualNic{
This: o.Reference(),
Portgroup: portgroup,
Nic: nic,
}
res, err := methods.AddServiceConsoleVirtualNic(ctx, o.c, &req)
if err != nil {
return "", err
}
return res.Returnval, nil
}
// AddVirtualNic wraps methods.AddVirtualNic
func (o HostNetworkSystem) AddVirtualNic(ctx context.Context, portgroup string, nic types.HostVirtualNicSpec) (string, error) {
req := types.AddVirtualNic{
This: o.Reference(),
Portgroup: portgroup,
Nic: nic,
}
res, err := methods.AddVirtualNic(ctx, o.c, &req)
if err != nil {
return "", err
}
return res.Returnval, nil
}
// AddVirtualSwitch wraps methods.AddVirtualSwitch
func (o HostNetworkSystem) AddVirtualSwitch(ctx context.Context, vswitchName string, spec *types.HostVirtualSwitchSpec) error {
req := types.AddVirtualSwitch{
This: o.Reference(),
VswitchName: vswitchName,
Spec: spec,
}
_, err := methods.AddVirtualSwitch(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// QueryNetworkHint wraps methods.QueryNetworkHint
func (o HostNetworkSystem) QueryNetworkHint(ctx context.Context, device []string) error {
req := types.QueryNetworkHint{
This: o.Reference(),
Device: device,
}
_, err := methods.QueryNetworkHint(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// RefreshNetworkSystem wraps methods.RefreshNetworkSystem
func (o HostNetworkSystem) RefreshNetworkSystem(ctx context.Context) error {
req := types.RefreshNetworkSystem{
This: o.Reference(),
}
_, err := methods.RefreshNetworkSystem(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// RemovePortGroup wraps methods.RemovePortGroup
func (o HostNetworkSystem) RemovePortGroup(ctx context.Context, pgName string) error {
req := types.RemovePortGroup{
This: o.Reference(),
PgName: pgName,
}
_, err := methods.RemovePortGroup(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// RemoveServiceConsoleVirtualNic wraps methods.RemoveServiceConsoleVirtualNic
func (o HostNetworkSystem) RemoveServiceConsoleVirtualNic(ctx context.Context, device string) error {
req := types.RemoveServiceConsoleVirtualNic{
This: o.Reference(),
Device: device,
}
_, err := methods.RemoveServiceConsoleVirtualNic(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// RemoveVirtualNic wraps methods.RemoveVirtualNic
func (o HostNetworkSystem) RemoveVirtualNic(ctx context.Context, device string) error {
req := types.RemoveVirtualNic{
This: o.Reference(),
Device: device,
}
_, err := methods.RemoveVirtualNic(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// RemoveVirtualSwitch wraps methods.RemoveVirtualSwitch
func (o HostNetworkSystem) RemoveVirtualSwitch(ctx context.Context, vswitchName string) error {
req := types.RemoveVirtualSwitch{
This: o.Reference(),
VswitchName: vswitchName,
}
_, err := methods.RemoveVirtualSwitch(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// RestartServiceConsoleVirtualNic wraps methods.RestartServiceConsoleVirtualNic
func (o HostNetworkSystem) RestartServiceConsoleVirtualNic(ctx context.Context, device string) error {
req := types.RestartServiceConsoleVirtualNic{
This: o.Reference(),
Device: device,
}
_, err := methods.RestartServiceConsoleVirtualNic(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdateConsoleIpRouteConfig wraps methods.UpdateConsoleIpRouteConfig
func (o HostNetworkSystem) UpdateConsoleIpRouteConfig(ctx context.Context, config types.BaseHostIpRouteConfig) error {
req := types.UpdateConsoleIpRouteConfig{
This: o.Reference(),
Config: config,
}
_, err := methods.UpdateConsoleIpRouteConfig(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdateDnsConfig wraps methods.UpdateDnsConfig
func (o HostNetworkSystem) UpdateDnsConfig(ctx context.Context, config types.BaseHostDnsConfig) error {
req := types.UpdateDnsConfig{
This: o.Reference(),
Config: config,
}
_, err := methods.UpdateDnsConfig(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdateIpRouteConfig wraps methods.UpdateIpRouteConfig
func (o HostNetworkSystem) UpdateIpRouteConfig(ctx context.Context, config types.BaseHostIpRouteConfig) error {
req := types.UpdateIpRouteConfig{
This: o.Reference(),
Config: config,
}
_, err := methods.UpdateIpRouteConfig(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdateIpRouteTableConfig wraps methods.UpdateIpRouteTableConfig
func (o HostNetworkSystem) UpdateIpRouteTableConfig(ctx context.Context, config types.HostIpRouteTableConfig) error {
req := types.UpdateIpRouteTableConfig{
This: o.Reference(),
Config: config,
}
_, err := methods.UpdateIpRouteTableConfig(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdateNetworkConfig wraps methods.UpdateNetworkConfig
func (o HostNetworkSystem) UpdateNetworkConfig(ctx context.Context, config types.HostNetworkConfig, changeMode string) (*types.HostNetworkConfigResult, error) {
req := types.UpdateNetworkConfig{
This: o.Reference(),
Config: config,
ChangeMode: changeMode,
}
res, err := methods.UpdateNetworkConfig(ctx, o.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
// UpdatePhysicalNicLinkSpeed wraps methods.UpdatePhysicalNicLinkSpeed
func (o HostNetworkSystem) UpdatePhysicalNicLinkSpeed(ctx context.Context, device string, linkSpeed *types.PhysicalNicLinkInfo) error {
req := types.UpdatePhysicalNicLinkSpeed{
This: o.Reference(),
Device: device,
LinkSpeed: linkSpeed,
}
_, err := methods.UpdatePhysicalNicLinkSpeed(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdatePortGroup wraps methods.UpdatePortGroup
func (o HostNetworkSystem) UpdatePortGroup(ctx context.Context, pgName string, portgrp types.HostPortGroupSpec) error {
req := types.UpdatePortGroup{
This: o.Reference(),
PgName: pgName,
Portgrp: portgrp,
}
_, err := methods.UpdatePortGroup(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdateServiceConsoleVirtualNic wraps methods.UpdateServiceConsoleVirtualNic
func (o HostNetworkSystem) UpdateServiceConsoleVirtualNic(ctx context.Context, device string, nic types.HostVirtualNicSpec) error {
req := types.UpdateServiceConsoleVirtualNic{
This: o.Reference(),
Device: device,
Nic: nic,
}
_, err := methods.UpdateServiceConsoleVirtualNic(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdateVirtualNic wraps methods.UpdateVirtualNic
func (o HostNetworkSystem) UpdateVirtualNic(ctx context.Context, device string, nic types.HostVirtualNicSpec) error {
req := types.UpdateVirtualNic{
This: o.Reference(),
Device: device,
Nic: nic,
}
_, err := methods.UpdateVirtualNic(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdateVirtualSwitch wraps methods.UpdateVirtualSwitch
func (o HostNetworkSystem) UpdateVirtualSwitch(ctx context.Context, vswitchName string, spec types.HostVirtualSwitchSpec) error {
req := types.UpdateVirtualSwitch{
This: o.Reference(),
VswitchName: vswitchName,
Spec: spec,
}
_, err := methods.UpdateVirtualSwitch(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,88 @@
/*
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 object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type HostServiceSystem struct {
Common
}
func NewHostServiceSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostServiceSystem {
return &HostServiceSystem{
Common: NewCommon(c, ref),
}
}
func (s HostServiceSystem) Service(ctx context.Context) ([]types.HostService, error) {
var ss mo.HostServiceSystem
err := s.Properties(ctx, s.Reference(), []string{"serviceInfo.service"}, &ss)
if err != nil {
return nil, err
}
return ss.ServiceInfo.Service, nil
}
func (s HostServiceSystem) Start(ctx context.Context, id string) error {
req := types.StartService{
This: s.Reference(),
Id: id,
}
_, err := methods.StartService(ctx, s.Client(), &req)
return err
}
func (s HostServiceSystem) Stop(ctx context.Context, id string) error {
req := types.StopService{
This: s.Reference(),
Id: id,
}
_, err := methods.StopService(ctx, s.Client(), &req)
return err
}
func (s HostServiceSystem) Restart(ctx context.Context, id string) error {
req := types.RestartService{
This: s.Reference(),
Id: id,
}
_, err := methods.RestartService(ctx, s.Client(), &req)
return err
}
func (s HostServiceSystem) UpdatePolicy(ctx context.Context, id string, policy string) error {
req := types.UpdateServicePolicy{
This: s.Reference(),
Id: id,
Policy: policy,
}
_, err := methods.UpdateServicePolicy(ctx, s.Client(), &req)
return err
}

View File

@ -0,0 +1,145 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"errors"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HostStorageSystem struct {
Common
}
func NewHostStorageSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostStorageSystem {
return &HostStorageSystem{
Common: NewCommon(c, ref),
}
}
func (s HostStorageSystem) RetrieveDiskPartitionInfo(ctx context.Context, devicePath string) (*types.HostDiskPartitionInfo, error) {
req := types.RetrieveDiskPartitionInfo{
This: s.Reference(),
DevicePath: []string{devicePath},
}
res, err := methods.RetrieveDiskPartitionInfo(ctx, s.c, &req)
if err != nil {
return nil, err
}
if res.Returnval == nil || len(res.Returnval) == 0 {
return nil, errors.New("no partition info")
}
return &res.Returnval[0], nil
}
func (s HostStorageSystem) ComputeDiskPartitionInfo(ctx context.Context, devicePath string, layout types.HostDiskPartitionLayout) (*types.HostDiskPartitionInfo, error) {
req := types.ComputeDiskPartitionInfo{
This: s.Reference(),
DevicePath: devicePath,
Layout: layout,
}
res, err := methods.ComputeDiskPartitionInfo(ctx, s.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
func (s HostStorageSystem) UpdateDiskPartitionInfo(ctx context.Context, devicePath string, spec types.HostDiskPartitionSpec) error {
req := types.UpdateDiskPartitions{
This: s.Reference(),
DevicePath: devicePath,
Spec: spec,
}
_, err := methods.UpdateDiskPartitions(ctx, s.c, &req)
return err
}
func (s HostStorageSystem) RescanAllHba(ctx context.Context) error {
req := types.RescanAllHba{
This: s.Reference(),
}
_, err := methods.RescanAllHba(ctx, s.c, &req)
return err
}
func (s HostStorageSystem) MarkAsSsd(ctx context.Context, uuid string) (*Task, error) {
req := types.MarkAsSsd_Task{
This: s.Reference(),
ScsiDiskUuid: uuid,
}
res, err := methods.MarkAsSsd_Task(ctx, s.c, &req)
if err != nil {
return nil, err
}
return NewTask(s.c, res.Returnval), nil
}
func (s HostStorageSystem) MarkAsNonSsd(ctx context.Context, uuid string) (*Task, error) {
req := types.MarkAsNonSsd_Task{
This: s.Reference(),
ScsiDiskUuid: uuid,
}
res, err := methods.MarkAsNonSsd_Task(ctx, s.c, &req)
if err != nil {
return nil, err
}
return NewTask(s.c, res.Returnval), nil
}
func (s HostStorageSystem) MarkAsLocal(ctx context.Context, uuid string) (*Task, error) {
req := types.MarkAsLocal_Task{
This: s.Reference(),
ScsiDiskUuid: uuid,
}
res, err := methods.MarkAsLocal_Task(ctx, s.c, &req)
if err != nil {
return nil, err
}
return NewTask(s.c, res.Returnval), nil
}
func (s HostStorageSystem) MarkAsNonLocal(ctx context.Context, uuid string) (*Task, error) {
req := types.MarkAsNonLocal_Task{
This: s.Reference(),
ScsiDiskUuid: uuid,
}
res, err := methods.MarkAsNonLocal_Task(ctx, s.c, &req)
if err != nil {
return nil, err
}
return NewTask(s.c, res.Returnval), nil
}

153
vendor/github.com/vmware/govmomi/object/host_system.go generated vendored Normal file
View File

@ -0,0 +1,153 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"fmt"
"net"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type HostSystem struct {
Common
}
func NewHostSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostSystem {
return &HostSystem{
Common: NewCommon(c, ref),
}
}
func (h HostSystem) ConfigManager() *HostConfigManager {
return NewHostConfigManager(h.c, h.Reference())
}
func (h HostSystem) ResourcePool(ctx context.Context) (*ResourcePool, error) {
var mh mo.HostSystem
err := h.Properties(ctx, h.Reference(), []string{"parent"}, &mh)
if err != nil {
return nil, err
}
var mcr *mo.ComputeResource
var parent interface{}
switch mh.Parent.Type {
case "ComputeResource":
mcr = new(mo.ComputeResource)
parent = mcr
case "ClusterComputeResource":
mcc := new(mo.ClusterComputeResource)
mcr = &mcc.ComputeResource
parent = mcc
default:
return nil, fmt.Errorf("unknown host parent type: %s", mh.Parent.Type)
}
err = h.Properties(ctx, *mh.Parent, []string{"resourcePool"}, parent)
if err != nil {
return nil, err
}
pool := NewResourcePool(h.c, *mcr.ResourcePool)
return pool, nil
}
func (h HostSystem) ManagementIPs(ctx context.Context) ([]net.IP, error) {
var mh mo.HostSystem
err := h.Properties(ctx, h.Reference(), []string{"config.virtualNicManagerInfo.netConfig"}, &mh)
if err != nil {
return nil, err
}
var ips []net.IP
for _, nc := range mh.Config.VirtualNicManagerInfo.NetConfig {
if nc.NicType == "management" && len(nc.CandidateVnic) > 0 {
ip := net.ParseIP(nc.CandidateVnic[0].Spec.Ip.IpAddress)
if ip != nil {
ips = append(ips, ip)
}
}
}
return ips, nil
}
func (h HostSystem) Disconnect(ctx context.Context) (*Task, error) {
req := types.DisconnectHost_Task{
This: h.Reference(),
}
res, err := methods.DisconnectHost_Task(ctx, h.c, &req)
if err != nil {
return nil, err
}
return NewTask(h.c, res.Returnval), nil
}
func (h HostSystem) Reconnect(ctx context.Context, cnxSpec *types.HostConnectSpec, reconnectSpec *types.HostSystemReconnectSpec) (*Task, error) {
req := types.ReconnectHost_Task{
This: h.Reference(),
CnxSpec: cnxSpec,
ReconnectSpec: reconnectSpec,
}
res, err := methods.ReconnectHost_Task(ctx, h.c, &req)
if err != nil {
return nil, err
}
return NewTask(h.c, res.Returnval), nil
}
func (h HostSystem) EnterMaintenanceMode(ctx context.Context, timeout int32, evacuate bool, spec *types.HostMaintenanceSpec) (*Task, error) {
req := types.EnterMaintenanceMode_Task{
This: h.Reference(),
Timeout: timeout,
EvacuatePoweredOffVms: types.NewBool(evacuate),
MaintenanceSpec: spec,
}
res, err := methods.EnterMaintenanceMode_Task(ctx, h.c, &req)
if err != nil {
return nil, err
}
return NewTask(h.c, res.Returnval), nil
}
func (h HostSystem) ExitMaintenanceMode(ctx context.Context, timeout int32) (*Task, error) {
req := types.ExitMaintenanceMode_Task{
This: h.Reference(),
Timeout: timeout,
}
res, err := methods.ExitMaintenanceMode_Task(ctx, h.c, &req)
if err != nil {
return nil, err
}
return NewTask(h.c, res.Returnval), nil
}

View File

@ -0,0 +1,93 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type HostVirtualNicManager struct {
Common
Host *HostSystem
}
func NewHostVirtualNicManager(c *vim25.Client, ref types.ManagedObjectReference, host types.ManagedObjectReference) *HostVirtualNicManager {
return &HostVirtualNicManager{
Common: NewCommon(c, ref),
Host: NewHostSystem(c, host),
}
}
func (m HostVirtualNicManager) Info(ctx context.Context) (*types.HostVirtualNicManagerInfo, error) {
var vnm mo.HostVirtualNicManager
err := m.Properties(ctx, m.Reference(), []string{"info"}, &vnm)
if err != nil {
return nil, err
}
return &vnm.Info, nil
}
func (m HostVirtualNicManager) DeselectVnic(ctx context.Context, nicType string, device string) error {
if nicType == string(types.HostVirtualNicManagerNicTypeVsan) {
// Avoid fault.NotSupported:
// "Error deselecting device '$device': VSAN interfaces must be deselected using vim.host.VsanSystem"
s, err := m.Host.ConfigManager().VsanSystem(ctx)
if err != nil {
return err
}
return s.updateVnic(ctx, device, false)
}
req := types.DeselectVnicForNicType{
This: m.Reference(),
NicType: nicType,
Device: device,
}
_, err := methods.DeselectVnicForNicType(ctx, m.Client(), &req)
return err
}
func (m HostVirtualNicManager) SelectVnic(ctx context.Context, nicType string, device string) error {
if nicType == string(types.HostVirtualNicManagerNicTypeVsan) {
// Avoid fault.NotSupported:
// "Error selecting device '$device': VSAN interfaces must be selected using vim.host.VsanSystem"
s, err := m.Host.ConfigManager().VsanSystem(ctx)
if err != nil {
return err
}
return s.updateVnic(ctx, device, true)
}
req := types.SelectVnicForNicType{
This: m.Reference(),
NicType: nicType,
Device: device,
}
_, err := methods.SelectVnicForNicType(ctx, m.Client(), &req)
return err
}

View File

@ -0,0 +1,117 @@
/*
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 object
import (
"context"
"encoding/json"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HostVsanInternalSystem struct {
Common
}
func NewHostVsanInternalSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostVsanInternalSystem {
m := HostVsanInternalSystem{
Common: NewCommon(c, ref),
}
return &m
}
// QueryVsanObjectUuidsByFilter returns vSAN DOM object uuids by filter.
func (m HostVsanInternalSystem) QueryVsanObjectUuidsByFilter(ctx context.Context, uuids []string, limit int32, version int32) ([]string, error) {
req := types.QueryVsanObjectUuidsByFilter{
This: m.Reference(),
Uuids: uuids,
Limit: limit,
Version: version,
}
res, err := methods.QueryVsanObjectUuidsByFilter(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
type VsanObjExtAttrs struct {
Type string `json:"Object type"`
Class string `json:"Object class"`
Size string `json:"Object size"`
Path string `json:"Object path"`
Name string `json:"User friendly name"`
}
func (a *VsanObjExtAttrs) DatastorePath(dir string) string {
l := len(dir)
path := a.Path
if len(path) >= l {
path = a.Path[l:]
}
if path != "" {
return path
}
return a.Name // vmnamespace
}
// GetVsanObjExtAttrs is internal and intended for troubleshooting/debugging situations in the field.
// WARNING: This API can be slow because we do IOs (reads) to all the objects.
func (m HostVsanInternalSystem) GetVsanObjExtAttrs(ctx context.Context, uuids []string) (map[string]VsanObjExtAttrs, error) {
req := types.GetVsanObjExtAttrs{
This: m.Reference(),
Uuids: uuids,
}
res, err := methods.GetVsanObjExtAttrs(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
var attrs map[string]VsanObjExtAttrs
err = json.Unmarshal([]byte(res.Returnval), &attrs)
return attrs, err
}
// DeleteVsanObjects is internal and intended for troubleshooting/debugging only.
// WARNING: This API can be slow because we do IOs to all the objects.
// DOM won't allow access to objects which have lost quorum. Such objects can be deleted with the optional "force" flag.
// These objects may however re-appear with quorum if the absent components come back (network partition gets resolved, etc.)
func (m HostVsanInternalSystem) DeleteVsanObjects(ctx context.Context, uuids []string, force *bool) ([]types.HostVsanInternalSystemDeleteVsanObjectsResult, error) {
req := types.DeleteVsanObjects{
This: m.Reference(),
Uuids: uuids,
Force: force,
}
res, err := methods.DeleteVsanObjects(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}

View File

@ -0,0 +1,88 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type HostVsanSystem struct {
Common
}
func NewHostVsanSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostVsanSystem {
return &HostVsanSystem{
Common: NewCommon(c, ref),
}
}
func (s HostVsanSystem) Update(ctx context.Context, config types.VsanHostConfigInfo) (*Task, error) {
req := types.UpdateVsan_Task{
This: s.Reference(),
Config: config,
}
res, err := methods.UpdateVsan_Task(ctx, s.Client(), &req)
if err != nil {
return nil, err
}
return NewTask(s.Client(), res.Returnval), nil
}
// updateVnic in support of the HostVirtualNicManager.{SelectVnic,DeselectVnic} methods
func (s HostVsanSystem) updateVnic(ctx context.Context, device string, enable bool) error {
var vsan mo.HostVsanSystem
err := s.Properties(ctx, s.Reference(), []string{"config.networkInfo.port"}, &vsan)
if err != nil {
return err
}
info := vsan.Config
var port []types.VsanHostConfigInfoNetworkInfoPortConfig
for _, p := range info.NetworkInfo.Port {
if p.Device == device {
continue
}
port = append(port, p)
}
if enable {
port = append(port, types.VsanHostConfigInfoNetworkInfoPortConfig{
Device: device,
})
}
info.NetworkInfo.Port = port
task, err := s.Update(ctx, info)
if err != nil {
return err
}
_, err = task.WaitForResult(ctx, nil)
return err
}

View File

@ -0,0 +1,143 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"errors"
"fmt"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type HttpNfcLease struct {
Common
}
func NewHttpNfcLease(c *vim25.Client, ref types.ManagedObjectReference) *HttpNfcLease {
return &HttpNfcLease{
Common: NewCommon(c, ref),
}
}
// HttpNfcLeaseAbort wraps methods.HttpNfcLeaseAbort
func (o HttpNfcLease) HttpNfcLeaseAbort(ctx context.Context, fault *types.LocalizedMethodFault) error {
req := types.HttpNfcLeaseAbort{
This: o.Reference(),
Fault: fault,
}
_, err := methods.HttpNfcLeaseAbort(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// HttpNfcLeaseComplete wraps methods.HttpNfcLeaseComplete
func (o HttpNfcLease) HttpNfcLeaseComplete(ctx context.Context) error {
req := types.HttpNfcLeaseComplete{
This: o.Reference(),
}
_, err := methods.HttpNfcLeaseComplete(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// HttpNfcLeaseGetManifest wraps methods.HttpNfcLeaseGetManifest
func (o HttpNfcLease) HttpNfcLeaseGetManifest(ctx context.Context) error {
req := types.HttpNfcLeaseGetManifest{
This: o.Reference(),
}
_, err := methods.HttpNfcLeaseGetManifest(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// HttpNfcLeaseProgress wraps methods.HttpNfcLeaseProgress
func (o HttpNfcLease) HttpNfcLeaseProgress(ctx context.Context, percent int32) error {
req := types.HttpNfcLeaseProgress{
This: o.Reference(),
Percent: percent,
}
_, err := methods.HttpNfcLeaseProgress(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
func (o HttpNfcLease) Wait(ctx context.Context) (*types.HttpNfcLeaseInfo, error) {
var lease mo.HttpNfcLease
pc := property.DefaultCollector(o.c)
err := property.Wait(ctx, pc, o.Reference(), []string{"state", "info", "error"}, func(pc []types.PropertyChange) bool {
done := false
for _, c := range pc {
if c.Val == nil {
continue
}
switch c.Name {
case "error":
val := c.Val.(types.LocalizedMethodFault)
lease.Error = &val
done = true
case "info":
val := c.Val.(types.HttpNfcLeaseInfo)
lease.Info = &val
case "state":
lease.State = c.Val.(types.HttpNfcLeaseState)
if lease.State != types.HttpNfcLeaseStateInitializing {
done = true
}
}
}
return done
})
if err != nil {
return nil, err
}
if lease.State == types.HttpNfcLeaseStateReady {
return lease.Info, nil
}
if lease.Error != nil {
return nil, errors.New(lease.Error.LocalizedMessage)
}
return nil, fmt.Errorf("unexpected nfc lease state: %s", lease.State)
}

View File

@ -0,0 +1,76 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type DatastoreNamespaceManager struct {
Common
}
func NewDatastoreNamespaceManager(c *vim25.Client) *DatastoreNamespaceManager {
n := DatastoreNamespaceManager{
Common: NewCommon(c, *c.ServiceContent.DatastoreNamespaceManager),
}
return &n
}
// CreateDirectory creates a top-level directory on the given vsan datastore, using
// the given user display name hint and opaque storage policy.
func (nm DatastoreNamespaceManager) CreateDirectory(ctx context.Context, ds *Datastore, displayName string, policy string) (string, error) {
req := &types.CreateDirectory{
This: nm.Reference(),
Datastore: ds.Reference(),
DisplayName: displayName,
Policy: policy,
}
resp, err := methods.CreateDirectory(ctx, nm.c, req)
if err != nil {
return "", err
}
return resp.Returnval, nil
}
// DeleteDirectory deletes the given top-level directory from a vsan datastore.
func (nm DatastoreNamespaceManager) DeleteDirectory(ctx context.Context, dc *Datacenter, datastorePath string) error {
req := &types.DeleteDirectory{
This: nm.Reference(),
DatastorePath: datastorePath,
}
if dc != nil {
ref := dc.Reference()
req.Datacenter = &ref
}
if _, err := methods.DeleteDirectory(ctx, nm.c, req); err != nil {
return err
}
return nil
}

56
vendor/github.com/vmware/govmomi/object/network.go generated vendored Normal file
View File

@ -0,0 +1,56 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type Network struct {
Common
}
func NewNetwork(c *vim25.Client, ref types.ManagedObjectReference) *Network {
return &Network{
Common: NewCommon(c, ref),
}
}
// EthernetCardBackingInfo returns the VirtualDeviceBackingInfo for this Network
func (n Network) EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) {
var e mo.Network
// Use Network.Name rather than Common.Name as the latter does not return the complete name if it contains a '/'
// We can't use Common.ObjectName here either as we need the ManagedEntity.Name field is not set since mo.Network
// has its own Name field.
err := n.Properties(ctx, n.Reference(), []string{"name"}, &e)
if err != nil {
return nil, err
}
backing := &types.VirtualEthernetCardNetworkBackingInfo{
VirtualDeviceDeviceBackingInfo: types.VirtualDeviceDeviceBackingInfo{
DeviceName: e.Name,
},
}
return backing, nil
}

View File

@ -0,0 +1,31 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25/types"
)
// The NetworkReference interface is implemented by managed objects
// which can be used as the backing for a VirtualEthernetCard.
type NetworkReference interface {
Reference
EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error)
}

View File

@ -0,0 +1,57 @@
/*
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 object
import (
"context"
"fmt"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type OpaqueNetwork struct {
Common
}
func NewOpaqueNetwork(c *vim25.Client, ref types.ManagedObjectReference) *OpaqueNetwork {
return &OpaqueNetwork{
Common: NewCommon(c, ref),
}
}
// EthernetCardBackingInfo returns the VirtualDeviceBackingInfo for this Network
func (n OpaqueNetwork) EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) {
var net mo.OpaqueNetwork
if err := n.Properties(ctx, n.Reference(), []string{"summary"}, &net); err != nil {
return nil, err
}
summary, ok := net.Summary.(*types.OpaqueNetworkSummary)
if !ok {
return nil, fmt.Errorf("%s unsupported network type: %T", n, net.Summary)
}
backing := &types.VirtualEthernetCardOpaqueNetworkBackingInfo{
OpaqueNetworkId: summary.OpaqueNetworkId,
OpaqueNetworkType: summary.OpaqueNetworkType,
}
return backing, nil
}

View File

@ -0,0 +1,59 @@
/*
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 object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type OptionManager struct {
Common
}
func NewOptionManager(c *vim25.Client, ref types.ManagedObjectReference) *OptionManager {
return &OptionManager{
Common: NewCommon(c, ref),
}
}
func (m OptionManager) Query(ctx context.Context, name string) ([]types.BaseOptionValue, error) {
req := types.QueryOptions{
This: m.Reference(),
Name: name,
}
res, err := methods.QueryOptions(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (m OptionManager) Update(ctx context.Context, value []types.BaseOptionValue) error {
req := types.UpdateOptions{
This: m.Reference(),
ChangedValue: value,
}
_, err := methods.UpdateOptions(ctx, m.Client(), &req)
return err
}

104
vendor/github.com/vmware/govmomi/object/ovf_manager.go generated vendored Normal file
View File

@ -0,0 +1,104 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type OvfManager struct {
Common
}
func NewOvfManager(c *vim25.Client) *OvfManager {
o := OvfManager{
Common: NewCommon(c, *c.ServiceContent.OvfManager),
}
return &o
}
// CreateDescriptor wraps methods.CreateDescriptor
func (o OvfManager) CreateDescriptor(ctx context.Context, obj Reference, cdp types.OvfCreateDescriptorParams) (*types.OvfCreateDescriptorResult, error) {
req := types.CreateDescriptor{
This: o.Reference(),
Obj: obj.Reference(),
Cdp: cdp,
}
res, err := methods.CreateDescriptor(ctx, o.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
// CreateImportSpec wraps methods.CreateImportSpec
func (o OvfManager) CreateImportSpec(ctx context.Context, ovfDescriptor string, resourcePool Reference, datastore Reference, cisp types.OvfCreateImportSpecParams) (*types.OvfCreateImportSpecResult, error) {
req := types.CreateImportSpec{
This: o.Reference(),
OvfDescriptor: ovfDescriptor,
ResourcePool: resourcePool.Reference(),
Datastore: datastore.Reference(),
Cisp: cisp,
}
res, err := methods.CreateImportSpec(ctx, o.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
// ParseDescriptor wraps methods.ParseDescriptor
func (o OvfManager) ParseDescriptor(ctx context.Context, ovfDescriptor string, pdp types.OvfParseDescriptorParams) (*types.OvfParseDescriptorResult, error) {
req := types.ParseDescriptor{
This: o.Reference(),
OvfDescriptor: ovfDescriptor,
Pdp: pdp,
}
res, err := methods.ParseDescriptor(ctx, o.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
// ValidateHost wraps methods.ValidateHost
func (o OvfManager) ValidateHost(ctx context.Context, ovfDescriptor string, host Reference, vhp types.OvfValidateHostParams) (*types.OvfValidateHostResult, error) {
req := types.ValidateHost{
This: o.Reference(),
OvfDescriptor: ovfDescriptor,
Host: host.Reference(),
Vhp: vhp,
}
res, err := methods.ValidateHost(ctx, o.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}

View File

@ -0,0 +1,137 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type ResourcePool struct {
Common
}
func NewResourcePool(c *vim25.Client, ref types.ManagedObjectReference) *ResourcePool {
return &ResourcePool{
Common: NewCommon(c, ref),
}
}
func (p ResourcePool) ImportVApp(ctx context.Context, spec types.BaseImportSpec, folder *Folder, host *HostSystem) (*HttpNfcLease, error) {
req := types.ImportVApp{
This: p.Reference(),
Spec: spec,
}
if folder != nil {
ref := folder.Reference()
req.Folder = &ref
}
if host != nil {
ref := host.Reference()
req.Host = &ref
}
res, err := methods.ImportVApp(ctx, p.c, &req)
if err != nil {
return nil, err
}
return NewHttpNfcLease(p.c, res.Returnval), nil
}
func (p ResourcePool) Create(ctx context.Context, name string, spec types.ResourceConfigSpec) (*ResourcePool, error) {
req := types.CreateResourcePool{
This: p.Reference(),
Name: name,
Spec: spec,
}
res, err := methods.CreateResourcePool(ctx, p.c, &req)
if err != nil {
return nil, err
}
return NewResourcePool(p.c, res.Returnval), nil
}
func (p ResourcePool) CreateVApp(ctx context.Context, name string, resSpec types.ResourceConfigSpec, configSpec types.VAppConfigSpec, folder *Folder) (*VirtualApp, error) {
req := types.CreateVApp{
This: p.Reference(),
Name: name,
ResSpec: resSpec,
ConfigSpec: configSpec,
}
if folder != nil {
ref := folder.Reference()
req.VmFolder = &ref
}
res, err := methods.CreateVApp(ctx, p.c, &req)
if err != nil {
return nil, err
}
return NewVirtualApp(p.c, res.Returnval), nil
}
func (p ResourcePool) UpdateConfig(ctx context.Context, name string, config *types.ResourceConfigSpec) error {
req := types.UpdateConfig{
This: p.Reference(),
Name: name,
Config: config,
}
if config != nil && config.Entity == nil {
ref := p.Reference()
// Create copy of config so changes won't leak back to the caller
newConfig := *config
newConfig.Entity = &ref
req.Config = &newConfig
}
_, err := methods.UpdateConfig(ctx, p.c, &req)
return err
}
func (p ResourcePool) DestroyChildren(ctx context.Context) error {
req := types.DestroyChildren{
This: p.Reference(),
}
_, err := methods.DestroyChildren(ctx, p.c, &req)
return err
}
func (p ResourcePool) Destroy(ctx context.Context) (*Task, error) {
req := types.Destroy_Task{
This: p.Reference(),
}
res, err := methods.Destroy_Task(ctx, p.c, &req)
if err != nil {
return nil, err
}
return NewTask(p.c, res.Returnval), nil
}

163
vendor/github.com/vmware/govmomi/object/search_index.go generated vendored Normal file
View File

@ -0,0 +1,163 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type SearchIndex struct {
Common
}
func NewSearchIndex(c *vim25.Client) *SearchIndex {
s := SearchIndex{
Common: NewCommon(c, *c.ServiceContent.SearchIndex),
}
return &s
}
// FindByDatastorePath finds a virtual machine by its location on a datastore.
func (s SearchIndex) FindByDatastorePath(ctx context.Context, dc *Datacenter, path string) (Reference, error) {
req := types.FindByDatastorePath{
This: s.Reference(),
Datacenter: dc.Reference(),
Path: path,
}
res, err := methods.FindByDatastorePath(ctx, s.c, &req)
if err != nil {
return nil, err
}
if res.Returnval == nil {
return nil, nil
}
return NewReference(s.c, *res.Returnval), nil
}
// FindByDnsName finds a virtual machine or host by DNS name.
func (s SearchIndex) FindByDnsName(ctx context.Context, dc *Datacenter, dnsName string, vmSearch bool) (Reference, error) {
req := types.FindByDnsName{
This: s.Reference(),
DnsName: dnsName,
VmSearch: vmSearch,
}
if dc != nil {
ref := dc.Reference()
req.Datacenter = &ref
}
res, err := methods.FindByDnsName(ctx, s.c, &req)
if err != nil {
return nil, err
}
if res.Returnval == nil {
return nil, nil
}
return NewReference(s.c, *res.Returnval), nil
}
// FindByInventoryPath finds a managed entity based on its location in the inventory.
func (s SearchIndex) FindByInventoryPath(ctx context.Context, path string) (Reference, error) {
req := types.FindByInventoryPath{
This: s.Reference(),
InventoryPath: path,
}
res, err := methods.FindByInventoryPath(ctx, s.c, &req)
if err != nil {
return nil, err
}
if res.Returnval == nil {
return nil, nil
}
return NewReference(s.c, *res.Returnval), nil
}
// FindByIp finds a virtual machine or host by IP address.
func (s SearchIndex) FindByIp(ctx context.Context, dc *Datacenter, ip string, vmSearch bool) (Reference, error) {
req := types.FindByIp{
This: s.Reference(),
Ip: ip,
VmSearch: vmSearch,
}
if dc != nil {
ref := dc.Reference()
req.Datacenter = &ref
}
res, err := methods.FindByIp(ctx, s.c, &req)
if err != nil {
return nil, err
}
if res.Returnval == nil {
return nil, nil
}
return NewReference(s.c, *res.Returnval), nil
}
// FindByUuid finds a virtual machine or host by UUID.
func (s SearchIndex) FindByUuid(ctx context.Context, dc *Datacenter, uuid string, vmSearch bool, instanceUuid *bool) (Reference, error) {
req := types.FindByUuid{
This: s.Reference(),
Uuid: uuid,
VmSearch: vmSearch,
InstanceUuid: instanceUuid,
}
if dc != nil {
ref := dc.Reference()
req.Datacenter = &ref
}
res, err := methods.FindByUuid(ctx, s.c, &req)
if err != nil {
return nil, err
}
if res.Returnval == nil {
return nil, nil
}
return NewReference(s.c, *res.Returnval), nil
}
// FindChild finds a particular child based on a managed entity name.
func (s SearchIndex) FindChild(ctx context.Context, entity Reference, name string) (Reference, error) {
req := types.FindChild{
This: s.Reference(),
Entity: entity.Reference(),
Name: name,
}
res, err := methods.FindChild(ctx, s.c, &req)
if err != nil {
return nil, err
}
if res.Returnval == nil {
return nil, nil
}
return NewReference(s.c, *res.Returnval), nil
}

34
vendor/github.com/vmware/govmomi/object/storage_pod.go generated vendored Normal file
View File

@ -0,0 +1,34 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/types"
)
type StoragePod struct {
*Folder
}
func NewStoragePod(c *vim25.Client, ref types.ManagedObjectReference) *StoragePod {
return &StoragePod{
Folder: &Folder{
Common: NewCommon(c, ref),
},
}
}

View File

@ -0,0 +1,179 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type StorageResourceManager struct {
Common
}
func NewStorageResourceManager(c *vim25.Client) *StorageResourceManager {
sr := StorageResourceManager{
Common: NewCommon(c, *c.ServiceContent.StorageResourceManager),
}
return &sr
}
func (sr StorageResourceManager) ApplyStorageDrsRecommendation(ctx context.Context, key []string) (*Task, error) {
req := types.ApplyStorageDrsRecommendation_Task{
This: sr.Reference(),
Key: key,
}
res, err := methods.ApplyStorageDrsRecommendation_Task(ctx, sr.c, &req)
if err != nil {
return nil, err
}
return NewTask(sr.c, res.Returnval), nil
}
func (sr StorageResourceManager) ApplyStorageDrsRecommendationToPod(ctx context.Context, pod *StoragePod, key string) (*Task, error) {
req := types.ApplyStorageDrsRecommendationToPod_Task{
This: sr.Reference(),
Key: key,
}
if pod != nil {
req.Pod = pod.Reference()
}
res, err := methods.ApplyStorageDrsRecommendationToPod_Task(ctx, sr.c, &req)
if err != nil {
return nil, err
}
return NewTask(sr.c, res.Returnval), nil
}
func (sr StorageResourceManager) CancelStorageDrsRecommendation(ctx context.Context, key []string) error {
req := types.CancelStorageDrsRecommendation{
This: sr.Reference(),
Key: key,
}
_, err := methods.CancelStorageDrsRecommendation(ctx, sr.c, &req)
return err
}
func (sr StorageResourceManager) ConfigureDatastoreIORM(ctx context.Context, datastore *Datastore, spec types.StorageIORMConfigSpec, key string) (*Task, error) {
req := types.ConfigureDatastoreIORM_Task{
This: sr.Reference(),
Spec: spec,
}
if datastore != nil {
req.Datastore = datastore.Reference()
}
res, err := methods.ConfigureDatastoreIORM_Task(ctx, sr.c, &req)
if err != nil {
return nil, err
}
return NewTask(sr.c, res.Returnval), nil
}
func (sr StorageResourceManager) ConfigureStorageDrsForPod(ctx context.Context, pod *StoragePod, spec types.StorageDrsConfigSpec, modify bool) (*Task, error) {
req := types.ConfigureStorageDrsForPod_Task{
This: sr.Reference(),
Spec: spec,
Modify: modify,
}
if pod != nil {
req.Pod = pod.Reference()
}
res, err := methods.ConfigureStorageDrsForPod_Task(ctx, sr.c, &req)
if err != nil {
return nil, err
}
return NewTask(sr.c, res.Returnval), nil
}
func (sr StorageResourceManager) QueryDatastorePerformanceSummary(ctx context.Context, datastore *Datastore) ([]types.StoragePerformanceSummary, error) {
req := types.QueryDatastorePerformanceSummary{
This: sr.Reference(),
}
if datastore != nil {
req.Datastore = datastore.Reference()
}
res, err := methods.QueryDatastorePerformanceSummary(ctx, sr.c, &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (sr StorageResourceManager) QueryIORMConfigOption(ctx context.Context, host *HostSystem) (*types.StorageIORMConfigOption, error) {
req := types.QueryIORMConfigOption{
This: sr.Reference(),
}
if host != nil {
req.Host = host.Reference()
}
res, err := methods.QueryIORMConfigOption(ctx, sr.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
func (sr StorageResourceManager) RecommendDatastores(ctx context.Context, storageSpec types.StoragePlacementSpec) (*types.StoragePlacementResult, error) {
req := types.RecommendDatastores{
This: sr.Reference(),
StorageSpec: storageSpec,
}
res, err := methods.RecommendDatastores(ctx, sr.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
func (sr StorageResourceManager) RefreshStorageDrsRecommendation(ctx context.Context, pod *StoragePod) error {
req := types.RefreshStorageDrsRecommendation{
This: sr.Reference(),
}
if pod != nil {
req.Pod = pod.Reference()
}
_, err := methods.RefreshStorageDrsRecommendation(ctx, sr.c, &req)
return err
}

53
vendor/github.com/vmware/govmomi/object/task.go generated vendored Normal file
View File

@ -0,0 +1,53 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/task"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/progress"
"github.com/vmware/govmomi/vim25/types"
)
// Task is a convenience wrapper around task.Task that keeps a reference to
// the client that was used to create it. This allows users to call the Wait()
// function with only a context parameter, instead of a context parameter, a
// soap.RoundTripper, and reference to the root property collector.
type Task struct {
Common
}
func NewTask(c *vim25.Client, ref types.ManagedObjectReference) *Task {
t := Task{
Common: NewCommon(c, ref),
}
return &t
}
func (t *Task) Wait(ctx context.Context) error {
_, err := t.WaitForResult(ctx, nil)
return err
}
func (t *Task) WaitForResult(ctx context.Context, s progress.Sinker) (*types.TaskInfo, error) {
p := property.DefaultCollector(t.c)
return task.Wait(ctx, t.Reference(), p, s)
}

65
vendor/github.com/vmware/govmomi/object/types.go generated vendored Normal file
View File

@ -0,0 +1,65 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/types"
)
type Reference interface {
Reference() types.ManagedObjectReference
}
func NewReference(c *vim25.Client, e types.ManagedObjectReference) Reference {
switch e.Type {
case "Folder":
return NewFolder(c, e)
case "StoragePod":
return &StoragePod{
NewFolder(c, e),
}
case "Datacenter":
return NewDatacenter(c, e)
case "VirtualMachine":
return NewVirtualMachine(c, e)
case "VirtualApp":
return &VirtualApp{
NewResourcePool(c, e),
}
case "ComputeResource":
return NewComputeResource(c, e)
case "ClusterComputeResource":
return NewClusterComputeResource(c, e)
case "HostSystem":
return NewHostSystem(c, e)
case "Network", "OpaqueNetwork":
return NewNetwork(c, e)
case "ResourcePool":
return NewResourcePool(c, e)
case "DistributedVirtualSwitch":
return NewDistributedVirtualSwitch(c, e)
case "VmwareDistributedVirtualSwitch":
return &VmwareDistributedVirtualSwitch{*NewDistributedVirtualSwitch(c, e)}
case "DistributedVirtualPortgroup":
return NewDistributedVirtualPortgroup(c, e)
case "Datastore":
return NewDatastore(c, e)
default:
panic("Unknown managed entity: " + e.Type)
}
}

105
vendor/github.com/vmware/govmomi/object/virtual_app.go generated vendored Normal file
View File

@ -0,0 +1,105 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type VirtualApp struct {
*ResourcePool
}
func NewVirtualApp(c *vim25.Client, ref types.ManagedObjectReference) *VirtualApp {
return &VirtualApp{
ResourcePool: NewResourcePool(c, ref),
}
}
func (p VirtualApp) CreateChildVM(ctx context.Context, config types.VirtualMachineConfigSpec, host *HostSystem) (*Task, error) {
req := types.CreateChildVM_Task{
This: p.Reference(),
Config: config,
}
if host != nil {
ref := host.Reference()
req.Host = &ref
}
res, err := methods.CreateChildVM_Task(ctx, p.c, &req)
if err != nil {
return nil, err
}
return NewTask(p.c, res.Returnval), nil
}
func (p VirtualApp) UpdateConfig(ctx context.Context, spec types.VAppConfigSpec) error {
req := types.UpdateVAppConfig{
This: p.Reference(),
Spec: spec,
}
_, err := methods.UpdateVAppConfig(ctx, p.c, &req)
return err
}
func (p VirtualApp) PowerOn(ctx context.Context) (*Task, error) {
req := types.PowerOnVApp_Task{
This: p.Reference(),
}
res, err := methods.PowerOnVApp_Task(ctx, p.c, &req)
if err != nil {
return nil, err
}
return NewTask(p.c, res.Returnval), nil
}
func (p VirtualApp) PowerOff(ctx context.Context, force bool) (*Task, error) {
req := types.PowerOffVApp_Task{
This: p.Reference(),
Force: force,
}
res, err := methods.PowerOffVApp_Task(ctx, p.c, &req)
if err != nil {
return nil, err
}
return NewTask(p.c, res.Returnval), nil
}
func (p VirtualApp) Suspend(ctx context.Context) (*Task, error) {
req := types.SuspendVApp_Task{
This: p.Reference(),
}
res, err := methods.SuspendVApp_Task(ctx, p.c, &req)
if err != nil {
return nil, err
}
return NewTask(p.c, res.Returnval), nil
}

View File

@ -0,0 +1,922 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"errors"
"fmt"
"path/filepath"
"reflect"
"regexp"
"sort"
"strings"
"github.com/vmware/govmomi/vim25/types"
)
// Type values for use in BootOrder
const (
DeviceTypeCdrom = "cdrom"
DeviceTypeDisk = "disk"
DeviceTypeEthernet = "ethernet"
DeviceTypeFloppy = "floppy"
)
// VirtualDeviceList provides helper methods for working with a list of virtual devices.
type VirtualDeviceList []types.BaseVirtualDevice
// SCSIControllerTypes are used for adding a new SCSI controller to a VM.
func SCSIControllerTypes() VirtualDeviceList {
// Return a mutable list of SCSI controller types, initialized with defaults.
return VirtualDeviceList([]types.BaseVirtualDevice{
&types.VirtualLsiLogicController{},
&types.VirtualBusLogicController{},
&types.ParaVirtualSCSIController{},
&types.VirtualLsiLogicSASController{},
}).Select(func(device types.BaseVirtualDevice) bool {
c := device.(types.BaseVirtualSCSIController).GetVirtualSCSIController()
c.SharedBus = types.VirtualSCSISharingNoSharing
c.BusNumber = -1
return true
})
}
// EthernetCardTypes are used for adding a new ethernet card to a VM.
func EthernetCardTypes() VirtualDeviceList {
return VirtualDeviceList([]types.BaseVirtualDevice{
&types.VirtualE1000{},
&types.VirtualE1000e{},
&types.VirtualVmxnet3{},
}).Select(func(device types.BaseVirtualDevice) bool {
c := device.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard()
c.GetVirtualDevice().Key = -1
return true
})
}
// Select returns a new list containing all elements of the list for which the given func returns true.
func (l VirtualDeviceList) Select(f func(device types.BaseVirtualDevice) bool) VirtualDeviceList {
var found VirtualDeviceList
for _, device := range l {
if f(device) {
found = append(found, device)
}
}
return found
}
// SelectByType returns a new list with devices that are equal to or extend the given type.
func (l VirtualDeviceList) SelectByType(deviceType types.BaseVirtualDevice) VirtualDeviceList {
dtype := reflect.TypeOf(deviceType)
if dtype == nil {
return nil
}
dname := dtype.Elem().Name()
return l.Select(func(device types.BaseVirtualDevice) bool {
t := reflect.TypeOf(device)
if t == dtype {
return true
}
_, ok := t.Elem().FieldByName(dname)
return ok
})
}
// SelectByBackingInfo returns a new list with devices matching the given backing info.
// If the value of backing is nil, any device with a backing of the same type will be returned.
func (l VirtualDeviceList) SelectByBackingInfo(backing types.BaseVirtualDeviceBackingInfo) VirtualDeviceList {
t := reflect.TypeOf(backing)
return l.Select(func(device types.BaseVirtualDevice) bool {
db := device.GetVirtualDevice().Backing
if db == nil {
return false
}
if reflect.TypeOf(db) != t {
return false
}
if reflect.ValueOf(backing).IsNil() {
// selecting by backing type
return true
}
switch a := db.(type) {
case *types.VirtualEthernetCardNetworkBackingInfo:
b := backing.(*types.VirtualEthernetCardNetworkBackingInfo)
return a.DeviceName == b.DeviceName
case *types.VirtualEthernetCardDistributedVirtualPortBackingInfo:
b := backing.(*types.VirtualEthernetCardDistributedVirtualPortBackingInfo)
return a.Port.SwitchUuid == b.Port.SwitchUuid &&
a.Port.PortgroupKey == b.Port.PortgroupKey
case *types.VirtualDiskFlatVer2BackingInfo:
b := backing.(*types.VirtualDiskFlatVer2BackingInfo)
if a.Parent != nil && b.Parent != nil {
return a.Parent.FileName == b.Parent.FileName
}
return a.FileName == b.FileName
case *types.VirtualSerialPortURIBackingInfo:
b := backing.(*types.VirtualSerialPortURIBackingInfo)
return a.ServiceURI == b.ServiceURI
case types.BaseVirtualDeviceFileBackingInfo:
b := backing.(types.BaseVirtualDeviceFileBackingInfo)
return a.GetVirtualDeviceFileBackingInfo().FileName == b.GetVirtualDeviceFileBackingInfo().FileName
default:
return false
}
})
}
// Find returns the device matching the given name.
func (l VirtualDeviceList) Find(name string) types.BaseVirtualDevice {
for _, device := range l {
if l.Name(device) == name {
return device
}
}
return nil
}
// FindByKey returns the device matching the given key.
func (l VirtualDeviceList) FindByKey(key int32) types.BaseVirtualDevice {
for _, device := range l {
if device.GetVirtualDevice().Key == key {
return device
}
}
return nil
}
// FindIDEController will find the named IDE controller if given, otherwise will pick an available controller.
// An error is returned if the named controller is not found or not an IDE controller. Or, if name is not
// given and no available controller can be found.
func (l VirtualDeviceList) FindIDEController(name string) (*types.VirtualIDEController, error) {
if name != "" {
d := l.Find(name)
if d == nil {
return nil, fmt.Errorf("device '%s' not found", name)
}
if c, ok := d.(*types.VirtualIDEController); ok {
return c, nil
}
return nil, fmt.Errorf("%s is not an IDE controller", name)
}
c := l.PickController((*types.VirtualIDEController)(nil))
if c == nil {
return nil, errors.New("no available IDE controller")
}
return c.(*types.VirtualIDEController), nil
}
// CreateIDEController creates a new IDE controller.
func (l VirtualDeviceList) CreateIDEController() (types.BaseVirtualDevice, error) {
ide := &types.VirtualIDEController{}
ide.Key = l.NewKey()
return ide, nil
}
// FindSCSIController will find the named SCSI controller if given, otherwise will pick an available controller.
// An error is returned if the named controller is not found or not an SCSI controller. Or, if name is not
// given and no available controller can be found.
func (l VirtualDeviceList) FindSCSIController(name string) (*types.VirtualSCSIController, error) {
if name != "" {
d := l.Find(name)
if d == nil {
return nil, fmt.Errorf("device '%s' not found", name)
}
if c, ok := d.(types.BaseVirtualSCSIController); ok {
return c.GetVirtualSCSIController(), nil
}
return nil, fmt.Errorf("%s is not an SCSI controller", name)
}
c := l.PickController((*types.VirtualSCSIController)(nil))
if c == nil {
return nil, errors.New("no available SCSI controller")
}
return c.(types.BaseVirtualSCSIController).GetVirtualSCSIController(), nil
}
// CreateSCSIController creates a new SCSI controller of type name if given, otherwise defaults to lsilogic.
func (l VirtualDeviceList) CreateSCSIController(name string) (types.BaseVirtualDevice, error) {
ctypes := SCSIControllerTypes()
if name == "scsi" || name == "" {
name = ctypes.Type(ctypes[0])
}
found := ctypes.Select(func(device types.BaseVirtualDevice) bool {
return l.Type(device) == name
})
if len(found) == 0 {
return nil, fmt.Errorf("unknown SCSI controller type '%s'", name)
}
c, ok := found[0].(types.BaseVirtualSCSIController)
if !ok {
return nil, fmt.Errorf("invalid SCSI controller type '%s'", name)
}
scsi := c.GetVirtualSCSIController()
scsi.BusNumber = l.newSCSIBusNumber()
scsi.Key = l.NewKey()
scsi.ScsiCtlrUnitNumber = 7
return c.(types.BaseVirtualDevice), nil
}
var scsiBusNumbers = []int{0, 1, 2, 3}
// newSCSIBusNumber returns the bus number to use for adding a new SCSI bus device.
// -1 is returned if there are no bus numbers available.
func (l VirtualDeviceList) newSCSIBusNumber() int32 {
var used []int
for _, d := range l.SelectByType((*types.VirtualSCSIController)(nil)) {
num := d.(types.BaseVirtualSCSIController).GetVirtualSCSIController().BusNumber
if num >= 0 {
used = append(used, int(num))
} // else caller is creating a new vm using SCSIControllerTypes
}
sort.Ints(used)
for i, n := range scsiBusNumbers {
if i == len(used) || n != used[i] {
return int32(n)
}
}
return -1
}
// FindNVMEController will find the named NVME controller if given, otherwise will pick an available controller.
// An error is returned if the named controller is not found or not an NVME controller. Or, if name is not
// given and no available controller can be found.
func (l VirtualDeviceList) FindNVMEController(name string) (*types.VirtualNVMEController, error) {
if name != "" {
d := l.Find(name)
if d == nil {
return nil, fmt.Errorf("device '%s' not found", name)
}
if c, ok := d.(*types.VirtualNVMEController); ok {
return c, nil
}
return nil, fmt.Errorf("%s is not an NVME controller", name)
}
c := l.PickController((*types.VirtualNVMEController)(nil))
if c == nil {
return nil, errors.New("no available NVME controller")
}
return c.(*types.VirtualNVMEController), nil
}
// CreateNVMEController creates a new NVMWE controller.
func (l VirtualDeviceList) CreateNVMEController() (types.BaseVirtualDevice, error) {
nvme := &types.VirtualNVMEController{}
nvme.BusNumber = l.newNVMEBusNumber()
nvme.Key = l.NewKey()
return nvme, nil
}
var nvmeBusNumbers = []int{0, 1, 2, 3}
// newNVMEBusNumber returns the bus number to use for adding a new NVME bus device.
// -1 is returned if there are no bus numbers available.
func (l VirtualDeviceList) newNVMEBusNumber() int32 {
var used []int
for _, d := range l.SelectByType((*types.VirtualNVMEController)(nil)) {
num := d.(types.BaseVirtualController).GetVirtualController().BusNumber
if num >= 0 {
used = append(used, int(num))
} // else caller is creating a new vm using NVMEControllerTypes
}
sort.Ints(used)
for i, n := range nvmeBusNumbers {
if i == len(used) || n != used[i] {
return int32(n)
}
}
return -1
}
// FindDiskController will find an existing ide or scsi disk controller.
func (l VirtualDeviceList) FindDiskController(name string) (types.BaseVirtualController, error) {
switch {
case name == "ide":
return l.FindIDEController("")
case name == "scsi" || name == "":
return l.FindSCSIController("")
case name == "nvme":
return l.FindNVMEController("")
default:
if c, ok := l.Find(name).(types.BaseVirtualController); ok {
return c, nil
}
return nil, fmt.Errorf("%s is not a valid controller", name)
}
}
// PickController returns a controller of the given type(s).
// If no controllers are found or have no available slots, then nil is returned.
func (l VirtualDeviceList) PickController(kind types.BaseVirtualController) types.BaseVirtualController {
l = l.SelectByType(kind.(types.BaseVirtualDevice)).Select(func(device types.BaseVirtualDevice) bool {
num := len(device.(types.BaseVirtualController).GetVirtualController().Device)
switch device.(type) {
case types.BaseVirtualSCSIController:
return num < 15
case *types.VirtualIDEController:
return num < 2
case *types.VirtualNVMEController:
return num < 8
default:
return true
}
})
if len(l) == 0 {
return nil
}
return l[0].(types.BaseVirtualController)
}
// newUnitNumber returns the unit number to use for attaching a new device to the given controller.
func (l VirtualDeviceList) newUnitNumber(c types.BaseVirtualController) int32 {
units := make([]bool, 30)
switch sc := c.(type) {
case types.BaseVirtualSCSIController:
// The SCSI controller sits on its own bus
units[sc.GetVirtualSCSIController().ScsiCtlrUnitNumber] = true
}
key := c.GetVirtualController().Key
for _, device := range l {
d := device.GetVirtualDevice()
if d.ControllerKey == key && d.UnitNumber != nil {
units[int(*d.UnitNumber)] = true
}
}
for unit, used := range units {
if !used {
return int32(unit)
}
}
return -1
}
// NewKey returns the key to use for adding a new device to the device list.
// The device list we're working with here may not be complete (e.g. when
// we're only adding new devices), so any positive keys could conflict with device keys
// that are already in use. To avoid this type of conflict, we can use negative keys
// here, which will be resolved to positive keys by vSphere as the reconfiguration is done.
func (l VirtualDeviceList) NewKey() int32 {
var key int32 = -200
for _, device := range l {
d := device.GetVirtualDevice()
if d.Key < key {
key = d.Key
}
}
return key - 1
}
// AssignController assigns a device to a controller.
func (l VirtualDeviceList) AssignController(device types.BaseVirtualDevice, c types.BaseVirtualController) {
d := device.GetVirtualDevice()
d.ControllerKey = c.GetVirtualController().Key
d.UnitNumber = new(int32)
*d.UnitNumber = l.newUnitNumber(c)
if d.Key == 0 {
d.Key = -1
}
}
// CreateDisk creates a new VirtualDisk device which can be added to a VM.
func (l VirtualDeviceList) CreateDisk(c types.BaseVirtualController, ds types.ManagedObjectReference, name string) *types.VirtualDisk {
// If name is not specified, one will be chosen for you.
// But if when given, make sure it ends in .vmdk, otherwise it will be treated as a directory.
if len(name) > 0 && filepath.Ext(name) != ".vmdk" {
name += ".vmdk"
}
device := &types.VirtualDisk{
VirtualDevice: types.VirtualDevice{
Backing: &types.VirtualDiskFlatVer2BackingInfo{
DiskMode: string(types.VirtualDiskModePersistent),
ThinProvisioned: types.NewBool(true),
VirtualDeviceFileBackingInfo: types.VirtualDeviceFileBackingInfo{
FileName: name,
Datastore: &ds,
},
},
},
}
l.AssignController(device, c)
return device
}
// ChildDisk creates a new VirtualDisk device, linked to the given parent disk, which can be added to a VM.
func (l VirtualDeviceList) ChildDisk(parent *types.VirtualDisk) *types.VirtualDisk {
disk := *parent
backing := disk.Backing.(*types.VirtualDiskFlatVer2BackingInfo)
p := new(DatastorePath)
p.FromString(backing.FileName)
p.Path = ""
// Use specified disk as parent backing to a new disk.
disk.Backing = &types.VirtualDiskFlatVer2BackingInfo{
VirtualDeviceFileBackingInfo: types.VirtualDeviceFileBackingInfo{
FileName: p.String(),
Datastore: backing.Datastore,
},
Parent: backing,
DiskMode: backing.DiskMode,
ThinProvisioned: backing.ThinProvisioned,
}
return &disk
}
func (l VirtualDeviceList) connectivity(device types.BaseVirtualDevice, v bool) error {
c := device.GetVirtualDevice().Connectable
if c == nil {
return fmt.Errorf("%s is not connectable", l.Name(device))
}
c.Connected = v
c.StartConnected = v
return nil
}
// Connect changes the device to connected, returns an error if the device is not connectable.
func (l VirtualDeviceList) Connect(device types.BaseVirtualDevice) error {
return l.connectivity(device, true)
}
// Disconnect changes the device to disconnected, returns an error if the device is not connectable.
func (l VirtualDeviceList) Disconnect(device types.BaseVirtualDevice) error {
return l.connectivity(device, false)
}
// FindCdrom finds a cdrom device with the given name, defaulting to the first cdrom device if any.
func (l VirtualDeviceList) FindCdrom(name string) (*types.VirtualCdrom, error) {
if name != "" {
d := l.Find(name)
if d == nil {
return nil, fmt.Errorf("device '%s' not found", name)
}
if c, ok := d.(*types.VirtualCdrom); ok {
return c, nil
}
return nil, fmt.Errorf("%s is not a cdrom device", name)
}
c := l.SelectByType((*types.VirtualCdrom)(nil))
if len(c) == 0 {
return nil, errors.New("no cdrom device found")
}
return c[0].(*types.VirtualCdrom), nil
}
// CreateCdrom creates a new VirtualCdrom device which can be added to a VM.
func (l VirtualDeviceList) CreateCdrom(c *types.VirtualIDEController) (*types.VirtualCdrom, error) {
device := &types.VirtualCdrom{}
l.AssignController(device, c)
l.setDefaultCdromBacking(device)
device.Connectable = &types.VirtualDeviceConnectInfo{
AllowGuestControl: true,
Connected: true,
StartConnected: true,
}
return device, nil
}
// InsertIso changes the cdrom device backing to use the given iso file.
func (l VirtualDeviceList) InsertIso(device *types.VirtualCdrom, iso string) *types.VirtualCdrom {
device.Backing = &types.VirtualCdromIsoBackingInfo{
VirtualDeviceFileBackingInfo: types.VirtualDeviceFileBackingInfo{
FileName: iso,
},
}
return device
}
// EjectIso removes the iso file based backing and replaces with the default cdrom backing.
func (l VirtualDeviceList) EjectIso(device *types.VirtualCdrom) *types.VirtualCdrom {
l.setDefaultCdromBacking(device)
return device
}
func (l VirtualDeviceList) setDefaultCdromBacking(device *types.VirtualCdrom) {
device.Backing = &types.VirtualCdromAtapiBackingInfo{
VirtualDeviceDeviceBackingInfo: types.VirtualDeviceDeviceBackingInfo{
DeviceName: fmt.Sprintf("%s-%d-%d", DeviceTypeCdrom, device.ControllerKey, device.UnitNumber),
UseAutoDetect: types.NewBool(false),
},
}
}
// FindFloppy finds a floppy device with the given name, defaulting to the first floppy device if any.
func (l VirtualDeviceList) FindFloppy(name string) (*types.VirtualFloppy, error) {
if name != "" {
d := l.Find(name)
if d == nil {
return nil, fmt.Errorf("device '%s' not found", name)
}
if c, ok := d.(*types.VirtualFloppy); ok {
return c, nil
}
return nil, fmt.Errorf("%s is not a floppy device", name)
}
c := l.SelectByType((*types.VirtualFloppy)(nil))
if len(c) == 0 {
return nil, errors.New("no floppy device found")
}
return c[0].(*types.VirtualFloppy), nil
}
// CreateFloppy creates a new VirtualFloppy device which can be added to a VM.
func (l VirtualDeviceList) CreateFloppy() (*types.VirtualFloppy, error) {
device := &types.VirtualFloppy{}
c := l.PickController((*types.VirtualSIOController)(nil))
if c == nil {
return nil, errors.New("no available SIO controller")
}
l.AssignController(device, c)
l.setDefaultFloppyBacking(device)
device.Connectable = &types.VirtualDeviceConnectInfo{
AllowGuestControl: true,
Connected: true,
StartConnected: true,
}
return device, nil
}
// InsertImg changes the floppy device backing to use the given img file.
func (l VirtualDeviceList) InsertImg(device *types.VirtualFloppy, img string) *types.VirtualFloppy {
device.Backing = &types.VirtualFloppyImageBackingInfo{
VirtualDeviceFileBackingInfo: types.VirtualDeviceFileBackingInfo{
FileName: img,
},
}
return device
}
// EjectImg removes the img file based backing and replaces with the default floppy backing.
func (l VirtualDeviceList) EjectImg(device *types.VirtualFloppy) *types.VirtualFloppy {
l.setDefaultFloppyBacking(device)
return device
}
func (l VirtualDeviceList) setDefaultFloppyBacking(device *types.VirtualFloppy) {
device.Backing = &types.VirtualFloppyDeviceBackingInfo{
VirtualDeviceDeviceBackingInfo: types.VirtualDeviceDeviceBackingInfo{
DeviceName: fmt.Sprintf("%s-%d", DeviceTypeFloppy, device.UnitNumber),
UseAutoDetect: types.NewBool(false),
},
}
}
// FindSerialPort finds a serial port device with the given name, defaulting to the first serial port device if any.
func (l VirtualDeviceList) FindSerialPort(name string) (*types.VirtualSerialPort, error) {
if name != "" {
d := l.Find(name)
if d == nil {
return nil, fmt.Errorf("device '%s' not found", name)
}
if c, ok := d.(*types.VirtualSerialPort); ok {
return c, nil
}
return nil, fmt.Errorf("%s is not a serial port device", name)
}
c := l.SelectByType((*types.VirtualSerialPort)(nil))
if len(c) == 0 {
return nil, errors.New("no serial port device found")
}
return c[0].(*types.VirtualSerialPort), nil
}
// CreateSerialPort creates a new VirtualSerialPort device which can be added to a VM.
func (l VirtualDeviceList) CreateSerialPort() (*types.VirtualSerialPort, error) {
device := &types.VirtualSerialPort{
YieldOnPoll: true,
}
c := l.PickController((*types.VirtualSIOController)(nil))
if c == nil {
return nil, errors.New("no available SIO controller")
}
l.AssignController(device, c)
l.setDefaultSerialPortBacking(device)
return device, nil
}
// ConnectSerialPort connects a serial port to a server or client uri.
func (l VirtualDeviceList) ConnectSerialPort(device *types.VirtualSerialPort, uri string, client bool, proxyuri string) *types.VirtualSerialPort {
if strings.HasPrefix(uri, "[") {
device.Backing = &types.VirtualSerialPortFileBackingInfo{
VirtualDeviceFileBackingInfo: types.VirtualDeviceFileBackingInfo{
FileName: uri,
},
}
return device
}
direction := types.VirtualDeviceURIBackingOptionDirectionServer
if client {
direction = types.VirtualDeviceURIBackingOptionDirectionClient
}
device.Backing = &types.VirtualSerialPortURIBackingInfo{
VirtualDeviceURIBackingInfo: types.VirtualDeviceURIBackingInfo{
Direction: string(direction),
ServiceURI: uri,
ProxyURI: proxyuri,
},
}
return device
}
// DisconnectSerialPort disconnects the serial port backing.
func (l VirtualDeviceList) DisconnectSerialPort(device *types.VirtualSerialPort) *types.VirtualSerialPort {
l.setDefaultSerialPortBacking(device)
return device
}
func (l VirtualDeviceList) setDefaultSerialPortBacking(device *types.VirtualSerialPort) {
device.Backing = &types.VirtualSerialPortURIBackingInfo{
VirtualDeviceURIBackingInfo: types.VirtualDeviceURIBackingInfo{
Direction: "client",
ServiceURI: "localhost:0",
},
}
}
// CreateEthernetCard creates a new VirtualEthernetCard of the given name name and initialized with the given backing.
func (l VirtualDeviceList) CreateEthernetCard(name string, backing types.BaseVirtualDeviceBackingInfo) (types.BaseVirtualDevice, error) {
ctypes := EthernetCardTypes()
if name == "" {
name = ctypes.deviceName(ctypes[0])
}
found := ctypes.Select(func(device types.BaseVirtualDevice) bool {
return l.deviceName(device) == name
})
if len(found) == 0 {
return nil, fmt.Errorf("unknown ethernet card type '%s'", name)
}
c, ok := found[0].(types.BaseVirtualEthernetCard)
if !ok {
return nil, fmt.Errorf("invalid ethernet card type '%s'", name)
}
c.GetVirtualEthernetCard().Backing = backing
return c.(types.BaseVirtualDevice), nil
}
// PrimaryMacAddress returns the MacAddress field of the primary VirtualEthernetCard
func (l VirtualDeviceList) PrimaryMacAddress() string {
eth0 := l.Find("ethernet-0")
if eth0 == nil {
return ""
}
return eth0.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard().MacAddress
}
// convert a BaseVirtualDevice to a BaseVirtualMachineBootOptionsBootableDevice
var bootableDevices = map[string]func(device types.BaseVirtualDevice) types.BaseVirtualMachineBootOptionsBootableDevice{
DeviceTypeCdrom: func(types.BaseVirtualDevice) types.BaseVirtualMachineBootOptionsBootableDevice {
return &types.VirtualMachineBootOptionsBootableCdromDevice{}
},
DeviceTypeDisk: func(d types.BaseVirtualDevice) types.BaseVirtualMachineBootOptionsBootableDevice {
return &types.VirtualMachineBootOptionsBootableDiskDevice{
DeviceKey: d.GetVirtualDevice().Key,
}
},
DeviceTypeEthernet: func(d types.BaseVirtualDevice) types.BaseVirtualMachineBootOptionsBootableDevice {
return &types.VirtualMachineBootOptionsBootableEthernetDevice{
DeviceKey: d.GetVirtualDevice().Key,
}
},
DeviceTypeFloppy: func(types.BaseVirtualDevice) types.BaseVirtualMachineBootOptionsBootableDevice {
return &types.VirtualMachineBootOptionsBootableFloppyDevice{}
},
}
// BootOrder returns a list of devices which can be used to set boot order via VirtualMachine.SetBootOptions.
// The order can any of "ethernet", "cdrom", "floppy" or "disk" or by specific device name.
func (l VirtualDeviceList) BootOrder(order []string) []types.BaseVirtualMachineBootOptionsBootableDevice {
var devices []types.BaseVirtualMachineBootOptionsBootableDevice
for _, name := range order {
if kind, ok := bootableDevices[name]; ok {
for _, device := range l {
if l.Type(device) == name {
devices = append(devices, kind(device))
}
}
continue
}
if d := l.Find(name); d != nil {
if kind, ok := bootableDevices[l.Type(d)]; ok {
devices = append(devices, kind(d))
}
}
}
return devices
}
// SelectBootOrder returns an ordered list of devices matching the given bootable device order
func (l VirtualDeviceList) SelectBootOrder(order []types.BaseVirtualMachineBootOptionsBootableDevice) VirtualDeviceList {
var devices VirtualDeviceList
for _, bd := range order {
for _, device := range l {
if kind, ok := bootableDevices[l.Type(device)]; ok {
if reflect.DeepEqual(kind(device), bd) {
devices = append(devices, device)
}
}
}
}
return devices
}
// TypeName returns the vmodl type name of the device
func (l VirtualDeviceList) TypeName(device types.BaseVirtualDevice) string {
dtype := reflect.TypeOf(device)
if dtype == nil {
return ""
}
return dtype.Elem().Name()
}
var deviceNameRegexp = regexp.MustCompile(`(?:Virtual)?(?:Machine)?(\w+?)(?:Card|Device|Controller)?$`)
func (l VirtualDeviceList) deviceName(device types.BaseVirtualDevice) string {
name := "device"
typeName := l.TypeName(device)
m := deviceNameRegexp.FindStringSubmatch(typeName)
if len(m) == 2 {
name = strings.ToLower(m[1])
}
return name
}
// Type returns a human-readable name for the given device
func (l VirtualDeviceList) Type(device types.BaseVirtualDevice) string {
switch device.(type) {
case types.BaseVirtualEthernetCard:
return DeviceTypeEthernet
case *types.ParaVirtualSCSIController:
return "pvscsi"
case *types.VirtualLsiLogicSASController:
return "lsilogic-sas"
case *types.VirtualNVMEController:
return "nvme"
default:
return l.deviceName(device)
}
}
// Name returns a stable, human-readable name for the given device
func (l VirtualDeviceList) Name(device types.BaseVirtualDevice) string {
var key string
var UnitNumber int32
d := device.GetVirtualDevice()
if d.UnitNumber != nil {
UnitNumber = *d.UnitNumber
}
dtype := l.Type(device)
switch dtype {
case DeviceTypeEthernet:
key = fmt.Sprintf("%d", UnitNumber-7)
case DeviceTypeDisk:
key = fmt.Sprintf("%d-%d", d.ControllerKey, UnitNumber)
default:
key = fmt.Sprintf("%d", d.Key)
}
return fmt.Sprintf("%s-%s", dtype, key)
}
// ConfigSpec creates a virtual machine configuration spec for
// the specified operation, for the list of devices in the device list.
func (l VirtualDeviceList) ConfigSpec(op types.VirtualDeviceConfigSpecOperation) ([]types.BaseVirtualDeviceConfigSpec, error) {
var fop types.VirtualDeviceConfigSpecFileOperation
switch op {
case types.VirtualDeviceConfigSpecOperationAdd:
fop = types.VirtualDeviceConfigSpecFileOperationCreate
case types.VirtualDeviceConfigSpecOperationEdit:
fop = types.VirtualDeviceConfigSpecFileOperationReplace
case types.VirtualDeviceConfigSpecOperationRemove:
fop = types.VirtualDeviceConfigSpecFileOperationDestroy
default:
panic("unknown op")
}
var res []types.BaseVirtualDeviceConfigSpec
for _, device := range l {
config := &types.VirtualDeviceConfigSpec{
Device: device,
Operation: op,
}
if disk, ok := device.(*types.VirtualDisk); ok {
config.FileOperation = fop
// Special case to attach an existing disk
if op == types.VirtualDeviceConfigSpecOperationAdd && disk.CapacityInKB == 0 {
childDisk := false
if b, ok := disk.Backing.(*types.VirtualDiskFlatVer2BackingInfo); ok {
childDisk = b.Parent != nil
}
if !childDisk {
// Existing disk, clear file operation
config.FileOperation = ""
}
}
}
res = append(res, config)
}
return res, nil
}

View File

@ -0,0 +1,170 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type VirtualDiskManager struct {
Common
}
func NewVirtualDiskManager(c *vim25.Client) *VirtualDiskManager {
m := VirtualDiskManager{
Common: NewCommon(c, *c.ServiceContent.VirtualDiskManager),
}
return &m
}
// CopyVirtualDisk copies a virtual disk, performing conversions as specified in the spec.
func (m VirtualDiskManager) CopyVirtualDisk(
ctx context.Context,
sourceName string, sourceDatacenter *Datacenter,
destName string, destDatacenter *Datacenter,
destSpec *types.VirtualDiskSpec, force bool) (*Task, error) {
req := types.CopyVirtualDisk_Task{
This: m.Reference(),
SourceName: sourceName,
DestName: destName,
DestSpec: destSpec,
Force: types.NewBool(force),
}
if sourceDatacenter != nil {
ref := sourceDatacenter.Reference()
req.SourceDatacenter = &ref
}
if destDatacenter != nil {
ref := destDatacenter.Reference()
req.DestDatacenter = &ref
}
res, err := methods.CopyVirtualDisk_Task(ctx, m.c, &req)
if err != nil {
return nil, err
}
return NewTask(m.c, res.Returnval), nil
}
// CreateVirtualDisk creates a new virtual disk.
func (m VirtualDiskManager) CreateVirtualDisk(
ctx context.Context,
name string, datacenter *Datacenter,
spec types.BaseVirtualDiskSpec) (*Task, error) {
req := types.CreateVirtualDisk_Task{
This: m.Reference(),
Name: name,
Spec: spec,
}
if datacenter != nil {
ref := datacenter.Reference()
req.Datacenter = &ref
}
res, err := methods.CreateVirtualDisk_Task(ctx, m.c, &req)
if err != nil {
return nil, err
}
return NewTask(m.c, res.Returnval), nil
}
// MoveVirtualDisk moves a virtual disk.
func (m VirtualDiskManager) MoveVirtualDisk(
ctx context.Context,
sourceName string, sourceDatacenter *Datacenter,
destName string, destDatacenter *Datacenter,
force bool) (*Task, error) {
req := types.MoveVirtualDisk_Task{
This: m.Reference(),
SourceName: sourceName,
DestName: destName,
Force: types.NewBool(force),
}
if sourceDatacenter != nil {
ref := sourceDatacenter.Reference()
req.SourceDatacenter = &ref
}
if destDatacenter != nil {
ref := destDatacenter.Reference()
req.DestDatacenter = &ref
}
res, err := methods.MoveVirtualDisk_Task(ctx, m.c, &req)
if err != nil {
return nil, err
}
return NewTask(m.c, res.Returnval), nil
}
// DeleteVirtualDisk deletes a virtual disk.
func (m VirtualDiskManager) DeleteVirtualDisk(ctx context.Context, name string, dc *Datacenter) (*Task, error) {
req := types.DeleteVirtualDisk_Task{
This: m.Reference(),
Name: name,
}
if dc != nil {
ref := dc.Reference()
req.Datacenter = &ref
}
res, err := methods.DeleteVirtualDisk_Task(ctx, m.c, &req)
if err != nil {
return nil, err
}
return NewTask(m.c, res.Returnval), nil
}
// Queries virtual disk uuid
func (m VirtualDiskManager) QueryVirtualDiskUuid(ctx context.Context, name string, dc *Datacenter) (string, error) {
req := types.QueryVirtualDiskUuid{
This: m.Reference(),
Name: name,
}
if dc != nil {
ref := dc.Reference()
req.Datacenter = &ref
}
res, err := methods.QueryVirtualDiskUuid(ctx, m.c, &req)
if err != nil {
return "", err
}
if res == nil {
return "", nil
}
return res.Returnval, nil
}

View File

@ -0,0 +1,97 @@
/*
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 object
import (
"context"
"reflect"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
func init() {
types.Add("ArrayOfVirtualDiskInfo", reflect.TypeOf((*arrayOfVirtualDiskInfo)(nil)).Elem())
types.Add("VirtualDiskInfo", reflect.TypeOf((*VirtualDiskInfo)(nil)).Elem())
}
type arrayOfVirtualDiskInfo struct {
VirtualDiskInfo []VirtualDiskInfo `xml:"VirtualDiskInfo,omitempty"`
}
type queryVirtualDiskInfoTaskRequest struct {
This types.ManagedObjectReference `xml:"_this"`
Name string `xml:"name"`
Datacenter *types.ManagedObjectReference `xml:"datacenter,omitempty"`
IncludeParents bool `xml:"includeParents"`
}
type queryVirtualDiskInfoTaskResponse struct {
Returnval types.ManagedObjectReference `xml:"returnval"`
}
type queryVirtualDiskInfoTaskBody struct {
Req *queryVirtualDiskInfoTaskRequest `xml:"urn:internalvim25 QueryVirtualDiskInfo_Task,omitempty"`
Res *queryVirtualDiskInfoTaskResponse `xml:"urn:vim25 QueryVirtualDiskInfo_TaskResponse,omitempty"`
Err *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *queryVirtualDiskInfoTaskBody) Fault() *soap.Fault { return b.Err }
func queryVirtualDiskInfoTask(ctx context.Context, r soap.RoundTripper, req *queryVirtualDiskInfoTaskRequest) (*queryVirtualDiskInfoTaskResponse, error) {
var reqBody, resBody queryVirtualDiskInfoTaskBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type VirtualDiskInfo struct {
Name string `xml:"unit>name"`
DiskType string `xml:"diskType"`
Parent string `xml:"parent,omitempty"`
}
func (m VirtualDiskManager) QueryVirtualDiskInfo(ctx context.Context, name string, dc *Datacenter, includeParents bool) ([]VirtualDiskInfo, error) {
req := queryVirtualDiskInfoTaskRequest{
This: m.Reference(),
Name: name,
IncludeParents: includeParents,
}
if dc != nil {
ref := dc.Reference()
req.Datacenter = &ref
}
res, err := queryVirtualDiskInfoTask(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
info, err := NewTask(m.Client(), res.Returnval).WaitForResult(ctx, nil)
if err != nil {
return nil, err
}
return info.Result.(arrayOfVirtualDiskInfo).VirtualDiskInfo, nil
}

View File

@ -0,0 +1,759 @@
/*
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 object
import (
"context"
"errors"
"fmt"
"net"
"path"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
const (
PropRuntimePowerState = "summary.runtime.powerState"
)
type VirtualMachine struct {
Common
}
func NewVirtualMachine(c *vim25.Client, ref types.ManagedObjectReference) *VirtualMachine {
return &VirtualMachine{
Common: NewCommon(c, ref),
}
}
func (v VirtualMachine) PowerState(ctx context.Context) (types.VirtualMachinePowerState, error) {
var o mo.VirtualMachine
err := v.Properties(ctx, v.Reference(), []string{PropRuntimePowerState}, &o)
if err != nil {
return "", err
}
return o.Summary.Runtime.PowerState, nil
}
func (v VirtualMachine) PowerOn(ctx context.Context) (*Task, error) {
req := types.PowerOnVM_Task{
This: v.Reference(),
}
res, err := methods.PowerOnVM_Task(ctx, v.c, &req)
if err != nil {
return nil, err
}
return NewTask(v.c, res.Returnval), nil
}
func (v VirtualMachine) PowerOff(ctx context.Context) (*Task, error) {
req := types.PowerOffVM_Task{
This: v.Reference(),
}
res, err := methods.PowerOffVM_Task(ctx, v.c, &req)
if err != nil {
return nil, err
}
return NewTask(v.c, res.Returnval), nil
}
func (v VirtualMachine) Reset(ctx context.Context) (*Task, error) {
req := types.ResetVM_Task{
This: v.Reference(),
}
res, err := methods.ResetVM_Task(ctx, v.c, &req)
if err != nil {
return nil, err
}
return NewTask(v.c, res.Returnval), nil
}
func (v VirtualMachine) Suspend(ctx context.Context) (*Task, error) {
req := types.SuspendVM_Task{
This: v.Reference(),
}
res, err := methods.SuspendVM_Task(ctx, v.c, &req)
if err != nil {
return nil, err
}
return NewTask(v.c, res.Returnval), nil
}
func (v VirtualMachine) ShutdownGuest(ctx context.Context) error {
req := types.ShutdownGuest{
This: v.Reference(),
}
_, err := methods.ShutdownGuest(ctx, v.c, &req)
return err
}
func (v VirtualMachine) RebootGuest(ctx context.Context) error {
req := types.RebootGuest{
This: v.Reference(),
}
_, err := methods.RebootGuest(ctx, v.c, &req)
return err
}
func (v VirtualMachine) Destroy(ctx context.Context) (*Task, error) {
req := types.Destroy_Task{
This: v.Reference(),
}
res, err := methods.Destroy_Task(ctx, v.c, &req)
if err != nil {
return nil, err
}
return NewTask(v.c, res.Returnval), nil
}
func (v VirtualMachine) Clone(ctx context.Context, folder *Folder, name string, config types.VirtualMachineCloneSpec) (*Task, error) {
req := types.CloneVM_Task{
This: v.Reference(),
Folder: folder.Reference(),
Name: name,
Spec: config,
}
res, err := methods.CloneVM_Task(ctx, v.c, &req)
if err != nil {
return nil, err
}
return NewTask(v.c, res.Returnval), nil
}
func (v VirtualMachine) Customize(ctx context.Context, spec types.CustomizationSpec) (*Task, error) {
req := types.CustomizeVM_Task{
This: v.Reference(),
Spec: spec,
}
res, err := methods.CustomizeVM_Task(ctx, v.c, &req)
if err != nil {
return nil, err
}
return NewTask(v.c, res.Returnval), nil
}
func (v VirtualMachine) Relocate(ctx context.Context, config types.VirtualMachineRelocateSpec, priority types.VirtualMachineMovePriority) (*Task, error) {
req := types.RelocateVM_Task{
This: v.Reference(),
Spec: config,
Priority: priority,
}
res, err := methods.RelocateVM_Task(ctx, v.c, &req)
if err != nil {
return nil, err
}
return NewTask(v.c, res.Returnval), nil
}
func (v VirtualMachine) Reconfigure(ctx context.Context, config types.VirtualMachineConfigSpec) (*Task, error) {
req := types.ReconfigVM_Task{
This: v.Reference(),
Spec: config,
}
res, err := methods.ReconfigVM_Task(ctx, v.c, &req)
if err != nil {
return nil, err
}
return NewTask(v.c, res.Returnval), nil
}
func (v VirtualMachine) WaitForIP(ctx context.Context) (string, error) {
var ip string
p := property.DefaultCollector(v.c)
err := property.Wait(ctx, p, v.Reference(), []string{"guest.ipAddress"}, func(pc []types.PropertyChange) bool {
for _, c := range pc {
if c.Name != "guest.ipAddress" {
continue
}
if c.Op != types.PropertyChangeOpAssign {
continue
}
if c.Val == nil {
continue
}
ip = c.Val.(string)
return true
}
return false
})
if err != nil {
return "", err
}
return ip, nil
}
// WaitForNetIP waits for the VM guest.net property to report an IP address for all VM NICs.
// Only consider IPv4 addresses if the v4 param is true.
// By default, wait for all NICs to get an IP address, unless 1 or more device is given.
// A device can be specified by the MAC address or the device name, e.g. "ethernet-0".
// Returns a map with MAC address as the key and IP address list as the value.
func (v VirtualMachine) WaitForNetIP(ctx context.Context, v4 bool, device ...string) (map[string][]string, error) {
macs := make(map[string][]string)
eths := make(map[string]string)
p := property.DefaultCollector(v.c)
// Wait for all NICs to have a MacAddress, which may not be generated yet.
err := property.Wait(ctx, p, v.Reference(), []string{"config.hardware.device"}, func(pc []types.PropertyChange) bool {
for _, c := range pc {
if c.Op != types.PropertyChangeOpAssign {
continue
}
devices := VirtualDeviceList(c.Val.(types.ArrayOfVirtualDevice).VirtualDevice)
for _, d := range devices {
if nic, ok := d.(types.BaseVirtualEthernetCard); ok {
mac := nic.GetVirtualEthernetCard().MacAddress
if mac == "" {
return false
}
macs[mac] = nil
eths[devices.Name(d)] = mac
}
}
}
return true
})
if len(device) != 0 {
// Only wait for specific NIC(s)
macs = make(map[string][]string)
for _, mac := range device {
if eth, ok := eths[mac]; ok {
mac = eth // device name, e.g. "ethernet-0"
}
macs[mac] = nil
}
}
err = property.Wait(ctx, p, v.Reference(), []string{"guest.net"}, func(pc []types.PropertyChange) bool {
for _, c := range pc {
if c.Op != types.PropertyChangeOpAssign {
continue
}
nics := c.Val.(types.ArrayOfGuestNicInfo).GuestNicInfo
for _, nic := range nics {
mac := nic.MacAddress
if mac == "" || nic.IpConfig == nil {
continue
}
for _, ip := range nic.IpConfig.IpAddress {
if _, ok := macs[mac]; !ok {
continue // Ignore any that don't correspond to a VM device
}
if v4 && net.ParseIP(ip.IpAddress).To4() == nil {
continue // Ignore non IPv4 address
}
macs[mac] = append(macs[mac], ip.IpAddress)
}
}
}
for _, ips := range macs {
if len(ips) == 0 {
return false
}
}
return true
})
if err != nil {
return nil, err
}
return macs, nil
}
// Device returns the VirtualMachine's config.hardware.device property.
func (v VirtualMachine) Device(ctx context.Context) (VirtualDeviceList, error) {
var o mo.VirtualMachine
err := v.Properties(ctx, v.Reference(), []string{"config.hardware.device", "summary.runtime.connectionState"}, &o)
if err != nil {
return nil, err
}
// Quoting the SDK doc:
// The virtual machine configuration is not guaranteed to be available.
// For example, the configuration information would be unavailable if the server
// is unable to access the virtual machine files on disk, and is often also unavailable
// during the initial phases of virtual machine creation.
if o.Config == nil {
return nil, fmt.Errorf("%s Config is not available, connectionState=%s",
v.Reference(), o.Summary.Runtime.ConnectionState)
}
return VirtualDeviceList(o.Config.Hardware.Device), nil
}
func (v VirtualMachine) HostSystem(ctx context.Context) (*HostSystem, error) {
var o mo.VirtualMachine
err := v.Properties(ctx, v.Reference(), []string{"summary.runtime.host"}, &o)
if err != nil {
return nil, err
}
host := o.Summary.Runtime.Host
if host == nil {
return nil, errors.New("VM doesn't have a HostSystem")
}
return NewHostSystem(v.c, *host), nil
}
func (v VirtualMachine) ResourcePool(ctx context.Context) (*ResourcePool, error) {
var o mo.VirtualMachine
err := v.Properties(ctx, v.Reference(), []string{"resourcePool"}, &o)
if err != nil {
return nil, err
}
rp := o.ResourcePool
if rp == nil {
return nil, errors.New("VM doesn't have a resourcePool")
}
return NewResourcePool(v.c, *rp), nil
}
func (v VirtualMachine) configureDevice(ctx context.Context, op types.VirtualDeviceConfigSpecOperation, fop types.VirtualDeviceConfigSpecFileOperation, devices ...types.BaseVirtualDevice) error {
spec := types.VirtualMachineConfigSpec{}
for _, device := range devices {
config := &types.VirtualDeviceConfigSpec{
Device: device,
Operation: op,
}
if disk, ok := device.(*types.VirtualDisk); ok {
config.FileOperation = fop
// Special case to attach an existing disk
if op == types.VirtualDeviceConfigSpecOperationAdd && disk.CapacityInKB == 0 {
childDisk := false
if b, ok := disk.Backing.(*types.VirtualDiskFlatVer2BackingInfo); ok {
childDisk = b.Parent != nil
}
if !childDisk {
config.FileOperation = "" // existing disk
}
}
}
spec.DeviceChange = append(spec.DeviceChange, config)
}
task, err := v.Reconfigure(ctx, spec)
if err != nil {
return err
}
return task.Wait(ctx)
}
// AddDevice adds the given devices to the VirtualMachine
func (v VirtualMachine) AddDevice(ctx context.Context, device ...types.BaseVirtualDevice) error {
return v.configureDevice(ctx, types.VirtualDeviceConfigSpecOperationAdd, types.VirtualDeviceConfigSpecFileOperationCreate, device...)
}
// EditDevice edits the given (existing) devices on the VirtualMachine
func (v VirtualMachine) EditDevice(ctx context.Context, device ...types.BaseVirtualDevice) error {
return v.configureDevice(ctx, types.VirtualDeviceConfigSpecOperationEdit, types.VirtualDeviceConfigSpecFileOperationReplace, device...)
}
// RemoveDevice removes the given devices on the VirtualMachine
func (v VirtualMachine) RemoveDevice(ctx context.Context, keepFiles bool, device ...types.BaseVirtualDevice) error {
fop := types.VirtualDeviceConfigSpecFileOperationDestroy
if keepFiles {
fop = ""
}
return v.configureDevice(ctx, types.VirtualDeviceConfigSpecOperationRemove, fop, device...)
}
// BootOptions returns the VirtualMachine's config.bootOptions property.
func (v VirtualMachine) BootOptions(ctx context.Context) (*types.VirtualMachineBootOptions, error) {
var o mo.VirtualMachine
err := v.Properties(ctx, v.Reference(), []string{"config.bootOptions"}, &o)
if err != nil {
return nil, err
}
return o.Config.BootOptions, nil
}
// SetBootOptions reconfigures the VirtualMachine with the given options.
func (v VirtualMachine) SetBootOptions(ctx context.Context, options *types.VirtualMachineBootOptions) error {
spec := types.VirtualMachineConfigSpec{}
spec.BootOptions = options
task, err := v.Reconfigure(ctx, spec)
if err != nil {
return err
}
return task.Wait(ctx)
}
// Answer answers a pending question.
func (v VirtualMachine) Answer(ctx context.Context, id, answer string) error {
req := types.AnswerVM{
This: v.Reference(),
QuestionId: id,
AnswerChoice: answer,
}
_, err := methods.AnswerVM(ctx, v.c, &req)
if err != nil {
return err
}
return nil
}
// CreateSnapshot creates a new snapshot of a virtual machine.
func (v VirtualMachine) CreateSnapshot(ctx context.Context, name string, description string, memory bool, quiesce bool) (*Task, error) {
req := types.CreateSnapshot_Task{
This: v.Reference(),
Name: name,
Description: description,
Memory: memory,
Quiesce: quiesce,
}
res, err := methods.CreateSnapshot_Task(ctx, v.c, &req)
if err != nil {
return nil, err
}
return NewTask(v.c, res.Returnval), nil
}
// RemoveAllSnapshot removes all snapshots of a virtual machine
func (v VirtualMachine) RemoveAllSnapshot(ctx context.Context, consolidate *bool) (*Task, error) {
req := types.RemoveAllSnapshots_Task{
This: v.Reference(),
Consolidate: consolidate,
}
res, err := methods.RemoveAllSnapshots_Task(ctx, v.c, &req)
if err != nil {
return nil, err
}
return NewTask(v.c, res.Returnval), nil
}
type snapshotMap map[string][]Reference
func (m snapshotMap) add(parent string, tree []types.VirtualMachineSnapshotTree) {
for i, st := range tree {
sname := st.Name
names := []string{sname, st.Snapshot.Value}
if parent != "" {
sname = path.Join(parent, sname)
// Add full path as an option to resolve duplicate names
names = append(names, sname)
}
for _, name := range names {
m[name] = append(m[name], &tree[i].Snapshot)
}
m.add(sname, st.ChildSnapshotList)
}
}
// FindSnapshot supports snapshot lookup by name, where name can be:
// 1) snapshot ManagedObjectReference.Value (unique)
// 2) snapshot name (may not be unique)
// 3) snapshot tree path (may not be unique)
func (v VirtualMachine) FindSnapshot(ctx context.Context, name string) (Reference, error) {
var o mo.VirtualMachine
err := v.Properties(ctx, v.Reference(), []string{"snapshot"}, &o)
if err != nil {
return nil, err
}
if o.Snapshot == nil || len(o.Snapshot.RootSnapshotList) == 0 {
return nil, errors.New("No snapshots for this VM")
}
m := make(snapshotMap)
m.add("", o.Snapshot.RootSnapshotList)
s := m[name]
switch len(s) {
case 0:
return nil, fmt.Errorf("snapshot %q not found", name)
case 1:
return s[0], nil
default:
return nil, fmt.Errorf("%q resolves to %d snapshots", name, len(s))
}
}
// RemoveSnapshot removes a named snapshot
func (v VirtualMachine) RemoveSnapshot(ctx context.Context, name string, removeChildren bool, consolidate *bool) (*Task, error) {
snapshot, err := v.FindSnapshot(ctx, name)
if err != nil {
return nil, err
}
req := types.RemoveSnapshot_Task{
This: snapshot.Reference(),
RemoveChildren: removeChildren,
Consolidate: consolidate,
}
res, err := methods.RemoveSnapshot_Task(ctx, v.c, &req)
if err != nil {
return nil, err
}
return NewTask(v.c, res.Returnval), nil
}
// RevertToCurrentSnapshot reverts to the current snapshot
func (v VirtualMachine) RevertToCurrentSnapshot(ctx context.Context, suppressPowerOn bool) (*Task, error) {
req := types.RevertToCurrentSnapshot_Task{
This: v.Reference(),
SuppressPowerOn: types.NewBool(suppressPowerOn),
}
res, err := methods.RevertToCurrentSnapshot_Task(ctx, v.c, &req)
if err != nil {
return nil, err
}
return NewTask(v.c, res.Returnval), nil
}
// RevertToSnapshot reverts to a named snapshot
func (v VirtualMachine) RevertToSnapshot(ctx context.Context, name string, suppressPowerOn bool) (*Task, error) {
snapshot, err := v.FindSnapshot(ctx, name)
if err != nil {
return nil, err
}
req := types.RevertToSnapshot_Task{
This: snapshot.Reference(),
SuppressPowerOn: types.NewBool(suppressPowerOn),
}
res, err := methods.RevertToSnapshot_Task(ctx, v.c, &req)
if err != nil {
return nil, err
}
return NewTask(v.c, res.Returnval), nil
}
// IsToolsRunning returns true if VMware Tools is currently running in the guest OS, and false otherwise.
func (v VirtualMachine) IsToolsRunning(ctx context.Context) (bool, error) {
var o mo.VirtualMachine
err := v.Properties(ctx, v.Reference(), []string{"guest.toolsRunningStatus"}, &o)
if err != nil {
return false, err
}
return o.Guest.ToolsRunningStatus == string(types.VirtualMachineToolsRunningStatusGuestToolsRunning), nil
}
// Wait for the VirtualMachine to change to the desired power state.
func (v VirtualMachine) WaitForPowerState(ctx context.Context, state types.VirtualMachinePowerState) error {
p := property.DefaultCollector(v.c)
err := property.Wait(ctx, p, v.Reference(), []string{PropRuntimePowerState}, func(pc []types.PropertyChange) bool {
for _, c := range pc {
if c.Name != PropRuntimePowerState {
continue
}
if c.Val == nil {
continue
}
ps := c.Val.(types.VirtualMachinePowerState)
if ps == state {
return true
}
}
return false
})
return err
}
func (v VirtualMachine) MarkAsTemplate(ctx context.Context) error {
req := types.MarkAsTemplate{
This: v.Reference(),
}
_, err := methods.MarkAsTemplate(ctx, v.c, &req)
if err != nil {
return err
}
return nil
}
func (v VirtualMachine) MarkAsVirtualMachine(ctx context.Context, pool ResourcePool, host *HostSystem) error {
req := types.MarkAsVirtualMachine{
This: v.Reference(),
Pool: pool.Reference(),
}
if host != nil {
ref := host.Reference()
req.Host = &ref
}
_, err := methods.MarkAsVirtualMachine(ctx, v.c, &req)
if err != nil {
return err
}
return nil
}
func (v VirtualMachine) Migrate(ctx context.Context, pool *ResourcePool, host *HostSystem, priority types.VirtualMachineMovePriority, state types.VirtualMachinePowerState) (*Task, error) {
req := types.MigrateVM_Task{
This: v.Reference(),
Priority: priority,
State: state,
}
if pool != nil {
ref := pool.Reference()
req.Pool = &ref
}
if host != nil {
ref := host.Reference()
req.Host = &ref
}
res, err := methods.MigrateVM_Task(ctx, v.c, &req)
if err != nil {
return nil, err
}
return NewTask(v.c, res.Returnval), nil
}
func (v VirtualMachine) Unregister(ctx context.Context) error {
req := types.UnregisterVM{
This: v.Reference(),
}
_, err := methods.UnregisterVM(ctx, v.Client(), &req)
return err
}
// QueryEnvironmentBrowser is a helper to get the environmentBrowser property.
func (v VirtualMachine) QueryConfigTarget(ctx context.Context) (*types.ConfigTarget, error) {
var vm mo.VirtualMachine
err := v.Properties(ctx, v.Reference(), []string{"environmentBrowser"}, &vm)
if err != nil {
return nil, err
}
req := types.QueryConfigTarget{
This: vm.EnvironmentBrowser,
}
res, err := methods.QueryConfigTarget(ctx, v.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (v VirtualMachine) MountToolsInstaller(ctx context.Context) error {
req := types.MountToolsInstaller{
This: v.Reference(),
}
_, err := methods.MountToolsInstaller(ctx, v.Client(), &req)
return err
}
func (v VirtualMachine) UnmountToolsInstaller(ctx context.Context) error {
req := types.UnmountToolsInstaller{
This: v.Reference(),
}
_, err := methods.UnmountToolsInstaller(ctx, v.Client(), &req)
return err
}
func (v VirtualMachine) UpgradeTools(ctx context.Context, options string) (*Task, error) {
req := types.UpgradeTools_Task{
This: v.Reference(),
InstallerOptions: options,
}
res, err := methods.UpgradeTools_Task(ctx, v.Client(), &req)
if err != nil {
return nil, err
}
return NewTask(v.c, res.Returnval), nil
}

View File

@ -0,0 +1,21 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
type VmwareDistributedVirtualSwitch struct {
DistributedVirtualSwitch
}

201
vendor/github.com/vmware/govmomi/property/collector.go generated vendored Normal file
View File

@ -0,0 +1,201 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package property
import (
"context"
"errors"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
// Collector models the PropertyCollector managed object.
//
// For more information, see:
// http://pubs.vmware.com/vsphere-60/index.jsp?topic=%2Fcom.vmware.wssdk.apiref.doc%2Fvmodl.query.PropertyCollector.html
//
type Collector struct {
roundTripper soap.RoundTripper
reference types.ManagedObjectReference
}
// DefaultCollector returns the session's default property collector.
func DefaultCollector(c *vim25.Client) *Collector {
p := Collector{
roundTripper: c,
reference: c.ServiceContent.PropertyCollector,
}
return &p
}
func (p Collector) Reference() types.ManagedObjectReference {
return p.reference
}
// Create creates a new session-specific Collector that can be used to
// retrieve property updates independent of any other Collector.
func (p *Collector) Create(ctx context.Context) (*Collector, error) {
req := types.CreatePropertyCollector{
This: p.Reference(),
}
res, err := methods.CreatePropertyCollector(ctx, p.roundTripper, &req)
if err != nil {
return nil, err
}
newp := Collector{
roundTripper: p.roundTripper,
reference: res.Returnval,
}
return &newp, nil
}
// Destroy destroys this Collector.
func (p *Collector) Destroy(ctx context.Context) error {
req := types.DestroyPropertyCollector{
This: p.Reference(),
}
_, err := methods.DestroyPropertyCollector(ctx, p.roundTripper, &req)
if err != nil {
return err
}
p.reference = types.ManagedObjectReference{}
return nil
}
func (p *Collector) CreateFilter(ctx context.Context, req types.CreateFilter) error {
req.This = p.Reference()
_, err := methods.CreateFilter(ctx, p.roundTripper, &req)
if err != nil {
return err
}
return nil
}
func (p *Collector) WaitForUpdates(ctx context.Context, v string) (*types.UpdateSet, error) {
req := types.WaitForUpdatesEx{
This: p.Reference(),
Version: v,
}
res, err := methods.WaitForUpdatesEx(ctx, p.roundTripper, &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (p *Collector) RetrieveProperties(ctx context.Context, req types.RetrieveProperties) (*types.RetrievePropertiesResponse, error) {
req.This = p.Reference()
return methods.RetrieveProperties(ctx, p.roundTripper, &req)
}
// Retrieve loads properties for a slice of managed objects. The dst argument
// must be a pointer to a []interface{}, which is populated with the instances
// of the specified managed objects, with the relevant properties filled in. If
// the properties slice is nil, all properties are loaded.
func (p *Collector) Retrieve(ctx context.Context, objs []types.ManagedObjectReference, ps []string, dst interface{}) error {
var propSpec *types.PropertySpec
var objectSet []types.ObjectSpec
for _, obj := range objs {
// Ensure that all object reference types are the same
if propSpec == nil {
propSpec = &types.PropertySpec{
Type: obj.Type,
}
if ps == nil {
propSpec.All = types.NewBool(true)
} else {
propSpec.PathSet = ps
}
} else {
if obj.Type != propSpec.Type {
return errors.New("object references must have the same type")
}
}
objectSpec := types.ObjectSpec{
Obj: obj,
Skip: types.NewBool(false),
}
objectSet = append(objectSet, objectSpec)
}
req := types.RetrieveProperties{
SpecSet: []types.PropertyFilterSpec{
{
ObjectSet: objectSet,
PropSet: []types.PropertySpec{*propSpec},
},
},
}
res, err := p.RetrieveProperties(ctx, req)
if err != nil {
return err
}
if d, ok := dst.(*[]types.ObjectContent); ok {
*d = res.Returnval
return nil
}
return mo.LoadRetrievePropertiesResponse(res, dst)
}
// RetrieveWithFilter populates dst as Retrieve does, but only for entities matching the given filter.
func (p *Collector) RetrieveWithFilter(ctx context.Context, objs []types.ManagedObjectReference, ps []string, dst interface{}, filter Filter) error {
if len(filter) == 0 {
return p.Retrieve(ctx, objs, ps, dst)
}
var content []types.ObjectContent
err := p.Retrieve(ctx, objs, filter.Keys(), &content)
if err != nil {
return err
}
objs = filter.MatchObjectContent(content)
if len(objs) == 0 {
return nil
}
return p.Retrieve(ctx, objs, ps, dst)
}
// RetrieveOne calls Retrieve with a single managed object reference.
func (p *Collector) RetrieveOne(ctx context.Context, obj types.ManagedObjectReference, ps []string, dst interface{}) error {
var objs = []types.ManagedObjectReference{obj}
return p.Retrieve(ctx, objs, ps, dst)
}

139
vendor/github.com/vmware/govmomi/property/filter.go generated vendored Normal file
View File

@ -0,0 +1,139 @@
/*
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 property
import (
"fmt"
"path"
"reflect"
"strconv"
"strings"
"github.com/vmware/govmomi/vim25/types"
)
// Filter provides methods for matching against types.DynamicProperty
type Filter map[string]types.AnyType
// Keys returns the Filter map keys as a []string
func (f Filter) Keys() []string {
keys := make([]string, 0, len(f))
for key := range f {
keys = append(keys, key)
}
return keys
}
// MatchProperty returns true if a Filter entry matches the given prop.
func (f Filter) MatchProperty(prop types.DynamicProperty) bool {
match, ok := f[prop.Name]
if !ok {
return false
}
if match == prop.Val {
return true
}
ptype := reflect.TypeOf(prop.Val)
if strings.HasPrefix(ptype.Name(), "ArrayOf") {
pval := reflect.ValueOf(prop.Val).Field(0)
for i := 0; i < pval.Len(); i++ {
prop.Val = pval.Index(i).Interface()
if f.MatchProperty(prop) {
return true
}
}
return false
}
if reflect.TypeOf(match) != ptype {
s, ok := match.(string)
if !ok {
return false
}
// convert if we can
switch prop.Val.(type) {
case bool:
match, _ = strconv.ParseBool(s)
case int16:
x, _ := strconv.ParseInt(s, 10, 16)
match = int16(x)
case int32:
x, _ := strconv.ParseInt(s, 10, 32)
match = int32(x)
case int64:
match, _ = strconv.ParseInt(s, 10, 64)
case float32:
x, _ := strconv.ParseFloat(s, 32)
match = float32(x)
case float64:
match, _ = strconv.ParseFloat(s, 64)
case fmt.Stringer:
prop.Val = prop.Val.(fmt.Stringer).String()
default:
if ptype.Kind() != reflect.String {
return false
}
// An enum type we can convert to a string type
prop.Val = reflect.ValueOf(prop.Val).String()
}
}
switch pval := prop.Val.(type) {
case string:
s := match.(string)
if s == "*" {
return true // TODO: path.Match fails if s contains a '/'
}
m, _ := path.Match(s, pval)
return m
default:
return reflect.DeepEqual(match, pval)
}
}
// MatchPropertyList returns true if all given props match the Filter.
func (f Filter) MatchPropertyList(props []types.DynamicProperty) bool {
for _, p := range props {
if !f.MatchProperty(p) {
return false
}
}
return true
}
// MatchObjectContent returns a list of ObjectContent.Obj where the ObjectContent.PropSet matches the Filter.
func (f Filter) MatchObjectContent(objects []types.ObjectContent) []types.ManagedObjectReference {
var refs []types.ManagedObjectReference
for _, o := range objects {
if f.MatchPropertyList(o.PropSet) {
refs = append(refs, o.Obj)
}
}
return refs
}

153
vendor/github.com/vmware/govmomi/property/wait.go generated vendored Normal file
View File

@ -0,0 +1,153 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package property
import (
"context"
"github.com/vmware/govmomi/vim25/types"
)
// Wait waits for any of the specified properties of the specified managed
// object to change. It calls the specified function for every update it
// receives. If this function returns false, it continues waiting for
// subsequent updates. If this function returns true, it stops waiting and
// returns.
//
// To only receive updates for the specified managed object, the function
// creates a new property collector and calls CreateFilter. A new property
// collector is required because filters can only be added, not removed.
//
// The newly created collector is destroyed before this function returns (both
// in case of success or error).
//
func Wait(ctx context.Context, c *Collector, obj types.ManagedObjectReference, ps []string, f func([]types.PropertyChange) bool) error {
p, err := c.Create(ctx)
if err != nil {
return err
}
// Attempt to destroy the collector using the background context, as the
// specified context may have timed out or have been cancelled.
defer p.Destroy(context.Background())
req := types.CreateFilter{
Spec: types.PropertyFilterSpec{
ObjectSet: []types.ObjectSpec{
{
Obj: obj,
},
},
PropSet: []types.PropertySpec{
{
PathSet: ps,
Type: obj.Type,
},
},
},
}
if len(ps) == 0 {
req.Spec.PropSet[0].All = types.NewBool(true)
}
err = p.CreateFilter(ctx, req)
if err != nil {
return err
}
return waitLoop(ctx, p, func(_ types.ManagedObjectReference, pc []types.PropertyChange) bool {
return f(pc)
})
}
// WaitForView waits for any of the specified properties of the managed
// objects in the View to change. It calls the specified function for every update it
// receives. If this function returns false, it continues waiting for
// subsequent updates. If this function returns true, it stops waiting and
// returns.
//
// To only receive updates for the View's specified managed objects, the function
// creates a new property collector and calls CreateFilter. A new property
// collector is required because filters can only be added, not removed.
//
// The newly created collector is destroyed before this function returns (both
// in case of success or error).
//
// The code assumes that all objects in the View are the same type
func WaitForView(ctx context.Context, c *Collector, view types.ManagedObjectReference, obj types.ManagedObjectReference, ps []string, f func(types.ManagedObjectReference, []types.PropertyChange) bool) error {
p, err := c.Create(ctx)
if err != nil {
return err
}
// Attempt to destroy the collector using the background context, as the
// specified context may have timed out or have been cancelled.
defer p.Destroy(context.Background())
req := types.CreateFilter{
Spec: types.PropertyFilterSpec{
ObjectSet: []types.ObjectSpec{
{
Obj: view,
SelectSet: []types.BaseSelectionSpec{
&types.TraversalSpec{
SelectionSpec: types.SelectionSpec{
Name: "traverseEntities",
},
Path: "view",
Type: view.Type}},
},
},
PropSet: []types.PropertySpec{
{
Type: obj.Type,
PathSet: ps,
},
},
}}
err = p.CreateFilter(ctx, req)
if err != nil {
return err
}
return waitLoop(ctx, p, f)
}
func waitLoop(ctx context.Context, c *Collector, f func(types.ManagedObjectReference, []types.PropertyChange) bool) error {
for version := ""; ; {
res, err := c.WaitForUpdates(ctx, version)
if err != nil {
return err
}
// Retry if the result came back empty
if res == nil {
continue
}
version = res.Version
for _, fs := range res.FilterSet {
for _, os := range fs.ObjectSet {
if f(os.Obj, os.ChangeSet) {
return nil
}
}
}
}
}

127
vendor/github.com/vmware/govmomi/session/keep_alive.go generated vendored Normal file
View File

@ -0,0 +1,127 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package session
import (
"context"
"sync"
"time"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/soap"
)
type keepAlive struct {
sync.Mutex
roundTripper soap.RoundTripper
idleTime time.Duration
notifyRequest chan struct{}
notifyStop chan struct{}
notifyWaitGroup sync.WaitGroup
// keepAlive executes a request in the background with the purpose of
// keeping the session active. The response for this request is discarded.
keepAlive func(soap.RoundTripper) error
}
func defaultKeepAlive(roundTripper soap.RoundTripper) error {
_, _ = methods.GetCurrentTime(context.Background(), roundTripper)
return nil
}
// KeepAlive wraps the specified soap.RoundTripper and executes a meaningless
// API request in the background after the RoundTripper has been idle for the
// specified amount of idle time. The keep alive process only starts once a
// user logs in and runs until the user logs out again.
func KeepAlive(roundTripper soap.RoundTripper, idleTime time.Duration) soap.RoundTripper {
return KeepAliveHandler(roundTripper, idleTime, defaultKeepAlive)
}
// KeepAliveHandler works as KeepAlive() does, but the handler param can decide how to handle errors.
// For example, if connectivity to ESX/VC is down long enough for a session to expire, a handler can choose to
// Login() on a types.NotAuthenticated error. If handler returns non-nil, the keep alive go routine will be stopped.
func KeepAliveHandler(roundTripper soap.RoundTripper, idleTime time.Duration, handler func(soap.RoundTripper) error) soap.RoundTripper {
k := &keepAlive{
roundTripper: roundTripper,
idleTime: idleTime,
notifyRequest: make(chan struct{}),
}
k.keepAlive = handler
return k
}
func (k *keepAlive) start() {
k.Lock()
defer k.Unlock()
if k.notifyStop != nil {
return
}
// This channel must be closed to terminate idle timer.
k.notifyStop = make(chan struct{})
k.notifyWaitGroup.Add(1)
go func() {
defer k.notifyWaitGroup.Done()
for t := time.NewTimer(k.idleTime); ; {
select {
case <-k.notifyStop:
return
case <-k.notifyRequest:
t.Reset(k.idleTime)
case <-t.C:
if err := k.keepAlive(k.roundTripper); err != nil {
k.stop()
}
t = time.NewTimer(k.idleTime)
}
}
}()
}
func (k *keepAlive) stop() {
k.Lock()
defer k.Unlock()
if k.notifyStop != nil {
close(k.notifyStop)
k.notifyWaitGroup.Wait()
k.notifyStop = nil
}
}
func (k *keepAlive) RoundTrip(ctx context.Context, req, res soap.HasFault) error {
err := k.roundTripper.RoundTrip(ctx, req, res)
if err != nil {
return err
}
// Start ticker on login, stop ticker on logout.
switch req.(type) {
case *methods.LoginBody, *methods.LoginExtensionByCertificateBody:
k.start()
case *methods.LogoutBody:
k.stop()
}
return nil
}

201
vendor/github.com/vmware/govmomi/session/manager.go generated vendored Normal file
View File

@ -0,0 +1,201 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package session
import (
"context"
"net/url"
"os"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
// Locale defaults to "en_US" and can be overridden via this var or the GOVMOMI_LOCALE env var.
// A value of "_" uses the server locale setting.
var Locale = os.Getenv("GOVMOMI_LOCALE")
func init() {
if Locale == "_" {
Locale = ""
} else if Locale == "" {
Locale = "en_US"
}
}
type Manager struct {
client *vim25.Client
userSession *types.UserSession
}
func NewManager(client *vim25.Client) *Manager {
m := Manager{
client: client,
}
return &m
}
func (sm Manager) Reference() types.ManagedObjectReference {
return *sm.client.ServiceContent.SessionManager
}
func (sm *Manager) SetLocale(ctx context.Context, locale string) error {
req := types.SetLocale{
This: sm.Reference(),
Locale: locale,
}
_, err := methods.SetLocale(ctx, sm.client, &req)
return err
}
func (sm *Manager) Login(ctx context.Context, u *url.Userinfo) error {
req := types.Login{
This: sm.Reference(),
Locale: Locale,
}
if u != nil {
req.UserName = u.Username()
if pw, ok := u.Password(); ok {
req.Password = pw
}
}
login, err := methods.Login(ctx, sm.client, &req)
if err != nil {
return err
}
sm.userSession = &login.Returnval
return nil
}
func (sm *Manager) LoginExtensionByCertificate(ctx context.Context, key string, locale string) error {
req := types.LoginExtensionByCertificate{
This: sm.Reference(),
ExtensionKey: key,
Locale: locale,
}
login, err := methods.LoginExtensionByCertificate(ctx, sm.client, &req)
if err != nil {
return err
}
sm.userSession = &login.Returnval
return nil
}
func (sm *Manager) Logout(ctx context.Context) error {
req := types.Logout{
This: sm.Reference(),
}
_, err := methods.Logout(ctx, sm.client, &req)
if err != nil {
return err
}
sm.userSession = nil
return nil
}
// UserSession retrieves and returns the SessionManager's CurrentSession field.
// Nil is returned if the session is not authenticated.
func (sm *Manager) UserSession(ctx context.Context) (*types.UserSession, error) {
var mgr mo.SessionManager
pc := property.DefaultCollector(sm.client)
err := pc.RetrieveOne(ctx, sm.Reference(), []string{"currentSession"}, &mgr)
if err != nil {
// It's OK if we can't retrieve properties because we're not authenticated
if f, ok := err.(types.HasFault); ok {
switch f.Fault().(type) {
case *types.NotAuthenticated:
return nil, nil
}
}
return nil, err
}
return mgr.CurrentSession, nil
}
func (sm *Manager) TerminateSession(ctx context.Context, sessionId []string) error {
req := types.TerminateSession{
This: sm.Reference(),
SessionId: sessionId,
}
_, err := methods.TerminateSession(ctx, sm.client, &req)
return err
}
// SessionIsActive checks whether the session that was created at login is
// still valid. This function only works against vCenter.
func (sm *Manager) SessionIsActive(ctx context.Context) (bool, error) {
if sm.userSession == nil {
return false, nil
}
req := types.SessionIsActive{
This: sm.Reference(),
SessionID: sm.userSession.Key,
UserName: sm.userSession.UserName,
}
active, err := methods.SessionIsActive(ctx, sm.client, &req)
if err != nil {
return false, err
}
return active.Returnval, err
}
func (sm *Manager) AcquireGenericServiceTicket(ctx context.Context, spec types.BaseSessionManagerServiceRequestSpec) (*types.SessionManagerGenericServiceTicket, error) {
req := types.AcquireGenericServiceTicket{
This: sm.Reference(),
Spec: spec,
}
res, err := methods.AcquireGenericServiceTicket(ctx, sm.client, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
func (sm *Manager) AcquireLocalTicket(ctx context.Context, userName string) (*types.SessionManagerLocalTicket, error) {
req := types.AcquireLocalTicket{
This: sm.Reference(),
UserName: userName,
}
res, err := methods.AcquireLocalTicket(ctx, sm.client, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}

32
vendor/github.com/vmware/govmomi/task/error.go generated vendored Normal file
View File

@ -0,0 +1,32 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package task
import "github.com/vmware/govmomi/vim25/types"
type Error struct {
*types.LocalizedMethodFault
}
// Error returns the task's localized fault message.
func (e Error) Error() string {
return e.LocalizedMethodFault.LocalizedMessage
}
func (e Error) Fault() types.BaseMethodFault {
return e.LocalizedMethodFault.Fault
}

132
vendor/github.com/vmware/govmomi/task/wait.go generated vendored Normal file
View File

@ -0,0 +1,132 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package task
import (
"context"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25/progress"
"github.com/vmware/govmomi/vim25/types"
)
type taskProgress struct {
info *types.TaskInfo
}
func (t taskProgress) Percentage() float32 {
return float32(t.info.Progress)
}
func (t taskProgress) Detail() string {
return ""
}
func (t taskProgress) Error() error {
if t.info.Error != nil {
return Error{t.info.Error}
}
return nil
}
type taskCallback struct {
ch chan<- progress.Report
info *types.TaskInfo
err error
}
func (t *taskCallback) fn(pc []types.PropertyChange) bool {
for _, c := range pc {
if c.Name != "info" {
continue
}
if c.Op != types.PropertyChangeOpAssign {
continue
}
if c.Val == nil {
continue
}
ti := c.Val.(types.TaskInfo)
t.info = &ti
}
// t.info could be nil if pc can't satify the rules above
if t.info == nil {
return false
}
pr := taskProgress{t.info}
// Store copy of error, so Wait() can return it as well.
t.err = pr.Error()
switch t.info.State {
case types.TaskInfoStateQueued, types.TaskInfoStateRunning:
if t.ch != nil {
// Don't care if this is dropped
select {
case t.ch <- pr:
default:
}
}
return false
case types.TaskInfoStateSuccess, types.TaskInfoStateError:
if t.ch != nil {
// Last one must always be delivered
t.ch <- pr
}
return true
default:
panic("unknown state: " + t.info.State)
}
}
// Wait waits for a task to finish with either success or failure. It does so
// by waiting for the "info" property of task managed object to change. The
// function returns when it finds the task in the "success" or "error" state.
// In the former case, the return value is nil. In the latter case the return
// value is an instance of this package's Error struct.
//
// Any error returned while waiting for property changes causes the function to
// return immediately and propagate the error.
//
// If the progress.Sinker argument is specified, any progress updates for the
// task are sent here. The completion percentage is passed through directly.
// The detail for the progress update is set to an empty string. If the task
// finishes in the error state, the error instance is passed through as well.
// Note that this error is the same error that is returned by this function.
//
func Wait(ctx context.Context, ref types.ManagedObjectReference, pc *property.Collector, s progress.Sinker) (*types.TaskInfo, error) {
cb := &taskCallback{}
// Include progress sink if specified
if s != nil {
cb.ch = s.Sink()
defer close(cb.ch)
}
err := property.Wait(ctx, pc, ref, []string{"info"}, cb.fn)
if err != nil {
return nil, err
}
return cb.info, cb.err
}

123
vendor/github.com/vmware/govmomi/vim25/client.go generated vendored Normal file
View File

@ -0,0 +1,123 @@
/*
Copyright (c) 2015-2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package vim25
import (
"context"
"encoding/json"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
// Client is a tiny wrapper around the vim25/soap Client that stores session
// specific state (i.e. state that only needs to be retrieved once after the
// client has been created). This means the client can be reused after
// serialization without performing additional requests for initialization.
type Client struct {
*soap.Client
ServiceContent types.ServiceContent
// RoundTripper is a separate field such that the client's implementation of
// the RoundTripper interface can be wrapped by separate implementations for
// extra functionality (for example, reauthentication on session timeout).
RoundTripper soap.RoundTripper
}
// NewClient creates and returns a new client wirh the ServiceContent field
// filled in.
func NewClient(ctx context.Context, rt soap.RoundTripper) (*Client, error) {
serviceContent, err := methods.GetServiceContent(ctx, rt)
if err != nil {
return nil, err
}
c := Client{
ServiceContent: serviceContent,
RoundTripper: rt,
}
// Set client if it happens to be a soap.Client
if sc, ok := rt.(*soap.Client); ok {
c.Client = sc
}
return &c, nil
}
// RoundTrip dispatches to the RoundTripper field.
func (c *Client) RoundTrip(ctx context.Context, req, res soap.HasFault) error {
return c.RoundTripper.RoundTrip(ctx, req, res)
}
type marshaledClient struct {
SoapClient *soap.Client
ServiceContent types.ServiceContent
}
func (c *Client) MarshalJSON() ([]byte, error) {
m := marshaledClient{
SoapClient: c.Client,
ServiceContent: c.ServiceContent,
}
return json.Marshal(m)
}
func (c *Client) UnmarshalJSON(b []byte) error {
var m marshaledClient
err := json.Unmarshal(b, &m)
if err != nil {
return err
}
*c = Client{
Client: m.SoapClient,
ServiceContent: m.ServiceContent,
RoundTripper: m.SoapClient,
}
return nil
}
// Valid returns whether or not the client is valid and ready for use.
// This should be called after unmarshalling the client.
func (c *Client) Valid() bool {
if c == nil {
return false
}
if c.Client == nil {
return false
}
// Use arbitrary pointer field in the service content.
// Doesn't matter which one, as long as it is populated by default.
if c.ServiceContent.SessionManager == nil {
return false
}
return true
}
// IsVC returns true if we are connected to a vCenter
func (c *Client) IsVC() bool {
return c.ServiceContent.About.ApiType == "VirtualCenter"
}

81
vendor/github.com/vmware/govmomi/vim25/debug/debug.go generated vendored Normal file
View File

@ -0,0 +1,81 @@
/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package debug
import (
"io"
"os"
"path"
)
// Provider specified the interface types must implement to be used as a
// debugging sink. Having multiple such sink implementations allows it to be
// changed externally (for example when running tests).
type Provider interface {
NewFile(s string) io.WriteCloser
Flush()
}
var currentProvider Provider = nil
func SetProvider(p Provider) {
if currentProvider != nil {
currentProvider.Flush()
}
currentProvider = p
}
// Enabled returns whether debugging is enabled or not.
func Enabled() bool {
return currentProvider != nil
}
// NewFile dispatches to the current provider's NewFile function.
func NewFile(s string) io.WriteCloser {
return currentProvider.NewFile(s)
}
// Flush dispatches to the current provider's Flush function.
func Flush() {
currentProvider.Flush()
}
// FileProvider implements a debugging provider that creates a real file for
// every call to NewFile. It maintains a list of all files that it creates,
// such that it can close them when its Flush function is called.
type FileProvider struct {
Path string
files []*os.File
}
func (fp *FileProvider) NewFile(p string) io.WriteCloser {
f, err := os.Create(path.Join(fp.Path, p))
if err != nil {
panic(err)
}
fp.files = append(fp.files, f)
return f
}
func (fp *FileProvider) Flush() {
for _, f := range fp.files {
f.Close()
}
}

29
vendor/github.com/vmware/govmomi/vim25/doc.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Package vim25 provides a minimal client implementation to use with other
packages in the vim25 tree. The code in this package intentionally does not
take any dependendies outside the vim25 tree.
The client implementation in this package embeds the soap.Client structure.
Additionally, it stores the value of the session's ServiceContent object. This
object stores references to a variety of subsystems, such as the root property
collector, the session manager, and the search index. The client is fully
functional after serialization and deserialization, without the need for
additional requests for initialization.
*/
package vim25

View File

@ -0,0 +1,124 @@
/*
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 methods
import (
"context"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type RetrieveDynamicTypeManagerBody struct {
Req *types.RetrieveDynamicTypeManager `xml:"urn:vim25 RetrieveDynamicTypeManager"`
Res *types.RetrieveDynamicTypeManagerResponse `xml:"urn:vim25 RetrieveDynamicTypeManagerResponse"`
Fault_ *soap.Fault
}
func (b *RetrieveDynamicTypeManagerBody) Fault() *soap.Fault { return b.Fault_ }
func RetrieveDynamicTypeManager(ctx context.Context, r soap.RoundTripper, req *types.RetrieveDynamicTypeManager) (*types.RetrieveDynamicTypeManagerResponse, error) {
var reqBody, resBody RetrieveDynamicTypeManagerBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type RetrieveManagedMethodExecuterBody struct {
Req *types.RetrieveManagedMethodExecuter `xml:"urn:vim25 RetrieveManagedMethodExecuter"`
Res *types.RetrieveManagedMethodExecuterResponse `xml:"urn:vim25 RetrieveManagedMethodExecuterResponse"`
Fault_ *soap.Fault
}
func (b *RetrieveManagedMethodExecuterBody) Fault() *soap.Fault { return b.Fault_ }
func RetrieveManagedMethodExecuter(ctx context.Context, r soap.RoundTripper, req *types.RetrieveManagedMethodExecuter) (*types.RetrieveManagedMethodExecuterResponse, error) {
var reqBody, resBody RetrieveManagedMethodExecuterBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type DynamicTypeMgrQueryMoInstancesBody struct {
Req *types.DynamicTypeMgrQueryMoInstances `xml:"urn:vim25 DynamicTypeMgrQueryMoInstances"`
Res *types.DynamicTypeMgrQueryMoInstancesResponse `xml:"urn:vim25 DynamicTypeMgrQueryMoInstancesResponse"`
Fault_ *soap.Fault
}
func (b *DynamicTypeMgrQueryMoInstancesBody) Fault() *soap.Fault { return b.Fault_ }
func DynamicTypeMgrQueryMoInstances(ctx context.Context, r soap.RoundTripper, req *types.DynamicTypeMgrQueryMoInstances) (*types.DynamicTypeMgrQueryMoInstancesResponse, error) {
var reqBody, resBody DynamicTypeMgrQueryMoInstancesBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type DynamicTypeMgrQueryTypeInfoBody struct {
Req *types.DynamicTypeMgrQueryTypeInfo `xml:"urn:vim25 DynamicTypeMgrQueryTypeInfo"`
Res *types.DynamicTypeMgrQueryTypeInfoResponse `xml:"urn:vim25 DynamicTypeMgrQueryTypeInfoResponse"`
Fault_ *soap.Fault
}
func (b *DynamicTypeMgrQueryTypeInfoBody) Fault() *soap.Fault { return b.Fault_ }
func DynamicTypeMgrQueryTypeInfo(ctx context.Context, r soap.RoundTripper, req *types.DynamicTypeMgrQueryTypeInfo) (*types.DynamicTypeMgrQueryTypeInfoResponse, error) {
var reqBody, resBody DynamicTypeMgrQueryTypeInfoBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type ExecuteSoapBody struct {
Req *types.ExecuteSoap `xml:"urn:vim25 ExecuteSoap"`
Res *types.ExecuteSoapResponse `xml:"urn:vim25 ExecuteSoapResponse"`
Fault_ *soap.Fault
}
func (b *ExecuteSoapBody) Fault() *soap.Fault { return b.Fault_ }
func ExecuteSoap(ctx context.Context, r soap.RoundTripper, req *types.ExecuteSoap) (*types.ExecuteSoapResponse, error) {
var reqBody, resBody ExecuteSoapBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}

16144
vendor/github.com/vmware/govmomi/vim25/methods/methods.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,56 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package methods
import (
"context"
"time"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
var ServiceInstance = types.ManagedObjectReference{
Type: "ServiceInstance",
Value: "ServiceInstance",
}
func GetServiceContent(ctx context.Context, r soap.RoundTripper) (types.ServiceContent, error) {
req := types.RetrieveServiceContent{
This: ServiceInstance,
}
res, err := RetrieveServiceContent(ctx, r, &req)
if err != nil {
return types.ServiceContent{}, err
}
return res.Returnval, nil
}
func GetCurrentTime(ctx context.Context, r soap.RoundTripper) (*time.Time, error) {
req := types.CurrentTime{
This: ServiceInstance,
}
res, err := CurrentTime(ctx, r, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}

137
vendor/github.com/vmware/govmomi/vim25/mo/ancestors.go generated vendored Normal file
View File

@ -0,0 +1,137 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package mo
import (
"context"
"fmt"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
// Ancestors returns the entire ancestry tree of a specified managed object.
// The return value includes the root node and the specified object itself.
func Ancestors(ctx context.Context, rt soap.RoundTripper, pc, obj types.ManagedObjectReference) ([]ManagedEntity, error) {
ospec := types.ObjectSpec{
Obj: obj,
SelectSet: []types.BaseSelectionSpec{
&types.TraversalSpec{
SelectionSpec: types.SelectionSpec{Name: "traverseParent"},
Type: "ManagedEntity",
Path: "parent",
Skip: types.NewBool(false),
SelectSet: []types.BaseSelectionSpec{
&types.SelectionSpec{Name: "traverseParent"},
},
},
&types.TraversalSpec{
SelectionSpec: types.SelectionSpec{},
Type: "VirtualMachine",
Path: "parentVApp",
Skip: types.NewBool(false),
SelectSet: []types.BaseSelectionSpec{
&types.SelectionSpec{Name: "traverseParent"},
},
},
},
Skip: types.NewBool(false),
}
pspec := []types.PropertySpec{
{
Type: "ManagedEntity",
PathSet: []string{"name", "parent"},
},
{
Type: "VirtualMachine",
PathSet: []string{"parentVApp"},
},
}
req := types.RetrieveProperties{
This: pc,
SpecSet: []types.PropertyFilterSpec{
{
ObjectSet: []types.ObjectSpec{ospec},
PropSet: pspec,
},
},
}
var ifaces []interface{}
err := RetrievePropertiesForRequest(ctx, rt, req, &ifaces)
if err != nil {
return nil, err
}
var out []ManagedEntity
// Build ancestry tree by iteratively finding a new child.
for len(out) < len(ifaces) {
var find types.ManagedObjectReference
if len(out) > 0 {
find = out[len(out)-1].Self
}
// Find entity we're looking for given the last entity in the current tree.
for _, iface := range ifaces {
me := iface.(IsManagedEntity).GetManagedEntity()
if me.Name == "" {
// The types below have their own 'Name' field, so ManagedEntity.Name (me.Name) is empty.
// We only hit this case when the 'obj' param is one of these types.
// In most cases, 'obj' is a Folder so Name isn't collected in this call.
switch x := iface.(type) {
case Network:
me.Name = x.Name
case DistributedVirtualSwitch:
me.Name = x.Name
case DistributedVirtualPortgroup:
me.Name = x.Name
case OpaqueNetwork:
me.Name = x.Name
default:
// ManagedEntity always has a Name, if we hit this point we missed a case above.
panic(fmt.Sprintf("%#v Name is empty", me.Reference()))
}
}
if me.Parent == nil {
// Special case for VirtualMachine within VirtualApp,
// unlikely to hit this other than via Finder.Element()
switch x := iface.(type) {
case VirtualMachine:
me.Parent = x.ParentVApp
}
}
if me.Parent == nil {
out = append(out, me)
break
}
if *me.Parent == find {
out = append(out, me)
break
}
}
}
return out, nil
}

24
vendor/github.com/vmware/govmomi/vim25/mo/entity.go generated vendored Normal file
View File

@ -0,0 +1,24 @@
/*
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 mo
// Entity is the interface that is implemented by all managed objects
// that extend ManagedEntity.
type Entity interface {
Reference
Entity() *ManagedEntity
}

61
vendor/github.com/vmware/govmomi/vim25/mo/extra.go generated vendored Normal file
View File

@ -0,0 +1,61 @@
/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package mo
type IsManagedEntity interface {
GetManagedEntity() ManagedEntity
}
func (m ComputeResource) GetManagedEntity() ManagedEntity {
return m.ManagedEntity
}
func (m Datacenter) GetManagedEntity() ManagedEntity {
return m.ManagedEntity
}
func (m Datastore) GetManagedEntity() ManagedEntity {
return m.ManagedEntity
}
func (m DistributedVirtualSwitch) GetManagedEntity() ManagedEntity {
return m.ManagedEntity
}
func (m DistributedVirtualPortgroup) GetManagedEntity() ManagedEntity {
return m.ManagedEntity
}
func (m Folder) GetManagedEntity() ManagedEntity {
return m.ManagedEntity
}
func (m HostSystem) GetManagedEntity() ManagedEntity {
return m.ManagedEntity
}
func (m Network) GetManagedEntity() ManagedEntity {
return m.ManagedEntity
}
func (m ResourcePool) GetManagedEntity() ManagedEntity {
return m.ManagedEntity
}
func (m VirtualMachine) GetManagedEntity() ManagedEntity {
return m.ManagedEntity
}

1757
vendor/github.com/vmware/govmomi/vim25/mo/mo.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

26
vendor/github.com/vmware/govmomi/vim25/mo/reference.go generated vendored Normal file
View File

@ -0,0 +1,26 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package mo
import "github.com/vmware/govmomi/vim25/types"
// Reference is the interface that is implemented by all the managed objects
// defined in this package. It specifies that these managed objects have a
// function that returns the managed object reference to themselves.
type Reference interface {
Reference() types.ManagedObjectReference
}

21
vendor/github.com/vmware/govmomi/vim25/mo/registry.go generated vendored Normal file
View File

@ -0,0 +1,21 @@
/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package mo
import "reflect"
var t = map[string]reflect.Type{}

174
vendor/github.com/vmware/govmomi/vim25/mo/retrieve.go generated vendored Normal file
View File

@ -0,0 +1,174 @@
/*
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 mo
import (
"context"
"reflect"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
func ignoreMissingProperty(ref types.ManagedObjectReference, p types.MissingProperty) bool {
switch ref.Type {
case "VirtualMachine":
switch p.Path {
case "environmentBrowser":
// See https://github.com/vmware/govmomi/pull/242
return true
case "alarmActionsEnabled":
// Seen with vApp child VM
return true
}
}
return false
}
// ObjectContentToType loads an ObjectContent value into the value it
// represents. If the ObjectContent value has a non-empty 'MissingSet' field,
// it returns the first fault it finds there as error. If the 'MissingSet'
// field is empty, it returns a pointer to a reflect.Value. It handles contain
// nested properties, such as 'guest.ipAddress' or 'config.hardware'.
func ObjectContentToType(o types.ObjectContent) (interface{}, error) {
// Expect no properties in the missing set
for _, p := range o.MissingSet {
if ignoreMissingProperty(o.Obj, p) {
continue
}
return nil, soap.WrapVimFault(p.Fault.Fault)
}
ti := typeInfoForType(o.Obj.Type)
v, err := ti.LoadFromObjectContent(o)
if err != nil {
return nil, err
}
return v.Elem().Interface(), nil
}
// LoadRetrievePropertiesResponse converts the response of a call to
// RetrieveProperties to one or more managed objects.
func LoadRetrievePropertiesResponse(res *types.RetrievePropertiesResponse, dst interface{}) error {
rt := reflect.TypeOf(dst)
if rt == nil || rt.Kind() != reflect.Ptr {
panic("need pointer")
}
rv := reflect.ValueOf(dst).Elem()
if !rv.CanSet() {
panic("cannot set dst")
}
isSlice := false
switch rt.Elem().Kind() {
case reflect.Struct:
case reflect.Slice:
isSlice = true
default:
panic("unexpected type")
}
if isSlice {
for _, p := range res.Returnval {
v, err := ObjectContentToType(p)
if err != nil {
return err
}
vt := reflect.TypeOf(v)
if !rv.Type().AssignableTo(vt) {
// For example: dst is []ManagedEntity, res is []HostSystem
if field, ok := vt.FieldByName(rt.Elem().Elem().Name()); ok && field.Anonymous {
rv.Set(reflect.Append(rv, reflect.ValueOf(v).FieldByIndex(field.Index)))
continue
}
}
rv.Set(reflect.Append(rv, reflect.ValueOf(v)))
}
} else {
switch len(res.Returnval) {
case 0:
case 1:
v, err := ObjectContentToType(res.Returnval[0])
if err != nil {
return err
}
vt := reflect.TypeOf(v)
if !rv.Type().AssignableTo(vt) {
// For example: dst is ComputeResource, res is ClusterComputeResource
if field, ok := vt.FieldByName(rt.Elem().Name()); ok && field.Anonymous {
rv.Set(reflect.ValueOf(v).FieldByIndex(field.Index))
return nil
}
}
rv.Set(reflect.ValueOf(v))
default:
// If dst is not a slice, expect to receive 0 or 1 results
panic("more than 1 result")
}
}
return nil
}
// RetrievePropertiesForRequest calls the RetrieveProperties method with the
// specified request and decodes the response struct into the value pointed to
// by dst.
func RetrievePropertiesForRequest(ctx context.Context, r soap.RoundTripper, req types.RetrieveProperties, dst interface{}) error {
res, err := methods.RetrieveProperties(ctx, r, &req)
if err != nil {
return err
}
return LoadRetrievePropertiesResponse(res, dst)
}
// RetrieveProperties retrieves the properties of the managed object specified
// as obj and decodes the response struct into the value pointed to by dst.
func RetrieveProperties(ctx context.Context, r soap.RoundTripper, pc, obj types.ManagedObjectReference, dst interface{}) error {
req := types.RetrieveProperties{
This: pc,
SpecSet: []types.PropertyFilterSpec{
{
ObjectSet: []types.ObjectSpec{
{
Obj: obj,
Skip: types.NewBool(false),
},
},
PropSet: []types.PropertySpec{
{
All: types.NewBool(true),
Type: obj.Type,
},
},
},
},
}
return RetrievePropertiesForRequest(ctx, r, req, dst)
}

247
vendor/github.com/vmware/govmomi/vim25/mo/type_info.go generated vendored Normal file
View File

@ -0,0 +1,247 @@
/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package mo
import (
"fmt"
"reflect"
"regexp"
"strings"
"sync"
"github.com/vmware/govmomi/vim25/types"
)
type typeInfo struct {
typ reflect.Type
// Field indices of "Self" field.
self []int
// Map property names to field indices.
props map[string][]int
}
var typeInfoLock sync.RWMutex
var typeInfoMap = make(map[string]*typeInfo)
func typeInfoForType(tname string) *typeInfo {
typeInfoLock.RLock()
ti, ok := typeInfoMap[tname]
typeInfoLock.RUnlock()
if ok {
return ti
}
// Create new typeInfo for type.
if typ, ok := t[tname]; !ok {
panic("unknown type: " + tname)
} else {
// Multiple routines may race to set it, but the result is the same.
typeInfoLock.Lock()
ti = newTypeInfo(typ)
typeInfoMap[tname] = ti
typeInfoLock.Unlock()
}
return ti
}
func newTypeInfo(typ reflect.Type) *typeInfo {
t := typeInfo{
typ: typ,
props: make(map[string][]int),
}
t.build(typ, "", []int{})
return &t
}
var managedObjectRefType = reflect.TypeOf((*types.ManagedObjectReference)(nil)).Elem()
func buildName(fn string, f reflect.StructField) string {
if fn != "" {
fn += "."
}
motag := f.Tag.Get("mo")
if motag != "" {
return fn + motag
}
xmltag := f.Tag.Get("xml")
if xmltag != "" {
tokens := strings.Split(xmltag, ",")
if tokens[0] != "" {
return fn + tokens[0]
}
}
return ""
}
func (t *typeInfo) build(typ reflect.Type, fn string, fi []int) {
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}
if typ.Kind() != reflect.Struct {
panic("need struct")
}
for i := 0; i < typ.NumField(); i++ {
f := typ.Field(i)
ftyp := f.Type
// Copy field indices so they can be passed along.
fic := make([]int, len(fi)+1)
copy(fic, fi)
fic[len(fi)] = i
// Recurse into embedded field.
if f.Anonymous {
t.build(ftyp, fn, fic)
continue
}
// Top level type has a "Self" field.
if f.Name == "Self" && ftyp == managedObjectRefType {
t.self = fic
continue
}
fnc := buildName(fn, f)
if fnc == "" {
continue
}
t.props[fnc] = fic
// Dereference pointer.
if ftyp.Kind() == reflect.Ptr {
ftyp = ftyp.Elem()
}
// Slices are not addressable by `foo.bar.qux`.
if ftyp.Kind() == reflect.Slice {
continue
}
// Skip the managed reference type.
if ftyp == managedObjectRefType {
continue
}
// Recurse into structs.
if ftyp.Kind() == reflect.Struct {
t.build(ftyp, fnc, fic)
}
}
}
// assignValue assignes a value 'pv' to the struct pointed to by 'val', given a
// slice of field indices. It recurses into the struct until it finds the field
// specified by the indices. It creates new values for pointer types where
// needed.
func assignValue(val reflect.Value, fi []int, pv reflect.Value) {
// Create new value if necessary.
if val.Kind() == reflect.Ptr {
if val.IsNil() {
val.Set(reflect.New(val.Type().Elem()))
}
val = val.Elem()
}
rv := val.Field(fi[0])
fi = fi[1:]
if len(fi) == 0 {
rt := rv.Type()
pt := pv.Type()
// If type is a pointer, create new instance of type.
if rt.Kind() == reflect.Ptr {
rv.Set(reflect.New(rt.Elem()))
rv = rv.Elem()
rt = rv.Type()
}
// If type is an interface, check if pv implements it.
if rt.Kind() == reflect.Interface && !pt.Implements(rt) {
// Check if pointer to pv implements it.
if reflect.PtrTo(pt).Implements(rt) {
npv := reflect.New(pt)
npv.Elem().Set(pv)
pv = npv
pt = pv.Type()
} else {
panic(fmt.Sprintf("type %s doesn't implement %s", pt.Name(), rt.Name()))
}
}
if pt.AssignableTo(rt) {
rv.Set(pv)
} else if rt.ConvertibleTo(pt) {
rv.Set(pv.Convert(rt))
} else {
panic(fmt.Sprintf("cannot assign %s (%s) to %s (%s)", rt.Name(), rt.Kind(), pt.Name(), pt.Kind()))
}
return
}
assignValue(rv, fi, pv)
}
var arrayOfRegexp = regexp.MustCompile("ArrayOf(.*)$")
func anyTypeToValue(t interface{}) reflect.Value {
rt := reflect.TypeOf(t)
rv := reflect.ValueOf(t)
// Dereference if ArrayOfXYZ type
m := arrayOfRegexp.FindStringSubmatch(rt.Name())
if len(m) > 0 {
// ArrayOfXYZ type has single field named XYZ
rv = rv.FieldByName(m[1])
if !rv.IsValid() {
panic(fmt.Sprintf("expected %s type to have field %s", m[0], m[1]))
}
}
return rv
}
// LoadObjectFromContent loads properties from the 'PropSet' field in the
// specified ObjectContent value into the value it represents, which is
// returned as a reflect.Value.
func (t *typeInfo) LoadFromObjectContent(o types.ObjectContent) (reflect.Value, error) {
v := reflect.New(t.typ)
assignValue(v, t.self, reflect.ValueOf(o.Obj))
for _, p := range o.PropSet {
rv, ok := t.props[p.Name]
if !ok {
continue
}
assignValue(v, rv, anyTypeToValue(p.Val))
}
return v, nil
}

View File

@ -0,0 +1,73 @@
/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package progress
import "sync"
type Aggregator struct {
downstream Sinker
upstream chan (<-chan Report)
done chan struct{}
w sync.WaitGroup
}
func NewAggregator(s Sinker) *Aggregator {
a := &Aggregator{
downstream: s,
upstream: make(chan (<-chan Report)),
done: make(chan struct{}),
}
a.w.Add(1)
go a.loop()
return a
}
func (a *Aggregator) loop() {
defer a.w.Done()
dch := a.downstream.Sink()
defer close(dch)
for {
select {
case uch := <-a.upstream:
// Drain upstream channel
for e := range uch {
dch <- e
}
case <-a.done:
return
}
}
}
func (a *Aggregator) Sink() chan<- Report {
ch := make(chan Report)
a.upstream <- ch
return ch
}
// Done marks the aggregator as done. No more calls to Sink() may be made and
// the downstream progress report channel will be closed when Done() returns.
func (a *Aggregator) Done() {
close(a.done)
a.w.Wait()
}

32
vendor/github.com/vmware/govmomi/vim25/progress/doc.go generated vendored Normal file
View File

@ -0,0 +1,32 @@
/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package progress
/*
The progress package contains functionality to deal with progress reporting.
The functionality is built to serve progress reporting for infrastructure
operations when talking the vSphere API, but is generic enough to be used
elsewhere.
At the core of this progress reporting API lies the Sinker interface. This
interface is implemented by any object that can act as a sink for progress
reports. Callers of the Sink() function receives a send-only channel for
progress reports. They are responsible for closing the channel when done.
This semantic makes it easy to keep track of multiple progress report channels;
they are only created when Sink() is called and assumed closed when any
function that receives a Sinker parameter returns.
*/

View File

@ -0,0 +1,54 @@
/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package progress
import "fmt"
type prefixedReport struct {
Report
prefix string
}
func (r prefixedReport) Detail() string {
if d := r.Report.Detail(); d != "" {
return fmt.Sprintf("%s: %s", r.prefix, d)
}
return r.prefix
}
func prefixLoop(upstream <-chan Report, downstream chan<- Report, prefix string) {
defer close(downstream)
for r := range upstream {
downstream <- prefixedReport{
Report: r,
prefix: prefix,
}
}
}
func Prefix(s Sinker, prefix string) Sinker {
fn := func() chan<- Report {
upstream := make(chan Report)
downstream := s.Sink()
go prefixLoop(upstream, downstream, prefix)
return upstream
}
return SinkFunc(fn)
}

View File

@ -0,0 +1,177 @@
/*
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 progress
import (
"container/list"
"fmt"
"io"
"sync/atomic"
"time"
)
type readerReport struct {
t time.Time
pos int64
size int64
bps *uint64
err error
}
func (r readerReport) Percentage() float32 {
return 100.0 * float32(r.pos) / float32(r.size)
}
func (r readerReport) Detail() string {
const (
KiB = 1024
MiB = 1024 * KiB
GiB = 1024 * MiB
)
// Use the reader's bps field, so this report returns an up-to-date number.
//
// For example: if there hasn't been progress for the last 5 seconds, the
// most recent report should return "0B/s".
//
bps := atomic.LoadUint64(r.bps)
switch {
case bps >= GiB:
return fmt.Sprintf("%.1fGiB/s", float32(bps)/float32(GiB))
case bps >= MiB:
return fmt.Sprintf("%.1fMiB/s", float32(bps)/float32(MiB))
case bps >= KiB:
return fmt.Sprintf("%.1fKiB/s", float32(bps)/float32(KiB))
default:
return fmt.Sprintf("%dB/s", bps)
}
}
func (p readerReport) Error() error {
return p.err
}
// reader wraps an io.Reader and sends a progress report over a channel for
// every read it handles.
type reader struct {
r io.Reader
pos int64
size int64
bps uint64
ch chan<- Report
}
func NewReader(s Sinker, r io.Reader, size int64) *reader {
pr := reader{
r: r,
size: size,
}
// Reports must be sent downstream and to the bps computation loop.
pr.ch = Tee(s, newBpsLoop(&pr.bps)).Sink()
return &pr
}
// Read calls the Read function on the underlying io.Reader. Additionally,
// every read causes a progress report to be sent to the progress reader's
// underlying channel.
func (r *reader) Read(b []byte) (int, error) {
n, err := r.r.Read(b)
if err != nil {
return n, err
}
r.pos += int64(n)
q := readerReport{
t: time.Now(),
pos: r.pos,
size: r.size,
bps: &r.bps,
}
r.ch <- q
return n, err
}
// Done marks the progress reader as done, optionally including an error in the
// progress report. After sending it, the underlying channel is closed.
func (r *reader) Done(err error) {
q := readerReport{
t: time.Now(),
pos: r.pos,
size: r.size,
bps: &r.bps,
err: err,
}
r.ch <- q
close(r.ch)
}
// newBpsLoop returns a sink that monitors and stores throughput.
func newBpsLoop(dst *uint64) SinkFunc {
fn := func() chan<- Report {
sink := make(chan Report)
go bpsLoop(sink, dst)
return sink
}
return fn
}
func bpsLoop(ch <-chan Report, dst *uint64) {
l := list.New()
for {
var tch <-chan time.Time
// Setup timer for front of list to become stale.
if e := l.Front(); e != nil {
dt := time.Second - time.Now().Sub(e.Value.(readerReport).t)
tch = time.After(dt)
}
select {
case q, ok := <-ch:
if !ok {
return
}
l.PushBack(q)
case <-tch:
l.Remove(l.Front())
}
// Compute new bps
if l.Len() == 0 {
atomic.StoreUint64(dst, 0)
} else {
f := l.Front().Value.(readerReport)
b := l.Back().Value.(readerReport)
atomic.StoreUint64(dst, uint64(b.pos-f.pos))
}
}
}

View File

@ -0,0 +1,26 @@
/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package progress
// Report defines the interface for types that can deliver progress reports.
// Examples include uploads/downloads in the http client and the task info
// field in the task managed object.
type Report interface {
Percentage() float32
Detail() string
Error() error
}

View File

@ -0,0 +1,76 @@
/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package progress
type scaledReport struct {
Report
n int
i int
}
func (r scaledReport) Percentage() float32 {
b := 100 * float32(r.i) / float32(r.n)
return b + (r.Report.Percentage() / float32(r.n))
}
type scaleOne struct {
s Sinker
n int
i int
}
func (s scaleOne) Sink() chan<- Report {
upstream := make(chan Report)
downstream := s.s.Sink()
go s.loop(upstream, downstream)
return upstream
}
func (s scaleOne) loop(upstream <-chan Report, downstream chan<- Report) {
defer close(downstream)
for r := range upstream {
downstream <- scaledReport{
Report: r,
n: s.n,
i: s.i,
}
}
}
type scaleMany struct {
s Sinker
n int
i int
}
func Scale(s Sinker, n int) Sinker {
return &scaleMany{
s: s,
n: n,
}
}
func (s *scaleMany) Sink() chan<- Report {
if s.i == s.n {
s.n++
}
ch := scaleOne{s: s.s, n: s.n, i: s.i}.Sink()
s.i++
return ch
}

View File

@ -0,0 +1,33 @@
/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package progress
// Sinker defines what is expected of a type that can act as a sink for
// progress reports. The semantics are as follows. If you call Sink(), you are
// responsible for closing the returned channel. Closing this channel means
// that the related task is done, or resulted in error.
type Sinker interface {
Sink() chan<- Report
}
// SinkFunc defines a function that returns a progress report channel.
type SinkFunc func() chan<- Report
// Sink makes the SinkFunc implement the Sinker interface.
func (fn SinkFunc) Sink() chan<- Report {
return fn()
}

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