mirror of
https://github.com/openshift/installer.git
synced 2026-02-05 06:46:36 +01:00
vshpere: download ova into cache
This change caches a copy of the vmware ova specified in rhcos.json in preperation to upload the OVA into a Template. Add vsphere terraform import ova - Using terraform-provider-vsphere as an example and source add a resource `vsphereprivate_import_ova`. - Modify existing terraform to use the above resource - Modify vsphere tfvars Co-authored-by: Jeremiah Stuever <jstuever@redhat.com>
This commit is contained in:
committed by
Joseph Callen
parent
0a22450774
commit
ff35ac0372
@@ -5,6 +5,13 @@ provider "vsphere" {
|
||||
allow_unverified_ssl = false
|
||||
}
|
||||
|
||||
provider "vsphereprivate" {
|
||||
user = var.vsphere_username
|
||||
password = var.vsphere_password
|
||||
vsphere_server = var.vsphere_url
|
||||
allow_unverified_ssl = false
|
||||
}
|
||||
|
||||
data "vsphere_datacenter" "datacenter" {
|
||||
name = var.vsphere_datacenter
|
||||
}
|
||||
@@ -25,10 +32,20 @@ data "vsphere_network" "network" {
|
||||
}
|
||||
|
||||
data "vsphere_virtual_machine" "template" {
|
||||
name = var.vsphere_template
|
||||
name = vsphereprivate_import_ova.import.name
|
||||
datacenter_id = data.vsphere_datacenter.datacenter.id
|
||||
}
|
||||
|
||||
resource "vsphereprivate_import_ova" "import" {
|
||||
name = var.vsphere_template
|
||||
filename = var.vsphere_ova_filepath
|
||||
cluster = var.vsphere_cluster
|
||||
datacenter = var.vsphere_datacenter
|
||||
datastore = var.vsphere_datastore
|
||||
network = var.vsphere_network
|
||||
folder = vsphere_folder.folder.path
|
||||
}
|
||||
|
||||
resource "vsphere_tag_category" "category" {
|
||||
name = "openshift-${var.cluster_id}"
|
||||
description = "Added by openshift-install do not remove"
|
||||
|
||||
@@ -22,7 +22,7 @@ data "ignition_config" "ign" {
|
||||
}
|
||||
|
||||
files = [
|
||||
data.ignition_file.hostname[count.index].id
|
||||
data.ignition_file.hostname[count.index].rendered
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,11 @@ variable "vsphere_datastore" {
|
||||
description = "This is the name of the vSphere data store."
|
||||
}
|
||||
|
||||
variable "vsphere_ova_filepath" {
|
||||
type = string
|
||||
description = "This is the filepath to the ova file that will be imported into vSphere."
|
||||
}
|
||||
|
||||
variable "vsphere_template" {
|
||||
type = string
|
||||
description = "This is the name of the VM template to clone."
|
||||
@@ -65,3 +70,4 @@ variable "vsphere_control_plane_num_cpus" {
|
||||
variable "vsphere_control_plane_cores_per_socket" {
|
||||
type = number
|
||||
}
|
||||
|
||||
|
||||
4
go.mod
4
go.mod
@@ -101,7 +101,7 @@ require (
|
||||
github.com/terraform-providers/terraform-provider-vsphere v1.16.2
|
||||
github.com/ulikunitz/xz v0.5.6
|
||||
github.com/vincent-petithory/dataurl v0.0.0-20191104211930-d1553a71de50
|
||||
github.com/vmware/govmomi v0.22.1
|
||||
github.com/vmware/govmomi v0.22.2
|
||||
go.uber.org/atomic v1.5.1 // indirect
|
||||
go.uber.org/multierr v1.4.0 // indirect
|
||||
go.uber.org/zap v1.13.0 // indirect
|
||||
@@ -116,7 +116,7 @@ require (
|
||||
gopkg.in/ini.v1 v1.51.0
|
||||
gopkg.in/yaml.v2 v2.2.8
|
||||
k8s.io/api v0.17.2
|
||||
k8s.io/apimachinery v0.17.2
|
||||
k8s.io/apimachinery v0.17.3
|
||||
k8s.io/client-go v12.0.0+incompatible
|
||||
k8s.io/klog v1.0.0
|
||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc
|
||||
|
||||
2
go.sum
2
go.sum
@@ -2179,6 +2179,8 @@ github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59b
|
||||
github.com/vmware/govmomi v0.21.0/go.mod h1:zbnFoBQ9GIjs2RVETy8CNEpb+L+Lwkjs3XZUL0B3/m0=
|
||||
github.com/vmware/govmomi v0.22.1 h1:ZIEYmBdAS2i+s7RctapqdHfbeGiUcL8LRN05uS4TfPc=
|
||||
github.com/vmware/govmomi v0.22.1/go.mod h1:Y+Wq4lst78L85Ge/F8+ORXIWiKYqaro1vhAulACy9Lc=
|
||||
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/vmw-guestinfo v0.0.0-20170707015358-25eff159a728/go.mod h1:x9oS4Wk2s2u4tS29nEaDLdzvuHdB19CvSGJjPgkZJNk=
|
||||
github.com/weppos/publicsuffix-go v0.4.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k=
|
||||
github.com/xanzy/ssh-agent v0.2.0/go.mod h1:0NyE30eGUDliuLEHJgYte/zncp2zdTStcOnWhgSqHD8=
|
||||
|
||||
@@ -447,6 +447,7 @@ func (t *TerraformVariables) Generate(parents asset.Parents) error {
|
||||
Username: installConfig.Config.VSphere.Username,
|
||||
Password: installConfig.Config.VSphere.Password,
|
||||
Cluster: installConfig.Config.VSphere.Cluster,
|
||||
ImageURL: string(*rhcosImage),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
@@ -325,8 +325,9 @@ func (m *Master) Generate(dependencies asset.Parents) error {
|
||||
mpool.Set(ic.Platform.VSphere.DefaultMachinePlatform)
|
||||
mpool.Set(pool.Platform.VSphere)
|
||||
pool.Platform.VSphere = &mpool
|
||||
templateName := clusterID.InfraID + "-rhcos"
|
||||
|
||||
machines, err = vsphere.Machines(clusterID.InfraID, ic, pool, string(*rhcosImage), "master", "master-user-data")
|
||||
machines, err = vsphere.Machines(clusterID.InfraID, ic, pool, templateName, "master", "master-user-data")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create master machine objects")
|
||||
}
|
||||
|
||||
@@ -322,8 +322,9 @@ func (w *Worker) Generate(dependencies asset.Parents) error {
|
||||
mpool.Set(ic.Platform.VSphere.DefaultMachinePlatform)
|
||||
mpool.Set(pool.Platform.VSphere)
|
||||
pool.Platform.VSphere = &mpool
|
||||
templateName := clusterID.InfraID + "-rhcos"
|
||||
|
||||
sets, err := vsphere.MachineSets(clusterID.InfraID, ic, &pool, string(*rhcosImage), "worker", "worker-user-data")
|
||||
sets, err := vsphere.MachineSets(clusterID.InfraID, ic, &pool, templateName, "worker", "worker-user-data")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create worker machine objects")
|
||||
}
|
||||
|
||||
@@ -101,8 +101,15 @@ func osImage(config *types.InstallConfig) (string, error) {
|
||||
// because this contains the necessary ironic config drive
|
||||
// ignition support, which isn't enabled in the UPI BM images
|
||||
osimage, err = rhcos.OpenStack(ctx, arch)
|
||||
case none.Name, vsphere.Name:
|
||||
case vsphere.Name:
|
||||
// Check for RHCOS image URL override
|
||||
if config.Platform.VSphere.ClusterOSImage != "" {
|
||||
osimage = config.Platform.VSphere.ClusterOSImage
|
||||
break
|
||||
}
|
||||
|
||||
osimage, err = rhcos.VMware(ctx, arch)
|
||||
case none.Name:
|
||||
default:
|
||||
return "", errors.New("invalid Platform")
|
||||
}
|
||||
|
||||
@@ -41,6 +41,10 @@ type metadata struct {
|
||||
SHA256 string `json:"sha256"`
|
||||
UncompressedSHA256 string `json:"uncompressed-sha256"`
|
||||
} `json:"openstack"`
|
||||
VMware struct {
|
||||
Path string `json:"path"`
|
||||
SHA256 string `json:"sha256"`
|
||||
} `json:"vmware"`
|
||||
} `json:"images"`
|
||||
OSTreeVersion string `json:"ostree-version"`
|
||||
}
|
||||
|
||||
43
pkg/rhcos/vmware.go
Normal file
43
pkg/rhcos/vmware.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package rhcos
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/openshift/installer/pkg/types"
|
||||
)
|
||||
|
||||
// VMware fetches the URL of the Red Hat Enterprise Linux CoreOS release.
|
||||
func VMware(ctx context.Context, arch types.Architecture) (string, error) {
|
||||
meta, err := fetchRHCOSBuild(ctx, arch)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to fetch RHCOS metadata")
|
||||
}
|
||||
|
||||
base, err := url.Parse(meta.BaseURI)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
image, err := url.Parse(meta.Images.VMware.Path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
baseURL := base.ResolveReference(image).String()
|
||||
|
||||
// Attach sha256 checksum to the URL. Always provide the
|
||||
// uncompressed SHA256; the cache will take care of
|
||||
// uncompressing before checksumming.
|
||||
baseURL += "?sha256=" + meta.Images.VMware.SHA256
|
||||
|
||||
// Check that we have generated a valid URL
|
||||
_, err = url.ParseRequestURI(baseURL)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return baseURL, nil
|
||||
}
|
||||
14
pkg/terraform/exec/plugins/vsphereprivate.go
Normal file
14
pkg/terraform/exec/plugins/vsphereprivate.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/plugin"
|
||||
"github.com/openshift/installer/pkg/terraform/exec/plugins/vsphereprivate"
|
||||
)
|
||||
|
||||
func init() {
|
||||
vspherePrivateProvider := func() {
|
||||
plugin.Serve(&plugin.ServeOpts{
|
||||
ProviderFunc: vsphereprivate.Provider})
|
||||
}
|
||||
KnownPlugins["terraform-provider-vsphereprivate"] = vspherePrivateProvider
|
||||
}
|
||||
67
pkg/terraform/exec/plugins/vsphereprivate/config.go
Normal file
67
pkg/terraform/exec/plugins/vsphereprivate/config.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package vsphereprivate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
||||
"github.com/terraform-providers/terraform-provider-vsphere/vsphere"
|
||||
"github.com/vmware/govmomi"
|
||||
)
|
||||
|
||||
// VSphereClient - The VIM/govmomi client.
|
||||
type VSphereClient struct {
|
||||
vimClient *govmomi.Client
|
||||
}
|
||||
|
||||
// ConfigWrapper - wrapping the terraform-provider-vsphere Config struct
|
||||
type ConfigWrapper struct {
|
||||
config *vsphere.Config
|
||||
}
|
||||
|
||||
// NewConfig function
|
||||
func NewConfig(d *schema.ResourceData) (*ConfigWrapper, error) {
|
||||
config, err := vsphere.NewConfig(d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ConfigWrapper{config}, nil
|
||||
}
|
||||
|
||||
// vimURL returns a URL to pass to the VIM SOAP client.
|
||||
func (cw *ConfigWrapper) vimURL() (*url.URL, error) {
|
||||
u, err := url.Parse("https://" + cw.config.VSphereServer + "/sdk")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parse url: %s", err)
|
||||
}
|
||||
|
||||
u.User = url.UserPassword(cw.config.User, cw.config.Password)
|
||||
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// Client returns a new client for accessing VMWare vSphere.
|
||||
func (cw *ConfigWrapper) Client() (*VSphereClient, error) {
|
||||
client := new(VSphereClient)
|
||||
|
||||
u, err := cw.vimURL()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error generating SOAP endpoint url: %s", err)
|
||||
}
|
||||
|
||||
err = cw.config.EnableDebug()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error setting up client debug: %s", err)
|
||||
}
|
||||
|
||||
// Set up the VIM/govmomi client connection, or load a previous session
|
||||
client.vimClient, err = cw.config.SavedVimSessionOrNew(u)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] VMWare vSphere Client configured for URL: %s", cw.config.VSphereServer)
|
||||
|
||||
return client, nil
|
||||
}
|
||||
36
pkg/terraform/exec/plugins/vsphereprivate/provider.go
Normal file
36
pkg/terraform/exec/plugins/vsphereprivate/provider.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package vsphereprivate
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/terraform"
|
||||
"github.com/terraform-providers/terraform-provider-vsphere/vsphere"
|
||||
)
|
||||
|
||||
// defaultAPITimeout is a default timeout value that is passed to functions
|
||||
// requiring contexts, and other various waiters.
|
||||
const defaultAPITimeout = time.Minute * 5
|
||||
|
||||
// Provider returns a terraform.ResourceProvider.
|
||||
func Provider() terraform.ResourceProvider {
|
||||
vsphereProvider := vsphere.Provider()
|
||||
|
||||
vsphereProvider.(*schema.Provider).DataSourcesMap = map[string]*schema.Resource{}
|
||||
|
||||
vsphereProvider.(*schema.Provider).ResourcesMap = map[string]*schema.Resource{
|
||||
"vsphereprivate_import_ova": resourceVSpherePrivateImportOva(),
|
||||
}
|
||||
|
||||
vsphereProvider.(*schema.Provider).ConfigureFunc = providerConfigure
|
||||
|
||||
return vsphereProvider
|
||||
}
|
||||
|
||||
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
|
||||
c, err := NewConfig(d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.Client()
|
||||
}
|
||||
@@ -0,0 +1,387 @@
|
||||
package vsphereprivate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vmware/govmomi/find"
|
||||
"github.com/vmware/govmomi/nfc"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/ovf"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
|
||||
"github.com/vmware/govmomi/govc/importx"
|
||||
)
|
||||
|
||||
func resourceVSpherePrivateImportOva() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceVSpherePrivateImportOvaCreate,
|
||||
Read: resourceVSpherePrivateImportOvaRead,
|
||||
Delete: resourceVSpherePrivateImportOvaDelete,
|
||||
SchemaVersion: 1,
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": {
|
||||
Type: schema.TypeString,
|
||||
Description: "The name of the virtual machine that will be created.",
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validation.NoZeroValues,
|
||||
},
|
||||
"filename": {
|
||||
Type: schema.TypeString,
|
||||
Description: "The filename path to the ova file to be imported.",
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validation.NoZeroValues,
|
||||
},
|
||||
"datacenter": {
|
||||
Type: schema.TypeString,
|
||||
Description: "The name of the datacenter.",
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validation.NoZeroValues,
|
||||
},
|
||||
"cluster": {
|
||||
Type: schema.TypeString,
|
||||
Description: "The name of the cluster.",
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validation.NoZeroValues,
|
||||
},
|
||||
"network": {
|
||||
Type: schema.TypeString,
|
||||
Description: "The name of a network that the virtual machine will use.",
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validation.NoZeroValues,
|
||||
},
|
||||
"datastore": {
|
||||
Type: schema.TypeString,
|
||||
Description: "The name of the virtual machine's datastore.",
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validation.NoZeroValues,
|
||||
},
|
||||
"folder": {
|
||||
Type: schema.TypeString,
|
||||
Description: "The name of the folder to locate the virtual machine in.",
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validation.NoZeroValues,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// importOvaParams contains the vCenter objects required to import a OVA into vSphere.
|
||||
type importOvaParams struct {
|
||||
ResourcePool *object.ResourcePool
|
||||
Datacenter *object.Datacenter
|
||||
Datastore *object.Datastore
|
||||
Network *object.Network
|
||||
Host *object.HostSystem
|
||||
Folder *object.Folder
|
||||
}
|
||||
|
||||
func findImportOvaParams(client *vim25.Client, datacenter, cluster, datastore, network string) (*importOvaParams, error) {
|
||||
var ccrMo mo.ClusterComputeResource
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.TODO(), defaultAPITimeout)
|
||||
defer cancel()
|
||||
|
||||
importOvaParams := &importOvaParams{}
|
||||
finder := find.NewFinder(client)
|
||||
|
||||
// Find the object Datacenter by using its name provided by install-config
|
||||
dcObj, err := finder.Datacenter(ctx, datacenter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
importOvaParams.Datacenter = dcObj
|
||||
|
||||
// Find the top-level (and hidden to view) folders in the
|
||||
// datacenter
|
||||
folders, err := importOvaParams.Datacenter.Folders(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// The only folder we are interested in is VmFolder
|
||||
// Which can contain our template
|
||||
importOvaParams.Folder = folders.VmFolder
|
||||
|
||||
clusterPath := fmt.Sprintf("/%s/host/%s", datacenter, cluster)
|
||||
|
||||
// Find the cluster object by the datacenter and cluster name to
|
||||
// generate the path e.g. /datacenter/host/cluster
|
||||
clusterComputeResource, err := finder.ClusterComputeResource(ctx, clusterPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get the network properties that is defined in ClusterComputeResource
|
||||
// We need to know if the network name provided exists in the cluster that was
|
||||
// also provided.
|
||||
err = clusterComputeResource.Properties(ctx, clusterComputeResource.Reference(), []string{"network"}, &ccrMo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Find the network object using the provided network name
|
||||
for _, networkMoRef := range ccrMo.Network {
|
||||
networkObj := object.NewNetwork(client, networkMoRef)
|
||||
networkObjectName, err := networkObj.ObjectName(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if network == networkObjectName {
|
||||
importOvaParams.Network = networkObj
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Find all the datastores that are configured under the cluster
|
||||
datastores, err := clusterComputeResource.Datastores(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Find the specific datastore by the name provided
|
||||
for _, datastoreObj := range datastores {
|
||||
datastoreObjName, err := datastoreObj.ObjectName(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if datastore == datastoreObjName {
|
||||
importOvaParams.Datastore = datastoreObj
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Find all the HostSystem(s) under cluster
|
||||
hosts, err := clusterComputeResource.Hosts(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
foundDatastore := false
|
||||
foundNetwork := false
|
||||
var hostSystemManagedObject mo.HostSystem
|
||||
|
||||
// Confirm that the network and datastore that was provided is
|
||||
// available for use on the HostSystem we will import the
|
||||
// OVA to.
|
||||
for _, hostObj := range hosts {
|
||||
hostObj.Properties(ctx, hostObj.Reference(), []string{"network", "datastore"}, &hostSystemManagedObject)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, dsMoRef := range hostSystemManagedObject.Datastore {
|
||||
|
||||
if importOvaParams.Datastore.Reference().Value == dsMoRef.Value {
|
||||
foundDatastore = true
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, nMoRef := range hostSystemManagedObject.Network {
|
||||
if importOvaParams.Network.Reference().Value == nMoRef.Value {
|
||||
foundNetwork = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if foundDatastore && foundNetwork {
|
||||
importOvaParams.Host = hostObj
|
||||
resourcePool, err := hostObj.ResourcePool(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
importOvaParams.ResourcePool = resourcePool
|
||||
}
|
||||
}
|
||||
if !foundDatastore {
|
||||
return nil, errors.Errorf("failed to find a host in the cluster that contains the provided datastore")
|
||||
}
|
||||
if !foundNetwork {
|
||||
return nil, errors.Errorf("failed to find a host in the cluster that contains the provided network")
|
||||
}
|
||||
|
||||
return importOvaParams, nil
|
||||
}
|
||||
|
||||
// Used govc/importx/ovf.go as an example to implement
|
||||
// resourceVspherePrivateImportOvaCreate and upload functions
|
||||
// See: https://github.com/vmware/govmomi/blob/cc10a0758d5b4d4873388bcea417251d1ad03e42/govc/importx/ovf.go#L196-L324
|
||||
func upload(ctx context.Context, archive *importx.ArchiveFlag, lease *nfc.Lease, item nfc.FileItem) error {
|
||||
file := item.Path
|
||||
|
||||
f, size, err := archive.Open(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
opts := soap.Upload{
|
||||
ContentLength: size,
|
||||
}
|
||||
|
||||
return lease.Upload(ctx, item, f, opts)
|
||||
}
|
||||
|
||||
func resourceVSpherePrivateImportOvaCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] %s: Beginning import ova create", d.Get("filename").(string))
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.TODO(), defaultAPITimeout)
|
||||
defer cancel()
|
||||
client := meta.(*VSphereClient).vimClient.Client
|
||||
archive := &importx.ArchiveFlag{Archive: &importx.TapeArchive{Path: d.Get("filename").(string)}}
|
||||
|
||||
importOvaParams, err := findImportOvaParams(client,
|
||||
d.Get("datacenter").(string),
|
||||
d.Get("cluster").(string),
|
||||
d.Get("datastore").(string),
|
||||
d.Get("network").(string))
|
||||
if err != nil {
|
||||
return errors.Errorf("failed to find provided vSphere objects: %s", err)
|
||||
}
|
||||
|
||||
ovfDescriptor, err := archive.ReadOvf("*.ovf")
|
||||
if err != nil {
|
||||
return errors.Errorf("failed to read ovf: %s", err)
|
||||
}
|
||||
|
||||
ovfEnvelope, err := archive.ReadEnvelope(ovfDescriptor)
|
||||
if err != nil {
|
||||
return errors.Errorf("failed to parse ovf: %s", err)
|
||||
}
|
||||
|
||||
// The RHCOS OVA only has one network defined by default
|
||||
// The OVF envelope defines this. We need a 1:1 mapping
|
||||
// between networks with the OVF and the host
|
||||
if len(ovfEnvelope.Network.Networks) != 1 {
|
||||
return errors.Errorf("Expected the OVA to only have a single network adapter")
|
||||
}
|
||||
// Create mapping between OVF and the network object
|
||||
// found by Name
|
||||
networkMappings := []types.OvfNetworkMapping{{
|
||||
Name: ovfEnvelope.Network.Networks[0].Name,
|
||||
Network: importOvaParams.Network.Reference(),
|
||||
}}
|
||||
// This is a very minimal spec for importing
|
||||
// an OVF.
|
||||
cisp := types.OvfCreateImportSpecParams{
|
||||
EntityName: d.Get("name").(string),
|
||||
NetworkMapping: networkMappings,
|
||||
}
|
||||
|
||||
m := ovf.NewManager(client)
|
||||
spec, err := m.CreateImportSpec(ctx,
|
||||
string(ovfDescriptor),
|
||||
importOvaParams.ResourcePool.Reference(),
|
||||
importOvaParams.Datastore.Reference(),
|
||||
cisp)
|
||||
|
||||
if err != nil {
|
||||
return errors.Errorf("failed to create import spec: %s", err)
|
||||
}
|
||||
if spec.Error != nil {
|
||||
return errors.New(spec.Error[0].LocalizedMessage)
|
||||
}
|
||||
|
||||
// The lease and upload cannot be used with a timeout
|
||||
// since we do not know how long it will take to upload
|
||||
// the ova to vSphere
|
||||
ctx = context.TODO()
|
||||
|
||||
//Creates a new entity in this resource pool.
|
||||
//See VMware vCenter API documentation: Managed Object - ResourcePool - ImportVApp
|
||||
lease, err := importOvaParams.ResourcePool.ImportVApp(ctx,
|
||||
spec.ImportSpec,
|
||||
importOvaParams.Folder,
|
||||
importOvaParams.Host)
|
||||
|
||||
if err != nil {
|
||||
return errors.Errorf("failed to import vapp: %s", err)
|
||||
}
|
||||
|
||||
info, err := lease.Wait(ctx, spec.FileItem)
|
||||
if err != nil {
|
||||
return errors.Errorf("failed to lease wait: %s", err)
|
||||
}
|
||||
|
||||
u := lease.StartUpdater(ctx, info)
|
||||
defer u.Done()
|
||||
|
||||
for _, i := range info.Items {
|
||||
// upload the vmdk to which ever host that was first
|
||||
// available with the required network and datastore.
|
||||
err = upload(ctx, archive, lease, i)
|
||||
if err != nil {
|
||||
return errors.Errorf("failed to upload: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
err = lease.Complete(ctx)
|
||||
if err != nil {
|
||||
return errors.Errorf("failed to lease complete: %s", err)
|
||||
}
|
||||
|
||||
d.SetId(info.Entity.Value)
|
||||
log.Printf("[DEBUG] %s: ova import complete", d.Get("name").(string))
|
||||
|
||||
return resourceVSpherePrivateImportOvaRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceVSpherePrivateImportOvaRead(d *schema.ResourceData, meta interface{}) error {
|
||||
client := meta.(*VSphereClient).vimClient.Client
|
||||
moRef := types.ManagedObjectReference{
|
||||
Value: d.Id(),
|
||||
Type: "VirtualMachine",
|
||||
}
|
||||
|
||||
vm := object.NewVirtualMachine(client, moRef)
|
||||
if vm == nil {
|
||||
return fmt.Errorf("error VirtualMachine not found, managed object id: %s", d.Id())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceVSpherePrivateImportOvaDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] %s: Beginning delete", d.Get("name").(string))
|
||||
ctx, cancel := context.WithTimeout(context.TODO(), defaultAPITimeout)
|
||||
defer cancel()
|
||||
|
||||
client := meta.(*VSphereClient).vimClient.Client
|
||||
moRef := types.ManagedObjectReference{
|
||||
Value: d.Id(),
|
||||
Type: "VirtualMachine",
|
||||
}
|
||||
|
||||
vm := object.NewVirtualMachine(client, moRef)
|
||||
if vm == nil {
|
||||
return errors.Errorf("VirtualMachine not found")
|
||||
}
|
||||
|
||||
task, err := vm.Destroy(ctx)
|
||||
if err != nil {
|
||||
return errors.Errorf("failed to destroy virtual machine %s", err)
|
||||
}
|
||||
|
||||
err = task.Wait(ctx)
|
||||
if err != nil {
|
||||
return errors.Errorf("failed to destroy virtual machine %s", err)
|
||||
}
|
||||
|
||||
d.SetId("")
|
||||
|
||||
log.Printf("[DEBUG] %s: Delete complete", d.Get("name").(string))
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -4,6 +4,9 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
vsphereapis "github.com/openshift/machine-api-operator/pkg/apis/vsphereprovider/v1alpha1"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/openshift/installer/pkg/tfvars/internal/cache"
|
||||
)
|
||||
|
||||
type config struct {
|
||||
@@ -20,6 +23,7 @@ type config struct {
|
||||
Folder string `json:"vsphere_folder"`
|
||||
Network string `json:"vsphere_network"`
|
||||
Template string `json:"vsphere_template"`
|
||||
OvaFilePath string `json:"vsphere_ova_filepath"`
|
||||
}
|
||||
|
||||
// TFVarsSources contains the parameters to be converted into Terraform variables
|
||||
@@ -28,12 +32,18 @@ type TFVarsSources struct {
|
||||
Username string
|
||||
Password string
|
||||
Cluster string
|
||||
ImageURL string
|
||||
}
|
||||
|
||||
//TFVars generate vSphere-specific Terraform variables
|
||||
func TFVars(sources TFVarsSources) ([]byte, error) {
|
||||
controlPlaneConfig := sources.ControlPlaneConfigs[0]
|
||||
|
||||
cachedImage, err := cache.DownloadImageFile(sources.ImageURL)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to use cached vsphere image")
|
||||
}
|
||||
|
||||
cfg := &config{
|
||||
VSphereURL: controlPlaneConfig.Workspace.Server,
|
||||
VSphereUsername: sources.Username,
|
||||
@@ -48,6 +58,7 @@ func TFVars(sources TFVarsSources) ([]byte, error) {
|
||||
Folder: controlPlaneConfig.Workspace.Folder,
|
||||
Network: controlPlaneConfig.Network.Devices[0].NetworkName,
|
||||
Template: controlPlaneConfig.Template,
|
||||
OvaFilePath: cachedImage,
|
||||
}
|
||||
|
||||
return json.MarshalIndent(cfg, "", " ")
|
||||
|
||||
4
vendor/github.com/kr/pretty/.gitignore
generated
vendored
Normal file
4
vendor/github.com/kr/pretty/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[568].out
|
||||
_go*
|
||||
_test*
|
||||
_obj
|
||||
21
vendor/github.com/kr/pretty/License
generated
vendored
Normal file
21
vendor/github.com/kr/pretty/License
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright 2012 Keith Rarick
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
9
vendor/github.com/kr/pretty/Readme
generated
vendored
Normal file
9
vendor/github.com/kr/pretty/Readme
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
package pretty
|
||||
|
||||
import "github.com/kr/pretty"
|
||||
|
||||
Package pretty provides pretty-printing for Go values.
|
||||
|
||||
Documentation
|
||||
|
||||
http://godoc.org/github.com/kr/pretty
|
||||
265
vendor/github.com/kr/pretty/diff.go
generated
vendored
Normal file
265
vendor/github.com/kr/pretty/diff.go
generated
vendored
Normal file
@@ -0,0 +1,265 @@
|
||||
package pretty
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type sbuf []string
|
||||
|
||||
func (p *sbuf) Printf(format string, a ...interface{}) {
|
||||
s := fmt.Sprintf(format, a...)
|
||||
*p = append(*p, s)
|
||||
}
|
||||
|
||||
// Diff returns a slice where each element describes
|
||||
// a difference between a and b.
|
||||
func Diff(a, b interface{}) (desc []string) {
|
||||
Pdiff((*sbuf)(&desc), a, b)
|
||||
return desc
|
||||
}
|
||||
|
||||
// wprintfer calls Fprintf on w for each Printf call
|
||||
// with a trailing newline.
|
||||
type wprintfer struct{ w io.Writer }
|
||||
|
||||
func (p *wprintfer) Printf(format string, a ...interface{}) {
|
||||
fmt.Fprintf(p.w, format+"\n", a...)
|
||||
}
|
||||
|
||||
// Fdiff writes to w a description of the differences between a and b.
|
||||
func Fdiff(w io.Writer, a, b interface{}) {
|
||||
Pdiff(&wprintfer{w}, a, b)
|
||||
}
|
||||
|
||||
type Printfer interface {
|
||||
Printf(format string, a ...interface{})
|
||||
}
|
||||
|
||||
// Pdiff prints to p a description of the differences between a and b.
|
||||
// It calls Printf once for each difference, with no trailing newline.
|
||||
// The standard library log.Logger is a Printfer.
|
||||
func Pdiff(p Printfer, a, b interface{}) {
|
||||
diffPrinter{w: p}.diff(reflect.ValueOf(a), reflect.ValueOf(b))
|
||||
}
|
||||
|
||||
type Logfer interface {
|
||||
Logf(format string, a ...interface{})
|
||||
}
|
||||
|
||||
// logprintfer calls Fprintf on w for each Printf call
|
||||
// with a trailing newline.
|
||||
type logprintfer struct{ l Logfer }
|
||||
|
||||
func (p *logprintfer) Printf(format string, a ...interface{}) {
|
||||
p.l.Logf(format, a...)
|
||||
}
|
||||
|
||||
// Ldiff prints to l a description of the differences between a and b.
|
||||
// It calls Logf once for each difference, with no trailing newline.
|
||||
// The standard library testing.T and testing.B are Logfers.
|
||||
func Ldiff(l Logfer, a, b interface{}) {
|
||||
Pdiff(&logprintfer{l}, a, b)
|
||||
}
|
||||
|
||||
type diffPrinter struct {
|
||||
w Printfer
|
||||
l string // label
|
||||
}
|
||||
|
||||
func (w diffPrinter) printf(f string, a ...interface{}) {
|
||||
var l string
|
||||
if w.l != "" {
|
||||
l = w.l + ": "
|
||||
}
|
||||
w.w.Printf(l+f, a...)
|
||||
}
|
||||
|
||||
func (w diffPrinter) diff(av, bv reflect.Value) {
|
||||
if !av.IsValid() && bv.IsValid() {
|
||||
w.printf("nil != %# v", formatter{v: bv, quote: true})
|
||||
return
|
||||
}
|
||||
if av.IsValid() && !bv.IsValid() {
|
||||
w.printf("%# v != nil", formatter{v: av, quote: true})
|
||||
return
|
||||
}
|
||||
if !av.IsValid() && !bv.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
at := av.Type()
|
||||
bt := bv.Type()
|
||||
if at != bt {
|
||||
w.printf("%v != %v", at, bt)
|
||||
return
|
||||
}
|
||||
|
||||
switch kind := at.Kind(); kind {
|
||||
case reflect.Bool:
|
||||
if a, b := av.Bool(), bv.Bool(); a != b {
|
||||
w.printf("%v != %v", a, b)
|
||||
}
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
if a, b := av.Int(), bv.Int(); a != b {
|
||||
w.printf("%d != %d", a, b)
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
if a, b := av.Uint(), bv.Uint(); a != b {
|
||||
w.printf("%d != %d", a, b)
|
||||
}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
if a, b := av.Float(), bv.Float(); a != b {
|
||||
w.printf("%v != %v", a, b)
|
||||
}
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
if a, b := av.Complex(), bv.Complex(); a != b {
|
||||
w.printf("%v != %v", a, b)
|
||||
}
|
||||
case reflect.Array:
|
||||
n := av.Len()
|
||||
for i := 0; i < n; i++ {
|
||||
w.relabel(fmt.Sprintf("[%d]", i)).diff(av.Index(i), bv.Index(i))
|
||||
}
|
||||
case reflect.Chan, reflect.Func, reflect.UnsafePointer:
|
||||
if a, b := av.Pointer(), bv.Pointer(); a != b {
|
||||
w.printf("%#x != %#x", a, b)
|
||||
}
|
||||
case reflect.Interface:
|
||||
w.diff(av.Elem(), bv.Elem())
|
||||
case reflect.Map:
|
||||
ak, both, bk := keyDiff(av.MapKeys(), bv.MapKeys())
|
||||
for _, k := range ak {
|
||||
w := w.relabel(fmt.Sprintf("[%#v]", k))
|
||||
w.printf("%q != (missing)", av.MapIndex(k))
|
||||
}
|
||||
for _, k := range both {
|
||||
w := w.relabel(fmt.Sprintf("[%#v]", k))
|
||||
w.diff(av.MapIndex(k), bv.MapIndex(k))
|
||||
}
|
||||
for _, k := range bk {
|
||||
w := w.relabel(fmt.Sprintf("[%#v]", k))
|
||||
w.printf("(missing) != %q", bv.MapIndex(k))
|
||||
}
|
||||
case reflect.Ptr:
|
||||
switch {
|
||||
case av.IsNil() && !bv.IsNil():
|
||||
w.printf("nil != %# v", formatter{v: bv, quote: true})
|
||||
case !av.IsNil() && bv.IsNil():
|
||||
w.printf("%# v != nil", formatter{v: av, quote: true})
|
||||
case !av.IsNil() && !bv.IsNil():
|
||||
w.diff(av.Elem(), bv.Elem())
|
||||
}
|
||||
case reflect.Slice:
|
||||
lenA := av.Len()
|
||||
lenB := bv.Len()
|
||||
if lenA != lenB {
|
||||
w.printf("%s[%d] != %s[%d]", av.Type(), lenA, bv.Type(), lenB)
|
||||
break
|
||||
}
|
||||
for i := 0; i < lenA; i++ {
|
||||
w.relabel(fmt.Sprintf("[%d]", i)).diff(av.Index(i), bv.Index(i))
|
||||
}
|
||||
case reflect.String:
|
||||
if a, b := av.String(), bv.String(); a != b {
|
||||
w.printf("%q != %q", a, b)
|
||||
}
|
||||
case reflect.Struct:
|
||||
for i := 0; i < av.NumField(); i++ {
|
||||
w.relabel(at.Field(i).Name).diff(av.Field(i), bv.Field(i))
|
||||
}
|
||||
default:
|
||||
panic("unknown reflect Kind: " + kind.String())
|
||||
}
|
||||
}
|
||||
|
||||
func (d diffPrinter) relabel(name string) (d1 diffPrinter) {
|
||||
d1 = d
|
||||
if d.l != "" && name[0] != '[' {
|
||||
d1.l += "."
|
||||
}
|
||||
d1.l += name
|
||||
return d1
|
||||
}
|
||||
|
||||
// keyEqual compares a and b for equality.
|
||||
// Both a and b must be valid map keys.
|
||||
func keyEqual(av, bv reflect.Value) bool {
|
||||
if !av.IsValid() && !bv.IsValid() {
|
||||
return true
|
||||
}
|
||||
if !av.IsValid() || !bv.IsValid() || av.Type() != bv.Type() {
|
||||
return false
|
||||
}
|
||||
switch kind := av.Kind(); kind {
|
||||
case reflect.Bool:
|
||||
a, b := av.Bool(), bv.Bool()
|
||||
return a == b
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
a, b := av.Int(), bv.Int()
|
||||
return a == b
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
a, b := av.Uint(), bv.Uint()
|
||||
return a == b
|
||||
case reflect.Float32, reflect.Float64:
|
||||
a, b := av.Float(), bv.Float()
|
||||
return a == b
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
a, b := av.Complex(), bv.Complex()
|
||||
return a == b
|
||||
case reflect.Array:
|
||||
for i := 0; i < av.Len(); i++ {
|
||||
if !keyEqual(av.Index(i), bv.Index(i)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case reflect.Chan, reflect.UnsafePointer, reflect.Ptr:
|
||||
a, b := av.Pointer(), bv.Pointer()
|
||||
return a == b
|
||||
case reflect.Interface:
|
||||
return keyEqual(av.Elem(), bv.Elem())
|
||||
case reflect.String:
|
||||
a, b := av.String(), bv.String()
|
||||
return a == b
|
||||
case reflect.Struct:
|
||||
for i := 0; i < av.NumField(); i++ {
|
||||
if !keyEqual(av.Field(i), bv.Field(i)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
default:
|
||||
panic("invalid map key type " + av.Type().String())
|
||||
}
|
||||
}
|
||||
|
||||
func keyDiff(a, b []reflect.Value) (ak, both, bk []reflect.Value) {
|
||||
for _, av := range a {
|
||||
inBoth := false
|
||||
for _, bv := range b {
|
||||
if keyEqual(av, bv) {
|
||||
inBoth = true
|
||||
both = append(both, av)
|
||||
break
|
||||
}
|
||||
}
|
||||
if !inBoth {
|
||||
ak = append(ak, av)
|
||||
}
|
||||
}
|
||||
for _, bv := range b {
|
||||
inBoth := false
|
||||
for _, av := range a {
|
||||
if keyEqual(av, bv) {
|
||||
inBoth = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !inBoth {
|
||||
bk = append(bk, bv)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
328
vendor/github.com/kr/pretty/formatter.go
generated
vendored
Normal file
328
vendor/github.com/kr/pretty/formatter.go
generated
vendored
Normal file
@@ -0,0 +1,328 @@
|
||||
package pretty
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/kr/text"
|
||||
)
|
||||
|
||||
type formatter struct {
|
||||
v reflect.Value
|
||||
force bool
|
||||
quote bool
|
||||
}
|
||||
|
||||
// Formatter makes a wrapper, f, that will format x as go source with line
|
||||
// breaks and tabs. Object f responds to the "%v" formatting verb when both the
|
||||
// "#" and " " (space) flags are set, for example:
|
||||
//
|
||||
// fmt.Sprintf("%# v", Formatter(x))
|
||||
//
|
||||
// If one of these two flags is not set, or any other verb is used, f will
|
||||
// format x according to the usual rules of package fmt.
|
||||
// In particular, if x satisfies fmt.Formatter, then x.Format will be called.
|
||||
func Formatter(x interface{}) (f fmt.Formatter) {
|
||||
return formatter{v: reflect.ValueOf(x), quote: true}
|
||||
}
|
||||
|
||||
func (fo formatter) String() string {
|
||||
return fmt.Sprint(fo.v.Interface()) // unwrap it
|
||||
}
|
||||
|
||||
func (fo formatter) passThrough(f fmt.State, c rune) {
|
||||
s := "%"
|
||||
for i := 0; i < 128; i++ {
|
||||
if f.Flag(i) {
|
||||
s += string(i)
|
||||
}
|
||||
}
|
||||
if w, ok := f.Width(); ok {
|
||||
s += fmt.Sprintf("%d", w)
|
||||
}
|
||||
if p, ok := f.Precision(); ok {
|
||||
s += fmt.Sprintf(".%d", p)
|
||||
}
|
||||
s += string(c)
|
||||
fmt.Fprintf(f, s, fo.v.Interface())
|
||||
}
|
||||
|
||||
func (fo formatter) Format(f fmt.State, c rune) {
|
||||
if fo.force || c == 'v' && f.Flag('#') && f.Flag(' ') {
|
||||
w := tabwriter.NewWriter(f, 4, 4, 1, ' ', 0)
|
||||
p := &printer{tw: w, Writer: w, visited: make(map[visit]int)}
|
||||
p.printValue(fo.v, true, fo.quote)
|
||||
w.Flush()
|
||||
return
|
||||
}
|
||||
fo.passThrough(f, c)
|
||||
}
|
||||
|
||||
type printer struct {
|
||||
io.Writer
|
||||
tw *tabwriter.Writer
|
||||
visited map[visit]int
|
||||
depth int
|
||||
}
|
||||
|
||||
func (p *printer) indent() *printer {
|
||||
q := *p
|
||||
q.tw = tabwriter.NewWriter(p.Writer, 4, 4, 1, ' ', 0)
|
||||
q.Writer = text.NewIndentWriter(q.tw, []byte{'\t'})
|
||||
return &q
|
||||
}
|
||||
|
||||
func (p *printer) printInline(v reflect.Value, x interface{}, showType bool) {
|
||||
if showType {
|
||||
io.WriteString(p, v.Type().String())
|
||||
fmt.Fprintf(p, "(%#v)", x)
|
||||
} else {
|
||||
fmt.Fprintf(p, "%#v", x)
|
||||
}
|
||||
}
|
||||
|
||||
// printValue must keep track of already-printed pointer values to avoid
|
||||
// infinite recursion.
|
||||
type visit struct {
|
||||
v uintptr
|
||||
typ reflect.Type
|
||||
}
|
||||
|
||||
func (p *printer) printValue(v reflect.Value, showType, quote bool) {
|
||||
if p.depth > 10 {
|
||||
io.WriteString(p, "!%v(DEPTH EXCEEDED)")
|
||||
return
|
||||
}
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.Bool:
|
||||
p.printInline(v, v.Bool(), showType)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
p.printInline(v, v.Int(), showType)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
p.printInline(v, v.Uint(), showType)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
p.printInline(v, v.Float(), showType)
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
fmt.Fprintf(p, "%#v", v.Complex())
|
||||
case reflect.String:
|
||||
p.fmtString(v.String(), quote)
|
||||
case reflect.Map:
|
||||
t := v.Type()
|
||||
if showType {
|
||||
io.WriteString(p, t.String())
|
||||
}
|
||||
writeByte(p, '{')
|
||||
if nonzero(v) {
|
||||
expand := !canInline(v.Type())
|
||||
pp := p
|
||||
if expand {
|
||||
writeByte(p, '\n')
|
||||
pp = p.indent()
|
||||
}
|
||||
keys := v.MapKeys()
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
showTypeInStruct := true
|
||||
k := keys[i]
|
||||
mv := v.MapIndex(k)
|
||||
pp.printValue(k, false, true)
|
||||
writeByte(pp, ':')
|
||||
if expand {
|
||||
writeByte(pp, '\t')
|
||||
}
|
||||
showTypeInStruct = t.Elem().Kind() == reflect.Interface
|
||||
pp.printValue(mv, showTypeInStruct, true)
|
||||
if expand {
|
||||
io.WriteString(pp, ",\n")
|
||||
} else if i < v.Len()-1 {
|
||||
io.WriteString(pp, ", ")
|
||||
}
|
||||
}
|
||||
if expand {
|
||||
pp.tw.Flush()
|
||||
}
|
||||
}
|
||||
writeByte(p, '}')
|
||||
case reflect.Struct:
|
||||
t := v.Type()
|
||||
if v.CanAddr() {
|
||||
addr := v.UnsafeAddr()
|
||||
vis := visit{addr, t}
|
||||
if vd, ok := p.visited[vis]; ok && vd < p.depth {
|
||||
p.fmtString(t.String()+"{(CYCLIC REFERENCE)}", false)
|
||||
break // don't print v again
|
||||
}
|
||||
p.visited[vis] = p.depth
|
||||
}
|
||||
|
||||
if showType {
|
||||
io.WriteString(p, t.String())
|
||||
}
|
||||
writeByte(p, '{')
|
||||
if nonzero(v) {
|
||||
expand := !canInline(v.Type())
|
||||
pp := p
|
||||
if expand {
|
||||
writeByte(p, '\n')
|
||||
pp = p.indent()
|
||||
}
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
showTypeInStruct := true
|
||||
if f := t.Field(i); f.Name != "" {
|
||||
io.WriteString(pp, f.Name)
|
||||
writeByte(pp, ':')
|
||||
if expand {
|
||||
writeByte(pp, '\t')
|
||||
}
|
||||
showTypeInStruct = labelType(f.Type)
|
||||
}
|
||||
pp.printValue(getField(v, i), showTypeInStruct, true)
|
||||
if expand {
|
||||
io.WriteString(pp, ",\n")
|
||||
} else if i < v.NumField()-1 {
|
||||
io.WriteString(pp, ", ")
|
||||
}
|
||||
}
|
||||
if expand {
|
||||
pp.tw.Flush()
|
||||
}
|
||||
}
|
||||
writeByte(p, '}')
|
||||
case reflect.Interface:
|
||||
switch e := v.Elem(); {
|
||||
case e.Kind() == reflect.Invalid:
|
||||
io.WriteString(p, "nil")
|
||||
case e.IsValid():
|
||||
pp := *p
|
||||
pp.depth++
|
||||
pp.printValue(e, showType, true)
|
||||
default:
|
||||
io.WriteString(p, v.Type().String())
|
||||
io.WriteString(p, "(nil)")
|
||||
}
|
||||
case reflect.Array, reflect.Slice:
|
||||
t := v.Type()
|
||||
if showType {
|
||||
io.WriteString(p, t.String())
|
||||
}
|
||||
if v.Kind() == reflect.Slice && v.IsNil() && showType {
|
||||
io.WriteString(p, "(nil)")
|
||||
break
|
||||
}
|
||||
if v.Kind() == reflect.Slice && v.IsNil() {
|
||||
io.WriteString(p, "nil")
|
||||
break
|
||||
}
|
||||
writeByte(p, '{')
|
||||
expand := !canInline(v.Type())
|
||||
pp := p
|
||||
if expand {
|
||||
writeByte(p, '\n')
|
||||
pp = p.indent()
|
||||
}
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
showTypeInSlice := t.Elem().Kind() == reflect.Interface
|
||||
pp.printValue(v.Index(i), showTypeInSlice, true)
|
||||
if expand {
|
||||
io.WriteString(pp, ",\n")
|
||||
} else if i < v.Len()-1 {
|
||||
io.WriteString(pp, ", ")
|
||||
}
|
||||
}
|
||||
if expand {
|
||||
pp.tw.Flush()
|
||||
}
|
||||
writeByte(p, '}')
|
||||
case reflect.Ptr:
|
||||
e := v.Elem()
|
||||
if !e.IsValid() {
|
||||
writeByte(p, '(')
|
||||
io.WriteString(p, v.Type().String())
|
||||
io.WriteString(p, ")(nil)")
|
||||
} else {
|
||||
pp := *p
|
||||
pp.depth++
|
||||
writeByte(pp, '&')
|
||||
pp.printValue(e, true, true)
|
||||
}
|
||||
case reflect.Chan:
|
||||
x := v.Pointer()
|
||||
if showType {
|
||||
writeByte(p, '(')
|
||||
io.WriteString(p, v.Type().String())
|
||||
fmt.Fprintf(p, ")(%#v)", x)
|
||||
} else {
|
||||
fmt.Fprintf(p, "%#v", x)
|
||||
}
|
||||
case reflect.Func:
|
||||
io.WriteString(p, v.Type().String())
|
||||
io.WriteString(p, " {...}")
|
||||
case reflect.UnsafePointer:
|
||||
p.printInline(v, v.Pointer(), showType)
|
||||
case reflect.Invalid:
|
||||
io.WriteString(p, "nil")
|
||||
}
|
||||
}
|
||||
|
||||
func canInline(t reflect.Type) bool {
|
||||
switch t.Kind() {
|
||||
case reflect.Map:
|
||||
return !canExpand(t.Elem())
|
||||
case reflect.Struct:
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
if canExpand(t.Field(i).Type) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case reflect.Interface:
|
||||
return false
|
||||
case reflect.Array, reflect.Slice:
|
||||
return !canExpand(t.Elem())
|
||||
case reflect.Ptr:
|
||||
return false
|
||||
case reflect.Chan, reflect.Func, reflect.UnsafePointer:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func canExpand(t reflect.Type) bool {
|
||||
switch t.Kind() {
|
||||
case reflect.Map, reflect.Struct,
|
||||
reflect.Interface, reflect.Array, reflect.Slice,
|
||||
reflect.Ptr:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func labelType(t reflect.Type) bool {
|
||||
switch t.Kind() {
|
||||
case reflect.Interface, reflect.Struct:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *printer) fmtString(s string, quote bool) {
|
||||
if quote {
|
||||
s = strconv.Quote(s)
|
||||
}
|
||||
io.WriteString(p, s)
|
||||
}
|
||||
|
||||
func writeByte(w io.Writer, b byte) {
|
||||
w.Write([]byte{b})
|
||||
}
|
||||
|
||||
func getField(v reflect.Value, i int) reflect.Value {
|
||||
val := v.Field(i)
|
||||
if val.Kind() == reflect.Interface && !val.IsNil() {
|
||||
val = val.Elem()
|
||||
}
|
||||
return val
|
||||
}
|
||||
3
vendor/github.com/kr/pretty/go.mod
generated
vendored
Normal file
3
vendor/github.com/kr/pretty/go.mod
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module "github.com/kr/pretty"
|
||||
|
||||
require "github.com/kr/text" v0.1.0
|
||||
108
vendor/github.com/kr/pretty/pretty.go
generated
vendored
Normal file
108
vendor/github.com/kr/pretty/pretty.go
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
// Package pretty provides pretty-printing for Go values. This is
|
||||
// useful during debugging, to avoid wrapping long output lines in
|
||||
// the terminal.
|
||||
//
|
||||
// It provides a function, Formatter, that can be used with any
|
||||
// function that accepts a format string. It also provides
|
||||
// convenience wrappers for functions in packages fmt and log.
|
||||
package pretty
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Errorf is a convenience wrapper for fmt.Errorf.
|
||||
//
|
||||
// Calling Errorf(f, x, y) is equivalent to
|
||||
// fmt.Errorf(f, Formatter(x), Formatter(y)).
|
||||
func Errorf(format string, a ...interface{}) error {
|
||||
return fmt.Errorf(format, wrap(a, false)...)
|
||||
}
|
||||
|
||||
// Fprintf is a convenience wrapper for fmt.Fprintf.
|
||||
//
|
||||
// Calling Fprintf(w, f, x, y) is equivalent to
|
||||
// fmt.Fprintf(w, f, Formatter(x), Formatter(y)).
|
||||
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, error error) {
|
||||
return fmt.Fprintf(w, format, wrap(a, false)...)
|
||||
}
|
||||
|
||||
// Log is a convenience wrapper for log.Printf.
|
||||
//
|
||||
// Calling Log(x, y) is equivalent to
|
||||
// log.Print(Formatter(x), Formatter(y)), but each operand is
|
||||
// formatted with "%# v".
|
||||
func Log(a ...interface{}) {
|
||||
log.Print(wrap(a, true)...)
|
||||
}
|
||||
|
||||
// Logf is a convenience wrapper for log.Printf.
|
||||
//
|
||||
// Calling Logf(f, x, y) is equivalent to
|
||||
// log.Printf(f, Formatter(x), Formatter(y)).
|
||||
func Logf(format string, a ...interface{}) {
|
||||
log.Printf(format, wrap(a, false)...)
|
||||
}
|
||||
|
||||
// Logln is a convenience wrapper for log.Printf.
|
||||
//
|
||||
// Calling Logln(x, y) is equivalent to
|
||||
// log.Println(Formatter(x), Formatter(y)), but each operand is
|
||||
// formatted with "%# v".
|
||||
func Logln(a ...interface{}) {
|
||||
log.Println(wrap(a, true)...)
|
||||
}
|
||||
|
||||
// Print pretty-prints its operands and writes to standard output.
|
||||
//
|
||||
// Calling Print(x, y) is equivalent to
|
||||
// fmt.Print(Formatter(x), Formatter(y)), but each operand is
|
||||
// formatted with "%# v".
|
||||
func Print(a ...interface{}) (n int, errno error) {
|
||||
return fmt.Print(wrap(a, true)...)
|
||||
}
|
||||
|
||||
// Printf is a convenience wrapper for fmt.Printf.
|
||||
//
|
||||
// Calling Printf(f, x, y) is equivalent to
|
||||
// fmt.Printf(f, Formatter(x), Formatter(y)).
|
||||
func Printf(format string, a ...interface{}) (n int, errno error) {
|
||||
return fmt.Printf(format, wrap(a, false)...)
|
||||
}
|
||||
|
||||
// Println pretty-prints its operands and writes to standard output.
|
||||
//
|
||||
// Calling Print(x, y) is equivalent to
|
||||
// fmt.Println(Formatter(x), Formatter(y)), but each operand is
|
||||
// formatted with "%# v".
|
||||
func Println(a ...interface{}) (n int, errno error) {
|
||||
return fmt.Println(wrap(a, true)...)
|
||||
}
|
||||
|
||||
// Sprint is a convenience wrapper for fmt.Sprintf.
|
||||
//
|
||||
// Calling Sprint(x, y) is equivalent to
|
||||
// fmt.Sprint(Formatter(x), Formatter(y)), but each operand is
|
||||
// formatted with "%# v".
|
||||
func Sprint(a ...interface{}) string {
|
||||
return fmt.Sprint(wrap(a, true)...)
|
||||
}
|
||||
|
||||
// Sprintf is a convenience wrapper for fmt.Sprintf.
|
||||
//
|
||||
// Calling Sprintf(f, x, y) is equivalent to
|
||||
// fmt.Sprintf(f, Formatter(x), Formatter(y)).
|
||||
func Sprintf(format string, a ...interface{}) string {
|
||||
return fmt.Sprintf(format, wrap(a, false)...)
|
||||
}
|
||||
|
||||
func wrap(a []interface{}, force bool) []interface{} {
|
||||
w := make([]interface{}, len(a))
|
||||
for i, x := range a {
|
||||
w[i] = formatter{v: reflect.ValueOf(x), force: force}
|
||||
}
|
||||
return w
|
||||
}
|
||||
41
vendor/github.com/kr/pretty/zero.go
generated
vendored
Normal file
41
vendor/github.com/kr/pretty/zero.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
package pretty
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func nonzero(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Bool:
|
||||
return v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() != 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() != 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() != 0
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
return v.Complex() != complex(0, 0)
|
||||
case reflect.String:
|
||||
return v.String() != ""
|
||||
case reflect.Struct:
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
if nonzero(getField(v, i)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
case reflect.Array:
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
if nonzero(v.Index(i)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
case reflect.Map, reflect.Interface, reflect.Slice, reflect.Ptr, reflect.Chan, reflect.Func:
|
||||
return !v.IsNil()
|
||||
case reflect.UnsafePointer:
|
||||
return v.Pointer() != 0
|
||||
}
|
||||
return true
|
||||
}
|
||||
19
vendor/github.com/kr/text/License
generated
vendored
Normal file
19
vendor/github.com/kr/text/License
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright 2012 Keith Rarick
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
3
vendor/github.com/kr/text/Readme
generated
vendored
Normal file
3
vendor/github.com/kr/text/Readme
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
This is a Go package for manipulating paragraphs of text.
|
||||
|
||||
See http://go.pkgdoc.org/github.com/kr/text for full documentation.
|
||||
3
vendor/github.com/kr/text/doc.go
generated
vendored
Normal file
3
vendor/github.com/kr/text/doc.go
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
// Package text provides rudimentary functions for manipulating text in
|
||||
// paragraphs.
|
||||
package text
|
||||
3
vendor/github.com/kr/text/go.mod
generated
vendored
Normal file
3
vendor/github.com/kr/text/go.mod
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module "github.com/kr/text"
|
||||
|
||||
require "github.com/kr/pty" v1.1.1
|
||||
74
vendor/github.com/kr/text/indent.go
generated
vendored
Normal file
74
vendor/github.com/kr/text/indent.go
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
package text
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// Indent inserts prefix at the beginning of each non-empty line of s. The
|
||||
// end-of-line marker is NL.
|
||||
func Indent(s, prefix string) string {
|
||||
return string(IndentBytes([]byte(s), []byte(prefix)))
|
||||
}
|
||||
|
||||
// IndentBytes inserts prefix at the beginning of each non-empty line of b.
|
||||
// The end-of-line marker is NL.
|
||||
func IndentBytes(b, prefix []byte) []byte {
|
||||
var res []byte
|
||||
bol := true
|
||||
for _, c := range b {
|
||||
if bol && c != '\n' {
|
||||
res = append(res, prefix...)
|
||||
}
|
||||
res = append(res, c)
|
||||
bol = c == '\n'
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Writer indents each line of its input.
|
||||
type indentWriter struct {
|
||||
w io.Writer
|
||||
bol bool
|
||||
pre [][]byte
|
||||
sel int
|
||||
off int
|
||||
}
|
||||
|
||||
// NewIndentWriter makes a new write filter that indents the input
|
||||
// lines. Each line is prefixed in order with the corresponding
|
||||
// element of pre. If there are more lines than elements, the last
|
||||
// element of pre is repeated for each subsequent line.
|
||||
func NewIndentWriter(w io.Writer, pre ...[]byte) io.Writer {
|
||||
return &indentWriter{
|
||||
w: w,
|
||||
pre: pre,
|
||||
bol: true,
|
||||
}
|
||||
}
|
||||
|
||||
// The only errors returned are from the underlying indentWriter.
|
||||
func (w *indentWriter) Write(p []byte) (n int, err error) {
|
||||
for _, c := range p {
|
||||
if w.bol {
|
||||
var i int
|
||||
i, err = w.w.Write(w.pre[w.sel][w.off:])
|
||||
w.off += i
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
_, err = w.w.Write([]byte{c})
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
n++
|
||||
w.bol = c == '\n'
|
||||
if w.bol {
|
||||
w.off = 0
|
||||
if w.sel < len(w.pre)-1 {
|
||||
w.sel++
|
||||
}
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
86
vendor/github.com/kr/text/wrap.go
generated
vendored
Normal file
86
vendor/github.com/kr/text/wrap.go
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
package text
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math"
|
||||
)
|
||||
|
||||
var (
|
||||
nl = []byte{'\n'}
|
||||
sp = []byte{' '}
|
||||
)
|
||||
|
||||
const defaultPenalty = 1e5
|
||||
|
||||
// Wrap wraps s into a paragraph of lines of length lim, with minimal
|
||||
// raggedness.
|
||||
func Wrap(s string, lim int) string {
|
||||
return string(WrapBytes([]byte(s), lim))
|
||||
}
|
||||
|
||||
// WrapBytes wraps b into a paragraph of lines of length lim, with minimal
|
||||
// raggedness.
|
||||
func WrapBytes(b []byte, lim int) []byte {
|
||||
words := bytes.Split(bytes.Replace(bytes.TrimSpace(b), nl, sp, -1), sp)
|
||||
var lines [][]byte
|
||||
for _, line := range WrapWords(words, 1, lim, defaultPenalty) {
|
||||
lines = append(lines, bytes.Join(line, sp))
|
||||
}
|
||||
return bytes.Join(lines, nl)
|
||||
}
|
||||
|
||||
// WrapWords is the low-level line-breaking algorithm, useful if you need more
|
||||
// control over the details of the text wrapping process. For most uses, either
|
||||
// Wrap or WrapBytes will be sufficient and more convenient.
|
||||
//
|
||||
// WrapWords splits a list of words into lines with minimal "raggedness",
|
||||
// treating each byte as one unit, accounting for spc units between adjacent
|
||||
// words on each line, and attempting to limit lines to lim units. Raggedness
|
||||
// is the total error over all lines, where error is the square of the
|
||||
// difference of the length of the line and lim. Too-long lines (which only
|
||||
// happen when a single word is longer than lim units) have pen penalty units
|
||||
// added to the error.
|
||||
func WrapWords(words [][]byte, spc, lim, pen int) [][][]byte {
|
||||
n := len(words)
|
||||
|
||||
length := make([][]int, n)
|
||||
for i := 0; i < n; i++ {
|
||||
length[i] = make([]int, n)
|
||||
length[i][i] = len(words[i])
|
||||
for j := i + 1; j < n; j++ {
|
||||
length[i][j] = length[i][j-1] + spc + len(words[j])
|
||||
}
|
||||
}
|
||||
|
||||
nbrk := make([]int, n)
|
||||
cost := make([]int, n)
|
||||
for i := range cost {
|
||||
cost[i] = math.MaxInt32
|
||||
}
|
||||
for i := n - 1; i >= 0; i-- {
|
||||
if length[i][n-1] <= lim || i == n-1 {
|
||||
cost[i] = 0
|
||||
nbrk[i] = n
|
||||
} else {
|
||||
for j := i + 1; j < n; j++ {
|
||||
d := lim - length[i][j-1]
|
||||
c := d*d + cost[j]
|
||||
if length[i][j-1] > lim {
|
||||
c += pen // too-long lines get a worse penalty
|
||||
}
|
||||
if c < cost[i] {
|
||||
cost[i] = c
|
||||
nbrk[i] = j
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var lines [][][]byte
|
||||
i := 0
|
||||
for i < n {
|
||||
lines = append(lines, words[i:nbrk[i]])
|
||||
i = nbrk[i]
|
||||
}
|
||||
return lines
|
||||
}
|
||||
193
vendor/github.com/vmware/govmomi/govc/cli/command.go
generated
vendored
Normal file
193
vendor/github.com/vmware/govmomi/govc/cli/command.go
generated
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type HasFlags interface {
|
||||
// Register may be called more than once and should be idempotent.
|
||||
Register(ctx context.Context, f *flag.FlagSet)
|
||||
|
||||
// Process may be called more than once and should be idempotent.
|
||||
Process(ctx context.Context) error
|
||||
}
|
||||
|
||||
type Command interface {
|
||||
HasFlags
|
||||
|
||||
Run(ctx context.Context, f *flag.FlagSet) error
|
||||
}
|
||||
|
||||
func generalHelp(w io.Writer, filter string) {
|
||||
var cmds, matches []string
|
||||
for name := range commands {
|
||||
cmds = append(cmds, name)
|
||||
|
||||
if filter != "" && strings.Contains(name, filter) {
|
||||
matches = append(matches, name)
|
||||
}
|
||||
}
|
||||
|
||||
if len(matches) == 0 {
|
||||
fmt.Fprintf(w, "Usage of %s:\n", os.Args[0])
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s: command '%s' not found, did you mean:\n", os.Args[0], filter)
|
||||
cmds = matches
|
||||
}
|
||||
|
||||
sort.Strings(cmds)
|
||||
for _, name := range cmds {
|
||||
fmt.Fprintf(w, " %s\n", name)
|
||||
}
|
||||
}
|
||||
|
||||
func commandHelp(w io.Writer, name string, cmd Command, f *flag.FlagSet) {
|
||||
type HasUsage interface {
|
||||
Usage() string
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "Usage: %s %s [OPTIONS]", os.Args[0], name)
|
||||
if u, ok := cmd.(HasUsage); ok {
|
||||
fmt.Fprintf(w, " %s", u.Usage())
|
||||
}
|
||||
fmt.Fprintf(w, "\n")
|
||||
|
||||
type HasDescription interface {
|
||||
Description() string
|
||||
}
|
||||
|
||||
if u, ok := cmd.(HasDescription); ok {
|
||||
fmt.Fprintf(w, "\n%s\n", u.Description())
|
||||
}
|
||||
|
||||
n := 0
|
||||
f.VisitAll(func(_ *flag.Flag) {
|
||||
n += 1
|
||||
})
|
||||
|
||||
if n > 0 {
|
||||
fmt.Fprintf(w, "\nOptions:\n")
|
||||
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
|
||||
f.VisitAll(func(f *flag.Flag) {
|
||||
fmt.Fprintf(tw, "\t-%s=%s\t%s\n", f.Name, f.DefValue, f.Usage)
|
||||
})
|
||||
tw.Flush()
|
||||
}
|
||||
}
|
||||
|
||||
func clientLogout(ctx context.Context, cmd Command) error {
|
||||
type logout interface {
|
||||
Logout(context.Context) error
|
||||
}
|
||||
|
||||
if l, ok := cmd.(logout); ok {
|
||||
return l.Logout(ctx)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Run(args []string) int {
|
||||
hw := os.Stderr
|
||||
rc := 1
|
||||
hwrc := func(arg string) {
|
||||
if arg == "-h" {
|
||||
hw = os.Stdout
|
||||
rc = 0
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
if len(args) == 0 {
|
||||
generalHelp(hw, "")
|
||||
return rc
|
||||
}
|
||||
|
||||
// Look up real command name in aliases table.
|
||||
name, ok := aliases[args[0]]
|
||||
if !ok {
|
||||
name = args[0]
|
||||
}
|
||||
|
||||
cmd, ok := commands[name]
|
||||
if !ok {
|
||||
hwrc(name)
|
||||
generalHelp(hw, name)
|
||||
return rc
|
||||
}
|
||||
|
||||
fs := flag.NewFlagSet("", flag.ContinueOnError)
|
||||
fs.SetOutput(ioutil.Discard)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
if id := os.Getenv("GOVC_OPERATION_ID"); id != "" {
|
||||
ctx = context.WithValue(ctx, types.ID{}, id)
|
||||
}
|
||||
|
||||
cmd.Register(ctx, fs)
|
||||
|
||||
if err = fs.Parse(args[1:]); err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
if err = cmd.Process(ctx); err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
if err = cmd.Run(ctx, fs); err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
if err = clientLogout(ctx, cmd); err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
return 0
|
||||
|
||||
error:
|
||||
if err == flag.ErrHelp {
|
||||
if len(args) == 2 {
|
||||
hwrc(args[1])
|
||||
}
|
||||
commandHelp(hw, args[0], cmd, fs)
|
||||
} else {
|
||||
if x, ok := err.(interface{ ExitCode() int }); ok {
|
||||
// propagate exit code, e.g. from guest.run
|
||||
rc = x.ExitCode()
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], err)
|
||||
}
|
||||
}
|
||||
|
||||
_ = clientLogout(ctx, cmd)
|
||||
|
||||
return rc
|
||||
}
|
||||
43
vendor/github.com/vmware/govmomi/govc/cli/register.go
generated
vendored
Normal file
43
vendor/github.com/vmware/govmomi/govc/cli/register.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cli
|
||||
|
||||
import "os"
|
||||
|
||||
var commands = map[string]Command{}
|
||||
|
||||
var aliases = map[string]string{}
|
||||
|
||||
// hideUnreleased allows commands to be compiled into the govc binary without being registered by default.
|
||||
// Unreleased commands are omitted from 'govc -h' help text and the generated govc/USAGE.md
|
||||
// Setting the env var GOVC_SHOW_UNRELEASED=true enables any commands registered as unreleased.
|
||||
var hideUnreleased = os.Getenv("GOVC_SHOW_UNRELEASED") != "true"
|
||||
|
||||
func Register(name string, c Command, unreleased ...bool) {
|
||||
if len(unreleased) != 0 && unreleased[0] && hideUnreleased {
|
||||
return
|
||||
}
|
||||
commands[name] = c
|
||||
}
|
||||
|
||||
func Alias(name string, alias string) {
|
||||
aliases[alias] = name
|
||||
}
|
||||
|
||||
func Commands() map[string]Command {
|
||||
return commands
|
||||
}
|
||||
711
vendor/github.com/vmware/govmomi/govc/flags/client.go
generated
vendored
Normal file
711
vendor/github.com/vmware/govmomi/govc/flags/client.go
generated
vendored
Normal file
@@ -0,0 +1,711 @@
|
||||
/*
|
||||
Copyright (c) 2014-2018 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha1"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/govmomi/session"
|
||||
"github.com/vmware/govmomi/sts"
|
||||
"github.com/vmware/govmomi/vapi/rest"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
const (
|
||||
envURL = "GOVC_URL"
|
||||
envUsername = "GOVC_USERNAME"
|
||||
envPassword = "GOVC_PASSWORD"
|
||||
envCertificate = "GOVC_CERTIFICATE"
|
||||
envPrivateKey = "GOVC_PRIVATE_KEY"
|
||||
envInsecure = "GOVC_INSECURE"
|
||||
envPersist = "GOVC_PERSIST_SESSION"
|
||||
envMinAPIVersion = "GOVC_MIN_API_VERSION"
|
||||
envVimNamespace = "GOVC_VIM_NAMESPACE"
|
||||
envVimVersion = "GOVC_VIM_VERSION"
|
||||
envTLSCaCerts = "GOVC_TLS_CA_CERTS"
|
||||
envTLSKnownHosts = "GOVC_TLS_KNOWN_HOSTS"
|
||||
|
||||
defaultMinVimVersion = "5.5"
|
||||
)
|
||||
|
||||
const cDescr = "ESX or vCenter URL"
|
||||
|
||||
type ClientFlag struct {
|
||||
common
|
||||
|
||||
*DebugFlag
|
||||
|
||||
url *url.URL
|
||||
username string
|
||||
password string
|
||||
cert string
|
||||
key string
|
||||
insecure bool
|
||||
persist bool
|
||||
minAPIVersion string
|
||||
vimNamespace string
|
||||
vimVersion string
|
||||
tlsCaCerts string
|
||||
tlsKnownHosts string
|
||||
client *vim25.Client
|
||||
|
||||
Login func(context.Context, *vim25.Client) error
|
||||
}
|
||||
|
||||
var (
|
||||
home = os.Getenv("GOVMOMI_HOME")
|
||||
clientFlagKey = flagKey("client")
|
||||
)
|
||||
|
||||
func init() {
|
||||
if home == "" {
|
||||
home = filepath.Join(os.Getenv("HOME"), ".govmomi")
|
||||
}
|
||||
}
|
||||
|
||||
func NewClientFlag(ctx context.Context) (*ClientFlag, context.Context) {
|
||||
if v := ctx.Value(clientFlagKey); v != nil {
|
||||
return v.(*ClientFlag), ctx
|
||||
}
|
||||
|
||||
v := &ClientFlag{}
|
||||
v.Login = v.login
|
||||
v.DebugFlag, ctx = NewDebugFlag(ctx)
|
||||
ctx = context.WithValue(ctx, clientFlagKey, v)
|
||||
return v, ctx
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) URLWithoutPassword() *url.URL {
|
||||
if flag.url == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
withoutCredentials := *flag.url
|
||||
withoutCredentials.User = url.User(flag.url.User.Username())
|
||||
return &withoutCredentials
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) Userinfo() *url.Userinfo {
|
||||
return flag.url.User
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) IsSecure() bool {
|
||||
return !flag.insecure
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) String() string {
|
||||
url := flag.URLWithoutPassword()
|
||||
if url == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return url.String()
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) Set(s string) error {
|
||||
var err error
|
||||
|
||||
flag.url, err = soap.ParseURL(s)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
flag.RegisterOnce(func() {
|
||||
flag.DebugFlag.Register(ctx, f)
|
||||
|
||||
{
|
||||
flag.Set(os.Getenv(envURL))
|
||||
usage := fmt.Sprintf("%s [%s]", cDescr, envURL)
|
||||
f.Var(flag, "u", usage)
|
||||
}
|
||||
|
||||
{
|
||||
flag.username = os.Getenv(envUsername)
|
||||
flag.password = os.Getenv(envPassword)
|
||||
}
|
||||
|
||||
{
|
||||
value := os.Getenv(envCertificate)
|
||||
usage := fmt.Sprintf("Certificate [%s]", envCertificate)
|
||||
f.StringVar(&flag.cert, "cert", value, usage)
|
||||
}
|
||||
|
||||
{
|
||||
value := os.Getenv(envPrivateKey)
|
||||
usage := fmt.Sprintf("Private key [%s]", envPrivateKey)
|
||||
f.StringVar(&flag.key, "key", value, usage)
|
||||
}
|
||||
|
||||
{
|
||||
insecure := false
|
||||
switch env := strings.ToLower(os.Getenv(envInsecure)); env {
|
||||
case "1", "true":
|
||||
insecure = true
|
||||
}
|
||||
|
||||
usage := fmt.Sprintf("Skip verification of server certificate [%s]", envInsecure)
|
||||
f.BoolVar(&flag.insecure, "k", insecure, usage)
|
||||
}
|
||||
|
||||
{
|
||||
persist := true
|
||||
switch env := strings.ToLower(os.Getenv(envPersist)); env {
|
||||
case "0", "false":
|
||||
persist = false
|
||||
}
|
||||
|
||||
usage := fmt.Sprintf("Persist session to disk [%s]", envPersist)
|
||||
f.BoolVar(&flag.persist, "persist-session", persist, usage)
|
||||
}
|
||||
|
||||
{
|
||||
env := os.Getenv(envMinAPIVersion)
|
||||
if env == "" {
|
||||
env = defaultMinVimVersion
|
||||
}
|
||||
|
||||
flag.minAPIVersion = env
|
||||
}
|
||||
|
||||
{
|
||||
value := os.Getenv(envVimNamespace)
|
||||
if value == "" {
|
||||
value = vim25.Namespace
|
||||
}
|
||||
usage := fmt.Sprintf("Vim namespace [%s]", envVimNamespace)
|
||||
f.StringVar(&flag.vimNamespace, "vim-namespace", value, usage)
|
||||
}
|
||||
|
||||
{
|
||||
value := os.Getenv(envVimVersion)
|
||||
if value == "" {
|
||||
value = vim25.Version
|
||||
}
|
||||
usage := fmt.Sprintf("Vim version [%s]", envVimVersion)
|
||||
f.StringVar(&flag.vimVersion, "vim-version", value, usage)
|
||||
}
|
||||
|
||||
{
|
||||
value := os.Getenv(envTLSCaCerts)
|
||||
usage := fmt.Sprintf("TLS CA certificates file [%s]", envTLSCaCerts)
|
||||
f.StringVar(&flag.tlsCaCerts, "tls-ca-certs", value, usage)
|
||||
}
|
||||
|
||||
{
|
||||
value := os.Getenv(envTLSKnownHosts)
|
||||
usage := fmt.Sprintf("TLS known hosts file [%s]", envTLSKnownHosts)
|
||||
f.StringVar(&flag.tlsKnownHosts, "tls-known-hosts", value, usage)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) Process(ctx context.Context) error {
|
||||
return flag.ProcessOnce(func() error {
|
||||
err := flag.DebugFlag.Process(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if flag.url == nil {
|
||||
return errors.New("specify an " + cDescr)
|
||||
}
|
||||
|
||||
flag.username, err = session.Secret(flag.username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
flag.password, err = session.Secret(flag.password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Override username if set
|
||||
if flag.username != "" {
|
||||
var password string
|
||||
var ok bool
|
||||
|
||||
if flag.url.User != nil {
|
||||
password, ok = flag.url.User.Password()
|
||||
}
|
||||
|
||||
if ok {
|
||||
flag.url.User = url.UserPassword(flag.username, password)
|
||||
} else {
|
||||
flag.url.User = url.User(flag.username)
|
||||
}
|
||||
}
|
||||
|
||||
// Override password if set
|
||||
if flag.password != "" {
|
||||
var username string
|
||||
|
||||
if flag.url.User != nil {
|
||||
username = flag.url.User.Username()
|
||||
}
|
||||
|
||||
flag.url.User = url.UserPassword(username, flag.password)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// configure TLS and retry settings before making any connections
|
||||
func (flag *ClientFlag) configure(sc *soap.Client) (soap.RoundTripper, error) {
|
||||
if flag.cert != "" {
|
||||
cert, err := tls.LoadX509KeyPair(flag.cert, flag.key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s=%q %s=%q: %s", envCertificate, flag.cert, envPrivateKey, flag.key, err)
|
||||
}
|
||||
|
||||
sc.SetCertificate(cert)
|
||||
}
|
||||
|
||||
// Set namespace and version
|
||||
sc.Namespace = "urn:" + flag.vimNamespace
|
||||
sc.Version = flag.vimVersion
|
||||
|
||||
sc.UserAgent = fmt.Sprintf("govc/%s", Version)
|
||||
|
||||
if err := flag.SetRootCAs(sc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := sc.LoadThumbprints(flag.tlsKnownHosts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if t, ok := sc.Transport.(*http.Transport); ok {
|
||||
var err error
|
||||
|
||||
value := os.Getenv("GOVC_TLS_HANDSHAKE_TIMEOUT")
|
||||
if value != "" {
|
||||
t.TLSHandshakeTimeout, err = time.ParseDuration(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Retry twice when a temporary I/O error occurs.
|
||||
// This means a maximum of 3 attempts.
|
||||
return vim25.Retry(sc, vim25.TemporaryNetworkError(3)), nil
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) sessionFile() string {
|
||||
url := flag.URLWithoutPassword()
|
||||
|
||||
// Key session file off of full URI and insecure setting.
|
||||
// Hash key to get a predictable, canonical format.
|
||||
key := fmt.Sprintf("%s#insecure=%t", url.String(), flag.insecure)
|
||||
name := fmt.Sprintf("%040x", sha1.Sum([]byte(key)))
|
||||
return filepath.Join(home, "sessions", name)
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) saveClient(c *vim25.Client) error {
|
||||
if !flag.persist {
|
||||
return nil
|
||||
}
|
||||
|
||||
p := flag.sessionFile()
|
||||
err := os.MkdirAll(filepath.Dir(p), 0700)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f, err := os.OpenFile(p, os.O_CREATE|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
err = json.NewEncoder(f).Encode(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) restoreClient(c *vim25.Client) (bool, error) {
|
||||
if !flag.persist {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
f, err := os.Open(flag.sessionFile())
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return false, err
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
dec := json.NewDecoder(f)
|
||||
err = dec.Decode(c)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) loadClient() (*vim25.Client, error) {
|
||||
c := new(vim25.Client)
|
||||
ok, err := flag.restoreClient(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !ok || !c.Valid() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
c.RoundTripper, err = flag.configure(c.Client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m := session.NewManager(c)
|
||||
u, err := m.UserSession(context.TODO())
|
||||
if err != nil {
|
||||
if soap.IsSoapFault(err) {
|
||||
fault := soap.ToSoapFault(err).VimFault()
|
||||
// If the PropertyCollector is not found, the saved session for this URL is not valid
|
||||
if _, ok := fault.(types.ManagedObjectNotFound); ok {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If the session is nil, the client is not authenticated
|
||||
if u == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) SetRootCAs(c *soap.Client) error {
|
||||
if flag.tlsCaCerts != "" {
|
||||
return c.SetRootCAs(flag.tlsCaCerts)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) login(ctx context.Context, c *vim25.Client) error {
|
||||
m := session.NewManager(c)
|
||||
u := flag.url.User
|
||||
name := u.Username()
|
||||
|
||||
if name == "" && !c.IsVC() {
|
||||
// If no username is provided, try to acquire a local ticket.
|
||||
// When invoked remotely, ESX returns an InvalidRequestFault.
|
||||
// So, rather than return an error here, fallthrough to Login() with the original User to
|
||||
// to avoid what would be a confusing error message.
|
||||
luser, lerr := flag.localTicket(ctx, m)
|
||||
if lerr == nil {
|
||||
// We are running directly on an ESX or Workstation host and can use the ticket with Login()
|
||||
u = luser
|
||||
name = u.Username()
|
||||
}
|
||||
}
|
||||
if name == "" {
|
||||
// Skip auto-login if we don't have a username
|
||||
flag.persist = true // Not persisting, but this avoids the call to Logout()
|
||||
return nil // Avoid SaveSession for non-authenticated session
|
||||
}
|
||||
|
||||
return m.Login(ctx, u)
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) newClient() (*vim25.Client, error) {
|
||||
ctx := context.TODO()
|
||||
sc := soap.NewClient(flag.url, flag.insecure)
|
||||
|
||||
rt, err := flag.configure(sc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, err := vim25.NewClient(ctx, rt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set client, since we didn't pass it in the constructor
|
||||
c.Client = sc
|
||||
|
||||
if flag.vimVersion == "" {
|
||||
if err = c.UseServiceVersion(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
flag.vimVersion = c.Version
|
||||
}
|
||||
|
||||
if err := flag.Login(ctx, c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c, flag.saveClient(c)
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) localTicket(ctx context.Context, m *session.Manager) (*url.Userinfo, error) {
|
||||
ticket, err := m.AcquireLocalTicket(ctx, os.Getenv("USER"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
password, err := ioutil.ReadFile(ticket.PasswordFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return url.UserPassword(ticket.UserName, string(password)), nil
|
||||
}
|
||||
|
||||
func isDevelopmentVersion(apiVersion string) bool {
|
||||
// Skip version check for development builds which can be in the form of "r4A70F" or "6.5.x"
|
||||
return strings.Count(apiVersion, ".") == 0 || strings.HasSuffix(apiVersion, ".x")
|
||||
}
|
||||
|
||||
// apiVersionValid returns whether or not the API version supported by the
|
||||
// server the client is connected to is not recent enough.
|
||||
func apiVersionValid(c *vim25.Client, minVersionString string) error {
|
||||
if minVersionString == "-" {
|
||||
// Disable version check
|
||||
return nil
|
||||
}
|
||||
|
||||
apiVersion := c.ServiceContent.About.ApiVersion
|
||||
if isDevelopmentVersion(apiVersion) {
|
||||
return nil
|
||||
}
|
||||
|
||||
realVersion, err := ParseVersion(apiVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing API version %q: %s", apiVersion, err)
|
||||
}
|
||||
|
||||
minVersion, err := ParseVersion(minVersionString)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing %s=%q: %s", envMinAPIVersion, minVersionString, err)
|
||||
}
|
||||
|
||||
if !minVersion.Lte(realVersion) {
|
||||
err = fmt.Errorf("require API version %q, connected to API version %q (set %s to override)",
|
||||
minVersionString,
|
||||
c.ServiceContent.About.ApiVersion,
|
||||
envMinAPIVersion)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) Client() (*vim25.Client, error) {
|
||||
if flag.client != nil {
|
||||
return flag.client, nil
|
||||
}
|
||||
|
||||
c, err := flag.loadClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// loadClient returns nil if it was unable to load a session from disk
|
||||
if c == nil {
|
||||
c, err = flag.newClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the endpoint has the right API version
|
||||
err = apiVersionValid(c, flag.minAPIVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
flag.client = c
|
||||
return flag.client, nil
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) Logout(ctx context.Context) error {
|
||||
if flag.persist || flag.client == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
m := session.NewManager(flag.client)
|
||||
|
||||
return m.Logout(ctx)
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) WithRestClient(ctx context.Context, f func(*rest.Client) error) error {
|
||||
vc, err := flag.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c := rest.NewClient(vc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: rest.Client session cookie should be persisted as the soap.Client session cookie is.
|
||||
if vc.Certificate() == nil {
|
||||
if err = c.Login(ctx, flag.Userinfo()); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// TODO: session.login should support rest.Client SSO login to avoid this env var (depends on the TODO above)
|
||||
token := os.Getenv("GOVC_LOGIN_TOKEN")
|
||||
if token == "" {
|
||||
return errors.New("GOVC_LOGIN_TOKEN must be set for rest.Client SSO login")
|
||||
}
|
||||
signer := &sts.Signer{
|
||||
Certificate: c.Certificate(),
|
||||
Token: token,
|
||||
}
|
||||
|
||||
if err = c.LoginByToken(c.WithSigner(ctx, signer)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := c.Logout(ctx); err != nil {
|
||||
log.Printf("user logout error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return f(c)
|
||||
}
|
||||
|
||||
// Environ returns the govc environment variables for this connection
|
||||
func (flag *ClientFlag) Environ(extra bool) []string {
|
||||
var env []string
|
||||
add := func(k, v string) {
|
||||
env = append(env, fmt.Sprintf("%s=%s", k, v))
|
||||
}
|
||||
|
||||
u := *flag.url
|
||||
if u.User != nil {
|
||||
add(envUsername, u.User.Username())
|
||||
|
||||
if p, ok := u.User.Password(); ok {
|
||||
add(envPassword, p)
|
||||
}
|
||||
|
||||
u.User = nil
|
||||
}
|
||||
|
||||
if u.Path == vim25.Path {
|
||||
u.Path = ""
|
||||
}
|
||||
u.Fragment = ""
|
||||
u.RawQuery = ""
|
||||
|
||||
add(envURL, strings.TrimPrefix(u.String(), "https://"))
|
||||
|
||||
keys := []string{
|
||||
envCertificate,
|
||||
envPrivateKey,
|
||||
envInsecure,
|
||||
envPersist,
|
||||
envMinAPIVersion,
|
||||
envVimNamespace,
|
||||
envVimVersion,
|
||||
}
|
||||
|
||||
for _, k := range keys {
|
||||
if v := os.Getenv(k); v != "" {
|
||||
add(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
if extra {
|
||||
add("GOVC_URL_SCHEME", flag.url.Scheme)
|
||||
|
||||
v := strings.SplitN(u.Host, ":", 2)
|
||||
add("GOVC_URL_HOST", v[0])
|
||||
if len(v) == 2 {
|
||||
add("GOVC_URL_PORT", v[1])
|
||||
}
|
||||
|
||||
add("GOVC_URL_PATH", flag.url.Path)
|
||||
|
||||
if f := flag.url.Fragment; f != "" {
|
||||
add("GOVC_URL_FRAGMENT", f)
|
||||
}
|
||||
|
||||
if q := flag.url.RawQuery; q != "" {
|
||||
add("GOVC_URL_QUERY", q)
|
||||
}
|
||||
}
|
||||
|
||||
return env
|
||||
}
|
||||
|
||||
// WithCancel calls the given function, returning when complete or canceled via SIGINT.
|
||||
func (flag *ClientFlag) WithCancel(ctx context.Context, f func(context.Context) error) error {
|
||||
sig := make(chan os.Signal, 1)
|
||||
signal.Notify(sig, syscall.SIGINT)
|
||||
|
||||
wctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
done := make(chan bool)
|
||||
var werr error
|
||||
|
||||
go func() {
|
||||
defer close(done)
|
||||
werr = f(wctx)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-sig:
|
||||
cancel()
|
||||
<-done // Wait for f() to complete
|
||||
case <-done:
|
||||
}
|
||||
|
||||
return werr
|
||||
}
|
||||
204
vendor/github.com/vmware/govmomi/govc/flags/cluster.go
generated
vendored
Normal file
204
vendor/github.com/vmware/govmomi/govc/flags/cluster.go
generated
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/view"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type ClusterFlag struct {
|
||||
common
|
||||
|
||||
*DatacenterFlag
|
||||
|
||||
Name string
|
||||
|
||||
cluster *object.ClusterComputeResource
|
||||
pc *property.Collector
|
||||
}
|
||||
|
||||
var clusterFlagKey = flagKey("cluster")
|
||||
|
||||
func NewClusterFlag(ctx context.Context) (*ClusterFlag, context.Context) {
|
||||
if v := ctx.Value(clusterFlagKey); v != nil {
|
||||
return v.(*ClusterFlag), ctx
|
||||
}
|
||||
|
||||
v := &ClusterFlag{}
|
||||
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
|
||||
ctx = context.WithValue(ctx, clusterFlagKey, v)
|
||||
return v, ctx
|
||||
}
|
||||
|
||||
func (f *ClusterFlag) Register(ctx context.Context, fs *flag.FlagSet) {
|
||||
f.RegisterOnce(func() {
|
||||
f.DatacenterFlag.Register(ctx, fs)
|
||||
|
||||
env := "GOVC_CLUSTER"
|
||||
value := os.Getenv(env)
|
||||
usage := fmt.Sprintf("Cluster [%s]", env)
|
||||
fs.StringVar(&f.Name, "cluster", value, usage)
|
||||
})
|
||||
}
|
||||
|
||||
// RegisterPlacement registers the -cluster flag without using GOVC_CLUSTER env as the default value,
|
||||
// usage is specific to VM placement.
|
||||
func (f *ClusterFlag) RegisterPlacement(ctx context.Context, fs *flag.FlagSet) {
|
||||
f.RegisterOnce(func() {
|
||||
f.DatacenterFlag.Register(ctx, fs)
|
||||
|
||||
fs.StringVar(&f.Name, "cluster", "", "Use cluster for VM placement via DRS")
|
||||
})
|
||||
}
|
||||
|
||||
func (f *ClusterFlag) Process(ctx context.Context) error {
|
||||
return f.ProcessOnce(func() error {
|
||||
if err := f.DatacenterFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (f *ClusterFlag) Cluster() (*object.ClusterComputeResource, error) {
|
||||
if f.cluster != nil {
|
||||
return f.cluster, nil
|
||||
}
|
||||
|
||||
finder, err := f.Finder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if f.cluster, err = finder.ClusterComputeResourceOrDefault(context.TODO(), f.Name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f.pc = property.DefaultCollector(f.cluster.Client())
|
||||
|
||||
return f.cluster, nil
|
||||
}
|
||||
|
||||
func (f *ClusterFlag) ClusterIfSpecified() (*object.ClusterComputeResource, error) {
|
||||
if f.Name == "" {
|
||||
return nil, nil
|
||||
}
|
||||
return f.Cluster()
|
||||
}
|
||||
|
||||
func (f *ClusterFlag) Reconfigure(ctx context.Context, spec types.BaseComputeResourceConfigSpec) error {
|
||||
cluster, err := f.Cluster()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
task, err := cluster.Reconfigure(ctx, spec, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logger := f.ProgressLogger(fmt.Sprintf("Reconfigure %s...", cluster.InventoryPath))
|
||||
defer logger.Wait()
|
||||
|
||||
_, err = task.WaitForResult(ctx, logger)
|
||||
return err
|
||||
}
|
||||
|
||||
func (f *ClusterFlag) objectMap(ctx context.Context, kind string, names []string) (map[string]types.ManagedObjectReference, error) {
|
||||
cluster, err := f.Cluster()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
objects := make(map[string]types.ManagedObjectReference, len(names))
|
||||
for _, name := range names {
|
||||
objects[name] = types.ManagedObjectReference{}
|
||||
}
|
||||
|
||||
m := view.NewManager(cluster.Client())
|
||||
v, err := m.CreateContainerView(ctx, cluster.Reference(), []string{kind}, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_ = v.Destroy(ctx)
|
||||
}()
|
||||
|
||||
var entities []mo.ManagedEntity
|
||||
|
||||
err = v.Retrieve(ctx, []string{"ManagedEntity"}, []string{"name"}, &entities)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, e := range entities {
|
||||
if _, ok := objects[e.Name]; ok {
|
||||
objects[e.Name] = e.Self
|
||||
}
|
||||
}
|
||||
|
||||
for name, ref := range objects {
|
||||
if ref.Value == "" {
|
||||
return nil, fmt.Errorf("%s %q not found", kind, name)
|
||||
}
|
||||
}
|
||||
|
||||
return objects, nil
|
||||
}
|
||||
|
||||
func (f *ClusterFlag) ObjectList(ctx context.Context, kind string, names []string) ([]types.ManagedObjectReference, error) {
|
||||
objs, err := f.objectMap(ctx, kind, names)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var refs []types.ManagedObjectReference
|
||||
|
||||
for _, name := range names { // preserve order
|
||||
refs = append(refs, objs[name])
|
||||
}
|
||||
|
||||
return refs, nil
|
||||
}
|
||||
|
||||
func (f *ClusterFlag) Names(ctx context.Context, refs []types.ManagedObjectReference) (map[types.ManagedObjectReference]string, error) {
|
||||
names := make(map[types.ManagedObjectReference]string, len(refs))
|
||||
|
||||
if len(refs) != 0 {
|
||||
var objs []mo.ManagedEntity
|
||||
err := f.pc.Retrieve(ctx, refs, []string{"name"}, &objs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, obj := range objs {
|
||||
names[obj.Self] = obj.Name
|
||||
}
|
||||
}
|
||||
|
||||
return names, nil
|
||||
}
|
||||
38
vendor/github.com/vmware/govmomi/govc/flags/common.go
generated
vendored
Normal file
38
vendor/github.com/vmware/govmomi/govc/flags/common.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright (c) 2015-2016 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package flags
|
||||
|
||||
import "sync"
|
||||
|
||||
// Key type for storing flag instances in a context.Context.
|
||||
type flagKey string
|
||||
|
||||
// Type to help flags out with only registering/processing once.
|
||||
type common struct {
|
||||
register sync.Once
|
||||
process sync.Once
|
||||
}
|
||||
|
||||
func (c *common) RegisterOnce(fn func()) {
|
||||
c.register.Do(fn)
|
||||
}
|
||||
|
||||
func (c *common) ProcessOnce(fn func() error) (err error) {
|
||||
c.process.Do(func() {
|
||||
err = fn()
|
||||
})
|
||||
return err
|
||||
}
|
||||
221
vendor/github.com/vmware/govmomi/govc/flags/datacenter.go
generated
vendored
Normal file
221
vendor/github.com/vmware/govmomi/govc/flags/datacenter.go
generated
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/find"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type DatacenterFlag struct {
|
||||
common
|
||||
|
||||
*ClientFlag
|
||||
*OutputFlag
|
||||
|
||||
Name string
|
||||
dc *object.Datacenter
|
||||
finder *find.Finder
|
||||
err error
|
||||
}
|
||||
|
||||
var datacenterFlagKey = flagKey("datacenter")
|
||||
|
||||
func NewDatacenterFlag(ctx context.Context) (*DatacenterFlag, context.Context) {
|
||||
if v := ctx.Value(datacenterFlagKey); v != nil {
|
||||
return v.(*DatacenterFlag), ctx
|
||||
}
|
||||
|
||||
v := &DatacenterFlag{}
|
||||
v.ClientFlag, ctx = NewClientFlag(ctx)
|
||||
v.OutputFlag, ctx = NewOutputFlag(ctx)
|
||||
ctx = context.WithValue(ctx, datacenterFlagKey, v)
|
||||
return v, ctx
|
||||
}
|
||||
|
||||
func (flag *DatacenterFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
flag.RegisterOnce(func() {
|
||||
flag.ClientFlag.Register(ctx, f)
|
||||
flag.OutputFlag.Register(ctx, f)
|
||||
|
||||
env := "GOVC_DATACENTER"
|
||||
value := os.Getenv(env)
|
||||
usage := fmt.Sprintf("Datacenter [%s]", env)
|
||||
f.StringVar(&flag.Name, "dc", value, usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *DatacenterFlag) Process(ctx context.Context) error {
|
||||
return flag.ProcessOnce(func() error {
|
||||
if err := flag.ClientFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := flag.OutputFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *DatacenterFlag) Finder(all ...bool) (*find.Finder, error) {
|
||||
if flag.finder != nil {
|
||||
return flag.finder, nil
|
||||
}
|
||||
|
||||
c, err := flag.Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
allFlag := false
|
||||
if len(all) == 1 {
|
||||
allFlag = all[0]
|
||||
}
|
||||
finder := find.NewFinder(c, allFlag)
|
||||
|
||||
// Datacenter is not required (ls command for example).
|
||||
// Set for relative func if dc flag is given or
|
||||
// if there is a single (default) Datacenter
|
||||
ctx := context.TODO()
|
||||
if flag.Name == "" {
|
||||
flag.dc, flag.err = finder.DefaultDatacenter(ctx)
|
||||
} else {
|
||||
if flag.dc, err = finder.Datacenter(ctx, flag.Name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
finder.SetDatacenter(flag.dc)
|
||||
|
||||
flag.finder = finder
|
||||
|
||||
return flag.finder, nil
|
||||
}
|
||||
|
||||
func (flag *DatacenterFlag) Datacenter() (*object.Datacenter, error) {
|
||||
if flag.dc != nil {
|
||||
return flag.dc, nil
|
||||
}
|
||||
|
||||
_, err := flag.Finder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if flag.err != nil {
|
||||
// Should only happen if no dc is specified and len(dcs) > 1
|
||||
return nil, flag.err
|
||||
}
|
||||
|
||||
return flag.dc, err
|
||||
}
|
||||
|
||||
func (flag *DatacenterFlag) DatacenterIfSpecified() (*object.Datacenter, error) {
|
||||
if flag.Name == "" {
|
||||
return nil, nil
|
||||
}
|
||||
return flag.Datacenter()
|
||||
}
|
||||
|
||||
func (flag *DatacenterFlag) ManagedObject(ctx context.Context, arg string) (types.ManagedObjectReference, error) {
|
||||
var ref types.ManagedObjectReference
|
||||
|
||||
finder, err := flag.Finder()
|
||||
if err != nil {
|
||||
return ref, err
|
||||
}
|
||||
|
||||
if ref.FromString(arg) {
|
||||
if strings.HasPrefix(ref.Type, "com.vmware.content.") {
|
||||
return ref, nil // special case for content library
|
||||
}
|
||||
pc := property.DefaultCollector(flag.client)
|
||||
var content []types.ObjectContent
|
||||
err = pc.RetrieveOne(ctx, ref, []string{"name"}, &content)
|
||||
if err == nil {
|
||||
return ref, nil
|
||||
}
|
||||
}
|
||||
|
||||
l, err := finder.ManagedObjectList(ctx, arg)
|
||||
if err != nil {
|
||||
return ref, err
|
||||
}
|
||||
|
||||
switch len(l) {
|
||||
case 0:
|
||||
return ref, fmt.Errorf("%s not found", arg)
|
||||
case 1:
|
||||
return l[0].Object.Reference(), nil
|
||||
default:
|
||||
var objs []types.ManagedObjectReference
|
||||
for _, o := range l {
|
||||
objs = append(objs, o.Object.Reference())
|
||||
}
|
||||
return ref, fmt.Errorf("%d objects at path %q: %s", len(l), arg, objs)
|
||||
}
|
||||
}
|
||||
|
||||
func (flag *DatacenterFlag) ManagedObjects(ctx context.Context, args []string) ([]types.ManagedObjectReference, error) {
|
||||
var refs []types.ManagedObjectReference
|
||||
|
||||
c, err := flag.Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
refs = append(refs, c.ServiceContent.RootFolder)
|
||||
return refs, nil
|
||||
}
|
||||
|
||||
finder, err := flag.Finder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, arg := range args {
|
||||
var ref types.ManagedObjectReference
|
||||
if ref.FromString(arg) {
|
||||
// e.g. output from object.collect
|
||||
refs = append(refs, ref)
|
||||
continue
|
||||
}
|
||||
elements, err := finder.ManagedObjectList(ctx, arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(elements) == 0 {
|
||||
return nil, fmt.Errorf("object '%s' not found", arg)
|
||||
}
|
||||
|
||||
for _, e := range elements {
|
||||
refs = append(refs, e.Object.Reference())
|
||||
}
|
||||
}
|
||||
|
||||
return refs, nil
|
||||
}
|
||||
146
vendor/github.com/vmware/govmomi/govc/flags/datastore.go
generated
vendored
Normal file
146
vendor/github.com/vmware/govmomi/govc/flags/datastore.go
generated
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type DatastoreFlag struct {
|
||||
common
|
||||
|
||||
*DatacenterFlag
|
||||
|
||||
Name string
|
||||
|
||||
ds *object.Datastore
|
||||
}
|
||||
|
||||
var datastoreFlagKey = flagKey("datastore")
|
||||
|
||||
// NewCustomDatastoreFlag creates and returns a new DatastoreFlag without
|
||||
// trying to retrieve an existing one from the specified context.
|
||||
func NewCustomDatastoreFlag(ctx context.Context) (*DatastoreFlag, context.Context) {
|
||||
v := &DatastoreFlag{}
|
||||
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
|
||||
return v, ctx
|
||||
}
|
||||
|
||||
func NewDatastoreFlag(ctx context.Context) (*DatastoreFlag, context.Context) {
|
||||
if v := ctx.Value(datastoreFlagKey); v != nil {
|
||||
return v.(*DatastoreFlag), ctx
|
||||
}
|
||||
|
||||
v, ctx := NewCustomDatastoreFlag(ctx)
|
||||
ctx = context.WithValue(ctx, datastoreFlagKey, v)
|
||||
return v, ctx
|
||||
}
|
||||
|
||||
func (f *DatastoreFlag) Register(ctx context.Context, fs *flag.FlagSet) {
|
||||
f.RegisterOnce(func() {
|
||||
f.DatacenterFlag.Register(ctx, fs)
|
||||
|
||||
env := "GOVC_DATASTORE"
|
||||
value := os.Getenv(env)
|
||||
usage := fmt.Sprintf("Datastore [%s]", env)
|
||||
fs.StringVar(&f.Name, "ds", value, usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (f *DatastoreFlag) Process(ctx context.Context) error {
|
||||
return f.ProcessOnce(func() error {
|
||||
if err := f.DatacenterFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (f *DatastoreFlag) Args(args []string) []object.DatastorePath {
|
||||
var files []object.DatastorePath
|
||||
|
||||
for _, arg := range args {
|
||||
var p object.DatastorePath
|
||||
|
||||
if p.FromString(arg) {
|
||||
f.Name = p.Datastore
|
||||
} else {
|
||||
p.Datastore = f.Name
|
||||
p.Path = arg
|
||||
}
|
||||
|
||||
files = append(files, p)
|
||||
}
|
||||
|
||||
return files
|
||||
}
|
||||
|
||||
func (f *DatastoreFlag) Datastore() (*object.Datastore, error) {
|
||||
if f.ds != nil {
|
||||
return f.ds, nil
|
||||
}
|
||||
|
||||
var p object.DatastorePath
|
||||
if p.FromString(f.Name) {
|
||||
// Example use case:
|
||||
// -ds "$(govc object.collect -s vm/foo config.files.logDirectory)"
|
||||
f.Name = p.Datastore
|
||||
}
|
||||
|
||||
finder, err := f.Finder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if f.ds, err = finder.DatastoreOrDefault(context.TODO(), f.Name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return f.ds, nil
|
||||
}
|
||||
|
||||
func (flag *DatastoreFlag) DatastoreIfSpecified() (*object.Datastore, error) {
|
||||
if flag.Name == "" {
|
||||
return nil, nil
|
||||
}
|
||||
return flag.Datastore()
|
||||
}
|
||||
|
||||
func (f *DatastoreFlag) DatastorePath(name string) (string, error) {
|
||||
ds, err := f.Datastore()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return ds.Path(name), nil
|
||||
}
|
||||
|
||||
func (f *DatastoreFlag) Stat(ctx context.Context, file string) (types.BaseFileInfo, error) {
|
||||
ds, err := f.Datastore()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ds.Stat(ctx, file)
|
||||
|
||||
}
|
||||
103
vendor/github.com/vmware/govmomi/govc/flags/debug.go
generated
vendored
Normal file
103
vendor/github.com/vmware/govmomi/govc/flags/debug.go
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/debug"
|
||||
)
|
||||
|
||||
type DebugFlag struct {
|
||||
common
|
||||
|
||||
enable bool
|
||||
}
|
||||
|
||||
var debugFlagKey = flagKey("debug")
|
||||
|
||||
func NewDebugFlag(ctx context.Context) (*DebugFlag, context.Context) {
|
||||
if v := ctx.Value(debugFlagKey); v != nil {
|
||||
return v.(*DebugFlag), ctx
|
||||
}
|
||||
|
||||
v := &DebugFlag{}
|
||||
ctx = context.WithValue(ctx, debugFlagKey, v)
|
||||
return v, ctx
|
||||
}
|
||||
|
||||
func (flag *DebugFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
flag.RegisterOnce(func() {
|
||||
env := "GOVC_DEBUG"
|
||||
enable := false
|
||||
switch env := strings.ToLower(os.Getenv(env)); env {
|
||||
case "1", "true":
|
||||
enable = true
|
||||
}
|
||||
|
||||
usage := fmt.Sprintf("Store debug logs [%s]", env)
|
||||
f.BoolVar(&flag.enable, "debug", enable, usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *DebugFlag) Process(ctx context.Context) error {
|
||||
if !flag.enable {
|
||||
return nil
|
||||
}
|
||||
|
||||
return flag.ProcessOnce(func() error {
|
||||
// Base path for storing debug logs.
|
||||
r := os.Getenv("GOVC_DEBUG_PATH")
|
||||
switch r {
|
||||
case "-":
|
||||
debug.SetProvider(&debug.LogProvider{})
|
||||
return nil
|
||||
case "":
|
||||
r = home
|
||||
}
|
||||
r = filepath.Join(r, "debug")
|
||||
|
||||
// Path for this particular run.
|
||||
run := os.Getenv("GOVC_DEBUG_PATH_RUN")
|
||||
if run == "" {
|
||||
now := time.Now().Format("2006-01-02T15-04-05.999999999")
|
||||
r = filepath.Join(r, now)
|
||||
} else {
|
||||
// reuse the same path
|
||||
r = filepath.Join(r, run)
|
||||
_ = os.RemoveAll(r)
|
||||
}
|
||||
|
||||
err := os.MkdirAll(r, 0700)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p := debug.FileProvider{
|
||||
Path: r,
|
||||
}
|
||||
|
||||
debug.SetProvider(&p)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
31
vendor/github.com/vmware/govmomi/govc/flags/empty.go
generated
vendored
Normal file
31
vendor/github.com/vmware/govmomi/govc/flags/empty.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
)
|
||||
|
||||
type EmptyFlag struct{}
|
||||
|
||||
func (flag *EmptyFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
}
|
||||
|
||||
func (flag *EmptyFlag) Process(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
131
vendor/github.com/vmware/govmomi/govc/flags/folder.go
generated
vendored
Normal file
131
vendor/github.com/vmware/govmomi/govc/flags/folder.go
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
)
|
||||
|
||||
type FolderFlag struct {
|
||||
common
|
||||
|
||||
*DatacenterFlag
|
||||
|
||||
name string
|
||||
folder *object.Folder
|
||||
}
|
||||
|
||||
var folderFlagKey = flagKey("folder")
|
||||
|
||||
func NewFolderFlag(ctx context.Context) (*FolderFlag, context.Context) {
|
||||
if v := ctx.Value(folderFlagKey); v != nil {
|
||||
return v.(*FolderFlag), ctx
|
||||
}
|
||||
|
||||
v := &FolderFlag{}
|
||||
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
|
||||
ctx = context.WithValue(ctx, folderFlagKey, v)
|
||||
return v, ctx
|
||||
}
|
||||
|
||||
func (flag *FolderFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
flag.RegisterOnce(func() {
|
||||
flag.DatacenterFlag.Register(ctx, f)
|
||||
|
||||
env := "GOVC_FOLDER"
|
||||
value := os.Getenv(env)
|
||||
usage := fmt.Sprintf("Inventory folder [%s]", env)
|
||||
f.StringVar(&flag.name, "folder", value, usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *FolderFlag) Process(ctx context.Context) error {
|
||||
return flag.ProcessOnce(func() error {
|
||||
if err := flag.DatacenterFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *FolderFlag) Folder() (*object.Folder, error) {
|
||||
if flag.folder != nil {
|
||||
return flag.folder, nil
|
||||
}
|
||||
|
||||
finder, err := flag.Finder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if flag.folder, err = finder.FolderOrDefault(context.TODO(), flag.name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return flag.folder, nil
|
||||
}
|
||||
|
||||
func (flag *FolderFlag) FolderOrDefault(kind string) (*object.Folder, error) {
|
||||
if flag.folder != nil {
|
||||
return flag.folder, nil
|
||||
}
|
||||
|
||||
if flag.name != "" {
|
||||
return flag.Folder()
|
||||
}
|
||||
|
||||
// RootFolder, no dc required
|
||||
if kind == "/" {
|
||||
client, err := flag.Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
flag.folder = object.NewRootFolder(client)
|
||||
return flag.folder, nil
|
||||
}
|
||||
|
||||
dc, err := flag.Datacenter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
folders, err := dc.Folders(context.TODO())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch kind {
|
||||
case "vm":
|
||||
flag.folder = folders.VmFolder
|
||||
case "host":
|
||||
flag.folder = folders.HostFolder
|
||||
case "datastore":
|
||||
flag.folder = folders.DatastoreFolder
|
||||
case "network":
|
||||
flag.folder = folders.NetworkFolder
|
||||
default:
|
||||
panic(kind)
|
||||
}
|
||||
|
||||
return flag.folder, nil
|
||||
}
|
||||
101
vendor/github.com/vmware/govmomi/govc/flags/host_connect.go
generated
vendored
Normal file
101
vendor/github.com/vmware/govmomi/govc/flags/host_connect.go
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type HostConnectFlag struct {
|
||||
common
|
||||
|
||||
types.HostConnectSpec
|
||||
|
||||
noverify bool
|
||||
}
|
||||
|
||||
var hostConnectFlagKey = flagKey("hostConnect")
|
||||
|
||||
func NewHostConnectFlag(ctx context.Context) (*HostConnectFlag, context.Context) {
|
||||
if v := ctx.Value(hostConnectFlagKey); v != nil {
|
||||
return v.(*HostConnectFlag), ctx
|
||||
}
|
||||
|
||||
v := &HostConnectFlag{}
|
||||
ctx = context.WithValue(ctx, hostConnectFlagKey, v)
|
||||
return v, ctx
|
||||
}
|
||||
|
||||
func (flag *HostConnectFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
flag.RegisterOnce(func() {
|
||||
f.StringVar(&flag.HostName, "hostname", "", "Hostname or IP address of the host")
|
||||
f.StringVar(&flag.UserName, "username", "", "Username of administration account on the host")
|
||||
f.StringVar(&flag.Password, "password", "", "Password of administration account on the host")
|
||||
f.StringVar(&flag.SslThumbprint, "thumbprint", "", "SHA-1 thumbprint of the host's SSL certificate")
|
||||
f.BoolVar(&flag.Force, "force", false, "Force when host is managed by another VC")
|
||||
|
||||
f.BoolVar(&flag.noverify, "noverify", false, "Accept host thumbprint without verification")
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *HostConnectFlag) Process(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Spec attempts to fill in SslThumbprint if empty.
|
||||
// First checks GOVC_TLS_KNOWN_HOSTS, if not found and noverify=true then
|
||||
// use object.HostCertificateInfo to get the thumbprint.
|
||||
func (flag *HostConnectFlag) Spec(c *vim25.Client) types.HostConnectSpec {
|
||||
spec := flag.HostConnectSpec
|
||||
|
||||
if spec.SslThumbprint == "" {
|
||||
spec.SslThumbprint = c.Thumbprint(spec.HostName)
|
||||
|
||||
if spec.SslThumbprint == "" && flag.noverify {
|
||||
var info object.HostCertificateInfo
|
||||
t := c.Transport.(*http.Transport)
|
||||
_ = info.FromURL(&url.URL{Host: spec.HostName}, t.TLSClientConfig)
|
||||
spec.SslThumbprint = info.ThumbprintSHA1
|
||||
}
|
||||
}
|
||||
|
||||
return spec
|
||||
}
|
||||
|
||||
// Fault checks if error is SSLVerifyFault, including the thumbprint if so
|
||||
func (flag *HostConnectFlag) Fault(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if f, ok := err.(types.HasFault); ok {
|
||||
switch fault := f.Fault().(type) {
|
||||
case *types.SSLVerifyFault:
|
||||
return fmt.Errorf("%s thumbprint=%s", err, fault.Thumbprint)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
141
vendor/github.com/vmware/govmomi/govc/flags/host_system.go
generated
vendored
Normal file
141
vendor/github.com/vmware/govmomi/govc/flags/host_system.go
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
)
|
||||
|
||||
type HostSystemFlag struct {
|
||||
common
|
||||
|
||||
*ClientFlag
|
||||
*DatacenterFlag
|
||||
*SearchFlag
|
||||
|
||||
name string
|
||||
host *object.HostSystem
|
||||
pool *object.ResourcePool
|
||||
}
|
||||
|
||||
var hostSystemFlagKey = flagKey("hostSystem")
|
||||
|
||||
func NewHostSystemFlag(ctx context.Context) (*HostSystemFlag, context.Context) {
|
||||
if v := ctx.Value(hostSystemFlagKey); v != nil {
|
||||
return v.(*HostSystemFlag), ctx
|
||||
}
|
||||
|
||||
v := &HostSystemFlag{}
|
||||
v.ClientFlag, ctx = NewClientFlag(ctx)
|
||||
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
|
||||
v.SearchFlag, ctx = NewSearchFlag(ctx, SearchHosts)
|
||||
ctx = context.WithValue(ctx, hostSystemFlagKey, v)
|
||||
return v, ctx
|
||||
}
|
||||
|
||||
func (flag *HostSystemFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
flag.RegisterOnce(func() {
|
||||
flag.ClientFlag.Register(ctx, f)
|
||||
flag.DatacenterFlag.Register(ctx, f)
|
||||
flag.SearchFlag.Register(ctx, f)
|
||||
|
||||
env := "GOVC_HOST"
|
||||
value := os.Getenv(env)
|
||||
usage := fmt.Sprintf("Host system [%s]", env)
|
||||
f.StringVar(&flag.name, "host", value, usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *HostSystemFlag) Process(ctx context.Context) error {
|
||||
return flag.ProcessOnce(func() error {
|
||||
if err := flag.ClientFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := flag.DatacenterFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := flag.SearchFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *HostSystemFlag) HostSystemIfSpecified() (*object.HostSystem, error) {
|
||||
if flag.host != nil {
|
||||
return flag.host, nil
|
||||
}
|
||||
|
||||
// Use search flags if specified.
|
||||
if flag.SearchFlag.IsSet() {
|
||||
host, err := flag.SearchFlag.HostSystem()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
flag.host = host
|
||||
return flag.host, nil
|
||||
}
|
||||
|
||||
// Never look for a default host system.
|
||||
// A host system parameter is optional for vm creation. It uses a mandatory
|
||||
// resource pool parameter to determine where the vm should be placed.
|
||||
if flag.name == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
finder, err := flag.Finder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
flag.host, err = finder.HostSystem(context.TODO(), flag.name)
|
||||
return flag.host, err
|
||||
}
|
||||
|
||||
func (flag *HostSystemFlag) HostSystem() (*object.HostSystem, error) {
|
||||
host, err := flag.HostSystemIfSpecified()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if host != nil {
|
||||
return host, nil
|
||||
}
|
||||
|
||||
finder, err := flag.Finder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
flag.host, err = finder.DefaultHostSystem(context.TODO())
|
||||
return flag.host, err
|
||||
}
|
||||
|
||||
func (flag *HostSystemFlag) HostNetworkSystem() (*object.HostNetworkSystem, error) {
|
||||
host, err := flag.HostSystem()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return host.ConfigManager().NetworkSystem(context.TODO())
|
||||
}
|
||||
72
vendor/github.com/vmware/govmomi/govc/flags/int32.go
generated
vendored
Normal file
72
vendor/github.com/vmware/govmomi/govc/flags/int32.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright (c) 2016-2017 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// This flag type is internal to stdlib:
|
||||
// https://github.com/golang/go/blob/master/src/cmd/internal/obj/flag.go
|
||||
type int32Value int32
|
||||
|
||||
func (i *int32Value) Set(s string) error {
|
||||
v, err := strconv.ParseInt(s, 0, 32)
|
||||
*i = int32Value(v)
|
||||
return err
|
||||
}
|
||||
|
||||
func (i *int32Value) Get() interface{} {
|
||||
return int32(*i)
|
||||
}
|
||||
|
||||
func (i *int32Value) String() string {
|
||||
return fmt.Sprintf("%v", *i)
|
||||
}
|
||||
|
||||
// NewInt32 behaves as flag.IntVar, but using an int32 type.
|
||||
func NewInt32(v *int32) flag.Value {
|
||||
return (*int32Value)(v)
|
||||
}
|
||||
|
||||
type int32ptrValue struct {
|
||||
val **int32
|
||||
}
|
||||
|
||||
func (i *int32ptrValue) Set(s string) error {
|
||||
v, err := strconv.ParseInt(s, 0, 32)
|
||||
*i.val = new(int32)
|
||||
**i.val = int32(v)
|
||||
return err
|
||||
}
|
||||
|
||||
func (i *int32ptrValue) Get() interface{} {
|
||||
if i.val == nil || *i.val == nil {
|
||||
return nil
|
||||
}
|
||||
return *i.val
|
||||
}
|
||||
|
||||
func (i *int32ptrValue) String() string {
|
||||
return fmt.Sprintf("%v", i.Get())
|
||||
}
|
||||
|
||||
func NewOptionalInt32(v **int32) flag.Value {
|
||||
return &int32ptrValue{val: v}
|
||||
}
|
||||
72
vendor/github.com/vmware/govmomi/govc/flags/int64.go
generated
vendored
Normal file
72
vendor/github.com/vmware/govmomi/govc/flags/int64.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// This flag type is internal to stdlib:
|
||||
// https://github.com/golang/go/blob/master/src/cmd/internal/obj/flag.go
|
||||
type int64Value int64
|
||||
|
||||
func (i *int64Value) Set(s string) error {
|
||||
v, err := strconv.ParseInt(s, 0, 64)
|
||||
*i = int64Value(v)
|
||||
return err
|
||||
}
|
||||
|
||||
func (i *int64Value) Get() interface{} {
|
||||
return int64(*i)
|
||||
}
|
||||
|
||||
func (i *int64Value) String() string {
|
||||
return fmt.Sprintf("%v", *i)
|
||||
}
|
||||
|
||||
// NewInt64 behaves as flag.IntVar, but using an int64 type.
|
||||
func NewInt64(v *int64) flag.Value {
|
||||
return (*int64Value)(v)
|
||||
}
|
||||
|
||||
type int64ptrValue struct {
|
||||
val **int64
|
||||
}
|
||||
|
||||
func (i *int64ptrValue) Set(s string) error {
|
||||
v, err := strconv.ParseInt(s, 0, 64)
|
||||
*i.val = new(int64)
|
||||
**i.val = int64(v)
|
||||
return err
|
||||
}
|
||||
|
||||
func (i *int64ptrValue) Get() interface{} {
|
||||
if i.val == nil || *i.val == nil {
|
||||
return nil
|
||||
}
|
||||
return **i.val
|
||||
}
|
||||
|
||||
func (i *int64ptrValue) String() string {
|
||||
return fmt.Sprintf("%v", i.Get())
|
||||
}
|
||||
|
||||
func NewOptionalInt64(v **int64) flag.Value {
|
||||
return &int64ptrValue{val: v}
|
||||
}
|
||||
30
vendor/github.com/vmware/govmomi/govc/flags/list.go
generated
vendored
Normal file
30
vendor/github.com/vmware/govmomi/govc/flags/list.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Copyright (c) 2019 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import "fmt"
|
||||
|
||||
type StringList []string
|
||||
|
||||
func (l *StringList) String() string {
|
||||
return fmt.Sprint(*l)
|
||||
}
|
||||
|
||||
func (l *StringList) Set(value string) error {
|
||||
*l = append(*l, value)
|
||||
return nil
|
||||
}
|
||||
147
vendor/github.com/vmware/govmomi/govc/flags/network.go
generated
vendored
Normal file
147
vendor/github.com/vmware/govmomi/govc/flags/network.go
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type NetworkFlag struct {
|
||||
common
|
||||
|
||||
*DatacenterFlag
|
||||
|
||||
name string
|
||||
net object.NetworkReference
|
||||
adapter string
|
||||
address string
|
||||
isset bool
|
||||
}
|
||||
|
||||
var networkFlagKey = flagKey("network")
|
||||
|
||||
func NewNetworkFlag(ctx context.Context) (*NetworkFlag, context.Context) {
|
||||
if v := ctx.Value(networkFlagKey); v != nil {
|
||||
return v.(*NetworkFlag), ctx
|
||||
}
|
||||
|
||||
v := &NetworkFlag{}
|
||||
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
|
||||
ctx = context.WithValue(ctx, networkFlagKey, v)
|
||||
return v, ctx
|
||||
}
|
||||
|
||||
func (flag *NetworkFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
flag.RegisterOnce(func() {
|
||||
flag.DatacenterFlag.Register(ctx, f)
|
||||
|
||||
env := "GOVC_NETWORK"
|
||||
value := os.Getenv(env)
|
||||
flag.name = value
|
||||
usage := fmt.Sprintf("Network [%s]", env)
|
||||
f.Var(flag, "net", usage)
|
||||
f.StringVar(&flag.adapter, "net.adapter", "e1000", "Network adapter type")
|
||||
f.StringVar(&flag.address, "net.address", "", "Network hardware address")
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *NetworkFlag) Process(ctx context.Context) error {
|
||||
return flag.ProcessOnce(func() error {
|
||||
if err := flag.DatacenterFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *NetworkFlag) String() string {
|
||||
return flag.name
|
||||
}
|
||||
|
||||
func (flag *NetworkFlag) Set(name string) error {
|
||||
flag.name = name
|
||||
flag.isset = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (flag *NetworkFlag) IsSet() bool {
|
||||
return flag.isset
|
||||
}
|
||||
|
||||
func (flag *NetworkFlag) Network() (object.NetworkReference, error) {
|
||||
if flag.net != nil {
|
||||
return flag.net, nil
|
||||
}
|
||||
|
||||
finder, err := flag.Finder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if flag.net, err = finder.NetworkOrDefault(context.TODO(), flag.name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return flag.net, nil
|
||||
}
|
||||
|
||||
func (flag *NetworkFlag) Device() (types.BaseVirtualDevice, error) {
|
||||
net, err := flag.Network()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
backing, err := net.EthernetCardBackingInfo(context.TODO())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
device, err := object.EthernetCardTypes().CreateEthernetCard(flag.adapter, backing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if flag.address != "" {
|
||||
card := device.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard()
|
||||
card.AddressType = string(types.VirtualEthernetCardMacTypeManual)
|
||||
card.MacAddress = flag.address
|
||||
}
|
||||
|
||||
return device, nil
|
||||
}
|
||||
|
||||
// Change applies update backing and hardware address changes to the given network device.
|
||||
func (flag *NetworkFlag) Change(device types.BaseVirtualDevice, update types.BaseVirtualDevice) {
|
||||
current := device.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard()
|
||||
changed := update.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard()
|
||||
|
||||
current.Backing = changed.Backing
|
||||
|
||||
if changed.MacAddress != "" {
|
||||
current.MacAddress = changed.MacAddress
|
||||
}
|
||||
|
||||
if changed.AddressType != "" {
|
||||
current.AddressType = changed.AddressType
|
||||
}
|
||||
}
|
||||
55
vendor/github.com/vmware/govmomi/govc/flags/optional_bool.go
generated
vendored
Normal file
55
vendor/github.com/vmware/govmomi/govc/flags/optional_bool.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type optionalBool struct {
|
||||
val **bool
|
||||
}
|
||||
|
||||
func (b *optionalBool) Set(s string) error {
|
||||
v, err := strconv.ParseBool(s)
|
||||
*b.val = &v
|
||||
return err
|
||||
}
|
||||
|
||||
func (b *optionalBool) Get() interface{} {
|
||||
if *b.val == nil {
|
||||
return nil
|
||||
}
|
||||
return **b.val
|
||||
}
|
||||
|
||||
func (b *optionalBool) String() string {
|
||||
if b.val == nil || *b.val == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
return fmt.Sprintf("%v", **b.val)
|
||||
}
|
||||
|
||||
func (b *optionalBool) IsBoolFlag() bool { return true }
|
||||
|
||||
// NewOptionalBool returns a flag.Value implementation where there is no default value.
|
||||
// This avoids sending a default value over the wire as using flag.BoolVar() would.
|
||||
func NewOptionalBool(v **bool) flag.Value {
|
||||
return &optionalBool{v}
|
||||
}
|
||||
251
vendor/github.com/vmware/govmomi/govc/flags/output.go
generated
vendored
Normal file
251
vendor/github.com/vmware/govmomi/govc/flags/output.go
generated
vendored
Normal file
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/kr/pretty"
|
||||
"github.com/vmware/govmomi/vim25/progress"
|
||||
)
|
||||
|
||||
type OutputWriter interface {
|
||||
Write(io.Writer) error
|
||||
}
|
||||
|
||||
type OutputFlag struct {
|
||||
common
|
||||
|
||||
JSON bool
|
||||
TTY bool
|
||||
Dump bool
|
||||
Out io.Writer
|
||||
}
|
||||
|
||||
var outputFlagKey = flagKey("output")
|
||||
|
||||
func NewOutputFlag(ctx context.Context) (*OutputFlag, context.Context) {
|
||||
if v := ctx.Value(outputFlagKey); v != nil {
|
||||
return v.(*OutputFlag), ctx
|
||||
}
|
||||
|
||||
v := &OutputFlag{Out: os.Stdout}
|
||||
ctx = context.WithValue(ctx, outputFlagKey, v)
|
||||
return v, ctx
|
||||
}
|
||||
|
||||
func (flag *OutputFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
flag.RegisterOnce(func() {
|
||||
f.BoolVar(&flag.JSON, "json", false, "Enable JSON output")
|
||||
f.BoolVar(&flag.Dump, "dump", false, "Enable Go output")
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *OutputFlag) Process(ctx context.Context) error {
|
||||
return flag.ProcessOnce(func() error {
|
||||
if !flag.JSON {
|
||||
// Assume we have a tty if not outputting JSON
|
||||
flag.TTY = true
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// Log outputs the specified string, prefixed with the current time.
|
||||
// A newline is not automatically added. If the specified string
|
||||
// starts with a '\r', the current line is cleared first.
|
||||
func (flag *OutputFlag) Log(s string) (int, error) {
|
||||
if len(s) > 0 && s[0] == '\r' {
|
||||
flag.Write([]byte{'\r', 033, '[', 'K'})
|
||||
s = s[1:]
|
||||
}
|
||||
|
||||
return flag.WriteString(time.Now().Format("[02-01-06 15:04:05] ") + s)
|
||||
}
|
||||
|
||||
func (flag *OutputFlag) Write(b []byte) (int, error) {
|
||||
if !flag.TTY {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
n, err := os.Stdout.Write(b)
|
||||
os.Stdout.Sync()
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (flag *OutputFlag) WriteString(s string) (int, error) {
|
||||
return flag.Write([]byte(s))
|
||||
}
|
||||
|
||||
func (flag *OutputFlag) All() bool {
|
||||
return flag.JSON || flag.Dump
|
||||
}
|
||||
|
||||
func dumpValue(val interface{}) interface{} {
|
||||
type dumper interface {
|
||||
Dump() interface{}
|
||||
}
|
||||
|
||||
if d, ok := val.(dumper); ok {
|
||||
return d.Dump()
|
||||
}
|
||||
|
||||
rval := reflect.ValueOf(val)
|
||||
if rval.Type().Kind() != reflect.Ptr {
|
||||
return val
|
||||
}
|
||||
|
||||
rval = rval.Elem()
|
||||
if rval.Type().Kind() == reflect.Struct {
|
||||
f := rval.Field(0)
|
||||
if f.Type().Kind() == reflect.Slice {
|
||||
// common case for the various 'type infoResult'
|
||||
if f.Len() == 1 {
|
||||
return f.Index(0).Interface()
|
||||
}
|
||||
return f.Interface()
|
||||
}
|
||||
}
|
||||
|
||||
return val
|
||||
}
|
||||
|
||||
func (flag *OutputFlag) WriteResult(result OutputWriter) error {
|
||||
var err error
|
||||
|
||||
if flag.JSON {
|
||||
err = json.NewEncoder(flag.Out).Encode(result)
|
||||
} else if flag.Dump {
|
||||
pretty.Fprintf(flag.Out, "%# v\n", dumpValue(result))
|
||||
} else {
|
||||
err = result.Write(flag.Out)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
type progressLogger struct {
|
||||
flag *OutputFlag
|
||||
prefix string
|
||||
|
||||
wg sync.WaitGroup
|
||||
|
||||
sink chan chan progress.Report
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
func newProgressLogger(flag *OutputFlag, prefix string) *progressLogger {
|
||||
p := &progressLogger{
|
||||
flag: flag,
|
||||
prefix: prefix,
|
||||
|
||||
sink: make(chan chan progress.Report),
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
|
||||
p.wg.Add(1)
|
||||
|
||||
go p.loopA()
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// loopA runs before Sink() has been called.
|
||||
func (p *progressLogger) loopA() {
|
||||
var err error
|
||||
|
||||
defer p.wg.Done()
|
||||
|
||||
tick := time.NewTicker(100 * time.Millisecond)
|
||||
defer tick.Stop()
|
||||
|
||||
called := false
|
||||
|
||||
for stop := false; !stop; {
|
||||
select {
|
||||
case ch := <-p.sink:
|
||||
err = p.loopB(tick, ch)
|
||||
stop = true
|
||||
called = true
|
||||
case <-p.done:
|
||||
stop = true
|
||||
case <-tick.C:
|
||||
line := fmt.Sprintf("\r%s", p.prefix)
|
||||
p.flag.Log(line)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil && err != io.EOF {
|
||||
p.flag.Log(fmt.Sprintf("\r%sError: %s\n", p.prefix, err))
|
||||
} else if called {
|
||||
p.flag.Log(fmt.Sprintf("\r%sOK\n", p.prefix))
|
||||
}
|
||||
}
|
||||
|
||||
// loopA runs after Sink() has been called.
|
||||
func (p *progressLogger) loopB(tick *time.Ticker, ch <-chan progress.Report) error {
|
||||
var r progress.Report
|
||||
var ok bool
|
||||
var err error
|
||||
|
||||
for ok = true; ok; {
|
||||
select {
|
||||
case r, ok = <-ch:
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
err = r.Error()
|
||||
case <-tick.C:
|
||||
line := fmt.Sprintf("\r%s", p.prefix)
|
||||
if r != nil {
|
||||
line += fmt.Sprintf("(%.0f%%", r.Percentage())
|
||||
detail := r.Detail()
|
||||
if detail != "" {
|
||||
line += fmt.Sprintf(", %s", detail)
|
||||
}
|
||||
line += ")"
|
||||
}
|
||||
p.flag.Log(line)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *progressLogger) Sink() chan<- progress.Report {
|
||||
ch := make(chan progress.Report)
|
||||
p.sink <- ch
|
||||
return ch
|
||||
}
|
||||
|
||||
func (p *progressLogger) Wait() {
|
||||
close(p.done)
|
||||
p.wg.Wait()
|
||||
}
|
||||
|
||||
func (flag *OutputFlag) ProgressLogger(prefix string) *progressLogger {
|
||||
return newProgressLogger(flag, prefix)
|
||||
}
|
||||
85
vendor/github.com/vmware/govmomi/govc/flags/resource_allocation_info.go
generated
vendored
Normal file
85
vendor/github.com/vmware/govmomi/govc/flags/resource_allocation_info.go
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type sharesInfo types.SharesInfo
|
||||
|
||||
func (s *sharesInfo) String() string {
|
||||
return string(s.Level)
|
||||
}
|
||||
|
||||
func (s *sharesInfo) Set(val string) error {
|
||||
switch val {
|
||||
case string(types.SharesLevelNormal), string(types.SharesLevelLow), string(types.SharesLevelHigh):
|
||||
s.Level = types.SharesLevel(val)
|
||||
default:
|
||||
n, err := strconv.Atoi(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Level = types.SharesLevelCustom
|
||||
s.Shares = int32(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type ResourceAllocationFlag struct {
|
||||
cpu, mem *types.ResourceAllocationInfo
|
||||
ExpandableReservation bool
|
||||
}
|
||||
|
||||
func NewResourceAllocationFlag(cpu, mem *types.ResourceAllocationInfo) *ResourceAllocationFlag {
|
||||
return &ResourceAllocationFlag{cpu, mem, true}
|
||||
}
|
||||
|
||||
func (r *ResourceAllocationFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
opts := []struct {
|
||||
name string
|
||||
units string
|
||||
*types.ResourceAllocationInfo
|
||||
}{
|
||||
{"CPU", "MHz", r.cpu},
|
||||
{"Memory", "MB", r.mem},
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
prefix := strings.ToLower(opt.name)[:3]
|
||||
shares := (*sharesInfo)(opt.Shares)
|
||||
|
||||
f.Var(NewOptionalInt64(&opt.Limit), prefix+".limit", opt.name+" limit in "+opt.units)
|
||||
f.Var(NewOptionalInt64(&opt.Reservation), prefix+".reservation", opt.name+" reservation in "+opt.units)
|
||||
if r.ExpandableReservation {
|
||||
f.Var(NewOptionalBool(&opt.ExpandableReservation), prefix+".expandable", opt.name+" expandable reservation")
|
||||
}
|
||||
f.Var(shares, prefix+".shares", opt.name+" shares level or number")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ResourceAllocationFlag) Process(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
92
vendor/github.com/vmware/govmomi/govc/flags/resource_pool.go
generated
vendored
Normal file
92
vendor/github.com/vmware/govmomi/govc/flags/resource_pool.go
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
)
|
||||
|
||||
type ResourcePoolFlag struct {
|
||||
common
|
||||
|
||||
*DatacenterFlag
|
||||
|
||||
name string
|
||||
pool *object.ResourcePool
|
||||
}
|
||||
|
||||
var resourcePoolFlagKey = flagKey("resourcePool")
|
||||
|
||||
func NewResourcePoolFlag(ctx context.Context) (*ResourcePoolFlag, context.Context) {
|
||||
if v := ctx.Value(resourcePoolFlagKey); v != nil {
|
||||
return v.(*ResourcePoolFlag), ctx
|
||||
}
|
||||
|
||||
v := &ResourcePoolFlag{}
|
||||
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
|
||||
ctx = context.WithValue(ctx, resourcePoolFlagKey, v)
|
||||
return v, ctx
|
||||
}
|
||||
|
||||
func (flag *ResourcePoolFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
flag.RegisterOnce(func() {
|
||||
flag.DatacenterFlag.Register(ctx, f)
|
||||
|
||||
env := "GOVC_RESOURCE_POOL"
|
||||
value := os.Getenv(env)
|
||||
usage := fmt.Sprintf("Resource pool [%s]", env)
|
||||
f.StringVar(&flag.name, "pool", value, usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *ResourcePoolFlag) Process(ctx context.Context) error {
|
||||
return flag.ProcessOnce(func() error {
|
||||
if err := flag.DatacenterFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *ResourcePoolFlag) ResourcePool() (*object.ResourcePool, error) {
|
||||
if flag.pool != nil {
|
||||
return flag.pool, nil
|
||||
}
|
||||
|
||||
finder, err := flag.Finder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if flag.pool, err = finder.ResourcePoolOrDefault(context.TODO(), flag.name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return flag.pool, nil
|
||||
}
|
||||
|
||||
func (flag *ResourcePoolFlag) ResourcePoolIfSpecified() (*object.ResourcePool, error) {
|
||||
if flag.name == "" {
|
||||
return nil, nil
|
||||
}
|
||||
return flag.ResourcePool()
|
||||
}
|
||||
434
vendor/github.com/vmware/govmomi/govc/flags/search.go
generated
vendored
Normal file
434
vendor/github.com/vmware/govmomi/govc/flags/search.go
generated
vendored
Normal file
@@ -0,0 +1,434 @@
|
||||
/*
|
||||
Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/find"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
const (
|
||||
SearchVirtualMachines = iota + 1
|
||||
SearchHosts
|
||||
SearchVirtualApps
|
||||
)
|
||||
|
||||
type SearchFlag struct {
|
||||
common
|
||||
|
||||
*ClientFlag
|
||||
*DatacenterFlag
|
||||
|
||||
t int
|
||||
entity string
|
||||
|
||||
byDatastorePath string
|
||||
byDNSName string
|
||||
byInventoryPath string
|
||||
byIP string
|
||||
byUUID string
|
||||
|
||||
isset bool
|
||||
}
|
||||
|
||||
var searchFlagKey = flagKey("search")
|
||||
|
||||
func NewSearchFlag(ctx context.Context, t int) (*SearchFlag, context.Context) {
|
||||
if v := ctx.Value(searchFlagKey); v != nil {
|
||||
return v.(*SearchFlag), ctx
|
||||
}
|
||||
|
||||
v := &SearchFlag{
|
||||
t: t,
|
||||
}
|
||||
|
||||
v.ClientFlag, ctx = NewClientFlag(ctx)
|
||||
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
|
||||
|
||||
switch t {
|
||||
case SearchVirtualMachines:
|
||||
v.entity = "VM"
|
||||
case SearchHosts:
|
||||
v.entity = "host"
|
||||
case SearchVirtualApps:
|
||||
v.entity = "vapp"
|
||||
default:
|
||||
panic("invalid search type")
|
||||
}
|
||||
|
||||
ctx = context.WithValue(ctx, searchFlagKey, v)
|
||||
return v, ctx
|
||||
}
|
||||
|
||||
func (flag *SearchFlag) Register(ctx context.Context, fs *flag.FlagSet) {
|
||||
flag.RegisterOnce(func() {
|
||||
flag.ClientFlag.Register(ctx, fs)
|
||||
flag.DatacenterFlag.Register(ctx, fs)
|
||||
|
||||
register := func(v *string, f string, d string) {
|
||||
f = fmt.Sprintf("%s.%s", strings.ToLower(flag.entity), f)
|
||||
d = fmt.Sprintf(d, flag.entity)
|
||||
fs.StringVar(v, f, "", d)
|
||||
}
|
||||
|
||||
switch flag.t {
|
||||
case SearchVirtualMachines:
|
||||
register(&flag.byDatastorePath, "path", "Find %s by path to .vmx file")
|
||||
}
|
||||
|
||||
switch flag.t {
|
||||
case SearchVirtualMachines, SearchHosts:
|
||||
register(&flag.byDNSName, "dns", "Find %s by FQDN")
|
||||
register(&flag.byIP, "ip", "Find %s by IP address")
|
||||
register(&flag.byUUID, "uuid", "Find %s by UUID")
|
||||
}
|
||||
|
||||
register(&flag.byInventoryPath, "ipath", "Find %s by inventory path")
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *SearchFlag) Process(ctx context.Context) error {
|
||||
return flag.ProcessOnce(func() error {
|
||||
if err := flag.ClientFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := flag.DatacenterFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
flags := []string{
|
||||
flag.byDatastorePath,
|
||||
flag.byDNSName,
|
||||
flag.byInventoryPath,
|
||||
flag.byIP,
|
||||
flag.byUUID,
|
||||
}
|
||||
|
||||
flag.isset = false
|
||||
for _, f := range flags {
|
||||
if f != "" {
|
||||
if flag.isset {
|
||||
return errors.New("cannot use more than one search flag")
|
||||
}
|
||||
flag.isset = true
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *SearchFlag) IsSet() bool {
|
||||
return flag.isset
|
||||
}
|
||||
|
||||
func (flag *SearchFlag) searchIndex(c *vim25.Client) *object.SearchIndex {
|
||||
return object.NewSearchIndex(c)
|
||||
}
|
||||
|
||||
func (flag *SearchFlag) searchByDatastorePath(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) {
|
||||
ctx := context.TODO()
|
||||
switch flag.t {
|
||||
case SearchVirtualMachines:
|
||||
return flag.searchIndex(c).FindByDatastorePath(ctx, dc, flag.byDatastorePath)
|
||||
default:
|
||||
panic("unsupported type")
|
||||
}
|
||||
}
|
||||
|
||||
func (flag *SearchFlag) searchByDNSName(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) {
|
||||
ctx := context.TODO()
|
||||
switch flag.t {
|
||||
case SearchVirtualMachines:
|
||||
return flag.searchIndex(c).FindByDnsName(ctx, dc, flag.byDNSName, true)
|
||||
case SearchHosts:
|
||||
return flag.searchIndex(c).FindByDnsName(ctx, dc, flag.byDNSName, false)
|
||||
default:
|
||||
panic("unsupported type")
|
||||
}
|
||||
}
|
||||
|
||||
func (flag *SearchFlag) searchByInventoryPath(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) {
|
||||
// TODO(PN): The datacenter flag should not be set because it is ignored.
|
||||
ctx := context.TODO()
|
||||
return flag.searchIndex(c).FindByInventoryPath(ctx, flag.byInventoryPath)
|
||||
}
|
||||
|
||||
func (flag *SearchFlag) searchByIP(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) {
|
||||
ctx := context.TODO()
|
||||
switch flag.t {
|
||||
case SearchVirtualMachines:
|
||||
return flag.searchIndex(c).FindByIp(ctx, dc, flag.byIP, true)
|
||||
case SearchHosts:
|
||||
return flag.searchIndex(c).FindByIp(ctx, dc, flag.byIP, false)
|
||||
default:
|
||||
panic("unsupported type")
|
||||
}
|
||||
}
|
||||
|
||||
func (flag *SearchFlag) searchByUUID(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) {
|
||||
ctx := context.TODO()
|
||||
isVM := false
|
||||
switch flag.t {
|
||||
case SearchVirtualMachines:
|
||||
isVM = true
|
||||
case SearchHosts:
|
||||
default:
|
||||
panic("unsupported type")
|
||||
}
|
||||
|
||||
var ref object.Reference
|
||||
var err error
|
||||
|
||||
for _, iu := range []*bool{nil, types.NewBool(true)} {
|
||||
ref, err = flag.searchIndex(c).FindByUuid(ctx, dc, flag.byUUID, isVM, iu)
|
||||
if err != nil {
|
||||
if soap.IsSoapFault(err) {
|
||||
fault := soap.ToSoapFault(err).VimFault()
|
||||
if _, ok := fault.(types.InvalidArgument); ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if ref != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return ref, nil
|
||||
}
|
||||
|
||||
func (flag *SearchFlag) search() (object.Reference, error) {
|
||||
ctx := context.TODO()
|
||||
var ref object.Reference
|
||||
var err error
|
||||
|
||||
c, err := flag.Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dc, err := flag.Datacenter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case flag.byDatastorePath != "":
|
||||
ref, err = flag.searchByDatastorePath(c, dc)
|
||||
case flag.byDNSName != "":
|
||||
ref, err = flag.searchByDNSName(c, dc)
|
||||
case flag.byInventoryPath != "":
|
||||
ref, err = flag.searchByInventoryPath(c, dc)
|
||||
case flag.byIP != "":
|
||||
ref, err = flag.searchByIP(c, dc)
|
||||
case flag.byUUID != "":
|
||||
ref, err = flag.searchByUUID(c, dc)
|
||||
default:
|
||||
err = errors.New("no search flag specified")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if ref == nil {
|
||||
return nil, fmt.Errorf("no such %s", flag.entity)
|
||||
}
|
||||
|
||||
// set the InventoryPath field
|
||||
finder, err := flag.Finder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ref, err = finder.ObjectReference(ctx, ref.Reference())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ref, nil
|
||||
}
|
||||
|
||||
func (flag *SearchFlag) VirtualMachine() (*object.VirtualMachine, error) {
|
||||
ref, err := flag.search()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vm, ok := ref.(*object.VirtualMachine)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected VirtualMachine entity, got %s", ref.Reference().Type)
|
||||
}
|
||||
|
||||
return vm, nil
|
||||
}
|
||||
|
||||
func (flag *SearchFlag) VirtualMachines(args []string) ([]*object.VirtualMachine, error) {
|
||||
ctx := context.TODO()
|
||||
var out []*object.VirtualMachine
|
||||
|
||||
if flag.IsSet() {
|
||||
vm, err := flag.VirtualMachine()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out = append(out, vm)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// List virtual machines
|
||||
if len(args) == 0 {
|
||||
return nil, errors.New("no argument")
|
||||
}
|
||||
|
||||
finder, err := flag.Finder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var nfe error
|
||||
|
||||
// List virtual machines for every argument
|
||||
for _, arg := range args {
|
||||
vms, err := finder.VirtualMachineList(ctx, arg)
|
||||
if err != nil {
|
||||
if _, ok := err.(*find.NotFoundError); ok {
|
||||
// Let caller decide how to handle NotFoundError
|
||||
nfe = err
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out = append(out, vms...)
|
||||
}
|
||||
|
||||
return out, nfe
|
||||
}
|
||||
|
||||
func (flag *SearchFlag) VirtualApp() (*object.VirtualApp, error) {
|
||||
ref, err := flag.search()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
app, ok := ref.(*object.VirtualApp)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected VirtualApp entity, got %s", ref.Reference().Type)
|
||||
}
|
||||
|
||||
return app, nil
|
||||
}
|
||||
|
||||
func (flag *SearchFlag) VirtualApps(args []string) ([]*object.VirtualApp, error) {
|
||||
ctx := context.TODO()
|
||||
var out []*object.VirtualApp
|
||||
|
||||
if flag.IsSet() {
|
||||
app, err := flag.VirtualApp()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out = append(out, app)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// List virtual apps
|
||||
if len(args) == 0 {
|
||||
return nil, errors.New("no argument")
|
||||
}
|
||||
|
||||
finder, err := flag.Finder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// List virtual apps for every argument
|
||||
for _, arg := range args {
|
||||
apps, err := finder.VirtualAppList(ctx, arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out = append(out, apps...)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (flag *SearchFlag) HostSystem() (*object.HostSystem, error) {
|
||||
ref, err := flag.search()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
host, ok := ref.(*object.HostSystem)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected HostSystem entity, got %s", ref.Reference().Type)
|
||||
}
|
||||
|
||||
return host, nil
|
||||
}
|
||||
|
||||
func (flag *SearchFlag) HostSystems(args []string) ([]*object.HostSystem, error) {
|
||||
ctx := context.TODO()
|
||||
var out []*object.HostSystem
|
||||
|
||||
if flag.IsSet() {
|
||||
host, err := flag.HostSystem()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out = append(out, host)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// List host system
|
||||
if len(args) == 0 {
|
||||
return nil, errors.New("no argument")
|
||||
}
|
||||
|
||||
finder, err := flag.Finder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// List host systems for every argument
|
||||
for _, arg := range args {
|
||||
vms, err := finder.HostSystemList(ctx, arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out = append(out, vms...)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
78
vendor/github.com/vmware/govmomi/govc/flags/storage_pod.go
generated
vendored
Normal file
78
vendor/github.com/vmware/govmomi/govc/flags/storage_pod.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
)
|
||||
|
||||
type StoragePodFlag struct {
|
||||
common
|
||||
|
||||
*DatacenterFlag
|
||||
|
||||
Name string
|
||||
|
||||
sp *object.StoragePod
|
||||
}
|
||||
|
||||
var storagePodFlagKey = flagKey("storagePod")
|
||||
|
||||
func NewStoragePodFlag(ctx context.Context) (*StoragePodFlag, context.Context) {
|
||||
if v := ctx.Value(storagePodFlagKey); v != nil {
|
||||
return v.(*StoragePodFlag), ctx
|
||||
}
|
||||
|
||||
v := &StoragePodFlag{}
|
||||
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
|
||||
ctx = context.WithValue(ctx, storagePodFlagKey, v)
|
||||
return v, ctx
|
||||
}
|
||||
|
||||
func (f *StoragePodFlag) Register(ctx context.Context, fs *flag.FlagSet) {
|
||||
f.RegisterOnce(func() {
|
||||
f.DatacenterFlag.Register(ctx, fs)
|
||||
|
||||
env := "GOVC_DATASTORE_CLUSTER"
|
||||
value := os.Getenv(env)
|
||||
usage := fmt.Sprintf("Datastore cluster [%s]", env)
|
||||
fs.StringVar(&f.Name, "datastore-cluster", value, usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (f *StoragePodFlag) Process(ctx context.Context) error {
|
||||
return f.DatacenterFlag.Process(ctx)
|
||||
}
|
||||
|
||||
func (f *StoragePodFlag) Isset() bool {
|
||||
return f.Name != ""
|
||||
}
|
||||
|
||||
func (f *StoragePodFlag) StoragePod() (*object.StoragePod, error) {
|
||||
ctx := context.TODO()
|
||||
if f.sp != nil {
|
||||
return f.sp, nil
|
||||
}
|
||||
|
||||
finder, err := f.Finder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if f.Isset() {
|
||||
f.sp, err = finder.DatastoreCluster(ctx, f.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
f.sp, err = finder.DefaultDatastoreCluster(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return f.sp, nil
|
||||
}
|
||||
66
vendor/github.com/vmware/govmomi/govc/flags/version.go
generated
vendored
Normal file
66
vendor/github.com/vmware/govmomi/govc/flags/version.go
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright (c) 2014-2020 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const Version = "0.22.1"
|
||||
|
||||
var GitVersion string
|
||||
|
||||
type version []int
|
||||
|
||||
func ParseVersion(s string) (version, error) {
|
||||
v := make(version, 0)
|
||||
ds := strings.Split(s, "-")
|
||||
ps := strings.Split(ds[0], ".")
|
||||
for _, p := range ps {
|
||||
i, err := strconv.Atoi(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v = append(v, i)
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (v version) Lte(u version) bool {
|
||||
lv := len(v)
|
||||
lu := len(u)
|
||||
|
||||
for i := 0; i < lv; i++ {
|
||||
// Everything up to here has been equal and v has more elements than u.
|
||||
if i >= lu {
|
||||
return false
|
||||
}
|
||||
|
||||
// Move to next digit if equal.
|
||||
if v[i] == u[i] {
|
||||
continue
|
||||
}
|
||||
|
||||
return v[i] < u[i]
|
||||
}
|
||||
|
||||
// Equal.
|
||||
return true
|
||||
}
|
||||
106
vendor/github.com/vmware/govmomi/govc/flags/virtual_app.go
generated
vendored
Normal file
106
vendor/github.com/vmware/govmomi/govc/flags/virtual_app.go
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
)
|
||||
|
||||
type VirtualAppFlag struct {
|
||||
common
|
||||
|
||||
*DatacenterFlag
|
||||
*SearchFlag
|
||||
|
||||
name string
|
||||
app *object.VirtualApp
|
||||
}
|
||||
|
||||
var virtualAppFlagKey = flagKey("virtualApp")
|
||||
|
||||
func NewVirtualAppFlag(ctx context.Context) (*VirtualAppFlag, context.Context) {
|
||||
if v := ctx.Value(virtualAppFlagKey); v != nil {
|
||||
return v.(*VirtualAppFlag), ctx
|
||||
}
|
||||
|
||||
v := &VirtualAppFlag{}
|
||||
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
|
||||
v.SearchFlag, ctx = NewSearchFlag(ctx, SearchVirtualApps)
|
||||
ctx = context.WithValue(ctx, virtualAppFlagKey, v)
|
||||
return v, ctx
|
||||
}
|
||||
|
||||
func (flag *VirtualAppFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
flag.RegisterOnce(func() {
|
||||
flag.DatacenterFlag.Register(ctx, f)
|
||||
flag.SearchFlag.Register(ctx, f)
|
||||
|
||||
env := "GOVC_VAPP"
|
||||
value := os.Getenv(env)
|
||||
usage := fmt.Sprintf("Virtual App [%s]", env)
|
||||
f.StringVar(&flag.name, "vapp", value, usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *VirtualAppFlag) Process(ctx context.Context) error {
|
||||
return flag.ProcessOnce(func() error {
|
||||
if err := flag.DatacenterFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := flag.SearchFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *VirtualAppFlag) VirtualApp() (*object.VirtualApp, error) {
|
||||
ctx := context.TODO()
|
||||
|
||||
if flag.app != nil {
|
||||
return flag.app, nil
|
||||
}
|
||||
|
||||
// Use search flags if specified.
|
||||
if flag.SearchFlag.IsSet() {
|
||||
app, err := flag.SearchFlag.VirtualApp()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
flag.app = app
|
||||
return flag.app, nil
|
||||
}
|
||||
|
||||
// Never look for a default virtual app.
|
||||
if flag.name == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
finder, err := flag.Finder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
flag.app, err = finder.VirtualApp(ctx, flag.name)
|
||||
return flag.app, err
|
||||
}
|
||||
112
vendor/github.com/vmware/govmomi/govc/flags/virtual_machine.go
generated
vendored
Normal file
112
vendor/github.com/vmware/govmomi/govc/flags/virtual_machine.go
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
)
|
||||
|
||||
type VirtualMachineFlag struct {
|
||||
common
|
||||
|
||||
*ClientFlag
|
||||
*DatacenterFlag
|
||||
*SearchFlag
|
||||
|
||||
name string
|
||||
vm *object.VirtualMachine
|
||||
}
|
||||
|
||||
var virtualMachineFlagKey = flagKey("virtualMachine")
|
||||
|
||||
func NewVirtualMachineFlag(ctx context.Context) (*VirtualMachineFlag, context.Context) {
|
||||
if v := ctx.Value(virtualMachineFlagKey); v != nil {
|
||||
return v.(*VirtualMachineFlag), ctx
|
||||
}
|
||||
|
||||
v := &VirtualMachineFlag{}
|
||||
v.ClientFlag, ctx = NewClientFlag(ctx)
|
||||
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
|
||||
v.SearchFlag, ctx = NewSearchFlag(ctx, SearchVirtualMachines)
|
||||
ctx = context.WithValue(ctx, virtualMachineFlagKey, v)
|
||||
return v, ctx
|
||||
}
|
||||
|
||||
func (flag *VirtualMachineFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
flag.RegisterOnce(func() {
|
||||
flag.ClientFlag.Register(ctx, f)
|
||||
flag.DatacenterFlag.Register(ctx, f)
|
||||
flag.SearchFlag.Register(ctx, f)
|
||||
|
||||
env := "GOVC_VM"
|
||||
value := os.Getenv(env)
|
||||
usage := fmt.Sprintf("Virtual machine [%s]", env)
|
||||
f.StringVar(&flag.name, "vm", value, usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *VirtualMachineFlag) Process(ctx context.Context) error {
|
||||
return flag.ProcessOnce(func() error {
|
||||
if err := flag.ClientFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := flag.DatacenterFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := flag.SearchFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *VirtualMachineFlag) VirtualMachine() (*object.VirtualMachine, error) {
|
||||
ctx := context.TODO()
|
||||
|
||||
if flag.vm != nil {
|
||||
return flag.vm, nil
|
||||
}
|
||||
|
||||
// Use search flags if specified.
|
||||
if flag.SearchFlag.IsSet() {
|
||||
vm, err := flag.SearchFlag.VirtualMachine()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
flag.vm = vm
|
||||
return flag.vm, nil
|
||||
}
|
||||
|
||||
// Never look for a default virtual machine.
|
||||
if flag.name == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
finder, err := flag.Finder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
flag.vm, err = finder.VirtualMachine(ctx, flag.name)
|
||||
return flag.vm, err
|
||||
}
|
||||
187
vendor/github.com/vmware/govmomi/govc/importx/archive.go
generated
vendored
Normal file
187
vendor/github.com/vmware/govmomi/govc/importx/archive.go
generated
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package importx
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/ovf"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
)
|
||||
|
||||
// ArchiveFlag doesn't register any flags;
|
||||
// only encapsulates some common archive related functionality.
|
||||
type ArchiveFlag struct {
|
||||
Archive
|
||||
}
|
||||
|
||||
func newArchiveFlag(ctx context.Context) (*ArchiveFlag, context.Context) {
|
||||
return &ArchiveFlag{}, ctx
|
||||
}
|
||||
|
||||
func (f *ArchiveFlag) Register(ctx context.Context, fs *flag.FlagSet) {
|
||||
}
|
||||
|
||||
func (f *ArchiveFlag) Process(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *ArchiveFlag) ReadOvf(fpath string) ([]byte, error) {
|
||||
r, _, err := f.Open(fpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
return ioutil.ReadAll(r)
|
||||
}
|
||||
|
||||
func (f *ArchiveFlag) ReadEnvelope(data []byte) (*ovf.Envelope, error) {
|
||||
e, err := ovf.Unmarshal(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse ovf: %s", err)
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
||||
|
||||
type Archive interface {
|
||||
Open(string) (io.ReadCloser, int64, error)
|
||||
}
|
||||
|
||||
type TapeArchive struct {
|
||||
Path string
|
||||
Opener
|
||||
}
|
||||
|
||||
type TapeArchiveEntry struct {
|
||||
io.Reader
|
||||
f io.Closer
|
||||
|
||||
Name string
|
||||
}
|
||||
|
||||
func (t *TapeArchiveEntry) Close() error {
|
||||
return t.f.Close()
|
||||
}
|
||||
|
||||
func (t *TapeArchive) Open(name string) (io.ReadCloser, int64, error) {
|
||||
f, _, err := t.OpenFile(t.Path)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
r := tar.NewReader(f)
|
||||
|
||||
for {
|
||||
h, err := r.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
matched, err := path.Match(name, path.Base(h.Name))
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if matched {
|
||||
return &TapeArchiveEntry{r, f, h.Name}, h.Size, nil
|
||||
}
|
||||
}
|
||||
|
||||
_ = f.Close()
|
||||
|
||||
return nil, 0, os.ErrNotExist
|
||||
}
|
||||
|
||||
type FileArchive struct {
|
||||
Path string
|
||||
Opener
|
||||
}
|
||||
|
||||
func (t *FileArchive) Open(name string) (io.ReadCloser, int64, error) {
|
||||
fpath := name
|
||||
if name != t.Path {
|
||||
index := strings.LastIndex(t.Path, "/")
|
||||
if index != -1 {
|
||||
fpath = t.Path[:index] + "/" + name
|
||||
}
|
||||
}
|
||||
|
||||
return t.OpenFile(fpath)
|
||||
}
|
||||
|
||||
type Opener struct {
|
||||
*vim25.Client
|
||||
}
|
||||
|
||||
func isRemotePath(path string) bool {
|
||||
if strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o Opener) OpenLocal(path string) (io.ReadCloser, int64, error) {
|
||||
f, err := os.Open(filepath.Clean(path))
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
s, err := f.Stat()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return f, s.Size(), nil
|
||||
}
|
||||
|
||||
func (o Opener) OpenFile(path string) (io.ReadCloser, int64, error) {
|
||||
if isRemotePath(path) {
|
||||
return o.OpenRemote(path)
|
||||
}
|
||||
return o.OpenLocal(path)
|
||||
}
|
||||
|
||||
func (o Opener) OpenRemote(link string) (io.ReadCloser, int64, error) {
|
||||
if o.Client == nil {
|
||||
return nil, 0, errors.New("remote path not supported")
|
||||
}
|
||||
|
||||
u, err := url.Parse(link)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return o.Download(context.Background(), u, &soap.DefaultDownload)
|
||||
}
|
||||
59
vendor/github.com/vmware/govmomi/govc/importx/importable.go
generated
vendored
Normal file
59
vendor/github.com/vmware/govmomi/govc/importx/importable.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
Copyright (c) 2014 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package importx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
)
|
||||
|
||||
type importable struct {
|
||||
localPath string
|
||||
remotePath string
|
||||
}
|
||||
|
||||
func (i importable) Ext() string {
|
||||
return path.Ext(i.localPath)
|
||||
}
|
||||
|
||||
func (i importable) Base() string {
|
||||
return path.Base(i.localPath)
|
||||
}
|
||||
|
||||
func (i importable) BaseClean() string {
|
||||
b := i.Base()
|
||||
e := i.Ext()
|
||||
return b[:len(b)-len(e)]
|
||||
}
|
||||
|
||||
func (i importable) RemoteSrcVMDK() string {
|
||||
file := fmt.Sprintf("%s-src.vmdk", i.BaseClean())
|
||||
return i.toRemotePath(file)
|
||||
}
|
||||
|
||||
func (i importable) RemoteDstVMDK() string {
|
||||
file := fmt.Sprintf("%s.vmdk", i.BaseClean())
|
||||
return i.toRemotePath(file)
|
||||
}
|
||||
|
||||
func (i importable) toRemotePath(p string) string {
|
||||
if i.remotePath == "" {
|
||||
return p
|
||||
}
|
||||
|
||||
return path.Join(i.remotePath, p)
|
||||
}
|
||||
205
vendor/github.com/vmware/govmomi/govc/importx/options.go
generated
vendored
Normal file
205
vendor/github.com/vmware/govmomi/govc/importx/options.go
generated
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package importx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/vmware/govmomi/govc/flags"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/ovf"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type Property struct {
|
||||
types.KeyValue
|
||||
Spec *ovf.Property `json:",omitempty"`
|
||||
}
|
||||
|
||||
type Network struct {
|
||||
Name string
|
||||
Network string
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
AllDeploymentOptions []string `json:",omitempty"`
|
||||
Deployment string `json:",omitempty"`
|
||||
|
||||
AllDiskProvisioningOptions []string `json:",omitempty"`
|
||||
DiskProvisioning string
|
||||
|
||||
AllIPAllocationPolicyOptions []string `json:",omitempty"`
|
||||
IPAllocationPolicy string
|
||||
|
||||
AllIPProtocolOptions []string `json:",omitempty"`
|
||||
IPProtocol string
|
||||
|
||||
PropertyMapping []Property `json:",omitempty"`
|
||||
|
||||
NetworkMapping []Network `json:",omitempty"`
|
||||
|
||||
Annotation string `json:",omitempty"`
|
||||
|
||||
MarkAsTemplate bool
|
||||
PowerOn bool
|
||||
InjectOvfEnv bool
|
||||
WaitForIP bool
|
||||
Name *string
|
||||
}
|
||||
|
||||
type OptionsFlag struct {
|
||||
Options Options
|
||||
|
||||
path string
|
||||
}
|
||||
|
||||
func newOptionsFlag(ctx context.Context) (*OptionsFlag, context.Context) {
|
||||
return &OptionsFlag{}, ctx
|
||||
}
|
||||
|
||||
func (flag *OptionsFlag) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
f.StringVar(&flag.path, "options", "", "Options spec file path for VM deployment")
|
||||
}
|
||||
|
||||
func (flag *OptionsFlag) Process(ctx context.Context) error {
|
||||
if len(flag.path) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
in := os.Stdin
|
||||
|
||||
if flag.path != "-" {
|
||||
in, err = os.Open(flag.path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer in.Close()
|
||||
}
|
||||
|
||||
return json.NewDecoder(in).Decode(&flag.Options)
|
||||
}
|
||||
|
||||
func (flag *OptionsFlag) powerOn(vm *object.VirtualMachine, out *flags.OutputFlag) error {
|
||||
if !flag.Options.PowerOn || flag.Options.MarkAsTemplate {
|
||||
return nil
|
||||
}
|
||||
|
||||
out.Log("Powering on VM...\n")
|
||||
|
||||
task, err := vm.PowerOn(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return task.Wait(context.Background())
|
||||
}
|
||||
|
||||
func (flag *OptionsFlag) markAsTemplate(vm *object.VirtualMachine, out *flags.OutputFlag) error {
|
||||
if !flag.Options.MarkAsTemplate {
|
||||
return nil
|
||||
}
|
||||
|
||||
out.Log("Marking VM as template...\n")
|
||||
|
||||
return vm.MarkAsTemplate(context.Background())
|
||||
}
|
||||
|
||||
func (flag *OptionsFlag) injectOvfEnv(vm *object.VirtualMachine, out *flags.OutputFlag) error {
|
||||
if !flag.Options.InjectOvfEnv {
|
||||
return nil
|
||||
}
|
||||
|
||||
out.Log("Injecting OVF environment...\n")
|
||||
|
||||
var opts []types.BaseOptionValue
|
||||
|
||||
a := vm.Client().ServiceContent.About
|
||||
|
||||
// build up Environment in order to marshal to xml
|
||||
var props []ovf.EnvProperty
|
||||
for _, p := range flag.Options.PropertyMapping {
|
||||
props = append(props, ovf.EnvProperty{
|
||||
Key: p.Key,
|
||||
Value: p.Value,
|
||||
})
|
||||
}
|
||||
|
||||
env := ovf.Env{
|
||||
EsxID: vm.Reference().Value,
|
||||
Platform: &ovf.PlatformSection{
|
||||
Kind: a.Name,
|
||||
Version: a.Version,
|
||||
Vendor: a.Vendor,
|
||||
Locale: "US",
|
||||
},
|
||||
Property: &ovf.PropertySection{
|
||||
Properties: props,
|
||||
},
|
||||
}
|
||||
|
||||
opts = append(opts, &types.OptionValue{
|
||||
Key: "guestinfo.ovfEnv",
|
||||
Value: env.MarshalManual(),
|
||||
})
|
||||
|
||||
task, err := vm.Reconfigure(context.Background(), types.VirtualMachineConfigSpec{
|
||||
ExtraConfig: opts,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return task.Wait(context.Background())
|
||||
}
|
||||
|
||||
func (flag *OptionsFlag) waitForIP(vm *object.VirtualMachine, out *flags.OutputFlag) error {
|
||||
if !flag.Options.PowerOn || !flag.Options.WaitForIP || flag.Options.MarkAsTemplate {
|
||||
return nil
|
||||
}
|
||||
|
||||
out.Log("Waiting for IP address...\n")
|
||||
ip, err := vm.WaitForIP(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.Log(fmt.Sprintf("Received IP address: %s\n", ip))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (flag *OptionsFlag) Deploy(vm *object.VirtualMachine, out *flags.OutputFlag) error {
|
||||
deploy := []func(*object.VirtualMachine, *flags.OutputFlag) error{
|
||||
flag.injectOvfEnv,
|
||||
flag.markAsTemplate,
|
||||
flag.powerOn,
|
||||
flag.waitForIP,
|
||||
}
|
||||
|
||||
for _, step := range deploy {
|
||||
if err := step(vm, out); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
63
vendor/github.com/vmware/govmomi/govc/importx/ova.go
generated
vendored
Normal file
63
vendor/github.com/vmware/govmomi/govc/importx/ova.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package importx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/govc/cli"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type ova struct {
|
||||
*ovfx
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("import.ova", &ova{&ovfx{}})
|
||||
}
|
||||
|
||||
func (cmd *ova) Usage() string {
|
||||
return "PATH_TO_OVA"
|
||||
}
|
||||
|
||||
func (cmd *ova) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
fpath, err := cmd.Prepare(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
archive := &TapeArchive{Path: fpath}
|
||||
archive.Client = cmd.Client
|
||||
|
||||
cmd.Archive = archive
|
||||
|
||||
moref, err := cmd.Import(fpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vm := object.NewVirtualMachine(cmd.Client, *moref)
|
||||
return cmd.Deploy(vm, cmd.OutputFlag)
|
||||
}
|
||||
|
||||
func (cmd *ova) Import(fpath string) (*types.ManagedObjectReference, error) {
|
||||
ovf := "*.ovf"
|
||||
return cmd.ovfx.Import(ovf)
|
||||
}
|
||||
324
vendor/github.com/vmware/govmomi/govc/importx/ovf.go
generated
vendored
Normal file
324
vendor/github.com/vmware/govmomi/govc/importx/ovf.go
generated
vendored
Normal file
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package importx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/vmware/govmomi/govc/cli"
|
||||
"github.com/vmware/govmomi/govc/flags"
|
||||
"github.com/vmware/govmomi/nfc"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/ovf"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type ovfx struct {
|
||||
*flags.DatastoreFlag
|
||||
*flags.HostSystemFlag
|
||||
*flags.OutputFlag
|
||||
*flags.ResourcePoolFlag
|
||||
*flags.FolderFlag
|
||||
|
||||
*ArchiveFlag
|
||||
*OptionsFlag
|
||||
|
||||
Name string
|
||||
|
||||
Client *vim25.Client
|
||||
Datacenter *object.Datacenter
|
||||
Datastore *object.Datastore
|
||||
ResourcePool *object.ResourcePool
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("import.ovf", &ovfx{})
|
||||
}
|
||||
|
||||
func (cmd *ovfx) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
|
||||
cmd.DatastoreFlag.Register(ctx, f)
|
||||
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
|
||||
cmd.HostSystemFlag.Register(ctx, f)
|
||||
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
|
||||
cmd.OutputFlag.Register(ctx, f)
|
||||
cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx)
|
||||
cmd.ResourcePoolFlag.Register(ctx, f)
|
||||
cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx)
|
||||
cmd.FolderFlag.Register(ctx, f)
|
||||
|
||||
cmd.ArchiveFlag, ctx = newArchiveFlag(ctx)
|
||||
cmd.ArchiveFlag.Register(ctx, f)
|
||||
cmd.OptionsFlag, ctx = newOptionsFlag(ctx)
|
||||
cmd.OptionsFlag.Register(ctx, f)
|
||||
|
||||
f.StringVar(&cmd.Name, "name", "", "Name to use for new entity")
|
||||
}
|
||||
|
||||
func (cmd *ovfx) Process(ctx context.Context) error {
|
||||
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.OutputFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.ResourcePoolFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.ArchiveFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.OptionsFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.FolderFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *ovfx) Usage() string {
|
||||
return "PATH_TO_OVF"
|
||||
}
|
||||
|
||||
func (cmd *ovfx) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
fpath, err := cmd.Prepare(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
archive := &FileArchive{Path: fpath}
|
||||
archive.Client = cmd.Client
|
||||
|
||||
cmd.Archive = archive
|
||||
|
||||
moref, err := cmd.Import(fpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vm := object.NewVirtualMachine(cmd.Client, *moref)
|
||||
return cmd.Deploy(vm, cmd.OutputFlag)
|
||||
}
|
||||
|
||||
func (cmd *ovfx) Prepare(f *flag.FlagSet) (string, error) {
|
||||
var err error
|
||||
|
||||
args := f.Args()
|
||||
if len(args) != 1 {
|
||||
return "", errors.New("no file specified")
|
||||
}
|
||||
|
||||
cmd.Client, err = cmd.DatastoreFlag.Client()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
cmd.Datacenter, err = cmd.DatastoreFlag.Datacenter()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
cmd.Datastore, err = cmd.DatastoreFlag.Datastore()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
cmd.ResourcePool, err = cmd.ResourcePoolFlag.ResourcePoolIfSpecified()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return f.Arg(0), nil
|
||||
}
|
||||
|
||||
func (cmd *ovfx) Map(op []Property) (p []types.KeyValue) {
|
||||
for _, v := range op {
|
||||
p = append(p, v.KeyValue)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (cmd *ovfx) NetworkMap(e *ovf.Envelope) (p []types.OvfNetworkMapping) {
|
||||
ctx := context.TODO()
|
||||
finder, err := cmd.DatastoreFlag.Finder()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
networks := map[string]string{}
|
||||
|
||||
if e.Network != nil {
|
||||
for _, net := range e.Network.Networks {
|
||||
networks[net.Name] = net.Name
|
||||
}
|
||||
}
|
||||
|
||||
for _, net := range cmd.Options.NetworkMapping {
|
||||
networks[net.Name] = net.Network
|
||||
}
|
||||
|
||||
for src, dst := range networks {
|
||||
if net, err := finder.Network(ctx, dst); err == nil {
|
||||
p = append(p, types.OvfNetworkMapping{
|
||||
Name: src,
|
||||
Network: net.Reference(),
|
||||
})
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (cmd *ovfx) Import(fpath string) (*types.ManagedObjectReference, error) {
|
||||
ctx := context.TODO()
|
||||
|
||||
o, err := cmd.ReadOvf(fpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
e, err := cmd.ReadEnvelope(o)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse ovf: %s", err)
|
||||
}
|
||||
|
||||
name := "Govc Virtual Appliance"
|
||||
if e.VirtualSystem != nil {
|
||||
name = e.VirtualSystem.ID
|
||||
if e.VirtualSystem.Name != nil {
|
||||
name = *e.VirtualSystem.Name
|
||||
}
|
||||
}
|
||||
|
||||
// Override name from options if specified
|
||||
if cmd.Options.Name != nil {
|
||||
name = *cmd.Options.Name
|
||||
}
|
||||
|
||||
// Override name from arguments if specified
|
||||
if cmd.Name != "" {
|
||||
name = cmd.Name
|
||||
}
|
||||
|
||||
cisp := types.OvfCreateImportSpecParams{
|
||||
DiskProvisioning: cmd.Options.DiskProvisioning,
|
||||
EntityName: name,
|
||||
IpAllocationPolicy: cmd.Options.IPAllocationPolicy,
|
||||
IpProtocol: cmd.Options.IPProtocol,
|
||||
OvfManagerCommonParams: types.OvfManagerCommonParams{
|
||||
DeploymentOption: cmd.Options.Deployment,
|
||||
Locale: "US"},
|
||||
PropertyMapping: cmd.Map(cmd.Options.PropertyMapping),
|
||||
NetworkMapping: cmd.NetworkMap(e),
|
||||
}
|
||||
|
||||
host, err := cmd.HostSystemIfSpecified()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cmd.ResourcePool == nil {
|
||||
if host == nil {
|
||||
cmd.ResourcePool, err = cmd.ResourcePoolFlag.ResourcePool()
|
||||
} else {
|
||||
cmd.ResourcePool, err = host.ResourcePool(ctx)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
m := ovf.NewManager(cmd.Client)
|
||||
spec, err := m.CreateImportSpec(ctx, string(o), cmd.ResourcePool, cmd.Datastore, cisp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if spec.Error != nil {
|
||||
return nil, errors.New(spec.Error[0].LocalizedMessage)
|
||||
}
|
||||
if spec.Warning != nil {
|
||||
for _, w := range spec.Warning {
|
||||
_, _ = cmd.Log(fmt.Sprintf("Warning: %s\n", w.LocalizedMessage))
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.Options.Annotation != "" {
|
||||
switch s := spec.ImportSpec.(type) {
|
||||
case *types.VirtualMachineImportSpec:
|
||||
s.ConfigSpec.Annotation = cmd.Options.Annotation
|
||||
case *types.VirtualAppImportSpec:
|
||||
s.VAppConfigSpec.Annotation = cmd.Options.Annotation
|
||||
}
|
||||
}
|
||||
|
||||
folder, err := cmd.FolderOrDefault("vm")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lease, err := cmd.ResourcePool.ImportVApp(ctx, spec.ImportSpec, folder, host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info, err := lease.Wait(ctx, spec.FileItem)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u := lease.StartUpdater(ctx, info)
|
||||
defer u.Done()
|
||||
|
||||
for _, i := range info.Items {
|
||||
err = cmd.Upload(ctx, lease, i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &info.Entity, lease.Complete(ctx)
|
||||
}
|
||||
|
||||
func (cmd *ovfx) Upload(ctx context.Context, lease *nfc.Lease, item nfc.FileItem) error {
|
||||
file := item.Path
|
||||
|
||||
f, size, err := cmd.Open(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
logger := cmd.ProgressLogger(fmt.Sprintf("Uploading %s... ", path.Base(file)))
|
||||
defer logger.Wait()
|
||||
|
||||
opts := soap.Upload{
|
||||
ContentLength: size,
|
||||
Progress: logger,
|
||||
}
|
||||
|
||||
return lease.Upload(ctx, item, f, opts)
|
||||
}
|
||||
222
vendor/github.com/vmware/govmomi/govc/importx/spec.go
generated
vendored
Normal file
222
vendor/github.com/vmware/govmomi/govc/importx/spec.go
generated
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
Copyright (c) 2015-2016 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package importx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/govc/cli"
|
||||
"github.com/vmware/govmomi/ovf"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
var (
|
||||
allDiskProvisioningOptions = []string{
|
||||
string(types.OvfCreateImportSpecParamsDiskProvisioningTypeFlat),
|
||||
string(types.OvfCreateImportSpecParamsDiskProvisioningTypeMonolithicSparse),
|
||||
string(types.OvfCreateImportSpecParamsDiskProvisioningTypeMonolithicFlat),
|
||||
string(types.OvfCreateImportSpecParamsDiskProvisioningTypeTwoGbMaxExtentSparse),
|
||||
string(types.OvfCreateImportSpecParamsDiskProvisioningTypeTwoGbMaxExtentFlat),
|
||||
string(types.OvfCreateImportSpecParamsDiskProvisioningTypeThin),
|
||||
string(types.OvfCreateImportSpecParamsDiskProvisioningTypeThick),
|
||||
string(types.OvfCreateImportSpecParamsDiskProvisioningTypeSeSparse),
|
||||
string(types.OvfCreateImportSpecParamsDiskProvisioningTypeEagerZeroedThick),
|
||||
string(types.OvfCreateImportSpecParamsDiskProvisioningTypeSparse),
|
||||
}
|
||||
allIPAllocationPolicyOptions = []string{
|
||||
string(types.VAppIPAssignmentInfoIpAllocationPolicyDhcpPolicy),
|
||||
string(types.VAppIPAssignmentInfoIpAllocationPolicyTransientPolicy),
|
||||
string(types.VAppIPAssignmentInfoIpAllocationPolicyFixedPolicy),
|
||||
string(types.VAppIPAssignmentInfoIpAllocationPolicyFixedAllocatedPolicy),
|
||||
}
|
||||
allIPProtocolOptions = []string{
|
||||
string(types.VAppIPAssignmentInfoProtocolsIPv4),
|
||||
string(types.VAppIPAssignmentInfoProtocolsIPv6),
|
||||
}
|
||||
)
|
||||
|
||||
type spec struct {
|
||||
*ArchiveFlag
|
||||
|
||||
verbose bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("import.spec", &spec{})
|
||||
}
|
||||
|
||||
func (cmd *spec) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.ArchiveFlag, ctx = newArchiveFlag(ctx)
|
||||
cmd.ArchiveFlag.Register(ctx, f)
|
||||
|
||||
f.BoolVar(&cmd.verbose, "verbose", false, "Verbose spec output")
|
||||
}
|
||||
|
||||
func (cmd *spec) Process(ctx context.Context) error {
|
||||
if err := cmd.ArchiveFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *spec) Usage() string {
|
||||
return "PATH_TO_OVF_OR_OVA"
|
||||
}
|
||||
|
||||
func (cmd *spec) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
fpath := ""
|
||||
args := f.Args()
|
||||
if len(args) == 1 {
|
||||
fpath = f.Arg(0)
|
||||
}
|
||||
|
||||
if len(fpath) > 0 {
|
||||
switch path.Ext(fpath) {
|
||||
case ".ovf":
|
||||
cmd.Archive = &FileArchive{Path: fpath}
|
||||
case "", ".ova":
|
||||
cmd.Archive = &TapeArchive{Path: fpath}
|
||||
fpath = "*.ovf"
|
||||
default:
|
||||
return fmt.Errorf("invalid file extension %s", path.Ext(fpath))
|
||||
}
|
||||
}
|
||||
|
||||
return cmd.Spec(fpath)
|
||||
}
|
||||
|
||||
func (cmd *spec) Map(e *ovf.Envelope) (res []Property) {
|
||||
if e == nil || e.VirtualSystem == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, p := range e.VirtualSystem.Product {
|
||||
for i, v := range p.Property {
|
||||
if v.UserConfigurable == nil || !*v.UserConfigurable {
|
||||
continue
|
||||
}
|
||||
|
||||
d := ""
|
||||
if v.Default != nil {
|
||||
d = *v.Default
|
||||
}
|
||||
|
||||
// vSphere only accept True/False as boolean values for some reason
|
||||
if v.Type == "boolean" {
|
||||
d = strings.Title(d)
|
||||
}
|
||||
|
||||
// From OVF spec, section 9.5.1:
|
||||
// key-value-env = [class-value "."] key-value-prod ["." instance-value]
|
||||
k := v.Key
|
||||
if p.Class != nil {
|
||||
k = fmt.Sprintf("%s.%s", *p.Class, k)
|
||||
}
|
||||
if p.Instance != nil {
|
||||
k = fmt.Sprintf("%s.%s", k, *p.Instance)
|
||||
}
|
||||
|
||||
np := Property{KeyValue: types.KeyValue{Key: k, Value: d}}
|
||||
if cmd.verbose {
|
||||
np.Spec = &p.Property[i]
|
||||
}
|
||||
|
||||
res = append(res, np)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (cmd *spec) Spec(fpath string) error {
|
||||
e := &ovf.Envelope{}
|
||||
if fpath != "" {
|
||||
d, err := cmd.ReadOvf(fpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if e, err = cmd.ReadEnvelope(d); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var deploymentOptions []string
|
||||
if e.DeploymentOption != nil && e.DeploymentOption.Configuration != nil {
|
||||
// add default first
|
||||
for _, c := range e.DeploymentOption.Configuration {
|
||||
if c.Default != nil && *c.Default {
|
||||
deploymentOptions = append(deploymentOptions, c.ID)
|
||||
}
|
||||
}
|
||||
|
||||
for _, c := range e.DeploymentOption.Configuration {
|
||||
if c.Default == nil || !*c.Default {
|
||||
deploymentOptions = append(deploymentOptions, c.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
o := Options{
|
||||
DiskProvisioning: allDiskProvisioningOptions[0],
|
||||
IPAllocationPolicy: allIPAllocationPolicyOptions[0],
|
||||
IPProtocol: allIPProtocolOptions[0],
|
||||
MarkAsTemplate: false,
|
||||
PowerOn: false,
|
||||
WaitForIP: false,
|
||||
InjectOvfEnv: false,
|
||||
PropertyMapping: cmd.Map(e),
|
||||
}
|
||||
|
||||
if deploymentOptions != nil {
|
||||
o.Deployment = deploymentOptions[0]
|
||||
}
|
||||
|
||||
if e.VirtualSystem != nil && e.VirtualSystem.Annotation != nil {
|
||||
for _, a := range e.VirtualSystem.Annotation {
|
||||
o.Annotation += a.Annotation
|
||||
}
|
||||
}
|
||||
|
||||
if e.Network != nil {
|
||||
for _, net := range e.Network.Networks {
|
||||
o.NetworkMapping = append(o.NetworkMapping, Network{net.Name, ""})
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.verbose {
|
||||
if deploymentOptions != nil {
|
||||
o.AllDeploymentOptions = deploymentOptions
|
||||
}
|
||||
o.AllDiskProvisioningOptions = allDiskProvisioningOptions
|
||||
o.AllIPAllocationPolicyOptions = allIPAllocationPolicyOptions
|
||||
o.AllIPProtocolOptions = allIPProtocolOptions
|
||||
}
|
||||
|
||||
j, err := json.Marshal(&o)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(string(j))
|
||||
return nil
|
||||
}
|
||||
132
vendor/github.com/vmware/govmomi/govc/importx/vmdk.go
generated
vendored
Normal file
132
vendor/github.com/vmware/govmomi/govc/importx/vmdk.go
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
Copyright (c) 2014-2017 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package importx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/vmware/govmomi/govc/cli"
|
||||
"github.com/vmware/govmomi/govc/flags"
|
||||
"github.com/vmware/govmomi/vmdk"
|
||||
)
|
||||
|
||||
type disk struct {
|
||||
*flags.DatastoreFlag
|
||||
*flags.ResourcePoolFlag
|
||||
*flags.FolderFlag
|
||||
*flags.OutputFlag
|
||||
|
||||
force bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("import.vmdk", &disk{})
|
||||
}
|
||||
|
||||
func (cmd *disk) Register(ctx context.Context, f *flag.FlagSet) {
|
||||
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
|
||||
cmd.DatastoreFlag.Register(ctx, f)
|
||||
cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx)
|
||||
cmd.ResourcePoolFlag.Register(ctx, f)
|
||||
cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx)
|
||||
cmd.FolderFlag.Register(ctx, f)
|
||||
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
|
||||
cmd.OutputFlag.Register(ctx, f)
|
||||
|
||||
f.BoolVar(&cmd.force, "force", false, "Overwrite existing disk")
|
||||
}
|
||||
|
||||
func (cmd *disk) Process(ctx context.Context) error {
|
||||
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.ResourcePoolFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.FolderFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.OutputFlag.Process(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *disk) Usage() string {
|
||||
return "PATH_TO_VMDK [REMOTE_DIRECTORY]"
|
||||
}
|
||||
|
||||
func (cmd *disk) Run(ctx context.Context, f *flag.FlagSet) error {
|
||||
args := f.Args()
|
||||
if len(args) < 1 {
|
||||
return errors.New("no file to import")
|
||||
}
|
||||
|
||||
src := f.Arg(0)
|
||||
|
||||
c, err := cmd.DatastoreFlag.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dc, err := cmd.DatastoreFlag.Datacenter()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ds, err := cmd.DatastoreFlag.Datastore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pool, err := cmd.ResourcePoolFlag.ResourcePool()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
folder, err := cmd.FolderOrDefault("vm")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logger := cmd.ProgressLogger(fmt.Sprintf("Uploading %s... ", path.Base(src)))
|
||||
defer logger.Wait()
|
||||
|
||||
p := vmdk.ImportParams{
|
||||
Path: f.Arg(1),
|
||||
Logger: logger,
|
||||
Type: "", // TODO: flag
|
||||
Force: cmd.force,
|
||||
Datacenter: dc,
|
||||
Pool: pool,
|
||||
Folder: folder,
|
||||
}
|
||||
|
||||
err = vmdk.Import(ctx, c, src, ds, p)
|
||||
if err != nil && err == vmdk.ErrInvalidFormat {
|
||||
return fmt.Errorf(`%s
|
||||
The vmdk can be converted using one of:
|
||||
vmware-vdiskmanager -t 5 -r '%s' new.vmdk
|
||||
qemu-img convert -O vmdk -o subformat=streamOptimized '%s' new.vmdk`, err, src, src)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
150
vendor/github.com/vmware/govmomi/lookup/client.go
generated
vendored
Normal file
150
vendor/github.com/vmware/govmomi/lookup/client.go
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
Copyright (c) 2018 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package lookup
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"log"
|
||||
"net/url"
|
||||
|
||||
"github.com/vmware/govmomi/lookup/methods"
|
||||
"github.com/vmware/govmomi/lookup/types"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
vim "github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
const (
|
||||
Namespace = "lookup"
|
||||
Version = "2.0"
|
||||
Path = "/lookupservice" + vim25.Path
|
||||
)
|
||||
|
||||
var (
|
||||
ServiceInstance = vim.ManagedObjectReference{
|
||||
Type: "LookupServiceInstance",
|
||||
Value: "ServiceInstance",
|
||||
}
|
||||
)
|
||||
|
||||
// Client is a soap.Client targeting the SSO Lookup Service API endpoint.
|
||||
type Client struct {
|
||||
*soap.Client
|
||||
|
||||
ServiceContent types.LookupServiceContent
|
||||
}
|
||||
|
||||
// NewClient returns a client targeting the SSO Lookup Service API endpoint.
|
||||
func NewClient(ctx context.Context, c *vim25.Client) (*Client, error) {
|
||||
// PSC may be external, attempt to derive from sts.uri
|
||||
path := &url.URL{Path: Path}
|
||||
if c.ServiceContent.Setting != nil {
|
||||
m := object.NewOptionManager(c, *c.ServiceContent.Setting)
|
||||
opts, err := m.Query(ctx, "config.vpxd.sso.sts.uri")
|
||||
if err == nil && len(opts) == 1 {
|
||||
u, err := url.Parse(opts[0].GetOptionValue().Value.(string))
|
||||
if err == nil {
|
||||
path.Scheme = u.Scheme
|
||||
path.Host = u.Host
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sc := c.Client.NewServiceClient(path.String(), Namespace)
|
||||
sc.Version = Version
|
||||
|
||||
req := types.RetrieveServiceContent{
|
||||
This: ServiceInstance,
|
||||
}
|
||||
|
||||
res, err := methods.RetrieveServiceContent(ctx, sc, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Client{sc, res.Returnval}, nil
|
||||
}
|
||||
|
||||
func (c *Client) List(ctx context.Context, filter *types.LookupServiceRegistrationFilter) ([]types.LookupServiceRegistrationInfo, error) {
|
||||
req := types.List{
|
||||
This: *c.ServiceContent.ServiceRegistration,
|
||||
FilterCriteria: filter,
|
||||
}
|
||||
|
||||
res, err := methods.List(ctx, c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res.Returnval, nil
|
||||
}
|
||||
|
||||
func (c *Client) SiteID(ctx context.Context) (string, error) {
|
||||
req := types.GetSiteId{
|
||||
This: *c.ServiceContent.ServiceRegistration,
|
||||
}
|
||||
|
||||
res, err := methods.GetSiteId(ctx, c, &req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return res.Returnval, nil
|
||||
}
|
||||
|
||||
// EndpointURL uses the Lookup Service to find the endpoint URL and thumbprint for the given filter.
|
||||
// If the endpoint is found, its TLS certificate is also added to the vim25.Client's trusted host thumbprints.
|
||||
// If the Lookup Service is not available, the given path is returned as the default.
|
||||
func EndpointURL(ctx context.Context, c *vim25.Client, path string, filter *types.LookupServiceRegistrationFilter) string {
|
||||
if lu, err := NewClient(ctx, c); err == nil {
|
||||
info, _ := lu.List(ctx, filter)
|
||||
if len(info) != 0 && len(info[0].ServiceEndpoints) != 0 {
|
||||
endpoint := &info[0].ServiceEndpoints[0]
|
||||
path = endpoint.Url
|
||||
|
||||
if u, err := url.Parse(path); err == nil {
|
||||
if c.Thumbprint(u.Host) == "" {
|
||||
c.SetThumbprint(u.Host, endpointThumbprint(endpoint))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
// endpointThumbprint converts the base64 encoded endpoint certificate to a SHA1 thumbprint.
|
||||
func endpointThumbprint(endpoint *types.LookupServiceRegistrationEndpoint) string {
|
||||
if len(endpoint.SslTrust) == 0 {
|
||||
return ""
|
||||
}
|
||||
enc := endpoint.SslTrust[0]
|
||||
|
||||
b, err := base64.StdEncoding.DecodeString(enc)
|
||||
if err != nil {
|
||||
log.Printf("base64.Decode(%q): %s", enc, err)
|
||||
return ""
|
||||
}
|
||||
|
||||
cert, err := x509.ParseCertificate(b)
|
||||
if err != nil {
|
||||
log.Printf("x509.ParseCertificate(%q): %s", enc, err)
|
||||
return ""
|
||||
}
|
||||
|
||||
return soap.ThumbprintSHA1(cert)
|
||||
}
|
||||
224
vendor/github.com/vmware/govmomi/lookup/methods/methods.go
generated
vendored
Normal file
224
vendor/github.com/vmware/govmomi/lookup/methods/methods.go
generated
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
Copyright (c) 2014-2018 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package methods
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/vmware/govmomi/lookup/types"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
)
|
||||
|
||||
type CreateBody struct {
|
||||
Req *types.Create `xml:"urn:lookup Create,omitempty"`
|
||||
Res *types.CreateResponse `xml:"urn:lookup CreateResponse,omitempty"`
|
||||
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
|
||||
}
|
||||
|
||||
func (b *CreateBody) Fault() *soap.Fault { return b.Fault_ }
|
||||
|
||||
func Create(ctx context.Context, r soap.RoundTripper, req *types.Create) (*types.CreateResponse, error) {
|
||||
var reqBody, resBody CreateBody
|
||||
|
||||
reqBody.Req = req
|
||||
|
||||
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resBody.Res, nil
|
||||
}
|
||||
|
||||
type DeleteBody struct {
|
||||
Req *types.Delete `xml:"urn:lookup Delete,omitempty"`
|
||||
Res *types.DeleteResponse `xml:"urn:lookup DeleteResponse,omitempty"`
|
||||
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
|
||||
}
|
||||
|
||||
func (b *DeleteBody) Fault() *soap.Fault { return b.Fault_ }
|
||||
|
||||
func Delete(ctx context.Context, r soap.RoundTripper, req *types.Delete) (*types.DeleteResponse, error) {
|
||||
var reqBody, resBody DeleteBody
|
||||
|
||||
reqBody.Req = req
|
||||
|
||||
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resBody.Res, nil
|
||||
}
|
||||
|
||||
type GetBody struct {
|
||||
Req *types.Get `xml:"urn:lookup Get,omitempty"`
|
||||
Res *types.GetResponse `xml:"urn:lookup GetResponse,omitempty"`
|
||||
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
|
||||
}
|
||||
|
||||
func (b *GetBody) Fault() *soap.Fault { return b.Fault_ }
|
||||
|
||||
func Get(ctx context.Context, r soap.RoundTripper, req *types.Get) (*types.GetResponse, error) {
|
||||
var reqBody, resBody GetBody
|
||||
|
||||
reqBody.Req = req
|
||||
|
||||
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resBody.Res, nil
|
||||
}
|
||||
|
||||
type GetLocaleBody struct {
|
||||
Req *types.GetLocale `xml:"urn:lookup GetLocale,omitempty"`
|
||||
Res *types.GetLocaleResponse `xml:"urn:lookup GetLocaleResponse,omitempty"`
|
||||
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
|
||||
}
|
||||
|
||||
func (b *GetLocaleBody) Fault() *soap.Fault { return b.Fault_ }
|
||||
|
||||
func GetLocale(ctx context.Context, r soap.RoundTripper, req *types.GetLocale) (*types.GetLocaleResponse, error) {
|
||||
var reqBody, resBody GetLocaleBody
|
||||
|
||||
reqBody.Req = req
|
||||
|
||||
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resBody.Res, nil
|
||||
}
|
||||
|
||||
type GetSiteIdBody struct {
|
||||
Req *types.GetSiteId `xml:"urn:lookup GetSiteId,omitempty"`
|
||||
Res *types.GetSiteIdResponse `xml:"urn:lookup GetSiteIdResponse,omitempty"`
|
||||
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
|
||||
}
|
||||
|
||||
func (b *GetSiteIdBody) Fault() *soap.Fault { return b.Fault_ }
|
||||
|
||||
func GetSiteId(ctx context.Context, r soap.RoundTripper, req *types.GetSiteId) (*types.GetSiteIdResponse, error) {
|
||||
var reqBody, resBody GetSiteIdBody
|
||||
|
||||
reqBody.Req = req
|
||||
|
||||
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resBody.Res, nil
|
||||
}
|
||||
|
||||
type ListBody struct {
|
||||
Req *types.List `xml:"urn:lookup List,omitempty"`
|
||||
Res *types.ListResponse `xml:"urn:lookup ListResponse,omitempty"`
|
||||
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
|
||||
}
|
||||
|
||||
func (b *ListBody) Fault() *soap.Fault { return b.Fault_ }
|
||||
|
||||
func List(ctx context.Context, r soap.RoundTripper, req *types.List) (*types.ListResponse, error) {
|
||||
var reqBody, resBody ListBody
|
||||
|
||||
reqBody.Req = req
|
||||
|
||||
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resBody.Res, nil
|
||||
}
|
||||
|
||||
type RetrieveHaBackupConfigurationBody struct {
|
||||
Req *types.RetrieveHaBackupConfiguration `xml:"urn:lookup RetrieveHaBackupConfiguration,omitempty"`
|
||||
Res *types.RetrieveHaBackupConfigurationResponse `xml:"urn:lookup RetrieveHaBackupConfigurationResponse,omitempty"`
|
||||
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
|
||||
}
|
||||
|
||||
func (b *RetrieveHaBackupConfigurationBody) Fault() *soap.Fault { return b.Fault_ }
|
||||
|
||||
func RetrieveHaBackupConfiguration(ctx context.Context, r soap.RoundTripper, req *types.RetrieveHaBackupConfiguration) (*types.RetrieveHaBackupConfigurationResponse, error) {
|
||||
var reqBody, resBody RetrieveHaBackupConfigurationBody
|
||||
|
||||
reqBody.Req = req
|
||||
|
||||
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resBody.Res, nil
|
||||
}
|
||||
|
||||
type RetrieveServiceContentBody struct {
|
||||
Req *types.RetrieveServiceContent `xml:"urn:lookup RetrieveServiceContent,omitempty"`
|
||||
Res *types.RetrieveServiceContentResponse `xml:"urn:lookup RetrieveServiceContentResponse,omitempty"`
|
||||
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
|
||||
}
|
||||
|
||||
func (b *RetrieveServiceContentBody) Fault() *soap.Fault { return b.Fault_ }
|
||||
|
||||
func RetrieveServiceContent(ctx context.Context, r soap.RoundTripper, req *types.RetrieveServiceContent) (*types.RetrieveServiceContentResponse, error) {
|
||||
var reqBody, resBody RetrieveServiceContentBody
|
||||
|
||||
reqBody.Req = req
|
||||
|
||||
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resBody.Res, nil
|
||||
}
|
||||
|
||||
type SetBody struct {
|
||||
Req *types.Set `xml:"urn:lookup Set,omitempty"`
|
||||
Res *types.SetResponse `xml:"urn:lookup SetResponse,omitempty"`
|
||||
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
|
||||
}
|
||||
|
||||
func (b *SetBody) Fault() *soap.Fault { return b.Fault_ }
|
||||
|
||||
func Set(ctx context.Context, r soap.RoundTripper, req *types.Set) (*types.SetResponse, error) {
|
||||
var reqBody, resBody SetBody
|
||||
|
||||
reqBody.Req = req
|
||||
|
||||
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resBody.Res, nil
|
||||
}
|
||||
|
||||
type SetLocaleBody struct {
|
||||
Req *types.SetLocale `xml:"urn:lookup SetLocale,omitempty"`
|
||||
Res *types.SetLocaleResponse `xml:"urn:lookup SetLocaleResponse,omitempty"`
|
||||
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
|
||||
}
|
||||
|
||||
func (b *SetLocaleBody) Fault() *soap.Fault { return b.Fault_ }
|
||||
|
||||
func SetLocale(ctx context.Context, r soap.RoundTripper, req *types.SetLocale) (*types.SetLocaleResponse, error) {
|
||||
var reqBody, resBody SetLocaleBody
|
||||
|
||||
reqBody.Req = req
|
||||
|
||||
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resBody.Res, nil
|
||||
}
|
||||
412
vendor/github.com/vmware/govmomi/lookup/types/types.go
generated
vendored
Normal file
412
vendor/github.com/vmware/govmomi/lookup/types/types.go
generated
vendored
Normal file
@@ -0,0 +1,412 @@
|
||||
/*
|
||||
Copyright (c) 2014-2018 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
vim "github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type Create CreateRequestType
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:Create", reflect.TypeOf((*Create)(nil)).Elem())
|
||||
}
|
||||
|
||||
type CreateRequestType struct {
|
||||
This vim.ManagedObjectReference `xml:"_this"`
|
||||
ServiceId string `xml:"serviceId"`
|
||||
CreateSpec LookupServiceRegistrationCreateSpec `xml:"createSpec"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:CreateRequestType", reflect.TypeOf((*CreateRequestType)(nil)).Elem())
|
||||
}
|
||||
|
||||
type CreateResponse struct {
|
||||
}
|
||||
|
||||
type Delete DeleteRequestType
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:Delete", reflect.TypeOf((*Delete)(nil)).Elem())
|
||||
}
|
||||
|
||||
type DeleteRequestType struct {
|
||||
This vim.ManagedObjectReference `xml:"_this"`
|
||||
ServiceId string `xml:"serviceId"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:DeleteRequestType", reflect.TypeOf((*DeleteRequestType)(nil)).Elem())
|
||||
}
|
||||
|
||||
type DeleteResponse struct {
|
||||
}
|
||||
|
||||
type Get GetRequestType
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:Get", reflect.TypeOf((*Get)(nil)).Elem())
|
||||
}
|
||||
|
||||
type GetLocale GetLocaleRequestType
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:GetLocale", reflect.TypeOf((*GetLocale)(nil)).Elem())
|
||||
}
|
||||
|
||||
type GetLocaleRequestType struct {
|
||||
This vim.ManagedObjectReference `xml:"_this"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:GetLocaleRequestType", reflect.TypeOf((*GetLocaleRequestType)(nil)).Elem())
|
||||
}
|
||||
|
||||
type GetLocaleResponse struct {
|
||||
Returnval string `xml:"returnval"`
|
||||
}
|
||||
|
||||
type GetRequestType struct {
|
||||
This vim.ManagedObjectReference `xml:"_this"`
|
||||
ServiceId string `xml:"serviceId"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:GetRequestType", reflect.TypeOf((*GetRequestType)(nil)).Elem())
|
||||
}
|
||||
|
||||
type GetResponse struct {
|
||||
Returnval LookupServiceRegistrationInfo `xml:"returnval"`
|
||||
}
|
||||
|
||||
type GetSiteId GetSiteIdRequestType
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:GetSiteId", reflect.TypeOf((*GetSiteId)(nil)).Elem())
|
||||
}
|
||||
|
||||
type GetSiteIdRequestType struct {
|
||||
This vim.ManagedObjectReference `xml:"_this"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:GetSiteIdRequestType", reflect.TypeOf((*GetSiteIdRequestType)(nil)).Elem())
|
||||
}
|
||||
|
||||
type GetSiteIdResponse struct {
|
||||
Returnval string `xml:"returnval"`
|
||||
}
|
||||
|
||||
type List ListRequestType
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:List", reflect.TypeOf((*List)(nil)).Elem())
|
||||
}
|
||||
|
||||
type ListRequestType struct {
|
||||
This vim.ManagedObjectReference `xml:"_this"`
|
||||
FilterCriteria *LookupServiceRegistrationFilter `xml:"filterCriteria,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:ListRequestType", reflect.TypeOf((*ListRequestType)(nil)).Elem())
|
||||
}
|
||||
|
||||
type ListResponse struct {
|
||||
Returnval []LookupServiceRegistrationInfo `xml:"returnval,omitempty"`
|
||||
}
|
||||
|
||||
type LookupFaultEntryExistsFault struct {
|
||||
LookupFaultServiceFault
|
||||
|
||||
Name string `xml:"name"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupFaultEntryExistsFault", reflect.TypeOf((*LookupFaultEntryExistsFault)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupFaultEntryExistsFaultFault LookupFaultEntryExistsFault
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupFaultEntryExistsFaultFault", reflect.TypeOf((*LookupFaultEntryExistsFaultFault)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupFaultEntryNotFoundFault struct {
|
||||
LookupFaultServiceFault
|
||||
|
||||
Name string `xml:"name"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupFaultEntryNotFoundFault", reflect.TypeOf((*LookupFaultEntryNotFoundFault)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupFaultEntryNotFoundFaultFault LookupFaultEntryNotFoundFault
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupFaultEntryNotFoundFaultFault", reflect.TypeOf((*LookupFaultEntryNotFoundFaultFault)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupFaultServiceFault struct {
|
||||
vim.MethodFault
|
||||
|
||||
ErrorMessage string `xml:"errorMessage,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupFaultServiceFault", reflect.TypeOf((*LookupFaultServiceFault)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupFaultUnsupportedSiteFault struct {
|
||||
LookupFaultServiceFault
|
||||
|
||||
OperatingSite string `xml:"operatingSite"`
|
||||
RequestedSite string `xml:"requestedSite"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupFaultUnsupportedSiteFault", reflect.TypeOf((*LookupFaultUnsupportedSiteFault)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupFaultUnsupportedSiteFaultFault LookupFaultUnsupportedSiteFault
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupFaultUnsupportedSiteFaultFault", reflect.TypeOf((*LookupFaultUnsupportedSiteFaultFault)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupHaBackupNodeConfiguration struct {
|
||||
vim.DynamicData
|
||||
|
||||
DbType string `xml:"dbType"`
|
||||
DbJdbcUrl string `xml:"dbJdbcUrl"`
|
||||
DbUser string `xml:"dbUser"`
|
||||
DbPass string `xml:"dbPass"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupHaBackupNodeConfiguration", reflect.TypeOf((*LookupHaBackupNodeConfiguration)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupServiceContent struct {
|
||||
vim.DynamicData
|
||||
|
||||
LookupService vim.ManagedObjectReference `xml:"lookupService"`
|
||||
ServiceRegistration *vim.ManagedObjectReference `xml:"serviceRegistration,omitempty"`
|
||||
DeploymentInformationService vim.ManagedObjectReference `xml:"deploymentInformationService"`
|
||||
L10n vim.ManagedObjectReference `xml:"l10n"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupServiceContent", reflect.TypeOf((*LookupServiceContent)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupServiceRegistrationAttribute struct {
|
||||
vim.DynamicData
|
||||
|
||||
Key string `xml:"key"`
|
||||
Value string `xml:"value"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupServiceRegistrationAttribute", reflect.TypeOf((*LookupServiceRegistrationAttribute)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupServiceRegistrationCommonServiceInfo struct {
|
||||
LookupServiceRegistrationMutableServiceInfo
|
||||
|
||||
OwnerId string `xml:"ownerId"`
|
||||
ServiceType LookupServiceRegistrationServiceType `xml:"serviceType"`
|
||||
NodeId string `xml:"nodeId,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupServiceRegistrationCommonServiceInfo", reflect.TypeOf((*LookupServiceRegistrationCommonServiceInfo)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupServiceRegistrationCreateSpec struct {
|
||||
LookupServiceRegistrationCommonServiceInfo
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupServiceRegistrationCreateSpec", reflect.TypeOf((*LookupServiceRegistrationCreateSpec)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupServiceRegistrationEndpoint struct {
|
||||
vim.DynamicData
|
||||
|
||||
Url string `xml:"url"`
|
||||
EndpointType LookupServiceRegistrationEndpointType `xml:"endpointType"`
|
||||
SslTrust []string `xml:"sslTrust,omitempty"`
|
||||
EndpointAttributes []LookupServiceRegistrationAttribute `xml:"endpointAttributes,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupServiceRegistrationEndpoint", reflect.TypeOf((*LookupServiceRegistrationEndpoint)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupServiceRegistrationEndpointType struct {
|
||||
vim.DynamicData
|
||||
|
||||
Protocol string `xml:"protocol,omitempty"`
|
||||
Type string `xml:"type,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupServiceRegistrationEndpointType", reflect.TypeOf((*LookupServiceRegistrationEndpointType)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupServiceRegistrationFilter struct {
|
||||
vim.DynamicData
|
||||
|
||||
SiteId string `xml:"siteId,omitempty"`
|
||||
NodeId string `xml:"nodeId,omitempty"`
|
||||
ServiceType *LookupServiceRegistrationServiceType `xml:"serviceType,omitempty"`
|
||||
EndpointType *LookupServiceRegistrationEndpointType `xml:"endpointType,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupServiceRegistrationFilter", reflect.TypeOf((*LookupServiceRegistrationFilter)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupServiceRegistrationInfo struct {
|
||||
LookupServiceRegistrationCommonServiceInfo
|
||||
|
||||
ServiceId string `xml:"serviceId"`
|
||||
SiteId string `xml:"siteId"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupServiceRegistrationInfo", reflect.TypeOf((*LookupServiceRegistrationInfo)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupServiceRegistrationMutableServiceInfo struct {
|
||||
vim.DynamicData
|
||||
|
||||
ServiceVersion string `xml:"serviceVersion"`
|
||||
VendorNameResourceKey string `xml:"vendorNameResourceKey,omitempty"`
|
||||
VendorNameDefault string `xml:"vendorNameDefault,omitempty"`
|
||||
VendorProductInfoResourceKey string `xml:"vendorProductInfoResourceKey,omitempty"`
|
||||
VendorProductInfoDefault string `xml:"vendorProductInfoDefault,omitempty"`
|
||||
ServiceEndpoints []LookupServiceRegistrationEndpoint `xml:"serviceEndpoints,omitempty"`
|
||||
ServiceAttributes []LookupServiceRegistrationAttribute `xml:"serviceAttributes,omitempty"`
|
||||
ServiceNameResourceKey string `xml:"serviceNameResourceKey,omitempty"`
|
||||
ServiceNameDefault string `xml:"serviceNameDefault,omitempty"`
|
||||
ServiceDescriptionResourceKey string `xml:"serviceDescriptionResourceKey,omitempty"`
|
||||
ServiceDescriptionDefault string `xml:"serviceDescriptionDefault,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupServiceRegistrationMutableServiceInfo", reflect.TypeOf((*LookupServiceRegistrationMutableServiceInfo)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupServiceRegistrationServiceType struct {
|
||||
vim.DynamicData
|
||||
|
||||
Product string `xml:"product"`
|
||||
Type string `xml:"type"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupServiceRegistrationServiceType", reflect.TypeOf((*LookupServiceRegistrationServiceType)(nil)).Elem())
|
||||
}
|
||||
|
||||
type LookupServiceRegistrationSetSpec struct {
|
||||
LookupServiceRegistrationMutableServiceInfo
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:LookupServiceRegistrationSetSpec", reflect.TypeOf((*LookupServiceRegistrationSetSpec)(nil)).Elem())
|
||||
}
|
||||
|
||||
type RetrieveHaBackupConfiguration RetrieveHaBackupConfigurationRequestType
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:RetrieveHaBackupConfiguration", reflect.TypeOf((*RetrieveHaBackupConfiguration)(nil)).Elem())
|
||||
}
|
||||
|
||||
type RetrieveHaBackupConfigurationRequestType struct {
|
||||
This vim.ManagedObjectReference `xml:"_this"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:RetrieveHaBackupConfigurationRequestType", reflect.TypeOf((*RetrieveHaBackupConfigurationRequestType)(nil)).Elem())
|
||||
}
|
||||
|
||||
type RetrieveHaBackupConfigurationResponse struct {
|
||||
Returnval LookupHaBackupNodeConfiguration `xml:"returnval"`
|
||||
}
|
||||
|
||||
type RetrieveServiceContent RetrieveServiceContentRequestType
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:RetrieveServiceContent", reflect.TypeOf((*RetrieveServiceContent)(nil)).Elem())
|
||||
}
|
||||
|
||||
type RetrieveServiceContentRequestType struct {
|
||||
This vim.ManagedObjectReference `xml:"_this"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:RetrieveServiceContentRequestType", reflect.TypeOf((*RetrieveServiceContentRequestType)(nil)).Elem())
|
||||
}
|
||||
|
||||
type RetrieveServiceContentResponse struct {
|
||||
Returnval LookupServiceContent `xml:"returnval"`
|
||||
}
|
||||
|
||||
type Set SetRequestType
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:Set", reflect.TypeOf((*Set)(nil)).Elem())
|
||||
}
|
||||
|
||||
type SetLocale SetLocaleRequestType
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:SetLocale", reflect.TypeOf((*SetLocale)(nil)).Elem())
|
||||
}
|
||||
|
||||
type SetLocaleRequestType struct {
|
||||
This vim.ManagedObjectReference `xml:"_this"`
|
||||
Locale string `xml:"locale"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:SetLocaleRequestType", reflect.TypeOf((*SetLocaleRequestType)(nil)).Elem())
|
||||
}
|
||||
|
||||
type SetLocaleResponse struct {
|
||||
Returnval string `xml:"returnval"`
|
||||
}
|
||||
|
||||
type SetRequestType struct {
|
||||
This vim.ManagedObjectReference `xml:"_this"`
|
||||
ServiceId string `xml:"serviceId"`
|
||||
ServiceSpec LookupServiceRegistrationSetSpec `xml:"serviceSpec"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("lookup:SetRequestType", reflect.TypeOf((*SetRequestType)(nil)).Elem())
|
||||
}
|
||||
|
||||
type SetResponse struct {
|
||||
}
|
||||
128
vendor/github.com/vmware/govmomi/ovf/cim.go
generated
vendored
Normal file
128
vendor/github.com/vmware/govmomi/ovf/cim.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package ovf
|
||||
|
||||
import (
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
/*
|
||||
Source: http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2.24.0/CIM_VirtualSystemSettingData.xsd
|
||||
*/
|
||||
|
||||
type CIMVirtualSystemSettingData struct {
|
||||
ElementName string `xml:"ElementName"`
|
||||
InstanceID string `xml:"InstanceID"`
|
||||
|
||||
AutomaticRecoveryAction *uint8 `xml:"AutomaticRecoveryAction"`
|
||||
AutomaticShutdownAction *uint8 `xml:"AutomaticShutdownAction"`
|
||||
AutomaticStartupAction *uint8 `xml:"AutomaticStartupAction"`
|
||||
AutomaticStartupActionDelay *string `xml:"AutomaticStartupActionDelay>Interval"`
|
||||
AutomaticStartupActionSequenceNumber *uint16 `xml:"AutomaticStartupActionSequenceNumber"`
|
||||
Caption *string `xml:"Caption"`
|
||||
ConfigurationDataRoot *string `xml:"ConfigurationDataRoot"`
|
||||
ConfigurationFile *string `xml:"ConfigurationFile"`
|
||||
ConfigurationID *string `xml:"ConfigurationID"`
|
||||
CreationTime *string `xml:"CreationTime"`
|
||||
Description *string `xml:"Description"`
|
||||
LogDataRoot *string `xml:"LogDataRoot"`
|
||||
Notes []string `xml:"Notes"`
|
||||
RecoveryFile *string `xml:"RecoveryFile"`
|
||||
SnapshotDataRoot *string `xml:"SnapshotDataRoot"`
|
||||
SuspendDataRoot *string `xml:"SuspendDataRoot"`
|
||||
SwapFileDataRoot *string `xml:"SwapFileDataRoot"`
|
||||
VirtualSystemIdentifier *string `xml:"VirtualSystemIdentifier"`
|
||||
VirtualSystemType *string `xml:"VirtualSystemType"`
|
||||
}
|
||||
|
||||
/*
|
||||
Source: http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2.24.0/CIM_ResourceAllocationSettingData.xsd
|
||||
*/
|
||||
|
||||
type CIMResourceAllocationSettingData struct {
|
||||
ElementName string `xml:"ElementName"`
|
||||
InstanceID string `xml:"InstanceID"`
|
||||
|
||||
ResourceType *uint16 `xml:"ResourceType"`
|
||||
OtherResourceType *string `xml:"OtherResourceType"`
|
||||
ResourceSubType *string `xml:"ResourceSubType"`
|
||||
|
||||
AddressOnParent *string `xml:"AddressOnParent"`
|
||||
Address *string `xml:"Address"`
|
||||
AllocationUnits *string `xml:"AllocationUnits"`
|
||||
AutomaticAllocation *bool `xml:"AutomaticAllocation"`
|
||||
AutomaticDeallocation *bool `xml:"AutomaticDeallocation"`
|
||||
Caption *string `xml:"Caption"`
|
||||
Connection []string `xml:"Connection"`
|
||||
ConsumerVisibility *uint16 `xml:"ConsumerVisibility"`
|
||||
Description *string `xml:"Description"`
|
||||
HostResource []string `xml:"HostResource"`
|
||||
Limit *uint64 `xml:"Limit"`
|
||||
MappingBehavior *uint `xml:"MappingBehavior"`
|
||||
Parent *string `xml:"Parent"`
|
||||
PoolID *string `xml:"PoolID"`
|
||||
Reservation *uint64 `xml:"Reservation"`
|
||||
VirtualQuantity *uint `xml:"VirtualQuantity"`
|
||||
VirtualQuantityUnits *string `xml:"VirtualQuantityUnits"`
|
||||
Weight *uint `xml:"Weight"`
|
||||
}
|
||||
|
||||
/*
|
||||
Source: http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2.24.0/CIM_StorageAllocationSettingData.xsd
|
||||
*/
|
||||
type CIMStorageAllocationSettingData struct {
|
||||
ElementName string `xml:"ElementName"`
|
||||
InstanceID string `xml:"InstanceID"`
|
||||
|
||||
ResourceType *uint16 `xml:"ResourceType"`
|
||||
OtherResourceType *string `xml:"OtherResourceType"`
|
||||
ResourceSubType *string `xml:"ResourceSubType"`
|
||||
|
||||
Access *uint16 `xml:"Access"`
|
||||
Address *string `xml:"Address"`
|
||||
AddressOnParent *string `xml:"AddressOnParent"`
|
||||
AllocationUnits *string `xml:"AllocationUnits"`
|
||||
AutomaticAllocation *bool `xml:"AutomaticAllocation"`
|
||||
AutomaticDeallocation *bool `xml:"AutomaticDeallocation"`
|
||||
Caption *string `xml:"Caption"`
|
||||
ChangeableType *uint16 `xml:"ChangeableType"`
|
||||
ComponentSetting []types.AnyType `xml:"ComponentSetting"`
|
||||
ConfigurationName *string `xml:"ConfigurationName"`
|
||||
Connection []string `xml:"Connection"`
|
||||
ConsumerVisibility *uint16 `xml:"ConsumerVisibility"`
|
||||
Description *string `xml:"Description"`
|
||||
Generation *uint64 `xml:"Generation"`
|
||||
HostExtentName *string `xml:"HostExtentName"`
|
||||
HostExtentNameFormat *uint16 `xml:"HostExtentNameFormat"`
|
||||
HostExtentNameNamespace *uint16 `xml:"HostExtentNameNamespace"`
|
||||
HostExtentStartingAddress *uint64 `xml:"HostExtentStartingAddress"`
|
||||
HostResource []string `xml:"HostResource"`
|
||||
HostResourceBlockSize *uint64 `xml:"HostResourceBlockSize"`
|
||||
Limit *uint64 `xml:"Limit"`
|
||||
MappingBehavior *uint `xml:"MappingBehavior"`
|
||||
OtherHostExtentNameFormat *string `xml:"OtherHostExtentNameFormat"`
|
||||
OtherHostExtentNameNamespace *string `xml:"OtherHostExtentNameNamespace"`
|
||||
Parent *string `xml:"Parent"`
|
||||
PoolID *string `xml:"PoolID"`
|
||||
Reservation *uint64 `xml:"Reservation"`
|
||||
SoID *string `xml:"SoID"`
|
||||
SoOrgID *string `xml:"SoOrgID"`
|
||||
VirtualQuantity *uint `xml:"VirtualQuantity"`
|
||||
VirtualQuantityUnits *string `xml:"VirtualQuantityUnits"`
|
||||
VirtualResourceBlockSize *uint64 `xml:"VirtualResourceBlockSize"`
|
||||
Weight *uint `xml:"Weight"`
|
||||
}
|
||||
25
vendor/github.com/vmware/govmomi/ovf/doc.go
generated
vendored
Normal file
25
vendor/github.com/vmware/govmomi/ovf/doc.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Package ovf provides functionality to unmarshal and inspect the structure
|
||||
of an OVF file. It is not a complete implementation of the specification and
|
||||
is intended to be used to import virtual infrastructure into vSphere.
|
||||
|
||||
For a complete specification of the OVF standard, refer to:
|
||||
https://www.dmtf.org/sites/default/files/standards/documents/DSP0243_2.1.0.pdf
|
||||
*/
|
||||
package ovf
|
||||
99
vendor/github.com/vmware/govmomi/ovf/env.go
generated
vendored
Normal file
99
vendor/github.com/vmware/govmomi/ovf/env.go
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package ovf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/xml"
|
||||
)
|
||||
|
||||
const (
|
||||
ovfEnvHeader = `<Environment
|
||||
xmlns="http://schemas.dmtf.org/ovf/environment/1"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:oe="http://schemas.dmtf.org/ovf/environment/1"
|
||||
xmlns:ve="http://www.vmware.com/schema/ovfenv"
|
||||
oe:id=""
|
||||
ve:esxId="%s">`
|
||||
ovfEnvPlatformSection = `<PlatformSection>
|
||||
<Kind>%s</Kind>
|
||||
<Version>%s</Version>
|
||||
<Vendor>%s</Vendor>
|
||||
<Locale>%s</Locale>
|
||||
</PlatformSection>`
|
||||
ovfEnvPropertyHeader = `<PropertySection>`
|
||||
ovfEnvPropertyEntry = `<Property oe:key="%s" oe:value="%s"/>`
|
||||
ovfEnvPropertyFooter = `</PropertySection>`
|
||||
ovfEnvFooter = `</Environment>`
|
||||
)
|
||||
|
||||
type Env struct {
|
||||
XMLName xml.Name `xml:"http://schemas.dmtf.org/ovf/environment/1 Environment"`
|
||||
ID string `xml:"id,attr"`
|
||||
EsxID string `xml:"http://www.vmware.com/schema/ovfenv esxId,attr"`
|
||||
|
||||
Platform *PlatformSection `xml:"PlatformSection"`
|
||||
Property *PropertySection `xml:"PropertySection"`
|
||||
}
|
||||
|
||||
type PlatformSection struct {
|
||||
Kind string `xml:"Kind"`
|
||||
Version string `xml:"Version"`
|
||||
Vendor string `xml:"Vendor"`
|
||||
Locale string `xml:"Locale"`
|
||||
}
|
||||
|
||||
type PropertySection struct {
|
||||
Properties []EnvProperty `xml:"Property"`
|
||||
}
|
||||
|
||||
type EnvProperty struct {
|
||||
Key string `xml:"key,attr"`
|
||||
Value string `xml:"value,attr"`
|
||||
}
|
||||
|
||||
// Marshal marshals Env to xml by using xml.Marshal.
|
||||
func (e Env) Marshal() (string, error) {
|
||||
x, err := xml.Marshal(e)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s%s", xml.Header, x), nil
|
||||
}
|
||||
|
||||
// MarshalManual manually marshals Env to xml suitable for a vApp guest.
|
||||
// It exists to overcome the lack of expressiveness in Go's XML namespaces.
|
||||
func (e Env) MarshalManual() string {
|
||||
var buffer bytes.Buffer
|
||||
|
||||
buffer.WriteString(xml.Header)
|
||||
buffer.WriteString(fmt.Sprintf(ovfEnvHeader, e.EsxID))
|
||||
buffer.WriteString(fmt.Sprintf(ovfEnvPlatformSection, e.Platform.Kind, e.Platform.Version, e.Platform.Vendor, e.Platform.Locale))
|
||||
|
||||
buffer.WriteString(fmt.Sprint(ovfEnvPropertyHeader))
|
||||
for _, p := range e.Property.Properties {
|
||||
buffer.WriteString(fmt.Sprintf(ovfEnvPropertyEntry, p.Key, p.Value))
|
||||
}
|
||||
buffer.WriteString(fmt.Sprint(ovfEnvPropertyFooter))
|
||||
|
||||
buffer.WriteString(fmt.Sprint(ovfEnvFooter))
|
||||
|
||||
return buffer.String()
|
||||
}
|
||||
200
vendor/github.com/vmware/govmomi/ovf/envelope.go
generated
vendored
Normal file
200
vendor/github.com/vmware/govmomi/ovf/envelope.go
generated
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package ovf
|
||||
|
||||
type Envelope struct {
|
||||
References []File `xml:"References>File"`
|
||||
|
||||
// Package level meta-data
|
||||
Annotation *AnnotationSection `xml:"AnnotationSection"`
|
||||
Product *ProductSection `xml:"ProductSection"`
|
||||
Network *NetworkSection `xml:"NetworkSection"`
|
||||
Disk *DiskSection `xml:"DiskSection"`
|
||||
OperatingSystem *OperatingSystemSection `xml:"OperatingSystemSection"`
|
||||
Eula *EulaSection `xml:"EulaSection"`
|
||||
VirtualHardware *VirtualHardwareSection `xml:"VirtualHardwareSection"`
|
||||
ResourceAllocation *ResourceAllocationSection `xml:"ResourceAllocationSection"`
|
||||
DeploymentOption *DeploymentOptionSection `xml:"DeploymentOptionSection"`
|
||||
|
||||
// Content: A VirtualSystem or a VirtualSystemCollection
|
||||
VirtualSystem *VirtualSystem `xml:"VirtualSystem"`
|
||||
}
|
||||
|
||||
type VirtualSystem struct {
|
||||
Content
|
||||
|
||||
Annotation []AnnotationSection `xml:"AnnotationSection"`
|
||||
Product []ProductSection `xml:"ProductSection"`
|
||||
OperatingSystem []OperatingSystemSection `xml:"OperatingSystemSection"`
|
||||
Eula []EulaSection `xml:"EulaSection"`
|
||||
VirtualHardware []VirtualHardwareSection `xml:"VirtualHardwareSection"`
|
||||
}
|
||||
|
||||
type File struct {
|
||||
ID string `xml:"id,attr"`
|
||||
Href string `xml:"href,attr"`
|
||||
Size uint `xml:"size,attr"`
|
||||
Compression *string `xml:"compression,attr"`
|
||||
ChunkSize *int `xml:"chunkSize,attr"`
|
||||
}
|
||||
|
||||
type Content struct {
|
||||
ID string `xml:"id,attr"`
|
||||
Info string `xml:"Info"`
|
||||
Name *string `xml:"Name"`
|
||||
}
|
||||
|
||||
type Section struct {
|
||||
Required *bool `xml:"required,attr"`
|
||||
Info string `xml:"Info"`
|
||||
}
|
||||
|
||||
type AnnotationSection struct {
|
||||
Section
|
||||
|
||||
Annotation string `xml:"Annotation"`
|
||||
}
|
||||
|
||||
type ProductSection struct {
|
||||
Section
|
||||
|
||||
Class *string `xml:"class,attr"`
|
||||
Instance *string `xml:"instance,attr"`
|
||||
|
||||
Product string `xml:"Product"`
|
||||
Vendor string `xml:"Vendor"`
|
||||
Version string `xml:"Version"`
|
||||
FullVersion string `xml:"FullVersion"`
|
||||
ProductURL string `xml:"ProductUrl"`
|
||||
VendorURL string `xml:"VendorUrl"`
|
||||
AppURL string `xml:"AppUrl"`
|
||||
Property []Property `xml:"Property"`
|
||||
}
|
||||
|
||||
type Property struct {
|
||||
Key string `xml:"key,attr"`
|
||||
Type string `xml:"type,attr"`
|
||||
Qualifiers *string `xml:"qualifiers,attr"`
|
||||
UserConfigurable *bool `xml:"userConfigurable,attr"`
|
||||
Default *string `xml:"value,attr"`
|
||||
Password *bool `xml:"password,attr"`
|
||||
|
||||
Label *string `xml:"Label"`
|
||||
Description *string `xml:"Description"`
|
||||
|
||||
Values []PropertyConfigurationValue `xml:"Value"`
|
||||
}
|
||||
|
||||
type PropertyConfigurationValue struct {
|
||||
Value string `xml:"value,attr"`
|
||||
Configuration *string `xml:"configuration,attr"`
|
||||
}
|
||||
|
||||
type NetworkSection struct {
|
||||
Section
|
||||
|
||||
Networks []Network `xml:"Network"`
|
||||
}
|
||||
|
||||
type Network struct {
|
||||
Name string `xml:"name,attr"`
|
||||
|
||||
Description string `xml:"Description"`
|
||||
}
|
||||
|
||||
type DiskSection struct {
|
||||
Section
|
||||
|
||||
Disks []VirtualDiskDesc `xml:"Disk"`
|
||||
}
|
||||
|
||||
type VirtualDiskDesc struct {
|
||||
DiskID string `xml:"diskId,attr"`
|
||||
FileRef *string `xml:"fileRef,attr"`
|
||||
Capacity string `xml:"capacity,attr"`
|
||||
CapacityAllocationUnits *string `xml:"capacityAllocationUnits,attr"`
|
||||
Format *string `xml:"format,attr"`
|
||||
PopulatedSize *int `xml:"populatedSize,attr"`
|
||||
ParentRef *string `xml:"parentRef,attr"`
|
||||
}
|
||||
|
||||
type OperatingSystemSection struct {
|
||||
Section
|
||||
|
||||
ID int16 `xml:"id,attr"`
|
||||
Version *string `xml:"version,attr"`
|
||||
OSType *string `xml:"osType,attr"`
|
||||
|
||||
Description *string `xml:"Description"`
|
||||
}
|
||||
|
||||
type EulaSection struct {
|
||||
Section
|
||||
|
||||
License string `xml:"License"`
|
||||
}
|
||||
|
||||
type VirtualHardwareSection struct {
|
||||
Section
|
||||
|
||||
ID *string `xml:"id,attr"`
|
||||
Transport *string `xml:"transport,attr"`
|
||||
|
||||
System *VirtualSystemSettingData `xml:"System"`
|
||||
Item []ResourceAllocationSettingData `xml:"Item"`
|
||||
StorageItem []StorageAllocationSettingData `xml:"StorageItem"`
|
||||
}
|
||||
|
||||
type VirtualSystemSettingData struct {
|
||||
CIMVirtualSystemSettingData
|
||||
}
|
||||
|
||||
type ResourceAllocationSettingData struct {
|
||||
CIMResourceAllocationSettingData
|
||||
|
||||
Required *bool `xml:"required,attr"`
|
||||
Configuration *string `xml:"configuration,attr"`
|
||||
Bound *string `xml:"bound,attr"`
|
||||
}
|
||||
|
||||
type StorageAllocationSettingData struct {
|
||||
CIMStorageAllocationSettingData
|
||||
|
||||
Required *bool `xml:"required,attr"`
|
||||
Configuration *string `xml:"configuration,attr"`
|
||||
Bound *string `xml:"bound,attr"`
|
||||
}
|
||||
|
||||
type ResourceAllocationSection struct {
|
||||
Section
|
||||
|
||||
Item []ResourceAllocationSettingData `xml:"Item"`
|
||||
}
|
||||
|
||||
type DeploymentOptionSection struct {
|
||||
Section
|
||||
|
||||
Configuration []DeploymentOptionConfiguration `xml:"Configuration"`
|
||||
}
|
||||
|
||||
type DeploymentOptionConfiguration struct {
|
||||
ID string `xml:"id,attr"`
|
||||
Default *bool `xml:"default,attr"`
|
||||
|
||||
Label string `xml:"Label"`
|
||||
Description string `xml:"Description"`
|
||||
}
|
||||
103
vendor/github.com/vmware/govmomi/ovf/manager.go
generated
vendored
Normal file
103
vendor/github.com/vmware/govmomi/ovf/manager.go
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
Copyright (c) 2015-2017 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package ovf
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/methods"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type Manager struct {
|
||||
types.ManagedObjectReference
|
||||
|
||||
c *vim25.Client
|
||||
}
|
||||
|
||||
func NewManager(c *vim25.Client) *Manager {
|
||||
return &Manager{*c.ServiceContent.OvfManager, c}
|
||||
}
|
||||
|
||||
// CreateDescriptor wraps methods.CreateDescriptor
|
||||
func (m *Manager) CreateDescriptor(ctx context.Context, obj mo.Reference, cdp types.OvfCreateDescriptorParams) (*types.OvfCreateDescriptorResult, error) {
|
||||
req := types.CreateDescriptor{
|
||||
This: m.Reference(),
|
||||
Obj: obj.Reference(),
|
||||
Cdp: cdp,
|
||||
}
|
||||
|
||||
res, err := methods.CreateDescriptor(ctx, m.c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &res.Returnval, nil
|
||||
}
|
||||
|
||||
// CreateImportSpec wraps methods.CreateImportSpec
|
||||
func (m *Manager) CreateImportSpec(ctx context.Context, ovfDescriptor string, resourcePool mo.Reference, datastore mo.Reference, cisp types.OvfCreateImportSpecParams) (*types.OvfCreateImportSpecResult, error) {
|
||||
req := types.CreateImportSpec{
|
||||
This: m.Reference(),
|
||||
OvfDescriptor: ovfDescriptor,
|
||||
ResourcePool: resourcePool.Reference(),
|
||||
Datastore: datastore.Reference(),
|
||||
Cisp: cisp,
|
||||
}
|
||||
|
||||
res, err := methods.CreateImportSpec(ctx, m.c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &res.Returnval, nil
|
||||
}
|
||||
|
||||
// ParseDescriptor wraps methods.ParseDescriptor
|
||||
func (m *Manager) ParseDescriptor(ctx context.Context, ovfDescriptor string, pdp types.OvfParseDescriptorParams) (*types.OvfParseDescriptorResult, error) {
|
||||
req := types.ParseDescriptor{
|
||||
This: m.Reference(),
|
||||
OvfDescriptor: ovfDescriptor,
|
||||
Pdp: pdp,
|
||||
}
|
||||
|
||||
res, err := methods.ParseDescriptor(ctx, m.c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &res.Returnval, nil
|
||||
}
|
||||
|
||||
// ValidateHost wraps methods.ValidateHost
|
||||
func (m *Manager) ValidateHost(ctx context.Context, ovfDescriptor string, host mo.Reference, vhp types.OvfValidateHostParams) (*types.OvfValidateHostResult, error) {
|
||||
req := types.ValidateHost{
|
||||
This: m.Reference(),
|
||||
OvfDescriptor: ovfDescriptor,
|
||||
Host: host.Reference(),
|
||||
Vhp: vhp,
|
||||
}
|
||||
|
||||
res, err := methods.ValidateHost(ctx, m.c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &res.Returnval, nil
|
||||
}
|
||||
35
vendor/github.com/vmware/govmomi/ovf/ovf.go
generated
vendored
Normal file
35
vendor/github.com/vmware/govmomi/ovf/ovf.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package ovf
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/xml"
|
||||
)
|
||||
|
||||
func Unmarshal(r io.Reader) (*Envelope, error) {
|
||||
var e Envelope
|
||||
|
||||
dec := xml.NewDecoder(r)
|
||||
err := dec.Decode(&e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &e, nil
|
||||
}
|
||||
209
vendor/github.com/vmware/govmomi/sts/client.go
generated
vendored
Normal file
209
vendor/github.com/vmware/govmomi/sts/client.go
generated
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
Copyright (c) 2018 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sts
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/govmomi/lookup"
|
||||
"github.com/vmware/govmomi/lookup/types"
|
||||
"github.com/vmware/govmomi/sts/internal"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
)
|
||||
|
||||
const (
|
||||
Namespace = "oasis:names:tc:SAML:2.0:assertion"
|
||||
Path = "/sts/STSService"
|
||||
)
|
||||
|
||||
// Client is a soap.Client targeting the STS (Secure Token Service) API endpoint.
|
||||
type Client struct {
|
||||
*soap.Client
|
||||
}
|
||||
|
||||
// NewClient returns a client targeting the STS API endpoint.
|
||||
// The Client.URL will be set to that of the Lookup Service's endpoint registration,
|
||||
// as the SSO endpoint can be external to vCenter. If the Lookup Service is not available,
|
||||
// URL defaults to Path on the vim25.Client.URL.Host.
|
||||
func NewClient(ctx context.Context, c *vim25.Client) (*Client, error) {
|
||||
filter := &types.LookupServiceRegistrationFilter{
|
||||
ServiceType: &types.LookupServiceRegistrationServiceType{
|
||||
Product: "com.vmware.cis",
|
||||
Type: "cs.identity",
|
||||
},
|
||||
EndpointType: &types.LookupServiceRegistrationEndpointType{
|
||||
Protocol: "wsTrust",
|
||||
Type: "com.vmware.cis.cs.identity.sso",
|
||||
},
|
||||
}
|
||||
|
||||
url := lookup.EndpointURL(ctx, c, Path, filter)
|
||||
sc := c.Client.NewServiceClient(url, Namespace)
|
||||
|
||||
return &Client{sc}, nil
|
||||
}
|
||||
|
||||
// TokenRequest parameters for issuing a SAML token.
|
||||
// At least one of Userinfo or Certificate must be specified.
|
||||
type TokenRequest struct {
|
||||
Userinfo *url.Userinfo // Userinfo when set issues a Bearer token
|
||||
Certificate *tls.Certificate // Certificate when set issues a HoK token
|
||||
Lifetime time.Duration // Lifetime is the token's lifetime, defaults to 10m
|
||||
Renewable bool // Renewable allows the issued token to be renewed
|
||||
Delegatable bool // Delegatable allows the issued token to be delegated (e.g. for use with ActAs)
|
||||
ActAs bool // ActAs allows to request an ActAs token based on the passed Token.
|
||||
Token string // Token for Renew request or Issue request ActAs identity or to be exchanged.
|
||||
KeyType string // KeyType for requested token (if not set will be decucted from Userinfo and Certificate options)
|
||||
KeyID string // KeyID used for signing the requests
|
||||
}
|
||||
|
||||
func (c *Client) newRequest(req TokenRequest, kind string, s *Signer) (internal.RequestSecurityToken, error) {
|
||||
if req.Lifetime == 0 {
|
||||
req.Lifetime = 5 * time.Minute
|
||||
}
|
||||
|
||||
created := time.Now().UTC()
|
||||
rst := internal.RequestSecurityToken{
|
||||
TokenType: c.Namespace,
|
||||
RequestType: "http://docs.oasis-open.org/ws-sx/ws-trust/200512/" + kind,
|
||||
SignatureAlgorithm: internal.SHA256,
|
||||
Lifetime: &internal.Lifetime{
|
||||
Created: created.Format(internal.Time),
|
||||
Expires: created.Add(req.Lifetime).Format(internal.Time),
|
||||
},
|
||||
Renewing: &internal.Renewing{
|
||||
Allow: req.Renewable,
|
||||
// /wst:RequestSecurityToken/wst:Renewing/@OK
|
||||
// "It NOT RECOMMENDED to use this as it can leave you open to certain types of security attacks.
|
||||
// Issuers MAY restrict the period after expiration during which time the token can be renewed.
|
||||
// This window is governed by the issuer's policy."
|
||||
OK: false,
|
||||
},
|
||||
Delegatable: req.Delegatable,
|
||||
KeyType: req.KeyType,
|
||||
}
|
||||
|
||||
if req.KeyType == "" {
|
||||
// Deduce KeyType based on Certificate nad Userinfo.
|
||||
if req.Certificate == nil {
|
||||
if req.Userinfo == nil {
|
||||
return rst, errors.New("one of TokenRequest Certificate or Userinfo is required")
|
||||
}
|
||||
rst.KeyType = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer"
|
||||
} else {
|
||||
rst.KeyType = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/PublicKey"
|
||||
// For HOK KeyID is required.
|
||||
if req.KeyID == "" {
|
||||
req.KeyID = newID()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if req.KeyID != "" {
|
||||
rst.UseKey = &internal.UseKey{Sig: req.KeyID}
|
||||
s.keyID = rst.UseKey.Sig
|
||||
}
|
||||
|
||||
return rst, nil
|
||||
}
|
||||
|
||||
func (s *Signer) setLifetime(lifetime *internal.Lifetime) error {
|
||||
var err error
|
||||
if lifetime != nil {
|
||||
s.Lifetime.Created, err = time.Parse(internal.Time, lifetime.Created)
|
||||
if err == nil {
|
||||
s.Lifetime.Expires, err = time.Parse(internal.Time, lifetime.Expires)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Issue is used to request a security token.
|
||||
// The returned Signer can be used to sign SOAP requests, such as the SessionManager LoginByToken method and the RequestSecurityToken method itself.
|
||||
// One of TokenRequest Certificate or Userinfo is required, with Certificate taking precedence.
|
||||
// When Certificate is set, a Holder-of-Key token will be requested. Otherwise, a Bearer token is requested with the Userinfo credentials.
|
||||
// See: http://docs.oasis-open.org/ws-sx/ws-trust/v1.4/errata01/os/ws-trust-1.4-errata01-os-complete.html#_Toc325658937
|
||||
func (c *Client) Issue(ctx context.Context, req TokenRequest) (*Signer, error) {
|
||||
s := &Signer{
|
||||
Certificate: req.Certificate,
|
||||
keyID: req.KeyID,
|
||||
Token: req.Token,
|
||||
user: req.Userinfo,
|
||||
}
|
||||
|
||||
rst, err := c.newRequest(req, "Issue", s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.ActAs {
|
||||
rst.ActAs = &internal.Target{
|
||||
Token: req.Token,
|
||||
}
|
||||
}
|
||||
|
||||
header := soap.Header{
|
||||
Security: s,
|
||||
Action: rst.Action(),
|
||||
}
|
||||
|
||||
res, err := internal.Issue(c.WithHeader(ctx, header), c, &rst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.Token = res.RequestSecurityTokenResponse.RequestedSecurityToken.Assertion
|
||||
|
||||
return s, s.setLifetime(res.RequestSecurityTokenResponse.Lifetime)
|
||||
}
|
||||
|
||||
// Renew is used to request a security token renewal.
|
||||
func (c *Client) Renew(ctx context.Context, req TokenRequest) (*Signer, error) {
|
||||
s := &Signer{
|
||||
Certificate: req.Certificate,
|
||||
}
|
||||
|
||||
rst, err := c.newRequest(req, "Renew", s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.Token == "" {
|
||||
return nil, errors.New("TokenRequest Token is required")
|
||||
}
|
||||
|
||||
rst.RenewTarget = &internal.Target{Token: req.Token}
|
||||
|
||||
header := soap.Header{
|
||||
Security: s,
|
||||
Action: rst.Action(),
|
||||
}
|
||||
|
||||
res, err := internal.Renew(c.WithHeader(ctx, header), c, &rst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.Token = res.RequestedSecurityToken.Assertion
|
||||
|
||||
return s, s.setLifetime(res.Lifetime)
|
||||
}
|
||||
694
vendor/github.com/vmware/govmomi/sts/internal/types.go
generated
vendored
Normal file
694
vendor/github.com/vmware/govmomi/sts/internal/types.go
generated
vendored
Normal file
@@ -0,0 +1,694 @@
|
||||
/*
|
||||
Copyright (c) 2018 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package internal
|
||||
|
||||
// The sts/internal package provides the types for invoking the sts.Issue method.
|
||||
// The sts.Issue and SessionManager LoginByToken methods require an XML signature.
|
||||
// Unlike the JRE and .NET runtimes, the Go stdlib does not support XML signing.
|
||||
// We should considering contributing to the goxmldsig package and gosaml2 to meet
|
||||
// the needs of sts.Issue rather than maintaining this package long term.
|
||||
// The tricky part of xmldig is the XML canonicalization (C14N), which is responsible
|
||||
// for most of the make-your-eyes bleed XML formatting in this package.
|
||||
// C14N is also why some structures use xml.Name without a field tag and methods modify the xml.Name directly,
|
||||
// though also working around Go's handling of XML namespace prefixes.
|
||||
// Most of the types in this package were originally generated from the wsdl and hacked up gen/ scripts,
|
||||
// but have since been modified by hand.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"log"
|
||||
"path"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"github.com/vmware/govmomi/vim25/xml"
|
||||
)
|
||||
|
||||
const (
|
||||
XSI = "http://www.w3.org/2001/XMLSchema-instance"
|
||||
WSU = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
|
||||
DSIG = "http://www.w3.org/2000/09/xmldsig#"
|
||||
SHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
|
||||
Time = "2006-01-02T15:04:05.000Z"
|
||||
)
|
||||
|
||||
// Security is used as soap.Envelope.Header.Security when signing requests.
|
||||
type Security struct {
|
||||
XMLName xml.Name `xml:"wsse:Security"`
|
||||
WSSE string `xml:"xmlns:wsse,attr"`
|
||||
WSU string `xml:"xmlns:wsu,attr"`
|
||||
Timestamp Timestamp
|
||||
BinarySecurityToken *BinarySecurityToken `xml:",omitempty"`
|
||||
UsernameToken *UsernameToken `xml:",omitempty"`
|
||||
Assertion string `xml:",innerxml"`
|
||||
Signature *Signature `xml:",omitempty"`
|
||||
}
|
||||
|
||||
type Timestamp struct {
|
||||
XMLName xml.Name `xml:"wsu:Timestamp"`
|
||||
NS string `xml:"xmlns:wsu,attr"`
|
||||
ID string `xml:"wsu:Id,attr"`
|
||||
Created string `xml:"wsu:Created"`
|
||||
Expires string `xml:"wsu:Expires"`
|
||||
}
|
||||
|
||||
func (t *Timestamp) C14N() string {
|
||||
return Marshal(t)
|
||||
}
|
||||
|
||||
type BinarySecurityToken struct {
|
||||
XMLName xml.Name `xml:"wsse:BinarySecurityToken"`
|
||||
EncodingType string `xml:"EncodingType,attr"`
|
||||
ValueType string `xml:"ValueType,attr"`
|
||||
ID string `xml:"wsu:Id,attr"`
|
||||
Value string `xml:",chardata"`
|
||||
}
|
||||
|
||||
type UsernameToken struct {
|
||||
XMLName xml.Name `xml:"wsse:UsernameToken"`
|
||||
Username string `xml:"wsse:Username"`
|
||||
Password string `xml:"wsse:Password"`
|
||||
}
|
||||
|
||||
type Signature struct {
|
||||
XMLName xml.Name
|
||||
NS string `xml:"xmlns:ds,attr"`
|
||||
ID string `xml:"Id,attr"`
|
||||
SignedInfo SignedInfo
|
||||
SignatureValue Value
|
||||
KeyInfo KeyInfo
|
||||
}
|
||||
|
||||
func (s *Signature) C14N() string {
|
||||
return fmt.Sprintf(`<ds:Signature xmlns:ds="%s">%s%s%s</ds:Signature>`,
|
||||
DSIG, s.SignedInfo.C14N(), s.SignatureValue.C14N(), s.KeyInfo.C14N())
|
||||
}
|
||||
|
||||
type SignedInfo struct {
|
||||
XMLName xml.Name
|
||||
NS string `xml:"xmlns:ds,attr,omitempty"`
|
||||
CanonicalizationMethod Method
|
||||
SignatureMethod Method
|
||||
Reference []Reference
|
||||
}
|
||||
|
||||
func (s SignedInfo) C14N() string {
|
||||
ns := "" // empty in ActAs c14n form for example
|
||||
if s.NS != "" {
|
||||
ns = fmt.Sprintf(` xmlns:ds="%s"`, s.NS)
|
||||
}
|
||||
|
||||
c14n := []string{fmt.Sprintf("<ds:SignedInfo%s>", ns)}
|
||||
c14n = append(c14n, s.CanonicalizationMethod.C14N(), s.SignatureMethod.C14N())
|
||||
for i := range s.Reference {
|
||||
c14n = append(c14n, s.Reference[i].C14N())
|
||||
}
|
||||
c14n = append(c14n, "</ds:SignedInfo>")
|
||||
|
||||
return strings.Join(c14n, "")
|
||||
}
|
||||
|
||||
type Method struct {
|
||||
XMLName xml.Name
|
||||
Algorithm string `xml:",attr"`
|
||||
}
|
||||
|
||||
func (m *Method) C14N() string {
|
||||
return mkns("ds", m, &m.XMLName)
|
||||
}
|
||||
|
||||
type Value struct {
|
||||
XMLName xml.Name
|
||||
Value string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
func (v *Value) C14N() string {
|
||||
return mkns("ds", v, &v.XMLName)
|
||||
}
|
||||
|
||||
type Reference struct {
|
||||
XMLName xml.Name
|
||||
URI string `xml:",attr"`
|
||||
Transforms Transforms
|
||||
DigestMethod Method
|
||||
DigestValue Value
|
||||
}
|
||||
|
||||
func (r Reference) C14N() string {
|
||||
for i := range r.Transforms.Transform {
|
||||
t := &r.Transforms.Transform[i]
|
||||
t.XMLName.Local = "ds:Transform"
|
||||
t.XMLName.Space = ""
|
||||
|
||||
if t.InclusiveNamespaces != nil {
|
||||
name := &t.InclusiveNamespaces.XMLName
|
||||
if !strings.HasPrefix(name.Local, "ec:") {
|
||||
name.Local = "ec:" + name.Local
|
||||
name.Space = ""
|
||||
}
|
||||
t.InclusiveNamespaces.NS = t.Algorithm
|
||||
}
|
||||
}
|
||||
|
||||
c14n := []string{
|
||||
fmt.Sprintf(`<ds:Reference URI="%s">`, r.URI),
|
||||
r.Transforms.C14N(),
|
||||
r.DigestMethod.C14N(),
|
||||
r.DigestValue.C14N(),
|
||||
"</ds:Reference>",
|
||||
}
|
||||
|
||||
return strings.Join(c14n, "")
|
||||
}
|
||||
|
||||
func NewReference(id string, val string) Reference {
|
||||
sum := sha256.Sum256([]byte(val))
|
||||
|
||||
return Reference{
|
||||
XMLName: xml.Name{Local: "ds:Reference"},
|
||||
URI: "#" + id,
|
||||
Transforms: Transforms{
|
||||
XMLName: xml.Name{Local: "ds:Transforms"},
|
||||
Transform: []Transform{
|
||||
Transform{
|
||||
XMLName: xml.Name{Local: "ds:Transform"},
|
||||
Algorithm: "http://www.w3.org/2001/10/xml-exc-c14n#",
|
||||
},
|
||||
},
|
||||
},
|
||||
DigestMethod: Method{
|
||||
XMLName: xml.Name{Local: "ds:DigestMethod"},
|
||||
Algorithm: "http://www.w3.org/2001/04/xmlenc#sha256",
|
||||
},
|
||||
DigestValue: Value{
|
||||
XMLName: xml.Name{Local: "ds:DigestValue"},
|
||||
Value: base64.StdEncoding.EncodeToString(sum[:]),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type Transforms struct {
|
||||
XMLName xml.Name
|
||||
Transform []Transform
|
||||
}
|
||||
|
||||
func (t *Transforms) C14N() string {
|
||||
return mkns("ds", t, &t.XMLName)
|
||||
}
|
||||
|
||||
type Transform struct {
|
||||
XMLName xml.Name
|
||||
Algorithm string `xml:",attr"`
|
||||
InclusiveNamespaces *InclusiveNamespaces `xml:",omitempty"`
|
||||
}
|
||||
|
||||
type InclusiveNamespaces struct {
|
||||
XMLName xml.Name
|
||||
NS string `xml:"xmlns:ec,attr,omitempty"`
|
||||
PrefixList string `xml:",attr"`
|
||||
}
|
||||
|
||||
type X509Data struct {
|
||||
XMLName xml.Name
|
||||
X509Certificate string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
type KeyInfo struct {
|
||||
XMLName xml.Name
|
||||
NS string `xml:"xmlns:ds,attr,omitempty"`
|
||||
SecurityTokenReference *SecurityTokenReference `xml:",omitempty"`
|
||||
X509Data *X509Data `xml:",omitempty"`
|
||||
}
|
||||
|
||||
func (o *KeyInfo) C14N() string {
|
||||
names := []*xml.Name{
|
||||
&o.XMLName,
|
||||
}
|
||||
|
||||
if o.SecurityTokenReference != nil {
|
||||
names = append(names, &o.SecurityTokenReference.XMLName)
|
||||
}
|
||||
if o.X509Data != nil {
|
||||
names = append(names, &o.X509Data.XMLName)
|
||||
}
|
||||
|
||||
return mkns("ds", o, names...)
|
||||
}
|
||||
|
||||
type SecurityTokenReference struct {
|
||||
XMLName xml.Name `xml:"wsse:SecurityTokenReference"`
|
||||
WSSE11 string `xml:"xmlns:wsse11,attr,omitempty"`
|
||||
TokenType string `xml:"wsse11:TokenType,attr,omitempty"`
|
||||
Reference *SecurityReference `xml:",omitempty"`
|
||||
KeyIdentifier *KeyIdentifier `xml:",omitempty"`
|
||||
}
|
||||
|
||||
type SecurityReference struct {
|
||||
XMLName xml.Name `xml:"wsse:Reference"`
|
||||
URI string `xml:",attr"`
|
||||
ValueType string `xml:",attr"`
|
||||
}
|
||||
|
||||
type KeyIdentifier struct {
|
||||
XMLName xml.Name `xml:"wsse:KeyIdentifier"`
|
||||
ID string `xml:",innerxml"`
|
||||
ValueType string `xml:",attr"`
|
||||
}
|
||||
|
||||
type Issuer struct {
|
||||
XMLName xml.Name
|
||||
Format string `xml:",attr"`
|
||||
Value string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
func (i *Issuer) C14N() string {
|
||||
return mkns("saml2", i, &i.XMLName)
|
||||
}
|
||||
|
||||
type Assertion struct {
|
||||
XMLName xml.Name
|
||||
ID string `xml:",attr"`
|
||||
IssueInstant string `xml:",attr"`
|
||||
Version string `xml:",attr"`
|
||||
Issuer Issuer
|
||||
Signature Signature
|
||||
Subject Subject
|
||||
Conditions Conditions
|
||||
AuthnStatement AuthnStatement
|
||||
AttributeStatement AttributeStatement
|
||||
}
|
||||
|
||||
func (a *Assertion) C14N() string {
|
||||
start := `<saml2:Assertion xmlns:saml2="%s" ID="%s" IssueInstant="%s" Version="%s">`
|
||||
c14n := []string{
|
||||
fmt.Sprintf(start, a.XMLName.Space, a.ID, a.IssueInstant, a.Version),
|
||||
a.Issuer.C14N(),
|
||||
a.Signature.C14N(),
|
||||
a.Subject.C14N(),
|
||||
a.Conditions.C14N(),
|
||||
a.AuthnStatement.C14N(),
|
||||
a.AttributeStatement.C14N(),
|
||||
`</saml2:Assertion>`,
|
||||
}
|
||||
|
||||
return strings.Join(c14n, "")
|
||||
}
|
||||
|
||||
type NameID struct {
|
||||
XMLName xml.Name
|
||||
Format string `xml:",attr"`
|
||||
ID string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
type Subject struct {
|
||||
XMLName xml.Name
|
||||
NameID NameID
|
||||
SubjectConfirmation SubjectConfirmation
|
||||
}
|
||||
|
||||
func (s *Subject) C14N() string {
|
||||
data := &s.SubjectConfirmation.SubjectConfirmationData
|
||||
names := []*xml.Name{
|
||||
&s.XMLName,
|
||||
&s.NameID.XMLName,
|
||||
&s.SubjectConfirmation.XMLName,
|
||||
&data.XMLName,
|
||||
}
|
||||
if s.SubjectConfirmation.NameID != nil {
|
||||
names = append(names, &s.SubjectConfirmation.NameID.XMLName)
|
||||
}
|
||||
if data.KeyInfo != nil {
|
||||
data.NS = XSI
|
||||
data.Type = "saml2:KeyInfoConfirmationDataType"
|
||||
data.KeyInfo.XMLName = xml.Name{Local: "ds:KeyInfo"}
|
||||
data.KeyInfo.X509Data.XMLName = xml.Name{Local: "ds:X509Data"}
|
||||
data.KeyInfo.NS = DSIG
|
||||
}
|
||||
return mkns("saml2", s, names...)
|
||||
}
|
||||
|
||||
type SubjectConfirmationData struct {
|
||||
XMLName xml.Name
|
||||
NS string `xml:"xmlns:xsi,attr,omitempty"`
|
||||
Type string `xml:"xsi:type,attr,omitempty"`
|
||||
NotOnOrAfter string `xml:",attr,omitempty"`
|
||||
KeyInfo *KeyInfo
|
||||
}
|
||||
|
||||
type SubjectConfirmation struct {
|
||||
XMLName xml.Name
|
||||
Method string `xml:",attr"`
|
||||
NameID *NameID
|
||||
SubjectConfirmationData SubjectConfirmationData
|
||||
}
|
||||
|
||||
type Condition struct {
|
||||
Type string `xml:"xsi:type,attr,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Condition) GetCondition() *Condition {
|
||||
return c
|
||||
}
|
||||
|
||||
type BaseCondition interface {
|
||||
GetCondition() *Condition
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("BaseCondition", reflect.TypeOf((*Condition)(nil)).Elem())
|
||||
types.Add("del:DelegationRestrictionType", reflect.TypeOf((*DelegateRestriction)(nil)).Elem())
|
||||
types.Add("rsa:RenewRestrictionType", reflect.TypeOf((*RenewRestriction)(nil)).Elem())
|
||||
}
|
||||
|
||||
type Conditions struct {
|
||||
XMLName xml.Name
|
||||
NotBefore string `xml:",attr"`
|
||||
NotOnOrAfter string `xml:",attr"`
|
||||
ProxyRestriction *ProxyRestriction `xml:",omitempty"`
|
||||
Condition []BaseCondition `xml:",omitempty"`
|
||||
}
|
||||
|
||||
func (c *Conditions) C14N() string {
|
||||
names := []*xml.Name{
|
||||
&c.XMLName,
|
||||
}
|
||||
|
||||
if c.ProxyRestriction != nil {
|
||||
names = append(names, &c.ProxyRestriction.XMLName)
|
||||
}
|
||||
|
||||
for i := range c.Condition {
|
||||
switch r := c.Condition[i].(type) {
|
||||
case *DelegateRestriction:
|
||||
names = append(names, &r.XMLName, &r.Delegate.NameID.XMLName)
|
||||
r.NS = XSI
|
||||
r.Type = "del:DelegationRestrictionType"
|
||||
r.Delegate.NS = r.Delegate.XMLName.Space
|
||||
r.Delegate.XMLName = xml.Name{Local: "del:Delegate"}
|
||||
case *RenewRestriction:
|
||||
names = append(names, &r.XMLName)
|
||||
r.NS = XSI
|
||||
r.Type = "rsa:RenewRestrictionType"
|
||||
}
|
||||
}
|
||||
|
||||
return mkns("saml2", c, names...)
|
||||
}
|
||||
|
||||
type ProxyRestriction struct {
|
||||
XMLName xml.Name
|
||||
Count int32 `xml:",attr"`
|
||||
}
|
||||
|
||||
type RenewRestriction struct {
|
||||
XMLName xml.Name
|
||||
NS string `xml:"xmlns:xsi,attr,omitempty"`
|
||||
Count int32 `xml:",attr"`
|
||||
Condition
|
||||
}
|
||||
|
||||
type Delegate struct {
|
||||
XMLName xml.Name
|
||||
NS string `xml:"xmlns:del,attr,omitempty"`
|
||||
DelegationInstant string `xml:",attr"`
|
||||
NameID NameID
|
||||
}
|
||||
|
||||
type DelegateRestriction struct {
|
||||
XMLName xml.Name
|
||||
NS string `xml:"xmlns:xsi,attr,omitempty"`
|
||||
Condition
|
||||
Delegate Delegate
|
||||
}
|
||||
|
||||
type AuthnStatement struct {
|
||||
XMLName xml.Name
|
||||
AuthnInstant string `xml:",attr"`
|
||||
AuthnContext struct {
|
||||
XMLName xml.Name
|
||||
AuthnContextClassRef struct {
|
||||
XMLName xml.Name
|
||||
Value string `xml:",innerxml"`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AuthnStatement) C14N() string {
|
||||
return mkns("saml2", a, &a.XMLName, &a.AuthnContext.XMLName, &a.AuthnContext.AuthnContextClassRef.XMLName)
|
||||
}
|
||||
|
||||
type AttributeStatement struct {
|
||||
XMLName xml.Name
|
||||
Attribute []Attribute
|
||||
}
|
||||
|
||||
func (a *AttributeStatement) C14N() string {
|
||||
c14n := []string{"<saml2:AttributeStatement>"}
|
||||
for i := range a.Attribute {
|
||||
c14n = append(c14n, a.Attribute[i].C14N())
|
||||
}
|
||||
c14n = append(c14n, "</saml2:AttributeStatement>")
|
||||
return strings.Join(c14n, "")
|
||||
}
|
||||
|
||||
type AttributeValue struct {
|
||||
XMLName xml.Name
|
||||
Type string `xml:"type,attr"`
|
||||
Value string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
func (a *AttributeValue) C14N() string {
|
||||
return fmt.Sprintf(`<saml2:AttributeValue xmlns:xsi="%s" xsi:type="%s">%s</saml2:AttributeValue>`, XSI, a.Type, a.Value)
|
||||
}
|
||||
|
||||
type Attribute struct {
|
||||
XMLName xml.Name
|
||||
FriendlyName string `xml:",attr"`
|
||||
Name string `xml:",attr"`
|
||||
NameFormat string `xml:",attr"`
|
||||
AttributeValue []AttributeValue
|
||||
}
|
||||
|
||||
func (a *Attribute) C14N() string {
|
||||
c14n := []string{
|
||||
fmt.Sprintf(`<saml2:Attribute FriendlyName="%s" Name="%s" NameFormat="%s">`, a.FriendlyName, a.Name, a.NameFormat),
|
||||
}
|
||||
|
||||
for i := range a.AttributeValue {
|
||||
c14n = append(c14n, a.AttributeValue[i].C14N())
|
||||
}
|
||||
|
||||
c14n = append(c14n, `</saml2:Attribute>`)
|
||||
|
||||
return strings.Join(c14n, "")
|
||||
}
|
||||
|
||||
type Lifetime struct {
|
||||
Created string `xml:"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd Created"`
|
||||
Expires string `xml:"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd Expires"`
|
||||
}
|
||||
|
||||
func (t *Lifetime) C14N() string {
|
||||
return fmt.Sprintf(`<Lifetime><wsu:Created>%s</wsu:Created><wsu:Expires>%s</wsu:Expires></Lifetime>`, t.Created, t.Expires)
|
||||
}
|
||||
|
||||
type Renewing struct {
|
||||
Allow bool `xml:",attr"`
|
||||
OK bool `xml:",attr"`
|
||||
}
|
||||
|
||||
type UseKey struct {
|
||||
Sig string `xml:",attr"`
|
||||
}
|
||||
|
||||
type Target struct {
|
||||
Token string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
type RequestSecurityToken struct {
|
||||
TokenType string `xml:",omitempty"`
|
||||
RequestType string `xml:",omitempty"`
|
||||
Lifetime *Lifetime `xml:",omitempty"`
|
||||
Renewing *Renewing `xml:",omitempty"`
|
||||
Delegatable bool `xml:",omitempty"`
|
||||
KeyType string `xml:",omitempty"`
|
||||
SignatureAlgorithm string `xml:",omitempty"`
|
||||
UseKey *UseKey `xml:",omitempty"`
|
||||
ActAs *Target `xml:",omitempty"`
|
||||
ValidateTarget *Target `xml:",omitempty"`
|
||||
RenewTarget *Target `xml:",omitempty"`
|
||||
}
|
||||
|
||||
func Unmarshal(data []byte, v interface{}) error {
|
||||
dec := xml.NewDecoder(bytes.NewReader(data))
|
||||
dec.TypeFunc = types.TypeFunc()
|
||||
return dec.Decode(v)
|
||||
}
|
||||
|
||||
// toString returns an XML encoded RequestSecurityToken.
|
||||
// When c14n is true, returns the canonicalized ActAs.Assertion which is required to sign the Issue request.
|
||||
// When c14n is false, returns the original content of the ActAs.Assertion.
|
||||
// The original content must be used within the request Body, as it has its own signature.
|
||||
func (r *RequestSecurityToken) toString(c14n bool) string {
|
||||
actas := ""
|
||||
if r.ActAs != nil {
|
||||
token := r.ActAs.Token
|
||||
if c14n {
|
||||
var a Assertion
|
||||
err := Unmarshal([]byte(r.ActAs.Token), &a)
|
||||
if err != nil {
|
||||
log.Printf("decode ActAs: %s", err)
|
||||
}
|
||||
token = a.C14N()
|
||||
}
|
||||
|
||||
actas = fmt.Sprintf(`<wst:ActAs xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200802">%s</wst:ActAs>`, token)
|
||||
}
|
||||
|
||||
body := []string{
|
||||
fmt.Sprintf(`<RequestSecurityToken xmlns="http://docs.oasis-open.org/ws-sx/ws-trust/200512">`),
|
||||
fmt.Sprintf(`<TokenType>%s</TokenType>`, r.TokenType),
|
||||
fmt.Sprintf(`<RequestType>%s</RequestType>`, r.RequestType),
|
||||
r.Lifetime.C14N(),
|
||||
}
|
||||
|
||||
if r.RenewTarget == nil {
|
||||
body = append(body,
|
||||
fmt.Sprintf(`<Renewing Allow="%t" OK="%t"></Renewing>`, r.Renewing.Allow, r.Renewing.OK),
|
||||
fmt.Sprintf(`<Delegatable>%t</Delegatable>`, r.Delegatable),
|
||||
actas,
|
||||
fmt.Sprintf(`<KeyType>%s</KeyType>`, r.KeyType),
|
||||
fmt.Sprintf(`<SignatureAlgorithm>%s</SignatureAlgorithm>`, r.SignatureAlgorithm),
|
||||
fmt.Sprintf(`<UseKey Sig="%s"></UseKey>`, r.UseKey.Sig))
|
||||
} else {
|
||||
token := r.RenewTarget.Token
|
||||
if c14n {
|
||||
var a Assertion
|
||||
err := Unmarshal([]byte(r.RenewTarget.Token), &a)
|
||||
if err != nil {
|
||||
log.Printf("decode Renew: %s", err)
|
||||
}
|
||||
token = a.C14N()
|
||||
}
|
||||
|
||||
body = append(body,
|
||||
fmt.Sprintf(`<UseKey Sig="%s"></UseKey>`, r.UseKey.Sig),
|
||||
fmt.Sprintf(`<RenewTarget>%s</RenewTarget>`, token))
|
||||
}
|
||||
|
||||
return strings.Join(append(body, `</RequestSecurityToken>`), "")
|
||||
}
|
||||
|
||||
func (r *RequestSecurityToken) C14N() string {
|
||||
return r.toString(true)
|
||||
}
|
||||
|
||||
func (r *RequestSecurityToken) String() string {
|
||||
return r.toString(false)
|
||||
}
|
||||
|
||||
type RequestSecurityTokenResponseCollection struct {
|
||||
RequestSecurityTokenResponse RequestSecurityTokenResponse
|
||||
}
|
||||
|
||||
type RequestSecurityTokenResponse struct {
|
||||
RequestedSecurityToken RequestedSecurityToken
|
||||
Lifetime *Lifetime `xml:"http://docs.oasis-open.org/ws-sx/ws-trust/200512 Lifetime"`
|
||||
}
|
||||
|
||||
type RequestedSecurityToken struct {
|
||||
Assertion string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
type RequestSecurityTokenBody struct {
|
||||
Req *RequestSecurityToken `xml:"http://docs.oasis-open.org/ws-sx/ws-trust/200512 RequestSecurityToken,omitempty"`
|
||||
Res *RequestSecurityTokenResponseCollection `xml:"http://docs.oasis-open.org/ws-sx/ws-trust/200512 RequestSecurityTokenResponseCollection,omitempty"`
|
||||
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
|
||||
}
|
||||
|
||||
func (b *RequestSecurityTokenBody) Fault() *soap.Fault { return b.Fault_ }
|
||||
|
||||
func (b *RequestSecurityTokenBody) RequestSecurityToken() *RequestSecurityToken { return b.Req }
|
||||
|
||||
func (r *RequestSecurityToken) Action() string {
|
||||
kind := path.Base(r.RequestType)
|
||||
return "http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/" + kind
|
||||
}
|
||||
|
||||
func Issue(ctx context.Context, r soap.RoundTripper, req *RequestSecurityToken) (*RequestSecurityTokenResponseCollection, error) {
|
||||
var reqBody, resBody RequestSecurityTokenBody
|
||||
|
||||
reqBody.Req = req
|
||||
|
||||
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resBody.Res, nil
|
||||
}
|
||||
|
||||
type RenewSecurityTokenBody struct {
|
||||
Req *RequestSecurityToken `xml:"http://docs.oasis-open.org/ws-sx/ws-trust/200512 RequestSecurityToken,omitempty"`
|
||||
Res *RequestSecurityTokenResponse `xml:"http://docs.oasis-open.org/ws-sx/ws-trust/200512 RequestSecurityTokenResponse,omitempty"`
|
||||
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
|
||||
}
|
||||
|
||||
func (b *RenewSecurityTokenBody) Fault() *soap.Fault { return b.Fault_ }
|
||||
|
||||
func (b *RenewSecurityTokenBody) RequestSecurityToken() *RequestSecurityToken { return b.Req }
|
||||
|
||||
func Renew(ctx context.Context, r soap.RoundTripper, req *RequestSecurityToken) (*RequestSecurityTokenResponse, error) {
|
||||
var reqBody, resBody RenewSecurityTokenBody
|
||||
|
||||
reqBody.Req = req
|
||||
|
||||
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resBody.Res, nil
|
||||
}
|
||||
|
||||
// Marshal panics if xml.Marshal returns an error
|
||||
func Marshal(val interface{}) string {
|
||||
b, err := xml.Marshal(val)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// mkns prepends the given namespace to xml.Name.Local and returns obj encoded as xml.
|
||||
// Note that the namespace is required when encoding, but the namespace prefix must not be
|
||||
// present when decoding as Go's decoding does not handle namespace prefix.
|
||||
func mkns(ns string, obj interface{}, name ...*xml.Name) string {
|
||||
ns += ":"
|
||||
for i := range name {
|
||||
name[i].Space = ""
|
||||
if !strings.HasPrefix(name[i].Local, ns) {
|
||||
name[i].Local = ns + name[i].Local
|
||||
}
|
||||
}
|
||||
|
||||
return Marshal(obj)
|
||||
}
|
||||
330
vendor/github.com/vmware/govmomi/sts/signer.go
generated
vendored
Normal file
330
vendor/github.com/vmware/govmomi/sts/signer.go
generated
vendored
Normal file
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
Copyright (c) 2018 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sts
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
mrand "math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/vmware/govmomi/sts/internal"
|
||||
"github.com/vmware/govmomi/vim25/methods"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/xml"
|
||||
)
|
||||
|
||||
// Signer implements the soap.Signer interface.
|
||||
type Signer struct {
|
||||
Token string // Token is a SAML token
|
||||
Certificate *tls.Certificate // Certificate is used to sign requests
|
||||
Lifetime struct {
|
||||
Created time.Time
|
||||
Expires time.Time
|
||||
}
|
||||
user *url.Userinfo // user contains the credentials for bearer token request
|
||||
keyID string // keyID is the Signature UseKey ID, which is referenced in both the soap body and header
|
||||
}
|
||||
|
||||
// signedEnvelope is similar to soap.Envelope, but with namespace and Body as innerxml
|
||||
type signedEnvelope struct {
|
||||
XMLName xml.Name `xml:"soap:Envelope"`
|
||||
NS string `xml:"xmlns:soap,attr"`
|
||||
Header soap.Header `xml:"soap:Header"`
|
||||
Body string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
// newID returns a unique Reference ID, with a leading underscore as required by STS.
|
||||
func newID() string {
|
||||
return "_" + uuid.New().String()
|
||||
}
|
||||
|
||||
func (s *Signer) setTokenReference(info *internal.KeyInfo) error {
|
||||
var token struct {
|
||||
ID string `xml:",attr"` // parse saml2:Assertion ID attribute
|
||||
InnerXML string `xml:",innerxml"` // no need to parse the entire token
|
||||
}
|
||||
if err := xml.Unmarshal([]byte(s.Token), &token); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
info.SecurityTokenReference = &internal.SecurityTokenReference{
|
||||
WSSE11: "http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd",
|
||||
TokenType: "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0",
|
||||
KeyIdentifier: &internal.KeyIdentifier{
|
||||
ID: token.ID,
|
||||
ValueType: "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLID",
|
||||
},
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sign is a soap.Signer implementation which can be used to sign RequestSecurityToken and LoginByTokenBody requests.
|
||||
func (s *Signer) Sign(env soap.Envelope) ([]byte, error) {
|
||||
var key *rsa.PrivateKey
|
||||
hasKey := false
|
||||
if s.Certificate != nil {
|
||||
key, hasKey = s.Certificate.PrivateKey.(*rsa.PrivateKey)
|
||||
if !hasKey {
|
||||
return nil, errors.New("sts: rsa.PrivateKey is required")
|
||||
}
|
||||
}
|
||||
|
||||
created := time.Now().UTC()
|
||||
header := &internal.Security{
|
||||
WSU: internal.WSU,
|
||||
WSSE: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
|
||||
Timestamp: internal.Timestamp{
|
||||
NS: internal.WSU,
|
||||
ID: newID(),
|
||||
Created: created.Format(internal.Time),
|
||||
Expires: created.Add(time.Minute).Format(internal.Time), // If STS receives this request after this, it is assumed to have expired.
|
||||
},
|
||||
}
|
||||
env.Header.Security = header
|
||||
|
||||
info := internal.KeyInfo{XMLName: xml.Name{Local: "ds:KeyInfo"}}
|
||||
var c14n, body string
|
||||
type requestToken interface {
|
||||
RequestSecurityToken() *internal.RequestSecurityToken
|
||||
}
|
||||
|
||||
switch x := env.Body.(type) {
|
||||
case requestToken:
|
||||
if hasKey {
|
||||
// We need c14n for all requests, as its digest is included in the signature and must match on the server side.
|
||||
// We need the body in original form when using an ActAs or RenewTarget token, where the token and its signature are embedded in the body.
|
||||
req := x.RequestSecurityToken()
|
||||
c14n = req.C14N()
|
||||
body = req.String()
|
||||
id := newID()
|
||||
|
||||
info.SecurityTokenReference = &internal.SecurityTokenReference{
|
||||
Reference: &internal.SecurityReference{
|
||||
URI: "#" + id,
|
||||
ValueType: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3",
|
||||
},
|
||||
}
|
||||
|
||||
header.BinarySecurityToken = &internal.BinarySecurityToken{
|
||||
EncodingType: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary",
|
||||
ValueType: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3",
|
||||
ID: id,
|
||||
Value: base64.StdEncoding.EncodeToString(s.Certificate.Certificate[0]),
|
||||
}
|
||||
}
|
||||
// When requesting HoK token for interactive user, request will have both priv. key and username/password.
|
||||
if s.user.Username() != "" {
|
||||
header.UsernameToken = &internal.UsernameToken{
|
||||
Username: s.user.Username(),
|
||||
}
|
||||
header.UsernameToken.Password, _ = s.user.Password()
|
||||
}
|
||||
case *methods.LoginByTokenBody:
|
||||
header.Assertion = s.Token
|
||||
|
||||
if hasKey {
|
||||
if err := s.setTokenReference(&info); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c14n = internal.Marshal(x.Req)
|
||||
}
|
||||
default:
|
||||
// We can end up here via ssoadmin.SessionManager.Login().
|
||||
// No other known cases where a signed request is needed.
|
||||
header.Assertion = s.Token
|
||||
if hasKey {
|
||||
if err := s.setTokenReference(&info); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
type Req interface {
|
||||
C14N() string
|
||||
}
|
||||
c14n = env.Body.(Req).C14N()
|
||||
}
|
||||
}
|
||||
|
||||
if !hasKey {
|
||||
return xml.Marshal(env) // Bearer token without key to sign
|
||||
}
|
||||
|
||||
id := newID()
|
||||
tmpl := `<soap:Body xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsu="%s" wsu:Id="%s">%s</soap:Body>`
|
||||
c14n = fmt.Sprintf(tmpl, internal.WSU, id, c14n)
|
||||
if body == "" {
|
||||
body = c14n
|
||||
} else {
|
||||
body = fmt.Sprintf(tmpl, internal.WSU, id, body)
|
||||
}
|
||||
|
||||
header.Signature = &internal.Signature{
|
||||
XMLName: xml.Name{Local: "ds:Signature"},
|
||||
NS: internal.DSIG,
|
||||
ID: s.keyID,
|
||||
KeyInfo: info,
|
||||
SignedInfo: internal.SignedInfo{
|
||||
XMLName: xml.Name{Local: "ds:SignedInfo"},
|
||||
NS: internal.DSIG,
|
||||
CanonicalizationMethod: internal.Method{
|
||||
XMLName: xml.Name{Local: "ds:CanonicalizationMethod"},
|
||||
Algorithm: "http://www.w3.org/2001/10/xml-exc-c14n#",
|
||||
},
|
||||
SignatureMethod: internal.Method{
|
||||
XMLName: xml.Name{Local: "ds:SignatureMethod"},
|
||||
Algorithm: internal.SHA256,
|
||||
},
|
||||
Reference: []internal.Reference{
|
||||
internal.NewReference(header.Timestamp.ID, header.Timestamp.C14N()),
|
||||
internal.NewReference(id, c14n),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
sum := sha256.Sum256([]byte(header.Signature.SignedInfo.C14N()))
|
||||
sig, err := rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, sum[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
header.Signature.SignatureValue = internal.Value{
|
||||
XMLName: xml.Name{Local: "ds:SignatureValue"},
|
||||
Value: base64.StdEncoding.EncodeToString(sig),
|
||||
}
|
||||
|
||||
return xml.Marshal(signedEnvelope{
|
||||
NS: "http://schemas.xmlsoap.org/soap/envelope/",
|
||||
Header: *env.Header,
|
||||
Body: body,
|
||||
})
|
||||
}
|
||||
|
||||
// SignRequest is a rest.Signer implementation which can be used to sign rest.Client.LoginByTokenBody requests.
|
||||
func (s *Signer) SignRequest(req *http.Request) error {
|
||||
type param struct {
|
||||
key, val string
|
||||
}
|
||||
var params []string
|
||||
add := func(p param) {
|
||||
params = append(params, fmt.Sprintf(`%s="%s"`, p.key, p.val))
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
gz := gzip.NewWriter(&buf)
|
||||
if _, err := io.WriteString(gz, s.Token); err != nil {
|
||||
return fmt.Errorf("zip token: %s", err)
|
||||
}
|
||||
if err := gz.Close(); err != nil {
|
||||
return fmt.Errorf("zip token: %s", err)
|
||||
}
|
||||
add(param{
|
||||
key: "token",
|
||||
val: base64.StdEncoding.EncodeToString(buf.Bytes()),
|
||||
})
|
||||
|
||||
if s.Certificate != nil {
|
||||
nonce := fmt.Sprintf("%d:%d", time.Now().UnixNano()/1e6, mrand.Int())
|
||||
var body []byte
|
||||
if req.GetBody != nil {
|
||||
r, rerr := req.GetBody()
|
||||
if rerr != nil {
|
||||
return fmt.Errorf("sts: getting http.Request body: %s", rerr)
|
||||
}
|
||||
defer r.Close()
|
||||
body, rerr = ioutil.ReadAll(r)
|
||||
if rerr != nil {
|
||||
return fmt.Errorf("sts: reading http.Request body: %s", rerr)
|
||||
}
|
||||
}
|
||||
bhash := sha256.New().Sum(body)
|
||||
|
||||
port := req.URL.Port()
|
||||
if port == "" {
|
||||
port = "80" // Default port for the "Host" header on the server side
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
msg := []string{
|
||||
nonce,
|
||||
req.Method,
|
||||
req.URL.Path,
|
||||
strings.ToLower(req.URL.Hostname()),
|
||||
port,
|
||||
}
|
||||
for i := range msg {
|
||||
buf.WriteString(msg[i])
|
||||
buf.WriteByte('\n')
|
||||
}
|
||||
buf.Write(bhash)
|
||||
buf.WriteByte('\n')
|
||||
|
||||
sum := sha256.Sum256(buf.Bytes())
|
||||
key, ok := s.Certificate.PrivateKey.(*rsa.PrivateKey)
|
||||
if !ok {
|
||||
return errors.New("sts: rsa.PrivateKey is required to sign http.Request")
|
||||
}
|
||||
sig, err := rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, sum[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
add(param{
|
||||
key: "signature_alg",
|
||||
val: "RSA-SHA256",
|
||||
})
|
||||
add(param{
|
||||
key: "signature",
|
||||
val: base64.StdEncoding.EncodeToString(sig),
|
||||
})
|
||||
add(param{
|
||||
key: "nonce",
|
||||
val: nonce,
|
||||
})
|
||||
add(param{
|
||||
key: "bodyhash",
|
||||
val: base64.StdEncoding.EncodeToString(bhash),
|
||||
})
|
||||
}
|
||||
|
||||
req.Header.Set("Authorization", fmt.Sprintf("SIGN %s", strings.Join(params, ", ")))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Signer) NewRequest() TokenRequest {
|
||||
return TokenRequest{
|
||||
Token: s.Token,
|
||||
Certificate: s.Certificate,
|
||||
Userinfo: s.user,
|
||||
KeyID: s.keyID,
|
||||
}
|
||||
}
|
||||
342
vendor/github.com/vmware/govmomi/vmdk/import.go
generated
vendored
Normal file
342
vendor/github.com/vmware/govmomi/vmdk/import.go
generated
vendored
Normal file
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
nSee the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package vmdk
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/ovf"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/progress"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidFormat = errors.New("vmdk: invalid format (must be streamOptimized)")
|
||||
)
|
||||
|
||||
// info is used to inspect a vmdk and generate an ovf template
|
||||
type info struct {
|
||||
Header struct {
|
||||
MagicNumber uint32
|
||||
Version uint32
|
||||
Flags uint32
|
||||
Capacity uint64
|
||||
}
|
||||
|
||||
Capacity uint64
|
||||
Size int64
|
||||
Name string
|
||||
ImportName string
|
||||
}
|
||||
|
||||
// stat looks at the vmdk header to make sure the format is streamOptimized and
|
||||
// extracts the disk capacity required to properly generate the ovf descriptor.
|
||||
func stat(name string) (*info, error) {
|
||||
f, err := os.Open(filepath.Clean(name))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var di info
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
||||
_, err = io.CopyN(&buf, f, int64(binary.Size(di.Header)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fi, err := f.Stat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = f.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = binary.Read(&buf, binary.LittleEndian, &di.Header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if di.Header.MagicNumber != 0x564d444b { // SPARSE_MAGICNUMBER
|
||||
return nil, ErrInvalidFormat
|
||||
}
|
||||
|
||||
if di.Header.Flags&(1<<16) == 0 { // SPARSEFLAG_COMPRESSED
|
||||
// Needs to be converted, for example:
|
||||
// vmware-vdiskmanager -r src.vmdk -t 5 dst.vmdk
|
||||
// qemu-img convert -O vmdk -o subformat=streamOptimized src.vmdk dst.vmdk
|
||||
return nil, ErrInvalidFormat
|
||||
}
|
||||
|
||||
di.Capacity = di.Header.Capacity * 512 // VMDK_SECTOR_SIZE
|
||||
di.Size = fi.Size()
|
||||
di.Name = filepath.Base(name)
|
||||
di.ImportName = strings.TrimSuffix(di.Name, ".vmdk")
|
||||
|
||||
return &di, nil
|
||||
}
|
||||
|
||||
// ovfenv is the minimal descriptor template required to import a vmdk
|
||||
var ovfenv = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Envelope xmlns="http://schemas.dmtf.org/ovf/envelope/1"
|
||||
xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"
|
||||
xmlns:cim="http://schemas.dmtf.org/wbem/wscim/1/common"
|
||||
xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData"
|
||||
xmlns:vmw="http://www.vmware.com/schema/ovf"
|
||||
xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<References>
|
||||
<File ovf:href="{{ .Name }}" ovf:id="file1" ovf:size="{{ .Size }}"/>
|
||||
</References>
|
||||
<DiskSection>
|
||||
<Info>Virtual disk information</Info>
|
||||
<Disk ovf:capacity="{{ .Capacity }}" ovf:capacityAllocationUnits="byte" ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format="http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" ovf:populatedSize="0"/>
|
||||
</DiskSection>
|
||||
<VirtualSystem ovf:id="{{ .ImportName }}">
|
||||
<Info>A virtual machine</Info>
|
||||
<Name>{{ .ImportName }}</Name>
|
||||
<OperatingSystemSection ovf:id="100" vmw:osType="other26xLinux64Guest">
|
||||
<Info>The kind of installed guest operating system</Info>
|
||||
</OperatingSystemSection>
|
||||
<VirtualHardwareSection>
|
||||
<Info>Virtual hardware requirements</Info>
|
||||
<System>
|
||||
<vssd:ElementName>Virtual Hardware Family</vssd:ElementName>
|
||||
<vssd:InstanceID>0</vssd:InstanceID>
|
||||
<vssd:VirtualSystemIdentifier>{{ .ImportName }}</vssd:VirtualSystemIdentifier>
|
||||
<vssd:VirtualSystemType>vmx-07</vssd:VirtualSystemType>
|
||||
</System>
|
||||
<Item>
|
||||
<rasd:AllocationUnits>hertz * 10^6</rasd:AllocationUnits>
|
||||
<rasd:Description>Number of Virtual CPUs</rasd:Description>
|
||||
<rasd:ElementName>1 virtual CPU(s)</rasd:ElementName>
|
||||
<rasd:InstanceID>1</rasd:InstanceID>
|
||||
<rasd:ResourceType>3</rasd:ResourceType>
|
||||
<rasd:VirtualQuantity>1</rasd:VirtualQuantity>
|
||||
</Item>
|
||||
<Item>
|
||||
<rasd:AllocationUnits>byte * 2^20</rasd:AllocationUnits>
|
||||
<rasd:Description>Memory Size</rasd:Description>
|
||||
<rasd:ElementName>1024MB of memory</rasd:ElementName>
|
||||
<rasd:InstanceID>2</rasd:InstanceID>
|
||||
<rasd:ResourceType>4</rasd:ResourceType>
|
||||
<rasd:VirtualQuantity>1024</rasd:VirtualQuantity>
|
||||
</Item>
|
||||
<Item>
|
||||
<rasd:Address>0</rasd:Address>
|
||||
<rasd:Description>SCSI Controller</rasd:Description>
|
||||
<rasd:ElementName>SCSI Controller 0</rasd:ElementName>
|
||||
<rasd:InstanceID>3</rasd:InstanceID>
|
||||
<rasd:ResourceSubType>VirtualSCSI</rasd:ResourceSubType>
|
||||
<rasd:ResourceType>6</rasd:ResourceType>
|
||||
</Item>
|
||||
<Item>
|
||||
<rasd:AddressOnParent>0</rasd:AddressOnParent>
|
||||
<rasd:ElementName>Hard Disk 1</rasd:ElementName>
|
||||
<rasd:HostResource>ovf:/disk/vmdisk1</rasd:HostResource>
|
||||
<rasd:InstanceID>9</rasd:InstanceID>
|
||||
<rasd:Parent>3</rasd:Parent>
|
||||
<rasd:ResourceType>17</rasd:ResourceType>
|
||||
<vmw:Config ovf:required="false" vmw:key="backing.writeThrough" vmw:value="false"/>
|
||||
</Item>
|
||||
</VirtualHardwareSection>
|
||||
</VirtualSystem>
|
||||
</Envelope>`
|
||||
|
||||
// ovf returns an expanded descriptor template
|
||||
func (di *info) ovf() (string, error) {
|
||||
var buf bytes.Buffer
|
||||
|
||||
tmpl, err := template.New("ovf").Parse(ovfenv)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
err = tmpl.Execute(&buf, di)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// ImportParams contains the set of optional params to the Import function.
|
||||
// Note that "optional" may depend on environment, such as ESX or vCenter.
|
||||
type ImportParams struct {
|
||||
Path string
|
||||
Logger progress.Sinker
|
||||
Type types.VirtualDiskType
|
||||
Force bool
|
||||
Datacenter *object.Datacenter
|
||||
Pool *object.ResourcePool
|
||||
Folder *object.Folder
|
||||
Host *object.HostSystem
|
||||
}
|
||||
|
||||
// Import uploads a local vmdk file specified by name to the given datastore.
|
||||
func Import(ctx context.Context, c *vim25.Client, name string, datastore *object.Datastore, p ImportParams) error {
|
||||
m := ovf.NewManager(c)
|
||||
fm := datastore.NewFileManager(p.Datacenter, p.Force)
|
||||
|
||||
disk, err := stat(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var rename string
|
||||
|
||||
p.Path = strings.TrimSuffix(p.Path, "/")
|
||||
if p.Path != "" {
|
||||
disk.ImportName = p.Path
|
||||
rename = path.Join(disk.ImportName, disk.Name)
|
||||
}
|
||||
|
||||
// "target" is the path that will be created by ImportVApp()
|
||||
// ImportVApp uses the same name for the VM and the disk.
|
||||
target := fmt.Sprintf("%s/%s.vmdk", disk.ImportName, disk.ImportName)
|
||||
|
||||
if _, err = datastore.Stat(ctx, target); err == nil {
|
||||
if p.Force {
|
||||
// If we don't delete, the nfc upload adds a file name suffix
|
||||
if err = fm.Delete(ctx, target); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("%s: %s", os.ErrExist, datastore.Path(target))
|
||||
}
|
||||
}
|
||||
|
||||
// If we need to rename at the end, check if the file exists early unless Force.
|
||||
if !p.Force && rename != "" {
|
||||
if _, err = datastore.Stat(ctx, rename); err == nil {
|
||||
return fmt.Errorf("%s: %s", os.ErrExist, datastore.Path(rename))
|
||||
}
|
||||
}
|
||||
|
||||
// Expand the ovf template
|
||||
descriptor, err := disk.ovf()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pool := p.Pool // TODO: use datastore to derive a default
|
||||
folder := p.Folder // TODO: use datacenter to derive a default
|
||||
|
||||
kind := p.Type
|
||||
if kind == "" {
|
||||
kind = types.VirtualDiskTypeThin
|
||||
}
|
||||
|
||||
params := types.OvfCreateImportSpecParams{
|
||||
DiskProvisioning: string(kind),
|
||||
EntityName: disk.ImportName,
|
||||
}
|
||||
|
||||
spec, err := m.CreateImportSpec(ctx, descriptor, pool, datastore, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if spec.Error != nil {
|
||||
return errors.New(spec.Error[0].LocalizedMessage)
|
||||
}
|
||||
|
||||
lease, err := pool.ImportVApp(ctx, spec.ImportSpec, folder, p.Host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
info, err := lease.Wait(ctx, spec.FileItem)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f, err := os.Open(filepath.Clean(name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
opts := soap.Upload{
|
||||
ContentLength: disk.Size,
|
||||
Progress: p.Logger,
|
||||
}
|
||||
|
||||
u := lease.StartUpdater(ctx, info)
|
||||
defer u.Done()
|
||||
|
||||
item := info.Items[0] // we only have 1 disk to upload
|
||||
|
||||
err = lease.Upload(ctx, item, f, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = f.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = lease.Complete(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// ImportVApp created a VM, here we detach the vmdk, then delete the VM.
|
||||
vm := object.NewVirtualMachine(c, info.Entity)
|
||||
|
||||
device, err := vm.Device(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
device = device.SelectByType((*types.VirtualDisk)(nil))
|
||||
|
||||
err = vm.RemoveDevice(ctx, true, device...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
task, err := vm.Destroy(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = task.Wait(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if rename == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fm.Move(ctx, target, rename)
|
||||
}
|
||||
18
vendor/modules.txt
vendored
18
vendor/modules.txt
vendored
@@ -919,6 +919,10 @@ github.com/keybase/go-crypto/rsa
|
||||
github.com/konsorten/go-windows-terminal-sequences
|
||||
# github.com/kr/fs v0.1.0
|
||||
github.com/kr/fs
|
||||
# github.com/kr/pretty v0.1.0
|
||||
github.com/kr/pretty
|
||||
# github.com/kr/text v0.1.0
|
||||
github.com/kr/text
|
||||
# github.com/lib/pq v1.2.0
|
||||
github.com/lib/pq
|
||||
github.com/lib/pq/oid
|
||||
@@ -1284,19 +1288,28 @@ github.com/vincent-petithory/dataurl
|
||||
# github.com/vmihailenco/msgpack v4.0.4+incompatible
|
||||
github.com/vmihailenco/msgpack
|
||||
github.com/vmihailenco/msgpack/codes
|
||||
# github.com/vmware/govmomi v0.22.1
|
||||
# github.com/vmware/govmomi v0.22.2
|
||||
github.com/vmware/govmomi
|
||||
github.com/vmware/govmomi/event
|
||||
github.com/vmware/govmomi/find
|
||||
github.com/vmware/govmomi/govc/cli
|
||||
github.com/vmware/govmomi/govc/flags
|
||||
github.com/vmware/govmomi/govc/importx
|
||||
github.com/vmware/govmomi/license
|
||||
github.com/vmware/govmomi/list
|
||||
github.com/vmware/govmomi/lookup
|
||||
github.com/vmware/govmomi/lookup/methods
|
||||
github.com/vmware/govmomi/lookup/types
|
||||
github.com/vmware/govmomi/nfc
|
||||
github.com/vmware/govmomi/object
|
||||
github.com/vmware/govmomi/ovf
|
||||
github.com/vmware/govmomi/pbm
|
||||
github.com/vmware/govmomi/pbm/methods
|
||||
github.com/vmware/govmomi/pbm/types
|
||||
github.com/vmware/govmomi/property
|
||||
github.com/vmware/govmomi/session
|
||||
github.com/vmware/govmomi/sts
|
||||
github.com/vmware/govmomi/sts/internal
|
||||
github.com/vmware/govmomi/task
|
||||
github.com/vmware/govmomi/vapi/internal
|
||||
github.com/vmware/govmomi/vapi/rest
|
||||
@@ -1310,6 +1323,7 @@ github.com/vmware/govmomi/vim25/progress
|
||||
github.com/vmware/govmomi/vim25/soap
|
||||
github.com/vmware/govmomi/vim25/types
|
||||
github.com/vmware/govmomi/vim25/xml
|
||||
github.com/vmware/govmomi/vmdk
|
||||
# github.com/xanzy/ssh-agent v0.2.1
|
||||
github.com/xanzy/ssh-agent
|
||||
# github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca
|
||||
@@ -1653,7 +1667,7 @@ k8s.io/api/settings/v1alpha1
|
||||
k8s.io/api/storage/v1
|
||||
k8s.io/api/storage/v1alpha1
|
||||
k8s.io/api/storage/v1beta1
|
||||
# k8s.io/apimachinery v0.17.2 => k8s.io/apimachinery v0.17.1
|
||||
# k8s.io/apimachinery v0.17.3 => k8s.io/apimachinery v0.17.1
|
||||
k8s.io/apimachinery/pkg/api/equality
|
||||
k8s.io/apimachinery/pkg/api/errors
|
||||
k8s.io/apimachinery/pkg/api/meta
|
||||
|
||||
Reference in New Issue
Block a user