Add option to also import OVF templates to the Content Library (#9755)

This commit is contained in:
Sylvia Moss 2020-08-19 13:20:25 +02:00 committed by GitHub
parent 01d45d67c8
commit a1524bf96a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 4237 additions and 738 deletions

View File

@ -36,8 +36,8 @@ type Config struct {
// Configuration for exporting VM to an ovf file.
// The VM will not be exported if no [Export Configuration](#export-configuration) is specified.
Export *common.ExportConfig `mapstructure:"export"`
// Configuration for importing the VM template to a Content Library.
// The VM template will not be imported if no [Content Library Import Configuration](#content-library-import-configuration) is specified.
// Configuration for importing a VM template or OVF template to a Content Library.
// The template will not be imported if no [Content Library Import Configuration](#content-library-import-configuration) is specified.
// The import doesn't work if [convert_to_template](#convert_to_template) is set to true.
ContentLibraryDestinationConfig *common.ContentLibraryDestinationConfig `mapstructure:"content_library_destination"`
// Customize the cloned VM to configure host, network, or licensing settings. See the [customization options](#customization).

View File

@ -13,28 +13,41 @@ import (
"github.com/vmware/govmomi/vapi/vcenter"
)
// With this configuration Packer creates a library item in a content library whose content is a virtual machine template created from the just built VM.
// The virtual machine template is stored in a newly created library item.
// With this configuration Packer creates a library item in a content library whose content is a VM template
// or an OVF template created from the just built VM.
// The template is stored in a existing or newly created library item.
type ContentLibraryDestinationConfig struct {
// Name of the library in which the new library item containing the VM template should be created.
// Name of the library in which the new library item containing the template should be created/updated.
// The Content Library should be of type Local to allow deploying virtual machines.
Library string `mapstructure:"library"`
// Name of the library item that will be created. The name of the item should be different from [vm_name](#vm_name).
// Defaults to [vm_name](#vm_name) + timestamp.
// Name of the library item that will be created or updated.
// For VM templates, the name of the item should be different from [vm_name](#vm_name) and
// the default is [vm_name](#vm_name) + timestamp when not set. VM templates will be always imported to a new library item.
// For OVF templates, the name defaults to [vm_name](#vm_name) when not set, and if an item with the same name already
// exists it will be then updated with the new OVF template, otherwise a new item will be created.
//
// ~> **Note**: It's not possible to update existing library items with a new VM template. If updating an existing library
// item is necessary, use an OVF template instead by setting the [ovf](#ovf) option as `true`.
//
Name string `mapstructure:"name"`
// Description of the library item that will be created. Defaults to "Packer imported [vm_name](#vm_name) VM template".
// Description of the library item that will be created.
// This option is not used when importing OVF templates.
// Defaults to "Packer imported [vm_name](#vm_name) VM template".
Description string `mapstructure:"description"`
// Cluster onto which the virtual machine template should be placed.
// If cluster and resource_pool are both specified, resource_pool must belong to cluster.
// If cluster and host are both specified, host must be a member of cluster.
// This option is not used when importing OVF templates.
// Defaults to [cluster](#cluster).
Cluster string `mapstructure:"cluster"`
// Virtual machine folder into which the virtual machine template should be placed.
// This option is not used when importing OVF templates.
// Defaults to the same folder as the source virtual machine.
Folder string `mapstructure:"folder"`
// Host onto which the virtual machine template should be placed.
// If host and resource_pool are both specified, resource_pool must belong to host.
// If host and cluster are both specified, host must be a member of cluster.
// This option is not used when importing OVF templates.
// Defaults to [host](#host).
Host string `mapstructure:"host"`
// Resource pool into which the virtual machine template should be placed.
@ -42,10 +55,14 @@ type ContentLibraryDestinationConfig struct {
// the system will attempt to choose a suitable resource pool for the virtual machine template.
ResourcePool string `mapstructure:"resource_pool"`
// The datastore for the virtual machine template's configuration and log files.
// This option is not used when importing OVF templates.
// Defaults to the storage backing associated with the library specified by library.
Datastore string `mapstructure:"datastore"`
// If set to true, the VM will be destroyed after deploying the template to the Content Library. Defaults to `false`.
// If set to true, the VM will be destroyed after deploying the template to the Content Library.
// Defaults to `false`.
Destroy bool `mapstructure:"destroy"`
// When set to true, Packer will import and OVF template to the content library item. Defaults to `false`.
Ovf bool `mapstructure:"ovf"`
}
func (c *ContentLibraryDestinationConfig) Prepare(lc *LocationConfig) []error {
@ -54,31 +71,38 @@ func (c *ContentLibraryDestinationConfig) Prepare(lc *LocationConfig) []error {
if c.Library == "" {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("a library name must be provided"))
}
if c.Name == lc.VMName {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("the content library destination name must be different from the VM name"))
}
if c.Name == "" {
// Add timestamp to the the name to differentiate from the original VM
// otherwise vSphere won't be able to create the template which will be imported
name, err := interpolate.Render(lc.VMName+"{{timestamp}}", nil)
if err != nil {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("unable to parse content library VM template name: %s", err))
if c.Ovf {
if c.Name == "" {
c.Name = lc.VMName
}
} else {
if c.Name == lc.VMName {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("the content library destination name must be different from the VM name"))
}
if c.Name == "" {
// Add timestamp to the name to differentiate from the original VM
// otherwise vSphere won't be able to create the template which will be imported
name, err := interpolate.Render(lc.VMName+"{{timestamp}}", nil)
if err != nil {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("unable to parse content library VM template name: %s", err))
}
c.Name = name
}
if c.Cluster == "" {
c.Cluster = lc.Cluster
}
if c.Host == "" {
c.Host = lc.Host
}
if c.ResourcePool == "" {
c.ResourcePool = lc.ResourcePool
}
if c.Description == "" {
c.Description = fmt.Sprintf("Packer imported %s VM template", lc.VMName)
}
c.Name = name
}
if c.Cluster == "" {
c.Cluster = lc.Cluster
}
if c.Host == "" {
c.Host = lc.Host
}
if c.ResourcePool == "" {
c.ResourcePool = lc.ResourcePool
}
if c.Description == "" {
c.Description = fmt.Sprintf("Packer imported %s VM template", lc.VMName)
}
if errs != nil && len(errs.Errors) > 0 {
@ -95,7 +119,42 @@ type StepImportToContentLibrary struct {
func (s *StepImportToContentLibrary) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
vm := state.Get("vm").(*driver.VirtualMachine)
var err error
if s.ContentLibConfig.Ovf {
ui.Say(fmt.Sprintf("Importing VM OVF template %s to Content Library...", s.ContentLibConfig.Name))
err = s.importOvfTemplate(vm)
} else {
ui.Say(fmt.Sprintf("Importing VM template %s to Content Library...", s.ContentLibConfig.Name))
err = s.importVmTemplate(vm)
}
if err != nil {
ui.Error(fmt.Sprintf("Failed to import template %s: %s", s.ContentLibConfig.Name, err.Error()))
state.Put("error", err)
return multistep.ActionHalt
}
if s.ContentLibConfig.Destroy {
state.Put("destroy_vm", s.ContentLibConfig.Destroy)
}
return multistep.ActionContinue
}
func (s *StepImportToContentLibrary) importOvfTemplate(vm *driver.VirtualMachine) error {
ovf := vcenter.OVF{
Spec: vcenter.CreateSpec{
Name: s.ContentLibConfig.Name,
},
Target: vcenter.LibraryTarget{
LibraryID: s.ContentLibConfig.Library,
},
}
return vm.ImportOvfToContentLibrary(ovf)
}
func (s *StepImportToContentLibrary) importVmTemplate(vm *driver.VirtualMachine) error {
template := vcenter.Template{
Name: s.ContentLibConfig.Name,
Description: s.ContentLibConfig.Description,
@ -114,19 +173,7 @@ func (s *StepImportToContentLibrary) Run(_ context.Context, state multistep.Stat
}
}
ui.Say(fmt.Sprintf("Importing VM template %s to Content Library...", s.ContentLibConfig.Name))
err := vm.ImportToContentLibrary(template)
if err != nil {
ui.Error(fmt.Sprintf("Failed to import VM template %s: %s", s.ContentLibConfig.Name, err.Error()))
state.Put("error", err)
return multistep.ActionHalt
}
if s.ContentLibConfig.Destroy {
state.Put("destroy_vm", s.ContentLibConfig.Destroy)
}
return multistep.ActionContinue
return vm.ImportToContentLibrary(template)
}
func (s *StepImportToContentLibrary) Cleanup(multistep.StateBag) {

View File

@ -18,6 +18,7 @@ type FlatContentLibraryDestinationConfig struct {
ResourcePool *string `mapstructure:"resource_pool" cty:"resource_pool" hcl:"resource_pool"`
Datastore *string `mapstructure:"datastore" cty:"datastore" hcl:"datastore"`
Destroy *bool `mapstructure:"destroy" cty:"destroy" hcl:"destroy"`
Ovf *bool `mapstructure:"ovf" cty:"ovf" hcl:"ovf"`
}
// FlatMapstructure returns a new FlatContentLibraryDestinationConfig.
@ -41,6 +42,7 @@ func (*FlatContentLibraryDestinationConfig) HCL2Spec() map[string]hcldec.Spec {
"resource_pool": &hcldec.AttrSpec{Name: "resource_pool", Type: cty.String, Required: false},
"datastore": &hcldec.AttrSpec{Name: "datastore", Type: cty.String, Required: false},
"destroy": &hcldec.AttrSpec{Name: "destroy", Type: cty.Bool, Required: false},
"ovf": &hcldec.AttrSpec{Name: "ovf", Type: cty.Bool, Required: false},
}
return s
}

View File

@ -1,6 +1,8 @@
package driver
import "github.com/vmware/govmomi/vapi/library"
import (
"github.com/vmware/govmomi/vapi/library"
)
type Library struct {
driver *Driver
@ -18,3 +20,17 @@ func (d *Driver) FindContentLibrary(name string) (*Library, error) {
driver: d,
}, nil
}
func (d *Driver) FindContentLibraryItem(libraryId string, name string) (*library.Item, error) {
lm := library.NewManager(d.restClient)
items, err := lm.GetLibraryItems(d.ctx, libraryId)
if err != nil {
return nil, err
}
for _, item := range items {
if item.Name == name {
return &item, nil
}
}
return nil, nil
}

View File

@ -683,17 +683,46 @@ func (vm *VirtualMachine) ConvertToTemplate() error {
return vm.vm.MarkAsTemplate(vm.driver.ctx)
}
func (vm *VirtualMachine) ImportToContentLibrary(template vcenter.Template) error {
template.SourceVM = vm.vm.Reference().Value
func (vm *VirtualMachine) ImportOvfToContentLibrary(ovf vcenter.OVF) error {
l, err := vm.driver.FindContentLibrary(ovf.Target.LibraryID)
if err != nil {
return err
}
if l.library.Type != "LOCAL" {
return fmt.Errorf("can not deploy a VM to the content library %s of type %s; "+
"the content library must be of type LOCAL", ovf.Target.LibraryID, l.library.Type)
}
item, err := vm.driver.FindContentLibraryItem(l.library.ID, ovf.Spec.Name)
if err != nil {
return err
}
if item != nil {
// Updates existing library item
ovf.Target.LibraryItemID = item.ID
}
ovf.Target.LibraryID = l.library.ID
ovf.Source.Value = vm.vm.Reference().Value
ovf.Source.Type = "VirtualMachine"
vcm := vcenter.NewManager(vm.driver.restClient)
_, err = vcm.CreateOVF(vm.driver.ctx, ovf)
return err
}
func (vm *VirtualMachine) ImportToContentLibrary(template vcenter.Template) error {
l, err := vm.driver.FindContentLibrary(template.Library)
if err != nil {
return err
}
if l.library.Type != "LOCAL" {
return fmt.Errorf("can not deploy a VM to the content library %s of type %s; the content library must be of type LOCAL", template.Library, l.library.Type)
return fmt.Errorf("can not deploy a VM to the content library %s of type %s; "+
"the content library must be of type LOCAL", template.Library, l.library.Type)
}
template.Library = l.library.ID
template.SourceVM = vm.vm.Reference().Value
if template.Placement.Cluster != "" {
c, err := vm.driver.FindCluster(template.Placement.Cluster)

2
go.mod
View File

@ -130,7 +130,7 @@ require (
github.com/ufilesdk-dev/ufile-gosdk v0.0.0-20190830075812-b4dbc4ef43a6
github.com/ugorji/go v0.0.0-20151218193438-646ae4a518c1
github.com/ulikunitz/xz v0.5.5
github.com/vmware/govmomi v0.22.2
github.com/vmware/govmomi v0.23.1
github.com/xanzy/go-cloudstack v0.0.0-20190526095453-42f262b63ed0
github.com/yandex-cloud/go-genproto v0.0.0-20200608085315-d6e7ef5ceb97
github.com/yandex-cloud/go-sdk v0.0.0-20200610100221-ae86895efb97

3
go.sum
View File

@ -612,6 +612,9 @@ github.com/vmihailenco/msgpack v3.3.3+incompatible h1:wapg9xDUZDzGCNFlwc5SqI1rvc
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmware/govmomi v0.22.2 h1:hmLv4f+RMTTseqtJRijjOWzwELiaLMIoHv2D6H3bF4I=
github.com/vmware/govmomi v0.22.2/go.mod h1:Y+Wq4lst78L85Ge/F8+ORXIWiKYqaro1vhAulACy9Lc=
github.com/vmware/govmomi v0.23.0/go.mod h1:Y+Wq4lst78L85Ge/F8+ORXIWiKYqaro1vhAulACy9Lc=
github.com/vmware/govmomi v0.23.1 h1:vU09hxnNR/I7e+4zCJvW+5vHu5dO64Aoe2Lw7Yi/KRg=
github.com/vmware/govmomi v0.23.1/go.mod h1:Y+Wq4lst78L85Ge/F8+ORXIWiKYqaro1vhAulACy9Lc=
github.com/vmware/vmw-guestinfo v0.0.0-20170707015358-25eff159a728/go.mod h1:x9oS4Wk2s2u4tS29nEaDLdzvuHdB19CvSGJjPgkZJNk=
github.com/xanzy/go-cloudstack v0.0.0-20190526095453-42f262b63ed0 h1:NJrcIkdzq0C3I8ypAZwFE9RHtGbfp+mJvqIcoFATZuk=
github.com/xanzy/go-cloudstack v0.0.0-20190526095453-42f262b63ed0/go.mod h1:sBh287mCRwCz6zyXHMmw7sSZGPohVpnx+o+OY4M+i3A=

View File

@ -1,12 +1,16 @@
Amanda H. L. de Andrade <amanda.andrade@serpro.gov.br> amandahla <amanda.andrade@serpro.gov.br>
Amanda H. L. de Andrade <amanda.andrade@serpro.gov.br> Amanda Hager Lopes de Andrade Katz <amanda.katz@serpro.gov.br>
Amanda H. L. de Andrade <amanda.andrade@serpro.gov.br> amandahla <amanda.andrade@serpro.gov.br>
Amit Bathla <abathla@.vmware.com> <abathla@promb-1s-dhcp216.eng.vmware.com>
Andrew Kutz <akutz@vmware.com> akutz <akutz@vmware.com>
Andrew Kutz <akutz@vmware.com> <sakutz@gmail.com>
Andrew Kutz <akutz@vmware.com> Andrew Kutz <101085+akutz@users.noreply.github.com>
Andrew Kutz <akutz@vmware.com> akutz <akutz@vmware.com>
Anfernee Yongkun Gui <agui@vmware.com> <anfernee.gui@gmail.com>
Anfernee Yongkun Gui <agui@vmware.com> Yongkun Anfernee Gui <agui@vmware.com>
Anna Carrigan <anna.carrigan@hpe.com> Anna <anna.carrigan@outlook.com>
Balu Dontu <bdontu@vmware.com> BaluDontu <bdontu@vmware.com>
Bruce Downs <bruceadowns@gmail.com> <bdowns@vmware.com>
Bruce Downs <bruceadowns@gmail.com> <bruce.downs@jivesoftware.com>
Bruce Downs <bruceadowns@gmail.com> <bruce.downs@autodesk.com>
Bruce Downs <bruceadowns@gmail.com> <bruce.downs@jivesoftware.com>
Clint Greenwood <cgreenwood@vmware.com> <clint.greenwood@gmail.com>
Cédric Blomart <cblomart@gmail.com> <cedric.blomart@minfin.fed.be>
Cédric Blomart <cblomart@gmail.com> cedric <cblomart@gmail.com>
@ -14,17 +18,18 @@ David Stark <dave@davidstark.name> <david.stark@bskyb.com>
Eric Gray <egray@vmware.com> <ericgray@users.noreply.github.com>
Eric Yutao <eric.yutao@gmail.com> eric <eric.yutao@gmail.com>
Fabio Rapposelli <fabio@vmware.com> <fabio@rapposelli.org>
Faiyaz Ahmed <faiyaza@vmware.com> Faiyaz Ahmed <ahmedf@vmware.com>
Faiyaz Ahmed <faiyaza@vmware.com> Faiyaz Ahmed <faiyaza@gmail.com>
Faiyaz Ahmed <faiyaza@vmware.com> Faiyaz Ahmed <fdawg4l@users.noreply.github.com>
Henrik Hodne <henrik@travis-ci.com> <henrik@hodne.io>
Jeremy Canady <jcanady@jackhenry.com> <jcanady@gmail.com>
Jiatong Wang <wjiatong@vmware.com> jiatongw <wjiatong@vmware.com>
Lintong Jiang <lintongj@vmware.com> lintongj <55512168+lintongj@users.noreply.github.com>
Pieter Noordhuis <pnoordhuis@vmware.com> <pcnoordhuis@gmail.com>
Takaaki Furukawa <takaaki.frkw@gmail.com> takaaki.furukawa <takaaki.furukawa@mail.rakuten.com>
Takaaki Furukawa <takaaki.frkw@gmail.com> tkak <takaaki.frkw@gmail.com>
Vadim Egorov <vegorov@vmware.com> <egorovv@gmail.com>
Anfernee Yongkun Gui <agui@vmware.com> <anfernee.gui@gmail.com>
Anfernee Yongkun Gui <agui@vmware.com> Yongkun Anfernee Gui <agui@vmware.com>
Zach Tucker <ztucker@vmware.com> <jzt@users.noreply.github.com>
Zee Yang <zeey@vmware.com> <zee.yang@gmail.com>
Jiatong Wang <wjiatong@vmware.com> jiatongw <wjiatong@vmware.com>
Uwe Bessle <Uwe.Bessle@iteratec.de> Uwe Bessle <u.bessle.extern@eos-ts.com>
Uwe Bessle <Uwe.Bessle@iteratec.de> Uwe Bessle <uwe.bessle@web.de>
Lintong Jiang <lintongj@vmware.com> lintongj <55512168+lintongj@users.noreply.github.com>
Vadim Egorov <vegorov@vmware.com> <egorovv@gmail.com>
Zach Tucker <ztucker@vmware.com> <jzt@users.noreply.github.com>
Zee Yang <zeey@vmware.com> <zee.yang@gmail.com>

View File

@ -12,7 +12,7 @@ services: false
# Set the version of Go.
language: go
go: 1.13
go: 1.14
# Always set the project's Go import path to ensure that forked
# builds get cloned to the correct location.

View File

@ -1,5 +1,27 @@
# changelog
### 0.23.0 (2020-06-11)
* Finder: support DistributedVirtualSwitch traversal
* Update to vSphere 7 APIs
* Avoid possible nil pointer dereference in guest TransferURL
* Refactor govc session persistence into session/cache package
* Add SetTaskState SetTaskDescription UpdateProgress to object package
* Add Content Library subscriptions support
* Add Content Library item copy support
* Sync vim25/xml with golang 1.13 encoding/xml
* vapi: Add cluster modules client and simulator
* Expose soap client default transport
### 0.22.1 (2020-01-13)
* Fix SAML token auth using Holder-of-Key with delegated Bearer identity against 6.7 U3b+

View File

@ -96,6 +96,9 @@ We follow the conventions on [How to Write a Git Commit Message](http://chris.be
Be sure to include any related GitHub issue references in the commit message.
### Running CI checks and tests
You can run both `make check` and `make test` from the top level of the repository. While `make check` will catch formatting and import errors, it will not apply any fixes. The developer is expected to do that.
## Reporting Bugs and Creating Issues
When opening a new issue, try to roughly follow the commit message format conventions above.

View File

@ -6,6 +6,7 @@
Abhijeet Kasurde <akasurde@redhat.com>
abrarshivani <abrarshivani@users.noreply.github.com>
Adam Shannon <adamkshannon@gmail.com>
Al Biheiri <abiheiri@apple.com>
Alessandro Cortiana <alessandro.cortiana@gmail.com>
Alex Bozhenko <alexbozhenko@fb.com>
Alex Ellis (VMware) <alexellis2@gmail.com>
@ -21,6 +22,8 @@ Andrey Klimentyev <andrey.klimentyev@flant.com>
Anfernee Yongkun Gui <agui@vmware.com>
angystardust <angystardust@users.noreply.github.com>
aniketGslab <aniket.shinde@gslab.com>
Ankit Vaidya <vaidyaa@vmware.com>
Anna Carrigan <anna.carrigan@hpe.com>
Arran Walker <arran.walker@zopa.com>
Artem Anisimov <aanisimov@inbox.ru>
Aryeh Weinreb <aryehweinreb@gmail.com>
@ -28,26 +31,33 @@ Austin Parker <aparker@apprenda.com>
Balu Dontu <bdontu@vmware.com>
bastienbc <bastien.barbe.creuly@gmail.com>
Ben Corrie <bcorrie@vmware.com>
Benjamin Davini <davinib@vmware.com>
Benjamin Peterson <benjamin@python.org>
Bob Killen <killen.bob@gmail.com>
Brad Fitzpatrick <bradfitz@golang.org>
Bruce Downs <bruceadowns@gmail.com>
Cédric Blomart <cblomart@gmail.com>
Cheng Cheng <chengch@vmware.com>
Chethan Venkatesh <chethanv@vmware.com>
Chris Marchesi <chrism@vancluevertech.com>
Christian Höltje <docwhat@gerf.org>
Clint Greenwood <cgreenwood@vmware.com>
CuiHaozhi <cuihaozhi@chinacloud.com.cn>
Daniel Mueller <deso@posteo.net>
Dan Ilan <danilan@google.com>
Danny Lockard <danny.lockard@banno.com>
Dave Gress <gressd@vmware.com>
Dave Smith-Uchida <dsmithuchida@vmware.com>
Dave Tucker <dave@dtucker.co.uk>
Davide Agnello <dagnello@hp.com>
David Gress <gressd@vmware.com>
David Stark <dave@davidstark.name>
Davinder Kumar <davinderk@vmware.com>
demarey <christophe.demarey@inria.fr>
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Deric Crago <deric.crago@gmail.com>
Divyen Patel <divyenp@vmware.com>
Dnyanesh Gate <dnyanesh.gate@druva.com>
Doug MacEachern <dougm@vmware.com>
Eloy Coto <eloy.coto@gmail.com>
Eric Edens <ericedens@google.com>
@ -56,8 +66,10 @@ Eric Gray <egray@vmware.com>
Eric Yutao <eric.yutao@gmail.com>
Erik Hollensbe <github@hollensbe.org>
Ethan Kaley <ethan.kaley@emc.com>
Evan Chu <echu@vmware.com>
Fabio Rapposelli <fabio@vmware.com>
Faiyaz Ahmed <ahmedf@vmware.com>
Faiyaz Ahmed <faiyaza@vmware.com>
Federico Pellegatta <12744504+federico-pellegatta@users.noreply.github.com>
forkbomber <forkbomber@users.noreply.github.com>
François Rigault <rigault.francois@gmail.com>
freebsdly <qinhuajun@outlook.com>
@ -86,6 +98,7 @@ kayrus <kay.diam@gmail.com>
Kevin George <georgek@vmware.com>
leslie-qiwa <leslie.qiwa@gmail.com>
Lintong Jiang <lintongj@vmware.com>
Liping Xue <lipingx@vmware.com>
Louie Jiang <jiangl@vmware.com>
Luther Monson <luther.monson@gmail.com>
maplain <fangyuanl@vmware.com>
@ -97,6 +110,7 @@ Mario Trangoni <mjtrangoni@gmail.com>
Mark Peek <markpeek@vmware.com>
Matt Clay <matt@mystile.com>
Matthew Cosgrove <matthew.cosgrove@dell.com>
Matt Moore <mattmoor@vmware.com>
Matt Moriarity <matt@mattmoriarity.com>
Mevan Samaratunga <mevansam@gmail.com>
Michal Jankowski <mjankowski@vmware.com>
@ -109,15 +123,20 @@ Pieter Noordhuis <pnoordhuis@vmware.com>
prydin <prydin@vmware.com>
rHermes <teodor_spaeren@riseup.net>
Rowan Jacobs <rojacobs@pivotal.io>
rsikdar <rsikdar@berkeley.edu>
runner.mei <runner.mei@gmail.com>
Sandeep Pissay Srinivasa Rao <ssrinivas@vmware.com>
S.Çağlar Onur <conur@vmware.com>
Sergey Ignatov <sergey.ignatov@jetbrains.com>
serokles <timbo.alexander@gmail.com>
Shalini Bhaskara <sbhaskara@vmware.com>
Shawn Neal <sneal@sneal.net>
shylasrinivas <sshyla@vmware.com>
sky-joker <sky.jokerxx@gmail.com>
Sten Feldman <exile@chamber.ee>
Stepan Mazurov <smazurov@gmail.com>
Steve Purcell <steve@sanityinc.com>
SUMIT AGRAWAL <asumit@vmware.com>
Takaaki Furukawa <takaaki.frkw@gmail.com>
Tamas Eger <tamas.eger@bitrise.io>
tanishi <tanishi503@gmail.com>
@ -128,13 +147,19 @@ Tim McNamara <tim.mcnamara@canonical.com>
Tjeu Kayim <15987676+TjeuKayim@users.noreply.github.com>
Toomas Pelberg <toomas.pelberg@playtech.com>
Trevor Dawe <trevor.dawe@gmail.com>
tshihad <tshihad9@gmail.com>
Uwe Bessle <Uwe.Bessle@iteratec.de>
Vadim Egorov <vegorov@vmware.com>
Vikram Krishnamurthy <vikramkrishnamu@vmware.com>
volanja <volaaanja@gmail.com>
Volodymyr Bobyr <pupsua@gmail.com>
Waldek Maleska <w.maleska@gmail.com>
William Lam <info.virtuallyghetto@gmail.com>
Witold Krecicki <wpk@culm.net>
xing-yang <xingyang105@gmail.com>
yangxi <yangxi@vmware.com>
Yang Yang <yangy@vmware.com>
Yann Hodique <yhodique@google.com>
ykakarap <yuva2811@gmail.com>
Yuya Kusakabe <yuya.kusakabe@gmail.com>
Zacharias Taubert <zacharias.taubert@gmail.com>

View File

@ -9,6 +9,7 @@ goimports:
@echo checking go imports...
@command -v goimports >/dev/null 2>&1 || $(GO) get golang.org/x/tools/cmd/goimports
@! goimports -d . 2>&1 | egrep -v '^$$'
@! TERM=xterm git grep encoding/xml -- '*.go' ':!vim25/xml/*.go'
govet:
@echo checking go vet...

View File

@ -15,9 +15,9 @@ In addition to the vSphere API client, this repository includes:
## Compatibility
This library is built for and tested against ESXi and vCenter 6.0, 6.5 and 6.7.
This library is built for and tested against ESXi and vCenter 6.5, 6.7 and 7.0.
It may work with versions 5.5 and 5.1, but neither are officially supported.
It may work with versions 5.1, 5.5 and 6.0, but neither are officially supported.
## Documentation
@ -28,7 +28,7 @@ The code in the `govmomi` package is a wrapper for the code that is generated fr
It primarily provides convenience functions for working with the vSphere API.
See [godoc.org][godoc] for documentation.
[apiref]:https://code.vmware.com/apis/196/vsphere
[apiref]:https://code.vmware.com/apis/968/vsphere
[godoc]:http://godoc.org/github.com/vmware/govmomi
## Installation
@ -85,12 +85,24 @@ Refer to the [CHANGELOG](CHANGELOG.md) for version to version changes.
* [Juju](https://github.com/juju/juju)
* [vSphere 7.0](https://docs.vmware.com/en/VMware-vSphere/7.0/rn/vsphere-esxi-vcenter-server-7-vsphere-with-kubernetes-release-notes.html)
* [OPS](https://github.com/nanovms/ops)
## Related projects
* [rbvmomi](https://github.com/vmware/rbvmomi)
* [pyvmomi](https://github.com/vmware/pyvmomi)
* [go-vmware-nsxt](https://github.com/vmware/go-vmware-nsxt)
## License
govmomi is available under the [Apache 2 license](LICENSE.txt).
## Name
Pronounced "go-v-mom-ie"
Follows pyvmomi and rbvmomi: language prefix + the vSphere acronym "VM Object Management Infrastructure".

View File

@ -165,6 +165,8 @@ func (l Lister) List(ctx context.Context) ([]Element, error) {
return l.ListHostSystem(ctx)
case "VirtualApp":
return l.ListVirtualApp(ctx)
case "VmwareDistributedVirtualSwitch", "DistributedVirtualSwitch":
return l.ListDistributedVirtualSwitch(ctx)
default:
return nil, fmt.Errorf("cannot traverse type " + l.Reference.Type)
}
@ -497,6 +499,69 @@ func (l Lister) ListHostSystem(ctx context.Context) ([]Element, error) {
return es, nil
}
func (l Lister) ListDistributedVirtualSwitch(ctx context.Context) ([]Element, error) {
ospec := types.ObjectSpec{
Obj: l.Reference,
Skip: types.NewBool(true),
}
fields := []string{
"portgroup",
}
for _, f := range fields {
tspec := types.TraversalSpec{
Path: f,
Skip: types.NewBool(false),
Type: "DistributedVirtualSwitch",
}
ospec.SelectSet = append(ospec.SelectSet, &tspec)
}
childTypes := []string{
"DistributedVirtualPortgroup",
}
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,

View File

@ -25,7 +25,6 @@ import (
"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"
)
@ -75,29 +74,22 @@ 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.
// ObjectName fetches the mo.ManagedEntity.Name field via the property collector.
func (c Common) ObjectName(ctx context.Context) (string, error) {
var o mo.ManagedEntity
var content []types.ObjectContent
err := c.Properties(ctx, c.Reference(), []string{"name"}, &o)
err := c.Properties(ctx, c.Reference(), []string{"name"}, &content)
if err != nil {
return "", err
}
if o.Name != "" {
return o.Name, nil
for i := range content {
for _, prop := range content[i].PropSet {
return prop.Val.(string), nil
}
}
// Network has its own "name" field...
var n mo.Network
err = c.Properties(ctx, c.Reference(), []string{"name"}, &n)
if err != nil {
return "", err
}
return n.Name, nil
return "", nil
}
// Properties is a wrapper for property.DefaultCollector().RetrieveOne()

View File

@ -20,7 +20,6 @@ import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
@ -40,19 +39,14 @@ func (n Network) GetInventoryPath() string {
// 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)
name, err := n.ObjectName(ctx)
if err != nil {
return nil, err
}
backing := &types.VirtualEthernetCardNetworkBackingInfo{
VirtualDeviceDeviceBackingInfo: types.VirtualDeviceDeviceBackingInfo{
DeviceName: e.Name,
DeviceName: name,
},
}

View File

@ -41,17 +41,11 @@ func (n OpaqueNetwork) GetInventoryPath() string {
// 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 {
summary, err := n.Summary(ctx)
if 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,
@ -59,3 +53,20 @@ func (n OpaqueNetwork) EthernetCardBackingInfo(ctx context.Context) (types.BaseV
return backing, nil
}
// Summary returns the mo.OpaqueNetwork.Summary property
func (n OpaqueNetwork) Summary(ctx context.Context) (*types.OpaqueNetworkSummary, error) {
var props mo.OpaqueNetwork
err := n.Properties(ctx, n.Reference(), []string{"summary"}, &props)
if err != nil {
return nil, err
}
summary, ok := props.Summary.(*types.OpaqueNetworkSummary)
if !ok {
return nil, fmt.Errorf("%s unsupported network summary type: %T", n, props.Summary)
}
return summary, nil
}

View File

@ -64,3 +64,37 @@ func (t *Task) Cancel(ctx context.Context) error {
return err
}
// SetState sets task state and optionally sets results or fault, as appropriate for state.
func (t *Task) SetState(ctx context.Context, state types.TaskInfoState, result types.AnyType, fault *types.LocalizedMethodFault) error {
req := types.SetTaskState{
This: t.Reference(),
State: state,
Result: result,
Fault: fault,
}
_, err := methods.SetTaskState(ctx, t.Common.Client(), &req)
return err
}
// SetDescription updates task description to describe the current phase of the task.
func (t *Task) SetDescription(ctx context.Context, description types.LocalizableMessage) error {
req := types.SetTaskDescription{
This: t.Reference(),
Description: description,
}
_, err := methods.SetTaskDescription(ctx, t.Common.Client(), &req)
return err
}
// UpdateProgress Sets percentage done for this task and recalculates overall percentage done.
// If a percentDone value of less than zero or greater than 100 is specified,
// a value of zero or 100 respectively is used.
func (t *Task) UpdateProgress(ctx context.Context, percentDone int) error {
req := types.UpdateProgress{
This: t.Reference(),
PercentDone: int32(percentDone),
}
_, err := methods.UpdateProgress(ctx, t.Common.Client(), &req)
return err
}

View File

@ -855,8 +855,10 @@ func (v VirtualMachine) UUID(ctx context.Context) string {
if err != nil {
return ""
}
return o.Config.Uuid
if o.Config != nil {
return o.Config.Uuid
}
return ""
}
func (v VirtualMachine) QueryChangedDiskAreas(ctx context.Context, baseSnapshot, curSnapshot *types.ManagedObjectReference, disk *types.VirtualDisk, offset int64) (types.DiskChangeInfo, error) {

View File

@ -143,7 +143,7 @@ func (p *Collector) Retrieve(ctx context.Context, objs []types.ManagedObjectRefe
spec := types.PropertySpec{
Type: obj.Type,
}
if ps == nil {
if len(ps) == 0 {
spec.All = types.NewBool(true)
} else {
spec.PathSet = ps

View File

@ -42,6 +42,9 @@ func (f Filter) Keys() []string {
// MatchProperty returns true if a Filter entry matches the given prop.
func (f Filter) MatchProperty(prop types.DynamicProperty) bool {
if prop.Val == nil {
return false
}
match, ok := f[prop.Name]
if !ok {
return false
@ -74,7 +77,7 @@ func (f Filter) MatchProperty(prop types.DynamicProperty) bool {
}
// convert if we can
switch prop.Val.(type) {
switch val := prop.Val.(type) {
case bool:
match, _ = strconv.ParseBool(s)
case int16:
@ -91,7 +94,9 @@ func (f Filter) MatchProperty(prop types.DynamicProperty) bool {
case float64:
match, _ = strconv.ParseFloat(s, 64)
case fmt.Stringer:
prop.Val = prop.Val.(fmt.Stringer).String()
prop.Val = val.String()
case *types.CustomFieldStringValue:
prop.Val = fmt.Sprintf("%d:%s", val.Key, val.Value)
default:
if ptype.Kind() != reflect.String {
return false

View File

@ -29,6 +29,7 @@ type WaitFilter struct {
types.CreateFilter
Options *types.WaitOptions
PropagateMissing bool
Truncated bool
}
// Add a new ObjectSpec and PropertySpec to the WaitFilter
@ -127,6 +128,10 @@ func WaitForUpdates(ctx context.Context, c *Collector, filter *WaitFilter, f fun
}
req.Version = set.Version
filter.Truncated = false
if set.Truncated != nil {
filter.Truncated = *set.Truncated
}
for _, fs := range set.FilterSet {
if filter.PropagateMissing {

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2015,2019 VMware, Inc. All Rights Reserved.
Copyright (c) 2015-2020 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -17,115 +17,24 @@ limitations under the License.
package session
import (
"context"
"sync"
"time"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/session/keepalive"
"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 {
_, err := methods.GetCurrentTime(context.Background(), roundTripper)
return err
}
// 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.
// KeepAlive is a backward compatible wrapper around KeepAliveHandler.
func KeepAlive(roundTripper soap.RoundTripper, idleTime time.Duration) soap.RoundTripper {
return KeepAliveHandler(roundTripper, idleTime, defaultKeepAlive)
return KeepAliveHandler(roundTripper, idleTime, nil)
}
// 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.
// KeepAliveHandler is a backward compatible wrapper around keepalive.NewHandlerSOAP.
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() {
for t := time.NewTimer(k.idleTime); ; {
select {
case <-k.notifyStop:
k.notifyWaitGroup.Done()
return
case <-k.notifyRequest:
t.Reset(k.idleTime)
case <-t.C:
if err := k.keepAlive(k.roundTripper); err != nil {
k.notifyWaitGroup.Done()
k.stop()
return
}
t = time.NewTimer(k.idleTime)
}
var f func() error
if handler != nil {
f = func() error {
return handler(roundTripper)
}
}()
}
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 {
// Stop ticker on logout.
switch req.(type) {
case *methods.LogoutBody:
k.stop()
}
err := k.roundTripper.RoundTrip(ctx, req, res)
if err != nil {
return err
}
// Start ticker on login.
switch req.(type) {
case *methods.LoginBody, *methods.LoginExtensionByCertificateBody, *methods.LoginByTokenBody:
k.start()
}
return nil
}
return keepalive.NewHandlerSOAP(roundTripper, idleTime, f)
}

View File

@ -0,0 +1,204 @@
/*
Copyright (c) 2020 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package keepalive
import (
"context"
"errors"
"net/http"
"sync"
"time"
"github.com/vmware/govmomi/vapi/rest"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/soap"
)
// handler contains the generic keep alive settings and logic
type handler struct {
mu sync.Mutex
notifyStop chan struct{}
notifyWaitGroup sync.WaitGroup
idle time.Duration
send func() error
}
// NewHandlerSOAP returns a soap.RoundTripper for use with a vim25.Client
// The idle time specifies the interval in between send() requests. Defaults to 10 minutes.
// The send func is used to keep a session alive. Defaults to calling vim25 GetCurrentTime().
// The keep alive goroutine starts when a Login method is called and runs until Logout is called or send returns an error.
func NewHandlerSOAP(c soap.RoundTripper, idle time.Duration, send func() error) *HandlerSOAP {
h := &handler{
idle: idle,
send: send,
}
if send == nil {
h.send = func() error {
return h.keepAliveSOAP(c)
}
}
return &HandlerSOAP{h, c}
}
// NewHandlerREST returns an http.RoundTripper for use with a rest.Client
// The idle time specifies the interval in between send() requests. Defaults to 10 minutes.
// The send func is used to keep a session alive. Defaults to calling the rest.Client.Session() method
// The keep alive goroutine starts when a Login method is called and runs until Logout is called or send returns an error.
func NewHandlerREST(c *rest.Client, idle time.Duration, send func() error) *HandlerREST {
h := &handler{
idle: idle,
send: send,
}
if send == nil {
h.send = func() error {
return h.keepAliveREST(c)
}
}
return &HandlerREST{h, c.Transport}
}
func (h *handler) keepAliveSOAP(rt soap.RoundTripper) error {
ctx := context.Background()
_, err := methods.GetCurrentTime(ctx, rt)
return err
}
func (h *handler) keepAliveREST(c *rest.Client) error {
ctx := context.Background()
s, err := c.Session(ctx)
if err != nil {
return err
}
if s != nil {
return nil
}
return errors.New(http.StatusText(http.StatusUnauthorized))
}
// Start explicitly starts the keep alive go routine.
// For use with session cache.Client, as cached sessions may not involve Login/Logout via RoundTripper.
func (h *handler) Start() {
h.mu.Lock()
defer h.mu.Unlock()
if h.notifyStop != nil {
return
}
if h.idle == 0 {
h.idle = time.Minute * 10
}
// This channel must be closed to terminate idle timer.
h.notifyStop = make(chan struct{})
h.notifyWaitGroup.Add(1)
go func() {
for t := time.NewTimer(h.idle); ; {
select {
case <-h.notifyStop:
h.notifyWaitGroup.Done()
t.Stop()
return
case <-t.C:
if err := h.send(); err != nil {
h.notifyWaitGroup.Done()
h.Stop()
return
}
t.Reset(h.idle)
}
}
}()
}
// Stop explicitly stops the keep alive go routine.
// For use with session cache.Client, as cached sessions may not involve Login/Logout via RoundTripper.
func (h *handler) Stop() {
h.mu.Lock()
defer h.mu.Unlock()
if h.notifyStop != nil {
close(h.notifyStop)
h.notifyWaitGroup.Wait()
h.notifyStop = nil
}
}
// HandlerSOAP is a keep alive implementation for use with vim25.Client
type HandlerSOAP struct {
*handler
roundTripper soap.RoundTripper
}
// RoundTrip implements soap.RoundTripper
func (h *HandlerSOAP) RoundTrip(ctx context.Context, req, res soap.HasFault) error {
// Stop ticker on logout.
switch req.(type) {
case *methods.LogoutBody:
h.Stop()
}
err := h.roundTripper.RoundTrip(ctx, req, res)
if err != nil {
return err
}
// Start ticker on login.
switch req.(type) {
case *methods.LoginBody, *methods.LoginExtensionByCertificateBody, *methods.LoginByTokenBody:
h.Start()
}
return nil
}
// HandlerREST is a keep alive implementation for use with rest.Client
type HandlerREST struct {
*handler
roundTripper http.RoundTripper
}
// RoundTrip implements http.RoundTripper
func (h *HandlerREST) RoundTrip(req *http.Request) (*http.Response, error) {
if req.URL.Path != "/rest/com/vmware/cis/session" {
return h.roundTripper.RoundTrip(req)
}
if req.Method == http.MethodDelete { // Logout
h.Stop()
}
res, err := h.roundTripper.RoundTrip(req)
if err != nil {
return res, err
}
if req.Method == http.MethodPost { // Login
h.Start()
}
return res, err
}

View File

@ -19,7 +19,6 @@ package session
import (
"context"
"io/ioutil"
"net/http"
"net/url"
"os"
"strings"
@ -124,7 +123,7 @@ func (sm *Manager) LoginExtensionByCertificate(ctx context.Context, key string)
// "Post https://sdkTunnel:8089/sdk: x509: certificate is valid for $vcenter_hostname, not sdkTunnel"
// The only easy way around this is to disable verification for the call to LoginExtensionByCertificate().
// TODO: find a way to avoid disabling InsecureSkipVerify.
c.Transport.(*http.Transport).TLSClientConfig.InsecureSkipVerify = true
c.DefaultTransport().TLSClientConfig.InsecureSkipVerify = true
}
req := types.LoginExtensionByCertificate{

View File

@ -38,10 +38,12 @@ const (
LocalLibraryPath = "/com/vmware/content/local-library"
SubscribedLibraryPath = "/com/vmware/content/subscribed-library"
SubscribedLibraryItem = "/com/vmware/content/library/subscribed-item"
Subscriptions = "/com/vmware/content/library/subscriptions"
VCenterOVFLibraryItem = "/com/vmware/vcenter/ovf/library-item"
VCenterVMTXLibraryItem = "/vcenter/vm-template/library-items"
VCenterVM = "/vcenter/vm"
SessionCookieName = "vmware-api-session-id"
UseHeaderAuthn = "vmware-use-header-authn"
)
// AssociatedObject is the same structure as types.ManagedObjectReference,
@ -69,3 +71,16 @@ func NewAssociation(ref mo.Reference) Association {
ObjectID: &obj,
}
}
type SubscriptionDestination struct {
ID string `json:"subscription"`
}
type SubscriptionDestinationSpec struct {
Subscriptions []SubscriptionDestination `json:"subscriptions,omitempty"`
}
type SubscriptionItemDestinationSpec struct {
Force bool `json:"force_sync_content"`
Subscriptions []SubscriptionDestination `json:"subscriptions,omitempty"`
}

View File

@ -46,6 +46,7 @@ type Library struct {
Type string `json:"type,omitempty"`
Version string `json:"version,omitempty"`
Subscription *Subscription `json:"subscription_info,omitempty"`
Publication *Publication `json:"publish_info,omitempty"`
}
// Subscription info
@ -59,6 +60,59 @@ type Subscription struct {
UserName string `json:"user_name,omitempty"`
}
// Publication info
type Publication struct {
AuthenticationMethod string `json:"authentication_method"`
UserName string `json:"user_name,omitempty"`
Password string `json:"password,omitempty"`
CurrentPassword string `json:"current_password,omitempty"`
PersistJSON *bool `json:"persist_json_enabled,omitempty"`
Published *bool `json:"published,omitempty"`
PublishURL string `json:"publish_url,omitempty"`
}
// SubscriberSummary as returned by ListSubscribers
type SubscriberSummary struct {
LibraryID string `json:"subscribed_library"`
LibraryName string `json:"subscribed_library_name"`
SubscriptionID string `json:"subscription"`
LibraryVcenterHostname string `json:"subscribed_library_vcenter_hostname,omitempty"`
}
// Placement information used to place a virtual machine template
type Placement struct {
ResourcePool string `json:"resource_pool,omitempty"`
Host string `json:"host,omitempty"`
Folder string `json:"folder,omitempty"`
Cluster string `json:"cluster,omitempty"`
Network string `json:"network,omitempty"`
}
// Vcenter contains information about the vCenter Server instance where a subscribed library associated with a subscription exists.
type Vcenter struct {
Hostname string `json:"hostname"`
Port int `json:"https_port,omitempty"`
ServerGUID string `json:"server_guid"`
}
// Subscriber contains the detailed info for a library subscriber.
type Subscriber struct {
LibraryID string `json:"subscribed_library"`
LibraryName string `json:"subscribed_library_name"`
LibraryLocation string `json:"subscribed_library_location"`
Placement *Placement `json:"subscribed_library_placement,omitempty"`
Vcenter *Vcenter `json:"subscribed_library_vcenter,omitempty"`
}
// SubscriberLibrary is the specification for a subscribed library to be associated with a subscription.
type SubscriberLibrary struct {
Target string `json:"target"`
LibraryID string `json:"subscribed_library,omitempty"`
Location string `json:"location"`
Vcenter *Vcenter `json:"vcenter,omitempty"`
Placement *Placement `json:"placement,omitempty"`
}
// Patch merges updates from the given src.
func (l *Library) Patch(src *Library) {
if src.Name != "" {
@ -124,7 +178,7 @@ func (c *Manager) CreateLibrary(ctx context.Context, library Library) (string, e
if u.Scheme == "https" && sub.SslThumbprint == "" {
thumbprint := c.Thumbprint(u.Host)
if thumbprint == "" {
t := c.Transport.(*http.Transport)
t := c.DefaultTransport()
if t.TLSClientConfig.InsecureSkipVerify {
var info object.HostCertificateInfo
_ = info.FromURL(u, t.TLSClientConfig)
@ -146,6 +200,18 @@ func (c *Manager) SyncLibrary(ctx context.Context, library *Library) error {
return c.Do(ctx, url.Request(http.MethodPost), nil)
}
// PublishLibrary publishes the library to specified subscriptions.
// If no subscriptions are specified, then publishes the library to all subscriptions.
func (c *Manager) PublishLibrary(ctx context.Context, library *Library, subscriptions []string) error {
path := internal.LocalLibraryPath
var spec internal.SubscriptionDestinationSpec
for i := range subscriptions {
spec.Subscriptions = append(spec.Subscriptions, internal.SubscriptionDestination{ID: subscriptions[i]})
}
url := c.Resource(path).WithID(library.ID).WithAction("publish")
return c.Do(ctx, url.Request(http.MethodPost, spec), nil)
}
// DeleteLibrary deletes an existing library.
func (c *Manager) DeleteLibrary(ctx context.Context, library *Library) error {
path := internal.LocalLibraryPath
@ -204,3 +270,39 @@ func (c *Manager) GetLibraries(ctx context.Context) ([]Library, error) {
}
return libraries, nil
}
// ListSubscribers lists the subscriptions of the published library.
func (c *Manager) ListSubscribers(ctx context.Context, library *Library) ([]SubscriberSummary, error) {
url := c.Resource(internal.Subscriptions).WithParam("library", library.ID)
var res []SubscriberSummary
return res, c.Do(ctx, url.Request(http.MethodGet), &res)
}
// CreateSubscriber creates a subscription of the published library.
func (c *Manager) CreateSubscriber(ctx context.Context, library *Library, s SubscriberLibrary) (string, error) {
var spec struct {
Sub struct {
SubscriberLibrary SubscriberLibrary `json:"subscribed_library"`
} `json:"spec"`
}
spec.Sub.SubscriberLibrary = s
url := c.Resource(internal.Subscriptions).WithID(library.ID)
var res string
return res, c.Do(ctx, url.Request(http.MethodPost, &spec), &res)
}
// GetSubscriber returns information about the specified subscriber of the published library.
func (c *Manager) GetSubscriber(ctx context.Context, library *Library, subscriber string) (*Subscriber, error) {
id := internal.SubscriptionDestination{ID: subscriber}
url := c.Resource(internal.Subscriptions).WithID(library.ID).WithAction("get")
var res Subscriber
return &res, c.Do(ctx, url.Request(http.MethodPost, &id), &res)
}
// DeleteSubscriber deletes the specified subscription of the published library.
// The subscribed library associated with the subscription will not be deleted.
func (c *Manager) DeleteSubscriber(ctx context.Context, library *Library, subscriber string) error {
id := internal.SubscriptionDestination{ID: subscriber}
url := c.Resource(internal.Subscriptions).WithID(library.ID).WithAction("delete")
return c.Do(ctx, url.Request(http.MethodPost, &id), nil)
}

View File

@ -88,6 +88,16 @@ func (c *Manager) CreateLibraryItem(ctx context.Context, item Item) (string, err
return res, c.Do(ctx, url.Request(http.MethodPost, spec), &res)
}
// CopyLibraryItem copies a library item
func (c *Manager) CopyLibraryItem(ctx context.Context, src *Item, dst Item) (string, error) {
body := struct {
Item `json:"destination_create_spec"`
}{dst}
url := c.Resource(internal.LibraryItemPath).WithID(src.ID).WithAction("copy")
var res string
return res, c.Do(ctx, url.Request(http.MethodPost, body), &res)
}
// SyncLibraryItem syncs a subscribed library item
func (c *Manager) SyncLibraryItem(ctx context.Context, item *Item, force bool) error {
body := struct {
@ -97,6 +107,19 @@ func (c *Manager) SyncLibraryItem(ctx context.Context, item *Item, force bool) e
return c.Do(ctx, url.Request(http.MethodPost, body), nil)
}
// PublishLibraryItem publishes a library item to specified subscriptions.
// If no subscriptions are specified, then publishes the library item to all subscriptions.
func (c *Manager) PublishLibraryItem(ctx context.Context, item *Item, force bool, subscriptions []string) error {
body := internal.SubscriptionItemDestinationSpec{
Force: force,
}
for i := range subscriptions {
body.Subscriptions = append(body.Subscriptions, internal.SubscriptionDestination{ID: subscriptions[i]})
}
url := c.Resource(internal.LibraryItemPath).WithID(item.ID).WithAction("publish")
return c.Do(ctx, url.Request(http.MethodPost, body), nil)
}
// DeleteLibraryItem deletes an existing library item.
func (c *Manager) DeleteLibraryItem(ctx context.Context, item *Item) error {
url := c.Resource(internal.LibraryItemPath).WithID(item.ID)

View File

@ -116,7 +116,7 @@ func (c *Manager) getContentLengthAndFingerprint(
}
fingerprint := c.Thumbprint(resp.Request.URL.Host)
if fingerprint == "" {
if c.Transport.(*http.Transport).TLSClientConfig.InsecureSkipVerify {
if c.DefaultTransport().TLSClientConfig.InsecureSkipVerify {
fingerprint = soap.ThumbprintSHA1(resp.TLS.PeerCertificates[0])
}
}

View File

@ -25,6 +25,7 @@ import (
"io/ioutil"
"net/http"
"net/url"
"sync"
"time"
"github.com/vmware/govmomi/vapi/internal"
@ -34,7 +35,10 @@ import (
// Client extends soap.Client to support JSON encoding, while inheriting security features, debug tracing and session persistence.
type Client struct {
mu sync.Mutex
*soap.Client
sessionID string
}
// Session information
@ -59,7 +63,47 @@ func (m *LocalizableMessage) Error() string {
func NewClient(c *vim25.Client) *Client {
sc := c.Client.NewServiceClient(Path, "")
return &Client{sc}
return &Client{Client: sc}
}
// SessionID is set by calling Login() or optionally with the given id param
func (c *Client) SessionID(id ...string) string {
c.mu.Lock()
defer c.mu.Unlock()
if len(id) != 0 {
c.sessionID = id[0]
}
return c.sessionID
}
type marshaledClient struct {
SoapClient *soap.Client
SessionID string
}
func (c *Client) MarshalJSON() ([]byte, error) {
m := marshaledClient{
SoapClient: c.Client,
SessionID: c.sessionID,
}
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,
sessionID: m.SessionID,
}
return nil
}
// Resource helper for the given path.
@ -96,6 +140,10 @@ func (c *Client) Do(ctx context.Context, req *http.Request, resBody interface{})
req.Header.Set("Accept", "application/json")
if id := c.SessionID(); id != "" {
req.Header.Set(internal.SessionCookieName, id)
}
if s, ok := ctx.Value(signerContext{}).(Signer); ok {
if err := s.SignRequest(req); err != nil {
return err
@ -105,6 +153,7 @@ func (c *Client) Do(ctx context.Context, req *http.Request, resBody interface{})
return c.Client.Do(ctx, req, func(res *http.Response) error {
switch res.StatusCode {
case http.StatusOK:
case http.StatusNoContent:
case http.StatusBadRequest:
// TODO: structured error types
detail, err := ioutil.ReadAll(res.Body)
@ -135,17 +184,62 @@ func (c *Client) Do(ctx context.Context, req *http.Request, resBody interface{})
})
}
// authHeaders ensures the given map contains a REST auth header
func (c *Client) authHeaders(h map[string]string) map[string]string {
if _, exists := h[internal.SessionCookieName]; exists {
return h
}
if h == nil {
h = make(map[string]string)
}
h[internal.SessionCookieName] = c.SessionID()
return h
}
// Download wraps soap.Client.Download, adding the REST authentication header
func (c *Client) Download(ctx context.Context, u *url.URL, param *soap.Download) (io.ReadCloser, int64, error) {
p := *param
p.Headers = c.authHeaders(p.Headers)
return c.Client.Download(ctx, u, &p)
}
// DownloadFile wraps soap.Client.DownloadFile, adding the REST authentication header
func (c *Client) DownloadFile(ctx context.Context, file string, u *url.URL, param *soap.Download) error {
p := *param
p.Headers = c.authHeaders(p.Headers)
return c.Client.DownloadFile(ctx, file, u, &p)
}
// Upload wraps soap.Client.Upload, adding the REST authentication header
func (c *Client) Upload(ctx context.Context, f io.Reader, u *url.URL, param *soap.Upload) error {
p := *param
p.Headers = c.authHeaders(p.Headers)
return c.Client.Upload(ctx, f, u, &p)
}
// Login creates a new session via Basic Authentication with the given url.Userinfo.
func (c *Client) Login(ctx context.Context, user *url.Userinfo) error {
req := c.Resource(internal.SessionPath).Request(http.MethodPost)
req.Header.Set(internal.UseHeaderAuthn, "true")
if user != nil {
if password, ok := user.Password(); ok {
req.SetBasicAuth(user.Username(), password)
}
}
return c.Do(ctx, req, nil)
var id string
err := c.Do(ctx, req, &id)
if err != nil {
return err
}
c.SessionID(id)
return nil
}
func (c *Client) LoginByToken(ctx context.Context) error {
@ -174,3 +268,22 @@ func (c *Client) Logout(ctx context.Context) error {
req := c.Resource(internal.SessionPath).Request(http.MethodDelete)
return c.Do(ctx, req, 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
}
return true
}
// Path returns rest.Path (see cache.Client)
func (c *Client) Path() string {
return Path
}

View File

@ -60,14 +60,13 @@ type AdditionalParams struct {
}
const (
ClassOvfParams = "com.vmware.vcenter.ovf.ovf_params"
ClassPropertyParams = "com.vmware.vcenter.ovf.property_params"
TypeDeploymentOptionParams = "DeploymentOptionParams"
TypeExtraConfigParams = "ExtraConfigParams"
TypeExtraConfigs = "ExtraConfigs"
TypeIPAllocationParams = "IpAllocationParams"
TypePropertyParams = "PropertyParams"
TypeSizeParams = "SizeParams"
ClassDeploymentOptionParams = "com.vmware.vcenter.ovf.deployment_option_params"
ClassPropertyParams = "com.vmware.vcenter.ovf.property_params"
TypeDeploymentOptionParams = "DeploymentOptionParams"
TypeExtraConfigParams = "ExtraConfigParams"
TypeIPAllocationParams = "IpAllocationParams"
TypePropertyParams = "PropertyParams"
TypeSizeParams = "SizeParams"
)
// DeploymentOption contains the information about a deployment option as defined in the OVF specification
@ -204,6 +203,33 @@ func (e *DeploymentError) Error() string {
return "deploy error: " + msg
}
// LibraryTarget specifies a Library or Library item
type LibraryTarget struct {
LibraryID string `json:"library_id,omitempty"`
LibraryItemID string `json:"library_item_id,omitempty"`
}
// CreateSpec info used to create an OVF package from a VM
type CreateSpec struct {
Description string `json:"description,omitempty"`
Name string `json:"name,omitempty"`
Flags []string `json:"flags,omitempty"`
}
// OVF data used by CreateOVF
type OVF struct {
Spec CreateSpec `json:"create_spec"`
Source ResourceID `json:"source"`
Target LibraryTarget `json:"target"`
}
// CreateResult used for decoded a CreateOVF response
type CreateResult struct {
Succeeded bool `json:"succeeded,omitempty"`
ID string `json:"ovf_library_item_id,omitempty"`
Error *DeploymentError `json:"error,omitempty"`
}
// Deployment is the results from issuing a library OVF deployment
type Deployment struct {
Succeeded bool `json:"succeeded,omitempty"`
@ -238,6 +264,23 @@ func NewManager(client *rest.Client) *Manager {
}
}
// CreateOVF creates a library OVF item in content library from an existing VM
func (c *Manager) CreateOVF(ctx context.Context, ovf OVF) (string, error) {
if ovf.Source.Type == "" {
ovf.Source.Type = "VirtualMachine"
}
url := c.Resource(internal.VCenterOVFLibraryItem)
var res CreateResult
err := c.Do(ctx, url.Request(http.MethodPost, ovf), &res)
if err != nil {
return "", err
}
if res.Succeeded {
return res.ID, nil
}
return "", res.Error
}
// DeployLibraryItem deploys a library OVF
func (c *Manager) DeployLibraryItem(ctx context.Context, libraryItemID string, deploy Deploy) (*types.ManagedObjectReference, error) {
url := c.Resource(internal.VCenterOVFLibraryItem).WithID(libraryItemID).WithAction("deploy")

View File

@ -53,12 +53,7 @@ type TemplateInfo struct {
}
// Placement information used to place the virtual machine template
type Placement struct {
ResourcePool string `json:"resource_pool,omitempty"`
Host string `json:"host,omitempty"`
Folder string `json:"folder,omitempty"`
Cluster string `json:"cluster,omitempty"`
}
type Placement = library.Placement
// StoragePolicy for DiskStorage
type StoragePolicy struct {
@ -113,7 +108,7 @@ type CheckIn struct {
Message string `json:"message"`
}
// CreateTemplate creates a library item in content library from an existing VM
// CreateTemplate creates a library VMTX item in content library from an existing VM
func (c *Manager) CreateTemplate(ctx context.Context, vmtx Template) (string, error) {
url := c.Resource(internal.VCenterVMTXLibraryItem)
var res string

View File

@ -19,7 +19,6 @@ package vim25
import (
"context"
"encoding/json"
"encoding/xml"
"fmt"
"net/http"
"path"
@ -28,11 +27,12 @@ import (
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
"github.com/vmware/govmomi/vim25/xml"
)
const (
Namespace = "vim25"
Version = "6.7"
Version = "7.0"
Path = "/sdk"
)
@ -89,9 +89,14 @@ func NewClient(ctx context.Context, rt soap.RoundTripper) (*Client, error) {
}
// UseServiceVersion sets soap.Client.Version to the current version of the service endpoint via /sdk/vimServiceVersions.xml
func (c *Client) UseServiceVersion() error {
func (c *Client) UseServiceVersion(kind ...string) error {
ns := "vim"
if len(kind) != 0 {
ns = kind[0]
}
u := c.URL()
u.Path = path.Join(Path, "vimServiceVersions.xml")
u.Path = path.Join(Path, ns+"ServiceVersions.xml")
res, err := c.Get(u.String())
if err != nil {
@ -103,8 +108,12 @@ func (c *Client) UseServiceVersion() error {
}
v := struct {
Version *string `xml:"namespace>version"`
}{&c.Version}
Namespace *string `xml:"namespace>name"`
Version *string `xml:"namespace>version"`
}{
&c.Namespace,
&c.Version,
}
err = xml.NewDecoder(res.Body).Decode(&v)
_ = res.Body.Close()
@ -171,6 +180,11 @@ func (c *Client) Valid() bool {
return true
}
// Path returns vim25.Path (see cache.Client)
func (c *Client) Path() string {
return Path
}
// IsVC returns true if we are connected to a vCenter
func (c *Client) IsVC() bool {
return c.ServiceContent.About.ApiType == "VirtualCenter"

View File

@ -63,6 +63,26 @@ func AbdicateDomOwnership(ctx context.Context, r soap.RoundTripper, req *types.A
return resBody.Res, nil
}
type AbortCustomization_TaskBody struct {
Req *types.AbortCustomization_Task `xml:"urn:vim25 AbortCustomization_Task,omitempty"`
Res *types.AbortCustomization_TaskResponse `xml:"AbortCustomization_TaskResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *AbortCustomization_TaskBody) Fault() *soap.Fault { return b.Fault_ }
func AbortCustomization_Task(ctx context.Context, r soap.RoundTripper, req *types.AbortCustomization_Task) (*types.AbortCustomization_TaskResponse, error) {
var reqBody, resBody AbortCustomization_TaskBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type AcknowledgeAlarmBody struct {
Req *types.AcknowledgeAlarm `xml:"urn:vim25 AcknowledgeAlarm,omitempty"`
Res *types.AcknowledgeAlarmResponse `xml:"AcknowledgeAlarmResponse,omitempty"`
@ -2263,6 +2283,26 @@ func ConfigureVFlashResourceEx_Task(ctx context.Context, r soap.RoundTripper, re
return resBody.Res, nil
}
type ConnectNvmeControllerBody struct {
Req *types.ConnectNvmeController `xml:"urn:vim25 ConnectNvmeController,omitempty"`
Res *types.ConnectNvmeControllerResponse `xml:"ConnectNvmeControllerResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *ConnectNvmeControllerBody) Fault() *soap.Fault { return b.Fault_ }
func ConnectNvmeController(ctx context.Context, r soap.RoundTripper, req *types.ConnectNvmeController) (*types.ConnectNvmeControllerResponse, error) {
var reqBody, resBody ConnectNvmeControllerBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type ConsolidateVMDisks_TaskBody struct {
Req *types.ConsolidateVMDisks_Task `xml:"urn:vim25 ConsolidateVMDisks_Task,omitempty"`
Res *types.ConsolidateVMDisks_TaskResponse `xml:"ConsolidateVMDisks_TaskResponse,omitempty"`
@ -2943,6 +2983,26 @@ func CreateNvdimmPMemNamespace_Task(ctx context.Context, r soap.RoundTripper, re
return resBody.Res, nil
}
type CreateNvmeOverRdmaAdapterBody struct {
Req *types.CreateNvmeOverRdmaAdapter `xml:"urn:vim25 CreateNvmeOverRdmaAdapter,omitempty"`
Res *types.CreateNvmeOverRdmaAdapterResponse `xml:"CreateNvmeOverRdmaAdapterResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *CreateNvmeOverRdmaAdapterBody) Fault() *soap.Fault { return b.Fault_ }
func CreateNvmeOverRdmaAdapter(ctx context.Context, r soap.RoundTripper, req *types.CreateNvmeOverRdmaAdapter) (*types.CreateNvmeOverRdmaAdapterResponse, error) {
var reqBody, resBody CreateNvmeOverRdmaAdapterBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type CreateObjectScheduledTaskBody struct {
Req *types.CreateObjectScheduledTask `xml:"urn:vim25 CreateObjectScheduledTask,omitempty"`
Res *types.CreateObjectScheduledTaskResponse `xml:"CreateObjectScheduledTaskResponse,omitempty"`
@ -3383,6 +3443,26 @@ func CreateVvolDatastore(ctx context.Context, r soap.RoundTripper, req *types.Cr
return resBody.Res, nil
}
type CryptoManagerHostDisableBody struct {
Req *types.CryptoManagerHostDisable `xml:"urn:vim25 CryptoManagerHostDisable,omitempty"`
Res *types.CryptoManagerHostDisableResponse `xml:"CryptoManagerHostDisableResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *CryptoManagerHostDisableBody) Fault() *soap.Fault { return b.Fault_ }
func CryptoManagerHostDisable(ctx context.Context, r soap.RoundTripper, req *types.CryptoManagerHostDisable) (*types.CryptoManagerHostDisableResponse, error) {
var reqBody, resBody CryptoManagerHostDisableBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type CryptoManagerHostEnableBody struct {
Req *types.CryptoManagerHostEnable `xml:"urn:vim25 CryptoManagerHostEnable,omitempty"`
Res *types.CryptoManagerHostEnableResponse `xml:"CryptoManagerHostEnableResponse,omitempty"`
@ -3483,6 +3563,26 @@ func CustomizationSpecItemToXml(ctx context.Context, r soap.RoundTripper, req *t
return resBody.Res, nil
}
type CustomizeGuest_TaskBody struct {
Req *types.CustomizeGuest_Task `xml:"urn:vim25 CustomizeGuest_Task,omitempty"`
Res *types.CustomizeGuest_TaskResponse `xml:"CustomizeGuest_TaskResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *CustomizeGuest_TaskBody) Fault() *soap.Fault { return b.Fault_ }
func CustomizeGuest_Task(ctx context.Context, r soap.RoundTripper, req *types.CustomizeGuest_Task) (*types.CustomizeGuest_TaskResponse, error) {
var reqBody, resBody CustomizeGuest_TaskBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type CustomizeVM_TaskBody struct {
Req *types.CustomizeVM_Task `xml:"urn:vim25 CustomizeVM_Task,omitempty"`
Res *types.CustomizeVM_TaskResponse `xml:"CustomizeVM_TaskResponse,omitempty"`
@ -4423,6 +4523,46 @@ func DetachTagFromVStorageObject(ctx context.Context, r soap.RoundTripper, req *
return resBody.Res, nil
}
type DisableAlarmBody struct {
Req *types.DisableAlarm `xml:"urn:vim25 DisableAlarm,omitempty"`
Res *types.DisableAlarmResponse `xml:"DisableAlarmResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *DisableAlarmBody) Fault() *soap.Fault { return b.Fault_ }
func DisableAlarm(ctx context.Context, r soap.RoundTripper, req *types.DisableAlarm) (*types.DisableAlarmResponse, error) {
var reqBody, resBody DisableAlarmBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type DisableClusteredVmdkSupportBody struct {
Req *types.DisableClusteredVmdkSupport `xml:"urn:vim25 DisableClusteredVmdkSupport,omitempty"`
Res *types.DisableClusteredVmdkSupportResponse `xml:"DisableClusteredVmdkSupportResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *DisableClusteredVmdkSupportBody) Fault() *soap.Fault { return b.Fault_ }
func DisableClusteredVmdkSupport(ctx context.Context, r soap.RoundTripper, req *types.DisableClusteredVmdkSupport) (*types.DisableClusteredVmdkSupportResponse, error) {
var reqBody, resBody DisableClusteredVmdkSupportBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type DisableEvcMode_TaskBody struct {
Req *types.DisableEvcMode_Task `xml:"urn:vim25 DisableEvcMode_Task,omitempty"`
Res *types.DisableEvcMode_TaskResponse `xml:"DisableEvcMode_TaskResponse,omitempty"`
@ -4583,6 +4723,26 @@ func DisconnectHost_Task(ctx context.Context, r soap.RoundTripper, req *types.Di
return resBody.Res, nil
}
type DisconnectNvmeControllerBody struct {
Req *types.DisconnectNvmeController `xml:"urn:vim25 DisconnectNvmeController,omitempty"`
Res *types.DisconnectNvmeControllerResponse `xml:"DisconnectNvmeControllerResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *DisconnectNvmeControllerBody) Fault() *soap.Fault { return b.Fault_ }
func DisconnectNvmeController(ctx context.Context, r soap.RoundTripper, req *types.DisconnectNvmeController) (*types.DisconnectNvmeControllerResponse, error) {
var reqBody, resBody DisconnectNvmeControllerBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type DiscoverFcoeHbasBody struct {
Req *types.DiscoverFcoeHbas `xml:"urn:vim25 DiscoverFcoeHbas,omitempty"`
Res *types.DiscoverFcoeHbasResponse `xml:"DiscoverFcoeHbasResponse,omitempty"`
@ -4603,6 +4763,26 @@ func DiscoverFcoeHbas(ctx context.Context, r soap.RoundTripper, req *types.Disco
return resBody.Res, nil
}
type DiscoverNvmeControllersBody struct {
Req *types.DiscoverNvmeControllers `xml:"urn:vim25 DiscoverNvmeControllers,omitempty"`
Res *types.DiscoverNvmeControllersResponse `xml:"DiscoverNvmeControllersResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *DiscoverNvmeControllersBody) Fault() *soap.Fault { return b.Fault_ }
func DiscoverNvmeControllers(ctx context.Context, r soap.RoundTripper, req *types.DiscoverNvmeControllers) (*types.DiscoverNvmeControllersResponse, error) {
var reqBody, resBody DiscoverNvmeControllersBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type DissociateProfileBody struct {
Req *types.DissociateProfile `xml:"urn:vim25 DissociateProfile,omitempty"`
Res *types.DissociateProfileResponse `xml:"DissociateProfileResponse,omitempty"`
@ -4643,6 +4823,26 @@ func DoesCustomizationSpecExist(ctx context.Context, r soap.RoundTripper, req *t
return resBody.Res, nil
}
type DownloadDescriptionTreeBody struct {
Req *types.DownloadDescriptionTree `xml:"urn:vim25 DownloadDescriptionTree,omitempty"`
Res *types.DownloadDescriptionTreeResponse `xml:"DownloadDescriptionTreeResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *DownloadDescriptionTreeBody) Fault() *soap.Fault { return b.Fault_ }
func DownloadDescriptionTree(ctx context.Context, r soap.RoundTripper, req *types.DownloadDescriptionTree) (*types.DownloadDescriptionTreeResponse, error) {
var reqBody, resBody DownloadDescriptionTreeBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type DuplicateCustomizationSpecBody struct {
Req *types.DuplicateCustomizationSpec `xml:"urn:vim25 DuplicateCustomizationSpec,omitempty"`
Res *types.DuplicateCustomizationSpecResponse `xml:"DuplicateCustomizationSpecResponse,omitempty"`
@ -4703,6 +4903,26 @@ func EagerZeroVirtualDisk_Task(ctx context.Context, r soap.RoundTripper, req *ty
return resBody.Res, nil
}
type EnableAlarmBody struct {
Req *types.EnableAlarm `xml:"urn:vim25 EnableAlarm,omitempty"`
Res *types.EnableAlarmResponse `xml:"EnableAlarmResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *EnableAlarmBody) Fault() *soap.Fault { return b.Fault_ }
func EnableAlarm(ctx context.Context, r soap.RoundTripper, req *types.EnableAlarm) (*types.EnableAlarmResponse, error) {
var reqBody, resBody EnableAlarmBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type EnableAlarmActionsBody struct {
Req *types.EnableAlarmActions `xml:"urn:vim25 EnableAlarmActions,omitempty"`
Res *types.EnableAlarmActionsResponse `xml:"EnableAlarmActionsResponse,omitempty"`
@ -4723,6 +4943,26 @@ func EnableAlarmActions(ctx context.Context, r soap.RoundTripper, req *types.Ena
return resBody.Res, nil
}
type EnableClusteredVmdkSupportBody struct {
Req *types.EnableClusteredVmdkSupport `xml:"urn:vim25 EnableClusteredVmdkSupport,omitempty"`
Res *types.EnableClusteredVmdkSupportResponse `xml:"EnableClusteredVmdkSupportResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *EnableClusteredVmdkSupportBody) Fault() *soap.Fault { return b.Fault_ }
func EnableClusteredVmdkSupport(ctx context.Context, r soap.RoundTripper, req *types.EnableClusteredVmdkSupport) (*types.EnableClusteredVmdkSupportResponse, error) {
var reqBody, resBody EnableClusteredVmdkSupportBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type EnableCryptoBody struct {
Req *types.EnableCrypto `xml:"urn:vim25 EnableCrypto,omitempty"`
Res *types.EnableCryptoResponse `xml:"EnableCryptoResponse,omitempty"`
@ -5963,6 +6203,26 @@ func GetCustomizationSpec(ctx context.Context, r soap.RoundTripper, req *types.G
return resBody.Res, nil
}
type GetDefaultKmsClusterBody struct {
Req *types.GetDefaultKmsCluster `xml:"urn:vim25 GetDefaultKmsCluster,omitempty"`
Res *types.GetDefaultKmsClusterResponse `xml:"GetDefaultKmsClusterResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *GetDefaultKmsClusterBody) Fault() *soap.Fault { return b.Fault_ }
func GetDefaultKmsCluster(ctx context.Context, r soap.RoundTripper, req *types.GetDefaultKmsCluster) (*types.GetDefaultKmsClusterResponse, error) {
var reqBody, resBody GetDefaultKmsClusterBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type GetPublicKeyBody struct {
Req *types.GetPublicKey `xml:"urn:vim25 GetPublicKey,omitempty"`
Res *types.GetPublicKeyResponse `xml:"GetPublicKeyResponse,omitempty"`
@ -6003,6 +6263,26 @@ func GetResourceUsage(ctx context.Context, r soap.RoundTripper, req *types.GetRe
return resBody.Res, nil
}
type GetSiteInfoBody struct {
Req *types.GetSiteInfo `xml:"urn:vim25 GetSiteInfo,omitempty"`
Res *types.GetSiteInfoResponse `xml:"GetSiteInfoResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *GetSiteInfoBody) Fault() *soap.Fault { return b.Fault_ }
func GetSiteInfo(ctx context.Context, r soap.RoundTripper, req *types.GetSiteInfo) (*types.GetSiteInfoResponse, error) {
var reqBody, resBody GetSiteInfoBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type GetVchaClusterHealthBody struct {
Req *types.GetVchaClusterHealth `xml:"urn:vim25 GetVchaClusterHealth,omitempty"`
Res *types.GetVchaClusterHealthResponse `xml:"GetVchaClusterHealthResponse,omitempty"`
@ -7203,6 +7483,26 @@ func InstantClone_Task(ctx context.Context, r soap.RoundTripper, req *types.Inst
return resBody.Res, nil
}
type IsKmsClusterActiveBody struct {
Req *types.IsKmsClusterActive `xml:"urn:vim25 IsKmsClusterActive,omitempty"`
Res *types.IsKmsClusterActiveResponse `xml:"IsKmsClusterActiveResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *IsKmsClusterActiveBody) Fault() *soap.Fault { return b.Fault_ }
func IsKmsClusterActive(ctx context.Context, r soap.RoundTripper, req *types.IsKmsClusterActive) (*types.IsKmsClusterActiveResponse, error) {
var reqBody, resBody IsKmsClusterActiveBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type IsSharedGraphicsActiveBody struct {
Req *types.IsSharedGraphicsActive `xml:"urn:vim25 IsSharedGraphicsActive,omitempty"`
Res *types.IsSharedGraphicsActiveResponse `xml:"IsSharedGraphicsActiveResponse,omitempty"`
@ -7423,6 +7723,26 @@ func ListKmipServers(ctx context.Context, r soap.RoundTripper, req *types.ListKm
return resBody.Res, nil
}
type ListKmsClustersBody struct {
Req *types.ListKmsClusters `xml:"urn:vim25 ListKmsClusters,omitempty"`
Res *types.ListKmsClustersResponse `xml:"ListKmsClustersResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *ListKmsClustersBody) Fault() *soap.Fault { return b.Fault_ }
func ListKmsClusters(ctx context.Context, r soap.RoundTripper, req *types.ListKmsClusters) (*types.ListKmsClustersResponse, error) {
var reqBody, resBody ListKmsClustersBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type ListProcessesInGuestBody struct {
Req *types.ListProcessesInGuest `xml:"urn:vim25 ListProcessesInGuest,omitempty"`
Res *types.ListProcessesInGuestResponse `xml:"ListProcessesInGuestResponse,omitempty"`
@ -8003,6 +8323,26 @@ func MarkPerenniallyReservedEx_Task(ctx context.Context, r soap.RoundTripper, re
return resBody.Res, nil
}
type MarkServiceProviderEntitiesBody struct {
Req *types.MarkServiceProviderEntities `xml:"urn:vim25 MarkServiceProviderEntities,omitempty"`
Res *types.MarkServiceProviderEntitiesResponse `xml:"MarkServiceProviderEntitiesResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *MarkServiceProviderEntitiesBody) Fault() *soap.Fault { return b.Fault_ }
func MarkServiceProviderEntities(ctx context.Context, r soap.RoundTripper, req *types.MarkServiceProviderEntities) (*types.MarkServiceProviderEntitiesResponse, error) {
var reqBody, resBody MarkServiceProviderEntitiesBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type MergeDvs_TaskBody struct {
Req *types.MergeDvs_Task `xml:"urn:vim25 MergeDvs_Task,omitempty"`
Res *types.MergeDvs_TaskResponse `xml:"MergeDvs_TaskResponse,omitempty"`
@ -11983,6 +12323,26 @@ func RegisterKmipServer(ctx context.Context, r soap.RoundTripper, req *types.Reg
return resBody.Res, nil
}
type RegisterKmsClusterBody struct {
Req *types.RegisterKmsCluster `xml:"urn:vim25 RegisterKmsCluster,omitempty"`
Res *types.RegisterKmsClusterResponse `xml:"RegisterKmsClusterResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *RegisterKmsClusterBody) Fault() *soap.Fault { return b.Fault_ }
func RegisterKmsCluster(ctx context.Context, r soap.RoundTripper, req *types.RegisterKmsCluster) (*types.RegisterKmsClusterResponse, error) {
var reqBody, resBody RegisterKmsClusterBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type RegisterVM_TaskBody struct {
Req *types.RegisterVM_Task `xml:"urn:vim25 RegisterVM_Task,omitempty"`
Res *types.RegisterVM_TaskResponse `xml:"RegisterVM_TaskResponse,omitempty"`
@ -12603,6 +12963,26 @@ func RemoveNetworkResourcePool(ctx context.Context, r soap.RoundTripper, req *ty
return resBody.Res, nil
}
type RemoveNvmeOverRdmaAdapterBody struct {
Req *types.RemoveNvmeOverRdmaAdapter `xml:"urn:vim25 RemoveNvmeOverRdmaAdapter,omitempty"`
Res *types.RemoveNvmeOverRdmaAdapterResponse `xml:"RemoveNvmeOverRdmaAdapterResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *RemoveNvmeOverRdmaAdapterBody) Fault() *soap.Fault { return b.Fault_ }
func RemoveNvmeOverRdmaAdapter(ctx context.Context, r soap.RoundTripper, req *types.RemoveNvmeOverRdmaAdapter) (*types.RemoveNvmeOverRdmaAdapterResponse, error) {
var reqBody, resBody RemoveNvmeOverRdmaAdapterBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type RemovePerfIntervalBody struct {
Req *types.RemovePerfInterval `xml:"urn:vim25 RemovePerfInterval,omitempty"`
Res *types.RemovePerfIntervalResponse `xml:"RemovePerfIntervalResponse,omitempty"`
@ -13563,6 +13943,26 @@ func RetrieveDiskPartitionInfo(ctx context.Context, r soap.RoundTripper, req *ty
return resBody.Res, nil
}
type RetrieveDynamicPassthroughInfoBody struct {
Req *types.RetrieveDynamicPassthroughInfo `xml:"urn:vim25 RetrieveDynamicPassthroughInfo,omitempty"`
Res *types.RetrieveDynamicPassthroughInfoResponse `xml:"RetrieveDynamicPassthroughInfoResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *RetrieveDynamicPassthroughInfoBody) Fault() *soap.Fault { return b.Fault_ }
func RetrieveDynamicPassthroughInfo(ctx context.Context, r soap.RoundTripper, req *types.RetrieveDynamicPassthroughInfo) (*types.RetrieveDynamicPassthroughInfoResponse, error) {
var reqBody, resBody RetrieveDynamicPassthroughInfoBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type RetrieveEntityPermissionsBody struct {
Req *types.RetrieveEntityPermissions `xml:"urn:vim25 RetrieveEntityPermissions,omitempty"`
Res *types.RetrieveEntityPermissionsResponse `xml:"RetrieveEntityPermissionsResponse,omitempty"`
@ -13603,6 +14003,26 @@ func RetrieveEntityScheduledTask(ctx context.Context, r soap.RoundTripper, req *
return resBody.Res, nil
}
type RetrieveFreeEpcMemoryBody struct {
Req *types.RetrieveFreeEpcMemory `xml:"urn:vim25 RetrieveFreeEpcMemory,omitempty"`
Res *types.RetrieveFreeEpcMemoryResponse `xml:"RetrieveFreeEpcMemoryResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *RetrieveFreeEpcMemoryBody) Fault() *soap.Fault { return b.Fault_ }
func RetrieveFreeEpcMemory(ctx context.Context, r soap.RoundTripper, req *types.RetrieveFreeEpcMemory) (*types.RetrieveFreeEpcMemoryResponse, error) {
var reqBody, resBody RetrieveFreeEpcMemoryBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type RetrieveHardwareUptimeBody struct {
Req *types.RetrieveHardwareUptime `xml:"urn:vim25 RetrieveHardwareUptime,omitempty"`
Res *types.RetrieveHardwareUptimeResponse `xml:"RetrieveHardwareUptimeResponse,omitempty"`
@ -13883,6 +14303,46 @@ func RetrieveServiceContent(ctx context.Context, r soap.RoundTripper, req *types
return resBody.Res, nil
}
type RetrieveServiceProviderEntitiesBody struct {
Req *types.RetrieveServiceProviderEntities `xml:"urn:vim25 RetrieveServiceProviderEntities,omitempty"`
Res *types.RetrieveServiceProviderEntitiesResponse `xml:"RetrieveServiceProviderEntitiesResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *RetrieveServiceProviderEntitiesBody) Fault() *soap.Fault { return b.Fault_ }
func RetrieveServiceProviderEntities(ctx context.Context, r soap.RoundTripper, req *types.RetrieveServiceProviderEntities) (*types.RetrieveServiceProviderEntitiesResponse, error) {
var reqBody, resBody RetrieveServiceProviderEntitiesBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type RetrieveSnapshotDetailsBody struct {
Req *types.RetrieveSnapshotDetails `xml:"urn:vim25 RetrieveSnapshotDetails,omitempty"`
Res *types.RetrieveSnapshotDetailsResponse `xml:"RetrieveSnapshotDetailsResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *RetrieveSnapshotDetailsBody) Fault() *soap.Fault { return b.Fault_ }
func RetrieveSnapshotDetails(ctx context.Context, r soap.RoundTripper, req *types.RetrieveSnapshotDetails) (*types.RetrieveSnapshotDetailsResponse, error) {
var reqBody, resBody RetrieveSnapshotDetailsBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type RetrieveSnapshotInfoBody struct {
Req *types.RetrieveSnapshotInfo `xml:"urn:vim25 RetrieveSnapshotInfo,omitempty"`
Res *types.RetrieveSnapshotInfoResponse `xml:"RetrieveSnapshotInfoResponse,omitempty"`
@ -14363,6 +14823,46 @@ func SetCollectorPageSize(ctx context.Context, r soap.RoundTripper, req *types.S
return resBody.Res, nil
}
type SetCryptoModeBody struct {
Req *types.SetCryptoMode `xml:"urn:vim25 SetCryptoMode,omitempty"`
Res *types.SetCryptoModeResponse `xml:"SetCryptoModeResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *SetCryptoModeBody) Fault() *soap.Fault { return b.Fault_ }
func SetCryptoMode(ctx context.Context, r soap.RoundTripper, req *types.SetCryptoMode) (*types.SetCryptoModeResponse, error) {
var reqBody, resBody SetCryptoModeBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type SetDefaultKmsClusterBody struct {
Req *types.SetDefaultKmsCluster `xml:"urn:vim25 SetDefaultKmsCluster,omitempty"`
Res *types.SetDefaultKmsClusterResponse `xml:"SetDefaultKmsClusterResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *SetDefaultKmsClusterBody) Fault() *soap.Fault { return b.Fault_ }
func SetDefaultKmsCluster(ctx context.Context, r soap.RoundTripper, req *types.SetDefaultKmsCluster) (*types.SetDefaultKmsClusterResponse, error) {
var reqBody, resBody SetDefaultKmsClusterBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type SetDisplayTopologyBody struct {
Req *types.SetDisplayTopology `xml:"urn:vim25 SetDisplayTopology,omitempty"`
Res *types.SetDisplayTopologyResponse `xml:"SetDisplayTopologyResponse,omitempty"`
@ -14783,6 +15283,26 @@ func StandbyGuest(ctx context.Context, r soap.RoundTripper, req *types.StandbyGu
return resBody.Res, nil
}
type StartGuestNetwork_TaskBody struct {
Req *types.StartGuestNetwork_Task `xml:"urn:vim25 StartGuestNetwork_Task,omitempty"`
Res *types.StartGuestNetwork_TaskResponse `xml:"StartGuestNetwork_TaskResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *StartGuestNetwork_TaskBody) Fault() *soap.Fault { return b.Fault_ }
func StartGuestNetwork_Task(ctx context.Context, r soap.RoundTripper, req *types.StartGuestNetwork_Task) (*types.StartGuestNetwork_TaskResponse, error) {
var reqBody, resBody StartGuestNetwork_TaskBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type StartProgramInGuestBody struct {
Req *types.StartProgramInGuest `xml:"urn:vim25 StartProgramInGuest,omitempty"`
Res *types.StartProgramInGuestResponse `xml:"StartProgramInGuestResponse,omitempty"`
@ -15223,6 +15743,26 @@ func UnmapVmfsVolumeEx_Task(ctx context.Context, r soap.RoundTripper, req *types
return resBody.Res, nil
}
type UnmarkServiceProviderEntitiesBody struct {
Req *types.UnmarkServiceProviderEntities `xml:"urn:vim25 UnmarkServiceProviderEntities,omitempty"`
Res *types.UnmarkServiceProviderEntitiesResponse `xml:"UnmarkServiceProviderEntitiesResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *UnmarkServiceProviderEntitiesBody) Fault() *soap.Fault { return b.Fault_ }
func UnmarkServiceProviderEntities(ctx context.Context, r soap.RoundTripper, req *types.UnmarkServiceProviderEntities) (*types.UnmarkServiceProviderEntitiesResponse, error) {
var reqBody, resBody UnmarkServiceProviderEntitiesBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type UnmountDiskMapping_TaskBody struct {
Req *types.UnmountDiskMapping_Task `xml:"urn:vim25 UnmountDiskMapping_Task,omitempty"`
Res *types.UnmountDiskMapping_TaskResponse `xml:"UnmountDiskMapping_TaskResponse,omitempty"`
@ -15403,6 +15943,26 @@ func UnregisterHealthUpdateProvider(ctx context.Context, r soap.RoundTripper, re
return resBody.Res, nil
}
type UnregisterKmsClusterBody struct {
Req *types.UnregisterKmsCluster `xml:"urn:vim25 UnregisterKmsCluster,omitempty"`
Res *types.UnregisterKmsClusterResponse `xml:"UnregisterKmsClusterResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *UnregisterKmsClusterBody) Fault() *soap.Fault { return b.Fault_ }
func UnregisterKmsCluster(ctx context.Context, r soap.RoundTripper, req *types.UnregisterKmsCluster) (*types.UnregisterKmsClusterResponse, error) {
var reqBody, resBody UnregisterKmsClusterBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type UnregisterVMBody struct {
Req *types.UnregisterVM `xml:"urn:vim25 UnregisterVM,omitempty"`
Res *types.UnregisterVMResponse `xml:"UnregisterVMResponse,omitempty"`
@ -15443,6 +16003,26 @@ func UpdateAnswerFile_Task(ctx context.Context, r soap.RoundTripper, req *types.
return resBody.Res, nil
}
type UpdateAssignableHardwareConfigBody struct {
Req *types.UpdateAssignableHardwareConfig `xml:"urn:vim25 UpdateAssignableHardwareConfig,omitempty"`
Res *types.UpdateAssignableHardwareConfigResponse `xml:"UpdateAssignableHardwareConfigResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *UpdateAssignableHardwareConfigBody) Fault() *soap.Fault { return b.Fault_ }
func UpdateAssignableHardwareConfig(ctx context.Context, r soap.RoundTripper, req *types.UpdateAssignableHardwareConfig) (*types.UpdateAssignableHardwareConfigResponse, error) {
var reqBody, resBody UpdateAssignableHardwareConfigBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type UpdateAssignedLicenseBody struct {
Req *types.UpdateAssignedLicense `xml:"urn:vim25 UpdateAssignedLicense,omitempty"`
Res *types.UpdateAssignedLicenseResponse `xml:"UpdateAssignedLicenseResponse,omitempty"`
@ -15923,6 +16503,26 @@ func UpdateHostSubSpecification(ctx context.Context, r soap.RoundTripper, req *t
return resBody.Res, nil
}
type UpdateHppMultipathLunPolicyBody struct {
Req *types.UpdateHppMultipathLunPolicy `xml:"urn:vim25 UpdateHppMultipathLunPolicy,omitempty"`
Res *types.UpdateHppMultipathLunPolicyResponse `xml:"UpdateHppMultipathLunPolicyResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *UpdateHppMultipathLunPolicyBody) Fault() *soap.Fault { return b.Fault_ }
func UpdateHppMultipathLunPolicy(ctx context.Context, r soap.RoundTripper, req *types.UpdateHppMultipathLunPolicy) (*types.UpdateHppMultipathLunPolicyResponse, error) {
var reqBody, resBody UpdateHppMultipathLunPolicyBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type UpdateInternetScsiAdvancedOptionsBody struct {
Req *types.UpdateInternetScsiAdvancedOptions `xml:"urn:vim25 UpdateInternetScsiAdvancedOptions,omitempty"`
Res *types.UpdateInternetScsiAdvancedOptionsResponse `xml:"UpdateInternetScsiAdvancedOptionsResponse,omitempty"`
@ -16783,6 +17383,26 @@ func UpdateVStorageInfrastructureObjectPolicy_Task(ctx context.Context, r soap.R
return resBody.Res, nil
}
type UpdateVStorageObjectCrypto_TaskBody struct {
Req *types.UpdateVStorageObjectCrypto_Task `xml:"urn:vim25 UpdateVStorageObjectCrypto_Task,omitempty"`
Res *types.UpdateVStorageObjectCrypto_TaskResponse `xml:"UpdateVStorageObjectCrypto_TaskResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *UpdateVStorageObjectCrypto_TaskBody) Fault() *soap.Fault { return b.Fault_ }
func UpdateVStorageObjectCrypto_Task(ctx context.Context, r soap.RoundTripper, req *types.UpdateVStorageObjectCrypto_Task) (*types.UpdateVStorageObjectCrypto_TaskResponse, error) {
var reqBody, resBody UpdateVStorageObjectCrypto_TaskBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type UpdateVStorageObjectPolicy_TaskBody struct {
Req *types.UpdateVStorageObjectPolicy_Task `xml:"urn:vim25 UpdateVStorageObjectPolicy_Task,omitempty"`
Res *types.UpdateVStorageObjectPolicy_TaskResponse `xml:"UpdateVStorageObjectPolicy_TaskResponse,omitempty"`
@ -17243,6 +17863,26 @@ func ValidateStoragePodConfig(ctx context.Context, r soap.RoundTripper, req *typ
return resBody.Res, nil
}
type VstorageObjectVCenterQueryChangedDiskAreasBody struct {
Req *types.VstorageObjectVCenterQueryChangedDiskAreas `xml:"urn:vim25 VstorageObjectVCenterQueryChangedDiskAreas,omitempty"`
Res *types.VstorageObjectVCenterQueryChangedDiskAreasResponse `xml:"VstorageObjectVCenterQueryChangedDiskAreasResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *VstorageObjectVCenterQueryChangedDiskAreasBody) Fault() *soap.Fault { return b.Fault_ }
func VstorageObjectVCenterQueryChangedDiskAreas(ctx context.Context, r soap.RoundTripper, req *types.VstorageObjectVCenterQueryChangedDiskAreas) (*types.VstorageObjectVCenterQueryChangedDiskAreasResponse, error) {
var reqBody, resBody VstorageObjectVCenterQueryChangedDiskAreasBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type WaitForUpdatesBody struct {
Req *types.WaitForUpdates `xml:"urn:vim25 WaitForUpdates,omitempty"`
Res *types.WaitForUpdatesResponse `xml:"WaitForUpdatesResponse,omitempty"`

View File

@ -129,6 +129,7 @@ type ComputeResource struct {
Summary types.BaseComputeResourceSummary `mo:"summary"`
EnvironmentBrowser *types.ManagedObjectReference `mo:"environmentBrowser"`
ConfigurationEx types.BaseComputeResourceConfigInfo `mo:"configurationEx"`
LifecycleManaged *bool `mo:"lifecycleManaged"`
}
func (m *ComputeResource) Entity() *ManagedEntity {
@ -442,6 +443,7 @@ type Folder struct {
ChildType []string `mo:"childType"`
ChildEntity []types.ManagedObjectReference `mo:"childEntity"`
Namespace *string `mo:"namespace"`
}
func (m *Folder) Entity() *ManagedEntity {
@ -578,6 +580,21 @@ func init() {
t["HostActiveDirectoryAuthentication"] = reflect.TypeOf((*HostActiveDirectoryAuthentication)(nil)).Elem()
}
type HostAssignableHardwareManager struct {
Self types.ManagedObjectReference
Binding []types.HostAssignableHardwareBinding `mo:"binding"`
Config types.HostAssignableHardwareConfig `mo:"config"`
}
func (m HostAssignableHardwareManager) Reference() types.ManagedObjectReference {
return m.Self
}
func init() {
t["HostAssignableHardwareManager"] = reflect.TypeOf((*HostAssignableHardwareManager)(nil)).Elem()
}
type HostAuthenticationManager struct {
Self types.ManagedObjectReference
@ -1266,10 +1283,10 @@ func init() {
type Network struct {
ManagedEntity
Name string `mo:"name"`
Summary types.BaseNetworkSummary `mo:"summary"`
Host []types.ManagedObjectReference `mo:"host"`
Vm []types.ManagedObjectReference `mo:"vm"`
Name string `mo:"name"`
}
func (m *Network) Entity() *ManagedEntity {
@ -1445,6 +1462,7 @@ type ResourcePool struct {
ResourcePool []types.ManagedObjectReference `mo:"resourcePool"`
Vm []types.ManagedObjectReference `mo:"vm"`
Config types.ResourceConfigSpec `mo:"config"`
Namespace *string `mo:"namespace"`
ChildConfiguration []types.ResourceConfigSpec `mo:"childConfiguration"`
}
@ -1557,6 +1575,18 @@ func init() {
t["SimpleCommand"] = reflect.TypeOf((*SimpleCommand)(nil)).Elem()
}
type SiteInfoManager struct {
Self types.ManagedObjectReference
}
func (m SiteInfoManager) Reference() types.ManagedObjectReference {
return m.Self
}
func init() {
t["SiteInfoManager"] = reflect.TypeOf((*SiteInfoManager)(nil)).Elem()
}
type StoragePod struct {
Folder
@ -1568,6 +1598,18 @@ func init() {
t["StoragePod"] = reflect.TypeOf((*StoragePod)(nil)).Elem()
}
type StorageQueryManager struct {
Self types.ManagedObjectReference
}
func (m StorageQueryManager) Reference() types.ManagedObjectReference {
return m.Self
}
func init() {
t["StorageQueryManager"] = reflect.TypeOf((*StorageQueryManager)(nil)).Elem()
}
type StorageResourceManager struct {
Self types.ManagedObjectReference
}
@ -1616,6 +1658,18 @@ func init() {
t["TaskManager"] = reflect.TypeOf((*TaskManager)(nil)).Elem()
}
type TenantTenantManager struct {
Self types.ManagedObjectReference
}
func (m TenantTenantManager) Reference() types.ManagedObjectReference {
return m.Self
}
func init() {
t["TenantTenantManager"] = reflect.TypeOf((*TenantTenantManager)(nil)).Elem()
}
type UserDirectory struct {
Self types.ManagedObjectReference
@ -1745,6 +1799,18 @@ func init() {
t["VirtualMachineCompatibilityChecker"] = reflect.TypeOf((*VirtualMachineCompatibilityChecker)(nil)).Elem()
}
type VirtualMachineGuestCustomizationManager struct {
Self types.ManagedObjectReference
}
func (m VirtualMachineGuestCustomizationManager) Reference() types.ManagedObjectReference {
return m.Self
}
func init() {
t["VirtualMachineGuestCustomizationManager"] = reflect.TypeOf((*VirtualMachineGuestCustomizationManager)(nil)).Elem()
}
type VirtualMachineProvisioningChecker struct {
Self types.ManagedObjectReference
}

View File

@ -159,6 +159,10 @@ func NewClient(u *url.URL, insecure bool) *Client {
return &c
}
func (c *Client) DefaultTransport() *http.Transport {
return c.t
}
// NewServiceClient creates a NewClient with the given URL.Path and namespace.
func (c *Client) NewServiceClient(path string, namespace string) *Client {
vc := c.URL()
@ -173,7 +177,7 @@ func (c *Client) NewServiceClient(path string, namespace string) *Client {
client := NewClient(u, c.k)
client.Namespace = "urn:" + namespace
client.Transport.(*http.Transport).TLSClientConfig = c.Transport.(*http.Transport).TLSClientConfig
client.DefaultTransport().TLSClientConfig = c.DefaultTransport().TLSClientConfig
if cert := c.Certificate(); cert != nil {
client.SetCertificate(*cert)
}

View File

@ -200,8 +200,7 @@ func init() {
type CannotEnableVmcpForClusterReason string
const (
CannotEnableVmcpForClusterReasonAPDTimeoutDisabled = CannotEnableVmcpForClusterReason("APDTimeoutDisabled")
CannotEnableVmcpForClusterReasonIncompatibleHostVersion = CannotEnableVmcpForClusterReason("IncompatibleHostVersion")
CannotEnableVmcpForClusterReasonAPDTimeoutDisabled = CannotEnableVmcpForClusterReason("APDTimeoutDisabled")
)
func init() {
@ -239,6 +238,8 @@ const (
CannotUseNetworkReasonMismatchedNetworkPolicies = CannotUseNetworkReason("MismatchedNetworkPolicies")
CannotUseNetworkReasonMismatchedDvsVersionOrVendor = CannotUseNetworkReason("MismatchedDvsVersionOrVendor")
CannotUseNetworkReasonVMotionToUnsupportedNetworkType = CannotUseNetworkReason("VMotionToUnsupportedNetworkType")
CannotUseNetworkReasonNetworkUnderMaintenance = CannotUseNetworkReason("NetworkUnderMaintenance")
CannotUseNetworkReasonMismatchedEnsMode = CannotUseNetworkReason("MismatchedEnsMode")
)
func init() {
@ -271,6 +272,17 @@ func init() {
t["ClusterComputeResourceHCIWorkflowState"] = reflect.TypeOf((*ClusterComputeResourceHCIWorkflowState)(nil)).Elem()
}
type ClusterCryptoConfigInfoCryptoMode string
const (
ClusterCryptoConfigInfoCryptoModeOnDemand = ClusterCryptoConfigInfoCryptoMode("onDemand")
ClusterCryptoConfigInfoCryptoModeForceEnable = ClusterCryptoConfigInfoCryptoMode("forceEnable")
)
func init() {
t["ClusterCryptoConfigInfoCryptoMode"] = reflect.TypeOf((*ClusterCryptoConfigInfoCryptoMode)(nil)).Elem()
}
type ClusterDasAamNodeStateDasState string
const (
@ -509,17 +521,28 @@ func init() {
type CryptoManagerKmipCryptoKeyStatusKeyUnavailableReason string
const (
CryptoManagerKmipCryptoKeyStatusKeyUnavailableReasonKeyStateMissingInCache = CryptoManagerKmipCryptoKeyStatusKeyUnavailableReason("KeyStateMissingInCache")
CryptoManagerKmipCryptoKeyStatusKeyUnavailableReasonKeyStateClusterInvalid = CryptoManagerKmipCryptoKeyStatusKeyUnavailableReason("KeyStateClusterInvalid")
CryptoManagerKmipCryptoKeyStatusKeyUnavailableReasonKeyStateClusterUnreachable = CryptoManagerKmipCryptoKeyStatusKeyUnavailableReason("KeyStateClusterUnreachable")
CryptoManagerKmipCryptoKeyStatusKeyUnavailableReasonKeyStateMissingInKMS = CryptoManagerKmipCryptoKeyStatusKeyUnavailableReason("KeyStateMissingInKMS")
CryptoManagerKmipCryptoKeyStatusKeyUnavailableReasonKeyStateNotActiveOrEnabled = CryptoManagerKmipCryptoKeyStatusKeyUnavailableReason("KeyStateNotActiveOrEnabled")
CryptoManagerKmipCryptoKeyStatusKeyUnavailableReasonKeyStateMissingInCache = CryptoManagerKmipCryptoKeyStatusKeyUnavailableReason("KeyStateMissingInCache")
CryptoManagerKmipCryptoKeyStatusKeyUnavailableReasonKeyStateClusterInvalid = CryptoManagerKmipCryptoKeyStatusKeyUnavailableReason("KeyStateClusterInvalid")
CryptoManagerKmipCryptoKeyStatusKeyUnavailableReasonKeyStateClusterUnreachable = CryptoManagerKmipCryptoKeyStatusKeyUnavailableReason("KeyStateClusterUnreachable")
CryptoManagerKmipCryptoKeyStatusKeyUnavailableReasonKeyStateMissingInKMS = CryptoManagerKmipCryptoKeyStatusKeyUnavailableReason("KeyStateMissingInKMS")
CryptoManagerKmipCryptoKeyStatusKeyUnavailableReasonKeyStateNotActiveOrEnabled = CryptoManagerKmipCryptoKeyStatusKeyUnavailableReason("KeyStateNotActiveOrEnabled")
CryptoManagerKmipCryptoKeyStatusKeyUnavailableReasonKeyStateManagedByTrustAuthority = CryptoManagerKmipCryptoKeyStatusKeyUnavailableReason("KeyStateManagedByTrustAuthority")
)
func init() {
t["CryptoManagerKmipCryptoKeyStatusKeyUnavailableReason"] = reflect.TypeOf((*CryptoManagerKmipCryptoKeyStatusKeyUnavailableReason)(nil)).Elem()
}
type CustomizationFailedReasonCode string
const (
CustomizationFailedReasonCodeUserDefinedScriptDisabled = CustomizationFailedReasonCode("userDefinedScriptDisabled")
)
func init() {
t["CustomizationFailedReasonCode"] = reflect.TypeOf((*CustomizationFailedReasonCode)(nil)).Elem()
}
type CustomizationLicenseDataMode string
const (
@ -602,6 +625,8 @@ const (
DasConfigFaultDasConfigFaultReasonCreateConfigVvolFailed = DasConfigFaultDasConfigFaultReason("CreateConfigVvolFailed")
DasConfigFaultDasConfigFaultReasonVSanNotSupportedOnHost = DasConfigFaultDasConfigFaultReason("VSanNotSupportedOnHost")
DasConfigFaultDasConfigFaultReasonDasNetworkMisconfiguration = DasConfigFaultDasConfigFaultReason("DasNetworkMisconfiguration")
DasConfigFaultDasConfigFaultReasonSetDesiredImageSpecFailed = DasConfigFaultDasConfigFaultReason("SetDesiredImageSpecFailed")
DasConfigFaultDasConfigFaultReasonApplyHAVibsOnClusterFailed = DasConfigFaultDasConfigFaultReason("ApplyHAVibsOnClusterFailed")
)
func init() {
@ -729,6 +754,17 @@ func init() {
t["DisallowedChangeByServiceDisallowedChange"] = reflect.TypeOf((*DisallowedChangeByServiceDisallowedChange)(nil)).Elem()
}
type DistributedVirtualPortgroupBackingType string
const (
DistributedVirtualPortgroupBackingTypeStandard = DistributedVirtualPortgroupBackingType("standard")
DistributedVirtualPortgroupBackingTypeNsx = DistributedVirtualPortgroupBackingType("nsx")
)
func init() {
t["DistributedVirtualPortgroupBackingType"] = reflect.TypeOf((*DistributedVirtualPortgroupBackingType)(nil)).Elem()
}
type DistributedVirtualPortgroupMetaTagName string
const (
@ -786,6 +822,17 @@ func init() {
t["DistributedVirtualSwitchHostMemberHostComponentState"] = reflect.TypeOf((*DistributedVirtualSwitchHostMemberHostComponentState)(nil)).Elem()
}
type DistributedVirtualSwitchHostMemberTransportZoneType string
const (
DistributedVirtualSwitchHostMemberTransportZoneTypeVlan = DistributedVirtualSwitchHostMemberTransportZoneType("vlan")
DistributedVirtualSwitchHostMemberTransportZoneTypeOverlay = DistributedVirtualSwitchHostMemberTransportZoneType("overlay")
)
func init() {
t["DistributedVirtualSwitchHostMemberTransportZoneType"] = reflect.TypeOf((*DistributedVirtualSwitchHostMemberTransportZoneType)(nil)).Elem()
}
type DistributedVirtualSwitchNetworkResourceControlVersion string
const (
@ -1272,9 +1319,10 @@ func init() {
type HostCryptoState string
const (
HostCryptoStateIncapable = HostCryptoState("incapable")
HostCryptoStatePrepared = HostCryptoState("prepared")
HostCryptoStateSafe = HostCryptoState("safe")
HostCryptoStateIncapable = HostCryptoState("incapable")
HostCryptoStatePrepared = HostCryptoState("prepared")
HostCryptoStateSafe = HostCryptoState("safe")
HostCryptoStatePendingIncapable = HostCryptoState("pendingIncapable")
)
func init() {
@ -1298,6 +1346,17 @@ func init() {
t["HostDasErrorEventHostDasErrorReason"] = reflect.TypeOf((*HostDasErrorEventHostDasErrorReason)(nil)).Elem()
}
type HostDateTimeInfoProtocol string
const (
HostDateTimeInfoProtocolNtp = HostDateTimeInfoProtocol("ntp")
HostDateTimeInfoProtocolPtp = HostDateTimeInfoProtocol("ptp")
)
func init() {
t["HostDateTimeInfoProtocol"] = reflect.TypeOf((*HostDateTimeInfoProtocol)(nil)).Elem()
}
type HostDigestInfoDigestMethodType string
const (
@ -1670,6 +1729,16 @@ func init() {
t["HostLowLevelProvisioningManagerReloadTarget"] = reflect.TypeOf((*HostLowLevelProvisioningManagerReloadTarget)(nil)).Elem()
}
type HostMaintenanceSpecPurpose string
const (
HostMaintenanceSpecPurposeHostUpgrade = HostMaintenanceSpecPurpose("hostUpgrade")
)
func init() {
t["HostMaintenanceSpecPurpose"] = reflect.TypeOf((*HostMaintenanceSpecPurpose)(nil)).Elem()
}
type HostMountInfoInaccessibleReason string
const (
@ -1763,12 +1832,65 @@ func init() {
t["HostNumericSensorType"] = reflect.TypeOf((*HostNumericSensorType)(nil)).Elem()
}
type HostNvmeDiscoveryLogSubsystemType string
const (
HostNvmeDiscoveryLogSubsystemTypeDiscovery = HostNvmeDiscoveryLogSubsystemType("discovery")
HostNvmeDiscoveryLogSubsystemTypeNvm = HostNvmeDiscoveryLogSubsystemType("nvm")
)
func init() {
t["HostNvmeDiscoveryLogSubsystemType"] = reflect.TypeOf((*HostNvmeDiscoveryLogSubsystemType)(nil)).Elem()
}
type HostNvmeDiscoveryLogTransportRequirements string
const (
HostNvmeDiscoveryLogTransportRequirementsSecureChannelRequired = HostNvmeDiscoveryLogTransportRequirements("secureChannelRequired")
HostNvmeDiscoveryLogTransportRequirementsSecureChannelNotRequired = HostNvmeDiscoveryLogTransportRequirements("secureChannelNotRequired")
HostNvmeDiscoveryLogTransportRequirementsRequirementsNotSpecified = HostNvmeDiscoveryLogTransportRequirements("requirementsNotSpecified")
)
func init() {
t["HostNvmeDiscoveryLogTransportRequirements"] = reflect.TypeOf((*HostNvmeDiscoveryLogTransportRequirements)(nil)).Elem()
}
type HostNvmeTransportParametersNvmeAddressFamily string
const (
HostNvmeTransportParametersNvmeAddressFamilyIpv4 = HostNvmeTransportParametersNvmeAddressFamily("ipv4")
HostNvmeTransportParametersNvmeAddressFamilyIpv6 = HostNvmeTransportParametersNvmeAddressFamily("ipv6")
HostNvmeTransportParametersNvmeAddressFamilyInfiniBand = HostNvmeTransportParametersNvmeAddressFamily("infiniBand")
HostNvmeTransportParametersNvmeAddressFamilyFc = HostNvmeTransportParametersNvmeAddressFamily("fc")
HostNvmeTransportParametersNvmeAddressFamilyLoopback = HostNvmeTransportParametersNvmeAddressFamily("loopback")
HostNvmeTransportParametersNvmeAddressFamilyUnknown = HostNvmeTransportParametersNvmeAddressFamily("unknown")
)
func init() {
t["HostNvmeTransportParametersNvmeAddressFamily"] = reflect.TypeOf((*HostNvmeTransportParametersNvmeAddressFamily)(nil)).Elem()
}
type HostNvmeTransportType string
const (
HostNvmeTransportTypePcie = HostNvmeTransportType("pcie")
HostNvmeTransportTypeFibreChannel = HostNvmeTransportType("fibreChannel")
HostNvmeTransportTypeRdma = HostNvmeTransportType("rdma")
HostNvmeTransportTypeLoopback = HostNvmeTransportType("loopback")
HostNvmeTransportTypeUnsupported = HostNvmeTransportType("unsupported")
)
func init() {
t["HostNvmeTransportType"] = reflect.TypeOf((*HostNvmeTransportType)(nil)).Elem()
}
type HostOpaqueSwitchOpaqueSwitchState string
const (
HostOpaqueSwitchOpaqueSwitchStateUp = HostOpaqueSwitchOpaqueSwitchState("up")
HostOpaqueSwitchOpaqueSwitchStateWarning = HostOpaqueSwitchOpaqueSwitchState("warning")
HostOpaqueSwitchOpaqueSwitchStateDown = HostOpaqueSwitchOpaqueSwitchState("down")
HostOpaqueSwitchOpaqueSwitchStateUp = HostOpaqueSwitchOpaqueSwitchState("up")
HostOpaqueSwitchOpaqueSwitchStateWarning = HostOpaqueSwitchOpaqueSwitchState("warning")
HostOpaqueSwitchOpaqueSwitchStateDown = HostOpaqueSwitchOpaqueSwitchState("down")
HostOpaqueSwitchOpaqueSwitchStateMaintenance = HostOpaqueSwitchOpaqueSwitchState("maintenance")
)
func init() {
@ -1921,6 +2043,21 @@ func init() {
t["HostProtocolEndpointProtocolEndpointType"] = reflect.TypeOf((*HostProtocolEndpointProtocolEndpointType)(nil)).Elem()
}
type HostRdmaDeviceConnectionState string
const (
HostRdmaDeviceConnectionStateUnknown = HostRdmaDeviceConnectionState("unknown")
HostRdmaDeviceConnectionStateDown = HostRdmaDeviceConnectionState("down")
HostRdmaDeviceConnectionStateInit = HostRdmaDeviceConnectionState("init")
HostRdmaDeviceConnectionStateArmed = HostRdmaDeviceConnectionState("armed")
HostRdmaDeviceConnectionStateActive = HostRdmaDeviceConnectionState("active")
HostRdmaDeviceConnectionStateActiveDefer = HostRdmaDeviceConnectionState("activeDefer")
)
func init() {
t["HostRdmaDeviceConnectionState"] = reflect.TypeOf((*HostRdmaDeviceConnectionState)(nil)).Elem()
}
type HostReplayUnsupportedReason string
const (
@ -1961,6 +2098,35 @@ func init() {
t["HostServicePolicy"] = reflect.TypeOf((*HostServicePolicy)(nil)).Elem()
}
type HostSgxInfoFlcModes string
const (
HostSgxInfoFlcModesOff = HostSgxInfoFlcModes("off")
HostSgxInfoFlcModesLocked = HostSgxInfoFlcModes("locked")
HostSgxInfoFlcModesUnlocked = HostSgxInfoFlcModes("unlocked")
)
func init() {
t["HostSgxInfoFlcModes"] = reflect.TypeOf((*HostSgxInfoFlcModes)(nil)).Elem()
}
type HostSgxInfoSgxStates string
const (
HostSgxInfoSgxStatesNotPresent = HostSgxInfoSgxStates("notPresent")
HostSgxInfoSgxStatesDisabledBIOS = HostSgxInfoSgxStates("disabledBIOS")
HostSgxInfoSgxStatesDisabledCFW101 = HostSgxInfoSgxStates("disabledCFW101")
HostSgxInfoSgxStatesDisabledCPUMismatch = HostSgxInfoSgxStates("disabledCPUMismatch")
HostSgxInfoSgxStatesDisabledNoFLC = HostSgxInfoSgxStates("disabledNoFLC")
HostSgxInfoSgxStatesDisabledNUMAUnsup = HostSgxInfoSgxStates("disabledNUMAUnsup")
HostSgxInfoSgxStatesDisabledMaxEPCRegs = HostSgxInfoSgxStates("disabledMaxEPCRegs")
HostSgxInfoSgxStatesEnabled = HostSgxInfoSgxStates("enabled")
)
func init() {
t["HostSgxInfoSgxStates"] = reflect.TypeOf((*HostSgxInfoSgxStates)(nil)).Elem()
}
type HostSnmpAgentCapability string
const (
@ -1986,6 +2152,17 @@ func init() {
t["HostStandbyMode"] = reflect.TypeOf((*HostStandbyMode)(nil)).Elem()
}
type HostStorageProtocol string
const (
HostStorageProtocolScsi = HostStorageProtocol("scsi")
HostStorageProtocolNvme = HostStorageProtocol("nvme")
)
func init() {
t["HostStorageProtocol"] = reflect.TypeOf((*HostStorageProtocol)(nil)).Elem()
}
type HostSystemConnectionState string
const (
@ -2084,6 +2261,8 @@ const (
HostVirtualNicManagerNicTypeVsan = HostVirtualNicManagerNicType("vsan")
HostVirtualNicManagerNicTypeVSphereProvisioning = HostVirtualNicManagerNicType("vSphereProvisioning")
HostVirtualNicManagerNicTypeVsanWitness = HostVirtualNicManagerNicType("vsanWitness")
HostVirtualNicManagerNicTypeVSphereBackupNFC = HostVirtualNicManagerNicType("vSphereBackupNFC")
HostVirtualNicManagerNicTypePtp = HostVirtualNicManagerNicType("ptp")
)
func init() {
@ -2246,6 +2425,18 @@ func init() {
t["IscsiPortInfoPathStatus"] = reflect.TypeOf((*IscsiPortInfoPathStatus)(nil)).Elem()
}
type KmipClusterInfoKmsManagementType string
const (
KmipClusterInfoKmsManagementTypeUnknown = KmipClusterInfoKmsManagementType("unknown")
KmipClusterInfoKmsManagementTypeVCenter = KmipClusterInfoKmsManagementType("vCenter")
KmipClusterInfoKmsManagementTypeTrustAuthority = KmipClusterInfoKmsManagementType("trustAuthority")
)
func init() {
t["KmipClusterInfoKmsManagementType"] = reflect.TypeOf((*KmipClusterInfoKmsManagementType)(nil)).Elem()
}
type LatencySensitivitySensitivityLevel string
const (
@ -2717,6 +2908,7 @@ const (
PerformanceManagerUnitWatt = PerformanceManagerUnit("watt")
PerformanceManagerUnitJoule = PerformanceManagerUnit("joule")
PerformanceManagerUnitTeraBytes = PerformanceManagerUnit("teraBytes")
PerformanceManagerUnitCelsius = PerformanceManagerUnit("celsius")
)
func init() {
@ -2907,6 +3099,9 @@ const (
RecommendationReasonCodeHostExitDegradation = RecommendationReasonCode("hostExitDegradation")
RecommendationReasonCodeMaxVmsConstraint = RecommendationReasonCode("maxVmsConstraint")
RecommendationReasonCodeFtConstraints = RecommendationReasonCode("ftConstraints")
RecommendationReasonCodeVmHostAffinityPolicy = RecommendationReasonCode("vmHostAffinityPolicy")
RecommendationReasonCodeVmHostAntiAffinityPolicy = RecommendationReasonCode("vmHostAntiAffinityPolicy")
RecommendationReasonCodeVmAntiAffinityPolicy = RecommendationReasonCode("vmAntiAffinityPolicy")
)
func init() {
@ -3009,6 +3204,17 @@ func init() {
t["ReplicationVmState"] = reflect.TypeOf((*ReplicationVmState)(nil)).Elem()
}
type ResourceConfigSpecScaleSharesBehavior string
const (
ResourceConfigSpecScaleSharesBehaviorDisabled = ResourceConfigSpecScaleSharesBehavior("disabled")
ResourceConfigSpecScaleSharesBehaviorScaleCpuAndMemoryShares = ResourceConfigSpecScaleSharesBehavior("scaleCpuAndMemoryShares")
)
func init() {
t["ResourceConfigSpecScaleSharesBehavior"] = reflect.TypeOf((*ResourceConfigSpecScaleSharesBehavior)(nil)).Elem()
}
type ScheduledHardwareUpgradeInfoHardwareUpgradePolicy string
const (
@ -4108,6 +4314,7 @@ const (
VirtualMachineGuestOsIdentifierWindows9_64Guest = VirtualMachineGuestOsIdentifier("windows9_64Guest")
VirtualMachineGuestOsIdentifierWindows9Server64Guest = VirtualMachineGuestOsIdentifier("windows9Server64Guest")
VirtualMachineGuestOsIdentifierWindowsHyperVGuest = VirtualMachineGuestOsIdentifier("windowsHyperVGuest")
VirtualMachineGuestOsIdentifierWindows2019srv_64Guest = VirtualMachineGuestOsIdentifier("windows2019srv_64Guest")
VirtualMachineGuestOsIdentifierFreebsdGuest = VirtualMachineGuestOsIdentifier("freebsdGuest")
VirtualMachineGuestOsIdentifierFreebsd64Guest = VirtualMachineGuestOsIdentifier("freebsd64Guest")
VirtualMachineGuestOsIdentifierFreebsd11Guest = VirtualMachineGuestOsIdentifier("freebsd11Guest")
@ -4176,6 +4383,8 @@ const (
VirtualMachineGuestOsIdentifierDebian9_64Guest = VirtualMachineGuestOsIdentifier("debian9_64Guest")
VirtualMachineGuestOsIdentifierDebian10Guest = VirtualMachineGuestOsIdentifier("debian10Guest")
VirtualMachineGuestOsIdentifierDebian10_64Guest = VirtualMachineGuestOsIdentifier("debian10_64Guest")
VirtualMachineGuestOsIdentifierDebian11Guest = VirtualMachineGuestOsIdentifier("debian11Guest")
VirtualMachineGuestOsIdentifierDebian11_64Guest = VirtualMachineGuestOsIdentifier("debian11_64Guest")
VirtualMachineGuestOsIdentifierAsianux3Guest = VirtualMachineGuestOsIdentifier("asianux3Guest")
VirtualMachineGuestOsIdentifierAsianux3_64Guest = VirtualMachineGuestOsIdentifier("asianux3_64Guest")
VirtualMachineGuestOsIdentifierAsianux4Guest = VirtualMachineGuestOsIdentifier("asianux4Guest")
@ -4229,11 +4438,14 @@ const (
VirtualMachineGuestOsIdentifierDarwin16_64Guest = VirtualMachineGuestOsIdentifier("darwin16_64Guest")
VirtualMachineGuestOsIdentifierDarwin17_64Guest = VirtualMachineGuestOsIdentifier("darwin17_64Guest")
VirtualMachineGuestOsIdentifierDarwin18_64Guest = VirtualMachineGuestOsIdentifier("darwin18_64Guest")
VirtualMachineGuestOsIdentifierDarwin19_64Guest = VirtualMachineGuestOsIdentifier("darwin19_64Guest")
VirtualMachineGuestOsIdentifierVmkernelGuest = VirtualMachineGuestOsIdentifier("vmkernelGuest")
VirtualMachineGuestOsIdentifierVmkernel5Guest = VirtualMachineGuestOsIdentifier("vmkernel5Guest")
VirtualMachineGuestOsIdentifierVmkernel6Guest = VirtualMachineGuestOsIdentifier("vmkernel6Guest")
VirtualMachineGuestOsIdentifierVmkernel65Guest = VirtualMachineGuestOsIdentifier("vmkernel65Guest")
VirtualMachineGuestOsIdentifierVmkernel7Guest = VirtualMachineGuestOsIdentifier("vmkernel7Guest")
VirtualMachineGuestOsIdentifierAmazonlinux2_64Guest = VirtualMachineGuestOsIdentifier("amazonlinux2_64Guest")
VirtualMachineGuestOsIdentifierCrxPod1Guest = VirtualMachineGuestOsIdentifier("crxPod1Guest")
VirtualMachineGuestOsIdentifierOtherGuest = VirtualMachineGuestOsIdentifier("otherGuest")
VirtualMachineGuestOsIdentifierOtherGuest64 = VirtualMachineGuestOsIdentifier("otherGuest64")
)
@ -4425,6 +4637,17 @@ func init() {
t["VirtualMachineScsiPassthroughType"] = reflect.TypeOf((*VirtualMachineScsiPassthroughType)(nil)).Elem()
}
type VirtualMachineSgxInfoFlcModes string
const (
VirtualMachineSgxInfoFlcModesLocked = VirtualMachineSgxInfoFlcModes("locked")
VirtualMachineSgxInfoFlcModesUnlocked = VirtualMachineSgxInfoFlcModes("unlocked")
)
func init() {
t["VirtualMachineSgxInfoFlcModes"] = reflect.TypeOf((*VirtualMachineSgxInfoFlcModes)(nil)).Elem()
}
type VirtualMachineStandbyActionType string
const (
@ -4450,11 +4673,12 @@ func init() {
type VirtualMachineTicketType string
const (
VirtualMachineTicketTypeMks = VirtualMachineTicketType("mks")
VirtualMachineTicketTypeDevice = VirtualMachineTicketType("device")
VirtualMachineTicketTypeGuestControl = VirtualMachineTicketType("guestControl")
VirtualMachineTicketTypeWebmks = VirtualMachineTicketType("webmks")
VirtualMachineTicketTypeGuestIntegrity = VirtualMachineTicketType("guestIntegrity")
VirtualMachineTicketTypeMks = VirtualMachineTicketType("mks")
VirtualMachineTicketTypeDevice = VirtualMachineTicketType("device")
VirtualMachineTicketTypeGuestControl = VirtualMachineTicketType("guestControl")
VirtualMachineTicketTypeWebmks = VirtualMachineTicketType("webmks")
VirtualMachineTicketTypeGuestIntegrity = VirtualMachineTicketType("guestIntegrity")
VirtualMachineTicketTypeWebRemoteDevice = VirtualMachineTicketType("webRemoteDevice")
)
func init() {
@ -4549,11 +4773,12 @@ func init() {
type VirtualMachineUsbInfoSpeed string
const (
VirtualMachineUsbInfoSpeedLow = VirtualMachineUsbInfoSpeed("low")
VirtualMachineUsbInfoSpeedFull = VirtualMachineUsbInfoSpeed("full")
VirtualMachineUsbInfoSpeedHigh = VirtualMachineUsbInfoSpeed("high")
VirtualMachineUsbInfoSpeedSuperSpeed = VirtualMachineUsbInfoSpeed("superSpeed")
VirtualMachineUsbInfoSpeedUnknownSpeed = VirtualMachineUsbInfoSpeed("unknownSpeed")
VirtualMachineUsbInfoSpeedLow = VirtualMachineUsbInfoSpeed("low")
VirtualMachineUsbInfoSpeedFull = VirtualMachineUsbInfoSpeed("full")
VirtualMachineUsbInfoSpeedHigh = VirtualMachineUsbInfoSpeed("high")
VirtualMachineUsbInfoSpeedSuperSpeed = VirtualMachineUsbInfoSpeed("superSpeed")
VirtualMachineUsbInfoSpeedSuperSpeedPlus = VirtualMachineUsbInfoSpeed("superSpeedPlus")
VirtualMachineUsbInfoSpeedUnknownSpeed = VirtualMachineUsbInfoSpeed("unknownSpeed")
)
func init() {

View File

@ -1424,6 +1424,28 @@ func init() {
t["BaseHostMultipathInfoLogicalUnitPolicy"] = reflect.TypeOf((*HostMultipathInfoLogicalUnitPolicy)(nil)).Elem()
}
func (b *HostNvmeSpec) GetHostNvmeSpec() *HostNvmeSpec { return b }
type BaseHostNvmeSpec interface {
GetHostNvmeSpec() *HostNvmeSpec
}
func init() {
t["BaseHostNvmeSpec"] = reflect.TypeOf((*HostNvmeSpec)(nil)).Elem()
}
func (b *HostNvmeTransportParameters) GetHostNvmeTransportParameters() *HostNvmeTransportParameters {
return b
}
type BaseHostNvmeTransportParameters interface {
GetHostNvmeTransportParameters() *HostNvmeTransportParameters
}
func init() {
t["BaseHostNvmeTransportParameters"] = reflect.TypeOf((*HostNvmeTransportParameters)(nil)).Elem()
}
func (b *HostPciPassthruConfig) GetHostPciPassthruConfig() *HostPciPassthruConfig { return b }
type BaseHostPciPassthruConfig interface {
@ -1476,6 +1498,16 @@ func init() {
t["BaseHostProfilesEntityCustomizations"] = reflect.TypeOf((*HostProfilesEntityCustomizations)(nil)).Elem()
}
func (b *HostRdmaDeviceBacking) GetHostRdmaDeviceBacking() *HostRdmaDeviceBacking { return b }
type BaseHostRdmaDeviceBacking interface {
GetHostRdmaDeviceBacking() *HostRdmaDeviceBacking
}
func init() {
t["BaseHostRdmaDeviceBacking"] = reflect.TypeOf((*HostRdmaDeviceBacking)(nil)).Elem()
}
func (b *HostSriovDevicePoolInfo) GetHostSriovDevicePoolInfo() *HostSriovDevicePoolInfo { return b }
type BaseHostSriovDevicePoolInfo interface {

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
Copyright (c) 2012 The Go Authors. All rights reserved.
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are

View File

@ -16,7 +16,7 @@ import (
)
const (
// A generic XML header suitable for use with the output of Marshal.
// Header is a generic XML header suitable for use with the output of Marshal.
// This is not automatically added to any output of this package,
// it is provided as a convenience.
Header = `<?xml version="1.0" encoding="UTF-8"?>` + "\n"
@ -24,21 +24,21 @@ const (
// Marshal returns the XML encoding of v.
//
// Marshal handles an array or slice by marshalling each of the elements.
// Marshal handles a pointer by marshalling the value it points at or, if the
// pointer is nil, by writing nothing. Marshal handles an interface value by
// marshalling the value it contains or, if the interface value is nil, by
// writing nothing. Marshal handles all other data by writing one or more XML
// Marshal handles an array or slice by marshaling each of the elements.
// Marshal handles a pointer by marshaling the value it points at or, if the
// pointer is nil, by writing nothing. Marshal handles an interface value by
// marshaling the value it contains or, if the interface value is nil, by
// writing nothing. Marshal handles all other data by writing one or more XML
// elements containing the data.
//
// The name for the XML elements is taken from, in order of preference:
// - the tag on the XMLName field, if the data is a struct
// - the value of the XMLName field of type xml.Name
// - the value of the XMLName field of type Name
// - the tag of the struct field used to obtain the data
// - the name of the struct field used to obtain the data
// - the name of the marshalled type
// - the name of the marshaled type
//
// The XML element for a struct contains marshalled elements for each of the
// The XML element for a struct contains marshaled elements for each of the
// exported fields of the struct, with these exceptions:
// - the XMLName field, described above, is omitted.
// - a field with tag "-" is omitted.
@ -48,10 +48,12 @@ const (
// field name in the XML element.
// - a field with tag ",chardata" is written as character data,
// not as an XML element.
// - a field with tag ",cdata" is written as character data
// wrapped in one or more <![CDATA[ ... ]]> tags, not as an XML element.
// - a field with tag ",innerxml" is written verbatim, not subject
// to the usual marshalling procedure.
// to the usual marshaling procedure.
// - a field with tag ",comment" is written as an XML comment, not
// subject to the usual marshalling procedure. It must not contain
// subject to the usual marshaling procedure. It must not contain
// the "--" string within it.
// - a field with a tag including the "omitempty" option is omitted
// if the field value is empty. The empty values are false, 0, any
@ -59,11 +61,18 @@ const (
// string of length zero.
// - an anonymous struct field is handled as if the fields of its
// value were part of the outer struct.
// - a field implementing Marshaler is written by calling its MarshalXML
// method.
// - a field implementing encoding.TextMarshaler is written by encoding the
// result of its MarshalText method as text.
//
// If a field uses a tag "a>b>c", then the element c will be nested inside
// parent elements a and b. Fields that appear next to each other that name
// parent elements a and b. Fields that appear next to each other that name
// the same parent will be enclosed in one XML element.
//
// If the XML name for a struct field is defined by both the field tag and the
// struct's XMLName field, the names must match.
//
// See MarshalIndent for an example.
//
// Marshal will return an error if asked to marshal a channel, function, or map.
@ -173,9 +182,9 @@ func (enc *Encoder) EncodeElement(v interface{}, start StartElement) error {
}
var (
endComment = []byte("-->")
endProcInst = []byte("?>")
endDirective = []byte(">")
begComment = []byte("<!--")
endComment = []byte("-->")
endProcInst = []byte("?>")
)
// EncodeToken writes the given XML token to the stream.
@ -191,6 +200,7 @@ var (
// EncodeToken allows writing a ProcInst with Target set to "xml" only as the first token
// in the stream.
func (enc *Encoder) EncodeToken(t Token) error {
p := &enc.p
switch t := t.(type) {
case StartElement:
@ -202,7 +212,7 @@ func (enc *Encoder) EncodeToken(t Token) error {
return err
}
case CharData:
EscapeText(p, t)
escapeText(p, t, false)
case Comment:
if bytes.Contains(t, endComment) {
return fmt.Errorf("xml: EncodeToken of Comment containing --> marker")
@ -213,7 +223,7 @@ func (enc *Encoder) EncodeToken(t Token) error {
return p.cachedWriteError()
case ProcInst:
// First token to be encoded which is also a ProcInst with target of xml
// is the xml declaration. The only ProcInst where target of xml is allowed.
// is the xml declaration. The only ProcInst where target of xml is allowed.
if t.Target == "xml" && p.Buffered() != 0 {
return fmt.Errorf("xml: EncodeToken of ProcInst xml target only valid for xml declaration, first token encoded")
}
@ -231,16 +241,59 @@ func (enc *Encoder) EncodeToken(t Token) error {
}
p.WriteString("?>")
case Directive:
if bytes.Contains(t, endDirective) {
return fmt.Errorf("xml: EncodeToken of Directive containing > marker")
if !isValidDirective(t) {
return fmt.Errorf("xml: EncodeToken of Directive containing wrong < or > markers")
}
p.WriteString("<!")
p.Write(t)
p.WriteString(">")
default:
return fmt.Errorf("xml: EncodeToken of invalid token type")
}
return p.cachedWriteError()
}
// isValidDirective reports whether dir is a valid directive text,
// meaning angle brackets are matched, ignoring comments and strings.
func isValidDirective(dir Directive) bool {
var (
depth int
inquote uint8
incomment bool
)
for i, c := range dir {
switch {
case incomment:
if c == '>' {
if n := 1 + i - len(endComment); n >= 0 && bytes.Equal(dir[n:i+1], endComment) {
incomment = false
}
}
// Just ignore anything in comment
case inquote != 0:
if c == inquote {
inquote = 0
}
// Just ignore anything within quotes
case c == '\'' || c == '"':
inquote = c
case c == '<':
if i+len(begComment) < len(dir) && bytes.Equal(dir[i:i+len(begComment)], begComment) {
incomment = true
} else {
depth++
}
case c == '>':
if depth == 0 {
return false
}
depth--
}
}
return depth == 0 && inquote == 0 && !incomment
}
// Flush flushes any buffered XML to the underlying writer.
// See the EncodeToken documentation for details about when it is necessary.
func (enc *Encoder) Flush() error {
@ -274,7 +327,7 @@ func (p *printer) createAttrPrefix(url string) string {
// (The "http://www.w3.org/2000/xmlns/" name space is also predefined as "xmlns",
// but users should not be trying to use that one directly - that's our job.)
if url == xmlURL {
return "xml"
return xmlPrefix
}
// Need to define a new name space.
@ -453,7 +506,6 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat
continue
}
fv := finfo.value(val)
name := Name{Space: finfo.xmlns, Local: finfo.name}
if finfo.flags&fOmitEmpty != 0 && isEmptyValue(fv) {
continue
@ -463,69 +515,10 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat
continue
}
if fv.CanInterface() && fv.Type().Implements(marshalerAttrType) {
attr, err := fv.Interface().(MarshalerAttr).MarshalXMLAttr(name)
if err != nil {
return err
}
if attr.Name.Local != "" {
start.Attr = append(start.Attr, attr)
}
continue
}
if fv.CanAddr() {
pv := fv.Addr()
if pv.CanInterface() && pv.Type().Implements(marshalerAttrType) {
attr, err := pv.Interface().(MarshalerAttr).MarshalXMLAttr(name)
if err != nil {
return err
}
if attr.Name.Local != "" {
start.Attr = append(start.Attr, attr)
}
continue
}
}
if fv.CanInterface() && fv.Type().Implements(textMarshalerType) {
text, err := fv.Interface().(encoding.TextMarshaler).MarshalText()
if err != nil {
return err
}
start.Attr = append(start.Attr, Attr{name, string(text)})
continue
}
if fv.CanAddr() {
pv := fv.Addr()
if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
text, err := pv.Interface().(encoding.TextMarshaler).MarshalText()
if err != nil {
return err
}
start.Attr = append(start.Attr, Attr{name, string(text)})
continue
}
}
// Dereference or skip nil pointer, interface values.
switch fv.Kind() {
case reflect.Ptr, reflect.Interface:
if fv.IsNil() {
continue
}
fv = fv.Elem()
}
s, b, err := p.marshalSimple(fv.Type(), fv)
if err != nil {
name := Name{Space: finfo.xmlns, Local: finfo.name}
if err := p.marshalAttr(&start, name, fv); err != nil {
return err
}
if b != nil {
s = string(b)
}
start.Attr = append(start.Attr, Attr{name, s})
}
if err := p.writeStart(&start); err != nil {
@ -555,6 +548,90 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat
return p.cachedWriteError()
}
// marshalAttr marshals an attribute with the given name and value, adding to start.Attr.
func (p *printer) marshalAttr(start *StartElement, name Name, val reflect.Value) error {
if val.CanInterface() && val.Type().Implements(marshalerAttrType) {
attr, err := val.Interface().(MarshalerAttr).MarshalXMLAttr(name)
if err != nil {
return err
}
if attr.Name.Local != "" {
start.Attr = append(start.Attr, attr)
}
return nil
}
if val.CanAddr() {
pv := val.Addr()
if pv.CanInterface() && pv.Type().Implements(marshalerAttrType) {
attr, err := pv.Interface().(MarshalerAttr).MarshalXMLAttr(name)
if err != nil {
return err
}
if attr.Name.Local != "" {
start.Attr = append(start.Attr, attr)
}
return nil
}
}
if val.CanInterface() && val.Type().Implements(textMarshalerType) {
text, err := val.Interface().(encoding.TextMarshaler).MarshalText()
if err != nil {
return err
}
start.Attr = append(start.Attr, Attr{name, string(text)})
return nil
}
if val.CanAddr() {
pv := val.Addr()
if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
text, err := pv.Interface().(encoding.TextMarshaler).MarshalText()
if err != nil {
return err
}
start.Attr = append(start.Attr, Attr{name, string(text)})
return nil
}
}
// Dereference or skip nil pointer, interface values.
switch val.Kind() {
case reflect.Ptr, reflect.Interface:
if val.IsNil() {
return nil
}
val = val.Elem()
}
// Walk slices.
if val.Kind() == reflect.Slice && val.Type().Elem().Kind() != reflect.Uint8 {
n := val.Len()
for i := 0; i < n; i++ {
if err := p.marshalAttr(start, name, val.Index(i)); err != nil {
return err
}
}
return nil
}
if val.Type() == attrType {
start.Attr = append(start.Attr, val.Interface().(Attr))
return nil
}
s, b, err := p.marshalSimple(val.Type(), val)
if err != nil {
return err
}
if b != nil {
s = string(b)
}
start.Attr = append(start.Attr, Attr{name, s})
return nil
}
// defaultStart returns the default start element to use,
// given the reflect type, field info, and start template.
func defaultStart(typ reflect.Type, finfo *fieldInfo, startTemplate *StartElement) StartElement {
@ -716,6 +793,20 @@ func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) (string, []
var ddBytes = []byte("--")
// indirect drills into interfaces and pointers, returning the pointed-at value.
// If it encounters a nil interface or pointer, indirect returns that nil value.
// This can turn into an infinite loop given a cyclic chain,
// but it matches the Go 1 behavior.
func indirect(vf reflect.Value) reflect.Value {
for vf.Kind() == reflect.Interface || vf.Kind() == reflect.Ptr {
if vf.IsNil() {
return vf
}
vf = vf.Elem()
}
return vf
}
func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
s := parentStack{p: p}
for i := range tinfo.fields {
@ -725,22 +816,23 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
}
vf := finfo.value(val)
// Dereference or skip nil pointer, interface values.
switch vf.Kind() {
case reflect.Ptr, reflect.Interface:
if !vf.IsNil() {
vf = vf.Elem()
}
}
switch finfo.flags & fMode {
case fCharData:
case fCDATA, fCharData:
emit := EscapeText
if finfo.flags&fMode == fCDATA {
emit = emitCDATA
}
if err := s.trim(finfo.parents); err != nil {
return err
}
if vf.CanInterface() && vf.Type().Implements(textMarshalerType) {
data, err := vf.Interface().(encoding.TextMarshaler).MarshalText()
if err != nil {
return err
}
Escape(p, data)
if err := emit(p, data); err != nil {
return err
}
continue
}
if vf.CanAddr() {
@ -750,27 +842,39 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
if err != nil {
return err
}
Escape(p, data)
if err := emit(p, data); err != nil {
return err
}
continue
}
}
var scratch [64]byte
vf = indirect(vf)
switch vf.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
Escape(p, strconv.AppendInt(scratch[:0], vf.Int(), 10))
if err := emit(p, strconv.AppendInt(scratch[:0], vf.Int(), 10)); err != nil {
return err
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
Escape(p, strconv.AppendUint(scratch[:0], vf.Uint(), 10))
if err := emit(p, strconv.AppendUint(scratch[:0], vf.Uint(), 10)); err != nil {
return err
}
case reflect.Float32, reflect.Float64:
Escape(p, strconv.AppendFloat(scratch[:0], vf.Float(), 'g', -1, vf.Type().Bits()))
if err := emit(p, strconv.AppendFloat(scratch[:0], vf.Float(), 'g', -1, vf.Type().Bits())); err != nil {
return err
}
case reflect.Bool:
Escape(p, strconv.AppendBool(scratch[:0], vf.Bool()))
if err := emit(p, strconv.AppendBool(scratch[:0], vf.Bool())); err != nil {
return err
}
case reflect.String:
if err := EscapeText(p, []byte(vf.String())); err != nil {
if err := emit(p, []byte(vf.String())); err != nil {
return err
}
case reflect.Slice:
if elem, ok := vf.Interface().([]byte); ok {
if err := EscapeText(p, elem); err != nil {
if err := emit(p, elem); err != nil {
return err
}
}
@ -778,6 +882,10 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
continue
case fComment:
if err := s.trim(finfo.parents); err != nil {
return err
}
vf = indirect(vf)
k := vf.Kind()
if !(k == reflect.String || k == reflect.Slice && vf.Type().Elem().Kind() == reflect.Uint8) {
return fmt.Errorf("xml: bad type for comment field of %s", val.Type())
@ -792,14 +900,14 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
switch k {
case reflect.String:
s := vf.String()
dashDash = strings.Index(s, "--") >= 0
dashDash = strings.Contains(s, "--")
dashLast = s[len(s)-1] == '-'
if !dashDash {
p.WriteString(s)
}
case reflect.Slice:
b := vf.Bytes()
dashDash = bytes.Index(b, ddBytes) >= 0
dashDash = bytes.Contains(b, ddBytes)
dashLast = b[len(b)-1] == '-'
if !dashDash {
p.Write(b)
@ -818,6 +926,7 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
continue
case fInnerXml:
vf = indirect(vf)
iface := vf.Interface()
switch raw := iface.(type) {
case []byte:
@ -891,8 +1000,8 @@ type parentStack struct {
}
// trim updates the XML context to match the longest common prefix of the stack
// and the given parents. A closing tag will be written for every parent
// popped. Passing a zero slice or nil will close all the elements.
// and the given parents. A closing tag will be written for every parent
// popped. Passing a zero slice or nil will close all the elements.
func (s *parentStack) trim(parents []string) error {
split := 0
for ; split < len(parents) && split < len(s.stack); split++ {
@ -905,7 +1014,7 @@ func (s *parentStack) trim(parents []string) error {
return err
}
}
s.stack = parents[:split]
s.stack = s.stack[:split]
return nil
}
@ -920,7 +1029,7 @@ func (s *parentStack) push(parents []string) error {
return nil
}
// A MarshalXMLError is returned when Marshal encounters a type
// UnsupportedTypeError is returned when Marshal encounters a type
// that cannot be converted into XML.
type UnsupportedTypeError struct {
Type reflect.Type

View File

@ -1,4 +1,4 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@ -27,7 +27,7 @@ import (
// discarded.
//
// Because Unmarshal uses the reflect package, it can only assign
// to exported (upper case) fields. Unmarshal uses a case-sensitive
// to exported (upper case) fields. Unmarshal uses a case-sensitive
// comparison to match XML element names to tag values and struct
// field names.
//
@ -37,9 +37,9 @@ import (
//
// * If the struct has a field of type []byte or string with tag
// ",innerxml", Unmarshal accumulates the raw XML nested inside the
// element in that field. The rest of the rules still apply.
// element in that field. The rest of the rules still apply.
//
// * If the struct has a field named XMLName of type xml.Name,
// * If the struct has a field named XMLName of type Name,
// Unmarshal records the element name in that field.
//
// * If the XMLName field has an associated tag of the form
@ -52,6 +52,11 @@ import (
// the explicit name in a struct field tag of the form "name,attr",
// Unmarshal records the attribute value in that field.
//
// * If the XML element has an attribute not handled by the previous
// rule and the struct has a field with an associated tag containing
// ",any,attr", Unmarshal records the attribute value in the first
// such field.
//
// * If the XML element contains character data, that data is
// accumulated in the first struct field that has tag ",chardata".
// The struct field may have type []byte or string.
@ -59,7 +64,7 @@ import (
//
// * If the XML element contains comments, they are accumulated in
// the first struct field that has tag ",comment". The struct
// field may have type []byte or string. If there is no such
// field may have type []byte or string. If there is no such
// field, the comments are discarded.
//
// * If the XML element contains a sub-element whose name matches
@ -85,7 +90,12 @@ import (
// * An anonymous struct field is handled as if the fields of its
// value were part of the outer struct.
//
// * A struct field with tag "-" is never unmarshalled into.
// * A struct field with tag "-" is never unmarshaled into.
//
// If Unmarshal encounters a field type that implements the Unmarshaler
// interface, Unmarshal calls its UnmarshalXML method to produce the value from
// the XML element. Otherwise, if the value implements
// encoding.TextUnmarshaler, Unmarshal calls that value's UnmarshalText method.
//
// Unmarshal maps an XML element to a string or []byte by saving the
// concatenation of that element's character data in the string or
@ -94,34 +104,42 @@ import (
// Unmarshal maps an attribute value to a string or []byte by saving
// the value in the string or slice.
//
// Unmarshal maps an XML element to a slice by extending the length of
// the slice and mapping the element to the newly created value.
// Unmarshal maps an attribute value to an Attr by saving the attribute,
// including its name, in the Attr.
//
// Unmarshal maps an XML element or attribute value to a slice by
// extending the length of the slice and mapping the element or attribute
// to the newly created value.
//
// Unmarshal maps an XML element or attribute value to a bool by
// setting it to the boolean value represented by the string.
// setting it to the boolean value represented by the string. Whitespace
// is trimmed and ignored.
//
// Unmarshal maps an XML element or attribute value to an integer or
// floating-point field by setting the field to the result of
// interpreting the string value in decimal. There is no check for
// overflow.
// interpreting the string value in decimal. There is no check for
// overflow. Whitespace is trimmed and ignored.
//
// Unmarshal maps an XML element to an xml.Name by recording the
// element name.
// Unmarshal maps an XML element to a Name by recording the element
// name.
//
// Unmarshal maps an XML element to a pointer by setting the pointer
// to a freshly allocated value and then mapping the element to that value.
//
// A missing element or empty attribute value will be unmarshaled as a zero value.
// If the field is a slice, a zero value will be appended to the field. Otherwise, the
// field will be set to its zero value.
func Unmarshal(data []byte, v interface{}) error {
return NewDecoder(bytes.NewReader(data)).Decode(v)
}
// Decode works like xml.Unmarshal, except it reads the decoder
// Decode works like Unmarshal, except it reads the decoder
// stream to find the start element.
func (d *Decoder) Decode(v interface{}) error {
return d.DecodeElement(v, nil)
}
// DecodeElement works like xml.Unmarshal except that it takes
// DecodeElement works like Unmarshal except that it takes
// a pointer to the start XML element to decode into v.
// It is useful when a client reads some raw XML tokens itself
// but also wants to defer to Unmarshal for some elements.
@ -133,7 +151,7 @@ func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error {
return d.unmarshal(val.Elem(), start)
}
// An UnmarshalError represents an error in the unmarshalling process.
// An UnmarshalError represents an error in the unmarshaling process.
type UnmarshalError string
func (e UnmarshalError) Error() string { return string(e) }
@ -148,7 +166,7 @@ func (e UnmarshalError) Error() string { return string(e) }
// UnmarshalXML must consume exactly one XML element.
// One common implementation strategy is to unmarshal into
// a separate value with a layout matching the expected XML
// using d.DecodeElement, and then to copy the data from
// using d.DecodeElement, and then to copy the data from
// that value into the receiver.
// Another common strategy is to use d.Token to process the
// XML object one token at a time.
@ -180,19 +198,19 @@ func receiverType(val interface{}) string {
// unmarshalInterface unmarshals a single XML element into val.
// start is the opening tag of the element.
func (p *Decoder) unmarshalInterface(val Unmarshaler, start *StartElement) error {
func (d *Decoder) unmarshalInterface(val Unmarshaler, start *StartElement) error {
// Record that decoder must stop at end tag corresponding to start.
p.pushEOF()
d.pushEOF()
p.unmarshalDepth++
err := val.UnmarshalXML(p, *start)
p.unmarshalDepth--
d.unmarshalDepth++
err := val.UnmarshalXML(d, *start)
d.unmarshalDepth--
if err != nil {
p.popEOF()
d.popEOF()
return err
}
if !p.popEOF() {
if !d.popEOF() {
return fmt.Errorf("xml: %s.UnmarshalXML did not consume entire <%s> element", receiverType(val), start.Name.Local)
}
@ -202,11 +220,11 @@ func (p *Decoder) unmarshalInterface(val Unmarshaler, start *StartElement) error
// unmarshalTextInterface unmarshals a single XML element into val.
// The chardata contained in the element (but not its children)
// is passed to the text unmarshaler.
func (p *Decoder) unmarshalTextInterface(val encoding.TextUnmarshaler, start *StartElement) error {
func (d *Decoder) unmarshalTextInterface(val encoding.TextUnmarshaler) error {
var buf []byte
depth := 1
for depth > 0 {
t, err := p.Token()
t, err := d.Token()
if err != nil {
return err
}
@ -225,14 +243,13 @@ func (p *Decoder) unmarshalTextInterface(val encoding.TextUnmarshaler, start *St
}
// unmarshalAttr unmarshals a single XML attribute into val.
func (p *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error {
func (d *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error {
if val.Kind() == reflect.Ptr {
if val.IsNil() {
val.Set(reflect.New(val.Type().Elem()))
}
val = val.Elem()
}
if val.CanInterface() && val.Type().Implements(unmarshalerAttrType) {
// This is an unmarshaler with a non-pointer receiver,
// so it's likely to be incorrect, but we do what we're told.
@ -258,11 +275,30 @@ func (p *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error {
}
}
copyValue(val, []byte(attr.Value))
return nil
if val.Type().Kind() == reflect.Slice && val.Type().Elem().Kind() != reflect.Uint8 {
// Slice of element values.
// Grow slice.
n := val.Len()
val.Set(reflect.Append(val, reflect.Zero(val.Type().Elem())))
// Recur to read element into slice.
if err := d.unmarshalAttr(val.Index(n), attr); err != nil {
val.SetLen(n)
return err
}
return nil
}
if val.Type() == attrType {
val.Set(reflect.ValueOf(attr))
return nil
}
return copyValue(val, []byte(attr.Value))
}
var (
attrType = reflect.TypeOf(Attr{})
unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
unmarshalerAttrType = reflect.TypeOf((*UnmarshalerAttr)(nil)).Elem()
textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
@ -271,21 +307,9 @@ var (
// Find reflect.Type for an element's type attribute.
func (p *Decoder) typeForElement(val reflect.Value, start *StartElement) reflect.Type {
t := ""
for i, a := range start.Attr {
for _, a := range start.Attr {
if a.Name == xmlSchemaInstance || a.Name == xsiType {
t = a.Value
// HACK: ensure xsi:type is last in the list to avoid using that value for
// a "type" attribute, such as ManagedObjectReference.Type for example.
// Note that xsi:type is already the last attribute in VC/ESX responses.
// This is only an issue with govmomi simulator generated responses.
// Proper fix will require finding a few needles in this xml package haystack.
// Note: govmomi uses xmlSchemaInstance, other clients (e.g. rbvmomi) use xsiType.
// They are the same thing to XML parsers, but not to this hack here.
x := len(start.Attr) - 1
if i != x {
start.Attr[i] = start.Attr[x]
start.Attr[x] = a
}
break
}
}
@ -312,11 +336,11 @@ func (p *Decoder) typeForElement(val reflect.Value, start *StartElement) reflect
}
// Unmarshal a single XML element into val.
func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
func (d *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
// Find start element if we need it.
if start == nil {
for {
tok, err := p.Token()
tok, err := d.Token()
if err != nil {
return err
}
@ -329,10 +353,10 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
// Try to figure out type for empty interface values.
if val.Kind() == reflect.Interface && val.IsNil() {
typ := p.typeForElement(val, start)
typ := d.typeForElement(val, start)
if typ != nil {
pval := reflect.New(typ).Elem()
err := p.unmarshal(pval, start)
err := d.unmarshal(pval, start)
if err != nil {
return err
}
@ -371,24 +395,24 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
if val.CanInterface() && val.Type().Implements(unmarshalerType) {
// This is an unmarshaler with a non-pointer receiver,
// so it's likely to be incorrect, but we do what we're told.
return p.unmarshalInterface(val.Interface().(Unmarshaler), start)
return d.unmarshalInterface(val.Interface().(Unmarshaler), start)
}
if val.CanAddr() {
pv := val.Addr()
if pv.CanInterface() && pv.Type().Implements(unmarshalerType) {
return p.unmarshalInterface(pv.Interface().(Unmarshaler), start)
return d.unmarshalInterface(pv.Interface().(Unmarshaler), start)
}
}
if val.CanInterface() && val.Type().Implements(textUnmarshalerType) {
return p.unmarshalTextInterface(val.Interface().(encoding.TextUnmarshaler), start)
return d.unmarshalTextInterface(val.Interface().(encoding.TextUnmarshaler))
}
if val.CanAddr() {
pv := val.Addr()
if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
return p.unmarshalTextInterface(pv.Interface().(encoding.TextUnmarshaler), start)
return d.unmarshalTextInterface(pv.Interface().(encoding.TextUnmarshaler))
}
}
@ -414,7 +438,7 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
// TODO: For now, simply ignore the field. In the near
// future we may choose to unmarshal the start
// element on it, if not nil.
return p.Skip()
return d.Skip()
case reflect.Slice:
typ := v.Type()
@ -427,19 +451,10 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
// Slice of element values.
// Grow slice.
n := v.Len()
if n >= v.Cap() {
ncap := 2 * n
if ncap < 4 {
ncap = 4
}
new := reflect.MakeSlice(typ, n, ncap)
reflect.Copy(new, v)
v.Set(new)
}
v.SetLen(n + 1)
v.Set(reflect.Append(val, reflect.Zero(v.Type().Elem())))
// Recur to read element into slice.
if err := p.unmarshal(v.Index(n), start); err != nil {
if err := d.unmarshal(v.Index(n), start); err != nil {
v.SetLen(n)
return err
}
@ -483,23 +498,45 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
}
// Assign attributes.
// Also, determine whether we need to save character data or comments.
for _, a := range start.Attr {
handled := false
any := -1
for i := range tinfo.fields {
finfo := &tinfo.fields[i]
switch finfo.flags & fMode {
case fAttr:
strv := finfo.value(sv)
if a.Name.Local == finfo.name && (finfo.xmlns == "" || finfo.xmlns == a.Name.Space) {
needTypeAttr := (finfo.flags & fTypeAttr) != 0
// HACK: avoid using xsi:type value for a "type" attribute, such as ManagedObjectReference.Type for example.
if needTypeAttr || (a.Name != xmlSchemaInstance && a.Name != xsiType) {
if err := d.unmarshalAttr(strv, a); err != nil {
return err
}
}
handled = true
}
case fAny | fAttr:
if any == -1 {
any = i
}
}
}
if !handled && any >= 0 {
finfo := &tinfo.fields[any]
strv := finfo.value(sv)
if err := d.unmarshalAttr(strv, a); err != nil {
return err
}
}
}
// Determine whether we need to save character data or comments.
for i := range tinfo.fields {
finfo := &tinfo.fields[i]
switch finfo.flags & fMode {
case fAttr:
strv := finfo.value(sv)
// Look for attribute.
for _, a := range start.Attr {
if a.Name.Local == finfo.name && (finfo.xmlns == "" || finfo.xmlns == a.Name.Space) {
if err := p.unmarshalAttr(strv, a); err != nil {
return err
}
break
}
}
case fCharData:
case fCDATA, fCharData:
if !saveData.IsValid() {
saveData = finfo.value(sv)
}
@ -517,11 +554,11 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
case fInnerXml:
if !saveXML.IsValid() {
saveXML = finfo.value(sv)
if p.saved == nil {
if d.saved == nil {
saveXMLIndex = 0
p.saved = new(bytes.Buffer)
d.saved = new(bytes.Buffer)
} else {
saveXMLIndex = p.savedOffset()
saveXMLIndex = d.savedOffset()
}
}
}
@ -534,9 +571,9 @@ Loop:
for {
var savedOffset int
if saveXML.IsValid() {
savedOffset = p.savedOffset()
savedOffset = d.savedOffset()
}
tok, err := p.Token()
tok, err := d.Token()
if err != nil {
return err
}
@ -544,28 +581,28 @@ Loop:
case StartElement:
consumed := false
if sv.IsValid() {
consumed, err = p.unmarshalPath(tinfo, sv, nil, &t)
consumed, err = d.unmarshalPath(tinfo, sv, nil, &t)
if err != nil {
return err
}
if !consumed && saveAny.IsValid() {
consumed = true
if err := p.unmarshal(saveAny, &t); err != nil {
if err := d.unmarshal(saveAny, &t); err != nil {
return err
}
}
}
if !consumed {
if err := p.Skip(); err != nil {
if err := d.Skip(); err != nil {
return err
}
}
case EndElement:
if saveXML.IsValid() {
saveXMLData = p.saved.Bytes()[saveXMLIndex:savedOffset]
saveXMLData = d.saved.Bytes()[saveXMLIndex:savedOffset]
if saveXMLIndex == 0 {
p.saved = nil
d.saved = nil
}
}
break Loop
@ -614,7 +651,9 @@ Loop:
case reflect.String:
t.SetString(string(saveXMLData))
case reflect.Slice:
t.Set(reflect.ValueOf(saveXMLData))
if t.Type().Elem().Kind() == reflect.Uint8 {
t.Set(reflect.ValueOf(saveXMLData))
}
}
return nil
@ -637,7 +676,11 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
default:
return errors.New("cannot unmarshal into " + dst0.Type().String())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
itmp, err := strconv.ParseInt(string(src), 10, dst.Type().Bits())
if len(src) == 0 {
dst.SetInt(0)
return nil
}
itmp, err := strconv.ParseInt(strings.TrimSpace(string(src)), 10, dst.Type().Bits())
if err != nil {
return err
}
@ -663,19 +706,32 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
utmp = uint64(uint64(itmp))
}
} else {
utmp, err = strconv.ParseUint(string(src), 10, dst.Type().Bits())
if len(src) == 0 {
dst.SetUint(0)
return nil
}
utmp, err = strconv.ParseUint(strings.TrimSpace(string(src)), 10, dst.Type().Bits())
if err != nil {
return err
}
}
dst.SetUint(utmp)
case reflect.Float32, reflect.Float64:
ftmp, err := strconv.ParseFloat(string(src), dst.Type().Bits())
if len(src) == 0 {
dst.SetFloat(0)
return nil
}
ftmp, err := strconv.ParseFloat(strings.TrimSpace(string(src)), dst.Type().Bits())
if err != nil {
return err
}
dst.SetFloat(ftmp)
case reflect.Bool:
if len(src) == 0 {
dst.SetBool(false)
return nil
}
value, err := strconv.ParseBool(strings.TrimSpace(string(src)))
if err != nil {
return err
@ -698,7 +754,7 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
// The consumed result tells whether XML elements have been consumed
// from the Decoder until start's matching end element, or if it's
// still untouched because start is uninteresting for sv's fields.
func (p *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) {
func (d *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) {
recurse := false
Loop:
for i := range tinfo.fields {
@ -713,7 +769,7 @@ Loop:
}
if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local {
// It's a perfect match, unmarshal the field.
return true, p.unmarshal(finfo.value(sv), start)
return true, d.unmarshal(finfo.value(sv), start)
}
if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local {
// It's a prefix for the field. Break and recurse
@ -736,18 +792,18 @@ Loop:
// prefix. Recurse and attempt to match these.
for {
var tok Token
tok, err = p.Token()
tok, err = d.Token()
if err != nil {
return true, err
}
switch t := tok.(type) {
case StartElement:
consumed2, err := p.unmarshalPath(tinfo, sv, parents, &t)
consumed2, err := d.unmarshalPath(tinfo, sv, parents, &t)
if err != nil {
return true, err
}
if !consumed2 {
if err := p.Skip(); err != nil {
if err := d.Skip(); err != nil {
return true, err
}
}

View File

@ -1,4 +1,4 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@ -31,6 +31,7 @@ type fieldFlags int
const (
fElement fieldFlags = 1 << iota
fAttr
fCDATA
fCharData
fInnerXml
fComment
@ -39,29 +40,28 @@ const (
fOmitEmpty
fTypeAttr
fMode = fElement | fAttr | fCharData | fInnerXml | fComment | fAny
fMode = fElement | fAttr | fCDATA | fCharData | fInnerXml | fComment | fAny
xmlName = "XMLName"
)
var tinfoMap = make(map[reflect.Type]*typeInfo)
var tinfoLock sync.RWMutex
var tinfoMap sync.Map // map[reflect.Type]*typeInfo
var nameType = reflect.TypeOf(Name{})
// getTypeInfo returns the typeInfo structure with details necessary
// for marshalling and unmarshalling typ.
// for marshaling and unmarshaling typ.
func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
tinfoLock.RLock()
tinfo, ok := tinfoMap[typ]
tinfoLock.RUnlock()
if ok {
return tinfo, nil
if ti, ok := tinfoMap.Load(typ); ok {
return ti.(*typeInfo), nil
}
tinfo = &typeInfo{}
tinfo := &typeInfo{}
if typ.Kind() == reflect.Struct && typ != nameType {
n := typ.NumField()
for i := 0; i < n; i++ {
f := typ.Field(i)
if f.PkgPath != "" || f.Tag.Get("xml") == "-" {
if (f.PkgPath != "" && !f.Anonymous) || f.Tag.Get("xml") == "-" {
continue // Private field
}
@ -94,7 +94,7 @@ func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
return nil, err
}
if f.Name == "XMLName" {
if f.Name == xmlName {
tinfo.xmlname = finfo
continue
}
@ -105,10 +105,9 @@ func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
}
}
}
tinfoLock.Lock()
tinfoMap[typ] = tinfo
tinfoLock.Unlock()
return tinfo, nil
ti, _ := tinfoMap.LoadOrStore(typ, tinfo)
return ti.(*typeInfo), nil
}
// structFieldInfo builds and returns a fieldInfo for f.
@ -131,6 +130,8 @@ func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, erro
switch flag {
case "attr":
finfo.flags |= fAttr
case "cdata":
finfo.flags |= fCDATA
case "chardata":
finfo.flags |= fCharData
case "innerxml":
@ -151,8 +152,8 @@ func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, erro
switch mode := finfo.flags & fMode; mode {
case 0:
finfo.flags |= fElement
case fAttr, fCharData, fInnerXml, fComment, fAny:
if f.Name == "XMLName" || tag != "" && mode != fAttr {
case fAttr, fCDATA, fCharData, fInnerXml, fComment, fAny, fAny | fAttr:
if f.Name == xmlName || tag != "" && mode != fAttr {
valid = false
}
default:
@ -177,7 +178,7 @@ func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, erro
f.Name, typ, f.Tag.Get("xml"))
}
if f.Name == "XMLName" {
if f.Name == xmlName {
// The XMLName field records the XML element name. Don't
// process it as usual because its name should default to
// empty rather than to the field name.
@ -214,7 +215,7 @@ func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, erro
}
// If the field type has an XMLName field, the names must match
// so that the behavior of both marshalling and unmarshalling
// so that the behavior of both marshaling and unmarshaling
// is straightforward and unambiguous.
if finfo.flags&fElement != 0 {
ftyp := f.Type
@ -239,11 +240,11 @@ func lookupXMLName(typ reflect.Type) (xmlname *fieldInfo) {
}
for i, n := 0, typ.NumField(); i < n; i++ {
f := typ.Field(i)
if f.Name != "XMLName" {
if f.Name != xmlName {
continue
}
finfo, err := structFieldInfo(typ, &f)
if finfo.name != "" && err == nil {
if err == nil && finfo.name != "" {
return finfo
}
// Also consider errors as a non-existent field tag
@ -334,7 +335,7 @@ Loop:
return nil
}
// A TagPathError represents an error in the unmarshalling process
// A TagPathError represents an error in the unmarshaling process
// caused by the use of field tags with conflicting paths.
type TagPathError struct {
Struct reflect.Type

View File

@ -7,8 +7,8 @@
package xml
// References:
// Annotated XML spec: http://www.xml.com/axml/testaxml.htm
// XML name spaces: http://www.w3.org/TR/REC-xml-names/
// Annotated XML spec: https://www.xml.com/axml/testaxml.htm
// XML name spaces: https://www.w3.org/TR/REC-xml-names/
// TODO(rsc):
// Test error handling.
@ -61,6 +61,7 @@ type StartElement struct {
Attr []Attr
}
// Copy creates a new copy of StartElement.
func (e StartElement) Copy() StartElement {
attrs := make([]Attr, len(e.Attr))
copy(attrs, e.Attr)
@ -89,12 +90,14 @@ func makeCopy(b []byte) []byte {
return b1
}
// Copy creates a new copy of CharData.
func (c CharData) Copy() CharData { return CharData(makeCopy(c)) }
// A Comment represents an XML comment of the form <!--comment-->.
// The bytes do not include the <!-- and --> comment markers.
type Comment []byte
// Copy creates a new copy of Comment.
func (c Comment) Copy() Comment { return Comment(makeCopy(c)) }
// A ProcInst represents an XML processing instruction of the form <?target inst?>
@ -103,6 +106,7 @@ type ProcInst struct {
Inst []byte
}
// Copy creates a new copy of ProcInst.
func (p ProcInst) Copy() ProcInst {
p.Inst = makeCopy(p.Inst)
return p
@ -112,6 +116,7 @@ func (p ProcInst) Copy() ProcInst {
// The bytes do not include the <! and > markers.
type Directive []byte
// Copy creates a new copy of Directive.
func (d Directive) Copy() Directive { return Directive(makeCopy(d)) }
// CopyToken returns a copy of a Token.
@ -131,6 +136,23 @@ func CopyToken(t Token) Token {
return t
}
// A TokenReader is anything that can decode a stream of XML tokens, including a
// Decoder.
//
// When Token encounters an error or end-of-file condition after successfully
// reading a token, it returns the token. It may return the (non-nil) error from
// the same call or return the error (and a nil token) from a subsequent call.
// An instance of this general case is that a TokenReader returning a non-nil
// token at the end of the token stream may return either io.EOF or a nil error.
// The next Read should return nil, io.EOF.
//
// Implementations of Token are discouraged from returning a nil token with a
// nil error. Callers should treat a return of nil, nil as indicating that
// nothing happened; in particular it does not indicate EOF.
type TokenReader interface {
Token() (Token, error)
}
// A Decoder represents an XML parser reading a particular input stream.
// The parser assumes that its input is encoded in UTF-8.
type Decoder struct {
@ -146,9 +168,9 @@ type Decoder struct {
//
// Setting:
//
// d.Strict = false;
// d.AutoClose = HTMLAutoClose;
// d.Entity = HTMLEntity
// d.Strict = false
// d.AutoClose = xml.HTMLAutoClose
// d.Entity = xml.HTMLEntity
//
// creates a parser that can handle typical HTML.
//
@ -177,7 +199,7 @@ type Decoder struct {
// charset-conversion readers, converting from the provided
// non-UTF-8 charset into UTF-8. If CharsetReader is nil or
// returns an error, parsing stops with an error. One of the
// the CharsetReader's result values must be non-nil.
// CharsetReader's result values must be non-nil.
CharsetReader func(charset string, input io.Reader) (io.Reader, error)
// DefaultSpace sets the default name space used for unadorned tags,
@ -189,6 +211,7 @@ type Decoder struct {
TypeFunc func(string) (reflect.Type, bool)
r io.ByteReader
t TokenReader
buf bytes.Buffer
saved *bytes.Buffer
stk *stack
@ -200,6 +223,7 @@ type Decoder struct {
ns map[string]string
err error
line int
offset int64
unmarshalDepth int
}
@ -217,12 +241,28 @@ func NewDecoder(r io.Reader) *Decoder {
return d
}
// NewTokenDecoder creates a new XML parser using an underlying token stream.
func NewTokenDecoder(t TokenReader) *Decoder {
// Is it already a Decoder?
if d, ok := t.(*Decoder); ok {
return d
}
d := &Decoder{
ns: make(map[string]string),
t: t,
nextByte: -1,
line: 1,
Strict: true,
}
return d
}
// Token returns the next XML token in the input stream.
// At the end of the input stream, Token returns nil, io.EOF.
//
// Slices of bytes in the returned token data refer to the
// parser's internal buffer and remain valid only until the next
// call to Token. To acquire a copy of the bytes, call CopyToken
// call to Token. To acquire a copy of the bytes, call CopyToken
// or the token's Copy method.
//
// Token expands self-closing elements such as <br/>
@ -230,25 +270,30 @@ func NewDecoder(r io.Reader) *Decoder {
//
// Token guarantees that the StartElement and EndElement
// tokens it returns are properly nested and matched:
// if Token encounters an unexpected end element,
// if Token encounters an unexpected end element
// or EOF before all expected end elements,
// it will return an error.
//
// Token implements XML name spaces as described by
// http://www.w3.org/TR/REC-xml-names/. Each of the
// https://www.w3.org/TR/REC-xml-names/. Each of the
// Name structures contained in the Token has the Space
// set to the URL identifying its name space when known.
// If Token encounters an unrecognized name space prefix,
// it uses the prefix as the Space rather than report an error.
func (d *Decoder) Token() (t Token, err error) {
func (d *Decoder) Token() (Token, error) {
var t Token
var err error
if d.stk != nil && d.stk.kind == stkEOF {
err = io.EOF
return
return nil, io.EOF
}
if d.nextToken != nil {
t = d.nextToken
d.nextToken = nil
} else if t, err = d.rawToken(); err != nil {
return
if err == io.EOF && d.stk != nil && d.stk.kind != stkEOF {
err = d.syntaxError("unexpected EOF")
}
return t, err
}
if !d.Strict {
@ -264,12 +309,12 @@ func (d *Decoder) Token() (t Token, err error) {
// to the other attribute names, so process
// the translations first.
for _, a := range t1.Attr {
if a.Name.Space == "xmlns" {
if a.Name.Space == xmlnsPrefix {
v, ok := d.ns[a.Name.Local]
d.pushNs(a.Name.Local, v, ok)
d.ns[a.Name.Local] = a.Value
}
if a.Name.Space == "" && a.Name.Local == "xmlns" {
if a.Name.Space == "" && a.Name.Local == xmlnsPrefix {
// Default space for untagged names
v, ok := d.ns[""]
d.pushNs("", v, ok)
@ -291,23 +336,27 @@ func (d *Decoder) Token() (t Token, err error) {
}
t = t1
}
return
return t, err
}
const xmlURL = "http://www.w3.org/XML/1998/namespace"
const (
xmlURL = "http://www.w3.org/XML/1998/namespace"
xmlnsPrefix = "xmlns"
xmlPrefix = "xml"
)
// Apply name space translation to name n.
// The default name space (for Space=="")
// applies only to element names, not to attribute names.
func (d *Decoder) translate(n *Name, isElementName bool) {
switch {
case n.Space == "xmlns":
case n.Space == xmlnsPrefix:
return
case n.Space == "" && !isElementName:
return
case n.Space == "xml":
case n.Space == xmlPrefix:
n.Space = xmlURL
case n.Space == "" && n.Local == "xmlns":
case n.Space == "" && n.Local == xmlnsPrefix:
return
}
if v, ok := d.ns[n.Space]; ok {
@ -330,7 +379,7 @@ func (d *Decoder) switchToReader(r io.Reader) {
}
// Parsing state - stack holds old name space translations
// and the current set of open elements. The translations to pop when
// and the current set of open elements. The translations to pop when
// ending a given tag are *below* it on the stack, which is
// more work but forced on us by XML.
type stack struct {
@ -501,6 +550,9 @@ func (d *Decoder) RawToken() (Token, error) {
}
func (d *Decoder) rawToken() (Token, error) {
if d.t != nil {
return d.t.Token()
}
if d.err != nil {
return nil, d.err
}
@ -552,7 +604,6 @@ func (d *Decoder) rawToken() (Token, error) {
case '?':
// <?: Processing instruction.
// TODO(rsc): Should parse the <?xml declaration to make sure the version is 1.0.
var target string
if target, ok = d.name(); !ok {
if d.err == nil {
@ -577,8 +628,14 @@ func (d *Decoder) rawToken() (Token, error) {
data = data[0 : len(data)-2] // chop ?>
if target == "xml" {
enc := procInstEncoding(string(data))
if enc != "" && enc != "utf-8" && enc != "UTF-8" {
content := string(data)
ver := procInst("version", content)
if ver != "" && ver != "1.0" {
d.err = fmt.Errorf("xml: unsupported version %q; only version 1.0 is supported", ver)
return nil, d.err
}
enc := procInst("encoding", content)
if enc != "" && enc != "utf-8" && enc != "UTF-8" && !strings.EqualFold(enc, "utf-8") {
if d.CharsetReader == nil {
d.err = fmt.Errorf("xml: encoding %q declared but Decoder.CharsetReader is nil", enc)
return nil, d.err
@ -619,7 +676,12 @@ func (d *Decoder) rawToken() (Token, error) {
return nil, d.err
}
d.buf.WriteByte(b)
if b0 == '-' && b1 == '-' && b == '>' {
if b0 == '-' && b1 == '-' {
if b != '>' {
d.err = d.syntaxError(
`invalid sequence "--" not allowed in comments`)
return nil, d.err
}
break
}
b0, b1 = b1, b
@ -726,7 +788,7 @@ func (d *Decoder) rawToken() (Token, error) {
return nil, d.err
}
attr = make([]Attr, 0, 4)
attr = []Attr{}
for {
d.space()
if b, ok = d.mustgetc(); !ok {
@ -748,14 +810,7 @@ func (d *Decoder) rawToken() (Token, error) {
}
d.ungetc(b)
n := len(attr)
if n >= cap(attr) {
nattr := make([]Attr, n, 2*cap(attr))
copy(nattr, attr)
attr = nattr
}
attr = attr[0 : n+1]
a := &attr[n]
a := Attr{}
if a.Name, ok = d.nsname(); !ok {
if d.err == nil {
d.err = d.syntaxError("expected attribute name in element")
@ -770,10 +825,9 @@ func (d *Decoder) rawToken() (Token, error) {
if d.Strict {
d.err = d.syntaxError("attribute name without = in element")
return nil, d.err
} else {
d.ungetc(b)
a.Value = a.Name.Local
}
d.ungetc(b)
a.Value = a.Name.Local
} else {
d.space()
data := d.attrval()
@ -782,6 +836,7 @@ func (d *Decoder) rawToken() (Token, error) {
}
a.Value = string(data)
}
attr = append(attr, a)
}
if empty {
d.needClose = true
@ -812,7 +867,7 @@ func (d *Decoder) attrval() []byte {
if !ok {
return nil
}
// http://www.w3.org/TR/REC-html40/intro/sgmltut.html#h-3.2.2
// https://www.w3.org/TR/REC-html40/intro/sgmltut.html#h-3.2.2
if 'a' <= b && b <= 'z' || 'A' <= b && b <= 'Z' ||
'0' <= b && b <= '9' || b == '_' || b == ':' || b == '-' {
d.buf.WriteByte(b)
@ -863,9 +918,17 @@ func (d *Decoder) getc() (b byte, ok bool) {
if b == '\n' {
d.line++
}
d.offset++
return b, true
}
// InputOffset returns the input stream byte offset of the current decoder position.
// The offset gives the location of the end of the most recently returned token
// and the beginning of the next token.
func (d *Decoder) InputOffset() int64 {
return d.offset
}
// Return saved offset.
// If we did ungetc (nextByte >= 0), have to back up one.
func (d *Decoder) savedOffset() int {
@ -895,6 +958,7 @@ func (d *Decoder) ungetc(b byte) {
d.line--
}
d.nextByte = int(b)
d.offset--
}
var entity = map[string]int{
@ -1002,7 +1066,6 @@ Input:
if d.err != nil {
return nil
}
ok = false
}
if b, ok = d.mustgetc(); !ok {
return nil
@ -1075,13 +1138,13 @@ Input:
}
// Decide whether the given rune is in the XML Character Range, per
// the Char production of http://www.xml.com/axml/testaxml.htm,
// the Char production of https://www.xml.com/axml/testaxml.htm,
// Section 2.2 Characters.
func isInCharacterRange(r rune) (inrange bool) {
return r == 0x09 ||
r == 0x0A ||
r == 0x0D ||
r >= 0x20 && r <= 0xDF77 ||
r >= 0x20 && r <= 0xD7FF ||
r >= 0xE000 && r <= 0xFFFD ||
r >= 0x10000 && r <= 0x10FFFF
}
@ -1113,12 +1176,12 @@ func (d *Decoder) name() (s string, ok bool) {
}
// Now we check the characters.
s = d.buf.String()
if !isName([]byte(s)) {
d.err = d.syntaxError("invalid XML name: " + s)
b := d.buf.Bytes()
if !isName(b) {
d.err = d.syntaxError("invalid XML name: " + string(b))
return "", false
}
return s, true
return string(b), true
}
// Read a name and append its bytes to d.buf.
@ -1204,8 +1267,8 @@ func isNameString(s string) bool {
}
// These tables were generated by cut and paste from Appendix B of
// the XML spec at http://www.xml.com/axml/testaxml.htm
// and then reformatting. First corresponds to (Letter | '_' | ':')
// the XML spec at https://www.xml.com/axml/testaxml.htm
// and then reformatting. First corresponds to (Letter | '_' | ':')
// and second corresponds to NameChar.
var first = &unicode.RangeTable{
@ -1522,7 +1585,9 @@ var second = &unicode.RangeTable{
// HTMLEntity is an entity map containing translations for the
// standard HTML entity characters.
var HTMLEntity = htmlEntity
//
// See the Decoder.Strict and Decoder.Entity fields' documentation.
var HTMLEntity map[string]string = htmlEntity
var htmlEntity = map[string]string{
/*
@ -1789,7 +1854,9 @@ var htmlEntity = map[string]string{
// HTMLAutoClose is the set of HTML elements that
// should be considered to close automatically.
var HTMLAutoClose = htmlAutoClose
//
// See the Decoder.Strict and Decoder.Entity fields' documentation.
var HTMLAutoClose []string = htmlAutoClose
var htmlAutoClose = []string{
/*
@ -1812,20 +1879,27 @@ var htmlAutoClose = []string{
}
var (
esc_quot = []byte("&#34;") // shorter than "&quot;"
esc_apos = []byte("&#39;") // shorter than "&apos;"
esc_amp = []byte("&amp;")
esc_lt = []byte("&lt;")
esc_gt = []byte("&gt;")
esc_tab = []byte("&#x9;")
esc_nl = []byte("&#xA;")
esc_cr = []byte("&#xD;")
esc_fffd = []byte("\uFFFD") // Unicode replacement character
escQuot = []byte("&#34;") // shorter than "&quot;"
escApos = []byte("&#39;") // shorter than "&apos;"
escAmp = []byte("&amp;")
escLT = []byte("&lt;")
escGT = []byte("&gt;")
escTab = []byte("&#x9;")
escNL = []byte("&#xA;")
escCR = []byte("&#xD;")
escFFFD = []byte("\uFFFD") // Unicode replacement character
)
// EscapeText writes to w the properly escaped XML equivalent
// of the plain text data s.
func EscapeText(w io.Writer, s []byte) error {
return escapeText(w, s, true)
}
// escapeText writes to w the properly escaped XML equivalent
// of the plain text data s. If escapeNewline is true, newline
// characters will be escaped.
func escapeText(w io.Writer, s []byte, escapeNewline bool) error {
var esc []byte
last := 0
for i := 0; i < len(s); {
@ -1833,24 +1907,27 @@ func EscapeText(w io.Writer, s []byte) error {
i += width
switch r {
case '"':
esc = esc_quot
esc = escQuot
case '\'':
esc = esc_apos
esc = escApos
case '&':
esc = esc_amp
esc = escAmp
case '<':
esc = esc_lt
esc = escLT
case '>':
esc = esc_gt
esc = escGT
case '\t':
esc = esc_tab
esc = escTab
case '\n':
esc = esc_nl
if !escapeNewline {
continue
}
esc = escNL
case '\r':
esc = esc_cr
esc = escCR
default:
if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
esc = esc_fffd
esc = escFFFD
break
}
continue
@ -1863,10 +1940,8 @@ func EscapeText(w io.Writer, s []byte) error {
}
last = i
}
if _, err := w.Write(s[last:]); err != nil {
return err
}
return nil
_, err := w.Write(s[last:])
return err
}
// EscapeString writes to p the properly escaped XML equivalent
@ -1879,24 +1954,24 @@ func (p *printer) EscapeString(s string) {
i += width
switch r {
case '"':
esc = esc_quot
esc = escQuot
case '\'':
esc = esc_apos
esc = escApos
case '&':
esc = esc_amp
esc = escAmp
case '<':
esc = esc_lt
esc = escLT
case '>':
esc = esc_gt
esc = escGT
case '\t':
esc = esc_tab
esc = escTab
case '\n':
esc = esc_nl
esc = escNL
case '\r':
esc = esc_cr
esc = escCR
default:
if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
esc = esc_fffd
esc = escFFFD
break
}
continue
@ -1915,16 +1990,55 @@ func Escape(w io.Writer, s []byte) {
EscapeText(w, s)
}
// procInstEncoding parses the `encoding="..."` or `encoding='...'`
var (
cdataStart = []byte("<![CDATA[")
cdataEnd = []byte("]]>")
cdataEscape = []byte("]]]]><![CDATA[>")
)
// emitCDATA writes to w the CDATA-wrapped plain text data s.
// It escapes CDATA directives nested in s.
func emitCDATA(w io.Writer, s []byte) error {
if len(s) == 0 {
return nil
}
if _, err := w.Write(cdataStart); err != nil {
return err
}
for {
i := bytes.Index(s, cdataEnd)
if i >= 0 && i+len(cdataEnd) <= len(s) {
// Found a nested CDATA directive end.
if _, err := w.Write(s[:i]); err != nil {
return err
}
if _, err := w.Write(cdataEscape); err != nil {
return err
}
i += len(cdataEnd)
} else {
if _, err := w.Write(s); err != nil {
return err
}
break
}
s = s[i:]
}
_, err := w.Write(cdataEnd)
return err
}
// procInst parses the `param="..."` or `param='...'`
// value out of the provided string, returning "" if not found.
func procInstEncoding(s string) string {
func procInst(param, s string) string {
// TODO: this parsing is somewhat lame and not exact.
// It works for all actual cases, though.
idx := strings.Index(s, "encoding=")
param = param + "="
idx := strings.Index(s, param)
if idx == -1 {
return ""
}
v := s[idx+len("encoding="):]
v := s[idx+len(param):]
if v == "" {
return ""
}

3
vendor/modules.txt vendored
View File

@ -559,7 +559,7 @@ github.com/ulikunitz/xz
github.com/ulikunitz/xz/internal/hash
github.com/ulikunitz/xz/internal/xlog
github.com/ulikunitz/xz/lzma
# github.com/vmware/govmomi v0.22.2
# github.com/vmware/govmomi v0.23.1
github.com/vmware/govmomi
github.com/vmware/govmomi/find
github.com/vmware/govmomi/list
@ -568,6 +568,7 @@ github.com/vmware/govmomi/object
github.com/vmware/govmomi/ovf
github.com/vmware/govmomi/property
github.com/vmware/govmomi/session
github.com/vmware/govmomi/session/keepalive
github.com/vmware/govmomi/task
github.com/vmware/govmomi/vapi/internal
github.com/vmware/govmomi/vapi/library

View File

@ -216,7 +216,7 @@ iso_paths = [
@include 'builder/vsphere/common/ContentLibraryDestinationConfig-not-required.mdx'
Minimal example of usage:
Minimal example of usage to import a VM template:
<Tabs>
<Tab heading="JSON">
@ -239,6 +239,31 @@ Minimal example of usage:
</Tab>
</Tabs>
Minimal example of usage to import a OVF template:
<Tabs>
<Tab heading="JSON">
```json
"content_library_destination" : {
"library": "Packer Library Test",
"ovf": true
}
```
</Tab>
<Tab heading="HCL2">
```hcl
content_library_destination {
library = "Packer Library Test"
ovf = true
}
```
</Tab>
</Tabs>
### Extra Configuration Parameters
@include 'builder/vsphere/common/ConfigParamsConfig-not-required.mdx'

View File

@ -8,8 +8,8 @@
- `export` (\*common.ExportConfig) - Configuration for exporting VM to an ovf file.
The VM will not be exported if no [Export Configuration](#export-configuration) is specified.
- `content_library_destination` (\*common.ContentLibraryDestinationConfig) - Configuration for importing the VM template to a Content Library.
The VM template will not be imported if no [Content Library Import Configuration](#content-library-import-configuration) is specified.
- `content_library_destination` (\*common.ContentLibraryDestinationConfig) - Configuration for importing a VM template or OVF template to a Content Library.
The template will not be imported if no [Content Library Import Configuration](#content-library-import-configuration) is specified.
The import doesn't work if [convert_to_template](#convert_to_template) is set to true.
- `customize` (\*CustomizeConfig) - Customize the cloned VM to configure host, network, or licensing settings. See the [customization options](#customization).

View File

@ -1,24 +1,35 @@
<!-- Code generated from the comments of the ContentLibraryDestinationConfig struct in builder/vsphere/common/step_import_to_content_library.go; DO NOT EDIT MANUALLY -->
- `library` (string) - Name of the library in which the new library item containing the VM template should be created.
- `library` (string) - Name of the library in which the new library item containing the template should be created/updated.
The Content Library should be of type Local to allow deploying virtual machines.
- `name` (string) - Name of the library item that will be created. The name of the item should be different from [vm_name](#vm_name).
Defaults to [vm_name](#vm_name) + timestamp.
- `name` (string) - Name of the library item that will be created or updated.
For VM templates, the name of the item should be different from [vm_name](#vm_name) and
the default is [vm_name](#vm_name) + timestamp when not set. VM templates will be always imported to a new library item.
For OVF templates, the name defaults to [vm_name](#vm_name) when not set, and if an item with the same name already
exists it will be then updated with the new OVF template, otherwise a new item will be created.
~> **Note**: It's not possible to update existing library items with a new VM template. If updating an existing library
item is necessary, use an OVF template instead by setting the [ovf](#ovf) option as `true`.
- `description` (string) - Description of the library item that will be created. Defaults to "Packer imported [vm_name](#vm_name) VM template".
- `description` (string) - Description of the library item that will be created.
This option is not used when importing OVF templates.
Defaults to "Packer imported [vm_name](#vm_name) VM template".
- `cluster` (string) - Cluster onto which the virtual machine template should be placed.
If cluster and resource_pool are both specified, resource_pool must belong to cluster.
If cluster and host are both specified, host must be a member of cluster.
This option is not used when importing OVF templates.
Defaults to [cluster](#cluster).
- `folder` (string) - Virtual machine folder into which the virtual machine template should be placed.
This option is not used when importing OVF templates.
Defaults to the same folder as the source virtual machine.
- `host` (string) - Host onto which the virtual machine template should be placed.
If host and resource_pool are both specified, resource_pool must belong to host.
If host and cluster are both specified, host must be a member of cluster.
This option is not used when importing OVF templates.
Defaults to [host](#host).
- `resource_pool` (string) - Resource pool into which the virtual machine template should be placed.
@ -26,6 +37,10 @@
the system will attempt to choose a suitable resource pool for the virtual machine template.
- `datastore` (string) - The datastore for the virtual machine template's configuration and log files.
This option is not used when importing OVF templates.
Defaults to the storage backing associated with the library specified by library.
- `destroy` (bool) - If set to true, the VM will be destroyed after deploying the template to the Content Library. Defaults to `false`.
- `destroy` (bool) - If set to true, the VM will be destroyed after deploying the template to the Content Library.
Defaults to `false`.
- `ovf` (bool) - When set to true, Packer will import and OVF template to the content library item. Defaults to `false`.

View File

@ -1,4 +1,5 @@
<!-- Code generated from the comments of the ContentLibraryDestinationConfig struct in builder/vsphere/common/step_import_to_content_library.go; DO NOT EDIT MANUALLY -->
With this configuration Packer creates a library item in a content library whose content is a virtual machine template created from the just built VM.
The virtual machine template is stored in a newly created library item.
With this configuration Packer creates a library item in a content library whose content is a VM template
or an OVF template created from the just built VM.
The template is stored in a existing or newly created library item.