diff --git a/.travis.yml b/.travis.yml
index 3e1b44ec..ad255a43 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,28 +1,27 @@
language: go
go:
- - 1.6
- - 1.7
+ - 1.9
- tip
os:
- linux
- osx
-env:
- matrix:
- - BUILD_GOARCH=amd64
- - BUILD_GOARCH=386
+matrix:
+ allow_failures:
+ - go: tip
+ fast_finish: true # don't wait for tip tests to finish before marking build "succeeded"
-before_install:
- - go get -u honnef.co/go/simple/cmd/gosimple
-
-# don't go get deps. will only build with code in vendor directory.
+# skip the install step. don't `go get` deps. only build with code in vendor/
install: true
+before_script:
+ - go get honnef.co/go/tools/cmd/megacheck
+ - GO_FILES=$(find . -iname '*.go' -type f | grep -v /vendor/)
+
script:
- # pkgs avoids testing anything in vendor/
- - pkgs=$(go list ./... | grep -v /vendor/)
- - go vet $pkgs
- - go test -v -race $pkgs
- - gosimple $pkgs
+ - test -z $(gofmt -s -l $GO_FILES)
+ - go vet ./...
+ - megacheck ./...
+ - go test -v -race $PKGS
diff --git a/Gopkg.lock b/Gopkg.lock
new file mode 100644
index 00000000..9971cf87
--- /dev/null
+++ b/Gopkg.lock
@@ -0,0 +1,117 @@
+# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
+
+
+[[projects]]
+ name = "cloud.google.com/go"
+ packages = ["compute/metadata"]
+ revision = "5a9e19d4e1e41a734154e44a2132b358afb49a03"
+ version = "v0.13.0"
+
+[[projects]]
+ name = "github.com/Azure/azure-sdk-for-go"
+ packages = ["arm/compute","arm/network","arm/resources/resources","arm/storage","management","management/hostedservice","management/location","management/virtualmachine","management/virtualmachinedisk","management/virtualnetwork","management/vmutils","storage"]
+ revision = "df4dd90d076ebbf6e87d08d3f00bfac8ff4bde1a"
+ version = "v10.3.1-beta"
+
+[[projects]]
+ name = "github.com/Azure/go-autorest"
+ packages = ["autorest","autorest/adal","autorest/azure","autorest/date","autorest/to","autorest/validation"]
+ revision = "5432abe734f8d95c78340cd56712f912906e6514"
+ version = "v8.3.1"
+
+[[projects]]
+ branch = "master"
+ name = "github.com/apcera/util"
+ packages = ["uuid"]
+ revision = "346d8c10c6f817df60ff768b05ced4170d747180"
+
+[[projects]]
+ name = "github.com/aws/aws-sdk-go"
+ packages = ["aws","aws/awserr","aws/awsutil","aws/client","aws/client/metadata","aws/corehandlers","aws/credentials","aws/credentials/ec2rolecreds","aws/credentials/endpointcreds","aws/credentials/stscreds","aws/defaults","aws/ec2metadata","aws/endpoints","aws/request","aws/session","aws/signer/v4","internal/shareddefaults","private/protocol","private/protocol/ec2query","private/protocol/query","private/protocol/query/queryutil","private/protocol/rest","private/protocol/xml/xmlutil","service/ec2","service/sts"]
+ revision = "54cc1aa0ef5ada10597b09e1939a8eb75f6aef96"
+ version = "v1.10.43"
+
+[[projects]]
+ name = "github.com/dgrijalva/jwt-go"
+ packages = ["."]
+ revision = "d2709f9f1f31ebcda9651b03077758c1f3a0018c"
+ version = "v3.0.0"
+
+[[projects]]
+ name = "github.com/go-ini/ini"
+ packages = ["."]
+ revision = "20b96f641a5ea98f2f8619ff4f3e061cff4833bd"
+ version = "v1.28.2"
+
+[[projects]]
+ branch = "master"
+ name = "github.com/golang/protobuf"
+ packages = ["proto"]
+ revision = "17ce1425424ab154092bbb43af630bd647f3bb0d"
+
+[[projects]]
+ branch = "master"
+ name = "github.com/gophercloud/gophercloud"
+ packages = [".","openstack","openstack/blockstorage/v1/volumes","openstack/compute/v2/extensions/floatingips","openstack/compute/v2/extensions/startstop","openstack/compute/v2/extensions/volumeattach","openstack/compute/v2/flavors","openstack/compute/v2/images","openstack/compute/v2/servers","openstack/identity/v2/tenants","openstack/identity/v2/tokens","openstack/identity/v3/tokens","openstack/networking/v2/networks","openstack/utils","pagination"]
+ revision = "e764e6cf0316a135851b56f8eea946b906988707"
+
+[[projects]]
+ name = "github.com/jmespath/go-jmespath"
+ packages = ["."]
+ revision = "3433f3ea46d9f8019119e7dd41274e112a2359a9"
+ version = "0.2.2"
+
+[[projects]]
+ branch = "master"
+ name = "github.com/pyr/egoscale"
+ packages = ["."]
+ revision = "325740036187ddae3a5b74be00fbbc70011c4d96"
+
+[[projects]]
+ name = "github.com/satori/uuid"
+ packages = ["."]
+ revision = "879c5887cd475cd7864858769793b2ceb0d44feb"
+ version = "v1.1.0"
+
+[[projects]]
+ branch = "master"
+ name = "github.com/vmware/govmomi"
+ packages = [".","find","list","nfc","object","ovf","property","session","task","vim25","vim25/debug","vim25/methods","vim25/mo","vim25/progress","vim25/soap","vim25/types","vim25/xml"]
+ revision = "17b8c9ccb7f8c7b015d44c4ea39305c970a7bf31"
+
+[[projects]]
+ branch = "master"
+ name = "golang.org/x/crypto"
+ packages = ["curve25519","ed25519","ed25519/internal/edwards25519","pkcs12","pkcs12/internal/rc2","ssh"]
+ revision = "faadfbdc035307d901e69eea569f5dda451a3ee3"
+
+[[projects]]
+ branch = "master"
+ name = "golang.org/x/net"
+ packages = ["context","context/ctxhttp"]
+ revision = "66aacef3dd8a676686c7ae3716979581e8b03c47"
+
+[[projects]]
+ branch = "master"
+ name = "golang.org/x/oauth2"
+ packages = [".","google","internal","jws","jwt"]
+ revision = "d89af98d7c6bba047c5a2622f36bc14b8766df85"
+
+[[projects]]
+ branch = "master"
+ name = "google.golang.org/api"
+ packages = ["compute/v1","gensupport","googleapi","googleapi/internal/uritemplates"]
+ revision = "6d17a978cb363067e40a571c7cd7ddc010af35b0"
+
+[[projects]]
+ name = "google.golang.org/appengine"
+ packages = [".","internal","internal/app_identity","internal/base","internal/datastore","internal/log","internal/modules","internal/remote_api","internal/urlfetch","urlfetch"]
+ revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a"
+ version = "v1.0.0"
+
+[solve-meta]
+ analyzer-name = "dep"
+ analyzer-version = 1
+ inputs-digest = "f4c60a26d2f23a002094604b4faabfe170b7136df9f5a264eeede7bf1b3246ec"
+ solver-name = "gps-cdcl"
+ solver-version = 1
diff --git a/Gopkg.toml b/Gopkg.toml
new file mode 100644
index 00000000..41dde688
--- /dev/null
+++ b/Gopkg.toml
@@ -0,0 +1,40 @@
+
+[[constraint]]
+ name = "github.com/Azure/azure-sdk-for-go"
+ version = "10.3.1-beta"
+
+[[constraint]]
+ name = "github.com/Azure/go-autorest"
+ version = "8.3.1"
+
+[[constraint]]
+ branch = "master"
+ name = "github.com/apcera/util"
+
+[[constraint]]
+ name = "github.com/aws/aws-sdk-go"
+ version = "1.10.43"
+
+[[constraint]]
+ branch = "master"
+ name = "github.com/gophercloud/gophercloud"
+
+[[constraint]]
+ branch = "master"
+ name = "github.com/pyr/egoscale"
+
+[[constraint]]
+ branch = "master"
+ name = "github.com/vmware/govmomi"
+
+[[constraint]]
+ branch = "master"
+ name = "golang.org/x/crypto"
+
+[[constraint]]
+ branch = "master"
+ name = "golang.org/x/oauth2"
+
+[[constraint]]
+ branch = "master"
+ name = "google.golang.org/api"
diff --git a/README.md b/README.md
index 9e163c8a..77412805 100644
--- a/README.md
+++ b/README.md
@@ -27,11 +27,11 @@ Supported Providers
Getting Started
================
-Go version 1.6+ is required.
+Go version 1.9+ is required.
-`go get github.com/apcera/libretto/...`
-
-`go build ./...`
+``` sh
+go get -u github.com/apcera/libretto
+```
Examples
=========
@@ -40,75 +40,73 @@ AWS
----
``` go
-
rawKey, err := ioutil.ReadFile(*key)
if err != nil {
- return err
+ return err
}
vm := &aws.VM{
- Name: "libretto-aws",
- AMI: "ami-984734",
- InstanceType: "m4.large",
- SSHCreds: ssh.Credentials{
- SSHUser: "ubuntu",
- SSHPrivateKey: string(rawKey),
- },
- Volumes: []aws.EBSVolume{
- {
- DeviceName: "/dev/sda1",
- },
- },
- Region: "ap-northeast-1",
- KeyPair: strings.TrimSuffix(filepath.Base(*key), filepath.Ext(*key)),
- SecurityGroup: "sg-9fdsfds",
+ Name: "libretto-aws",
+ AMI: "ami-984734",
+ InstanceType: "m4.large",
+ SSHCreds: ssh.Credentials{
+ SSHUser: "ubuntu",
+ SSHPrivateKey: string(rawKey),
+ },
+ Volumes: []aws.EBSVolume{
+ {
+ DeviceName: "/dev/sda1",
+ },
+ },
+ Region: "ap-northeast-1",
+ KeyPair: strings.TrimSuffix(filepath.Base(*key), filepath.Ext(*key)),
+ SecurityGroup: "sg-9fdsfds",
}
-if err := aws.ValidCredentials(vm.Region); err != nil {
- return err
+err = aws.ValidCredentials(vm.Region)
+if err != nil {
+ return err
}
-if err := vm.Provision(); err != nil {
- return err
+err = vm.Provision()
+if err != nil {
+ return err
}
-
```
Azure
------
``` go
-
vm := &azure.VM{
- Creds: azure.OAuthCredentials{
- SubscriptionID: os.Getenv("AZURE_SUBSCRIPTION_ID"),
- TenantID: os.Getenv("AZURE_TENANT_ID"),
- ClientID: os.Getenv("AZURE_CLIENT_ID"),
- ClientSecret: os.Getenv("AZURE_CLIENT_SECRET"),
- },
- ImagePublisher: "Canonical",
- ImageOffer: "UbuntuServer",
- ImageSku: "14.04.3-LTS",
- Size: "Standard_A1",
- DiskSize: 40 // Set to 0 if you don't want to attach any additional disk
- Name: "libretto",
- ResourceGroup: "libretto-rg",
- StorageAccount: "libretto-sa",
- StorageContainer: "libretto-sc",
- SSHCreds: ssh.Credentials{
- SSHUser: os.Getenv("AZURE_USER"),
- SSHPassword: os.Getenv("AZURE_PASSWORD"),
- },
-
- NetworkSecurityGroup: "libretto-sg",
- VirtualNetwork: "libretto-vn",
- Subnet: "libretto-sn",
+ Creds: azure.OAuthCredentials{
+ SubscriptionID: os.Getenv("AZURE_SUBSCRIPTION_ID"),
+ TenantID: os.Getenv("AZURE_TENANT_ID"),
+ ClientID: os.Getenv("AZURE_CLIENT_ID"),
+ ClientSecret: os.Getenv("AZURE_CLIENT_SECRET"),
+ },
+ ImagePublisher: "Canonical",
+ ImageOffer: "UbuntuServer",
+ ImageSku: "14.04.3-LTS",
+ Size: "Standard_A1",
+ DiskSize: 40, // Set to 0 if you don't want to attach any additional disk
+ Name: "libretto",
+ ResourceGroup: "libretto-rg",
+ StorageAccount: "libretto-sa",
+ StorageContainer: "libretto-sc",
+ SSHCreds: ssh.Credentials{
+ SSHUser: os.Getenv("AZURE_USER"),
+ SSHPassword: os.Getenv("AZURE_PASSWORD"),
+ },
+
+ NetworkSecurityGroup: "libretto-sg",
+ VirtualNetwork: "libretto-vn",
+ Subnet: "libretto-sn",
}
if err := vm.Provision(); err != nil {
- return err
+ return err
}
-
```
Digital Ocean
@@ -117,178 +115,171 @@ Digital Ocean
``` go
token := os.Getenv("DIGITALOCEAN_API_KEY")
if token == "" {
- return fmt.Errorf("Please export your DigitalOcean API key to 'DIGITALOCEAN_API_KEY' and run again.")
+ return fmt.Errorf("Please export your DigitalOcean API key to 'DIGITALOCEAN_API_KEY' and run again.")
}
config := digitalocean.Config{
- Name: defaultDropletName,
- Region: defaultDropletRegion,
- Image: defaultDropletImage,
- Size: defaultDropletSize,
+ Name: defaultDropletName,
+ Region: defaultDropletRegion,
+ Image: defaultDropletImage,
+ Size: defaultDropletSize,
}
vm := digitalocean.VM{
- APIToken: token,
- Config: config,
+ APIToken: token,
+ Config: config,
}
if err := vm.Provision(); err != nil {
- return err
+ return err
}
```
Exoscale
---------
- ``` go
-
- vm := exoscale.VM{
- Config: exoscale.Config{
- Endpoint: "https://api.exoscale.ch/compute",
- APIKey: os.Getenv("EXOSCALE_API_KEY"),
- APISecret: os.Getenv("EXOSCALE_API_SECRET"),
- },
- Template: exoscale.Template{
- Name: "Linux Ubuntu 16.04 LTS 64-bit",
- StorageGB: 10,
- ZoneName: "ch-dk-2",
- },
- ServiceOffering: exoscale.ServiceOffering{
- Name: exoscale.Medium,
- },
- SecurityGroups: []exoscale.SecurityGroup{
- {Name: "default"},
- {Name: "my sg"},
- },
- Zone: exoscale.Zone{
- Name: "ch-dk-2",
- },
- KeypairName: "mydev",
- Name: "libretto-exoscale",
- Userdata: `
-#cloud-config
+``` go
+vm := exoscale.VM{
+ Config: exoscale.Config{
+ Endpoint: "https://api.exoscale.ch/compute",
+ APIKey: os.Getenv("EXOSCALE_API_KEY"),
+ APISecret: os.Getenv("EXOSCALE_API_SECRET"),
+ },
+ Template: exoscale.Template{
+ Name: "Linux Ubuntu 16.04 LTS 64-bit",
+ StorageGB: 10,
+ ZoneName: "ch-dk-2",
+ },
+ ServiceOffering: exoscale.ServiceOffering{
+ Name: exoscale.Medium,
+ },
+ SecurityGroups: []exoscale.SecurityGroup{
+ {Name: "default"},
+ {Name: "my sg"},
+ },
+ Zone: exoscale.Zone{
+ Name: "ch-dk-2",
+ },
+ KeypairName: "mydev",
+ Name: "libretto-exoscale",
+ Userdata: `
+# cloud-config
manage_etc_hosts: true
fqdn: new.host
`,
- }
-
- if err := vm.Provision(); err != nil {
- fmt.Printf("Error provisioning machine: %s\n", err)
- }
+}
- // get VM ID polling every 5 seconds, timeout after 30
- vm.WaitVMCreation(30, 5)
+if err := vm.Provision(); err != nil {
+ fmt.Printf("Error provisioning machine: %s\n", err)
+}
- ```
+// get VM ID polling every 5 seconds, timeout after 30
+vm.WaitVMCreation(30, 5)
+```
Google Cloud Platform
----------
``` go
-
vm := &gcp.VM{
- Name: "libretto-vm-1",
- Zone: "us-central1-a",
- MachineType: "n1-standard-1",
- SourceImage: "ubuntu-1404-trusty-v20160516",
- Disks: []gcp.Disk{
- {
- DiskType: "pd-standard",
- DiskSizeGb: 10,
- AutoDelete: true,
- },
- {
- DiskType: "pd-standard",
- DiskSizeGb: 500,
- AutoDelete: true,
- Name: "addtional-disk",
- },
- },
- Preemptible: false,
- Network: "default",
- Subnetwork: "default",
- UseInternalIP: false,
- Project: os.Getenv("YOUR-GOOGLE-PROJECT"),
- Scopes: scopes,
-
- AccountFile: accountFile,
- SSHCreds: ssh.Credentials{
- SSHUser: "ubuntu",
- SSHPrivateKey: string(sshPrivateKey),
- },
- SSHPublicKey: string(sshPublicKey),
- Tags: []string{"libretto"},
- }
-
- err := vm.Provision()
- if err != nil {
- return err
- }
- ```
+ Name: "libretto-vm-1",
+ Zone: "us-central1-a",
+ MachineType: "n1-standard-1",
+ SourceImage: "ubuntu-1404-trusty-v20160516",
+ Disks: []gcp.Disk{
+ {
+ DiskType: "pd-standard",
+ DiskSizeGb: 10,
+ AutoDelete: true,
+ },
+ {
+ DiskType: "pd-standard",
+ DiskSizeGb: 500,
+ AutoDelete: true,
+ Name: "addtional-disk",
+ },
+ },
+ Preemptible: false,
+ Network: "default",
+ Subnetwork: "default",
+ UseInternalIP: false,
+ Project: os.Getenv("YOUR-GOOGLE-PROJECT"),
+ Scopes: scopes,
+
+ AccountFile: accountFile,
+ SSHCreds: ssh.Credentials{
+ SSHUser: "ubuntu",
+ SSHPrivateKey: string(sshPrivateKey),
+ },
+ SSHPublicKey: string(sshPublicKey),
+ Tags: []string{"libretto"},
+}
+
+if err := vm.Provision(); err != nil {
+ return err
+}
+```
Openstack
----------
``` go
+metadata := openstack.NewDefaultImageMetadata()
+volume := openstack.NewDefaultVolume()
+// Optional
+cloudInit, err := ioutil.ReadFile("/your/user/data")
+if err != nil {
+ return err
+}
- metadata := openstack.NewDefaultImageMetadata()
- volume := openstack.NewDefaultVolume()
-
- // Optional
- cloudInit, err := ioutil.ReadFile("/your/user/data")
- if err != nil {
- return err
- }
-
- vm := &openstack.VM{
- IdentityEndpoint: os.Getenv("OS_AUTH_URL"),
- Username: os.Getenv("OS_USERNAME"),
- Password: os.Getenv("OS_PASSWORD"),
- Region: os.Getenv("OS_REGION_NAME"),
- TenantName: os.Getenv("OS_TENANT_NAME"),
- FlavorName: "m1.medium",
- ImageID: "",
- ImageMetadata: metadata,
- ImagePath: os.Getenv("OS_IMAGE_PATH"),
- Volume: volume,
- InstanceID: "",
- Name: "test",
- Networks: []string{"eab29109-3363-4b03-8a56-8fe27b71f3a0"},
- FloatingIPPool: "net04_ext",
- FloatingIP: nil,
- SecurityGroup: "test",
- AdminPassword: os.Getenv("OS_ADMIN_PASSWORD"),
- UserData: cloudInit,
- Credentials: ssh.Credentials{
- SSHUser: "ubuntu",
- SSHPassword: "ubuntu",
- },
- }
-
- err := vm.Provision()
- if err != nil {
- return err
- }
- ```
+vm := &openstack.VM{
+ IdentityEndpoint: os.Getenv("OS_AUTH_URL"),
+ Username: os.Getenv("OS_USERNAME"),
+ Password: os.Getenv("OS_PASSWORD"),
+ Region: os.Getenv("OS_REGION_NAME"),
+ TenantName: os.Getenv("OS_TENANT_NAME"),
+ FlavorName: "m1.medium",
+ ImageID: "",
+ ImageMetadata: metadata,
+ ImagePath: os.Getenv("OS_IMAGE_PATH"),
+ Volume: volume,
+ InstanceID: "",
+ Name: "test",
+ Networks: []string{"eab29109-3363-4b03-8a56-8fe27b71f3a0"},
+ FloatingIPPool: "net04_ext",
+ FloatingIP: nil,
+ SecurityGroup: "test",
+ AdminPassword: os.Getenv("OS_ADMIN_PASSWORD"),
+ UserData: cloudInit,
+ Credentials: ssh.Credentials{
+ SSHUser: "ubuntu",
+ SSHPassword: "ubuntu",
+ },
+}
+
+err = vm.Provision()
+if err != nil {
+ return err
+}
+```
Virtualbox
-----------
``` go
-
var config virtualbox.Config
config.NICs = []virtualbox.NIC{
- virtualbox.NIC{Idx: 1, Backing: virtualbox.Bridged, BackingDevice: "en0: Wi-Fi (AirPort)"},
+ virtualbox.NIC{Idx: 1, Backing: virtualbox.Bridged, BackingDevice: "en0: Wi-Fi (AirPort)"},
}
vm := virtualbox.VM{Src: "/Users/Admin/vm-bfb21a62-60c5-11e5-9fc5-a45e60e45ad5.ova",
- Credentials: ssh.Credentials{
- SSHUser: "ubuntu",
- SSHPassword: "ubuntu",
- },
- Config: config,
+ Credentials: ssh.Credentials{
+ SSHUser: "ubuntu",
+ SSHPassword: "ubuntu",
+ },
+ Config: config,
}
if err := vm.Provision(); err != nil {
- return err
+ return err
}
```
@@ -296,31 +287,30 @@ vSphere
--------
``` go
-
vm := &vsphere.VM{
- Host: "10.2.1.11",
- Username: "username",
- Password: "password",
- Datacenter: "test-dc",
- Datastores: []string{"datastore1", "datastore2"},
- Networks: map[string]string{"nat": "network1"},
- Credentials: ssh.Credentials{
- SSHUser: "ubuntu",
- SSHPassword: "ubuntu",
- },
- SkipExisting: true,
- Insecure: true,
- Destination: vsphere.Destination{
- DestinationName: "Host1",
- DestinationType: "host",
- HostSystem: "",
- },
- Name: "test-vm",
- Template: "test-template",
- OvfPath: "/Users/Test/Downloads/file.ovf",
+ Host: "10.2.1.11",
+ Username: "username",
+ Password: "password",
+ Datacenter: "test-dc",
+ Datastores: []string{"datastore1", "datastore2"},
+ Networks: map[string]string{"nat": "network1"},
+ Credentials: ssh.Credentials{
+ SSHUser: "ubuntu",
+ SSHPassword: "ubuntu",
+ },
+ SkipExisting: true,
+ Insecure: true,
+ Destination: vsphere.Destination{
+ DestinationName: "Host1",
+ DestinationType: "host",
+ HostSystem: "",
+ },
+ Name: "test-vm",
+ Template: "test-template",
+ OvfPath: "/Users/Test/Downloads/file.ovf",
}
if err := vm.Provision(); err != nil {
- return err
+ return err
}
```
@@ -331,18 +321,18 @@ VMware Fusion/Workstation (vmrun)
``` go
var config vmrun.Config
config.NICs = []vmrun.NIC{
- vmrun.NIC{Idx: 0, Backing: vmrun.Nat, BackingDevice: "en0"},
+ vmrun.NIC{Idx: 0, Backing: vmrun.Nat, BackingDevice: "en0"},
}
vm := vmrun.VM{Src: "/Users/Admin/vmware_desktop/trusty-orchestrator-dev.vmx",
- Dst: "/Users/Admin/Documents/VMs",
- Credentials: ssh.Credentials{
- SSHUser: "ubuntu",
- SSHPassword: "ubuntu",
- },
- Config: config,
+ Dst: "/Users/Admin/Documents/VMs",
+ Credentials: ssh.Credentials{
+ SSHUser: "ubuntu",
+ SSHPassword: "ubuntu",
+ },
+ Config: config,
}
if err := vm.Provision(); err != nil {
- return err
+ return err
}
```
@@ -352,8 +342,8 @@ FAQ
* Why write Libretto?
-We couldn't find a suitable Golang binding for this functionality, so we
-created this library. There are a couple of similar libraries but not in golang
+We couldn't find a suitable Golang binding for this functionality, so we created
+this library. There are a couple of similar libraries but not in golang
(fog.io in ruby, jcloud in java, libcloud in python).
Docker Machine is an effort toward that direction, but it is very Docker
@@ -362,14 +352,13 @@ number of parameters, but reduces the flexibility of the tool.
* What is the scope for Libretto?
-Virtual machine creation and life cycle
-management as well as common configuration steps during a deploy such as
-configuring SSH keys.
+Virtual machine creation and life cycle management as well as common
+configuration steps during a deploy such as configuring SSH keys.
* Why use this library over other tools?
-Actively used and developed. Can be called natively from Go in a Go application
-instead of shelling out to other tools.
+Can be called natively from Go in a Go application instead of shelling out to
+other tools.
Known Issues
=============
@@ -398,8 +387,8 @@ Libretto `VirtualMachine` interface. The provider should work at the minimum on
the Linux, Windows and OS X platforms unless it is a platform specific provider
in which case it should at least compile and return a descriptive error.
-Dependencies should be versioned and stored using `gvt`
-(https://github.com/FiloSottile/gvt)
+Dependencies should be vendored using [`dep ensure`](https://github.com/golang/dep),
+followed by [`dep prune`](https://github.com/golang/dep).
Errors should be lower case so that they can be wrapped by the calling code. If
possible, types defined in the top level `virtualmachine` package should be
diff --git a/libretto.jpg b/libretto.jpg
index fb867c6f..6e18b250 100644
Binary files a/libretto.jpg and b/libretto.jpg differ
diff --git a/ssh/mock_ssh.go b/ssh/mock_ssh.go
index ab9118bb..18923dd9 100644
--- a/ssh/mock_ssh.go
+++ b/ssh/mock_ssh.go
@@ -7,6 +7,22 @@ import (
"time"
)
+// MockSSHClient represents a Mock Client wrapper.
+type MockSSHClient struct {
+ MockConnect func() error
+ MockDisconnect func()
+ MockDownload func(src io.WriteCloser, dst string) error
+ MockRun func(command string, stdout io.Writer, stderr io.Writer) error
+ MockUpload func(src io.Reader, dst string, size int, mode uint32) error
+ MockValidate func() error
+ MockWaitForSSH func(maxWait time.Duration) error
+
+ MockSetSSHPrivateKey func(string)
+ MockGetSSHPrivateKey func() string
+ MockSetSSHPassword func(string)
+ MockGetSSHPassword func() string
+}
+
// Connect calls the mocked connect.
func (c *MockSSHClient) Connect() error {
if c.MockConnect != nil {
@@ -19,9 +35,7 @@ func (c *MockSSHClient) Connect() error {
func (c *MockSSHClient) Disconnect() {
if c.MockDisconnect != nil {
c.MockDisconnect()
- return
}
- return
}
// Download calls the mocked download.
@@ -41,9 +55,9 @@ func (c *MockSSHClient) Run(command string, stdout io.Writer, stderr io.Writer)
}
// Upload calls the mocked upload
-func (c *MockSSHClient) Upload(src io.Reader, dst string, mode uint32) error {
+func (c *MockSSHClient) Upload(src io.Reader, dst string, size int, mode uint32) error {
if c.MockUpload != nil {
- return c.MockUpload(src, dst, mode)
+ return c.MockUpload(src, dst, size, mode)
}
return ErrNotImplemented
}
@@ -68,9 +82,7 @@ func (c *MockSSHClient) WaitForSSH(maxWait time.Duration) error {
func (c *MockSSHClient) SetSSHPrivateKey(s string) {
if c.MockSetSSHPrivateKey != nil {
c.MockSetSSHPrivateKey(s)
- return
}
- return
}
// GetSSHPrivateKey calls the mocked GetSSHPrivateKey
@@ -85,9 +97,7 @@ func (c *MockSSHClient) GetSSHPrivateKey() string {
func (c *MockSSHClient) SetSSHPassword(s string) {
if c.MockSetSSHPassword != nil {
c.MockSetSSHPassword(s)
- return
}
- return
}
// GetSSHPassword calls the mocked GetSSHPassword
diff --git a/ssh/ssh.go b/ssh/ssh.go
index 1b535e5e..fc4496d9 100644
--- a/ssh/ssh.go
+++ b/ssh/ssh.go
@@ -4,11 +4,9 @@ package ssh
import (
"bufio"
- "bytes"
"errors"
"fmt"
"io"
- "io/ioutil"
"net"
"os"
"path"
@@ -39,8 +37,6 @@ var (
ErrUnableToWriteFile = errors.New("Unable to write file")
// ErrNotImplemented is returned when a function is not implemented (typically by the Mock implementation).
ErrNotImplemented = errors.New("Operation not implemented")
- // Setup a mutex for the close channel for thread safety.
- closeMutex sync.Mutex
)
const (
@@ -62,7 +58,7 @@ type Client interface {
Disconnect()
Download(src io.WriteCloser, dst string) error
Run(command string, stdout io.Writer, stderr io.Writer) error
- Upload(src io.Reader, dst string, mode uint32) error
+ Upload(src io.Reader, dst string, size int, mode uint32) error
Validate() error
WaitForSSH(maxWait time.Duration) error
@@ -98,63 +94,6 @@ type SSHClient struct {
close chan bool
}
-// MockSSHClient represents a Mock Client wrapper.
-type MockSSHClient struct {
- MockConnect func() error
- MockDisconnect func()
- MockDownload func(src io.WriteCloser, dst string) error
- MockRun func(command string, stdout io.Writer, stderr io.Writer) error
- MockUpload func(src io.Reader, dst string, mode uint32) error
- MockValidate func() error
- MockWaitForSSH func(maxWait time.Duration) error
-
- MockSetSSHPrivateKey func(string)
- MockGetSSHPrivateKey func() string
- MockSetSSHPassword func(string)
- MockGetSSHPassword func() string
-}
-
-// dial will attempt to connect to an SSH server.
-var dial = func(network, addr string, config *cssh.ClientConfig) (*cssh.Client, error) {
- d := net.Dialer{Timeout: Timeout, KeepAlive: 2 * time.Second}
-
- conn, err := d.Dial(network, addr)
- if err != nil {
- return nil, err
- }
-
- c, chans, reqs, err := cssh.NewClientConn(conn, addr, config)
- if err != nil {
- return nil, err
- }
-
- return cssh.NewClient(c, chans, reqs), nil
-}
-
-var readPrivateKey = func(key string) (cssh.AuthMethod, error) {
- signer, err := cssh.ParsePrivateKey([]byte(key))
- if err != nil {
- return nil, err
- }
-
- return cssh.PublicKeys(signer), nil
-}
-
-var getAuth = func(c *Credentials, authType string) (cssh.AuthMethod, error) {
- var (
- auth cssh.AuthMethod
- err error
- )
-
- switch authType {
- case PasswordAuth:
- return cssh.Password(c.SSHPassword), nil
- case KeyAuth:
- return readPrivateKey(c.SSHPrivateKey)
- }
- return auth, err
-}
-
// Connect connects to a machine using SSH.
func (client *SSHClient) Connect() error {
var (
@@ -183,6 +122,7 @@ func (client *SSHClient) Connect() error {
Auth: []cssh.AuthMethod{
auth,
},
+ HostKeyCallback: cssh.InsecureIgnoreHostKey(),
}
port := sshPort
@@ -197,12 +137,8 @@ func (client *SSHClient) Connect() error {
client.cryptoClient = c
- closeMutex.Lock()
- defer closeMutex.Unlock()
+ client.close = make(chan bool, 1)
- if client.close == nil {
- client.close = make(chan bool, 1)
- }
if client.Options.KeepAlive > 0 {
go client.keepAlive()
}
@@ -226,17 +162,7 @@ func (client *SSHClient) keepAlive() {
// Disconnect should be called when the ssh client is no longer needed, and state can be cleaned up
func (client *SSHClient) Disconnect() {
- select {
- case <-client.close:
- default:
- closeMutex.Lock()
- defer closeMutex.Unlock()
-
- if client.close != nil {
- close(client.close)
- client.close = nil
- }
- }
+ client.close <- true
}
// Download downloads a file via SSH (SCP)
@@ -362,18 +288,14 @@ func (client *SSHClient) Run(command string, stdout io.Writer, stderr io.Writer)
return session.Run(command)
}
-// Upload uploads a new file via SSH (SCP)
-func (client *SSHClient) Upload(src io.Reader, dst string, mode uint32) error {
- fileContent, err := ioutil.ReadAll(src)
- if err != nil {
- return err
- }
-
+// Upload uploads a new file via SSH (SCP). dst is the destination path for the
+// file on the remote machine. size is the number of bytes to be uploaded. mode
+// is the permissions the file should have, e.g. 0744.
+func (client *SSHClient) Upload(src io.Reader, dst string, size int, mode uint32) error {
session, err := client.cryptoClient.NewSession()
if err != nil {
return err
}
-
defer session.Close()
w, err := session.StdinPipe()
@@ -393,8 +315,8 @@ func (client *SSHClient) Upload(src io.Reader, dst string, mode uint32) error {
defer wg.Done()
// Signals to the SSH receiver that content is being passed.
- fmt.Fprintf(w, "C%#o %d %s\n", mode, len(fileContent), remoteFileName)
- _, err = io.Copy(w, bytes.NewReader(fileContent))
+ fmt.Fprintf(w, "C%#o %d %s\n", mode, size, remoteFileName)
+ _, err = io.Copy(w, src)
if err != nil {
errorChan <- err
return
@@ -486,3 +408,44 @@ func (client *SSHClient) GetSSHPassword() string {
defer client.Creds.mu.Unlock()
return client.Creds.SSHPassword
}
+
+// dial will attempt to connect to an SSH server.
+var dial = func(network, addr string, config *cssh.ClientConfig) (*cssh.Client, error) {
+ d := net.Dialer{Timeout: Timeout, KeepAlive: 2 * time.Second}
+
+ conn, err := d.Dial(network, addr)
+ if err != nil {
+ return nil, err
+ }
+
+ c, chans, reqs, err := cssh.NewClientConn(conn, addr, config)
+ if err != nil {
+ return nil, err
+ }
+
+ return cssh.NewClient(c, chans, reqs), nil
+}
+
+var readPrivateKey = func(key string) (cssh.AuthMethod, error) {
+ signer, err := cssh.ParsePrivateKey([]byte(key))
+ if err != nil {
+ return nil, err
+ }
+
+ return cssh.PublicKeys(signer), nil
+}
+
+var getAuth = func(c *Credentials, authType string) (cssh.AuthMethod, error) {
+ var (
+ auth cssh.AuthMethod
+ err error
+ )
+
+ switch authType {
+ case PasswordAuth:
+ return cssh.Password(c.SSHPassword), nil
+ case KeyAuth:
+ return readPrivateKey(c.SSHPrivateKey)
+ }
+ return auth, err
+}
diff --git a/vendor/github.com/vmware/govmomi/event/processor.go b/vendor/github.com/vmware/govmomi/event/processor.go
index 1f287b8d..18084d48 100644
--- a/vendor/github.com/vmware/govmomi/event/processor.go
+++ b/vendor/github.com/vmware/govmomi/event/processor.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2016 VMware, Inc. All Rights Reserved.
+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.
@@ -25,8 +25,6 @@ import (
"github.com/vmware/govmomi/vim25/types"
)
-const latestPageProp = "latestPage"
-
type tailInfo struct {
t *eventTailer
obj types.ManagedObjectReference
@@ -81,53 +79,47 @@ func (p *eventProcessor) run(ctx context.Context, tail bool) error {
return nil
}
- var err error
var collectors []types.ManagedObjectReference
for _, t := range p.tailers {
collectors = append(collectors, t.collector)
}
- if len(p.tailers) > 1 {
- // create and populate a ListView
- viewMgr := view.NewManager(p.mgr.Client())
- var listView *view.ListView
- listView, err = viewMgr.CreateListView(ctx, collectors)
- if err != nil {
- return err
- }
+ c := property.DefaultCollector(p.mgr.Client())
+ props := []string{"latestPage"}
- count := 0
- // Retrieve the property from the objects in the ListView
- err = property.WaitForView(ctx, property.DefaultCollector(p.mgr.Client()), listView.Reference(), collectors[0], []string{latestPageProp}, func(c types.ManagedObjectReference, pc []types.PropertyChange) bool {
- if err = p.process(c, pc); err != nil {
+ if len(collectors) == 1 {
+ // only one object to follow, don't bother creating a view
+ return property.Wait(ctx, c, collectors[0], props, func(pc []types.PropertyChange) bool {
+ if err := p.process(collectors[0], pc); err != nil {
return false
}
- count++
- if count == len(collectors) && !tail {
- return true
- }
-
- return false
+ return !tail
})
+ }
+ // create and populate a ListView
+ m := view.NewManager(p.mgr.Client())
+
+ list, err := m.CreateListView(ctx, collectors)
+ if err != nil {
return err
}
- // only one object to follow
- err = property.Wait(ctx, property.DefaultCollector(p.mgr.Client()), collectors[0], []string{latestPageProp}, func(pc []types.PropertyChange) bool {
- if err = p.process(collectors[0], pc); err != nil {
- return false
- }
+ defer list.Destroy(context.Background())
+
+ ref := list.Reference()
+ filter := new(property.WaitFilter).Add(ref, collectors[0].Type, props, list.TraversalSpec())
- if !tail {
- return true
+ return property.WaitForUpdates(ctx, c, filter, func(updates []types.ObjectUpdate) bool {
+ for _, update := range updates {
+ if err := p.process(update.Obj, update.ChangeSet); err != nil {
+ return false
+ }
}
- return false
+ return !tail
})
-
- return err
}
func (p *eventProcessor) process(c types.ManagedObjectReference, pc []types.PropertyChange) error {
@@ -137,10 +129,6 @@ func (p *eventProcessor) process(c types.ManagedObjectReference, pc []types.Prop
}
for _, u := range pc {
- if u.Name != latestPageProp {
- continue
- }
-
evs := t.t.newEvents(u.Val.(types.ArrayOfEvent).Event)
if len(evs) == 0 {
continue
diff --git a/vendor/github.com/vmware/govmomi/examples/datastores/main.go b/vendor/github.com/vmware/govmomi/examples/datastores/main.go
index 87902e87..67c8720c 100644
--- a/vendor/github.com/vmware/govmomi/examples/datastores/main.go
+++ b/vendor/github.com/vmware/govmomi/examples/datastores/main.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2015 VMware, Inc. All Rights Reserved.
+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.
@@ -15,7 +15,7 @@ limitations under the License.
*/
/*
-This example program shows how the `finder` and `property` packages can
+This example program shows how the `view` and `property` packages can
be used to navigate a vSphere inventory structure using govmomi.
*/
@@ -23,158 +23,59 @@ package main
import (
"context"
- "flag"
"fmt"
- "net/url"
+ "log"
"os"
- "strings"
"text/tabwriter"
- "github.com/vmware/govmomi"
- "github.com/vmware/govmomi/find"
- "github.com/vmware/govmomi/property"
+ "github.com/vmware/govmomi/examples"
"github.com/vmware/govmomi/units"
+ "github.com/vmware/govmomi/view"
"github.com/vmware/govmomi/vim25/mo"
- "github.com/vmware/govmomi/vim25/types"
)
-// GetEnvString returns string from environment variable.
-func GetEnvString(v string, def string) string {
- r := os.Getenv(v)
- if r == "" {
- return def
- }
-
- return r
-}
-
-// GetEnvBool returns boolean from environment variable.
-func GetEnvBool(v string, def bool) bool {
- r := os.Getenv(v)
- if r == "" {
- return def
- }
-
- switch strings.ToLower(r[0:1]) {
- case "t", "y", "1":
- return true
- }
-
- return false
-}
-
-const (
- envURL = "GOVMOMI_URL"
- envUserName = "GOVMOMI_USERNAME"
- envPassword = "GOVMOMI_PASSWORD"
- envInsecure = "GOVMOMI_INSECURE"
-)
-
-var urlDescription = fmt.Sprintf("ESX or vCenter URL [%s]", envURL)
-var urlFlag = flag.String("url", GetEnvString(envURL, "https://username:password@host/sdk"), urlDescription)
-
-var insecureDescription = fmt.Sprintf("Don't verify the server's certificate chain [%s]", envInsecure)
-var insecureFlag = flag.Bool("insecure", GetEnvBool(envInsecure, false), insecureDescription)
-
-func processOverride(u *url.URL) {
- envUsername := os.Getenv(envUserName)
- envPassword := os.Getenv(envPassword)
-
- // Override username if provided
- if envUsername != "" {
- var password string
- var ok bool
-
- if u.User != nil {
- password, ok = u.User.Password()
- }
-
- if ok {
- u.User = url.UserPassword(envUsername, password)
- } else {
- u.User = url.User(envUsername)
- }
- }
-
- // Override password if provided
- if envPassword != "" {
- var username string
-
- if u.User != nil {
- username = u.User.Username()
- }
-
- u.User = url.UserPassword(username, envPassword)
- }
-}
-
-func exit(err error) {
- fmt.Fprintf(os.Stderr, "Error: %s\n", err)
- os.Exit(1)
-}
-
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- flag.Parse()
-
- // Parse URL from string
- u, err := url.Parse(*urlFlag)
- if err != nil {
- exit(err)
- }
-
- // Override username and/or password as required
- processOverride(u)
-
// Connect and log in to ESX or vCenter
- c, err := govmomi.NewClient(ctx, u, *insecureFlag)
+ c, err := examples.NewClient(ctx)
if err != nil {
- exit(err)
+ log.Fatal(err)
}
- f := find.NewFinder(c.Client, true)
+ defer c.Logout(ctx)
- // Find one and only datacenter
- dc, err := f.DefaultDatacenter(ctx)
- if err != nil {
- exit(err)
- }
-
- // Make future calls local to this datacenter
- f.SetDatacenter(dc)
+ // Create a view of Datastore objects
+ m := view.NewManager(c.Client)
- // Find datastores in datacenter
- dss, err := f.DatastoreList(ctx, "*")
+ v, err := m.CreateContainerView(ctx, c.ServiceContent.RootFolder, []string{"Datastore"}, true)
if err != nil {
- exit(err)
+ log.Fatal(err)
}
- pc := property.DefaultCollector(c.Client)
-
- // Convert datastores into list of references
- var refs []types.ManagedObjectReference
- for _, ds := range dss {
- refs = append(refs, ds.Reference())
- }
+ defer v.Destroy(ctx)
// Retrieve summary property for all datastores
- var dst []mo.Datastore
- err = pc.Retrieve(ctx, refs, []string{"summary"}, &dst)
+ // Reference: http://pubs.vmware.com/vsphere-60/topic/com.vmware.wssdk.apiref.doc/vim.Datastore.html
+ var dss []mo.Datastore
+ err = v.Retrieve(ctx, []string{"Datastore"}, []string{"summary"}, &dss)
if err != nil {
- exit(err)
+ log.Fatal(err)
}
- // Print summary per datastore
+ // Print summary per datastore (see also: govc/datastore/info.go)
+
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
fmt.Fprintf(tw, "Name:\tType:\tCapacity:\tFree:\n")
- for _, ds := range dst {
+
+ for _, ds := range dss {
fmt.Fprintf(tw, "%s\t", ds.Summary.Name)
fmt.Fprintf(tw, "%s\t", ds.Summary.Type)
fmt.Fprintf(tw, "%s\t", units.ByteSize(ds.Summary.Capacity))
fmt.Fprintf(tw, "%s\t", units.ByteSize(ds.Summary.FreeSpace))
fmt.Fprintf(tw, "\n")
}
- tw.Flush()
+
+ _ = tw.Flush()
}
diff --git a/vendor/github.com/vmware/govmomi/examples/examples.go b/vendor/github.com/vmware/govmomi/examples/examples.go
new file mode 100644
index 00000000..1bd0728f
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/examples/examples.go
@@ -0,0 +1,116 @@
+/*
+Copyright (c) 2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package examples
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "net/url"
+ "os"
+ "strings"
+
+ "github.com/vmware/govmomi"
+ "github.com/vmware/govmomi/vim25/soap"
+)
+
+// getEnvString returns string from environment variable.
+func getEnvString(v string, def string) string {
+ r := os.Getenv(v)
+ if r == "" {
+ return def
+ }
+
+ return r
+}
+
+// getEnvBool returns boolean from environment variable.
+func getEnvBool(v string, def bool) bool {
+ r := os.Getenv(v)
+ if r == "" {
+ return def
+ }
+
+ switch strings.ToLower(r[0:1]) {
+ case "t", "y", "1":
+ return true
+ }
+
+ return false
+}
+
+const (
+ envURL = "GOVMOMI_URL"
+ envUserName = "GOVMOMI_USERNAME"
+ envPassword = "GOVMOMI_PASSWORD"
+ envInsecure = "GOVMOMI_INSECURE"
+)
+
+var urlDescription = fmt.Sprintf("ESX or vCenter URL [%s]", envURL)
+var urlFlag = flag.String("url", getEnvString(envURL, "https://username:password@host/sdk"), urlDescription)
+
+var insecureDescription = fmt.Sprintf("Don't verify the server's certificate chain [%s]", envInsecure)
+var insecureFlag = flag.Bool("insecure", getEnvBool(envInsecure, false), insecureDescription)
+
+func processOverride(u *url.URL) {
+ envUsername := os.Getenv(envUserName)
+ envPassword := os.Getenv(envPassword)
+
+ // Override username if provided
+ if envUsername != "" {
+ var password string
+ var ok bool
+
+ if u.User != nil {
+ password, ok = u.User.Password()
+ }
+
+ if ok {
+ u.User = url.UserPassword(envUsername, password)
+ } else {
+ u.User = url.User(envUsername)
+ }
+ }
+
+ // Override password if provided
+ if envPassword != "" {
+ var username string
+
+ if u.User != nil {
+ username = u.User.Username()
+ }
+
+ u.User = url.UserPassword(username, envPassword)
+ }
+}
+
+// NewClient creates a govmomi.Client for use in the examples
+func NewClient(ctx context.Context) (*govmomi.Client, error) {
+ flag.Parse()
+
+ // Parse URL from string
+ u, err := soap.ParseURL(*urlFlag)
+ if err != nil {
+ return nil, err
+ }
+
+ // Override username and/or password as required
+ processOverride(u)
+
+ // Connect and log in to ESX or vCenter
+ return govmomi.NewClient(ctx, u, *insecureFlag)
+}
diff --git a/vendor/github.com/vmware/govmomi/examples/hosts/main.go b/vendor/github.com/vmware/govmomi/examples/hosts/main.go
new file mode 100644
index 00000000..625e2aed
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/examples/hosts/main.go
@@ -0,0 +1,87 @@
+/*
+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.
+*/
+
+/*
+This example program shows how the `view` and `property` packages can
+be used to navigate a vSphere inventory structure using govmomi.
+*/
+
+package main
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "os"
+ "text/tabwriter"
+
+ "github.com/vmware/govmomi/examples"
+ "github.com/vmware/govmomi/units"
+ "github.com/vmware/govmomi/view"
+ "github.com/vmware/govmomi/vim25/mo"
+)
+
+func main() {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ // Connect and login to ESX or vCenter
+ c, err := examples.NewClient(ctx)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ defer c.Logout(ctx)
+
+ // Create a view of HostSystem objects
+ m := view.NewManager(c.Client)
+
+ v, err := m.CreateContainerView(ctx, c.ServiceContent.RootFolder, []string{"HostSystem"}, true)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ defer v.Destroy(ctx)
+
+ // Retrieve summary property for all hosts
+ // Reference: http://pubs.vmware.com/vsphere-60/topic/com.vmware.wssdk.apiref.doc/vim.HostSystem.html
+ var hss []mo.HostSystem
+ err = v.Retrieve(ctx, []string{"HostSystem"}, []string{"summary"}, &hss)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Print summary per host (see also: govc/host/info.go)
+
+ tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
+ fmt.Fprintf(tw, "Name:\tUsed CPU:\tTotal CPU:\tFree CPU:\tUsed Memory:\tTotal Memory:\tFree Memory\t:\n")
+
+ for _, hs := range hss {
+ totalCPU := int64(hs.Summary.Hardware.CpuMhz) * int64(hs.Summary.Hardware.NumCpuCores)
+ freeCPU := int64(totalCPU) - int64(hs.Summary.QuickStats.OverallCpuUsage)
+ freeMemory := int64(hs.Summary.Hardware.MemorySize) - (int64(hs.Summary.QuickStats.OverallMemoryUsage) * 1024 * 1024)
+ fmt.Fprintf(tw, "%s\t", hs.Summary.Config.Name)
+ fmt.Fprintf(tw, "%d\t", hs.Summary.QuickStats.OverallCpuUsage)
+ fmt.Fprintf(tw, "%d\t", totalCPU)
+ fmt.Fprintf(tw, "%d\t", freeCPU)
+ fmt.Fprintf(tw, "%s\t", units.ByteSize(hs.Summary.QuickStats.OverallMemoryUsage))
+ fmt.Fprintf(tw, "%s\t", units.ByteSize(hs.Summary.Hardware.MemorySize))
+ fmt.Fprintf(tw, "%d\t", freeMemory)
+ fmt.Fprintf(tw, "\n")
+ }
+
+ _ = tw.Flush()
+}
diff --git a/vendor/github.com/vmware/govmomi/examples/networks/main.go b/vendor/github.com/vmware/govmomi/examples/networks/main.go
new file mode 100644
index 00000000..1640af34
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/examples/networks/main.go
@@ -0,0 +1,61 @@
+/*
+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 main
+
+import (
+ "context"
+ "fmt"
+ "log"
+
+ "github.com/vmware/govmomi/examples"
+ "github.com/vmware/govmomi/view"
+ "github.com/vmware/govmomi/vim25/mo"
+)
+
+func main() {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ // Connect and login to ESX or vCenter
+ c, err := examples.NewClient(ctx)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ defer c.Logout(ctx)
+
+ // Create a view of Network types
+ m := view.NewManager(c.Client)
+
+ v, err := m.CreateContainerView(ctx, c.ServiceContent.RootFolder, []string{"Network"}, true)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ defer v.Destroy(ctx)
+
+ // Reference: http://pubs.vmware.com/vsphere-60/topic/com.vmware.wssdk.apiref.doc/vim.Network.html
+ var networks []mo.Network
+ err = v.Retrieve(ctx, []string{"Network"}, nil, &networks)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ for _, net := range networks {
+ fmt.Printf("%s: %s\n", net.Name, net.Reference())
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/examples/virtualmachines/main.go b/vendor/github.com/vmware/govmomi/examples/virtualmachines/main.go
new file mode 100644
index 00000000..f6982e41
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/examples/virtualmachines/main.go
@@ -0,0 +1,69 @@
+/*
+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.
+*/
+
+/*
+This example program shows how the `view` package can
+be used to navigate a vSphere inventory structure using govmomi.
+*/
+
+package main
+
+import (
+ "context"
+ "fmt"
+ "log"
+
+ "github.com/vmware/govmomi/examples"
+ "github.com/vmware/govmomi/view"
+ "github.com/vmware/govmomi/vim25/mo"
+)
+
+func main() {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ // Connect and login to ESX or vCenter
+ c, err := examples.NewClient(ctx)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ defer c.Logout(ctx)
+
+ // Create view of VirtualMachine objects
+ m := view.NewManager(c.Client)
+
+ v, err := m.CreateContainerView(ctx, c.ServiceContent.RootFolder, []string{"VirtualMachine"}, true)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ defer v.Destroy(ctx)
+
+ // Retrieve summary property for all machines
+ // Reference: http://pubs.vmware.com/vsphere-60/topic/com.vmware.wssdk.apiref.doc/vim.VirtualMachine.html
+ var vms []mo.VirtualMachine
+ err = v.Retrieve(ctx, []string{"VirtualMachine"}, []string{"summary"}, &vms)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Print summary per vm (see also: govc/vm/info.go)
+
+ for _, vm := range vms {
+ fmt.Printf("%s: %s\n", vm.Summary.Config.Name, vm.Summary.Config.GuestFullName)
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/find/doc.go b/vendor/github.com/vmware/govmomi/find/doc.go
new file mode 100644
index 00000000..0c8acee0
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/find/doc.go
@@ -0,0 +1,37 @@
+/*
+Copyright (c) 2014-2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+/*
+Package find implements inventory listing and searching.
+
+The Finder is an alternative to the object.SearchIndex FindByInventoryPath() and FindChild() methods.
+SearchIndex.FindByInventoryPath requires an absolute path, whereas the Finder also supports relative paths
+and patterns via path.Match.
+SearchIndex.FindChild requires a parent to find the child, whereas the Finder also supports an ancestor via
+recursive object traversal.
+
+The various Finder methods accept a "path" argument, which can absolute or relative to the Folder for the object type.
+The Finder supports two modes, "list" and "find". The "list" mode behaves like the "ls" command, only searching within
+the immediate path. The "find" mode behaves like the "find" command, with the search starting at the immediate path but
+also recursing into sub Folders relative to the Datacenter. The default mode is "list" if the given path contains a "/",
+otherwise "find" mode is used.
+
+The exception is to use a "..." wildcard with a path to find all objects recursively underneath any root object.
+For example: VirtualMachineList("/DC1/...")
+
+See also: https://github.com/vmware/govmomi/blob/master/govc/README.md#usage
+*/
+package find
diff --git a/vendor/github.com/vmware/govmomi/find/finder.go b/vendor/github.com/vmware/govmomi/find/finder.go
index 9f638a52..04d0e891 100644
--- a/vendor/github.com/vmware/govmomi/find/finder.go
+++ b/vendor/github.com/vmware/govmomi/find/finder.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
+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.
@@ -20,6 +20,7 @@ import (
"context"
"errors"
"path"
+ "strings"
"github.com/vmware/govmomi/list"
"github.com/vmware/govmomi/object"
@@ -30,17 +31,18 @@ import (
)
type Finder struct {
- client *vim25.Client
- recurser list.Recurser
-
+ client *vim25.Client
+ r recurser
dc *object.Datacenter
+ si *object.SearchIndex
folders *object.DatacenterFolders
}
func NewFinder(client *vim25.Client, all bool) *Finder {
f := &Finder{
client: client,
- recurser: list.Recurser{
+ si: object.NewSearchIndex(client),
+ r: recurser{
Collector: property.DefaultCollector(client),
All: all,
},
@@ -55,9 +57,41 @@ func (f *Finder) SetDatacenter(dc *object.Datacenter) *Finder {
return f
}
-type findRelativeFunc func(ctx context.Context) (object.Reference, error)
+// findRoot makes it possible to use "find" mode with a different root path.
+// Example: ResourcePoolList("/dc1/host/cluster1/...")
+func (f *Finder) findRoot(ctx context.Context, root *list.Element, parts []string) bool {
+ if len(parts) == 0 {
+ return false
+ }
+
+ ix := len(parts) - 1
+
+ if parts[ix] != "..." {
+ return false
+ }
+
+ if ix == 0 {
+ return true // We already have the Object for root.Path
+ }
+
+ // Lookup the Object for the new root.Path
+ rootPath := path.Join(root.Path, path.Join(parts[:ix]...))
+
+ ref, err := f.si.FindByInventoryPath(ctx, rootPath)
+ if err != nil || ref == nil {
+ // If we get an error or fail to match, fall through to find() with the original root and path
+ return false
+ }
+
+ root.Path = rootPath
+ root.Object = ref
+
+ return true
+}
+
+func (f *Finder) find(ctx context.Context, arg string, s *spec) ([]list.Element, error) {
+ isPath := strings.Contains(arg, "/")
-func (f *Finder) find(ctx context.Context, fn findRelativeFunc, tl bool, arg string) ([]list.Element, error) {
root := list.Element{
Path: "/",
Object: object.NewRootFolder(f.client),
@@ -70,7 +104,7 @@ func (f *Finder) find(ctx context.Context, fn findRelativeFunc, tl bool, arg str
case "..": // Not supported; many edge case, little value
return nil, errors.New("cannot traverse up a tree")
case ".": // Relative to whatever
- pivot, err := fn(ctx)
+ pivot, err := s.Relative(ctx)
if err != nil {
return nil, err
}
@@ -93,13 +127,17 @@ func (f *Finder) find(ctx context.Context, fn findRelativeFunc, tl bool, arg str
}
}
- f.recurser.TraverseLeafs = tl
- es, err := f.recurser.Recurse(ctx, root, parts)
- if err != nil {
- return nil, err
+ if s.listMode(isPath) {
+ if f.findRoot(ctx, &root, parts) {
+ parts = []string{"*"}
+ } else {
+ return f.r.List(ctx, s, root, parts)
+ }
}
- return es, nil
+ s.Parents = append(s.Parents, s.Nested...)
+
+ return f.r.Find(ctx, s, root, parts)
}
func (f *Finder) datacenter() (*object.Datacenter, error) {
@@ -208,7 +246,7 @@ func (f *Finder) rootFolder(_ context.Context) (object.Reference, error) {
return object.NewRootFolder(f.client), nil
}
-func (f *Finder) managedObjectList(ctx context.Context, path string, tl bool) ([]list.Element, error) {
+func (f *Finder) managedObjectList(ctx context.Context, path string, tl bool, include []string) ([]list.Element, error) {
fn := f.rootFolder
if f.dc != nil {
@@ -219,7 +257,18 @@ func (f *Finder) managedObjectList(ctx context.Context, path string, tl bool) ([
path = "."
}
- return f.find(ctx, fn, tl, path)
+ s := &spec{
+ Relative: fn,
+ Parents: []string{"ComputeResource", "ClusterComputeResource", "HostSystem", "VirtualApp", "StoragePod"},
+ Include: include,
+ }
+
+ if tl {
+ s.Contents = true
+ s.ListMode = types.NewBool(true)
+ }
+
+ return f.find(ctx, path, s)
}
// Element returns an Element for the given ManagedObjectReference
@@ -229,7 +278,11 @@ func (f *Finder) Element(ctx context.Context, ref types.ManagedObjectReference)
return ref, nil
}
- e, err := f.find(ctx, rl, false, ".")
+ s := &spec{
+ Relative: rl,
+ }
+
+ e, err := f.find(ctx, "./", s)
if err != nil {
return nil, err
}
@@ -270,16 +323,21 @@ func (f *Finder) ObjectReference(ctx context.Context, ref types.ManagedObjectRef
return r, nil
}
-func (f *Finder) ManagedObjectList(ctx context.Context, path string) ([]list.Element, error) {
- return f.managedObjectList(ctx, path, false)
+func (f *Finder) ManagedObjectList(ctx context.Context, path string, include ...string) ([]list.Element, error) {
+ return f.managedObjectList(ctx, path, false, include)
}
-func (f *Finder) ManagedObjectListChildren(ctx context.Context, path string) ([]list.Element, error) {
- return f.managedObjectList(ctx, path, true)
+func (f *Finder) ManagedObjectListChildren(ctx context.Context, path string, include ...string) ([]list.Element, error) {
+ return f.managedObjectList(ctx, path, true, include)
}
func (f *Finder) DatacenterList(ctx context.Context, path string) ([]*object.Datacenter, error) {
- es, err := f.find(ctx, f.rootFolder, false, path)
+ s := &spec{
+ Relative: f.rootFolder,
+ Include: []string{"Datacenter"},
+ }
+
+ es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
@@ -336,7 +394,12 @@ func (f *Finder) DatacenterOrDefault(ctx context.Context, path string) (*object.
}
func (f *Finder) DatastoreList(ctx context.Context, path string) ([]*object.Datastore, error) {
- es, err := f.find(ctx, f.datastoreFolder, false, path)
+ s := &spec{
+ Relative: f.datastoreFolder,
+ Parents: []string{"StoragePod"},
+ }
+
+ es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
@@ -404,7 +467,11 @@ func (f *Finder) DatastoreOrDefault(ctx context.Context, path string) (*object.D
}
func (f *Finder) DatastoreClusterList(ctx context.Context, path string) ([]*object.StoragePod, error) {
- es, err := f.find(ctx, f.datastoreFolder, false, path)
+ s := &spec{
+ Relative: f.datastoreFolder,
+ }
+
+ es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
@@ -461,7 +528,11 @@ func (f *Finder) DatastoreClusterOrDefault(ctx context.Context, path string) (*o
}
func (f *Finder) ComputeResourceList(ctx context.Context, path string) ([]*object.ComputeResource, error) {
- es, err := f.find(ctx, f.hostFolder, false, path)
+ s := &spec{
+ Relative: f.hostFolder,
+ }
+
+ es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
@@ -523,7 +594,11 @@ func (f *Finder) ComputeResourceOrDefault(ctx context.Context, path string) (*ob
}
func (f *Finder) ClusterComputeResourceList(ctx context.Context, path string) ([]*object.ClusterComputeResource, error) {
- es, err := f.find(ctx, f.hostFolder, false, path)
+ s := &spec{
+ Relative: f.hostFolder,
+ }
+
+ es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
@@ -564,7 +639,13 @@ func (f *Finder) ClusterComputeResource(ctx context.Context, path string) (*obje
}
func (f *Finder) HostSystemList(ctx context.Context, path string) ([]*object.HostSystem, error) {
- es, err := f.find(ctx, f.hostFolder, false, path)
+ s := &spec{
+ Relative: f.hostFolder,
+ Parents: []string{"ComputeResource", "ClusterComputeResource"},
+ Include: []string{"HostSystem"},
+ }
+
+ es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
@@ -635,7 +716,11 @@ func (f *Finder) HostSystemOrDefault(ctx context.Context, path string) (*object.
}
func (f *Finder) NetworkList(ctx context.Context, path string) ([]object.NetworkReference, error) {
- es, err := f.find(ctx, f.networkFolder, false, path)
+ s := &spec{
+ Relative: f.networkFolder,
+ }
+
+ es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
@@ -644,10 +729,14 @@ func (f *Finder) NetworkList(ctx context.Context, path string) ([]object.Network
for _, e := range es {
ref := e.Object.Reference()
switch ref.Type {
- case "Network", "OpaqueNetwork":
+ case "Network":
r := object.NewNetwork(f.client, ref)
r.InventoryPath = e.Path
ns = append(ns, r)
+ case "OpaqueNetwork":
+ r := object.NewOpaqueNetwork(f.client, ref)
+ r.InventoryPath = e.Path
+ ns = append(ns, r)
case "DistributedVirtualPortgroup":
r := object.NewDistributedVirtualPortgroup(f.client, ref)
r.InventoryPath = e.Path
@@ -701,7 +790,14 @@ func (f *Finder) NetworkOrDefault(ctx context.Context, path string) (object.Netw
}
func (f *Finder) ResourcePoolList(ctx context.Context, path string) ([]*object.ResourcePool, error) {
- es, err := f.find(ctx, f.hostFolder, true, path)
+ s := &spec{
+ Relative: f.hostFolder,
+ Parents: []string{"ComputeResource", "ClusterComputeResource", "VirtualApp"},
+ Nested: []string{"ResourcePool"},
+ Contents: true,
+ }
+
+ es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
@@ -804,7 +900,12 @@ func (f *Finder) FolderOrDefault(ctx context.Context, path string) (*object.Fold
}
func (f *Finder) VirtualMachineList(ctx context.Context, path string) ([]*object.VirtualMachine, error) {
- es, err := f.find(ctx, f.vmFolder, false, path)
+ s := &spec{
+ Relative: f.vmFolder,
+ Parents: []string{"VirtualApp"},
+ }
+
+ es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
@@ -840,7 +941,11 @@ func (f *Finder) VirtualMachine(ctx context.Context, path string) (*object.Virtu
}
func (f *Finder) VirtualAppList(ctx context.Context, path string) ([]*object.VirtualApp, error) {
- es, err := f.find(ctx, f.vmFolder, false, path)
+ s := &spec{
+ Relative: f.vmFolder,
+ }
+
+ es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/vmware/govmomi/find/recurser.go b/vendor/github.com/vmware/govmomi/find/recurser.go
new file mode 100644
index 00000000..80602956
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/find/recurser.go
@@ -0,0 +1,253 @@
+/*
+Copyright (c) 2014-2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package find
+
+import (
+ "context"
+ "os"
+ "path"
+ "strings"
+
+ "github.com/vmware/govmomi/list"
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/property"
+ "github.com/vmware/govmomi/vim25/mo"
+)
+
+// spec is used to specify per-search configuration, independent of the Finder instance.
+type spec struct {
+ // Relative returns the root object to resolve Relative paths (starts with ".")
+ Relative func(ctx context.Context) (object.Reference, error)
+
+ // ListMode can be used to optionally force "ls" behavior, rather than "find" behavior
+ ListMode *bool
+
+ // Contents configures the Recurser to list the Contents of traversable leaf nodes.
+ // This is typically set to true when used from the ls command, where listing
+ // a folder means listing its Contents. This is typically set to false for
+ // commands that take managed entities that are not folders as input.
+ Contents bool
+
+ // Parents specifies the types which can contain the child types being searched for.
+ // for example, when searching for a HostSystem, parent types can be
+ // "ComputeResource" or "ClusterComputeResource".
+ Parents []string
+
+ // Include specifies which types to be included in the results, used only in "find" mode.
+ Include []string
+
+ // Nested should be set to types that can be Nested, used only in "find" mode.
+ Nested []string
+
+ // ChildType avoids traversing into folders that can't contain the Include types, used only in "find" mode.
+ ChildType []string
+}
+
+func (s *spec) traversable(o mo.Reference) bool {
+ ref := o.Reference()
+
+ switch ref.Type {
+ case "Datacenter":
+ if len(s.Include) == 1 && s.Include[0] == "Datacenter" {
+ // No point in traversing deeper as Datacenters cannot be nested
+ return false
+ }
+ return true
+ case "Folder":
+ if f, ok := o.(mo.Folder); ok {
+ // TODO: Not making use of this yet, but here we can optimize when searching the entire
+ // inventory across Datacenters for specific types, for example: 'govc ls -t VirtualMachine /**'
+ // should not traverse into a Datacenter's host, network or datatore folders.
+ if !s.traversableChildType(f.ChildType) {
+ return false
+ }
+ }
+
+ return true
+ }
+
+ for _, kind := range s.Parents {
+ if kind == ref.Type {
+ return true
+ }
+ }
+
+ return false
+}
+
+func (s *spec) traversableChildType(ctypes []string) bool {
+ if len(s.ChildType) == 0 {
+ return true
+ }
+
+ for _, t := range ctypes {
+ for _, c := range s.ChildType {
+ if t == c {
+ return true
+ }
+ }
+ }
+
+ return false
+}
+
+func (s *spec) wanted(e list.Element) bool {
+ if len(s.Include) == 0 {
+ return true
+ }
+
+ w := e.Object.Reference().Type
+
+ for _, kind := range s.Include {
+ if w == kind {
+ return true
+ }
+ }
+
+ return false
+}
+
+// listMode is a global option to revert to the original Finder behavior,
+// disabling the newer "find" mode.
+var listMode = os.Getenv("GOVMOMI_FINDER_LIST_MODE") == "true"
+
+func (s *spec) listMode(isPath bool) bool {
+ if listMode {
+ return true
+ }
+
+ if s.ListMode != nil {
+ return *s.ListMode
+ }
+
+ return isPath
+}
+
+type recurser struct {
+ Collector *property.Collector
+
+ // All configures the recurses to fetch complete objects for leaf nodes.
+ All bool
+}
+
+func (r recurser) List(ctx context.Context, s *spec, root list.Element, parts []string) ([]list.Element, error) {
+ if len(parts) == 0 {
+ // Include non-traversable leaf elements in result. For example, consider
+ // the pattern "./vm/my-vm-*", where the pattern should match the VMs and
+ // not try to traverse them.
+ //
+ // Include traversable leaf elements in result, if the contents
+ // field is set to false.
+ //
+ if !s.Contents || !s.traversable(root.Object.Reference()) {
+ return []list.Element{root}, nil
+ }
+ }
+
+ k := list.Lister{
+ Collector: r.Collector,
+ Reference: root.Object.Reference(),
+ Prefix: root.Path,
+ }
+
+ if r.All && len(parts) < 2 {
+ k.All = true
+ }
+
+ in, err := k.List(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ // This folder is a leaf as far as the glob goes.
+ if len(parts) == 0 {
+ return in, nil
+ }
+
+ all := parts
+ pattern := parts[0]
+ parts = parts[1:]
+
+ var out []list.Element
+ for _, e := range in {
+ matched, err := path.Match(pattern, path.Base(e.Path))
+ if err != nil {
+ return nil, err
+ }
+
+ if !matched {
+ matched = strings.HasSuffix(e.Path, path.Join(all...))
+ if matched {
+ // name contains a '/'
+ out = append(out, e)
+ }
+
+ continue
+ }
+
+ nres, err := r.List(ctx, s, e, parts)
+ if err != nil {
+ return nil, err
+ }
+
+ out = append(out, nres...)
+ }
+
+ return out, nil
+}
+
+func (r recurser) Find(ctx context.Context, s *spec, root list.Element, parts []string) ([]list.Element, error) {
+ var out []list.Element
+
+ if len(parts) > 0 {
+ pattern := parts[0]
+ matched, err := path.Match(pattern, path.Base(root.Path))
+ if err != nil {
+ return nil, err
+ }
+
+ if matched && s.wanted(root) {
+ out = append(out, root)
+ }
+ }
+
+ if !s.traversable(root.Object) {
+ return out, nil
+ }
+
+ k := list.Lister{
+ Collector: r.Collector,
+ Reference: root.Object.Reference(),
+ Prefix: root.Path,
+ }
+
+ in, err := k.List(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ for _, e := range in {
+ nres, err := r.Find(ctx, s, e, parts)
+ if err != nil {
+ return nil, err
+ }
+
+ out = append(out, nres...)
+ }
+
+ return out, nil
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/datacenter/info.go b/vendor/github.com/vmware/govmomi/govc/datacenter/info.go
index 1850965a..e0fd0d0c 100644
--- a/vendor/github.com/vmware/govmomi/govc/datacenter/info.go
+++ b/vendor/github.com/vmware/govmomi/govc/datacenter/info.go
@@ -148,6 +148,7 @@ func (r *infoResult) Write(w io.Writer) error {
for _, o := range r.objects {
dc := objects[o.Reference()]
fmt.Fprintf(tw, "Name:\t%s\n", dc.Name)
+ fmt.Fprintf(tw, " Path:\t%s\n", o.InventoryPath)
folders, err := o.Folders(r.ctx)
if err != nil {
diff --git a/vendor/github.com/vmware/govmomi/govc/datastore/cp.go b/vendor/github.com/vmware/govmomi/govc/datastore/cp.go
index 44925c54..83c49553 100644
--- a/vendor/github.com/vmware/govmomi/govc/datastore/cp.go
+++ b/vendor/github.com/vmware/govmomi/govc/datastore/cp.go
@@ -61,6 +61,14 @@ func (cmd *cp) Usage() string {
return "SRC DST"
}
+func (cmd *cp) Description() string {
+ return `Copy SRC to DST on DATASTORE.
+
+Examples:
+ govc datastore.cp foo/foo.vmx foo/foo.vmx.old
+ govc datastore.cp -f my.vmx foo/foo.vmx`
+}
+
func (cmd *cp) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args()
if len(args) != 2 {
diff --git a/vendor/github.com/vmware/govmomi/govc/datastore/disk/create.go b/vendor/github.com/vmware/govmomi/govc/datastore/disk/create.go
new file mode 100644
index 00000000..c629c2a2
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/datastore/disk/create.go
@@ -0,0 +1,98 @@
+/*
+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 disk
+
+import (
+ "context"
+ "flag"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/govc/flags"
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/units"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type create struct {
+ *flags.DatastoreFlag
+
+ Bytes units.ByteSize
+}
+
+func init() {
+ cli.Register("datastore.disk.create", &create{})
+}
+
+func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
+ cmd.DatastoreFlag.Register(ctx, f)
+
+ _ = cmd.Bytes.Set("10G")
+ f.Var(&cmd.Bytes, "size", "Size of new disk")
+}
+
+func (cmd *create) Process(ctx context.Context) error {
+ if err := cmd.DatastoreFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cmd *create) Usage() string {
+ return "VMDK"
+}
+
+func (cmd *create) Description() string {
+ return `Create VMDK on DS.
+
+Examples:
+ govc datastore.mkdir disks
+ govc datastore.disk.create -size 24G disks/disk1.vmdk`
+}
+
+func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
+ if f.NArg() == 0 {
+ return flag.ErrHelp
+ }
+
+ dc, err := cmd.Datacenter()
+ if err != nil {
+ return err
+ }
+
+ ds, err := cmd.Datastore()
+ if err != nil {
+ return err
+ }
+
+ m := object.NewVirtualDiskManager(ds.Client())
+
+ spec := &types.FileBackedVirtualDiskSpec{
+ VirtualDiskSpec: types.VirtualDiskSpec{
+ AdapterType: string(types.VirtualDiskAdapterTypeLsiLogic),
+ DiskType: string(types.VirtualDiskTypeThin),
+ },
+ CapacityKb: int64(cmd.Bytes) / 1024,
+ }
+
+ task, err := m.CreateVirtualDisk(ctx, ds.Path(f.Arg(0)), dc, spec)
+ if err != nil {
+ return err
+ }
+
+ return task.Wait(ctx)
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/datastore/disk/info.go b/vendor/github.com/vmware/govmomi/govc/datastore/disk/info.go
new file mode 100644
index 00000000..338c5c82
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/datastore/disk/info.go
@@ -0,0 +1,145 @@
+/*
+Copyright (c) 2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package disk
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "io"
+ "strings"
+ "text/tabwriter"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/govc/flags"
+ "github.com/vmware/govmomi/object"
+)
+
+type info struct {
+ *flags.DatastoreFlag
+
+ c bool
+ d bool
+ p bool
+}
+
+func init() {
+ cli.Register("datastore.disk.info", &info{})
+}
+
+func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
+ cmd.DatastoreFlag.Register(ctx, f)
+
+ f.BoolVar(&cmd.c, "c", false, "Chain format")
+ f.BoolVar(&cmd.d, "d", false, "Include datastore in output")
+ f.BoolVar(&cmd.p, "p", true, "Include parents")
+}
+
+func (cmd *info) Process(ctx context.Context) error {
+ if err := cmd.DatastoreFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cmd *info) Usage() string {
+ return "VMDK"
+}
+
+func (cmd *info) Description() string {
+ return `Query VMDK info on DS.
+
+Examples:
+ govc datastore.disk.info disks/disk1.vmdk`
+}
+
+func fullPath(s string) string {
+ return s
+}
+
+func dsPath(s string) string {
+ var p object.DatastorePath
+
+ if p.FromString(s) {
+ return p.Path
+ }
+
+ return s
+}
+
+var infoPath = dsPath
+
+type infoResult []object.VirtualDiskInfo
+
+func (r infoResult) Write(w io.Writer) error {
+ tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
+
+ for _, info := range r {
+ fmt.Fprintf(tw, "Name:\t%s\n", infoPath(info.Name))
+ fmt.Fprintf(tw, " Type:\t%s\n", info.DiskType)
+ fmt.Fprintf(tw, " Parent:\t%s\n", infoPath(info.Parent))
+ }
+
+ return tw.Flush()
+}
+
+type chainResult []object.VirtualDiskInfo
+
+func (r chainResult) Write(w io.Writer) error {
+ for i, info := range r {
+ fmt.Fprint(w, strings.Repeat(" ", i*2))
+ fmt.Fprintln(w, infoPath(info.Name))
+ }
+
+ return nil
+}
+
+func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
+ if f.NArg() != 1 {
+ return flag.ErrHelp
+ }
+
+ dc, err := cmd.Datacenter()
+ if err != nil {
+ return err
+ }
+
+ ds, err := cmd.Datastore()
+ if err != nil {
+ return err
+ }
+
+ m := object.NewVirtualDiskManager(ds.Client())
+
+ info, err := m.QueryVirtualDiskInfo(ctx, ds.Path(f.Arg(0)), dc, cmd.p)
+ if err != nil {
+ return err
+ }
+
+ if cmd.d {
+ infoPath = fullPath
+ }
+
+ var r flags.OutputWriter = infoResult(info)
+
+ if cmd.c {
+ r = chainResult(info)
+ }
+
+ return cmd.WriteResult(r)
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/datastore/ls.go b/vendor/github.com/vmware/govmomi/govc/datastore/ls.go
index f0486c9c..6c33a27f 100644
--- a/vendor/github.com/vmware/govmomi/govc/datastore/ls.go
+++ b/vendor/github.com/vmware/govmomi/govc/datastore/ls.go
@@ -74,6 +74,17 @@ func (cmd *ls) Usage() string {
return "[FILE]..."
}
+func isInvalid(err error) bool {
+ if f, ok := err.(types.HasFault); ok {
+ switch f.Fault().(type) {
+ case *types.InvalidArgument:
+ return true
+ }
+ }
+
+ return false
+}
+
func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
ds, err := cmd.Datastore()
if err != nil {
@@ -113,7 +124,7 @@ func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
r, err := cmd.ListPath(b, arg, spec)
if err != nil {
// Treat the argument as a match pattern if not found as directory
- if i == 0 && types.IsFileNotFound(err) {
+ if i == 0 && types.IsFileNotFound(err) || isInvalid(err) {
spec.MatchPattern[0] = path.Base(arg)
arg = path.Dir(arg)
continue
@@ -187,7 +198,7 @@ func (o *listOutput) add(r types.HostDatastoreBrowserSearchResults) {
}
for _, p := range path {
- if p[0] == '.' {
+ if len(p) != 0 && p[0] == '.' {
return
}
}
diff --git a/vendor/github.com/vmware/govmomi/govc/datastore/mv.go b/vendor/github.com/vmware/govmomi/govc/datastore/mv.go
index 7c99550e..ee11c376 100644
--- a/vendor/github.com/vmware/govmomi/govc/datastore/mv.go
+++ b/vendor/github.com/vmware/govmomi/govc/datastore/mv.go
@@ -54,6 +54,14 @@ func (cmd *mv) Usage() string {
return "SRC DST"
}
+func (cmd *mv) Description() string {
+ return `Move SRC to DST on DATASTORE.
+
+Examples:
+ govc datastore.mv foo/foo.vmx foo/foo.vmx.old
+ govc datastore.mv -f my.vmx foo/foo.vmx`
+}
+
func (cmd *mv) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args()
if len(args) != 2 {
diff --git a/vendor/github.com/vmware/govmomi/govc/datastore/rm.go b/vendor/github.com/vmware/govmomi/govc/datastore/rm.go
index 58676ba5..9c292024 100644
--- a/vendor/github.com/vmware/govmomi/govc/datastore/rm.go
+++ b/vendor/github.com/vmware/govmomi/govc/datastore/rm.go
@@ -18,7 +18,6 @@ package datastore
import (
"context"
- "errors"
"flag"
"github.com/vmware/govmomi/govc/cli"
@@ -30,6 +29,7 @@ import (
type rm struct {
*flags.DatastoreFlag
+ kind bool
force bool
isNamespace bool
}
@@ -43,6 +43,7 @@ func (cmd *rm) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
+ f.BoolVar(&cmd.kind, "t", true, "Use file type to choose disk or file manager")
f.BoolVar(&cmd.force, "f", false, "Force; ignore nonexistent files and arguments")
f.BoolVar(&cmd.isNamespace, "namespace", false, "Path is uuid of namespace on vsan datastore")
}
@@ -58,10 +59,19 @@ func (cmd *rm) Usage() string {
return "FILE"
}
+func (cmd *rm) Description() string {
+ return `Remove FILE from DATASTORE.
+
+Examples:
+ govc datastore.rm vm/vmware.log
+ govc datastore.rm vm
+ govc datastore.rm -f images/base.vmdk`
+}
+
func (cmd *rm) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args()
if len(args) == 0 {
- return errors.New("missing operand")
+ return flag.ErrHelp
}
c, err := cmd.Client()
@@ -75,28 +85,25 @@ func (cmd *rm) Run(ctx context.Context, f *flag.FlagSet) error {
return err
}
+ ds, err := cmd.Datastore()
+ if err != nil {
+ return err
+ }
+
if cmd.isNamespace {
path := args[0]
nm := object.NewDatastoreNamespaceManager(c)
err = nm.DeleteDirectory(ctx, dc, path)
} else {
- var path string
- var task *object.Task
-
- // TODO(PN): Accept multiple args
- path, err = cmd.DatastorePath(args[0])
- if err != nil {
- return err
- }
+ fm := ds.NewFileManager(dc, cmd.force)
- m := object.NewFileManager(c)
- task, err = m.DeleteDatastoreFile(ctx, path, dc)
- if err != nil {
- return err
+ remove := fm.DeleteFile // File delete
+ if cmd.kind {
+ remove = fm.Delete // VirtualDisk or File delete
}
- err = task.Wait(ctx)
+ err = remove(ctx, args[0])
}
if err != nil {
diff --git a/vendor/github.com/vmware/govmomi/govc/datastore/vsan/ls.go b/vendor/github.com/vmware/govmomi/govc/datastore/vsan/ls.go
new file mode 100644
index 00000000..3b7b50f1
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/datastore/vsan/ls.go
@@ -0,0 +1,156 @@
+/*
+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 vsan
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "net/url"
+ "text/tabwriter"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/govc/flags"
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/vim25/mo"
+)
+
+type ls struct {
+ *flags.DatastoreFlag
+
+ long bool
+ orphan bool
+}
+
+func init() {
+ cli.Register("datastore.vsan.dom.ls", &ls{})
+}
+
+func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
+ cmd.DatastoreFlag.Register(ctx, f)
+
+ f.BoolVar(&cmd.long, "l", false, "Long listing")
+ f.BoolVar(&cmd.orphan, "o", false, "List orphan objects")
+}
+
+func (cmd *ls) Process(ctx context.Context) error {
+ if err := cmd.DatastoreFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cmd *ls) Usage() string {
+ return "[UUID]..."
+}
+
+func (cmd *ls) Description() string {
+ return `List vSAN DOM objects in DS.
+
+Examples:
+ govc datastore.vsan.dom.ls
+ govc datastore.vsan.dom.ls -ds vsanDatastore -l
+ govc datastore.vsan.dom.ls -l d85aa758-63f5-500a-3150-0200308e589c`
+}
+
+func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
+ ds, err := cmd.Datastore()
+ if err != nil {
+ return err
+ }
+
+ var mds mo.Datastore
+ err = ds.Properties(ctx, ds.Reference(), []string{"summary"}, &mds)
+ if err != nil {
+ return err
+ }
+
+ if mds.Summary.Type != "vsan" {
+ return flag.ErrHelp
+ }
+
+ hosts, err := ds.AttachedHosts(ctx)
+ if err != nil {
+ return err
+ }
+
+ if len(hosts) == 0 {
+ return flag.ErrHelp
+ }
+
+ m, err := hosts[0].ConfigManager().VsanInternalSystem(ctx)
+ if err != nil {
+ return err
+ }
+
+ ids, err := m.QueryVsanObjectUuidsByFilter(ctx, f.Args(), 0, 0)
+ if err != nil {
+ return err
+ }
+
+ if len(ids) == 0 {
+ return nil
+ }
+
+ if !cmd.long && !cmd.orphan {
+ for _, id := range ids {
+ fmt.Fprintln(cmd.Out, id)
+ }
+
+ return nil
+ }
+
+ objs, err := m.GetVsanObjExtAttrs(ctx, ids)
+ if err != nil {
+ return err
+ }
+
+ u, err := url.Parse(mds.Summary.Url)
+ if err != nil {
+ return err
+ }
+
+ tw := tabwriter.NewWriter(cmd.Out, 2, 0, 2, ' ', 0)
+ cmd.Out = tw
+
+ for id, obj := range objs {
+ path := obj.DatastorePath(u.Path)
+
+ if cmd.orphan {
+ _, err = ds.Stat(ctx, path)
+ if err == nil {
+ continue
+ }
+
+ switch err.(type) {
+ case object.DatastoreNoSuchDirectoryError, object.DatastoreNoSuchFileError:
+ default:
+ return err
+ }
+
+ if !cmd.long {
+ fmt.Fprintln(cmd.Out, id)
+ continue
+ }
+ }
+
+ fmt.Fprintf(cmd.Out, "%s\t%s\t%s\n", id, obj.Class, path)
+ }
+
+ return tw.Flush()
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/datastore/vsan/rm.go b/vendor/github.com/vmware/govmomi/govc/datastore/vsan/rm.go
new file mode 100644
index 00000000..23024716
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/datastore/vsan/rm.go
@@ -0,0 +1,108 @@
+/*
+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 vsan
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/govc/flags"
+)
+
+type rm struct {
+ *flags.DatastoreFlag
+
+ force bool
+ verbose bool
+}
+
+func init() {
+ cli.Register("datastore.vsan.dom.rm", &rm{})
+}
+
+func (cmd *rm) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
+ cmd.DatastoreFlag.Register(ctx, f)
+
+ f.BoolVar(&cmd.force, "f", false, "Force delete")
+ f.BoolVar(&cmd.verbose, "v", false, "Print deleted UUIDs to stdout, failed to stderr")
+}
+
+func (cmd *rm) Process(ctx context.Context) error {
+ if err := cmd.DatastoreFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cmd *rm) Usage() string {
+ return "UUID..."
+}
+
+func (cmd *rm) Description() string {
+ return `Remove vSAN DOM objects in DS.
+
+Examples:
+ govc datastore.vsan.dom.rm d85aa758-63f5-500a-3150-0200308e589c
+ govc datastore.vsan.dom.rm -f d85aa758-63f5-500a-3150-0200308e589c
+ govc datastore.vsan.dom.ls -o | xargs govc datastore.vsan.dom.rm`
+}
+
+func (cmd *rm) Run(ctx context.Context, f *flag.FlagSet) error {
+ if f.NArg() == 0 {
+ return flag.ErrHelp
+ }
+
+ ds, err := cmd.Datastore()
+ if err != nil {
+ return err
+ }
+
+ hosts, err := ds.AttachedHosts(ctx)
+ if err != nil {
+ return err
+ }
+
+ if len(hosts) == 0 {
+ return flag.ErrHelp
+ }
+
+ m, err := hosts[0].ConfigManager().VsanInternalSystem(ctx)
+ if err != nil {
+ return err
+ }
+
+ res, err := m.DeleteVsanObjects(ctx, f.Args(), &cmd.force)
+ if err != nil {
+ return err
+ }
+
+ if cmd.verbose {
+ for _, r := range res {
+ if r.Success {
+ fmt.Fprintln(cmd.Out, r.Uuid)
+ } else {
+ fmt.Fprintf(os.Stderr, "%s %s\n", r.Uuid, r.FailureReason[0].Message)
+ }
+ }
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/device/boot.go b/vendor/github.com/vmware/govmomi/govc/device/boot.go
index 970b0594..977b10c0 100644
--- a/vendor/github.com/vmware/govmomi/govc/device/boot.go
+++ b/vendor/github.com/vmware/govmomi/govc/device/boot.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
diff --git a/vendor/github.com/vmware/govmomi/govc/device/cdrom/add.go b/vendor/github.com/vmware/govmomi/govc/device/cdrom/add.go
index e42c6b1f..24089a48 100644
--- a/vendor/github.com/vmware/govmomi/govc/device/cdrom/add.go
+++ b/vendor/github.com/vmware/govmomi/govc/device/cdrom/add.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
diff --git a/vendor/github.com/vmware/govmomi/govc/device/cdrom/eject.go b/vendor/github.com/vmware/govmomi/govc/device/cdrom/eject.go
index 78cce90d..330ba3d8 100644
--- a/vendor/github.com/vmware/govmomi/govc/device/cdrom/eject.go
+++ b/vendor/github.com/vmware/govmomi/govc/device/cdrom/eject.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
diff --git a/vendor/github.com/vmware/govmomi/govc/device/cdrom/insert.go b/vendor/github.com/vmware/govmomi/govc/device/cdrom/insert.go
index 4ff8142c..fef8d996 100644
--- a/vendor/github.com/vmware/govmomi/govc/device/cdrom/insert.go
+++ b/vendor/github.com/vmware/govmomi/govc/device/cdrom/insert.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
diff --git a/vendor/github.com/vmware/govmomi/govc/device/connect.go b/vendor/github.com/vmware/govmomi/govc/device/connect.go
index bb6b0661..a0fc57aa 100644
--- a/vendor/github.com/vmware/govmomi/govc/device/connect.go
+++ b/vendor/github.com/vmware/govmomi/govc/device/connect.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -49,6 +49,13 @@ func (cmd *connect) Usage() string {
return "DEVICE..."
}
+func (cmd *connect) Description() string {
+ return `Connect DEVICE on VM.
+
+Examples:
+ govc device.connect -vm $name cdrom-3000`
+}
+
func (cmd *connect) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
diff --git a/vendor/github.com/vmware/govmomi/govc/device/disconnect.go b/vendor/github.com/vmware/govmomi/govc/device/disconnect.go
index 95a22ca7..503de17f 100644
--- a/vendor/github.com/vmware/govmomi/govc/device/disconnect.go
+++ b/vendor/github.com/vmware/govmomi/govc/device/disconnect.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -49,6 +49,13 @@ func (cmd *disconnect) Usage() string {
return "DEVICE..."
}
+func (cmd *disconnect) Description() string {
+ return `Disconnect DEVICE on VM.
+
+Examples:
+ govc device.disconnect -vm $name cdrom-3000`
+}
+
func (cmd *disconnect) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
diff --git a/vendor/github.com/vmware/govmomi/govc/device/floppy/add.go b/vendor/github.com/vmware/govmomi/govc/device/floppy/add.go
index 9c3716d0..bcb5512a 100644
--- a/vendor/github.com/vmware/govmomi/govc/device/floppy/add.go
+++ b/vendor/github.com/vmware/govmomi/govc/device/floppy/add.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
diff --git a/vendor/github.com/vmware/govmomi/govc/device/floppy/eject.go b/vendor/github.com/vmware/govmomi/govc/device/floppy/eject.go
index 5ef9b08b..37c1aae1 100644
--- a/vendor/github.com/vmware/govmomi/govc/device/floppy/eject.go
+++ b/vendor/github.com/vmware/govmomi/govc/device/floppy/eject.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
diff --git a/vendor/github.com/vmware/govmomi/govc/device/floppy/insert.go b/vendor/github.com/vmware/govmomi/govc/device/floppy/insert.go
index f61ea4ff..83f6f804 100644
--- a/vendor/github.com/vmware/govmomi/govc/device/floppy/insert.go
+++ b/vendor/github.com/vmware/govmomi/govc/device/floppy/insert.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
diff --git a/vendor/github.com/vmware/govmomi/govc/device/info.go b/vendor/github.com/vmware/govmomi/govc/device/info.go
index a2eae500..6c4a801f 100644
--- a/vendor/github.com/vmware/govmomi/govc/device/info.go
+++ b/vendor/github.com/vmware/govmomi/govc/device/info.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -18,11 +18,12 @@ package device
import (
"context"
+ "encoding/json"
"flag"
"fmt"
"io"
"os"
- "path/filepath"
+ "path"
"strings"
"text/tabwriter"
@@ -70,10 +71,19 @@ func (cmd *info) Usage() string {
return "[DEVICE]..."
}
+func (cmd *info) Description() string {
+ return `Device info for VM.
+
+Examples:
+ govc device.info -vm $name
+ govc device.info -vm $name disk-*
+ govc device.info -vm $name -json ethernet-0 | jq -r .Devices[].MacAddress`
+}
+
func (cmd *info) match(p string, devices object.VirtualDeviceList) object.VirtualDeviceList {
var matches object.VirtualDeviceList
match := func(name string) bool {
- matched, _ := filepath.Match(p, name)
+ matched, _ := path.Match(p, name)
return matched
}
@@ -125,7 +135,7 @@ func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
}
if f.NArg() == 0 {
- res.Devices = devices
+ res.Devices = toInfoList(devices)
} else {
for _, name := range f.Args() {
matches := cmd.match(name, devices)
@@ -133,15 +143,41 @@ func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
return fmt.Errorf("device '%s' not found", name)
}
- res.Devices = append(res.Devices, matches...)
+ res.Devices = append(res.Devices, toInfoList(matches)...)
}
}
return cmd.WriteResult(&res)
}
+func toInfoList(devices object.VirtualDeviceList) []infoDevice {
+ var res []infoDevice
+
+ for _, device := range devices {
+ res = append(res, infoDevice{devices.Name(device), device})
+ }
+
+ return res
+}
+
+type infoDevice struct {
+ Name string
+ types.BaseVirtualDevice
+}
+
+func (d *infoDevice) MarshalJSON() ([]byte, error) {
+ b, err := json.Marshal(d.BaseVirtualDevice)
+ if err != nil {
+ return b, err
+ }
+
+ // TODO: make use of "inline" tag if it comes to be: https://github.com/golang/go/issues/6213
+
+ return append([]byte(fmt.Sprintf(`{"Name":"%s",`, d.Name)), b[1:]...), err
+}
+
type infoResult struct {
- Devices object.VirtualDeviceList
+ Devices []infoDevice
// need the full list of devices to lookup attached devices and controllers
list object.VirtualDeviceList
}
@@ -149,12 +185,13 @@ type infoResult struct {
func (r *infoResult) Write(w io.Writer) error {
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
- for _, device := range r.Devices {
+ for i := range r.Devices {
+ device := r.Devices[i].BaseVirtualDevice
d := device.GetVirtualDevice()
info := d.DeviceInfo.GetDescription()
- fmt.Fprintf(tw, "Name:\t%s\n", r.Devices.Name(device))
- fmt.Fprintf(tw, " Type:\t%s\n", r.Devices.TypeName(device))
+ fmt.Fprintf(tw, "Name:\t%s\n", r.Devices[i].Name)
+ fmt.Fprintf(tw, " Type:\t%s\n", r.list.TypeName(device))
fmt.Fprintf(tw, " Label:\t%s\n", info.Label)
fmt.Fprintf(tw, " Summary:\t%s\n", info.Summary)
fmt.Fprintf(tw, " Key:\t%d\n", d.Key)
@@ -162,12 +199,12 @@ func (r *infoResult) Write(w io.Writer) error {
if c, ok := device.(types.BaseVirtualController); ok {
var attached []string
for _, key := range c.GetVirtualController().Device {
- attached = append(attached, r.Devices.Name(r.list.FindByKey(key)))
+ attached = append(attached, r.list.Name(r.list.FindByKey(key)))
}
fmt.Fprintf(tw, " Devices:\t%s\n", strings.Join(attached, ", "))
} else {
if c := r.list.FindByKey(d.ControllerKey); c != nil {
- fmt.Fprintf(tw, " Controller:\t%s\n", r.Devices.Name(c))
+ fmt.Fprintf(tw, " Controller:\t%s\n", r.list.Name(c))
if d.UnitNumber != nil {
fmt.Fprintf(tw, " Unit number:\t%d\n", *d.UnitNumber)
} else {
diff --git a/vendor/github.com/vmware/govmomi/govc/device/ls.go b/vendor/github.com/vmware/govmomi/govc/device/ls.go
index a71add23..1775ebd3 100644
--- a/vendor/github.com/vmware/govmomi/govc/device/ls.go
+++ b/vendor/github.com/vmware/govmomi/govc/device/ls.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -51,6 +51,13 @@ func (cmd *ls) Process(ctx context.Context) error {
return nil
}
+func (cmd *ls) Description() string {
+ return `List devices for VM.
+
+Examples:
+ govc device.ls -vm $name`
+}
+
func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
diff --git a/vendor/github.com/vmware/govmomi/govc/device/remove.go b/vendor/github.com/vmware/govmomi/govc/device/remove.go
index cb531b3e..fb776fc0 100644
--- a/vendor/github.com/vmware/govmomi/govc/device/remove.go
+++ b/vendor/github.com/vmware/govmomi/govc/device/remove.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -51,6 +51,14 @@ func (cmd *remove) Usage() string {
return "DEVICE..."
}
+func (cmd *remove) Description() string {
+ return `Remove DEVICE from VM.
+
+Examples:
+ govc device.remove -vm $name cdrom-3000
+ govc device.remove -vm $name -keep disk-1000`
+}
+
func (cmd *remove) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
diff --git a/vendor/github.com/vmware/govmomi/govc/device/scsi/add.go b/vendor/github.com/vmware/govmomi/govc/device/scsi/add.go
index 490d94c2..855fc5be 100644
--- a/vendor/github.com/vmware/govmomi/govc/device/scsi/add.go
+++ b/vendor/github.com/vmware/govmomi/govc/device/scsi/add.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
diff --git a/vendor/github.com/vmware/govmomi/govc/device/serial/add.go b/vendor/github.com/vmware/govmomi/govc/device/serial/add.go
index b8303388..d7206142 100644
--- a/vendor/github.com/vmware/govmomi/govc/device/serial/add.go
+++ b/vendor/github.com/vmware/govmomi/govc/device/serial/add.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
diff --git a/vendor/github.com/vmware/govmomi/govc/device/serial/disconnect.go b/vendor/github.com/vmware/govmomi/govc/device/serial/disconnect.go
index 6da1609b..5bc9c8d2 100644
--- a/vendor/github.com/vmware/govmomi/govc/device/serial/disconnect.go
+++ b/vendor/github.com/vmware/govmomi/govc/device/serial/disconnect.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
diff --git a/vendor/github.com/vmware/govmomi/govc/dvs/portgroup/info.go b/vendor/github.com/vmware/govmomi/govc/dvs/portgroup/info.go
index 8c3df625..9cc8adb6 100644
--- a/vendor/github.com/vmware/govmomi/govc/dvs/portgroup/info.go
+++ b/vendor/github.com/vmware/govmomi/govc/dvs/portgroup/info.go
@@ -66,6 +66,18 @@ func (cmd *info) Process(ctx context.Context) error {
return nil
}
+func (cmd *info) Usage() string {
+ return "DVS"
+}
+
+func (cmd *info) Description() string {
+ return `Portgroup info for DVS.
+
+Examples:
+ govc dvs.portgroup.info DSwitch
+ govc find / -type DistributedVirtualSwitch | xargs -n1 govc dvs.portgroup.info`
+}
+
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 1 {
return flag.ErrHelp
diff --git a/vendor/github.com/vmware/govmomi/govc/flags/datacenter.go b/vendor/github.com/vmware/govmomi/govc/flags/datacenter.go
index a776ed6e..8ae8787a 100644
--- a/vendor/github.com/vmware/govmomi/govc/flags/datacenter.go
+++ b/vendor/github.com/vmware/govmomi/govc/flags/datacenter.go
@@ -126,6 +126,13 @@ func (flag *DatacenterFlag) Datacenter() (*object.Datacenter, error) {
return flag.dc, err
}
+func (flag *DatacenterFlag) DatacenterIfSpecified() (*object.Datacenter, error) {
+ if flag.path == "" {
+ return nil, nil
+ }
+ return flag.Datacenter()
+}
+
func (flag *DatacenterFlag) ManagedObjects(ctx context.Context, args []string) ([]types.ManagedObjectReference, error) {
var refs []types.ManagedObjectReference
diff --git a/vendor/github.com/vmware/govmomi/govc/flags/int32.go b/vendor/github.com/vmware/govmomi/govc/flags/int32.go
index 5ab58aa0..503b4ec4 100644
--- a/vendor/github.com/vmware/govmomi/govc/flags/int32.go
+++ b/vendor/github.com/vmware/govmomi/govc/flags/int32.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2016 VMware, Inc. All Rights Reserved.
+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.
@@ -27,7 +27,7 @@ import (
type int32Value int32
func (i *int32Value) Set(s string) error {
- v, err := strconv.ParseInt(s, 0, 64)
+ v, err := strconv.ParseInt(s, 0, 32)
*i = int32Value(v)
return err
}
@@ -44,3 +44,29 @@ func (i *int32Value) String() string {
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 {
+ return -1
+ }
+ return *i.val
+}
+
+func (i *int32ptrValue) String() string {
+ return fmt.Sprintf("%v", i.Get())
+}
+
+func NewOptionalInt32(v **int32) flag.Value {
+ return &int32ptrValue{val: v}
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/flags/output.go b/vendor/github.com/vmware/govmomi/govc/flags/output.go
index 0ad0d95b..b02231d8 100644
--- a/vendor/github.com/vmware/govmomi/govc/flags/output.go
+++ b/vendor/github.com/vmware/govmomi/govc/flags/output.go
@@ -150,11 +150,14 @@ func (p *progressLogger) loopA() {
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:
@@ -165,7 +168,7 @@ func (p *progressLogger) loopA() {
if err != nil && err != io.EOF {
p.flag.Log(fmt.Sprintf("\r%sError: %s\n", p.prefix, err))
- } else {
+ } else if called {
p.flag.Log(fmt.Sprintf("\r%sOK\n", p.prefix))
}
}
diff --git a/vendor/github.com/vmware/govmomi/govc/flags/version.go b/vendor/github.com/vmware/govmomi/govc/flags/version.go
index 65b9f39a..59761365 100644
--- a/vendor/github.com/vmware/govmomi/govc/flags/version.go
+++ b/vendor/github.com/vmware/govmomi/govc/flags/version.go
@@ -21,7 +21,7 @@ import (
"strings"
)
-const Version = "0.12.1"
+const Version = "0.15.0"
type version []int
diff --git a/vendor/github.com/vmware/govmomi/govc/host/autostart/add.go b/vendor/github.com/vmware/govmomi/govc/host/autostart/add.go
index b453c7e1..4cabbd3d 100644
--- a/vendor/github.com/vmware/govmomi/govc/host/autostart/add.go
+++ b/vendor/github.com/vmware/govmomi/govc/host/autostart/add.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2015 VMware, Inc. All Rights Reserved.
+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.
@@ -19,22 +19,49 @@ package autostart
import (
"context"
"flag"
+ "fmt"
+ "strings"
"github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)
type add struct {
*AutostartFlag
+ // from types.AutoStartPowerInfo
+ StartOrder int32
+ StartDelay int32
+ WaitForHeartbeat string
+ StartAction string
+ StopDelay int32
+ StopAction string
}
func init() {
cli.Register("host.autostart.add", &add{})
}
+var waitHeartbeatTypes = []string{
+ string(types.AutoStartWaitHeartbeatSettingSystemDefault),
+ string(types.AutoStartWaitHeartbeatSettingYes),
+ string(types.AutoStartWaitHeartbeatSettingNo),
+}
+
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.AutostartFlag, ctx = newAutostartFlag(ctx)
cmd.AutostartFlag.Register(ctx, f)
+
+ cmd.StartOrder = -1
+ cmd.StartDelay = -1
+ cmd.StopDelay = -1
+ f.Var(flags.NewInt32(&cmd.StartOrder), "start-order", "Start Order")
+ f.Var(flags.NewInt32(&cmd.StartDelay), "start-delay", "Start Delay")
+ f.Var(flags.NewInt32(&cmd.StopDelay), "stop-delay", "Stop Delay")
+ f.StringVar(&cmd.StartAction, "start-action", "powerOn", "Start Action")
+ f.StringVar(&cmd.StopAction, "stop-action", "systemDefault", "Stop Action")
+ f.StringVar(&cmd.WaitForHeartbeat, "wait", waitHeartbeatTypes[0],
+ fmt.Sprintf("Wait for Hearbeat Setting (%s)", strings.Join(waitHeartbeatTypes, "|")))
}
func (cmd *add) Process(ctx context.Context) error {
@@ -49,14 +76,13 @@ func (cmd *add) Usage() string {
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
- var powerInfo = types.AutoStartPowerInfo{
- StartAction: "powerOn",
- StartDelay: -1,
- StartOrder: -1,
- StopAction: "systemDefault",
- StopDelay: -1,
- WaitForHeartbeat: types.AutoStartWaitHeartbeatSettingSystemDefault,
+ powerInfo := types.AutoStartPowerInfo{
+ StartOrder: cmd.StartOrder,
+ StartDelay: cmd.StartDelay,
+ WaitForHeartbeat: types.AutoStartWaitHeartbeatSetting(cmd.WaitForHeartbeat),
+ StartAction: cmd.StartAction,
+ StopDelay: cmd.StopDelay,
+ StopAction: cmd.StopAction,
}
-
return cmd.ReconfigureVMs(f.Args(), powerInfo)
}
diff --git a/vendor/github.com/vmware/govmomi/govc/host/info.go b/vendor/github.com/vmware/govmomi/govc/host/info.go
index ee05fcdf..ef482d4c 100644
--- a/vendor/github.com/vmware/govmomi/govc/host/info.go
+++ b/vendor/github.com/vmware/govmomi/govc/host/info.go
@@ -152,6 +152,11 @@ func (r *infoResult) Write(w io.Writer) error {
fmt.Fprintf(tw, " Memory:\t%dMB\n", h.MemorySize/(1024*1024))
fmt.Fprintf(tw, " Memory usage:\t%d MB (%.1f%%)\n", z.OverallMemoryUsage, memUsage)
fmt.Fprintf(tw, " Boot time:\t%s\n", s.Runtime.BootTime)
+ if s.Runtime.InMaintenanceMode {
+ fmt.Fprint(tw, " State: Maintenance Mode")
+ } else {
+ fmt.Fprintf(tw, " State:\t%s\n", s.Runtime.ConnectionState)
+ }
}
return tw.Flush()
diff --git a/vendor/github.com/vmware/govmomi/govc/host/maintenance/enter.go b/vendor/github.com/vmware/govmomi/govc/host/maintenance/enter.go
index 69758079..4b7fe9dc 100644
--- a/vendor/github.com/vmware/govmomi/govc/host/maintenance/enter.go
+++ b/vendor/github.com/vmware/govmomi/govc/host/maintenance/enter.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package maintenancec
+package maintenance
import (
"context"
diff --git a/vendor/github.com/vmware/govmomi/govc/host/maintenance/exit.go b/vendor/github.com/vmware/govmomi/govc/host/maintenance/exit.go
index 879a4e17..6259033e 100644
--- a/vendor/github.com/vmware/govmomi/govc/host/maintenance/exit.go
+++ b/vendor/github.com/vmware/govmomi/govc/host/maintenance/exit.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package maintenancec
+package maintenance
import (
"context"
diff --git a/vendor/github.com/vmware/govmomi/govc/host/option/ls.go b/vendor/github.com/vmware/govmomi/govc/host/option/ls.go
index 50f07648..9077492f 100644
--- a/vendor/github.com/vmware/govmomi/govc/host/option/ls.go
+++ b/vendor/github.com/vmware/govmomi/govc/host/option/ls.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2016 VMware, Inc. All Rights Reserved.
+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.
@@ -19,19 +19,14 @@ package option
import (
"context"
"flag"
- "fmt"
- "io"
- "os"
- "text/tabwriter"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
- "github.com/vmware/govmomi/vim25/types"
+ "github.com/vmware/govmomi/govc/option"
)
type ls struct {
- *flags.ClientFlag
- *flags.OutputFlag
+ *option.List
*flags.HostSystemFlag
}
@@ -40,21 +35,19 @@ func init() {
}
func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
- cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
- cmd.ClientFlag.Register(ctx, f)
+ cmd.List = &option.List{}
+ cmd.List.ClientFlag, ctx = flags.NewClientFlag(ctx)
+ cmd.List.ClientFlag.Register(ctx, f)
- cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
- cmd.OutputFlag.Register(ctx, f)
+ cmd.List.OutputFlag, ctx = flags.NewOutputFlag(ctx)
+ cmd.List.OutputFlag.Register(ctx, f)
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
}
func (cmd *ls) Process(ctx context.Context) error {
- if err := cmd.ClientFlag.Process(ctx); err != nil {
- return err
- }
- if err := cmd.OutputFlag.Process(ctx); err != nil {
+ if err := cmd.List.Process(ctx); err != nil {
return err
}
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
@@ -63,21 +56,16 @@ func (cmd *ls) Process(ctx context.Context) error {
return nil
}
-func (cmd *ls) Usage() string {
- return "NAME"
-}
-
func (cmd *ls) Description() string {
- return `List option with the given NAME.
+ return option.ListDescription + `
-If NAME ends with a dot, all options for that subtree are listed.`
+Examples:
+ govc host.option.ls
+ govc host.option.ls Config.HostAgent.
+ govc host.option.ls Config.HostAgent.plugins.solo.enableMob`
}
func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
- if f.NArg() != 1 {
- return flag.ErrHelp
- }
-
host, err := cmd.HostSystem()
if err != nil {
return err
@@ -88,21 +76,5 @@ func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
return err
}
- opts, err := m.Query(ctx, f.Arg(0))
- if err != nil {
- return err
- }
-
- return cmd.WriteResult(optionResult(opts))
-}
-
-type optionResult []types.BaseOptionValue
-
-func (r optionResult) Write(w io.Writer) error {
- tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
- for _, opt := range r {
- o := opt.GetOptionValue()
- fmt.Fprintf(tw, "%s:\t%v\n", o.Key, o.Value)
- }
- return tw.Flush()
+ return cmd.Query(ctx, f, m)
}
diff --git a/vendor/github.com/vmware/govmomi/govc/host/option/set.go b/vendor/github.com/vmware/govmomi/govc/host/option/set.go
index 5e4f24a5..a347718b 100644
--- a/vendor/github.com/vmware/govmomi/govc/host/option/set.go
+++ b/vendor/github.com/vmware/govmomi/govc/host/option/set.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2016 VMware, Inc. All Rights Reserved.
+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.
@@ -19,16 +19,14 @@ package option
import (
"context"
"flag"
- "fmt"
- "strconv"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
- "github.com/vmware/govmomi/vim25/types"
+ "github.com/vmware/govmomi/govc/option"
)
type set struct {
- *flags.ClientFlag
+ *option.Set
*flags.HostSystemFlag
}
@@ -37,15 +35,16 @@ func init() {
}
func (cmd *set) Register(ctx context.Context, f *flag.FlagSet) {
- cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
- cmd.ClientFlag.Register(ctx, f)
+ cmd.Set = &option.Set{}
+ cmd.Set.ClientFlag, ctx = flags.NewClientFlag(ctx)
+ cmd.Set.ClientFlag.Register(ctx, f)
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
}
func (cmd *set) Process(ctx context.Context) error {
- if err := cmd.ClientFlag.Process(ctx); err != nil {
+ if err := cmd.Set.Process(ctx); err != nil {
return err
}
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
@@ -54,12 +53,8 @@ func (cmd *set) Process(ctx context.Context) error {
return nil
}
-func (cmd *set) Usage() string {
- return "NAME VALUE"
-}
-
func (cmd *set) Description() string {
- return `Set host option NAME to VALUE.
+ return option.SetDescription + `
Examples:
govc host.option.set Config.HostAgent.plugins.solo.enableMob true
@@ -77,47 +72,5 @@ func (cmd *set) Run(ctx context.Context, f *flag.FlagSet) error {
return err
}
- if f.NArg() != 2 {
- return flag.ErrHelp
- }
-
- name := f.Arg(0)
- opts, err := m.Query(ctx, name)
- if err != nil {
- return err
- }
-
- if len(opts) != 1 {
- return flag.ErrHelp
- }
-
- val := f.Arg(1)
- var set types.AnyType
-
- switch x := opts[0].GetOptionValue().Value.(type) {
- case string:
- set = val
- case bool:
- set, err = strconv.ParseBool(val)
- if err != nil {
- return err
- }
- case int32:
- s, err := strconv.ParseInt(val, 10, 32)
- if err != nil {
- return err
- }
- set = s
- case int64:
- set, err = strconv.ParseInt(val, 10, 64)
- if err != nil {
- return err
- }
- default:
- return fmt.Errorf("type %T conversion not supported", x)
- }
-
- opts[0].GetOptionValue().Value = set
-
- return m.Update(ctx, opts)
+ return cmd.Update(ctx, f, m)
}
diff --git a/vendor/github.com/vmware/govmomi/govc/host/shutdown.go b/vendor/github.com/vmware/govmomi/govc/host/shutdown.go
new file mode 100644
index 00000000..97d1b01a
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/host/shutdown.go
@@ -0,0 +1,119 @@
+/*
+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 host
+
+import (
+ "context"
+ "flag"
+ "fmt"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/govc/flags"
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type shutdown struct {
+ *flags.HostSystemFlag
+ force bool
+ reboot bool
+}
+
+func init() {
+ cli.Register("host.shutdown", &shutdown{})
+}
+
+func (cmd *shutdown) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
+ cmd.HostSystemFlag.Register(ctx, f)
+
+ f.BoolVar(&cmd.force, "f", false, "Force shutdown when host is not in maintenance mode")
+ f.BoolVar(&cmd.reboot, "r", false, "Reboot host")
+}
+
+func (cmd *shutdown) Process(ctx context.Context) error {
+ if err := cmd.HostSystemFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cmd *shutdown) Description() string {
+ return `Shutdown HOST.`
+}
+
+func (cmd *shutdown) Shutdown(ctx context.Context, host *object.HostSystem) error {
+ req := types.ShutdownHost_Task{
+ This: host.Reference(),
+ Force: cmd.force,
+ }
+
+ res, err := methods.ShutdownHost_Task(ctx, host.Client(), &req)
+ if err != nil {
+ return err
+ }
+
+ task := object.NewTask(host.Client(), res.Returnval)
+
+ logger := cmd.ProgressLogger(fmt.Sprintf("%s shutdown... ", host.InventoryPath))
+ defer logger.Wait()
+
+ _, err = task.WaitForResult(ctx, logger)
+ return err
+}
+
+func (cmd *shutdown) Reboot(ctx context.Context, host *object.HostSystem) error {
+ req := types.RebootHost_Task{
+ This: host.Reference(),
+ Force: cmd.force,
+ }
+
+ res, err := methods.RebootHost_Task(ctx, host.Client(), &req)
+ if err != nil {
+ return err
+ }
+
+ task := object.NewTask(host.Client(), res.Returnval)
+
+ logger := cmd.ProgressLogger(fmt.Sprintf("%s reboot... ", host.InventoryPath))
+ defer logger.Wait()
+
+ _, err = task.WaitForResult(ctx, logger)
+ return err
+}
+
+func (cmd *shutdown) Run(ctx context.Context, f *flag.FlagSet) error {
+ hosts, err := cmd.HostSystems(f.Args())
+ if err != nil {
+ return err
+ }
+
+ s := cmd.Shutdown
+ if cmd.reboot {
+ s = cmd.Reboot
+ }
+
+ for _, host := range hosts {
+ err = s(ctx, host)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/host/vnic/service.go b/vendor/github.com/vmware/govmomi/govc/host/vnic/service.go
index c80071f4..f759ab7a 100644
--- a/vendor/github.com/vmware/govmomi/govc/host/vnic/service.go
+++ b/vendor/github.com/vmware/govmomi/govc/host/vnic/service.go
@@ -30,8 +30,7 @@ import (
type service struct {
*flags.HostSystemFlag
- Enable bool
- Disable bool
+ Enable bool
}
func init() {
@@ -42,18 +41,13 @@ func (cmd *service) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
- f.BoolVar(&cmd.Enable, "enable", false, "Enable service")
- f.BoolVar(&cmd.Disable, "disable", false, "Disable service")
+ f.BoolVar(&cmd.Enable, "enable", true, "Enable service")
}
func (cmd *service) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
- // Either may be true or none may be true.
- if cmd.Enable && cmd.Disable {
- return flag.ErrHelp
- }
return nil
}
@@ -81,7 +75,7 @@ Where DEVICE is one of: %s
Examples:
govc host.vnic.service -host hostname -enable vsan vmk0
-`,
+ govc host.vnic.service -host hostname -enable=false vmotion vmk1`,
strings.Join(nicTypes, "|"),
strings.Join([]string{"vmk0", "vmk1", "..."}, "|"))
}
@@ -108,7 +102,7 @@ func (cmd *service) Run(ctx context.Context, f *flag.FlagSet) error {
if cmd.Enable {
method = m.SelectVnic
- } else if cmd.Disable {
+ } else {
method = m.DeselectVnic
}
diff --git a/vendor/github.com/vmware/govmomi/govc/importx/archive.go b/vendor/github.com/vmware/govmomi/govc/importx/archive.go
index a77d542f..ff8499d0 100644
--- a/vendor/github.com/vmware/govmomi/govc/importx/archive.go
+++ b/vendor/github.com/vmware/govmomi/govc/importx/archive.go
@@ -59,7 +59,7 @@ func (f *ArchiveFlag) ReadOvf(fpath string) ([]byte, error) {
func (f *ArchiveFlag) ReadEnvelope(fpath string) (*ovf.Envelope, error) {
if fpath == "" {
- return nil, nil
+ return &ovf.Envelope{}, nil
}
r, _, err := f.Open(fpath)
@@ -110,7 +110,7 @@ func (t *TapeArchive) Open(name string) (io.ReadCloser, int64, error) {
return nil, 0, err
}
- matched, err := filepath.Match(name, path.Base(h.Name))
+ matched, err := path.Match(name, path.Base(h.Name))
if err != nil {
return nil, 0, err
}
diff --git a/vendor/github.com/vmware/govmomi/govc/importx/folder.go b/vendor/github.com/vmware/govmomi/govc/importx/folder.go
deleted file mode 100644
index 427c29b1..00000000
--- a/vendor/github.com/vmware/govmomi/govc/importx/folder.go
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
-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"
- "errors"
- "flag"
-
- "github.com/vmware/govmomi/govc/flags"
- "github.com/vmware/govmomi/object"
-)
-
-type FolderFlag struct {
- *flags.DatacenterFlag
-
- folder string
-}
-
-func newFolderFlag(ctx context.Context) (*FolderFlag, context.Context) {
- f := &FolderFlag{}
- f.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
- return f, ctx
-}
-
-func (flag *FolderFlag) Register(ctx context.Context, f *flag.FlagSet) {
- flag.DatacenterFlag.Register(ctx, f)
-
- f.StringVar(&flag.folder, "folder", "", "Path to folder to add the VM to")
-}
-
-func (flag *FolderFlag) Process(ctx context.Context) error {
- return flag.DatacenterFlag.Process(ctx)
-}
-
-func (flag *FolderFlag) Folder() (*object.Folder, error) {
- ctx := context.TODO()
- if len(flag.folder) == 0 {
- dc, err := flag.Datacenter()
- if err != nil {
- return nil, err
- }
- folders, err := dc.Folders(ctx)
- if err != nil {
- return nil, err
- }
- return folders.VmFolder, nil
- }
-
- finder, err := flag.Finder()
- if err != nil {
- return nil, err
- }
-
- mo, err := finder.ManagedObjectList(ctx, flag.folder)
- if err != nil {
- return nil, err
- }
- if len(mo) == 0 {
- return nil, errors.New("folder argument does not resolve to object")
- }
- if len(mo) > 1 {
- return nil, errors.New("folder argument resolves to more than one object")
- }
-
- ref := mo[0].Object.Reference()
- if ref.Type != "Folder" {
- return nil, errors.New("folder argument does not resolve to folder")
- }
-
- c, err := flag.Client()
- if err != nil {
- return nil, err
- }
-
- return object.NewFolder(c, ref), nil
-}
diff --git a/vendor/github.com/vmware/govmomi/govc/importx/ovf.go b/vendor/github.com/vmware/govmomi/govc/importx/ovf.go
index dd1b211a..debbc48a 100644
--- a/vendor/github.com/vmware/govmomi/govc/importx/ovf.go
+++ b/vendor/github.com/vmware/govmomi/govc/importx/ovf.go
@@ -25,10 +25,10 @@ import (
"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/progress"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
@@ -38,10 +38,10 @@ type ovfx struct {
*flags.HostSystemFlag
*flags.OutputFlag
*flags.ResourcePoolFlag
+ *flags.FolderFlag
*ArchiveFlag
*OptionsFlag
- *FolderFlag
Name string
@@ -64,13 +64,13 @@ func (cmd *ovfx) Register(ctx context.Context, f *flag.FlagSet) {
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)
- cmd.FolderFlag, ctx = newFolderFlag(ctx)
- cmd.FolderFlag.Register(ctx, f)
f.StringVar(&cmd.Name, "name", "", "Name to use for new entity")
}
@@ -248,7 +248,7 @@ func (cmd *ovfx) Import(fpath string) (*types.ManagedObjectReference, error) {
NetworkMapping: cmd.NetworkMap(e),
}
- m := object.NewOvfManager(cmd.Client)
+ m := ovf.NewManager(cmd.Client)
spec, err := m.CreateImportSpec(ctx, string(o), cmd.ResourcePool, cmd.Datastore, cisp)
if err != nil {
return nil, err
@@ -278,7 +278,7 @@ func (cmd *ovfx) Import(fpath string) (*types.ManagedObjectReference, error) {
}
}
- folder, err := cmd.Folder()
+ folder, err := cmd.FolderOrDefault("vm")
if err != nil {
return nil, err
}
@@ -288,51 +288,25 @@ func (cmd *ovfx) Import(fpath string) (*types.ManagedObjectReference, error) {
return nil, err
}
- info, err := lease.Wait(ctx)
+ info, err := lease.Wait(ctx, spec.FileItem)
if err != nil {
return nil, err
}
- // Build slice of items and URLs first, so that the lease updater can know
- // about every item that needs to be uploaded, and thereby infer progress.
- var items []ovfFileItem
-
- for _, device := range info.DeviceUrl {
- for _, item := range spec.FileItem {
- if device.ImportKey != item.DeviceId {
- continue
- }
-
- u, err := cmd.Client.ParseURL(device.Url)
- if err != nil {
- return nil, err
- }
-
- i := ovfFileItem{
- url: u,
- item: item,
- ch: make(chan progress.Report),
- }
-
- items = append(items, i)
- }
- }
-
- u := newLeaseUpdater(cmd.Client, lease, items)
+ u := lease.StartUpdater(ctx, info)
defer u.Done()
- for _, i := range items {
- err = cmd.Upload(lease, i)
+ for _, i := range info.Items {
+ err = cmd.Upload(ctx, lease, i)
if err != nil {
return nil, err
}
}
- return &info.Entity, lease.HttpNfcLeaseComplete(ctx)
+ return &info.Entity, lease.Complete(ctx)
}
-func (cmd *ovfx) Upload(lease *object.HttpNfcLease, ofi ovfFileItem) error {
- item := ofi.item
+func (cmd *ovfx) Upload(ctx context.Context, lease *nfc.Lease, item nfc.FileItem) error {
file := item.Path
f, size, err := cmd.Open(file)
@@ -346,22 +320,10 @@ func (cmd *ovfx) Upload(lease *object.HttpNfcLease, ofi ovfFileItem) error {
opts := soap.Upload{
ContentLength: size,
- Progress: progress.Tee(ofi, logger),
- }
-
- // Non-disk files (such as .iso) use the PUT method.
- // Overwrite: t header is also required in this case (ovftool does the same)
- if item.Create {
- opts.Method = "PUT"
- opts.Headers = map[string]string{
- "Overwrite": "t",
- }
- } else {
- opts.Method = "POST"
- opts.Type = "application/x-vnd.vmware-streamVmdk"
+ Progress: logger,
}
- return cmd.Client.Client.Upload(f, ofi.url, &opts)
+ return lease.Upload(ctx, item, f, opts)
}
func (cmd *ovfx) PowerOn(vm *object.VirtualMachine) error {
diff --git a/vendor/github.com/vmware/govmomi/govc/importx/spec.go b/vendor/github.com/vmware/govmomi/govc/importx/spec.go
index 4245403a..c490a28b 100644
--- a/vendor/github.com/vmware/govmomi/govc/importx/spec.go
+++ b/vendor/github.com/vmware/govmomi/govc/importx/spec.go
@@ -88,7 +88,7 @@ func (cmd *spec) Run(ctx context.Context, f *flag.FlagSet) error {
}
func (cmd *spec) Map(e *ovf.Envelope) (res []Property) {
- if e == nil {
+ if e == nil || e.VirtualSystem == nil {
return nil
}
@@ -128,7 +128,7 @@ func (cmd *spec) Spec(fpath string) error {
}
var deploymentOptions = allDeploymentOptions
- if e != nil && e.DeploymentOption != nil && e.DeploymentOption.Configuration != nil {
+ if e.DeploymentOption != nil && e.DeploymentOption.Configuration != nil {
deploymentOptions = nil
// add default first
@@ -155,7 +155,7 @@ func (cmd *spec) Spec(fpath string) error {
InjectOvfEnv: false,
PropertyMapping: cmd.Map(e)}
- if e.VirtualSystem.Annotation != nil {
+ if e.VirtualSystem != nil && e.VirtualSystem.Annotation != nil {
for _, a := range e.VirtualSystem.Annotation {
o.Annotation += a.Annotation
}
diff --git a/vendor/github.com/vmware/govmomi/govc/importx/vmdk.go b/vendor/github.com/vmware/govmomi/govc/importx/vmdk.go
index 270e37b0..6e0ac5f9 100644
--- a/vendor/github.com/vmware/govmomi/govc/importx/vmdk.go
+++ b/vendor/github.com/vmware/govmomi/govc/importx/vmdk.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
+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.
@@ -22,483 +22,111 @@ import (
"flag"
"fmt"
"path"
- "reflect"
- "regexp"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
- "github.com/vmware/govmomi/object"
- "github.com/vmware/govmomi/property"
- "github.com/vmware/govmomi/vim25"
- "github.com/vmware/govmomi/vim25/mo"
- "github.com/vmware/govmomi/vim25/progress"
- "github.com/vmware/govmomi/vim25/soap"
- "github.com/vmware/govmomi/vim25/types"
+ "github.com/vmware/govmomi/vmdk"
)
-type vmdk struct {
+type disk struct {
*flags.DatastoreFlag
*flags.ResourcePoolFlag
+ *flags.FolderFlag
*flags.OutputFlag
- upload bool
- force bool
- keep bool
-
- Client *vim25.Client
- Datacenter *object.Datacenter
- Datastore *object.Datastore
- ResourcePool *object.ResourcePool
+ force bool
}
func init() {
- cli.Register("import.vmdk", &vmdk{})
- cli.Alias("import.vmdk", "datastore.import")
+ cli.Register("import.vmdk", &disk{})
}
-func (cmd *vmdk) Register(ctx context.Context, f *flag.FlagSet) {
+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.upload, "upload", true, "Upload specified disk")
f.BoolVar(&cmd.force, "force", false, "Overwrite existing disk")
- f.BoolVar(&cmd.keep, "keep", false, "Keep uploaded disk after import")
}
-func (cmd *vmdk) Process(ctx context.Context) error {
+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 *vmdk) Usage() string {
+func (cmd *disk) Usage() string {
return "PATH_TO_VMDK [REMOTE_DIRECTORY]"
}
-func (cmd *vmdk) Run(ctx context.Context, f *flag.FlagSet) error {
- var err error
-
+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")
}
- file := importable{
- localPath: f.Arg(0),
- }
-
- // Include remote path if specified
- if len(args) >= 2 {
- file.remotePath = f.Arg(1)
- }
+ src := f.Arg(0)
- cmd.Client, err = cmd.DatastoreFlag.Client()
+ c, err := cmd.DatastoreFlag.Client()
if err != nil {
return err
}
- cmd.Datacenter, err = cmd.DatastoreFlag.Datacenter()
+ dc, err := cmd.DatastoreFlag.Datacenter()
if err != nil {
return err
}
- cmd.Datastore, err = cmd.DatastoreFlag.Datastore()
+ ds, err := cmd.DatastoreFlag.Datastore()
if err != nil {
return err
}
- cmd.ResourcePool, err = cmd.ResourcePoolFlag.ResourcePool()
+ pool, err := cmd.ResourcePoolFlag.ResourcePool()
if err != nil {
return err
}
- err = cmd.PrepareDestination(file)
+ folder, err := cmd.FolderOrDefault("vm")
if err != nil {
return err
}
- if cmd.upload {
- err = cmd.Upload(file)
- if err != nil {
- return err
- }
- }
-
- return cmd.Import(file)
-}
-
-// PrepareDestination makes sure that the destination VMDK does not yet exist.
-// If the force flag is passed, it removes the existing VMDK. This functions
-// exists to give a meaningful error if the remote VMDK already exists.
-//
-// CopyVirtualDisk can return a " file does not exist" error while in fact
-// the source file *does* exist and the *destination* file also exist.
-//
-func (cmd *vmdk) PrepareDestination(i importable) error {
- ctx := context.TODO()
- vmdkPath := i.RemoteDstVMDK()
- res, err := cmd.Datastore.Stat(ctx, vmdkPath)
- if err != nil {
- switch err.(type) {
- case object.DatastoreNoSuchDirectoryError:
- // The base path doesn't exist. Create it.
- dsPath := cmd.Datastore.Path(path.Dir(vmdkPath))
- m := object.NewFileManager(cmd.Client)
- return m.MakeDirectory(ctx, dsPath, cmd.Datacenter, true)
- case object.DatastoreNoSuchFileError:
- // Destination path doesn't exist; all good to continue with import.
- return nil
- }
-
- return err
- }
-
- // Check that the returned entry has the right type.
- switch res.(type) {
- case *types.VmDiskFileInfo:
- default:
- expected := "VmDiskFileInfo"
- actual := reflect.TypeOf(res)
- panic(fmt.Sprintf("Expected: %s, actual: %s", expected, actual))
- }
-
- if !cmd.force {
- dsPath := cmd.Datastore.Path(vmdkPath)
- err = fmt.Errorf("File %s already exists", dsPath)
- return err
- }
-
- // Delete existing disk.
- err = cmd.DeleteDisk(vmdkPath)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func (cmd *vmdk) Upload(i importable) error {
- ctx := context.TODO()
- p := soap.DefaultUpload
- if cmd.OutputFlag.TTY {
- logger := cmd.ProgressLogger("Uploading... ")
- p.Progress = logger
- defer logger.Wait()
- }
-
- return cmd.Datastore.UploadFile(ctx, i.localPath, i.RemoteSrcVMDK(), &p)
-}
-
-func (cmd *vmdk) Import(i importable) error {
- err := cmd.Copy(i)
- if err != nil {
- return err
- }
-
- if !cmd.keep {
- err = cmd.DeleteDisk(i.RemoteSrcVMDK())
- if err != nil {
- return err
- }
- }
-
- return nil
-}
-
-func (cmd *vmdk) Copy(i importable) error {
- var err error
-
- logger := cmd.ProgressLogger("Importing... ")
+ logger := cmd.ProgressLogger(fmt.Sprintf("Uploading %s... ", path.Base(src)))
defer logger.Wait()
- agg := progress.NewAggregator(logger)
- defer agg.Done()
-
- switch p := cmd.Client.ServiceContent.About.ApiType; p {
- case "HostAgent":
- err = cmd.CopyHostAgent(i, agg)
- case "VirtualCenter":
- err = cmd.CopyVirtualCenter(i, agg)
- default:
- return fmt.Errorf("unsupported ApiType: %s", p)
+ p := vmdk.ImportParams{
+ Path: f.Arg(1),
+ Logger: logger,
+ Type: "", // TODO: flag
+ Force: cmd.force,
+ Datacenter: dc,
+ Pool: pool,
+ Folder: folder,
}
- return err
-}
-
-func (cmd *vmdk) CopyHostAgent(i importable, s progress.Sinker) error {
- ctx := context.TODO()
- spec := &types.VirtualDiskSpec{
- AdapterType: "lsiLogic",
- DiskType: "thin",
- }
-
- dc := cmd.Datacenter
- src := cmd.Datastore.Path(i.RemoteSrcVMDK())
- dst := cmd.Datastore.Path(i.RemoteDstVMDK())
- vdm := object.NewVirtualDiskManager(cmd.Client)
- task, err := vdm.CopyVirtualDisk(ctx, src, dc, dst, dc, spec, false)
- if err != nil {
- return err
- }
-
- ps := progress.Prefix(s, "copying disk")
- _, err = task.WaitForResult(ctx, ps)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func (cmd *vmdk) CopyVirtualCenter(i importable, s progress.Sinker) error {
- var err error
-
- srcName := i.BaseClean() + "-srcvm"
- dstName := i.BaseClean() + "-dstvm"
-
- spec := &configSpec{
- Name: srcName,
- GuestId: "otherGuest",
- Files: &types.VirtualMachineFileInfo{
- VmPathName: fmt.Sprintf("[%s]", cmd.Datastore.Name()),
- },
- }
-
- spec.AddDisk(cmd.Datastore, i.RemoteSrcVMDK())
-
- src, err := cmd.CreateVM(spec)
- if err != nil {
- return err
- }
-
- dst, err := cmd.CloneVM(src, dstName)
- if err != nil {
- return err
- }
-
- err = cmd.DestroyVM(src)
- if err != nil {
- return err
- }
-
- vmdk, err := cmd.DetachDisk(dst)
- if err != nil {
- return err
+ 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)
}
- err = cmd.MoveDisk(vmdk, i.RemoteDstVMDK())
- if err != nil {
- return err
- }
-
- err = cmd.DestroyVM(dst)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func (cmd *vmdk) MoveDisk(src, dst string) error {
- ctx := context.TODO()
- dsSrc := cmd.Datastore.Path(src)
- dsDst := cmd.Datastore.Path(dst)
- vdm := object.NewVirtualDiskManager(cmd.Client)
- task, err := vdm.MoveVirtualDisk(ctx, dsSrc, cmd.Datacenter, dsDst, cmd.Datacenter, true)
- if err != nil {
- return err
- }
-
- return task.Wait(ctx)
-}
-
-func (cmd *vmdk) DeleteDisk(path string) error {
- ctx := context.TODO()
- vdm := object.NewVirtualDiskManager(cmd.Client)
- task, err := vdm.DeleteVirtualDisk(ctx, cmd.Datastore.Path(path), cmd.Datacenter)
- if err != nil {
- return err
- }
-
- return task.Wait(ctx)
-}
-
-func (cmd *vmdk) DetachDisk(vm *object.VirtualMachine) (string, error) {
- ctx := context.TODO()
- var mvm mo.VirtualMachine
-
- pc := property.DefaultCollector(cmd.Client)
- err := pc.RetrieveOne(ctx, vm.Reference(), []string{"config.hardware"}, &mvm)
- if err != nil {
- return "", err
- }
-
- spec := new(configSpec)
- dsFile := spec.RemoveDisk(&mvm)
-
- task, err := vm.Reconfigure(ctx, spec.ToSpec())
- if err != nil {
- return "", err
- }
-
- err = task.Wait(ctx)
- if err != nil {
- return "", err
- }
-
- return dsFile, nil
-}
-
-func (cmd *vmdk) CreateVM(spec *configSpec) (*object.VirtualMachine, error) {
- ctx := context.TODO()
- folders, err := cmd.Datacenter.Folders(ctx)
- if err != nil {
- return nil, err
- }
-
- task, err := folders.VmFolder.CreateVM(ctx, spec.ToSpec(), cmd.ResourcePool, nil)
- if err != nil {
- return nil, err
- }
-
- info, err := task.WaitForResult(ctx, nil)
- if err != nil {
- return nil, err
- }
-
- return object.NewVirtualMachine(cmd.Client, info.Result.(types.ManagedObjectReference)), nil
-}
-
-func (cmd *vmdk) CloneVM(vm *object.VirtualMachine, name string) (*object.VirtualMachine, error) {
- ctx := context.TODO()
- folders, err := cmd.Datacenter.Folders(ctx)
- if err != nil {
- return nil, err
- }
-
- spec := types.VirtualMachineCloneSpec{
- Config: &types.VirtualMachineConfigSpec{},
- Location: types.VirtualMachineRelocateSpec{},
- }
-
- task, err := vm.Clone(ctx, folders.VmFolder, name, spec)
- if err != nil {
- return nil, err
- }
-
- info, err := task.WaitForResult(ctx, nil)
- if err != nil {
- return nil, err
- }
-
- return object.NewVirtualMachine(cmd.Client, info.Result.(types.ManagedObjectReference)), nil
-}
-
-func (cmd *vmdk) DestroyVM(vm *object.VirtualMachine) error {
- ctx := context.TODO()
- _, err := cmd.DetachDisk(vm)
- if err != nil {
- return err
- }
-
- task, err := vm.Destroy(ctx)
- if err != nil {
- return err
- }
-
- err = task.Wait(ctx)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-type configSpec types.VirtualMachineConfigSpec
-
-func (c *configSpec) ToSpec() types.VirtualMachineConfigSpec {
- return types.VirtualMachineConfigSpec(*c)
-}
-
-func (c *configSpec) AddChange(d types.BaseVirtualDeviceConfigSpec) {
- c.DeviceChange = append(c.DeviceChange, d)
-}
-
-func (c *configSpec) AddDisk(ds *object.Datastore, path string) {
- var devices object.VirtualDeviceList
-
- controller, err := devices.CreateSCSIController("")
- if err != nil {
- panic(err)
- }
- devices = append(devices, controller)
-
- disk := devices.CreateDisk(controller.(types.BaseVirtualController), ds.Reference(), ds.Path(path))
- devices = append(devices, disk)
-
- spec, err := devices.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd)
- if err != nil {
- panic(err)
- }
-
- c.DeviceChange = append(c.DeviceChange, spec...)
-}
-
-var dsPathRegexp = regexp.MustCompile(`^\[.*\] (.*)$`)
-
-func (c *configSpec) RemoveDisk(vm *mo.VirtualMachine) string {
- var file string
-
- for _, d := range vm.Config.Hardware.Device {
- switch device := d.(type) {
- case *types.VirtualDisk:
- if file != "" {
- panic("expected VM to have only one disk")
- }
-
- switch backing := device.Backing.(type) {
- case *types.VirtualDiskFlatVer1BackingInfo:
- file = backing.FileName
- case *types.VirtualDiskFlatVer2BackingInfo:
- file = backing.FileName
- case *types.VirtualDiskSeSparseBackingInfo:
- file = backing.FileName
- case *types.VirtualDiskSparseVer1BackingInfo:
- file = backing.FileName
- case *types.VirtualDiskSparseVer2BackingInfo:
- file = backing.FileName
- default:
- name := reflect.TypeOf(device.Backing).String()
- panic(fmt.Sprintf("unexpected backing type: %s", name))
- }
-
- // Remove [datastore] prefix
- m := dsPathRegexp.FindStringSubmatch(file)
- if len(m) != 2 {
- panic(fmt.Sprintf("expected regexp match for %#v", file))
- }
- file = m[1]
-
- removeOp := &types.VirtualDeviceConfigSpec{
- Operation: types.VirtualDeviceConfigSpecOperationRemove,
- Device: device,
- }
-
- c.AddChange(removeOp)
- }
- }
-
- return file
+ return err
}
diff --git a/vendor/github.com/vmware/govmomi/govc/ls/command.go b/vendor/github.com/vmware/govmomi/govc/ls/command.go
index bbd20196..06a9b409 100644
--- a/vendor/github.com/vmware/govmomi/govc/ls/command.go
+++ b/vendor/github.com/vmware/govmomi/govc/ls/command.go
@@ -99,6 +99,12 @@ func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
var ref = new(types.ManagedObjectReference)
+ var types []string
+ if cmd.Type != "" {
+ // TODO: support multiple -t flags
+ types = []string{cmd.Type}
+ }
+
for _, arg := range args {
if cmd.DeRef && ref.FromString(arg) {
e, err := finder.Element(ctx, *ref)
@@ -115,7 +121,7 @@ func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
}
}
- es, err := finder.ManagedObjectListChildren(ctx, arg)
+ es, err := finder.ManagedObjectListChildren(ctx, arg, types...)
if err != nil {
return err
}
diff --git a/vendor/github.com/vmware/govmomi/govc/main.go b/vendor/github.com/vmware/govmomi/govc/main.go
index 474b5c4c..4931b5ed 100644
--- a/vendor/github.com/vmware/govmomi/govc/main.go
+++ b/vendor/github.com/vmware/govmomi/govc/main.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -25,6 +25,8 @@ import (
_ "github.com/vmware/govmomi/govc/cluster"
_ "github.com/vmware/govmomi/govc/datacenter"
_ "github.com/vmware/govmomi/govc/datastore"
+ _ "github.com/vmware/govmomi/govc/datastore/disk"
+ _ "github.com/vmware/govmomi/govc/datastore/vsan"
_ "github.com/vmware/govmomi/govc/device"
_ "github.com/vmware/govmomi/govc/device/cdrom"
_ "github.com/vmware/govmomi/govc/device/floppy"
@@ -56,11 +58,15 @@ import (
_ "github.com/vmware/govmomi/govc/license"
_ "github.com/vmware/govmomi/govc/logs"
_ "github.com/vmware/govmomi/govc/ls"
+ _ "github.com/vmware/govmomi/govc/metric"
+ _ "github.com/vmware/govmomi/govc/metric/interval"
_ "github.com/vmware/govmomi/govc/object"
+ _ "github.com/vmware/govmomi/govc/option"
_ "github.com/vmware/govmomi/govc/permissions"
_ "github.com/vmware/govmomi/govc/pool"
_ "github.com/vmware/govmomi/govc/role"
_ "github.com/vmware/govmomi/govc/session"
+ _ "github.com/vmware/govmomi/govc/task"
_ "github.com/vmware/govmomi/govc/vapp"
_ "github.com/vmware/govmomi/govc/version"
_ "github.com/vmware/govmomi/govc/vm"
diff --git a/vendor/github.com/vmware/govmomi/govc/metric/change.go b/vendor/github.com/vmware/govmomi/govc/metric/change.go
new file mode 100644
index 00000000..1a69ce3b
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/metric/change.go
@@ -0,0 +1,101 @@
+/*
+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 metric
+
+import (
+ "context"
+ "flag"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type change struct {
+ *PerformanceFlag
+
+ level int
+ device int
+}
+
+func init() {
+ cli.Register("metric.change", &change{})
+}
+
+func (cmd *change) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.PerformanceFlag, ctx = NewPerformanceFlag(ctx)
+ cmd.PerformanceFlag.Register(ctx, f)
+
+ f.IntVar(&cmd.level, "level", 0, "Level for the aggregate counter")
+ f.IntVar(&cmd.device, "device-level", 0, "Level for the per device counter")
+}
+
+func (cmd *change) Usage() string {
+ return "NAME..."
+}
+
+func (cmd *change) Description() string {
+ return `Change counter NAME levels.
+
+Examples:
+ govc metric.change -level 1 net.bytesRx.average net.bytesTx.average`
+}
+
+func (cmd *change) Process(ctx context.Context) error {
+ if err := cmd.PerformanceFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cmd *change) Run(ctx context.Context, f *flag.FlagSet) error {
+ if f.NArg() == 0 || (cmd.level == 0 && cmd.device == 0) {
+ return flag.ErrHelp
+ }
+
+ m, err := cmd.Manager(ctx)
+ if err != nil {
+ return err
+ }
+
+ counters, err := m.CounterInfoByName(ctx)
+ if err != nil {
+ return err
+ }
+
+ var mapping []types.PerformanceManagerCounterLevelMapping
+
+ for _, name := range f.Args() {
+ counter, ok := counters[name]
+ if !ok {
+ return cmd.ErrNotFound(name)
+ }
+
+ mapping = append(mapping, types.PerformanceManagerCounterLevelMapping{
+ CounterId: counter.Key,
+ AggregateLevel: int32(cmd.level),
+ PerDeviceLevel: int32(cmd.device),
+ })
+ }
+
+ _, err = methods.UpdateCounterLevelMapping(ctx, m.Client(), &types.UpdateCounterLevelMapping{
+ This: m.Reference(),
+ CounterLevelMap: mapping,
+ })
+
+ return err
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/metric/info.go b/vendor/github.com/vmware/govmomi/govc/metric/info.go
new file mode 100644
index 00000000..c30cbfc3
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/metric/info.go
@@ -0,0 +1,230 @@
+/*
+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 metric
+
+import (
+ "context"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "io"
+ "strings"
+ "text/tabwriter"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type info struct {
+ *PerformanceFlag
+}
+
+func init() {
+ cli.Register("metric.info", &info{})
+}
+
+func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.PerformanceFlag, ctx = NewPerformanceFlag(ctx)
+ cmd.PerformanceFlag.Register(ctx, f)
+}
+
+func (cmd *info) Usage() string {
+ return "PATH [NAME]..."
+}
+
+func (cmd *info) Description() string {
+ return `Metric info for NAME.
+
+If PATH is a value other than '-', provider summary and instance list are included
+for the given object type.
+
+If NAME is not specified, all available metrics for the given INTERVAL are listed.
+An object PATH must be provided in this case.
+
+Examples:
+ govc metric.info vm/my-vm
+ govc metric.info -i 300 vm/my-vm
+ govc metric.info - cpu.usage.average
+ govc metric.info /dc1/host/cluster cpu.usage.average`
+}
+
+func (cmd *info) Process(ctx context.Context) error {
+ if err := cmd.PerformanceFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+type EntityDetail struct {
+ Realtime bool
+ Historical bool
+ Instance []string
+}
+
+type MetricInfo struct {
+ Counter *types.PerfCounterInfo
+ Enabled []string
+ PerDeviceEnabled []string
+ Detail *EntityDetail
+}
+
+type infoResult struct {
+ cmd *info
+ Info []*MetricInfo
+}
+
+func (r *infoResult) Write(w io.Writer) error {
+ tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
+
+ for _, info := range r.Info {
+ counter := info.Counter
+
+ fmt.Fprintf(tw, "Name:\t%s\n", counter.Name())
+ fmt.Fprintf(tw, " Label:\t%s\n", counter.NameInfo.GetElementDescription().Label)
+ fmt.Fprintf(tw, " Summary:\t%s\n", counter.NameInfo.GetElementDescription().Summary)
+ fmt.Fprintf(tw, " Group:\t%s\n", counter.GroupInfo.GetElementDescription().Label)
+ fmt.Fprintf(tw, " Unit:\t%s\n", counter.UnitInfo.GetElementDescription().Label)
+ fmt.Fprintf(tw, " Rollup type:\t%s\n", counter.RollupType)
+ fmt.Fprintf(tw, " Stats type:\t%s\n", counter.StatsType)
+ fmt.Fprintf(tw, " Level:\t%d\n", counter.Level)
+ fmt.Fprintf(tw, " Intervals:\t%s\n", strings.Join(info.Enabled, ","))
+ fmt.Fprintf(tw, " Per-device level:\t%d\n", counter.PerDeviceLevel)
+ fmt.Fprintf(tw, " Intervals:\t%s\n", strings.Join(info.PerDeviceEnabled, ","))
+
+ summary := info.Detail
+ if summary == nil {
+ continue
+ }
+
+ fmt.Fprintf(tw, " Realtime:\t%t\n", summary.Realtime)
+ fmt.Fprintf(tw, " Historical:\t%t\n", summary.Historical)
+ fmt.Fprintf(tw, " Instances:\t%s\n", strings.Join(summary.Instance, ","))
+ }
+
+ return tw.Flush()
+}
+
+func (r *infoResult) MarshalJSON() ([]byte, error) {
+ m := make(map[string]*MetricInfo)
+
+ for _, info := range r.Info {
+ m[info.Counter.Name()] = info
+ }
+
+ return json.Marshal(m)
+}
+
+func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
+ if f.NArg() == 0 {
+ return flag.ErrHelp
+ }
+
+ names := f.Args()[1:]
+
+ m, err := cmd.Manager(ctx)
+ if err != nil {
+ return err
+ }
+
+ counters, err := m.CounterInfoByName(ctx)
+ if err != nil {
+ return err
+ }
+
+ intervals, err := m.HistoricalInterval(ctx)
+ if err != nil {
+ return err
+ }
+ enabled := intervals.Enabled()
+
+ var summary *types.PerfProviderSummary
+ var mids map[int32][]*types.PerfMetricId
+
+ if f.Arg(0) == "-" {
+ if len(names) == 0 {
+ return flag.ErrHelp
+ }
+ } else {
+ objs, err := cmd.ManagedObjects(ctx, f.Args()[:1])
+ if err != nil {
+ return err
+ }
+
+ summary, err = m.ProviderSummary(ctx, objs[0])
+ if err != nil {
+ return err
+ }
+
+ all, err := m.AvailableMetric(ctx, objs[0], cmd.Interval(summary.RefreshRate))
+ if err != nil {
+ return err
+ }
+
+ mids = all.ByKey()
+
+ if len(names) == 0 {
+ nc, _ := m.CounterInfoByKey(ctx)
+
+ for i := range all {
+ id := &all[i]
+ if id.Instance != "" {
+ continue
+ }
+
+ names = append(names, nc[id.CounterId].Name())
+ }
+ }
+ }
+
+ var metrics []*MetricInfo
+
+ for _, name := range names {
+ counter, ok := counters[name]
+ if !ok {
+ return cmd.ErrNotFound(name)
+ }
+
+ info := &MetricInfo{
+ Counter: counter,
+ Enabled: enabled[counter.Level],
+ PerDeviceEnabled: enabled[counter.PerDeviceLevel],
+ }
+
+ metrics = append(metrics, info)
+
+ if summary == nil {
+ continue
+ }
+
+ var instances []string
+
+ for _, id := range mids[counter.Key] {
+ if id.Instance != "" {
+ instances = append(instances, id.Instance)
+ }
+ }
+
+ info.Detail = &EntityDetail{
+ Realtime: summary.CurrentSupported,
+ Historical: summary.SummarySupported,
+ Instance: instances,
+ }
+
+ }
+
+ return cmd.WriteResult(&infoResult{cmd, metrics})
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/metric/interval/change.go b/vendor/github.com/vmware/govmomi/govc/metric/interval/change.go
new file mode 100644
index 00000000..ab034f9e
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/metric/interval/change.go
@@ -0,0 +1,111 @@
+/*
+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 interval
+
+import (
+ "context"
+ "flag"
+ "fmt"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/govc/flags"
+ "github.com/vmware/govmomi/govc/metric"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type change struct {
+ *metric.PerformanceFlag
+
+ enabled *bool
+ level int
+}
+
+func init() {
+ cli.Register("metric.interval.change", &change{})
+}
+
+func (cmd *change) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.PerformanceFlag, ctx = metric.NewPerformanceFlag(ctx)
+ cmd.PerformanceFlag.Register(ctx, f)
+
+ f.Var(flags.NewOptionalBool(&cmd.enabled), "enabled", "Enable or disable")
+ f.IntVar(&cmd.level, "level", 0, "Level")
+}
+
+func (cmd *change) Description() string {
+ return `Change historical metric intervals.
+
+Examples:
+ govc metric.interval.change -i 300 -level 2
+ govc metric.interval.change -i 86400 -enabled=false`
+}
+
+func (cmd *change) Process(ctx context.Context) error {
+ if err := cmd.PerformanceFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cmd *change) Run(ctx context.Context, f *flag.FlagSet) error {
+ m, err := cmd.Manager(ctx)
+ if err != nil {
+ return err
+ }
+
+ intervals, err := m.HistoricalInterval(ctx)
+ if err != nil {
+ return err
+ }
+
+ interval := cmd.Interval(0)
+ if interval == 0 {
+ return flag.ErrHelp
+ }
+
+ var current *types.PerfInterval
+
+ for _, i := range intervals {
+ if i.SamplingPeriod == interval {
+ current = &i
+ break
+ }
+ }
+
+ if current == nil {
+ return fmt.Errorf("%d interval ID not found", interval)
+ }
+
+ if cmd.level != 0 {
+ if cmd.level > 4 {
+ return flag.ErrHelp
+ }
+ current.Level = int32(cmd.level)
+ }
+
+ if cmd.enabled != nil {
+ current.Enabled = *cmd.enabled
+ }
+
+ _, err = methods.UpdatePerfInterval(ctx, m.Client(), &types.UpdatePerfInterval{
+ This: m.Reference(),
+ Interval: *current,
+ })
+
+ return err
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/metric/interval/info.go b/vendor/github.com/vmware/govmomi/govc/metric/interval/info.go
new file mode 100644
index 00000000..01f66b9e
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/metric/interval/info.go
@@ -0,0 +1,87 @@
+/*
+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 interval
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "text/tabwriter"
+ "time"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/govc/metric"
+)
+
+type info struct {
+ *metric.PerformanceFlag
+}
+
+func init() {
+ cli.Register("metric.interval.info", &info{})
+}
+
+func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.PerformanceFlag, ctx = metric.NewPerformanceFlag(ctx)
+ cmd.PerformanceFlag.Register(ctx, f)
+}
+
+func (cmd *info) Description() string {
+ return `List historical metric intervals.
+
+Examples:
+ govc metric.interval.info
+ govc metric.interval.info -i 300`
+}
+
+func (cmd *info) Process(ctx context.Context) error {
+ if err := cmd.PerformanceFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
+ m, err := cmd.Manager(ctx)
+ if err != nil {
+ return err
+ }
+
+ intervals, err := m.HistoricalInterval(ctx)
+ if err != nil {
+ return err
+ }
+
+ tw := tabwriter.NewWriter(cmd.Out, 2, 0, 2, ' ', 0)
+ cmd.Out = tw
+
+ interval := cmd.Interval(0)
+
+ for _, i := range intervals {
+ if interval != 0 && i.SamplingPeriod != interval {
+ continue
+ }
+
+ fmt.Fprintf(cmd.Out, "ID:\t%d\n", i.SamplingPeriod)
+ fmt.Fprintf(cmd.Out, " Enabled:\t%t\n", i.Enabled)
+ fmt.Fprintf(cmd.Out, " Interval:\t%s\n", time.Duration(i.SamplingPeriod)*time.Second)
+ fmt.Fprintf(cmd.Out, " Name:\t%s\n", i.Name)
+ fmt.Fprintf(cmd.Out, " Level:\t%d\n", i.Level)
+ }
+
+ return tw.Flush()
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/metric/ls.go b/vendor/github.com/vmware/govmomi/govc/metric/ls.go
new file mode 100644
index 00000000..69b30228
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/metric/ls.go
@@ -0,0 +1,140 @@
+/*
+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 metric
+
+import (
+ "context"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "io"
+ "text/tabwriter"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/performance"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type ls struct {
+ *PerformanceFlag
+
+ long bool
+}
+
+func init() {
+ cli.Register("metric.ls", &ls{})
+}
+
+func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.PerformanceFlag, ctx = NewPerformanceFlag(ctx)
+ cmd.PerformanceFlag.Register(ctx, f)
+
+ f.BoolVar(&cmd.long, "l", false, "Long listing format")
+}
+
+func (cmd *ls) Usage() string {
+ return "PATH"
+}
+
+func (cmd *ls) Description() string {
+ return `List available metrics for PATH.
+
+Examples:
+ govc metric.ls /dc1/host/cluster1
+ govc metric.ls datastore/*
+ govc metric.ls vm/* | grep mem. | xargs govc metric.sample vm/*`
+}
+
+func (cmd *ls) Process(ctx context.Context) error {
+ if err := cmd.PerformanceFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+type lsResult struct {
+ cmd *ls
+ counters map[int32]*types.PerfCounterInfo
+ performance.MetricList
+}
+
+func (r *lsResult) Write(w io.Writer) error {
+ tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
+
+ for _, id := range r.MetricList {
+ if id.Instance != "" {
+ continue
+ }
+
+ info := r.counters[id.CounterId]
+
+ if r.cmd.long {
+ fmt.Fprintf(w, "%s\t%s\n", info.Name(),
+ info.NameInfo.GetElementDescription().Label)
+ continue
+ }
+
+ fmt.Fprintln(w, info.Name())
+ }
+
+ return tw.Flush()
+}
+
+func (r *lsResult) MarshalJSON() ([]byte, error) {
+ m := make(map[string]*types.PerfCounterInfo)
+
+ for _, id := range r.MetricList {
+ info := r.counters[id.CounterId]
+
+ m[info.Name()] = info
+ }
+
+ return json.Marshal(m)
+}
+
+func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
+ if f.NArg() != 1 {
+ return flag.ErrHelp
+ }
+
+ objs, err := cmd.ManagedObjects(ctx, f.Args())
+ if err != nil {
+ return err
+ }
+
+ m, err := cmd.Manager(ctx)
+ if err != nil {
+ return err
+ }
+
+ s, err := m.ProviderSummary(ctx, objs[0])
+ if err != nil {
+ return err
+ }
+
+ mids, err := m.AvailableMetric(ctx, objs[0], cmd.Interval(s.RefreshRate))
+ if err != nil {
+ return err
+ }
+
+ counters, err := m.CounterInfoByKey(ctx)
+ if err != nil {
+ return err
+ }
+
+ return cmd.WriteResult(&lsResult{cmd, counters, mids})
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/metric/performance.go b/vendor/github.com/vmware/govmomi/govc/metric/performance.go
new file mode 100644
index 00000000..893aeaa9
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/metric/performance.go
@@ -0,0 +1,96 @@
+/*
+Copyright (c) 2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package metric
+
+import (
+ "context"
+ "flag"
+ "fmt"
+
+ "github.com/vmware/govmomi/govc/flags"
+ "github.com/vmware/govmomi/performance"
+)
+
+type PerformanceFlag struct {
+ *flags.DatacenterFlag
+ *flags.OutputFlag
+
+ m *performance.Manager
+
+ interval int
+}
+
+func NewPerformanceFlag(ctx context.Context) (*PerformanceFlag, context.Context) {
+ f := &PerformanceFlag{}
+ f.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
+ f.OutputFlag, ctx = flags.NewOutputFlag(ctx)
+ return f, ctx
+}
+
+func (f *PerformanceFlag) Register(ctx context.Context, fs *flag.FlagSet) {
+ f.DatacenterFlag.Register(ctx, fs)
+ f.OutputFlag.Register(ctx, fs)
+
+ fs.IntVar(&f.interval, "i", 0, "Interval ID")
+}
+
+func (f *PerformanceFlag) Process(ctx context.Context) error {
+ if err := f.DatacenterFlag.Process(ctx); err != nil {
+ return err
+ }
+ if err := f.OutputFlag.Process(ctx); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (f *PerformanceFlag) Manager(ctx context.Context) (*performance.Manager, error) {
+ if f.m != nil {
+ return f.m, nil
+ }
+
+ c, err := f.Client()
+ if err != nil {
+ return nil, err
+ }
+
+ f.m = performance.NewManager(c)
+
+ f.m.Sort = true
+
+ return f.m, err
+}
+
+func (f *PerformanceFlag) Interval(val int32) int32 {
+ interval := int32(f.interval)
+
+ if interval == 0 {
+ if val == -1 {
+ // realtime not supported
+ return 300
+ }
+
+ return val
+ }
+
+ return interval
+}
+
+func (f *PerformanceFlag) ErrNotFound(name string) error {
+ return fmt.Errorf("counter %q not found", name)
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/metric/reset.go b/vendor/github.com/vmware/govmomi/govc/metric/reset.go
new file mode 100644
index 00000000..a73a220a
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/metric/reset.go
@@ -0,0 +1,91 @@
+/*
+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 metric
+
+import (
+ "context"
+ "flag"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type reset struct {
+ *PerformanceFlag
+}
+
+func init() {
+ cli.Register("metric.reset", &reset{})
+}
+
+func (cmd *reset) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.PerformanceFlag, ctx = NewPerformanceFlag(ctx)
+ cmd.PerformanceFlag.Register(ctx, f)
+}
+
+func (cmd *reset) Usage() string {
+ return "NAME..."
+}
+
+func (cmd *reset) Description() string {
+ return `Reset counter NAME to the default level of data collection.
+
+Examples:
+ govc metric.reset net.bytesRx.average net.bytesTx.average`
+}
+
+func (cmd *reset) Process(ctx context.Context) error {
+ if err := cmd.PerformanceFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cmd *reset) Run(ctx context.Context, f *flag.FlagSet) error {
+ if f.NArg() == 0 {
+ return flag.ErrHelp
+ }
+
+ m, err := cmd.Manager(ctx)
+ if err != nil {
+ return err
+ }
+
+ counters, err := m.CounterInfoByName(ctx)
+ if err != nil {
+ return err
+ }
+
+ var ids []int32
+
+ for _, name := range f.Args() {
+ counter, ok := counters[name]
+ if !ok {
+ return cmd.ErrNotFound(name)
+ }
+
+ ids = append(ids, counter.Key)
+ }
+
+ _, err = methods.ResetCounterLevelMapping(ctx, m.Client(), &types.ResetCounterLevelMapping{
+ This: m.Reference(),
+ Counters: ids,
+ })
+
+ return err
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/metric/sample.go b/vendor/github.com/vmware/govmomi/govc/metric/sample.go
new file mode 100644
index 00000000..a85ca20f
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/metric/sample.go
@@ -0,0 +1,330 @@
+/*
+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 metric
+
+import (
+ "context"
+ "crypto/md5"
+ "flag"
+ "fmt"
+ "io"
+ "os"
+ "os/exec"
+ "path"
+ "strings"
+ "text/tabwriter"
+ "time"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/performance"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type sample struct {
+ *PerformanceFlag
+
+ d int
+ n int
+ t bool
+ plot string
+ instance string
+}
+
+func init() {
+ cli.Register("metric.sample", &sample{})
+}
+
+func (cmd *sample) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.PerformanceFlag, ctx = NewPerformanceFlag(ctx)
+ cmd.PerformanceFlag.Register(ctx, f)
+
+ f.IntVar(&cmd.d, "d", 30, "Limit object display name to D chars")
+ f.IntVar(&cmd.n, "n", 6, "Max number of samples")
+ f.StringVar(&cmd.plot, "plot", "", "Plot data using gnuplot")
+ f.BoolVar(&cmd.t, "t", false, "Include sample times")
+ f.StringVar(&cmd.instance, "instance", "*", "Instance")
+}
+
+func (cmd *sample) Usage() string {
+ return "PATH... NAME..."
+}
+
+func (cmd *sample) Description() string {
+ return `Sample for object PATH of metric NAME.
+
+Interval ID defaults to 20 (realtime) if supported, otherwise 300 (5m interval).
+
+By default, INSTANCE '*' samples all instances and the aggregate counter.
+An INSTANCE value of '-' will only sample the aggregate counter.
+An INSTANCE value other than '*' or '-' will only sample the given instance counter.
+
+If PLOT value is set to '-', output a gnuplot script. If non-empty with another
+value, PLOT will pipe the script to gnuplot for you. The value is also used to set
+the gnuplot 'terminal' variable, unless the value is that of the DISPLAY env var.
+Only 1 metric NAME can be specified when the PLOT flag is set.
+
+Examples:
+ govc metric.sample host/cluster1/* cpu.usage.average
+ govc metric.sample -plot .png host/cluster1/* cpu.usage.average | xargs open
+ govc metric.sample vm/* net.bytesTx.average net.bytesTx.average
+ govc metric.sample -instance vmnic0 vm/* net.bytesTx.average
+ govc metric.sample -instance - vm/* net.bytesTx.average`
+}
+
+func (cmd *sample) Process(ctx context.Context) error {
+ if err := cmd.PerformanceFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+type sampleResult struct {
+ cmd *sample
+ m *performance.Manager
+ counters map[string]*types.PerfCounterInfo
+ Sample []performance.EntityMetric
+}
+
+func (r *sampleResult) name(e types.ManagedObjectReference) string {
+ var me mo.ManagedEntity
+ _ = r.m.Properties(context.Background(), e, []string{"name"}, &me)
+
+ name := me.Name
+
+ if r.cmd.d > 0 && len(name) > r.cmd.d {
+ return name[:r.cmd.d] + "*"
+ }
+
+ return name
+}
+
+func sampleInfoTimes(m *performance.EntityMetric) []string {
+ vals := make([]string, len(m.SampleInfo))
+
+ for i := range m.SampleInfo {
+ vals[i] = m.SampleInfo[i].Timestamp.Format(time.RFC3339)
+ }
+
+ return vals
+}
+
+func (r *sampleResult) Plot(w io.Writer) error {
+ if len(r.Sample) == 0 {
+ return nil
+ }
+
+ if r.cmd.plot != "-" {
+ cmd := exec.Command("gnuplot", "-persist")
+ cmd.Stdout = w
+ cmd.Stderr = os.Stderr
+ stdin, err := cmd.StdinPipe()
+ if err != nil {
+ return err
+ }
+
+ if err = cmd.Start(); err != nil {
+ return err
+ }
+
+ w = stdin
+ defer func() {
+ _ = stdin.Close()
+ _ = cmd.Wait()
+ }()
+ }
+
+ counter := r.counters[r.Sample[0].Value[0].Name]
+ unit := counter.UnitInfo.GetElementDescription()
+
+ fmt.Fprintf(w, "set title %q\n", counter.Name())
+ fmt.Fprintf(w, "set ylabel %q\n", unit.Label)
+ fmt.Fprintf(w, "set xlabel %q\n", "Time")
+ fmt.Fprintf(w, "set xdata %s\n", "time")
+ fmt.Fprintf(w, "set format x %q\n", "%H:%M")
+ fmt.Fprintf(w, "set timefmt %q\n", "%Y-%m-%dT%H:%M:%SZ")
+
+ ext := path.Ext(r.cmd.plot)
+ if ext != "" {
+ // If a file name is given, use the extension as terminal type.
+ // If just an ext is given, use the entities and counter as the file name.
+ file := r.cmd.plot
+ name := r.cmd.plot[:len(r.cmd.plot)-len(ext)]
+ r.cmd.plot = ext[1:]
+
+ if name == "" {
+ h := md5.New()
+
+ for i := range r.Sample {
+ _, _ = io.WriteString(h, r.Sample[i].Entity.String())
+ }
+ _, _ = io.WriteString(h, counter.Name())
+
+ file = fmt.Sprintf("govc-plot-%x%s", h.Sum(nil), ext)
+ }
+
+ fmt.Fprintf(w, "set output %q\n", file)
+
+ defer func() {
+ fmt.Fprintln(r.cmd.Out, file)
+ }()
+ }
+
+ switch r.cmd.plot {
+ case "-", os.Getenv("DISPLAY"):
+ default:
+ fmt.Fprintf(w, "set terminal %s\n", r.cmd.plot)
+ }
+
+ if unit.Key == string(types.PerformanceManagerUnitPercent) {
+ fmt.Fprintln(w, "set yrange [0:100]")
+ }
+
+ fmt.Fprintln(w)
+
+ var set []string
+
+ for i := range r.Sample {
+ name := r.name(r.Sample[i].Entity)
+ name = strings.Replace(name, "_", "*", -1) // underscore is some gnuplot markup?
+ set = append(set, fmt.Sprintf("'-' using 1:2 title '%s' with lines", name))
+ }
+
+ fmt.Fprintf(w, "plot %s\n", strings.Join(set, ", "))
+
+ for i := range r.Sample {
+ times := sampleInfoTimes(&r.Sample[i])
+
+ for _, value := range r.Sample[i].Value {
+ for j := range value.Value {
+ fmt.Fprintf(w, "%s %s\n", times[j], value.Format(value.Value[j]))
+ }
+ }
+
+ fmt.Fprintln(w, "e")
+ }
+
+ return nil
+}
+
+func (r *sampleResult) Write(w io.Writer) error {
+ if r.cmd.plot != "" {
+ return r.Plot(w)
+ }
+
+ cmd := r.cmd
+ tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
+
+ for i := range r.Sample {
+ metric := r.Sample[i]
+ name := r.name(metric.Entity)
+ t := ""
+ if cmd.t {
+ t = metric.SampleInfoCSV()
+ }
+
+ for _, v := range metric.Value {
+ counter := r.counters[v.Name]
+ units := counter.UnitInfo.GetElementDescription().Label
+
+ instance := v.Instance
+ if instance == "" {
+ instance = "-"
+ }
+
+ fmt.Fprintf(tw, "%s\t%s\t%s\t%v\t%s\t%s\n",
+ name, instance, v.Name, t, v.ValueCSV(), units)
+ }
+ }
+
+ return tw.Flush()
+}
+
+func (cmd *sample) Run(ctx context.Context, f *flag.FlagSet) error {
+ m, err := cmd.Manager(ctx)
+ if err != nil {
+ return err
+ }
+
+ var paths []string
+ var names []string
+
+ byName, err := m.CounterInfoByName(ctx)
+ if err != nil {
+ return err
+ }
+
+ for _, arg := range f.Args() {
+ if _, ok := byName[arg]; ok {
+ names = append(names, arg)
+ } else {
+ paths = append(paths, arg)
+ }
+ }
+
+ if len(paths) == 0 || len(names) == 0 {
+ return flag.ErrHelp
+ }
+
+ if cmd.plot != "" {
+ if len(names) > 1 {
+ return flag.ErrHelp
+ }
+
+ if cmd.instance == "*" {
+ cmd.instance = ""
+ }
+ }
+
+ objs, err := cmd.ManagedObjects(ctx, paths)
+ if err != nil {
+ return err
+ }
+
+ s, err := m.ProviderSummary(ctx, objs[0])
+ if err != nil {
+ return err
+ }
+
+ if cmd.instance == "-" {
+ cmd.instance = ""
+ }
+
+ spec := types.PerfQuerySpec{
+ Format: string(types.PerfFormatNormal),
+ MaxSample: int32(cmd.n),
+ MetricId: []types.PerfMetricId{{Instance: cmd.instance}},
+ IntervalId: cmd.Interval(s.RefreshRate),
+ }
+
+ sample, err := m.SampleByName(ctx, spec, names, objs)
+ if err != nil {
+ return err
+ }
+
+ result, err := m.ToMetricSeries(ctx, sample)
+ if err != nil {
+ return err
+ }
+
+ counters, err := m.CounterInfoByName(ctx)
+ if err != nil {
+ return err
+ }
+
+ return cmd.WriteResult(&sampleResult{cmd, m, counters, result})
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/object/collect.go b/vendor/github.com/vmware/govmomi/govc/object/collect.go
index 48b22909..3f696695 100644
--- a/vendor/github.com/vmware/govmomi/govc/object/collect.go
+++ b/vendor/github.com/vmware/govmomi/govc/object/collect.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2016 VMware, Inc. All Rights Reserved.
+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.
@@ -29,6 +29,7 @@ import (
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/property"
+ "github.com/vmware/govmomi/view"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
@@ -39,6 +40,10 @@ type collect struct {
single bool
simple bool
n int
+ kind kinds
+
+ filter property.Filter
+ obj string
}
func init() {
@@ -51,6 +56,7 @@ func (cmd *collect) Register(ctx context.Context, f *flag.FlagSet) {
f.BoolVar(&cmd.simple, "s", false, "Output property value only")
f.IntVar(&cmd.n, "n", 0, "Wait for N property updates")
+ f.Var(&cmd.kind, "type", "Resource type. If specified, MOID is used for a container view root")
}
func (cmd *collect) Usage() string {
@@ -61,14 +67,20 @@ func (cmd *collect) Description() string {
return `Collect managed object properties.
MOID can be an inventory path or ManagedObjectReference.
-MOID defaults to '-', an alias for 'ServiceInstance:ServiceInstance'.
+MOID defaults to '-', an alias for 'ServiceInstance:ServiceInstance' or the root folder if a '-type' flag is given.
+
+If a '-type' flag is given, properties are collected using a ContainerView object where MOID is the root of the view.
-By default only the current property value(s) are collected. Use the '-n' flag to wait for updates.
+By default only the current property value(s) are collected. To wait for updates, use the '-n' flag or
+specify a property filter. A property filter can be specified by prefixing the property name with a '-',
+followed by the value to match.
Examples:
govc object.collect - content
govc object.collect -s HostSystem:ha-host hardware.systemInfo.uuid
govc object.collect -s /ha-datacenter/vm/foo overallStatus
+ govc object.collect -s /ha-datacenter/vm/foo -guest.guestOperationsReady true # property filter
+ govc object.collect -type m / name runtime.powerState # collect properties for multiple objects
govc object.collect -json -n=-1 EventManager:ha-eventmgr latestEvent | jq .
govc object.collect -json -s $(govc object.collect -s - content.perfManager) description.counterType | jq .`
}
@@ -83,12 +95,16 @@ func (cmd *collect) Process(ctx context.Context) error {
var stringer = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
type change struct {
- cmd *collect
- PropertyChange []types.PropertyChange
+ cmd *collect
+ Update types.ObjectUpdate
}
func (pc *change) MarshalJSON() ([]byte, error) {
- return json.Marshal(pc.PropertyChange)
+ if len(pc.cmd.kind) == 0 {
+ return json.Marshal(pc.Update.ChangeSet)
+ }
+
+ return json.Marshal(pc.Update)
}
func (pc *change) output(name string, rval reflect.Value, rtype reflect.Type) {
@@ -145,14 +161,33 @@ func (pc *change) output(name string, rval reflect.Value, rtype reflect.Type) {
return
}
+ if pc.cmd.obj != "" {
+ fmt.Fprintf(pc.cmd.Out, "%s\t", pc.cmd.obj)
+ }
+
fmt.Fprintf(pc.cmd.Out, "%s\t%s\t%s\n", name, rtype, s)
}
+func (pc *change) writeStruct(name string, rval reflect.Value, rtype reflect.Type) {
+ for i := 0; i < rval.NumField(); i++ {
+ fval := rval.Field(i)
+ field := rtype.Field(i)
+
+ if field.Anonymous {
+ pc.writeStruct(name, fval, fval.Type())
+ continue
+ }
+
+ fname := fmt.Sprintf("%s.%s%s", name, strings.ToLower(field.Name[:1]), field.Name[1:])
+ pc.output(fname, fval, field.Type)
+ }
+}
+
func (pc *change) Write(w io.Writer) error {
tw := tabwriter.NewWriter(pc.cmd.Out, 4, 0, 2, ' ', 0)
pc.cmd.Out = tw
- for _, c := range pc.PropertyChange {
+ for _, c := range pc.Update.ChangeSet {
if c.Val == nil {
// type is unknown in this case, as xsi:type was not provided - just skip for now
continue
@@ -166,18 +201,12 @@ func (pc *change) Write(w io.Writer) error {
rtype = rval.Type()
}
- if pc.cmd.single && rtype.Kind() == reflect.Struct && !rtype.Implements(stringer) {
- for i := 0; i < rval.NumField(); i++ {
- fval := rval.Field(i)
- field := rtype.Field(i)
-
- if field.Anonymous {
- continue
- }
+ if len(pc.cmd.kind) != 0 {
+ pc.cmd.obj = pc.Update.Obj.String()
+ }
- fname := fmt.Sprintf("%s.%s%s", c.Name, strings.ToLower(field.Name[:1]), field.Name[1:])
- pc.output(fname, fval, field.Type)
- }
+ if pc.cmd.single && rtype.Kind() == reflect.Struct && !rtype.Implements(stringer) {
+ pc.writeStruct(c.Name, rval, rtype)
continue
}
@@ -187,6 +216,33 @@ func (pc *change) Write(w io.Writer) error {
return tw.Flush()
}
+func (cmd *collect) match(update types.ObjectUpdate) bool {
+ if len(cmd.filter) == 0 {
+ return false
+ }
+
+ for _, c := range update.ChangeSet {
+ if cmd.filter.MatchProperty(types.DynamicProperty{Name: c.Name, Val: c.Val}) {
+ return true
+ }
+ }
+
+ return false
+}
+
+func (cmd *collect) toFilter(f *flag.FlagSet, props []string) ([]string, error) {
+ // TODO: Only supporting 1 filter prop for now. More than one would require some
+ // accounting / accumulating of multiple updates. And need to consider objects
+ // then enter/leave a container view.
+ if len(props) != 2 || !strings.HasPrefix(props[0], "-") {
+ return props, nil
+ }
+
+ cmd.filter = property.Filter{props[0][1:]: props[1]}
+
+ return cmd.filter.Keys(), nil
+}
+
func (cmd *collect) Run(ctx context.Context, f *flag.FlagSet) error {
client, err := cmd.Client()
if err != nil {
@@ -201,6 +257,10 @@ func (cmd *collect) Run(ctx context.Context, f *flag.FlagSet) error {
ref := methods.ServiceInstance
arg := f.Arg(0)
+ if len(cmd.kind) != 0 {
+ ref = client.ServiceContent.RootFolder
+ }
+
switch arg {
case "", "-":
default:
@@ -222,6 +282,7 @@ func (cmd *collect) Run(ctx context.Context, f *flag.FlagSet) error {
}
p := property.DefaultCollector(client)
+ filter := new(property.WaitFilter)
var props []string
if f.NArg() > 1 {
@@ -229,8 +290,63 @@ func (cmd *collect) Run(ctx context.Context, f *flag.FlagSet) error {
cmd.single = len(props) == 1
}
- return property.Wait(ctx, p, ref, props, func(pc []types.PropertyChange) bool {
- _ = cmd.WriteResult(&change{cmd, pc})
+ props, err = cmd.toFilter(f, props)
+ if err != nil {
+ return err
+ }
+
+ if len(cmd.kind) == 0 {
+ filter.Add(ref, ref.Type, props)
+ } else {
+ m := view.NewManager(client)
+
+ v, err := m.CreateContainerView(ctx, ref, cmd.kind, true)
+ if err != nil {
+ return err
+ }
+
+ defer v.Destroy(ctx)
+
+ for _, kind := range cmd.kind {
+ filter.Add(v.Reference(), kind, props, v.TraversalSpec())
+ }
+ }
+
+ entered := false
+ hasFilter := len(cmd.filter) != 0
+
+ return property.WaitForUpdates(ctx, p, filter, func(updates []types.ObjectUpdate) bool {
+ matches := 0
+
+ for _, update := range updates {
+ if entered && update.Kind == types.ObjectUpdateKindEnter {
+ // on the first update we only get kind "enter"
+ // if a new object is added, the next update with have both "enter" and "modify".
+ continue
+ }
+
+ c := &change{cmd, update}
+
+ if hasFilter {
+ if cmd.match(update) {
+ matches++
+ } else {
+ continue
+ }
+ }
+
+ _ = cmd.WriteResult(c)
+ }
+
+ entered = true
+
+ if hasFilter {
+ if matches > 0 {
+ return true
+ }
+
+ return false
+ }
cmd.n--
diff --git a/vendor/github.com/vmware/govmomi/govc/object/find.go b/vendor/github.com/vmware/govmomi/govc/object/find.go
new file mode 100644
index 00000000..5b924566
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/object/find.go
@@ -0,0 +1,324 @@
+/*
+Copyright (c) 2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package object
+
+import (
+ "bytes"
+ "context"
+ "flag"
+ "fmt"
+ "strings"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/govc/flags"
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/property"
+ "github.com/vmware/govmomi/view"
+ "github.com/vmware/govmomi/vim25"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type find struct {
+ *flags.DatacenterFlag
+
+ ref bool
+ kind kinds
+ name string
+ maxdepth int
+}
+
+var alias = []struct {
+ name string
+ kind string
+}{
+ {"a", "VirtualApp"},
+ {"c", "ClusterComputeResource"},
+ {"d", "Datacenter"},
+ {"f", "Folder"},
+ {"g", "DistributedVirtualPortgroup"},
+ {"h", "HostSystem"},
+ {"m", "VirtualMachine"},
+ {"n", "Network"},
+ {"o", "OpaqueNetwork"},
+ {"p", "ResourcePool"},
+ {"r", "ComputeResource"},
+ {"s", "Datastore"},
+ {"w", "DistributedVirtualSwitch"},
+}
+
+func aliasHelp() string {
+ var help bytes.Buffer
+
+ for _, a := range alias {
+ fmt.Fprintf(&help, " %s %s\n", a.name, a.kind)
+ }
+
+ return help.String()
+}
+
+type kinds []string
+
+func (e *kinds) String() string {
+ return fmt.Sprint(*e)
+}
+
+func (e *kinds) Set(value string) error {
+ *e = append(*e, e.alias(value))
+ return nil
+}
+
+func (e *kinds) alias(value string) string {
+ if len(value) != 1 {
+ return value
+ }
+
+ for _, a := range alias {
+ if a.name == value {
+ return a.kind
+ }
+ }
+
+ return value
+}
+
+func (e *kinds) wanted(kind string) bool {
+ if len(*e) == 0 {
+ return true
+ }
+
+ for _, k := range *e {
+ if kind == k {
+ return true
+ }
+ }
+
+ return false
+}
+
+func init() {
+ cli.Register("find", &find{})
+}
+
+func (cmd *find) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
+ cmd.DatacenterFlag.Register(ctx, f)
+
+ f.Var(&cmd.kind, "type", "Resource type")
+ f.StringVar(&cmd.name, "name", "*", "Resource name")
+ f.IntVar(&cmd.maxdepth, "maxdepth", -1, "Max depth")
+ f.BoolVar(&cmd.ref, "i", false, "Print the managed object reference")
+}
+
+func (cmd *find) Usage() string {
+ return "[ROOT] [KEY VAL]..."
+}
+
+func (cmd *find) Description() string {
+ atable := aliasHelp()
+
+ return fmt.Sprintf(`Find managed objects.
+
+ROOT can be an inventory path or ManagedObjectReference.
+ROOT defaults to '.', an alias for the root folder or DC if set.
+
+Optional KEY VAL pairs can be used to filter results against object instance properties.
+
+The '-type' flag value can be a managed entity type or one of the following aliases:
+
+%s
+Examples:
+ govc find
+ govc find /dc1 -type c
+ govc find vm -name my-vm-*
+ govc find . -type n
+ govc find . -type m -runtime.powerState poweredOn
+ govc find . -type m -datastore $(govc find -i datastore -name vsanDatastore)
+ govc find . -type s -summary.type vsan
+ govc find . -type h -hardware.cpuInfo.numCpuCores 16`, atable)
+}
+
+func (cmd *find) Process(ctx context.Context) error {
+ if err := cmd.DatacenterFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+// rootMatch returns true if the root object path should be printed
+func (cmd *find) rootMatch(ctx context.Context, root object.Reference, client *vim25.Client, filter property.Filter) bool {
+ ref := root.Reference()
+
+ if !cmd.kind.wanted(ref.Type) {
+ return false
+ }
+
+ if len(filter) == 1 && filter["name"] == "*" {
+ return true
+ }
+
+ var content []types.ObjectContent
+
+ pc := property.DefaultCollector(client)
+ _ = pc.RetrieveWithFilter(ctx, []types.ManagedObjectReference{ref}, filter.Keys(), &content, filter)
+
+ return content != nil
+}
+
+func (cmd *find) Run(ctx context.Context, f *flag.FlagSet) error {
+ client, err := cmd.Client()
+ if err != nil {
+ return err
+ }
+
+ finder, err := cmd.Finder()
+ if err != nil {
+ return err
+ }
+
+ root := client.ServiceContent.RootFolder
+ rootPath := "/"
+
+ arg := f.Arg(0)
+ props := f.Args()
+
+ if len(props) > 0 {
+ if strings.HasPrefix(arg, "-") {
+ arg = "."
+ } else {
+ props = props[1:]
+ }
+ }
+
+ if len(props)%2 != 0 {
+ return flag.ErrHelp
+ }
+
+ switch arg {
+ case rootPath:
+ case "", ".":
+ dc, _ := cmd.DatacenterIfSpecified()
+ if dc == nil {
+ arg = rootPath
+ } else {
+ arg = "."
+ root = dc.Reference()
+ rootPath = dc.InventoryPath
+ }
+ default:
+ l, ferr := finder.ManagedObjectList(ctx, arg)
+ if ferr != nil {
+ return err
+ }
+
+ switch len(l) {
+ case 0:
+ return fmt.Errorf("%s not found", arg)
+ case 1:
+ root = l[0].Object.Reference()
+ rootPath = l[0].Path
+ default:
+ return flag.ErrHelp
+ }
+ }
+
+ filter := property.Filter{}
+
+ if len(props)%2 != 0 {
+ return flag.ErrHelp
+ }
+
+ for i := 0; i < len(props); i++ {
+ key := props[i]
+ if !strings.HasPrefix(key, "-") {
+ return flag.ErrHelp
+ }
+
+ key = key[1:]
+ i++
+ val := props[i]
+
+ if xf := f.Lookup(key); xf != nil {
+ // Support use of -flag following the ROOT arg (flag package does not do this)
+ if err = xf.Value.Set(val); err != nil {
+ return err
+ }
+ } else {
+ filter[key] = val
+ }
+ }
+
+ filter["name"] = cmd.name
+
+ printPath := func(o types.ManagedObjectReference, p string) {
+ if cmd.ref {
+ fmt.Fprintln(cmd.Out, o)
+ return
+ }
+
+ path := strings.Replace(p, rootPath, arg, 1)
+ fmt.Fprintln(cmd.Out, path)
+ }
+
+ recurse := false
+
+ switch cmd.maxdepth {
+ case -1:
+ recurse = true
+ case 0:
+ case 1:
+ default:
+ return flag.ErrHelp // TODO: ?
+ }
+
+ if cmd.rootMatch(ctx, root, client, filter) {
+ printPath(root, arg)
+ }
+
+ if cmd.maxdepth == 0 {
+ return nil
+ }
+
+ m := view.NewManager(client)
+
+ v, err := m.CreateContainerView(ctx, root, cmd.kind, recurse)
+ if err != nil {
+ return err
+ }
+
+ defer v.Destroy(ctx)
+
+ objs, err := v.Find(ctx, cmd.kind, filter)
+ if err != nil {
+ return err
+ }
+
+ for _, o := range objs {
+ var path string
+
+ if !cmd.ref {
+ e, err := finder.Element(ctx, o)
+ if err != nil {
+ return err
+ }
+ path = e.Path
+ }
+
+ printPath(o, path)
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/object/method.go b/vendor/github.com/vmware/govmomi/govc/object/method.go
new file mode 100644
index 00000000..3cc24e98
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/object/method.go
@@ -0,0 +1,104 @@
+/*
+Copyright (c) 2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package object
+
+import (
+ "context"
+ "flag"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/govc/flags"
+ "github.com/vmware/govmomi/object"
+)
+
+type method struct {
+ *flags.DatacenterFlag
+
+ name string
+ reason string
+ source string
+ enable bool
+}
+
+func init() {
+ cli.Register("object.method", &method{})
+}
+
+func (cmd *method) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
+ cmd.DatacenterFlag.Register(ctx, f)
+
+ f.StringVar(&cmd.name, "name", "", "Method name")
+ f.StringVar(&cmd.reason, "reason", "", "Reason for disabling method")
+ f.StringVar(&cmd.source, "source", "govc", "Source ID")
+ f.BoolVar(&cmd.enable, "enable", true, "Enable method")
+}
+
+func (cmd *method) Usage() string {
+ return "PATH..."
+}
+
+func (cmd *method) Description() string {
+ return `Enable or disable methods for managed objects.
+
+Examples:
+ govc object.method -name Destroy_Task -enable=false /dc1/vm/foo
+ govc object.collect /dc1/vm/foo disabledMethod | grep --color Destroy_Task
+ govc object.method -name Destroy_Task -enable /dc1/vm/foo`
+}
+
+func (cmd *method) Process(ctx context.Context) error {
+ if err := cmd.DatacenterFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cmd *method) Run(ctx context.Context, f *flag.FlagSet) error {
+ if f.NArg() == 0 {
+ return flag.ErrHelp
+ }
+
+ if cmd.name == "" {
+ return flag.ErrHelp
+ }
+
+ c, err := cmd.Client()
+ if err != nil {
+ return err
+ }
+
+ objs, err := cmd.ManagedObjects(ctx, f.Args())
+ if err != nil {
+ return err
+ }
+
+ m := object.NewAuthorizationManager(c)
+
+ if cmd.enable {
+ return m.EnableMethods(ctx, objs, []string{cmd.name}, cmd.source)
+ }
+
+ method := []object.DisabledMethodRequest{
+ {
+ Method: cmd.name,
+ Reason: cmd.reason,
+ },
+ }
+
+ return m.DisableMethods(ctx, objs, method, cmd.source)
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/option/ls.go b/vendor/github.com/vmware/govmomi/govc/option/ls.go
new file mode 100644
index 00000000..4facb0c7
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/option/ls.go
@@ -0,0 +1,121 @@
+/*
+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 option
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "io"
+ "os"
+ "text/tabwriter"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/govc/flags"
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type List struct {
+ *flags.ClientFlag
+ *flags.OutputFlag
+}
+
+func init() {
+ cli.Register("option.ls", &List{})
+}
+
+func (cmd *List) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
+ cmd.ClientFlag.Register(ctx, f)
+
+ cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
+ cmd.OutputFlag.Register(ctx, f)
+}
+
+func (cmd *List) Process(ctx context.Context) error {
+ if err := cmd.ClientFlag.Process(ctx); err != nil {
+ return err
+ }
+ if err := cmd.OutputFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cmd *List) Usage() string {
+ return "[NAME]"
+}
+
+var ListDescription = `List option with the given NAME.
+
+If NAME ends with a dot, all options for that subtree are listed.`
+
+func (cmd *List) Description() string {
+ return ListDescription + `
+
+Examples:
+ govc option.ls
+ govc option.ls config.vpxd.sso.
+ govc option.ls config.vpxd.sso.sts.uri`
+}
+
+func (cmd *List) Query(ctx context.Context, f *flag.FlagSet, m *object.OptionManager) error {
+ var err error
+ var opts []types.BaseOptionValue
+
+ if f.NArg() > 1 {
+ return flag.ErrHelp
+ }
+
+ if f.NArg() == 1 {
+ opts, err = m.Query(ctx, f.Arg(0))
+ } else {
+ var om mo.OptionManager
+ err = m.Properties(ctx, m.Reference(), []string{"setting"}, &om)
+ opts = om.Setting
+ }
+
+ if err != nil {
+ return err
+ }
+
+ return cmd.WriteResult(optionResult(opts))
+}
+
+func (cmd *List) Run(ctx context.Context, f *flag.FlagSet) error {
+ c, err := cmd.Client()
+ if err != nil {
+ return err
+ }
+
+ m := object.NewOptionManager(c, *c.ServiceContent.Setting)
+
+ return cmd.Query(ctx, f, m)
+}
+
+type optionResult []types.BaseOptionValue
+
+func (r optionResult) Write(w io.Writer) error {
+ tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
+ for _, opt := range r {
+ o := opt.GetOptionValue()
+ fmt.Fprintf(tw, "%s:\t%v\n", o.Key, o.Value)
+ }
+ return tw.Flush()
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/option/set.go b/vendor/github.com/vmware/govmomi/govc/option/set.go
new file mode 100644
index 00000000..09d18f44
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/option/set.go
@@ -0,0 +1,120 @@
+/*
+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 option
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "strconv"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/govc/flags"
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type Set struct {
+ *flags.ClientFlag
+}
+
+func init() {
+ cli.Register("option.set", &Set{})
+}
+
+func (cmd *Set) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
+ cmd.ClientFlag.Register(ctx, f)
+}
+
+func (cmd *Set) Process(ctx context.Context) error {
+ if err := cmd.ClientFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cmd *Set) Usage() string {
+ return "NAME VALUE"
+}
+
+var SetDescription = `Set option NAME to VALUE.`
+
+func (cmd *Set) Description() string {
+ return SetDescription + `
+
+Examples:
+ govc option.set log.level info
+ govc option.set logger.Vsan verbose`
+}
+
+func (cmd *Set) Update(ctx context.Context, f *flag.FlagSet, m *object.OptionManager) error {
+ if f.NArg() != 2 {
+ return flag.ErrHelp
+ }
+
+ name := f.Arg(0)
+ opts, err := m.Query(ctx, name)
+ if err != nil {
+ return err
+ }
+
+ if len(opts) != 1 {
+ return flag.ErrHelp
+ }
+
+ val := f.Arg(1)
+ var set types.AnyType
+
+ switch x := opts[0].GetOptionValue().Value.(type) {
+ case string:
+ set = val
+ case bool:
+ set, err = strconv.ParseBool(val)
+ if err != nil {
+ return err
+ }
+ case int32:
+ s, err := strconv.ParseInt(val, 10, 32)
+ if err != nil {
+ return err
+ }
+ set = s
+ case int64:
+ set, err = strconv.ParseInt(val, 10, 64)
+ if err != nil {
+ return err
+ }
+ default:
+ return fmt.Errorf("type %T conversion not supported", x)
+ }
+
+ opts[0].GetOptionValue().Value = set
+
+ return m.Update(ctx, opts)
+}
+
+func (cmd *Set) Run(ctx context.Context, f *flag.FlagSet) error {
+ c, err := cmd.Client()
+ if err != nil {
+ return err
+ }
+
+ m := object.NewOptionManager(c, *c.ServiceContent.Setting)
+
+ return cmd.Update(ctx, f, m)
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/role/update.go b/vendor/github.com/vmware/govmomi/govc/role/update.go
index 3937626a..ad059ad0 100644
--- a/vendor/github.com/vmware/govmomi/govc/role/update.go
+++ b/vendor/github.com/vmware/govmomi/govc/role/update.go
@@ -42,7 +42,7 @@ func (cmd *update) Register(ctx context.Context, f *flag.FlagSet) {
f.StringVar(&cmd.name, "name", "", "Change role name")
f.BoolVar(&cmd.remove, "r", false, "Remove given PRIVILEGE(s)")
- f.BoolVar(&cmd.add, "a", false, "Remove given PRIVILEGE(s)")
+ f.BoolVar(&cmd.add, "a", false, "Add given PRIVILEGE(s)")
}
func (cmd *update) Process(ctx context.Context) error {
diff --git a/vendor/github.com/vmware/govmomi/govc/task/cancel.go b/vendor/github.com/vmware/govmomi/govc/task/cancel.go
new file mode 100644
index 00000000..77187186
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/task/cancel.go
@@ -0,0 +1,81 @@
+/*
+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 task
+
+import (
+ "context"
+ "flag"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/govc/flags"
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type cancel struct {
+ *flags.ClientFlag
+}
+
+func init() {
+ cli.Register("task.cancel", &cancel{})
+}
+
+func (cmd *cancel) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
+ cmd.ClientFlag.Register(ctx, f)
+}
+
+func (cmd *cancel) Description() string {
+ return `Cancel tasks.
+
+Examples:
+ govc task.cancel task-759`
+}
+
+func (cmd *cancel) Usage() string {
+ return "ID..."
+}
+
+func (cmd *cancel) Process(ctx context.Context) error {
+ if err := cmd.ClientFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cmd *cancel) Run(ctx context.Context, f *flag.FlagSet) error {
+ c, err := cmd.Client()
+ if err != nil {
+ return err
+ }
+
+ for _, id := range f.Args() {
+ var ref types.ManagedObjectReference
+
+ if !ref.FromString(id) {
+ ref.Type = "Task"
+ ref.Value = id
+ }
+
+ err = object.NewTask(c, ref).Cancel(ctx)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/task/recent.go b/vendor/github.com/vmware/govmomi/govc/task/recent.go
new file mode 100644
index 00000000..f5bd92fa
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/task/recent.go
@@ -0,0 +1,179 @@
+/*
+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 task
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "strings"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/govc/flags"
+ "github.com/vmware/govmomi/view"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type recent struct {
+ *flags.DatacenterFlag
+
+ max int
+ follow bool
+}
+
+func init() {
+ cli.Register("tasks", &recent{})
+}
+
+func (cmd *recent) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
+ cmd.DatacenterFlag.Register(ctx, f)
+
+ f.IntVar(&cmd.max, "n", 25, "Output the last N tasks")
+ f.BoolVar(&cmd.follow, "f", false, "Follow recent task updates")
+}
+
+func (cmd *recent) Description() string {
+ return `Display info for recent tasks.
+
+When a task has completed, the result column includes the task duration on success or
+error message on failure. If a task is still in progress, the result column displays
+the completion percentage and the task ID. The task ID can be used as an argument to
+the 'task.cancel' command.
+
+By default, all recent tasks are included (via TaskManager), but can be limited by PATH
+to a specific inventory object.
+
+Examples:
+ govc tasks
+ govc tasks -f
+ govc tasks -f /dc1/host/cluster1`
+}
+
+func (cmd *recent) Usage() string {
+ return "[PATH]"
+}
+
+func (cmd *recent) Process(ctx context.Context) error {
+ if err := cmd.DatacenterFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func chop(s string) string {
+ if len(s) < 30 {
+ return s
+ }
+
+ return s[:29] + "*"
+}
+
+func (cmd *recent) Run(ctx context.Context, f *flag.FlagSet) error {
+ c, err := cmd.Client()
+ if err != nil {
+ return err
+ }
+
+ m := c.ServiceContent.TaskManager
+
+ watch := *m
+
+ if f.NArg() == 1 {
+ refs, merr := cmd.ManagedObjects(ctx, f.Args())
+ if merr != nil {
+ return merr
+ }
+ watch = refs[0]
+ }
+
+ v, err := view.NewManager(c).CreateTaskView(ctx, &watch)
+ if err != nil {
+ return nil
+ }
+
+ defer v.Destroy(context.Background())
+
+ v.Follow = cmd.follow
+
+ stamp := "15:04:05"
+ tmpl := "%-30s %-30s %13s %9s %9s %9s %s\n"
+ fmt.Fprintf(cmd.Out, tmpl, "Task", "Target", "Initiator", "Queued", "Started", "Completed", "Result")
+
+ var last string
+ updated := false
+
+ return v.Collect(ctx, func(tasks []types.TaskInfo) {
+ if !updated && len(tasks) > cmd.max {
+ tasks = tasks[len(tasks)-cmd.max:]
+ }
+ updated = true
+
+ for _, info := range tasks {
+ var user string
+
+ switch x := info.Reason.(type) {
+ case *types.TaskReasonUser:
+ user = x.UserName
+ }
+
+ if info.EntityName == "" || user == "" {
+ continue
+ }
+
+ ruser := strings.SplitN(user, "\\", 2)
+ if len(ruser) == 2 {
+ user = ruser[1] // discard domain
+ }
+
+ queued := info.QueueTime.Format(stamp)
+ start := "-"
+ end := start
+
+ if info.StartTime != nil {
+ start = info.StartTime.Format(stamp)
+ }
+
+ result := fmt.Sprintf("%2d%% %s", info.Progress, info.Task)
+
+ if info.CompleteTime != nil {
+ if info.State == types.TaskInfoStateError {
+ result = info.Error.LocalizedMessage
+ } else {
+ result = fmt.Sprintf("%s (%s)", info.State, info.CompleteTime.Sub(*info.StartTime).String())
+ }
+
+ end = info.CompleteTime.Format(stamp)
+ }
+
+ name := strings.TrimSuffix(info.Name, "_Task")
+ switch name {
+ case "Destroy", "Rename":
+ name = info.Entity.Type + "." + name
+ }
+
+ item := fmt.Sprintf(tmpl, name, chop(info.EntityName), user, queued, start, end, result)
+
+ if item == last {
+ continue // task info was updated, but the fields we display were not
+ }
+ last = item
+
+ fmt.Fprint(cmd.Out, item)
+ }
+ })
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/vm/change.go b/vendor/github.com/vmware/govmomi/govc/vm/change.go
index bbfcecf4..af00b36c 100644
--- a/vendor/github.com/vmware/govmomi/govc/vm/change.go
+++ b/vendor/github.com/vmware/govmomi/govc/vm/change.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2015 VMware, Inc. All Rights Reserved.
+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.
@@ -37,8 +37,6 @@ func (e *extraConfig) Set(v string) error {
r := strings.SplitN(v, "=", 2)
if len(r) < 2 {
return fmt.Errorf("failed to parse extraConfig: %s", v)
- } else if r[1] == "" {
- return fmt.Errorf("empty value: %s", v)
}
*e = append(*e, &types.OptionValue{Key: r[0], Value: r[1]})
return nil
@@ -73,8 +71,13 @@ func (cmd *change) Register(ctx context.Context, f *flag.FlagSet) {
func (cmd *change) Description() string {
return `Change VM configuration.
+To add ExtraConfig variables that can read within the guest, use the 'guestinfo.' prefix.
+
Examples:
- govc vm.change -vm $vm -e smc.present=TRUE -e ich7m.present=TRUE`
+ govc vm.change -vm $vm -e smc.present=TRUE -e ich7m.present=TRUE
+ govc vm.change -vm $vm -e guestinfo.vmname $vm
+ # Read the variable set above inside the guest:
+ vmware-rpctool "info-get guestinfo.vmname"`
}
func (cmd *change) Process(ctx context.Context) error {
diff --git a/vendor/github.com/vmware/govmomi/govc/vm/disk/create.go b/vendor/github.com/vmware/govmomi/govc/vm/disk/create.go
index d297a3cd..4c0aac4e 100644
--- a/vendor/github.com/vmware/govmomi/govc/vm/disk/create.go
+++ b/vendor/github.com/vmware/govmomi/govc/vm/disk/create.go
@@ -89,6 +89,13 @@ func (cmd *create) Process(ctx context.Context) error {
return nil
}
+func (cmd *create) Description() string {
+ return `Create disk and attach to VM.
+
+Examples:
+ govc vm.disk.create -vm $name -name $name/disk1 -size 10G`
+}
+
func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
if len(cmd.Name) == 0 {
return errors.New("please specify a disk name")
diff --git a/vendor/github.com/vmware/govmomi/govc/vm/guest/chmod.go b/vendor/github.com/vmware/govmomi/govc/vm/guest/chmod.go
index ed634c23..29f0745b 100644
--- a/vendor/github.com/vmware/govmomi/govc/vm/guest/chmod.go
+++ b/vendor/github.com/vmware/govmomi/govc/vm/guest/chmod.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -19,13 +19,14 @@ package guest
import (
"context"
"flag"
+ "strconv"
"github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/vim25/types"
)
type chmod struct {
*GuestFlag
- *FileAttrFlag
}
func init() {
@@ -35,25 +36,42 @@ func init() {
func (cmd *chmod) Register(ctx context.Context, f *flag.FlagSet) {
cmd.GuestFlag, ctx = newGuestFlag(ctx)
cmd.GuestFlag.Register(ctx, f)
- cmd.FileAttrFlag, ctx = newFileAttrFlag(ctx)
- cmd.FileAttrFlag.Register(ctx, f)
}
func (cmd *chmod) Process(ctx context.Context) error {
if err := cmd.GuestFlag.Process(ctx); err != nil {
return err
}
- if err := cmd.FileAttrFlag.Process(ctx); err != nil {
- return err
- }
return nil
}
+func (cmd *chmod) Usage() string {
+ return "MODE FILE"
+}
+
+func (cmd *chmod) Description() string {
+ return `Change FILE MODE on VM.
+
+Examples:
+ govc guest.chmod -vm $name 0644 /var/log/foo.log`
+}
+
func (cmd *chmod) Run(ctx context.Context, f *flag.FlagSet) error {
+ if f.NArg() != 2 {
+ return flag.ErrHelp
+ }
+
m, err := cmd.FileManager()
if err != nil {
return err
}
- return m.ChangeFileAttributes(ctx, cmd.Auth(), f.Arg(0), cmd.Attr())
+ var attr types.GuestPosixFileAttributes
+
+ attr.Permissions, err = strconv.ParseInt(f.Arg(0), 0, 64)
+ if err != nil {
+ return err
+ }
+
+ return m.ChangeFileAttributes(ctx, cmd.Auth(), f.Arg(1), &attr)
}
diff --git a/vendor/github.com/vmware/govmomi/govc/vm/guest/chown.go b/vendor/github.com/vmware/govmomi/govc/vm/guest/chown.go
new file mode 100644
index 00000000..0b6a455a
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/vm/guest/chown.go
@@ -0,0 +1,96 @@
+/*
+Copyright (c) 2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package guest
+
+import (
+ "context"
+ "flag"
+ "strconv"
+ "strings"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type chown struct {
+ *GuestFlag
+}
+
+func init() {
+ cli.Register("guest.chown", &chown{})
+}
+
+func (cmd *chown) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.GuestFlag, ctx = newGuestFlag(ctx)
+ cmd.GuestFlag.Register(ctx, f)
+}
+
+func (cmd *chown) Process(ctx context.Context) error {
+ if err := cmd.GuestFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cmd *chown) Usage() string {
+ return "UID[:GID] FILE"
+}
+
+func (cmd *chown) Description() string {
+ return `Change FILE UID and GID on VM.
+
+Examples:
+ govc guest.chown -vm $name UID[:GID] /var/log/foo.log`
+}
+
+func (cmd *chown) Run(ctx context.Context, f *flag.FlagSet) error {
+ if f.NArg() != 2 {
+ return flag.ErrHelp
+ }
+
+ m, err := cmd.FileManager()
+ if err != nil {
+ return err
+ }
+
+ var attr types.GuestPosixFileAttributes
+
+ ids := strings.SplitN(f.Arg(0), ":", 2)
+ if len(ids) == 0 {
+ return flag.ErrHelp
+ }
+
+ id, err := strconv.Atoi(ids[0])
+ if err != nil {
+ return err
+ }
+
+ attr.OwnerId = new(int32)
+ *attr.OwnerId = int32(id)
+
+ if len(ids) == 2 {
+ id, err = strconv.Atoi(ids[1])
+ if err != nil {
+ return err
+ }
+
+ attr.GroupId = new(int32)
+ *attr.GroupId = int32(id)
+ }
+
+ return m.ChangeFileAttributes(ctx, cmd.Auth(), f.Arg(1), &attr)
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/vm/guest/download.go b/vendor/github.com/vmware/govmomi/govc/vm/guest/download.go
index 9e336d0b..4f0d789e 100644
--- a/vendor/github.com/vmware/govmomi/govc/vm/guest/download.go
+++ b/vendor/github.com/vmware/govmomi/govc/vm/guest/download.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -24,7 +24,7 @@ import (
"os"
"github.com/vmware/govmomi/govc/cli"
- "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/progress"
)
type download struct {
@@ -70,50 +70,36 @@ func (cmd *download) Run(ctx context.Context, f *flag.FlagSet) error {
return flag.ErrHelp
}
- m, err := cmd.FileManager()
- if err != nil {
- return err
- }
-
src := f.Arg(0)
dst := f.Arg(1)
- _, err = os.Stat(dst)
+ _, err := os.Stat(dst)
if err == nil && !cmd.overwrite {
return os.ErrExist
}
- info, err := m.InitiateFileTransferFromGuest(ctx, cmd.Auth(), src)
+ c, err := cmd.Toolbox()
if err != nil {
return err
}
- u, err := cmd.ParseURL(info.Url)
+ s, n, err := c.Download(ctx, src)
if err != nil {
return err
}
- c, err := cmd.Client()
- if err != nil {
- return nil
- }
-
- p := soap.DefaultDownload
-
if dst == "-" {
- f, _, err := c.Client.Download(u, &p)
- if err != nil {
- return err
- }
- _, err = io.Copy(os.Stdout, f)
+ _, err = io.Copy(os.Stdout, s)
return err
}
+ var p progress.Sinker
+
if cmd.OutputFlag.TTY {
logger := cmd.ProgressLogger("Downloading... ")
- p.Progress = logger
+ p = logger
defer logger.Wait()
}
- return c.Client.DownloadFile(dst, u, &p)
+ return c.ProcessManager.Client().WriteFile(dst, s, n, p)
}
diff --git a/vendor/github.com/vmware/govmomi/govc/vm/guest/file_attr.go b/vendor/github.com/vmware/govmomi/govc/vm/guest/file_attr.go
index 3ff3b6bb..3e18602f 100644
--- a/vendor/github.com/vmware/govmomi/govc/vm/guest/file_attr.go
+++ b/vendor/github.com/vmware/govmomi/govc/vm/guest/file_attr.go
@@ -33,8 +33,8 @@ func newFileAttrFlag(ctx context.Context) (*FileAttrFlag, context.Context) {
}
func (flag *FileAttrFlag) Register(ctx context.Context, f *flag.FlagSet) {
- f.Var(flags.NewInt32(&flag.OwnerId), "uid", "User ID")
- f.Var(flags.NewInt32(&flag.GroupId), "gid", "Group ID")
+ f.Var(flags.NewOptionalInt32(&flag.OwnerId), "uid", "User ID")
+ f.Var(flags.NewOptionalInt32(&flag.GroupId), "gid", "Group ID")
f.Int64Var(&flag.Permissions, "perm", 0, "File permissions")
}
diff --git a/vendor/github.com/vmware/govmomi/govc/vm/guest/getenv.go b/vendor/github.com/vmware/govmomi/govc/vm/guest/getenv.go
index 7d850aca..dc0c2b42 100644
--- a/vendor/github.com/vmware/govmomi/govc/vm/guest/getenv.go
+++ b/vendor/github.com/vmware/govmomi/govc/vm/guest/getenv.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -44,6 +44,18 @@ func (cmd *getenv) Process(ctx context.Context) error {
return nil
}
+func (cmd *getenv) Usage() string {
+ return "[NAME]..."
+}
+
+func (cmd *getenv) Description() string {
+ return `Read NAME environment variables from VM.
+
+Examples:
+ govc guest.getenv -vm $name
+ govc guest.getenv -vm $name HOME`
+}
+
func (cmd *getenv) Run(ctx context.Context, f *flag.FlagSet) error {
m, err := cmd.ProcessManager()
if err != nil {
diff --git a/vendor/github.com/vmware/govmomi/govc/vm/guest/guest.go b/vendor/github.com/vmware/govmomi/govc/vm/guest/guest.go
index 4018bf0b..b71dfdda 100644
--- a/vendor/github.com/vmware/govmomi/govc/vm/guest/guest.go
+++ b/vendor/github.com/vmware/govmomi/govc/vm/guest/guest.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -25,6 +25,7 @@ import (
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/guest"
+ "github.com/vmware/govmomi/guest/toolbox"
"github.com/vmware/govmomi/object"
)
@@ -62,6 +63,24 @@ func (flag *GuestFlag) Process(ctx context.Context) error {
return nil
}
+func (flag *GuestFlag) Toolbox() (*toolbox.Client, error) {
+ pm, err := flag.ProcessManager()
+ if err != nil {
+ return nil, err
+ }
+
+ fm, err := flag.FileManager()
+ if err != nil {
+ return nil, err
+ }
+
+ return &toolbox.Client{
+ ProcessManager: pm,
+ FileManager: fm,
+ Authentication: flag.Auth(),
+ }, nil
+}
+
func (flag *GuestFlag) FileManager() (*guest.FileManager, error) {
ctx := context.TODO()
c, err := flag.Client()
diff --git a/vendor/github.com/vmware/govmomi/govc/vm/guest/kill.go b/vendor/github.com/vmware/govmomi/govc/vm/guest/kill.go
index 0f008f21..ef1273d8 100644
--- a/vendor/github.com/vmware/govmomi/govc/vm/guest/kill.go
+++ b/vendor/github.com/vmware/govmomi/govc/vm/guest/kill.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -47,6 +47,13 @@ func (cmd *kill) Process(ctx context.Context) error {
return nil
}
+func (cmd *kill) Description() string {
+ return `Kill process ID on VM.
+
+Examples:
+ govc guest.kill -vm $name -p 12345`
+}
+
func (cmd *kill) Run(ctx context.Context, f *flag.FlagSet) error {
m, err := cmd.ProcessManager()
if err != nil {
diff --git a/vendor/github.com/vmware/govmomi/govc/vm/guest/ls.go b/vendor/github.com/vmware/govmomi/govc/vm/guest/ls.go
index dc95ab02..2d236ae0 100644
--- a/vendor/github.com/vmware/govmomi/govc/vm/guest/ls.go
+++ b/vendor/github.com/vmware/govmomi/govc/vm/guest/ls.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -24,10 +24,14 @@ import (
"text/tabwriter"
"github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/units"
+ "github.com/vmware/govmomi/vim25/types"
)
type ls struct {
*GuestFlag
+
+ simple bool
}
func init() {
@@ -37,6 +41,8 @@ func init() {
func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
cmd.GuestFlag, ctx = newGuestFlag(ctx)
cmd.GuestFlag.Register(ctx, f)
+
+ f.BoolVar(&cmd.simple, "s", false, "Simple path only listing") // sadly we used '-l' for guest login
}
func (cmd *ls) Process(ctx context.Context) error {
@@ -46,6 +52,17 @@ func (cmd *ls) Process(ctx context.Context) error {
return nil
}
+func (cmd *ls) Usage() string {
+ return "PATH"
+}
+
+func (cmd *ls) Description() string {
+ return `List PATH files in VM.
+
+Examples:
+ govc guest.ls -vm $name /tmp`
+}
+
func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
m, err := cmd.FileManager()
if err != nil {
@@ -53,7 +70,7 @@ func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
}
var offset int32
- tw := tabwriter.NewWriter(os.Stdout, 3, 0, 2, ' ', 0)
+ tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
for {
info, err := m.ListFiles(ctx, cmd.Auth(), f.Arg(0), offset, 0, f.Arg(1))
@@ -62,8 +79,38 @@ func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
}
for _, f := range info.Files {
- attr := f.Attributes.GetGuestFileAttributes() // TODO: GuestPosixFileAttributes
- fmt.Fprintf(tw, "%d\t%s\t%s\n", f.Size, attr.ModificationTime.Format("Mon Jan 2 15:04:05 2006"), f.Path)
+ if cmd.simple {
+ fmt.Fprintln(tw, f.Path)
+ continue
+ }
+
+ var kind byte
+
+ switch types.GuestFileType(f.Type) {
+ case types.GuestFileTypeDirectory:
+ kind = 'd'
+ if f.Size == 0 {
+ f.Size = 4092
+ }
+ case types.GuestFileTypeSymlink:
+ kind = 'l'
+ case types.GuestFileTypeFile:
+ kind = '-'
+ }
+
+ switch x := f.Attributes.(type) {
+ case *types.GuestPosixFileAttributes:
+ perm := os.FileMode(x.Permissions).Perm().String()[1:]
+ fmt.Fprintf(tw, "%c%s\t%d\t%d\t", kind, perm, *x.OwnerId, *x.GroupId)
+ }
+
+ attr := f.Attributes.GetGuestFileAttributes()
+
+ fmt.Fprintf(tw, "%s\t%s\t%s", units.FileSize(f.Size), attr.ModificationTime.Format("Jan 2 15:04 2006"), f.Path)
+ if attr.SymlinkTarget != "" {
+ fmt.Fprintf(tw, " -> %s", attr.SymlinkTarget)
+ }
+ fmt.Fprintln(tw)
}
_ = tw.Flush()
diff --git a/vendor/github.com/vmware/govmomi/govc/vm/guest/mkdir.go b/vendor/github.com/vmware/govmomi/govc/vm/guest/mkdir.go
index 7b317108..541f6d7f 100644
--- a/vendor/github.com/vmware/govmomi/govc/vm/guest/mkdir.go
+++ b/vendor/github.com/vmware/govmomi/govc/vm/guest/mkdir.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -49,6 +49,18 @@ func (cmd *mkdir) Process(ctx context.Context) error {
return nil
}
+func (cmd *mkdir) Usage() string {
+ return "PATH"
+}
+
+func (cmd *mkdir) Description() string {
+ return `Create directory PATH in VM.
+
+Examples:
+ govc guest.mkdir -vm $name /tmp/logs
+ govc guest.mkdir -vm $name -p /tmp/logs/foo/bar`
+}
+
func (cmd *mkdir) Run(ctx context.Context, f *flag.FlagSet) error {
m, err := cmd.FileManager()
if err != nil {
diff --git a/vendor/github.com/vmware/govmomi/govc/vm/guest/mktemp.go b/vendor/github.com/vmware/govmomi/govc/vm/guest/mktemp.go
index 2769e883..3637bcef 100644
--- a/vendor/github.com/vmware/govmomi/govc/vm/guest/mktemp.go
+++ b/vendor/github.com/vmware/govmomi/govc/vm/guest/mktemp.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -28,6 +28,7 @@ type mktemp struct {
*GuestFlag
dir bool
+ path string
prefix string
suffix string
}
@@ -41,6 +42,7 @@ func (cmd *mktemp) Register(ctx context.Context, f *flag.FlagSet) {
cmd.GuestFlag.Register(ctx, f)
f.BoolVar(&cmd.dir, "d", false, "Make a directory instead of a file")
+ f.StringVar(&cmd.path, "p", "", "If specified, create relative to this directory")
f.StringVar(&cmd.prefix, "t", "", "Prefix")
f.StringVar(&cmd.suffix, "s", "", "Suffix")
}
@@ -52,6 +54,16 @@ func (cmd *mktemp) Process(ctx context.Context) error {
return nil
}
+func (cmd *mktemp) Description() string {
+ return `Create a temporary file or directory in VM.
+
+Examples:
+ govc guest.mktemp -vm $name
+ govc guest.mktemp -vm $name -d
+ govc guest.mktemp -vm $name -t myprefix
+ govc guest.mktemp -vm $name -p /var/tmp/$USER`
+}
+
func (cmd *mktemp) Run(ctx context.Context, f *flag.FlagSet) error {
m, err := cmd.FileManager()
if err != nil {
@@ -63,7 +75,7 @@ func (cmd *mktemp) Run(ctx context.Context, f *flag.FlagSet) error {
mk = m.CreateTemporaryDirectory
}
- name, err := mk(ctx, cmd.Auth(), cmd.prefix, cmd.suffix)
+ name, err := mk(ctx, cmd.Auth(), cmd.prefix, cmd.suffix, cmd.path)
if err != nil {
return err
}
diff --git a/vendor/github.com/vmware/govmomi/govc/vm/guest/mv.go b/vendor/github.com/vmware/govmomi/govc/vm/guest/mv.go
new file mode 100644
index 00000000..4890a6f8
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/vm/guest/mv.go
@@ -0,0 +1,85 @@
+/*
+Copyright (c) 2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package guest
+
+import (
+ "context"
+ "flag"
+
+ "github.com/vmware/govmomi/govc/cli"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type mv struct {
+ *GuestFlag
+
+ noclobber bool
+}
+
+func init() {
+ cli.Register("guest.mv", &mv{})
+}
+
+func (cmd *mv) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.GuestFlag, ctx = newGuestFlag(ctx)
+ cmd.GuestFlag.Register(ctx, f)
+
+ f.BoolVar(&cmd.noclobber, "n", false, "Do not overwrite an existing file")
+}
+
+func (cmd *mv) Process(ctx context.Context) error {
+ if err := cmd.GuestFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cmd *mv) Usage() string {
+ return "SOURCE DEST"
+}
+
+func (cmd *mv) Description() string {
+ return `Move (rename) files in VM.
+
+Examples:
+ govc guest.mv -vm $name /tmp/foo.sh /tmp/bar.sh
+ govc guest.mv -vm $name -n /tmp/baz.sh /tmp/bar.sh`
+}
+
+func (cmd *mv) Run(ctx context.Context, f *flag.FlagSet) error {
+ m, err := cmd.FileManager()
+ if err != nil {
+ return err
+ }
+
+ src := f.Arg(0)
+ dst := f.Arg(1)
+
+ err = m.MoveFile(ctx, cmd.Auth(), src, dst, !cmd.noclobber)
+
+ if err != nil {
+ if soap.IsSoapFault(err) {
+ soapFault := soap.ToSoapFault(err)
+ if _, ok := soapFault.VimFault().(types.NotAFile); ok {
+ err = m.MoveDirectory(ctx, cmd.Auth(), src, dst)
+ }
+ }
+ }
+
+ return err
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/vm/guest/ps.go b/vendor/github.com/vmware/govmomi/govc/vm/guest/ps.go
index f7a99154..217986b9 100644
--- a/vendor/github.com/vmware/govmomi/govc/vm/guest/ps.go
+++ b/vendor/github.com/vmware/govmomi/govc/vm/guest/ps.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -21,8 +21,8 @@ import (
"flag"
"fmt"
"io"
- "os"
"strconv"
+ "strings"
"text/tabwriter"
"time"
@@ -36,6 +36,7 @@ type ps struct {
*GuestFlag
every bool
+ exit bool
wait bool
pids pidSelector
@@ -81,6 +82,7 @@ func (cmd *ps) Register(ctx context.Context, f *flag.FlagSet) {
cmd.uids = make(map[string]bool)
f.BoolVar(&cmd.every, "e", false, "Select all processes")
+ f.BoolVar(&cmd.exit, "x", false, "Output exit time and code")
f.BoolVar(&cmd.wait, "X", false, "Wait for process to exit")
f.Var(&cmd.pids, "p", "Select by process ID")
f.Var(&cmd.uids, "U", "Select by process UID")
@@ -96,6 +98,22 @@ func (cmd *ps) Process(ctx context.Context) error {
return nil
}
+func (cmd *ps) Description() string {
+ return `List processes in VM.
+
+By default, unless the '-e', '-p' or '-U' flag is specified, only processes owned
+by the '-l' flag user are displayed.
+
+The '-x' and '-X' flags only apply to processes started by vmware-tools,
+such as those started with the govc guest.start command.
+
+Examples:
+ govc guest.ps -vm $name
+ govc guest.ps -vm $name -e
+ govc guest.ps -vm $name -p 12345
+ govc guest.ps -vm $name -U root`
+}
+
func running(procs []types.GuestProcessInfo) bool {
for _, p := range procs {
if p.EndTime == nil {
@@ -145,9 +163,17 @@ type psResult struct {
}
func (r *psResult) Write(w io.Writer) error {
- tw := tabwriter.NewWriter(os.Stdout, 4, 0, 2, ' ', 0)
+ tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
+
+ fmt.Fprintf(tw, "%s\t%s\t%s", "UID", "PID", "STIME")
+ if r.cmd.exit {
+ fmt.Fprintf(tw, "\t%s\t%s", "XTIME", "XCODE")
+ }
+ fmt.Fprint(tw, "\tCMD\n")
- fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n", "UID", "PID", "STIME", "CMD")
+ if len(r.cmd.pids) != 0 {
+ r.cmd.every = true
+ }
if !r.cmd.every && len(r.cmd.uids) == 0 {
r.cmd.uids[r.cmd.auth.Username] = true
@@ -155,7 +181,17 @@ func (r *psResult) Write(w io.Writer) error {
for _, p := range r.ProcessInfo {
if r.cmd.every || r.cmd.uids[p.Owner] {
- fmt.Fprintf(tw, "%s\t%d\t%s\t%s\n", p.Owner, p.Pid, p.StartTime.Format("15:04"), p.CmdLine)
+ fmt.Fprintf(tw, "%s\t%d\t%s", p.Owner, p.Pid, p.StartTime.Format("15:04"))
+ if r.cmd.exit {
+ etime := "-"
+ ecode := "-"
+ if p.EndTime != nil {
+ etime = p.EndTime.Format("15:04")
+ ecode = strconv.Itoa(int(p.ExitCode))
+ }
+ fmt.Fprintf(tw, "\t%s\t%s", etime, ecode)
+ }
+ fmt.Fprintf(tw, "\t%s\n", strings.TrimSpace(p.CmdLine))
}
}
diff --git a/vendor/github.com/vmware/govmomi/govc/vm/guest/rm.go b/vendor/github.com/vmware/govmomi/govc/vm/guest/rm.go
index 9592f146..bd21a55e 100644
--- a/vendor/github.com/vmware/govmomi/govc/vm/guest/rm.go
+++ b/vendor/github.com/vmware/govmomi/govc/vm/guest/rm.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -43,6 +43,17 @@ func (cmd *rm) Process(ctx context.Context) error {
return nil
}
+func (cmd *rm) Usage() string {
+ return "PATH"
+}
+
+func (cmd *rm) Description() string {
+ return `Remove file PATH in VM.
+
+Examples:
+ govc guest.rm -vm $name /tmp/foo.log`
+}
+
func (cmd *rm) Run(ctx context.Context, f *flag.FlagSet) error {
m, err := cmd.FileManager()
if err != nil {
diff --git a/vendor/github.com/vmware/govmomi/govc/vm/guest/rmdir.go b/vendor/github.com/vmware/govmomi/govc/vm/guest/rmdir.go
index 0843a4df..7b69a879 100644
--- a/vendor/github.com/vmware/govmomi/govc/vm/guest/rmdir.go
+++ b/vendor/github.com/vmware/govmomi/govc/vm/guest/rmdir.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -47,6 +47,18 @@ func (cmd *rmdir) Process(ctx context.Context) error {
return nil
}
+func (cmd *rmdir) Usage() string {
+ return "PATH"
+}
+
+func (cmd *rmdir) Description() string {
+ return `Remove directory PATH in VM.
+
+Examples:
+ govc guest.rmdir -vm $name /tmp/empty-dir
+ govc guest.rmdir -vm $name -r /tmp/non-empty-dir`
+}
+
func (cmd *rmdir) Run(ctx context.Context, f *flag.FlagSet) error {
m, err := cmd.FileManager()
if err != nil {
diff --git a/vendor/github.com/vmware/govmomi/govc/vm/guest/run.go b/vendor/github.com/vmware/govmomi/govc/vm/guest/run.go
new file mode 100644
index 00000000..84dca194
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/govc/vm/guest/run.go
@@ -0,0 +1,156 @@
+/*
+Copyright (c) 2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package guest
+
+import (
+ "bytes"
+ "context"
+ "flag"
+ "fmt"
+ "io"
+ "net/http"
+ "os"
+ "os/exec"
+ "strings"
+
+ "github.com/vmware/govmomi/govc/cli"
+)
+
+type run struct {
+ *GuestFlag
+
+ data string
+ verbose bool
+ dir string
+ vars env
+}
+
+func init() {
+ cli.Register("guest.run", &run{})
+}
+
+func (cmd *run) Register(ctx context.Context, f *flag.FlagSet) {
+ cmd.GuestFlag, ctx = newGuestFlag(ctx)
+ cmd.GuestFlag.Register(ctx, f)
+
+ f.StringVar(&cmd.data, "d", "", "Input data")
+ f.BoolVar(&cmd.verbose, "v", false, "Verbose")
+ f.StringVar(&cmd.dir, "C", "", "The absolute path of the working directory for the program to start")
+ f.Var(&cmd.vars, "e", "Set environment variable or HTTP header")
+}
+
+func (cmd *run) Process(ctx context.Context) error {
+ if err := cmd.GuestFlag.Process(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cmd *run) Usage() string {
+ return "NAME [ARG]..."
+}
+
+func (cmd *run) Description() string {
+ return `Run program NAME in VM and display output.
+
+This command depends on govmomi/toolbox running in the VM guest and does not work with standard VMware tools.
+
+If the program NAME is an HTTP verb, the toolbox's http.RoundTripper will be used as the HTTP transport.
+
+Examples:
+ govc guest.run -vm $name kubectl get pods
+ govc guest.run -vm $name -d - kubectl create -f - 0 && nc.NicType == kind {
+ ip := net.ParseIP(nc.CandidateVnic[0].Spec.Ip.IpAddress)
+ if ip != nil {
+ mname = ip.String()
+ m.mu.Lock()
+ m.hosts[name] = mname
+ m.mu.Unlock()
+ name = mname
+ break
+ }
+ }
+ }
+
+ url.Host = net.JoinHostPort(name, port)
+
+ m.c.SetThumbprint(url.Host, host.Summary.Config.SslThumbprint)
+
+ return url, nil
+}
+
func (m FileManager) InitiateFileTransferFromGuest(ctx context.Context, auth types.BaseGuestAuthentication, guestFilePath string) (*types.FileTransferInformation, error) {
req := types.InitiateFileTransferFromGuest{
This: m.Reference(),
diff --git a/vendor/github.com/vmware/govmomi/guest/operations_manager.go b/vendor/github.com/vmware/govmomi/guest/operations_manager.go
index 016503c8..d02fb4ea 100644
--- a/vendor/github.com/vmware/govmomi/guest/operations_manager.go
+++ b/vendor/github.com/vmware/govmomi/guest/operations_manager.go
@@ -18,6 +18,7 @@ package guest
import (
"context"
+ "sync"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25"
@@ -58,7 +59,13 @@ func (m OperationsManager) FileManager(ctx context.Context) (*FileManager, error
return nil, err
}
- return &FileManager{*g.FileManager, m.vm, m.c}, nil
+ return &FileManager{
+ ManagedObjectReference: *g.FileManager,
+ vm: m.vm,
+ c: m.c,
+ mu: new(sync.Mutex),
+ hosts: make(map[string]string),
+ }, nil
}
func (m OperationsManager) ProcessManager(ctx context.Context) (*ProcessManager, error) {
diff --git a/vendor/github.com/vmware/govmomi/guest/process_manager.go b/vendor/github.com/vmware/govmomi/guest/process_manager.go
index 55db1e39..74741a1c 100644
--- a/vendor/github.com/vmware/govmomi/guest/process_manager.go
+++ b/vendor/github.com/vmware/govmomi/guest/process_manager.go
@@ -32,6 +32,10 @@ type ProcessManager struct {
c *vim25.Client
}
+func (m ProcessManager) Client() *vim25.Client {
+ return m.c
+}
+
func (m ProcessManager) Reference() types.ManagedObjectReference {
return m.ManagedObjectReference
}
diff --git a/vendor/github.com/vmware/govmomi/guest/toolbox/client.go b/vendor/github.com/vmware/govmomi/guest/toolbox/client.go
new file mode 100644
index 00000000..5244e310
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/guest/toolbox/client.go
@@ -0,0 +1,345 @@
+/*
+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 toolbox
+
+import (
+ "bufio"
+ "bytes"
+ "context"
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "os"
+ "os/exec"
+ "strings"
+
+ "github.com/vmware/govmomi/guest"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+// Client attempts to expose guest.OperationsManager as idiomatic Go interfaces
+type Client struct {
+ ProcessManager *guest.ProcessManager
+ FileManager *guest.FileManager
+ Authentication types.BaseGuestAuthentication
+}
+
+// procReader retries InitiateFileTransferFromGuest calls if toolbox is still running the process.
+// See also: ProcessManager.Stat
+func (c *Client) procReader(ctx context.Context, src string) (*types.FileTransferInformation, error) {
+ for {
+ info, err := c.FileManager.InitiateFileTransferFromGuest(ctx, c.Authentication, src)
+ if err != nil {
+ if soap.IsSoapFault(err) {
+ if _, ok := soap.ToSoapFault(err).VimFault().(types.CannotAccessFile); ok {
+ // We're not waiting in between retries since ProcessManager.Stat
+ // has already waited. In the case that this client was pointed at
+ // standard vmware-tools, the types.NotFound fault would have been
+ // returned since the file "/proc/$pid/stdout" does not exist - in
+ // which case, we won't retry at all.
+ continue
+ }
+ }
+
+ return nil, err
+ }
+
+ return info, err
+ }
+}
+
+// RoundTrip implements http.RoundTripper over vmx guest RPC.
+// This transport depends on govmomi/toolbox running in the VM guest and does not work with standard VMware tools.
+// Using this transport makes it is possible to connect to HTTP endpoints that are bound to the VM's loopback address.
+// Note that the toolbox's http.RoundTripper only supports the "http" scheme, "https" is not supported.
+func (c *Client) RoundTrip(req *http.Request) (*http.Response, error) {
+ if req.URL.Scheme != "http" {
+ return nil, fmt.Errorf("%q scheme not supported", req.URL.Scheme)
+ }
+
+ ctx := req.Context()
+
+ req.Header.Set("Connection", "close") // we need the server to close the connection after 1 request
+
+ spec := types.GuestProgramSpec{
+ ProgramPath: "http.RoundTrip",
+ Arguments: req.URL.Host,
+ }
+
+ pid, err := c.ProcessManager.StartProgram(ctx, c.Authentication, &spec)
+ if err != nil {
+ return nil, err
+ }
+
+ dst := fmt.Sprintf("/proc/%d/stdin", pid)
+ src := fmt.Sprintf("/proc/%d/stdout", pid)
+
+ var buf bytes.Buffer
+ err = req.Write(&buf)
+ if err != nil {
+ return nil, err
+ }
+
+ attr := new(types.GuestPosixFileAttributes)
+ size := int64(buf.Len())
+
+ url, err := c.FileManager.InitiateFileTransferToGuest(ctx, c.Authentication, dst, attr, size, true)
+ if err != nil {
+ return nil, err
+ }
+
+ vc := c.ProcessManager.Client()
+
+ u, err := c.FileManager.TransferURL(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+
+ p := soap.DefaultUpload
+ p.ContentLength = size
+
+ err = vc.Client.Upload(&buf, u, &p)
+ if err != nil {
+ return nil, err
+ }
+
+ info, err := c.procReader(ctx, src)
+ if err != nil {
+ return nil, err
+ }
+
+ u, err = c.FileManager.TransferURL(ctx, info.Url)
+ if err != nil {
+ return nil, err
+ }
+
+ f, _, err := vc.Client.Download(u, &soap.DefaultDownload)
+ if err != nil {
+ return nil, err
+ }
+
+ return http.ReadResponse(bufio.NewReader(f), req)
+}
+
+// Run implements exec.Cmd.Run over vmx guest RPC.
+func (c *Client) Run(ctx context.Context, cmd *exec.Cmd) error {
+ vc := c.ProcessManager.Client()
+
+ spec := types.GuestProgramSpec{
+ ProgramPath: cmd.Path,
+ Arguments: strings.Join(cmd.Args, " "),
+ EnvVariables: cmd.Env,
+ WorkingDirectory: cmd.Dir,
+ }
+
+ pid, serr := c.ProcessManager.StartProgram(ctx, c.Authentication, &spec)
+ if serr != nil {
+ return serr
+ }
+
+ if cmd.Stdin != nil {
+ dst := fmt.Sprintf("/proc/%d/stdin", pid)
+
+ var buf bytes.Buffer
+ size, err := io.Copy(&buf, cmd.Stdin)
+ if err != nil {
+ return err
+ }
+
+ attr := new(types.GuestPosixFileAttributes)
+
+ url, err := c.FileManager.InitiateFileTransferToGuest(ctx, c.Authentication, dst, attr, size, true)
+ if err != nil {
+ return err
+ }
+
+ u, err := c.FileManager.TransferURL(ctx, url)
+ if err != nil {
+ return err
+ }
+
+ p := soap.DefaultUpload
+ p.ContentLength = size
+
+ err = vc.Client.Upload(&buf, u, &p)
+ if err != nil {
+ return err
+ }
+ }
+
+ names := []string{"out", "err"}
+
+ for i, w := range []io.Writer{cmd.Stdout, cmd.Stderr} {
+ if w == nil {
+ continue
+ }
+
+ src := fmt.Sprintf("/proc/%d/std%s", pid, names[i])
+
+ info, err := c.procReader(ctx, src)
+ if err != nil {
+ return err
+ }
+
+ u, err := c.FileManager.TransferURL(ctx, info.Url)
+ if err != nil {
+ return err
+ }
+
+ f, _, err := vc.Client.Download(u, &soap.DefaultDownload)
+ if err != nil {
+ return err
+ }
+
+ _, err = io.Copy(w, f)
+ _ = f.Close()
+ if err != nil {
+ return err
+ }
+ }
+
+ procs, err := c.ProcessManager.ListProcesses(ctx, c.Authentication, []int64{pid})
+ if err != nil {
+ return err
+ }
+
+ if len(procs) == 1 {
+ rc := procs[0].ExitCode
+ if rc != 0 {
+ return fmt.Errorf("%s: exit %d", cmd.Path, rc)
+ }
+ }
+
+ return nil
+}
+
+// archiveReader wraps an io.ReadCloser to support streaming download
+// of a guest directory, stops reading once it sees the stream trailer.
+// This is only useful when guest tools is the Go toolbox.
+// The trailer is required since TransferFromGuest requires a Content-Length,
+// which toolbox doesn't know ahead of time as the gzip'd tarball never touches the disk.
+// We opted to wrap this here for now rather than guest.FileManager so
+// DownloadFile can be also be used as-is to handle this use case.
+type archiveReader struct {
+ io.ReadCloser
+}
+
+var (
+ gzipHeader = []byte{0x1f, 0x8b, 0x08} // rfc1952 {ID1, ID2, CM}
+ gzipHeaderLen = len(gzipHeader)
+)
+
+func (r *archiveReader) Read(buf []byte) (int, error) {
+ nr, err := r.ReadCloser.Read(buf)
+
+ // Stop reading if the last N bytes are the gzipTrailer
+ if nr >= gzipHeaderLen {
+ if bytes.Equal(buf[nr-gzipHeaderLen:nr], gzipHeader) {
+ nr -= gzipHeaderLen
+ err = io.EOF
+ }
+ }
+
+ return nr, err
+}
+
+func isDir(src string) bool {
+ u, err := url.Parse(src)
+ if err != nil {
+ return false
+ }
+
+ return strings.HasSuffix(u.Path, "/")
+}
+
+// Download initiates a file transfer from the guest
+func (c *Client) Download(ctx context.Context, src string) (io.ReadCloser, int64, error) {
+ vc := c.ProcessManager.Client()
+
+ info, err := c.FileManager.InitiateFileTransferFromGuest(ctx, c.Authentication, src)
+ if err != nil {
+ return nil, 0, err
+ }
+
+ u, err := c.FileManager.TransferURL(ctx, info.Url)
+ if err != nil {
+ return nil, 0, err
+ }
+
+ p := soap.DefaultDownload
+
+ f, n, err := vc.Download(u, &p)
+ if err != nil {
+ return nil, n, err
+ }
+
+ if strings.HasPrefix(src, "/archive:/") || isDir(src) {
+ f = &archiveReader{ReadCloser: f} // look for the gzip trailer
+ }
+
+ return f, n, nil
+}
+
+// Upload transfers a file to the guest
+func (c *Client) Upload(ctx context.Context, src io.Reader, dst string, p soap.Upload, attr types.BaseGuestFileAttributes, force bool) error {
+ vc := c.ProcessManager.Client()
+
+ var err error
+
+ if p.ContentLength == 0 { // Content-Length is required
+ switch r := src.(type) {
+ case *bytes.Buffer:
+ p.ContentLength = int64(r.Len())
+ case *bytes.Reader:
+ p.ContentLength = int64(r.Len())
+ case *strings.Reader:
+ p.ContentLength = int64(r.Len())
+ case *os.File:
+ info, serr := r.Stat()
+ if serr != nil {
+ return serr
+ }
+
+ p.ContentLength = info.Size()
+ }
+
+ if p.ContentLength == 0 { // os.File for example could be a device (stdin)
+ buf := new(bytes.Buffer)
+
+ p.ContentLength, err = io.Copy(buf, src)
+ if err != nil {
+ return err
+ }
+
+ src = buf
+ }
+ }
+
+ url, err := c.FileManager.InitiateFileTransferToGuest(ctx, c.Authentication, dst, attr, p.ContentLength, force)
+ if err != nil {
+ return err
+ }
+
+ u, err := c.FileManager.TransferURL(ctx, url)
+ if err != nil {
+ return err
+ }
+
+ return vc.Client.Upload(src, u, &p)
+}
diff --git a/vendor/github.com/vmware/govmomi/list/lister.go b/vendor/github.com/vmware/govmomi/list/lister.go
index ae162b7f..2ee32e6b 100644
--- a/vendor/github.com/vmware/govmomi/list/lister.go
+++ b/vendor/github.com/vmware/govmomi/list/lister.go
@@ -33,6 +33,10 @@ type Element struct {
Object mo.Reference
}
+func (e Element) String() string {
+ return fmt.Sprintf("%s @ %s", e.Object.Reference(), e.Path)
+}
+
func ToElement(r mo.Reference, prefix string) Element {
var name string
@@ -112,23 +116,6 @@ type Lister struct {
All bool
}
-func traversable(ref types.ManagedObjectReference) bool {
- switch ref.Type {
- case "Folder":
- case "Datacenter":
- case "ComputeResource", "ClusterComputeResource":
- // Treat ComputeResource and ClusterComputeResource as one and the same.
- // It doesn't matter from the perspective of the lister.
- case "HostSystem":
- case "VirtualApp":
- case "StoragePod":
- default:
- return false
- }
-
- return true
-}
-
func (l Lister) retrieveProperties(ctx context.Context, req types.RetrieveProperties, dst *[]interface{}) error {
res, err := l.Collector.RetrieveProperties(ctx, req)
if err != nil {
@@ -225,6 +212,8 @@ func (l Lister) ListFolder(ctx context.Context) ([]Element, error) {
// Additional basic properties.
switch t {
+ case "Folder":
+ pspec.PathSet = append(pspec.PathSet, "childType")
case "ComputeResource", "ClusterComputeResource":
// The ComputeResource and ClusterComputeResource are dereferenced in
// the ResourcePoolFlag. Make sure they always have their resourcePool
@@ -286,7 +275,7 @@ func (l Lister) ListDatacenter(ctx context.Context) ([]Element, error) {
if l.All {
pspec.All = types.NewBool(true)
} else {
- pspec.PathSet = []string{"name"}
+ pspec.PathSet = []string{"name", "childType"}
}
req := types.RetrieveProperties{
diff --git a/vendor/github.com/vmware/govmomi/list/recurser.go b/vendor/github.com/vmware/govmomi/list/recurser.go
deleted file mode 100644
index 32a67829..00000000
--- a/vendor/github.com/vmware/govmomi/list/recurser.go
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
-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 list
-
-import (
- "context"
- "path"
- "path/filepath"
-
- "github.com/vmware/govmomi/property"
-)
-
-type Recurser struct {
- Collector *property.Collector
-
- // All configures the recurses to fetch complete objects for leaf nodes.
- All bool
-
- // TraverseLeafs configures the Recurser to traverse traversable leaf nodes.
- // This is typically set to true when used from the ls command, where listing
- // a folder means listing its contents. This is typically set to false for
- // commands that take managed entities that are not folders as input.
- TraverseLeafs bool
-}
-
-func (r Recurser) Recurse(ctx context.Context, root Element, parts []string) ([]Element, error) {
- if len(parts) == 0 {
- // Include non-traversable leaf elements in result. For example, consider
- // the pattern "./vm/my-vm-*", where the pattern should match the VMs and
- // not try to traverse them.
- //
- // Include traversable leaf elements in result, if the TraverseLeafs
- // field is set to false.
- //
- if !traversable(root.Object.Reference()) || !r.TraverseLeafs {
- return []Element{root}, nil
- }
- }
-
- k := Lister{
- Collector: r.Collector,
- Reference: root.Object.Reference(),
- Prefix: root.Path,
- }
-
- if r.All && len(parts) < 2 {
- k.All = true
- }
-
- in, err := k.List(ctx)
- if err != nil {
- return nil, err
- }
-
- // This folder is a leaf as far as the glob goes.
- if len(parts) == 0 {
- return in, nil
- }
-
- pattern := parts[0]
- parts = parts[1:]
-
- var out []Element
- for _, e := range in {
- matched, err := filepath.Match(pattern, path.Base(e.Path))
- if err != nil {
- return nil, err
- }
-
- if !matched {
- continue
- }
-
- nres, err := r.Recurse(ctx, e, parts)
- if err != nil {
- return nil, err
- }
-
- out = append(out, nres...)
- }
-
- return out, nil
-}
diff --git a/vendor/github.com/vmware/govmomi/nfc/lease.go b/vendor/github.com/vmware/govmomi/nfc/lease.go
new file mode 100644
index 00000000..20323805
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/nfc/lease.go
@@ -0,0 +1,205 @@
+/*
+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 nfc
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "io"
+
+ "github.com/vmware/govmomi/property"
+ "github.com/vmware/govmomi/vim25"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/progress"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type Lease struct {
+ types.ManagedObjectReference
+
+ c *vim25.Client
+}
+
+func NewLease(c *vim25.Client, ref types.ManagedObjectReference) *Lease {
+ return &Lease{ref, c}
+}
+
+// Abort wraps methods.Abort
+func (l *Lease) Abort(ctx context.Context, fault *types.LocalizedMethodFault) error {
+ req := types.HttpNfcLeaseAbort{
+ This: l.Reference(),
+ Fault: fault,
+ }
+
+ _, err := methods.HttpNfcLeaseAbort(ctx, l.c, &req)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// Complete wraps methods.Complete
+func (l *Lease) Complete(ctx context.Context) error {
+ req := types.HttpNfcLeaseComplete{
+ This: l.Reference(),
+ }
+
+ _, err := methods.HttpNfcLeaseComplete(ctx, l.c, &req)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// GetManifest wraps methods.GetManifest
+func (l *Lease) GetManifest(ctx context.Context) error {
+ req := types.HttpNfcLeaseGetManifest{
+ This: l.Reference(),
+ }
+
+ _, err := methods.HttpNfcLeaseGetManifest(ctx, l.c, &req)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// Progress wraps methods.Progress
+func (l *Lease) Progress(ctx context.Context, percent int32) error {
+ req := types.HttpNfcLeaseProgress{
+ This: l.Reference(),
+ Percent: percent,
+ }
+
+ _, err := methods.HttpNfcLeaseProgress(ctx, l.c, &req)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+type LeaseInfo struct {
+ types.HttpNfcLeaseInfo
+
+ Items []FileItem
+}
+
+func (l *Lease) newLeaseInfo(li *types.HttpNfcLeaseInfo, items []types.OvfFileItem) (*LeaseInfo, error) {
+ info := &LeaseInfo{
+ HttpNfcLeaseInfo: *li,
+ }
+
+ for _, device := range li.DeviceUrl {
+ u, err := l.c.ParseURL(device.Url)
+ if err != nil {
+ return nil, err
+ }
+
+ if device.SslThumbprint != "" {
+ // TODO: prefer host management IP
+ l.c.SetThumbprint(u.Host, device.SslThumbprint)
+ }
+
+ for _, item := range items {
+ if device.ImportKey == item.DeviceId {
+ info.Items = append(info.Items, NewFileItem(u, item))
+ break
+ }
+ }
+ }
+
+ return info, nil
+}
+
+func (l *Lease) Wait(ctx context.Context, items []types.OvfFileItem) (*LeaseInfo, error) {
+ var lease mo.HttpNfcLease
+
+ pc := property.DefaultCollector(l.c)
+ err := property.Wait(ctx, pc, l.Reference(), []string{"state", "info", "error"}, func(pc []types.PropertyChange) bool {
+ done := false
+
+ for _, c := range pc {
+ if c.Val == nil {
+ continue
+ }
+
+ switch c.Name {
+ case "error":
+ val := c.Val.(types.LocalizedMethodFault)
+ lease.Error = &val
+ done = true
+ case "info":
+ val := c.Val.(types.HttpNfcLeaseInfo)
+ lease.Info = &val
+ case "state":
+ lease.State = c.Val.(types.HttpNfcLeaseState)
+ if lease.State != types.HttpNfcLeaseStateInitializing {
+ done = true
+ }
+ }
+ }
+
+ return done
+ })
+
+ if err != nil {
+ return nil, err
+ }
+
+ if lease.State == types.HttpNfcLeaseStateReady {
+ return l.newLeaseInfo(lease.Info, items)
+ }
+
+ if lease.Error != nil {
+ return nil, errors.New(lease.Error.LocalizedMessage)
+ }
+
+ return nil, fmt.Errorf("unexpected nfc lease state: %s", lease.State)
+}
+
+func (l *Lease) StartUpdater(ctx context.Context, info *LeaseInfo) *LeaseUpdater {
+ return newLeaseUpdater(ctx, l, info)
+}
+
+func (l *Lease) Upload(ctx context.Context, item FileItem, f io.Reader, opts soap.Upload) error {
+ if opts.Progress == nil {
+ opts.Progress = item
+ } else {
+ opts.Progress = progress.Tee(item, opts.Progress)
+ }
+
+ // Non-disk files (such as .iso) use the PUT method.
+ // Overwrite: t header is also required in this case (ovftool does the same)
+ if item.Create {
+ opts.Method = "PUT"
+ opts.Headers = map[string]string{
+ "Overwrite": "t",
+ }
+ } else {
+ opts.Method = "POST"
+ opts.Type = "application/x-vnd.vmware-streamVmdk"
+ }
+
+ return l.c.Upload(f, item.URL, &opts)
+}
diff --git a/vendor/github.com/vmware/govmomi/govc/importx/lease_updater.go b/vendor/github.com/vmware/govmomi/nfc/lease_updater.go
similarity index 72%
rename from vendor/github.com/vmware/govmomi/govc/importx/lease_updater.go
rename to vendor/github.com/vmware/govmomi/nfc/lease_updater.go
index aa05bd49..0b9757d3 100644
--- a/vendor/github.com/vmware/govmomi/govc/importx/lease_updater.go
+++ b/vendor/github.com/vmware/govmomi/nfc/lease_updater.go
@@ -14,35 +14,41 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package importx
+package nfc
import (
"context"
- "fmt"
+ "log"
"net/url"
"sync"
"sync/atomic"
"time"
- "github.com/vmware/govmomi/object"
- "github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/progress"
"github.com/vmware/govmomi/vim25/types"
)
-type ovfFileItem struct {
- url *url.URL
- item types.OvfFileItem
- ch chan progress.Report
+type FileItem struct {
+ types.OvfFileItem
+ URL *url.URL
+
+ ch chan progress.Report
}
-func (o ovfFileItem) Sink() chan<- progress.Report {
+func NewFileItem(u *url.URL, item types.OvfFileItem) FileItem {
+ return FileItem{
+ OvfFileItem: item,
+ URL: u,
+ ch: make(chan progress.Report),
+ }
+}
+
+func (o FileItem) Sink() chan<- progress.Report {
return o.ch
}
-type leaseUpdater struct {
- client *vim25.Client
- lease *object.HttpNfcLease
+type LeaseUpdater struct {
+ lease *Lease
pos int64 // Number of bytes
total int64 // Total number of bytes
@@ -52,16 +58,15 @@ type leaseUpdater struct {
wg sync.WaitGroup // Track when update loop is done
}
-func newLeaseUpdater(client *vim25.Client, lease *object.HttpNfcLease, items []ovfFileItem) *leaseUpdater {
- l := leaseUpdater{
- client: client,
- lease: lease,
+func newLeaseUpdater(ctx context.Context, lease *Lease, info *LeaseInfo) *LeaseUpdater {
+ l := LeaseUpdater{
+ lease: lease,
done: make(chan struct{}),
}
- for _, item := range items {
- l.total += item.item.Size
+ for _, item := range info.Items {
+ l.total += item.Size
go l.waitForProgress(item)
}
@@ -72,10 +77,10 @@ func newLeaseUpdater(client *vim25.Client, lease *object.HttpNfcLease, items []o
return &l
}
-func (l *leaseUpdater) waitForProgress(item ovfFileItem) {
+func (l *LeaseUpdater) waitForProgress(item FileItem) {
var pos, total int64
- total = item.item.Size
+ total = item.Size
for {
select {
@@ -101,7 +106,7 @@ func (l *leaseUpdater) waitForProgress(item ovfFileItem) {
}
}
-func (l *leaseUpdater) run() {
+func (l *LeaseUpdater) run() {
defer l.wg.Done()
tick := time.NewTicker(2 * time.Second)
@@ -117,15 +122,16 @@ func (l *leaseUpdater) run() {
// Always report the current value of percent, as it will renew the
// lease even if the value hasn't changed or is 0.
percent := int32(float32(100*atomic.LoadInt64(&l.pos)) / float32(l.total))
- err := l.lease.HttpNfcLeaseProgress(context.TODO(), percent)
+ err := l.lease.Progress(context.TODO(), percent)
if err != nil {
- fmt.Printf("from lease updater: %s\n", err)
+ log.Printf("NFC lease progress: %s", err)
+ return
}
}
}
}
-func (l *leaseUpdater) Done() {
+func (l *LeaseUpdater) Done() {
close(l.done)
l.wg.Wait()
}
diff --git a/vendor/github.com/vmware/govmomi/object/authorization_manager_internal.go b/vendor/github.com/vmware/govmomi/object/authorization_manager_internal.go
new file mode 100644
index 00000000..4fa520f5
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/object/authorization_manager_internal.go
@@ -0,0 +1,86 @@
+/*
+Copyright (c) 2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package object
+
+import (
+ "context"
+
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type DisabledMethodRequest struct {
+ Method string `xml:"method"`
+ Reason string `xml:"reasonId"`
+}
+
+type disableMethodsRequest struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Entity []types.ManagedObjectReference `xml:"entity"`
+ Method []DisabledMethodRequest `xml:"method"`
+ Source string `xml:"sourceId"`
+ Scope bool `xml:"sessionScope,omitempty"`
+}
+
+type disableMethodsBody struct {
+ Req *disableMethodsRequest `xml:"urn:internalvim25 DisableMethods,omitempty"`
+ Res interface{} `xml:"urn:vim25 DisableMethodsResponse,omitempty"`
+ Err *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *disableMethodsBody) Fault() *soap.Fault { return b.Err }
+
+func (m AuthorizationManager) DisableMethods(ctx context.Context, entity []types.ManagedObjectReference, method []DisabledMethodRequest, source string) error {
+ var reqBody, resBody disableMethodsBody
+
+ reqBody.Req = &disableMethodsRequest{
+ This: m.Reference(),
+ Entity: entity,
+ Method: method,
+ Source: source,
+ }
+
+ return m.Client().RoundTrip(ctx, &reqBody, &resBody)
+}
+
+type enableMethodsRequest struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Entity []types.ManagedObjectReference `xml:"entity"`
+ Method []string `xml:"method"`
+ Source string `xml:"sourceId"`
+}
+
+type enableMethodsBody struct {
+ Req *enableMethodsRequest `xml:"urn:internalvim25 EnableMethods,omitempty"`
+ Res interface{} `xml:"urn:vim25 EnableMethodsResponse,omitempty"`
+ Err *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *enableMethodsBody) Fault() *soap.Fault { return b.Err }
+
+func (m AuthorizationManager) EnableMethods(ctx context.Context, entity []types.ManagedObjectReference, method []string, source string) error {
+ var reqBody, resBody enableMethodsBody
+
+ reqBody.Req = &enableMethodsRequest{
+ This: m.Reference(),
+ Entity: entity,
+ Method: method,
+ Source: source,
+ }
+
+ return m.Client().RoundTrip(ctx, &reqBody, &resBody)
+}
diff --git a/vendor/github.com/vmware/govmomi/object/common.go b/vendor/github.com/vmware/govmomi/object/common.go
index 52feeed6..8f0a94ff 100644
--- a/vendor/github.com/vmware/govmomi/object/common.go
+++ b/vendor/github.com/vmware/govmomi/object/common.go
@@ -80,11 +80,6 @@ func (c *Common) SetInventoryPath(p string) {
func (c Common) ObjectName(ctx context.Context) (string, error) {
var o mo.ManagedEntity
- name := c.Name()
- if name != "" {
- return name, nil
- }
-
err := c.Properties(ctx, c.Reference(), []string{"name"}, &o)
if err != nil {
return "", err
diff --git a/vendor/github.com/vmware/govmomi/object/datastore_file.go b/vendor/github.com/vmware/govmomi/object/datastore_file.go
index 1306ef6d..a73990f1 100644
--- a/vendor/github.com/vmware/govmomi/object/datastore_file.go
+++ b/vendor/github.com/vmware/govmomi/object/datastore_file.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2016 VMware, Inc. All Rights Reserved.
+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.
@@ -25,6 +25,7 @@ import (
"net/http"
"os"
"path"
+ "sync"
"time"
"github.com/vmware/govmomi/vim25/soap"
@@ -232,8 +233,9 @@ func (f *DatastoreFile) get() (io.Reader, error) {
return f.body, nil
}
-func lastIndexLines(s []byte, n *int) int64 {
+func lastIndexLines(s []byte, line *int, include func(l int, m string) bool) (int64, bool) {
i := len(s) - 1
+ done := false
for i > 0 {
o := bytes.LastIndexByte(s[:i], '\n')
@@ -241,18 +243,27 @@ func lastIndexLines(s []byte, n *int) int64 {
break
}
- i = o
- *n--
- if *n == 0 {
+ msg := string(s[o+1 : i+1])
+ if !include(*line, msg) {
+ done = true
break
+ } else {
+ i = o
+ *line++
}
}
- return int64(i)
+ return int64(i), done
}
// Tail seeks to the position of the last N lines of the file.
func (f *DatastoreFile) Tail(n int) error {
+ return f.TailFunc(n, func(line int, _ string) bool { return n > line })
+}
+
+// TailFunc will seek backwards in the datastore file until it hits a line that does
+// not satisfy the supplied `include` function.
+func (f *DatastoreFile) TailFunc(lines int, include func(line int, message string) bool) error {
// Read the file in reverse using bsize chunks
const bsize = int64(1024 * 16)
@@ -261,13 +272,14 @@ func (f *DatastoreFile) Tail(n int) error {
return err
}
- if n == 0 {
+ if lines == 0 {
return nil
}
chunk := int64(-1)
buf := bytes.NewBuffer(make([]byte, 0, bsize))
+ line := 0
for {
var eof bool
@@ -298,19 +310,19 @@ func (f *DatastoreFile) Tail(n int) error {
}
b := buf.Bytes()
- idx := lastIndexLines(b, &n) + 1
+ idx, done := lastIndexLines(b, &line, include)
- if n == 0 {
+ if done {
if chunk == -1 {
// We found all N lines in the last chunk of the file.
// The seek offset is also now at the current end of file.
// Save this buffer to avoid another GET request when Read() is called.
- buf.Next(int(idx))
+ buf.Next(int(idx + 1))
f.buf = buf
return nil
}
- if _, err = f.Seek(pos+idx, io.SeekStart); err != nil {
+ if _, err = f.Seek(pos+idx+1, io.SeekStart); err != nil {
return err
}
@@ -336,6 +348,7 @@ type followDatastoreFile struct {
r *DatastoreFile
c chan struct{}
i time.Duration
+ o sync.Once
}
// Read reads up to len(b) bytes from the DatastoreFile being followed.
@@ -344,8 +357,6 @@ func (f *followDatastoreFile) Read(p []byte) (int, error) {
offset := f.r.offset.seek
stop := false
- defer f.r.Close()
-
for {
n, err := f.r.Read(p)
if err != nil && err == io.EOF {
@@ -389,11 +400,15 @@ func (f *followDatastoreFile) Read(p []byte) (int, error) {
// Close will stop Follow polling and close the underlying DatastoreFile.
func (f *followDatastoreFile) Close() error {
- close(f.c)
+ f.o.Do(func() { close(f.c) })
return nil
}
// Follow returns an io.ReadCloser to stream the file contents as data is appended.
func (f *DatastoreFile) Follow(interval time.Duration) io.ReadCloser {
- return &followDatastoreFile{f, make(chan struct{}), interval}
+ return &followDatastoreFile{
+ r: f,
+ c: make(chan struct{}),
+ i: interval,
+ }
}
diff --git a/vendor/github.com/vmware/govmomi/object/datastore_file_manager.go b/vendor/github.com/vmware/govmomi/object/datastore_file_manager.go
new file mode 100644
index 00000000..e4843680
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/object/datastore_file_manager.go
@@ -0,0 +1,164 @@
+/*
+Copyright (c) 2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package object
+
+import (
+ "bufio"
+ "bytes"
+ "context"
+ "fmt"
+ "io"
+ "log"
+ "path"
+ "strings"
+
+ "github.com/vmware/govmomi/vim25/soap"
+)
+
+// DatastoreFileManager combines FileManager and VirtualDiskManager to manage files on a Datastore
+type DatastoreFileManager struct {
+ Datacenter *Datacenter
+ Datastore *Datastore
+ FileManager *FileManager
+ VirtualDiskManager *VirtualDiskManager
+
+ Force bool
+}
+
+// NewFileManager creates a new instance of DatastoreFileManager
+func (d Datastore) NewFileManager(dc *Datacenter, force bool) *DatastoreFileManager {
+ c := d.Client()
+
+ m := &DatastoreFileManager{
+ Datacenter: dc,
+ Datastore: &d,
+ FileManager: NewFileManager(c),
+ VirtualDiskManager: NewVirtualDiskManager(c),
+ Force: force,
+ }
+
+ return m
+}
+
+// Delete dispatches to the appropriate Delete method based on file name extension
+func (m *DatastoreFileManager) Delete(ctx context.Context, name string) error {
+ switch path.Ext(name) {
+ case ".vmdk":
+ return m.DeleteVirtualDisk(ctx, name)
+ default:
+ return m.DeleteFile(ctx, name)
+ }
+}
+
+// DeleteFile calls FileManager.DeleteDatastoreFile
+func (m *DatastoreFileManager) DeleteFile(ctx context.Context, name string) error {
+ p := m.Path(name)
+
+ task, err := m.FileManager.DeleteDatastoreFile(ctx, p.String(), m.Datacenter)
+ if err != nil {
+ return err
+ }
+
+ return task.Wait(ctx)
+}
+
+// DeleteVirtualDisk calls VirtualDiskManager.DeleteVirtualDisk
+// Regardless of the Datastore type, DeleteVirtualDisk will fail if 'ddb.deletable=false',
+// so if Force=true this method attempts to set 'ddb.deletable=true' before starting the delete task.
+func (m *DatastoreFileManager) DeleteVirtualDisk(ctx context.Context, name string) error {
+ p := m.Path(name)
+
+ var merr error
+
+ if m.Force {
+ merr = m.markDiskAsDeletable(ctx, p)
+ }
+
+ task, err := m.VirtualDiskManager.DeleteVirtualDisk(ctx, p.String(), m.Datacenter)
+ if err != nil {
+ log.Printf("markDiskAsDeletable(%s): %s", p, merr)
+ return err
+ }
+
+ return task.Wait(ctx)
+}
+
+// Move dispatches to the appropriate Move method based on file name extension
+func (m *DatastoreFileManager) Move(ctx context.Context, src string, dst string) error {
+ srcp := m.Path(src)
+ dstp := m.Path(dst)
+
+ f := m.FileManager.MoveDatastoreFile
+
+ if srcp.IsVMDK() {
+ f = m.VirtualDiskManager.MoveVirtualDisk
+ }
+
+ task, err := f(ctx, srcp.String(), m.Datacenter, dstp.String(), m.Datacenter, m.Force)
+ if err != nil {
+ return err
+ }
+
+ return task.Wait(ctx)
+}
+
+// Path converts path name to a DatastorePath
+func (m *DatastoreFileManager) Path(name string) *DatastorePath {
+ var p DatastorePath
+
+ if !p.FromString(name) {
+ p.Path = name
+ p.Datastore = m.Datastore.Name()
+ }
+
+ return &p
+}
+
+func (m *DatastoreFileManager) markDiskAsDeletable(ctx context.Context, path *DatastorePath) error {
+ r, _, err := m.Datastore.Download(ctx, path.Path, &soap.DefaultDownload)
+ if err != nil {
+ return err
+ }
+
+ defer r.Close()
+
+ hasFlag := false
+ buf := new(bytes.Buffer)
+
+ s := bufio.NewScanner(&io.LimitedReader{R: r, N: 2048}) // should be only a few hundred bytes, limit to be sure
+
+ for s.Scan() {
+ line := s.Text()
+ if strings.HasPrefix(line, "ddb.deletable") {
+ hasFlag = true
+ continue
+ }
+
+ fmt.Fprintln(buf, line)
+ }
+
+ if err := s.Err(); err != nil {
+ return err // any error other than EOF
+ }
+
+ if !hasFlag {
+ return nil // already deletable, so leave as-is
+ }
+
+ // rewrite the .vmdk with ddb.deletable flag removed (the default is true)
+ return m.Datastore.Upload(ctx, buf, path.Path, &soap.DefaultUpload)
+}
diff --git a/vendor/github.com/vmware/govmomi/object/datastore_path.go b/vendor/github.com/vmware/govmomi/object/datastore_path.go
index ea152103..1563ee1e 100644
--- a/vendor/github.com/vmware/govmomi/object/datastore_path.go
+++ b/vendor/github.com/vmware/govmomi/object/datastore_path.go
@@ -18,6 +18,7 @@ package object
import (
"fmt"
+ "path"
"strings"
)
@@ -63,3 +64,8 @@ func (p *DatastorePath) String() string {
return strings.Join([]string{s, p.Path}, " ")
}
+
+// IsVMDK returns true if Path has a ".vmdk" extension
+func (p *DatastorePath) IsVMDK() bool {
+ return path.Ext(p.Path) == ".vmdk"
+}
diff --git a/vendor/github.com/vmware/govmomi/object/host_config_manager.go b/vendor/github.com/vmware/govmomi/object/host_config_manager.go
index 6f061a6d..123227ec 100644
--- a/vendor/github.com/vmware/govmomi/object/host_config_manager.go
+++ b/vendor/github.com/vmware/govmomi/object/host_config_manager.go
@@ -105,6 +105,22 @@ func (m HostConfigManager) VsanSystem(ctx context.Context) (*HostVsanSystem, err
return NewHostVsanSystem(m.c, *h.ConfigManager.VsanSystem), nil
}
+func (m HostConfigManager) VsanInternalSystem(ctx context.Context) (*HostVsanInternalSystem, error) {
+ var h mo.HostSystem
+
+ err := m.Properties(ctx, m.Reference(), []string{"configManager.vsanInternalSystem"}, &h)
+ if err != nil {
+ return nil, err
+ }
+
+ // Added in 5.5
+ if h.ConfigManager.VsanInternalSystem == nil {
+ return nil, ErrNotSupported
+ }
+
+ return NewHostVsanInternalSystem(m.c, *h.ConfigManager.VsanInternalSystem), nil
+}
+
func (m HostConfigManager) AccountManager(ctx context.Context) (*HostAccountManager, error) {
var h mo.HostSystem
diff --git a/vendor/github.com/vmware/govmomi/object/host_vsan_internal_system.go b/vendor/github.com/vmware/govmomi/object/host_vsan_internal_system.go
new file mode 100644
index 00000000..65e4587f
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/object/host_vsan_internal_system.go
@@ -0,0 +1,117 @@
+/*
+Copyright (c) 2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package object
+
+import (
+ "context"
+ "encoding/json"
+
+ "github.com/vmware/govmomi/vim25"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type HostVsanInternalSystem struct {
+ Common
+}
+
+func NewHostVsanInternalSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostVsanInternalSystem {
+ m := HostVsanInternalSystem{
+ Common: NewCommon(c, ref),
+ }
+
+ return &m
+}
+
+// QueryVsanObjectUuidsByFilter returns vSAN DOM object uuids by filter.
+func (m HostVsanInternalSystem) QueryVsanObjectUuidsByFilter(ctx context.Context, uuids []string, limit int32, version int32) ([]string, error) {
+ req := types.QueryVsanObjectUuidsByFilter{
+ This: m.Reference(),
+ Uuids: uuids,
+ Limit: limit,
+ Version: version,
+ }
+
+ res, err := methods.QueryVsanObjectUuidsByFilter(ctx, m.Client(), &req)
+ if err != nil {
+ return nil, err
+ }
+
+ return res.Returnval, nil
+}
+
+type VsanObjExtAttrs struct {
+ Type string `json:"Object type"`
+ Class string `json:"Object class"`
+ Size string `json:"Object size"`
+ Path string `json:"Object path"`
+ Name string `json:"User friendly name"`
+}
+
+func (a *VsanObjExtAttrs) DatastorePath(dir string) string {
+ l := len(dir)
+ path := a.Path
+
+ if len(path) >= l {
+ path = a.Path[l:]
+ }
+
+ if path != "" {
+ return path
+ }
+
+ return a.Name // vmnamespace
+}
+
+// GetVsanObjExtAttrs is internal and intended for troubleshooting/debugging situations in the field.
+// WARNING: This API can be slow because we do IOs (reads) to all the objects.
+func (m HostVsanInternalSystem) GetVsanObjExtAttrs(ctx context.Context, uuids []string) (map[string]VsanObjExtAttrs, error) {
+ req := types.GetVsanObjExtAttrs{
+ This: m.Reference(),
+ Uuids: uuids,
+ }
+
+ res, err := methods.GetVsanObjExtAttrs(ctx, m.Client(), &req)
+ if err != nil {
+ return nil, err
+ }
+
+ var attrs map[string]VsanObjExtAttrs
+
+ err = json.Unmarshal([]byte(res.Returnval), &attrs)
+
+ return attrs, err
+}
+
+// DeleteVsanObjects is internal and intended for troubleshooting/debugging only.
+// WARNING: This API can be slow because we do IOs to all the objects.
+// DOM won't allow access to objects which have lost quorum. Such objects can be deleted with the optional "force" flag.
+// These objects may however re-appear with quorum if the absent components come back (network partition gets resolved, etc.)
+func (m HostVsanInternalSystem) DeleteVsanObjects(ctx context.Context, uuids []string, force *bool) ([]types.HostVsanInternalSystemDeleteVsanObjectsResult, error) {
+ req := types.DeleteVsanObjects{
+ This: m.Reference(),
+ Uuids: uuids,
+ Force: force,
+ }
+
+ res, err := methods.DeleteVsanObjects(ctx, m.Client(), &req)
+ if err != nil {
+ return nil, err
+ }
+
+ return res.Returnval, nil
+}
diff --git a/vendor/github.com/vmware/govmomi/object/http_nfc_lease.go b/vendor/github.com/vmware/govmomi/object/http_nfc_lease.go
deleted file mode 100644
index 3ca53558..00000000
--- a/vendor/github.com/vmware/govmomi/object/http_nfc_lease.go
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
-Copyright (c) 2015 VMware, Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package object
-
-import (
- "context"
- "errors"
- "fmt"
-
- "github.com/vmware/govmomi/property"
- "github.com/vmware/govmomi/vim25"
- "github.com/vmware/govmomi/vim25/methods"
- "github.com/vmware/govmomi/vim25/mo"
- "github.com/vmware/govmomi/vim25/types"
-)
-
-type HttpNfcLease struct {
- Common
-}
-
-func NewHttpNfcLease(c *vim25.Client, ref types.ManagedObjectReference) *HttpNfcLease {
- return &HttpNfcLease{
- Common: NewCommon(c, ref),
- }
-}
-
-// HttpNfcLeaseAbort wraps methods.HttpNfcLeaseAbort
-func (o HttpNfcLease) HttpNfcLeaseAbort(ctx context.Context, fault *types.LocalizedMethodFault) error {
- req := types.HttpNfcLeaseAbort{
- This: o.Reference(),
- Fault: fault,
- }
-
- _, err := methods.HttpNfcLeaseAbort(ctx, o.c, &req)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-// HttpNfcLeaseComplete wraps methods.HttpNfcLeaseComplete
-func (o HttpNfcLease) HttpNfcLeaseComplete(ctx context.Context) error {
- req := types.HttpNfcLeaseComplete{
- This: o.Reference(),
- }
-
- _, err := methods.HttpNfcLeaseComplete(ctx, o.c, &req)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-// HttpNfcLeaseGetManifest wraps methods.HttpNfcLeaseGetManifest
-func (o HttpNfcLease) HttpNfcLeaseGetManifest(ctx context.Context) error {
- req := types.HttpNfcLeaseGetManifest{
- This: o.Reference(),
- }
-
- _, err := methods.HttpNfcLeaseGetManifest(ctx, o.c, &req)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-// HttpNfcLeaseProgress wraps methods.HttpNfcLeaseProgress
-func (o HttpNfcLease) HttpNfcLeaseProgress(ctx context.Context, percent int32) error {
- req := types.HttpNfcLeaseProgress{
- This: o.Reference(),
- Percent: percent,
- }
-
- _, err := methods.HttpNfcLeaseProgress(ctx, o.c, &req)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func (o HttpNfcLease) Wait(ctx context.Context) (*types.HttpNfcLeaseInfo, error) {
- var lease mo.HttpNfcLease
-
- pc := property.DefaultCollector(o.c)
- err := property.Wait(ctx, pc, o.Reference(), []string{"state", "info", "error"}, func(pc []types.PropertyChange) bool {
- done := false
-
- for _, c := range pc {
- if c.Val == nil {
- continue
- }
-
- switch c.Name {
- case "error":
- val := c.Val.(types.LocalizedMethodFault)
- lease.Error = &val
- done = true
- case "info":
- val := c.Val.(types.HttpNfcLeaseInfo)
- lease.Info = &val
- case "state":
- lease.State = c.Val.(types.HttpNfcLeaseState)
- if lease.State != types.HttpNfcLeaseStateInitializing {
- done = true
- }
- }
- }
-
- return done
- })
-
- if err != nil {
- return nil, err
- }
-
- if lease.State == types.HttpNfcLeaseStateReady {
- return lease.Info, nil
- }
-
- if lease.Error != nil {
- return nil, errors.New(lease.Error.LocalizedMessage)
- }
-
- return nil, fmt.Errorf("unexpected nfc lease state: %s", lease.State)
-}
diff --git a/vendor/github.com/vmware/govmomi/object/list_view.go b/vendor/github.com/vmware/govmomi/object/list_view.go
deleted file mode 100644
index 8c755427..00000000
--- a/vendor/github.com/vmware/govmomi/object/list_view.go
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
-Copyright (c) 2015 VMware, Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package object
-
-import (
- "context"
-
- "github.com/vmware/govmomi/vim25"
- "github.com/vmware/govmomi/vim25/methods"
- "github.com/vmware/govmomi/vim25/types"
-)
-
-type ListView struct {
- Common
-}
-
-func NewListView(c *vim25.Client, ref types.ManagedObjectReference) *ListView {
- return &ListView{
- Common: NewCommon(c, ref),
- }
-}
-
-func (v ListView) Destroy(ctx context.Context) error {
- req := types.DestroyView{
- This: v.Reference(),
- }
- _, err := methods.DestroyView(ctx, v.c, &req)
- return err
-}
-
-func (v ListView) Add(ctx context.Context, refs []types.ManagedObjectReference) error {
- req := types.ModifyListView{
- This: v.Reference(),
- Add: refs,
- }
- _, err := methods.ModifyListView(ctx, v.c, &req)
- return err
-}
-
-func (v ListView) Remove(ctx context.Context, refs []types.ManagedObjectReference) error {
- req := types.ModifyListView{
- This: v.Reference(),
- Remove: refs,
- }
- _, err := methods.ModifyListView(ctx, v.c, &req)
- return err
-}
-
-func (v ListView) Reset(ctx context.Context, refs []types.ManagedObjectReference) error {
- req := types.ResetListView{
- This: v.Reference(),
- Obj: refs,
- }
- _, err := methods.ResetListView(ctx, v.c, &req)
- return err
-}
diff --git a/vendor/github.com/vmware/govmomi/object/network.go b/vendor/github.com/vmware/govmomi/object/network.go
index a76b17d9..d1dc7ce0 100644
--- a/vendor/github.com/vmware/govmomi/object/network.go
+++ b/vendor/github.com/vmware/govmomi/object/network.go
@@ -20,6 +20,7 @@ import (
"context"
"github.com/vmware/govmomi/vim25"
+ "github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
@@ -34,12 +35,20 @@ func NewNetwork(c *vim25.Client, ref types.ManagedObjectReference) *Network {
}
// EthernetCardBackingInfo returns the VirtualDeviceBackingInfo for this Network
-func (n Network) EthernetCardBackingInfo(_ context.Context) (types.BaseVirtualDeviceBackingInfo, error) {
- name := n.Name()
+func (n Network) EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) {
+ var e mo.Network
+
+ // Use Network.Name rather than Common.Name as the latter does not return the complete name if it contains a '/'
+ // We can't use Common.ObjectName here either as we need the ManagedEntity.Name field is not set since mo.Network
+ // has its own Name field.
+ err := n.Properties(ctx, n.Reference(), []string{"name"}, &e)
+ if err != nil {
+ return nil, err
+ }
backing := &types.VirtualEthernetCardNetworkBackingInfo{
VirtualDeviceDeviceBackingInfo: types.VirtualDeviceDeviceBackingInfo{
- DeviceName: name,
+ DeviceName: e.Name,
},
}
diff --git a/vendor/github.com/vmware/govmomi/object/opaque_network.go b/vendor/github.com/vmware/govmomi/object/opaque_network.go
new file mode 100644
index 00000000..47ce4cef
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/object/opaque_network.go
@@ -0,0 +1,57 @@
+/*
+Copyright (c) 2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package object
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/vmware/govmomi/vim25"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type OpaqueNetwork struct {
+ Common
+}
+
+func NewOpaqueNetwork(c *vim25.Client, ref types.ManagedObjectReference) *OpaqueNetwork {
+ return &OpaqueNetwork{
+ Common: NewCommon(c, ref),
+ }
+}
+
+// EthernetCardBackingInfo returns the VirtualDeviceBackingInfo for this Network
+func (n OpaqueNetwork) EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) {
+ var net mo.OpaqueNetwork
+
+ if err := n.Properties(ctx, n.Reference(), []string{"summary"}, &net); err != nil {
+ return nil, err
+ }
+
+ summary, ok := net.Summary.(*types.OpaqueNetworkSummary)
+ if !ok {
+ return nil, fmt.Errorf("%s unsupported network type: %T", n, net.Summary)
+ }
+
+ backing := &types.VirtualEthernetCardOpaqueNetworkBackingInfo{
+ OpaqueNetworkId: summary.OpaqueNetworkId,
+ OpaqueNetworkType: summary.OpaqueNetworkType,
+ }
+
+ return backing, nil
+}
diff --git a/vendor/github.com/vmware/govmomi/object/resource_pool.go b/vendor/github.com/vmware/govmomi/object/resource_pool.go
index 791fd382..55c2e2b2 100644
--- a/vendor/github.com/vmware/govmomi/object/resource_pool.go
+++ b/vendor/github.com/vmware/govmomi/object/resource_pool.go
@@ -19,6 +19,7 @@ package object
import (
"context"
+ "github.com/vmware/govmomi/nfc"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
@@ -34,7 +35,7 @@ func NewResourcePool(c *vim25.Client, ref types.ManagedObjectReference) *Resourc
}
}
-func (p ResourcePool) ImportVApp(ctx context.Context, spec types.BaseImportSpec, folder *Folder, host *HostSystem) (*HttpNfcLease, error) {
+func (p ResourcePool) ImportVApp(ctx context.Context, spec types.BaseImportSpec, folder *Folder, host *HostSystem) (*nfc.Lease, error) {
req := types.ImportVApp{
This: p.Reference(),
Spec: spec,
@@ -55,7 +56,7 @@ func (p ResourcePool) ImportVApp(ctx context.Context, spec types.BaseImportSpec,
return nil, err
}
- return NewHttpNfcLease(p.c, res.Returnval), nil
+ return nfc.NewLease(p.c, res.Returnval), nil
}
func (p ResourcePool) Create(ctx context.Context, name string, spec types.ResourceConfigSpec) (*ResourcePool, error) {
diff --git a/vendor/github.com/vmware/govmomi/object/task.go b/vendor/github.com/vmware/govmomi/object/task.go
index 8572b436..2b66aa93 100644
--- a/vendor/github.com/vmware/govmomi/object/task.go
+++ b/vendor/github.com/vmware/govmomi/object/task.go
@@ -22,6 +22,7 @@ import (
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/task"
"github.com/vmware/govmomi/vim25"
+ "github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/progress"
"github.com/vmware/govmomi/vim25/types"
)
@@ -51,3 +52,11 @@ func (t *Task) WaitForResult(ctx context.Context, s progress.Sinker) (*types.Tas
p := property.DefaultCollector(t.c)
return task.Wait(ctx, t.Reference(), p, s)
}
+
+func (t *Task) Cancel(ctx context.Context) error {
+ _, err := methods.CancelTask(ctx, t.Client(), &types.CancelTask{
+ This: t.Reference(),
+ })
+
+ return err
+}
diff --git a/vendor/github.com/vmware/govmomi/object/virtual_disk_manager_internal.go b/vendor/github.com/vmware/govmomi/object/virtual_disk_manager_internal.go
new file mode 100644
index 00000000..642cd62f
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/object/virtual_disk_manager_internal.go
@@ -0,0 +1,97 @@
+/*
+Copyright (c) 2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package object
+
+import (
+ "context"
+ "reflect"
+
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+func init() {
+ types.Add("ArrayOfVirtualDiskInfo", reflect.TypeOf((*arrayOfVirtualDiskInfo)(nil)).Elem())
+
+ types.Add("VirtualDiskInfo", reflect.TypeOf((*VirtualDiskInfo)(nil)).Elem())
+}
+
+type arrayOfVirtualDiskInfo struct {
+ VirtualDiskInfo []VirtualDiskInfo `xml:"VirtualDiskInfo,omitempty"`
+}
+
+type queryVirtualDiskInfoTaskRequest struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Name string `xml:"name"`
+ Datacenter *types.ManagedObjectReference `xml:"datacenter,omitempty"`
+ IncludeParents bool `xml:"includeParents"`
+}
+
+type queryVirtualDiskInfoTaskResponse struct {
+ Returnval types.ManagedObjectReference `xml:"returnval"`
+}
+
+type queryVirtualDiskInfoTaskBody struct {
+ Req *queryVirtualDiskInfoTaskRequest `xml:"urn:internalvim25 QueryVirtualDiskInfo_Task,omitempty"`
+ Res *queryVirtualDiskInfoTaskResponse `xml:"urn:vim25 QueryVirtualDiskInfo_TaskResponse,omitempty"`
+ Err *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *queryVirtualDiskInfoTaskBody) Fault() *soap.Fault { return b.Err }
+
+func queryVirtualDiskInfoTask(ctx context.Context, r soap.RoundTripper, req *queryVirtualDiskInfoTaskRequest) (*queryVirtualDiskInfoTaskResponse, error) {
+ var reqBody, resBody queryVirtualDiskInfoTaskBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type VirtualDiskInfo struct {
+ Name string `xml:"unit>name"`
+ DiskType string `xml:"diskType"`
+ Parent string `xml:"parent,omitempty"`
+}
+
+func (m VirtualDiskManager) QueryVirtualDiskInfo(ctx context.Context, name string, dc *Datacenter, includeParents bool) ([]VirtualDiskInfo, error) {
+ req := queryVirtualDiskInfoTaskRequest{
+ This: m.Reference(),
+ Name: name,
+ IncludeParents: includeParents,
+ }
+
+ if dc != nil {
+ ref := dc.Reference()
+ req.Datacenter = &ref
+ }
+
+ res, err := queryVirtualDiskInfoTask(ctx, m.Client(), &req)
+ if err != nil {
+ return nil, err
+ }
+
+ info, err := NewTask(m.Client(), res.Returnval).WaitForResult(ctx, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return info.Result.(arrayOfVirtualDiskInfo).VirtualDiskInfo, nil
+}
diff --git a/vendor/github.com/vmware/govmomi/object/virtual_machine.go b/vendor/github.com/vmware/govmomi/object/virtual_machine.go
index 87ae9a51..02c4e237 100644
--- a/vendor/github.com/vmware/govmomi/object/virtual_machine.go
+++ b/vendor/github.com/vmware/govmomi/object/virtual_machine.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2015 VMware, Inc. All Rights Reserved.
+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.
@@ -518,11 +518,11 @@ func (m snapshotMap) add(parent string, tree []types.VirtualMachineSnapshotTree)
}
}
-// findSnapshot supports snapshot lookup by name, where name can be:
+// FindSnapshot supports snapshot lookup by name, where name can be:
// 1) snapshot ManagedObjectReference.Value (unique)
// 2) snapshot name (may not be unique)
// 3) snapshot tree path (may not be unique)
-func (v VirtualMachine) findSnapshot(ctx context.Context, name string) (Reference, error) {
+func (v VirtualMachine) FindSnapshot(ctx context.Context, name string) (Reference, error) {
var o mo.VirtualMachine
err := v.Properties(ctx, v.Reference(), []string{"snapshot"}, &o)
@@ -550,7 +550,7 @@ func (v VirtualMachine) findSnapshot(ctx context.Context, name string) (Referenc
// RemoveSnapshot removes a named snapshot
func (v VirtualMachine) RemoveSnapshot(ctx context.Context, name string, removeChildren bool, consolidate *bool) (*Task, error) {
- snapshot, err := v.findSnapshot(ctx, name)
+ snapshot, err := v.FindSnapshot(ctx, name)
if err != nil {
return nil, err
}
@@ -586,7 +586,7 @@ func (v VirtualMachine) RevertToCurrentSnapshot(ctx context.Context, suppressPow
// RevertToSnapshot reverts to a named snapshot
func (v VirtualMachine) RevertToSnapshot(ctx context.Context, name string, suppressPowerOn bool) (*Task, error) {
- snapshot, err := v.findSnapshot(ctx, name)
+ snapshot, err := v.FindSnapshot(ctx, name)
if err != nil {
return nil, err
}
@@ -725,3 +725,35 @@ func (v VirtualMachine) QueryConfigTarget(ctx context.Context) (*types.ConfigTar
return res.Returnval, nil
}
+
+func (v VirtualMachine) MountToolsInstaller(ctx context.Context) error {
+ req := types.MountToolsInstaller{
+ This: v.Reference(),
+ }
+
+ _, err := methods.MountToolsInstaller(ctx, v.Client(), &req)
+ return err
+}
+
+func (v VirtualMachine) UnmountToolsInstaller(ctx context.Context) error {
+ req := types.UnmountToolsInstaller{
+ This: v.Reference(),
+ }
+
+ _, err := methods.UnmountToolsInstaller(ctx, v.Client(), &req)
+ return err
+}
+
+func (v VirtualMachine) UpgradeTools(ctx context.Context, options string) (*Task, error) {
+ req := types.UpgradeTools_Task{
+ This: v.Reference(),
+ InstallerOptions: options,
+ }
+
+ res, err := methods.UpgradeTools_Task(ctx, v.Client(), &req)
+ if err != nil {
+ return nil, err
+ }
+
+ return NewTask(v.c, res.Returnval), nil
+}
diff --git a/vendor/github.com/vmware/govmomi/object/ovf_manager.go b/vendor/github.com/vmware/govmomi/ovf/manager.go
similarity index 55%
rename from vendor/github.com/vmware/govmomi/object/ovf_manager.go
rename to vendor/github.com/vmware/govmomi/ovf/manager.go
index 7fedf689..3ee2afdd 100644
--- a/vendor/github.com/vmware/govmomi/object/ovf_manager.go
+++ b/vendor/github.com/vmware/govmomi/ovf/manager.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2015 VMware, Inc. All Rights Reserved.
+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.
@@ -14,37 +14,36 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package object
+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 OvfManager struct {
- Common
-}
+type Manager struct {
+ types.ManagedObjectReference
-func NewOvfManager(c *vim25.Client) *OvfManager {
- o := OvfManager{
- Common: NewCommon(c, *c.ServiceContent.OvfManager),
- }
+ c *vim25.Client
+}
- return &o
+func NewManager(c *vim25.Client) *Manager {
+ return &Manager{*c.ServiceContent.OvfManager, c}
}
// CreateDescriptor wraps methods.CreateDescriptor
-func (o OvfManager) CreateDescriptor(ctx context.Context, obj Reference, cdp types.OvfCreateDescriptorParams) (*types.OvfCreateDescriptorResult, error) {
+func (m *Manager) CreateDescriptor(ctx context.Context, obj mo.Reference, cdp types.OvfCreateDescriptorParams) (*types.OvfCreateDescriptorResult, error) {
req := types.CreateDescriptor{
- This: o.Reference(),
+ This: m.Reference(),
Obj: obj.Reference(),
Cdp: cdp,
}
- res, err := methods.CreateDescriptor(ctx, o.c, &req)
+ res, err := methods.CreateDescriptor(ctx, m.c, &req)
if err != nil {
return nil, err
}
@@ -53,16 +52,16 @@ func (o OvfManager) CreateDescriptor(ctx context.Context, obj Reference, cdp typ
}
// CreateImportSpec wraps methods.CreateImportSpec
-func (o OvfManager) CreateImportSpec(ctx context.Context, ovfDescriptor string, resourcePool Reference, datastore Reference, cisp types.OvfCreateImportSpecParams) (*types.OvfCreateImportSpecResult, error) {
+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: o.Reference(),
+ This: m.Reference(),
OvfDescriptor: ovfDescriptor,
ResourcePool: resourcePool.Reference(),
Datastore: datastore.Reference(),
Cisp: cisp,
}
- res, err := methods.CreateImportSpec(ctx, o.c, &req)
+ res, err := methods.CreateImportSpec(ctx, m.c, &req)
if err != nil {
return nil, err
}
@@ -71,14 +70,14 @@ func (o OvfManager) CreateImportSpec(ctx context.Context, ovfDescriptor string,
}
// ParseDescriptor wraps methods.ParseDescriptor
-func (o OvfManager) ParseDescriptor(ctx context.Context, ovfDescriptor string, pdp types.OvfParseDescriptorParams) (*types.OvfParseDescriptorResult, error) {
+func (m *Manager) ParseDescriptor(ctx context.Context, ovfDescriptor string, pdp types.OvfParseDescriptorParams) (*types.OvfParseDescriptorResult, error) {
req := types.ParseDescriptor{
- This: o.Reference(),
+ This: m.Reference(),
OvfDescriptor: ovfDescriptor,
Pdp: pdp,
}
- res, err := methods.ParseDescriptor(ctx, o.c, &req)
+ res, err := methods.ParseDescriptor(ctx, m.c, &req)
if err != nil {
return nil, err
}
@@ -87,15 +86,15 @@ func (o OvfManager) ParseDescriptor(ctx context.Context, ovfDescriptor string, p
}
// ValidateHost wraps methods.ValidateHost
-func (o OvfManager) ValidateHost(ctx context.Context, ovfDescriptor string, host Reference, vhp types.OvfValidateHostParams) (*types.OvfValidateHostResult, error) {
+func (m *Manager) ValidateHost(ctx context.Context, ovfDescriptor string, host mo.Reference, vhp types.OvfValidateHostParams) (*types.OvfValidateHostResult, error) {
req := types.ValidateHost{
- This: o.Reference(),
+ This: m.Reference(),
OvfDescriptor: ovfDescriptor,
Host: host.Reference(),
Vhp: vhp,
}
- res, err := methods.ValidateHost(ctx, o.c, &req)
+ res, err := methods.ValidateHost(ctx, m.c, &req)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/vmware/govmomi/pbm/client.go b/vendor/github.com/vmware/govmomi/pbm/client.go
new file mode 100644
index 00000000..a0f07fc9
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/pbm/client.go
@@ -0,0 +1,217 @@
+/*
+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 pbm
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/vmware/govmomi/pbm/methods"
+ "github.com/vmware/govmomi/pbm/types"
+ "github.com/vmware/govmomi/vim25"
+ "github.com/vmware/govmomi/vim25/soap"
+ vim "github.com/vmware/govmomi/vim25/types"
+)
+
+type Client struct {
+ *soap.Client
+
+ ServiceContent types.PbmServiceInstanceContent
+}
+
+func NewClient(ctx context.Context, c *vim25.Client) (*Client, error) {
+ sc := c.Client.NewServiceClient("/pbm/sdk", "urn:pbm")
+
+ req := types.PbmRetrieveServiceContent{
+ This: vim.ManagedObjectReference{
+ Type: "PbmServiceInstance",
+ Value: "ServiceInstance",
+ },
+ }
+
+ res, err := methods.PbmRetrieveServiceContent(ctx, sc, &req)
+ if err != nil {
+ return nil, err
+ }
+
+ return &Client{sc, res.Returnval}, nil
+}
+
+func (c *Client) QueryProfile(ctx context.Context, rtype types.PbmProfileResourceType, category string) ([]types.PbmProfileId, error) {
+ req := types.PbmQueryProfile{
+ This: c.ServiceContent.ProfileManager,
+ ResourceType: rtype,
+ ProfileCategory: category,
+ }
+
+ res, err := methods.PbmQueryProfile(ctx, c, &req)
+ if err != nil {
+ return nil, err
+ }
+
+ return res.Returnval, nil
+}
+
+func (c *Client) RetrieveContent(ctx context.Context, ids []types.PbmProfileId) ([]types.BasePbmProfile, error) {
+ req := types.PbmRetrieveContent{
+ This: c.ServiceContent.ProfileManager,
+ ProfileIds: ids,
+ }
+
+ res, err := methods.PbmRetrieveContent(ctx, c, &req)
+ if err != nil {
+ return nil, err
+ }
+
+ return res.Returnval, nil
+}
+
+type PlacementCompatibilityResult []types.PbmPlacementCompatibilityResult
+
+func (c *Client) CheckRequirements(ctx context.Context, hubs []types.PbmPlacementHub, ref *types.PbmServerObjectRef, preq []types.BasePbmPlacementRequirement) (PlacementCompatibilityResult, error) {
+ req := types.PbmCheckRequirements{
+ This: c.ServiceContent.PlacementSolver,
+ HubsToSearch: hubs,
+ PlacementSubjectRef: ref,
+ PlacementSubjectRequirement: preq,
+ }
+
+ res, err := methods.PbmCheckRequirements(ctx, c, &req)
+ if err != nil {
+ return nil, err
+ }
+
+ return res.Returnval, nil
+}
+
+func (l PlacementCompatibilityResult) CompatibleDatastores() []types.PbmPlacementHub {
+ var compatibleDatastores []types.PbmPlacementHub
+
+ for _, res := range l {
+ if len(res.Error) == 0 {
+ compatibleDatastores = append(compatibleDatastores, res.Hub)
+ }
+ }
+ return compatibleDatastores
+}
+
+func (l PlacementCompatibilityResult) NonCompatibleDatastores() []types.PbmPlacementHub {
+ var nonCompatibleDatastores []types.PbmPlacementHub
+
+ for _, res := range l {
+ if len(res.Error) > 0 {
+ nonCompatibleDatastores = append(nonCompatibleDatastores, res.Hub)
+ }
+ }
+ return nonCompatibleDatastores
+}
+
+func (c *Client) CreateProfile(ctx context.Context, capabilityProfileCreateSpec types.PbmCapabilityProfileCreateSpec) (*types.PbmProfileId, error) {
+ req := types.PbmCreate{
+ This: c.ServiceContent.ProfileManager,
+ CreateSpec: capabilityProfileCreateSpec,
+ }
+
+ res, err := methods.PbmCreate(ctx, c, &req)
+ if err != nil {
+ return nil, err
+ }
+
+ return &res.Returnval, nil
+}
+
+func (c *Client) UpdateProfile(ctx context.Context, id types.PbmProfileId, updateSpec types.PbmCapabilityProfileUpdateSpec) error {
+ req := types.PbmUpdate{
+ This: c.ServiceContent.ProfileManager,
+ ProfileId: id,
+ UpdateSpec: updateSpec,
+ }
+
+ _, err := methods.PbmUpdate(ctx, c, &req)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (c *Client) DeleteProfile(ctx context.Context, ids []types.PbmProfileId) ([]types.PbmProfileOperationOutcome, error) {
+ req := types.PbmDelete{
+ This: c.ServiceContent.ProfileManager,
+ ProfileId: ids,
+ }
+
+ res, err := methods.PbmDelete(ctx, c, &req)
+ if err != nil {
+ return nil, err
+ }
+
+ return res.Returnval, nil
+}
+
+func (c *Client) QueryAssociatedEntity(ctx context.Context, id types.PbmProfileId, entityType string) ([]types.PbmServerObjectRef, error) {
+ req := types.PbmQueryAssociatedEntity{
+ This: c.ServiceContent.ProfileManager,
+ Profile: id,
+ EntityType: entityType,
+ }
+
+ res, err := methods.PbmQueryAssociatedEntity(ctx, c, &req)
+ if err != nil {
+ return nil, err
+ }
+
+ return res.Returnval, nil
+}
+
+func (c *Client) QueryAssociatedEntities(ctx context.Context, ids []types.PbmProfileId) ([]types.PbmQueryProfileResult, error) {
+ req := types.PbmQueryAssociatedEntities{
+ This: c.ServiceContent.ProfileManager,
+ Profiles: ids,
+ }
+
+ res, err := methods.PbmQueryAssociatedEntities(ctx, c, &req)
+ if err != nil {
+ return nil, err
+ }
+
+ return res.Returnval, nil
+}
+
+func (c *Client) ProfileIDByName(ctx context.Context, profileName string) (string, error) {
+ resourceType := types.PbmProfileResourceType{
+ ResourceType: string(types.PbmProfileResourceTypeEnumSTORAGE),
+ }
+ category := types.PbmProfileCategoryEnumREQUIREMENT
+ ids, err := c.QueryProfile(ctx, resourceType, string(category))
+ if err != nil {
+ return "", err
+ }
+
+ profiles, err := c.RetrieveContent(ctx, ids)
+ if err != nil {
+ return "", err
+ }
+
+ for i := range profiles {
+ profile := profiles[i].GetPbmProfile()
+ if profile.Name == profileName {
+ return profile.ProfileId.UniqueId, nil
+ }
+ }
+ return "", fmt.Errorf("no pbm profile found with name: %q", profileName)
+}
diff --git a/vendor/github.com/vmware/govmomi/pbm/methods/methods.go b/vendor/github.com/vmware/govmomi/pbm/methods/methods.go
new file mode 100644
index 00000000..08ee48e9
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/pbm/methods/methods.go
@@ -0,0 +1,664 @@
+/*
+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 methods
+
+import (
+ "context"
+
+ "github.com/vmware/govmomi/pbm/types"
+ "github.com/vmware/govmomi/vim25/soap"
+)
+
+type PbmAssignDefaultRequirementProfileBody struct {
+ Req *types.PbmAssignDefaultRequirementProfile `xml:"urn:pbm PbmAssignDefaultRequirementProfile,omitempty"`
+ Res *types.PbmAssignDefaultRequirementProfileResponse `xml:"urn:pbm PbmAssignDefaultRequirementProfileResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmAssignDefaultRequirementProfileBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmAssignDefaultRequirementProfile(ctx context.Context, r soap.RoundTripper, req *types.PbmAssignDefaultRequirementProfile) (*types.PbmAssignDefaultRequirementProfileResponse, error) {
+ var reqBody, resBody PbmAssignDefaultRequirementProfileBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmCheckCompatibilityBody struct {
+ Req *types.PbmCheckCompatibility `xml:"urn:pbm PbmCheckCompatibility,omitempty"`
+ Res *types.PbmCheckCompatibilityResponse `xml:"urn:pbm PbmCheckCompatibilityResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmCheckCompatibilityBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmCheckCompatibility(ctx context.Context, r soap.RoundTripper, req *types.PbmCheckCompatibility) (*types.PbmCheckCompatibilityResponse, error) {
+ var reqBody, resBody PbmCheckCompatibilityBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmCheckCompatibilityWithSpecBody struct {
+ Req *types.PbmCheckCompatibilityWithSpec `xml:"urn:pbm PbmCheckCompatibilityWithSpec,omitempty"`
+ Res *types.PbmCheckCompatibilityWithSpecResponse `xml:"urn:pbm PbmCheckCompatibilityWithSpecResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmCheckCompatibilityWithSpecBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmCheckCompatibilityWithSpec(ctx context.Context, r soap.RoundTripper, req *types.PbmCheckCompatibilityWithSpec) (*types.PbmCheckCompatibilityWithSpecResponse, error) {
+ var reqBody, resBody PbmCheckCompatibilityWithSpecBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmCheckComplianceBody struct {
+ Req *types.PbmCheckCompliance `xml:"urn:pbm PbmCheckCompliance,omitempty"`
+ Res *types.PbmCheckComplianceResponse `xml:"urn:pbm PbmCheckComplianceResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmCheckComplianceBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmCheckCompliance(ctx context.Context, r soap.RoundTripper, req *types.PbmCheckCompliance) (*types.PbmCheckComplianceResponse, error) {
+ var reqBody, resBody PbmCheckComplianceBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmCheckRequirementsBody struct {
+ Req *types.PbmCheckRequirements `xml:"urn:pbm PbmCheckRequirements,omitempty"`
+ Res *types.PbmCheckRequirementsResponse `xml:"urn:pbm PbmCheckRequirementsResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmCheckRequirementsBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmCheckRequirements(ctx context.Context, r soap.RoundTripper, req *types.PbmCheckRequirements) (*types.PbmCheckRequirementsResponse, error) {
+ var reqBody, resBody PbmCheckRequirementsBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmCheckRollupComplianceBody struct {
+ Req *types.PbmCheckRollupCompliance `xml:"urn:pbm PbmCheckRollupCompliance,omitempty"`
+ Res *types.PbmCheckRollupComplianceResponse `xml:"urn:pbm PbmCheckRollupComplianceResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmCheckRollupComplianceBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmCheckRollupCompliance(ctx context.Context, r soap.RoundTripper, req *types.PbmCheckRollupCompliance) (*types.PbmCheckRollupComplianceResponse, error) {
+ var reqBody, resBody PbmCheckRollupComplianceBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmCreateBody struct {
+ Req *types.PbmCreate `xml:"urn:pbm PbmCreate,omitempty"`
+ Res *types.PbmCreateResponse `xml:"urn:pbm PbmCreateResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmCreateBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmCreate(ctx context.Context, r soap.RoundTripper, req *types.PbmCreate) (*types.PbmCreateResponse, error) {
+ var reqBody, resBody PbmCreateBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmDeleteBody struct {
+ Req *types.PbmDelete `xml:"urn:pbm PbmDelete,omitempty"`
+ Res *types.PbmDeleteResponse `xml:"urn:pbm PbmDeleteResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmDeleteBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmDelete(ctx context.Context, r soap.RoundTripper, req *types.PbmDelete) (*types.PbmDeleteResponse, error) {
+ var reqBody, resBody PbmDeleteBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmFetchCapabilityMetadataBody struct {
+ Req *types.PbmFetchCapabilityMetadata `xml:"urn:pbm PbmFetchCapabilityMetadata,omitempty"`
+ Res *types.PbmFetchCapabilityMetadataResponse `xml:"urn:pbm PbmFetchCapabilityMetadataResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmFetchCapabilityMetadataBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmFetchCapabilityMetadata(ctx context.Context, r soap.RoundTripper, req *types.PbmFetchCapabilityMetadata) (*types.PbmFetchCapabilityMetadataResponse, error) {
+ var reqBody, resBody PbmFetchCapabilityMetadataBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmFetchCapabilitySchemaBody struct {
+ Req *types.PbmFetchCapabilitySchema `xml:"urn:pbm PbmFetchCapabilitySchema,omitempty"`
+ Res *types.PbmFetchCapabilitySchemaResponse `xml:"urn:pbm PbmFetchCapabilitySchemaResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmFetchCapabilitySchemaBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmFetchCapabilitySchema(ctx context.Context, r soap.RoundTripper, req *types.PbmFetchCapabilitySchema) (*types.PbmFetchCapabilitySchemaResponse, error) {
+ var reqBody, resBody PbmFetchCapabilitySchemaBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmFetchComplianceResultBody struct {
+ Req *types.PbmFetchComplianceResult `xml:"urn:pbm PbmFetchComplianceResult,omitempty"`
+ Res *types.PbmFetchComplianceResultResponse `xml:"urn:pbm PbmFetchComplianceResultResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmFetchComplianceResultBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmFetchComplianceResult(ctx context.Context, r soap.RoundTripper, req *types.PbmFetchComplianceResult) (*types.PbmFetchComplianceResultResponse, error) {
+ var reqBody, resBody PbmFetchComplianceResultBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmFetchResourceTypeBody struct {
+ Req *types.PbmFetchResourceType `xml:"urn:pbm PbmFetchResourceType,omitempty"`
+ Res *types.PbmFetchResourceTypeResponse `xml:"urn:pbm PbmFetchResourceTypeResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmFetchResourceTypeBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmFetchResourceType(ctx context.Context, r soap.RoundTripper, req *types.PbmFetchResourceType) (*types.PbmFetchResourceTypeResponse, error) {
+ var reqBody, resBody PbmFetchResourceTypeBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmFetchRollupComplianceResultBody struct {
+ Req *types.PbmFetchRollupComplianceResult `xml:"urn:pbm PbmFetchRollupComplianceResult,omitempty"`
+ Res *types.PbmFetchRollupComplianceResultResponse `xml:"urn:pbm PbmFetchRollupComplianceResultResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmFetchRollupComplianceResultBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmFetchRollupComplianceResult(ctx context.Context, r soap.RoundTripper, req *types.PbmFetchRollupComplianceResult) (*types.PbmFetchRollupComplianceResultResponse, error) {
+ var reqBody, resBody PbmFetchRollupComplianceResultBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmFetchVendorInfoBody struct {
+ Req *types.PbmFetchVendorInfo `xml:"urn:pbm PbmFetchVendorInfo,omitempty"`
+ Res *types.PbmFetchVendorInfoResponse `xml:"urn:pbm PbmFetchVendorInfoResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmFetchVendorInfoBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmFetchVendorInfo(ctx context.Context, r soap.RoundTripper, req *types.PbmFetchVendorInfo) (*types.PbmFetchVendorInfoResponse, error) {
+ var reqBody, resBody PbmFetchVendorInfoBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmFindApplicableDefaultProfileBody struct {
+ Req *types.PbmFindApplicableDefaultProfile `xml:"urn:pbm PbmFindApplicableDefaultProfile,omitempty"`
+ Res *types.PbmFindApplicableDefaultProfileResponse `xml:"urn:pbm PbmFindApplicableDefaultProfileResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmFindApplicableDefaultProfileBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmFindApplicableDefaultProfile(ctx context.Context, r soap.RoundTripper, req *types.PbmFindApplicableDefaultProfile) (*types.PbmFindApplicableDefaultProfileResponse, error) {
+ var reqBody, resBody PbmFindApplicableDefaultProfileBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmQueryAssociatedEntitiesBody struct {
+ Req *types.PbmQueryAssociatedEntities `xml:"urn:pbm PbmQueryAssociatedEntities,omitempty"`
+ Res *types.PbmQueryAssociatedEntitiesResponse `xml:"urn:pbm PbmQueryAssociatedEntitiesResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmQueryAssociatedEntitiesBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmQueryAssociatedEntities(ctx context.Context, r soap.RoundTripper, req *types.PbmQueryAssociatedEntities) (*types.PbmQueryAssociatedEntitiesResponse, error) {
+ var reqBody, resBody PbmQueryAssociatedEntitiesBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmQueryAssociatedEntityBody struct {
+ Req *types.PbmQueryAssociatedEntity `xml:"urn:pbm PbmQueryAssociatedEntity,omitempty"`
+ Res *types.PbmQueryAssociatedEntityResponse `xml:"urn:pbm PbmQueryAssociatedEntityResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmQueryAssociatedEntityBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmQueryAssociatedEntity(ctx context.Context, r soap.RoundTripper, req *types.PbmQueryAssociatedEntity) (*types.PbmQueryAssociatedEntityResponse, error) {
+ var reqBody, resBody PbmQueryAssociatedEntityBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmQueryAssociatedProfileBody struct {
+ Req *types.PbmQueryAssociatedProfile `xml:"urn:pbm PbmQueryAssociatedProfile,omitempty"`
+ Res *types.PbmQueryAssociatedProfileResponse `xml:"urn:pbm PbmQueryAssociatedProfileResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmQueryAssociatedProfileBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmQueryAssociatedProfile(ctx context.Context, r soap.RoundTripper, req *types.PbmQueryAssociatedProfile) (*types.PbmQueryAssociatedProfileResponse, error) {
+ var reqBody, resBody PbmQueryAssociatedProfileBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmQueryAssociatedProfilesBody struct {
+ Req *types.PbmQueryAssociatedProfiles `xml:"urn:pbm PbmQueryAssociatedProfiles,omitempty"`
+ Res *types.PbmQueryAssociatedProfilesResponse `xml:"urn:pbm PbmQueryAssociatedProfilesResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmQueryAssociatedProfilesBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmQueryAssociatedProfiles(ctx context.Context, r soap.RoundTripper, req *types.PbmQueryAssociatedProfiles) (*types.PbmQueryAssociatedProfilesResponse, error) {
+ var reqBody, resBody PbmQueryAssociatedProfilesBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmQueryByRollupComplianceStatusBody struct {
+ Req *types.PbmQueryByRollupComplianceStatus `xml:"urn:pbm PbmQueryByRollupComplianceStatus,omitempty"`
+ Res *types.PbmQueryByRollupComplianceStatusResponse `xml:"urn:pbm PbmQueryByRollupComplianceStatusResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmQueryByRollupComplianceStatusBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmQueryByRollupComplianceStatus(ctx context.Context, r soap.RoundTripper, req *types.PbmQueryByRollupComplianceStatus) (*types.PbmQueryByRollupComplianceStatusResponse, error) {
+ var reqBody, resBody PbmQueryByRollupComplianceStatusBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmQueryDefaultRequirementProfileBody struct {
+ Req *types.PbmQueryDefaultRequirementProfile `xml:"urn:pbm PbmQueryDefaultRequirementProfile,omitempty"`
+ Res *types.PbmQueryDefaultRequirementProfileResponse `xml:"urn:pbm PbmQueryDefaultRequirementProfileResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmQueryDefaultRequirementProfileBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmQueryDefaultRequirementProfile(ctx context.Context, r soap.RoundTripper, req *types.PbmQueryDefaultRequirementProfile) (*types.PbmQueryDefaultRequirementProfileResponse, error) {
+ var reqBody, resBody PbmQueryDefaultRequirementProfileBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmQueryDefaultRequirementProfilesBody struct {
+ Req *types.PbmQueryDefaultRequirementProfiles `xml:"urn:pbm PbmQueryDefaultRequirementProfiles,omitempty"`
+ Res *types.PbmQueryDefaultRequirementProfilesResponse `xml:"urn:pbm PbmQueryDefaultRequirementProfilesResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmQueryDefaultRequirementProfilesBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmQueryDefaultRequirementProfiles(ctx context.Context, r soap.RoundTripper, req *types.PbmQueryDefaultRequirementProfiles) (*types.PbmQueryDefaultRequirementProfilesResponse, error) {
+ var reqBody, resBody PbmQueryDefaultRequirementProfilesBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmQueryMatchingHubBody struct {
+ Req *types.PbmQueryMatchingHub `xml:"urn:pbm PbmQueryMatchingHub,omitempty"`
+ Res *types.PbmQueryMatchingHubResponse `xml:"urn:pbm PbmQueryMatchingHubResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmQueryMatchingHubBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmQueryMatchingHub(ctx context.Context, r soap.RoundTripper, req *types.PbmQueryMatchingHub) (*types.PbmQueryMatchingHubResponse, error) {
+ var reqBody, resBody PbmQueryMatchingHubBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmQueryMatchingHubWithSpecBody struct {
+ Req *types.PbmQueryMatchingHubWithSpec `xml:"urn:pbm PbmQueryMatchingHubWithSpec,omitempty"`
+ Res *types.PbmQueryMatchingHubWithSpecResponse `xml:"urn:pbm PbmQueryMatchingHubWithSpecResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmQueryMatchingHubWithSpecBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmQueryMatchingHubWithSpec(ctx context.Context, r soap.RoundTripper, req *types.PbmQueryMatchingHubWithSpec) (*types.PbmQueryMatchingHubWithSpecResponse, error) {
+ var reqBody, resBody PbmQueryMatchingHubWithSpecBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmQueryProfileBody struct {
+ Req *types.PbmQueryProfile `xml:"urn:pbm PbmQueryProfile,omitempty"`
+ Res *types.PbmQueryProfileResponse `xml:"urn:pbm PbmQueryProfileResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmQueryProfileBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmQueryProfile(ctx context.Context, r soap.RoundTripper, req *types.PbmQueryProfile) (*types.PbmQueryProfileResponse, error) {
+ var reqBody, resBody PbmQueryProfileBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmQueryReplicationGroupsBody struct {
+ Req *types.PbmQueryReplicationGroups `xml:"urn:pbm PbmQueryReplicationGroups,omitempty"`
+ Res *types.PbmQueryReplicationGroupsResponse `xml:"urn:pbm PbmQueryReplicationGroupsResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmQueryReplicationGroupsBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmQueryReplicationGroups(ctx context.Context, r soap.RoundTripper, req *types.PbmQueryReplicationGroups) (*types.PbmQueryReplicationGroupsResponse, error) {
+ var reqBody, resBody PbmQueryReplicationGroupsBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmQuerySpaceStatsForStorageContainerBody struct {
+ Req *types.PbmQuerySpaceStatsForStorageContainer `xml:"urn:pbm PbmQuerySpaceStatsForStorageContainer,omitempty"`
+ Res *types.PbmQuerySpaceStatsForStorageContainerResponse `xml:"urn:pbm PbmQuerySpaceStatsForStorageContainerResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmQuerySpaceStatsForStorageContainerBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmQuerySpaceStatsForStorageContainer(ctx context.Context, r soap.RoundTripper, req *types.PbmQuerySpaceStatsForStorageContainer) (*types.PbmQuerySpaceStatsForStorageContainerResponse, error) {
+ var reqBody, resBody PbmQuerySpaceStatsForStorageContainerBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmResetDefaultRequirementProfileBody struct {
+ Req *types.PbmResetDefaultRequirementProfile `xml:"urn:pbm PbmResetDefaultRequirementProfile,omitempty"`
+ Res *types.PbmResetDefaultRequirementProfileResponse `xml:"urn:pbm PbmResetDefaultRequirementProfileResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmResetDefaultRequirementProfileBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmResetDefaultRequirementProfile(ctx context.Context, r soap.RoundTripper, req *types.PbmResetDefaultRequirementProfile) (*types.PbmResetDefaultRequirementProfileResponse, error) {
+ var reqBody, resBody PbmResetDefaultRequirementProfileBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmResetVSanDefaultProfileBody struct {
+ Req *types.PbmResetVSanDefaultProfile `xml:"urn:pbm PbmResetVSanDefaultProfile,omitempty"`
+ Res *types.PbmResetVSanDefaultProfileResponse `xml:"urn:pbm PbmResetVSanDefaultProfileResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmResetVSanDefaultProfileBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmResetVSanDefaultProfile(ctx context.Context, r soap.RoundTripper, req *types.PbmResetVSanDefaultProfile) (*types.PbmResetVSanDefaultProfileResponse, error) {
+ var reqBody, resBody PbmResetVSanDefaultProfileBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmRetrieveContentBody struct {
+ Req *types.PbmRetrieveContent `xml:"urn:pbm PbmRetrieveContent,omitempty"`
+ Res *types.PbmRetrieveContentResponse `xml:"urn:pbm PbmRetrieveContentResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmRetrieveContentBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmRetrieveContent(ctx context.Context, r soap.RoundTripper, req *types.PbmRetrieveContent) (*types.PbmRetrieveContentResponse, error) {
+ var reqBody, resBody PbmRetrieveContentBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmRetrieveServiceContentBody struct {
+ Req *types.PbmRetrieveServiceContent `xml:"urn:pbm PbmRetrieveServiceContent,omitempty"`
+ Res *types.PbmRetrieveServiceContentResponse `xml:"urn:pbm PbmRetrieveServiceContentResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmRetrieveServiceContentBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmRetrieveServiceContent(ctx context.Context, r soap.RoundTripper, req *types.PbmRetrieveServiceContent) (*types.PbmRetrieveServiceContentResponse, error) {
+ var reqBody, resBody PbmRetrieveServiceContentBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
+
+type PbmUpdateBody struct {
+ Req *types.PbmUpdate `xml:"urn:pbm PbmUpdate,omitempty"`
+ Res *types.PbmUpdateResponse `xml:"urn:pbm PbmUpdateResponse,omitempty"`
+ Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *PbmUpdateBody) Fault() *soap.Fault { return b.Fault_ }
+
+func PbmUpdate(ctx context.Context, r soap.RoundTripper, req *types.PbmUpdate) (*types.PbmUpdateResponse, error) {
+ var reqBody, resBody PbmUpdateBody
+
+ reqBody.Req = req
+
+ if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+ return nil, err
+ }
+
+ return resBody.Res, nil
+}
diff --git a/vendor/github.com/vmware/govmomi/pbm/pbm_util.go b/vendor/github.com/vmware/govmomi/pbm/pbm_util.go
new file mode 100644
index 00000000..4cc8085f
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/pbm/pbm_util.go
@@ -0,0 +1,146 @@
+/*
+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 pbm
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "github.com/vmware/govmomi/pbm/types"
+)
+
+// A struct to capture pbm create spec details.
+type CapabilityProfileCreateSpec struct {
+ Name string
+ Description string
+ Category string
+ CapabilityList []Capability
+}
+
+// A struct to capture pbm capability instance details.
+type Capability struct {
+ ID string
+ Namespace string
+ PropertyList []Property
+}
+
+// A struct to capture pbm property instance details.
+type Property struct {
+ ID string
+ Operator string
+ Value string
+ DataType string
+}
+
+func CreateCapabilityProfileSpec(pbmCreateSpec CapabilityProfileCreateSpec) (*types.PbmCapabilityProfileCreateSpec, error) {
+ capabilities, err := createCapabilityInstances(pbmCreateSpec.CapabilityList)
+ if err != nil {
+ return nil, err
+ }
+
+ pbmCapabilityProfileSpec := types.PbmCapabilityProfileCreateSpec{
+ Name: pbmCreateSpec.Name,
+ Description: pbmCreateSpec.Description,
+ Category: pbmCreateSpec.Category,
+ ResourceType: types.PbmProfileResourceType{
+ ResourceType: string(types.PbmProfileResourceTypeEnumSTORAGE),
+ },
+ Constraints: &types.PbmCapabilitySubProfileConstraints{
+ SubProfiles: []types.PbmCapabilitySubProfile{
+ types.PbmCapabilitySubProfile{
+ Capability: capabilities,
+ },
+ },
+ },
+ }
+ return &pbmCapabilityProfileSpec, nil
+}
+
+func createCapabilityInstances(rules []Capability) ([]types.PbmCapabilityInstance, error) {
+ var capabilityInstances []types.PbmCapabilityInstance
+ for _, capabilityRule := range rules {
+ capability := types.PbmCapabilityInstance{
+ Id: types.PbmCapabilityMetadataUniqueId{
+ Namespace: capabilityRule.Namespace,
+ Id: capabilityRule.ID,
+ },
+ }
+
+ var propertyInstances []types.PbmCapabilityPropertyInstance
+ for _, propertyRule := range capabilityRule.PropertyList {
+ property := types.PbmCapabilityPropertyInstance{
+ Id: propertyRule.ID,
+ }
+ if propertyRule.Operator != "" {
+ property.Operator = propertyRule.Operator
+ }
+ var err error
+ switch strings.ToLower(propertyRule.DataType) {
+ case "int":
+ // Go int32 is marshalled to xsi:int whereas Go int is marshalled to xsi:long when sending down the wire.
+ var val int32
+ val, err = verifyPropertyValueIsInt(propertyRule.Value, propertyRule.DataType)
+ property.Value = val
+ case "bool":
+ var val bool
+ val, err = verifyPropertyValueIsBoolean(propertyRule.Value, propertyRule.DataType)
+ property.Value = val
+ case "string":
+ property.Value = propertyRule.Value
+ case "set":
+ set := types.PbmCapabilityDiscreteSet{}
+ for _, val := range strings.Split(propertyRule.Value, ",") {
+ set.Values = append(set.Values, val)
+ }
+ property.Value = set
+ default:
+ return nil, fmt.Errorf("invalid value: %q with datatype: %q", propertyRule.Value, propertyRule.Value)
+ }
+ if err != nil {
+ return nil, fmt.Errorf("invalid value: %q with datatype: %q", propertyRule.Value, propertyRule.Value)
+ }
+ propertyInstances = append(propertyInstances, property)
+ }
+ constraintInstances := []types.PbmCapabilityConstraintInstance{
+ types.PbmCapabilityConstraintInstance{
+ PropertyInstance: propertyInstances,
+ },
+ }
+ capability.Constraint = constraintInstances
+ capabilityInstances = append(capabilityInstances, capability)
+ }
+ return capabilityInstances, nil
+}
+
+// Verify if the capability value is of type integer.
+func verifyPropertyValueIsInt(propertyValue string, dataType string) (int32, error) {
+ val, err := strconv.ParseInt(propertyValue, 10, 32)
+ if err != nil {
+ return -1, err
+ }
+ return int32(val), nil
+}
+
+// Verify if the capability value is of type integer.
+func verifyPropertyValueIsBoolean(propertyValue string, dataType string) (bool, error) {
+ val, err := strconv.ParseBool(propertyValue)
+ if err != nil {
+ return false, err
+ }
+ return val, nil
+}
diff --git a/vendor/github.com/vmware/govmomi/pbm/types/enum.go b/vendor/github.com/vmware/govmomi/pbm/types/enum.go
new file mode 100644
index 00000000..7cee7514
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/pbm/types/enum.go
@@ -0,0 +1,211 @@
+/*
+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 types
+
+import (
+ "reflect"
+
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type PbmBuiltinGenericType string
+
+const (
+ PbmBuiltinGenericTypeVMW_RANGE = PbmBuiltinGenericType("VMW_RANGE")
+ PbmBuiltinGenericTypeVMW_SET = PbmBuiltinGenericType("VMW_SET")
+)
+
+func init() {
+ types.Add("pbm:PbmBuiltinGenericType", reflect.TypeOf((*PbmBuiltinGenericType)(nil)).Elem())
+}
+
+type PbmBuiltinType string
+
+const (
+ PbmBuiltinTypeXSD_LONG = PbmBuiltinType("XSD_LONG")
+ PbmBuiltinTypeXSD_SHORT = PbmBuiltinType("XSD_SHORT")
+ PbmBuiltinTypeXSD_INTEGER = PbmBuiltinType("XSD_INTEGER")
+ PbmBuiltinTypeXSD_INT = PbmBuiltinType("XSD_INT")
+ PbmBuiltinTypeXSD_STRING = PbmBuiltinType("XSD_STRING")
+ PbmBuiltinTypeXSD_BOOLEAN = PbmBuiltinType("XSD_BOOLEAN")
+ PbmBuiltinTypeXSD_DOUBLE = PbmBuiltinType("XSD_DOUBLE")
+ PbmBuiltinTypeXSD_DATETIME = PbmBuiltinType("XSD_DATETIME")
+ PbmBuiltinTypeVMW_TIMESPAN = PbmBuiltinType("VMW_TIMESPAN")
+ PbmBuiltinTypeVMW_POLICY = PbmBuiltinType("VMW_POLICY")
+)
+
+func init() {
+ types.Add("pbm:PbmBuiltinType", reflect.TypeOf((*PbmBuiltinType)(nil)).Elem())
+}
+
+type PbmCapabilityOperator string
+
+const (
+ PbmCapabilityOperatorNOT = PbmCapabilityOperator("NOT")
+)
+
+func init() {
+ types.Add("pbm:PbmCapabilityOperator", reflect.TypeOf((*PbmCapabilityOperator)(nil)).Elem())
+}
+
+type PbmCapabilityTimeUnitType string
+
+const (
+ PbmCapabilityTimeUnitTypeSECONDS = PbmCapabilityTimeUnitType("SECONDS")
+ PbmCapabilityTimeUnitTypeMINUTES = PbmCapabilityTimeUnitType("MINUTES")
+ PbmCapabilityTimeUnitTypeHOURS = PbmCapabilityTimeUnitType("HOURS")
+ PbmCapabilityTimeUnitTypeDAYS = PbmCapabilityTimeUnitType("DAYS")
+ PbmCapabilityTimeUnitTypeWEEKS = PbmCapabilityTimeUnitType("WEEKS")
+ PbmCapabilityTimeUnitTypeMONTHS = PbmCapabilityTimeUnitType("MONTHS")
+ PbmCapabilityTimeUnitTypeYEARS = PbmCapabilityTimeUnitType("YEARS")
+)
+
+func init() {
+ types.Add("pbm:PbmCapabilityTimeUnitType", reflect.TypeOf((*PbmCapabilityTimeUnitType)(nil)).Elem())
+}
+
+type PbmComplianceResultComplianceTaskStatus string
+
+const (
+ PbmComplianceResultComplianceTaskStatusInProgress = PbmComplianceResultComplianceTaskStatus("inProgress")
+ PbmComplianceResultComplianceTaskStatusSuccess = PbmComplianceResultComplianceTaskStatus("success")
+ PbmComplianceResultComplianceTaskStatusFailed = PbmComplianceResultComplianceTaskStatus("failed")
+)
+
+func init() {
+ types.Add("pbm:PbmComplianceResultComplianceTaskStatus", reflect.TypeOf((*PbmComplianceResultComplianceTaskStatus)(nil)).Elem())
+}
+
+type PbmComplianceStatus string
+
+const (
+ PbmComplianceStatusCompliant = PbmComplianceStatus("compliant")
+ PbmComplianceStatusNonCompliant = PbmComplianceStatus("nonCompliant")
+ PbmComplianceStatusUnknown = PbmComplianceStatus("unknown")
+ PbmComplianceStatusNotApplicable = PbmComplianceStatus("notApplicable")
+ PbmComplianceStatusOutOfDate = PbmComplianceStatus("outOfDate")
+)
+
+func init() {
+ types.Add("pbm:PbmComplianceStatus", reflect.TypeOf((*PbmComplianceStatus)(nil)).Elem())
+}
+
+type PbmIofilterInfoFilterType string
+
+const (
+ PbmIofilterInfoFilterTypeINSPECTION = PbmIofilterInfoFilterType("INSPECTION")
+ PbmIofilterInfoFilterTypeCOMPRESSION = PbmIofilterInfoFilterType("COMPRESSION")
+ PbmIofilterInfoFilterTypeENCRYPTION = PbmIofilterInfoFilterType("ENCRYPTION")
+ PbmIofilterInfoFilterTypeREPLICATION = PbmIofilterInfoFilterType("REPLICATION")
+ PbmIofilterInfoFilterTypeCACHE = PbmIofilterInfoFilterType("CACHE")
+ PbmIofilterInfoFilterTypeDATAPROVIDER = PbmIofilterInfoFilterType("DATAPROVIDER")
+ PbmIofilterInfoFilterTypeDATASTOREIOCONTROL = PbmIofilterInfoFilterType("DATASTOREIOCONTROL")
+)
+
+func init() {
+ types.Add("pbm:PbmIofilterInfoFilterType", reflect.TypeOf((*PbmIofilterInfoFilterType)(nil)).Elem())
+}
+
+type PbmLineOfServiceInfoLineOfServiceEnum string
+
+const (
+ PbmLineOfServiceInfoLineOfServiceEnumINSPECTION = PbmLineOfServiceInfoLineOfServiceEnum("INSPECTION")
+ PbmLineOfServiceInfoLineOfServiceEnumCOMPRESSION = PbmLineOfServiceInfoLineOfServiceEnum("COMPRESSION")
+ PbmLineOfServiceInfoLineOfServiceEnumENCRYPTION = PbmLineOfServiceInfoLineOfServiceEnum("ENCRYPTION")
+ PbmLineOfServiceInfoLineOfServiceEnumREPLICATION = PbmLineOfServiceInfoLineOfServiceEnum("REPLICATION")
+ PbmLineOfServiceInfoLineOfServiceEnumCACHING = PbmLineOfServiceInfoLineOfServiceEnum("CACHING")
+ PbmLineOfServiceInfoLineOfServiceEnumPERSISTENCE = PbmLineOfServiceInfoLineOfServiceEnum("PERSISTENCE")
+ PbmLineOfServiceInfoLineOfServiceEnumDATA_PROVIDER = PbmLineOfServiceInfoLineOfServiceEnum("DATA_PROVIDER")
+ PbmLineOfServiceInfoLineOfServiceEnumDATASTORE_IO_CONTROL = PbmLineOfServiceInfoLineOfServiceEnum("DATASTORE_IO_CONTROL")
+)
+
+func init() {
+ types.Add("pbm:PbmLineOfServiceInfoLineOfServiceEnum", reflect.TypeOf((*PbmLineOfServiceInfoLineOfServiceEnum)(nil)).Elem())
+}
+
+type PbmObjectType string
+
+const (
+ PbmObjectTypeVirtualMachine = PbmObjectType("virtualMachine")
+ PbmObjectTypeVirtualMachineAndDisks = PbmObjectType("virtualMachineAndDisks")
+ PbmObjectTypeVirtualDiskId = PbmObjectType("virtualDiskId")
+ PbmObjectTypeVirtualDiskUUID = PbmObjectType("virtualDiskUUID")
+ PbmObjectTypeDatastore = PbmObjectType("datastore")
+ PbmObjectTypeUnknown = PbmObjectType("unknown")
+)
+
+func init() {
+ types.Add("pbm:PbmObjectType", reflect.TypeOf((*PbmObjectType)(nil)).Elem())
+}
+
+type PbmProfileCategoryEnum string
+
+const (
+ PbmProfileCategoryEnumREQUIREMENT = PbmProfileCategoryEnum("REQUIREMENT")
+ PbmProfileCategoryEnumRESOURCE = PbmProfileCategoryEnum("RESOURCE")
+ PbmProfileCategoryEnumDATA_SERVICE_POLICY = PbmProfileCategoryEnum("DATA_SERVICE_POLICY")
+)
+
+func init() {
+ types.Add("pbm:PbmProfileCategoryEnum", reflect.TypeOf((*PbmProfileCategoryEnum)(nil)).Elem())
+}
+
+type PbmProfileResourceTypeEnum string
+
+const (
+ PbmProfileResourceTypeEnumSTORAGE = PbmProfileResourceTypeEnum("STORAGE")
+)
+
+func init() {
+ types.Add("pbm:PbmProfileResourceTypeEnum", reflect.TypeOf((*PbmProfileResourceTypeEnum)(nil)).Elem())
+}
+
+type PbmSystemCreatedProfileType string
+
+const (
+ PbmSystemCreatedProfileTypeVsanDefaultProfile = PbmSystemCreatedProfileType("VsanDefaultProfile")
+ PbmSystemCreatedProfileTypeVVolDefaultProfile = PbmSystemCreatedProfileType("VVolDefaultProfile")
+)
+
+func init() {
+ types.Add("pbm:PbmSystemCreatedProfileType", reflect.TypeOf((*PbmSystemCreatedProfileType)(nil)).Elem())
+}
+
+type PbmVmOperation string
+
+const (
+ PbmVmOperationCREATE = PbmVmOperation("CREATE")
+ PbmVmOperationRECONFIGURE = PbmVmOperation("RECONFIGURE")
+ PbmVmOperationMIGRATE = PbmVmOperation("MIGRATE")
+ PbmVmOperationCLONE = PbmVmOperation("CLONE")
+)
+
+func init() {
+ types.Add("pbm:PbmVmOperation", reflect.TypeOf((*PbmVmOperation)(nil)).Elem())
+}
+
+type PbmVvolType string
+
+const (
+ PbmVvolTypeConfig = PbmVvolType("Config")
+ PbmVvolTypeData = PbmVvolType("Data")
+ PbmVvolTypeSwap = PbmVvolType("Swap")
+)
+
+func init() {
+ types.Add("pbm:PbmVvolType", reflect.TypeOf((*PbmVvolType)(nil)).Elem())
+}
diff --git a/vendor/github.com/vmware/govmomi/pbm/types/if.go b/vendor/github.com/vmware/govmomi/pbm/types/if.go
new file mode 100644
index 00000000..2a3ac5ac
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/pbm/types/if.go
@@ -0,0 +1,139 @@
+/*
+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 types
+
+import (
+ "reflect"
+
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+func (b *PbmCapabilityConstraints) GetPbmCapabilityConstraints() *PbmCapabilityConstraints { return b }
+
+type BasePbmCapabilityConstraints interface {
+ GetPbmCapabilityConstraints() *PbmCapabilityConstraints
+}
+
+func init() {
+ types.Add("BasePbmCapabilityConstraints", reflect.TypeOf((*PbmCapabilityConstraints)(nil)).Elem())
+}
+
+func (b *PbmCapabilityProfile) GetPbmCapabilityProfile() *PbmCapabilityProfile { return b }
+
+type BasePbmCapabilityProfile interface {
+ GetPbmCapabilityProfile() *PbmCapabilityProfile
+}
+
+func init() {
+ types.Add("BasePbmCapabilityProfile", reflect.TypeOf((*PbmCapabilityProfile)(nil)).Elem())
+}
+
+func (b *PbmCapabilityProfilePropertyMismatchFault) GetPbmCapabilityProfilePropertyMismatchFault() *PbmCapabilityProfilePropertyMismatchFault {
+ return b
+}
+
+type BasePbmCapabilityProfilePropertyMismatchFault interface {
+ GetPbmCapabilityProfilePropertyMismatchFault() *PbmCapabilityProfilePropertyMismatchFault
+}
+
+func init() {
+ types.Add("BasePbmCapabilityProfilePropertyMismatchFault", reflect.TypeOf((*PbmCapabilityProfilePropertyMismatchFault)(nil)).Elem())
+}
+
+func (b *PbmCapabilityTypeInfo) GetPbmCapabilityTypeInfo() *PbmCapabilityTypeInfo { return b }
+
+type BasePbmCapabilityTypeInfo interface {
+ GetPbmCapabilityTypeInfo() *PbmCapabilityTypeInfo
+}
+
+func init() {
+ types.Add("BasePbmCapabilityTypeInfo", reflect.TypeOf((*PbmCapabilityTypeInfo)(nil)).Elem())
+}
+
+func (b *PbmCompatibilityCheckFault) GetPbmCompatibilityCheckFault() *PbmCompatibilityCheckFault {
+ return b
+}
+
+type BasePbmCompatibilityCheckFault interface {
+ GetPbmCompatibilityCheckFault() *PbmCompatibilityCheckFault
+}
+
+func init() {
+ types.Add("BasePbmCompatibilityCheckFault", reflect.TypeOf((*PbmCompatibilityCheckFault)(nil)).Elem())
+}
+
+func (b *PbmFault) GetPbmFault() *PbmFault { return b }
+
+type BasePbmFault interface {
+ GetPbmFault() *PbmFault
+}
+
+func init() {
+ types.Add("BasePbmFault", reflect.TypeOf((*PbmFault)(nil)).Elem())
+}
+
+func (b *PbmLineOfServiceInfo) GetPbmLineOfServiceInfo() *PbmLineOfServiceInfo { return b }
+
+type BasePbmLineOfServiceInfo interface {
+ GetPbmLineOfServiceInfo() *PbmLineOfServiceInfo
+}
+
+func init() {
+ types.Add("BasePbmLineOfServiceInfo", reflect.TypeOf((*PbmLineOfServiceInfo)(nil)).Elem())
+}
+
+func (b *PbmPlacementMatchingResources) GetPbmPlacementMatchingResources() *PbmPlacementMatchingResources {
+ return b
+}
+
+type BasePbmPlacementMatchingResources interface {
+ GetPbmPlacementMatchingResources() *PbmPlacementMatchingResources
+}
+
+func init() {
+ types.Add("BasePbmPlacementMatchingResources", reflect.TypeOf((*PbmPlacementMatchingResources)(nil)).Elem())
+}
+
+func (b *PbmPlacementRequirement) GetPbmPlacementRequirement() *PbmPlacementRequirement { return b }
+
+type BasePbmPlacementRequirement interface {
+ GetPbmPlacementRequirement() *PbmPlacementRequirement
+}
+
+func init() {
+ types.Add("BasePbmPlacementRequirement", reflect.TypeOf((*PbmPlacementRequirement)(nil)).Elem())
+}
+
+func (b *PbmProfile) GetPbmProfile() *PbmProfile { return b }
+
+type BasePbmProfile interface {
+ GetPbmProfile() *PbmProfile
+}
+
+func init() {
+ types.Add("BasePbmProfile", reflect.TypeOf((*PbmProfile)(nil)).Elem())
+}
+
+func (b *PbmPropertyMismatchFault) GetPbmPropertyMismatchFault() *PbmPropertyMismatchFault { return b }
+
+type BasePbmPropertyMismatchFault interface {
+ GetPbmPropertyMismatchFault() *PbmPropertyMismatchFault
+}
+
+func init() {
+ types.Add("BasePbmPropertyMismatchFault", reflect.TypeOf((*PbmPropertyMismatchFault)(nil)).Elem())
+}
diff --git a/vendor/github.com/vmware/govmomi/pbm/types/types.go b/vendor/github.com/vmware/govmomi/pbm/types/types.go
new file mode 100644
index 00000000..47bd73c1
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/pbm/types/types.go
@@ -0,0 +1,1712 @@
+/*
+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 types
+
+import (
+ "reflect"
+ "time"
+
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type ArrayOfPbmCapabilityConstraintInstance struct {
+ PbmCapabilityConstraintInstance []PbmCapabilityConstraintInstance `xml:"PbmCapabilityConstraintInstance,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmCapabilityConstraintInstance", reflect.TypeOf((*ArrayOfPbmCapabilityConstraintInstance)(nil)).Elem())
+}
+
+type ArrayOfPbmCapabilityInstance struct {
+ PbmCapabilityInstance []PbmCapabilityInstance `xml:"PbmCapabilityInstance,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmCapabilityInstance", reflect.TypeOf((*ArrayOfPbmCapabilityInstance)(nil)).Elem())
+}
+
+type ArrayOfPbmCapabilityMetadata struct {
+ PbmCapabilityMetadata []PbmCapabilityMetadata `xml:"PbmCapabilityMetadata,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmCapabilityMetadata", reflect.TypeOf((*ArrayOfPbmCapabilityMetadata)(nil)).Elem())
+}
+
+type ArrayOfPbmCapabilityMetadataPerCategory struct {
+ PbmCapabilityMetadataPerCategory []PbmCapabilityMetadataPerCategory `xml:"PbmCapabilityMetadataPerCategory,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmCapabilityMetadataPerCategory", reflect.TypeOf((*ArrayOfPbmCapabilityMetadataPerCategory)(nil)).Elem())
+}
+
+type ArrayOfPbmCapabilityPropertyInstance struct {
+ PbmCapabilityPropertyInstance []PbmCapabilityPropertyInstance `xml:"PbmCapabilityPropertyInstance,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmCapabilityPropertyInstance", reflect.TypeOf((*ArrayOfPbmCapabilityPropertyInstance)(nil)).Elem())
+}
+
+type ArrayOfPbmCapabilityPropertyMetadata struct {
+ PbmCapabilityPropertyMetadata []PbmCapabilityPropertyMetadata `xml:"PbmCapabilityPropertyMetadata,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmCapabilityPropertyMetadata", reflect.TypeOf((*ArrayOfPbmCapabilityPropertyMetadata)(nil)).Elem())
+}
+
+type ArrayOfPbmCapabilitySchema struct {
+ PbmCapabilitySchema []PbmCapabilitySchema `xml:"PbmCapabilitySchema,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmCapabilitySchema", reflect.TypeOf((*ArrayOfPbmCapabilitySchema)(nil)).Elem())
+}
+
+type ArrayOfPbmCapabilitySubProfile struct {
+ PbmCapabilitySubProfile []PbmCapabilitySubProfile `xml:"PbmCapabilitySubProfile,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmCapabilitySubProfile", reflect.TypeOf((*ArrayOfPbmCapabilitySubProfile)(nil)).Elem())
+}
+
+type ArrayOfPbmCapabilityVendorNamespaceInfo struct {
+ PbmCapabilityVendorNamespaceInfo []PbmCapabilityVendorNamespaceInfo `xml:"PbmCapabilityVendorNamespaceInfo,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmCapabilityVendorNamespaceInfo", reflect.TypeOf((*ArrayOfPbmCapabilityVendorNamespaceInfo)(nil)).Elem())
+}
+
+type ArrayOfPbmCapabilityVendorResourceTypeInfo struct {
+ PbmCapabilityVendorResourceTypeInfo []PbmCapabilityVendorResourceTypeInfo `xml:"PbmCapabilityVendorResourceTypeInfo,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmCapabilityVendorResourceTypeInfo", reflect.TypeOf((*ArrayOfPbmCapabilityVendorResourceTypeInfo)(nil)).Elem())
+}
+
+type ArrayOfPbmCompliancePolicyStatus struct {
+ PbmCompliancePolicyStatus []PbmCompliancePolicyStatus `xml:"PbmCompliancePolicyStatus,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmCompliancePolicyStatus", reflect.TypeOf((*ArrayOfPbmCompliancePolicyStatus)(nil)).Elem())
+}
+
+type ArrayOfPbmComplianceResult struct {
+ PbmComplianceResult []PbmComplianceResult `xml:"PbmComplianceResult,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmComplianceResult", reflect.TypeOf((*ArrayOfPbmComplianceResult)(nil)).Elem())
+}
+
+type ArrayOfPbmDatastoreSpaceStatistics struct {
+ PbmDatastoreSpaceStatistics []PbmDatastoreSpaceStatistics `xml:"PbmDatastoreSpaceStatistics,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmDatastoreSpaceStatistics", reflect.TypeOf((*ArrayOfPbmDatastoreSpaceStatistics)(nil)).Elem())
+}
+
+type ArrayOfPbmDefaultProfileInfo struct {
+ PbmDefaultProfileInfo []PbmDefaultProfileInfo `xml:"PbmDefaultProfileInfo,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmDefaultProfileInfo", reflect.TypeOf((*ArrayOfPbmDefaultProfileInfo)(nil)).Elem())
+}
+
+type ArrayOfPbmPlacementCompatibilityResult struct {
+ PbmPlacementCompatibilityResult []PbmPlacementCompatibilityResult `xml:"PbmPlacementCompatibilityResult,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmPlacementCompatibilityResult", reflect.TypeOf((*ArrayOfPbmPlacementCompatibilityResult)(nil)).Elem())
+}
+
+type ArrayOfPbmPlacementHub struct {
+ PbmPlacementHub []PbmPlacementHub `xml:"PbmPlacementHub,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmPlacementHub", reflect.TypeOf((*ArrayOfPbmPlacementHub)(nil)).Elem())
+}
+
+type ArrayOfPbmPlacementMatchingResources struct {
+ PbmPlacementMatchingResources []BasePbmPlacementMatchingResources `xml:"PbmPlacementMatchingResources,omitempty,typeattr"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmPlacementMatchingResources", reflect.TypeOf((*ArrayOfPbmPlacementMatchingResources)(nil)).Elem())
+}
+
+type ArrayOfPbmPlacementRequirement struct {
+ PbmPlacementRequirement []BasePbmPlacementRequirement `xml:"PbmPlacementRequirement,omitempty,typeattr"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmPlacementRequirement", reflect.TypeOf((*ArrayOfPbmPlacementRequirement)(nil)).Elem())
+}
+
+type ArrayOfPbmPlacementResourceUtilization struct {
+ PbmPlacementResourceUtilization []PbmPlacementResourceUtilization `xml:"PbmPlacementResourceUtilization,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmPlacementResourceUtilization", reflect.TypeOf((*ArrayOfPbmPlacementResourceUtilization)(nil)).Elem())
+}
+
+type ArrayOfPbmProfile struct {
+ PbmProfile []BasePbmProfile `xml:"PbmProfile,omitempty,typeattr"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmProfile", reflect.TypeOf((*ArrayOfPbmProfile)(nil)).Elem())
+}
+
+type ArrayOfPbmProfileId struct {
+ PbmProfileId []PbmProfileId `xml:"PbmProfileId,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmProfileId", reflect.TypeOf((*ArrayOfPbmProfileId)(nil)).Elem())
+}
+
+type ArrayOfPbmProfileOperationOutcome struct {
+ PbmProfileOperationOutcome []PbmProfileOperationOutcome `xml:"PbmProfileOperationOutcome,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmProfileOperationOutcome", reflect.TypeOf((*ArrayOfPbmProfileOperationOutcome)(nil)).Elem())
+}
+
+type ArrayOfPbmProfileResourceType struct {
+ PbmProfileResourceType []PbmProfileResourceType `xml:"PbmProfileResourceType,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmProfileResourceType", reflect.TypeOf((*ArrayOfPbmProfileResourceType)(nil)).Elem())
+}
+
+type ArrayOfPbmProfileType struct {
+ PbmProfileType []PbmProfileType `xml:"PbmProfileType,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmProfileType", reflect.TypeOf((*ArrayOfPbmProfileType)(nil)).Elem())
+}
+
+type ArrayOfPbmQueryProfileResult struct {
+ PbmQueryProfileResult []PbmQueryProfileResult `xml:"PbmQueryProfileResult,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmQueryProfileResult", reflect.TypeOf((*ArrayOfPbmQueryProfileResult)(nil)).Elem())
+}
+
+type ArrayOfPbmQueryReplicationGroupResult struct {
+ PbmQueryReplicationGroupResult []PbmQueryReplicationGroupResult `xml:"PbmQueryReplicationGroupResult,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmQueryReplicationGroupResult", reflect.TypeOf((*ArrayOfPbmQueryReplicationGroupResult)(nil)).Elem())
+}
+
+type ArrayOfPbmRollupComplianceResult struct {
+ PbmRollupComplianceResult []PbmRollupComplianceResult `xml:"PbmRollupComplianceResult,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmRollupComplianceResult", reflect.TypeOf((*ArrayOfPbmRollupComplianceResult)(nil)).Elem())
+}
+
+type ArrayOfPbmServerObjectRef struct {
+ PbmServerObjectRef []PbmServerObjectRef `xml:"PbmServerObjectRef,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:ArrayOfPbmServerObjectRef", reflect.TypeOf((*ArrayOfPbmServerObjectRef)(nil)).Elem())
+}
+
+type PbmAboutInfo struct {
+ types.DynamicData
+
+ Name string `xml:"name"`
+ Version string `xml:"version"`
+ InstanceUuid string `xml:"instanceUuid"`
+}
+
+func init() {
+ types.Add("pbm:PbmAboutInfo", reflect.TypeOf((*PbmAboutInfo)(nil)).Elem())
+}
+
+type PbmAlreadyExists struct {
+ PbmFault
+
+ Name string `xml:"name,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmAlreadyExists", reflect.TypeOf((*PbmAlreadyExists)(nil)).Elem())
+}
+
+type PbmAssignDefaultRequirementProfile PbmAssignDefaultRequirementProfileRequestType
+
+func init() {
+ types.Add("pbm:PbmAssignDefaultRequirementProfile", reflect.TypeOf((*PbmAssignDefaultRequirementProfile)(nil)).Elem())
+}
+
+type PbmAssignDefaultRequirementProfileRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Profile PbmProfileId `xml:"profile"`
+ Datastores []PbmPlacementHub `xml:"datastores"`
+}
+
+func init() {
+ types.Add("pbm:PbmAssignDefaultRequirementProfileRequestType", reflect.TypeOf((*PbmAssignDefaultRequirementProfileRequestType)(nil)).Elem())
+}
+
+type PbmAssignDefaultRequirementProfileResponse struct {
+}
+
+type PbmCapabilityConstraintInstance struct {
+ types.DynamicData
+
+ PropertyInstance []PbmCapabilityPropertyInstance `xml:"propertyInstance"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityConstraintInstance", reflect.TypeOf((*PbmCapabilityConstraintInstance)(nil)).Elem())
+}
+
+type PbmCapabilityConstraints struct {
+ types.DynamicData
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityConstraints", reflect.TypeOf((*PbmCapabilityConstraints)(nil)).Elem())
+}
+
+type PbmCapabilityDescription struct {
+ types.DynamicData
+
+ Description PbmExtendedElementDescription `xml:"description"`
+ Value types.AnyType `xml:"value,typeattr"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityDescription", reflect.TypeOf((*PbmCapabilityDescription)(nil)).Elem())
+}
+
+type PbmCapabilityDiscreteSet struct {
+ types.DynamicData
+
+ Values []types.AnyType `xml:"values,typeattr"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityDiscreteSet", reflect.TypeOf((*PbmCapabilityDiscreteSet)(nil)).Elem())
+}
+
+type PbmCapabilityGenericTypeInfo struct {
+ PbmCapabilityTypeInfo
+
+ GenericTypeName string `xml:"genericTypeName"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityGenericTypeInfo", reflect.TypeOf((*PbmCapabilityGenericTypeInfo)(nil)).Elem())
+}
+
+type PbmCapabilityInstance struct {
+ types.DynamicData
+
+ Id PbmCapabilityMetadataUniqueId `xml:"id"`
+ Constraint []PbmCapabilityConstraintInstance `xml:"constraint"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityInstance", reflect.TypeOf((*PbmCapabilityInstance)(nil)).Elem())
+}
+
+type PbmCapabilityMetadata struct {
+ types.DynamicData
+
+ Id PbmCapabilityMetadataUniqueId `xml:"id"`
+ Summary PbmExtendedElementDescription `xml:"summary"`
+ Mandatory *bool `xml:"mandatory"`
+ Hint *bool `xml:"hint"`
+ KeyId string `xml:"keyId,omitempty"`
+ AllowMultipleConstraints *bool `xml:"allowMultipleConstraints"`
+ PropertyMetadata []PbmCapabilityPropertyMetadata `xml:"propertyMetadata"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityMetadata", reflect.TypeOf((*PbmCapabilityMetadata)(nil)).Elem())
+}
+
+type PbmCapabilityMetadataPerCategory struct {
+ types.DynamicData
+
+ SubCategory string `xml:"subCategory"`
+ CapabilityMetadata []PbmCapabilityMetadata `xml:"capabilityMetadata"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityMetadataPerCategory", reflect.TypeOf((*PbmCapabilityMetadataPerCategory)(nil)).Elem())
+}
+
+type PbmCapabilityMetadataUniqueId struct {
+ types.DynamicData
+
+ Namespace string `xml:"namespace"`
+ Id string `xml:"id"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityMetadataUniqueId", reflect.TypeOf((*PbmCapabilityMetadataUniqueId)(nil)).Elem())
+}
+
+type PbmCapabilityNamespaceInfo struct {
+ types.DynamicData
+
+ Version string `xml:"version"`
+ Namespace string `xml:"namespace"`
+ Info *PbmExtendedElementDescription `xml:"info,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityNamespaceInfo", reflect.TypeOf((*PbmCapabilityNamespaceInfo)(nil)).Elem())
+}
+
+type PbmCapabilityProfile struct {
+ PbmProfile
+
+ ProfileCategory string `xml:"profileCategory"`
+ ResourceType PbmProfileResourceType `xml:"resourceType"`
+ Constraints BasePbmCapabilityConstraints `xml:"constraints,typeattr"`
+ GenerationId int64 `xml:"generationId,omitempty"`
+ IsDefault bool `xml:"isDefault"`
+ SystemCreatedProfileType string `xml:"systemCreatedProfileType,omitempty"`
+ LineOfService string `xml:"lineOfService,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityProfile", reflect.TypeOf((*PbmCapabilityProfile)(nil)).Elem())
+}
+
+type PbmCapabilityProfileCreateSpec struct {
+ types.DynamicData
+
+ Name string `xml:"name"`
+ Description string `xml:"description,omitempty"`
+ Category string `xml:"category,omitempty"`
+ ResourceType PbmProfileResourceType `xml:"resourceType"`
+ Constraints BasePbmCapabilityConstraints `xml:"constraints,typeattr"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityProfileCreateSpec", reflect.TypeOf((*PbmCapabilityProfileCreateSpec)(nil)).Elem())
+}
+
+type PbmCapabilityProfilePropertyMismatchFault struct {
+ PbmPropertyMismatchFault
+
+ ResourcePropertyInstance PbmCapabilityPropertyInstance `xml:"resourcePropertyInstance"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityProfilePropertyMismatchFault", reflect.TypeOf((*PbmCapabilityProfilePropertyMismatchFault)(nil)).Elem())
+}
+
+type PbmCapabilityProfilePropertyMismatchFaultFault BasePbmCapabilityProfilePropertyMismatchFault
+
+func init() {
+ types.Add("pbm:PbmCapabilityProfilePropertyMismatchFaultFault", reflect.TypeOf((*PbmCapabilityProfilePropertyMismatchFaultFault)(nil)).Elem())
+}
+
+type PbmCapabilityProfileUpdateSpec struct {
+ types.DynamicData
+
+ Name string `xml:"name,omitempty"`
+ Description string `xml:"description,omitempty"`
+ Constraints BasePbmCapabilityConstraints `xml:"constraints,omitempty,typeattr"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityProfileUpdateSpec", reflect.TypeOf((*PbmCapabilityProfileUpdateSpec)(nil)).Elem())
+}
+
+type PbmCapabilityPropertyInstance struct {
+ types.DynamicData
+
+ Id string `xml:"id"`
+ Operator string `xml:"operator,omitempty"`
+ Value types.AnyType `xml:"value,typeattr"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityPropertyInstance", reflect.TypeOf((*PbmCapabilityPropertyInstance)(nil)).Elem())
+}
+
+type PbmCapabilityPropertyMetadata struct {
+ types.DynamicData
+
+ Id string `xml:"id"`
+ Summary PbmExtendedElementDescription `xml:"summary"`
+ Mandatory bool `xml:"mandatory"`
+ Type BasePbmCapabilityTypeInfo `xml:"type,omitempty,typeattr"`
+ DefaultValue types.AnyType `xml:"defaultValue,omitempty,typeattr"`
+ AllowedValue types.AnyType `xml:"allowedValue,omitempty,typeattr"`
+ RequirementsTypeHint string `xml:"requirementsTypeHint,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityPropertyMetadata", reflect.TypeOf((*PbmCapabilityPropertyMetadata)(nil)).Elem())
+}
+
+type PbmCapabilityRange struct {
+ types.DynamicData
+
+ Min types.AnyType `xml:"min,typeattr"`
+ Max types.AnyType `xml:"max,typeattr"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityRange", reflect.TypeOf((*PbmCapabilityRange)(nil)).Elem())
+}
+
+type PbmCapabilitySchema struct {
+ types.DynamicData
+
+ VendorInfo PbmCapabilitySchemaVendorInfo `xml:"vendorInfo"`
+ NamespaceInfo PbmCapabilityNamespaceInfo `xml:"namespaceInfo"`
+ LineOfService BasePbmLineOfServiceInfo `xml:"lineOfService,omitempty,typeattr"`
+ CapabilityMetadataPerCategory []PbmCapabilityMetadataPerCategory `xml:"capabilityMetadataPerCategory"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilitySchema", reflect.TypeOf((*PbmCapabilitySchema)(nil)).Elem())
+}
+
+type PbmCapabilitySchemaVendorInfo struct {
+ types.DynamicData
+
+ VendorUuid string `xml:"vendorUuid"`
+ Info PbmExtendedElementDescription `xml:"info"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilitySchemaVendorInfo", reflect.TypeOf((*PbmCapabilitySchemaVendorInfo)(nil)).Elem())
+}
+
+type PbmCapabilitySubProfile struct {
+ types.DynamicData
+
+ Name string `xml:"name"`
+ Capability []PbmCapabilityInstance `xml:"capability"`
+ ForceProvision *bool `xml:"forceProvision"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilitySubProfile", reflect.TypeOf((*PbmCapabilitySubProfile)(nil)).Elem())
+}
+
+type PbmCapabilitySubProfileConstraints struct {
+ PbmCapabilityConstraints
+
+ SubProfiles []PbmCapabilitySubProfile `xml:"subProfiles"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilitySubProfileConstraints", reflect.TypeOf((*PbmCapabilitySubProfileConstraints)(nil)).Elem())
+}
+
+type PbmCapabilityTimeSpan struct {
+ types.DynamicData
+
+ Value int32 `xml:"value"`
+ Unit string `xml:"unit"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityTimeSpan", reflect.TypeOf((*PbmCapabilityTimeSpan)(nil)).Elem())
+}
+
+type PbmCapabilityTypeInfo struct {
+ types.DynamicData
+
+ TypeName string `xml:"typeName"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityTypeInfo", reflect.TypeOf((*PbmCapabilityTypeInfo)(nil)).Elem())
+}
+
+type PbmCapabilityVendorNamespaceInfo struct {
+ types.DynamicData
+
+ VendorInfo PbmCapabilitySchemaVendorInfo `xml:"vendorInfo"`
+ NamespaceInfo PbmCapabilityNamespaceInfo `xml:"namespaceInfo"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityVendorNamespaceInfo", reflect.TypeOf((*PbmCapabilityVendorNamespaceInfo)(nil)).Elem())
+}
+
+type PbmCapabilityVendorResourceTypeInfo struct {
+ types.DynamicData
+
+ ResourceType string `xml:"resourceType"`
+ VendorNamespaceInfo []PbmCapabilityVendorNamespaceInfo `xml:"vendorNamespaceInfo"`
+}
+
+func init() {
+ types.Add("pbm:PbmCapabilityVendorResourceTypeInfo", reflect.TypeOf((*PbmCapabilityVendorResourceTypeInfo)(nil)).Elem())
+}
+
+type PbmCheckCompatibility PbmCheckCompatibilityRequestType
+
+func init() {
+ types.Add("pbm:PbmCheckCompatibility", reflect.TypeOf((*PbmCheckCompatibility)(nil)).Elem())
+}
+
+type PbmCheckCompatibilityRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ HubsToSearch []PbmPlacementHub `xml:"hubsToSearch,omitempty"`
+ Profile PbmProfileId `xml:"profile"`
+}
+
+func init() {
+ types.Add("pbm:PbmCheckCompatibilityRequestType", reflect.TypeOf((*PbmCheckCompatibilityRequestType)(nil)).Elem())
+}
+
+type PbmCheckCompatibilityResponse struct {
+ Returnval []PbmPlacementCompatibilityResult `xml:"returnval,omitempty"`
+}
+
+type PbmCheckCompatibilityWithSpec PbmCheckCompatibilityWithSpecRequestType
+
+func init() {
+ types.Add("pbm:PbmCheckCompatibilityWithSpec", reflect.TypeOf((*PbmCheckCompatibilityWithSpec)(nil)).Elem())
+}
+
+type PbmCheckCompatibilityWithSpecRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ HubsToSearch []PbmPlacementHub `xml:"hubsToSearch,omitempty"`
+ ProfileSpec PbmCapabilityProfileCreateSpec `xml:"profileSpec"`
+}
+
+func init() {
+ types.Add("pbm:PbmCheckCompatibilityWithSpecRequestType", reflect.TypeOf((*PbmCheckCompatibilityWithSpecRequestType)(nil)).Elem())
+}
+
+type PbmCheckCompatibilityWithSpecResponse struct {
+ Returnval []PbmPlacementCompatibilityResult `xml:"returnval,omitempty"`
+}
+
+type PbmCheckCompliance PbmCheckComplianceRequestType
+
+func init() {
+ types.Add("pbm:PbmCheckCompliance", reflect.TypeOf((*PbmCheckCompliance)(nil)).Elem())
+}
+
+type PbmCheckComplianceRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Entities []PbmServerObjectRef `xml:"entities"`
+ Profile *PbmProfileId `xml:"profile,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmCheckComplianceRequestType", reflect.TypeOf((*PbmCheckComplianceRequestType)(nil)).Elem())
+}
+
+type PbmCheckComplianceResponse struct {
+ Returnval []PbmComplianceResult `xml:"returnval,omitempty"`
+}
+
+type PbmCheckRequirements PbmCheckRequirementsRequestType
+
+func init() {
+ types.Add("pbm:PbmCheckRequirements", reflect.TypeOf((*PbmCheckRequirements)(nil)).Elem())
+}
+
+type PbmCheckRequirementsRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ HubsToSearch []PbmPlacementHub `xml:"hubsToSearch,omitempty"`
+ PlacementSubjectRef *PbmServerObjectRef `xml:"placementSubjectRef,omitempty"`
+ PlacementSubjectRequirement []BasePbmPlacementRequirement `xml:"placementSubjectRequirement,omitempty,typeattr"`
+}
+
+func init() {
+ types.Add("pbm:PbmCheckRequirementsRequestType", reflect.TypeOf((*PbmCheckRequirementsRequestType)(nil)).Elem())
+}
+
+type PbmCheckRequirementsResponse struct {
+ Returnval []PbmPlacementCompatibilityResult `xml:"returnval,omitempty"`
+}
+
+type PbmCheckRollupCompliance PbmCheckRollupComplianceRequestType
+
+func init() {
+ types.Add("pbm:PbmCheckRollupCompliance", reflect.TypeOf((*PbmCheckRollupCompliance)(nil)).Elem())
+}
+
+type PbmCheckRollupComplianceRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Entity []PbmServerObjectRef `xml:"entity"`
+}
+
+func init() {
+ types.Add("pbm:PbmCheckRollupComplianceRequestType", reflect.TypeOf((*PbmCheckRollupComplianceRequestType)(nil)).Elem())
+}
+
+type PbmCheckRollupComplianceResponse struct {
+ Returnval []PbmRollupComplianceResult `xml:"returnval,omitempty"`
+}
+
+type PbmCompatibilityCheckFault struct {
+ PbmFault
+
+ Hub PbmPlacementHub `xml:"hub"`
+}
+
+func init() {
+ types.Add("pbm:PbmCompatibilityCheckFault", reflect.TypeOf((*PbmCompatibilityCheckFault)(nil)).Elem())
+}
+
+type PbmCompatibilityCheckFaultFault BasePbmCompatibilityCheckFault
+
+func init() {
+ types.Add("pbm:PbmCompatibilityCheckFaultFault", reflect.TypeOf((*PbmCompatibilityCheckFaultFault)(nil)).Elem())
+}
+
+type PbmComplianceOperationalStatus struct {
+ types.DynamicData
+
+ Healthy *bool `xml:"healthy"`
+ OperationETA *time.Time `xml:"operationETA"`
+ OperationProgress int64 `xml:"operationProgress,omitempty"`
+ Transitional *bool `xml:"transitional"`
+}
+
+func init() {
+ types.Add("pbm:PbmComplianceOperationalStatus", reflect.TypeOf((*PbmComplianceOperationalStatus)(nil)).Elem())
+}
+
+type PbmCompliancePolicyStatus struct {
+ types.DynamicData
+
+ ExpectedValue PbmCapabilityInstance `xml:"expectedValue"`
+ CurrentValue *PbmCapabilityInstance `xml:"currentValue,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmCompliancePolicyStatus", reflect.TypeOf((*PbmCompliancePolicyStatus)(nil)).Elem())
+}
+
+type PbmComplianceResult struct {
+ types.DynamicData
+
+ CheckTime time.Time `xml:"checkTime"`
+ Entity PbmServerObjectRef `xml:"entity"`
+ Profile *PbmProfileId `xml:"profile,omitempty"`
+ ComplianceTaskStatus string `xml:"complianceTaskStatus,omitempty"`
+ ComplianceStatus string `xml:"complianceStatus"`
+ Mismatch bool `xml:"mismatch"`
+ ViolatedPolicies []PbmCompliancePolicyStatus `xml:"violatedPolicies,omitempty"`
+ ErrorCause []types.LocalizedMethodFault `xml:"errorCause,omitempty"`
+ OperationalStatus *PbmComplianceOperationalStatus `xml:"operationalStatus,omitempty"`
+ Info *PbmExtendedElementDescription `xml:"info,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmComplianceResult", reflect.TypeOf((*PbmComplianceResult)(nil)).Elem())
+}
+
+type PbmCreate PbmCreateRequestType
+
+func init() {
+ types.Add("pbm:PbmCreate", reflect.TypeOf((*PbmCreate)(nil)).Elem())
+}
+
+type PbmCreateRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ CreateSpec PbmCapabilityProfileCreateSpec `xml:"createSpec"`
+}
+
+func init() {
+ types.Add("pbm:PbmCreateRequestType", reflect.TypeOf((*PbmCreateRequestType)(nil)).Elem())
+}
+
+type PbmCreateResponse struct {
+ Returnval PbmProfileId `xml:"returnval"`
+}
+
+type PbmDataServiceToPoliciesMap struct {
+ types.DynamicData
+
+ DataServicePolicy PbmProfileId `xml:"dataServicePolicy"`
+ ParentStoragePolicies []PbmProfileId `xml:"parentStoragePolicies,omitempty"`
+ Fault *types.LocalizedMethodFault `xml:"fault,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmDataServiceToPoliciesMap", reflect.TypeOf((*PbmDataServiceToPoliciesMap)(nil)).Elem())
+}
+
+type PbmDatastoreSpaceStatistics struct {
+ types.DynamicData
+
+ ProfileId string `xml:"profileId,omitempty"`
+ PhysicalTotalInMB int64 `xml:"physicalTotalInMB"`
+ PhysicalFreeInMB int64 `xml:"physicalFreeInMB"`
+ PhysicalUsedInMB int64 `xml:"physicalUsedInMB"`
+ LogicalLimitInMB int64 `xml:"logicalLimitInMB,omitempty"`
+ LogicalFreeInMB int64 `xml:"logicalFreeInMB"`
+ LogicalUsedInMB int64 `xml:"logicalUsedInMB"`
+}
+
+func init() {
+ types.Add("pbm:PbmDatastoreSpaceStatistics", reflect.TypeOf((*PbmDatastoreSpaceStatistics)(nil)).Elem())
+}
+
+type PbmDefaultCapabilityProfile struct {
+ PbmCapabilityProfile
+
+ VvolType []string `xml:"vvolType"`
+ ContainerId string `xml:"containerId"`
+}
+
+func init() {
+ types.Add("pbm:PbmDefaultCapabilityProfile", reflect.TypeOf((*PbmDefaultCapabilityProfile)(nil)).Elem())
+}
+
+type PbmDefaultProfileAppliesFault struct {
+ PbmCompatibilityCheckFault
+}
+
+func init() {
+ types.Add("pbm:PbmDefaultProfileAppliesFault", reflect.TypeOf((*PbmDefaultProfileAppliesFault)(nil)).Elem())
+}
+
+type PbmDefaultProfileAppliesFaultFault PbmDefaultProfileAppliesFault
+
+func init() {
+ types.Add("pbm:PbmDefaultProfileAppliesFaultFault", reflect.TypeOf((*PbmDefaultProfileAppliesFaultFault)(nil)).Elem())
+}
+
+type PbmDefaultProfileInfo struct {
+ types.DynamicData
+
+ Datastores []PbmPlacementHub `xml:"datastores"`
+ DefaultProfile BasePbmProfile `xml:"defaultProfile,omitempty,typeattr"`
+}
+
+func init() {
+ types.Add("pbm:PbmDefaultProfileInfo", reflect.TypeOf((*PbmDefaultProfileInfo)(nil)).Elem())
+}
+
+type PbmDelete PbmDeleteRequestType
+
+func init() {
+ types.Add("pbm:PbmDelete", reflect.TypeOf((*PbmDelete)(nil)).Elem())
+}
+
+type PbmDeleteRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ ProfileId []PbmProfileId `xml:"profileId"`
+}
+
+func init() {
+ types.Add("pbm:PbmDeleteRequestType", reflect.TypeOf((*PbmDeleteRequestType)(nil)).Elem())
+}
+
+type PbmDeleteResponse struct {
+ Returnval []PbmProfileOperationOutcome `xml:"returnval,omitempty"`
+}
+
+type PbmDuplicateName struct {
+ PbmFault
+
+ Name string `xml:"name"`
+}
+
+func init() {
+ types.Add("pbm:PbmDuplicateName", reflect.TypeOf((*PbmDuplicateName)(nil)).Elem())
+}
+
+type PbmDuplicateNameFault PbmDuplicateName
+
+func init() {
+ types.Add("pbm:PbmDuplicateNameFault", reflect.TypeOf((*PbmDuplicateNameFault)(nil)).Elem())
+}
+
+type PbmExtendedElementDescription struct {
+ types.DynamicData
+
+ Label string `xml:"label"`
+ Summary string `xml:"summary"`
+ Key string `xml:"key"`
+ MessageCatalogKeyPrefix string `xml:"messageCatalogKeyPrefix"`
+ MessageArg []types.KeyAnyValue `xml:"messageArg,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmExtendedElementDescription", reflect.TypeOf((*PbmExtendedElementDescription)(nil)).Elem())
+}
+
+type PbmFault struct {
+ types.MethodFault
+}
+
+func init() {
+ types.Add("pbm:PbmFault", reflect.TypeOf((*PbmFault)(nil)).Elem())
+}
+
+type PbmFaultFault BasePbmFault
+
+func init() {
+ types.Add("pbm:PbmFaultFault", reflect.TypeOf((*PbmFaultFault)(nil)).Elem())
+}
+
+type PbmFaultInvalidLogin struct {
+ PbmFault
+}
+
+func init() {
+ types.Add("pbm:PbmFaultInvalidLogin", reflect.TypeOf((*PbmFaultInvalidLogin)(nil)).Elem())
+}
+
+type PbmFaultInvalidLoginFault PbmFaultInvalidLogin
+
+func init() {
+ types.Add("pbm:PbmFaultInvalidLoginFault", reflect.TypeOf((*PbmFaultInvalidLoginFault)(nil)).Elem())
+}
+
+type PbmFaultNotFound struct {
+ PbmFault
+}
+
+func init() {
+ types.Add("pbm:PbmFaultNotFound", reflect.TypeOf((*PbmFaultNotFound)(nil)).Elem())
+}
+
+type PbmFaultNotFoundFault PbmFaultNotFound
+
+func init() {
+ types.Add("pbm:PbmFaultNotFoundFault", reflect.TypeOf((*PbmFaultNotFoundFault)(nil)).Elem())
+}
+
+type PbmFaultProfileStorageFault struct {
+ PbmFault
+}
+
+func init() {
+ types.Add("pbm:PbmFaultProfileStorageFault", reflect.TypeOf((*PbmFaultProfileStorageFault)(nil)).Elem())
+}
+
+type PbmFaultProfileStorageFaultFault PbmFaultProfileStorageFault
+
+func init() {
+ types.Add("pbm:PbmFaultProfileStorageFaultFault", reflect.TypeOf((*PbmFaultProfileStorageFaultFault)(nil)).Elem())
+}
+
+type PbmFetchCapabilityMetadata PbmFetchCapabilityMetadataRequestType
+
+func init() {
+ types.Add("pbm:PbmFetchCapabilityMetadata", reflect.TypeOf((*PbmFetchCapabilityMetadata)(nil)).Elem())
+}
+
+type PbmFetchCapabilityMetadataRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ ResourceType *PbmProfileResourceType `xml:"resourceType,omitempty"`
+ VendorUuid string `xml:"vendorUuid,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmFetchCapabilityMetadataRequestType", reflect.TypeOf((*PbmFetchCapabilityMetadataRequestType)(nil)).Elem())
+}
+
+type PbmFetchCapabilityMetadataResponse struct {
+ Returnval []PbmCapabilityMetadataPerCategory `xml:"returnval,omitempty"`
+}
+
+type PbmFetchCapabilitySchema PbmFetchCapabilitySchemaRequestType
+
+func init() {
+ types.Add("pbm:PbmFetchCapabilitySchema", reflect.TypeOf((*PbmFetchCapabilitySchema)(nil)).Elem())
+}
+
+type PbmFetchCapabilitySchemaRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ VendorUuid string `xml:"vendorUuid,omitempty"`
+ LineOfService []string `xml:"lineOfService,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmFetchCapabilitySchemaRequestType", reflect.TypeOf((*PbmFetchCapabilitySchemaRequestType)(nil)).Elem())
+}
+
+type PbmFetchCapabilitySchemaResponse struct {
+ Returnval []PbmCapabilitySchema `xml:"returnval,omitempty"`
+}
+
+type PbmFetchComplianceResult PbmFetchComplianceResultRequestType
+
+func init() {
+ types.Add("pbm:PbmFetchComplianceResult", reflect.TypeOf((*PbmFetchComplianceResult)(nil)).Elem())
+}
+
+type PbmFetchComplianceResultRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Entities []PbmServerObjectRef `xml:"entities"`
+ Profile *PbmProfileId `xml:"profile,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmFetchComplianceResultRequestType", reflect.TypeOf((*PbmFetchComplianceResultRequestType)(nil)).Elem())
+}
+
+type PbmFetchComplianceResultResponse struct {
+ Returnval []PbmComplianceResult `xml:"returnval,omitempty"`
+}
+
+type PbmFetchResourceType PbmFetchResourceTypeRequestType
+
+func init() {
+ types.Add("pbm:PbmFetchResourceType", reflect.TypeOf((*PbmFetchResourceType)(nil)).Elem())
+}
+
+type PbmFetchResourceTypeRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+}
+
+func init() {
+ types.Add("pbm:PbmFetchResourceTypeRequestType", reflect.TypeOf((*PbmFetchResourceTypeRequestType)(nil)).Elem())
+}
+
+type PbmFetchResourceTypeResponse struct {
+ Returnval []PbmProfileResourceType `xml:"returnval,omitempty"`
+}
+
+type PbmFetchRollupComplianceResult PbmFetchRollupComplianceResultRequestType
+
+func init() {
+ types.Add("pbm:PbmFetchRollupComplianceResult", reflect.TypeOf((*PbmFetchRollupComplianceResult)(nil)).Elem())
+}
+
+type PbmFetchRollupComplianceResultRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Entity []PbmServerObjectRef `xml:"entity"`
+}
+
+func init() {
+ types.Add("pbm:PbmFetchRollupComplianceResultRequestType", reflect.TypeOf((*PbmFetchRollupComplianceResultRequestType)(nil)).Elem())
+}
+
+type PbmFetchRollupComplianceResultResponse struct {
+ Returnval []PbmRollupComplianceResult `xml:"returnval,omitempty"`
+}
+
+type PbmFetchVendorInfo PbmFetchVendorInfoRequestType
+
+func init() {
+ types.Add("pbm:PbmFetchVendorInfo", reflect.TypeOf((*PbmFetchVendorInfo)(nil)).Elem())
+}
+
+type PbmFetchVendorInfoRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ ResourceType *PbmProfileResourceType `xml:"resourceType,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmFetchVendorInfoRequestType", reflect.TypeOf((*PbmFetchVendorInfoRequestType)(nil)).Elem())
+}
+
+type PbmFetchVendorInfoResponse struct {
+ Returnval []PbmCapabilityVendorResourceTypeInfo `xml:"returnval,omitempty"`
+}
+
+type PbmFindApplicableDefaultProfile PbmFindApplicableDefaultProfileRequestType
+
+func init() {
+ types.Add("pbm:PbmFindApplicableDefaultProfile", reflect.TypeOf((*PbmFindApplicableDefaultProfile)(nil)).Elem())
+}
+
+type PbmFindApplicableDefaultProfileRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Datastores []PbmPlacementHub `xml:"datastores"`
+}
+
+func init() {
+ types.Add("pbm:PbmFindApplicableDefaultProfileRequestType", reflect.TypeOf((*PbmFindApplicableDefaultProfileRequestType)(nil)).Elem())
+}
+
+type PbmFindApplicableDefaultProfileResponse struct {
+ Returnval []BasePbmProfile `xml:"returnval,omitempty,typeattr"`
+}
+
+type PbmIncompatibleVendorSpecificRuleSet struct {
+ PbmCapabilityProfilePropertyMismatchFault
+}
+
+func init() {
+ types.Add("pbm:PbmIncompatibleVendorSpecificRuleSet", reflect.TypeOf((*PbmIncompatibleVendorSpecificRuleSet)(nil)).Elem())
+}
+
+type PbmIncompatibleVendorSpecificRuleSetFault PbmIncompatibleVendorSpecificRuleSet
+
+func init() {
+ types.Add("pbm:PbmIncompatibleVendorSpecificRuleSetFault", reflect.TypeOf((*PbmIncompatibleVendorSpecificRuleSetFault)(nil)).Elem())
+}
+
+type PbmLegacyHubsNotSupported struct {
+ PbmFault
+
+ Hubs []PbmPlacementHub `xml:"hubs"`
+}
+
+func init() {
+ types.Add("pbm:PbmLegacyHubsNotSupported", reflect.TypeOf((*PbmLegacyHubsNotSupported)(nil)).Elem())
+}
+
+type PbmLegacyHubsNotSupportedFault PbmLegacyHubsNotSupported
+
+func init() {
+ types.Add("pbm:PbmLegacyHubsNotSupportedFault", reflect.TypeOf((*PbmLegacyHubsNotSupportedFault)(nil)).Elem())
+}
+
+type PbmLineOfServiceInfo struct {
+ types.DynamicData
+
+ LineOfService string `xml:"lineOfService"`
+ Name PbmExtendedElementDescription `xml:"name"`
+ Description *PbmExtendedElementDescription `xml:"description,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmLineOfServiceInfo", reflect.TypeOf((*PbmLineOfServiceInfo)(nil)).Elem())
+}
+
+type PbmNonExistentHubs struct {
+ PbmFault
+
+ Hubs []PbmPlacementHub `xml:"hubs"`
+}
+
+func init() {
+ types.Add("pbm:PbmNonExistentHubs", reflect.TypeOf((*PbmNonExistentHubs)(nil)).Elem())
+}
+
+type PbmNonExistentHubsFault PbmNonExistentHubs
+
+func init() {
+ types.Add("pbm:PbmNonExistentHubsFault", reflect.TypeOf((*PbmNonExistentHubsFault)(nil)).Elem())
+}
+
+type PbmPersistenceBasedDataServiceInfo struct {
+ PbmLineOfServiceInfo
+
+ CompatiblePersistenceSchemaNamespace []string `xml:"compatiblePersistenceSchemaNamespace,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmPersistenceBasedDataServiceInfo", reflect.TypeOf((*PbmPersistenceBasedDataServiceInfo)(nil)).Elem())
+}
+
+type PbmPlacementCapabilityConstraintsRequirement struct {
+ PbmPlacementRequirement
+
+ Constraints BasePbmCapabilityConstraints `xml:"constraints,typeattr"`
+}
+
+func init() {
+ types.Add("pbm:PbmPlacementCapabilityConstraintsRequirement", reflect.TypeOf((*PbmPlacementCapabilityConstraintsRequirement)(nil)).Elem())
+}
+
+type PbmPlacementCapabilityProfileRequirement struct {
+ PbmPlacementRequirement
+
+ ProfileId PbmProfileId `xml:"profileId"`
+}
+
+func init() {
+ types.Add("pbm:PbmPlacementCapabilityProfileRequirement", reflect.TypeOf((*PbmPlacementCapabilityProfileRequirement)(nil)).Elem())
+}
+
+type PbmPlacementCompatibilityResult struct {
+ types.DynamicData
+
+ Hub PbmPlacementHub `xml:"hub"`
+ MatchingResources []BasePbmPlacementMatchingResources `xml:"matchingResources,omitempty,typeattr"`
+ HowMany int64 `xml:"howMany,omitempty"`
+ Utilization []PbmPlacementResourceUtilization `xml:"utilization,omitempty"`
+ Warning []types.LocalizedMethodFault `xml:"warning,omitempty"`
+ Error []types.LocalizedMethodFault `xml:"error,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmPlacementCompatibilityResult", reflect.TypeOf((*PbmPlacementCompatibilityResult)(nil)).Elem())
+}
+
+type PbmPlacementHub struct {
+ types.DynamicData
+
+ HubType string `xml:"hubType"`
+ HubId string `xml:"hubId"`
+}
+
+func init() {
+ types.Add("pbm:PbmPlacementHub", reflect.TypeOf((*PbmPlacementHub)(nil)).Elem())
+}
+
+type PbmPlacementMatchingReplicationResources struct {
+ PbmPlacementMatchingResources
+
+ ReplicationGroup []types.ReplicationGroupId `xml:"replicationGroup,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmPlacementMatchingReplicationResources", reflect.TypeOf((*PbmPlacementMatchingReplicationResources)(nil)).Elem())
+}
+
+type PbmPlacementMatchingResources struct {
+ types.DynamicData
+}
+
+func init() {
+ types.Add("pbm:PbmPlacementMatchingResources", reflect.TypeOf((*PbmPlacementMatchingResources)(nil)).Elem())
+}
+
+type PbmPlacementRequirement struct {
+ types.DynamicData
+}
+
+func init() {
+ types.Add("pbm:PbmPlacementRequirement", reflect.TypeOf((*PbmPlacementRequirement)(nil)).Elem())
+}
+
+type PbmPlacementResourceUtilization struct {
+ types.DynamicData
+
+ Name PbmExtendedElementDescription `xml:"name"`
+ Description PbmExtendedElementDescription `xml:"description"`
+ AvailableBefore int64 `xml:"availableBefore,omitempty"`
+ AvailableAfter int64 `xml:"availableAfter,omitempty"`
+ Total int64 `xml:"total,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmPlacementResourceUtilization", reflect.TypeOf((*PbmPlacementResourceUtilization)(nil)).Elem())
+}
+
+type PbmProfile struct {
+ types.DynamicData
+
+ ProfileId PbmProfileId `xml:"profileId"`
+ Name string `xml:"name"`
+ Description string `xml:"description,omitempty"`
+ CreationTime time.Time `xml:"creationTime"`
+ CreatedBy string `xml:"createdBy"`
+ LastUpdatedTime time.Time `xml:"lastUpdatedTime"`
+ LastUpdatedBy string `xml:"lastUpdatedBy"`
+}
+
+func init() {
+ types.Add("pbm:PbmProfile", reflect.TypeOf((*PbmProfile)(nil)).Elem())
+}
+
+type PbmProfileId struct {
+ types.DynamicData
+
+ UniqueId string `xml:"uniqueId"`
+}
+
+func init() {
+ types.Add("pbm:PbmProfileId", reflect.TypeOf((*PbmProfileId)(nil)).Elem())
+}
+
+type PbmProfileOperationOutcome struct {
+ types.DynamicData
+
+ ProfileId PbmProfileId `xml:"profileId"`
+ Fault *types.LocalizedMethodFault `xml:"fault,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmProfileOperationOutcome", reflect.TypeOf((*PbmProfileOperationOutcome)(nil)).Elem())
+}
+
+type PbmProfileResourceType struct {
+ types.DynamicData
+
+ ResourceType string `xml:"resourceType"`
+}
+
+func init() {
+ types.Add("pbm:PbmProfileResourceType", reflect.TypeOf((*PbmProfileResourceType)(nil)).Elem())
+}
+
+type PbmProfileType struct {
+ types.DynamicData
+
+ UniqueId string `xml:"uniqueId"`
+}
+
+func init() {
+ types.Add("pbm:PbmProfileType", reflect.TypeOf((*PbmProfileType)(nil)).Elem())
+}
+
+type PbmPropertyMismatchFault struct {
+ PbmCompatibilityCheckFault
+
+ CapabilityInstanceId PbmCapabilityMetadataUniqueId `xml:"capabilityInstanceId"`
+ RequirementPropertyInstance PbmCapabilityPropertyInstance `xml:"requirementPropertyInstance"`
+}
+
+func init() {
+ types.Add("pbm:PbmPropertyMismatchFault", reflect.TypeOf((*PbmPropertyMismatchFault)(nil)).Elem())
+}
+
+type PbmPropertyMismatchFaultFault BasePbmPropertyMismatchFault
+
+func init() {
+ types.Add("pbm:PbmPropertyMismatchFaultFault", reflect.TypeOf((*PbmPropertyMismatchFaultFault)(nil)).Elem())
+}
+
+type PbmQueryAssociatedEntities PbmQueryAssociatedEntitiesRequestType
+
+func init() {
+ types.Add("pbm:PbmQueryAssociatedEntities", reflect.TypeOf((*PbmQueryAssociatedEntities)(nil)).Elem())
+}
+
+type PbmQueryAssociatedEntitiesRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Profiles []PbmProfileId `xml:"profiles,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmQueryAssociatedEntitiesRequestType", reflect.TypeOf((*PbmQueryAssociatedEntitiesRequestType)(nil)).Elem())
+}
+
+type PbmQueryAssociatedEntitiesResponse struct {
+ Returnval []PbmQueryProfileResult `xml:"returnval,omitempty"`
+}
+
+type PbmQueryAssociatedEntity PbmQueryAssociatedEntityRequestType
+
+func init() {
+ types.Add("pbm:PbmQueryAssociatedEntity", reflect.TypeOf((*PbmQueryAssociatedEntity)(nil)).Elem())
+}
+
+type PbmQueryAssociatedEntityRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Profile PbmProfileId `xml:"profile"`
+ EntityType string `xml:"entityType,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmQueryAssociatedEntityRequestType", reflect.TypeOf((*PbmQueryAssociatedEntityRequestType)(nil)).Elem())
+}
+
+type PbmQueryAssociatedEntityResponse struct {
+ Returnval []PbmServerObjectRef `xml:"returnval,omitempty"`
+}
+
+type PbmQueryAssociatedProfile PbmQueryAssociatedProfileRequestType
+
+func init() {
+ types.Add("pbm:PbmQueryAssociatedProfile", reflect.TypeOf((*PbmQueryAssociatedProfile)(nil)).Elem())
+}
+
+type PbmQueryAssociatedProfileRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Entity PbmServerObjectRef `xml:"entity"`
+}
+
+func init() {
+ types.Add("pbm:PbmQueryAssociatedProfileRequestType", reflect.TypeOf((*PbmQueryAssociatedProfileRequestType)(nil)).Elem())
+}
+
+type PbmQueryAssociatedProfileResponse struct {
+ Returnval []PbmProfileId `xml:"returnval,omitempty"`
+}
+
+type PbmQueryAssociatedProfiles PbmQueryAssociatedProfilesRequestType
+
+func init() {
+ types.Add("pbm:PbmQueryAssociatedProfiles", reflect.TypeOf((*PbmQueryAssociatedProfiles)(nil)).Elem())
+}
+
+type PbmQueryAssociatedProfilesRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Entities []PbmServerObjectRef `xml:"entities"`
+}
+
+func init() {
+ types.Add("pbm:PbmQueryAssociatedProfilesRequestType", reflect.TypeOf((*PbmQueryAssociatedProfilesRequestType)(nil)).Elem())
+}
+
+type PbmQueryAssociatedProfilesResponse struct {
+ Returnval []PbmQueryProfileResult `xml:"returnval,omitempty"`
+}
+
+type PbmQueryByRollupComplianceStatus PbmQueryByRollupComplianceStatusRequestType
+
+func init() {
+ types.Add("pbm:PbmQueryByRollupComplianceStatus", reflect.TypeOf((*PbmQueryByRollupComplianceStatus)(nil)).Elem())
+}
+
+type PbmQueryByRollupComplianceStatusRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Status string `xml:"status"`
+}
+
+func init() {
+ types.Add("pbm:PbmQueryByRollupComplianceStatusRequestType", reflect.TypeOf((*PbmQueryByRollupComplianceStatusRequestType)(nil)).Elem())
+}
+
+type PbmQueryByRollupComplianceStatusResponse struct {
+ Returnval []PbmServerObjectRef `xml:"returnval,omitempty"`
+}
+
+type PbmQueryDefaultRequirementProfile PbmQueryDefaultRequirementProfileRequestType
+
+func init() {
+ types.Add("pbm:PbmQueryDefaultRequirementProfile", reflect.TypeOf((*PbmQueryDefaultRequirementProfile)(nil)).Elem())
+}
+
+type PbmQueryDefaultRequirementProfileRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Hub PbmPlacementHub `xml:"hub"`
+}
+
+func init() {
+ types.Add("pbm:PbmQueryDefaultRequirementProfileRequestType", reflect.TypeOf((*PbmQueryDefaultRequirementProfileRequestType)(nil)).Elem())
+}
+
+type PbmQueryDefaultRequirementProfileResponse struct {
+ Returnval *PbmProfileId `xml:"returnval,omitempty"`
+}
+
+type PbmQueryDefaultRequirementProfiles PbmQueryDefaultRequirementProfilesRequestType
+
+func init() {
+ types.Add("pbm:PbmQueryDefaultRequirementProfiles", reflect.TypeOf((*PbmQueryDefaultRequirementProfiles)(nil)).Elem())
+}
+
+type PbmQueryDefaultRequirementProfilesRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Datastores []PbmPlacementHub `xml:"datastores"`
+}
+
+func init() {
+ types.Add("pbm:PbmQueryDefaultRequirementProfilesRequestType", reflect.TypeOf((*PbmQueryDefaultRequirementProfilesRequestType)(nil)).Elem())
+}
+
+type PbmQueryDefaultRequirementProfilesResponse struct {
+ Returnval []PbmDefaultProfileInfo `xml:"returnval"`
+}
+
+type PbmQueryMatchingHub PbmQueryMatchingHubRequestType
+
+func init() {
+ types.Add("pbm:PbmQueryMatchingHub", reflect.TypeOf((*PbmQueryMatchingHub)(nil)).Elem())
+}
+
+type PbmQueryMatchingHubRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ HubsToSearch []PbmPlacementHub `xml:"hubsToSearch,omitempty"`
+ Profile PbmProfileId `xml:"profile"`
+}
+
+func init() {
+ types.Add("pbm:PbmQueryMatchingHubRequestType", reflect.TypeOf((*PbmQueryMatchingHubRequestType)(nil)).Elem())
+}
+
+type PbmQueryMatchingHubResponse struct {
+ Returnval []PbmPlacementHub `xml:"returnval,omitempty"`
+}
+
+type PbmQueryMatchingHubWithSpec PbmQueryMatchingHubWithSpecRequestType
+
+func init() {
+ types.Add("pbm:PbmQueryMatchingHubWithSpec", reflect.TypeOf((*PbmQueryMatchingHubWithSpec)(nil)).Elem())
+}
+
+type PbmQueryMatchingHubWithSpecRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ HubsToSearch []PbmPlacementHub `xml:"hubsToSearch,omitempty"`
+ CreateSpec PbmCapabilityProfileCreateSpec `xml:"createSpec"`
+}
+
+func init() {
+ types.Add("pbm:PbmQueryMatchingHubWithSpecRequestType", reflect.TypeOf((*PbmQueryMatchingHubWithSpecRequestType)(nil)).Elem())
+}
+
+type PbmQueryMatchingHubWithSpecResponse struct {
+ Returnval []PbmPlacementHub `xml:"returnval,omitempty"`
+}
+
+type PbmQueryProfile PbmQueryProfileRequestType
+
+func init() {
+ types.Add("pbm:PbmQueryProfile", reflect.TypeOf((*PbmQueryProfile)(nil)).Elem())
+}
+
+type PbmQueryProfileRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ ResourceType PbmProfileResourceType `xml:"resourceType"`
+ ProfileCategory string `xml:"profileCategory,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmQueryProfileRequestType", reflect.TypeOf((*PbmQueryProfileRequestType)(nil)).Elem())
+}
+
+type PbmQueryProfileResponse struct {
+ Returnval []PbmProfileId `xml:"returnval,omitempty"`
+}
+
+type PbmQueryProfileResult struct {
+ types.DynamicData
+
+ Object PbmServerObjectRef `xml:"object"`
+ ProfileId []PbmProfileId `xml:"profileId,omitempty"`
+ Fault *types.LocalizedMethodFault `xml:"fault,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmQueryProfileResult", reflect.TypeOf((*PbmQueryProfileResult)(nil)).Elem())
+}
+
+type PbmQueryReplicationGroupResult struct {
+ types.DynamicData
+
+ Object PbmServerObjectRef `xml:"object"`
+ ReplicationGroupId *types.ReplicationGroupId `xml:"replicationGroupId,omitempty"`
+ Fault *types.LocalizedMethodFault `xml:"fault,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmQueryReplicationGroupResult", reflect.TypeOf((*PbmQueryReplicationGroupResult)(nil)).Elem())
+}
+
+type PbmQueryReplicationGroups PbmQueryReplicationGroupsRequestType
+
+func init() {
+ types.Add("pbm:PbmQueryReplicationGroups", reflect.TypeOf((*PbmQueryReplicationGroups)(nil)).Elem())
+}
+
+type PbmQueryReplicationGroupsRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Entities []PbmServerObjectRef `xml:"entities,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmQueryReplicationGroupsRequestType", reflect.TypeOf((*PbmQueryReplicationGroupsRequestType)(nil)).Elem())
+}
+
+type PbmQueryReplicationGroupsResponse struct {
+ Returnval []PbmQueryReplicationGroupResult `xml:"returnval,omitempty"`
+}
+
+type PbmQuerySpaceStatsForStorageContainer PbmQuerySpaceStatsForStorageContainerRequestType
+
+func init() {
+ types.Add("pbm:PbmQuerySpaceStatsForStorageContainer", reflect.TypeOf((*PbmQuerySpaceStatsForStorageContainer)(nil)).Elem())
+}
+
+type PbmQuerySpaceStatsForStorageContainerRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Datastore PbmServerObjectRef `xml:"datastore"`
+ CapabilityProfileId []PbmProfileId `xml:"capabilityProfileId,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmQuerySpaceStatsForStorageContainerRequestType", reflect.TypeOf((*PbmQuerySpaceStatsForStorageContainerRequestType)(nil)).Elem())
+}
+
+type PbmQuerySpaceStatsForStorageContainerResponse struct {
+ Returnval []PbmDatastoreSpaceStatistics `xml:"returnval,omitempty"`
+}
+
+type PbmResetDefaultRequirementProfile PbmResetDefaultRequirementProfileRequestType
+
+func init() {
+ types.Add("pbm:PbmResetDefaultRequirementProfile", reflect.TypeOf((*PbmResetDefaultRequirementProfile)(nil)).Elem())
+}
+
+type PbmResetDefaultRequirementProfileRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ Profile *PbmProfileId `xml:"profile,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmResetDefaultRequirementProfileRequestType", reflect.TypeOf((*PbmResetDefaultRequirementProfileRequestType)(nil)).Elem())
+}
+
+type PbmResetDefaultRequirementProfileResponse struct {
+}
+
+type PbmResetVSanDefaultProfile PbmResetVSanDefaultProfileRequestType
+
+func init() {
+ types.Add("pbm:PbmResetVSanDefaultProfile", reflect.TypeOf((*PbmResetVSanDefaultProfile)(nil)).Elem())
+}
+
+type PbmResetVSanDefaultProfileRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+}
+
+func init() {
+ types.Add("pbm:PbmResetVSanDefaultProfileRequestType", reflect.TypeOf((*PbmResetVSanDefaultProfileRequestType)(nil)).Elem())
+}
+
+type PbmResetVSanDefaultProfileResponse struct {
+}
+
+type PbmResourceInUse struct {
+ PbmFault
+
+ Type string `xml:"type,omitempty"`
+ Name string `xml:"name,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmResourceInUse", reflect.TypeOf((*PbmResourceInUse)(nil)).Elem())
+}
+
+type PbmResourceInUseFault PbmResourceInUse
+
+func init() {
+ types.Add("pbm:PbmResourceInUseFault", reflect.TypeOf((*PbmResourceInUseFault)(nil)).Elem())
+}
+
+type PbmRetrieveContent PbmRetrieveContentRequestType
+
+func init() {
+ types.Add("pbm:PbmRetrieveContent", reflect.TypeOf((*PbmRetrieveContent)(nil)).Elem())
+}
+
+type PbmRetrieveContentRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ ProfileIds []PbmProfileId `xml:"profileIds"`
+}
+
+func init() {
+ types.Add("pbm:PbmRetrieveContentRequestType", reflect.TypeOf((*PbmRetrieveContentRequestType)(nil)).Elem())
+}
+
+type PbmRetrieveContentResponse struct {
+ Returnval []BasePbmProfile `xml:"returnval,typeattr"`
+}
+
+type PbmRetrieveServiceContent PbmRetrieveServiceContentRequestType
+
+func init() {
+ types.Add("pbm:PbmRetrieveServiceContent", reflect.TypeOf((*PbmRetrieveServiceContent)(nil)).Elem())
+}
+
+type PbmRetrieveServiceContentRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+}
+
+func init() {
+ types.Add("pbm:PbmRetrieveServiceContentRequestType", reflect.TypeOf((*PbmRetrieveServiceContentRequestType)(nil)).Elem())
+}
+
+type PbmRetrieveServiceContentResponse struct {
+ Returnval PbmServiceInstanceContent `xml:"returnval"`
+}
+
+type PbmRollupComplianceResult struct {
+ types.DynamicData
+
+ OldestCheckTime time.Time `xml:"oldestCheckTime"`
+ Entity PbmServerObjectRef `xml:"entity"`
+ OverallComplianceStatus string `xml:"overallComplianceStatus"`
+ OverallComplianceTaskStatus string `xml:"overallComplianceTaskStatus,omitempty"`
+ Result []PbmComplianceResult `xml:"result,omitempty"`
+ ErrorCause []types.LocalizedMethodFault `xml:"errorCause,omitempty"`
+ ProfileMismatch bool `xml:"profileMismatch"`
+}
+
+func init() {
+ types.Add("pbm:PbmRollupComplianceResult", reflect.TypeOf((*PbmRollupComplianceResult)(nil)).Elem())
+}
+
+type PbmServerObjectRef struct {
+ types.DynamicData
+
+ ObjectType string `xml:"objectType"`
+ Key string `xml:"key"`
+ ServerUuid string `xml:"serverUuid,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmServerObjectRef", reflect.TypeOf((*PbmServerObjectRef)(nil)).Elem())
+}
+
+type PbmServiceInstanceContent struct {
+ types.DynamicData
+
+ AboutInfo PbmAboutInfo `xml:"aboutInfo"`
+ SessionManager types.ManagedObjectReference `xml:"sessionManager"`
+ CapabilityMetadataManager types.ManagedObjectReference `xml:"capabilityMetadataManager"`
+ ProfileManager types.ManagedObjectReference `xml:"profileManager"`
+ ComplianceManager types.ManagedObjectReference `xml:"complianceManager"`
+ PlacementSolver types.ManagedObjectReference `xml:"placementSolver"`
+ ReplicationManager *types.ManagedObjectReference `xml:"replicationManager,omitempty"`
+}
+
+func init() {
+ types.Add("pbm:PbmServiceInstanceContent", reflect.TypeOf((*PbmServiceInstanceContent)(nil)).Elem())
+}
+
+type PbmUpdate PbmUpdateRequestType
+
+func init() {
+ types.Add("pbm:PbmUpdate", reflect.TypeOf((*PbmUpdate)(nil)).Elem())
+}
+
+type PbmUpdateRequestType struct {
+ This types.ManagedObjectReference `xml:"_this"`
+ ProfileId PbmProfileId `xml:"profileId"`
+ UpdateSpec PbmCapabilityProfileUpdateSpec `xml:"updateSpec"`
+}
+
+func init() {
+ types.Add("pbm:PbmUpdateRequestType", reflect.TypeOf((*PbmUpdateRequestType)(nil)).Elem())
+}
+
+type PbmUpdateResponse struct {
+}
+
+type PbmVaioDataServiceInfo struct {
+ PbmLineOfServiceInfo
+}
+
+func init() {
+ types.Add("pbm:PbmVaioDataServiceInfo", reflect.TypeOf((*PbmVaioDataServiceInfo)(nil)).Elem())
+}
diff --git a/vendor/github.com/vmware/govmomi/performance/manager.go b/vendor/github.com/vmware/govmomi/performance/manager.go
new file mode 100644
index 00000000..736c9e19
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/performance/manager.go
@@ -0,0 +1,431 @@
+/*
+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 performance
+
+import (
+ "context"
+ "fmt"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/vim25"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+// Manager wraps mo.PerformanceManager.
+type Manager struct {
+ object.Common
+
+ Sort bool
+
+ pm struct {
+ sync.Mutex
+ *mo.PerformanceManager
+ }
+
+ providerSummary struct {
+ sync.Mutex
+ m map[string]*types.PerfProviderSummary
+ }
+
+ infoByName struct {
+ sync.Mutex
+ m map[string]*types.PerfCounterInfo
+ }
+
+ infoByKey struct {
+ sync.Mutex
+ m map[int32]*types.PerfCounterInfo
+ }
+}
+
+// NewManager creates a new Manager instance.
+func NewManager(client *vim25.Client) *Manager {
+ m := Manager{
+ Common: object.NewCommon(client, *client.ServiceContent.PerfManager),
+ }
+
+ m.pm.PerformanceManager = new(mo.PerformanceManager)
+
+ return &m
+}
+
+// IntervalList wraps []types.PerfInterval.
+type IntervalList []types.PerfInterval
+
+// Enabled returns a map with Level as the key and enabled PerfInterval.Name(s) as the value.
+func (l IntervalList) Enabled() map[int32][]string {
+ enabled := make(map[int32][]string)
+
+ for level := int32(0); level <= 4; level++ {
+ var names []string
+
+ for _, interval := range l {
+ if interval.Enabled && interval.Level >= level {
+ names = append(names, interval.Name)
+ }
+ }
+
+ enabled[level] = names
+ }
+
+ return enabled
+}
+
+// HistoricalInterval gets the PerformanceManager.HistoricalInterval property and wraps as an IntervalList.
+func (m *Manager) HistoricalInterval(ctx context.Context) (IntervalList, error) {
+ var pm mo.PerformanceManager
+
+ err := m.Properties(ctx, m.Reference(), []string{"historicalInterval"}, &pm)
+ if err != nil {
+ return nil, err
+ }
+
+ return IntervalList(pm.HistoricalInterval), nil
+}
+
+// CounterInfo gets the PerformanceManager.PerfCounter property.
+// The property value is only collected once, subsequent calls return the cached value.
+func (m *Manager) CounterInfo(ctx context.Context) ([]types.PerfCounterInfo, error) {
+ m.pm.Lock()
+ defer m.pm.Unlock()
+
+ if len(m.pm.PerfCounter) == 0 {
+ err := m.Properties(ctx, m.Reference(), []string{"perfCounter"}, m.pm.PerformanceManager)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return m.pm.PerfCounter, nil
+}
+
+// CounterInfoByName converts the PerformanceManager.PerfCounter property to a map,
+// where key is types.PerfCounterInfo.Name().
+func (m *Manager) CounterInfoByName(ctx context.Context) (map[string]*types.PerfCounterInfo, error) {
+ m.infoByName.Lock()
+ defer m.infoByName.Unlock()
+
+ if m.infoByName.m != nil {
+ return m.infoByName.m, nil
+ }
+
+ info, err := m.CounterInfo(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ m.infoByName.m = make(map[string]*types.PerfCounterInfo)
+
+ for i := range info {
+ c := &info[i]
+
+ m.infoByName.m[c.Name()] = c
+ }
+
+ return m.infoByName.m, nil
+}
+
+// CounterInfoByKey converts the PerformanceManager.PerfCounter property to a map,
+// where key is types.PerfCounterInfo.Key.
+func (m *Manager) CounterInfoByKey(ctx context.Context) (map[int32]*types.PerfCounterInfo, error) {
+ m.infoByKey.Lock()
+ defer m.infoByKey.Unlock()
+
+ if m.infoByKey.m != nil {
+ return m.infoByKey.m, nil
+ }
+
+ info, err := m.CounterInfo(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ m.infoByKey.m = make(map[int32]*types.PerfCounterInfo)
+
+ for i := range info {
+ c := &info[i]
+
+ m.infoByKey.m[c.Key] = c
+ }
+
+ return m.infoByKey.m, nil
+}
+
+// ProviderSummary wraps the QueryPerfProviderSummary method, caching the value based on entity.Type.
+func (m *Manager) ProviderSummary(ctx context.Context, entity types.ManagedObjectReference) (*types.PerfProviderSummary, error) {
+ m.providerSummary.Lock()
+ defer m.providerSummary.Unlock()
+
+ if m.providerSummary.m == nil {
+ m.providerSummary.m = make(map[string]*types.PerfProviderSummary)
+ }
+
+ s, ok := m.providerSummary.m[entity.Type]
+ if ok {
+ return s, nil
+ }
+
+ req := types.QueryPerfProviderSummary{
+ This: m.Reference(),
+ Entity: entity,
+ }
+
+ res, err := methods.QueryPerfProviderSummary(ctx, m.Client(), &req)
+ if err != nil {
+ return nil, err
+ }
+
+ s = &res.Returnval
+
+ m.providerSummary.m[entity.Type] = s
+
+ return s, nil
+}
+
+type groupPerfCounterInfo struct {
+ info map[int32]*types.PerfCounterInfo
+ ids []types.PerfMetricId
+}
+
+func (d groupPerfCounterInfo) Len() int {
+ return len(d.ids)
+}
+
+func (d groupPerfCounterInfo) Less(i, j int) bool {
+ ci := d.ids[i].CounterId
+ cj := d.ids[j].CounterId
+ gi := d.info[ci].GroupInfo.GetElementDescription()
+ gj := d.info[cj].GroupInfo.GetElementDescription()
+
+ return gi.Key < gj.Key
+}
+
+func (d groupPerfCounterInfo) Swap(i, j int) {
+ d.ids[i], d.ids[j] = d.ids[j], d.ids[i]
+}
+
+// MetricList wraps []types.PerfMetricId
+type MetricList []types.PerfMetricId
+
+// ByKey converts MetricList to map, where key is types.PerfMetricId.CounterId / types.PerfCounterInfo.Key
+func (l MetricList) ByKey() map[int32][]*types.PerfMetricId {
+ ids := make(map[int32][]*types.PerfMetricId, len(l))
+
+ for i := range l {
+ id := &l[i]
+ ids[id.CounterId] = append(ids[id.CounterId], id)
+ }
+
+ return ids
+}
+
+// AvailableMetric wraps the QueryAvailablePerfMetric method.
+// The MetricList is sorted by PerfCounterInfo.GroupInfo.Key if Manager.Sort == true.
+func (m *Manager) AvailableMetric(ctx context.Context, entity types.ManagedObjectReference, interval int32) (MetricList, error) {
+ req := types.QueryAvailablePerfMetric{
+ This: m.Reference(),
+ Entity: entity.Reference(),
+ IntervalId: interval,
+ }
+
+ res, err := methods.QueryAvailablePerfMetric(ctx, m.Client(), &req)
+ if err != nil {
+ return nil, err
+ }
+
+ if m.Sort {
+ info, err := m.CounterInfoByKey(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ sort.Sort(groupPerfCounterInfo{info, res.Returnval})
+ }
+
+ return MetricList(res.Returnval), nil
+}
+
+// Query wraps the QueryPerf method.
+func (m *Manager) Query(ctx context.Context, spec []types.PerfQuerySpec) ([]types.BasePerfEntityMetricBase, error) {
+ req := types.QueryPerf{
+ This: m.Reference(),
+ QuerySpec: spec,
+ }
+
+ res, err := methods.QueryPerf(ctx, m.Client(), &req)
+ if err != nil {
+ return nil, err
+ }
+
+ return res.Returnval, nil
+}
+
+// SampleByName uses the spec param as a template, constructing a []types.PerfQuerySpec for the given metrics and entities
+// and invoking the Query method.
+// The spec template can specify instances using the MetricId.Instance field, by default all instances are collected.
+// The spec template MaxSample defaults to 1.
+// If the spec template IntervalId is a historical interval and StartTime is not specified,
+// the StartTime is set to the current time - (IntervalId * MaxSample).
+func (m *Manager) SampleByName(ctx context.Context, spec types.PerfQuerySpec, metrics []string, entity []types.ManagedObjectReference) ([]types.BasePerfEntityMetricBase, error) {
+ info, err := m.CounterInfoByName(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ var ids []types.PerfMetricId
+
+ instances := spec.MetricId
+ if len(instances) == 0 {
+ // Default to all instances
+ instances = []types.PerfMetricId{{Instance: "*"}}
+ }
+
+ for _, name := range metrics {
+ counter, ok := info[name]
+ if !ok {
+ return nil, fmt.Errorf("counter %q not found", name)
+ }
+
+ for _, i := range instances {
+ ids = append(ids, types.PerfMetricId{CounterId: counter.Key, Instance: i.Instance})
+ }
+ }
+
+ spec.MetricId = ids
+
+ if spec.MaxSample == 0 {
+ spec.MaxSample = 1
+ }
+
+ if spec.IntervalId >= 60 && spec.StartTime == nil {
+ // Need a StartTime to make use of history
+ now, err := methods.GetCurrentTime(ctx, m.Client())
+ if err != nil {
+ return nil, err
+ }
+
+ // Go back in time
+ x := spec.IntervalId * -1 * spec.MaxSample
+ t := now.Add(time.Duration(x) * time.Second)
+ spec.StartTime = &t
+ }
+
+ var query []types.PerfQuerySpec
+
+ for _, e := range entity {
+ spec.Entity = e.Reference()
+ query = append(query, spec)
+ }
+
+ return m.Query(ctx, query)
+}
+
+// MetricSeries contains the same data as types.PerfMetricIntSeries, but with the CounterId converted to Name.
+type MetricSeries struct {
+ Name string
+ unit string
+ Instance string
+ Value []int64
+}
+
+func (s *MetricSeries) Format(val int64) string {
+ switch types.PerformanceManagerUnit(s.unit) {
+ case types.PerformanceManagerUnitPercent:
+ return strconv.FormatFloat(float64(val)/100.0, 'f', 2, 64)
+ default:
+ return strconv.FormatInt(val, 10)
+ }
+}
+
+// ValueCSV converts the Value field to a CSV string
+func (s *MetricSeries) ValueCSV() string {
+ vals := make([]string, len(s.Value))
+
+ for i := range s.Value {
+ vals[i] = s.Format(s.Value[i])
+ }
+
+ return strings.Join(vals, ",")
+}
+
+// EntityMetric contains the same data as types.PerfEntityMetric, but with MetricSeries type for the Value field.
+type EntityMetric struct {
+ Entity types.ManagedObjectReference
+
+ SampleInfo []types.PerfSampleInfo
+ Value []MetricSeries
+}
+
+// SampleInfoCSV converts the SampleInfo field to a CSV string
+func (m *EntityMetric) SampleInfoCSV() string {
+ vals := make([]string, len(m.SampleInfo)*2)
+
+ i := 0
+
+ for _, s := range m.SampleInfo {
+ vals[i] = s.Timestamp.Format(time.RFC3339)
+ i++
+ vals[i] = strconv.Itoa(int(s.Interval))
+ i++
+ }
+
+ return strings.Join(vals, ",")
+}
+
+// ToMetricSeries converts []BasePerfEntityMetricBase to []EntityMetric
+func (m *Manager) ToMetricSeries(ctx context.Context, series []types.BasePerfEntityMetricBase) ([]EntityMetric, error) {
+ counters, err := m.CounterInfoByKey(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ var result []EntityMetric
+
+ for i := range series {
+ var values []MetricSeries
+ s, ok := series[i].(*types.PerfEntityMetric)
+ if !ok {
+ panic(fmt.Errorf("expected type %T, got: %T", s, series[i]))
+ }
+
+ for j := range s.Value {
+ v := s.Value[j].(*types.PerfMetricIntSeries)
+
+ values = append(values, MetricSeries{
+ Name: counters[v.Id.CounterId].Name(),
+ unit: counters[v.Id.CounterId].UnitInfo.GetElementDescription().Key,
+ Instance: v.Id.Instance,
+ Value: v.Value,
+ })
+ }
+
+ result = append(result, EntityMetric{
+ Entity: s.Entity,
+ SampleInfo: s.SampleInfo,
+ Value: values,
+ })
+ }
+
+ return result, nil
+}
diff --git a/vendor/github.com/vmware/govmomi/property/collector.go b/vendor/github.com/vmware/govmomi/property/collector.go
index 32a0e409..04a9e773 100644
--- a/vendor/github.com/vmware/govmomi/property/collector.go
+++ b/vendor/github.com/vmware/govmomi/property/collector.go
@@ -30,7 +30,7 @@ import (
// Collector models the PropertyCollector managed object.
//
// For more information, see:
-// http://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vmodl.query.PropertyCollector.html
+// http://pubs.vmware.com/vsphere-60/index.jsp?topic=%2Fcom.vmware.wssdk.apiref.doc%2Fvmodl.query.PropertyCollector.html
//
type Collector struct {
roundTripper soap.RoundTripper
@@ -164,9 +164,36 @@ func (p *Collector) Retrieve(ctx context.Context, objs []types.ManagedObjectRefe
return err
}
+ if d, ok := dst.(*[]types.ObjectContent); ok {
+ *d = res.Returnval
+ return nil
+ }
+
return mo.LoadRetrievePropertiesResponse(res, dst)
}
+// RetrieveWithFilter populates dst as Retrieve does, but only for entities matching the given filter.
+func (p *Collector) RetrieveWithFilter(ctx context.Context, objs []types.ManagedObjectReference, ps []string, dst interface{}, filter Filter) error {
+ if len(filter) == 0 {
+ return p.Retrieve(ctx, objs, ps, dst)
+ }
+
+ var content []types.ObjectContent
+
+ err := p.Retrieve(ctx, objs, filter.Keys(), &content)
+ if err != nil {
+ return err
+ }
+
+ objs = filter.MatchObjectContent(content)
+
+ if len(objs) == 0 {
+ return nil
+ }
+
+ return p.Retrieve(ctx, objs, ps, dst)
+}
+
// RetrieveOne calls Retrieve with a single managed object reference.
func (p *Collector) RetrieveOne(ctx context.Context, obj types.ManagedObjectReference, ps []string, dst interface{}) error {
var objs = []types.ManagedObjectReference{obj}
diff --git a/vendor/github.com/vmware/govmomi/property/filter.go b/vendor/github.com/vmware/govmomi/property/filter.go
new file mode 100644
index 00000000..8284b0c7
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/property/filter.go
@@ -0,0 +1,139 @@
+/*
+Copyright (c) 2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package property
+
+import (
+ "fmt"
+ "path"
+ "reflect"
+ "strconv"
+ "strings"
+
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+// Filter provides methods for matching against types.DynamicProperty
+type Filter map[string]types.AnyType
+
+// Keys returns the Filter map keys as a []string
+func (f Filter) Keys() []string {
+ keys := make([]string, 0, len(f))
+
+ for key := range f {
+ keys = append(keys, key)
+ }
+
+ return keys
+}
+
+// MatchProperty returns true if a Filter entry matches the given prop.
+func (f Filter) MatchProperty(prop types.DynamicProperty) bool {
+ match, ok := f[prop.Name]
+ if !ok {
+ return false
+ }
+
+ if match == prop.Val {
+ return true
+ }
+
+ ptype := reflect.TypeOf(prop.Val)
+
+ if strings.HasPrefix(ptype.Name(), "ArrayOf") {
+ pval := reflect.ValueOf(prop.Val).Field(0)
+
+ for i := 0; i < pval.Len(); i++ {
+ prop.Val = pval.Index(i).Interface()
+
+ if f.MatchProperty(prop) {
+ return true
+ }
+ }
+
+ return false
+ }
+
+ if reflect.TypeOf(match) != ptype {
+ s, ok := match.(string)
+ if !ok {
+ return false
+ }
+
+ // convert if we can
+ switch prop.Val.(type) {
+ case bool:
+ match, _ = strconv.ParseBool(s)
+ case int16:
+ x, _ := strconv.ParseInt(s, 10, 16)
+ match = int16(x)
+ case int32:
+ x, _ := strconv.ParseInt(s, 10, 32)
+ match = int32(x)
+ case int64:
+ match, _ = strconv.ParseInt(s, 10, 64)
+ case float32:
+ x, _ := strconv.ParseFloat(s, 32)
+ match = float32(x)
+ case float64:
+ match, _ = strconv.ParseFloat(s, 64)
+ case fmt.Stringer:
+ prop.Val = prop.Val.(fmt.Stringer).String()
+ default:
+ if ptype.Kind() != reflect.String {
+ return false
+ }
+ // An enum type we can convert to a string type
+ prop.Val = reflect.ValueOf(prop.Val).String()
+ }
+ }
+
+ switch pval := prop.Val.(type) {
+ case string:
+ s := match.(string)
+ if s == "*" {
+ return true // TODO: path.Match fails if s contains a '/'
+ }
+ m, _ := path.Match(s, pval)
+ return m
+ default:
+ return reflect.DeepEqual(match, pval)
+ }
+}
+
+// MatchPropertyList returns true if all given props match the Filter.
+func (f Filter) MatchPropertyList(props []types.DynamicProperty) bool {
+ for _, p := range props {
+ if !f.MatchProperty(p) {
+ return false
+ }
+ }
+
+ return true
+}
+
+// MatchObjectContent returns a list of ObjectContent.Obj where the ObjectContent.PropSet matches the Filter.
+func (f Filter) MatchObjectContent(objects []types.ObjectContent) []types.ManagedObjectReference {
+ var refs []types.ManagedObjectReference
+
+ for _, o := range objects {
+ if f.MatchPropertyList(o.PropSet) {
+ refs = append(refs, o.Obj)
+ }
+ }
+
+ return refs
+}
diff --git a/vendor/github.com/vmware/govmomi/property/wait.go b/vendor/github.com/vmware/govmomi/property/wait.go
index 689477bf..fe847926 100644
--- a/vendor/github.com/vmware/govmomi/property/wait.go
+++ b/vendor/github.com/vmware/govmomi/property/wait.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2015 VMware, Inc. All Rights Reserved.
+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.
@@ -22,73 +22,63 @@ import (
"github.com/vmware/govmomi/vim25/types"
)
-// Wait waits for any of the specified properties of the specified managed
-// object to change. It calls the specified function for every update it
-// receives. If this function returns false, it continues waiting for
-// subsequent updates. If this function returns true, it stops waiting and
-// returns.
-//
-// To only receive updates for the specified managed object, the function
-// creates a new property collector and calls CreateFilter. A new property
-// collector is required because filters can only be added, not removed.
-//
-// The newly created collector is destroyed before this function returns (both
-// in case of success or error).
-//
-func Wait(ctx context.Context, c *Collector, obj types.ManagedObjectReference, ps []string, f func([]types.PropertyChange) bool) error {
- p, err := c.Create(ctx)
- if err != nil {
- return err
- }
+// WaitFilter provides helpers to construct a types.CreateFilter for use with property.Wait
+type WaitFilter struct {
+ types.CreateFilter
+}
- // Attempt to destroy the collector using the background context, as the
- // specified context may have timed out or have been cancelled.
- defer p.Destroy(context.Background())
+// Add a new ObjectSpec and PropertySpec to the WaitFilter
+func (f *WaitFilter) Add(obj types.ManagedObjectReference, kind string, ps []string, set ...types.BaseSelectionSpec) *WaitFilter {
+ spec := types.ObjectSpec{
+ Obj: obj,
+ SelectSet: set,
+ }
- req := types.CreateFilter{
- Spec: types.PropertyFilterSpec{
- ObjectSet: []types.ObjectSpec{
- {
- Obj: obj,
- },
- },
- PropSet: []types.PropertySpec{
- {
- PathSet: ps,
- Type: obj.Type,
- },
- },
- },
+ pset := types.PropertySpec{
+ Type: kind,
+ PathSet: ps,
}
if len(ps) == 0 {
- req.Spec.PropSet[0].All = types.NewBool(true)
+ pset.All = types.NewBool(true)
}
- err = p.CreateFilter(ctx, req)
- if err != nil {
- return err
- }
- return waitLoop(ctx, p, func(_ types.ManagedObjectReference, pc []types.PropertyChange) bool {
- return f(pc)
+ f.Spec.ObjectSet = append(f.Spec.ObjectSet, spec)
+
+ f.Spec.PropSet = append(f.Spec.PropSet, pset)
+
+ return f
+}
+
+// Wait creates a new WaitFilter and calls the specified function for each ObjectUpdate via WaitForUpdates
+func Wait(ctx context.Context, c *Collector, obj types.ManagedObjectReference, ps []string, f func([]types.PropertyChange) bool) error {
+ filter := new(WaitFilter).Add(obj, obj.Type, ps)
+
+ return WaitForUpdates(ctx, c, filter, func(updates []types.ObjectUpdate) bool {
+ for _, update := range updates {
+ if f(update.ChangeSet) {
+ return true
+ }
+ }
+
+ return false
})
}
-// WaitForView waits for any of the specified properties of the managed
-// objects in the View to change. It calls the specified function for every update it
+// WaitForUpdates waits for any of the specified properties of the specified managed
+// object to change. It calls the specified function for every update it
// receives. If this function returns false, it continues waiting for
// subsequent updates. If this function returns true, it stops waiting and
// returns.
//
-// To only receive updates for the View's specified managed objects, the function
+// To only receive updates for the specified managed object, the function
// creates a new property collector and calls CreateFilter. A new property
// collector is required because filters can only be added, not removed.
//
// The newly created collector is destroyed before this function returns (both
// in case of success or error).
//
-// The code assumes that all objects in the View are the same type
-func WaitForView(ctx context.Context, c *Collector, view types.ManagedObjectReference, obj types.ManagedObjectReference, ps []string, f func(types.ManagedObjectReference, []types.PropertyChange) bool) error {
+func WaitForUpdates(ctx context.Context, c *Collector, filter *WaitFilter, f func([]types.ObjectUpdate) bool) error {
p, err := c.Create(ctx)
if err != nil {
return err
@@ -98,38 +88,13 @@ func WaitForView(ctx context.Context, c *Collector, view types.ManagedObjectRefe
// specified context may have timed out or have been cancelled.
defer p.Destroy(context.Background())
- req := types.CreateFilter{
- Spec: types.PropertyFilterSpec{
- ObjectSet: []types.ObjectSpec{
- {
- Obj: view,
- SelectSet: []types.BaseSelectionSpec{
- &types.TraversalSpec{
- SelectionSpec: types.SelectionSpec{
- Name: "traverseEntities",
- },
- Path: "view",
- Type: view.Type}},
- },
- },
- PropSet: []types.PropertySpec{
- {
- Type: obj.Type,
- PathSet: ps,
- },
- },
- }}
-
- err = p.CreateFilter(ctx, req)
+ err = p.CreateFilter(ctx, filter.CreateFilter)
if err != nil {
return err
}
- return waitLoop(ctx, p, f)
-}
-func waitLoop(ctx context.Context, c *Collector, f func(types.ManagedObjectReference, []types.PropertyChange) bool) error {
for version := ""; ; {
- res, err := c.WaitForUpdates(ctx, version)
+ res, err := p.WaitForUpdates(ctx, version)
if err != nil {
return err
}
@@ -142,12 +107,9 @@ func waitLoop(ctx context.Context, c *Collector, f func(types.ManagedObjectRefer
version = res.Version
for _, fs := range res.FilterSet {
- for _, os := range fs.ObjectSet {
- if f(os.Obj, os.ChangeSet) {
- return nil
- }
+ if f(fs.ObjectSet) {
+ return nil
}
}
}
-
}
diff --git a/vendor/github.com/vmware/govmomi/simulator/cluster_compute_resource.go b/vendor/github.com/vmware/govmomi/simulator/cluster_compute_resource.go
new file mode 100644
index 00000000..d743c13a
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/cluster_compute_resource.go
@@ -0,0 +1,99 @@
+/*
+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 simulator
+
+import (
+ "github.com/vmware/govmomi/simulator/esx"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type ClusterComputeResource struct {
+ mo.ClusterComputeResource
+}
+
+type addHost struct {
+ *ClusterComputeResource
+
+ req *types.AddHost_Task
+}
+
+func (add *addHost) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
+ spec := add.req.Spec
+
+ if spec.HostName == "" {
+ return nil, &types.NoHost{}
+ }
+
+ host := NewHostSystem(esx.HostSystem)
+ host.Summary.Config.Name = spec.HostName
+ host.Name = host.Summary.Config.Name
+ host.Runtime.ConnectionState = types.HostSystemConnectionStateDisconnected
+
+ cr := add.ClusterComputeResource
+ Map.PutEntity(cr, Map.NewEntity(host))
+
+ cr.Host = append(cr.Host, host.Reference())
+
+ if add.req.AsConnected {
+ host.Runtime.ConnectionState = types.HostSystemConnectionStateConnected
+ }
+
+ return host.Reference(), nil
+}
+
+func (c *ClusterComputeResource) AddHostTask(add *types.AddHost_Task) soap.HasFault {
+ r := &methods.AddHost_TaskBody{}
+
+ task := NewTask(&addHost{c, add})
+
+ r.Res = &types.AddHost_TaskResponse{
+ Returnval: task.Self,
+ }
+
+ task.Run()
+
+ return r
+}
+
+func CreateClusterComputeResource(f *Folder, name string, spec types.ClusterConfigSpecEx) (*ClusterComputeResource, types.BaseMethodFault) {
+ if e := Map.FindByName(name, f.ChildEntity); e != nil {
+ return nil, &types.DuplicateName{
+ Name: e.Entity().Name,
+ Object: e.Reference(),
+ }
+ }
+
+ cluster := &ClusterComputeResource{}
+ cluster.Name = name
+
+ config := &types.ClusterConfigInfoEx{}
+ cluster.ConfigurationEx = config
+
+ config.DrsConfig.Enabled = types.NewBool(true)
+
+ pool := NewResourcePool()
+ Map.PutEntity(cluster, Map.NewEntity(pool))
+ cluster.ResourcePool = &pool.Self
+
+ f.putChild(cluster)
+ pool.Owner = cluster.Self
+
+ return cluster, nil
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/datacenter.go b/vendor/github.com/vmware/govmomi/simulator/datacenter.go
new file mode 100644
index 00000000..15b5d432
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/datacenter.go
@@ -0,0 +1,76 @@
+/*
+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 simulator
+
+import (
+ "strings"
+
+ "github.com/vmware/govmomi/simulator/esx"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+// Create Datacenter Folders.
+// Every Datacenter has 4 inventory Folders: Vm, Host, Datastore and Network.
+// The ESX folder child types are limited to 1 type.
+// The VC folders have additional child types, including nested folders.
+func createDatacenterFolders(dc *mo.Datacenter, isVC bool) {
+ folders := []struct {
+ ref *types.ManagedObjectReference
+ name string
+ types []string
+ }{
+ {&dc.VmFolder, "vm", []string{"VirtualMachine", "VirtualApp", "Folder"}},
+ {&dc.HostFolder, "host", []string{"ComputeResource", "Folder"}},
+ {&dc.DatastoreFolder, "datastore", []string{"Datastore", "StoragePod", "Folder"}},
+ {&dc.NetworkFolder, "network", []string{"Network", "DistributedVirtualSwitch", "Folder"}},
+ }
+
+ for _, f := range folders {
+ folder := &Folder{}
+ folder.Name = f.name
+
+ if isVC {
+ folder.ChildType = f.types
+ e := Map.PutEntity(dc, folder)
+
+ // propagate the generated morefs to Datacenter
+ ref := e.Reference()
+ f.ref.Type = ref.Type
+ f.ref.Value = ref.Value
+ } else {
+ folder.ChildType = f.types[:1]
+ folder.Self = *f.ref
+ Map.PutEntity(dc, folder)
+ }
+ }
+
+ net := Map.Get(dc.NetworkFolder).(*Folder)
+
+ for _, ref := range esx.Datacenter.Network {
+ // Add VM Network by default to each Datacenter
+ network := &mo.Network{}
+ network.Self = ref
+ network.Name = strings.Split(ref.Value, "-")[1]
+ network.Entity().Name = network.Name
+ if isVC {
+ network.Self.Value = "" // we want a different moid per-DC
+ }
+
+ net.putChild(network)
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/datastore.go b/vendor/github.com/vmware/govmomi/simulator/datastore.go
new file mode 100644
index 00000000..4098fbcf
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/datastore.go
@@ -0,0 +1,76 @@
+/*
+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 simulator
+
+import (
+ "os/exec"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type Datastore struct {
+ mo.Datastore
+}
+
+func parseDatastorePath(dsPath string) (*object.DatastorePath, types.BaseMethodFault) {
+ var p object.DatastorePath
+
+ if p.FromString(dsPath) {
+ return &p, nil
+ }
+
+ return nil, &types.InvalidDatastorePath{DatastorePath: dsPath}
+}
+
+func (ds *Datastore) RefreshDatastore(*types.RefreshDatastore) soap.HasFault {
+ r := &methods.RefreshDatastoreBody{}
+
+ info := ds.Info.GetDatastoreInfo()
+
+ // #nosec: Subprocess launching with variable
+ buf, err := exec.Command("df", "-k", info.Url).Output()
+
+ if err != nil {
+ r.Fault_ = Fault(err.Error(), &types.HostConfigFault{})
+ return r
+ }
+
+ lines := strings.Split(string(buf), "\n")
+ columns := strings.Fields(lines[1])
+
+ used, _ := strconv.ParseInt(columns[2], 10, 64)
+ info.FreeSpace, _ = strconv.ParseInt(columns[3], 10, 64)
+
+ info.FreeSpace *= 1024
+ used *= 1024
+
+ ds.Summary.FreeSpace = info.FreeSpace
+ ds.Summary.Capacity = info.FreeSpace + used
+
+ now := time.Now()
+
+ info.Timestamp = &now
+
+ return r
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/dvs.go b/vendor/github.com/vmware/govmomi/simulator/dvs.go
new file mode 100644
index 00000000..4b62c55f
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/dvs.go
@@ -0,0 +1,124 @@
+/*
+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 simulator
+
+import (
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type VmwareDistributedVirtualSwitch struct {
+ mo.VmwareDistributedVirtualSwitch
+}
+
+func (s *VmwareDistributedVirtualSwitch) AddDVPortgroupTask(c *types.AddDVPortgroup_Task) soap.HasFault {
+ task := CreateTask(s, "addDVPortgroup", func(t *Task) (types.AnyType, types.BaseMethodFault) {
+ f := Map.getEntityParent(s, "Folder").(*Folder)
+
+ for _, spec := range c.Spec {
+ pg := &mo.DistributedVirtualPortgroup{}
+ pg.Name = spec.Name
+ pg.Entity().Name = pg.Name
+
+ if obj := Map.FindByName(pg.Name, f.ChildEntity); obj != nil {
+ return nil, &types.DuplicateName{
+ Name: pg.Name,
+ Object: obj.Reference(),
+ }
+ }
+
+ f.putChild(pg)
+
+ pg.Key = pg.Self.Value
+ pg.Config.DistributedVirtualSwitch = &s.Self
+
+ s.Portgroup = append(s.Portgroup, pg.Self)
+ s.Summary.PortgroupName = append(s.Summary.PortgroupName, pg.Name)
+
+ for _, h := range s.Summary.HostMember {
+ pg.Host = AddReference(h, pg.Host)
+ host := Map.Get(h).(*HostSystem)
+ host.Network = append(host.Network, pg.Reference())
+ }
+ }
+
+ return nil, nil
+ })
+
+ task.Run()
+
+ return &methods.AddDVPortgroup_TaskBody{
+ Res: &types.AddDVPortgroup_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
+
+func (s *VmwareDistributedVirtualSwitch) ReconfigureDvsTask(req *types.ReconfigureDvs_Task) soap.HasFault {
+ task := CreateTask(s, "reconfigureDvs", func(t *Task) (types.AnyType, types.BaseMethodFault) {
+ spec := req.Spec.GetDVSConfigSpec()
+
+ for _, member := range spec.Host {
+ h := Map.Get(member.Host)
+ if h == nil {
+ return nil, &types.ManagedObjectNotFound{Obj: member.Host}
+ }
+
+ host := h.(*HostSystem)
+
+ switch types.ConfigSpecOperation(member.Operation) {
+ case types.ConfigSpecOperationAdd:
+ if FindReference(host.Network, s.Self) != nil {
+ return nil, &types.AlreadyExists{Name: host.Name}
+ }
+
+ host.Network = append(host.Network, s.Self)
+ host.Network = append(host.Network, s.Portgroup...)
+ s.Summary.HostMember = append(s.Summary.HostMember, member.Host)
+
+ for _, ref := range s.Portgroup {
+ pg := Map.Get(ref).(*mo.DistributedVirtualPortgroup)
+ pg.Host = AddReference(member.Host, pg.Host)
+ }
+ case types.ConfigSpecOperationRemove:
+ if pg := FindReference(host.Network, s.Portgroup...); pg != nil {
+ return nil, &types.ResourceInUse{
+ Type: pg.Type,
+ Name: pg.Value,
+ }
+ }
+
+ host.Network = RemoveReference(s.Self, host.Network)
+ s.Summary.HostMember = RemoveReference(s.Self, s.Summary.HostMember)
+ case types.ConfigSpecOperationEdit:
+ return nil, &types.NotSupported{}
+ }
+ }
+
+ return nil, nil
+ })
+
+ task.Run()
+
+ return &methods.ReconfigureDvs_TaskBody{
+ Res: &types.ReconfigureDvs_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/entity.go b/vendor/github.com/vmware/govmomi/simulator/entity.go
new file mode 100644
index 00000000..06c61411
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/entity.go
@@ -0,0 +1,48 @@
+/*
+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 simulator
+
+import (
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+func RenameTask(e mo.Entity, r *types.Rename_Task) soap.HasFault {
+ task := CreateTask(e, "rename", func(t *Task) (types.AnyType, types.BaseMethodFault) {
+ obj := Map.Get(r.This).(mo.Entity).Entity()
+
+ if parent, ok := Map.Get(*obj.Parent).(*Folder); ok {
+ if Map.FindByName(r.NewName, parent.ChildEntity) != nil {
+ return nil, &types.InvalidArgument{InvalidProperty: "name"}
+ }
+ }
+
+ obj.Name = r.NewName
+
+ return nil, nil
+ })
+
+ task.Run()
+
+ return &methods.Rename_TaskBody{
+ Res: &types.Rename_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/datacenter.go b/vendor/github.com/vmware/govmomi/simulator/esx/datacenter.go
new file mode 100644
index 00000000..b202cbff
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/esx/datacenter.go
@@ -0,0 +1,57 @@
+/*
+Copyright (c) 2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package esx
+
+import (
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+var Datacenter = mo.Datacenter{
+ ManagedEntity: mo.ManagedEntity{
+ ExtensibleManagedObject: mo.ExtensibleManagedObject{
+ Self: types.ManagedObjectReference{Type: "Datacenter", Value: "ha-datacenter"},
+ Value: nil,
+ AvailableField: nil,
+ },
+ Parent: (*types.ManagedObjectReference)(nil),
+ CustomValue: nil,
+ OverallStatus: "",
+ ConfigStatus: "",
+ ConfigIssue: nil,
+ EffectiveRole: nil,
+ Permission: nil,
+ Name: "ha-datacenter",
+ DisabledMethod: nil,
+ RecentTask: nil,
+ DeclaredAlarmState: nil,
+ TriggeredAlarmState: nil,
+ AlarmActionsEnabled: (*bool)(nil),
+ Tag: nil,
+ },
+ VmFolder: types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-vm"},
+ HostFolder: types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-host"},
+ DatastoreFolder: types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-datastore"},
+ NetworkFolder: types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-network"},
+ Datastore: []types.ManagedObjectReference{
+ {Type: "Datastore", Value: "57089c25-85e3ccd4-17b6-000c29d0beb3"},
+ },
+ Network: []types.ManagedObjectReference{
+ {Type: "Network", Value: "HaNetwork-VM Network"},
+ },
+ Configuration: types.DatacenterConfigInfo{},
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/doc.go b/vendor/github.com/vmware/govmomi/simulator/esx/doc.go
new file mode 100644
index 00000000..3c0f4035
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/esx/doc.go
@@ -0,0 +1,20 @@
+/*
+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 esx contains SOAP responses from an ESX server, captured using `govc ... -debug`.
+*/
+package esx
diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/host_config_info.go b/vendor/github.com/vmware/govmomi/simulator/esx/host_config_info.go
new file mode 100644
index 00000000..559a6eb3
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/esx/host_config_info.go
@@ -0,0 +1,1088 @@
+/*
+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 esx
+
+import "github.com/vmware/govmomi/vim25/types"
+
+var HostConfigInfo = types.HostConfigInfo{
+ Host: types.ManagedObjectReference{Type: "HostSystem", Value: "ha-host"},
+ Product: types.AboutInfo{
+ Name: "VMware ESXi",
+ FullName: "VMware ESXi 6.5.0 build-5969303",
+ Vendor: "VMware, Inc.",
+ Version: "6.5.0",
+ Build: "5969303",
+ LocaleVersion: "INTL",
+ LocaleBuild: "000",
+ OsType: "vmnix-x86",
+ ProductLineId: "embeddedEsx",
+ ApiType: "HostAgent",
+ ApiVersion: "6.5",
+ InstanceUuid: "",
+ LicenseProductName: "VMware ESX Server",
+ LicenseProductVersion: "6.0",
+ },
+ DeploymentInfo: &types.HostDeploymentInfo{
+ BootedFromStatelessCache: types.NewBool(false),
+ },
+ HyperThread: &types.HostHyperThreadScheduleInfo{
+ Available: false,
+ Active: false,
+ Config: true,
+ },
+ ConsoleReservation: (*types.ServiceConsoleReservationInfo)(nil),
+ VirtualMachineReservation: (*types.VirtualMachineMemoryReservationInfo)(nil),
+ StorageDevice: nil,
+ SystemFile: nil,
+ Network: &types.HostNetworkInfo{
+ Vswitch: []types.HostVirtualSwitch{
+ {
+ Name: "vSwitch0",
+ Key: "key-vim.host.VirtualSwitch-vSwitch0",
+ NumPorts: 1536,
+ NumPortsAvailable: 1530,
+ Mtu: 1500,
+ Portgroup: []string{"key-vim.host.PortGroup-VM Network", "key-vim.host.PortGroup-Management Network"},
+ Pnic: []string{"key-vim.host.PhysicalNic-vmnic0"},
+ Spec: types.HostVirtualSwitchSpec{
+ NumPorts: 128,
+ Bridge: &types.HostVirtualSwitchBondBridge{
+ HostVirtualSwitchBridge: types.HostVirtualSwitchBridge{},
+ NicDevice: []string{"vmnic0"},
+ Beacon: &types.HostVirtualSwitchBeaconConfig{
+ Interval: 1,
+ },
+ LinkDiscoveryProtocolConfig: &types.LinkDiscoveryProtocolConfig{
+ Protocol: "cdp",
+ Operation: "listen",
+ },
+ },
+ Policy: &types.HostNetworkPolicy{
+ Security: &types.HostNetworkSecurityPolicy{
+ AllowPromiscuous: types.NewBool(false),
+ MacChanges: types.NewBool(true),
+ ForgedTransmits: types.NewBool(true),
+ },
+ NicTeaming: &types.HostNicTeamingPolicy{
+ Policy: "loadbalance_srcid",
+ ReversePolicy: types.NewBool(true),
+ NotifySwitches: types.NewBool(true),
+ RollingOrder: types.NewBool(false),
+ FailureCriteria: &types.HostNicFailureCriteria{
+ CheckSpeed: "minimum",
+ Speed: 10,
+ CheckDuplex: types.NewBool(false),
+ FullDuplex: types.NewBool(false),
+ CheckErrorPercent: types.NewBool(false),
+ Percentage: 0,
+ CheckBeacon: types.NewBool(false),
+ },
+ NicOrder: &types.HostNicOrderPolicy{
+ ActiveNic: []string{"vmnic0"},
+ StandbyNic: nil,
+ },
+ },
+ OffloadPolicy: &types.HostNetOffloadCapabilities{
+ CsumOffload: types.NewBool(true),
+ TcpSegmentation: types.NewBool(true),
+ ZeroCopyXmit: types.NewBool(true),
+ },
+ ShapingPolicy: &types.HostNetworkTrafficShapingPolicy{
+ Enabled: types.NewBool(false),
+ AverageBandwidth: 0,
+ PeakBandwidth: 0,
+ BurstSize: 0,
+ },
+ },
+ Mtu: 0,
+ },
+ },
+ },
+ ProxySwitch: nil,
+ Portgroup: []types.HostPortGroup{
+ {
+ Key: "key-vim.host.PortGroup-VM Network",
+ Port: nil,
+ Vswitch: "key-vim.host.VirtualSwitch-vSwitch0",
+ ComputedPolicy: types.HostNetworkPolicy{
+ Security: &types.HostNetworkSecurityPolicy{
+ AllowPromiscuous: types.NewBool(false),
+ MacChanges: types.NewBool(true),
+ ForgedTransmits: types.NewBool(true),
+ },
+ NicTeaming: &types.HostNicTeamingPolicy{
+ Policy: "loadbalance_srcid",
+ ReversePolicy: types.NewBool(true),
+ NotifySwitches: types.NewBool(true),
+ RollingOrder: types.NewBool(false),
+ FailureCriteria: &types.HostNicFailureCriteria{
+ CheckSpeed: "minimum",
+ Speed: 10,
+ CheckDuplex: types.NewBool(false),
+ FullDuplex: types.NewBool(false),
+ CheckErrorPercent: types.NewBool(false),
+ Percentage: 0,
+ CheckBeacon: types.NewBool(false),
+ },
+ NicOrder: &types.HostNicOrderPolicy{
+ ActiveNic: []string{"vmnic0"},
+ StandbyNic: nil,
+ },
+ },
+ OffloadPolicy: &types.HostNetOffloadCapabilities{
+ CsumOffload: types.NewBool(true),
+ TcpSegmentation: types.NewBool(true),
+ ZeroCopyXmit: types.NewBool(true),
+ },
+ ShapingPolicy: &types.HostNetworkTrafficShapingPolicy{
+ Enabled: types.NewBool(false),
+ AverageBandwidth: 0,
+ PeakBandwidth: 0,
+ BurstSize: 0,
+ },
+ },
+ Spec: types.HostPortGroupSpec{
+ Name: "VM Network",
+ VlanId: 0,
+ VswitchName: "vSwitch0",
+ Policy: types.HostNetworkPolicy{
+ Security: &types.HostNetworkSecurityPolicy{},
+ NicTeaming: &types.HostNicTeamingPolicy{
+ Policy: "",
+ ReversePolicy: (*bool)(nil),
+ NotifySwitches: (*bool)(nil),
+ RollingOrder: (*bool)(nil),
+ FailureCriteria: &types.HostNicFailureCriteria{},
+ NicOrder: (*types.HostNicOrderPolicy)(nil),
+ },
+ OffloadPolicy: &types.HostNetOffloadCapabilities{},
+ ShapingPolicy: &types.HostNetworkTrafficShapingPolicy{},
+ },
+ },
+ },
+ {
+ Key: "key-vim.host.PortGroup-Management Network",
+ Port: []types.HostPortGroupPort{
+ {
+ Key: "key-vim.host.PortGroup.Port-33554436",
+ Mac: []string{"00:0c:29:81:d8:a0"},
+ Type: "host",
+ },
+ },
+ Vswitch: "key-vim.host.VirtualSwitch-vSwitch0",
+ ComputedPolicy: types.HostNetworkPolicy{
+ Security: &types.HostNetworkSecurityPolicy{
+ AllowPromiscuous: types.NewBool(false),
+ MacChanges: types.NewBool(true),
+ ForgedTransmits: types.NewBool(true),
+ },
+ NicTeaming: &types.HostNicTeamingPolicy{
+ Policy: "loadbalance_srcid",
+ ReversePolicy: types.NewBool(true),
+ NotifySwitches: types.NewBool(true),
+ RollingOrder: types.NewBool(false),
+ FailureCriteria: &types.HostNicFailureCriteria{
+ CheckSpeed: "minimum",
+ Speed: 10,
+ CheckDuplex: types.NewBool(false),
+ FullDuplex: types.NewBool(false),
+ CheckErrorPercent: types.NewBool(false),
+ Percentage: 0,
+ CheckBeacon: types.NewBool(false),
+ },
+ NicOrder: &types.HostNicOrderPolicy{
+ ActiveNic: []string{"vmnic0"},
+ StandbyNic: nil,
+ },
+ },
+ OffloadPolicy: &types.HostNetOffloadCapabilities{
+ CsumOffload: types.NewBool(true),
+ TcpSegmentation: types.NewBool(true),
+ ZeroCopyXmit: types.NewBool(true),
+ },
+ ShapingPolicy: &types.HostNetworkTrafficShapingPolicy{
+ Enabled: types.NewBool(false),
+ AverageBandwidth: 0,
+ PeakBandwidth: 0,
+ BurstSize: 0,
+ },
+ },
+ Spec: types.HostPortGroupSpec{
+ Name: "Management Network",
+ VlanId: 0,
+ VswitchName: "vSwitch0",
+ Policy: types.HostNetworkPolicy{
+ Security: &types.HostNetworkSecurityPolicy{},
+ NicTeaming: &types.HostNicTeamingPolicy{
+ Policy: "loadbalance_srcid",
+ ReversePolicy: (*bool)(nil),
+ NotifySwitches: types.NewBool(true),
+ RollingOrder: types.NewBool(false),
+ FailureCriteria: &types.HostNicFailureCriteria{
+ CheckSpeed: "",
+ Speed: 0,
+ CheckDuplex: (*bool)(nil),
+ FullDuplex: (*bool)(nil),
+ CheckErrorPercent: (*bool)(nil),
+ Percentage: 0,
+ CheckBeacon: types.NewBool(false),
+ },
+ NicOrder: &types.HostNicOrderPolicy{
+ ActiveNic: []string{"vmnic0"},
+ StandbyNic: nil,
+ },
+ },
+ OffloadPolicy: &types.HostNetOffloadCapabilities{},
+ ShapingPolicy: &types.HostNetworkTrafficShapingPolicy{},
+ },
+ },
+ },
+ },
+ Pnic: []types.PhysicalNic{
+ {
+ Key: "key-vim.host.PhysicalNic-vmnic0",
+ Device: "vmnic0",
+ Pci: "0000:0b:00.0",
+ Driver: "nvmxnet3",
+ LinkSpeed: &types.PhysicalNicLinkInfo{
+ SpeedMb: 10000,
+ Duplex: true,
+ },
+ ValidLinkSpecification: []types.PhysicalNicLinkInfo{
+ {
+ SpeedMb: 10000,
+ Duplex: true,
+ },
+ },
+ Spec: types.PhysicalNicSpec{
+ Ip: &types.HostIpConfig{},
+ LinkSpeed: &types.PhysicalNicLinkInfo{
+ SpeedMb: 10000,
+ Duplex: true,
+ },
+ },
+ WakeOnLanSupported: false,
+ Mac: "00:0c:29:81:d8:a0",
+ FcoeConfiguration: &types.FcoeConfig{
+ PriorityClass: 3,
+ SourceMac: "00:0c:29:81:d8:a0",
+ VlanRange: []types.FcoeConfigVlanRange{
+ {},
+ },
+ Capabilities: types.FcoeConfigFcoeCapabilities{
+ PriorityClass: false,
+ SourceMacAddress: false,
+ VlanRange: true,
+ },
+ FcoeActive: false,
+ },
+ VmDirectPathGen2Supported: types.NewBool(false),
+ VmDirectPathGen2SupportedMode: "",
+ ResourcePoolSchedulerAllowed: types.NewBool(true),
+ ResourcePoolSchedulerDisallowedReason: nil,
+ AutoNegotiateSupported: types.NewBool(false),
+ },
+ {
+ Key: "key-vim.host.PhysicalNic-vmnic1",
+ Device: "vmnic1",
+ Pci: "0000:13:00.0",
+ Driver: "nvmxnet3",
+ LinkSpeed: &types.PhysicalNicLinkInfo{
+ SpeedMb: 10000,
+ Duplex: true,
+ },
+ ValidLinkSpecification: []types.PhysicalNicLinkInfo{
+ {
+ SpeedMb: 10000,
+ Duplex: true,
+ },
+ },
+ Spec: types.PhysicalNicSpec{
+ Ip: &types.HostIpConfig{},
+ LinkSpeed: &types.PhysicalNicLinkInfo{
+ SpeedMb: 10000,
+ Duplex: true,
+ },
+ },
+ WakeOnLanSupported: false,
+ Mac: "00:0c:29:81:d8:aa",
+ FcoeConfiguration: &types.FcoeConfig{
+ PriorityClass: 3,
+ SourceMac: "00:0c:29:81:d8:aa",
+ VlanRange: []types.FcoeConfigVlanRange{
+ {},
+ },
+ Capabilities: types.FcoeConfigFcoeCapabilities{
+ PriorityClass: false,
+ SourceMacAddress: false,
+ VlanRange: true,
+ },
+ FcoeActive: false,
+ },
+ VmDirectPathGen2Supported: types.NewBool(false),
+ VmDirectPathGen2SupportedMode: "",
+ ResourcePoolSchedulerAllowed: types.NewBool(true),
+ ResourcePoolSchedulerDisallowedReason: nil,
+ AutoNegotiateSupported: types.NewBool(false),
+ },
+ },
+ Vnic: []types.HostVirtualNic{
+ {
+ Device: "vmk0",
+ Key: "key-vim.host.VirtualNic-vmk0",
+ Portgroup: "Management Network",
+ Spec: types.HostVirtualNicSpec{
+ Ip: &types.HostIpConfig{
+ Dhcp: true,
+ IpAddress: "127.0.0.1",
+ SubnetMask: "255.0.0.0",
+ IpV6Config: (*types.HostIpConfigIpV6AddressConfiguration)(nil),
+ },
+ Mac: "00:0c:29:81:d8:a0",
+ DistributedVirtualPort: (*types.DistributedVirtualSwitchPortConnection)(nil),
+ Portgroup: "Management Network",
+ Mtu: 1500,
+ TsoEnabled: types.NewBool(true),
+ NetStackInstanceKey: "defaultTcpipStack",
+ OpaqueNetwork: (*types.HostVirtualNicOpaqueNetworkSpec)(nil),
+ ExternalId: "",
+ PinnedPnic: "",
+ IpRouteSpec: (*types.HostVirtualNicIpRouteSpec)(nil),
+ },
+ Port: "key-vim.host.PortGroup.Port-33554436",
+ },
+ },
+ ConsoleVnic: nil,
+ DnsConfig: &types.HostDnsConfig{
+ Dhcp: true,
+ VirtualNicDevice: "vmk0",
+ HostName: "localhost",
+ DomainName: "localdomain",
+ Address: []string{"8.8.8.8"},
+ SearchDomain: []string{"localdomain"},
+ },
+ IpRouteConfig: &types.HostIpRouteConfig{
+ DefaultGateway: "127.0.0.1",
+ GatewayDevice: "",
+ IpV6DefaultGateway: "",
+ IpV6GatewayDevice: "",
+ },
+ ConsoleIpRouteConfig: nil,
+ RouteTableInfo: &types.HostIpRouteTableInfo{
+ IpRoute: []types.HostIpRouteEntry{
+ {
+ Network: "0.0.0.0",
+ PrefixLength: 0,
+ Gateway: "127.0.0.1",
+ DeviceName: "vmk0",
+ },
+ {
+ Network: "127.0.0.0",
+ PrefixLength: 8,
+ Gateway: "0.0.0.0",
+ DeviceName: "vmk0",
+ },
+ },
+ Ipv6Route: nil,
+ },
+ Dhcp: nil,
+ Nat: nil,
+ IpV6Enabled: types.NewBool(false),
+ AtBootIpV6Enabled: types.NewBool(false),
+ NetStackInstance: []types.HostNetStackInstance{
+ {
+ Key: "vSphereProvisioning",
+ Name: "",
+ DnsConfig: &types.HostDnsConfig{},
+ IpRouteConfig: &types.HostIpRouteConfig{},
+ RequestedMaxNumberOfConnections: 11000,
+ CongestionControlAlgorithm: "newreno",
+ IpV6Enabled: types.NewBool(true),
+ RouteTableConfig: (*types.HostIpRouteTableConfig)(nil),
+ },
+ {
+ Key: "vmotion",
+ Name: "",
+ DnsConfig: &types.HostDnsConfig{},
+ IpRouteConfig: &types.HostIpRouteConfig{},
+ RequestedMaxNumberOfConnections: 11000,
+ CongestionControlAlgorithm: "newreno",
+ IpV6Enabled: types.NewBool(true),
+ RouteTableConfig: (*types.HostIpRouteTableConfig)(nil),
+ },
+ {
+ Key: "defaultTcpipStack",
+ Name: "defaultTcpipStack",
+ DnsConfig: &types.HostDnsConfig{
+ Dhcp: true,
+ VirtualNicDevice: "vmk0",
+ HostName: "localhost",
+ DomainName: "localdomain",
+ Address: []string{"8.8.8.8"},
+ SearchDomain: []string{"localdomain"},
+ },
+ IpRouteConfig: &types.HostIpRouteConfig{
+ DefaultGateway: "127.0.0.1",
+ GatewayDevice: "",
+ IpV6DefaultGateway: "",
+ IpV6GatewayDevice: "",
+ },
+ RequestedMaxNumberOfConnections: 11000,
+ CongestionControlAlgorithm: "newreno",
+ IpV6Enabled: types.NewBool(true),
+ RouteTableConfig: &types.HostIpRouteTableConfig{
+ IpRoute: []types.HostIpRouteOp{
+ {
+ ChangeOperation: "ignore",
+ Route: types.HostIpRouteEntry{
+ Network: "0.0.0.0",
+ PrefixLength: 0,
+ Gateway: "127.0.0.1",
+ DeviceName: "vmk0",
+ },
+ },
+ {
+ ChangeOperation: "ignore",
+ Route: types.HostIpRouteEntry{
+ Network: "127.0.0.0",
+ PrefixLength: 8,
+ Gateway: "0.0.0.0",
+ DeviceName: "vmk0",
+ },
+ },
+ },
+ Ipv6Route: nil,
+ },
+ },
+ },
+ OpaqueSwitch: nil,
+ OpaqueNetwork: nil,
+ },
+ Vmotion: &types.HostVMotionInfo{
+ NetConfig: &types.HostVMotionNetConfig{
+ CandidateVnic: []types.HostVirtualNic{
+ {
+ Device: "vmk0",
+ Key: "VMotionConfig.vmotion.key-vim.host.VirtualNic-vmk0",
+ Portgroup: "Management Network",
+ Spec: types.HostVirtualNicSpec{
+ Ip: &types.HostIpConfig{
+ Dhcp: true,
+ IpAddress: "127.0.0.1",
+ SubnetMask: "255.0.0.0",
+ IpV6Config: (*types.HostIpConfigIpV6AddressConfiguration)(nil),
+ },
+ Mac: "00:0c:29:81:d8:a0",
+ DistributedVirtualPort: (*types.DistributedVirtualSwitchPortConnection)(nil),
+ Portgroup: "Management Network",
+ Mtu: 1500,
+ TsoEnabled: types.NewBool(true),
+ NetStackInstanceKey: "defaultTcpipStack",
+ OpaqueNetwork: (*types.HostVirtualNicOpaqueNetworkSpec)(nil),
+ ExternalId: "",
+ PinnedPnic: "",
+ IpRouteSpec: (*types.HostVirtualNicIpRouteSpec)(nil),
+ },
+ Port: "",
+ },
+ },
+ SelectedVnic: "",
+ },
+ IpConfig: (*types.HostIpConfig)(nil),
+ },
+ VirtualNicManagerInfo: &types.HostVirtualNicManagerInfo{
+ NetConfig: []types.VirtualNicManagerNetConfig{
+ {
+ NicType: "faultToleranceLogging",
+ MultiSelectAllowed: true,
+ CandidateVnic: []types.HostVirtualNic{
+ {
+ Device: "vmk0",
+ Key: "faultToleranceLogging.key-vim.host.VirtualNic-vmk0",
+ Portgroup: "Management Network",
+ Spec: types.HostVirtualNicSpec{
+ Ip: &types.HostIpConfig{
+ Dhcp: true,
+ IpAddress: "127.0.0.1",
+ SubnetMask: "255.0.0.0",
+ IpV6Config: (*types.HostIpConfigIpV6AddressConfiguration)(nil),
+ },
+ Mac: "00:0c:29:81:d8:a0",
+ DistributedVirtualPort: (*types.DistributedVirtualSwitchPortConnection)(nil),
+ Portgroup: "Management Network",
+ Mtu: 1500,
+ TsoEnabled: types.NewBool(true),
+ NetStackInstanceKey: "defaultTcpipStack",
+ OpaqueNetwork: (*types.HostVirtualNicOpaqueNetworkSpec)(nil),
+ ExternalId: "",
+ PinnedPnic: "",
+ IpRouteSpec: (*types.HostVirtualNicIpRouteSpec)(nil),
+ },
+ Port: "",
+ },
+ },
+ SelectedVnic: nil,
+ },
+ {
+ NicType: "management",
+ MultiSelectAllowed: true,
+ CandidateVnic: []types.HostVirtualNic{
+ {
+ Device: "vmk0",
+ Key: "management.key-vim.host.VirtualNic-vmk0",
+ Portgroup: "Management Network",
+ Spec: types.HostVirtualNicSpec{
+ Ip: &types.HostIpConfig{
+ Dhcp: true,
+ IpAddress: "127.0.0.1",
+ SubnetMask: "255.0.0.0",
+ IpV6Config: (*types.HostIpConfigIpV6AddressConfiguration)(nil),
+ },
+ Mac: "00:0c:29:81:d8:a0",
+ DistributedVirtualPort: (*types.DistributedVirtualSwitchPortConnection)(nil),
+ Portgroup: "Management Network",
+ Mtu: 1500,
+ TsoEnabled: types.NewBool(true),
+ NetStackInstanceKey: "defaultTcpipStack",
+ OpaqueNetwork: (*types.HostVirtualNicOpaqueNetworkSpec)(nil),
+ ExternalId: "",
+ PinnedPnic: "",
+ IpRouteSpec: (*types.HostVirtualNicIpRouteSpec)(nil),
+ },
+ Port: "",
+ },
+ },
+ SelectedVnic: []string{"management.key-vim.host.VirtualNic-vmk0"},
+ },
+ {
+ NicType: "vSphereProvisioning",
+ MultiSelectAllowed: true,
+ CandidateVnic: []types.HostVirtualNic{
+ {
+ Device: "vmk0",
+ Key: "vSphereProvisioning.key-vim.host.VirtualNic-vmk0",
+ Portgroup: "Management Network",
+ Spec: types.HostVirtualNicSpec{
+ Ip: &types.HostIpConfig{
+ Dhcp: true,
+ IpAddress: "127.0.0.1",
+ SubnetMask: "255.0.0.0",
+ IpV6Config: (*types.HostIpConfigIpV6AddressConfiguration)(nil),
+ },
+ Mac: "00:0c:29:81:d8:a0",
+ DistributedVirtualPort: (*types.DistributedVirtualSwitchPortConnection)(nil),
+ Portgroup: "Management Network",
+ Mtu: 1500,
+ TsoEnabled: types.NewBool(true),
+ NetStackInstanceKey: "defaultTcpipStack",
+ OpaqueNetwork: (*types.HostVirtualNicOpaqueNetworkSpec)(nil),
+ ExternalId: "",
+ PinnedPnic: "",
+ IpRouteSpec: (*types.HostVirtualNicIpRouteSpec)(nil),
+ },
+ Port: "",
+ },
+ },
+ SelectedVnic: nil,
+ },
+ {
+ NicType: "vSphereReplication",
+ MultiSelectAllowed: true,
+ CandidateVnic: []types.HostVirtualNic{
+ {
+ Device: "vmk0",
+ Key: "vSphereReplication.key-vim.host.VirtualNic-vmk0",
+ Portgroup: "Management Network",
+ Spec: types.HostVirtualNicSpec{
+ Ip: &types.HostIpConfig{
+ Dhcp: true,
+ IpAddress: "127.0.0.1",
+ SubnetMask: "255.0.0.0",
+ IpV6Config: (*types.HostIpConfigIpV6AddressConfiguration)(nil),
+ },
+ Mac: "00:0c:29:81:d8:a0",
+ DistributedVirtualPort: (*types.DistributedVirtualSwitchPortConnection)(nil),
+ Portgroup: "Management Network",
+ Mtu: 1500,
+ TsoEnabled: types.NewBool(true),
+ NetStackInstanceKey: "defaultTcpipStack",
+ OpaqueNetwork: (*types.HostVirtualNicOpaqueNetworkSpec)(nil),
+ ExternalId: "",
+ PinnedPnic: "",
+ IpRouteSpec: (*types.HostVirtualNicIpRouteSpec)(nil),
+ },
+ Port: "",
+ },
+ },
+ SelectedVnic: nil,
+ },
+ {
+ NicType: "vSphereReplicationNFC",
+ MultiSelectAllowed: true,
+ CandidateVnic: []types.HostVirtualNic{
+ {
+ Device: "vmk0",
+ Key: "vSphereReplicationNFC.key-vim.host.VirtualNic-vmk0",
+ Portgroup: "Management Network",
+ Spec: types.HostVirtualNicSpec{
+ Ip: &types.HostIpConfig{
+ Dhcp: true,
+ IpAddress: "127.0.0.1",
+ SubnetMask: "255.0.0.0",
+ IpV6Config: (*types.HostIpConfigIpV6AddressConfiguration)(nil),
+ },
+ Mac: "00:0c:29:81:d8:a0",
+ DistributedVirtualPort: (*types.DistributedVirtualSwitchPortConnection)(nil),
+ Portgroup: "Management Network",
+ Mtu: 1500,
+ TsoEnabled: types.NewBool(true),
+ NetStackInstanceKey: "defaultTcpipStack",
+ OpaqueNetwork: (*types.HostVirtualNicOpaqueNetworkSpec)(nil),
+ ExternalId: "",
+ PinnedPnic: "",
+ IpRouteSpec: (*types.HostVirtualNicIpRouteSpec)(nil),
+ },
+ Port: "",
+ },
+ },
+ SelectedVnic: nil,
+ },
+ {
+ NicType: "vmotion",
+ MultiSelectAllowed: true,
+ CandidateVnic: []types.HostVirtualNic{
+ {
+ Device: "vmk0",
+ Key: "vmotion.key-vim.host.VirtualNic-vmk0",
+ Portgroup: "Management Network",
+ Spec: types.HostVirtualNicSpec{
+ Ip: &types.HostIpConfig{
+ Dhcp: true,
+ IpAddress: "127.0.0.1",
+ SubnetMask: "255.0.0.0",
+ IpV6Config: (*types.HostIpConfigIpV6AddressConfiguration)(nil),
+ },
+ Mac: "00:0c:29:81:d8:a0",
+ DistributedVirtualPort: (*types.DistributedVirtualSwitchPortConnection)(nil),
+ Portgroup: "Management Network",
+ Mtu: 1500,
+ TsoEnabled: types.NewBool(true),
+ NetStackInstanceKey: "defaultTcpipStack",
+ OpaqueNetwork: (*types.HostVirtualNicOpaqueNetworkSpec)(nil),
+ ExternalId: "",
+ PinnedPnic: "",
+ IpRouteSpec: (*types.HostVirtualNicIpRouteSpec)(nil),
+ },
+ Port: "",
+ },
+ },
+ SelectedVnic: nil,
+ },
+ {
+ NicType: "vsan",
+ MultiSelectAllowed: true,
+ CandidateVnic: []types.HostVirtualNic{
+ {
+ Device: "vmk0",
+ Key: "vsan.key-vim.host.VirtualNic-vmk0",
+ Portgroup: "Management Network",
+ Spec: types.HostVirtualNicSpec{
+ Ip: &types.HostIpConfig{
+ Dhcp: true,
+ IpAddress: "127.0.0.1",
+ SubnetMask: "255.0.0.0",
+ IpV6Config: (*types.HostIpConfigIpV6AddressConfiguration)(nil),
+ },
+ Mac: "00:0c:29:81:d8:a0",
+ DistributedVirtualPort: (*types.DistributedVirtualSwitchPortConnection)(nil),
+ Portgroup: "Management Network",
+ Mtu: 1500,
+ TsoEnabled: types.NewBool(true),
+ NetStackInstanceKey: "defaultTcpipStack",
+ OpaqueNetwork: (*types.HostVirtualNicOpaqueNetworkSpec)(nil),
+ ExternalId: "",
+ PinnedPnic: "",
+ IpRouteSpec: (*types.HostVirtualNicIpRouteSpec)(nil),
+ },
+ Port: "",
+ },
+ },
+ SelectedVnic: nil,
+ },
+ {
+ NicType: "vsanWitness",
+ MultiSelectAllowed: true,
+ CandidateVnic: []types.HostVirtualNic{
+ {
+ Device: "vmk0",
+ Key: "vsanWitness.key-vim.host.VirtualNic-vmk0",
+ Portgroup: "Management Network",
+ Spec: types.HostVirtualNicSpec{
+ Ip: &types.HostIpConfig{
+ Dhcp: true,
+ IpAddress: "127.0.0.1",
+ SubnetMask: "255.0.0.0",
+ IpV6Config: (*types.HostIpConfigIpV6AddressConfiguration)(nil),
+ },
+ Mac: "00:0c:29:81:d8:a0",
+ DistributedVirtualPort: (*types.DistributedVirtualSwitchPortConnection)(nil),
+ Portgroup: "Management Network",
+ Mtu: 1500,
+ TsoEnabled: types.NewBool(true),
+ NetStackInstanceKey: "defaultTcpipStack",
+ OpaqueNetwork: (*types.HostVirtualNicOpaqueNetworkSpec)(nil),
+ ExternalId: "",
+ PinnedPnic: "",
+ IpRouteSpec: (*types.HostVirtualNicIpRouteSpec)(nil),
+ },
+ Port: "",
+ },
+ },
+ SelectedVnic: nil,
+ },
+ },
+ },
+ Capabilities: &types.HostNetCapabilities{
+ CanSetPhysicalNicLinkSpeed: true,
+ SupportsNicTeaming: true,
+ NicTeamingPolicy: []string{"loadbalance_ip", "loadbalance_srcmac", "loadbalance_srcid", "failover_explicit"},
+ SupportsVlan: true,
+ UsesServiceConsoleNic: false,
+ SupportsNetworkHints: true,
+ MaxPortGroupsPerVswitch: 0,
+ VswitchConfigSupported: true,
+ VnicConfigSupported: true,
+ IpRouteConfigSupported: true,
+ DnsConfigSupported: true,
+ DhcpOnVnicSupported: true,
+ IpV6Supported: types.NewBool(true),
+ },
+ DatastoreCapabilities: &types.HostDatastoreSystemCapabilities{
+ NfsMountCreationRequired: true,
+ NfsMountCreationSupported: true,
+ LocalDatastoreSupported: false,
+ VmfsExtentExpansionSupported: types.NewBool(true),
+ },
+ OffloadCapabilities: &types.HostNetOffloadCapabilities{
+ CsumOffload: types.NewBool(true),
+ TcpSegmentation: types.NewBool(true),
+ ZeroCopyXmit: types.NewBool(true),
+ },
+ Service: &types.HostServiceInfo{
+ Service: []types.HostService{
+ {
+ Key: "DCUI",
+ Label: "Direct Console UI",
+ Required: false,
+ Uninstallable: false,
+ Running: true,
+ Ruleset: nil,
+ Policy: "on",
+ SourcePackage: &types.HostServiceSourcePackage{
+ SourcePackageName: "esx-base",
+ Description: "This VIB contains all of the base functionality of vSphere ESXi.",
+ },
+ },
+ {
+ Key: "TSM",
+ Label: "ESXi Shell",
+ Required: false,
+ Uninstallable: false,
+ Running: false,
+ Ruleset: nil,
+ Policy: "off",
+ SourcePackage: &types.HostServiceSourcePackage{
+ SourcePackageName: "esx-base",
+ Description: "This VIB contains all of the base functionality of vSphere ESXi.",
+ },
+ },
+ {
+ Key: "TSM-SSH",
+ Label: "SSH",
+ Required: false,
+ Uninstallable: false,
+ Running: false,
+ Ruleset: nil,
+ Policy: "off",
+ SourcePackage: &types.HostServiceSourcePackage{
+ SourcePackageName: "esx-base",
+ Description: "This VIB contains all of the base functionality of vSphere ESXi.",
+ },
+ },
+ {
+ Key: "lbtd",
+ Label: "Load-Based Teaming Daemon",
+ Required: false,
+ Uninstallable: false,
+ Running: true,
+ Ruleset: nil,
+ Policy: "on",
+ SourcePackage: &types.HostServiceSourcePackage{
+ SourcePackageName: "esx-base",
+ Description: "This VIB contains all of the base functionality of vSphere ESXi.",
+ },
+ },
+ {
+ Key: "lwsmd",
+ Label: "Active Directory Service",
+ Required: false,
+ Uninstallable: false,
+ Running: false,
+ Ruleset: nil,
+ Policy: "off",
+ SourcePackage: &types.HostServiceSourcePackage{
+ SourcePackageName: "esx-base",
+ Description: "This VIB contains all of the base functionality of vSphere ESXi.",
+ },
+ },
+ {
+ Key: "ntpd",
+ Label: "NTP Daemon",
+ Required: false,
+ Uninstallable: false,
+ Running: false,
+ Ruleset: []string{"ntpClient"},
+ Policy: "off",
+ SourcePackage: &types.HostServiceSourcePackage{
+ SourcePackageName: "esx-base",
+ Description: "This VIB contains all of the base functionality of vSphere ESXi.",
+ },
+ },
+ {
+ Key: "pcscd",
+ Label: "PC/SC Smart Card Daemon",
+ Required: false,
+ Uninstallable: false,
+ Running: false,
+ Ruleset: nil,
+ Policy: "off",
+ SourcePackage: &types.HostServiceSourcePackage{
+ SourcePackageName: "esx-base",
+ Description: "This VIB contains all of the base functionality of vSphere ESXi.",
+ },
+ },
+ {
+ Key: "sfcbd-watchdog",
+ Label: "CIM Server",
+ Required: false,
+ Uninstallable: false,
+ Running: false,
+ Ruleset: []string{"CIMHttpServer", "CIMHttpsServer"},
+ Policy: "on",
+ SourcePackage: &types.HostServiceSourcePackage{
+ SourcePackageName: "esx-base",
+ Description: "This VIB contains all of the base functionality of vSphere ESXi.",
+ },
+ },
+ {
+ Key: "snmpd",
+ Label: "SNMP Server",
+ Required: false,
+ Uninstallable: false,
+ Running: false,
+ Ruleset: []string{"snmp"},
+ Policy: "on",
+ SourcePackage: &types.HostServiceSourcePackage{
+ SourcePackageName: "esx-base",
+ Description: "This VIB contains all of the base functionality of vSphere ESXi.",
+ },
+ },
+ {
+ Key: "vmsyslogd",
+ Label: "Syslog Server",
+ Required: true,
+ Uninstallable: false,
+ Running: true,
+ Ruleset: nil,
+ Policy: "on",
+ SourcePackage: &types.HostServiceSourcePackage{
+ SourcePackageName: "esx-base",
+ Description: "This VIB contains all of the base functionality of vSphere ESXi.",
+ },
+ },
+ {
+ Key: "vpxa",
+ Label: "VMware vCenter Agent",
+ Required: false,
+ Uninstallable: false,
+ Running: false,
+ Ruleset: []string{"vpxHeartbeats"},
+ Policy: "on",
+ SourcePackage: &types.HostServiceSourcePackage{
+ SourcePackageName: "esx-base",
+ Description: "This VIB contains all of the base functionality of vSphere ESXi.",
+ },
+ },
+ {
+ Key: "xorg",
+ Label: "X.Org Server",
+ Required: false,
+ Uninstallable: false,
+ Running: false,
+ Ruleset: nil,
+ Policy: "on",
+ SourcePackage: &types.HostServiceSourcePackage{
+ SourcePackageName: "esx-xserver",
+ Description: "This VIB contains X Server used for virtual machine 3D hardware acceleration.",
+ },
+ },
+ },
+ },
+ Firewall: &HostFirewallInfo,
+ AutoStart: &types.HostAutoStartManagerConfig{
+ Defaults: &types.AutoStartDefaults{
+ Enabled: (*bool)(nil),
+ StartDelay: 120,
+ StopDelay: 120,
+ WaitForHeartbeat: types.NewBool(false),
+ StopAction: "PowerOff",
+ },
+ PowerInfo: nil,
+ },
+ ActiveDiagnosticPartition: &types.HostDiagnosticPartition{
+ StorageType: "directAttached",
+ DiagnosticType: "singleHost",
+ Slots: -15,
+ Id: types.HostScsiDiskPartition{
+ DiskName: "mpx.vmhba0:C0:T0:L0",
+ Partition: 9,
+ },
+ },
+ Option: nil,
+ OptionDef: nil,
+ Flags: &types.HostFlagInfo{},
+ AdminDisabled: (*bool)(nil),
+ LockdownMode: "lockdownDisabled",
+ Ipmi: (*types.HostIpmiInfo)(nil),
+ SslThumbprintInfo: (*types.HostSslThumbprintInfo)(nil),
+ SslThumbprintData: nil,
+ Certificate: []uint8{0x31, 0x30},
+ PciPassthruInfo: nil,
+ AuthenticationManagerInfo: &types.HostAuthenticationManagerInfo{
+ AuthConfig: []types.BaseHostAuthenticationStoreInfo{
+ &types.HostLocalAuthenticationInfo{
+ HostAuthenticationStoreInfo: types.HostAuthenticationStoreInfo{
+ Enabled: true,
+ },
+ },
+ &types.HostActiveDirectoryInfo{
+ HostDirectoryStoreInfo: types.HostDirectoryStoreInfo{},
+ JoinedDomain: "",
+ TrustedDomain: nil,
+ DomainMembershipStatus: "",
+ SmartCardAuthenticationEnabled: types.NewBool(false),
+ },
+ },
+ },
+ FeatureVersion: nil,
+ PowerSystemCapability: &types.PowerSystemCapability{
+ AvailablePolicy: []types.HostPowerPolicy{
+ {
+ Key: 1,
+ Name: "PowerPolicy.static.name",
+ ShortName: "static",
+ Description: "PowerPolicy.static.description",
+ },
+ {
+ Key: 2,
+ Name: "PowerPolicy.dynamic.name",
+ ShortName: "dynamic",
+ Description: "PowerPolicy.dynamic.description",
+ },
+ {
+ Key: 3,
+ Name: "PowerPolicy.low.name",
+ ShortName: "low",
+ Description: "PowerPolicy.low.description",
+ },
+ {
+ Key: 4,
+ Name: "PowerPolicy.custom.name",
+ ShortName: "custom",
+ Description: "PowerPolicy.custom.description",
+ },
+ },
+ },
+ PowerSystemInfo: &types.PowerSystemInfo{
+ CurrentPolicy: types.HostPowerPolicy{
+ Key: 2,
+ Name: "PowerPolicy.dynamic.name",
+ ShortName: "dynamic",
+ Description: "PowerPolicy.dynamic.description",
+ },
+ },
+ CacheConfigurationInfo: []types.HostCacheConfigurationInfo{
+ {
+ Key: types.ManagedObjectReference{Type: "Datastore", Value: "5980f676-21a5db76-9eef-000c2981d8a0"},
+ SwapSize: 0,
+ },
+ },
+ WakeOnLanCapable: types.NewBool(false),
+ FeatureCapability: nil,
+ MaskedFeatureCapability: nil,
+ VFlashConfigInfo: nil,
+ VsanHostConfig: &types.VsanHostConfigInfo{
+ Enabled: types.NewBool(false),
+ HostSystem: &types.ManagedObjectReference{Type: "HostSystem", Value: "ha-host"},
+ ClusterInfo: &types.VsanHostConfigInfoClusterInfo{},
+ StorageInfo: &types.VsanHostConfigInfoStorageInfo{
+ AutoClaimStorage: types.NewBool(false),
+ DiskMapping: nil,
+ DiskMapInfo: nil,
+ ChecksumEnabled: (*bool)(nil),
+ },
+ NetworkInfo: &types.VsanHostConfigInfoNetworkInfo{},
+ FaultDomainInfo: &types.VsanHostFaultDomainInfo{},
+ },
+ DomainList: nil,
+ ScriptCheckSum: nil,
+ HostConfigCheckSum: nil,
+ GraphicsInfo: nil,
+ SharedPassthruGpuTypes: nil,
+ GraphicsConfig: &types.HostGraphicsConfig{
+ HostDefaultGraphicsType: "shared",
+ SharedPassthruAssignmentPolicy: "performance",
+ DeviceType: nil,
+ },
+ IoFilterInfo: []types.HostIoFilterInfo{
+ {
+ IoFilterInfo: types.IoFilterInfo{
+ Id: "VMW_spm_1.0.0",
+ Name: "spm",
+ Vendor: "VMW",
+ Version: "1.0.230",
+ Type: "datastoreIoControl",
+ Summary: "VMware Storage I/O Control",
+ ReleaseDate: "2016-07-21",
+ },
+ Available: true,
+ },
+ {
+ IoFilterInfo: types.IoFilterInfo{
+ Id: "VMW_vmwarevmcrypt_1.0.0",
+ Name: "vmwarevmcrypt",
+ Vendor: "VMW",
+ Version: "1.0.0",
+ Type: "encryption",
+ Summary: "VMcrypt IO Filter",
+ ReleaseDate: "2016-07-21",
+ },
+ Available: true,
+ },
+ },
+ SriovDevicePool: nil,
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/host_firewall_system.go b/vendor/github.com/vmware/govmomi/simulator/esx/host_firewall_system.go
new file mode 100644
index 00000000..9c890bfa
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/esx/host_firewall_system.go
@@ -0,0 +1,1422 @@
+/*
+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 esx
+
+import "github.com/vmware/govmomi/vim25/types"
+
+var HostFirewallInfo = types.HostFirewallInfo{
+ DynamicData: types.DynamicData{},
+ DefaultPolicy: types.HostFirewallDefaultPolicy{
+ DynamicData: types.DynamicData{},
+ IncomingBlocked: types.NewBool(true),
+ OutgoingBlocked: types.NewBool(true),
+ },
+ Ruleset: []types.HostFirewallRuleset{
+ {
+ DynamicData: types.DynamicData{},
+ Key: "CIMHttpServer",
+ Label: "CIM Server",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 5988,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "sfcbd-watchdog",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "CIMHttpsServer",
+ Label: "CIM Secure Server",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 5989,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "sfcbd-watchdog",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "CIMSLP",
+ Label: "CIM SLP",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 427,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 427,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 427,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 427,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "DHCPv6",
+ Label: "DHCPv6",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 547,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 546,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 547,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 546,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ },
+ Service: "",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "DVFilter",
+ Label: "DVFilter",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 2222,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "DVSSync",
+ Label: "DVSSync",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 8302,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 8301,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 8301,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 8302,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ },
+ Service: "",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "HBR",
+ Label: "HBR",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 31031,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 44046,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "NFC",
+ Label: "NFC",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 902,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 902,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "WOL",
+ Label: "WOL",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 9,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ },
+ Service: "",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "activeDirectoryAll",
+ Label: "Active Directory All",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 88,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 88,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 123,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 137,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 139,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 389,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 389,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 445,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 464,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 464,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 3268,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 7476,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 2020,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "cmmds",
+ Label: "Virtual SAN Clustering Service",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 12345,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 23451,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 12345,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 23451,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 12321,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 12321,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "dhcp",
+ Label: "DHCP Client",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 68,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 68,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "src",
+ Protocol: "udp",
+ },
+ },
+ Service: "",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "dns",
+ Label: "DNS Client",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 53,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 53,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 53,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "esxupdate",
+ Label: "esxupdate",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 443,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "faultTolerance",
+ Label: "Fault Tolerance",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 80,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 8300,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 8300,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "ftpClient",
+ Label: "FTP Client",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 21,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 20,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "src",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "gdbserver",
+ Label: "gdbserver",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 1000,
+ EndPort: 9999,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 50000,
+ EndPort: 50999,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "httpClient",
+ Label: "httpClient",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 80,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 443,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "iSCSI",
+ Label: "Software iSCSI Client",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 3260,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "iofiltervp",
+ Label: "iofiltervp",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 9080,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "ipfam",
+ Label: "NSX Distributed Logical Router Service",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 6999,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 6999,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "nfs41Client",
+ Label: "nfs41Client",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 0,
+ EndPort: 65535,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "nfsClient",
+ Label: "NFS Client",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 0,
+ EndPort: 65535,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "ntpClient",
+ Label: "NTP Client",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 123,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ },
+ Service: "ntpd",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "pvrdma",
+ Label: "pvrdma",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 28250,
+ EndPort: 28761,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 28250,
+ EndPort: 28761,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "rabbitmqproxy",
+ Label: "rabbitmqproxy",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 5671,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "rdt",
+ Label: "Virtual SAN Transport",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 2233,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 2233,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "remoteSerialPort",
+ Label: "VM serial port connected over network",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 0,
+ EndPort: 65535,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 23,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 1024,
+ EndPort: 65535,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "snmp",
+ Label: "SNMP Server",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 161,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ },
+ Service: "snmpd",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "sshClient",
+ Label: "SSH Client",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 22,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "sshServer",
+ Label: "SSH Server",
+ Required: true,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 22,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "syslog",
+ Label: "syslog",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 514,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 514,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 1514,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "updateManager",
+ Label: "vCenter Update Manager",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 80,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 9000,
+ EndPort: 9100,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "vMotion",
+ Label: "vMotion",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 8000,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 8000,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "vSPC",
+ Label: "VM serial port connected to vSPC",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 0,
+ EndPort: 65535,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "vSphereClient",
+ Label: "vSphere Web Client",
+ Required: true,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 902,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 443,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "vpxHeartbeats",
+ Label: "VMware vCenter Agent",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 902,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ },
+ Service: "vpxa",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "vsanEncryption",
+ Label: "vsanEncryption",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 0,
+ EndPort: 65535,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "vsanhealth-multicasttest",
+ Label: "vsanhealth-multicasttest",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 5001,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 5001,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "udp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "vsanvp",
+ Label: "vsanvp",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 8080,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Port: 8080,
+ EndPort: 0,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "vvold",
+ Label: "vvold",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 0,
+ EndPort: 65535,
+ Direction: "outbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: false,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Key: "webAccess",
+ Label: "vSphere Web Access",
+ Required: false,
+ Rule: []types.HostFirewallRule{
+ {
+ DynamicData: types.DynamicData{},
+ Port: 80,
+ EndPort: 0,
+ Direction: "inbound",
+ PortType: "dst",
+ Protocol: "tcp",
+ },
+ },
+ Service: "",
+ Enabled: true,
+ AllowedHosts: &types.HostFirewallRulesetIpList{
+ DynamicData: types.DynamicData{},
+ IpAddress: nil,
+ IpNetwork: nil,
+ AllIp: true,
+ },
+ },
+ },
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/host_hardware_info.go b/vendor/github.com/vmware/govmomi/simulator/esx/host_hardware_info.go
new file mode 100644
index 00000000..a1c9ad73
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/esx/host_hardware_info.go
@@ -0,0 +1,861 @@
+/*
+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 esx
+
+import (
+ "time"
+
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+var HostHardwareInfo = &types.HostHardwareInfo{
+ SystemInfo: types.HostSystemInfo{
+ Vendor: "VMware, Inc.",
+ Model: "VMware Virtual Platform",
+ Uuid: "e88d4d56-9f1e-3ea1-71fa-13a8e1a7fd70",
+ OtherIdentifyingInfo: []types.HostSystemIdentificationInfo{
+ {
+ IdentifierValue: " No Asset Tag",
+ IdentifierType: &types.ElementDescription{
+ Description: types.Description{
+ Label: "Asset Tag",
+ Summary: "Asset tag of the system",
+ },
+ Key: "AssetTag",
+ },
+ },
+ {
+ IdentifierValue: "[MS_VM_CERT/SHA1/27d66596a61c48dd3dc7216fd715126e33f59ae7]",
+ IdentifierType: &types.ElementDescription{
+ Description: types.Description{
+ Label: "OEM specific string",
+ Summary: "OEM specific string",
+ },
+ Key: "OemSpecificString",
+ },
+ },
+ {
+ IdentifierValue: "Welcome to the Virtual Machine",
+ IdentifierType: &types.ElementDescription{
+ Description: types.Description{
+ Label: "OEM specific string",
+ Summary: "OEM specific string",
+ },
+ Key: "OemSpecificString",
+ },
+ },
+ {
+ IdentifierValue: "VMware-56 4d 8d e8 1e 9f a1 3e-71 fa 13 a8 e1 a7 fd 70",
+ IdentifierType: &types.ElementDescription{
+ Description: types.Description{
+ Label: "Service tag",
+ Summary: "Service tag of the system",
+ },
+ Key: "ServiceTag",
+ },
+ },
+ },
+ },
+ CpuPowerManagementInfo: &types.HostCpuPowerManagementInfo{
+ CurrentPolicy: "Balanced",
+ HardwareSupport: "",
+ },
+ CpuInfo: types.HostCpuInfo{
+ NumCpuPackages: 2,
+ NumCpuCores: 2,
+ NumCpuThreads: 2,
+ Hz: 3591345000,
+ },
+ CpuPkg: []types.HostCpuPackage{
+ {
+ Index: 0,
+ Vendor: "intel",
+ Hz: 3591345000,
+ BusHz: 115849838,
+ Description: "Intel(R) Xeon(R) CPU E5-1620 0 @ 3.60GHz",
+ ThreadId: []int16{0},
+ CpuFeature: []types.HostCpuIdInfo{
+ {
+ Level: 0,
+ Vendor: "",
+ Eax: "0000:0000:0000:0000:0000:0000:0000:1101",
+ Ebx: "0111:0101:0110:1110:0110:0101:0100:0111",
+ Ecx: "0110:1100:0110:0101:0111:0100:0110:1110",
+ Edx: "0100:1001:0110:0101:0110:1110:0110:1001",
+ },
+ {
+ Level: 1,
+ Vendor: "",
+ Eax: "0000:0000:0000:0010:0000:0110:1101:0111",
+ Ebx: "0000:0000:0000:0001:0000:1000:0000:0000",
+ Ecx: "1001:0111:1011:1010:0010:0010:0010:1011",
+ Edx: "0000:1111:1010:1011:1111:1011:1111:1111",
+ },
+ {
+ Level: -2147483648,
+ Vendor: "",
+ Eax: "1000:0000:0000:0000:0000:0000:0000:1000",
+ Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Ecx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Edx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ },
+ {
+ Level: -2147483647,
+ Vendor: "",
+ Eax: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Ecx: "0000:0000:0000:0000:0000:0000:0000:0001",
+ Edx: "0010:1000:0001:0000:0000:1000:0000:0000",
+ },
+ {
+ Level: -2147483640,
+ Vendor: "",
+ Eax: "0000:0000:0000:0000:0011:0000:0010:1010",
+ Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Ecx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Edx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ },
+ },
+ },
+ {
+ Index: 1,
+ Vendor: "intel",
+ Hz: 3591345000,
+ BusHz: 115849838,
+ Description: "Intel(R) Xeon(R) CPU E5-1620 0 @ 3.60GHz",
+ ThreadId: []int16{1},
+ CpuFeature: []types.HostCpuIdInfo{
+ {
+ Level: 0,
+ Vendor: "",
+ Eax: "0000:0000:0000:0000:0000:0000:0000:1101",
+ Ebx: "0111:0101:0110:1110:0110:0101:0100:0111",
+ Ecx: "0110:1100:0110:0101:0111:0100:0110:1110",
+ Edx: "0100:1001:0110:0101:0110:1110:0110:1001",
+ },
+ {
+ Level: 1,
+ Vendor: "",
+ Eax: "0000:0000:0000:0010:0000:0110:1101:0111",
+ Ebx: "0000:0010:0000:0001:0000:1000:0000:0000",
+ Ecx: "1001:0111:1011:1010:0010:0010:0010:1011",
+ Edx: "0000:1111:1010:1011:1111:1011:1111:1111",
+ },
+ {
+ Level: -2147483648,
+ Vendor: "",
+ Eax: "1000:0000:0000:0000:0000:0000:0000:1000",
+ Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Ecx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Edx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ },
+ {
+ Level: -2147483647,
+ Vendor: "",
+ Eax: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Ecx: "0000:0000:0000:0000:0000:0000:0000:0001",
+ Edx: "0010:1000:0001:0000:0000:1000:0000:0000",
+ },
+ {
+ Level: -2147483640,
+ Vendor: "",
+ Eax: "0000:0000:0000:0000:0011:0000:0010:1010",
+ Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Ecx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Edx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ },
+ },
+ },
+ },
+ MemorySize: 4294430720,
+ NumaInfo: &types.HostNumaInfo{
+ Type: "NUMA",
+ NumNodes: 1,
+ NumaNode: []types.HostNumaNode{
+ {
+ TypeId: 0x0,
+ CpuID: []int16{1, 0},
+ MemoryRangeBegin: 4294967296,
+ MemoryRangeLength: 1073741824,
+ },
+ },
+ },
+ SmcPresent: types.NewBool(false),
+ PciDevice: []types.HostPciDevice{
+ {
+ Id: "0000:00:00.0",
+ ClassId: 1536,
+ Bus: 0x0,
+ Slot: 0x0,
+ Function: 0x0,
+ VendorId: -32634,
+ SubVendorId: 5549,
+ VendorName: "Intel Corporation",
+ DeviceId: 29072,
+ SubDeviceId: 6518,
+ ParentBridge: "",
+ DeviceName: "Virtual Machine Chipset",
+ },
+ {
+ Id: "0000:00:01.0",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x1,
+ Function: 0x0,
+ VendorId: -32634,
+ SubVendorId: 0,
+ VendorName: "Intel Corporation",
+ DeviceId: 29073,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "440BX/ZX/DX - 82443BX/ZX/DX AGP bridge",
+ },
+ {
+ Id: "0000:00:07.0",
+ ClassId: 1537,
+ Bus: 0x0,
+ Slot: 0x7,
+ Function: 0x0,
+ VendorId: -32634,
+ SubVendorId: 5549,
+ VendorName: "Intel Corporation",
+ DeviceId: 28944,
+ SubDeviceId: 6518,
+ ParentBridge: "",
+ DeviceName: "Virtual Machine Chipset",
+ },
+ {
+ Id: "0000:00:07.1",
+ ClassId: 257,
+ Bus: 0x0,
+ Slot: 0x7,
+ Function: 0x1,
+ VendorId: -32634,
+ SubVendorId: 5549,
+ VendorName: "Intel Corporation",
+ DeviceId: 28945,
+ SubDeviceId: 6518,
+ ParentBridge: "",
+ DeviceName: "PIIX4 for 430TX/440BX/MX IDE Controller",
+ },
+ {
+ Id: "0000:00:07.3",
+ ClassId: 1664,
+ Bus: 0x0,
+ Slot: 0x7,
+ Function: 0x3,
+ VendorId: -32634,
+ SubVendorId: 5549,
+ VendorName: "Intel Corporation",
+ DeviceId: 28947,
+ SubDeviceId: 6518,
+ ParentBridge: "",
+ DeviceName: "Virtual Machine Chipset",
+ },
+ {
+ Id: "0000:00:07.7",
+ ClassId: 2176,
+ Bus: 0x0,
+ Slot: 0x7,
+ Function: 0x7,
+ VendorId: 5549,
+ SubVendorId: 5549,
+ VendorName: "VMware",
+ DeviceId: 1856,
+ SubDeviceId: 1856,
+ ParentBridge: "",
+ DeviceName: "Virtual Machine Communication Interface",
+ },
+ {
+ Id: "0000:00:0f.0",
+ ClassId: 768,
+ Bus: 0x0,
+ Slot: 0xf,
+ Function: 0x0,
+ VendorId: 5549,
+ SubVendorId: 5549,
+ VendorName: "VMware",
+ DeviceId: 1029,
+ SubDeviceId: 1029,
+ ParentBridge: "",
+ DeviceName: "SVGA II Adapter",
+ },
+ {
+ Id: "0000:00:11.0",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x11,
+ Function: 0x0,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1936,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI bridge",
+ },
+ {
+ Id: "0000:00:15.0",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x15,
+ Function: 0x0,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:15.1",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x15,
+ Function: 0x1,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:15.2",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x15,
+ Function: 0x2,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:15.3",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x15,
+ Function: 0x3,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:15.4",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x15,
+ Function: 0x4,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:15.5",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x15,
+ Function: 0x5,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:15.6",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x15,
+ Function: 0x6,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:15.7",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x15,
+ Function: 0x7,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:16.0",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x16,
+ Function: 0x0,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:16.1",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x16,
+ Function: 0x1,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:16.2",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x16,
+ Function: 0x2,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:16.3",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x16,
+ Function: 0x3,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:16.4",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x16,
+ Function: 0x4,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:16.5",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x16,
+ Function: 0x5,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:16.6",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x16,
+ Function: 0x6,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:16.7",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x16,
+ Function: 0x7,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:17.0",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x17,
+ Function: 0x0,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:17.1",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x17,
+ Function: 0x1,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:17.2",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x17,
+ Function: 0x2,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:17.3",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x17,
+ Function: 0x3,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:17.4",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x17,
+ Function: 0x4,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:17.5",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x17,
+ Function: 0x5,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:17.6",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x17,
+ Function: 0x6,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:17.7",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x17,
+ Function: 0x7,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:18.0",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x18,
+ Function: 0x0,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:18.1",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x18,
+ Function: 0x1,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:18.2",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x18,
+ Function: 0x2,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:18.3",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x18,
+ Function: 0x3,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:18.4",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x18,
+ Function: 0x4,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:18.5",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x18,
+ Function: 0x5,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:18.6",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x18,
+ Function: 0x6,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:00:18.7",
+ ClassId: 1540,
+ Bus: 0x0,
+ Slot: 0x18,
+ Function: 0x7,
+ VendorId: 5549,
+ SubVendorId: 0,
+ VendorName: "VMware",
+ DeviceId: 1952,
+ SubDeviceId: 0,
+ ParentBridge: "",
+ DeviceName: "PCI Express Root Port",
+ },
+ {
+ Id: "0000:03:00.0",
+ ClassId: 263,
+ Bus: 0x3,
+ Slot: 0x0,
+ Function: 0x0,
+ VendorId: 5549,
+ SubVendorId: 5549,
+ VendorName: "VMware",
+ DeviceId: 1984,
+ SubDeviceId: 1984,
+ ParentBridge: "0000:00:15.0",
+ DeviceName: "PVSCSI SCSI Controller",
+ },
+ {
+ Id: "0000:0b:00.0",
+ ClassId: 512,
+ Bus: 0xb,
+ Slot: 0x0,
+ Function: 0x0,
+ VendorId: 5549,
+ SubVendorId: 5549,
+ VendorName: "VMware Inc.",
+ DeviceId: 1968,
+ SubDeviceId: 1968,
+ ParentBridge: "0000:00:16.0",
+ DeviceName: "vmxnet3 Virtual Ethernet Controller",
+ },
+ {
+ Id: "0000:13:00.0",
+ ClassId: 512,
+ Bus: 0x13,
+ Slot: 0x0,
+ Function: 0x0,
+ VendorId: 5549,
+ SubVendorId: 5549,
+ VendorName: "VMware Inc.",
+ DeviceId: 1968,
+ SubDeviceId: 1968,
+ ParentBridge: "0000:00:17.0",
+ DeviceName: "vmxnet3 Virtual Ethernet Controller",
+ },
+ },
+ CpuFeature: []types.HostCpuIdInfo{
+ {
+ Level: 0,
+ Vendor: "",
+ Eax: "0000:0000:0000:0000:0000:0000:0000:1101",
+ Ebx: "0111:0101:0110:1110:0110:0101:0100:0111",
+ Ecx: "0110:1100:0110:0101:0111:0100:0110:1110",
+ Edx: "0100:1001:0110:0101:0110:1110:0110:1001",
+ },
+ {
+ Level: 1,
+ Vendor: "",
+ Eax: "0000:0000:0000:0010:0000:0110:1101:0111",
+ Ebx: "0000:0000:0000:0001:0000:1000:0000:0000",
+ Ecx: "1001:0111:1011:1010:0010:0010:0010:1011",
+ Edx: "0000:1111:1010:1011:1111:1011:1111:1111",
+ },
+ {
+ Level: -2147483648,
+ Vendor: "",
+ Eax: "1000:0000:0000:0000:0000:0000:0000:1000",
+ Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Ecx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Edx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ },
+ {
+ Level: -2147483647,
+ Vendor: "",
+ Eax: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Ecx: "0000:0000:0000:0000:0000:0000:0000:0001",
+ Edx: "0010:1000:0001:0000:0000:1000:0000:0000",
+ },
+ {
+ Level: -2147483640,
+ Vendor: "",
+ Eax: "0000:0000:0000:0000:0011:0000:0010:1010",
+ Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Ecx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ Edx: "0000:0000:0000:0000:0000:0000:0000:0000",
+ },
+ },
+ BiosInfo: &types.HostBIOSInfo{
+ BiosVersion: "6.00",
+ ReleaseDate: nil,
+ Vendor: "",
+ MajorRelease: 0,
+ MinorRelease: 0,
+ FirmwareMajorRelease: 0,
+ FirmwareMinorRelease: 0,
+ },
+ ReliableMemoryInfo: &types.HostReliableMemoryInfo{},
+}
+
+func init() {
+ date, _ := time.Parse("2006-01-02", "2015-07-02")
+
+ HostHardwareInfo.BiosInfo.ReleaseDate = &date
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/host_system.go b/vendor/github.com/vmware/govmomi/simulator/esx/host_system.go
new file mode 100644
index 00000000..e25f39a5
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/esx/host_system.go
@@ -0,0 +1,1788 @@
+/*
+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 esx
+
+import (
+ "time"
+
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+var HostSystem = mo.HostSystem{
+ ManagedEntity: mo.ManagedEntity{
+ ExtensibleManagedObject: mo.ExtensibleManagedObject{
+ Self: types.ManagedObjectReference{Type: "HostSystem", Value: "ha-host"},
+ Value: nil,
+ AvailableField: nil,
+ },
+ Parent: &types.ManagedObjectReference{Type: "ComputeResource", Value: "ha-compute-res"},
+ CustomValue: nil,
+ OverallStatus: "",
+ ConfigStatus: "",
+ ConfigIssue: nil,
+ EffectiveRole: nil,
+ Permission: nil,
+ Name: "",
+ DisabledMethod: nil,
+ RecentTask: nil,
+ DeclaredAlarmState: nil,
+ TriggeredAlarmState: nil,
+ AlarmActionsEnabled: (*bool)(nil),
+ Tag: nil,
+ },
+ Runtime: types.HostRuntimeInfo{
+ DynamicData: types.DynamicData{},
+ ConnectionState: "connected",
+ PowerState: "poweredOn",
+ StandbyMode: "",
+ InMaintenanceMode: false,
+ BootTime: (*time.Time)(nil),
+ HealthSystemRuntime: &types.HealthSystemRuntime{
+ DynamicData: types.DynamicData{},
+ SystemHealthInfo: &types.HostSystemHealthInfo{
+ DynamicData: types.DynamicData{},
+ NumericSensorInfo: []types.HostNumericSensorInfo{
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware Rollup Health State",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "system",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "CPU socket #0 Level-1 Cache is 16384 B",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Processors",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "CPU socket #0 Level-2 Cache is 0 B",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Processors",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "CPU socket #1 Level-1 Cache is 16384 B",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Processors",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "CPU socket #1 Level-2 Cache is 0 B",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Processors",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "Phoenix Technologies LTD System BIOS 6.00 2014-05-20 00:00:00.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware, Inc. VMware ESXi 6.0.0 build-3634798 2016-03-07 00:00:00.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware sata-ata-piix 2.12-10vmw.600.2.34.3634798 2016-03-08 07:38:41.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware lsu-lsi-mptsas-plugin 1.0.0-1vmw.600.2.34.3634798 2016-03-08 07:39:28.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware net-mlx4-core 1.9.7.0-1vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware lsu-lsi-mpt2sas-plugin 1.0.0-4vmw.600.2.34.3634798 2016-03-08 07:39:28.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware scsi-aacraid 1.1.5.1-9vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware ata-pata-via 0.3.3-2vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware scsi-qla4xxx 5.01.03.2-7vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware sata-sata-promise 2.12-3vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware scsi-megaraid-mbox 2.20.5.1-6vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware vsan 6.0.0-2.34.3563498 2016-02-17 17:18:19.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware net-e1000 8.0.3.1-5vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware ata-pata-serverworks 0.4.3-3vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware scsi-mptspi 4.23.01.00-9vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware net-nx-nic 5.0.621-5vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware block-cciss 3.6.14-10vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware net-bnx2x 1.78.80.v60.12-1vmw.600.2.34.3634798 2016-03-08 07:38:41.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware ipmi-ipmi-devintf 39.1-4vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware scsi-mptsas 4.23.01.00-9vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware scsi-megaraid2 2.00.4-9vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware nvme 1.0e.0.35-1vmw.600.2.34.3634798 2016-03-08 07:38:46.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware esx-xserver 6.0.0-2.34.3634798 2016-03-08 07:39:27.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware nmlx4-en 3.0.0.0-1vmw.600.2.34.3634798 2016-03-08 07:38:46.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware lsu-hp-hpsa-plugin 1.0.0-1vmw.600.2.34.3634798 2016-03-08 07:39:28.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware scsi-megaraid-sas 6.603.55.00-2vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware net-enic 2.1.2.38-2vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware lsi-msgpt3 06.255.12.00-8vmw.600.2.34.3634798 2016-03-08 07:38:46.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware sata-ahci 3.0-22vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware net-forcedeth 0.61-2vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware ata-pata-atiixp 0.4.6-4vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware elxnet 10.2.309.6v-1vmw.600.2.34.3634798 2016-03-08 07:38:46.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware esx-dvfilter-generic-fastpath 6.0.0-2.34.3634798 2016-03-08 07:39:28.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware uhci-usb-uhci 1.0-3vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware ata-pata-amd 0.3.10-3vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware sata-sata-sil24 1.1-1vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware ohci-usb-ohci 1.0-3vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware net-igb 5.0.5.1.1-5vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware ata-pata-pdc2027x 1.0-3vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware ehci-ehci-hcd 1.0-3vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware lsu-lsi-lsi-mr3-plugin 1.0.0-2vmw.600.2.34.3634798 2016-03-08 07:39:28.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware net-ixgbe 3.7.13.7.14iov-20vmw.600.2.34.3634798 2016-03-08 07:38:41.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware vsanhealth 6.0.0-3000000.3.0.2.34.3544323 2016-02-12 06:45:30.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware net-cnic 1.78.76.v60.13-2vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware sata-sata-svw 2.3-3vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware ipmi-ipmi-msghandler 39.1-4vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware emulex-esx-elxnetcli 10.2.309.6v-2.34.3634798 2016-03-08 07:39:28.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware scsi-aic79xx 3.1-5vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware qlnativefc 2.0.12.0-5vmw.600.2.34.3634798 2016-03-08 07:38:46.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware lsu-lsi-lsi-msgpt3-plugin 1.0.0-1vmw.600.2.34.3634798 2016-03-08 07:39:28.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware ima-qla4xxx 2.02.18-1vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware net-mlx4-en 1.9.7.0-1vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware net-e1000e 3.2.2.1-1vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware net-tg3 3.131d.v60.4-2vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware scsi-hpsa 6.0.0.44-4vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware scsi-bnx2fc 1.78.78.v60.8-1vmw.600.2.34.3634798 2016-03-08 07:38:41.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware cpu-microcode 6.0.0-2.34.3634798 2016-03-08 07:39:28.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware scsi-fnic 1.5.0.45-3vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware nmlx4-rdma 3.0.0.0-1vmw.600.2.34.3634798 2016-03-08 07:38:46.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware net-vmxnet3 1.1.3.0-3vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware lpfc 10.2.309.8-2vmw.600.2.34.3634798 2016-03-08 07:38:46.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware esx-ui 1.0.0-3617585 2016-03-03 04:52:43.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware ata-pata-cmd64x 0.2.5-3vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware lsi-mr3 6.605.08.00-7vmw.600.2.34.3634798 2016-03-08 07:38:46.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware ata-pata-hpt3x2n 0.3.4-3vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware sata-sata-nv 3.5-4vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware misc-cnic-register 1.78.75.v60.7-1vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware lsu-lsi-megaraid-sas-plugin 1.0.0-2vmw.600.2.34.3634798 2016-03-08 07:39:28.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware ata-pata-sil680 0.4.8-3vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware esx-tboot 6.0.0-2.34.3634798 2016-03-08 07:39:27.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware xhci-xhci 1.0-3vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware scsi-ips 7.12.05-4vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware scsi-adp94xx 1.0.8.12-6vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware rste 2.0.2.0088-4vmw.600.2.34.3634798 2016-03-08 07:38:46.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware ipmi-ipmi-si-drv 39.1-4vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMWARE mtip32xx-native 3.8.5-1vmw.600.2.34.3634798 2016-03-08 07:38:46.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware scsi-mpt2sas 19.00.00.00-1vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware misc-drivers 6.0.0-2.34.3634798 2016-03-08 07:38:41.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware nmlx4-core 3.0.0.0-1vmw.600.2.34.3634798 2016-03-08 07:38:46.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware sata-sata-sil 2.3-4vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware esx-base 6.0.0-2.34.3634798 2016-03-08 07:39:18.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware scsi-bnx2i 2.78.76.v60.8-1vmw.600.2.34.3634798 2016-03-08 07:38:41.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "VMware net-bnx2 2.2.4f.v60.10-1vmw.600.2.34.3634798 2016-03-08 07:38:45.000",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "e1000 driver 8.0.3.1-NAPI",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Name: "e1000 device firmware N/A",
+ HealthState: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Sensor is operating under normal conditions",
+ },
+ Key: "green",
+ },
+ CurrentReading: 0,
+ UnitModifier: 0,
+ BaseUnits: "",
+ RateUnits: "",
+ SensorType: "Software Components",
+ },
+ },
+ },
+ HardwareStatusInfo: &types.HostHardwareStatusInfo{
+ DynamicData: types.DynamicData{},
+ MemoryStatusInfo: nil,
+ CpuStatusInfo: []types.BaseHostHardwareElementInfo{
+ &types.HostHardwareElementInfo{
+ DynamicData: types.DynamicData{},
+ Name: "CPU socket #0",
+ Status: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Physical element is functioning as expected",
+ },
+ Key: "Green",
+ },
+ },
+ &types.HostHardwareElementInfo{
+ DynamicData: types.DynamicData{},
+ Name: "CPU socket #1",
+ Status: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Green",
+ Summary: "Physical element is functioning as expected",
+ },
+ Key: "Green",
+ },
+ },
+ },
+ StorageStatusInfo: nil,
+ },
+ },
+ DasHostState: (*types.ClusterDasFdmHostState)(nil),
+ TpmPcrValues: nil,
+ VsanRuntimeInfo: &types.VsanHostRuntimeInfo{},
+ NetworkRuntimeInfo: &types.HostRuntimeInfoNetworkRuntimeInfo{
+ DynamicData: types.DynamicData{},
+ NetStackInstanceRuntimeInfo: []types.HostRuntimeInfoNetStackInstanceRuntimeInfo{
+ {
+ DynamicData: types.DynamicData{},
+ NetStackInstanceKey: "defaultTcpipStack",
+ State: "active",
+ VmknicKeys: []string{"vmk0"},
+ MaxNumberOfConnections: 11000,
+ CurrentIpV6Enabled: types.NewBool(true),
+ },
+ },
+ NetworkResourceRuntime: (*types.HostNetworkResourceRuntime)(nil),
+ },
+ VFlashResourceRuntimeInfo: (*types.HostVFlashManagerVFlashResourceRunTimeInfo)(nil),
+ HostMaxVirtualDiskCapacity: 68169720922112,
+ },
+ Summary: types.HostListSummary{
+ DynamicData: types.DynamicData{},
+ Host: &types.ManagedObjectReference{Type: "HostSystem", Value: "ha-host"},
+ Hardware: &types.HostHardwareSummary{
+ DynamicData: types.DynamicData{},
+ Vendor: "VMware, Inc.",
+ Model: "VMware Virtual Platform",
+ Uuid: "564d2f12-8041-639b-5018-05a835b72eaf",
+ OtherIdentifyingInfo: []types.HostSystemIdentificationInfo{
+ {
+ DynamicData: types.DynamicData{},
+ IdentifierValue: " No Asset Tag",
+ IdentifierType: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Asset Tag",
+ Summary: "Asset tag of the system",
+ },
+ Key: "AssetTag",
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ IdentifierValue: "[MS_VM_CERT/SHA1/27d66596a61c48dd3dc7216fd715126e33f59ae7]",
+ IdentifierType: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "OEM specific string",
+ Summary: "OEM specific string",
+ },
+ Key: "OemSpecificString",
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ IdentifierValue: "Welcome to the Virtual Machine",
+ IdentifierType: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "OEM specific string",
+ Summary: "OEM specific string",
+ },
+ Key: "OemSpecificString",
+ },
+ },
+ {
+ DynamicData: types.DynamicData{},
+ IdentifierValue: "VMware-56 4d 2f 12 80 41 63 9b-50 18 05 a8 35 b7 2e af",
+ IdentifierType: &types.ElementDescription{
+ Description: types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Service tag",
+ Summary: "Service tag of the system",
+ },
+ Key: "ServiceTag",
+ },
+ },
+ },
+ MemorySize: 4294430720,
+ CpuModel: "Intel(R) Core(TM) i7-3615QM CPU @ 2.30GHz",
+ CpuMhz: 2294,
+ NumCpuPkgs: 2,
+ NumCpuCores: 2,
+ NumCpuThreads: 2,
+ NumNics: 1,
+ NumHBAs: 3,
+ },
+ Runtime: (*types.HostRuntimeInfo)(nil),
+ Config: types.HostConfigSummary{
+ DynamicData: types.DynamicData{},
+ Name: "localhost.localdomain",
+ Port: 902,
+ SslThumbprint: "",
+ Product: &HostConfigInfo.Product,
+ VmotionEnabled: false,
+ FaultToleranceEnabled: types.NewBool(true),
+ FeatureVersion: nil,
+ AgentVmDatastore: (*types.ManagedObjectReference)(nil),
+ AgentVmNetwork: (*types.ManagedObjectReference)(nil),
+ },
+ QuickStats: types.HostListSummaryQuickStats{
+ DynamicData: types.DynamicData{},
+ OverallCpuUsage: 67,
+ OverallMemoryUsage: 1404,
+ DistributedCpuFairness: 0,
+ DistributedMemoryFairness: 0,
+ Uptime: 77229,
+ },
+ OverallStatus: "gray",
+ RebootRequired: false,
+ CustomValue: nil,
+ ManagementServerIp: "",
+ MaxEVCModeKey: "",
+ CurrentEVCModeKey: "",
+ Gateway: (*types.HostListSummaryGatewaySummary)(nil),
+ },
+ Hardware: (*types.HostHardwareInfo)(nil),
+ Capability: (*types.HostCapability)(nil),
+ LicensableResource: types.HostLicensableResourceInfo{},
+ ConfigManager: types.HostConfigManager{
+ DynamicData: types.DynamicData{},
+ CpuScheduler: &types.ManagedObjectReference{Type: "HostCpuSchedulerSystem", Value: "cpuSchedulerSystem"},
+ DatastoreSystem: &types.ManagedObjectReference{Type: "HostDatastoreSystem", Value: "ha-datastoresystem"},
+ MemoryManager: &types.ManagedObjectReference{Type: "HostMemorySystem", Value: "memoryManagerSystem"},
+ StorageSystem: &types.ManagedObjectReference{Type: "HostStorageSystem", Value: "storageSystem"},
+ NetworkSystem: &types.ManagedObjectReference{Type: "HostNetworkSystem", Value: "networkSystem"},
+ VmotionSystem: &types.ManagedObjectReference{Type: "HostVMotionSystem", Value: "ha-vmotion-system"},
+ VirtualNicManager: &types.ManagedObjectReference{Type: "HostVirtualNicManager", Value: "ha-vnic-mgr"},
+ ServiceSystem: &types.ManagedObjectReference{Type: "HostServiceSystem", Value: "serviceSystem"},
+ FirewallSystem: &types.ManagedObjectReference{Type: "HostFirewallSystem", Value: "firewallSystem"},
+ AdvancedOption: &types.ManagedObjectReference{Type: "OptionManager", Value: "ha-adv-options"},
+ DiagnosticSystem: &types.ManagedObjectReference{Type: "HostDiagnosticSystem", Value: "diagnosticsystem"},
+ AutoStartManager: &types.ManagedObjectReference{Type: "HostAutoStartManager", Value: "ha-autostart-mgr"},
+ SnmpSystem: &types.ManagedObjectReference{Type: "HostSnmpSystem", Value: "ha-snmp-agent"},
+ DateTimeSystem: &types.ManagedObjectReference{Type: "HostDateTimeSystem", Value: "dateTimeSystem"},
+ PatchManager: &types.ManagedObjectReference{Type: "HostPatchManager", Value: "ha-host-patch-manager"},
+ ImageConfigManager: &types.ManagedObjectReference{Type: "HostImageConfigManager", Value: "ha-image-config-manager"},
+ BootDeviceSystem: (*types.ManagedObjectReference)(nil),
+ FirmwareSystem: &types.ManagedObjectReference{Type: "HostFirmwareSystem", Value: "ha-firmwareSystem"},
+ HealthStatusSystem: &types.ManagedObjectReference{Type: "HostHealthStatusSystem", Value: "healthStatusSystem"},
+ PciPassthruSystem: &types.ManagedObjectReference{Type: "HostPciPassthruSystem", Value: "ha-pcipassthrusystem"},
+ LicenseManager: &types.ManagedObjectReference{Type: "LicenseManager", Value: "ha-license-manager"},
+ KernelModuleSystem: &types.ManagedObjectReference{Type: "HostKernelModuleSystem", Value: "kernelModuleSystem"},
+ AuthenticationManager: &types.ManagedObjectReference{Type: "HostAuthenticationManager", Value: "ha-auth-manager"},
+ PowerSystem: &types.ManagedObjectReference{Type: "HostPowerSystem", Value: "ha-power-system"},
+ CacheConfigurationManager: &types.ManagedObjectReference{Type: "HostCacheConfigurationManager", Value: "ha-cache-configuration-manager"},
+ EsxAgentHostManager: (*types.ManagedObjectReference)(nil),
+ IscsiManager: &types.ManagedObjectReference{Type: "IscsiManager", Value: "iscsiManager"},
+ VFlashManager: &types.ManagedObjectReference{Type: "HostVFlashManager", Value: "ha-vflash-manager"},
+ VsanSystem: &types.ManagedObjectReference{Type: "HostVsanSystem", Value: "vsanSystem"},
+ MessageBusProxy: &types.ManagedObjectReference{Type: "MessageBusProxy", Value: "messageBusProxy"},
+ UserDirectory: &types.ManagedObjectReference{Type: "UserDirectory", Value: "ha-user-directory"},
+ AccountManager: &types.ManagedObjectReference{Type: "HostLocalAccountManager", Value: "ha-localacctmgr"},
+ HostAccessManager: &types.ManagedObjectReference{Type: "HostAccessManager", Value: "ha-host-access-manager"},
+ GraphicsManager: &types.ManagedObjectReference{Type: "HostGraphicsManager", Value: "ha-graphics-manager"},
+ VsanInternalSystem: &types.ManagedObjectReference{Type: "HostVsanInternalSystem", Value: "ha-vsan-internal-system"},
+ CertificateManager: &types.ManagedObjectReference{Type: "HostCertificateManager", Value: "ha-certificate-manager"},
+ },
+ Config: &HostConfigInfo,
+ Vm: nil,
+ Datastore: nil,
+ Network: nil,
+ DatastoreBrowser: types.ManagedObjectReference{Type: "HostDatastoreBrowser", Value: "ha-host-datastorebrowser"},
+ SystemResources: (*types.HostSystemResourceInfo)(nil),
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/resource_pool.go b/vendor/github.com/vmware/govmomi/simulator/esx/resource_pool.go
new file mode 100644
index 00000000..08d6da5d
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/esx/resource_pool.go
@@ -0,0 +1,162 @@
+/*
+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 esx
+
+import (
+ "time"
+
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+var ResourcePool = mo.ResourcePool{
+ ManagedEntity: mo.ManagedEntity{
+ ExtensibleManagedObject: mo.ExtensibleManagedObject{
+ Self: types.ManagedObjectReference{Type: "ResourcePool", Value: "ha-root-pool"},
+ Value: nil,
+ AvailableField: nil,
+ },
+ Parent: &types.ManagedObjectReference{Type: "ComputeResource", Value: "ha-compute-res"},
+ CustomValue: nil,
+ OverallStatus: "green",
+ ConfigStatus: "green",
+ ConfigIssue: nil,
+ EffectiveRole: []int32{-1},
+ Permission: nil,
+ Name: "Resources",
+ DisabledMethod: []string{"CreateVApp", "CreateChildVM_Task"},
+ RecentTask: nil,
+ DeclaredAlarmState: nil,
+ TriggeredAlarmState: nil,
+ AlarmActionsEnabled: (*bool)(nil),
+ Tag: nil,
+ },
+ Summary: &types.ResourcePoolSummary{
+ DynamicData: types.DynamicData{},
+ Name: "Resources",
+ Config: types.ResourceConfigSpec{
+ DynamicData: types.DynamicData{},
+ Entity: &types.ManagedObjectReference{Type: "ResourcePool", Value: "ha-root-pool"},
+ ChangeVersion: "",
+ LastModified: (*time.Time)(nil),
+ CpuAllocation: &types.ResourceAllocationInfo{
+ DynamicData: types.DynamicData{},
+ Reservation: 4121,
+ ExpandableReservation: types.NewBool(false),
+ Limit: 4121,
+ Shares: &types.SharesInfo{
+ DynamicData: types.DynamicData{},
+ Shares: 9000,
+ Level: "custom",
+ },
+ OverheadLimit: 0,
+ },
+ MemoryAllocation: &types.ResourceAllocationInfo{
+ DynamicData: types.DynamicData{},
+ Reservation: 961,
+ ExpandableReservation: types.NewBool(false),
+ Limit: 961,
+ Shares: &types.SharesInfo{
+ DynamicData: types.DynamicData{},
+ Shares: 9000,
+ Level: "custom",
+ },
+ OverheadLimit: 0,
+ },
+ },
+ Runtime: types.ResourcePoolRuntimeInfo{
+ DynamicData: types.DynamicData{},
+ Memory: types.ResourcePoolResourceUsage{
+ DynamicData: types.DynamicData{},
+ ReservationUsed: 0,
+ ReservationUsedForVm: 0,
+ UnreservedForPool: 1007681536,
+ UnreservedForVm: 1007681536,
+ OverallUsage: 0,
+ MaxUsage: 1007681536,
+ },
+ Cpu: types.ResourcePoolResourceUsage{
+ DynamicData: types.DynamicData{},
+ ReservationUsed: 0,
+ ReservationUsedForVm: 0,
+ UnreservedForPool: 4121,
+ UnreservedForVm: 4121,
+ OverallUsage: 0,
+ MaxUsage: 4121,
+ },
+ OverallStatus: "green",
+ },
+ QuickStats: (*types.ResourcePoolQuickStats)(nil),
+ ConfiguredMemoryMB: 0,
+ },
+ Runtime: types.ResourcePoolRuntimeInfo{
+ DynamicData: types.DynamicData{},
+ Memory: types.ResourcePoolResourceUsage{
+ DynamicData: types.DynamicData{},
+ ReservationUsed: 0,
+ ReservationUsedForVm: 0,
+ UnreservedForPool: 1007681536,
+ UnreservedForVm: 1007681536,
+ OverallUsage: 0,
+ MaxUsage: 1007681536,
+ },
+ Cpu: types.ResourcePoolResourceUsage{
+ DynamicData: types.DynamicData{},
+ ReservationUsed: 0,
+ ReservationUsedForVm: 0,
+ UnreservedForPool: 4121,
+ UnreservedForVm: 4121,
+ OverallUsage: 0,
+ MaxUsage: 4121,
+ },
+ OverallStatus: "green",
+ },
+ Owner: types.ManagedObjectReference{Type: "ComputeResource", Value: "ha-compute-res"},
+ ResourcePool: nil,
+ Vm: nil,
+ Config: types.ResourceConfigSpec{
+ DynamicData: types.DynamicData{},
+ Entity: &types.ManagedObjectReference{Type: "ResourcePool", Value: "ha-root-pool"},
+ ChangeVersion: "",
+ LastModified: (*time.Time)(nil),
+ CpuAllocation: &types.ResourceAllocationInfo{
+ DynamicData: types.DynamicData{},
+ Reservation: 4121,
+ ExpandableReservation: types.NewBool(false),
+ Limit: 4121,
+ Shares: &types.SharesInfo{
+ DynamicData: types.DynamicData{},
+ Shares: 9000,
+ Level: "custom",
+ },
+ OverheadLimit: 0,
+ },
+ MemoryAllocation: &types.ResourceAllocationInfo{
+ DynamicData: types.DynamicData{},
+ Reservation: 961,
+ ExpandableReservation: types.NewBool(false),
+ Limit: 961,
+ Shares: &types.SharesInfo{
+ DynamicData: types.DynamicData{},
+ Shares: 9000,
+ Level: "custom",
+ },
+ OverheadLimit: 0,
+ },
+ },
+ ChildConfiguration: nil,
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/root_folder.go b/vendor/github.com/vmware/govmomi/simulator/esx/root_folder.go
new file mode 100644
index 00000000..bb40706f
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/esx/root_folder.go
@@ -0,0 +1,73 @@
+/*
+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 esx
+
+import (
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+var RootFolder = mo.Folder{
+ ManagedEntity: mo.ManagedEntity{
+ ExtensibleManagedObject: mo.ExtensibleManagedObject{
+ Self: types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-root"},
+ Value: nil,
+ AvailableField: nil,
+ },
+ Parent: (*types.ManagedObjectReference)(nil),
+ CustomValue: nil,
+ OverallStatus: "green",
+ ConfigStatus: "green",
+ ConfigIssue: nil,
+ EffectiveRole: []int32{-1},
+ Permission: []types.Permission{
+ {
+ DynamicData: types.DynamicData{},
+ Entity: &types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-root"},
+ Principal: "vpxuser",
+ Group: false,
+ RoleId: -1,
+ Propagate: true,
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Entity: &types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-root"},
+ Principal: "dcui",
+ Group: false,
+ RoleId: -1,
+ Propagate: true,
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Entity: &types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-root"},
+ Principal: "root",
+ Group: false,
+ RoleId: -1,
+ Propagate: true,
+ },
+ },
+ Name: "ha-folder-root",
+ DisabledMethod: nil,
+ RecentTask: nil,
+ DeclaredAlarmState: nil,
+ TriggeredAlarmState: nil,
+ AlarmActionsEnabled: (*bool)(nil),
+ Tag: nil,
+ },
+ ChildType: []string{"Datacenter"},
+ ChildEntity: nil,
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/service_content.go b/vendor/github.com/vmware/govmomi/simulator/esx/service_content.go
new file mode 100644
index 00000000..88f2cbbb
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/esx/service_content.go
@@ -0,0 +1,79 @@
+/*
+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 esx
+
+import "github.com/vmware/govmomi/vim25/types"
+
+var ServiceContent = types.ServiceContent{
+ DynamicData: types.DynamicData{},
+ RootFolder: types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-root"},
+ PropertyCollector: types.ManagedObjectReference{Type: "PropertyCollector", Value: "ha-property-collector"},
+ ViewManager: &types.ManagedObjectReference{Type: "ViewManager", Value: "ViewManager"},
+ About: types.AboutInfo{
+ DynamicData: types.DynamicData{},
+ Name: "VMware ESXi",
+ FullName: "VMware ESXi 6.0.0 build-3620759",
+ Vendor: "VMware, Inc.",
+ Version: "6.0.0",
+ Build: "3620759",
+ LocaleVersion: "INTL",
+ LocaleBuild: "000",
+ OsType: "vmnix-x86",
+ ProductLineId: "embeddedEsx",
+ ApiType: "HostAgent",
+ ApiVersion: "6.0",
+ InstanceUuid: "",
+ LicenseProductName: "VMware ESX Server",
+ LicenseProductVersion: "6.0",
+ },
+ Setting: &types.ManagedObjectReference{Type: "OptionManager", Value: "HostAgentSettings"},
+ UserDirectory: &types.ManagedObjectReference{Type: "UserDirectory", Value: "ha-user-directory"},
+ SessionManager: &types.ManagedObjectReference{Type: "SessionManager", Value: "ha-sessionmgr"},
+ AuthorizationManager: &types.ManagedObjectReference{Type: "AuthorizationManager", Value: "ha-authmgr"},
+ ServiceManager: &types.ManagedObjectReference{Type: "ServiceManager", Value: "ha-servicemanager"},
+ PerfManager: &types.ManagedObjectReference{Type: "PerformanceManager", Value: "ha-perfmgr"},
+ ScheduledTaskManager: (*types.ManagedObjectReference)(nil),
+ AlarmManager: (*types.ManagedObjectReference)(nil),
+ EventManager: &types.ManagedObjectReference{Type: "EventManager", Value: "ha-eventmgr"},
+ TaskManager: &types.ManagedObjectReference{Type: "TaskManager", Value: "ha-taskmgr"},
+ ExtensionManager: (*types.ManagedObjectReference)(nil),
+ CustomizationSpecManager: (*types.ManagedObjectReference)(nil),
+ CustomFieldsManager: (*types.ManagedObjectReference)(nil),
+ AccountManager: &types.ManagedObjectReference{Type: "HostLocalAccountManager", Value: "ha-localacctmgr"},
+ DiagnosticManager: &types.ManagedObjectReference{Type: "DiagnosticManager", Value: "ha-diagnosticmgr"},
+ LicenseManager: &types.ManagedObjectReference{Type: "LicenseManager", Value: "ha-license-manager"},
+ SearchIndex: &types.ManagedObjectReference{Type: "SearchIndex", Value: "ha-searchindex"},
+ FileManager: &types.ManagedObjectReference{Type: "FileManager", Value: "ha-nfc-file-manager"},
+ DatastoreNamespaceManager: &types.ManagedObjectReference{Type: "DatastoreNamespaceManager", Value: "ha-datastore-namespace-manager"},
+ VirtualDiskManager: &types.ManagedObjectReference{Type: "VirtualDiskManager", Value: "ha-vdiskmanager"},
+ VirtualizationManager: (*types.ManagedObjectReference)(nil),
+ SnmpSystem: (*types.ManagedObjectReference)(nil),
+ VmProvisioningChecker: (*types.ManagedObjectReference)(nil),
+ VmCompatibilityChecker: (*types.ManagedObjectReference)(nil),
+ OvfManager: &types.ManagedObjectReference{Type: "OvfManager", Value: "ha-ovf-manager"},
+ IpPoolManager: (*types.ManagedObjectReference)(nil),
+ DvSwitchManager: &types.ManagedObjectReference{Type: "DistributedVirtualSwitchManager", Value: "ha-dvsmanager"},
+ HostProfileManager: (*types.ManagedObjectReference)(nil),
+ ClusterProfileManager: (*types.ManagedObjectReference)(nil),
+ ComplianceManager: (*types.ManagedObjectReference)(nil),
+ LocalizationManager: &types.ManagedObjectReference{Type: "LocalizationManager", Value: "ha-l10n-manager"},
+ StorageResourceManager: &types.ManagedObjectReference{Type: "StorageResourceManager", Value: "ha-storage-resource-manager"},
+ GuestOperationsManager: &types.ManagedObjectReference{Type: "GuestOperationsManager", Value: "ha-guest-operations-manager"},
+ OverheadMemoryManager: (*types.ManagedObjectReference)(nil),
+ CertificateManager: (*types.ManagedObjectReference)(nil),
+ IoFilterManager: (*types.ManagedObjectReference)(nil),
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/setting.go b/vendor/github.com/vmware/govmomi/simulator/esx/setting.go
new file mode 100644
index 00000000..c5c6ae60
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/esx/setting.go
@@ -0,0 +1,28 @@
+/*
+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 esx
+
+import "github.com/vmware/govmomi/vim25/types"
+
+// Setting is captured from ESX's HostSystem.configManager.advancedOption
+var Setting = []types.BaseOptionValue{
+ // This list is currently pruned to include a single option for testing
+ &types.OptionValue{
+ Key: "Config.HostAgent.log.level",
+ Value: "info",
+ },
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/virtual_device.go b/vendor/github.com/vmware/govmomi/simulator/esx/virtual_device.go
new file mode 100644
index 00000000..0d394364
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/esx/virtual_device.go
@@ -0,0 +1,243 @@
+/*
+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 esx
+
+import "github.com/vmware/govmomi/vim25/types"
+
+// VirtualDevice is the default set of VirtualDevice types created for a VirtualMachine
+var VirtualDevice = []types.BaseVirtualDevice{
+ &types.VirtualIDEController{
+ VirtualController: types.VirtualController{
+ VirtualDevice: types.VirtualDevice{
+ DynamicData: types.DynamicData{},
+ Key: 200,
+ DeviceInfo: &types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "IDE 0",
+ Summary: "IDE 0",
+ },
+ Backing: nil,
+ Connectable: (*types.VirtualDeviceConnectInfo)(nil),
+ SlotInfo: nil,
+ ControllerKey: 0,
+ UnitNumber: (*int32)(nil),
+ },
+ BusNumber: 0,
+ Device: nil,
+ },
+ },
+ &types.VirtualIDEController{
+ VirtualController: types.VirtualController{
+ VirtualDevice: types.VirtualDevice{
+ DynamicData: types.DynamicData{},
+ Key: 201,
+ DeviceInfo: &types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "IDE 1",
+ Summary: "IDE 1",
+ },
+ Backing: nil,
+ Connectable: (*types.VirtualDeviceConnectInfo)(nil),
+ SlotInfo: nil,
+ ControllerKey: 0,
+ UnitNumber: (*int32)(nil),
+ },
+ BusNumber: 1,
+ Device: nil,
+ },
+ },
+ &types.VirtualPS2Controller{
+ VirtualController: types.VirtualController{
+ VirtualDevice: types.VirtualDevice{
+ DynamicData: types.DynamicData{},
+ Key: 300,
+ DeviceInfo: &types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "PS2 controller 0",
+ Summary: "PS2 controller 0",
+ },
+ Backing: nil,
+ Connectable: (*types.VirtualDeviceConnectInfo)(nil),
+ SlotInfo: nil,
+ ControllerKey: 0,
+ UnitNumber: (*int32)(nil),
+ },
+ BusNumber: 0,
+ Device: []int32{600, 700},
+ },
+ },
+ &types.VirtualPCIController{
+ VirtualController: types.VirtualController{
+ VirtualDevice: types.VirtualDevice{
+ DynamicData: types.DynamicData{},
+ Key: 100,
+ DeviceInfo: &types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "PCI controller 0",
+ Summary: "PCI controller 0",
+ },
+ Backing: nil,
+ Connectable: (*types.VirtualDeviceConnectInfo)(nil),
+ SlotInfo: nil,
+ ControllerKey: 0,
+ UnitNumber: (*int32)(nil),
+ },
+ BusNumber: 0,
+ Device: []int32{500, 12000},
+ },
+ },
+ &types.VirtualSIOController{
+ VirtualController: types.VirtualController{
+ VirtualDevice: types.VirtualDevice{
+ DynamicData: types.DynamicData{},
+ Key: 400,
+ DeviceInfo: &types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "SIO controller 0",
+ Summary: "SIO controller 0",
+ },
+ Backing: nil,
+ Connectable: (*types.VirtualDeviceConnectInfo)(nil),
+ SlotInfo: nil,
+ ControllerKey: 0,
+ UnitNumber: (*int32)(nil),
+ },
+ BusNumber: 0,
+ Device: nil,
+ },
+ },
+ &types.VirtualKeyboard{
+ VirtualDevice: types.VirtualDevice{
+ DynamicData: types.DynamicData{},
+ Key: 600,
+ DeviceInfo: &types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Keyboard ",
+ Summary: "Keyboard",
+ },
+ Backing: nil,
+ Connectable: (*types.VirtualDeviceConnectInfo)(nil),
+ SlotInfo: nil,
+ ControllerKey: 300,
+ UnitNumber: newInt32(0),
+ },
+ },
+ &types.VirtualPointingDevice{
+ VirtualDevice: types.VirtualDevice{
+ DynamicData: types.DynamicData{},
+ Key: 700,
+ DeviceInfo: &types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Pointing device",
+ Summary: "Pointing device; Device",
+ },
+ Backing: &types.VirtualPointingDeviceDeviceBackingInfo{
+ VirtualDeviceDeviceBackingInfo: types.VirtualDeviceDeviceBackingInfo{
+ VirtualDeviceBackingInfo: types.VirtualDeviceBackingInfo{},
+ DeviceName: "",
+ UseAutoDetect: types.NewBool(false),
+ },
+ HostPointingDevice: "autodetect",
+ },
+ Connectable: (*types.VirtualDeviceConnectInfo)(nil),
+ SlotInfo: nil,
+ ControllerKey: 300,
+ UnitNumber: newInt32(1),
+ },
+ },
+ &types.VirtualMachineVideoCard{
+ VirtualDevice: types.VirtualDevice{
+ DynamicData: types.DynamicData{},
+ Key: 500,
+ DeviceInfo: &types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "Video card ",
+ Summary: "Video card",
+ },
+ Backing: nil,
+ Connectable: (*types.VirtualDeviceConnectInfo)(nil),
+ SlotInfo: nil,
+ ControllerKey: 100,
+ UnitNumber: newInt32(0),
+ },
+ VideoRamSizeInKB: 4096,
+ NumDisplays: 1,
+ UseAutoDetect: types.NewBool(false),
+ Enable3DSupport: types.NewBool(false),
+ Use3dRenderer: "automatic",
+ GraphicsMemorySizeInKB: 262144,
+ },
+ &types.VirtualMachineVMCIDevice{
+ VirtualDevice: types.VirtualDevice{
+ DynamicData: types.DynamicData{},
+ Key: 12000,
+ DeviceInfo: &types.Description{
+ DynamicData: types.DynamicData{},
+ Label: "VMCI device",
+ Summary: "Device on the virtual machine PCI bus that provides support for the virtual machine communication interface",
+ },
+ Backing: nil,
+ Connectable: (*types.VirtualDeviceConnectInfo)(nil),
+ SlotInfo: nil,
+ ControllerKey: 100,
+ UnitNumber: newInt32(17),
+ },
+ Id: -1,
+ AllowUnrestrictedCommunication: types.NewBool(false),
+ FilterEnable: types.NewBool(true),
+ FilterInfo: (*types.VirtualMachineVMCIDeviceFilterInfo)(nil),
+ },
+}
+
+// EthernetCard template for types.VirtualEthernetCard
+var EthernetCard = types.VirtualE1000{
+ VirtualEthernetCard: types.VirtualEthernetCard{
+ VirtualDevice: types.VirtualDevice{
+ DynamicData: types.DynamicData{},
+ Key: 4000,
+ Backing: &types.VirtualEthernetCardNetworkBackingInfo{
+ VirtualDeviceDeviceBackingInfo: types.VirtualDeviceDeviceBackingInfo{
+ VirtualDeviceBackingInfo: types.VirtualDeviceBackingInfo{},
+ DeviceName: "VM Network",
+ UseAutoDetect: types.NewBool(false),
+ },
+ Network: (*types.ManagedObjectReference)(nil),
+ InPassthroughMode: types.NewBool(false),
+ },
+ Connectable: &types.VirtualDeviceConnectInfo{
+ DynamicData: types.DynamicData{},
+ StartConnected: true,
+ AllowGuestControl: true,
+ Connected: false,
+ Status: "untried",
+ },
+ SlotInfo: &types.VirtualDevicePciBusSlotInfo{
+ VirtualDeviceBusSlotInfo: types.VirtualDeviceBusSlotInfo{},
+ PciSlotNumber: 32,
+ },
+ ControllerKey: 100,
+ UnitNumber: newInt32(7),
+ },
+ AddressType: "generated",
+ MacAddress: "",
+ WakeOnLanEnabled: types.NewBool(true),
+ },
+}
+
+func newInt32(n int32) *int32 {
+ return &n
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/file_manager.go b/vendor/github.com/vmware/govmomi/simulator/file_manager.go
new file mode 100644
index 00000000..26bb4a25
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/file_manager.go
@@ -0,0 +1,257 @@
+/*
+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 simulator
+
+import (
+ "io"
+ "os"
+ "path"
+
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/simulator/esx"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type FileManager struct {
+ mo.FileManager
+}
+
+func NewFileManager(ref types.ManagedObjectReference) object.Reference {
+ m := &FileManager{}
+ m.Self = ref
+ return m
+}
+
+func (f *FileManager) findDatastore(ref mo.Reference, name string) (*Datastore, types.BaseMethodFault) {
+ var refs []types.ManagedObjectReference
+
+ switch obj := ref.(type) {
+ case *Folder:
+ refs = obj.ChildEntity
+ case *StoragePod:
+ refs = obj.ChildEntity
+ }
+
+ for _, ref := range refs {
+ switch obj := Map.Get(ref).(type) {
+ case *Datastore:
+ if obj.Name == name {
+ return obj, nil
+ }
+ case *Folder, *StoragePod:
+ ds, _ := f.findDatastore(obj, name)
+ if ds != nil {
+ return ds, nil
+ }
+ }
+ }
+
+ return nil, &types.InvalidDatastore{Name: name}
+}
+
+func (f *FileManager) resolve(dc *types.ManagedObjectReference, name string) (string, types.BaseMethodFault) {
+ p, fault := parseDatastorePath(name)
+ if fault != nil {
+ return "", fault
+ }
+
+ if dc == nil {
+ if Map.IsESX() {
+ dc = &esx.Datacenter.Self
+ } else {
+ return "", &types.InvalidArgument{InvalidProperty: "dc"}
+ }
+ }
+
+ folder := Map.Get(*dc).(*mo.Datacenter).DatastoreFolder
+
+ ds, fault := f.findDatastore(Map.Get(folder), p.Datastore)
+ if fault != nil {
+ return "", fault
+ }
+
+ dir := ds.Info.GetDatastoreInfo().Url
+
+ return path.Join(dir, p.Path), nil
+}
+
+func (f *FileManager) fault(name string, err error, fault types.BaseFileFault) types.BaseMethodFault {
+ switch {
+ case os.IsNotExist(err):
+ fault = new(types.FileNotFound)
+ case os.IsExist(err):
+ fault = new(types.FileAlreadyExists)
+ }
+
+ fault.GetFileFault().File = name
+
+ return fault.(types.BaseMethodFault)
+}
+
+func (f *FileManager) deleteDatastoreFile(req *types.DeleteDatastoreFile_Task) types.BaseMethodFault {
+ file, fault := f.resolve(req.Datacenter, req.Name)
+ if fault != nil {
+ return fault
+ }
+
+ _, err := os.Stat(file)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return f.fault(file, err, new(types.CannotDeleteFile))
+ }
+ }
+
+ err = os.RemoveAll(file)
+ if err != nil {
+ return f.fault(file, err, new(types.CannotDeleteFile))
+ }
+
+ return nil
+}
+
+func (f *FileManager) DeleteDatastoreFileTask(req *types.DeleteDatastoreFile_Task) soap.HasFault {
+ task := CreateTask(f, "deleteDatastoreFile", func(*Task) (types.AnyType, types.BaseMethodFault) {
+ return nil, f.deleteDatastoreFile(req)
+ })
+
+ task.Run()
+
+ return &methods.DeleteDatastoreFile_TaskBody{
+ Res: &types.DeleteDatastoreFile_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
+
+func (f *FileManager) MakeDirectory(req *types.MakeDirectory) soap.HasFault {
+ body := &methods.MakeDirectoryBody{}
+
+ name, fault := f.resolve(req.Datacenter, req.Name)
+ if fault != nil {
+ body.Fault_ = Fault("", fault)
+ return body
+ }
+
+ mkdir := os.Mkdir
+
+ if isTrue(req.CreateParentDirectories) {
+ mkdir = os.MkdirAll
+ }
+
+ err := mkdir(name, 0700)
+ if err != nil {
+ fault = f.fault(req.Name, err, new(types.CannotCreateFile))
+ body.Fault_ = Fault(err.Error(), fault)
+ return body
+ }
+
+ return body
+}
+
+func (f *FileManager) moveDatastoreFile(req *types.MoveDatastoreFile_Task) types.BaseMethodFault {
+ src, fault := f.resolve(req.SourceDatacenter, req.SourceName)
+ if fault != nil {
+ return fault
+ }
+
+ dst, fault := f.resolve(req.DestinationDatacenter, req.DestinationName)
+ if fault != nil {
+ return fault
+ }
+
+ if !isTrue(req.Force) {
+ _, err := os.Stat(dst)
+ if err == nil {
+ return f.fault(dst, nil, new(types.FileAlreadyExistsFault))
+ }
+ }
+
+ err := os.Rename(src, dst)
+ if err != nil {
+ return f.fault(src, err, new(types.CannotAccessFile))
+ }
+
+ return nil
+}
+
+func (f *FileManager) MoveDatastoreFileTask(req *types.MoveDatastoreFile_Task) soap.HasFault {
+ task := CreateTask(f, "moveDatastoreFile", func(*Task) (types.AnyType, types.BaseMethodFault) {
+ return nil, f.moveDatastoreFile(req)
+ })
+
+ task.Run()
+
+ return &methods.MoveDatastoreFile_TaskBody{
+ Res: &types.MoveDatastoreFile_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
+
+func (f *FileManager) copyDatastoreFile(req *types.CopyDatastoreFile_Task) types.BaseMethodFault {
+ src, fault := f.resolve(req.SourceDatacenter, req.SourceName)
+ if fault != nil {
+ return fault
+ }
+
+ dst, fault := f.resolve(req.DestinationDatacenter, req.DestinationName)
+ if fault != nil {
+ return fault
+ }
+
+ if !isTrue(req.Force) {
+ _, err := os.Stat(dst)
+ if err == nil {
+ return f.fault(dst, nil, new(types.FileAlreadyExistsFault))
+ }
+ }
+
+ r, err := os.Open(src)
+ if err != nil {
+ return f.fault(dst, err, new(types.CannotAccessFile))
+ }
+ defer r.Close()
+
+ w, err := os.Create(dst)
+ if err != nil {
+ return f.fault(dst, err, new(types.CannotCreateFile))
+ }
+ defer w.Close()
+
+ if _, err = io.Copy(w, r); err != nil {
+ return f.fault(dst, err, new(types.CannotCreateFile))
+ }
+
+ return nil
+}
+
+func (f *FileManager) CopyDatastoreFileTask(req *types.CopyDatastoreFile_Task) soap.HasFault {
+ task := CreateTask(f, "copyDatastoreFile", func(*Task) (types.AnyType, types.BaseMethodFault) {
+ return nil, f.copyDatastoreFile(req)
+ })
+
+ task.Run()
+
+ return &methods.CopyDatastoreFile_TaskBody{
+ Res: &types.CopyDatastoreFile_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/folder.go b/vendor/github.com/vmware/govmomi/simulator/folder.go
new file mode 100644
index 00000000..2fe93ae0
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/folder.go
@@ -0,0 +1,438 @@
+/*
+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 simulator
+
+import (
+ "fmt"
+ "math/rand"
+ "path"
+ "sync"
+
+ "github.com/google/uuid"
+
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type Folder struct {
+ mo.Folder
+
+ m sync.Mutex
+}
+
+// update references when objects are added/removed from a Folder
+func (f *Folder) update(o mo.Reference, u func(types.ManagedObjectReference, []types.ManagedObjectReference) []types.ManagedObjectReference) {
+ ref := o.Reference()
+
+ if f.Parent == nil {
+ return // this is the root folder
+ }
+
+ switch ref.Type {
+ case "Datacenter", "Folder":
+ return // nothing to update
+ }
+
+ dc := Map.getEntityDatacenter(f)
+
+ switch ref.Type {
+ case "Network", "DistributedVirtualSwitch", "DistributedVirtualPortgroup":
+ dc.Network = u(ref, dc.Network)
+ case "Datastore":
+ dc.Datastore = u(ref, dc.Datastore)
+ }
+}
+
+func (f *Folder) putChild(o mo.Entity) {
+ Map.PutEntity(f, o)
+
+ f.m.Lock()
+ defer f.m.Unlock()
+
+ f.ChildEntity = AddReference(o.Reference(), f.ChildEntity)
+
+ f.update(o, AddReference)
+}
+
+func (f *Folder) removeChild(o mo.Reference) {
+ Map.Remove(o.Reference())
+
+ f.m.Lock()
+ defer f.m.Unlock()
+
+ f.ChildEntity = RemoveReference(o.Reference(), f.ChildEntity)
+
+ f.update(o, RemoveReference)
+}
+
+func (f *Folder) hasChildType(kind string) bool {
+ for _, t := range f.ChildType {
+ if t == kind {
+ return true
+ }
+ }
+ return false
+}
+
+func (f *Folder) typeNotSupported() *soap.Fault {
+ return Fault(fmt.Sprintf("%s supports types: %#v", f.Self, f.ChildType), &types.NotSupported{})
+}
+
+type addStandaloneHost struct {
+ *Folder
+
+ req *types.AddStandaloneHost_Task
+}
+
+func (add *addStandaloneHost) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
+ host, err := CreateStandaloneHost(add.Folder, add.req.Spec)
+ if err != nil {
+ return nil, err
+ }
+
+ if add.req.AddConnected {
+ host.Runtime.ConnectionState = types.HostSystemConnectionStateConnected
+ }
+
+ return host.Reference(), nil
+}
+
+func (f *Folder) AddStandaloneHostTask(a *types.AddStandaloneHost_Task) soap.HasFault {
+ r := &methods.AddStandaloneHost_TaskBody{}
+
+ if f.hasChildType("ComputeResource") && f.hasChildType("Folder") {
+ task := NewTask(&addStandaloneHost{f, a})
+
+ r.Res = &types.AddStandaloneHost_TaskResponse{
+ Returnval: task.Self,
+ }
+
+ task.Run()
+ } else {
+ r.Fault_ = f.typeNotSupported()
+ }
+
+ return r
+}
+
+func (f *Folder) CreateFolder(c *types.CreateFolder) soap.HasFault {
+ r := &methods.CreateFolderBody{}
+
+ if f.hasChildType("Folder") {
+ folder := &Folder{}
+
+ folder.Name = c.Name
+ folder.ChildType = f.ChildType
+
+ f.putChild(folder)
+
+ r.Res = &types.CreateFolderResponse{
+ Returnval: folder.Self,
+ }
+ } else {
+ r.Fault_ = f.typeNotSupported()
+ }
+
+ return r
+}
+
+// StoragePod aka "Datastore Cluster"
+type StoragePod struct {
+ mo.StoragePod
+}
+
+func (f *Folder) CreateStoragePod(c *types.CreateStoragePod) soap.HasFault {
+ r := &methods.CreateStoragePodBody{}
+
+ if f.hasChildType("StoragePod") {
+ pod := &StoragePod{}
+
+ pod.Name = c.Name
+ pod.ChildType = []string{"Datastore"}
+
+ f.putChild(pod)
+
+ r.Res = &types.CreateStoragePodResponse{
+ Returnval: pod.Self,
+ }
+ } else {
+ r.Fault_ = f.typeNotSupported()
+ }
+
+ return r
+}
+
+func (p *StoragePod) MoveIntoFolderTask(c *types.MoveIntoFolder_Task) soap.HasFault {
+ return (&Folder{Folder: p.Folder}).MoveIntoFolderTask(c)
+}
+
+func (f *Folder) CreateDatacenter(c *types.CreateDatacenter) soap.HasFault {
+ r := &methods.CreateDatacenterBody{}
+
+ if f.hasChildType("Datacenter") && f.hasChildType("Folder") {
+ dc := &mo.Datacenter{}
+
+ dc.Name = c.Name
+
+ f.putChild(dc)
+
+ createDatacenterFolders(dc, true)
+
+ r.Res = &types.CreateDatacenterResponse{
+ Returnval: dc.Self,
+ }
+ } else {
+ r.Fault_ = f.typeNotSupported()
+ }
+
+ return r
+}
+
+func (f *Folder) CreateClusterEx(c *types.CreateClusterEx) soap.HasFault {
+ r := &methods.CreateClusterExBody{}
+
+ if f.hasChildType("ComputeResource") && f.hasChildType("Folder") {
+ cluster, err := CreateClusterComputeResource(f, c.Name, c.Spec)
+ if err != nil {
+ r.Fault_ = Fault("", err)
+ return r
+ }
+
+ r.Res = &types.CreateClusterExResponse{
+ Returnval: cluster.Self,
+ }
+ } else {
+ r.Fault_ = f.typeNotSupported()
+ }
+
+ return r
+}
+
+type createVM struct {
+ *Folder
+
+ req *types.CreateVM_Task
+
+ register bool
+}
+
+func (c *createVM) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
+ vm, err := NewVirtualMachine(c.Folder.Self, &c.req.Config)
+ if err != nil {
+ return nil, err
+ }
+
+ vm.ResourcePool = &c.req.Pool
+
+ if c.req.Host == nil {
+ var hosts []types.ManagedObjectReference
+
+ pool := Map.Get(c.req.Pool).(mo.Entity)
+
+ switch cr := Map.getEntityComputeResource(pool).(type) {
+ case *mo.ComputeResource:
+ hosts = cr.Host
+ case *ClusterComputeResource:
+ hosts = cr.Host
+ }
+
+ // Assuming for now that all hosts have access to the datastore
+ host := hosts[rand.Intn(len(hosts))]
+ vm.Runtime.Host = &host
+ } else {
+ vm.Runtime.Host = c.req.Host
+ }
+
+ vm.Summary.Config.VmPathName = vm.Config.Files.VmPathName
+ vm.Summary.Runtime.Host = vm.Runtime.Host
+
+ err = vm.create(&c.req.Config, c.register)
+ if err != nil {
+ return nil, err
+ }
+
+ c.Folder.putChild(vm)
+
+ host := Map.Get(*vm.Runtime.Host).(*HostSystem)
+ host.Vm = append(host.Vm, vm.Self)
+
+ for i := range vm.Datastore {
+ ds := Map.Get(vm.Datastore[i]).(*Datastore)
+ ds.Vm = append(ds.Vm, vm.Self)
+ }
+
+ switch rp := Map.Get(*vm.ResourcePool).(type) {
+ case *ResourcePool:
+ rp.Vm = append(rp.Vm, vm.Self)
+ case *VirtualApp:
+ rp.Vm = append(rp.Vm, vm.Self)
+ }
+
+ return vm.Reference(), nil
+}
+
+func (f *Folder) CreateVMTask(c *types.CreateVM_Task) soap.HasFault {
+ r := &methods.CreateVM_TaskBody{}
+
+ task := NewTask(&createVM{f, c, false})
+
+ r.Res = &types.CreateVM_TaskResponse{
+ Returnval: task.Self,
+ }
+
+ task.Run()
+
+ return r
+}
+
+type registerVM struct {
+ *Folder
+
+ req *types.RegisterVM_Task
+}
+
+func (c *registerVM) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
+ if c.req.AsTemplate {
+ return nil, &types.NotSupported{}
+ }
+
+ if c.req.Pool == nil {
+ return nil, &types.InvalidArgument{InvalidProperty: "pool"}
+ }
+
+ if c.req.Path == "" {
+ return nil, &types.InvalidArgument{InvalidProperty: "path"}
+ }
+
+ p := Map.Get(*c.req.Pool).(mo.Entity)
+ s := Map.SearchIndex()
+ r := s.FindByDatastorePath(&types.FindByDatastorePath{
+ This: s.Reference(),
+ Path: c.req.Path,
+ Datacenter: Map.getEntityDatacenter(p).Reference(),
+ })
+
+ if ref := r.(*methods.FindByDatastorePathBody).Res.Returnval; ref != nil {
+ return nil, &types.AlreadyExists{Name: ref.Value}
+ }
+
+ if c.req.Name == "" {
+ p, err := parseDatastorePath(c.req.Path)
+ if err != nil {
+ return nil, err
+ }
+
+ c.req.Name = path.Dir(p.Path)
+ }
+
+ create := NewTask(&createVM{
+ Folder: c.Folder,
+ register: true,
+ req: &types.CreateVM_Task{
+ This: c.Folder.Reference(),
+ Config: types.VirtualMachineConfigSpec{
+ Name: c.req.Name,
+ Files: &types.VirtualMachineFileInfo{
+ VmPathName: c.req.Path,
+ },
+ },
+ Pool: *c.req.Pool,
+ Host: c.req.Host,
+ },
+ })
+
+ create.Run()
+
+ if create.Info.Error != nil {
+ return nil, create.Info.Error.Fault
+ }
+
+ return create.Info.Result, nil
+}
+
+func (f *Folder) RegisterVMTask(c *types.RegisterVM_Task) soap.HasFault {
+ r := &methods.RegisterVM_TaskBody{}
+
+ task := NewTask(®isterVM{f, c})
+
+ r.Res = &types.RegisterVM_TaskResponse{
+ Returnval: task.Self,
+ }
+
+ task.Run()
+
+ return r
+}
+
+func (f *Folder) MoveIntoFolderTask(c *types.MoveIntoFolder_Task) soap.HasFault {
+ task := CreateTask(f, "moveIntoFolder", func(t *Task) (types.AnyType, types.BaseMethodFault) {
+ for _, ref := range c.List {
+ obj := Map.Get(ref).(mo.Entity)
+
+ parent, ok := Map.Get(*(obj.Entity()).Parent).(*Folder)
+
+ if !ok || !f.hasChildType(ref.Type) {
+ return nil, &types.NotSupported{}
+ }
+
+ parent.removeChild(ref)
+ f.putChild(obj)
+ }
+
+ return nil, nil
+ })
+
+ task.Run()
+
+ return &methods.MoveIntoFolder_TaskBody{
+ Res: &types.MoveIntoFolder_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
+
+func (f *Folder) CreateDVSTask(c *types.CreateDVS_Task) soap.HasFault {
+ task := CreateTask(f, "createDVS", func(t *Task) (types.AnyType, types.BaseMethodFault) {
+ dvs := &VmwareDistributedVirtualSwitch{}
+ dvs.Name = c.Spec.ConfigSpec.GetDVSConfigSpec().Name
+ dvs.Entity().Name = dvs.Name
+
+ if Map.FindByName(dvs.Name, f.ChildEntity) != nil {
+ return nil, &types.InvalidArgument{InvalidProperty: "name"}
+ }
+
+ dvs.Uuid = uuid.New().String()
+
+ f.putChild(dvs)
+
+ return dvs.Reference(), nil
+ })
+
+ task.Run()
+
+ return &methods.CreateDVS_TaskBody{
+ Res: &types.CreateDVS_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
+
+func (f *Folder) RenameTask(r *types.Rename_Task) soap.HasFault {
+ return RenameTask(f, r)
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/host_datastore_browser.go b/vendor/github.com/vmware/govmomi/simulator/host_datastore_browser.go
new file mode 100644
index 00000000..d7e9ad7c
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/host_datastore_browser.go
@@ -0,0 +1,258 @@
+/*
+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 simulator
+
+import (
+ "io/ioutil"
+ "log"
+ "os"
+ "path"
+ "strings"
+
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type HostDatastoreBrowser struct {
+ mo.HostDatastoreBrowser
+}
+
+type searchDatastore struct {
+ *HostDatastoreBrowser
+
+ DatastorePath string
+ SearchSpec *types.HostDatastoreBrowserSearchSpec
+
+ res []types.HostDatastoreBrowserSearchResults
+
+ recurse bool
+}
+
+func (s *searchDatastore) addFile(file os.FileInfo, res *types.HostDatastoreBrowserSearchResults) {
+ details := s.SearchSpec.Details
+ if details == nil {
+ details = new(types.FileQueryFlags)
+ }
+
+ name := file.Name()
+
+ info := types.FileInfo{
+ Path: name,
+ }
+
+ var finfo types.BaseFileInfo = &info
+
+ if details.FileSize {
+ info.FileSize = file.Size()
+ }
+
+ if details.Modification {
+ mtime := file.ModTime()
+ info.Modification = &mtime
+ }
+
+ if isTrue(details.FileOwner) {
+ // Assume for now this process created all files in the datastore
+ user := os.Getenv("USER")
+
+ info.Owner = user
+ }
+
+ if file.IsDir() {
+ finfo = &types.FolderFileInfo{FileInfo: info}
+ } else if details.FileType {
+ switch path.Ext(name) {
+ case ".img":
+ finfo = &types.FloppyImageFileInfo{FileInfo: info}
+ case ".iso":
+ finfo = &types.IsoImageFileInfo{FileInfo: info}
+ case ".log":
+ finfo = &types.VmLogFileInfo{FileInfo: info}
+ case ".nvram":
+ finfo = &types.VmNvramFileInfo{FileInfo: info}
+ case ".vmdk":
+ // TODO: lookup device to set other fields
+ finfo = &types.VmDiskFileInfo{FileInfo: info}
+ case ".vmx":
+ finfo = &types.VmConfigFileInfo{FileInfo: info}
+ }
+ }
+
+ res.File = append(res.File, finfo)
+}
+
+func (s *searchDatastore) queryMatch(file os.FileInfo) bool {
+ if len(s.SearchSpec.Query) == 0 {
+ return true
+ }
+
+ name := file.Name()
+ ext := path.Ext(name)
+
+ for _, q := range s.SearchSpec.Query {
+ switch q.(type) {
+ case *types.FileQuery:
+ return true
+ case *types.FolderFileQuery:
+ if file.IsDir() {
+ return true
+ }
+ case *types.FloppyImageFileQuery:
+ if ext == ".img" {
+ return true
+ }
+ case *types.IsoImageFileQuery:
+ if ext == ".iso" {
+ return true
+ }
+ case *types.VmConfigFileQuery:
+ if ext == ".vmx" {
+ // TODO: check Filter and Details fields
+ return true
+ }
+ case *types.VmDiskFileQuery:
+ if ext == ".vmdk" {
+ if strings.HasSuffix(name, "-flat.vmdk") {
+ // only matches the descriptor, not the backing file(s)
+ return false
+ }
+ // TODO: check Filter and Details fields
+ return true
+ }
+ case *types.VmLogFileQuery:
+ if ext == ".log" {
+ return strings.HasPrefix(name, "vmware")
+ }
+ case *types.VmNvramFileQuery:
+ if ext == ".nvram" {
+ return true
+ }
+ case *types.VmSnapshotFileQuery:
+ if ext == ".vmsn" {
+ return true
+ }
+ }
+ }
+
+ return false
+}
+
+func (s *searchDatastore) search(ds *types.ManagedObjectReference, folder string, dir string) error {
+ files, err := ioutil.ReadDir(dir)
+ if err != nil {
+ log.Printf("search %s: %s", dir, err)
+ return err
+ }
+
+ res := types.HostDatastoreBrowserSearchResults{
+ Datastore: ds,
+ FolderPath: folder,
+ }
+
+ for _, file := range files {
+ name := file.Name()
+
+ if s.queryMatch(file) {
+ for _, m := range s.SearchSpec.MatchPattern {
+ if ok, _ := path.Match(m, name); ok {
+ s.addFile(file, &res)
+ break
+ }
+ }
+ }
+
+ if s.recurse && file.IsDir() {
+ _ = s.search(ds, path.Join(folder, name), path.Join(dir, name))
+ }
+ }
+
+ s.res = append(s.res, res)
+
+ return nil
+}
+
+func (s *searchDatastore) Run(Task *Task) (types.AnyType, types.BaseMethodFault) {
+ p, fault := parseDatastorePath(s.DatastorePath)
+ if fault != nil {
+ return nil, fault
+ }
+
+ ref := Map.FindByName(p.Datastore, s.Datastore)
+ if ref == nil {
+ return nil, &types.InvalidDatastore{Name: p.Datastore}
+ }
+
+ ds := ref.(*Datastore)
+
+ dir := path.Join(ds.Info.GetDatastoreInfo().Url, p.Path)
+
+ err := s.search(&ds.Self, s.DatastorePath, dir)
+ if err != nil {
+ ff := types.FileFault{
+ File: p.Path,
+ }
+
+ if os.IsNotExist(err) {
+ return nil, &types.FileNotFound{FileFault: ff}
+ }
+
+ return nil, &types.InvalidArgument{InvalidProperty: p.Path}
+ }
+
+ if s.recurse {
+ return types.ArrayOfHostDatastoreBrowserSearchResults{
+ HostDatastoreBrowserSearchResults: s.res,
+ }, nil
+ }
+
+ return s.res[0], nil
+}
+
+func (b *HostDatastoreBrowser) SearchDatastoreTask(s *types.SearchDatastore_Task) soap.HasFault {
+ task := NewTask(&searchDatastore{
+ HostDatastoreBrowser: b,
+ DatastorePath: s.DatastorePath,
+ SearchSpec: s.SearchSpec,
+ })
+
+ task.Run()
+
+ return &methods.SearchDatastore_TaskBody{
+ Res: &types.SearchDatastore_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
+
+func (b *HostDatastoreBrowser) SearchDatastoreSubFoldersTask(s *types.SearchDatastoreSubFolders_Task) soap.HasFault {
+ task := NewTask(&searchDatastore{
+ HostDatastoreBrowser: b,
+ DatastorePath: s.DatastorePath,
+ SearchSpec: s.SearchSpec,
+ recurse: true,
+ })
+
+ task.Run()
+
+ return &methods.SearchDatastoreSubFolders_TaskBody{
+ Res: &types.SearchDatastoreSubFolders_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/host_datastore_system.go b/vendor/github.com/vmware/govmomi/simulator/host_datastore_system.go
new file mode 100644
index 00000000..32da7d0e
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/host_datastore_system.go
@@ -0,0 +1,161 @@
+/*
+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 simulator
+
+import (
+ "os"
+ "path"
+
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type HostDatastoreSystem struct {
+ mo.HostDatastoreSystem
+
+ Host *mo.HostSystem
+}
+
+func (dss *HostDatastoreSystem) add(ds *Datastore) *soap.Fault {
+ info := ds.Info.GetDatastoreInfo()
+
+ info.Name = ds.Name
+
+ if e := Map.FindByName(ds.Name, dss.Datastore); e != nil {
+ return Fault(e.Reference().Value, &types.DuplicateName{
+ Name: ds.Name,
+ Object: e.Reference(),
+ })
+ }
+
+ fi, err := os.Stat(info.Url)
+ if err == nil && !fi.IsDir() {
+ err = os.ErrInvalid
+ }
+
+ if err != nil {
+ switch {
+ case os.IsNotExist(err):
+ return Fault(err.Error(), &types.NotFound{})
+ default:
+ return Fault(err.Error(), &types.HostConfigFault{})
+ }
+ }
+
+ folder := Map.getEntityFolder(dss.Host, "datastore")
+ ds.Self.Type = TypeName(ds)
+ // Datastore is the only type where create methods do not include the parent (Folder in this case),
+ // but we need the moref to be unique per DC/datastoreFolder, but not per-HostSystem.
+ ds.Self.Value += "@" + folder.Self.Value
+ // TODO: name should be made unique in the case of Local ds type
+
+ ds.Summary.Datastore = &ds.Self
+ ds.Summary.Name = ds.Name
+ ds.Summary.Url = info.Url
+
+ dss.Datastore = append(dss.Datastore, ds.Self)
+ dss.Host.Datastore = dss.Datastore
+ parent := hostParent(dss.Host)
+ parent.Datastore = AddReference(ds.Self, parent.Datastore)
+
+ browser := &HostDatastoreBrowser{}
+ browser.Datastore = dss.Datastore
+ ds.Browser = Map.Put(browser).Reference()
+
+ folder.putChild(ds)
+
+ return nil
+}
+
+func (dss *HostDatastoreSystem) CreateLocalDatastore(c *types.CreateLocalDatastore) soap.HasFault {
+ r := &methods.CreateLocalDatastoreBody{}
+
+ ds := &Datastore{}
+ ds.Name = c.Name
+ ds.Self.Value = c.Path
+
+ ds.Info = &types.LocalDatastoreInfo{
+ DatastoreInfo: types.DatastoreInfo{
+ Name: c.Name,
+ Url: c.Path,
+ },
+ Path: c.Path,
+ }
+
+ ds.Summary.Type = "local"
+
+ if err := dss.add(ds); err != nil {
+ r.Fault_ = err
+ return r
+ }
+
+ ds.Host = append(ds.Host, types.DatastoreHostMount{
+ Key: dss.Host.Reference(),
+ MountInfo: types.HostMountInfo{
+ AccessMode: string(types.HostMountModeReadWrite),
+ Mounted: types.NewBool(true),
+ Accessible: types.NewBool(true),
+ },
+ })
+
+ _ = ds.RefreshDatastore(&types.RefreshDatastore{This: ds.Self})
+
+ r.Res = &types.CreateLocalDatastoreResponse{
+ Returnval: ds.Self,
+ }
+
+ return r
+}
+
+func (dss *HostDatastoreSystem) CreateNasDatastore(c *types.CreateNasDatastore) soap.HasFault {
+ r := &methods.CreateNasDatastoreBody{}
+
+ ds := &Datastore{}
+ ds.Name = path.Base(c.Spec.LocalPath)
+ ds.Self.Value = c.Spec.RemoteHost + ":" + c.Spec.RemotePath
+
+ ds.Info = &types.NasDatastoreInfo{
+ DatastoreInfo: types.DatastoreInfo{
+ Url: c.Spec.LocalPath,
+ },
+ Nas: &types.HostNasVolume{
+ HostFileSystemVolume: types.HostFileSystemVolume{
+ Name: c.Spec.LocalPath,
+ Type: c.Spec.Type,
+ },
+ RemoteHost: c.Spec.RemoteHost,
+ RemotePath: c.Spec.RemotePath,
+ },
+ }
+
+ ds.Summary.Type = c.Spec.Type
+
+ if err := dss.add(ds); err != nil {
+ r.Fault_ = err
+ return r
+ }
+
+ _ = ds.RefreshDatastore(&types.RefreshDatastore{This: ds.Self})
+
+ r.Res = &types.CreateNasDatastoreResponse{
+ Returnval: ds.Self,
+ }
+
+ return r
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/host_firewall_system.go b/vendor/github.com/vmware/govmomi/simulator/host_firewall_system.go
new file mode 100644
index 00000000..fd596386
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/host_firewall_system.go
@@ -0,0 +1,87 @@
+/*
+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 simulator
+
+import (
+ "github.com/vmware/govmomi/simulator/esx"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type HostFirewallSystem struct {
+ mo.HostFirewallSystem
+}
+
+func NewHostFirewallSystem(_ *mo.HostSystem) *HostFirewallSystem {
+ info := esx.HostFirewallInfo
+
+ return &HostFirewallSystem{
+ HostFirewallSystem: mo.HostFirewallSystem{
+ FirewallInfo: &info,
+ },
+ }
+}
+
+func DisableRuleset(info *types.HostFirewallInfo, id string) bool {
+ for i := range info.Ruleset {
+ if info.Ruleset[i].Key == id {
+ info.Ruleset[i].Enabled = false
+ return true
+ }
+ }
+
+ return false
+}
+
+func (s *HostFirewallSystem) DisableRuleset(req *types.DisableRuleset) soap.HasFault {
+ body := &methods.DisableRulesetBody{}
+
+ if DisableRuleset(s.HostFirewallSystem.FirewallInfo, req.Id) {
+ body.Res = new(types.DisableRulesetResponse)
+ return body
+ }
+
+ body.Fault_ = Fault("", &types.NotFound{})
+
+ return body
+}
+
+func EnableRuleset(info *types.HostFirewallInfo, id string) bool {
+ for i := range info.Ruleset {
+ if info.Ruleset[i].Key == id {
+ info.Ruleset[i].Enabled = true
+ return true
+ }
+ }
+
+ return false
+}
+
+func (s *HostFirewallSystem) EnableRuleset(req *types.EnableRuleset) soap.HasFault {
+ body := &methods.EnableRulesetBody{}
+
+ if EnableRuleset(s.HostFirewallSystem.FirewallInfo, req.Id) {
+ body.Res = new(types.EnableRulesetResponse)
+ return body
+ }
+
+ body.Fault_ = Fault("", &types.NotFound{})
+
+ return body
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/host_network_system.go b/vendor/github.com/vmware/govmomi/simulator/host_network_system.go
new file mode 100644
index 00000000..d0502c9a
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/host_network_system.go
@@ -0,0 +1,161 @@
+/*
+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 simulator
+
+import (
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type HostNetworkSystem struct {
+ mo.HostNetworkSystem
+
+ Host *mo.HostSystem
+}
+
+func NewHostNetworkSystem(host *mo.HostSystem) *HostNetworkSystem {
+ return &HostNetworkSystem{
+ Host: host,
+ HostNetworkSystem: mo.HostNetworkSystem{
+ NetworkInfo: &types.HostNetworkInfo{
+ Vswitch: []types.HostVirtualSwitch{
+ {
+ Name: "vSwitch0",
+ Portgroup: []string{"VM Network"},
+ },
+ },
+ },
+ },
+ }
+}
+
+func (s *HostNetworkSystem) folder() *Folder {
+ f := Map.getEntityDatacenter(s.Host).NetworkFolder
+ return Map.Get(f).(*Folder)
+}
+
+func (s *HostNetworkSystem) AddVirtualSwitch(c *types.AddVirtualSwitch) soap.HasFault {
+ r := &methods.AddVirtualSwitchBody{}
+
+ for _, vswitch := range s.NetworkInfo.Vswitch {
+ if vswitch.Name == c.VswitchName {
+ r.Fault_ = Fault("", &types.AlreadyExists{Name: c.VswitchName})
+ return r
+ }
+ }
+
+ s.NetworkInfo.Vswitch = append(s.NetworkInfo.Vswitch, types.HostVirtualSwitch{
+ Name: c.VswitchName,
+ })
+
+ r.Res = &types.AddVirtualSwitchResponse{}
+
+ return r
+}
+
+func (s *HostNetworkSystem) RemoveVirtualSwitch(c *types.RemoveVirtualSwitch) soap.HasFault {
+ r := &methods.RemoveVirtualSwitchBody{}
+
+ vs := s.NetworkInfo.Vswitch
+
+ for i, v := range vs {
+ if v.Name == c.VswitchName {
+ s.NetworkInfo.Vswitch = append(vs[:i], vs[i+1:]...)
+ r.Res = &types.RemoveVirtualSwitchResponse{}
+ return r
+ }
+ }
+
+ r.Fault_ = Fault("", &types.NotFound{})
+
+ return r
+}
+
+func (s *HostNetworkSystem) AddPortGroup(c *types.AddPortGroup) soap.HasFault {
+ var vswitch *types.HostVirtualSwitch
+
+ r := &methods.AddPortGroupBody{}
+
+ if c.Portgrp.Name == "" {
+ r.Fault_ = Fault("", &types.InvalidArgument{InvalidProperty: "name"})
+ return r
+ }
+
+ for i := range s.NetworkInfo.Vswitch {
+ if s.NetworkInfo.Vswitch[i].Name == c.Portgrp.VswitchName {
+ vswitch = &s.NetworkInfo.Vswitch[i]
+ break
+ }
+ }
+
+ if vswitch == nil {
+ r.Fault_ = Fault("", &types.NotFound{})
+ return r
+ }
+
+ network := &mo.Network{}
+ network.Name = c.Portgrp.Name
+ network.Entity().Name = network.Name
+
+ folder := s.folder()
+
+ if obj := Map.FindByName(c.Portgrp.Name, folder.ChildEntity); obj != nil {
+ r.Fault_ = Fault("", &types.DuplicateName{
+ Name: c.Portgrp.Name,
+ Object: obj.Reference(),
+ })
+
+ return r
+ }
+
+ folder.putChild(network)
+
+ vswitch.Portgroup = append(vswitch.Portgroup, c.Portgrp.Name)
+ r.Res = &types.AddPortGroupResponse{}
+
+ return r
+}
+
+func (s *HostNetworkSystem) RemovePortGroup(c *types.RemovePortGroup) soap.HasFault {
+ var vswitch *types.HostVirtualSwitch
+
+ r := &methods.RemovePortGroupBody{}
+
+ for i, v := range s.NetworkInfo.Vswitch {
+ for j, pg := range v.Portgroup {
+ if pg == c.PgName {
+ vswitch = &s.NetworkInfo.Vswitch[i]
+ vswitch.Portgroup = append(vswitch.Portgroup[:j], vswitch.Portgroup[j+1:]...)
+ }
+ }
+ }
+
+ if vswitch == nil {
+ r.Fault_ = Fault("", &types.NotFound{})
+ return r
+ }
+
+ folder := s.folder()
+ e := Map.FindByName(c.PgName, folder.ChildEntity)
+ folder.removeChild(e.Reference())
+
+ r.Res = &types.RemovePortGroupResponse{}
+
+ return r
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/host_system.go b/vendor/github.com/vmware/govmomi/simulator/host_system.go
new file mode 100644
index 00000000..779c578c
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/host_system.go
@@ -0,0 +1,132 @@
+/*
+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 simulator
+
+import (
+ "time"
+
+ "github.com/google/uuid"
+ "github.com/vmware/govmomi/simulator/esx"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type HostSystem struct {
+ mo.HostSystem
+}
+
+func NewHostSystem(host mo.HostSystem) *HostSystem {
+ now := time.Now()
+
+ host.Name = host.Summary.Config.Name
+ host.Summary.Runtime = &host.Runtime
+ host.Summary.Runtime.BootTime = &now
+
+ hw := *host.Summary.Hardware // shallow copy
+ hw.Uuid = uuid.New().String()
+ host.Summary.Hardware = &hw
+
+ info := *esx.HostHardwareInfo
+ info.SystemInfo.Uuid = hw.Uuid
+ host.Hardware = &info
+
+ hs := &HostSystem{
+ HostSystem: host,
+ }
+
+ config := []struct {
+ ref **types.ManagedObjectReference
+ obj mo.Reference
+ }{
+ {&hs.ConfigManager.DatastoreSystem, &HostDatastoreSystem{Host: &hs.HostSystem}},
+ {&hs.ConfigManager.NetworkSystem, NewHostNetworkSystem(&hs.HostSystem)},
+ {&hs.ConfigManager.AdvancedOption, NewOptionManager(nil, esx.Setting)},
+ {&hs.ConfigManager.FirewallSystem, NewHostFirewallSystem(&hs.HostSystem)},
+ }
+
+ for _, c := range config {
+ ref := Map.Put(c.obj).Reference()
+
+ *c.ref = &ref
+ }
+
+ return hs
+}
+
+func hostParent(host *mo.HostSystem) *mo.ComputeResource {
+ switch parent := Map.Get(*host.Parent).(type) {
+ case *mo.ComputeResource:
+ return parent
+ case *ClusterComputeResource:
+ return &parent.ComputeResource
+ default:
+ return nil
+ }
+}
+
+// CreateDefaultESX creates a standalone ESX
+// Adds objects of type: Datacenter, Network, ComputeResource, ResourcePool and HostSystem
+func CreateDefaultESX(f *Folder) {
+ dc := &esx.Datacenter
+ f.putChild(dc)
+ createDatacenterFolders(dc, false)
+
+ host := NewHostSystem(esx.HostSystem)
+
+ cr := &mo.ComputeResource{}
+ cr.Self = *host.Parent
+ cr.Name = host.Name
+ cr.Host = append(cr.Host, host.Reference())
+ Map.PutEntity(cr, host)
+
+ pool := NewResourcePool()
+ cr.ResourcePool = &pool.Self
+ Map.PutEntity(cr, pool)
+ pool.Owner = cr.Self
+
+ Map.Get(dc.HostFolder).(*Folder).putChild(cr)
+}
+
+// CreateStandaloneHost uses esx.HostSystem as a template, applying the given spec
+// and creating the ComputeResource parent and ResourcePool sibling.
+func CreateStandaloneHost(f *Folder, spec types.HostConnectSpec) (*HostSystem, types.BaseMethodFault) {
+ if spec.HostName == "" {
+ return nil, &types.NoHost{}
+ }
+
+ pool := NewResourcePool()
+ host := NewHostSystem(esx.HostSystem)
+
+ host.Summary.Config.Name = spec.HostName
+ host.Name = host.Summary.Config.Name
+ host.Runtime.ConnectionState = types.HostSystemConnectionStateDisconnected
+
+ cr := &mo.ComputeResource{}
+
+ Map.PutEntity(cr, Map.NewEntity(host))
+
+ Map.PutEntity(cr, Map.NewEntity(pool))
+
+ cr.Name = host.Name
+ cr.Host = append(cr.Host, host.Reference())
+ cr.ResourcePool = &pool.Self
+
+ f.putChild(cr)
+ pool.Owner = cr.Self
+
+ return host, nil
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/license_manager.go b/vendor/github.com/vmware/govmomi/simulator/license_manager.go
new file mode 100644
index 00000000..adabfc54
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/license_manager.go
@@ -0,0 +1,111 @@
+/*
+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.
+*/
+// Copyright 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 simulator
+
+import (
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+// EvalLicense is the default license
+var EvalLicense = types.LicenseManagerLicenseInfo{
+ LicenseKey: "00000-00000-00000-00000-00000",
+ EditionKey: "eval",
+ Name: "Evaluation Mode",
+ Properties: []types.KeyAnyValue{
+ {
+ Key: "feature",
+ Value: types.KeyValue{
+ Key: "serialuri:2",
+ Value: "Remote virtual Serial Port Concentrator",
+ },
+ },
+ {
+ Key: "feature",
+ Value: types.KeyValue{
+ Key: "dvs",
+ Value: "vSphere Distributed Switch",
+ },
+ },
+ },
+}
+
+type LicenseManager struct {
+ mo.LicenseManager
+}
+
+func NewLicenseManager(ref types.ManagedObjectReference) object.Reference {
+ m := &LicenseManager{}
+ m.Self = ref
+ m.Licenses = []types.LicenseManagerLicenseInfo{EvalLicense}
+
+ if Map.IsVPX() {
+ am := Map.Put(&LicenseAssignmentManager{}).Reference()
+ m.LicenseAssignmentManager = &am
+ }
+
+ return m
+}
+
+type LicenseAssignmentManager struct {
+ mo.LicenseAssignmentManager
+}
+
+func (m *LicenseAssignmentManager) QueryAssignedLicenses(req *types.QueryAssignedLicenses) soap.HasFault {
+ body := &methods.QueryAssignedLicensesBody{
+ Res: &types.QueryAssignedLicensesResponse{},
+ }
+
+ // EntityId can be a HostSystem or the vCenter InstanceUuid
+ if req.EntityId != "" {
+ if req.EntityId != Map.content().About.InstanceUuid {
+ id := types.ManagedObjectReference{
+ Type: "HostSystem",
+ Value: req.EntityId,
+ }
+
+ if Map.Get(id) == nil {
+ return body
+ }
+ }
+ }
+
+ body.Res.Returnval = []types.LicenseAssignmentManagerLicenseAssignment{
+ {
+ EntityId: req.EntityId,
+ AssignedLicense: EvalLicense,
+ },
+ }
+
+ return body
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/model.go b/vendor/github.com/vmware/govmomi/simulator/model.go
new file mode 100644
index 00000000..18daccbd
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/model.go
@@ -0,0 +1,473 @@
+/*
+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 simulator
+
+import (
+ "context"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path"
+
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/simulator/esx"
+ "github.com/vmware/govmomi/simulator/vpx"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+// Model is used to populate a Model with an initial set of managed entities.
+// This is a simple helper for tests running against a simulator, to populate an inventory
+// with commonly used models.
+type Model struct {
+ Service *Service
+
+ ServiceContent types.ServiceContent
+ RootFolder mo.Folder
+
+ // Datacenter specifies the number of Datacenter entities to create
+ Datacenter int
+
+ // Portgroup specifies the number of DistributedVirtualPortgroup entities to create per Datacenter
+ Portgroup int
+
+ // Host specifies the number of standalone HostSystems entities to create per Datacenter
+ Host int
+
+ // Cluster specifies the number of ClusterComputeResource entities to create per Datacenter
+ Cluster int
+
+ // ClusterHost specifies the number of HostSystems entities to create within a Cluster
+ ClusterHost int
+
+ // Pool specifies the number of ResourcePool entities to create per Cluster
+ Pool int
+
+ // Datastore specifies the number of Datastore entities to create
+ // Each Datastore will have temporary local file storage and will be mounted
+ // on every HostSystem created by the ModelConfig
+ Datastore int
+
+ // Machine specifies the number of VirtualMachine entities to create per ResourcePool
+ Machine int
+
+ // Folder specifies the number of Datacenter to place within a Folder.
+ // This includes a folder for the Datacenter itself and its host, vm, network and datastore folders.
+ // All resources for the Datacenter are placed within these folders, rather than the top-level folders.
+ Folder int
+
+ // App specifies the number of VirtualApp to create per Cluster
+ App int
+
+ // Pod specifies the number of StoragePod to create per Cluster
+ Pod int
+
+ // total number of inventory objects, set by Count()
+ total int
+
+ dirs []string
+}
+
+// ESX is the default Model for a standalone ESX instance
+func ESX() *Model {
+ return &Model{
+ ServiceContent: esx.ServiceContent,
+ RootFolder: esx.RootFolder,
+ Datastore: 1,
+ Machine: 2,
+ }
+}
+
+// VPX is the default Model for a vCenter instance
+func VPX() *Model {
+ return &Model{
+ ServiceContent: vpx.ServiceContent,
+ RootFolder: vpx.RootFolder,
+ Datacenter: 1,
+ Portgroup: 1,
+ Host: 1,
+ Cluster: 1,
+ ClusterHost: 3,
+ Datastore: 1,
+ Machine: 2,
+ }
+}
+
+// Count returns a Model with total number of each existing type
+func (m *Model) Count() Model {
+ count := Model{}
+
+ for ref, obj := range Map.objects {
+ if _, ok := obj.(mo.Entity); !ok {
+ continue
+ }
+
+ count.total++
+
+ switch ref.Type {
+ case "Datacenter":
+ count.Datacenter++
+ case "DistributedVirtualPortgroup":
+ count.Portgroup++
+ case "ClusterComputeResource":
+ count.Cluster++
+ case "Datastore":
+ count.Datastore++
+ case "HostSystem":
+ count.Host++
+ case "VirtualMachine":
+ count.Machine++
+ case "ResourcePool":
+ count.Pool++
+ case "VirtualApp":
+ count.App++
+ case "Folder":
+ count.Folder++
+ case "StoragePod":
+ count.Pod++
+ }
+ }
+
+ return count
+}
+
+func (*Model) fmtName(prefix string, num int) string {
+ return fmt.Sprintf("%s%d", prefix, num)
+}
+
+// Create populates the Model with the given ModelConfig
+func (m *Model) Create() error {
+ m.Service = New(NewServiceInstance(m.ServiceContent, m.RootFolder))
+
+ ctx := context.Background()
+ client := m.Service.client
+ root := object.NewRootFolder(client)
+
+ // After all hosts are created, this var is used to mount the host datastores.
+ var hosts []*object.HostSystem
+ // We need to defer VM creation until after the datastores are created.
+ var vms []func() error
+ // 1 DVS per DC, added to all hosts
+ var dvs *object.DistributedVirtualSwitch
+ // 1 NIC per VM, backed by a DVPG if Model.Portgroup > 0
+ vmnet := esx.EthernetCard.Backing
+
+ // addHost adds a cluster host or a stanalone host.
+ addHost := func(name string, f func(types.HostConnectSpec) (*object.Task, error)) (*object.HostSystem, error) {
+ spec := types.HostConnectSpec{
+ HostName: name,
+ }
+
+ task, err := f(spec)
+ if err != nil {
+ return nil, err
+ }
+
+ info, err := task.WaitForResult(context.Background(), nil)
+ if err != nil {
+ return nil, err
+ }
+
+ host := object.NewHostSystem(client, info.Result.(types.ManagedObjectReference))
+ hosts = append(hosts, host)
+
+ if dvs != nil {
+ config := &types.DVSConfigSpec{
+ Host: []types.DistributedVirtualSwitchHostMemberConfigSpec{{
+ Operation: string(types.ConfigSpecOperationAdd),
+ Host: host.Reference(),
+ }},
+ }
+
+ _, _ = dvs.Reconfigure(ctx, config)
+ }
+
+ return host, nil
+ }
+
+ // addMachine returns a func to create a VM.
+ addMachine := func(prefix string, host *object.HostSystem, pool *object.ResourcePool, folders *object.DatacenterFolders) {
+ nic := esx.EthernetCard
+ nic.Backing = vmnet
+ ds := types.ManagedObjectReference{}
+
+ f := func() error {
+ for i := 0; i < m.Machine; i++ {
+ name := m.fmtName(prefix+"_VM", i)
+
+ config := types.VirtualMachineConfigSpec{
+ Name: name,
+ GuestId: string(types.VirtualMachineGuestOsIdentifierOtherGuest),
+ Files: &types.VirtualMachineFileInfo{
+ VmPathName: "[LocalDS_0]",
+ },
+ }
+
+ if pool == nil {
+ pool, _ = host.ResourcePool(ctx)
+ }
+
+ var devices object.VirtualDeviceList
+
+ scsi, _ := devices.CreateSCSIController("pvscsi")
+ ide, _ := devices.CreateIDEController()
+ cdrom, _ := devices.CreateCdrom(ide.(*types.VirtualIDEController))
+ disk := devices.CreateDisk(scsi.(types.BaseVirtualController), ds,
+ config.Files.VmPathName+" "+path.Join(name, "disk1.vmdk"))
+
+ devices = append(devices, scsi, cdrom, disk, &nic)
+
+ config.DeviceChange, _ = devices.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd)
+
+ task, err := folders.VmFolder.CreateVM(ctx, config, pool, host)
+ if err != nil {
+ return err
+ }
+
+ err = task.Wait(ctx)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+ }
+
+ vms = append(vms, f)
+ }
+
+ nfolder := 0
+
+ for ndc := 0; ndc < m.Datacenter; ndc++ {
+ dcName := m.fmtName("DC", ndc)
+ folder := root
+ fName := m.fmtName("F", nfolder)
+
+ // If Datacenter > Folder, don't create folders for the first N DCs.
+ if nfolder < m.Folder && ndc >= (m.Datacenter-m.Folder) {
+ f, err := folder.CreateFolder(ctx, fName)
+ if err != nil {
+ return err
+ }
+ folder = f
+ }
+
+ dc, err := folder.CreateDatacenter(ctx, dcName)
+ if err != nil {
+ return err
+ }
+
+ folders, err := dc.Folders(ctx)
+ if err != nil {
+ return err
+ }
+
+ if m.Pod > 0 {
+ for pod := 0; pod < m.Pod; pod++ {
+ _, _ = folders.DatastoreFolder.CreateStoragePod(ctx, m.fmtName(dcName+"_POD", pod))
+ }
+ }
+
+ if folder != root {
+ // Create sub-folders and use them to create any resources that follow
+ subs := []**object.Folder{&folders.DatastoreFolder, &folders.HostFolder, &folders.NetworkFolder, &folders.VmFolder}
+
+ for _, sub := range subs {
+ f, err := (*sub).CreateFolder(ctx, fName)
+ if err != nil {
+ return err
+ }
+
+ *sub = f
+ }
+
+ nfolder++
+ }
+
+ if m.Portgroup > 0 {
+ var spec types.DVSCreateSpec
+ spec.ConfigSpec = &types.VMwareDVSConfigSpec{}
+ spec.ConfigSpec.GetDVSConfigSpec().Name = m.fmtName("DVS", 0)
+
+ task, err := folders.NetworkFolder.CreateDVS(ctx, spec)
+ if err != nil {
+ return err
+ }
+
+ info, err := task.WaitForResult(ctx, nil)
+ if err != nil {
+ return err
+ }
+
+ dvs = object.NewDistributedVirtualSwitch(client, info.Result.(types.ManagedObjectReference))
+
+ for npg := 0; npg < m.Portgroup; npg++ {
+ name := m.fmtName(dcName+"_DVPG", npg)
+
+ task, err = dvs.AddPortgroup(ctx, []types.DVPortgroupConfigSpec{{Name: name}})
+ if err != nil {
+ return err
+ }
+
+ err = task.Wait(ctx)
+ if err != nil {
+ return err
+ }
+
+ // Use the 1st DVPG for the VMs eth0 backing
+ if npg == 0 {
+ // AddPortgroup_Task does not return the moid, so we look it up by name
+ net := Map.Get(folders.NetworkFolder.Reference()).(*Folder)
+ pg := Map.FindByName(name, net.ChildEntity)
+
+ vmnet, _ = object.NewDistributedVirtualPortgroup(client, pg.Reference()).EthernetCardBackingInfo(ctx)
+ }
+ }
+ }
+
+ for nhost := 0; nhost < m.Host; nhost++ {
+ name := m.fmtName(dcName+"_H", nhost)
+
+ host, err := addHost(name, func(spec types.HostConnectSpec) (*object.Task, error) {
+ return folders.HostFolder.AddStandaloneHost(ctx, spec, true, nil, nil)
+ })
+ if err != nil {
+ return err
+ }
+
+ addMachine(name, host, nil, folders)
+ }
+
+ for ncluster := 0; ncluster < m.Cluster; ncluster++ {
+ clusterName := m.fmtName(dcName+"_C", ncluster)
+
+ cluster, err := folders.HostFolder.CreateCluster(ctx, clusterName, types.ClusterConfigSpecEx{})
+ if err != nil {
+ return err
+ }
+
+ for nhost := 0; nhost < m.ClusterHost; nhost++ {
+ name := m.fmtName(clusterName+"_H", nhost)
+
+ _, err = addHost(name, func(spec types.HostConnectSpec) (*object.Task, error) {
+ return cluster.AddHost(ctx, spec, true, nil, nil)
+ })
+ if err != nil {
+ return err
+ }
+ }
+
+ pool, err := cluster.ResourcePool(ctx)
+ if err != nil {
+ return err
+ }
+
+ prefix := clusterName + "_RP"
+
+ addMachine(prefix+"0", nil, pool, folders)
+
+ for npool := 1; npool <= m.Pool; npool++ {
+ spec := NewResourceConfigSpec()
+
+ _, err = pool.Create(ctx, m.fmtName(prefix, npool), spec)
+ if err != nil {
+ return err
+ }
+ }
+
+ prefix = clusterName + "_APP"
+
+ for napp := 0; napp < m.App; napp++ {
+ rspec := NewResourceConfigSpec()
+ vspec := NewVAppConfigSpec()
+ name := m.fmtName(prefix, napp)
+
+ vapp, err := pool.CreateVApp(ctx, name, rspec, vspec, nil)
+ if err != nil {
+ return err
+ }
+
+ addMachine(name, nil, vapp.ResourcePool, folders)
+ }
+ }
+ }
+
+ if m.ServiceContent.RootFolder == esx.RootFolder.Reference() {
+ // ESX model
+ host := object.NewHostSystem(client, esx.HostSystem.Reference())
+ hosts = append(hosts, host)
+
+ dc := object.NewDatacenter(client, esx.Datacenter.Reference())
+ folders, err := dc.Folders(ctx)
+ if err != nil {
+ return err
+ }
+
+ addMachine(host.Reference().Value, host, nil, folders)
+ }
+
+ for i := 0; i < m.Datastore; i++ {
+ err := m.createLocalDatastore(m.fmtName("LocalDS_", i), hosts)
+ if err != nil {
+ return err
+ }
+ }
+
+ for _, createVM := range vms {
+ err := createVM()
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+var tempDir = func() (string, error) {
+ return ioutil.TempDir("", "govcsim-")
+}
+
+func (m *Model) createLocalDatastore(name string, hosts []*object.HostSystem) error {
+ ctx := context.Background()
+ dir, err := tempDir()
+ if err != nil {
+ return err
+ }
+
+ m.dirs = append(m.dirs, dir)
+
+ for _, host := range hosts {
+ dss, err := host.ConfigManager().DatastoreSystem(ctx)
+ if err != nil {
+ return err
+ }
+
+ _, err = dss.CreateLocalDatastore(ctx, name, dir)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// Remove cleans up items created by the Model, such as local datastore directories
+func (m *Model) Remove() {
+ for _, dir := range m.dirs {
+ _ = os.RemoveAll(dir)
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/option_manager.go b/vendor/github.com/vmware/govmomi/simulator/option_manager.go
new file mode 100644
index 00000000..4615882c
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/option_manager.go
@@ -0,0 +1,59 @@
+/*
+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 simulator
+
+import (
+ "strings"
+
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type OptionManager struct {
+ mo.OptionManager
+}
+
+func NewOptionManager(ref *types.ManagedObjectReference, setting []types.BaseOptionValue) object.Reference {
+ s := &OptionManager{}
+ if ref != nil {
+ s.Self = *ref
+ }
+ s.Setting = setting
+ return s
+}
+
+func (m *OptionManager) QueryOptions(req *types.QueryOptions) soap.HasFault {
+ body := &methods.QueryOptionsBody{}
+ res := &types.QueryOptionsResponse{}
+
+ for _, opt := range m.Setting {
+ if strings.HasPrefix(opt.GetOptionValue().Key, req.Name) {
+ res.Returnval = append(res.Returnval, opt)
+ }
+ }
+
+ if len(res.Returnval) == 0 {
+ body.Fault_ = Fault("", &types.InvalidName{Name: req.Name})
+ } else {
+ body.Res = res
+ }
+
+ return body
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/property_collector.go b/vendor/github.com/vmware/govmomi/simulator/property_collector.go
new file mode 100644
index 00000000..f2b8d0a7
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/property_collector.go
@@ -0,0 +1,539 @@
+/*
+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 simulator
+
+import (
+ "errors"
+ "log"
+ "path"
+ "reflect"
+ "strings"
+
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type PropertyCollector struct {
+ mo.PropertyCollector
+}
+
+func NewPropertyCollector(ref types.ManagedObjectReference) object.Reference {
+ s := &PropertyCollector{}
+ s.Self = ref
+ return s
+}
+
+var errMissingField = errors.New("missing field")
+var errEmptyField = errors.New("empty field")
+
+func getObject(ref types.ManagedObjectReference) (reflect.Value, bool) {
+ obj := Map.Get(ref)
+ if obj == nil {
+ return reflect.Value{}, false
+ }
+
+ rval := reflect.ValueOf(obj).Elem()
+ rtype := rval.Type()
+
+ // PropertyCollector is for Managed Object types only (package mo).
+ // If the registry object is not in the mo package, assume it is a wrapper
+ // type where the first field is an embedded mo type.
+ // We need to dig out the mo type for PropSet.All to work properly and
+ // for the case where the type has a field of the same name, for example:
+ // mo.ResourcePool.ResourcePool
+ for {
+ if path.Base(rtype.PkgPath()) != "mo" {
+ if rtype.Kind() != reflect.Struct || rtype.NumField() == 0 {
+ log.Printf("%#v does not have an embedded mo type", ref)
+ return reflect.Value{}, false
+ }
+ rval = rval.Field(0)
+ rtype = rval.Type()
+ } else {
+ break
+ }
+ }
+
+ return rval, true
+}
+
+func fieldValueInterface(f reflect.StructField, rval reflect.Value) interface{} {
+ if rval.Kind() == reflect.Ptr {
+ rval = rval.Elem()
+ }
+
+ pval := rval.Interface()
+
+ if rval.Kind() == reflect.Slice {
+ // Convert slice to types.ArrayOf*
+ switch v := pval.(type) {
+ case []string:
+ pval = &types.ArrayOfString{
+ String: v,
+ }
+ case []int32:
+ pval = &types.ArrayOfInt{
+ Int: v,
+ }
+ default:
+ kind := f.Type.Elem().Name()
+ // Remove govmomi interface prefix name
+ if strings.HasPrefix(kind, "Base") {
+ kind = kind[4:]
+ }
+ akind, _ := typeFunc("ArrayOf" + kind)
+ a := reflect.New(akind)
+ a.Elem().FieldByName(kind).Set(rval)
+ pval = a.Interface()
+ }
+ }
+
+ return pval
+}
+
+func fieldValue(rval reflect.Value, p string) (interface{}, error) {
+ var value interface{}
+
+ fields := strings.Split(p, ".")
+
+ for i, name := range fields {
+ kind := rval.Type().Kind()
+ if kind == reflect.Ptr || kind == reflect.Interface {
+ if rval.IsNil() {
+ continue
+ }
+ rval = rval.Elem()
+ }
+
+ x := ucFirst(name)
+ val := rval.FieldByName(x)
+ if !val.IsValid() {
+ return nil, errMissingField
+ }
+
+ if isEmpty(val) {
+ return nil, errEmptyField
+ }
+
+ if i == len(fields)-1 {
+ ftype, _ := rval.Type().FieldByName(x)
+ value = fieldValueInterface(ftype, val)
+ break
+ }
+
+ rval = val
+ }
+
+ return value, nil
+}
+
+func fieldRefs(f interface{}) []types.ManagedObjectReference {
+ switch fv := f.(type) {
+ case types.ManagedObjectReference:
+ return []types.ManagedObjectReference{fv}
+ case *types.ArrayOfManagedObjectReference:
+ return fv.ManagedObjectReference
+ case nil:
+ // empty field
+ }
+
+ return nil
+}
+
+func isEmpty(rval reflect.Value) bool {
+ switch rval.Kind() {
+ case reflect.Ptr:
+ return rval.IsNil()
+ case reflect.String, reflect.Slice:
+ return rval.Len() == 0
+ }
+
+ return false
+}
+
+func isTrue(v *bool) bool {
+ return v != nil && *v
+}
+
+func isFalse(v *bool) bool {
+ return v == nil || *v == false
+}
+
+func lcFirst(s string) string {
+ return strings.ToLower(s[:1]) + s[1:]
+}
+
+func ucFirst(s string) string {
+ return strings.ToUpper(s[:1]) + s[1:]
+}
+
+type retrieveResult struct {
+ *types.RetrieveResult
+ req *types.RetrievePropertiesEx
+ collected map[types.ManagedObjectReference]bool
+ specs map[string]*types.TraversalSpec
+}
+
+func (rr *retrieveResult) collectAll(rval reflect.Value, rtype reflect.Type, content *types.ObjectContent) {
+ for i := 0; i < rval.NumField(); i++ {
+ val := rval.Field(i)
+
+ f := rtype.Field(i)
+
+ if isEmpty(val) || f.Name == "Self" {
+ continue
+ }
+
+ if f.Anonymous {
+ // recurse into embedded field
+ rr.collectAll(val, f.Type, content)
+ continue
+ }
+
+ content.PropSet = append(content.PropSet, types.DynamicProperty{
+ Name: lcFirst(f.Name),
+ Val: fieldValueInterface(f, val),
+ })
+ }
+}
+
+func (rr *retrieveResult) collectFields(rval reflect.Value, fields []string, content *types.ObjectContent) {
+ seen := make(map[string]bool)
+
+ for i := range content.PropSet {
+ seen[content.PropSet[i].Name] = true // mark any already collected via embedded field
+ }
+
+ for _, name := range fields {
+ if seen[name] {
+ // rvc 'ls' includes the "name" property twice, then fails with no error message or stack trace
+ // in RbVmomi::VIM::ObjectContent.to_hash_uncached when it sees the 2nd "name" property.
+ continue
+ }
+ seen[name] = true
+
+ val, err := fieldValue(rval, name)
+ if err == nil {
+ prop := types.DynamicProperty{
+ Name: name,
+ Val: val,
+ }
+
+ content.PropSet = append(content.PropSet, prop)
+ continue
+ }
+
+ switch err {
+ case errEmptyField:
+ // ok
+ case errMissingField:
+ content.MissingSet = append(content.MissingSet, types.MissingProperty{
+ Path: name,
+ Fault: types.LocalizedMethodFault{Fault: &types.InvalidProperty{
+ Name: name,
+ }},
+ })
+ }
+ }
+}
+
+func (rr *retrieveResult) collect(ref types.ManagedObjectReference) {
+ if rr.collected[ref] {
+ return
+ }
+
+ content := types.ObjectContent{
+ Obj: ref,
+ }
+
+ rval, ok := getObject(ref)
+ if !ok {
+ // Possible if a test uses Map.Remove instead of Destroy_Task
+ log.Printf("object %s no longer exists", ref)
+ return
+ }
+
+ rtype := rval.Type()
+
+ for _, spec := range rr.req.SpecSet {
+ for _, p := range spec.PropSet {
+ if p.Type != ref.Type {
+ // e.g. ManagedEntity, ComputeResource
+ field, ok := rtype.FieldByName(p.Type)
+
+ if !(ok && field.Anonymous) {
+ continue
+ }
+ }
+
+ if isTrue(p.All) {
+ rr.collectAll(rval, rtype, &content)
+ continue
+ }
+
+ rr.collectFields(rval, p.PathSet, &content)
+ }
+ }
+
+ if len(content.PropSet) != 0 || len(content.MissingSet) != 0 {
+ rr.Objects = append(rr.Objects, content)
+ }
+
+ rr.collected[ref] = true
+}
+
+func (rr *retrieveResult) selectSet(obj reflect.Value, s []types.BaseSelectionSpec, refs *[]types.ManagedObjectReference) types.BaseMethodFault {
+ for _, ss := range s {
+ ts, ok := ss.(*types.TraversalSpec)
+
+ if ok {
+ if ts.Name != "" {
+ rr.specs[ts.Name] = ts
+ }
+ }
+ }
+
+ for _, ss := range s {
+ ts, ok := ss.(*types.TraversalSpec)
+ if !ok {
+ ts = rr.specs[ss.GetSelectionSpec().Name]
+ if ts == nil {
+ return &types.InvalidArgument{InvalidProperty: "undefined TraversalSpec name"}
+ }
+ }
+
+ f, _ := fieldValue(obj, ts.Path)
+
+ for _, ref := range fieldRefs(f) {
+ if isFalse(ts.Skip) {
+ *refs = append(*refs, ref)
+ }
+
+ rval, ok := getObject(ref)
+ if ok {
+ if err := rr.selectSet(rval, ts.SelectSet, refs); err != nil {
+ return err
+ }
+ }
+ }
+ }
+
+ return nil
+}
+
+func (pc *PropertyCollector) collect(r *types.RetrievePropertiesEx) (*types.RetrieveResult, types.BaseMethodFault) {
+ var refs []types.ManagedObjectReference
+
+ rr := &retrieveResult{
+ RetrieveResult: &types.RetrieveResult{},
+ req: r,
+ collected: make(map[types.ManagedObjectReference]bool),
+ specs: make(map[string]*types.TraversalSpec),
+ }
+
+ // Select object references
+ for _, spec := range r.SpecSet {
+ for _, o := range spec.ObjectSet {
+ rval, ok := getObject(o.Obj)
+
+ if !ok {
+ if isFalse(spec.ReportMissingObjectsInResults) {
+ return nil, &types.ManagedObjectNotFound{Obj: o.Obj}
+ }
+ continue
+ }
+
+ if o.SelectSet == nil || isFalse(o.Skip) {
+ refs = append(refs, o.Obj)
+ }
+
+ if err := rr.selectSet(rval, o.SelectSet, &refs); err != nil {
+ return nil, err
+ }
+ }
+ }
+
+ for _, ref := range refs {
+ rr.collect(ref)
+ }
+
+ return rr.RetrieveResult, nil
+}
+
+func (pc *PropertyCollector) CreateFilter(c *types.CreateFilter) soap.HasFault {
+ body := &methods.CreateFilterBody{}
+
+ filter := &PropertyFilter{pc: pc}
+ filter.PartialUpdates = c.PartialUpdates
+ filter.Spec = c.Spec
+
+ pc.Filter = append(pc.Filter, Map.Put(filter).Reference())
+
+ body.Res = &types.CreateFilterResponse{
+ Returnval: filter.Self,
+ }
+
+ return body
+}
+
+func (pc *PropertyCollector) CreatePropertyCollector(c *types.CreatePropertyCollector) soap.HasFault {
+ body := &methods.CreatePropertyCollectorBody{}
+
+ cpc := &PropertyCollector{}
+
+ body.Res = &types.CreatePropertyCollectorResponse{
+ Returnval: Map.Put(cpc).Reference(),
+ }
+
+ return body
+}
+
+func (pc *PropertyCollector) DestroyPropertyCollector(c *types.DestroyPropertyCollector) soap.HasFault {
+ body := &methods.DestroyPropertyCollectorBody{}
+
+ for _, ref := range pc.Filter {
+ filter := Map.Get(ref).(*PropertyFilter)
+ filter.DestroyPropertyFilter(&types.DestroyPropertyFilter{This: ref})
+ }
+
+ Map.Remove(c.This)
+
+ body.Res = &types.DestroyPropertyCollectorResponse{}
+
+ return body
+}
+
+func (pc *PropertyCollector) RetrievePropertiesEx(r *types.RetrievePropertiesEx) soap.HasFault {
+ body := &methods.RetrievePropertiesExBody{}
+
+ res, fault := pc.collect(r)
+
+ if fault != nil {
+ body.Fault_ = Fault("", fault)
+ } else {
+ body.Res = &types.RetrievePropertiesExResponse{
+ Returnval: res,
+ }
+ }
+
+ return body
+}
+
+// RetrieveProperties is deprecated, but govmomi is still using it at the moment.
+func (pc *PropertyCollector) RetrieveProperties(r *types.RetrieveProperties) soap.HasFault {
+ body := &methods.RetrievePropertiesBody{}
+
+ res := pc.RetrievePropertiesEx(&types.RetrievePropertiesEx{
+ This: r.This,
+ SpecSet: r.SpecSet,
+ })
+
+ if res.Fault() != nil {
+ body.Fault_ = res.Fault()
+ } else {
+ body.Res = &types.RetrievePropertiesResponse{
+ Returnval: res.(*methods.RetrievePropertiesExBody).Res.Returnval.Objects,
+ }
+ }
+
+ return body
+}
+
+func (pc *PropertyCollector) CancelWaitForUpdates(r *types.CancelWaitForUpdates) soap.HasFault {
+ return &methods.CancelWaitForUpdatesBody{Res: new(types.CancelWaitForUpdatesResponse)}
+}
+
+func (pc *PropertyCollector) WaitForUpdatesEx(r *types.WaitForUpdatesEx) soap.HasFault {
+ body := &methods.WaitForUpdatesExBody{}
+
+ // At the moment we need to support Task completion. Handlers can simply set the Task
+ // state before returning and the non-incremental update is enough for the client.
+ // We can wait for incremental updates to simulate timeouts, etc.
+ if r.Version != "" {
+ body.Fault_ = Fault("incremental updates not supported yet", &types.NotSupported{})
+ return body
+ }
+
+ update := &types.UpdateSet{
+ Version: "-",
+ }
+
+ for _, ref := range pc.Filter {
+ filter := Map.Get(ref).(*PropertyFilter)
+
+ r := &types.RetrievePropertiesEx{}
+ r.SpecSet = append(r.SpecSet, filter.Spec)
+
+ res, fault := pc.collect(r)
+ if fault != nil {
+ body.Fault_ = Fault("", fault)
+ return body
+ }
+
+ fu := types.PropertyFilterUpdate{
+ Filter: ref,
+ }
+
+ for _, o := range res.Objects {
+ ou := types.ObjectUpdate{
+ Obj: o.Obj,
+ Kind: types.ObjectUpdateKindEnter,
+ }
+
+ for _, p := range o.PropSet {
+ ou.ChangeSet = append(ou.ChangeSet, types.PropertyChange{
+ Op: types.PropertyChangeOpAssign,
+ Name: p.Name,
+ Val: p.Val,
+ })
+ }
+
+ fu.ObjectSet = append(fu.ObjectSet, ou)
+ }
+
+ update.FilterSet = append(update.FilterSet, fu)
+ }
+
+ body.Res = &types.WaitForUpdatesExResponse{
+ Returnval: update,
+ }
+
+ return body
+}
+
+// WaitForUpdates is deprecated, but pyvmomi is still using it at the moment.
+func (pc *PropertyCollector) WaitForUpdates(r *types.WaitForUpdates) soap.HasFault {
+ body := &methods.WaitForUpdatesBody{}
+
+ res := pc.WaitForUpdatesEx(&types.WaitForUpdatesEx{
+ This: r.This,
+ Version: r.Version,
+ })
+
+ if res.Fault() != nil {
+ body.Fault_ = res.Fault()
+ } else {
+ body.Res = &types.WaitForUpdatesResponse{
+ Returnval: *res.(*methods.WaitForUpdatesExBody).Res.Returnval,
+ }
+ }
+
+ return body
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/property_filter.go b/vendor/github.com/vmware/govmomi/simulator/property_filter.go
new file mode 100644
index 00000000..0d7d9a38
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/property_filter.go
@@ -0,0 +1,42 @@
+/*
+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 simulator
+
+import (
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type PropertyFilter struct {
+ mo.PropertyFilter
+
+ pc *PropertyCollector
+}
+
+func (f *PropertyFilter) DestroyPropertyFilter(c *types.DestroyPropertyFilter) soap.HasFault {
+ body := &methods.DestroyPropertyFilterBody{}
+
+ f.pc.Filter = RemoveReference(c.This, f.pc.Filter)
+
+ Map.Remove(c.This)
+
+ body.Res = &types.DestroyPropertyFilterResponse{}
+
+ return body
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/registry.go b/vendor/github.com/vmware/govmomi/simulator/registry.go
new file mode 100644
index 00000000..8384b7a6
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/registry.go
@@ -0,0 +1,309 @@
+/*
+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 simulator
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+ "sync"
+
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+// Map is the default Registry instance.
+var Map = NewRegistry()
+
+// RegisterObject interface supports callbacks when objects are added and removed from the Registry
+type RegisterObject interface {
+ mo.Reference
+ PutObject(mo.Reference)
+ RemoveObject(types.ManagedObjectReference)
+}
+
+// Registry manages a map of mo.Reference objects
+type Registry struct {
+ m sync.Mutex
+ objects map[types.ManagedObjectReference]mo.Reference
+ handlers map[types.ManagedObjectReference]RegisterObject
+ counter int
+}
+
+// NewRegistry creates a new instances of Registry
+func NewRegistry() *Registry {
+ r := &Registry{
+ objects: make(map[types.ManagedObjectReference]mo.Reference),
+ handlers: make(map[types.ManagedObjectReference]RegisterObject),
+ }
+
+ return r
+}
+
+// TypeName returns the type of the given object.
+func TypeName(item mo.Reference) string {
+ return reflect.TypeOf(item).Elem().Name()
+}
+
+// newReference returns a new MOR, where Type defaults to type of the given item
+// and Value defaults to a unique id for the given type.
+func (r *Registry) newReference(item mo.Reference) types.ManagedObjectReference {
+ ref := item.Reference()
+
+ if ref.Type == "" {
+ ref.Type = TypeName(item)
+ }
+
+ if ref.Value == "" {
+ r.counter++
+ ref.Value = fmt.Sprintf("%s-%d", strings.ToLower(ref.Type), r.counter)
+ }
+
+ return ref
+}
+
+// AddHandler adds a RegisterObject handler to the Registry.
+func (r *Registry) AddHandler(h RegisterObject) {
+ r.handlers[h.Reference()] = h
+}
+
+// NewEntity sets Entity().Self with a new, unique Value.
+// Useful for creating object instances from templates.
+func (r *Registry) NewEntity(item mo.Entity) mo.Entity {
+ e := item.Entity()
+ e.Self.Value = ""
+ e.Self = r.newReference(item)
+ return item
+}
+
+// PutEntity sets item.Parent to that of parent.Self before adding item to the Registry.
+func (r *Registry) PutEntity(parent mo.Entity, item mo.Entity) mo.Entity {
+ e := item.Entity()
+
+ if parent != nil {
+ e.Parent = &parent.Entity().Self
+ }
+
+ r.Put(item)
+
+ return item
+}
+
+// Get returns the object for the given reference.
+func (r *Registry) Get(ref types.ManagedObjectReference) mo.Reference {
+ r.m.Lock()
+ defer r.m.Unlock()
+
+ return r.objects[ref]
+}
+
+// Any returns the first instance of entity type specified by kind.
+func (r *Registry) Any(kind string) mo.Entity {
+ r.m.Lock()
+ defer r.m.Unlock()
+
+ for ref, val := range r.objects {
+ if ref.Type == kind {
+ return val.(mo.Entity)
+ }
+ }
+
+ return nil
+}
+
+// Put adds a new object to Registry, generating a ManagedObjectReference if not already set.
+func (r *Registry) Put(item mo.Reference) mo.Reference {
+ r.m.Lock()
+ defer r.m.Unlock()
+
+ ref := item.Reference()
+ if ref.Type == "" || ref.Value == "" {
+ ref = r.newReference(item)
+ // mo.Reference() returns a value, not a pointer so use reflect to set the Self field
+ reflect.ValueOf(item).Elem().FieldByName("Self").Set(reflect.ValueOf(ref))
+ }
+
+ r.objects[ref] = item
+
+ for _, h := range r.handlers {
+ h.PutObject(item)
+ }
+
+ return item
+}
+
+// Remove removes an object from the Registry.
+func (r *Registry) Remove(item types.ManagedObjectReference) {
+ r.m.Lock()
+ defer r.m.Unlock()
+
+ for _, h := range r.handlers {
+ h.RemoveObject(item)
+ }
+
+ delete(r.objects, item)
+ delete(r.handlers, item)
+}
+
+// getEntityParent traverses up the inventory and returns the first object of type kind.
+// If no object of type kind is found, the method will panic when it reaches the
+// inventory root Folder where the Parent field is nil.
+func (r *Registry) getEntityParent(item mo.Entity, kind string) mo.Entity {
+ for {
+ parent := item.Entity().Parent
+
+ item = r.Get(*parent).(mo.Entity)
+
+ if item.Reference().Type == kind {
+ return item
+ }
+ }
+}
+
+// getEntityDatacenter returns the Datacenter containing the given item
+func (r *Registry) getEntityDatacenter(item mo.Entity) *mo.Datacenter {
+ return r.getEntityParent(item, "Datacenter").(*mo.Datacenter)
+}
+
+func (r *Registry) getEntityFolder(item mo.Entity, kind string) *Folder {
+ dc := Map.getEntityDatacenter(item)
+
+ var ref types.ManagedObjectReference
+
+ switch kind {
+ case "datastore":
+ ref = dc.DatastoreFolder
+ }
+
+ folder := r.Get(ref).(*Folder)
+
+ // If Model was created with Folder option, use that Folder; else use top-level folder
+ for _, child := range folder.ChildEntity {
+ if child.Type == "Folder" {
+ folder = Map.Get(child).(*Folder)
+ break
+ }
+ }
+
+ return folder
+}
+
+// getEntityComputeResource returns the ComputeResource parent for the given item.
+// A ResourcePool for example may have N Parents of type ResourcePool, but the top
+// most Parent pool is always a ComputeResource child.
+func (r *Registry) getEntityComputeResource(item mo.Entity) mo.Entity {
+ for {
+ parent := item.Entity().Parent
+
+ item = r.Get(*parent).(mo.Entity)
+
+ switch item.Reference().Type {
+ case "ComputeResource":
+ return item
+ case "ClusterComputeResource":
+ return item
+ }
+ }
+}
+
+// FindByName returns the first mo.Entity of the given refs whose Name field is equal to the given name.
+// If there is no match, nil is returned.
+// This method is useful for cases where objects are required to have a unique name, such as Datastore with
+// a HostStorageSystem or HostSystem within a ClusterComputeResource.
+func (r *Registry) FindByName(name string, refs []types.ManagedObjectReference) mo.Entity {
+ for _, ref := range refs {
+ if e, ok := r.Get(ref).(mo.Entity); ok {
+ if name == e.Entity().Name {
+ return e
+ }
+ }
+ }
+
+ return nil
+}
+
+// FindReference returns the 1st match found in refs, or nil if not found.
+func FindReference(refs []types.ManagedObjectReference, match ...types.ManagedObjectReference) *types.ManagedObjectReference {
+ for _, ref := range refs {
+ for _, m := range match {
+ if ref == m {
+ return &ref
+ }
+ }
+ }
+
+ return nil
+}
+
+// RemoveReference returns a slice with ref removed from refs
+func RemoveReference(ref types.ManagedObjectReference, refs []types.ManagedObjectReference) []types.ManagedObjectReference {
+ var result []types.ManagedObjectReference
+
+ for i, r := range refs {
+ if r == ref {
+ result = append(result, refs[i+1:]...)
+ break
+ }
+
+ result = append(result, r)
+ }
+
+ return result
+}
+
+// AddReference returns a slice with ref appended if not already in refs.
+func AddReference(ref types.ManagedObjectReference, refs []types.ManagedObjectReference) []types.ManagedObjectReference {
+ if FindReference(refs, ref) == nil {
+ return append(refs, ref)
+ }
+
+ return refs
+}
+
+func (r *Registry) content() types.ServiceContent {
+ return r.Get(serviceInstance).(*ServiceInstance).Content
+}
+
+// IsESX returns true if this Registry maps an ESX model
+func (r *Registry) IsESX() bool {
+ return r.content().About.ApiType == "HostAgent"
+}
+
+// IsVPX returns true if this Registry maps a VPX model
+func (r *Registry) IsVPX() bool {
+ return !r.IsESX()
+}
+
+// SearchIndex returns the SearchIndex singleton
+func (r *Registry) SearchIndex() *SearchIndex {
+ return r.Get(r.content().SearchIndex.Reference()).(*SearchIndex)
+}
+
+// FileManager returns the FileManager singleton
+func (r *Registry) FileManager() *FileManager {
+ return r.Get(r.content().FileManager.Reference()).(*FileManager)
+}
+
+// VirtualDiskManager returns the VirtualDiskManager singleton
+func (r *Registry) VirtualDiskManager() *VirtualDiskManager {
+ return r.Get(r.content().VirtualDiskManager.Reference()).(*VirtualDiskManager)
+}
+
+// ViewManager returns the ViewManager singleton
+func (r *Registry) ViewManager() *ViewManager {
+ return r.Get(r.content().ViewManager.Reference()).(*ViewManager)
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/resource_pool.go b/vendor/github.com/vmware/govmomi/simulator/resource_pool.go
new file mode 100644
index 00000000..ed8de91d
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/resource_pool.go
@@ -0,0 +1,238 @@
+/*
+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 simulator
+
+import (
+ "strings"
+
+ "github.com/vmware/govmomi/simulator/esx"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type ResourcePool struct {
+ mo.ResourcePool
+}
+
+func NewResourcePool() *ResourcePool {
+ pool := &ResourcePool{
+ ResourcePool: esx.ResourcePool,
+ }
+
+ if Map.IsVPX() {
+ pool.DisabledMethod = nil // Enable VApp methods for VC
+ }
+
+ return pool
+}
+
+func NewResourceConfigSpec() types.ResourceConfigSpec {
+ spec := types.ResourceConfigSpec{
+ CpuAllocation: new(types.ResourceAllocationInfo),
+ MemoryAllocation: new(types.ResourceAllocationInfo),
+ }
+
+ return spec
+}
+
+func (p *ResourcePool) setDefaultConfig(c types.BaseResourceAllocationInfo) {
+ info := c.GetResourceAllocationInfo()
+
+ if info.Shares == nil {
+ info.Shares = new(types.SharesInfo)
+ }
+
+ if info.Shares.Level == "" {
+ info.Shares.Level = types.SharesLevelNormal
+ }
+
+ if info.ExpandableReservation == nil {
+ info.ExpandableReservation = types.NewBool(false)
+ }
+}
+
+func (p *ResourcePool) createChild(name string, spec types.ResourceConfigSpec) (*ResourcePool, *soap.Fault) {
+ if e := Map.FindByName(name, p.ResourcePool.ResourcePool); e != nil {
+ return nil, Fault("", &types.DuplicateName{
+ Name: e.Entity().Name,
+ Object: e.Reference(),
+ })
+ }
+
+ child := NewResourcePool()
+
+ child.Name = name
+ child.Owner = p.Owner
+ child.Summary.GetResourcePoolSummary().Name = name
+ child.Config.CpuAllocation = spec.CpuAllocation
+ child.Config.MemoryAllocation = spec.MemoryAllocation
+ child.Config.Entity = spec.Entity
+
+ p.setDefaultConfig(child.Config.CpuAllocation)
+ p.setDefaultConfig(child.Config.MemoryAllocation)
+
+ return child, nil
+}
+
+func (p *ResourcePool) CreateResourcePool(c *types.CreateResourcePool) soap.HasFault {
+ body := &methods.CreateResourcePoolBody{}
+
+ child, err := p.createChild(c.Name, c.Spec)
+ if err != nil {
+ body.Fault_ = err
+ return body
+ }
+
+ Map.PutEntity(p, Map.NewEntity(child))
+
+ p.ResourcePool.ResourcePool = append(p.ResourcePool.ResourcePool, child.Reference())
+
+ body.Res = &types.CreateResourcePoolResponse{
+ Returnval: child.Reference(),
+ }
+
+ return body
+}
+
+type VirtualApp struct {
+ mo.VirtualApp
+}
+
+func NewVAppConfigSpec() types.VAppConfigSpec {
+ spec := types.VAppConfigSpec{
+ Annotation: "vcsim",
+ VmConfigSpec: types.VmConfigSpec{
+ Product: []types.VAppProductSpec{
+ {
+ Info: &types.VAppProductInfo{
+ Name: "vcsim",
+ Vendor: "VMware",
+ VendorUrl: "http://www.vmware.com/",
+ Version: "0.1",
+ },
+ ArrayUpdateSpec: types.ArrayUpdateSpec{
+ Operation: types.ArrayUpdateOperationAdd,
+ },
+ },
+ },
+ },
+ }
+
+ return spec
+}
+
+func (p *ResourcePool) CreateVApp(req *types.CreateVApp) soap.HasFault {
+ body := &methods.CreateVAppBody{}
+
+ pool, err := p.createChild(req.Name, req.ResSpec)
+ if err != nil {
+ body.Fault_ = err
+ return body
+ }
+
+ child := &VirtualApp{}
+ child.ResourcePool = pool.ResourcePool
+ child.Self.Type = "VirtualApp"
+ child.ParentFolder = req.VmFolder
+
+ if child.ParentFolder == nil {
+ folder := Map.getEntityDatacenter(p).VmFolder
+ child.ParentFolder = &folder
+ }
+
+ child.VAppConfig = &types.VAppConfigInfo{
+ VmConfigInfo: types.VmConfigInfo{},
+ Annotation: req.ConfigSpec.Annotation,
+ }
+
+ for _, product := range req.ConfigSpec.Product {
+ child.VAppConfig.Product = append(child.VAppConfig.Product, *product.Info)
+ }
+
+ Map.PutEntity(p, Map.NewEntity(child))
+
+ p.ResourcePool.ResourcePool = append(p.ResourcePool.ResourcePool, child.Reference())
+
+ body.Res = &types.CreateVAppResponse{
+ Returnval: child.Reference(),
+ }
+
+ return body
+}
+
+func (a *VirtualApp) CreateChildVMTask(req *types.CreateChildVM_Task) soap.HasFault {
+ body := &methods.CreateChildVM_TaskBody{}
+
+ folder := Map.Get(*a.ParentFolder).(*Folder)
+
+ res := folder.CreateVMTask(&types.CreateVM_Task{
+ This: folder.Self,
+ Config: req.Config,
+ Host: req.Host,
+ Pool: req.This,
+ })
+
+ body.Res = &types.CreateChildVM_TaskResponse{
+ Returnval: res.(*methods.CreateVM_TaskBody).Res.Returnval,
+ }
+
+ return body
+}
+
+func (a *VirtualApp) DestroyTask(req *types.Destroy_Task) soap.HasFault {
+ return (&ResourcePool{ResourcePool: a.ResourcePool}).DestroyTask(req)
+}
+
+func (p *ResourcePool) DestroyTask(req *types.Destroy_Task) soap.HasFault {
+ task := CreateTask(p, "destroy", func(t *Task) (types.AnyType, types.BaseMethodFault) {
+ if strings.HasSuffix(p.Parent.Type, "ComputeResource") {
+ // Can't destroy the root pool
+ return nil, &types.InvalidArgument{}
+ }
+
+ pp := Map.Get(*p.Parent).(*ResourcePool)
+
+ parent := &pp.ResourcePool
+ // Remove child reference from rp
+ parent.ResourcePool = RemoveReference(req.This, parent.ResourcePool)
+
+ // The grandchildren become children of the parent (rp)
+ parent.ResourcePool = append(parent.ResourcePool, p.ResourcePool.ResourcePool...)
+
+ // And VMs move to the parent
+ vms := p.ResourcePool.Vm
+ for _, vm := range vms {
+ Map.Get(vm).(*VirtualMachine).ResourcePool = &parent.Self
+ }
+
+ parent.Vm = append(parent.Vm, vms...)
+
+ Map.Remove(req.This)
+
+ return nil, nil
+ })
+
+ task.Run()
+
+ return &methods.Destroy_TaskBody{
+ Res: &types.Destroy_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/search_index.go b/vendor/github.com/vmware/govmomi/simulator/search_index.go
new file mode 100644
index 00000000..c56dff2c
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/search_index.go
@@ -0,0 +1,155 @@
+/*
+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 simulator
+
+import (
+ "strings"
+
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type SearchIndex struct {
+ mo.SearchIndex
+}
+
+func NewSearchIndex(ref types.ManagedObjectReference) object.Reference {
+ m := &SearchIndex{}
+ m.Self = ref
+ return m
+}
+
+func (s *SearchIndex) FindByDatastorePath(r *types.FindByDatastorePath) soap.HasFault {
+ res := &methods.FindByDatastorePathBody{Res: new(types.FindByDatastorePathResponse)}
+
+ for ref, obj := range Map.objects {
+ vm, ok := obj.(*VirtualMachine)
+ if !ok {
+ continue
+ }
+
+ if vm.Config.Files.VmPathName == r.Path {
+ res.Res.Returnval = &ref
+ break
+ }
+ }
+
+ return res
+}
+
+func (s *SearchIndex) FindByInventoryPath(req *types.FindByInventoryPath) soap.HasFault {
+ body := &methods.FindByInventoryPathBody{Res: new(types.FindByInventoryPathResponse)}
+
+ path := strings.Split(req.InventoryPath, "/")
+ if len(path) <= 1 {
+ return body
+ }
+
+ root := Map.content().RootFolder
+ o := &root
+
+ for _, name := range path[1:] {
+ f := s.FindChild(&types.FindChild{Entity: *o, Name: name})
+
+ o = f.(*methods.FindChildBody).Res.Returnval
+ if o == nil {
+ break
+ }
+ }
+
+ body.Res.Returnval = o
+
+ return body
+}
+
+func (s *SearchIndex) FindChild(req *types.FindChild) soap.HasFault {
+ body := &methods.FindChildBody{}
+
+ obj := Map.Get(req.Entity)
+
+ if obj == nil {
+ body.Fault_ = Fault("", &types.ManagedObjectNotFound{Obj: req.Entity})
+ return body
+ }
+
+ body.Res = new(types.FindChildResponse)
+
+ var children []types.ManagedObjectReference
+
+ switch e := obj.(type) {
+ case *mo.Datacenter:
+ children = []types.ManagedObjectReference{e.VmFolder, e.HostFolder, e.DatastoreFolder, e.NetworkFolder}
+ case *Folder:
+ children = e.ChildEntity
+ case *mo.ComputeResource:
+ children = e.Host
+ children = append(children, *e.ResourcePool)
+ case *ClusterComputeResource:
+ children = e.Host
+ children = append(children, *e.ResourcePool)
+ case *ResourcePool:
+ children = e.ResourcePool.ResourcePool
+ children = append(children, e.Vm...)
+ case *VirtualApp:
+ children = e.ResourcePool.ResourcePool
+ children = append(children, e.Vm...)
+ }
+
+ match := Map.FindByName(req.Name, children)
+
+ if match != nil {
+ ref := match.Reference()
+ body.Res.Returnval = &ref
+ }
+
+ return body
+}
+
+func (s *SearchIndex) FindByUuid(req *types.FindByUuid) soap.HasFault {
+ body := &methods.FindByUuidBody{Res: new(types.FindByUuidResponse)}
+
+ if req.VmSearch {
+ // Find Virtual Machine using UUID
+ for ref, obj := range Map.objects {
+ vm, ok := obj.(*VirtualMachine)
+ if !ok {
+ continue
+ }
+ if vm.Config.Uuid == req.Uuid {
+ body.Res.Returnval = &ref
+ break
+ }
+ }
+ } else {
+ // Find Host System using UUID
+ for ref, obj := range Map.objects {
+ host, ok := obj.(*HostSystem)
+ if !ok {
+ continue
+ }
+ if host.Summary.Hardware.Uuid == req.Uuid {
+ body.Res.Returnval = &ref
+ break
+ }
+ }
+ }
+
+ return body
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/service_instance.go b/vendor/github.com/vmware/govmomi/simulator/service_instance.go
new file mode 100644
index 00000000..ca46c490
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/service_instance.go
@@ -0,0 +1,93 @@
+/*
+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 simulator
+
+import (
+ "time"
+
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/simulator/vpx"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type ServiceInstance struct {
+ mo.ServiceInstance
+}
+
+var serviceInstance = types.ManagedObjectReference{
+ Type: "ServiceInstance",
+ Value: "ServiceInstance",
+}
+
+func NewServiceInstance(content types.ServiceContent, folder mo.Folder) *ServiceInstance {
+ Map = NewRegistry()
+
+ s := &ServiceInstance{}
+
+ s.Self = serviceInstance
+ s.Content = content
+
+ Map.Put(s)
+
+ f := &Folder{Folder: folder}
+ Map.Put(f)
+
+ var setting []types.BaseOptionValue
+
+ if content.About.ApiType == "HostAgent" {
+ CreateDefaultESX(f)
+ } else {
+ setting = vpx.Setting
+ }
+
+ objects := []object.Reference{
+ NewSessionManager(*s.Content.SessionManager),
+ NewPropertyCollector(s.Content.PropertyCollector),
+ NewFileManager(*s.Content.FileManager),
+ NewVirtualDiskManager(*s.Content.VirtualDiskManager),
+ NewLicenseManager(*s.Content.LicenseManager),
+ NewSearchIndex(*s.Content.SearchIndex),
+ NewViewManager(*s.Content.ViewManager),
+ NewTaskManager(*s.Content.TaskManager),
+ NewOptionManager(s.Content.Setting, setting),
+ }
+
+ for _, o := range objects {
+ Map.Put(o)
+ }
+
+ return s
+}
+
+func (s *ServiceInstance) RetrieveServiceContent(*types.RetrieveServiceContent) soap.HasFault {
+ return &methods.RetrieveServiceContentBody{
+ Res: &types.RetrieveServiceContentResponse{
+ Returnval: s.Content,
+ },
+ }
+}
+
+func (*ServiceInstance) CurrentTime(*types.CurrentTime) soap.HasFault {
+ return &methods.CurrentTimeBody{
+ Res: &types.CurrentTimeResponse{
+ Returnval: time.Now(),
+ },
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/session_manager.go b/vendor/github.com/vmware/govmomi/simulator/session_manager.go
new file mode 100644
index 00000000..d05d5f5d
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/session_manager.go
@@ -0,0 +1,83 @@
+/*
+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 simulator
+
+import (
+ "time"
+
+ "github.com/google/uuid"
+
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/session"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type SessionManager struct {
+ mo.SessionManager
+
+ ServiceHostName string
+}
+
+func NewSessionManager(ref types.ManagedObjectReference) object.Reference {
+ s := &SessionManager{}
+ s.Self = ref
+ return s
+}
+
+func (s *SessionManager) Login(login *types.Login) soap.HasFault {
+ body := &methods.LoginBody{}
+
+ if login.Locale == "" {
+ login.Locale = session.Locale
+ }
+
+ if login.UserName == "" || login.Password == "" {
+ body.Fault_ = Fault("Login failure", &types.InvalidLogin{})
+ } else {
+ body.Res = &types.LoginResponse{
+ Returnval: types.UserSession{
+ Key: uuid.New().String(),
+ UserName: login.UserName,
+ FullName: login.UserName,
+ LoginTime: time.Now(),
+ LastActiveTime: time.Now(),
+ Locale: login.Locale,
+ MessageLocale: login.Locale,
+ },
+ }
+ }
+
+ return body
+}
+
+func (s *SessionManager) Logout(*types.Logout) soap.HasFault {
+ return &methods.LogoutBody{}
+}
+
+func (s *SessionManager) AcquireGenericServiceTicket(ticket *types.AcquireGenericServiceTicket) soap.HasFault {
+ return &methods.AcquireGenericServiceTicketBody{
+ Res: &types.AcquireGenericServiceTicketResponse{
+ Returnval: types.SessionManagerGenericServiceTicket{
+ Id: uuid.New().String(),
+ HostName: s.ServiceHostName,
+ },
+ },
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/simulator.go b/vendor/github.com/vmware/govmomi/simulator/simulator.go
new file mode 100644
index 00000000..d8878098
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/simulator.go
@@ -0,0 +1,526 @@
+/*
+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 simulator
+
+import (
+ "bytes"
+ "context"
+ "crypto/tls"
+ "crypto/x509"
+ "encoding/json"
+ "encoding/pem"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "os"
+ "path"
+ "reflect"
+ "sort"
+ "strings"
+
+ "github.com/vmware/govmomi/find"
+ "github.com/vmware/govmomi/object"
+ "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/vim25/xml"
+)
+
+// Trace when set to true, writes SOAP traffic to stderr
+var Trace = false
+
+// Method encapsulates a decoded SOAP client request
+type Method struct {
+ Name string
+ This types.ManagedObjectReference
+ Body types.AnyType
+}
+
+// Service decodes incoming requests and dispatches to a Handler
+type Service struct {
+ client *vim25.Client
+
+ readAll func(io.Reader) ([]byte, error)
+
+ TLS *tls.Config
+}
+
+// Server provides a simulator Service over HTTP
+type Server struct {
+ *httptest.Server
+ URL *url.URL
+
+ caFile string
+}
+
+// New returns an initialized simulator Service instance
+func New(instance *ServiceInstance) *Service {
+ s := &Service{
+ readAll: ioutil.ReadAll,
+ }
+
+ s.client, _ = vim25.NewClient(context.Background(), s)
+
+ return s
+}
+
+type serverFaultBody struct {
+ Reason *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *serverFaultBody) Fault() *soap.Fault { return b.Reason }
+
+func serverFault(msg string) soap.HasFault {
+ return &serverFaultBody{Reason: Fault(msg, &types.InvalidRequest{})}
+}
+
+// Fault wraps the given message and fault in a soap.Fault
+func Fault(msg string, fault types.BaseMethodFault) *soap.Fault {
+ f := &soap.Fault{
+ Code: "ServerFaultCode",
+ String: msg,
+ }
+
+ f.Detail.Fault = fault
+
+ return f
+}
+
+func (s *Service) call(method *Method) soap.HasFault {
+ handler := Map.Get(method.This)
+
+ if handler == nil {
+ msg := fmt.Sprintf("managed object not found: %s", method.This)
+ log.Print(msg)
+ fault := &types.ManagedObjectNotFound{Obj: method.This}
+ return &serverFaultBody{Reason: Fault(msg, fault)}
+ }
+
+ name := method.Name
+
+ if strings.HasSuffix(name, vTaskSuffix) {
+ // Make golint happy renaming "Foo_Task" -> "FooTask"
+ name = name[:len(name)-len(vTaskSuffix)] + sTaskSuffix
+ }
+
+ m := reflect.ValueOf(handler).MethodByName(name)
+ if !m.IsValid() {
+ msg := fmt.Sprintf("%s does not implement: %s", method.This, method.Name)
+ log.Print(msg)
+ fault := &types.MethodNotFound{Receiver: method.This, Method: method.Name}
+ return &serverFaultBody{Reason: Fault(msg, fault)}
+ }
+
+ if e, ok := handler.(mo.Entity); ok {
+ for _, dm := range e.Entity().DisabledMethod {
+ if name == dm {
+ msg := fmt.Sprintf("%s method is disabled: %s", method.This, method.Name)
+ fault := &types.MethodDisabled{}
+ return &serverFaultBody{Reason: Fault(msg, fault)}
+ }
+ }
+ }
+
+ res := m.Call([]reflect.Value{reflect.ValueOf(method.Body)})
+
+ return res[0].Interface().(soap.HasFault)
+}
+
+// RoundTrip implements the soap.RoundTripper interface in process.
+// Rather than encode/decode SOAP over HTTP, this implementation uses reflection.
+func (s *Service) RoundTrip(ctx context.Context, request, response soap.HasFault) error {
+ field := func(r soap.HasFault, name string) reflect.Value {
+ return reflect.ValueOf(r).Elem().FieldByName(name)
+ }
+
+ // Every struct passed to soap.RoundTrip has "Req" and "Res" fields
+ req := field(request, "Req")
+
+ // Every request has a "This" field.
+ this := req.Elem().FieldByName("This")
+
+ method := &Method{
+ Name: req.Elem().Type().Name(),
+ This: this.Interface().(types.ManagedObjectReference),
+ Body: req.Interface(),
+ }
+
+ res := s.call(method)
+
+ if err := res.Fault(); err != nil {
+ return soap.WrapSoapFault(err)
+ }
+
+ field(response, "Res").Set(field(res, "Res"))
+
+ return nil
+}
+
+// soapEnvelope is a copy of soap.Envelope, with namespace changed to "soapenv",
+// and additional namespace attributes required by some client libraries.
+// Go still has issues decoding with such a namespace, but encoding is ok.
+type soapEnvelope struct {
+ XMLName xml.Name `xml:"soapenv:Envelope"`
+ Enc string `xml:"xmlns:soapenc,attr"`
+ Env string `xml:"xmlns:soapenv,attr"`
+ XSD string `xml:"xmlns:xsd,attr"`
+ XSI string `xml:"xmlns:xsi,attr"`
+ Body interface{} `xml:"soapenv:Body"`
+}
+
+// About generates some info about the simulator.
+func (s *Service) About(w http.ResponseWriter, r *http.Request) {
+ var about struct {
+ Methods []string
+ Types []string
+ }
+
+ seen := make(map[string]bool)
+
+ f := reflect.TypeOf((*soap.HasFault)(nil)).Elem()
+
+ for _, obj := range Map.objects {
+ kind := obj.Reference().Type
+ if seen[kind] {
+ continue
+ }
+ seen[kind] = true
+
+ about.Types = append(about.Types, kind)
+
+ t := reflect.TypeOf(obj)
+ for i := 0; i < t.NumMethod(); i++ {
+ m := t.Method(i)
+ if seen[m.Name] {
+ continue
+ }
+ seen[m.Name] = true
+
+ if m.Type.NumIn() != 2 || m.Type.NumOut() != 1 || m.Type.Out(0) != f {
+ continue
+ }
+
+ about.Methods = append(about.Methods, strings.Replace(m.Name, "Task", "_Task", 1))
+ }
+ }
+
+ sort.Strings(about.Methods)
+ sort.Strings(about.Types)
+
+ w.Header().Set("Content-Type", "application/json")
+ enc := json.NewEncoder(w)
+ enc.SetIndent("", " ")
+ _ = enc.Encode(&about)
+}
+
+// ServeSDK implements the http.Handler interface
+func (s *Service) ServeSDK(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "POST" {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+
+ body, err := s.readAll(r.Body)
+ _ = r.Body.Close()
+ if err != nil {
+ log.Printf("error reading body: %s", err)
+ w.WriteHeader(http.StatusBadRequest)
+ return
+ }
+
+ if Trace {
+ fmt.Fprintf(os.Stderr, "Request: %s\n", string(body))
+ }
+
+ var res soap.HasFault
+
+ method, err := UnmarshalBody(body)
+ if err != nil {
+ res = serverFault(err.Error())
+ } else {
+ res = s.call(method)
+ }
+
+ if res.Fault() == nil {
+ w.WriteHeader(http.StatusOK)
+ } else {
+ w.WriteHeader(http.StatusInternalServerError)
+ }
+
+ var out bytes.Buffer
+
+ fmt.Fprint(&out, xml.Header)
+ e := xml.NewEncoder(&out)
+ err = e.Encode(&soapEnvelope{
+ Enc: "http://schemas.xmlsoap.org/soap/encoding/",
+ Env: "http://schemas.xmlsoap.org/soap/envelope/",
+ XSD: "http://www.w3.org/2001/XMLSchema",
+ XSI: "http://www.w3.org/2001/XMLSchema-instance",
+ Body: res,
+ })
+ if err == nil {
+ err = e.Flush()
+ }
+
+ if err != nil {
+ log.Printf("error encoding %s response: %s", method.Name, err)
+ return
+ }
+
+ if Trace {
+ fmt.Fprintf(os.Stderr, "Response: %s\n", out.String())
+ }
+
+ _, _ = w.Write(out.Bytes())
+}
+
+func (s *Service) findDatastore(query url.Values) (*Datastore, error) {
+ ctx := context.Background()
+
+ finder := find.NewFinder(s.client, false)
+ dc, err := finder.DatacenterOrDefault(ctx, query.Get("dcName"))
+ if err != nil {
+ return nil, err
+ }
+
+ finder.SetDatacenter(dc)
+
+ ds, err := finder.DatastoreOrDefault(ctx, query.Get("dsName"))
+ if err != nil {
+ return nil, err
+ }
+
+ return Map.Get(ds.Reference()).(*Datastore), nil
+}
+
+const folderPrefix = "/folder/"
+
+// ServeDatastore handler for Datastore access via /folder path.
+func (s *Service) ServeDatastore(w http.ResponseWriter, r *http.Request) {
+ ds, ferr := s.findDatastore(r.URL.Query())
+ if ferr != nil {
+ log.Printf("failed to locate datastore with query params: %s", r.URL.RawQuery)
+ w.WriteHeader(http.StatusNotFound)
+ return
+ }
+
+ file := strings.TrimPrefix(r.URL.Path, folderPrefix)
+ p := path.Join(ds.Info.GetDatastoreInfo().Url, file)
+
+ switch r.Method {
+ case "GET":
+ f, err := os.Open(p)
+ if err != nil {
+ log.Printf("failed to %s '%s': %s", r.Method, p, err)
+ w.WriteHeader(http.StatusNotFound)
+ return
+ }
+ defer f.Close()
+
+ _, _ = io.Copy(w, f)
+ case "POST":
+ _, err := os.Stat(p)
+ if err == nil {
+ // File exists
+ w.WriteHeader(http.StatusConflict)
+ return
+ }
+
+ // File does not exist, fallthrough to create via PUT logic
+ fallthrough
+ case "PUT":
+ f, err := os.Create(p)
+ if err != nil {
+ log.Printf("failed to %s '%s': %s", r.Method, p, err)
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+ defer f.Close()
+
+ _, _ = io.Copy(f, r.Body)
+ default:
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ }
+}
+
+// ServiceVersions handler for the /sdk/vimServiceVersions.xml path.
+func (*Service) ServiceVersions(w http.ResponseWriter, r *http.Request) {
+ // pyvmomi depends on this
+
+ const versions = xml.Header + `
+
+ urn:vim25
+ 6.5
+
+ 6.0
+ 5.5
+
+
+
+`
+ fmt.Fprint(w, versions)
+}
+
+// NewServer returns an http Server instance for the given service
+func (s *Service) NewServer() *Server {
+ mux := http.NewServeMux()
+ path := "/sdk"
+
+ mux.HandleFunc(path, s.ServeSDK)
+ mux.HandleFunc(path+"/vimServiceVersions.xml", s.ServiceVersions)
+ mux.HandleFunc(folderPrefix, s.ServeDatastore)
+ mux.HandleFunc("/about", s.About)
+
+ // Using NewUnstartedServer() instead of NewServer(),
+ // for use in main.go, where Start() blocks, we can still set ServiceHostName
+ ts := httptest.NewUnstartedServer(mux)
+
+ u := &url.URL{
+ Scheme: "http",
+ Host: ts.Listener.Addr().String(),
+ Path: path,
+ User: url.UserPassword("user", "pass"),
+ }
+
+ // Redirect clients to this http server, rather than HostSystem.Name
+ Map.Get(*s.client.ServiceContent.SessionManager).(*SessionManager).ServiceHostName = u.Host
+
+ if f := flag.Lookup("httptest.serve"); f != nil {
+ // Avoid the blocking behaviour of httptest.Server.Start() when this flag is set
+ _ = f.Value.Set("")
+ }
+
+ if s.TLS == nil {
+ ts.Start()
+ } else {
+ ts.TLS = s.TLS
+ ts.StartTLS()
+ u.Scheme += "s"
+ }
+
+ return &Server{
+ Server: ts,
+ URL: u,
+ }
+}
+
+// Certificate returns the TLS certificate for the Server if started with TLS enabled.
+// This method will panic if TLS is not enabled for the server.
+func (s *Server) Certificate() *x509.Certificate {
+ // By default httptest.StartTLS uses http/internal.LocalhostCert, which we can access here:
+ cert, _ := x509.ParseCertificate(s.TLS.Certificates[0].Certificate[0])
+ return cert
+}
+
+// CertificateInfo returns Server.Certificate() as object.HostCertificateInfo
+func (s *Server) CertificateInfo() *object.HostCertificateInfo {
+ info := new(object.HostCertificateInfo)
+ info.FromCertificate(s.Certificate())
+ return info
+}
+
+// CertificateFile returns a file name, where the file contains the PEM encoded Server.Certificate.
+// The temporary file is removed when Server.Close() is called.
+func (s *Server) CertificateFile() (string, error) {
+ if s.caFile != "" {
+ return s.caFile, nil
+ }
+
+ f, err := ioutil.TempFile("", "vcsim-")
+ if err != nil {
+ return "", err
+ }
+ defer f.Close()
+
+ s.caFile = f.Name()
+ cert := s.Certificate()
+ return s.caFile, pem.Encode(f, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})
+}
+
+// Close shuts down the server and blocks until all outstanding
+// requests on this server have completed.
+func (s *Server) Close() {
+ s.Server.Close()
+ if s.caFile != "" {
+ _ = os.Remove(s.caFile)
+ }
+}
+
+var typeFunc = types.TypeFunc()
+
+// UnmarshalBody extracts the Body from a soap.Envelope and unmarshals to the corresponding govmomi type
+func UnmarshalBody(data []byte) (*Method, error) {
+ body := struct {
+ Content string `xml:",innerxml"`
+ }{}
+
+ req := soap.Envelope{
+ Body: &body,
+ }
+
+ err := xml.Unmarshal(data, &req)
+ if err != nil {
+ return nil, fmt.Errorf("xml.Unmarshal: %s", err)
+ }
+
+ decoder := xml.NewDecoder(bytes.NewReader([]byte(body.Content)))
+ decoder.TypeFunc = typeFunc // required to decode interface types
+
+ var start *xml.StartElement
+
+ for {
+ tok, derr := decoder.Token()
+ if derr != nil {
+ return nil, fmt.Errorf("decoding body: %s", err)
+ }
+ if t, ok := tok.(xml.StartElement); ok {
+ start = &t
+ break
+ }
+ }
+
+ kind := start.Name.Local
+
+ rtype, ok := typeFunc(kind)
+ if !ok {
+ return nil, fmt.Errorf("no vmomi type defined for '%s'", kind)
+ }
+
+ var val interface{}
+ if rtype != nil {
+ val = reflect.New(rtype).Interface()
+ }
+
+ err = decoder.DecodeElement(val, start)
+ if err != nil {
+ return nil, fmt.Errorf("decoding %s: %s", kind, err)
+ }
+
+ method := &Method{Name: kind, Body: val}
+
+ field := reflect.ValueOf(val).Elem().FieldByName("This")
+
+ method.This = field.Interface().(types.ManagedObjectReference)
+
+ return method, nil
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/task.go b/vendor/github.com/vmware/govmomi/simulator/task.go
new file mode 100644
index 00000000..7ef17498
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/task.go
@@ -0,0 +1,100 @@
+/*
+Copyright (c) 2017 VMware, Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package simulator
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+ "time"
+
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+const vTaskSuffix = "_Task" // vmomi suffix
+const sTaskSuffix = "Task" // simulator suffix (avoiding golint warning)
+
+type Task struct {
+ mo.Task
+
+ Execute func(*Task) (types.AnyType, types.BaseMethodFault)
+}
+
+func NewTask(runner TaskRunner) *Task {
+ ref := runner.Reference()
+ name := reflect.TypeOf(runner).Elem().Name()
+ name = strings.Replace(name, "VM", "Vm", 1) // "VM" for the type to make go-lint happy, but "Vm" for the vmodl ID
+ return CreateTask(ref, name, runner.Run)
+}
+
+func CreateTask(e mo.Reference, name string, run func(*Task) (types.AnyType, types.BaseMethodFault)) *Task {
+ ref := e.Reference()
+ id := name
+
+ if strings.HasSuffix(id, sTaskSuffix) {
+ id = id[:len(id)-len(sTaskSuffix)]
+ name = id + vTaskSuffix
+ }
+
+ task := &Task{
+ Execute: run,
+ }
+
+ Map.Put(task)
+
+ task.Info.Key = task.Self.Value
+ task.Info.Task = task.Self
+ task.Info.Name = ucFirst(name)
+ task.Info.DescriptionId = fmt.Sprintf("%s.%s", ref.Type, id)
+ task.Info.Entity = &ref
+ task.Info.EntityName = ref.Value
+
+ task.Info.QueueTime = time.Now()
+ task.Info.State = types.TaskInfoStateQueued
+
+ return task
+}
+
+type TaskRunner interface {
+ mo.Reference
+
+ Run(*Task) (types.AnyType, types.BaseMethodFault)
+}
+
+func (t *Task) Run() {
+ now := time.Now()
+ t.Info.StartTime = &now
+
+ t.Info.State = types.TaskInfoStateRunning
+
+ res, err := t.Execute(t)
+
+ now = time.Now()
+ t.Info.CompleteTime = &now
+
+ if err != nil {
+ t.Info.State = types.TaskInfoStateError
+ t.Info.Error = &types.LocalizedMethodFault{
+ Fault: err,
+ LocalizedMessage: fmt.Sprintf("%T", err),
+ }
+ } else {
+ t.Info.Result = res
+ t.Info.State = types.TaskInfoStateSuccess
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/task_manager.go b/vendor/github.com/vmware/govmomi/simulator/task_manager.go
new file mode 100644
index 00000000..df271082
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/task_manager.go
@@ -0,0 +1,52 @@
+/*
+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 simulator
+
+import (
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+var recentTaskMax = 200 // the VC limit
+
+type TaskManager struct {
+ mo.TaskManager
+}
+
+func NewTaskManager(ref types.ManagedObjectReference) object.Reference {
+ s := &TaskManager{}
+ s.Self = ref
+ Map.AddHandler(s)
+ return s
+}
+
+func (m *TaskManager) PutObject(obj mo.Reference) {
+ ref := obj.Reference()
+ if ref.Type != "Task" {
+ return
+ }
+
+ m.RecentTask = append(m.RecentTask, ref)
+
+ if len(m.RecentTask) > recentTaskMax {
+ m.RecentTask = m.RecentTask[1:]
+ }
+}
+
+func (m *TaskManager) RemoveObject(_ types.ManagedObjectReference) {
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/view_manager.go b/vendor/github.com/vmware/govmomi/simulator/view_manager.go
new file mode 100644
index 00000000..959f2284
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/view_manager.go
@@ -0,0 +1,184 @@
+/*
+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 simulator
+
+import (
+ "reflect"
+
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type ViewManager struct {
+ mo.ViewManager
+
+ entities map[string]bool
+}
+
+var entities = []struct {
+ Type reflect.Type
+ Container bool
+}{
+ {reflect.TypeOf((*mo.ManagedEntity)(nil)).Elem(), true},
+ {reflect.TypeOf((*mo.Folder)(nil)).Elem(), true},
+ {reflect.TypeOf((*mo.StoragePod)(nil)).Elem(), true},
+ {reflect.TypeOf((*mo.Datacenter)(nil)).Elem(), true},
+ {reflect.TypeOf((*mo.ComputeResource)(nil)).Elem(), true},
+ {reflect.TypeOf((*mo.ClusterComputeResource)(nil)).Elem(), true},
+ {reflect.TypeOf((*mo.HostSystem)(nil)).Elem(), true},
+ {reflect.TypeOf((*mo.ResourcePool)(nil)).Elem(), true},
+ {reflect.TypeOf((*mo.VirtualApp)(nil)).Elem(), true},
+ {reflect.TypeOf((*mo.VirtualMachine)(nil)).Elem(), false},
+ {reflect.TypeOf((*mo.Datastore)(nil)).Elem(), false},
+ {reflect.TypeOf((*mo.Network)(nil)).Elem(), false},
+ {reflect.TypeOf((*mo.OpaqueNetwork)(nil)).Elem(), false},
+ {reflect.TypeOf((*mo.DistributedVirtualPortgroup)(nil)).Elem(), false},
+ {reflect.TypeOf((*mo.DistributedVirtualSwitch)(nil)).Elem(), false},
+ {reflect.TypeOf((*mo.VmwareDistributedVirtualSwitch)(nil)).Elem(), false},
+}
+
+func NewViewManager(ref types.ManagedObjectReference) object.Reference {
+ s := &ViewManager{
+ entities: make(map[string]bool),
+ }
+
+ s.Self = ref
+
+ for _, e := range entities {
+ s.entities[e.Type.Name()] = e.Container
+ }
+
+ return s
+}
+
+func destroyView(ref types.ManagedObjectReference) soap.HasFault {
+ m := Map.ViewManager()
+
+ m.ViewList = RemoveReference(ref, m.ViewList)
+
+ return &methods.DestroyViewBody{
+ Res: &types.DestroyViewResponse{},
+ }
+}
+
+func (m *ViewManager) CreateContainerView(req *types.CreateContainerView) soap.HasFault {
+ body := &methods.CreateContainerViewBody{}
+
+ root := Map.Get(req.Container)
+ if root == nil {
+ body.Fault_ = Fault("", &types.ManagedObjectNotFound{Obj: req.Container})
+ return body
+ }
+
+ if m.entities[root.Reference().Type] != true {
+ body.Fault_ = Fault("", &types.InvalidArgument{InvalidProperty: "container"})
+ return body
+ }
+
+ container := &ContainerView{
+ mo.ContainerView{
+ Container: root.Reference(),
+ Recursive: req.Recursive,
+ Type: req.Type,
+ },
+ make(map[string]bool),
+ }
+
+ for _, ctype := range container.Type {
+ if _, ok := m.entities[ctype]; !ok {
+ body.Fault_ = Fault("", &types.InvalidArgument{InvalidProperty: "type"})
+ return body
+ }
+
+ container.types[ctype] = true
+
+ for _, e := range entities {
+ // Check for embedded types
+ if f, ok := e.Type.FieldByName(ctype); ok && f.Anonymous {
+ container.types[e.Type.Name()] = true
+ }
+ }
+ }
+
+ Map.Put(container)
+
+ m.ViewList = append(m.ViewList, container.Reference())
+
+ body.Res = &types.CreateContainerViewResponse{
+ Returnval: container.Self,
+ }
+
+ container.add(root)
+
+ return body
+}
+
+type ContainerView struct {
+ mo.ContainerView
+
+ types map[string]bool
+}
+
+func (v *ContainerView) DestroyView(c *types.DestroyView) soap.HasFault {
+ return destroyView(c.This)
+}
+
+func (v *ContainerView) include(o types.ManagedObjectReference) bool {
+ if len(v.types) == 0 {
+ return true
+ }
+
+ return v.types[o.Type]
+}
+
+func (v *ContainerView) add(root mo.Reference) {
+ var children []types.ManagedObjectReference
+
+ switch e := root.(type) {
+ case *mo.Datacenter:
+ children = []types.ManagedObjectReference{e.VmFolder, e.HostFolder, e.DatastoreFolder, e.NetworkFolder}
+ case *Folder:
+ children = e.ChildEntity
+ case *mo.ComputeResource:
+ children = e.Host
+ children = append(children, *e.ResourcePool)
+ case *ClusterComputeResource:
+ children = e.Host
+ children = append(children, *e.ResourcePool)
+ case *ResourcePool:
+ children = e.ResourcePool.ResourcePool
+ children = append(children, e.Vm...)
+ case *VirtualApp:
+ children = e.ResourcePool.ResourcePool
+ children = append(children, e.Vm...)
+ case *HostSystem:
+ children = e.Vm
+ }
+
+ for _, child := range children {
+ if v.include(child) {
+ v.View = AddReference(child, v.View)
+ }
+
+ if v.Recursive {
+ v.add(Map.Get(child))
+ }
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/virtual_disk_manager.go b/vendor/github.com/vmware/govmomi/simulator/virtual_disk_manager.go
new file mode 100644
index 00000000..622d272e
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/virtual_disk_manager.go
@@ -0,0 +1,175 @@
+/*
+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 simulator
+
+import (
+ "os"
+ "strings"
+
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type VirtualDiskManager struct {
+ mo.VirtualDiskManager
+}
+
+func NewVirtualDiskManager(ref types.ManagedObjectReference) object.Reference {
+ m := &VirtualDiskManager{}
+ m.Self = ref
+ return m
+}
+
+func (m *VirtualDiskManager) names(name string) []string {
+ return []string{
+ strings.Replace(name, ".vmdk", "-flat.vmdk", 1),
+ name,
+ }
+}
+
+func (m *VirtualDiskManager) createVirtualDisk(req *types.CreateVirtualDisk_Task) types.BaseMethodFault {
+ fm := Map.FileManager()
+
+ file, fault := fm.resolve(req.Datacenter, req.Name)
+ if fault != nil {
+ return fault
+ }
+
+ for _, name := range m.names(file) {
+ _, err := os.Stat(name)
+ if err == nil {
+ return fm.fault(name, nil, new(types.FileAlreadyExists))
+ }
+
+ f, err := os.Create(name)
+ if err != nil {
+ return fm.fault(name, err, new(types.CannotCreateFile))
+ }
+
+ _ = f.Close()
+ }
+
+ return nil
+}
+
+func (m *VirtualDiskManager) CreateVirtualDiskTask(req *types.CreateVirtualDisk_Task) soap.HasFault {
+ task := CreateTask(m, "createVirtualDisk", func(*Task) (types.AnyType, types.BaseMethodFault) {
+ return nil, m.createVirtualDisk(req)
+ })
+
+ task.Run()
+
+ return &methods.CreateVirtualDisk_TaskBody{
+ Res: &types.CreateVirtualDisk_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
+
+func (m *VirtualDiskManager) DeleteVirtualDiskTask(req *types.DeleteVirtualDisk_Task) soap.HasFault {
+ task := CreateTask(m, "deleteVirtualDisk", func(*Task) (types.AnyType, types.BaseMethodFault) {
+ fm := Map.FileManager()
+
+ for _, name := range m.names(req.Name) {
+ err := fm.deleteDatastoreFile(&types.DeleteDatastoreFile_Task{
+ Name: name,
+ Datacenter: req.Datacenter,
+ })
+
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return nil, nil
+ })
+
+ task.Run()
+
+ return &methods.DeleteVirtualDisk_TaskBody{
+ Res: &types.DeleteVirtualDisk_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
+
+func (m *VirtualDiskManager) MoveVirtualDiskTask(req *types.MoveVirtualDisk_Task) soap.HasFault {
+ task := CreateTask(m, "moveVirtualDisk", func(*Task) (types.AnyType, types.BaseMethodFault) {
+ fm := Map.FileManager()
+
+ dest := m.names(req.DestName)
+
+ for i, name := range m.names(req.SourceName) {
+ err := fm.moveDatastoreFile(&types.MoveDatastoreFile_Task{
+ SourceName: name,
+ SourceDatacenter: req.SourceDatacenter,
+ DestinationName: dest[i],
+ DestinationDatacenter: req.DestDatacenter,
+ Force: req.Force,
+ })
+
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return nil, nil
+ })
+
+ task.Run()
+
+ return &methods.MoveVirtualDisk_TaskBody{
+ Res: &types.MoveVirtualDisk_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
+
+func (m *VirtualDiskManager) CopyVirtualDiskTask(req *types.CopyVirtualDisk_Task) soap.HasFault {
+ task := CreateTask(m, "copyVirtualDisk", func(*Task) (types.AnyType, types.BaseMethodFault) {
+ fm := Map.FileManager()
+
+ dest := m.names(req.DestName)
+
+ for i, name := range m.names(req.SourceName) {
+ err := fm.copyDatastoreFile(&types.CopyDatastoreFile_Task{
+ SourceName: name,
+ SourceDatacenter: req.SourceDatacenter,
+ DestinationName: dest[i],
+ DestinationDatacenter: req.DestDatacenter,
+ Force: req.Force,
+ })
+
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return nil, nil
+ })
+
+ task.Run()
+
+ return &methods.CopyVirtualDisk_TaskBody{
+ Res: &types.CopyVirtualDisk_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/virtual_machine.go b/vendor/github.com/vmware/govmomi/simulator/virtual_machine.go
new file mode 100644
index 00000000..dd3e2c75
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/virtual_machine.go
@@ -0,0 +1,641 @@
+/*
+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 simulator
+
+import (
+ "fmt"
+ "io"
+ "log"
+ "net"
+ "os"
+ "path"
+ "strings"
+ "time"
+
+ "github.com/google/uuid"
+
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/simulator/esx"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/soap"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type VirtualMachine struct {
+ mo.VirtualMachine
+
+ log *log.Logger
+ out io.Closer
+}
+
+func NewVirtualMachine(parent types.ManagedObjectReference, spec *types.VirtualMachineConfigSpec) (*VirtualMachine, types.BaseMethodFault) {
+ vm := &VirtualMachine{}
+ vm.Parent = &parent
+
+ if spec.Name == "" {
+ return nil, &types.InvalidVmConfig{Property: "configSpec.name"}
+ }
+
+ if spec.Files == nil || spec.Files.VmPathName == "" {
+ return nil, &types.InvalidVmConfig{Property: "configSpec.files.vmPathName"}
+ }
+
+ vm.Config = &types.VirtualMachineConfigInfo{
+ ExtraConfig: []types.BaseOptionValue{&types.OptionValue{Key: "govcsim", Value: "TRUE"}},
+ }
+ vm.Summary.Guest = &types.VirtualMachineGuestSummary{}
+ vm.Summary.Storage = &types.VirtualMachineStorageSummary{}
+
+ // Append VM Name as the directory name if not specified
+ if strings.HasSuffix(spec.Files.VmPathName, "]") { // e.g. "[datastore1]"
+ spec.Files.VmPathName += " " + spec.Name
+ }
+
+ if !strings.HasSuffix(spec.Files.VmPathName, ".vmx") {
+ spec.Files.VmPathName = path.Join(spec.Files.VmPathName, spec.Name+".vmx")
+ }
+
+ dsPath := path.Dir(spec.Files.VmPathName)
+
+ defaults := types.VirtualMachineConfigSpec{
+ NumCPUs: 1,
+ NumCoresPerSocket: 1,
+ MemoryMB: 32,
+ Uuid: uuid.New().String(),
+ Version: "vmx-11",
+ Files: &types.VirtualMachineFileInfo{
+ SnapshotDirectory: dsPath,
+ SuspendDirectory: dsPath,
+ LogDirectory: dsPath,
+ },
+ }
+
+ // Add the default devices
+ defaults.DeviceChange, _ = object.VirtualDeviceList(esx.VirtualDevice).ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd)
+
+ err := vm.configure(&defaults)
+ if err != nil {
+ return nil, err
+ }
+
+ vm.Runtime.PowerState = types.VirtualMachinePowerStatePoweredOff
+ vm.Runtime.ConnectionState = types.VirtualMachineConnectionStateConnected
+ vm.Summary.Runtime = vm.Runtime
+
+ vm.Summary.QuickStats.GuestHeartbeatStatus = types.ManagedEntityStatusGray
+ vm.Summary.OverallStatus = types.ManagedEntityStatusGreen
+ vm.ConfigStatus = types.ManagedEntityStatusGreen
+
+ return vm, nil
+}
+
+func (vm *VirtualMachine) apply(spec *types.VirtualMachineConfigSpec) {
+ if spec.Files == nil {
+ spec.Files = new(types.VirtualMachineFileInfo)
+ }
+
+ apply := []struct {
+ src string
+ dst *string
+ }{
+ {spec.Name, &vm.Name},
+ {spec.Name, &vm.Config.Name},
+ {spec.Name, &vm.Summary.Config.Name},
+ {spec.GuestId, &vm.Config.GuestId},
+ {spec.GuestId, &vm.Config.GuestFullName},
+ {spec.GuestId, &vm.Summary.Guest.GuestId},
+ {spec.GuestId, &vm.Summary.Config.GuestId},
+ {spec.GuestId, &vm.Summary.Config.GuestFullName},
+ {spec.Uuid, &vm.Config.Uuid},
+ {spec.Version, &vm.Config.Version},
+ {spec.Files.VmPathName, &vm.Config.Files.VmPathName},
+ {spec.Files.VmPathName, &vm.Summary.Config.VmPathName},
+ {spec.Files.SnapshotDirectory, &vm.Config.Files.SnapshotDirectory},
+ {spec.Files.LogDirectory, &vm.Config.Files.LogDirectory},
+ }
+
+ for _, f := range apply {
+ if f.src != "" {
+ *f.dst = f.src
+ }
+ }
+
+ if spec.MemoryMB != 0 {
+ vm.Config.Hardware.MemoryMB = int32(spec.MemoryMB)
+ vm.Summary.Config.MemorySizeMB = vm.Config.Hardware.MemoryMB
+ }
+
+ if spec.NumCPUs != 0 {
+ vm.Config.Hardware.NumCPU = spec.NumCPUs
+ vm.Summary.Config.NumCpu = vm.Config.Hardware.NumCPU
+ }
+
+ vm.Config.ExtraConfig = append(vm.Config.ExtraConfig, spec.ExtraConfig...)
+
+ vm.Config.Modified = time.Now()
+
+ vm.Summary.Config.Uuid = vm.Config.Uuid
+}
+
+func (vm *VirtualMachine) configure(spec *types.VirtualMachineConfigSpec) types.BaseMethodFault {
+ vm.apply(spec)
+
+ return vm.configureDevices(spec)
+}
+
+func (vm *VirtualMachine) useDatastore(name string) *Datastore {
+ host := Map.Get(*vm.Runtime.Host).(*HostSystem)
+
+ ds := Map.FindByName(name, host.Datastore).(*Datastore)
+
+ vm.Datastore = AddReference(ds.Self, vm.Datastore)
+
+ return ds
+}
+
+func (vm *VirtualMachine) setLog(w io.WriteCloser) {
+ vm.out = w
+ vm.log = log.New(w, "vmx ", log.Flags())
+}
+
+func (vm *VirtualMachine) createFile(spec string, name string, register bool) (*os.File, types.BaseMethodFault) {
+ p, fault := parseDatastorePath(spec)
+ if fault != nil {
+ return nil, fault
+ }
+
+ ds := vm.useDatastore(p.Datastore)
+
+ file := path.Join(ds.Info.GetDatastoreInfo().Url, p.Path)
+
+ if name != "" {
+ if path.Ext(file) != "" {
+ file = path.Dir(file)
+ }
+
+ file = path.Join(file, name)
+ }
+
+ if register {
+ f, err := os.Open(file)
+ if err != nil {
+ log.Printf("register %s: %s", vm.Reference(), err)
+ if os.IsNotExist(err) {
+ return nil, &types.NotFound{}
+ }
+
+ return nil, &types.InvalidArgument{}
+ }
+
+ return f, nil
+ }
+
+ dir := path.Dir(file)
+
+ _ = os.MkdirAll(dir, 0700)
+
+ _, err := os.Stat(file)
+ if err == nil {
+ return nil, &types.FileAlreadyExists{
+ FileFault: types.FileFault{
+ File: file,
+ },
+ }
+ }
+
+ f, err := os.Create(file)
+ if err != nil {
+ return nil, &types.FileFault{
+ File: file,
+ }
+ }
+
+ return f, nil
+}
+
+func (vm *VirtualMachine) create(spec *types.VirtualMachineConfigSpec, register bool) types.BaseMethodFault {
+ vm.apply(spec)
+
+ files := []struct {
+ spec string
+ name string
+ use func(w io.WriteCloser)
+ }{
+ {vm.Config.Files.VmPathName, "", nil},
+ {vm.Config.Files.VmPathName, fmt.Sprintf("%s.nvram", vm.Name), nil},
+ {vm.Config.Files.LogDirectory, "vmware.log", vm.setLog},
+ }
+
+ for _, file := range files {
+ f, err := vm.createFile(file.spec, file.name, register)
+ if err != nil {
+ return err
+ }
+
+ if file.use != nil {
+ file.use(f)
+ } else {
+ _ = f.Close()
+ }
+ }
+
+ vm.log.Print("created")
+
+ return vm.configureDevices(spec)
+}
+
+var vmwOUI = net.HardwareAddr([]byte{0x0, 0xc, 0x29})
+
+// From http://pubs.vmware.com/vsphere-60/index.jsp?topic=%2Fcom.vmware.vsphere.networking.doc%2FGUID-DC7478FF-DC44-4625-9AD7-38208C56A552.html
+// "The host generates generateMAC addresses that consists of the VMware OUI 00:0C:29 and the last three octets in hexadecimal
+// format of the virtual machine UUID. The virtual machine UUID is based on a hash calculated by using the UUID of the
+// ESXi physical machine and the path to the configuration file (.vmx) of the virtual machine."
+func (vm *VirtualMachine) generateMAC() string {
+ id := uuid.New() // Random is fine for now.
+
+ offset := len(id) - len(vmwOUI)
+
+ mac := append(vmwOUI, id[offset:]...)
+
+ return mac.String()
+}
+
+func (vm *VirtualMachine) configureDevice(devices object.VirtualDeviceList, device types.BaseVirtualDevice) types.BaseMethodFault {
+ d := device.GetVirtualDevice()
+ var controller types.BaseVirtualController
+
+ if d.Key < 0 {
+ // Choose a unique key
+ if d.Key == -1 {
+ d.Key = devices.NewKey()
+ }
+
+ d.Key *= -1
+
+ for {
+ if devices.FindByKey(d.Key) == nil {
+ break
+ }
+ d.Key++
+ }
+ }
+
+ label := devices.Name(device)
+ summary := label
+ dc := Map.getEntityDatacenter(Map.Get(*vm.Parent).(mo.Entity))
+ dm := Map.VirtualDiskManager()
+
+ switch x := device.(type) {
+ case types.BaseVirtualEthernetCard:
+ controller = devices.PickController((*types.VirtualPCIController)(nil))
+ var net types.ManagedObjectReference
+
+ switch b := d.Backing.(type) {
+ case *types.VirtualEthernetCardNetworkBackingInfo:
+ summary = b.DeviceName
+ net = Map.FindByName(b.DeviceName, dc.Network).Reference()
+ b.Network = &net
+ case *types.VirtualEthernetCardDistributedVirtualPortBackingInfo:
+ summary = fmt.Sprintf("DVSwitch: %s", b.Port.SwitchUuid)
+ net.Type = "DistributedVirtualPortgroup"
+ net.Value = b.Port.PortgroupKey
+ }
+
+ vm.Network = append(vm.Network, net)
+
+ c := x.GetVirtualEthernetCard()
+ if c.MacAddress == "" {
+ c.MacAddress = vm.generateMAC()
+ }
+ case *types.VirtualDisk:
+ switch b := d.Backing.(type) {
+ case types.BaseVirtualDeviceFileBackingInfo:
+ err := dm.createVirtualDisk(&types.CreateVirtualDisk_Task{
+ Datacenter: &dc.Self,
+ Name: b.GetVirtualDeviceFileBackingInfo().FileName,
+ })
+
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ if d.UnitNumber == nil && controller != nil {
+ devices.AssignController(device, controller)
+ }
+
+ if d.DeviceInfo == nil {
+ d.DeviceInfo = &types.Description{
+ Label: label,
+ Summary: summary,
+ }
+ }
+
+ return nil
+}
+
+func removeDevice(devices object.VirtualDeviceList, device types.BaseVirtualDevice) object.VirtualDeviceList {
+ var result object.VirtualDeviceList
+
+ for i, d := range devices {
+ if d.GetVirtualDevice().Key == device.GetVirtualDevice().Key {
+ result = append(result, devices[i+1:]...)
+ break
+ }
+
+ result = append(result, d)
+ }
+
+ return result
+}
+
+func (vm *VirtualMachine) configureDevices(spec *types.VirtualMachineConfigSpec) types.BaseMethodFault {
+ devices := object.VirtualDeviceList(vm.Config.Hardware.Device)
+
+ for i, change := range spec.DeviceChange {
+ dspec := change.GetVirtualDeviceConfigSpec()
+ device := dspec.Device.GetVirtualDevice()
+ invalid := &types.InvalidDeviceSpec{DeviceIndex: int32(i)}
+
+ switch dspec.Operation {
+ case types.VirtualDeviceConfigSpecOperationAdd:
+ if devices.FindByKey(device.Key) != nil {
+ if vm.Self.Value != "" { // moid isn't set until CreateVM is done
+ return invalid
+ }
+
+ // In this case, the CreateVM() spec included one of the default devices
+ devices = removeDevice(devices, device)
+ }
+
+ err := vm.configureDevice(devices, dspec.Device)
+ if err != nil {
+ return err
+ }
+
+ devices = append(devices, dspec.Device)
+ case types.VirtualDeviceConfigSpecOperationRemove:
+ devices = removeDevice(devices, dspec.Device)
+ }
+ }
+
+ vm.Config.Hardware.Device = []types.BaseVirtualDevice(devices)
+
+ return nil
+}
+
+type powerVMTask struct {
+ *VirtualMachine
+
+ state types.VirtualMachinePowerState
+}
+
+func (c *powerVMTask) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
+ c.log.Printf("running power task: requesting %s, existing %s",
+ c.state, c.VirtualMachine.Runtime.PowerState)
+
+ if c.VirtualMachine.Runtime.PowerState == c.state {
+ return nil, &types.InvalidPowerState{
+ RequestedState: c.state,
+ ExistingState: c.VirtualMachine.Runtime.PowerState,
+ }
+ }
+
+ c.VirtualMachine.Runtime.PowerState = c.state
+ c.VirtualMachine.Summary.Runtime.PowerState = c.state
+
+ bt := &c.VirtualMachine.Summary.Runtime.BootTime
+ if c.state == types.VirtualMachinePowerStatePoweredOn {
+ now := time.Now()
+ *bt = &now
+ } else {
+ *bt = nil
+ }
+
+ return nil, nil
+}
+
+func (vm *VirtualMachine) PowerOnVMTask(c *types.PowerOnVM_Task) soap.HasFault {
+ r := &methods.PowerOnVM_TaskBody{}
+
+ runner := &powerVMTask{vm, types.VirtualMachinePowerStatePoweredOn}
+ task := CreateTask(runner.Reference(), "powerOn", runner.Run)
+
+ r.Res = &types.PowerOnVM_TaskResponse{
+ Returnval: task.Self,
+ }
+
+ task.Run()
+
+ return r
+}
+
+func (vm *VirtualMachine) PowerOffVMTask(c *types.PowerOffVM_Task) soap.HasFault {
+ r := &methods.PowerOffVM_TaskBody{}
+
+ runner := &powerVMTask{vm, types.VirtualMachinePowerStatePoweredOff}
+ task := CreateTask(runner.Reference(), "powerOff", runner.Run)
+
+ r.Res = &types.PowerOffVM_TaskResponse{
+ Returnval: task.Self,
+ }
+
+ task.Run()
+
+ return r
+}
+
+func (vm *VirtualMachine) ReconfigVMTask(req *types.ReconfigVM_Task) soap.HasFault {
+ task := CreateTask(vm, "reconfigVm", func(t *Task) (types.AnyType, types.BaseMethodFault) {
+ err := vm.configure(&req.Spec)
+ if err != nil {
+ return nil, err
+ }
+
+ return nil, nil
+ })
+
+ task.Run()
+
+ return &methods.ReconfigVM_TaskBody{
+ Res: &types.ReconfigVM_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
+
+func (vm *VirtualMachine) DestroyTask(req *types.Destroy_Task) soap.HasFault {
+ task := CreateTask(vm, "destroy", func(t *Task) (types.AnyType, types.BaseMethodFault) {
+ r := vm.UnregisterVM(&types.UnregisterVM{
+ This: req.This,
+ })
+
+ if r.Fault() != nil {
+ return nil, r.Fault().VimFault().(types.BaseMethodFault)
+ }
+
+ // Delete VM files from the datastore (ignoring result for now)
+ m := Map.FileManager()
+ dc := Map.getEntityDatacenter(vm).Reference()
+
+ _ = m.DeleteDatastoreFileTask(&types.DeleteDatastoreFile_Task{
+ This: m.Reference(),
+ Name: vm.Config.Files.LogDirectory,
+ Datacenter: &dc,
+ })
+
+ return nil, nil
+ })
+
+ task.Run()
+
+ return &methods.Destroy_TaskBody{
+ Res: &types.Destroy_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
+
+func (vm *VirtualMachine) UnregisterVM(c *types.UnregisterVM) soap.HasFault {
+ r := &methods.UnregisterVMBody{}
+
+ if vm.Runtime.PowerState == types.VirtualMachinePowerStatePoweredOn {
+ r.Fault_ = Fault("", &types.InvalidPowerState{
+ RequestedState: types.VirtualMachinePowerStatePoweredOff,
+ ExistingState: vm.Runtime.PowerState,
+ })
+
+ return r
+ }
+
+ _ = vm.out.Close() // Close log fd
+
+ Map.getEntityParent(vm, "Folder").(*Folder).removeChild(c.This)
+
+ host := Map.Get(*vm.Runtime.Host).(*HostSystem)
+ host.Vm = RemoveReference(vm.Self, host.Vm)
+
+ switch pool := Map.Get(*vm.ResourcePool).(type) {
+ case *ResourcePool:
+ pool.Vm = RemoveReference(vm.Self, pool.Vm)
+ case *VirtualApp:
+ pool.Vm = RemoveReference(vm.Self, pool.Vm)
+ }
+
+ for i := range vm.Datastore {
+ ds := Map.Get(vm.Datastore[i]).(*Datastore)
+ ds.Vm = RemoveReference(vm.Self, ds.Vm)
+ }
+
+ r.Res = new(types.UnregisterVMResponse)
+
+ return r
+}
+
+func (vm *VirtualMachine) CloneVMTask(req *types.CloneVM_Task) soap.HasFault {
+ task := CreateTask(vm, "cloneVm", func(t *Task) (types.AnyType, types.BaseMethodFault) {
+ folder := Map.Get(req.Folder).(*Folder)
+
+ config := types.VirtualMachineConfigSpec{
+ Name: req.Name,
+ GuestId: vm.Config.GuestId,
+ Files: &types.VirtualMachineFileInfo{
+ VmPathName: strings.Replace(vm.Config.Files.VmPathName, vm.Name, req.Name, -1),
+ },
+ }
+
+ res := folder.CreateVMTask(&types.CreateVM_Task{
+ This: folder.Self,
+ Config: config,
+ Pool: *vm.ResourcePool,
+ })
+
+ ctask := Map.Get(res.(*methods.CreateVM_TaskBody).Res.Returnval).(*Task)
+ if ctask.Info.Error != nil {
+ return nil, ctask.Info.Error.Fault
+ }
+
+ return ctask.Info.Result.(types.ManagedObjectReference), nil
+ })
+
+ task.Run()
+
+ return &methods.CloneVM_TaskBody{
+ Res: &types.CloneVM_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
+
+func (vm *VirtualMachine) RelocateVMTask(req *types.RelocateVM_Task) soap.HasFault {
+ task := CreateTask(vm, "relocateVm", func(t *Task) (types.AnyType, types.BaseMethodFault) {
+ if ref := req.Spec.Datastore; ref != nil {
+ ds := Map.Get(*ref).(*Datastore)
+ ds.Vm = RemoveReference(*ref, ds.Vm)
+
+ vm.Datastore = []types.ManagedObjectReference{*ref}
+
+ // TODO: migrate vm.Config.Files (and vm.Summary.Config.VmPathName)
+ }
+
+ if ref := req.Spec.Pool; ref != nil {
+ pool := Map.Get(*ref).(*ResourcePool)
+ pool.Vm = RemoveReference(*ref, pool.Vm)
+
+ vm.ResourcePool = ref
+ }
+
+ if ref := req.Spec.Host; ref != nil {
+ host := Map.Get(*ref).(*HostSystem)
+ host.Vm = RemoveReference(*ref, host.Vm)
+
+ vm.Runtime.Host = ref
+ }
+
+ return nil, nil
+ })
+
+ task.Run()
+
+ return &methods.RelocateVM_TaskBody{
+ Res: &types.RelocateVM_TaskResponse{
+ Returnval: task.Self,
+ },
+ }
+}
+
+func (vm *VirtualMachine) ShutdownGuest(c *types.ShutdownGuest) soap.HasFault {
+ r := &methods.ShutdownGuestBody{}
+ // should be poweron
+ if vm.Runtime.PowerState == types.VirtualMachinePowerStatePoweredOff {
+ r.Fault_ = Fault("", &types.InvalidPowerState{
+ RequestedState: types.VirtualMachinePowerStatePoweredOn,
+ ExistingState: vm.Runtime.PowerState,
+ })
+
+ return r
+ }
+ // change state
+ vm.Runtime.PowerState = types.VirtualMachinePowerStatePoweredOff
+ vm.Summary.Runtime.PowerState = types.VirtualMachinePowerStatePoweredOff
+
+ r.Res = new(types.ShutdownGuestResponse)
+
+ return r
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/vpx/doc.go b/vendor/github.com/vmware/govmomi/simulator/vpx/doc.go
new file mode 100644
index 00000000..ca98ec73
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/vpx/doc.go
@@ -0,0 +1,20 @@
+/*
+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 vpx contains SOAP responses from a vCenter server, captured using `govc ... -debug`.
+*/
+package vpx
diff --git a/vendor/github.com/vmware/govmomi/simulator/vpx/root_folder.go b/vendor/github.com/vmware/govmomi/simulator/vpx/root_folder.go
new file mode 100644
index 00000000..a1cce0d8
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/vpx/root_folder.go
@@ -0,0 +1,64 @@
+/*
+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 vpx
+
+import (
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+var RootFolder = mo.Folder{
+ ManagedEntity: mo.ManagedEntity{
+ ExtensibleManagedObject: mo.ExtensibleManagedObject{
+ Self: types.ManagedObjectReference{Type: "Folder", Value: "group-d1"},
+ Value: nil,
+ AvailableField: nil,
+ },
+ Parent: (*types.ManagedObjectReference)(nil),
+ CustomValue: nil,
+ OverallStatus: "green",
+ ConfigStatus: "green",
+ ConfigIssue: nil,
+ EffectiveRole: []int32{-1},
+ Permission: []types.Permission{
+ {
+ DynamicData: types.DynamicData{},
+ Entity: &types.ManagedObjectReference{Type: "Folder", Value: "group-d1"},
+ Principal: "VSPHERE.LOCAL\\Administrator",
+ Group: false,
+ RoleId: -1,
+ Propagate: true,
+ },
+ {
+ DynamicData: types.DynamicData{},
+ Entity: &types.ManagedObjectReference{Type: "Folder", Value: "group-d1"},
+ Principal: "VSPHERE.LOCAL\\Administrators",
+ Group: true,
+ RoleId: -1,
+ Propagate: true,
+ },
+ },
+ Name: "Datacenters",
+ DisabledMethod: nil,
+ RecentTask: nil,
+ DeclaredAlarmState: nil,
+ AlarmActionsEnabled: (*bool)(nil),
+ Tag: nil,
+ },
+ ChildType: []string{"Folder", "Datacenter"},
+ ChildEntity: nil,
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/vpx/service_content.go b/vendor/github.com/vmware/govmomi/simulator/vpx/service_content.go
new file mode 100644
index 00000000..1c570f80
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/vpx/service_content.go
@@ -0,0 +1,79 @@
+/*
+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 vpx
+
+import "github.com/vmware/govmomi/vim25/types"
+
+var ServiceContent = types.ServiceContent{
+ DynamicData: types.DynamicData{},
+ RootFolder: types.ManagedObjectReference{Type: "Folder", Value: "group-d1"},
+ PropertyCollector: types.ManagedObjectReference{Type: "PropertyCollector", Value: "propertyCollector"},
+ ViewManager: &types.ManagedObjectReference{Type: "ViewManager", Value: "ViewManager"},
+ About: types.AboutInfo{
+ DynamicData: types.DynamicData{},
+ Name: "VMware vCenter Server",
+ FullName: "VMware vCenter Server 6.0.0 build-3634794",
+ Vendor: "VMware, Inc.",
+ Version: "6.0.0",
+ Build: "3634794",
+ LocaleVersion: "INTL",
+ LocaleBuild: "000",
+ OsType: "linux-x64",
+ ProductLineId: "vpx",
+ ApiType: "VirtualCenter",
+ ApiVersion: "6.0",
+ InstanceUuid: "8e7597d6-f720-4b5c-b9fc-3412faf07d99",
+ LicenseProductName: "VMware VirtualCenter Server",
+ LicenseProductVersion: "6.0",
+ },
+ Setting: &types.ManagedObjectReference{Type: "OptionManager", Value: "VpxSettings"},
+ UserDirectory: &types.ManagedObjectReference{Type: "UserDirectory", Value: "UserDirectory"},
+ SessionManager: &types.ManagedObjectReference{Type: "SessionManager", Value: "SessionManager"},
+ AuthorizationManager: &types.ManagedObjectReference{Type: "AuthorizationManager", Value: "AuthorizationManager"},
+ ServiceManager: &types.ManagedObjectReference{Type: "ServiceManager", Value: "ServiceMgr"},
+ PerfManager: &types.ManagedObjectReference{Type: "PerformanceManager", Value: "PerfMgr"},
+ ScheduledTaskManager: &types.ManagedObjectReference{Type: "ScheduledTaskManager", Value: "ScheduledTaskManager"},
+ AlarmManager: &types.ManagedObjectReference{Type: "AlarmManager", Value: "AlarmManager"},
+ EventManager: &types.ManagedObjectReference{Type: "EventManager", Value: "EventManager"},
+ TaskManager: &types.ManagedObjectReference{Type: "TaskManager", Value: "TaskManager"},
+ ExtensionManager: &types.ManagedObjectReference{Type: "ExtensionManager", Value: "ExtensionManager"},
+ CustomizationSpecManager: &types.ManagedObjectReference{Type: "CustomizationSpecManager", Value: "CustomizationSpecManager"},
+ CustomFieldsManager: &types.ManagedObjectReference{Type: "CustomFieldsManager", Value: "CustomFieldsManager"},
+ AccountManager: (*types.ManagedObjectReference)(nil),
+ DiagnosticManager: &types.ManagedObjectReference{Type: "DiagnosticManager", Value: "DiagMgr"},
+ LicenseManager: &types.ManagedObjectReference{Type: "LicenseManager", Value: "LicenseManager"},
+ SearchIndex: &types.ManagedObjectReference{Type: "SearchIndex", Value: "SearchIndex"},
+ FileManager: &types.ManagedObjectReference{Type: "FileManager", Value: "FileManager"},
+ DatastoreNamespaceManager: &types.ManagedObjectReference{Type: "DatastoreNamespaceManager", Value: "DatastoreNamespaceManager"},
+ VirtualDiskManager: &types.ManagedObjectReference{Type: "VirtualDiskManager", Value: "virtualDiskManager"},
+ VirtualizationManager: (*types.ManagedObjectReference)(nil),
+ SnmpSystem: &types.ManagedObjectReference{Type: "HostSnmpSystem", Value: "SnmpSystem"},
+ VmProvisioningChecker: &types.ManagedObjectReference{Type: "VirtualMachineProvisioningChecker", Value: "ProvChecker"},
+ VmCompatibilityChecker: &types.ManagedObjectReference{Type: "VirtualMachineCompatibilityChecker", Value: "CompatChecker"},
+ OvfManager: &types.ManagedObjectReference{Type: "OvfManager", Value: "OvfManager"},
+ IpPoolManager: &types.ManagedObjectReference{Type: "IpPoolManager", Value: "IpPoolManager"},
+ DvSwitchManager: &types.ManagedObjectReference{Type: "DistributedVirtualSwitchManager", Value: "DVSManager"},
+ HostProfileManager: &types.ManagedObjectReference{Type: "HostProfileManager", Value: "HostProfileManager"},
+ ClusterProfileManager: &types.ManagedObjectReference{Type: "ClusterProfileManager", Value: "ClusterProfileManager"},
+ ComplianceManager: &types.ManagedObjectReference{Type: "ProfileComplianceManager", Value: "MoComplianceManager"},
+ LocalizationManager: &types.ManagedObjectReference{Type: "LocalizationManager", Value: "LocalizationManager"},
+ StorageResourceManager: &types.ManagedObjectReference{Type: "StorageResourceManager", Value: "StorageResourceManager"},
+ GuestOperationsManager: &types.ManagedObjectReference{Type: "GuestOperationsManager", Value: "guestOperationsManager"},
+ OverheadMemoryManager: &types.ManagedObjectReference{Type: "OverheadMemoryManager", Value: "OverheadMemoryManger"},
+ CertificateManager: &types.ManagedObjectReference{Type: "CertificateManager", Value: "certificateManager"},
+ IoFilterManager: &types.ManagedObjectReference{Type: "IoFilterManager", Value: "IoFilterManager"},
+}
diff --git a/vendor/github.com/vmware/govmomi/simulator/vpx/setting.go b/vendor/github.com/vmware/govmomi/simulator/vpx/setting.go
new file mode 100644
index 00000000..dfbb28b7
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/simulator/vpx/setting.go
@@ -0,0 +1,60 @@
+/*
+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 vpx
+
+import "github.com/vmware/govmomi/vim25/types"
+
+// Setting is captured from VC's ServiceContent.OptionManager.setting
+var Setting = []types.BaseOptionValue{
+ // This list is currently pruned to include sso options only with sso.enabled set to false
+ &types.OptionValue{
+ Key: "config.vpxd.sso.sts.uri",
+ Value: "https://127.0.0.1/sts/STSService/vsphere.local",
+ },
+ &types.OptionValue{
+ Key: "config.vpxd.sso.solutionUser.privateKey",
+ Value: "/etc/vmware-vpx/ssl/vcsoluser.key",
+ },
+ &types.OptionValue{
+ Key: "config.vpxd.sso.solutionUser.name",
+ Value: "vpxd-b643d01c-928f-469b-96a5-d571d762a78e@vsphere.local",
+ },
+ &types.OptionValue{
+ Key: "config.vpxd.sso.solutionUser.certificate",
+ Value: "/etc/vmware-vpx/ssl/vcsoluser.crt",
+ },
+ &types.OptionValue{
+ Key: "config.vpxd.sso.groupcheck.uri",
+ Value: "https://127.0.0.1/sso-adminserver/sdk/vsphere.local",
+ },
+ &types.OptionValue{
+ Key: "config.vpxd.sso.enabled",
+ Value: "false",
+ },
+ &types.OptionValue{
+ Key: "config.vpxd.sso.default.isGroup",
+ Value: "false",
+ },
+ &types.OptionValue{
+ Key: "config.vpxd.sso.default.admin",
+ Value: "Administrator@vsphere.local",
+ },
+ &types.OptionValue{
+ Key: "config.vpxd.sso.admin.uri",
+ Value: "https://127.0.0.1/sso-adminserver/sdk/vsphere.local",
+ },
+}
diff --git a/vendor/github.com/vmware/govmomi/task/wait.go b/vendor/github.com/vmware/govmomi/task/wait.go
index 379093ee..19fee538 100644
--- a/vendor/github.com/vmware/govmomi/task/wait.go
+++ b/vendor/github.com/vmware/govmomi/task/wait.go
@@ -68,6 +68,11 @@ func (t *taskCallback) fn(pc []types.PropertyChange) bool {
t.info = &ti
}
+ // t.info could be nil if pc can't satify the rules above
+ if t.info == nil {
+ return false
+ }
+
pr := taskProgress{t.info}
// Store copy of error, so Wait() can return it as well.
diff --git a/vendor/github.com/vmware/govmomi/toolbox/backdoor.go b/vendor/github.com/vmware/govmomi/toolbox/backdoor.go
new file mode 100644
index 00000000..62927316
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/backdoor.go
@@ -0,0 +1,80 @@
+/*
+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 toolbox
+
+import (
+ "errors"
+
+ "github.com/vmware/vmw-guestinfo/message"
+ "github.com/vmware/vmw-guestinfo/vmcheck"
+)
+
+const (
+ rpciProtocol uint32 = 0x49435052
+ tcloProtocol uint32 = 0x4f4c4354
+)
+
+var (
+ ErrNotVirtualWorld = errors.New("not in a virtual world")
+)
+
+type backdoorChannel struct {
+ protocol uint32
+
+ *message.Channel
+}
+
+func (b *backdoorChannel) Start() error {
+ if !vmcheck.IsVirtualCPU() {
+ return ErrNotVirtualWorld
+ }
+
+ channel, err := message.NewChannel(b.protocol)
+ if err != nil {
+ return err
+ }
+
+ b.Channel = channel
+
+ return nil
+}
+
+func (b *backdoorChannel) Stop() error {
+ if b.Channel == nil {
+ return nil
+ }
+
+ err := b.Channel.Close()
+
+ b.Channel = nil
+
+ return err
+}
+
+// NewBackdoorChannelOut creates a Channel for use with the RPCI protocol
+func NewBackdoorChannelOut() Channel {
+ return &backdoorChannel{
+ protocol: rpciProtocol,
+ }
+}
+
+// NewBackdoorChannelIn creates a Channel for use with the TCLO protocol
+func NewBackdoorChannelIn() Channel {
+ return &backdoorChannel{
+ protocol: tcloProtocol,
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/channel.go b/vendor/github.com/vmware/govmomi/toolbox/channel.go
new file mode 100644
index 00000000..8d217833
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/channel.go
@@ -0,0 +1,58 @@
+/*
+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 toolbox
+
+import (
+ "bytes"
+ "fmt"
+)
+
+// Channel abstracts the guest<->vmx RPC transport
+type Channel interface {
+ Start() error
+ Stop() error
+ Send([]byte) error
+ Receive() ([]byte, error)
+}
+
+var (
+ rpciOK = []byte{'1', ' '}
+ rpciERR = []byte{'0', ' '}
+)
+
+// ChannelOut extends Channel to provide RPCI protocol helpers
+type ChannelOut struct {
+ Channel
+}
+
+// Request sends an RPC command to the vmx and checks the return code for success or error
+func (c *ChannelOut) Request(request []byte) ([]byte, error) {
+ if err := c.Send(request); err != nil {
+ return nil, err
+ }
+
+ reply, err := c.Receive()
+ if err != nil {
+ return nil, err
+ }
+
+ if bytes.HasPrefix(reply, rpciOK) {
+ return reply[2:], nil
+ }
+
+ return nil, fmt.Errorf("request %q: %q", request, reply)
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/command.go b/vendor/github.com/vmware/govmomi/toolbox/command.go
new file mode 100644
index 00000000..84d4b808
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/command.go
@@ -0,0 +1,708 @@
+/*
+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 toolbox
+
+import (
+ "bytes"
+ "encoding/base64"
+ "encoding/binary"
+ "encoding/hex"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "time"
+
+ "github.com/vmware/govmomi/toolbox/hgfs"
+ "github.com/vmware/govmomi/toolbox/vix"
+)
+
+type CommandHandler func(vix.CommandRequestHeader, []byte) ([]byte, error)
+
+type CommandServer struct {
+ Out *ChannelOut
+
+ ProcessManager *ProcessManager
+
+ Authenticate func(vix.CommandRequestHeader, []byte) error
+
+ ProcessStartCommand func(*ProcessManager, *vix.StartProgramRequest) (int64, error)
+
+ handlers map[uint32]CommandHandler
+
+ FileServer *hgfs.Server
+}
+
+func registerCommandServer(service *Service) *CommandServer {
+ server := &CommandServer{
+ Out: service.out,
+ ProcessManager: NewProcessManager(),
+ }
+
+ server.handlers = map[uint32]CommandHandler{
+ vix.CommandGetToolsState: server.GetToolsState,
+ vix.CommandStartProgram: server.StartCommand,
+ vix.CommandTerminateProcess: server.KillProcess,
+ vix.CommandListProcessesEx: server.ListProcesses,
+ vix.CommandReadEnvVariables: server.ReadEnvironmentVariables,
+ vix.CommandCreateTemporaryFileEx: server.CreateTemporaryFile,
+ vix.CommandCreateTemporaryDirectory: server.CreateTemporaryDirectory,
+ vix.CommandDeleteGuestFileEx: server.DeleteFile,
+ vix.CommandCreateDirectoryEx: server.CreateDirectory,
+ vix.CommandDeleteGuestDirectoryEx: server.DeleteDirectory,
+ vix.CommandMoveGuestFileEx: server.MoveFile,
+ vix.CommandMoveGuestDirectory: server.MoveDirectory,
+ vix.CommandListFiles: server.ListFiles,
+ vix.CommandSetGuestFileAttributes: server.SetGuestFileAttributes,
+ vix.CommandInitiateFileTransferFromGuest: server.InitiateFileTransferFromGuest,
+ vix.CommandInitiateFileTransferToGuest: server.InitiateFileTransferToGuest,
+ vix.HgfsSendPacketCommand: server.ProcessHgfsPacket,
+ }
+
+ server.ProcessStartCommand = DefaultStartCommand
+
+ service.RegisterHandler("Vix_1_Relayed_Command", server.Dispatch)
+
+ return server
+}
+
+func commandResult(header vix.CommandRequestHeader, rc int, err error, response []byte) []byte {
+ // All Foundry tools commands return results that start with a foundry error
+ // and a guest-OS-specific error (e.g. errno)
+ errno := 0
+
+ if err != nil {
+ // TODO: inspect err for system error, setting errno
+
+ response = []byte(err.Error())
+
+ log.Printf("[vix] op=%d error: %s", header.OpCode, err)
+ }
+
+ buf := bytes.NewBufferString(fmt.Sprintf("%d %d ", rc, errno))
+
+ if header.CommonFlags&vix.CommandGuestReturnsBinary != 0 {
+ // '#' delimits end of ascii and the start of the binary data (see ToolsDaemonTcloReceiveVixCommand)
+ _ = buf.WriteByte('#')
+ }
+
+ _, _ = buf.Write(response)
+
+ if header.CommonFlags&vix.CommandGuestReturnsBinary == 0 {
+ // this is not binary data, so it should be a NULL terminated string (see ToolsDaemonTcloReceiveVixCommand)
+ _ = buf.WriteByte(0)
+ }
+
+ return buf.Bytes()
+}
+
+func (c *CommandServer) Dispatch(data []byte) ([]byte, error) {
+ // See ToolsDaemonTcloGetQuotedString
+ if data[0] == '"' {
+ data = data[1:]
+ }
+
+ var name string
+
+ ix := bytes.IndexByte(data, '"')
+ if ix > 0 {
+ name = string(data[:ix])
+ data = data[ix+1:]
+ }
+ // skip the NULL
+ if data[0] == 0 {
+ data = data[1:]
+ }
+
+ if Trace {
+ fmt.Fprintf(os.Stderr, "vix dispatch %q...\n%s\n", name, hex.Dump(data))
+ }
+
+ var header vix.CommandRequestHeader
+ buf := bytes.NewBuffer(data)
+ err := binary.Read(buf, binary.LittleEndian, &header)
+ if err != nil {
+ return nil, err
+ }
+
+ if header.Magic != vix.CommandMagicWord {
+ return commandResult(header, vix.InvalidMessageHeader, nil, nil), nil
+ }
+
+ handler, ok := c.handlers[header.OpCode]
+ if !ok {
+ return commandResult(header, vix.UnrecognizedCommandInGuest, nil, nil), nil
+ }
+
+ if header.OpCode != vix.CommandGetToolsState {
+ // Every command expect GetToolsState requires authentication
+ creds := buf.Bytes()[header.BodyLength:]
+
+ err = c.authenticate(header, creds[:header.CredentialLength])
+ if err != nil {
+ return commandResult(header, vix.AuthenticationFail, err, nil), nil
+ }
+ }
+
+ rc := vix.OK
+
+ response, err := handler(header, buf.Bytes())
+ if err != nil {
+ rc = vix.ErrorCode(err)
+ }
+
+ return commandResult(header, rc, err, response), nil
+}
+
+func (c *CommandServer) RegisterHandler(op uint32, handler CommandHandler) {
+ c.handlers[op] = handler
+}
+
+func (c *CommandServer) GetToolsState(_ vix.CommandRequestHeader, _ []byte) ([]byte, error) {
+ hostname, _ := os.Hostname()
+ osname := fmt.Sprintf("%s-%s", runtime.GOOS, runtime.GOARCH)
+
+ // Note that vmtoolsd sends back 40 or so of these properties, sticking with the minimal set for now.
+ props := vix.PropertyList{
+ vix.NewStringProperty(vix.PropertyGuestOsVersion, osname),
+ vix.NewStringProperty(vix.PropertyGuestOsVersionShort, osname),
+ vix.NewStringProperty(vix.PropertyGuestToolsProductNam, "VMware Tools (Go)"),
+ vix.NewStringProperty(vix.PropertyGuestToolsVersion, "10.0.5 build-3227872 (Compatible)"),
+ vix.NewStringProperty(vix.PropertyGuestName, hostname),
+ vix.NewInt32Property(vix.PropertyGuestToolsAPIOptions, 0x0001), // TODO: const VIX_TOOLSFEATURE_SUPPORT_GET_HANDLE_STATE
+ vix.NewInt32Property(vix.PropertyGuestOsFamily, 1), // TODO: const GUEST_OS_FAMILY_*
+ vix.NewBoolProperty(vix.PropertyGuestStartProgramEnabled, true),
+ vix.NewBoolProperty(vix.PropertyGuestTerminateProcessEnabled, true),
+ vix.NewBoolProperty(vix.PropertyGuestListProcessesEnabled, true),
+ vix.NewBoolProperty(vix.PropertyGuestReadEnvironmentVariableEnabled, true),
+ vix.NewBoolProperty(vix.PropertyGuestMakeDirectoryEnabled, true),
+ vix.NewBoolProperty(vix.PropertyGuestDeleteFileEnabled, true),
+ vix.NewBoolProperty(vix.PropertyGuestDeleteDirectoryEnabled, true),
+ vix.NewBoolProperty(vix.PropertyGuestMoveDirectoryEnabled, true),
+ vix.NewBoolProperty(vix.PropertyGuestMoveFileEnabled, true),
+ vix.NewBoolProperty(vix.PropertyGuestCreateTempFileEnabled, true),
+ vix.NewBoolProperty(vix.PropertyGuestCreateTempDirectoryEnabled, true),
+ vix.NewBoolProperty(vix.PropertyGuestListFilesEnabled, true),
+ vix.NewBoolProperty(vix.PropertyGuestChangeFileAttributesEnabled, true),
+ vix.NewBoolProperty(vix.PropertyGuestInitiateFileTransferFromGuestEnabled, true),
+ vix.NewBoolProperty(vix.PropertyGuestInitiateFileTransferToGuestEnabled, true),
+ }
+
+ src, _ := props.MarshalBinary()
+ enc := base64.StdEncoding
+ buf := make([]byte, enc.EncodedLen(len(src)))
+ enc.Encode(buf, src)
+
+ return buf, nil
+}
+
+func (c *CommandServer) StartCommand(header vix.CommandRequestHeader, data []byte) ([]byte, error) {
+ r := &vix.StartProgramRequest{
+ CommandRequestHeader: header,
+ }
+
+ err := r.UnmarshalBinary(data)
+ if err != nil {
+ return nil, err
+ }
+
+ pid, err := c.ProcessStartCommand(c.ProcessManager, r)
+ if err != nil {
+ return nil, err
+ }
+
+ return append([]byte(fmt.Sprintf("%d", pid)), 0), nil
+}
+
+func DefaultStartCommand(m *ProcessManager, r *vix.StartProgramRequest) (int64, error) {
+ p := NewProcess()
+
+ switch r.ProgramPath {
+ case "http.RoundTrip":
+ p = NewProcessRoundTrip()
+ default:
+ // Standard vmware-tools requires an absolute path,
+ // we'll enable IO redirection by default without an absolute path.
+ if !strings.Contains(r.ProgramPath, "/") {
+ p = p.WithIO()
+ }
+ }
+
+ return m.Start(r, p)
+}
+
+func (c *CommandServer) KillProcess(header vix.CommandRequestHeader, data []byte) ([]byte, error) {
+ r := &vix.KillProcessRequest{
+ CommandRequestHeader: header,
+ }
+
+ err := r.UnmarshalBinary(data)
+ if err != nil {
+ return nil, err
+ }
+
+ if c.ProcessManager.Kill(r.Body.Pid) {
+ return nil, err
+ }
+
+ // TODO: could kill process started outside of toolbox
+
+ return nil, vix.Error(vix.NoSuchProcess)
+}
+
+func (c *CommandServer) ListProcesses(header vix.CommandRequestHeader, data []byte) ([]byte, error) {
+ r := &vix.ListProcessesRequest{
+ CommandRequestHeader: header,
+ }
+
+ err := r.UnmarshalBinary(data)
+ if err != nil {
+ return nil, err
+ }
+
+ state := c.ProcessManager.ListProcesses(r.Pids)
+
+ return state, nil
+}
+
+func (c *CommandServer) ReadEnvironmentVariables(header vix.CommandRequestHeader, data []byte) ([]byte, error) {
+ r := &vix.ReadEnvironmentVariablesRequest{
+ CommandRequestHeader: header,
+ }
+
+ err := r.UnmarshalBinary(data)
+ if err != nil {
+ return nil, err
+ }
+
+ buf := new(bytes.Buffer)
+
+ if len(r.Names) == 0 {
+ for _, e := range os.Environ() {
+ _, _ = buf.WriteString(fmt.Sprintf("%s", xmlEscape.Replace(e)))
+ }
+ } else {
+ for _, key := range r.Names {
+ val := os.Getenv(key)
+ if val == "" {
+ continue
+ }
+ _, _ = buf.WriteString(fmt.Sprintf("%s=%s", xmlEscape.Replace(key), xmlEscape.Replace(val)))
+ }
+ }
+
+ return buf.Bytes(), nil
+}
+
+func (c *CommandServer) CreateTemporaryFile(header vix.CommandRequestHeader, data []byte) ([]byte, error) {
+ r := &vix.CreateTempFileRequest{
+ CommandRequestHeader: header,
+ }
+
+ err := r.UnmarshalBinary(data)
+ if err != nil {
+ return nil, err
+ }
+
+ f, err := ioutil.TempFile(r.DirectoryPath, r.FilePrefix+"vmware")
+ if err != nil {
+ return nil, err
+ }
+
+ _ = f.Close()
+
+ return []byte(f.Name()), nil
+}
+
+func (c *CommandServer) CreateTemporaryDirectory(header vix.CommandRequestHeader, data []byte) ([]byte, error) {
+ r := &vix.CreateTempFileRequest{
+ CommandRequestHeader: header,
+ }
+
+ err := r.UnmarshalBinary(data)
+ if err != nil {
+ return nil, err
+ }
+
+ name, err := ioutil.TempDir(r.DirectoryPath, r.FilePrefix+"vmware")
+ if err != nil {
+ return nil, err
+ }
+
+ return []byte(name), nil
+}
+
+func (c *CommandServer) DeleteFile(header vix.CommandRequestHeader, data []byte) ([]byte, error) {
+ r := &vix.FileRequest{
+ CommandRequestHeader: header,
+ }
+
+ err := r.UnmarshalBinary(data)
+ if err != nil {
+ return nil, err
+ }
+
+ info, err := os.Stat(r.GuestPathName)
+ if err != nil {
+ return nil, err
+ }
+
+ if info.IsDir() {
+ return nil, vix.Error(vix.NotAFile)
+ }
+
+ err = os.Remove(r.GuestPathName)
+
+ return nil, err
+}
+
+func (c *CommandServer) DeleteDirectory(header vix.CommandRequestHeader, data []byte) ([]byte, error) {
+ r := &vix.DirRequest{
+ CommandRequestHeader: header,
+ }
+
+ err := r.UnmarshalBinary(data)
+ if err != nil {
+ return nil, err
+ }
+
+ info, err := os.Stat(r.GuestPathName)
+ if err != nil {
+ return nil, err
+ }
+
+ if !info.IsDir() {
+ return nil, vix.Error(vix.NotADirectory)
+ }
+
+ if r.Body.Recursive {
+ err = os.RemoveAll(r.GuestPathName)
+ } else {
+ err = os.Remove(r.GuestPathName)
+ }
+
+ return nil, err
+}
+
+func (c *CommandServer) CreateDirectory(header vix.CommandRequestHeader, data []byte) ([]byte, error) {
+ r := &vix.DirRequest{
+ CommandRequestHeader: header,
+ }
+
+ err := r.UnmarshalBinary(data)
+ if err != nil {
+ return nil, err
+ }
+
+ mkdir := os.Mkdir
+
+ if r.Body.Recursive {
+ mkdir = os.MkdirAll
+ }
+
+ err = mkdir(r.GuestPathName, 0700)
+
+ return nil, err
+}
+
+func (c *CommandServer) MoveDirectory(header vix.CommandRequestHeader, data []byte) ([]byte, error) {
+ r := &vix.RenameFileRequest{
+ CommandRequestHeader: header,
+ }
+
+ err := r.UnmarshalBinary(data)
+ if err != nil {
+ return nil, err
+ }
+
+ info, err := os.Stat(r.OldPathName)
+ if err != nil {
+ return nil, err
+ }
+
+ if !info.IsDir() {
+ return nil, vix.Error(vix.NotADirectory)
+ }
+
+ if !r.Body.Overwrite {
+ info, err = os.Stat(r.NewPathName)
+ if err == nil {
+ return nil, vix.Error(vix.FileAlreadyExists)
+ }
+ }
+
+ return nil, os.Rename(r.OldPathName, r.NewPathName)
+}
+
+func (c *CommandServer) MoveFile(header vix.CommandRequestHeader, data []byte) ([]byte, error) {
+ r := &vix.RenameFileRequest{
+ CommandRequestHeader: header,
+ }
+
+ err := r.UnmarshalBinary(data)
+ if err != nil {
+ return nil, err
+ }
+
+ info, err := os.Stat(r.OldPathName)
+ if err != nil {
+ return nil, err
+ }
+
+ if info.IsDir() {
+ return nil, vix.Error(vix.NotAFile)
+ }
+
+ if !r.Body.Overwrite {
+ info, err = os.Stat(r.NewPathName)
+ if err == nil {
+ return nil, vix.Error(vix.FileAlreadyExists)
+ }
+ }
+
+ return nil, os.Rename(r.OldPathName, r.NewPathName)
+}
+
+func (c *CommandServer) ListFiles(header vix.CommandRequestHeader, data []byte) ([]byte, error) {
+ r := &vix.ListFilesRequest{
+ CommandRequestHeader: header,
+ }
+
+ err := r.UnmarshalBinary(data)
+ if err != nil {
+ return nil, err
+ }
+
+ info, err := os.Lstat(r.GuestPathName)
+ if err != nil {
+ return nil, err
+ }
+
+ var dir string
+ var files []os.FileInfo
+
+ if info.IsDir() {
+ dir = r.GuestPathName
+ files, err = ioutil.ReadDir(r.GuestPathName)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ dir = filepath.Dir(r.GuestPathName)
+ files = append(files, info)
+ }
+
+ offset := r.Body.Offset + uint64(r.Body.Index)
+ total := uint64(len(files)) - offset
+
+ files = files[offset:]
+
+ var remaining uint64
+
+ if r.Body.MaxResults > 0 && total > uint64(r.Body.MaxResults) {
+ remaining = total - uint64(r.Body.MaxResults)
+ files = files[:r.Body.MaxResults]
+ }
+
+ buf := new(bytes.Buffer)
+ buf.WriteString(fmt.Sprintf("%d", remaining))
+
+ for _, info = range files {
+ buf.WriteString(fileExtendedInfoFormat(dir, info))
+ }
+
+ return buf.Bytes(), nil
+}
+
+func chtimes(r *vix.SetGuestFileAttributesRequest) error {
+ var mtime, atime *time.Time
+
+ if r.IsSet(vix.FileAttributeSetModifyDate) {
+ t := time.Unix(r.Body.ModificationTime, 0)
+ mtime = &t
+ }
+
+ if r.IsSet(vix.FileAttributeSetAccessDate) {
+ t := time.Unix(r.Body.AccessTime, 0)
+ atime = &t
+ }
+
+ if mtime == nil && atime == nil {
+ return nil
+ }
+
+ info, err := os.Stat(r.GuestPathName)
+ if err != nil {
+ return err
+ }
+
+ if mtime == nil {
+ t := info.ModTime()
+ mtime = &t
+ }
+
+ if atime == nil {
+ t := info.ModTime()
+ atime = &t
+ }
+
+ return os.Chtimes(r.GuestPathName, *atime, *mtime)
+}
+
+func chown(r *vix.SetGuestFileAttributesRequest) error {
+ uid := -1
+ gid := -1
+
+ if r.IsSet(vix.FileAttributeSetUnixOwnerid) {
+ uid = int(r.Body.OwnerID)
+ }
+
+ if r.IsSet(vix.FileAttributeSetUnixGroupid) {
+ gid = int(r.Body.GroupID)
+ }
+
+ if uid == -1 && gid == -1 {
+ return nil
+ }
+
+ return os.Chown(r.GuestPathName, uid, gid)
+}
+
+func chmod(r *vix.SetGuestFileAttributesRequest) error {
+ if r.IsSet(vix.FileAttributeSetUnixPermissions) {
+ return os.Chmod(r.GuestPathName, os.FileMode(r.Body.Permissions).Perm())
+ }
+
+ return nil
+}
+
+func (c *CommandServer) SetGuestFileAttributes(header vix.CommandRequestHeader, data []byte) ([]byte, error) {
+ r := &vix.SetGuestFileAttributesRequest{
+ CommandRequestHeader: header,
+ }
+
+ err := r.UnmarshalBinary(data)
+ if err != nil {
+ return nil, err
+ }
+
+ for _, set := range []func(*vix.SetGuestFileAttributesRequest) error{chtimes, chown, chmod} {
+ err = set(r)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return nil, nil
+}
+
+func (c *CommandServer) InitiateFileTransferFromGuest(header vix.CommandRequestHeader, data []byte) ([]byte, error) {
+ r := &vix.ListFilesRequest{
+ CommandRequestHeader: header,
+ }
+
+ err := r.UnmarshalBinary(data)
+ if err != nil {
+ return nil, err
+ }
+
+ info, err := c.FileServer.Stat(r.GuestPathName)
+ if err != nil {
+ return nil, err
+ }
+
+ if info.Mode()&os.ModeSymlink == os.ModeSymlink {
+ return nil, vix.Error(vix.InvalidArg)
+ }
+
+ if info.IsDir() {
+ return nil, vix.Error(vix.NotAFile)
+ }
+
+ return []byte(fileExtendedInfoFormat("", info)), nil
+}
+
+func (c *CommandServer) InitiateFileTransferToGuest(header vix.CommandRequestHeader, data []byte) ([]byte, error) {
+ r := &vix.InitiateFileTransferToGuestRequest{
+ CommandRequestHeader: header,
+ }
+
+ err := r.UnmarshalBinary(data)
+ if err != nil {
+ return nil, err
+ }
+
+ info, err := c.FileServer.Stat(r.GuestPathName)
+ if err == nil {
+ if info.Mode()&os.ModeSymlink == os.ModeSymlink {
+ return nil, vix.Error(vix.InvalidArg)
+ }
+
+ if info.IsDir() {
+ return nil, vix.Error(vix.NotAFile)
+ }
+
+ if !r.Body.Overwrite {
+ return nil, vix.Error(vix.FileAlreadyExists)
+ }
+ } else {
+ if !os.IsNotExist(err) {
+ return nil, err
+ }
+ }
+
+ return nil, nil
+}
+
+func (c *CommandServer) ProcessHgfsPacket(header vix.CommandRequestHeader, data []byte) ([]byte, error) {
+ r := &vix.CommandHgfsSendPacket{
+ CommandRequestHeader: header,
+ }
+
+ err := r.UnmarshalBinary(data)
+ if err != nil {
+ return nil, err
+ }
+
+ return c.FileServer.Dispatch(r.Packet)
+}
+
+func (c *CommandServer) authenticate(r vix.CommandRequestHeader, data []byte) error {
+ if c.Authenticate != nil {
+ return c.Authenticate(r, data)
+ }
+
+ switch r.UserCredentialType {
+ case vix.UserCredentialTypeNamePassword:
+ var c vix.UserCredentialNamePassword
+
+ if err := c.UnmarshalBinary(data); err != nil {
+ return err
+ }
+
+ if Trace {
+ fmt.Fprintf(traceLog, "ignoring credentials: %q:%q\n", c.Name, c.Password)
+ }
+
+ return nil
+ default:
+ return fmt.Errorf("unsupported UserCredentialType=%d", r.UserCredentialType)
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/guest_info.go b/vendor/github.com/vmware/govmomi/toolbox/guest_info.go
new file mode 100644
index 00000000..9054cedf
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/guest_info.go
@@ -0,0 +1,202 @@
+/*
+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 toolbox
+
+import (
+ "bytes"
+ "fmt"
+ "net"
+
+ "github.com/davecgh/go-xdr/xdr2"
+)
+
+// Defs from: open-vm-tools/lib/guestRpc/nicinfo.x
+
+type TypedIPAddress struct {
+ Type int32
+ Address []byte
+}
+
+type IPAddressEntry struct {
+ Address TypedIPAddress
+ PrefixLength uint32
+ Origin *int32 `xdr:"optional"`
+ Status *int32 `xdr:"optional"`
+}
+
+type InetCidrRouteEntry struct {
+ Dest TypedIPAddress
+ PrefixLength uint32
+ NextHop *TypedIPAddress `xdr:"optional"`
+ IfIndex uint32
+ Type int32
+ Metric uint32
+}
+
+type DNSConfigInfo struct {
+ HostName *string `xdr:"optional"`
+ DomainName *string `xdr:"optional"`
+ Servers []TypedIPAddress
+ Search *string `xdr:"optional"`
+}
+
+type WinsConfigInfo struct {
+ Primary TypedIPAddress
+ Secondary TypedIPAddress
+}
+
+type DhcpConfigInfo struct {
+ Enabled bool
+ Settings string
+}
+
+type GuestNicV3 struct {
+ MacAddress string
+ IPs []IPAddressEntry
+ DNSConfigInfo *DNSConfigInfo `xdr:"optional"`
+ WinsConfigInfo *WinsConfigInfo `xdr:"optional"`
+ DhcpConfigInfov4 *DhcpConfigInfo `xdr:"optional"`
+ DhcpConfigInfov6 *DhcpConfigInfo `xdr:"optional"`
+}
+
+type NicInfoV3 struct {
+ Nics []GuestNicV3
+ Routes []InetCidrRouteEntry
+ DNSConfigInfo *DNSConfigInfo `xdr:"optional"`
+ WinsConfigInfo *WinsConfigInfo `xdr:"optional"`
+ DhcpConfigInfov4 *DhcpConfigInfo `xdr:"optional"`
+ DhcpConfigInfov6 *DhcpConfigInfo `xdr:"optional"`
+}
+
+type GuestNicInfo struct {
+ Version int32
+ V3 *NicInfoV3 `xdr:"optional"`
+}
+
+func EncodeXDR(val interface{}) ([]byte, error) {
+ var buf bytes.Buffer
+
+ _, err := xdr.Marshal(&buf, val)
+ if err != nil {
+ return nil, err
+ }
+
+ return buf.Bytes(), nil
+}
+
+func DecodeXDR(buf []byte, val interface{}) error {
+ r := bytes.NewReader(buf)
+ _, err := xdr.Unmarshal(r, val)
+ return err
+}
+
+func NewGuestNicInfo() *GuestNicInfo {
+ return &GuestNicInfo{
+ Version: 3,
+ V3: &NicInfoV3{},
+ }
+}
+
+func (nic *GuestNicV3) AddIP(addr net.Addr) {
+ ip, ok := addr.(*net.IPNet)
+ if !ok {
+ return
+ }
+
+ kind := int32(1) // IAT_IPV4
+ if ip.IP.To4() == nil {
+ kind = 2 // IAT_IPV6
+ } else {
+ ip.IP = ip.IP.To4() // convert to 4-byte representation
+ }
+
+ size, _ := ip.Mask.Size()
+
+ // nicinfo.x defines enum IpAddressStatus, but vmtoolsd only uses IAS_PREFERRED
+ var status int32 = 1 // IAS_PREFERRED
+
+ e := IPAddressEntry{
+ Address: TypedIPAddress{
+ Type: kind,
+ Address: []byte(ip.IP),
+ },
+ PrefixLength: uint32(size),
+ Status: &status,
+ }
+
+ nic.IPs = append(nic.IPs, e)
+}
+
+func GuestInfoCommand(kind int, req []byte) []byte {
+ request := fmt.Sprintf("SetGuestInfo %d ", kind)
+ return append([]byte(request), req...)
+}
+
+var (
+ netInterfaces = net.Interfaces
+ maxNics = 16 // guestRpc/nicinfo.x:NICINFO_MAX_NICS
+)
+
+//
+func DefaultGuestNicInfo() *GuestNicInfo {
+ proto := NewGuestNicInfo()
+ info := proto.V3
+ // #nosec: Errors unhandled
+ ifs, _ := netInterfaces()
+
+ for _, i := range ifs {
+ if i.Flags&net.FlagLoopback == net.FlagLoopback {
+ continue
+ }
+
+ if len(i.HardwareAddr) == 0 {
+ continue // Not useful from outside the guest without a MAC
+ }
+
+ // #nosec: Errors unhandled
+ addrs, _ := i.Addrs()
+
+ if len(addrs) == 0 {
+ continue // Not useful from outside the guest without an IP
+ }
+
+ nic := GuestNicV3{
+ MacAddress: i.HardwareAddr.String(),
+ }
+
+ for _, addr := range addrs {
+ nic.AddIP(addr)
+ }
+
+ info.Nics = append(info.Nics, nic)
+
+ if len(info.Nics) >= maxNics {
+ break
+ }
+ }
+
+ return proto
+}
+
+func GuestInfoNicInfoRequest() ([]byte, error) {
+ r, err := EncodeXDR(DefaultGuestNicInfo())
+ if err != nil {
+ return nil, err
+ }
+
+ return GuestInfoCommand(9 /*INFO_IPADDRESS_V3*/, r), nil
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/hgfs/archive.go b/vendor/github.com/vmware/govmomi/toolbox/hgfs/archive.go
new file mode 100644
index 00000000..24908a00
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/hgfs/archive.go
@@ -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.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package hgfs
+
+import (
+ "archive/tar"
+ "bufio"
+ "bytes"
+ "compress/gzip"
+ "io"
+ "io/ioutil"
+ "log"
+ "math"
+ "net/url"
+ "os"
+ "path/filepath"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/vmware/govmomi/toolbox/vix"
+)
+
+// ArchiveScheme is the default scheme used to register the archive FileHandler
+var ArchiveScheme = "archive"
+
+// ArchiveHandler implements a FileHandler for transferring directories.
+type ArchiveHandler struct {
+ Read func(*url.URL, *tar.Reader) error
+ Write func(*url.URL, *tar.Writer) error
+}
+
+// NewArchiveHandler returns a FileHandler implementation for transferring directories using gzip'd tar files.
+func NewArchiveHandler() FileHandler {
+ return &ArchiveHandler{
+ Read: archiveRead,
+ Write: archiveWrite,
+ }
+}
+
+// Stat implements FileHandler.Stat
+func (*ArchiveHandler) Stat(u *url.URL) (os.FileInfo, error) {
+ switch u.Query().Get("format") {
+ case "", "tar", "tgz":
+ // ok
+ default:
+ log.Printf("unknown archive format: %q", u)
+ return nil, vix.Error(vix.InvalidArg)
+ }
+
+ return &archive{
+ name: u.Path,
+ size: math.MaxInt64,
+ }, nil
+}
+
+// Open implements FileHandler.Open
+func (h *ArchiveHandler) Open(u *url.URL, mode int32) (File, error) {
+ switch mode {
+ case OpenModeReadOnly:
+ return h.newArchiveFromGuest(u)
+ case OpenModeWriteOnly:
+ return h.newArchiveToGuest(u)
+ default:
+ return nil, os.ErrNotExist
+ }
+}
+
+// archive implements the hgfs.File and os.FileInfo interfaces.
+type archive struct {
+ name string
+ size int64
+ done func() error
+
+ io.Reader
+ io.Writer
+}
+
+// Name implementation of the os.FileInfo interface method.
+func (a *archive) Name() string {
+ return a.name
+}
+
+// Size implementation of the os.FileInfo interface method.
+func (a *archive) Size() int64 {
+ return a.size
+}
+
+// Mode implementation of the os.FileInfo interface method.
+func (a *archive) Mode() os.FileMode {
+ return 0600
+}
+
+// ModTime implementation of the os.FileInfo interface method.
+func (a *archive) ModTime() time.Time {
+ return time.Now()
+}
+
+// IsDir implementation of the os.FileInfo interface method.
+func (a *archive) IsDir() bool {
+ return false
+}
+
+// Sys implementation of the os.FileInfo interface method.
+func (a *archive) Sys() interface{} {
+ return nil
+}
+
+// The trailer is required since TransferFromGuest requires a Content-Length,
+// which toolbox doesn't know ahead of time as the gzip'd tarball never touches the disk.
+// HTTP clients need to be aware of this and stop reading when they see the 2nd gzip header.
+var gzipHeader = []byte{0x1f, 0x8b, 0x08} // rfc1952 {ID1, ID2, CM}
+
+var gzipTrailer = true
+
+// newArchiveFromGuest returns an hgfs.File implementation to read a directory as a gzip'd tar.
+func (h *ArchiveHandler) newArchiveFromGuest(u *url.URL) (File, error) {
+ r, w := io.Pipe()
+
+ a := &archive{
+ name: u.Path,
+ done: r.Close,
+ Reader: r,
+ Writer: w,
+ }
+
+ var z io.Writer = w
+ var c io.Closer = ioutil.NopCloser(nil)
+
+ switch u.Query().Get("format") {
+ case "tgz":
+ gz := gzip.NewWriter(w)
+ z = gz
+ c = gz
+ }
+
+ tw := tar.NewWriter(z)
+
+ go func() {
+ err := h.Write(u, tw)
+
+ _ = tw.Close()
+ _ = c.Close()
+ if gzipTrailer {
+ _, _ = w.Write(gzipHeader)
+ }
+ _ = w.CloseWithError(err)
+ }()
+
+ return a, nil
+}
+
+// newArchiveToGuest returns an hgfs.File implementation to expand a gzip'd tar into a directory.
+func (h *ArchiveHandler) newArchiveToGuest(u *url.URL) (File, error) {
+ r, w := io.Pipe()
+
+ buf := bufio.NewReader(r)
+
+ a := &archive{
+ name: u.Path,
+ Reader: buf,
+ Writer: w,
+ }
+
+ var cerr error
+ var wg sync.WaitGroup
+
+ a.done = func() error {
+ _ = w.Close()
+ // We need to wait for unpack to finish to complete its work
+ // and to propagate the error if any to Close.
+ wg.Wait()
+ return cerr
+ }
+
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+
+ c := func() error {
+ // Drain the pipe of tar trailer data (two null blocks)
+ if cerr == nil {
+ _, _ = io.Copy(ioutil.Discard, a.Reader)
+ }
+ return nil
+ }
+
+ header, _ := buf.Peek(len(gzipHeader))
+
+ if bytes.Equal(header, gzipHeader) {
+ gz, err := gzip.NewReader(a.Reader)
+ if err != nil {
+ _ = r.CloseWithError(err)
+ cerr = err
+ return
+ }
+
+ c = gz.Close
+ a.Reader = gz
+ }
+
+ tr := tar.NewReader(a.Reader)
+
+ cerr = h.Read(u, tr)
+
+ _ = c()
+ _ = r.CloseWithError(cerr)
+ }()
+
+ return a, nil
+}
+
+func (a *archive) Close() error {
+ return a.done()
+}
+
+// archiveRead writes the contents of the given tar.Reader to the given directory.
+func archiveRead(u *url.URL, tr *tar.Reader) error {
+ for {
+ header, err := tr.Next()
+ if err != nil {
+ if err == io.EOF {
+ return nil
+ }
+ return err
+ }
+
+ name := filepath.Join(u.Path, header.Name)
+ mode := os.FileMode(header.Mode)
+
+ switch header.Typeflag {
+ case tar.TypeDir:
+ err = os.MkdirAll(name, mode)
+ case tar.TypeReg:
+ _ = os.MkdirAll(filepath.Dir(name), 0755)
+
+ var f *os.File
+
+ f, err = os.OpenFile(name, os.O_CREATE|os.O_RDWR|os.O_TRUNC, mode)
+ if err == nil {
+ _, cerr := io.Copy(f, tr)
+ err = f.Close()
+ if cerr != nil {
+ err = cerr
+ }
+ }
+ case tar.TypeSymlink:
+ err = os.Symlink(header.Linkname, name)
+ }
+
+ // TODO: Uid/Gid may not be meaningful here without some mapping.
+ // The other option to consider would be making use of the guest auth user ID.
+ // os.Lchown(name, header.Uid, header.Gid)
+
+ if err != nil {
+ return err
+ }
+ }
+}
+
+// archiveWrite writes the contents of the given source directory to the given tar.Writer.
+func archiveWrite(u *url.URL, tw *tar.Writer) error {
+ info, err := os.Stat(u.Path)
+ if err != nil {
+ return err
+ }
+
+ // Note that the VMX will trim any trailing slash. For example:
+ // "/foo/bar/?prefix=bar/" will end up here as "/foo/bar/?prefix=bar"
+ // Escape to avoid this: "/for/bar/?prefix=bar%2F"
+ prefix := u.Query().Get("prefix")
+
+ dir := u.Path
+
+ f := func(file string, fi os.FileInfo, err error) error {
+ if err != nil {
+ return filepath.SkipDir
+ }
+
+ name := strings.TrimPrefix(file, dir)
+ name = strings.TrimPrefix(name, "/")
+
+ if name == "" {
+ return nil // this is u.Path itself (which may or may not have a trailing "/")
+ }
+
+ if prefix != "" {
+ name = prefix + name
+ }
+
+ header, _ := tar.FileInfoHeader(fi, name)
+
+ header.Name = name
+
+ if header.Typeflag == tar.TypeDir {
+ header.Name += "/"
+ }
+
+ var f *os.File
+
+ if header.Typeflag == tar.TypeReg && fi.Size() != 0 {
+ f, err = os.Open(file)
+ if err != nil {
+ if os.IsPermission(err) {
+ return nil
+ }
+ return err
+ }
+ }
+
+ _ = tw.WriteHeader(header)
+
+ if f != nil {
+ _, err = io.Copy(tw, f)
+ _ = f.Close()
+ }
+
+ return err
+ }
+
+ if info.IsDir() {
+ return filepath.Walk(u.Path, f)
+ }
+
+ dir = filepath.Dir(dir)
+
+ return f(u.Path, info, nil)
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/hgfs/encoding.go b/vendor/github.com/vmware/govmomi/toolbox/hgfs/encoding.go
new file mode 100644
index 00000000..24f71f6c
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/hgfs/encoding.go
@@ -0,0 +1,73 @@
+/*
+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 hgfs
+
+import (
+ "bytes"
+ "encoding"
+ "encoding/binary"
+)
+
+// MarshalBinary is a wrapper around binary.Write
+func MarshalBinary(fields ...interface{}) ([]byte, error) {
+ buf := new(bytes.Buffer)
+
+ for _, p := range fields {
+ switch m := p.(type) {
+ case encoding.BinaryMarshaler:
+ data, err := m.MarshalBinary()
+ if err != nil {
+ return nil, ProtocolError(err)
+ }
+
+ _, _ = buf.Write(data)
+ case []byte:
+ _, _ = buf.Write(m)
+ case string:
+ _, _ = buf.WriteString(m)
+ default:
+ err := binary.Write(buf, binary.LittleEndian, p)
+ if err != nil {
+ return nil, ProtocolError(err)
+ }
+ }
+ }
+
+ return buf.Bytes(), nil
+}
+
+// UnmarshalBinary is a wrapper around binary.Read
+func UnmarshalBinary(data []byte, fields ...interface{}) error {
+ buf := bytes.NewBuffer(data)
+
+ for _, p := range fields {
+ switch m := p.(type) {
+ case encoding.BinaryUnmarshaler:
+ return m.UnmarshalBinary(buf.Bytes())
+ case *[]byte:
+ *m = buf.Bytes()
+ return nil
+ default:
+ err := binary.Read(buf, binary.LittleEndian, p)
+ if err != nil {
+ return ProtocolError(err)
+ }
+ }
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/hgfs/hgfs_darwin.go b/vendor/github.com/vmware/govmomi/toolbox/hgfs/hgfs_darwin.go
new file mode 100644
index 00000000..8c3dcdec
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/hgfs/hgfs_darwin.go
@@ -0,0 +1,24 @@
+/*
+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 hgfs
+
+import (
+ "os"
+)
+
+func (a *AttrV2) sysStat(info os.FileInfo) {
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/hgfs/hgfs_linux.go b/vendor/github.com/vmware/govmomi/toolbox/hgfs/hgfs_linux.go
new file mode 100644
index 00000000..16794ae5
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/hgfs/hgfs_linux.go
@@ -0,0 +1,58 @@
+/*
+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 hgfs
+
+import (
+ "os"
+ "syscall"
+)
+
+const attrMask = AttrValidAllocationSize |
+ AttrValidAccessTime | AttrValidWriteTime | AttrValidCreateTime | AttrValidChangeTime |
+ AttrValidSpecialPerms | AttrValidOwnerPerms | AttrValidGroupPerms | AttrValidOtherPerms | AttrValidEffectivePerms |
+ AttrValidUserID | AttrValidGroupID | AttrValidFileID | AttrValidVolID
+
+func (a *AttrV2) sysStat(info os.FileInfo) {
+ sys, ok := info.Sys().(*syscall.Stat_t)
+
+ if !ok {
+ return
+ }
+
+ a.AllocationSize = uint64(sys.Blocks * 512)
+
+ nt := func(t syscall.Timespec) uint64 {
+ return uint64(t.Nano()) // TODO: this is supposed to be Windows NT system time, not needed atm
+ }
+
+ a.AccessTime = nt(sys.Atim)
+ a.WriteTime = nt(sys.Mtim)
+ a.CreationTime = a.WriteTime // see HgfsGetCreationTime
+ a.AttrChangeTime = nt(sys.Ctim)
+
+ a.SpecialPerms = uint8((sys.Mode & (syscall.S_ISUID | syscall.S_ISGID | syscall.S_ISVTX)) >> 9)
+ a.OwnerPerms = uint8((sys.Mode & syscall.S_IRWXU) >> 6)
+ a.GroupPerms = uint8((sys.Mode & syscall.S_IRWXG) >> 3)
+ a.OtherPerms = uint8(sys.Mode & syscall.S_IRWXO)
+
+ a.UserID = sys.Uid
+ a.GroupID = sys.Gid
+ a.HostFileID = sys.Ino
+ a.VolumeID = uint32(sys.Dev)
+
+ a.Mask |= attrMask
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/hgfs/hgfs_windows.go b/vendor/github.com/vmware/govmomi/toolbox/hgfs/hgfs_windows.go
new file mode 100644
index 00000000..8c3dcdec
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/hgfs/hgfs_windows.go
@@ -0,0 +1,24 @@
+/*
+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 hgfs
+
+import (
+ "os"
+)
+
+func (a *AttrV2) sysStat(info os.FileInfo) {
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/hgfs/protocol.go b/vendor/github.com/vmware/govmomi/toolbox/hgfs/protocol.go
new file mode 100644
index 00000000..a91a0269
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/hgfs/protocol.go
@@ -0,0 +1,847 @@
+/*
+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 hgfs
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "log"
+ "os"
+ "strings"
+)
+
+// See: https://github.com/vmware/open-vm-tools/blob/master/open-vm-tools/lib/include/hgfsProto.h
+
+// Opcodes for server operations as defined in hgfsProto.h
+const (
+ OpOpen = iota /* Open file */
+ OpRead /* Read from file */
+ OpWrite /* Write to file */
+ OpClose /* Close file */
+ OpSearchOpen /* Start new search */
+ OpSearchRead /* Get next search response */
+ OpSearchClose /* End a search */
+ OpGetattr /* Get file attributes */
+ OpSetattr /* Set file attributes */
+ OpCreateDir /* Create new directory */
+ OpDeleteFile /* Delete a file */
+ OpDeleteDir /* Delete a directory */
+ OpRename /* Rename a file or directory */
+ OpQueryVolumeInfo /* Query volume information */
+ OpOpenV2 /* Open file */
+ OpGetattrV2 /* Get file attributes */
+ OpSetattrV2 /* Set file attributes */
+ OpSearchReadV2 /* Get next search response */
+ OpCreateSymlink /* Create a symlink */
+ OpServerLockChange /* Change the oplock on a file */
+ OpCreateDirV2 /* Create a directory */
+ OpDeleteFileV2 /* Delete a file */
+ OpDeleteDirV2 /* Delete a directory */
+ OpRenameV2 /* Rename a file or directory */
+ OpOpenV3 /* Open file */
+ OpReadV3 /* Read from file */
+ OpWriteV3 /* Write to file */
+ OpCloseV3 /* Close file */
+ OpSearchOpenV3 /* Start new search */
+ OpSearchReadV3 /* Read V3 directory entries */
+ OpSearchCloseV3 /* End a search */
+ OpGetattrV3 /* Get file attributes */
+ OpSetattrV3 /* Set file attributes */
+ OpCreateDirV3 /* Create new directory */
+ OpDeleteFileV3 /* Delete a file */
+ OpDeleteDirV3 /* Delete a directory */
+ OpRenameV3 /* Rename a file or directory */
+ OpQueryVolumeInfoV3 /* Query volume information */
+ OpCreateSymlinkV3 /* Create a symlink */
+ OpServerLockChangeV3 /* Change the oplock on a file */
+ OpWriteWin32StreamV3 /* Write WIN32_STREAM_ID format data to file */
+ OpCreateSessionV4 /* Create a session and return host capabilities. */
+ OpDestroySessionV4 /* Destroy/close session. */
+ OpReadFastV4 /* Read */
+ OpWriteFastV4 /* Write */
+ OpSetWatchV4 /* Start monitoring directory changes. */
+ OpRemoveWatchV4 /* Stop monitoring directory changes. */
+ OpNotifyV4 /* Notification for a directory change event. */
+ OpSearchReadV4 /* Read V4 directory entries. */
+ OpOpenV4 /* Open file */
+ OpEnumerateStreamsV4 /* Enumerate alternative named streams for a file. */
+ OpGetattrV4 /* Get file attributes */
+ OpSetattrV4 /* Set file attributes */
+ OpDeleteV4 /* Delete a file or a directory */
+ OpLinkmoveV4 /* Rename/move/create hard link. */
+ OpFsctlV4 /* Sending FS control requests. */
+ OpAccessCheckV4 /* Access check. */
+ OpFsyncV4 /* Flush all cached data to the disk. */
+ OpQueryVolumeInfoV4 /* Query volume information. */
+ OpOplockAcquireV4 /* Acquire OPLOCK. */
+ OpOplockBreakV4 /* Break or downgrade OPLOCK. */
+ OpLockByteRangeV4 /* Acquire byte range lock. */
+ OpUnlockByteRangeV4 /* Release byte range lock. */
+ OpQueryEasV4 /* Query extended attributes. */
+ OpSetEasV4 /* Add or modify extended attributes. */
+ OpNewHeader = 0xff /* Header op, must be unique, distinguishes packet headers. */
+)
+
+// Status codes
+const (
+ StatusSuccess = iota
+ StatusNoSuchFileOrDir
+ StatusInvalidHandle
+ StatusOperationNotPermitted
+ StatusFileExists
+ StatusNotDirectory
+ StatusDirNotEmpty
+ StatusProtocolError
+ StatusAccessDenied
+ StatusInvalidName
+ StatusGenericError
+ StatusSharingViolation
+ StatusNoSpace
+ StatusOperationNotSupported
+ StatusNameTooLong
+ StatusInvalidParameter
+ StatusNotSameDevice
+ StatusStaleSession
+ StatusTooManySessions
+ StatusTransportError
+)
+
+// Flags for attr mask
+const (
+ AttrValidType = 1 << iota
+ AttrValidSize
+ AttrValidCreateTime
+ AttrValidAccessTime
+ AttrValidWriteTime
+ AttrValidChangeTime
+ AttrValidSpecialPerms
+ AttrValidOwnerPerms
+ AttrValidGroupPerms
+ AttrValidOtherPerms
+ AttrValidFlags
+ AttrValidAllocationSize
+ AttrValidUserID
+ AttrValidGroupID
+ AttrValidFileID
+ AttrValidVolID
+ AttrValidNonStaticFileID
+ AttrValidEffectivePerms
+ AttrValidExtendAttrSize
+ AttrValidReparsePoint
+ AttrValidShortName
+)
+
+// HeaderVersion for HGFS protocol version 4
+const HeaderVersion = 0x1
+
+// LargePacketMax is maximum size of an hgfs packet
+const LargePacketMax = 0xf800 // HGFS_LARGE_PACKET_MAX
+
+// Packet flags
+const (
+ PacketFlagRequest = 1 << iota
+ PacketFlagReply
+ PacketFlagInfoExterror
+ PacketFlagValidFlags = 0x7
+)
+
+// Status is an error type that encapsulates an error status code and the cause
+type Status struct {
+ Err error
+ Code uint32
+}
+
+func (s *Status) Error() string {
+ if s.Err != nil {
+ return s.Err.Error()
+ }
+
+ return fmt.Sprintf("hgfs.Status=%d", s.Code)
+}
+
+// errorStatus maps the given error type to a status code
+func errorStatus(err error) uint32 {
+ if x, ok := err.(*Status); ok {
+ return x.Code
+ }
+
+ switch {
+ case os.IsNotExist(err):
+ return StatusNoSuchFileOrDir
+ case os.IsExist(err):
+ return StatusFileExists
+ case os.IsPermission(err):
+ return StatusOperationNotPermitted
+ }
+
+ return StatusGenericError
+}
+
+// ProtocolError wraps the given error as a Status type
+func ProtocolError(err error) error {
+ return &Status{
+ Err: err,
+ Code: StatusProtocolError,
+ }
+}
+
+// Request as defined in hgfsProto.h:HgfsRequest
+type Request struct {
+ Handle uint32
+ Op int32
+}
+
+// Reply as defined in hgfsProto.h:HgfsReply
+type Reply struct {
+ Handle uint32
+ Status uint32
+}
+
+// Header as defined in hgfsProto.h:HgfsHeader
+type Header struct {
+ Version uint8
+ Reserved1 [3]uint8
+ Dummy int32
+ PacketSize uint32
+ HeaderSize uint32
+ RequestID uint32
+ Op int32
+ Status uint32
+ Flags uint32
+ Information uint32
+ SessionID uint64
+ Reserved uint64
+}
+
+var (
+ headerSize = uint32(binary.Size(new(Header)))
+
+ packetSize = func(r *Packet) uint32 {
+ return headerSize + uint32(len(r.Payload))
+ }
+)
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (h *Header) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ err := binary.Read(buf, binary.LittleEndian, h)
+ if err != nil {
+ return fmt.Errorf("reading hgfs header: %s", err)
+ }
+
+ if h.Dummy != OpNewHeader {
+ return fmt.Errorf("expected hgfs header with OpNewHeader (%#x), got: %#x", OpNewHeader, h.Dummy)
+ }
+
+ return nil
+}
+
+// Packet encapsulates an hgfs Header and Payload
+type Packet struct {
+ Header
+
+ Payload []byte
+}
+
+// Reply composes a new Packet with the given payload or error
+func (r *Packet) Reply(payload interface{}, err error) ([]byte, error) {
+ p := new(Packet)
+
+ status := uint32(StatusSuccess)
+
+ if err != nil {
+ status = errorStatus(err)
+ } else {
+ p.Payload, err = MarshalBinary(payload)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ p.Header = Header{
+ Version: HeaderVersion,
+ Dummy: OpNewHeader,
+ PacketSize: headerSize + uint32(len(p.Payload)),
+ HeaderSize: headerSize,
+ RequestID: r.RequestID,
+ Op: r.Op,
+ Status: status,
+ Flags: PacketFlagReply,
+ Information: 0,
+ SessionID: r.SessionID,
+ }
+
+ if Trace {
+ rc := "OK"
+ if err != nil {
+ rc = err.Error()
+ }
+ fmt.Fprintf(os.Stderr, "[hgfs] response %#v [%s]\n", p.Header, rc)
+ } else if err != nil {
+ log.Printf("[hgfs] op=%d error: %s", r.Op, err)
+ }
+
+ return p.MarshalBinary()
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *Packet) MarshalBinary() ([]byte, error) {
+ r.Header.PacketSize = packetSize(r)
+
+ buf, _ := MarshalBinary(r.Header)
+
+ return append(buf, r.Payload...), nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *Packet) UnmarshalBinary(data []byte) error {
+ err := r.Header.UnmarshalBinary(data)
+ if err != nil {
+ return err
+ }
+
+ r.Payload = data[r.HeaderSize:r.PacketSize]
+
+ return nil
+}
+
+// Capability as defined in hgfsProto.h:HgfsCapability
+type Capability struct {
+ Op int32
+ Flags uint32
+}
+
+// RequestCreateSessionV4 as defined in hgfsProto.h:HgfsRequestCreateSessionV4
+type RequestCreateSessionV4 struct {
+ NumCapabilities uint32
+ MaxPacketSize uint32
+ Flags uint32
+ Reserved uint32
+ Capabilities []Capability
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *RequestCreateSessionV4) MarshalBinary() ([]byte, error) {
+ buf := new(bytes.Buffer)
+
+ r.NumCapabilities = uint32(len(r.Capabilities))
+
+ fields := []*uint32{
+ &r.NumCapabilities,
+ &r.MaxPacketSize,
+ &r.Flags,
+ &r.Reserved,
+ }
+
+ for _, p := range fields {
+ err := binary.Write(buf, binary.LittleEndian, p)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ for i := uint32(0); i < r.NumCapabilities; i++ {
+ err := binary.Write(buf, binary.LittleEndian, &r.Capabilities[i])
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return buf.Bytes(), nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *RequestCreateSessionV4) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ fields := []*uint32{
+ &r.NumCapabilities,
+ &r.MaxPacketSize,
+ &r.Flags,
+ &r.Reserved,
+ }
+
+ for _, p := range fields {
+ err := binary.Read(buf, binary.LittleEndian, p)
+ if err != nil {
+ return err
+ }
+ }
+
+ for i := uint32(0); i < r.NumCapabilities; i++ {
+ var cap Capability
+ err := binary.Read(buf, binary.LittleEndian, &cap)
+ if err != nil {
+ return err
+ }
+
+ r.Capabilities = append(r.Capabilities, cap)
+ }
+
+ return nil
+}
+
+// ReplyCreateSessionV4 as defined in hgfsProto.h:HgfsReplyCreateSessionV4
+type ReplyCreateSessionV4 struct {
+ SessionID uint64
+ NumCapabilities uint32
+ MaxPacketSize uint32
+ IdentityOffset uint32
+ Flags uint32
+ Reserved uint32
+ Capabilities []Capability
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *ReplyCreateSessionV4) MarshalBinary() ([]byte, error) {
+ buf := new(bytes.Buffer)
+
+ fields := []interface{}{
+ &r.SessionID,
+ &r.NumCapabilities,
+ &r.MaxPacketSize,
+ &r.IdentityOffset,
+ &r.Flags,
+ &r.Reserved,
+ }
+
+ for _, p := range fields {
+ err := binary.Write(buf, binary.LittleEndian, p)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ for i := uint32(0); i < r.NumCapabilities; i++ {
+ err := binary.Write(buf, binary.LittleEndian, &r.Capabilities[i])
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return buf.Bytes(), nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *ReplyCreateSessionV4) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ fields := []interface{}{
+ &r.SessionID,
+ &r.NumCapabilities,
+ &r.MaxPacketSize,
+ &r.IdentityOffset,
+ &r.Flags,
+ &r.Reserved,
+ }
+
+ for _, p := range fields {
+ err := binary.Read(buf, binary.LittleEndian, p)
+ if err != nil {
+ return err
+ }
+ }
+
+ for i := uint32(0); i < r.NumCapabilities; i++ {
+ var cap Capability
+ err := binary.Read(buf, binary.LittleEndian, &cap)
+ if err != nil {
+ return err
+ }
+
+ r.Capabilities = append(r.Capabilities, cap)
+ }
+
+ return nil
+}
+
+// RequestDestroySessionV4 as defined in hgfsProto.h:HgfsRequestDestroySessionV4
+type RequestDestroySessionV4 struct {
+ Reserved uint64
+}
+
+// ReplyDestroySessionV4 as defined in hgfsProto.h:HgfsReplyDestroySessionV4
+type ReplyDestroySessionV4 struct {
+ Reserved uint64
+}
+
+// FileName as defined in hgfsProto.h:HgfsFileName
+type FileName struct {
+ Length uint32
+ Name string
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (f *FileName) MarshalBinary() ([]byte, error) {
+ name := f.Name
+ f.Length = uint32(len(f.Name))
+ if f.Length == 0 {
+ // field is defined as 'char name[1];', this byte is required for min sizeof() validation
+ name = "\x00"
+ }
+ return MarshalBinary(&f.Length, name)
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (f *FileName) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ _ = binary.Read(buf, binary.LittleEndian, &f.Length)
+
+ f.Name = string(buf.Next(int(f.Length)))
+
+ return nil
+}
+
+const serverPolicyRootShareName = "root"
+
+// FromString converts name to a FileName
+func (f *FileName) FromString(name string) {
+ name = strings.TrimPrefix(name, "/")
+
+ cp := strings.Split(name, "/")
+
+ cp = append([]string{serverPolicyRootShareName}, cp...)
+
+ f.Name = strings.Join(cp, "\x00")
+ f.Length = uint32(len(f.Name))
+}
+
+// Path converts FileName to a string
+func (f *FileName) Path() string {
+ cp := strings.Split(f.Name, "\x00")
+
+ if len(cp) == 0 || cp[0] != serverPolicyRootShareName {
+ return "" // TODO: not happening until if/when we handle Windows shares
+ }
+
+ cp[0] = ""
+
+ return strings.Join(cp, "/")
+}
+
+// FileNameV3 as defined in hgfsProto.h:HgfsFileNameV3
+type FileNameV3 struct {
+ Length uint32
+ Flags uint32
+ CaseType int32
+ ID uint32
+ Name string
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (f *FileNameV3) MarshalBinary() ([]byte, error) {
+ name := f.Name
+ f.Length = uint32(len(f.Name))
+ if f.Length == 0 {
+ // field is defined as 'char name[1];', this byte is required for min sizeof() validation
+ name = "\x00"
+ }
+ return MarshalBinary(&f.Length, &f.Flags, &f.CaseType, &f.ID, name)
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (f *FileNameV3) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ fields := []interface{}{
+ &f.Length, &f.Flags, &f.CaseType, &f.ID,
+ }
+
+ for _, p := range fields {
+ if err := binary.Read(buf, binary.LittleEndian, p); err != nil {
+ return err
+ }
+ }
+
+ f.Name = string(buf.Next(int(f.Length)))
+
+ return nil
+}
+
+// FromString converts name to a FileNameV3
+func (f *FileNameV3) FromString(name string) {
+ p := new(FileName)
+ p.FromString(name)
+ f.Name = p.Name
+ f.Length = p.Length
+}
+
+// Path converts FileNameV3 to a string
+func (f *FileNameV3) Path() string {
+ return (&FileName{Name: f.Name, Length: f.Length}).Path()
+}
+
+// FileType
+const (
+ FileTypeRegular = iota
+ FileTypeDirectory
+ FileTypeSymlink
+)
+
+// AttrV2 as defined in hgfsProto.h:HgfsAttrV2
+type AttrV2 struct {
+ Mask uint64
+ Type int32
+ Size uint64
+ CreationTime uint64
+ AccessTime uint64
+ WriteTime uint64
+ AttrChangeTime uint64
+ SpecialPerms uint8
+ OwnerPerms uint8
+ GroupPerms uint8
+ OtherPerms uint8
+ AttrFlags uint64
+ AllocationSize uint64
+ UserID uint32
+ GroupID uint32
+ HostFileID uint64
+ VolumeID uint32
+ EffectivePerms uint32
+ Reserved2 uint64
+}
+
+// RequestGetattrV2 as defined in hgfsProto.h:HgfsRequestGetattrV2
+type RequestGetattrV2 struct {
+ Request
+ AttrHint uint64
+ Handle uint32
+ FileName FileName
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *RequestGetattrV2) MarshalBinary() ([]byte, error) {
+ return MarshalBinary(&r.Request, &r.AttrHint, &r.Handle, &r.FileName)
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *RequestGetattrV2) UnmarshalBinary(data []byte) error {
+ return UnmarshalBinary(data, &r.Request, &r.AttrHint, &r.Handle, &r.FileName)
+}
+
+// ReplyGetattrV2 as defined in hgfsProto.h:HgfsReplyGetattrV2
+type ReplyGetattrV2 struct {
+ Reply
+ Attr AttrV2
+ SymlinkTarget FileName
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *ReplyGetattrV2) MarshalBinary() ([]byte, error) {
+ return MarshalBinary(&r.Reply, &r.Attr, &r.SymlinkTarget)
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *ReplyGetattrV2) UnmarshalBinary(data []byte) error {
+ return UnmarshalBinary(data, &r.Reply, &r.Attr, &r.SymlinkTarget)
+}
+
+// RequestSetattrV2 as defined in hgfsProto.h:HgfsRequestSetattrV2
+type RequestSetattrV2 struct {
+ Request
+ Hints uint64
+ Attr AttrV2
+ Handle uint32
+ FileName FileName
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *RequestSetattrV2) MarshalBinary() ([]byte, error) {
+ return MarshalBinary(&r.Request, &r.Hints, &r.Attr, &r.Handle, &r.FileName)
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *RequestSetattrV2) UnmarshalBinary(data []byte) error {
+ return UnmarshalBinary(data, &r.Request, &r.Hints, &r.Attr, &r.Handle, &r.FileName)
+}
+
+// ReplySetattrV2 as defined in hgfsProto.h:HgfsReplySetattrV2
+type ReplySetattrV2 struct {
+ Header Reply
+}
+
+// OpenMode
+const (
+ OpenModeReadOnly = iota
+ OpenModeWriteOnly
+ OpenModeReadWrite
+ OpenModeAccmodes
+)
+
+// OpenFlags
+const (
+ Open = iota
+ OpenEmpty
+ OpenCreate
+ OpenCreateSafe
+ OpenCreateEmpty
+)
+
+// Permissions
+const (
+ PermRead = 4
+ PermWrite = 2
+ PermExec = 1
+)
+
+// RequestOpen as defined in hgfsProto.h:HgfsRequestOpen
+type RequestOpen struct {
+ Request
+ OpenMode int32
+ OpenFlags int32
+ Permissions uint8
+ FileName FileName
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *RequestOpen) MarshalBinary() ([]byte, error) {
+ return MarshalBinary(&r.Request, &r.OpenMode, &r.OpenFlags, r.Permissions, &r.FileName)
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *RequestOpen) UnmarshalBinary(data []byte) error {
+ return UnmarshalBinary(data, &r.Request, &r.OpenMode, &r.OpenFlags, &r.Permissions, &r.FileName)
+}
+
+// ReplyOpen as defined in hgfsProto.h:HgfsReplyOpen
+type ReplyOpen struct {
+ Reply
+ Handle uint32
+}
+
+// RequestClose as defined in hgfsProto.h:HgfsRequestClose
+type RequestClose struct {
+ Request
+ Handle uint32
+}
+
+// ReplyClose as defined in hgfsProto.h:HgfsReplyClose
+type ReplyClose struct {
+ Reply
+}
+
+// Lock type
+const (
+ LockNone = iota
+ LockOpportunistic
+ LockExclusive
+ LockShared
+ LockBatch
+ LockLease
+)
+
+// RequestOpenV3 as defined in hgfsProto.h:HgfsRequestOpenV3
+type RequestOpenV3 struct {
+ Mask uint64
+ OpenMode int32
+ OpenFlags int32
+ SpecialPerms uint8
+ OwnerPerms uint8
+ GroupPerms uint8
+ OtherPerms uint8
+ AttrFlags uint64
+ AllocationSize uint64
+ DesiredAccess uint32
+ ShareAccess uint32
+ DesiredLock int32
+ Reserved1 uint64
+ Reserved2 uint64
+ FileName FileNameV3
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *RequestOpenV3) MarshalBinary() ([]byte, error) {
+ return MarshalBinary(&r.Mask, &r.OpenMode, &r.OpenFlags,
+ &r.SpecialPerms, &r.OwnerPerms, &r.GroupPerms, &r.OtherPerms,
+ &r.AttrFlags, &r.AllocationSize, &r.DesiredAccess, &r.ShareAccess,
+ &r.DesiredLock, &r.Reserved1, &r.Reserved2, &r.FileName)
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *RequestOpenV3) UnmarshalBinary(data []byte) error {
+ return UnmarshalBinary(data, &r.Mask, &r.OpenMode, &r.OpenFlags,
+ &r.SpecialPerms, &r.OwnerPerms, &r.GroupPerms, &r.OtherPerms,
+ &r.AttrFlags, &r.AllocationSize, &r.DesiredAccess, &r.ShareAccess,
+ &r.DesiredLock, &r.Reserved1, &r.Reserved2, &r.FileName)
+}
+
+// ReplyOpenV3 as defined in hgfsProto.h:HgfsReplyOpenV3
+type ReplyOpenV3 struct {
+ Handle uint32
+ AcquiredLock int32
+ Flags int32
+ Reserved uint32
+}
+
+// RequestReadV3 as defined in hgfsProto.h:HgfsRequestReadV3
+type RequestReadV3 struct {
+ Handle uint32
+ Offset uint64
+ RequiredSize uint32
+ Reserved uint64
+}
+
+// ReplyReadV3 as defined in hgfsProto.h:HgfsReplyReadV3
+type ReplyReadV3 struct {
+ ActualSize uint32
+ Reserved uint64
+ Payload []byte
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *ReplyReadV3) MarshalBinary() ([]byte, error) {
+ return MarshalBinary(&r.ActualSize, &r.Reserved, r.Payload)
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *ReplyReadV3) UnmarshalBinary(data []byte) error {
+ return UnmarshalBinary(data, &r.ActualSize, &r.Reserved, &r.Payload)
+}
+
+// Write flags
+const (
+ WriteAppend = 1
+)
+
+// RequestWriteV3 as defined in hgfsProto.h:HgfsRequestWriteV3
+type RequestWriteV3 struct {
+ Handle uint32
+ WriteFlags uint8
+ Offset uint64
+ RequiredSize uint32
+ Reserved uint64
+ Payload []byte
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *RequestWriteV3) MarshalBinary() ([]byte, error) {
+ return MarshalBinary(&r.Handle, &r.WriteFlags, &r.Offset, &r.RequiredSize, &r.Reserved, r.Payload)
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *RequestWriteV3) UnmarshalBinary(data []byte) error {
+ return UnmarshalBinary(data, &r.Handle, &r.WriteFlags, &r.Offset, &r.RequiredSize, &r.Reserved, &r.Payload)
+}
+
+// ReplyWriteV3 as defined in hgfsProto.h:HgfsReplyWriteV3
+type ReplyWriteV3 struct {
+ ActualSize uint32
+ Reserved uint64
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/hgfs/server.go b/vendor/github.com/vmware/govmomi/toolbox/hgfs/server.go
new file mode 100644
index 00000000..5a233f26
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/hgfs/server.go
@@ -0,0 +1,584 @@
+/*
+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 hgfs
+
+import (
+ "errors"
+ "flag"
+ "fmt"
+ "io"
+ "log"
+ "math/rand"
+ "net/url"
+ "os"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+)
+
+// See: https://github.com/vmware/open-vm-tools/blob/master/open-vm-tools/lib/hgfsServer/hgfsServer.c
+
+var (
+ // Trace enables hgfs packet tracing
+ Trace = false
+)
+
+// Server provides an HGFS protocol implementation to support guest tools VmxiHgfsSendPacketCommand
+type Server struct {
+ Capabilities []Capability
+
+ handlers map[int32]func(*Packet) (interface{}, error)
+ schemes map[string]FileHandler
+ sessions map[uint64]*session
+ mu sync.Mutex
+ handle uint32
+
+ chmod func(string, os.FileMode) error
+ chown func(string, int, int) error
+}
+
+// NewServer creates a new Server instance with the default handlers
+func NewServer() *Server {
+ if f := flag.Lookup("toolbox.trace"); f != nil {
+ Trace, _ = strconv.ParseBool(f.Value.String())
+ }
+
+ s := &Server{
+ sessions: make(map[uint64]*session),
+ schemes: make(map[string]FileHandler),
+ chmod: os.Chmod,
+ chown: os.Chown,
+ }
+
+ s.handlers = map[int32]func(*Packet) (interface{}, error){
+ OpCreateSessionV4: s.CreateSessionV4,
+ OpDestroySessionV4: s.DestroySessionV4,
+ OpGetattrV2: s.GetattrV2,
+ OpSetattrV2: s.SetattrV2,
+ OpOpen: s.Open,
+ OpClose: s.Close,
+ OpOpenV3: s.OpenV3,
+ OpReadV3: s.ReadV3,
+ OpWriteV3: s.WriteV3,
+ }
+
+ for op := range s.handlers {
+ s.Capabilities = append(s.Capabilities, Capability{Op: op, Flags: 0x1})
+ }
+
+ return s
+}
+
+// RegisterFileHandler enables dispatch to handler for the given scheme.
+func (s *Server) RegisterFileHandler(scheme string, handler FileHandler) {
+ if handler == nil {
+ delete(s.schemes, scheme)
+ return
+ }
+ s.schemes[scheme] = handler
+}
+
+// Dispatch unpacks the given request packet and dispatches to the appropriate handler
+func (s *Server) Dispatch(packet []byte) ([]byte, error) {
+ req := &Packet{}
+
+ err := req.UnmarshalBinary(packet)
+ if err != nil {
+ return nil, err
+ }
+
+ if Trace {
+ fmt.Fprintf(os.Stderr, "[hgfs] request %#v\n", req.Header)
+ }
+
+ var res interface{}
+
+ handler, ok := s.handlers[req.Op]
+ if ok {
+ res, err = handler(req)
+ } else {
+ err = &Status{
+ Code: StatusOperationNotSupported,
+ Err: fmt.Errorf("unsupported Op(%d)", req.Op),
+ }
+ }
+
+ return req.Reply(res, err)
+}
+
+// File interface abstracts standard i/o methods to support transfer
+// of regular files and archives of directories.
+type File interface {
+ io.Reader
+ io.Writer
+ io.Closer
+
+ Name() string
+}
+
+// FileHandler is the plugin interface for hgfs file transport.
+type FileHandler interface {
+ Stat(*url.URL) (os.FileInfo, error)
+ Open(*url.URL, int32) (File, error)
+}
+
+// urlParse attempts to convert the given name to a URL with scheme for use as FileHandler dispatch.
+func urlParse(name string) *url.URL {
+ var info os.FileInfo
+
+ u, err := url.Parse(name)
+ if err == nil && u.Scheme == "" {
+ info, err = os.Stat(u.Path)
+ if err == nil && info.IsDir() {
+ u.Scheme = ArchiveScheme // special case for IsDir()
+ return u
+ }
+ }
+
+ u, err = url.Parse(strings.TrimPrefix(name, "/")) // must appear to be an absolute path or hgfs errors
+ if err != nil {
+ u = &url.URL{Path: name}
+ }
+
+ if u.Scheme == "" {
+ ix := strings.Index(u.Path, "/")
+ if ix > 0 {
+ u.Scheme = u.Path[:ix]
+ u.Path = u.Path[ix:]
+ }
+ }
+
+ return u
+}
+
+// OpenFile selects the File implementation based on file type and mode.
+func (s *Server) OpenFile(name string, mode int32) (File, error) {
+ u := urlParse(name)
+
+ if h, ok := s.schemes[u.Scheme]; ok {
+ f, serr := h.Open(u, mode)
+ if serr != os.ErrNotExist {
+ return f, serr
+ }
+ }
+
+ switch mode {
+ case OpenModeReadOnly:
+ return os.Open(name)
+ case OpenModeWriteOnly:
+ flag := os.O_WRONLY | os.O_CREATE | os.O_TRUNC
+ return os.OpenFile(name, flag, 0600)
+ default:
+ return nil, &Status{
+ Err: fmt.Errorf("open mode(%d) not supported for file %q", mode, name),
+ Code: StatusAccessDenied,
+ }
+ }
+}
+
+// Stat wraps os.Stat such that we can report directory types as regular files to support archive streaming.
+// In the case of standard vmware-tools, attempts to transfer directories result
+// with a VIX_E_NOT_A_FILE (see InitiateFileTransfer{To,From}Guest).
+// Note that callers on the VMX side that reach this path are only concerned with:
+// - does the file exist?
+// - size:
+// + used for UI progress with desktop Drag-N-Drop operations, which toolbox does not support.
+// + sent to as Content-Length header in response to GET of FileTransferInformation.Url,
+// if the first ReadV3 size is > HGFS_LARGE_PACKET_MAX
+func (s *Server) Stat(name string) (os.FileInfo, error) {
+ u := urlParse(name)
+
+ if h, ok := s.schemes[u.Scheme]; ok {
+ sinfo, serr := h.Stat(u)
+ if serr != os.ErrNotExist {
+ return sinfo, serr
+ }
+ }
+
+ return os.Stat(name)
+}
+
+type session struct {
+ files map[uint32]File
+ mu sync.Mutex
+}
+
+// TODO: we currently depend on the VMX to close files and remove sessions,
+// which it does provided it can communicate with the toolbox. Let's look at
+// adding session expiration when implementing OpenModeWriteOnly support.
+func newSession() *session {
+ return &session{
+ files: make(map[uint32]File),
+ }
+}
+
+func (s *Server) getSession(p *Packet) (*session, error) {
+ s.mu.Lock()
+ session, ok := s.sessions[p.SessionID]
+ s.mu.Unlock()
+
+ if !ok {
+ return nil, &Status{
+ Code: StatusStaleSession,
+ Err: errors.New("session not found"),
+ }
+ }
+
+ return session, nil
+}
+
+func (s *Server) removeSession(id uint64) bool {
+ s.mu.Lock()
+ session, ok := s.sessions[id]
+ delete(s.sessions, id)
+ s.mu.Unlock()
+
+ if !ok {
+ return false
+ }
+
+ session.mu.Lock()
+ defer session.mu.Unlock()
+
+ for _, f := range session.files {
+ log.Printf("[hgfs] session %X removed with open file: %s", id, f.Name())
+ _ = f.Close()
+ }
+
+ return true
+}
+
+// open-vm-tools' session max is 1024, there shouldn't be more than a handful at a given time in our use cases
+const maxSessions = 24
+
+// CreateSessionV4 handls OpCreateSessionV4 requests
+func (s *Server) CreateSessionV4(p *Packet) (interface{}, error) {
+ const SessionMaxPacketSizeValid = 0x1
+
+ req := new(RequestCreateSessionV4)
+ err := UnmarshalBinary(p.Payload, req)
+ if err != nil {
+ return nil, err
+ }
+
+ res := &ReplyCreateSessionV4{
+ SessionID: uint64(rand.Int63()),
+ NumCapabilities: uint32(len(s.Capabilities)),
+ MaxPacketSize: LargePacketMax,
+ Flags: SessionMaxPacketSizeValid,
+ Capabilities: s.Capabilities,
+ }
+
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ if len(s.sessions) > maxSessions {
+ return nil, &Status{Code: StatusTooManySessions}
+ }
+
+ s.sessions[res.SessionID] = newSession()
+
+ return res, nil
+}
+
+// DestroySessionV4 handls OpDestroySessionV4 requests
+func (s *Server) DestroySessionV4(p *Packet) (interface{}, error) {
+ if s.removeSession(p.SessionID) {
+ return &ReplyDestroySessionV4{}, nil
+ }
+
+ return nil, &Status{Code: StatusStaleSession}
+}
+
+// Stat maps os.FileInfo to AttrV2
+func (a *AttrV2) Stat(info os.FileInfo) {
+ switch {
+ case info.IsDir():
+ a.Type = FileTypeDirectory
+ case info.Mode()&os.ModeSymlink == os.ModeSymlink:
+ a.Type = FileTypeSymlink
+ default:
+ a.Type = FileTypeRegular
+ }
+
+ a.Size = uint64(info.Size())
+
+ a.Mask = AttrValidType | AttrValidSize
+
+ a.sysStat(info)
+}
+
+// GetattrV2 handles OpGetattrV2 requests
+func (s *Server) GetattrV2(p *Packet) (interface{}, error) {
+ res := &ReplyGetattrV2{}
+
+ req := new(RequestGetattrV2)
+ err := UnmarshalBinary(p.Payload, req)
+ if err != nil {
+ return nil, err
+ }
+
+ name := req.FileName.Path()
+ info, err := s.Stat(name)
+ if err != nil {
+ return nil, err
+ }
+
+ res.Attr.Stat(info)
+
+ return res, nil
+}
+
+// SetattrV2 handles OpSetattrV2 requests
+func (s *Server) SetattrV2(p *Packet) (interface{}, error) {
+ res := &ReplySetattrV2{}
+
+ req := new(RequestSetattrV2)
+ err := UnmarshalBinary(p.Payload, req)
+ if err != nil {
+ return nil, err
+ }
+
+ name := req.FileName.Path()
+
+ _, err = os.Stat(name)
+ if err != nil && os.IsNotExist(err) {
+ // assuming this is a virtual file
+ return res, nil
+ }
+
+ uid := -1
+ if req.Attr.Mask&AttrValidUserID == AttrValidUserID {
+ uid = int(req.Attr.UserID)
+ }
+
+ gid := -1
+ if req.Attr.Mask&AttrValidGroupID == AttrValidGroupID {
+ gid = int(req.Attr.GroupID)
+ }
+
+ err = s.chown(name, uid, gid)
+ if err != nil {
+ return nil, err
+ }
+
+ var perm os.FileMode
+
+ if req.Attr.Mask&AttrValidOwnerPerms == AttrValidOwnerPerms {
+ perm |= os.FileMode(req.Attr.OwnerPerms) << 6
+ }
+
+ if req.Attr.Mask&AttrValidGroupPerms == AttrValidGroupPerms {
+ perm |= os.FileMode(req.Attr.GroupPerms) << 3
+ }
+
+ if req.Attr.Mask&AttrValidOtherPerms == AttrValidOtherPerms {
+ perm |= os.FileMode(req.Attr.OtherPerms)
+ }
+
+ if perm != 0 {
+ err = s.chmod(name, perm)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return res, nil
+}
+
+func (s *Server) newHandle() uint32 {
+ return atomic.AddUint32(&s.handle, 1)
+}
+
+// Open handles OpOpen requests
+func (s *Server) Open(p *Packet) (interface{}, error) {
+ req := new(RequestOpen)
+ err := UnmarshalBinary(p.Payload, req)
+ if err != nil {
+ return nil, err
+ }
+
+ session, err := s.getSession(p)
+ if err != nil {
+ return nil, err
+ }
+
+ name := req.FileName.Path()
+ mode := req.OpenMode
+
+ if mode != OpenModeReadOnly {
+ return nil, &Status{
+ Err: fmt.Errorf("open mode(%d) not supported for file %q", mode, name),
+ Code: StatusAccessDenied,
+ }
+ }
+
+ file, err := s.OpenFile(name, mode)
+ if err != nil {
+ return nil, err
+ }
+
+ res := &ReplyOpen{
+ Handle: s.newHandle(),
+ }
+
+ session.mu.Lock()
+ session.files[res.Handle] = file
+ session.mu.Unlock()
+
+ return res, nil
+}
+
+// Close handles OpClose requests
+func (s *Server) Close(p *Packet) (interface{}, error) {
+ req := new(RequestClose)
+ err := UnmarshalBinary(p.Payload, req)
+ if err != nil {
+ return nil, err
+ }
+
+ session, err := s.getSession(p)
+ if err != nil {
+ return nil, err
+ }
+
+ session.mu.Lock()
+ file, ok := session.files[req.Handle]
+ if ok {
+ delete(session.files, req.Handle)
+ }
+ session.mu.Unlock()
+
+ if ok {
+ err = file.Close()
+ } else {
+ return nil, &Status{Code: StatusInvalidHandle}
+ }
+
+ return &ReplyClose{}, err
+}
+
+// OpenV3 handles OpOpenV3 requests
+func (s *Server) OpenV3(p *Packet) (interface{}, error) {
+ req := new(RequestOpenV3)
+ err := UnmarshalBinary(p.Payload, req)
+ if err != nil {
+ return nil, err
+ }
+
+ session, err := s.getSession(p)
+ if err != nil {
+ return nil, err
+ }
+
+ name := req.FileName.Path()
+
+ if req.DesiredLock != LockNone {
+ return nil, &Status{
+ Err: fmt.Errorf("open lock type=%d not supported for file %q", req.DesiredLock, name),
+ Code: StatusOperationNotSupported,
+ }
+ }
+
+ file, err := s.OpenFile(name, req.OpenMode)
+ if err != nil {
+ return nil, err
+ }
+
+ res := &ReplyOpenV3{
+ Handle: s.newHandle(),
+ }
+
+ session.mu.Lock()
+ session.files[res.Handle] = file
+ session.mu.Unlock()
+
+ return res, nil
+}
+
+// ReadV3 handles OpReadV3 requests
+func (s *Server) ReadV3(p *Packet) (interface{}, error) {
+ req := new(RequestReadV3)
+ err := UnmarshalBinary(p.Payload, req)
+ if err != nil {
+ return nil, err
+ }
+
+ session, err := s.getSession(p)
+ if err != nil {
+ return nil, err
+ }
+
+ session.mu.Lock()
+ file, ok := session.files[req.Handle]
+ session.mu.Unlock()
+
+ if !ok {
+ return nil, &Status{Code: StatusInvalidHandle}
+ }
+
+ buf := make([]byte, req.RequiredSize)
+
+ // Use ReadFull as Read() of an archive io.Pipe may return much smaller chunks,
+ // such as when we've read a tar header.
+ n, err := io.ReadFull(file, buf)
+ if err != nil && n == 0 {
+ if err != io.EOF {
+ return nil, err
+ }
+ }
+
+ res := &ReplyReadV3{
+ ActualSize: uint32(n),
+ Payload: buf[:n],
+ }
+
+ return res, nil
+}
+
+// WriteV3 handles OpWriteV3 requests
+func (s *Server) WriteV3(p *Packet) (interface{}, error) {
+ req := new(RequestWriteV3)
+ err := UnmarshalBinary(p.Payload, req)
+ if err != nil {
+ return nil, err
+ }
+
+ session, err := s.getSession(p)
+ if err != nil {
+ return nil, err
+ }
+
+ session.mu.Lock()
+ file, ok := session.files[req.Handle]
+ session.mu.Unlock()
+
+ if !ok {
+ return nil, &Status{Code: StatusInvalidHandle}
+ }
+
+ n, err := file.Write(req.Payload)
+ if err != nil {
+ return nil, err
+ }
+
+ res := &ReplyWriteV3{
+ ActualSize: uint32(n),
+ }
+
+ return res, nil
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/power.go b/vendor/github.com/vmware/govmomi/toolbox/power.go
new file mode 100644
index 00000000..918f9be1
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/power.go
@@ -0,0 +1,118 @@
+/*
+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 toolbox
+
+import (
+ "fmt"
+ "log"
+ "os/exec"
+)
+
+// GuestOsState enum as defined in open-vm-tools/lib/include/vmware/guestrpc/powerops.h
+const (
+ _ = iota
+ powerStateHalt
+ powerStateReboot
+ powerStatePowerOn
+ powerStateResume
+ powerStateSuspend
+)
+
+var (
+ shutdown = "/sbin/shutdown"
+)
+
+type PowerCommand struct {
+ Handler func() error
+
+ out *ChannelOut
+ state int
+ name string
+}
+
+type PowerCommandHandler struct {
+ Halt PowerCommand
+ Reboot PowerCommand
+ PowerOn PowerCommand
+ Resume PowerCommand
+ Suspend PowerCommand
+}
+
+func registerPowerCommandHandler(service *Service) *PowerCommandHandler {
+ handler := new(PowerCommandHandler)
+
+ handlers := map[string]struct {
+ cmd *PowerCommand
+ state int
+ }{
+ "OS_Halt": {&handler.Halt, powerStateHalt},
+ "OS_Reboot": {&handler.Reboot, powerStateReboot},
+ "OS_PowerOn": {&handler.PowerOn, powerStatePowerOn},
+ "OS_Resume": {&handler.Resume, powerStateResume},
+ "OS_Suspend": {&handler.Suspend, powerStateSuspend},
+ }
+
+ for name, h := range handlers {
+ *h.cmd = PowerCommand{
+ name: name,
+ state: h.state,
+ out: service.out,
+ }
+
+ service.RegisterHandler(name, h.cmd.Dispatch)
+ }
+
+ return handler
+}
+
+func (c *PowerCommand) Dispatch([]byte) ([]byte, error) {
+ rc := rpciOK
+
+ log.Printf("dispatching power op %q", c.name)
+
+ if c.Handler == nil {
+ if c.state == powerStateHalt || c.state == powerStateReboot {
+ rc = rpciERR
+ }
+ }
+
+ msg := fmt.Sprintf("tools.os.statechange.status %s%d\x00", rc, c.state)
+
+ if _, err := c.out.Request([]byte(msg)); err != nil {
+ log.Printf("unable to send %q: %q", msg, err)
+ }
+
+ if c.Handler != nil {
+ if err := c.Handler(); err != nil {
+ log.Printf("%s: %s", c.name, err)
+ }
+ }
+
+ return nil, nil
+}
+
+func Halt() error {
+ log.Printf("Halting system...")
+ // #nosec: Subprocess launching with variable
+ return exec.Command(shutdown, "-h", "now").Run()
+}
+
+func Reboot() error {
+ log.Printf("Rebooting system...")
+ // #nosec: Subprocess launching with variable
+ return exec.Command(shutdown, "-r", "now").Run()
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/process.go b/vendor/github.com/vmware/govmomi/toolbox/process.go
new file mode 100644
index 00000000..695b5ee0
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/process.go
@@ -0,0 +1,630 @@
+/*
+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 toolbox
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net"
+ "net/url"
+ "os"
+ "os/exec"
+ "path"
+ "path/filepath"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "syscall"
+ "time"
+
+ "github.com/vmware/govmomi/toolbox/hgfs"
+ "github.com/vmware/govmomi/toolbox/vix"
+)
+
+var (
+ xmlEscape *strings.Replacer
+
+ shell = "/bin/sh"
+
+ defaultOwner = os.Getenv("USER")
+)
+
+func init() {
+ // See: VixToolsEscapeXMLString
+ chars := []string{
+ `"`,
+ "%",
+ "&",
+ "'",
+ "<",
+ ">",
+ }
+
+ replace := make([]string, 0, len(chars)*2)
+
+ for _, c := range chars {
+ replace = append(replace, c)
+ replace = append(replace, url.QueryEscape(c))
+ }
+
+ xmlEscape = strings.NewReplacer(replace...)
+
+ // See procMgrPosix.c:ProcMgrStartProcess:
+ // Prefer bash -c as is uses exec() to replace itself,
+ // whereas bourne shell does a fork & exec, so two processes are started.
+ if sh, err := exec.LookPath("bash"); err != nil {
+ shell = sh
+ }
+
+ if defaultOwner == "" {
+ defaultOwner = "toolbox"
+ }
+}
+
+// ProcessIO encapsulates IO for Go functions and OS commands such that they can interact via the OperationsManager
+// without file system disk IO.
+type ProcessIO struct {
+ In struct {
+ io.Writer
+ io.Reader
+ io.Closer // Closer for the write side of the pipe, can be closed via hgfs ops (FileTranfserToGuest)
+ }
+
+ Out *bytes.Buffer
+ Err *bytes.Buffer
+}
+
+// ProcessState is the toolbox representation of the GuestProcessInfo type
+type ProcessState struct {
+ Name string
+ Args string
+ Owner string
+ Pid int64
+ ExitCode int32
+ StartTime int64
+ EndTime int64
+
+ IO *ProcessIO
+}
+
+// WithIO enables toolbox Process IO without file system disk IO.
+func (p *Process) WithIO() *Process {
+ p.IO = &ProcessIO{
+ Out: new(bytes.Buffer),
+ Err: new(bytes.Buffer),
+ }
+
+ return p
+}
+
+// ProcessFile implements the os.FileInfo interface to enable toolbox interaction with virtual files.
+type ProcessFile struct {
+ io.Reader
+ io.Writer
+ io.Closer
+
+ name string
+ size int
+}
+
+// Name implementation of the os.FileInfo interface method.
+func (a *ProcessFile) Name() string {
+ return a.name
+}
+
+// Size implementation of the os.FileInfo interface method.
+func (a *ProcessFile) Size() int64 {
+ return int64(a.size)
+}
+
+// Mode implementation of the os.FileInfo interface method.
+func (a *ProcessFile) Mode() os.FileMode {
+ if strings.HasSuffix(a.name, "stdin") {
+ return 0200
+ }
+ return 0400
+}
+
+// ModTime implementation of the os.FileInfo interface method.
+func (a *ProcessFile) ModTime() time.Time {
+ return time.Now()
+}
+
+// IsDir implementation of the os.FileInfo interface method.
+func (a *ProcessFile) IsDir() bool {
+ return false
+}
+
+// Sys implementation of the os.FileInfo interface method.
+func (a *ProcessFile) Sys() interface{} {
+ return nil
+}
+
+func (s *ProcessState) toXML() string {
+ const format = "" +
+ "%s" +
+ "%s" +
+ "%d" +
+ "%s" +
+ "%d" +
+ "%d" +
+ "%d" +
+ ""
+
+ name := filepath.Base(s.Name)
+
+ argv := []string{s.Name}
+
+ if len(s.Args) != 0 {
+ argv = append(argv, xmlEscape.Replace(s.Args))
+ }
+
+ args := strings.Join(argv, " ")
+
+ exit := atomic.LoadInt32(&s.ExitCode)
+ end := atomic.LoadInt64(&s.EndTime)
+
+ return fmt.Sprintf(format, name, args, s.Pid, s.Owner, s.StartTime, exit, end)
+}
+
+// Process managed by the ProcessManager.
+type Process struct {
+ ProcessState
+
+ Start func(*Process, *vix.StartProgramRequest) (int64, error)
+ Wait func() error
+ Kill context.CancelFunc
+
+ ctx context.Context
+}
+
+// ProcessError can be returned by the Process.Wait function to propagate ExitCode to ProcessState.
+type ProcessError struct {
+ Err error
+ ExitCode int32
+}
+
+func (e *ProcessError) Error() string {
+ return e.Err.Error()
+}
+
+// ProcessManager manages processes within the guest.
+// See: http://pubs.vmware.com/vsphere-60/topic/com.vmware.wssdk.apiref.doc/vim.vm.guest.ProcessManager.html
+type ProcessManager struct {
+ wg sync.WaitGroup
+ mu sync.Mutex
+ expire time.Duration
+ entries map[int64]*Process
+ pids sync.Pool
+}
+
+// NewProcessManager creates a new ProcessManager instance.
+func NewProcessManager() *ProcessManager {
+ // We use pseudo PIDs that don't conflict with OS PIDs, so they can live in the same table.
+ // For the pseudo PIDs, we use a sync.Pool rather than a plain old counter to avoid the unlikely,
+ // but possible wrapping should such a counter exceed MaxInt64.
+ pid := int64(32768) // TODO: /proc/sys/kernel/pid_max
+
+ return &ProcessManager{
+ expire: time.Minute * 5,
+ entries: make(map[int64]*Process),
+ pids: sync.Pool{
+ New: func() interface{} {
+ return atomic.AddInt64(&pid, 1)
+ },
+ },
+ }
+}
+
+// Start calls the Process.Start function, returning the pid on success or an error.
+// A goroutine is started that calls the Process.Wait function. After Process.Wait has
+// returned, the ProcessState EndTime and ExitCode fields are set. The process state can be
+// queried via ListProcessesInGuest until it is removed, 5 minutes after Wait returns.
+func (m *ProcessManager) Start(r *vix.StartProgramRequest, p *Process) (int64, error) {
+ p.Name = r.ProgramPath
+ p.Args = r.Arguments
+
+ // Owner is cosmetic, but useful for example with: govc guest.ps -U $uid
+ if p.Owner == "" {
+ p.Owner = defaultOwner
+ }
+
+ p.StartTime = time.Now().Unix()
+
+ p.ctx, p.Kill = context.WithCancel(context.Background())
+
+ pid, err := p.Start(p, r)
+ if err != nil {
+ return -1, err
+ }
+
+ if pid == 0 {
+ p.Pid = m.pids.Get().(int64) // pseudo pid for funcs
+ } else {
+ p.Pid = pid
+ }
+
+ m.mu.Lock()
+ m.entries[p.Pid] = p
+ m.mu.Unlock()
+
+ m.wg.Add(1)
+ go func() {
+ werr := p.Wait()
+
+ atomic.StoreInt64(&p.EndTime, time.Now().Unix())
+
+ if werr != nil {
+ rc := int32(1)
+ if xerr, ok := werr.(*ProcessError); ok {
+ rc = xerr.ExitCode
+ }
+
+ atomic.StoreInt32(&p.ExitCode, rc)
+ }
+
+ m.wg.Done()
+ p.Kill() // cancel context for those waiting on p.ctx.Done()
+
+ // See: http://pubs.vmware.com/vsphere-65/topic/com.vmware.wssdk.apiref.doc/vim.vm.guest.ProcessManager.ProcessInfo.html
+ // "If the process was started using StartProgramInGuest then the process completion time
+ // will be available if queried within 5 minutes after it completes."
+ <-time.After(m.expire)
+
+ m.mu.Lock()
+ delete(m.entries, p.Pid)
+ m.mu.Unlock()
+
+ if pid == 0 {
+ m.pids.Put(p.Pid) // pseudo pid can be reused now
+ }
+ }()
+
+ return p.Pid, nil
+}
+
+// Kill cancels the Process Context.
+// Returns true if pid exists in the process table, false otherwise.
+func (m *ProcessManager) Kill(pid int64) bool {
+ m.mu.Lock()
+ entry, ok := m.entries[pid]
+ m.mu.Unlock()
+
+ if ok {
+ entry.Kill()
+ return true
+ }
+
+ return false
+}
+
+// ListProcesses marshals the ProcessState for the given pids.
+// If no pids are specified, all current processes are included.
+// The return value can be used for responding to a VixMsgListProcessesExRequest.
+func (m *ProcessManager) ListProcesses(pids []int64) []byte {
+ w := new(bytes.Buffer)
+
+ m.mu.Lock()
+
+ if len(pids) == 0 {
+ for _, p := range m.entries {
+ _, _ = w.WriteString(p.toXML())
+ }
+ } else {
+ for _, id := range pids {
+ p, ok := m.entries[id]
+ if !ok {
+ continue
+ }
+
+ _, _ = w.WriteString(p.toXML())
+ }
+ }
+
+ m.mu.Unlock()
+
+ return w.Bytes()
+}
+
+type procFileInfo struct {
+ os.FileInfo
+}
+
+// Size returns hgfs.LargePacketMax such that InitiateFileTransferFromGuest can download a /proc/ file from the guest.
+// If we were to return the size '0' here, then a 'Content-Length: 0' header is returned by VC/ESX.
+func (p procFileInfo) Size() int64 {
+ return hgfs.LargePacketMax // Remember, Sully, when I promised to kill you last? I lied.
+}
+
+// Stat implements hgfs.FileHandler.Stat
+func (m *ProcessManager) Stat(u *url.URL) (os.FileInfo, error) {
+ name := path.Join("/proc", u.Path)
+
+ info, err := os.Stat(name)
+ if err == nil && info.Size() == 0 {
+ // This is a real /proc file
+ return &procFileInfo{info}, nil
+ }
+
+ dir, file := path.Split(u.Path)
+
+ pid, err := strconv.ParseInt(path.Base(dir), 10, 64)
+ if err != nil {
+ return nil, os.ErrNotExist
+ }
+
+ m.mu.Lock()
+ p := m.entries[pid]
+ m.mu.Unlock()
+
+ if p == nil || p.IO == nil {
+ return nil, os.ErrNotExist
+ }
+
+ pf := &ProcessFile{
+ name: name,
+ Closer: ioutil.NopCloser(nil), // via hgfs, nop for stdout and stderr
+ }
+
+ var r *bytes.Buffer
+
+ switch file {
+ case "stdin":
+ pf.Writer = p.IO.In.Writer
+ pf.Closer = p.IO.In.Closer
+ return pf, nil
+ case "stdout":
+ r = p.IO.Out
+ case "stderr":
+ r = p.IO.Err
+ default:
+ return nil, os.ErrNotExist
+ }
+
+ select {
+ case <-p.ctx.Done():
+ case <-time.After(time.Second):
+ // The vmx guest RPC calls are queue based, serialized on the vmx side.
+ // There are 5 seconds between "ping" RPC calls and after a few misses,
+ // the vmx considers tools as not running. In this case, the vmx would timeout
+ // a file transfer after 60 seconds.
+ //
+ // vix.FileAccessError is converted to a CannotAccessFile fault,
+ // so the client can choose to retry the transfer in this case.
+ // Would have preferred vix.ObjectIsBusy (EBUSY), but VC/ESX converts that
+ // to a general SystemErrorFault with nothing but a localized string message
+ // to check against: "vix error codes = (5, 0)."
+ // Is standard vmware-tools, EACCES is converted to a CannotAccessFile fault.
+ return nil, vix.Error(vix.FileAccessError)
+ }
+
+ pf.Reader = r
+ pf.size = r.Len()
+
+ return pf, nil
+}
+
+// Open implements hgfs.FileHandler.Open
+func (m *ProcessManager) Open(u *url.URL, mode int32) (hgfs.File, error) {
+ info, err := m.Stat(u)
+ if err != nil {
+ return nil, err
+ }
+
+ pinfo, ok := info.(*ProcessFile)
+
+ if !ok {
+ return nil, os.ErrNotExist // fall through to default os.Open
+ }
+
+ switch path.Base(u.Path) {
+ case "stdin":
+ if mode != hgfs.OpenModeWriteOnly {
+ return nil, vix.Error(vix.InvalidArg)
+ }
+ case "stdout", "stderr":
+ if mode != hgfs.OpenModeReadOnly {
+ return nil, vix.Error(vix.InvalidArg)
+ }
+ }
+
+ return pinfo, nil
+}
+
+type processFunc struct {
+ wg sync.WaitGroup
+
+ run func(context.Context, string) error
+
+ err error
+}
+
+// NewProcessFunc creates a new Process, where the Start function calls the given run function within a goroutine.
+// The Wait function waits for the goroutine to finish and returns the error returned by run.
+// The run ctx param may be used to return early via the ProcessManager.Kill method.
+// The run args command is that of the VixMsgStartProgramRequest.Arguments field.
+func NewProcessFunc(run func(ctx context.Context, args string) error) *Process {
+ f := &processFunc{run: run}
+
+ return &Process{
+ Start: f.start,
+ Wait: f.wait,
+ }
+}
+
+// ProcessFuncIO is the Context key to access optional ProcessIO
+var ProcessFuncIO = struct {
+ key int
+}{vix.CommandMagicWord}
+
+func (f *processFunc) start(p *Process, r *vix.StartProgramRequest) (int64, error) {
+ f.wg.Add(1)
+
+ var c io.Closer
+
+ if p.IO != nil {
+ pr, pw := io.Pipe()
+
+ p.IO.In.Reader, p.IO.In.Writer = pr, pw
+ c, p.IO.In.Closer = pr, pw
+
+ p.ctx = context.WithValue(p.ctx, ProcessFuncIO, p.IO)
+ }
+
+ go func() {
+ f.err = f.run(p.ctx, r.Arguments)
+
+ if p.IO != nil {
+ _ = c.Close()
+
+ if f.err != nil && p.IO.Err.Len() == 0 {
+ p.IO.Err.WriteString(f.err.Error())
+ }
+ }
+
+ f.wg.Done()
+ }()
+
+ return 0, nil
+}
+
+func (f *processFunc) wait() error {
+ f.wg.Wait()
+ return f.err
+}
+
+type processCmd struct {
+ cmd *exec.Cmd
+}
+
+// NewProcess creates a new Process, where the Start function use exec.CommandContext to create and start the process.
+// The Wait function waits for the process to finish and returns the error returned by exec.Cmd.Wait().
+// Prior to Wait returning, the exec.Cmd.Wait() error is used to set the ProcessState.ExitCode, if error is of type exec.ExitError.
+// The ctx param may be used to kill the process via the ProcessManager.Kill method.
+// The VixMsgStartProgramRequest param fields are mapped to the exec.Cmd counterpart fields.
+// Processes are started within a sub-shell, allowing for i/o redirection, just as with the C version of vmware-tools.
+func NewProcess() *Process {
+ c := new(processCmd)
+
+ return &Process{
+ Start: c.start,
+ Wait: c.wait,
+ }
+}
+
+func (c *processCmd) start(p *Process, r *vix.StartProgramRequest) (int64, error) {
+ name, err := exec.LookPath(r.ProgramPath)
+ if err != nil {
+ return -1, err
+ }
+ // #nosec: Subprocess launching with variable
+ // Note that processCmd is currently used only for testing.
+ c.cmd = exec.CommandContext(p.ctx, shell, "-c", fmt.Sprintf("%s %s", name, r.Arguments))
+ c.cmd.Dir = r.WorkingDir
+ c.cmd.Env = r.EnvVars
+
+ if p.IO != nil {
+ in, perr := c.cmd.StdinPipe()
+ if perr != nil {
+ return -1, perr
+ }
+
+ p.IO.In.Writer = in
+ p.IO.In.Closer = in
+
+ // Note we currently use a Buffer in addition to the os.Pipe so that:
+ // - Stat() can provide a size
+ // - FileTransferFromGuest won't block
+ // - Can't use the exec.Cmd.Std{out,err}Pipe methods since Wait() closes the pipes.
+ // We could use os.Pipe directly, but toolbox needs to take care of closing both ends,
+ // but also need to prevent FileTransferFromGuest from blocking.
+ c.cmd.Stdout = p.IO.Out
+ c.cmd.Stderr = p.IO.Err
+ }
+
+ err = c.cmd.Start()
+ if err != nil {
+ return -1, err
+ }
+
+ return int64(c.cmd.Process.Pid), nil
+}
+
+func (c *processCmd) wait() error {
+ err := c.cmd.Wait()
+ if err != nil {
+ xerr := &ProcessError{
+ Err: err,
+ ExitCode: 1,
+ }
+
+ if x, ok := err.(*exec.ExitError); ok {
+ if status, ok := x.Sys().(syscall.WaitStatus); ok {
+ xerr.ExitCode = int32(status.ExitStatus())
+ }
+ }
+
+ return xerr
+ }
+
+ return nil
+}
+
+// NewProcessRoundTrip starts a Go function to implement a toolbox backed http.RoundTripper
+func NewProcessRoundTrip() *Process {
+ return NewProcessFunc(func(ctx context.Context, host string) error {
+ p, _ := ctx.Value(ProcessFuncIO).(*ProcessIO)
+
+ closers := []io.Closer{p.In.Closer}
+
+ defer func() {
+ for _, c := range closers {
+ _ = c.Close()
+ }
+ }()
+
+ c, err := new(net.Dialer).DialContext(ctx, "tcp", host)
+ if err != nil {
+ return err
+ }
+
+ closers = append(closers, c)
+
+ go func() {
+ <-ctx.Done()
+ if ctx.Err() == context.DeadlineExceeded {
+ _ = c.Close()
+ }
+ }()
+
+ _, err = io.Copy(c, p.In.Reader)
+ if err != nil {
+ return err
+ }
+
+ _, err = io.Copy(p.Out, c)
+ if err != nil {
+ return err
+ }
+
+ return nil
+ }).WithIO()
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/service.go b/vendor/github.com/vmware/govmomi/toolbox/service.go
new file mode 100644
index 00000000..81c9f397
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/service.go
@@ -0,0 +1,336 @@
+/*
+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 toolbox
+
+import (
+ "bytes"
+ "fmt"
+ "log"
+ "net"
+ "os"
+ "sync"
+ "time"
+
+ "github.com/vmware/govmomi/toolbox/hgfs"
+)
+
+const (
+ // TOOLS_VERSION_UNMANAGED as defined in open-vm-tools/lib/include/vm_tools_version.h
+ toolsVersionUnmanaged = 0x7fffffff
+
+ // RPCIN_MAX_DELAY as defined in rpcChannelInt.h:
+ maxDelay = 10
+)
+
+var (
+ capabilities = []string{
+ // Without tools.set.version, the UI reports Tools are "running", but "not installed"
+ fmt.Sprintf("tools.set.version %d", toolsVersionUnmanaged),
+
+ // Required to invoke guest power operations (shutdown, reboot)
+ "tools.capability.statechange",
+
+ "tools.capability.hgfs_server toolbox 1",
+ }
+
+ netInterfaceAddrs = net.InterfaceAddrs
+
+ // If we have an RPCI send error, the channels will be reset.
+ // open-vm-tools/lib/rpcChannel/rpcChannel.c:RpcChannelCheckReset also backs off in this case
+ resetDelay = time.Duration(500) // 500 * 10ms == 5s
+)
+
+// Service receives and dispatches incoming RPC requests from the vmx
+type Service struct {
+ name string
+ in Channel
+ out *ChannelOut
+ handlers map[string]Handler
+ stop chan struct{}
+ wg *sync.WaitGroup
+ delay time.Duration
+ rpcError bool
+
+ Command *CommandServer
+ Power *PowerCommandHandler
+
+ PrimaryIP func() string
+}
+
+// NewService initializes a Service instance
+func NewService(rpcIn Channel, rpcOut Channel) *Service {
+ s := &Service{
+ name: "toolbox", // Same name used by vmtoolsd
+ in: NewTraceChannel(rpcIn),
+ out: &ChannelOut{NewTraceChannel(rpcOut)},
+ handlers: make(map[string]Handler),
+ wg: new(sync.WaitGroup),
+ stop: make(chan struct{}),
+
+ PrimaryIP: DefaultIP,
+ }
+
+ s.RegisterHandler("reset", s.Reset)
+ s.RegisterHandler("ping", s.Ping)
+ s.RegisterHandler("Set_Option", s.SetOption)
+ s.RegisterHandler("Capabilities_Register", s.CapabilitiesRegister)
+
+ s.Command = registerCommandServer(s)
+ s.Command.FileServer = hgfs.NewServer()
+ s.Command.FileServer.RegisterFileHandler("proc", s.Command.ProcessManager)
+ s.Command.FileServer.RegisterFileHandler(hgfs.ArchiveScheme, hgfs.NewArchiveHandler())
+
+ s.Power = registerPowerCommandHandler(s)
+
+ return s
+}
+
+// backoff exponentially increases the RPC poll delay up to maxDelay
+func (s *Service) backoff() {
+ if s.delay < maxDelay {
+ if s.delay > 0 {
+ d := s.delay * 2
+ if d > s.delay && d < maxDelay {
+ s.delay = d
+ } else {
+ s.delay = maxDelay
+ }
+ } else {
+ s.delay = 1
+ }
+ }
+}
+
+func (s *Service) stopChannel() {
+ _ = s.in.Stop()
+ _ = s.out.Stop()
+}
+
+func (s *Service) startChannel() error {
+ err := s.in.Start()
+ if err != nil {
+ return err
+ }
+
+ return s.out.Start()
+}
+
+func (s *Service) checkReset() error {
+ if s.rpcError {
+ s.stopChannel()
+ err := s.startChannel()
+ if err != nil {
+ s.delay = resetDelay
+ return err
+ }
+ s.rpcError = false
+ }
+
+ return nil
+}
+
+// Start initializes the RPC channels and starts a goroutine to listen for incoming RPC requests
+func (s *Service) Start() error {
+ err := s.startChannel()
+ if err != nil {
+ return err
+ }
+
+ s.wg.Add(1)
+ go func() {
+ defer s.wg.Done()
+
+ // Same polling interval and backoff logic as vmtoolsd.
+ // Required in our case at startup at least, otherwise it is possible
+ // we miss the 1 Capabilities_Register call for example.
+
+ // Note we Send(response) even when nil, to let the VMX know we are here
+ var response []byte
+
+ for {
+ select {
+ case <-s.stop:
+ s.stopChannel()
+ return
+ case <-time.After(time.Millisecond * 10 * s.delay):
+ if err = s.checkReset(); err != nil {
+ continue
+ }
+
+ err = s.in.Send(response)
+ response = nil
+ if err != nil {
+ s.delay = resetDelay
+ s.rpcError = true
+ continue
+ }
+
+ request, _ := s.in.Receive()
+
+ if len(request) > 0 {
+ response = s.Dispatch(request)
+
+ s.delay = 0
+ } else {
+ s.backoff()
+ }
+ }
+ }
+ }()
+
+ return nil
+}
+
+// Stop cancels the RPC listener routine created via Start
+func (s *Service) Stop() {
+ close(s.stop)
+}
+
+// Wait blocks until Start returns, allowing any current RPC in progress to complete.
+func (s *Service) Wait() {
+ s.wg.Wait()
+}
+
+// Handler is given the raw argument portion of an RPC request and returns a response
+type Handler func([]byte) ([]byte, error)
+
+// RegisterHandler for the given RPC name
+func (s *Service) RegisterHandler(name string, handler Handler) {
+ s.handlers[name] = handler
+}
+
+// Dispatch an incoming RPC request to a Handler
+func (s *Service) Dispatch(request []byte) []byte {
+ msg := bytes.SplitN(request, []byte{' '}, 2)
+ name := msg[0]
+
+ // Trim NULL byte terminator
+ name = bytes.TrimRight(name, "\x00")
+
+ handler, ok := s.handlers[string(name)]
+
+ if !ok {
+ log.Printf("unknown command: %q\n", name)
+ return []byte("Unknown Command")
+ }
+
+ var args []byte
+ if len(msg) == 2 {
+ args = msg[1]
+ }
+
+ response, err := handler(args)
+ if err == nil {
+ response = append([]byte("OK "), response...)
+ } else {
+ log.Printf("error calling %s: %s\n", name, err)
+ response = append([]byte("ERR "), response...)
+ }
+
+ return response
+}
+
+// Reset is the default Handler for reset requests
+func (s *Service) Reset([]byte) ([]byte, error) {
+ s.SendGuestInfo() // Send the IP info ASAP
+
+ return []byte("ATR " + s.name), nil
+}
+
+// Ping is the default Handler for ping requests
+func (s *Service) Ping([]byte) ([]byte, error) {
+ return nil, nil
+}
+
+// SetOption is the default Handler for Set_Option requests
+func (s *Service) SetOption(args []byte) ([]byte, error) {
+ opts := bytes.SplitN(args, []byte{' '}, 2)
+ key := string(opts[0])
+ val := string(opts[1])
+
+ if Trace {
+ fmt.Fprintf(os.Stderr, "set option %q=%q\n", key, val)
+ }
+
+ switch key {
+ case "broadcastIP": // TODO: const-ify
+ if val == "1" {
+ ip := s.PrimaryIP()
+ if ip == "" {
+ log.Printf("failed to find primary IP")
+ return nil, nil
+ }
+ msg := fmt.Sprintf("info-set guestinfo.ip %s", ip)
+ _, err := s.out.Request([]byte(msg))
+ if err != nil {
+ return nil, err
+ }
+
+ s.SendGuestInfo()
+ }
+ default:
+ // TODO: handle other options...
+ }
+
+ return nil, nil
+}
+
+// DefaultIP is used by default when responding to a Set_Option broadcastIP request
+// It can be overridden with the Service.PrimaryIP field
+func DefaultIP() string {
+ addrs, err := netInterfaceAddrs()
+ if err == nil {
+ for _, addr := range addrs {
+ if ip, ok := addr.(*net.IPNet); ok && !ip.IP.IsLoopback() {
+ if ip.IP.To4() != nil {
+ return ip.IP.String()
+ }
+ }
+ }
+ }
+
+ return ""
+}
+
+func (s *Service) CapabilitiesRegister([]byte) ([]byte, error) {
+ for _, cap := range capabilities {
+ _, err := s.out.Request([]byte(cap))
+ if err != nil {
+ log.Printf("send %q: %s", cap, err)
+ }
+ }
+
+ return nil, nil
+}
+
+func (s *Service) SendGuestInfo() {
+ info := []func() ([]byte, error){
+ GuestInfoNicInfoRequest,
+ }
+
+ for i, r := range info {
+ b, err := r()
+
+ if err == nil {
+ _, err = s.out.Request(b)
+ }
+
+ if err != nil {
+ log.Printf("SendGuestInfo %d: %s", i, err)
+ }
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/toolbox/main.go b/vendor/github.com/vmware/govmomi/toolbox/toolbox/main.go
new file mode 100644
index 00000000..083d9f1f
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/toolbox/main.go
@@ -0,0 +1,71 @@
+/*
+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.
+*/
+// Copyright 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 main
+
+import (
+ "flag"
+ "log"
+ "os"
+ "os/signal"
+ "syscall"
+
+ "github.com/vmware/govmomi/toolbox"
+)
+
+// This example can be run on a VM hosted by ESX, Fusion or Workstation
+func main() {
+ flag.Parse()
+
+ in := toolbox.NewBackdoorChannelIn()
+ out := toolbox.NewBackdoorChannelOut()
+
+ service := toolbox.NewService(in, out)
+
+ if os.Getuid() == 0 {
+ service.Power.Halt.Handler = toolbox.Halt
+ service.Power.Reboot.Handler = toolbox.Reboot
+ }
+
+ err := service.Start()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // handle the signals and gracefully shutdown the service
+ sig := make(chan os.Signal, 1)
+ signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
+
+ go func() {
+ log.Printf("signal %s received", <-sig)
+ service.Stop()
+ }()
+
+ service.Wait()
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/toolbox_darwin.go b/vendor/github.com/vmware/govmomi/toolbox/toolbox_darwin.go
new file mode 100644
index 00000000..fb3c1303
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/toolbox_darwin.go
@@ -0,0 +1,25 @@
+/*
+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 toolbox
+
+import (
+ "os"
+)
+
+func fileExtendedInfoFormat(dir string, info os.FileInfo) string {
+ return ""
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/toolbox_linux.go b/vendor/github.com/vmware/govmomi/toolbox/toolbox_linux.go
new file mode 100644
index 00000000..35e671a9
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/toolbox_linux.go
@@ -0,0 +1,69 @@
+/*
+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 toolbox
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "syscall"
+ "time"
+
+ "github.com/vmware/govmomi/toolbox/vix"
+)
+
+func fileExtendedInfoFormat(dir string, info os.FileInfo) string {
+ const format = "" +
+ "%s" +
+ "%d" +
+ "%d" +
+ "%d" +
+ "%d" +
+ "%d" +
+ "%d" +
+ "%d" +
+ "%s" +
+ ""
+
+ props := 0
+ targ := ""
+
+ if info.IsDir() {
+ props |= vix.FileAttributesDirectory
+ }
+
+ if info.Mode()&os.ModeSymlink == os.ModeSymlink {
+ props |= vix.FileAttributesSymlink
+ targ, _ = os.Readlink(filepath.Join(dir, info.Name()))
+ }
+
+ size := info.Size()
+ mtime := info.ModTime().Unix()
+ perm := info.Mode().Perm()
+
+ atime := mtime
+ uid := os.Getuid()
+ gid := os.Getgid()
+
+ if sys, ok := info.Sys().(*syscall.Stat_t); ok {
+ atime = time.Unix(sys.Atim.Unix()).Unix()
+ uid = int(sys.Uid)
+ gid = int(sys.Gid)
+ }
+
+ return fmt.Sprintf(format, info.Name(), props, size, mtime, atime, uid, gid, perm, targ)
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/toolbox_windows.go b/vendor/github.com/vmware/govmomi/toolbox/toolbox_windows.go
new file mode 100644
index 00000000..7e5c11e5
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/toolbox_windows.go
@@ -0,0 +1,41 @@
+/*
+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 toolbox
+
+import (
+ "fmt"
+ "os"
+)
+
+func fileExtendedInfoFormat(dir string, info os.FileInfo) string {
+ const format = "" +
+ "%s" +
+ "%d" +
+ "%d" +
+ "%d" +
+ "%d" +
+ "%d" +
+ ""
+
+ props := 0
+ size := info.Size()
+ mtime := info.ModTime().Unix()
+ ctime := 0
+ atime := 0
+
+ return fmt.Sprintf(format, info.Name(), props, size, mtime, ctime, atime)
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/trace_channel.go b/vendor/github.com/vmware/govmomi/toolbox/trace_channel.go
new file mode 100644
index 00000000..925ce4ce
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/trace_channel.go
@@ -0,0 +1,83 @@
+/*
+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 toolbox
+
+import (
+ "encoding/hex"
+ "flag"
+ "fmt"
+ "io"
+ "os"
+)
+
+var (
+ Trace = false
+
+ traceLog io.Writer = os.Stderr
+)
+
+func init() {
+ flag.BoolVar(&Trace, "toolbox.trace", Trace, "Enable toolbox trace")
+}
+
+type TraceChannel struct {
+ Channel
+ log io.Writer
+}
+
+func NewTraceChannel(c Channel) Channel {
+ if !Trace {
+ return c
+ }
+
+ return &TraceChannel{
+ Channel: c,
+ log: traceLog,
+ }
+}
+
+func (d *TraceChannel) Start() error {
+ err := d.Channel.Start()
+
+ return err
+}
+
+func (d *TraceChannel) Stop() error {
+ err := d.Channel.Stop()
+
+ return err
+}
+
+func (d *TraceChannel) Send(buf []byte) error {
+ if len(buf) > 0 {
+ fmt.Fprintf(d.log, "SEND %d...\n%s\n", len(buf), hex.Dump(buf))
+ }
+
+ err := d.Channel.Send(buf)
+
+ return err
+}
+
+func (d *TraceChannel) Receive() ([]byte, error) {
+ buf, err := d.Channel.Receive()
+
+ if err == nil && len(buf) > 0 {
+ fmt.Fprintf(d.log, "RECV %d...\n%s\n", len(buf), hex.Dump(buf))
+ }
+
+ return buf, err
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/vix/property.go b/vendor/github.com/vmware/govmomi/toolbox/vix/property.go
new file mode 100644
index 00000000..aa708c4e
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/vix/property.go
@@ -0,0 +1,236 @@
+/*
+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 vix
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+)
+
+// Property type enum as defined in open-vm-tools/lib/include/vix.h
+const (
+ _ = iota // ANY type not supported
+ vixPropertyTypeInt32
+ vixPropertyTypeString
+ vixPropertyTypeBool
+ _ // HANDLE type not supported
+ vixPropertyTypeInt64
+ vixPropertyTypeBlob
+)
+
+// Property ID enum as defined in open-vm-tools/lib/include/vixOpenSource.h
+const (
+ PropertyGuestToolsAPIOptions = 4501
+ PropertyGuestOsFamily = 4502
+ PropertyGuestOsVersion = 4503
+ PropertyGuestToolsProductNam = 4511
+ PropertyGuestToolsVersion = 4500
+ PropertyGuestName = 4505
+ PropertyGuestOsVersionShort = 4520
+
+ PropertyGuestStartProgramEnabled = 4540
+ PropertyGuestListProcessesEnabled = 4541
+ PropertyGuestTerminateProcessEnabled = 4542
+ PropertyGuestReadEnvironmentVariableEnabled = 4543
+
+ PropertyGuestMakeDirectoryEnabled = 4547
+ PropertyGuestDeleteFileEnabled = 4548
+ PropertyGuestDeleteDirectoryEnabled = 4549
+ PropertyGuestMoveDirectoryEnabled = 4550
+ PropertyGuestMoveFileEnabled = 4551
+ PropertyGuestCreateTempFileEnabled = 4552
+ PropertyGuestCreateTempDirectoryEnabled = 4553
+ PropertyGuestListFilesEnabled = 4554
+ PropertyGuestChangeFileAttributesEnabled = 4555
+ PropertyGuestInitiateFileTransferFromGuestEnabled = 4556
+ PropertyGuestInitiateFileTransferToGuestEnabled = 4557
+)
+
+type Property struct {
+ header struct {
+ ID int32
+ Kind int32
+ Length int32
+ }
+
+ data struct {
+ Int32 int32
+ String string
+ Bool uint8
+ Int64 int64
+ Blob []byte
+ }
+}
+
+var int32Size int32
+
+func init() {
+ var i int32
+ int32Size = int32(binary.Size(&i))
+}
+
+type PropertyList []*Property
+
+func NewInt32Property(ID int32, val int32) *Property {
+ p := new(Property)
+ p.header.ID = ID
+ p.header.Kind = vixPropertyTypeInt32
+ p.header.Length = int32Size
+ p.data.Int32 = val
+ return p
+}
+
+func NewStringProperty(ID int32, val string) *Property {
+ p := new(Property)
+ p.header.ID = ID
+ p.header.Kind = vixPropertyTypeString
+ p.header.Length = int32(len(val) + 1)
+ p.data.String = val
+ return p
+}
+
+func NewBoolProperty(ID int32, val bool) *Property {
+ p := new(Property)
+ p.header.ID = ID
+ p.header.Kind = vixPropertyTypeBool
+ p.header.Length = 1
+ if val {
+ p.data.Bool = 1
+ }
+ return p
+}
+
+func NewInt64Property(ID int32, val int64) *Property {
+ p := new(Property)
+ p.header.ID = ID
+ p.header.Kind = vixPropertyTypeInt64
+ p.header.Length = int32Size * 2
+ p.data.Int64 = val
+ return p
+}
+
+func NewBlobProperty(ID int32, val []byte) *Property {
+ p := new(Property)
+ p.header.ID = ID
+ p.header.Kind = vixPropertyTypeBlob
+ p.header.Length = int32(len(val))
+ p.data.Blob = val
+ return p
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (p *Property) MarshalBinary() ([]byte, error) {
+ buf := new(bytes.Buffer)
+
+ // #nosec: Errors unhandled
+ _ = binary.Write(buf, binary.LittleEndian, &p.header)
+
+ switch p.header.Kind {
+ case vixPropertyTypeBool:
+ // #nosec: Errors unhandled
+ _ = binary.Write(buf, binary.LittleEndian, p.data.Bool)
+ case vixPropertyTypeInt32:
+ // #nosec: Errors unhandled
+ _ = binary.Write(buf, binary.LittleEndian, p.data.Int32)
+ case vixPropertyTypeInt64:
+ // #nosec: Errors unhandled
+ _ = binary.Write(buf, binary.LittleEndian, p.data.Int64)
+ case vixPropertyTypeString:
+ // #nosec: Errors unhandled
+ _, _ = buf.WriteString(p.data.String)
+ // #nosec: Errors unhandled
+ _ = buf.WriteByte(0)
+ case vixPropertyTypeBlob:
+ // #nosec: Errors unhandled
+ _, _ = buf.Write(p.data.Blob)
+ }
+
+ return buf.Bytes(), nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (p *Property) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ err := binary.Read(buf, binary.LittleEndian, &p.header)
+ if err != nil {
+ return err
+ }
+
+ switch p.header.Kind {
+ case vixPropertyTypeBool:
+ return binary.Read(buf, binary.LittleEndian, &p.data.Bool)
+ case vixPropertyTypeInt32:
+ return binary.Read(buf, binary.LittleEndian, &p.data.Int32)
+ case vixPropertyTypeInt64:
+ return binary.Read(buf, binary.LittleEndian, &p.data.Int64)
+ case vixPropertyTypeString:
+ s := make([]byte, p.header.Length)
+ if _, err := buf.Read(s); err != nil {
+ return err
+ }
+
+ p.data.String = string(bytes.TrimRight(s, "\x00"))
+ case vixPropertyTypeBlob:
+ p.data.Blob = make([]byte, p.header.Length)
+ if _, err := buf.Read(p.data.Blob); err != nil {
+ return err
+ }
+ default:
+ return errors.New("VIX_E_UNRECOGNIZED_PROPERTY")
+ }
+
+ return nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (l *PropertyList) UnmarshalBinary(data []byte) error {
+ headerSize := int32Size * 3
+
+ for {
+ p := new(Property)
+
+ err := p.UnmarshalBinary(data)
+ if err != nil {
+ return err
+ }
+
+ *l = append(*l, p)
+
+ offset := headerSize + p.header.Length
+ data = data[offset:]
+
+ if len(data) == 0 {
+ return nil
+ }
+ }
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (l *PropertyList) MarshalBinary() ([]byte, error) {
+ var buf bytes.Buffer
+
+ for _, p := range *l {
+ // #nosec: Errors unhandled
+ b, _ := p.MarshalBinary()
+ // #nosec: Errors unhandled
+ _, _ = buf.Write(b)
+ }
+
+ return buf.Bytes(), nil
+}
diff --git a/vendor/github.com/vmware/govmomi/toolbox/vix/protocol.go b/vendor/github.com/vmware/govmomi/toolbox/vix/protocol.go
new file mode 100644
index 00000000..c15c4598
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/toolbox/vix/protocol.go
@@ -0,0 +1,847 @@
+/*
+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 vix
+
+import (
+ "bytes"
+ "encoding/base64"
+ "encoding/binary"
+ "fmt"
+ "os"
+ "os/exec"
+ "syscall"
+)
+
+const (
+ CommandMagicWord = 0xd00d0001
+
+ CommandGetToolsState = 62
+
+ CommandStartProgram = 185
+ CommandListProcessesEx = 186
+ CommandReadEnvVariables = 187
+ CommandTerminateProcess = 193
+
+ CommandCreateDirectoryEx = 178
+ CommandMoveGuestFileEx = 179
+ CommandMoveGuestDirectory = 180
+ CommandCreateTemporaryFileEx = 181
+ CommandCreateTemporaryDirectory = 182
+ CommandSetGuestFileAttributes = 183
+ CommandDeleteGuestFileEx = 194
+ CommandDeleteGuestDirectoryEx = 195
+
+ CommandListFiles = 177
+ HgfsSendPacketCommand = 84
+ CommandInitiateFileTransferFromGuest = 188
+ CommandInitiateFileTransferToGuest = 189
+
+ // VIX_USER_CREDENTIAL_NAME_PASSWORD
+ UserCredentialTypeNamePassword = 1
+
+ // VIX_E_* constants from vix.h
+ OK = 0
+ Fail = 1
+ InvalidArg = 3
+ FileNotFound = 4
+ FileAlreadyExists = 12
+ FileAccessError = 13
+ AuthenticationFail = 35
+
+ UnrecognizedCommandInGuest = 3025
+ InvalidMessageHeader = 10000
+ InvalidMessageBody = 10001
+ NotAFile = 20001
+ NotADirectory = 20002
+ NoSuchProcess = 20003
+ DirectoryNotEmpty = 20006
+
+ // VIX_COMMAND_* constants from Commands.h
+ CommandGuestReturnsBinary = 0x80
+
+ // VIX_FILE_ATTRIBUTES_ constants from vix.h
+ FileAttributesDirectory = 0x0001
+ FileAttributesSymlink = 0x0002
+)
+
+// SetGuestFileAttributes flags as defined in vixOpenSource.h
+const (
+ FileAttributeSetAccessDate = 0x0001
+ FileAttributeSetModifyDate = 0x0002
+ FileAttributeSetReadonly = 0x0004
+ FileAttributeSetHidden = 0x0008
+ FileAttributeSetUnixOwnerid = 0x0010
+ FileAttributeSetUnixGroupid = 0x0020
+ FileAttributeSetUnixPermissions = 0x0040
+)
+
+type Error int
+
+func (err Error) Error() string {
+ return fmt.Sprintf("vix error=%d", err)
+}
+
+// ErrorCode does its best to map the given error to a VIX error code.
+// See also: Vix_TranslateErrno
+func ErrorCode(err error) int {
+ switch t := err.(type) {
+ case Error:
+ return int(t)
+ case *os.PathError:
+ if errno, ok := t.Err.(syscall.Errno); ok {
+ switch errno {
+ case syscall.ENOTEMPTY:
+ return DirectoryNotEmpty
+ }
+ }
+ case *exec.Error:
+ if t.Err == exec.ErrNotFound {
+ return FileNotFound
+ }
+ }
+
+ switch {
+ case os.IsNotExist(err):
+ return FileNotFound
+ case os.IsExist(err):
+ return FileAlreadyExists
+ case os.IsPermission(err):
+ return FileAccessError
+ default:
+ return Fail
+ }
+}
+
+type Header struct {
+ Magic uint32
+ MessageVersion uint16
+
+ TotalMessageLength uint32
+ HeaderLength uint32
+ BodyLength uint32
+ CredentialLength uint32
+
+ CommonFlags uint8
+}
+
+type CommandRequestHeader struct {
+ Header
+
+ OpCode uint32
+ RequestFlags uint32
+
+ TimeOut uint32
+
+ Cookie uint64
+ ClientHandleID uint32
+
+ UserCredentialType uint32
+}
+
+type StartProgramRequest struct {
+ CommandRequestHeader
+
+ Body struct {
+ StartMinimized uint8
+ ProgramPathLength uint32
+ ArgumentsLength uint32
+ WorkingDirLength uint32
+ NumEnvVars uint32
+ EnvVarLength uint32
+ }
+
+ ProgramPath string
+ Arguments string
+ WorkingDir string
+ EnvVars []string
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *StartProgramRequest) MarshalBinary() ([]byte, error) {
+ var env bytes.Buffer
+
+ if n := len(r.EnvVars); n != 0 {
+ for _, e := range r.EnvVars {
+ _, _ = env.Write([]byte(e))
+ _ = env.WriteByte(0)
+ }
+ r.Body.NumEnvVars = uint32(n)
+ r.Body.EnvVarLength = uint32(env.Len())
+ }
+
+ var fields []string
+
+ add := func(s string, l *uint32) {
+ if n := len(s); n != 0 {
+ *l = uint32(n) + 1
+ fields = append(fields, s)
+ }
+ }
+
+ add(r.ProgramPath, &r.Body.ProgramPathLength)
+ add(r.Arguments, &r.Body.ArgumentsLength)
+ add(r.WorkingDir, &r.Body.WorkingDirLength)
+
+ buf := new(bytes.Buffer)
+
+ _ = binary.Write(buf, binary.LittleEndian, &r.Body)
+
+ for _, val := range fields {
+ _, _ = buf.Write([]byte(val))
+ _ = buf.WriteByte(0)
+ }
+
+ if r.Body.EnvVarLength != 0 {
+ _, _ = buf.Write(env.Bytes())
+ }
+
+ return buf.Bytes(), nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *StartProgramRequest) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ err := binary.Read(buf, binary.LittleEndian, &r.Body)
+ if err != nil {
+ return err
+ }
+
+ fields := []struct {
+ len uint32
+ val *string
+ }{
+ {r.Body.ProgramPathLength, &r.ProgramPath},
+ {r.Body.ArgumentsLength, &r.Arguments},
+ {r.Body.WorkingDirLength, &r.WorkingDir},
+ }
+
+ for _, field := range fields {
+ if field.len == 0 {
+ continue
+ }
+
+ x := buf.Next(int(field.len))
+ *field.val = string(bytes.TrimRight(x, "\x00"))
+ }
+
+ for i := 0; i < int(r.Body.NumEnvVars); i++ {
+ env, rerr := buf.ReadString(0)
+ if rerr != nil {
+ return rerr
+ }
+
+ env = env[:len(env)-1] // discard NULL terminator
+ r.EnvVars = append(r.EnvVars, env)
+ }
+
+ return nil
+}
+
+type KillProcessRequest struct {
+ CommandRequestHeader
+
+ Body struct {
+ Pid int64
+ Options uint32
+ }
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *KillProcessRequest) MarshalBinary() ([]byte, error) {
+ buf := new(bytes.Buffer)
+
+ _ = binary.Write(buf, binary.LittleEndian, &r.Body)
+
+ return buf.Bytes(), nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *KillProcessRequest) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ return binary.Read(buf, binary.LittleEndian, &r.Body)
+}
+
+type ListProcessesRequest struct {
+ CommandRequestHeader
+
+ Body struct {
+ Key uint32
+ Offset uint32
+ NumPids uint32
+ }
+
+ Pids []int64
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *ListProcessesRequest) MarshalBinary() ([]byte, error) {
+ r.Body.NumPids = uint32(len(r.Pids))
+
+ buf := new(bytes.Buffer)
+
+ _ = binary.Write(buf, binary.LittleEndian, &r.Body)
+
+ for _, pid := range r.Pids {
+ _ = binary.Write(buf, binary.LittleEndian, &pid)
+ }
+
+ return buf.Bytes(), nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *ListProcessesRequest) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ err := binary.Read(buf, binary.LittleEndian, &r.Body)
+ if err != nil {
+ return err
+ }
+
+ r.Pids = make([]int64, r.Body.NumPids)
+
+ for i := uint32(0); i < r.Body.NumPids; i++ {
+ err := binary.Read(buf, binary.LittleEndian, &r.Pids[i])
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+type ReadEnvironmentVariablesRequest struct {
+ CommandRequestHeader
+
+ Body struct {
+ NumNames uint32
+ NamesLength uint32
+ }
+
+ Names []string
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *ReadEnvironmentVariablesRequest) MarshalBinary() ([]byte, error) {
+ var env bytes.Buffer
+
+ if n := len(r.Names); n != 0 {
+ for _, e := range r.Names {
+ _, _ = env.Write([]byte(e))
+ _ = env.WriteByte(0)
+ }
+ r.Body.NumNames = uint32(n)
+ r.Body.NamesLength = uint32(env.Len())
+ }
+
+ buf := new(bytes.Buffer)
+
+ _ = binary.Write(buf, binary.LittleEndian, &r.Body)
+
+ if r.Body.NamesLength != 0 {
+ _, _ = buf.Write(env.Bytes())
+ }
+
+ return buf.Bytes(), nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *ReadEnvironmentVariablesRequest) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ err := binary.Read(buf, binary.LittleEndian, &r.Body)
+ if err != nil {
+ return err
+ }
+
+ for i := 0; i < int(r.Body.NumNames); i++ {
+ env, rerr := buf.ReadString(0)
+ if rerr != nil {
+ return rerr
+ }
+
+ env = env[:len(env)-1] // discard NULL terminator
+ r.Names = append(r.Names, env)
+ }
+
+ return nil
+}
+
+type CreateTempFileRequest struct {
+ CommandRequestHeader
+
+ Body struct {
+ Options int32
+ FilePrefixLength uint32
+ FileSuffixLength uint32
+ DirectoryPathLength uint32
+ PropertyListLength uint32
+ }
+
+ FilePrefix string
+ FileSuffix string
+ DirectoryPath string
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *CreateTempFileRequest) MarshalBinary() ([]byte, error) {
+ var fields []string
+
+ add := func(s string, l *uint32) {
+ *l = uint32(len(s)) // NOTE: NULL byte is not included in the length fields on the wire
+ fields = append(fields, s)
+ }
+
+ add(r.FilePrefix, &r.Body.FilePrefixLength)
+ add(r.FileSuffix, &r.Body.FileSuffixLength)
+ add(r.DirectoryPath, &r.Body.DirectoryPathLength)
+
+ buf := new(bytes.Buffer)
+
+ _ = binary.Write(buf, binary.LittleEndian, &r.Body)
+
+ for _, val := range fields {
+ _, _ = buf.Write([]byte(val))
+ _ = buf.WriteByte(0)
+ }
+
+ return buf.Bytes(), nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *CreateTempFileRequest) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ err := binary.Read(buf, binary.LittleEndian, &r.Body)
+ if err != nil {
+ return err
+ }
+
+ fields := []struct {
+ len uint32
+ val *string
+ }{
+ {r.Body.FilePrefixLength, &r.FilePrefix},
+ {r.Body.FileSuffixLength, &r.FileSuffix},
+ {r.Body.DirectoryPathLength, &r.DirectoryPath},
+ }
+
+ for _, field := range fields {
+ field.len++ // NOTE: NULL byte is not included in the length fields on the wire
+
+ x := buf.Next(int(field.len))
+ *field.val = string(bytes.TrimRight(x, "\x00"))
+ }
+
+ return nil
+}
+
+type FileRequest struct {
+ CommandRequestHeader
+
+ Body struct {
+ FileOptions int32
+ GuestPathNameLength uint32
+ }
+
+ GuestPathName string
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *FileRequest) MarshalBinary() ([]byte, error) {
+ buf := new(bytes.Buffer)
+
+ r.Body.GuestPathNameLength = uint32(len(r.GuestPathName))
+
+ _ = binary.Write(buf, binary.LittleEndian, &r.Body)
+
+ _, _ = buf.WriteString(r.GuestPathName)
+ _ = buf.WriteByte(0)
+
+ return buf.Bytes(), nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *FileRequest) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ err := binary.Read(buf, binary.LittleEndian, &r.Body)
+ if err != nil {
+ return err
+ }
+
+ name := buf.Next(int(r.Body.GuestPathNameLength))
+ r.GuestPathName = string(bytes.TrimRight(name, "\x00"))
+
+ return nil
+}
+
+type DirRequest struct {
+ CommandRequestHeader
+
+ Body struct {
+ FileOptions int32
+ GuestPathNameLength uint32
+ FilePropertiesLength uint32
+ Recursive bool
+ }
+
+ GuestPathName string
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *DirRequest) MarshalBinary() ([]byte, error) {
+ buf := new(bytes.Buffer)
+
+ r.Body.GuestPathNameLength = uint32(len(r.GuestPathName))
+
+ _ = binary.Write(buf, binary.LittleEndian, &r.Body)
+
+ _, _ = buf.WriteString(r.GuestPathName)
+ _ = buf.WriteByte(0)
+
+ return buf.Bytes(), nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *DirRequest) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ err := binary.Read(buf, binary.LittleEndian, &r.Body)
+ if err != nil {
+ return err
+ }
+
+ name := buf.Next(int(r.Body.GuestPathNameLength))
+ r.GuestPathName = string(bytes.TrimRight(name, "\x00"))
+
+ return nil
+}
+
+type RenameFileRequest struct {
+ CommandRequestHeader
+
+ Body struct {
+ CopyFileOptions int32
+ OldPathNameLength uint32
+ NewPathNameLength uint32
+ FilePropertiesLength uint32
+ Overwrite bool
+ }
+
+ OldPathName string
+ NewPathName string
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *RenameFileRequest) MarshalBinary() ([]byte, error) {
+ var fields []string
+
+ add := func(s string, l *uint32) {
+ *l = uint32(len(s)) // NOTE: NULL byte is not included in the length fields on the wire
+ fields = append(fields, s)
+ }
+
+ add(r.OldPathName, &r.Body.OldPathNameLength)
+ add(r.NewPathName, &r.Body.NewPathNameLength)
+
+ buf := new(bytes.Buffer)
+
+ _ = binary.Write(buf, binary.LittleEndian, &r.Body)
+
+ for _, val := range fields {
+ _, _ = buf.Write([]byte(val))
+ _ = buf.WriteByte(0)
+ }
+
+ return buf.Bytes(), nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *RenameFileRequest) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ err := binary.Read(buf, binary.LittleEndian, &r.Body)
+ if err != nil {
+ return err
+ }
+
+ fields := []struct {
+ len uint32
+ val *string
+ }{
+ {r.Body.OldPathNameLength, &r.OldPathName},
+ {r.Body.NewPathNameLength, &r.NewPathName},
+ }
+
+ for _, field := range fields {
+ field.len++ // NOTE: NULL byte is not included in the length fields on the wire
+
+ x := buf.Next(int(field.len))
+ *field.val = string(bytes.TrimRight(x, "\x00"))
+ }
+
+ return nil
+}
+
+type ListFilesRequest struct {
+ CommandRequestHeader
+
+ Body struct {
+ FileOptions int32
+ GuestPathNameLength uint32
+ PatternLength uint32
+ Index int32
+ MaxResults int32
+ Offset uint64
+ }
+
+ GuestPathName string
+ Pattern string
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *ListFilesRequest) MarshalBinary() ([]byte, error) {
+ var fields []string
+
+ add := func(s string, l *uint32) {
+ if n := len(s); n != 0 {
+ *l = uint32(n) + 1
+ fields = append(fields, s)
+ }
+ }
+
+ add(r.GuestPathName, &r.Body.GuestPathNameLength)
+ add(r.Pattern, &r.Body.PatternLength)
+
+ buf := new(bytes.Buffer)
+
+ _ = binary.Write(buf, binary.LittleEndian, &r.Body)
+
+ for _, val := range fields {
+ _, _ = buf.Write([]byte(val))
+ _ = buf.WriteByte(0)
+ }
+
+ return buf.Bytes(), nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *ListFilesRequest) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ err := binary.Read(buf, binary.LittleEndian, &r.Body)
+ if err != nil {
+ return err
+ }
+
+ fields := []struct {
+ len uint32
+ val *string
+ }{
+ {r.Body.GuestPathNameLength, &r.GuestPathName},
+ {r.Body.PatternLength, &r.Pattern},
+ }
+
+ for _, field := range fields {
+ if field.len == 0 {
+ continue
+ }
+
+ x := buf.Next(int(field.len))
+ *field.val = string(bytes.TrimRight(x, "\x00"))
+ }
+
+ return nil
+}
+
+type SetGuestFileAttributesRequest struct {
+ CommandRequestHeader
+
+ Body struct {
+ FileOptions int32
+ AccessTime int64
+ ModificationTime int64
+ OwnerID int32
+ GroupID int32
+ Permissions int32
+ Hidden bool
+ ReadOnly bool
+ GuestPathNameLength uint32
+ }
+
+ GuestPathName string
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *SetGuestFileAttributesRequest) MarshalBinary() ([]byte, error) {
+ buf := new(bytes.Buffer)
+
+ r.Body.GuestPathNameLength = uint32(len(r.GuestPathName))
+
+ _ = binary.Write(buf, binary.LittleEndian, &r.Body)
+
+ _, _ = buf.WriteString(r.GuestPathName)
+ _ = buf.WriteByte(0)
+
+ return buf.Bytes(), nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *SetGuestFileAttributesRequest) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ err := binary.Read(buf, binary.LittleEndian, &r.Body)
+ if err != nil {
+ return err
+ }
+
+ name := buf.Next(int(r.Body.GuestPathNameLength))
+ r.GuestPathName = string(bytes.TrimRight(name, "\x00"))
+
+ return nil
+}
+
+func (r *SetGuestFileAttributesRequest) IsSet(opt int32) bool {
+ return r.Body.FileOptions&opt == opt
+}
+
+type CommandHgfsSendPacket struct {
+ CommandRequestHeader
+
+ Body struct {
+ PacketSize uint32
+ Timeout int32
+ }
+
+ Packet []byte
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *CommandHgfsSendPacket) MarshalBinary() ([]byte, error) {
+ buf := new(bytes.Buffer)
+
+ _ = binary.Write(buf, binary.LittleEndian, &r.Body)
+
+ _, _ = buf.Write(r.Packet)
+
+ return buf.Bytes(), nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *CommandHgfsSendPacket) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ err := binary.Read(buf, binary.LittleEndian, &r.Body)
+ if err != nil {
+ return err
+ }
+
+ r.Packet = buf.Next(int(r.Body.PacketSize))
+
+ return nil
+}
+
+type InitiateFileTransferToGuestRequest struct {
+ CommandRequestHeader
+
+ Body struct {
+ Options int32
+ GuestPathNameLength uint32
+ Overwrite bool
+ }
+
+ GuestPathName string
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface
+func (r *InitiateFileTransferToGuestRequest) MarshalBinary() ([]byte, error) {
+ buf := new(bytes.Buffer)
+
+ r.Body.GuestPathNameLength = uint32(len(r.GuestPathName))
+
+ _ = binary.Write(buf, binary.LittleEndian, &r.Body)
+
+ _, _ = buf.WriteString(r.GuestPathName)
+ _ = buf.WriteByte(0)
+
+ return buf.Bytes(), nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
+func (r *InitiateFileTransferToGuestRequest) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(data)
+
+ err := binary.Read(buf, binary.LittleEndian, &r.Body)
+ if err != nil {
+ return err
+ }
+
+ name := buf.Next(int(r.Body.GuestPathNameLength))
+ r.GuestPathName = string(bytes.TrimRight(name, "\x00"))
+
+ return nil
+}
+
+type UserCredentialNamePassword struct {
+ Body struct {
+ NameLength uint32
+ PasswordLength uint32
+ }
+
+ Name string
+ Password string
+}
+
+func (c *UserCredentialNamePassword) UnmarshalBinary(data []byte) error {
+ buf := bytes.NewBuffer(bytes.TrimRight(data, "\x00"))
+
+ err := binary.Read(buf, binary.LittleEndian, &c.Body)
+ if err != nil {
+ return err
+ }
+
+ str, err := base64.StdEncoding.DecodeString(string(buf.Bytes()))
+ if err != nil {
+ return err
+ }
+
+ c.Name = string(str[0:c.Body.NameLength])
+ c.Password = string(str[c.Body.NameLength+1 : len(str)-1])
+
+ return nil
+}
+
+func (c *UserCredentialNamePassword) MarshalBinary() ([]byte, error) {
+ buf := new(bytes.Buffer)
+
+ c.Body.NameLength = uint32(len(c.Name))
+ c.Body.PasswordLength = uint32(len(c.Password))
+
+ _ = binary.Write(buf, binary.LittleEndian, &c.Body)
+
+ src := append([]byte(c.Name+"\x00"), []byte(c.Password+"\x00")...)
+
+ enc := base64.StdEncoding
+ pwd := make([]byte, enc.EncodedLen(len(src)))
+ enc.Encode(pwd, src)
+ _, _ = buf.Write(pwd)
+ _ = buf.WriteByte(0)
+
+ return buf.Bytes(), nil
+}
diff --git a/vendor/github.com/vmware/govmomi/units/size.go b/vendor/github.com/vmware/govmomi/units/size.go
index 48208364..f4ee3fcf 100644
--- a/vendor/github.com/vmware/govmomi/units/size.go
+++ b/vendor/github.com/vmware/govmomi/units/size.go
@@ -53,6 +53,26 @@ func (b ByteSize) String() string {
return fmt.Sprintf("%dB", b)
}
+type FileSize int64
+
+func (b FileSize) String() string {
+ switch {
+ case b >= EB:
+ return fmt.Sprintf("%.1fE", float32(b)/EB)
+ case b >= PB:
+ return fmt.Sprintf("%.1fP", float32(b)/PB)
+ case b >= TB:
+ return fmt.Sprintf("%.1fT", float32(b)/TB)
+ case b >= GB:
+ return fmt.Sprintf("%.1fG", float32(b)/GB)
+ case b >= MB:
+ return fmt.Sprintf("%.1fM", float32(b)/MB)
+ case b >= KB:
+ return fmt.Sprintf("%.1fK", float32(b)/KB)
+ }
+ return fmt.Sprintf("%d", b)
+}
+
var bytesRegexp = regexp.MustCompile(`^(?i)(\d+)([BKMGTPE]?)(ib|b)?$`)
func (b *ByteSize) Set(s string) error {
diff --git a/vendor/github.com/vmware/govmomi/vcsim/main.go b/vendor/github.com/vmware/govmomi/vcsim/main.go
new file mode 100644
index 00000000..b2aa6a10
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vcsim/main.go
@@ -0,0 +1,124 @@
+/*
+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 main
+
+import (
+ "crypto/tls"
+ "flag"
+ "fmt"
+ "log"
+ "os"
+ "os/signal"
+ "runtime"
+ "syscall"
+
+ "github.com/google/uuid"
+ "github.com/vmware/govmomi/simulator"
+ "github.com/vmware/govmomi/simulator/esx"
+)
+
+func main() {
+ model := simulator.VPX()
+
+ flag.IntVar(&model.Datacenter, "dc", model.Datacenter, "Number of datacenters")
+ flag.IntVar(&model.Cluster, "cluster", model.Cluster, "Number of clusters")
+ flag.IntVar(&model.ClusterHost, "host", model.ClusterHost, "Number of hosts per cluster")
+ flag.IntVar(&model.Host, "standalone-host", model.Host, "Number of standalone hosts")
+ flag.IntVar(&model.Datastore, "ds", model.Datastore, "Number of local datastores")
+ flag.IntVar(&model.Machine, "vm", model.Machine, "Number of virtual machines per resource pool")
+ flag.IntVar(&model.Pool, "pool", model.Pool, "Number of resource pools per compute resource")
+ flag.IntVar(&model.App, "app", model.App, "Number of virtual apps per compute resource")
+ flag.IntVar(&model.Pod, "pod", model.Pod, "Number of storage pods per datacenter")
+ flag.IntVar(&model.Portgroup, "pg", model.Portgroup, "Number of port groups")
+ flag.IntVar(&model.Folder, "folder", model.Folder, "Number of folders")
+
+ isESX := flag.Bool("esx", false, "Simulate standalone ESX")
+ isTLS := flag.Bool("tls", true, "Enable TLS")
+ cert := flag.String("tlscert", "", "Path to TLS certificate file")
+ key := flag.String("tlskey", "", "Path to TLS key file")
+ env := flag.String("E", "-", "Output vcsim variables to the given fifo or stdout")
+ flag.BoolVar(&simulator.Trace, "trace", simulator.Trace, "Trace SOAP to stderr")
+
+ flag.Parse()
+
+ switch flag.Arg(0) {
+ case "uuidgen": // util-linux not installed on Travis CI
+ fmt.Println(uuid.New().String())
+ return
+ }
+
+ var err error
+ out := os.Stdout
+
+ if *env != "-" {
+ out, err = os.OpenFile(*env, os.O_WRONLY, 0)
+ if err != nil {
+ log.Fatal(err)
+ }
+ }
+
+ f := flag.Lookup("httptest.serve")
+ if f.Value.String() == "" {
+ // #nosec: Errors unhandled
+ _ = f.Value.Set("127.0.0.1:8989")
+ }
+
+ if *isESX {
+ opts := model
+ model = simulator.ESX()
+ // Preserve options that also apply to ESX
+ model.Datastore = opts.Datastore
+ model.Machine = opts.Machine
+ }
+
+ tag := " (govmomi simulator)"
+ model.ServiceContent.About.Name += tag
+ model.ServiceContent.About.OsType = runtime.GOOS + "-" + runtime.GOARCH
+
+ esx.HostSystem.Summary.Hardware.Vendor += tag
+
+ err = model.Create()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if *isTLS {
+ model.Service.TLS = new(tls.Config)
+ if *cert != "" {
+ c, err := tls.LoadX509KeyPair(*cert, *key)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ model.Service.TLS.Certificates = []tls.Certificate{c}
+ }
+ }
+
+ s := model.Service.NewServer()
+
+ fmt.Fprintf(out, "export GOVC_URL=%s GOVC_SIM_PID=%d\n", s.URL, os.Getpid())
+ if out != os.Stdout {
+ _ = out.Close()
+ }
+
+ sig := make(chan os.Signal, 1)
+ signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
+
+ <-sig
+
+ model.Remove()
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-spew/spew/bypass.go b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-spew/spew/bypass.go
index 565bf589..d42a0bc4 100644
--- a/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-spew/spew/bypass.go
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-spew/spew/bypass.go
@@ -13,9 +13,10 @@
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// NOTE: Due to the following build constraints, this file will only be compiled
-// when the code is not running on Google App Engine and "-tags disableunsafe"
-// is not added to the go build command line.
-// +build !appengine,!disableunsafe
+// when the code is not running on Google App Engine, compiled by GopherJS, and
+// "-tags safe" is not added to the go build command line. The "disableunsafe"
+// tag is deprecated and thus should not be used.
+// +build !js,!appengine,!safe,!disableunsafe
package spew
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
index 457e4123..e47a4e79 100644
--- a/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
@@ -13,9 +13,10 @@
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// NOTE: Due to the following build constraints, this file will only be compiled
-// when either the code is running on Google App Engine or "-tags disableunsafe"
-// is added to the go build command line.
-// +build appengine disableunsafe
+// when the code is running on Google App Engine, compiled by GopherJS, or
+// "-tags safe" is added to the go build command line. The "disableunsafe"
+// tag is deprecated and thus should not be used.
+// +build js appengine safe disableunsafe
package spew
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-spew/spew/config.go b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-spew/spew/config.go
index ee1ab07b..9db83c66 100644
--- a/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-spew/spew/config.go
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-spew/spew/config.go
@@ -64,9 +64,18 @@ type ConfigState struct {
// inside these interface methods. As a result, this option relies on
// access to the unsafe package, so it will not have any effect when
// running in environments without access to the unsafe package such as
- // Google App Engine or with the "disableunsafe" build tag specified.
+ // Google App Engine or with the "safe" build tag specified.
DisablePointerMethods bool
+ // DisablePointerAddresses specifies whether to disable the printing of
+ // pointer addresses. This is useful when diffing data structures in tests.
+ DisablePointerAddresses bool
+
+ // DisableCapacities specifies whether to disable the printing of capacities
+ // for arrays, slices, maps and channels. This is useful when diffing
+ // data structures in tests.
+ DisableCapacities bool
+
// ContinueOnMethod specifies whether or not recursion should continue once
// a custom error or Stringer interface is invoked. The default, false,
// means it will print the results of invoking the custom error or Stringer
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-spew/spew/dump.go b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-spew/spew/dump.go
index a0ff95e2..95f9dbfe 100644
--- a/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-spew/spew/dump.go
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-spew/spew/dump.go
@@ -129,7 +129,7 @@ func (d *dumpState) dumpPtr(v reflect.Value) {
d.w.Write(closeParenBytes)
// Display pointer information.
- if len(pointerChain) > 0 {
+ if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 {
d.w.Write(openParenBytes)
for i, addr := range pointerChain {
if i > 0 {
@@ -282,13 +282,13 @@ func (d *dumpState) dump(v reflect.Value) {
case reflect.Map, reflect.String:
valueLen = v.Len()
}
- if valueLen != 0 || valueCap != 0 {
+ if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 {
d.w.Write(openParenBytes)
if valueLen != 0 {
d.w.Write(lenEqualsBytes)
printInt(d.w, int64(valueLen), 10)
}
- if valueCap != 0 {
+ if !d.cs.DisableCapacities && valueCap != 0 {
if valueLen != 0 {
d.w.Write(spaceBytes)
}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-xdr/xdr2/decode.go b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-xdr/xdr2/decode.go
new file mode 100644
index 00000000..6f37f76b
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-xdr/xdr2/decode.go
@@ -0,0 +1,918 @@
+/*
+ * Copyright (c) 2012-2014 Dave Collins
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package xdr
+
+import (
+ "fmt"
+ "io"
+ "math"
+ "reflect"
+ "strconv"
+ "time"
+)
+
+var (
+ errMaxSlice = "data exceeds max slice limit"
+ errIODecode = "%s while decoding %d bytes"
+)
+
+/*
+Unmarshal parses XDR-encoded data into the value pointed to by v reading from
+reader r and returning the total number of bytes read. An addressable pointer
+must be provided since Unmarshal needs to both store the result of the decode as
+well as obtain target type information. Unmarhsal traverses v recursively and
+automatically indirects pointers through arbitrary depth, allocating them as
+necessary, to decode the data into the underlying value pointed to.
+
+Unmarshal uses reflection to determine the type of the concrete value contained
+by v and performs a mapping of underlying XDR types to Go types as follows:
+
+ Go Type <- XDR Type
+ --------------------
+ int8, int16, int32, int <- XDR Integer
+ uint8, uint16, uint32, uint <- XDR Unsigned Integer
+ int64 <- XDR Hyper Integer
+ uint64 <- XDR Unsigned Hyper Integer
+ bool <- XDR Boolean
+ float32 <- XDR Floating-Point
+ float64 <- XDR Double-Precision Floating-Point
+ string <- XDR String
+ byte <- XDR Integer
+ []byte <- XDR Variable-Length Opaque Data
+ [#]byte <- XDR Fixed-Length Opaque Data
+ [] <- XDR Variable-Length Array
+ [#] <- XDR Fixed-Length Array
+ struct <- XDR Structure
+ map <- XDR Variable-Length Array of two-element XDR Structures
+ time.Time <- XDR String encoded with RFC3339 nanosecond precision
+
+Notes and Limitations:
+
+ * Automatic unmarshalling of variable and fixed-length arrays of uint8s
+ requires a special struct tag `xdropaque:"false"` since byte slices
+ and byte arrays are assumed to be opaque data and byte is a Go alias
+ for uint8 thus indistinguishable under reflection
+ * Cyclic data structures are not supported and will result in infinite
+ loops
+
+If any issues are encountered during the unmarshalling process, an
+UnmarshalError is returned with a human readable description as well as
+an ErrorCode value for further inspection from sophisticated callers. Some
+potential issues are unsupported Go types, attempting to decode a value which is
+too large to fit into a specified Go type, and exceeding max slice limitations.
+*/
+func Unmarshal(r io.Reader, v interface{}) (int, error) {
+ d := Decoder{r: r}
+ return d.Decode(v)
+}
+
+// UnmarshalLimited is identical to Unmarshal but it sets maxReadSize in order
+// to cap reads.
+func UnmarshalLimited(r io.Reader, v interface{}, maxSize uint) (int, error) {
+ d := Decoder{r: r, maxReadSize: maxSize}
+ return d.Decode(v)
+}
+
+// A Decoder wraps an io.Reader that is expected to provide an XDR-encoded byte
+// stream and provides several exposed methods to manually decode various XDR
+// primitives without relying on reflection. The NewDecoder function can be
+// used to get a new Decoder directly.
+//
+// Typically, Unmarshal should be used instead of manual decoding. A Decoder
+// is exposed so it is possible to perform manual decoding should it be
+// necessary in complex scenarios where automatic reflection-based decoding
+// won't work.
+type Decoder struct {
+ r io.Reader
+
+ // maxReadSize is the default maximum bytes an element can contain. 0
+ // is unlimited and provides backwards compatability. Setting it to a
+ // non-zero value caps reads.
+ maxReadSize uint
+}
+
+// DecodeInt treats the next 4 bytes as an XDR encoded integer and returns the
+// result as an int32 along with the number of bytes actually read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining.
+//
+// Reference:
+// RFC Section 4.1 - Integer
+// 32-bit big-endian signed integer in range [-2147483648, 2147483647]
+func (d *Decoder) DecodeInt() (int32, int, error) {
+ var buf [4]byte
+ n, err := io.ReadFull(d.r, buf[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIODecode, err.Error(), 4)
+ err := unmarshalError("DecodeInt", ErrIO, msg, buf[:n], err)
+ return 0, n, err
+ }
+
+ rv := int32(buf[3]) | int32(buf[2])<<8 |
+ int32(buf[1])<<16 | int32(buf[0])<<24
+ return rv, n, nil
+}
+
+// DecodeUint treats the next 4 bytes as an XDR encoded unsigned integer and
+// returns the result as a uint32 along with the number of bytes actually read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining.
+//
+// Reference:
+// RFC Section 4.2 - Unsigned Integer
+// 32-bit big-endian unsigned integer in range [0, 4294967295]
+func (d *Decoder) DecodeUint() (uint32, int, error) {
+ var buf [4]byte
+ n, err := io.ReadFull(d.r, buf[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIODecode, err.Error(), 4)
+ err := unmarshalError("DecodeUint", ErrIO, msg, buf[:n], err)
+ return 0, n, err
+ }
+
+ rv := uint32(buf[3]) | uint32(buf[2])<<8 |
+ uint32(buf[1])<<16 | uint32(buf[0])<<24
+ return rv, n, nil
+}
+
+// DecodeEnum treats the next 4 bytes as an XDR encoded enumeration value and
+// returns the result as an int32 after verifying that the value is in the
+// provided map of valid values. It also returns the number of bytes actually
+// read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining or
+// the parsed enumeration value is not one of the provided valid values.
+//
+// Reference:
+// RFC Section 4.3 - Enumeration
+// Represented as an XDR encoded signed integer
+func (d *Decoder) DecodeEnum(validEnums map[int32]bool) (int32, int, error) {
+ val, n, err := d.DecodeInt()
+ if err != nil {
+ return 0, n, err
+ }
+
+ if !validEnums[val] {
+ err := unmarshalError("DecodeEnum", ErrBadEnumValue,
+ "invalid enum", val, nil)
+ return 0, n, err
+ }
+ return val, n, nil
+}
+
+// DecodeBool treats the next 4 bytes as an XDR encoded boolean value and
+// returns the result as a bool along with the number of bytes actually read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining or
+// the parsed value is not a 0 or 1.
+//
+// Reference:
+// RFC Section 4.4 - Boolean
+// Represented as an XDR encoded enumeration where 0 is false and 1 is true
+func (d *Decoder) DecodeBool() (bool, int, error) {
+ val, n, err := d.DecodeInt()
+ if err != nil {
+ return false, n, err
+ }
+ switch val {
+ case 0:
+ return false, n, nil
+ case 1:
+ return true, n, nil
+ }
+
+ err = unmarshalError("DecodeBool", ErrBadEnumValue, "bool not 0 or 1",
+ val, nil)
+ return false, n, err
+}
+
+// DecodeHyper treats the next 8 bytes as an XDR encoded hyper value and
+// returns the result as an int64 along with the number of bytes actually read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining.
+//
+// Reference:
+// RFC Section 4.5 - Hyper Integer
+// 64-bit big-endian signed integer in range [-9223372036854775808, 9223372036854775807]
+func (d *Decoder) DecodeHyper() (int64, int, error) {
+ var buf [8]byte
+ n, err := io.ReadFull(d.r, buf[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIODecode, err.Error(), 8)
+ err := unmarshalError("DecodeHyper", ErrIO, msg, buf[:n], err)
+ return 0, n, err
+ }
+
+ rv := int64(buf[7]) | int64(buf[6])<<8 |
+ int64(buf[5])<<16 | int64(buf[4])<<24 |
+ int64(buf[3])<<32 | int64(buf[2])<<40 |
+ int64(buf[1])<<48 | int64(buf[0])<<56
+ return rv, n, err
+}
+
+// DecodeUhyper treats the next 8 bytes as an XDR encoded unsigned hyper value
+// and returns the result as a uint64 along with the number of bytes actually
+// read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining.
+//
+// Reference:
+// RFC Section 4.5 - Unsigned Hyper Integer
+// 64-bit big-endian unsigned integer in range [0, 18446744073709551615]
+func (d *Decoder) DecodeUhyper() (uint64, int, error) {
+ var buf [8]byte
+ n, err := io.ReadFull(d.r, buf[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIODecode, err.Error(), 8)
+ err := unmarshalError("DecodeUhyper", ErrIO, msg, buf[:n], err)
+ return 0, n, err
+ }
+
+ rv := uint64(buf[7]) | uint64(buf[6])<<8 |
+ uint64(buf[5])<<16 | uint64(buf[4])<<24 |
+ uint64(buf[3])<<32 | uint64(buf[2])<<40 |
+ uint64(buf[1])<<48 | uint64(buf[0])<<56
+ return rv, n, nil
+}
+
+// DecodeFloat treats the next 4 bytes as an XDR encoded floating point and
+// returns the result as a float32 along with the number of bytes actually read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining.
+//
+// Reference:
+// RFC Section 4.6 - Floating Point
+// 32-bit single-precision IEEE 754 floating point
+func (d *Decoder) DecodeFloat() (float32, int, error) {
+ var buf [4]byte
+ n, err := io.ReadFull(d.r, buf[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIODecode, err.Error(), 4)
+ err := unmarshalError("DecodeFloat", ErrIO, msg, buf[:n], err)
+ return 0, n, err
+ }
+
+ val := uint32(buf[3]) | uint32(buf[2])<<8 |
+ uint32(buf[1])<<16 | uint32(buf[0])<<24
+ return math.Float32frombits(val), n, nil
+}
+
+// DecodeDouble treats the next 8 bytes as an XDR encoded double-precision
+// floating point and returns the result as a float64 along with the number of
+// bytes actually read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining.
+//
+// Reference:
+// RFC Section 4.7 - Double-Precision Floating Point
+// 64-bit double-precision IEEE 754 floating point
+func (d *Decoder) DecodeDouble() (float64, int, error) {
+ var buf [8]byte
+ n, err := io.ReadFull(d.r, buf[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIODecode, err.Error(), 8)
+ err := unmarshalError("DecodeDouble", ErrIO, msg, buf[:n], err)
+ return 0, n, err
+ }
+
+ val := uint64(buf[7]) | uint64(buf[6])<<8 |
+ uint64(buf[5])<<16 | uint64(buf[4])<<24 |
+ uint64(buf[3])<<32 | uint64(buf[2])<<40 |
+ uint64(buf[1])<<48 | uint64(buf[0])<<56
+ return math.Float64frombits(val), n, nil
+}
+
+// RFC Section 4.8 - Quadruple-Precision Floating Point
+// 128-bit quadruple-precision floating point
+// Not Implemented
+
+// DecodeFixedOpaque treats the next 'size' bytes as XDR encoded opaque data and
+// returns the result as a byte slice along with the number of bytes actually
+// read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining to
+// satisfy the passed size, including the necessary padding to make it a
+// multiple of 4.
+//
+// Reference:
+// RFC Section 4.9 - Fixed-Length Opaque Data
+// Fixed-length uninterpreted data zero-padded to a multiple of four
+func (d *Decoder) DecodeFixedOpaque(size int32) ([]byte, int, error) {
+ // Nothing to do if size is 0.
+ if size == 0 {
+ return nil, 0, nil
+ }
+
+ pad := (4 - (size % 4)) % 4
+ paddedSize := size + pad
+ if uint(paddedSize) > uint(math.MaxInt32) {
+ err := unmarshalError("DecodeFixedOpaque", ErrOverflow,
+ errMaxSlice, paddedSize, nil)
+ return nil, 0, err
+ }
+
+ buf := make([]byte, paddedSize)
+ n, err := io.ReadFull(d.r, buf)
+ if err != nil {
+ msg := fmt.Sprintf(errIODecode, err.Error(), paddedSize)
+ err := unmarshalError("DecodeFixedOpaque", ErrIO, msg, buf[:n],
+ err)
+ return nil, n, err
+ }
+ return buf[0:size], n, nil
+}
+
+// DecodeOpaque treats the next bytes as variable length XDR encoded opaque
+// data and returns the result as a byte slice along with the number of bytes
+// actually read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining or
+// the opaque data is larger than the max length of a Go slice.
+//
+// Reference:
+// RFC Section 4.10 - Variable-Length Opaque Data
+// Unsigned integer length followed by fixed opaque data of that length
+func (d *Decoder) DecodeOpaque() ([]byte, int, error) {
+ dataLen, n, err := d.DecodeUint()
+ if err != nil {
+ return nil, n, err
+ }
+ if uint(dataLen) > uint(math.MaxInt32) ||
+ (d.maxReadSize != 0 && uint(dataLen) > d.maxReadSize) {
+ err := unmarshalError("DecodeOpaque", ErrOverflow, errMaxSlice,
+ dataLen, nil)
+ return nil, n, err
+ }
+
+ rv, n2, err := d.DecodeFixedOpaque(int32(dataLen))
+ n += n2
+ if err != nil {
+ return nil, n, err
+ }
+ return rv, n, nil
+}
+
+// DecodeString treats the next bytes as a variable length XDR encoded string
+// and returns the result as a string along with the number of bytes actually
+// read. Character encoding is assumed to be UTF-8 and therefore ASCII
+// compatible. If the underlying character encoding is not compatibile with
+// this assumption, the data can instead be read as variable-length opaque data
+// (DecodeOpaque) and manually converted as needed.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining or
+// the string data is larger than the max length of a Go slice.
+//
+// Reference:
+// RFC Section 4.11 - String
+// Unsigned integer length followed by bytes zero-padded to a multiple of
+// four
+func (d *Decoder) DecodeString() (string, int, error) {
+ dataLen, n, err := d.DecodeUint()
+ if err != nil {
+ return "", n, err
+ }
+ if uint(dataLen) > uint(math.MaxInt32) ||
+ (d.maxReadSize != 0 && uint(dataLen) > d.maxReadSize) {
+ err = unmarshalError("DecodeString", ErrOverflow, errMaxSlice,
+ dataLen, nil)
+ return "", n, err
+ }
+
+ opaque, n2, err := d.DecodeFixedOpaque(int32(dataLen))
+ n += n2
+ if err != nil {
+ return "", n, err
+ }
+ return string(opaque), n, nil
+}
+
+// decodeFixedArray treats the next bytes as a series of XDR encoded elements
+// of the same type as the array represented by the reflection value and decodes
+// each element into the passed array. The ignoreOpaque flag controls whether
+// or not uint8 (byte) elements should be decoded individually or as a fixed
+// sequence of opaque data. It returns the the number of bytes actually read.
+//
+// An UnmarshalError is returned if any issues are encountered while decoding
+// the array elements.
+//
+// Reference:
+// RFC Section 4.12 - Fixed-Length Array
+// Individually XDR encoded array elements
+func (d *Decoder) decodeFixedArray(v reflect.Value, ignoreOpaque bool) (int, error) {
+ // Treat [#]byte (byte is alias for uint8) as opaque data unless
+ // ignored.
+ if !ignoreOpaque && v.Type().Elem().Kind() == reflect.Uint8 {
+ data, n, err := d.DecodeFixedOpaque(int32(v.Len()))
+ if err != nil {
+ return n, err
+ }
+ reflect.Copy(v, reflect.ValueOf(data))
+ return n, nil
+ }
+
+ // Decode each array element.
+ var n int
+ for i := 0; i < v.Len(); i++ {
+ n2, err := d.decode(v.Index(i))
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ }
+ return n, nil
+}
+
+// decodeArray treats the next bytes as a variable length series of XDR encoded
+// elements of the same type as the array represented by the reflection value.
+// The number of elements is obtained by first decoding the unsigned integer
+// element count. Then each element is decoded into the passed array. The
+// ignoreOpaque flag controls whether or not uint8 (byte) elements should be
+// decoded individually or as a variable sequence of opaque data. It returns
+// the number of bytes actually read.
+//
+// An UnmarshalError is returned if any issues are encountered while decoding
+// the array elements.
+//
+// Reference:
+// RFC Section 4.13 - Variable-Length Array
+// Unsigned integer length followed by individually XDR encoded array
+// elements
+func (d *Decoder) decodeArray(v reflect.Value, ignoreOpaque bool) (int, error) {
+ dataLen, n, err := d.DecodeUint()
+ if err != nil {
+ return n, err
+ }
+ if uint(dataLen) > uint(math.MaxInt32) ||
+ (d.maxReadSize != 0 && uint(dataLen) > d.maxReadSize) {
+ err := unmarshalError("decodeArray", ErrOverflow, errMaxSlice,
+ dataLen, nil)
+ return n, err
+ }
+
+ // Allocate storage for the slice elements (the underlying array) if
+ // existing slice does not have enough capacity.
+ sliceLen := int(dataLen)
+ if v.Cap() < sliceLen {
+ v.Set(reflect.MakeSlice(v.Type(), sliceLen, sliceLen))
+ }
+ if v.Len() < sliceLen {
+ v.SetLen(sliceLen)
+ }
+
+ // Treat []byte (byte is alias for uint8) as opaque data unless ignored.
+ if !ignoreOpaque && v.Type().Elem().Kind() == reflect.Uint8 {
+ data, n2, err := d.DecodeFixedOpaque(int32(sliceLen))
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ v.SetBytes(data)
+ return n, nil
+ }
+
+ // Decode each slice element.
+ for i := 0; i < sliceLen; i++ {
+ n2, err := d.decode(v.Index(i))
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ }
+ return n, nil
+}
+
+// decodeStruct treats the next bytes as a series of XDR encoded elements
+// of the same type as the exported fields of the struct represented by the
+// passed reflection value. Pointers are automatically indirected and
+// allocated as necessary. It returns the the number of bytes actually read.
+//
+// An UnmarshalError is returned if any issues are encountered while decoding
+// the elements.
+//
+// Reference:
+// RFC Section 4.14 - Structure
+// XDR encoded elements in the order of their declaration in the struct
+func (d *Decoder) decodeStruct(v reflect.Value) (int, error) {
+ var n int
+ var union string
+ vt := v.Type()
+ for i := 0; i < v.NumField(); i++ {
+ // Skip unexported fields.
+ vtf := vt.Field(i)
+ if vtf.PkgPath != "" {
+ continue
+ }
+
+ vf := v.Field(i)
+ tag := parseTag(vtf.Tag)
+
+ // RFC Section 4.19 - Optional data
+ if tag.Get("optional") == "true" {
+ if vf.Type().Kind() != reflect.Ptr {
+ msg := fmt.Sprintf("optional must be a pointer, not '%v'",
+ vf.Type().String())
+ err := unmarshalError("decodeStruct", ErrBadOptional,
+ msg, nil, nil)
+ return n, err
+ }
+
+ hasopt, n2, err := d.DecodeBool()
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ if !hasopt {
+ continue
+ }
+ }
+
+ // Indirect through pointers allocating them as needed and
+ // ensure the field is settable.
+ vf, err := d.indirect(vf)
+ if err != nil {
+ return n, err
+ }
+
+ if !vf.CanSet() {
+ msg := fmt.Sprintf("can't decode to unsettable '%v'",
+ vf.Type().String())
+ err := unmarshalError("decodeStruct", ErrNotSettable,
+ msg, nil, nil)
+ return n, err
+ }
+
+ // Handle non-opaque data to []uint8 and [#]uint8 based on
+ // struct tag.
+ if tag.Get("opaque") == "false" {
+ switch vf.Kind() {
+ case reflect.Slice:
+ n2, err := d.decodeArray(vf, true)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ continue
+
+ case reflect.Array:
+ n2, err := d.decodeFixedArray(vf, true)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ continue
+ }
+ }
+
+ if union != "" {
+ ucase := tag.Get("unioncase")
+ if ucase != "" && ucase != union {
+ continue
+ }
+ }
+
+ // Decode each struct field.
+ n2, err := d.decode(vf)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+
+ if tag.Get("union") == "true" {
+ if vf.Type().ConvertibleTo(reflect.TypeOf(0)) {
+ union = strconv.Itoa(int(vf.Convert(reflect.TypeOf(0)).Int()))
+ } else if vf.Kind() == reflect.Bool {
+ if vf.Bool() {
+ union = "1"
+ } else {
+ union = "0"
+ }
+ } else {
+ msg := fmt.Sprintf("type '%s' is not valid", vf.Kind().String())
+ return n, unmarshalError("decodeStruct", ErrBadDiscriminant, msg, nil, nil)
+ }
+ }
+
+ }
+
+ return n, nil
+}
+
+// RFC Section 4.16 - Void
+// RFC Section 4.17 - Constant
+// RFC Section 4.18 - Typedef
+// RFC Section 4.19 - Optional data
+// RFC Sections 4.15 though 4.19 only apply to the data specification language
+// which is not implemented by this package.
+
+// decodeMap treats the next bytes as an XDR encoded variable array of 2-element
+// structures whose fields are of the same type as the map keys and elements
+// represented by the passed reflection value. Pointers are automatically
+// indirected and allocated as necessary. It returns the the number of bytes
+// actually read.
+//
+// An UnmarshalError is returned if any issues are encountered while decoding
+// the elements.
+func (d *Decoder) decodeMap(v reflect.Value) (int, error) {
+ dataLen, n, err := d.DecodeUint()
+ if err != nil {
+ return n, err
+ }
+
+ // Allocate storage for the underlying map if needed.
+ vt := v.Type()
+ if v.IsNil() {
+ v.Set(reflect.MakeMap(vt))
+ }
+
+ // Decode each key and value according to their type.
+ keyType := vt.Key()
+ elemType := vt.Elem()
+ for i := uint32(0); i < dataLen; i++ {
+ key := reflect.New(keyType).Elem()
+ n2, err := d.decode(key)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+
+ val := reflect.New(elemType).Elem()
+ n2, err = d.decode(val)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ v.SetMapIndex(key, val)
+ }
+ return n, nil
+}
+
+// decodeInterface examines the interface represented by the passed reflection
+// value to detect whether it is an interface that can be decoded into and
+// if it is, extracts the underlying value to pass back into the decode function
+// for decoding according to its type. It returns the the number of bytes
+// actually read.
+//
+// An UnmarshalError is returned if any issues are encountered while decoding
+// the interface.
+func (d *Decoder) decodeInterface(v reflect.Value) (int, error) {
+ if v.IsNil() || !v.CanInterface() {
+ msg := fmt.Sprintf("can't decode to nil interface")
+ err := unmarshalError("decodeInterface", ErrNilInterface, msg,
+ nil, nil)
+ return 0, err
+ }
+
+ // Extract underlying value from the interface and indirect through
+ // pointers allocating them as needed.
+ ve := reflect.ValueOf(v.Interface())
+ ve, err := d.indirect(ve)
+ if err != nil {
+ return 0, err
+ }
+ if !ve.CanSet() {
+ msg := fmt.Sprintf("can't decode to unsettable '%v'",
+ ve.Type().String())
+ err := unmarshalError("decodeInterface", ErrNotSettable, msg,
+ nil, nil)
+ return 0, err
+ }
+ return d.decode(ve)
+}
+
+// decode is the main workhorse for unmarshalling via reflection. It uses
+// the passed reflection value to choose the XDR primitives to decode from
+// the encapsulated reader. It is a recursive function,
+// so cyclic data structures are not supported and will result in an infinite
+// loop. It returns the the number of bytes actually read.
+func (d *Decoder) decode(v reflect.Value) (int, error) {
+ if !v.IsValid() {
+ msg := fmt.Sprintf("type '%s' is not valid", v.Kind().String())
+ err := unmarshalError("decode", ErrUnsupportedType, msg, nil, nil)
+ return 0, err
+ }
+
+ // Indirect through pointers allocating them as needed.
+ ve, err := d.indirect(v)
+ if err != nil {
+ return 0, err
+ }
+
+ // Handle time.Time values by decoding them as an RFC3339 formatted
+ // string with nanosecond precision. Check the type string rather
+ // than doing a full blown conversion to interface and type assertion
+ // since checking a string is much quicker.
+ if ve.Type().String() == "time.Time" {
+ // Read the value as a string and parse it.
+ timeString, n, err := d.DecodeString()
+ if err != nil {
+ return n, err
+ }
+ ttv, err := time.Parse(time.RFC3339, timeString)
+ if err != nil {
+ err := unmarshalError("decode", ErrParseTime,
+ err.Error(), timeString, err)
+ return n, err
+ }
+ ve.Set(reflect.ValueOf(ttv))
+ return n, nil
+ }
+
+ // Handle native Go types.
+ switch ve.Kind() {
+ case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int:
+ i, n, err := d.DecodeInt()
+ if err != nil {
+ return n, err
+ }
+ if ve.OverflowInt(int64(i)) {
+ msg := fmt.Sprintf("signed integer too large to fit '%s'",
+ ve.Kind().String())
+ err = unmarshalError("decode", ErrOverflow, msg, i, nil)
+ return n, err
+ }
+ ve.SetInt(int64(i))
+ return n, nil
+
+ case reflect.Int64:
+ i, n, err := d.DecodeHyper()
+ if err != nil {
+ return n, err
+ }
+ ve.SetInt(i)
+ return n, nil
+
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint:
+ ui, n, err := d.DecodeUint()
+ if err != nil {
+ return n, err
+ }
+ if ve.OverflowUint(uint64(ui)) {
+ msg := fmt.Sprintf("unsigned integer too large to fit '%s'",
+ ve.Kind().String())
+ err = unmarshalError("decode", ErrOverflow, msg, ui, nil)
+ return n, err
+ }
+ ve.SetUint(uint64(ui))
+ return n, nil
+
+ case reflect.Uint64:
+ ui, n, err := d.DecodeUhyper()
+ if err != nil {
+ return n, err
+ }
+ ve.SetUint(ui)
+ return n, nil
+
+ case reflect.Bool:
+ b, n, err := d.DecodeBool()
+ if err != nil {
+ return n, err
+ }
+ ve.SetBool(b)
+ return n, nil
+
+ case reflect.Float32:
+ f, n, err := d.DecodeFloat()
+ if err != nil {
+ return n, err
+ }
+ ve.SetFloat(float64(f))
+ return n, nil
+
+ case reflect.Float64:
+ f, n, err := d.DecodeDouble()
+ if err != nil {
+ return n, err
+ }
+ ve.SetFloat(f)
+ return n, nil
+
+ case reflect.String:
+ s, n, err := d.DecodeString()
+ if err != nil {
+ return n, err
+ }
+ ve.SetString(s)
+ return n, nil
+
+ case reflect.Array:
+ n, err := d.decodeFixedArray(ve, false)
+ if err != nil {
+ return n, err
+ }
+ return n, nil
+
+ case reflect.Slice:
+ n, err := d.decodeArray(ve, false)
+ if err != nil {
+ return n, err
+ }
+ return n, nil
+
+ case reflect.Struct:
+ n, err := d.decodeStruct(ve)
+ if err != nil {
+ return n, err
+ }
+ return n, nil
+
+ case reflect.Map:
+ n, err := d.decodeMap(ve)
+ if err != nil {
+ return n, err
+ }
+ return n, nil
+
+ case reflect.Interface:
+ n, err := d.decodeInterface(ve)
+ if err != nil {
+ return n, err
+ }
+ return n, nil
+ }
+
+ // The only unhandled types left are unsupported. At the time of this
+ // writing the only remaining unsupported types that exist are
+ // reflect.Uintptr and reflect.UnsafePointer.
+ msg := fmt.Sprintf("unsupported Go type '%s'", ve.Kind().String())
+ err = unmarshalError("decode", ErrUnsupportedType, msg, nil, nil)
+ return 0, err
+}
+
+// indirect dereferences pointers allocating them as needed until it reaches
+// a non-pointer. This allows transparent decoding through arbitrary levels
+// of indirection.
+func (d *Decoder) indirect(v reflect.Value) (reflect.Value, error) {
+ rv := v
+ for rv.Kind() == reflect.Ptr {
+ // Allocate pointer if needed.
+ isNil := rv.IsNil()
+ if isNil && !rv.CanSet() {
+ msg := fmt.Sprintf("unable to allocate pointer for '%v'",
+ rv.Type().String())
+ err := unmarshalError("indirect", ErrNotSettable, msg,
+ nil, nil)
+ return rv, err
+ }
+ if isNil {
+ rv.Set(reflect.New(rv.Type().Elem()))
+ }
+ rv = rv.Elem()
+ }
+ return rv, nil
+}
+
+// Decode operates identically to the Unmarshal function with the exception of
+// using the reader associated with the Decoder as the source of XDR-encoded
+// data instead of a user-supplied reader. See the Unmarhsal documentation for
+// specifics.
+func (d *Decoder) Decode(v interface{}) (int, error) {
+ if v == nil {
+ msg := "can't unmarshal to nil interface"
+ return 0, unmarshalError("Unmarshal", ErrNilInterface, msg, nil,
+ nil)
+ }
+
+ vv := reflect.ValueOf(v)
+ if vv.Kind() != reflect.Ptr {
+ msg := fmt.Sprintf("can't unmarshal to non-pointer '%v' - use "+
+ "& operator", vv.Type().String())
+ err := unmarshalError("Unmarshal", ErrBadArguments, msg, nil, nil)
+ return 0, err
+ }
+ if vv.IsNil() && !vv.CanSet() {
+ msg := fmt.Sprintf("can't unmarshal to unsettable '%v' - use "+
+ "& operator", vv.Type().String())
+ err := unmarshalError("Unmarshal", ErrNotSettable, msg, nil, nil)
+ return 0, err
+ }
+
+ return d.decode(vv)
+}
+
+// NewDecoder returns a Decoder that can be used to manually decode XDR data
+// from a provided reader. Typically, Unmarshal should be used instead of
+// manually creating a Decoder.
+func NewDecoder(r io.Reader) *Decoder {
+ return &Decoder{r: r}
+}
+
+// NewDecoderLimited is identical to NewDecoder but it sets maxReadSize in
+// order to cap reads.
+func NewDecoderLimited(r io.Reader, maxSize uint) *Decoder {
+ return &Decoder{r: r, maxReadSize: maxSize}
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-xdr/xdr2/doc.go b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-xdr/xdr2/doc.go
new file mode 100644
index 00000000..1904d2b8
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-xdr/xdr2/doc.go
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2012-2014 Dave Collins
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+Package xdr implements the data representation portion of the External Data
+Representation (XDR) standard protocol as specified in RFC 4506 (obsoletes
+RFC 1832 and RFC 1014).
+
+The XDR RFC defines both a data specification language and a data
+representation standard. This package implements methods to encode and decode
+XDR data per the data representation standard with the exception of 128-bit
+quadruple-precision floating points. It does not currently implement parsing of
+the data specification language. In other words, the ability to automatically
+generate Go code by parsing an XDR data specification file (typically .x
+extension) is not supported. In practice, this limitation of the package is
+fairly minor since it is largely unnecessary due to the reflection capabilities
+of Go as described below.
+
+This package provides two approaches for encoding and decoding XDR data:
+
+ 1) Marshal/Unmarshal functions which automatically map between XDR and Go types
+ 2) Individual Encoder/Decoder objects to manually work with XDR primitives
+
+For the Marshal/Unmarshal functions, Go reflection capabilities are used to
+choose the type of the underlying XDR data based upon the Go type to encode or
+the target Go type to decode into. A description of how each type is mapped is
+provided below, however one important type worth reviewing is Go structs. In
+the case of structs, each exported field (first letter capitalized) is reflected
+and mapped in order. As a result, this means a Go struct with exported fields
+of the appropriate types listed in the expected order can be used to
+automatically encode / decode the XDR data thereby eliminating the need to write
+a lot of boilerplate code to encode/decode and error check each piece of XDR
+data as is typically required with C based XDR libraries.
+
+Go Type to XDR Type Mappings
+
+The following chart shows an overview of how Go types are mapped to XDR types
+for automatic marshalling and unmarshalling. The documentation for the Marshal
+and Unmarshal functions has specific details of how the mapping proceeds.
+
+ Go Type <-> XDR Type
+ --------------------
+ int8, int16, int32, int <-> XDR Integer
+ uint8, uint16, uint32, uint <-> XDR Unsigned Integer
+ int64 <-> XDR Hyper Integer
+ uint64 <-> XDR Unsigned Hyper Integer
+ bool <-> XDR Boolean
+ float32 <-> XDR Floating-Point
+ float64 <-> XDR Double-Precision Floating-Point
+ string <-> XDR String
+ byte <-> XDR Integer
+ []byte <-> XDR Variable-Length Opaque Data
+ [#]byte <-> XDR Fixed-Length Opaque Data
+ [] <-> XDR Variable-Length Array
+ [#] <-> XDR Fixed-Length Array
+ * <-> XDR Optional data (when marked with struct tag `xdr:"optional"`)
+ struct <-> XDR Structure or Discriminated Unions
+ map <-> XDR Variable-Length Array of two-element XDR Structures
+ time.Time <-> XDR String encoded with RFC3339 nanosecond precision
+
+Notes and Limitations:
+
+ * Automatic marshalling and unmarshalling of variable and fixed-length
+ arrays of uint8s require a special struct tag `xdr:"opaque=false"`
+ since byte slices and byte arrays are assumed to be opaque data and
+ byte is a Go alias for uint8 thus indistinguishable under reflection
+ * Channel, complex, and function types cannot be encoded
+ * Interfaces without a concrete value cannot be encoded
+ * Cyclic data structures are not supported and will result in infinite
+ loops
+ * Strings are marshalled and unmarshalled with UTF-8 character encoding
+ which differs from the XDR specification of ASCII, however UTF-8 is
+ backwards compatible with ASCII so this should rarely cause issues
+
+
+Encoding
+
+To encode XDR data, use the Marshal function.
+ func Marshal(w io.Writer, v interface{}) (int, error)
+
+For example, given the following code snippet:
+
+ type ImageHeader struct {
+ Signature [3]byte
+ Version uint32
+ IsGrayscale bool
+ NumSections uint32
+ }
+ h := ImageHeader{[3]byte{0xAB, 0xCD, 0xEF}, 2, true, 10}
+
+ var w bytes.Buffer
+ bytesWritten, err := xdr.Marshal(&w, &h)
+ // Error check elided
+
+The result, encodedData, will then contain the following XDR encoded byte
+sequence:
+
+ 0xAB, 0xCD, 0xEF, 0x00,
+ 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x0A
+
+
+In addition, while the automatic marshalling discussed above will work for the
+vast majority of cases, an Encoder object is provided that can be used to
+manually encode XDR primitives for complex scenarios where automatic
+reflection-based encoding won't work. The included examples provide a sample of
+manual usage via an Encoder.
+
+
+Decoding
+
+To decode XDR data, use the Unmarshal function.
+ func Unmarshal(r io.Reader, v interface{}) (int, error)
+
+For example, given the following code snippet:
+
+ type ImageHeader struct {
+ Signature [3]byte
+ Version uint32
+ IsGrayscale bool
+ NumSections uint32
+ }
+
+ // Using output from the Encoding section above.
+ encodedData := []byte{
+ 0xAB, 0xCD, 0xEF, 0x00,
+ 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x0A,
+ }
+
+ var h ImageHeader
+ bytesRead, err := xdr.Unmarshal(bytes.NewReader(encodedData), &h)
+ // Error check elided
+
+The struct instance, h, will then contain the following values:
+
+ h.Signature = [3]byte{0xAB, 0xCD, 0xEF}
+ h.Version = 2
+ h.IsGrayscale = true
+ h.NumSections = 10
+
+In addition, while the automatic unmarshalling discussed above will work for the
+vast majority of cases, a Decoder object is provided that can be used to
+manually decode XDR primitives for complex scenarios where automatic
+reflection-based decoding won't work. The included examples provide a sample of
+manual usage via a Decoder.
+
+
+Discriminated Unions
+
+Discriminated unions are marshalled via Go structs, using special struct tags
+to mark the discriminant and the different cases. For instance:
+
+ type ReturnValue struct {
+ Status int `xdr:"union"`
+ StatusOk struct {
+ Width int
+ Height int
+ } `xdr:"unioncase=0"`
+ StatusError struct {
+ ErrMsg string
+ } `xdr:"unioncase=-1"`
+ }
+
+The Status field is the discriminant of the union, and is always serialized;
+if its value is 0, the StatusOK struct is serialized while the StatusErr struct
+is ignored; if its value is -1, the opposite happens. If the value is different
+from both 0 and -1, only the Status field is serialized. Any additional field
+not marked with unioncase is always serialized as normal.
+
+You are not forced to use sub-structures; for instance, the following is also
+valid:
+
+ type ReturnValue struct {
+ Status int `xdr:"union"`
+ Width int `xdr:"unioncase=0"`
+ Height int `xdr:"unioncase=0"`
+ ErrMsg string `xdr:"unioncase=-1"`
+ }
+
+
+Errors
+
+All errors are either of type UnmarshalError or MarshalError. Both provide
+human-readable output as well as an ErrorCode field which can be inspected by
+sophisticated callers if necessary.
+
+See the documentation of UnmarshalError, MarshalError, and ErrorCode for further
+details.
+*/
+package xdr
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-xdr/xdr2/encode.go b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-xdr/xdr2/encode.go
new file mode 100644
index 00000000..73a2ff00
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-xdr/xdr2/encode.go
@@ -0,0 +1,718 @@
+/*
+ * Copyright (c) 2012-2014 Dave Collins
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package xdr
+
+import (
+ "fmt"
+ "io"
+ "math"
+ "reflect"
+ "strconv"
+ "time"
+)
+
+var errIOEncode = "%s while encoding %d bytes"
+
+/*
+Marshal writes the XDR encoding of v to writer w and returns the number of bytes
+written. It traverses v recursively and automatically indirects pointers
+through arbitrary depth to encode the actual value pointed to.
+
+Marshal uses reflection to determine the type of the concrete value contained by
+v and performs a mapping of Go types to the underlying XDR types as follows:
+
+ Go Type -> XDR Type
+ --------------------
+ int8, int16, int32, int -> XDR Integer
+ uint8, uint16, uint32, uint -> XDR Unsigned Integer
+ int64 -> XDR Hyper Integer
+ uint64 -> XDR Unsigned Hyper Integer
+ bool -> XDR Boolean
+ float32 -> XDR Floating-Point
+ float64 -> XDR Double-Precision Floating-Point
+ string -> XDR String
+ byte -> XDR Integer
+ []byte -> XDR Variable-Length Opaque Data
+ [#]byte -> XDR Fixed-Length Opaque Data
+ [] -> XDR Variable-Length Array
+ [#] -> XDR Fixed-Length Array
+ struct -> XDR Structure
+ map -> XDR Variable-Length Array of two-element XDR Structures
+ time.Time -> XDR String encoded with RFC3339 nanosecond precision
+
+Notes and Limitations:
+
+ * Automatic marshalling of variable and fixed-length arrays of uint8s
+ requires a special struct tag `xdropaque:"false"` since byte slices and
+ byte arrays are assumed to be opaque data and byte is a Go alias for uint8
+ thus indistinguishable under reflection
+ * Channel, complex, and function types cannot be encoded
+ * Interfaces without a concrete value cannot be encoded
+ * Cyclic data structures are not supported and will result in infinite loops
+ * Strings are marshalled with UTF-8 character encoding which differs from
+ the XDR specification of ASCII, however UTF-8 is backwards compatible with
+ ASCII so this should rarely cause issues
+
+If any issues are encountered during the marshalling process, a MarshalError is
+returned with a human readable description as well as an ErrorCode value for
+further inspection from sophisticated callers. Some potential issues are
+unsupported Go types, attempting to encode more opaque data than can be
+represented by a single opaque XDR entry, and exceeding max slice limitations.
+*/
+func Marshal(w io.Writer, v interface{}) (int, error) {
+ enc := Encoder{w: w}
+ return enc.Encode(v)
+}
+
+// An Encoder wraps an io.Writer that will receive the XDR encoded byte stream.
+// See NewEncoder.
+type Encoder struct {
+ w io.Writer
+}
+
+// EncodeInt writes the XDR encoded representation of the passed 32-bit signed
+// integer to the encapsulated writer and returns the number of bytes written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.1 - Integer
+// 32-bit big-endian signed integer in range [-2147483648, 2147483647]
+func (enc *Encoder) EncodeInt(v int32) (int, error) {
+ var b [4]byte
+ b[0] = byte(v >> 24)
+ b[1] = byte(v >> 16)
+ b[2] = byte(v >> 8)
+ b[3] = byte(v)
+
+ n, err := enc.w.Write(b[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIOEncode, err.Error(), 4)
+ err := marshalError("EncodeInt", ErrIO, msg, b[:n], err)
+ return n, err
+ }
+
+ return n, nil
+}
+
+// EncodeUint writes the XDR encoded representation of the passed 32-bit
+// unsigned integer to the encapsulated writer and returns the number of bytes
+// written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.2 - Unsigned Integer
+// 32-bit big-endian unsigned integer in range [0, 4294967295]
+func (enc *Encoder) EncodeUint(v uint32) (int, error) {
+ var b [4]byte
+ b[0] = byte(v >> 24)
+ b[1] = byte(v >> 16)
+ b[2] = byte(v >> 8)
+ b[3] = byte(v)
+
+ n, err := enc.w.Write(b[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIOEncode, err.Error(), 4)
+ err := marshalError("EncodeUint", ErrIO, msg, b[:n], err)
+ return n, err
+ }
+
+ return n, nil
+}
+
+// EncodeEnum treats the passed 32-bit signed integer as an enumeration value
+// and, if it is in the list of passed valid enumeration values, writes the XDR
+// encoded representation of it to the encapsulated writer. It returns the
+// number of bytes written.
+//
+// A MarshalError is returned if the enumeration value is not one of the
+// provided valid values or if writing the data fails.
+//
+// Reference:
+// RFC Section 4.3 - Enumeration
+// Represented as an XDR encoded signed integer
+func (enc *Encoder) EncodeEnum(v int32, validEnums map[int32]bool) (int, error) {
+ if !validEnums[v] {
+ err := marshalError("EncodeEnum", ErrBadEnumValue,
+ "invalid enum", v, nil)
+ return 0, err
+ }
+ return enc.EncodeInt(v)
+}
+
+// EncodeBool writes the XDR encoded representation of the passed boolean to the
+// encapsulated writer and returns the number of bytes written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.4 - Boolean
+// Represented as an XDR encoded enumeration where 0 is false and 1 is true
+func (enc *Encoder) EncodeBool(v bool) (int, error) {
+ i := int32(0)
+ if v == true {
+ i = 1
+ }
+ return enc.EncodeInt(i)
+}
+
+// EncodeHyper writes the XDR encoded representation of the passed 64-bit
+// signed integer to the encapsulated writer and returns the number of bytes
+// written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.5 - Hyper Integer
+// 64-bit big-endian signed integer in range [-9223372036854775808, 9223372036854775807]
+func (enc *Encoder) EncodeHyper(v int64) (int, error) {
+ var b [8]byte
+ b[0] = byte(v >> 56)
+ b[1] = byte(v >> 48)
+ b[2] = byte(v >> 40)
+ b[3] = byte(v >> 32)
+ b[4] = byte(v >> 24)
+ b[5] = byte(v >> 16)
+ b[6] = byte(v >> 8)
+ b[7] = byte(v)
+
+ n, err := enc.w.Write(b[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIOEncode, err.Error(), 8)
+ err := marshalError("EncodeHyper", ErrIO, msg, b[:n], err)
+ return n, err
+ }
+
+ return n, nil
+}
+
+// EncodeUhyper writes the XDR encoded representation of the passed 64-bit
+// unsigned integer to the encapsulated writer and returns the number of bytes
+// written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.5 - Unsigned Hyper Integer
+// 64-bit big-endian unsigned integer in range [0, 18446744073709551615]
+func (enc *Encoder) EncodeUhyper(v uint64) (int, error) {
+ var b [8]byte
+ b[0] = byte(v >> 56)
+ b[1] = byte(v >> 48)
+ b[2] = byte(v >> 40)
+ b[3] = byte(v >> 32)
+ b[4] = byte(v >> 24)
+ b[5] = byte(v >> 16)
+ b[6] = byte(v >> 8)
+ b[7] = byte(v)
+
+ n, err := enc.w.Write(b[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIOEncode, err.Error(), 8)
+ err := marshalError("EncodeUhyper", ErrIO, msg, b[:n], err)
+ return n, err
+ }
+
+ return n, nil
+}
+
+// EncodeFloat writes the XDR encoded representation of the passed 32-bit
+// (single-precision) floating point to the encapsulated writer and returns the
+// number of bytes written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.6 - Floating Point
+// 32-bit single-precision IEEE 754 floating point
+func (enc *Encoder) EncodeFloat(v float32) (int, error) {
+ ui := math.Float32bits(v)
+ return enc.EncodeUint(ui)
+}
+
+// EncodeDouble writes the XDR encoded representation of the passed 64-bit
+// (double-precision) floating point to the encapsulated writer and returns the
+// number of bytes written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.7 - Double-Precision Floating Point
+// 64-bit double-precision IEEE 754 floating point
+func (enc *Encoder) EncodeDouble(v float64) (int, error) {
+ ui := math.Float64bits(v)
+ return enc.EncodeUhyper(ui)
+}
+
+// RFC Section 4.8 - Quadruple-Precision Floating Point
+// 128-bit quadruple-precision floating point
+// Not Implemented
+
+// EncodeFixedOpaque treats the passed byte slice as opaque data of a fixed
+// size and writes the XDR encoded representation of it to the encapsulated
+// writer. It returns the number of bytes written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.9 - Fixed-Length Opaque Data
+// Fixed-length uninterpreted data zero-padded to a multiple of four
+func (enc *Encoder) EncodeFixedOpaque(v []byte) (int, error) {
+ l := len(v)
+ pad := (4 - (l % 4)) % 4
+
+ // Write the actual bytes.
+ n, err := enc.w.Write(v)
+ if err != nil {
+ msg := fmt.Sprintf(errIOEncode, err.Error(), len(v))
+ err := marshalError("EncodeFixedOpaque", ErrIO, msg, v[:n], err)
+ return n, err
+ }
+
+ // Write any padding if needed.
+ if pad > 0 {
+ b := make([]byte, pad)
+ n2, err := enc.w.Write(b)
+ n += n2
+ if err != nil {
+ written := make([]byte, l+n2)
+ copy(written, v)
+ copy(written[l:], b[:n2])
+ msg := fmt.Sprintf(errIOEncode, err.Error(), l+pad)
+ err := marshalError("EncodeFixedOpaque", ErrIO, msg,
+ written, err)
+ return n, err
+ }
+ }
+
+ return n, nil
+}
+
+// EncodeOpaque treats the passed byte slice as opaque data of a variable
+// size and writes the XDR encoded representation of it to the encapsulated
+// writer. It returns the number of bytes written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.10 - Variable-Length Opaque Data
+// Unsigned integer length followed by fixed opaque data of that length
+func (enc *Encoder) EncodeOpaque(v []byte) (int, error) {
+ // Length of opaque data.
+ n, err := enc.EncodeUint(uint32(len(v)))
+ if err != nil {
+ return n, err
+ }
+
+ n2, err := enc.EncodeFixedOpaque(v)
+ n += n2
+ return n, err
+}
+
+// EncodeString writes the XDR encoded representation of the passed string
+// to the encapsulated writer and returns the number of bytes written.
+// Character encoding is assumed to be UTF-8 and therefore ASCII compatible. If
+// the underlying character encoding is not compatible with this assumption, the
+// data can instead be written as variable-length opaque data (EncodeOpaque) and
+// manually converted as needed.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.11 - String
+// Unsigned integer length followed by bytes zero-padded to a multiple of four
+func (enc *Encoder) EncodeString(v string) (int, error) {
+ // Length of string.
+ n, err := enc.EncodeUint(uint32(len(v)))
+ if err != nil {
+ return n, err
+ }
+
+ n2, err := enc.EncodeFixedOpaque([]byte(v))
+ n += n2
+ return n, err
+}
+
+// encodeFixedArray writes the XDR encoded representation of each element
+// in the passed array represented by the reflection value to the encapsulated
+// writer and returns the number of bytes written. The ignoreOpaque flag
+// controls whether or not uint8 (byte) elements should be encoded individually
+// or as a fixed sequence of opaque data.
+//
+// A MarshalError is returned if any issues are encountered while encoding
+// the array elements.
+//
+// Reference:
+// RFC Section 4.12 - Fixed-Length Array
+// Individually XDR encoded array elements
+func (enc *Encoder) encodeFixedArray(v reflect.Value, ignoreOpaque bool) (int, error) {
+ // Treat [#]byte (byte is alias for uint8) as opaque data unless ignored.
+ if !ignoreOpaque && v.Type().Elem().Kind() == reflect.Uint8 {
+ // Create a slice of the underlying array for better efficiency
+ // when possible. Can't create a slice of an unaddressable
+ // value.
+ if v.CanAddr() {
+ return enc.EncodeFixedOpaque(v.Slice(0, v.Len()).Bytes())
+ }
+
+ // When the underlying array isn't addressable fall back to
+ // copying the array into a new slice. This is rather ugly, but
+ // the inability to create a constant slice from an
+ // unaddressable array is a limitation of Go.
+ slice := make([]byte, v.Len(), v.Len())
+ reflect.Copy(reflect.ValueOf(slice), v)
+ return enc.EncodeFixedOpaque(slice)
+ }
+
+ // Encode each array element.
+ var n int
+ for i := 0; i < v.Len(); i++ {
+ n2, err := enc.encode(v.Index(i))
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ }
+
+ return n, nil
+}
+
+// encodeArray writes an XDR encoded integer representing the number of
+// elements in the passed slice represented by the reflection value followed by
+// the XDR encoded representation of each element in slice to the encapsulated
+// writer and returns the number of bytes written. The ignoreOpaque flag
+// controls whether or not uint8 (byte) elements should be encoded individually
+// or as a variable sequence of opaque data.
+//
+// A MarshalError is returned if any issues are encountered while encoding
+// the array elements.
+//
+// Reference:
+// RFC Section 4.13 - Variable-Length Array
+// Unsigned integer length followed by individually XDR encoded array elements
+func (enc *Encoder) encodeArray(v reflect.Value, ignoreOpaque bool) (int, error) {
+ numItems := uint32(v.Len())
+ n, err := enc.EncodeUint(numItems)
+ if err != nil {
+ return n, err
+ }
+
+ n2, err := enc.encodeFixedArray(v, ignoreOpaque)
+ n += n2
+ return n, err
+}
+
+// encodeStruct writes an XDR encoded representation of each value in the
+// exported fields of the struct represented by the passed reflection value to
+// the encapsulated writer and returns the number of bytes written. Pointers
+// are automatically indirected through arbitrary depth to encode the actual
+// value pointed to.
+//
+// A MarshalError is returned if any issues are encountered while encoding
+// the elements.
+//
+// Reference:
+// RFC Section 4.14 - Structure
+// XDR encoded elements in the order of their declaration in the struct
+func (enc *Encoder) encodeStruct(v reflect.Value) (int, error) {
+ var n int
+ var union string
+ vt := v.Type()
+ for i := 0; i < v.NumField(); i++ {
+ // Skip unexported fields and indirect through pointers.
+ vtf := vt.Field(i)
+ if vtf.PkgPath != "" {
+ continue
+ }
+
+ vf := v.Field(i)
+ tag := parseTag(vtf.Tag)
+
+ // RFC Section 4.19 - Optional data
+ if tag.Get("optional") == "true" {
+ if vf.Type().Kind() != reflect.Ptr {
+ msg := fmt.Sprintf("optional must be a pointer, not '%v'",
+ vf.Type().String())
+ err := marshalError("encodeStruct", ErrBadOptional,
+ msg, nil, nil)
+ return n, err
+ }
+
+ hasopt := !vf.IsNil()
+ n2, err := enc.EncodeBool(hasopt)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ if !hasopt {
+ continue
+ }
+ }
+
+ vf = enc.indirect(vf)
+
+ // Handle non-opaque data to []uint8 and [#]uint8 based on struct tag.
+ if tag.Get("opaque") == "false" {
+ switch vf.Kind() {
+ case reflect.Slice:
+ n2, err := enc.encodeArray(vf, true)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ continue
+
+ case reflect.Array:
+ n2, err := enc.encodeFixedArray(vf, true)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ continue
+ }
+ }
+
+ // RFC Section 4.15 - Discriminated Union
+ // The tag option "union" marks the discriminant in the struct; the tag
+ // option "unioncase=N" marks a struct field that is only serialized
+ // when the discriminant has the specified value.
+ if tag.Get("union") == "true" {
+ if vf.Type().ConvertibleTo(reflect.TypeOf(0)) {
+ union = strconv.Itoa(int(vf.Convert(reflect.TypeOf(0)).Int()))
+ } else if vf.Kind() == reflect.Bool {
+ if vf.Bool() {
+ union = "1"
+ } else {
+ union = "0"
+ }
+ } else {
+ msg := fmt.Sprintf("type '%s' is not valid", vf.Kind().String())
+ return n, marshalError("encodeStruct", ErrBadDiscriminant, msg, nil, nil)
+ }
+ }
+
+ if union != "" {
+ ucase := tag.Get("unioncase")
+ if ucase != "" && ucase != union {
+ continue
+ }
+ }
+
+ // Encode each struct field.
+ n2, err := enc.encode(vf)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ }
+
+ return n, nil
+}
+
+// RFC Section 4.16 - Void
+// RFC Section 4.17 - Constant
+// RFC Section 4.18 - Typedef
+// RFC Section 4.19 - Optional data
+// RFC Sections 4.16 though 4.19 only apply to the data specification language
+// which is not implemented by this package.
+
+// encodeMap treats the map represented by the passed reflection value as a
+// variable-length array of 2-element structures whose fields are of the same
+// type as the map keys and elements and writes its XDR encoded representation
+// to the encapsulated writer. It returns the number of bytes written.
+//
+// A MarshalError is returned if any issues are encountered while encoding
+// the elements.
+func (enc *Encoder) encodeMap(v reflect.Value) (int, error) {
+ // Number of elements.
+ n, err := enc.EncodeUint(uint32(v.Len()))
+ if err != nil {
+ return n, err
+ }
+
+ // Encode each key and value according to their type.
+ for _, key := range v.MapKeys() {
+ n2, err := enc.encode(key)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+
+ n2, err = enc.encode(v.MapIndex(key))
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ }
+
+ return n, nil
+}
+
+// encodeInterface examines the interface represented by the passed reflection
+// value to detect whether it is an interface that can be encoded if it is,
+// extracts the underlying value to pass back into the encode function for
+// encoding according to its type.
+//
+// A MarshalError is returned if any issues are encountered while encoding
+// the interface.
+func (enc *Encoder) encodeInterface(v reflect.Value) (int, error) {
+ if v.IsNil() || !v.CanInterface() {
+ msg := fmt.Sprintf("can't encode nil interface")
+ err := marshalError("encodeInterface", ErrNilInterface, msg,
+ nil, nil)
+ return 0, err
+ }
+
+ // Extract underlying value from the interface and indirect through pointers.
+ ve := reflect.ValueOf(v.Interface())
+ ve = enc.indirect(ve)
+ return enc.encode(ve)
+}
+
+// encode is the main workhorse for marshalling via reflection. It uses
+// the passed reflection value to choose the XDR primitives to encode into
+// the encapsulated writer and returns the number of bytes written. It is a
+// recursive function, so cyclic data structures are not supported and will
+// result in an infinite loop.
+func (enc *Encoder) encode(v reflect.Value) (int, error) {
+ if !v.IsValid() {
+ msg := fmt.Sprintf("type '%s' is not valid", v.Kind().String())
+ err := marshalError("encode", ErrUnsupportedType, msg, nil, nil)
+ return 0, err
+ }
+
+ // Indirect through pointers to get at the concrete value.
+ ve := enc.indirect(v)
+
+ // Handle time.Time values by encoding them as an RFC3339 formatted
+ // string with nanosecond precision. Check the type string before
+ // doing a full blown conversion to interface and type assertion since
+ // checking a string is much quicker.
+ if ve.Type().String() == "time.Time" && ve.CanInterface() {
+ viface := ve.Interface()
+ if tv, ok := viface.(time.Time); ok {
+ return enc.EncodeString(tv.Format(time.RFC3339Nano))
+ }
+ }
+
+ // Handle native Go types.
+ switch ve.Kind() {
+ case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int:
+ return enc.EncodeInt(int32(ve.Int()))
+
+ case reflect.Int64:
+ return enc.EncodeHyper(ve.Int())
+
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint:
+ return enc.EncodeUint(uint32(ve.Uint()))
+
+ case reflect.Uint64:
+ return enc.EncodeUhyper(ve.Uint())
+
+ case reflect.Bool:
+ return enc.EncodeBool(ve.Bool())
+
+ case reflect.Float32:
+ return enc.EncodeFloat(float32(ve.Float()))
+
+ case reflect.Float64:
+ return enc.EncodeDouble(ve.Float())
+
+ case reflect.String:
+ return enc.EncodeString(ve.String())
+
+ case reflect.Array:
+ return enc.encodeFixedArray(ve, false)
+
+ case reflect.Slice:
+ return enc.encodeArray(ve, false)
+
+ case reflect.Struct:
+ return enc.encodeStruct(ve)
+
+ case reflect.Map:
+ return enc.encodeMap(ve)
+
+ case reflect.Interface:
+ return enc.encodeInterface(ve)
+ }
+
+ // The only unhandled types left are unsupported. At the time of this
+ // writing the only remaining unsupported types that exist are
+ // reflect.Uintptr and reflect.UnsafePointer.
+ msg := fmt.Sprintf("unsupported Go type '%s'", ve.Kind().String())
+ err := marshalError("encode", ErrUnsupportedType, msg, nil, nil)
+ return 0, err
+}
+
+// indirect dereferences pointers until it reaches a non-pointer. This allows
+// transparent encoding through arbitrary levels of indirection.
+func (enc *Encoder) indirect(v reflect.Value) reflect.Value {
+ rv := v
+ for rv.Kind() == reflect.Ptr {
+ rv = rv.Elem()
+ }
+ return rv
+}
+
+// Encode operates identically to the Marshal function with the exception of
+// using the writer associated with the Encoder for the destination of the
+// XDR-encoded data instead of a user-supplied writer. See the Marshal
+// documentation for specifics.
+func (enc *Encoder) Encode(v interface{}) (int, error) {
+ if v == nil {
+ msg := "can't marshal nil interface"
+ err := marshalError("Marshal", ErrNilInterface, msg, nil, nil)
+ return 0, err
+ }
+
+ vv := reflect.ValueOf(v)
+ vve := vv
+ for vve.Kind() == reflect.Ptr {
+ if vve.IsNil() {
+ msg := fmt.Sprintf("can't marshal nil pointer '%v'",
+ vv.Type().String())
+ err := marshalError("Marshal", ErrBadArguments, msg,
+ nil, nil)
+ return 0, err
+ }
+ vve = vve.Elem()
+ }
+
+ return enc.encode(vve)
+}
+
+// NewEncoder returns an object that can be used to manually choose fields to
+// XDR encode to the passed writer w. Typically, Marshal should be used instead
+// of manually creating an Encoder. An Encoder, along with several of its
+// methods to encode XDR primitives, is exposed so it is possible to perform
+// manual encoding of data without relying on reflection should it be necessary
+// in complex scenarios where automatic reflection-based encoding won't work.
+func NewEncoder(w io.Writer) *Encoder {
+ return &Encoder{w: w}
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-xdr/xdr2/error.go b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-xdr/xdr2/error.go
new file mode 100644
index 00000000..8c1f3aec
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-xdr/xdr2/error.go
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2012-2014 Dave Collins
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package xdr
+
+import "fmt"
+
+// ErrorCode identifies a kind of error.
+type ErrorCode int
+
+const (
+ // ErrBadArguments indicates arguments passed to the function are not
+ // what was expected.
+ ErrBadArguments ErrorCode = iota
+
+ // ErrUnsupportedType indicates the Go type is not a supported type for
+ // marshalling and unmarshalling XDR data.
+ ErrUnsupportedType
+
+ // ErrBadEnumValue indicates an enumeration value is not in the list of
+ // valid values.
+ ErrBadEnumValue
+
+ // ErrNotSettable indicates an interface value cannot be written to.
+ // This usually means the interface value was not passed with the &
+ // operator, but it can also happen if automatic pointer allocation
+ // fails.
+ ErrNotSettable
+
+ // ErrOverflow indicates that the data in question is too large to fit
+ // into the corresponding Go or XDR data type. For example, an integer
+ // decoded from XDR that is too large to fit into a target type of int8,
+ // or opaque data that exceeds the max length of a Go slice.
+ ErrOverflow
+
+ // ErrNilInterface indicates an interface with no concrete type
+ // information was encountered. Type information is necessary to
+ // perform mapping between XDR and Go types.
+ ErrNilInterface
+
+ // ErrIO indicates an error was encountered while reading or writing to
+ // an io.Reader or io.Writer, respectively. The actual underlying error
+ // will be available via the Err field of the MarshalError or
+ // UnmarshalError struct.
+ ErrIO
+
+ // ErrParseTime indicates an error was encountered while parsing an
+ // RFC3339 formatted time value. The actual underlying error will be
+ // available via the Err field of the UnmarshalError struct.
+ ErrParseTime
+
+ // ErrBadDiscriminant indicates that a non-integer field of a struct
+ // was marked as a union discriminant through a struct tag.
+ ErrBadDiscriminant
+
+ // ErrBadOptional indicates that a non-pointer field of a struct
+ // was marked as an optional-data.
+ ErrBadOptional
+)
+
+// Map of ErrorCode values back to their constant names for pretty printing.
+var errorCodeStrings = map[ErrorCode]string{
+ ErrBadArguments: "ErrBadArguments",
+ ErrUnsupportedType: "ErrUnsupportedType",
+ ErrBadEnumValue: "ErrBadEnumValue",
+ ErrNotSettable: "ErrNotSettable",
+ ErrOverflow: "ErrOverflow",
+ ErrNilInterface: "ErrNilInterface",
+ ErrIO: "ErrIO",
+ ErrParseTime: "ErrParseTime",
+ ErrBadDiscriminant: "ErrBadDiscriminant",
+ ErrBadOptional: "ErrBadOptional",
+}
+
+// String returns the ErrorCode as a human-readable name.
+func (e ErrorCode) String() string {
+ if s := errorCodeStrings[e]; s != "" {
+ return s
+ }
+ return fmt.Sprintf("Unknown ErrorCode (%d)", e)
+}
+
+// UnmarshalError describes a problem encountered while unmarshaling data.
+// Some potential issues are unsupported Go types, attempting to decode a value
+// which is too large to fit into a specified Go type, and exceeding max slice
+// limitations.
+type UnmarshalError struct {
+ ErrorCode ErrorCode // Describes the kind of error
+ Func string // Function name
+ Value interface{} // Value actually parsed where appropriate
+ Description string // Human readable description of the issue
+ Err error // The underlying error for IO errors
+}
+
+// Error satisfies the error interface and prints human-readable errors.
+func (e *UnmarshalError) Error() string {
+ switch e.ErrorCode {
+ case ErrBadEnumValue, ErrOverflow, ErrIO, ErrParseTime:
+ return fmt.Sprintf("xdr:%s: %s - read: '%v'", e.Func,
+ e.Description, e.Value)
+ }
+ return fmt.Sprintf("xdr:%s: %s", e.Func, e.Description)
+}
+
+// unmarshalError creates an error given a set of arguments and will copy byte
+// slices into the Value field since they might otherwise be changed from from
+// the original value.
+func unmarshalError(f string, c ErrorCode, desc string, v interface{}, err error) *UnmarshalError {
+ e := &UnmarshalError{ErrorCode: c, Func: f, Description: desc, Err: err}
+ switch t := v.(type) {
+ case []byte:
+ slice := make([]byte, len(t))
+ copy(slice, t)
+ e.Value = slice
+ default:
+ e.Value = v
+ }
+
+ return e
+}
+
+// IsIO returns a boolean indicating whether the error is known to report that
+// the underlying reader or writer encountered an ErrIO.
+func IsIO(err error) bool {
+ switch e := err.(type) {
+ case *UnmarshalError:
+ return e.ErrorCode == ErrIO
+ case *MarshalError:
+ return e.ErrorCode == ErrIO
+ }
+ return false
+}
+
+// MarshalError describes a problem encountered while marshaling data.
+// Some potential issues are unsupported Go types, attempting to encode more
+// opaque data than can be represented by a single opaque XDR entry, and
+// exceeding max slice limitations.
+type MarshalError struct {
+ ErrorCode ErrorCode // Describes the kind of error
+ Func string // Function name
+ Value interface{} // Value actually parsed where appropriate
+ Description string // Human readable description of the issue
+ Err error // The underlying error for IO errors
+}
+
+// Error satisfies the error interface and prints human-readable errors.
+func (e *MarshalError) Error() string {
+ switch e.ErrorCode {
+ case ErrIO:
+ return fmt.Sprintf("xdr:%s: %s - wrote: '%v'", e.Func,
+ e.Description, e.Value)
+ case ErrBadEnumValue:
+ return fmt.Sprintf("xdr:%s: %s - value: '%v'", e.Func,
+ e.Description, e.Value)
+ }
+ return fmt.Sprintf("xdr:%s: %s", e.Func, e.Description)
+}
+
+// marshalError creates an error given a set of arguments and will copy byte
+// slices into the Value field since they might otherwise be changed from from
+// the original value.
+func marshalError(f string, c ErrorCode, desc string, v interface{}, err error) *MarshalError {
+ e := &MarshalError{ErrorCode: c, Func: f, Description: desc, Err: err}
+ switch t := v.(type) {
+ case []byte:
+ slice := make([]byte, len(t))
+ copy(slice, t)
+ e.Value = slice
+ default:
+ e.Value = v
+ }
+
+ return e
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-xdr/xdr2/tag.go b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-xdr/xdr2/tag.go
new file mode 100644
index 00000000..7b5fe24b
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/davecgh/go-xdr/xdr2/tag.go
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015-2017 Giovanni Bajo
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package xdr
+
+import (
+ "reflect"
+ "strings"
+)
+
+// xdrtag represents a XDR struct tag, identified by the name "xdr:".
+// The value of the tag is a string that is parsed as a comma-separated
+// list of =-separated key-value options. If an option has no value,
+// "true" is assumed to be the default value.
+//
+// For instance:
+//
+// `xdr:"foo,bar=2,baz=false"
+//
+// After parsing this tag, Get("foo") will return "true", Get("bar")
+// will return "2", and Get("baz") will return "false".
+type xdrtag string
+
+// parseTag extracts a xdrtag from the original reflect.StructTag as found in
+// in the struct field. If the tag was not specified, an empty strtag is
+// returned.
+func parseTag(tag reflect.StructTag) xdrtag {
+ t := tag.Get("xdr")
+ // Handle backward compatibility with the previous "xdropaque"
+ // tag which is now deprecated.
+ if tag.Get("xdropaque") == "false" {
+ if t == "" {
+ t = ","
+ }
+ t += ",opaque=false"
+ }
+ return xdrtag(t)
+}
+
+// Get returns the value for the specified option. If the option is not
+// present in the tag, an empty string is returned. If the option is
+// present but has no value, the string "true" is returned as default value.
+func (t xdrtag) Get(opt string) string {
+ tag := string(t)
+ for tag != "" {
+ var next string
+ i := strings.Index(tag, ",")
+ if i >= 0 {
+ tag, next = tag[:i], tag[i+1:]
+ }
+ if tag == opt {
+ return "true"
+ }
+ if len(tag) > len(opt) && tag[:len(opt)] == opt && tag[len(opt)] == '=' {
+ return tag[len(opt)+1:]
+ }
+ tag = next
+ }
+ return ""
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/dce.go b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/dce.go
new file mode 100644
index 00000000..a6479dba
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/dce.go
@@ -0,0 +1,80 @@
+// Copyright 2016 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package uuid
+
+import (
+ "encoding/binary"
+ "fmt"
+ "os"
+)
+
+// A Domain represents a Version 2 domain
+type Domain byte
+
+// Domain constants for DCE Security (Version 2) UUIDs.
+const (
+ Person = Domain(0)
+ Group = Domain(1)
+ Org = Domain(2)
+)
+
+// NewDCESecurity returns a DCE Security (Version 2) UUID.
+//
+// The domain should be one of Person, Group or Org.
+// On a POSIX system the id should be the users UID for the Person
+// domain and the users GID for the Group. The meaning of id for
+// the domain Org or on non-POSIX systems is site defined.
+//
+// For a given domain/id pair the same token may be returned for up to
+// 7 minutes and 10 seconds.
+func NewDCESecurity(domain Domain, id uint32) (UUID, error) {
+ uuid, err := NewUUID()
+ if err == nil {
+ uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2
+ uuid[9] = byte(domain)
+ binary.BigEndian.PutUint32(uuid[0:], id)
+ }
+ return uuid, err
+}
+
+// NewDCEPerson returns a DCE Security (Version 2) UUID in the person
+// domain with the id returned by os.Getuid.
+//
+// NewDCEPerson(Person, uint32(os.Getuid()))
+func NewDCEPerson() (UUID, error) {
+ return NewDCESecurity(Person, uint32(os.Getuid()))
+}
+
+// NewDCEGroup returns a DCE Security (Version 2) UUID in the group
+// domain with the id returned by os.Getgid.
+//
+// NewDCEGroup(Group, uint32(os.Getgid()))
+func NewDCEGroup() (UUID, error) {
+ return NewDCESecurity(Group, uint32(os.Getgid()))
+}
+
+// Domain returns the domain for a Version 2 UUID. Domains are only defined
+// for Version 2 UUIDs.
+func (uuid UUID) Domain() Domain {
+ return Domain(uuid[9])
+}
+
+// ID returns the id for a Version 2 UUID. IDs are only defined for Version 2
+// UUIDs.
+func (uuid UUID) ID() uint32 {
+ return binary.BigEndian.Uint32(uuid[0:4])
+}
+
+func (d Domain) String() string {
+ switch d {
+ case Person:
+ return "Person"
+ case Group:
+ return "Group"
+ case Org:
+ return "Org"
+ }
+ return fmt.Sprintf("Domain%d", int(d))
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/doc.go b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/doc.go
new file mode 100644
index 00000000..5b8a4b9a
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/doc.go
@@ -0,0 +1,12 @@
+// Copyright 2016 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package uuid generates and inspects UUIDs.
+//
+// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security
+// Services.
+//
+// A UUID is a 16 byte (128 bit) array. UUIDs may be used as keys to
+// maps or compared directly.
+package uuid
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/hash.go b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/hash.go
new file mode 100644
index 00000000..4fc5a77d
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/hash.go
@@ -0,0 +1,53 @@
+// Copyright 2016 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package uuid
+
+import (
+ "crypto/md5"
+ "crypto/sha1"
+ "hash"
+)
+
+// Well known namespace IDs and UUIDs
+var (
+ NameSpaceDNS = Must(Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
+ NameSpaceURL = Must(Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8"))
+ NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
+ NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))
+ Nil UUID // empty UUID, all zeros
+)
+
+// NewHash returns a new UUID derived from the hash of space concatenated with
+// data generated by h. The hash should be at least 16 byte in length. The
+// first 16 bytes of the hash are used to form the UUID. The version of the
+// UUID will be the lower 4 bits of version. NewHash is used to implement
+// NewMD5 and NewSHA1.
+func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
+ h.Reset()
+ h.Write(space[:])
+ h.Write([]byte(data))
+ s := h.Sum(nil)
+ var uuid UUID
+ copy(uuid[:], s)
+ uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4)
+ uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant
+ return uuid
+}
+
+// NewMD5 returns a new MD5 (Version 3) UUID based on the
+// supplied name space and data. It is the same as calling:
+//
+// NewHash(md5.New(), space, data, 3)
+func NewMD5(space UUID, data []byte) UUID {
+ return NewHash(md5.New(), space, data, 3)
+}
+
+// NewSHA1 returns a new SHA1 (Version 5) UUID based on the
+// supplied name space and data. It is the same as calling:
+//
+// NewHash(sha1.New(), space, data, 5)
+func NewSHA1(space UUID, data []byte) UUID {
+ return NewHash(sha1.New(), space, data, 5)
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/marshal.go b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/marshal.go
new file mode 100644
index 00000000..84bbc588
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/marshal.go
@@ -0,0 +1,39 @@
+// Copyright 2016 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package uuid
+
+import "fmt"
+
+// MarshalText implements encoding.TextMarshaler.
+func (uuid UUID) MarshalText() ([]byte, error) {
+ var js [36]byte
+ encodeHex(js[:], uuid)
+ return js[:], nil
+}
+
+// UnmarshalText implements encoding.TextUnmarshaler.
+func (uuid *UUID) UnmarshalText(data []byte) error {
+ // See comment in ParseBytes why we do this.
+ // id, err := ParseBytes(data)
+ id, err := ParseBytes(data)
+ if err == nil {
+ *uuid = id
+ }
+ return err
+}
+
+// MarshalBinary implements encoding.BinaryMarshaler.
+func (uuid UUID) MarshalBinary() ([]byte, error) {
+ return uuid[:], nil
+}
+
+// UnmarshalBinary implements encoding.BinaryUnmarshaler.
+func (uuid *UUID) UnmarshalBinary(data []byte) error {
+ if len(data) != 16 {
+ return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
+ }
+ copy(uuid[:], data)
+ return nil
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/node.go b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/node.go
new file mode 100644
index 00000000..5f0156a2
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/node.go
@@ -0,0 +1,103 @@
+// Copyright 2016 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package uuid
+
+import (
+ "net"
+ "sync"
+)
+
+var (
+ nodeMu sync.Mutex
+ interfaces []net.Interface // cached list of interfaces
+ ifname string // name of interface being used
+ nodeID [6]byte // hardware for version 1 UUIDs
+ zeroID [6]byte // nodeID with only 0's
+)
+
+// NodeInterface returns the name of the interface from which the NodeID was
+// derived. The interface "user" is returned if the NodeID was set by
+// SetNodeID.
+func NodeInterface() string {
+ defer nodeMu.Unlock()
+ nodeMu.Lock()
+ return ifname
+}
+
+// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs.
+// If name is "" then the first usable interface found will be used or a random
+// Node ID will be generated. If a named interface cannot be found then false
+// is returned.
+//
+// SetNodeInterface never fails when name is "".
+func SetNodeInterface(name string) bool {
+ defer nodeMu.Unlock()
+ nodeMu.Lock()
+ return setNodeInterface(name)
+}
+
+func setNodeInterface(name string) bool {
+ if interfaces == nil {
+ var err error
+ interfaces, err = net.Interfaces()
+ if err != nil && name != "" {
+ return false
+ }
+ }
+
+ for _, ifs := range interfaces {
+ if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) {
+ copy(nodeID[:], ifs.HardwareAddr)
+ ifname = ifs.Name
+ return true
+ }
+ }
+
+ // We found no interfaces with a valid hardware address. If name
+ // does not specify a specific interface generate a random Node ID
+ // (section 4.1.6)
+ if name == "" {
+ randomBits(nodeID[:])
+ return true
+ }
+ return false
+}
+
+// NodeID returns a slice of a copy of the current Node ID, setting the Node ID
+// if not already set.
+func NodeID() []byte {
+ defer nodeMu.Unlock()
+ nodeMu.Lock()
+ if nodeID == zeroID {
+ setNodeInterface("")
+ }
+ nid := nodeID
+ return nid[:]
+}
+
+// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes
+// of id are used. If id is less than 6 bytes then false is returned and the
+// Node ID is not set.
+func SetNodeID(id []byte) bool {
+ if len(id) < 6 {
+ return false
+ }
+ defer nodeMu.Unlock()
+ nodeMu.Lock()
+ copy(nodeID[:], id)
+ ifname = "user"
+ return true
+}
+
+// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is
+// not valid. The NodeID is only well defined for version 1 and 2 UUIDs.
+func (uuid UUID) NodeID() []byte {
+ if len(uuid) != 16 {
+ return nil
+ }
+ var node [6]byte
+ copy(node[:], uuid[10:])
+ return node[:]
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/sql.go b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/sql.go
new file mode 100644
index 00000000..f326b54d
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/sql.go
@@ -0,0 +1,59 @@
+// Copyright 2016 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package uuid
+
+import (
+ "database/sql/driver"
+ "fmt"
+)
+
+// Scan implements sql.Scanner so UUIDs can be read from databases transparently
+// Currently, database types that map to string and []byte are supported. Please
+// consult database-specific driver documentation for matching types.
+func (uuid *UUID) Scan(src interface{}) error {
+ switch src := src.(type) {
+ case nil:
+ return nil
+
+ case string:
+ // if an empty UUID comes from a table, we return a null UUID
+ if src == "" {
+ return nil
+ }
+
+ // see Parse for required string format
+ u, err := Parse(src)
+ if err != nil {
+ return fmt.Errorf("Scan: %v", err)
+ }
+
+ *uuid = u
+
+ case []byte:
+ // if an empty UUID comes from a table, we return a null UUID
+ if len(src) == 0 {
+ return nil
+ }
+
+ // assumes a simple slice of bytes if 16 bytes
+ // otherwise attempts to parse
+ if len(src) != 16 {
+ return uuid.Scan(string(src))
+ }
+ copy((*uuid)[:], src)
+
+ default:
+ return fmt.Errorf("Scan: unable to scan type %T into UUID", src)
+ }
+
+ return nil
+}
+
+// Value implements sql.Valuer so that UUIDs can be written to databases
+// transparently. Currently, UUIDs map to strings. Please consult
+// database-specific driver documentation for matching types.
+func (uuid UUID) Value() (driver.Value, error) {
+ return uuid.String(), nil
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/time.go b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/time.go
new file mode 100644
index 00000000..fd7fe0ac
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/time.go
@@ -0,0 +1,123 @@
+// Copyright 2016 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package uuid
+
+import (
+ "encoding/binary"
+ "sync"
+ "time"
+)
+
+// A Time represents a time as the number of 100's of nanoseconds since 15 Oct
+// 1582.
+type Time int64
+
+const (
+ lillian = 2299160 // Julian day of 15 Oct 1582
+ unix = 2440587 // Julian day of 1 Jan 1970
+ epoch = unix - lillian // Days between epochs
+ g1582 = epoch * 86400 // seconds between epochs
+ g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs
+)
+
+var (
+ timeMu sync.Mutex
+ lasttime uint64 // last time we returned
+ clockSeq uint16 // clock sequence for this run
+
+ timeNow = time.Now // for testing
+)
+
+// UnixTime converts t the number of seconds and nanoseconds using the Unix
+// epoch of 1 Jan 1970.
+func (t Time) UnixTime() (sec, nsec int64) {
+ sec = int64(t - g1582ns100)
+ nsec = (sec % 10000000) * 100
+ sec /= 10000000
+ return sec, nsec
+}
+
+// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and
+// clock sequence as well as adjusting the clock sequence as needed. An error
+// is returned if the current time cannot be determined.
+func GetTime() (Time, uint16, error) {
+ defer timeMu.Unlock()
+ timeMu.Lock()
+ return getTime()
+}
+
+func getTime() (Time, uint16, error) {
+ t := timeNow()
+
+ // If we don't have a clock sequence already, set one.
+ if clockSeq == 0 {
+ setClockSequence(-1)
+ }
+ now := uint64(t.UnixNano()/100) + g1582ns100
+
+ // If time has gone backwards with this clock sequence then we
+ // increment the clock sequence
+ if now <= lasttime {
+ clockSeq = ((clockSeq + 1) & 0x3fff) | 0x8000
+ }
+ lasttime = now
+ return Time(now), clockSeq, nil
+}
+
+// ClockSequence returns the current clock sequence, generating one if not
+// already set. The clock sequence is only used for Version 1 UUIDs.
+//
+// The uuid package does not use global static storage for the clock sequence or
+// the last time a UUID was generated. Unless SetClockSequence is used, a new
+// random clock sequence is generated the first time a clock sequence is
+// requested by ClockSequence, GetTime, or NewUUID. (section 4.2.1.1)
+func ClockSequence() int {
+ defer timeMu.Unlock()
+ timeMu.Lock()
+ return clockSequence()
+}
+
+func clockSequence() int {
+ if clockSeq == 0 {
+ setClockSequence(-1)
+ }
+ return int(clockSeq & 0x3fff)
+}
+
+// SetClockSeq sets the clock sequence to the lower 14 bits of seq. Setting to
+// -1 causes a new sequence to be generated.
+func SetClockSequence(seq int) {
+ defer timeMu.Unlock()
+ timeMu.Lock()
+ setClockSequence(seq)
+}
+
+func setClockSequence(seq int) {
+ if seq == -1 {
+ var b [2]byte
+ randomBits(b[:]) // clock sequence
+ seq = int(b[0])<<8 | int(b[1])
+ }
+ old_seq := clockSeq
+ clockSeq = uint16(seq&0x3fff) | 0x8000 // Set our variant
+ if old_seq != clockSeq {
+ lasttime = 0
+ }
+}
+
+// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
+// uuid. The time is only defined for version 1 and 2 UUIDs.
+func (uuid UUID) Time() Time {
+ time := int64(binary.BigEndian.Uint32(uuid[0:4]))
+ time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
+ time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
+ return Time(time)
+}
+
+// ClockSequence returns the clock sequence encoded in uuid.
+// The clock sequence is only well defined for version 1 and 2 UUIDs.
+func (uuid UUID) ClockSequence() int {
+ return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/util.go b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/util.go
new file mode 100644
index 00000000..5ea6c737
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/util.go
@@ -0,0 +1,43 @@
+// Copyright 2016 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package uuid
+
+import (
+ "io"
+)
+
+// randomBits completely fills slice b with random data.
+func randomBits(b []byte) {
+ if _, err := io.ReadFull(rander, b); err != nil {
+ panic(err.Error()) // rand should never fail
+ }
+}
+
+// xvalues returns the value of a byte as a hexadecimal digit or 255.
+var xvalues = [256]byte{
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
+ 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+}
+
+// xtob converts hex characters x1 and x2 into a byte.
+func xtob(x1, x2 byte) (byte, bool) {
+ b1 := xvalues[x1]
+ b2 := xvalues[x2]
+ return (b1 << 4) | b2, b1 != 255 && b2 != 255
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/uuid.go b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/uuid.go
new file mode 100644
index 00000000..b7b9ced3
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/uuid.go
@@ -0,0 +1,191 @@
+// Copyright 2016 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package uuid
+
+import (
+ "bytes"
+ "crypto/rand"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "io"
+ "strings"
+)
+
+// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
+// 4122.
+type UUID [16]byte
+
+// A Version represents a UUID's version.
+type Version byte
+
+// A Variant represents a UUID's variant.
+type Variant byte
+
+// Constants returned by Variant.
+const (
+ Invalid = Variant(iota) // Invalid UUID
+ RFC4122 // The variant specified in RFC4122
+ Reserved // Reserved, NCS backward compatibility.
+ Microsoft // Reserved, Microsoft Corporation backward compatibility.
+ Future // Reserved for future definition.
+)
+
+var rander = rand.Reader // random function
+
+// Parse decodes s into a UUID or returns an error. Both the UUID form of
+// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
+// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded.
+func Parse(s string) (UUID, error) {
+ var uuid UUID
+ if len(s) != 36 {
+ if len(s) != 36+9 {
+ return uuid, fmt.Errorf("invalid UUID length: %d", len(s))
+ }
+ if strings.ToLower(s[:9]) != "urn:uuid:" {
+ return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9])
+ }
+ s = s[9:]
+ }
+ if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
+ return uuid, errors.New("invalid UUID format")
+ }
+ for i, x := range [16]int{
+ 0, 2, 4, 6,
+ 9, 11,
+ 14, 16,
+ 19, 21,
+ 24, 26, 28, 30, 32, 34} {
+ if v, ok := xtob(s[x], s[x+1]); !ok {
+ return uuid, errors.New("invalid UUID format")
+ } else {
+ uuid[i] = v
+ }
+ }
+ return uuid, nil
+}
+
+// ParseBytes is like Parse, except it parses a byte slice instead of a string.
+func ParseBytes(b []byte) (UUID, error) {
+ var uuid UUID
+ if len(b) != 36 {
+ if len(b) != 36+9 {
+ return uuid, fmt.Errorf("invalid UUID length: %d", len(b))
+ }
+ if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) {
+ return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9])
+ }
+ b = b[9:]
+ }
+ if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' {
+ return uuid, errors.New("invalid UUID format")
+ }
+ for i, x := range [16]int{
+ 0, 2, 4, 6,
+ 9, 11,
+ 14, 16,
+ 19, 21,
+ 24, 26, 28, 30, 32, 34} {
+ if v, ok := xtob(b[x], b[x+1]); !ok {
+ return uuid, errors.New("invalid UUID format")
+ } else {
+ uuid[i] = v
+ }
+ }
+ return uuid, nil
+}
+
+// Must returns uuid if err is nil and panics otherwise.
+func Must(uuid UUID, err error) UUID {
+ if err != nil {
+ panic(err)
+ }
+ return uuid
+}
+
+// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+// , or "" if uuid is invalid.
+func (uuid UUID) String() string {
+ var buf [36]byte
+ encodeHex(buf[:], uuid)
+ return string(buf[:])
+}
+
+// URN returns the RFC 2141 URN form of uuid,
+// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid.
+func (uuid UUID) URN() string {
+ var buf [36 + 9]byte
+ copy(buf[:], "urn:uuid:")
+ encodeHex(buf[9:], uuid)
+ return string(buf[:])
+}
+
+func encodeHex(dst []byte, uuid UUID) {
+ hex.Encode(dst[:], uuid[:4])
+ dst[8] = '-'
+ hex.Encode(dst[9:13], uuid[4:6])
+ dst[13] = '-'
+ hex.Encode(dst[14:18], uuid[6:8])
+ dst[18] = '-'
+ hex.Encode(dst[19:23], uuid[8:10])
+ dst[23] = '-'
+ hex.Encode(dst[24:], uuid[10:])
+}
+
+// Variant returns the variant encoded in uuid.
+func (uuid UUID) Variant() Variant {
+ switch {
+ case (uuid[8] & 0xc0) == 0x80:
+ return RFC4122
+ case (uuid[8] & 0xe0) == 0xc0:
+ return Microsoft
+ case (uuid[8] & 0xe0) == 0xe0:
+ return Future
+ default:
+ return Reserved
+ }
+}
+
+// Version returns the version of uuid.
+func (uuid UUID) Version() Version {
+ return Version(uuid[6] >> 4)
+}
+
+func (v Version) String() string {
+ if v > 15 {
+ return fmt.Sprintf("BAD_VERSION_%d", v)
+ }
+ return fmt.Sprintf("VERSION_%d", v)
+}
+
+func (v Variant) String() string {
+ switch v {
+ case RFC4122:
+ return "RFC4122"
+ case Reserved:
+ return "Reserved"
+ case Microsoft:
+ return "Microsoft"
+ case Future:
+ return "Future"
+ case Invalid:
+ return "Invalid"
+ }
+ return fmt.Sprintf("BadVariant%d", int(v))
+}
+
+// SetRand sets the random number generator to r, which implents io.Reader.
+// If r.Read returns an error when the package requests random data then
+// a panic will be issued.
+//
+// Calling SetRand with nil sets the random number generator to the default
+// generator.
+func SetRand(r io.Reader) {
+ if r == nil {
+ rander = rand.Reader
+ return
+ }
+ rander = r
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/version1.go b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/version1.go
new file mode 100644
index 00000000..22dc07cd
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/version1.go
@@ -0,0 +1,44 @@
+// Copyright 2016 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package uuid
+
+import (
+ "encoding/binary"
+)
+
+// NewUUID returns a Version 1 UUID based on the current NodeID and clock
+// sequence, and the current time. If the NodeID has not been set by SetNodeID
+// or SetNodeInterface then it will be set automatically. If the NodeID cannot
+// be set NewUUID returns nil. If clock sequence has not been set by
+// SetClockSequence then it will be set automatically. If GetTime fails to
+// return the current NewUUID returns Nil and an error.
+//
+// In most cases, New should be used.
+func NewUUID() (UUID, error) {
+ nodeMu.Lock()
+ if nodeID == zeroID {
+ setNodeInterface("")
+ }
+ nodeMu.Unlock()
+
+ var uuid UUID
+ now, seq, err := GetTime()
+ if err != nil {
+ return uuid, err
+ }
+
+ timeLow := uint32(now & 0xffffffff)
+ timeMid := uint16((now >> 32) & 0xffff)
+ timeHi := uint16((now >> 48) & 0x0fff)
+ timeHi |= 0x1000 // Version 1
+
+ binary.BigEndian.PutUint32(uuid[0:], timeLow)
+ binary.BigEndian.PutUint16(uuid[4:], timeMid)
+ binary.BigEndian.PutUint16(uuid[6:], timeHi)
+ binary.BigEndian.PutUint16(uuid[8:], seq)
+ copy(uuid[10:], nodeID[:])
+
+ return uuid, nil
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/version4.go b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/version4.go
new file mode 100644
index 00000000..390dd2ca
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/google/uuid/version4.go
@@ -0,0 +1,38 @@
+// Copyright 2016 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package uuid
+
+import "io"
+
+// New is creates a new random UUID or panics. New is equivalent to
+// the expression
+//
+// uuid.Must(uuid.NewRandom())
+func New() UUID {
+ return Must(NewRandom())
+}
+
+// NewRandom returns a Random (Version 4) UUID or panics.
+//
+// The strength of the UUIDs is based on the strength of the crypto/rand
+// package.
+//
+// A note about uniqueness derived from from the UUID Wikipedia entry:
+//
+// Randomly generated UUIDs have 122 random bits. One's annual risk of being
+// hit by a meteorite is estimated to be one chance in 17 billion, that
+// means the probability is about 0.00000000006 (6 × 10−11),
+// equivalent to the odds of creating a few tens of trillions of UUIDs in a
+// year and having one duplicate.
+func NewRandom() (UUID, error) {
+ var uuid UUID
+ _, err := io.ReadFull(rander, uuid[:])
+ if err != nil {
+ return Nil, err
+ }
+ uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
+ uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
+ return uuid, nil
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor.go b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor.go
new file mode 100644
index 00000000..43ee14cf
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor.go
@@ -0,0 +1,104 @@
+// Copyright 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 bdoor
+
+const (
+ BackdoorPort = uint16(0x5658)
+ BackdoorHighBWPort = uint16(0x5659)
+
+ CommandGetVersion = uint32(10)
+
+ CommandMessage = uint16(0x1e)
+ CommandHighBWMessage = uint16(0)
+ CommandFlagCookie = uint32(0x80000000)
+)
+
+func (p *BackdoorProto) InOut() *BackdoorProto {
+ p.DX.AsUInt32().Low = BackdoorPort
+ p.AX.SetValue(BackdoorMagic)
+
+ retax, retbx, retcx, retdx, retsi, retdi, retbp := bdoor_inout(
+ p.AX.Value(),
+ p.BX.Value(),
+ p.CX.Value(),
+ p.DX.Value(),
+ p.SI.Value(),
+ p.DI.Value(),
+ p.BP.Value(),
+ )
+
+ ret := &BackdoorProto{}
+ ret.AX.SetValue(retax)
+ ret.BX.SetValue(retbx)
+ ret.CX.SetValue(retcx)
+ ret.DX.SetValue(retdx)
+ ret.SI.SetValue(retsi)
+ ret.DI.SetValue(retdi)
+ ret.BP.SetValue(retbp)
+
+ return ret
+}
+
+func (p *BackdoorProto) HighBandwidthOut() *BackdoorProto {
+ p.DX.AsUInt32().Low = BackdoorHighBWPort
+ p.AX.SetValue(BackdoorMagic)
+
+ retax, retbx, retcx, retdx, retsi, retdi, retbp := bdoor_hbout(
+ p.AX.Value(),
+ p.BX.Value(),
+ p.CX.Value(),
+ p.DX.Value(),
+ p.SI.Value(),
+ p.DI.Value(),
+ p.BP.Value(),
+ )
+
+ ret := &BackdoorProto{}
+ ret.AX.SetValue(retax)
+ ret.BX.SetValue(retbx)
+ ret.CX.SetValue(retcx)
+ ret.DX.SetValue(retdx)
+ ret.SI.SetValue(retsi)
+ ret.DI.SetValue(retdi)
+ ret.BP.SetValue(retbp)
+
+ return ret
+}
+
+func (p *BackdoorProto) HighBandwidthIn() *BackdoorProto {
+ p.DX.AsUInt32().Low = BackdoorHighBWPort
+ p.AX.SetValue(BackdoorMagic)
+
+ retax, retbx, retcx, retdx, retsi, retdi, retbp := bdoor_hbin(
+ p.AX.Value(),
+ p.BX.Value(),
+ p.CX.Value(),
+ p.DX.Value(),
+ p.SI.Value(),
+ p.DI.Value(),
+ p.BP.Value(),
+ )
+
+ ret := &BackdoorProto{}
+ ret.AX.SetValue(retax)
+ ret.BX.SetValue(retbx)
+ ret.CX.SetValue(retcx)
+ ret.DX.SetValue(retdx)
+ ret.SI.SetValue(retsi)
+ ret.DI.SetValue(retdi)
+ ret.BP.SetValue(retbp)
+
+ return ret
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_386.go b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_386.go
new file mode 100644
index 00000000..ea9a2f25
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_386.go
@@ -0,0 +1,48 @@
+// Copyright 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 bdoor
+
+const (
+ BackdoorMagic = uint32(0x564D5868)
+)
+
+type BackdoorProto struct {
+ // typedef union {
+ // struct {
+ // DECLARE_REG_NAMED_STRUCT(ax);
+ // size_t size; /* Register bx. */
+ // DECLARE_REG_NAMED_STRUCT(cx);
+ // DECLARE_REG_NAMED_STRUCT(dx);
+ // DECLARE_REG_NAMED_STRUCT(si);
+ // DECLARE_REG_NAMED_STRUCT(di);
+ // } in;
+ // struct {
+ // DECLARE_REG_NAMED_STRUCT(ax);
+ // DECLARE_REG_NAMED_STRUCT(bx);
+ // DECLARE_REG_NAMED_STRUCT(cx);
+ // DECLARE_REG_NAMED_STRUCT(dx);
+ // DECLARE_REG_NAMED_STRUCT(si);
+ // DECLARE_REG_NAMED_STRUCT(di);
+ // } out;
+ // } proto;
+
+ AX, BX, CX, DX, SI, DI, BP UInt32
+ size uint32
+}
+
+func bdoor_inout(ax, bx, cx, dx, si, di, bp uint32) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint32)
+func bdoor_hbout(ax, bx, cx, dx, si, di, bp uint32) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint32)
+func bdoor_hbin(ax, bx, cx, dx, si, di, bp uint32) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint32)
+func bdoor_inout_test(ax, bx, cx, dx, si, di, bp uint32) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint32)
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_386.s b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_386.s
new file mode 100644
index 00000000..a6e11b11
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_386.s
@@ -0,0 +1,112 @@
+#include "textflag.h"
+
+// Doc of the golang plan9 assembler
+// http://p9.nyx.link/labs/sys/doc/asm.html
+//
+// A good primer of how to write golang with some plan9 flavored assembly
+// http://www.doxsey.net/blog/go-and-assembly
+//
+// Some x86 references
+// http://www.eecg.toronto.edu/~amza/www.mindsec.com/files/x86regs.html
+// https://cseweb.ucsd.edu/classes/sp10/cse141/pdf/02/S01_x86_64.key.pdf
+// https://en.wikibooks.org/wiki/X86_Assembly/Other_Instructions
+//
+// (This one is invaluable. Has a working example of how a standard function
+// call looks on the stack with the associated assembly.)
+// https://www.recurse.com/blog/7-understanding-c-by-learning-assembly
+//
+// Reference with raw form of the Opcode
+// http://x86.renejeschke.de/html/file_module_x86_id_139.html
+//
+// Massive x86_64 reference
+// http://ref.x86asm.net/coder64.html#xED
+//
+// Adding instructions to the go assembler
+// https://blog.klauspost.com/adding-unsupported-instructions-in-golang-assembler/
+//
+// Backdoor commands
+// https://sites.google.com/site/chitchatvmback/backdoor
+
+// func bdoor_inout(ax, bx, cx, dx, si, di, bp uint32) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint32)
+TEXT ·bdoor_inout(SB), NOSPLIT|WRAPPER, $0
+ MOVL ax+0(FP), AX
+ MOVL bx+4(FP), BX
+ MOVL cx+8(FP), CX
+ MOVL dx+12(FP), DX
+ MOVL si+16(FP), SI
+ MOVL di+20(FP), DI
+ MOVL bp+24(FP), BP
+
+ // IN to DX from EAX
+ INL
+
+ MOVL AX, retax+28(FP)
+ MOVL BX, retbx+32(FP)
+ MOVL CX, retcx+36(FP)
+ MOVL DX, retdx+40(FP)
+ MOVL SI, retsi+44(FP)
+ MOVL DI, retdi+48(FP)
+ MOVL BP, retbp+52(FP)
+ RET
+
+// func bdoor_hbout(ax, bx, cx, dx, si, di, bp uint32) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint32)
+TEXT ·bdoor_hbout(SB), NOSPLIT|WRAPPER, $0
+ MOVL ax+0(FP), AX
+ MOVL bx+4(FP), BX
+ MOVL cx+8(FP), CX
+ MOVL dx+12(FP), DX
+ MOVL si+16(FP), SI
+ MOVL di+20(FP), DI
+ MOVL bp+24(FP), BP
+
+ CLD; REP; OUTSB
+
+ MOVL AX, retax+28(FP)
+ MOVL BX, retbx+32(FP)
+ MOVL CX, retcx+36(FP)
+ MOVL DX, retdx+40(FP)
+ MOVL SI, retsi+44(FP)
+ MOVL DI, retdi+48(FP)
+ MOVL BP, retbp+52(FP)
+ RET
+
+// func bdoor_hbin(ax, bx, cx, dx, si, di, bp uint32) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint32)
+TEXT ·bdoor_hbin(SB), NOSPLIT|WRAPPER, $0
+ MOVL ax+0(FP), AX
+ MOVL bx+4(FP), BX
+ MOVL cx+8(FP), CX
+ MOVL dx+12(FP), DX
+ MOVL si+16(FP), SI
+ MOVL di+20(FP), DI
+ MOVL bp+24(FP), BP
+
+ CLD; REP; INSB
+
+ MOVL AX, retax+28(FP)
+ MOVL BX, retbx+32(FP)
+ MOVL CX, retcx+40(FP)
+ MOVL DX, retdx+44(FP)
+ MOVL SI, retsi+48(FP)
+ MOVL DI, retdi+52(FP)
+ MOVL BP, retbp+56(FP)
+ RET
+
+// func bdoor_inout_test(ax, bx, cx, dx, si, di, bp uint32) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint32)
+TEXT ·bdoor_inout_test(SB), NOSPLIT|WRAPPER, $0
+ MOVL ax+0(FP), AX
+ MOVL bx+4(FP), BX
+ MOVL cx+8(FP), CX
+ MOVL dx+12(FP), DX
+ MOVL si+16(FP), SI
+ MOVL di+20(FP), DI
+ MOVL bp+24(FP), BP
+
+ MOVL AX, retax+28(FP)
+ MOVL BX, retbx+32(FP)
+ MOVL CX, retcx+36(FP)
+ MOVL DX, retdx+40(FP)
+ MOVL SI, retsi+44(FP)
+ MOVL DI, retdi+48(FP)
+ MOVL BP, retbp+52(FP)
+ RET
+
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_amd64.go b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_amd64.go
new file mode 100644
index 00000000..0793c699
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_amd64.go
@@ -0,0 +1,48 @@
+// Copyright 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 bdoor
+
+const (
+ BackdoorMagic = uint64(0x564D5868)
+)
+
+type BackdoorProto struct {
+ // typedef union {
+ // struct {
+ // DECLARE_REG_NAMED_STRUCT(ax);
+ // size_t size; /* Register bx. */
+ // DECLARE_REG_NAMED_STRUCT(cx);
+ // DECLARE_REG_NAMED_STRUCT(dx);
+ // DECLARE_REG_NAMED_STRUCT(si);
+ // DECLARE_REG_NAMED_STRUCT(di);
+ // } in;
+ // struct {
+ // DECLARE_REG_NAMED_STRUCT(ax);
+ // DECLARE_REG_NAMED_STRUCT(bx);
+ // DECLARE_REG_NAMED_STRUCT(cx);
+ // DECLARE_REG_NAMED_STRUCT(dx);
+ // DECLARE_REG_NAMED_STRUCT(si);
+ // DECLARE_REG_NAMED_STRUCT(di);
+ // } out;
+ // } proto;
+
+ AX, BX, CX, DX, SI, DI, BP UInt64
+ size uint32
+}
+
+func bdoor_inout(ax, bx, cx, dx, si, di, bp uint64) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint64)
+func bdoor_hbout(ax, bx, cx, dx, si, di, bp uint64) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint64)
+func bdoor_hbin(ax, bx, cx, dx, si, di, bp uint64) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint64)
+func bdoor_inout_test(ax, bx, cx, dx, si, di, bp uint64) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint64)
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_amd64.s b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_amd64.s
new file mode 100644
index 00000000..62f0c06d
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_amd64.s
@@ -0,0 +1,112 @@
+#include "textflag.h"
+
+// Doc of the golang plan9 assembler
+// http://p9.nyx.link/labs/sys/doc/asm.html
+//
+// A good primer of how to write golang with some plan9 flavored assembly
+// http://www.doxsey.net/blog/go-and-assembly
+//
+// Some x86 references
+// http://www.eecg.toronto.edu/~amza/www.mindsec.com/files/x86regs.html
+// https://cseweb.ucsd.edu/classes/sp10/cse141/pdf/02/S01_x86_64.key.pdf
+// https://en.wikibooks.org/wiki/X86_Assembly/Other_Instructions
+//
+// (This one is invaluable. Has a working example of how a standard function
+// call looks on the stack with the associated assembly.)
+// https://www.recurse.com/blog/7-understanding-c-by-learning-assembly
+//
+// Reference with raw form of the Opcode
+// http://x86.renejeschke.de/html/file_module_x86_id_139.html
+//
+// Massive x86_64 reference
+// http://ref.x86asm.net/coder64.html#xED
+//
+// Adding instructions to the go assembler
+// https://blog.klauspost.com/adding-unsupported-instructions-in-golang-assembler/
+//
+// Backdoor commands
+// https://sites.google.com/site/chitchatvmback/backdoor
+
+// func bdoor_inout(ax, bx, cx, dx, si, di, bp uint64) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint64)
+TEXT ·bdoor_inout(SB), NOSPLIT|WRAPPER, $0
+ MOVQ ax+0(FP), AX
+ MOVQ bx+8(FP), BX
+ MOVQ cx+16(FP), CX
+ MOVQ dx+24(FP), DX
+ MOVQ si+32(FP), SI
+ MOVQ di+40(FP), DI
+ MOVQ bp+48(FP), BP
+
+ // IN to DX from EAX
+ INL
+
+ MOVQ AX, retax+56(FP)
+ MOVQ BX, retbx+64(FP)
+ MOVQ CX, retcx+72(FP)
+ MOVQ DX, retdx+80(FP)
+ MOVQ SI, retsi+88(FP)
+ MOVQ DI, retdi+96(FP)
+ MOVQ BP, retbp+104(FP)
+ RET
+
+// func bdoor_hbout(ax, bx, cx, dx, si, di, bp uint64) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint64)
+TEXT ·bdoor_hbout(SB), NOSPLIT|WRAPPER, $0
+ MOVQ ax+0(FP), AX
+ MOVQ bx+8(FP), BX
+ MOVQ cx+16(FP), CX
+ MOVQ dx+24(FP), DX
+ MOVQ si+32(FP), SI
+ MOVQ di+40(FP), DI
+ MOVQ bp+48(FP), BP
+
+ CLD; REP; OUTSB
+
+ MOVQ AX, retax+56(FP)
+ MOVQ BX, retbx+64(FP)
+ MOVQ CX, retcx+72(FP)
+ MOVQ DX, retdx+80(FP)
+ MOVQ SI, retsi+88(FP)
+ MOVQ DI, retdi+96(FP)
+ MOVQ BP, retbp+104(FP)
+ RET
+
+// func bdoor_hbin(ax, bx, cx, dx, si, di, bp uint64) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint64)
+TEXT ·bdoor_hbin(SB), NOSPLIT|WRAPPER, $0
+ MOVQ ax+0(FP), AX
+ MOVQ bx+8(FP), BX
+ MOVQ cx+16(FP), CX
+ MOVQ dx+24(FP), DX
+ MOVQ si+32(FP), SI
+ MOVQ di+40(FP), DI
+ MOVQ bp+48(FP), BP
+
+ CLD; REP; INSB
+
+ MOVQ AX, retax+56(FP)
+ MOVQ BX, retbx+64(FP)
+ MOVQ CX, retcx+72(FP)
+ MOVQ DX, retdx+80(FP)
+ MOVQ SI, retsi+88(FP)
+ MOVQ DI, retdi+96(FP)
+ MOVQ BP, retbp+104(FP)
+ RET
+
+// func bdoor_inout_test(ax, bx, cx, dx, si, di, bp uint64) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint64)
+TEXT ·bdoor_inout_test(SB), NOSPLIT|WRAPPER, $0
+ MOVQ ax+0(FP), AX
+ MOVQ bx+8(FP), BX
+ MOVQ cx+16(FP), CX
+ MOVQ dx+24(FP), DX
+ MOVQ si+32(FP), SI
+ MOVQ di+40(FP), DI
+ MOVQ bp+48(FP), BP
+
+ MOVQ AX, retax+56(FP)
+ MOVQ BX, retbx+64(FP)
+ MOVQ CX, retcx+72(FP)
+ MOVQ DX, retdx+80(FP)
+ MOVQ SI, retsi+88(FP)
+ MOVQ DI, retdi+96(FP)
+ MOVQ BP, retbp+104(FP)
+ RET
+
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/word.go b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/word.go
new file mode 100644
index 00000000..ec1ee13b
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/bdoor/word.go
@@ -0,0 +1,77 @@
+// Copyright 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 bdoor
+
+import "unsafe"
+
+type UInt32 struct {
+ High uint16
+ Low uint16
+}
+
+func (u *UInt32) Word() uint32 {
+ return uint32(u.High)<<16 + uint32(u.Low)
+}
+
+func (u *UInt32) SetWord(w uint32) {
+ u.High = uint16(w >> 16)
+ u.Low = uint16(w)
+}
+
+func (u *UInt32) AsUInt32() *UInt32 {
+ return u
+}
+
+func (u *UInt32) Value() uint32 {
+ return u.Word()
+}
+
+func (u *UInt32) SetValue(val uint32) {
+ u.SetWord(val)
+}
+
+func (u *UInt32) SetPointer(p unsafe.Pointer) {
+ u.SetWord(uint32(uintptr(p)))
+}
+
+type UInt64 struct {
+ High UInt32
+ Low UInt32
+}
+
+func (u *UInt64) Quad() uint64 {
+ return uint64(u.High.Word())<<32 + uint64(u.Low.Word())
+}
+
+func (u *UInt64) SetQuad(w uint64) {
+ u.High.SetWord(uint32(w >> 32))
+ u.Low.SetWord(uint32(w))
+}
+
+func (u *UInt64) AsUInt32() *UInt32 {
+ return &u.Low
+}
+
+func (u *UInt64) Value() uint64 {
+ return u.Quad()
+}
+
+func (u *UInt64) SetValue(val uint64) {
+ u.SetQuad(val)
+}
+
+func (u *UInt64) SetPointer(p unsafe.Pointer) {
+ u.SetQuad(uint64(uintptr(p)))
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/examples/main.go b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/examples/main.go
new file mode 100644
index 00000000..6658020c
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/examples/main.go
@@ -0,0 +1,75 @@
+// Copyright 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 main
+
+import (
+ "flag"
+ "fmt"
+ "log"
+
+ "github.com/vmware/vmw-guestinfo/rpcvmx"
+ "github.com/vmware/vmw-guestinfo/vmcheck"
+)
+
+var (
+ set bool
+ get bool
+)
+
+func init() {
+
+ flag.BoolVar(&set, "set", false, "Sets the guestinfo.KEY with the string VALUE")
+ flag.BoolVar(&get, "get", false, "Returns the config string in the guestinfo.* namespace")
+
+ flag.Parse()
+}
+
+func main() {
+
+ isVM, err := vmcheck.IsVirtualWorld()
+ if err != nil {
+ log.Fatalf("Error: %s", err)
+ }
+
+ if !isVM {
+ log.Fatalf("ERROR: not in a virtual world.")
+ }
+
+ if !set && !get {
+ flag.Usage()
+ }
+
+ config := rpcvmx.NewConfig()
+ if set {
+ if flag.NArg() != 2 {
+ log.Fatalf("ERROR: Please provide guestinfo key / value pair (eg; -set foo bar")
+ }
+ if err := config.SetString(flag.Arg(0), flag.Arg(1)); err != nil {
+ log.Fatalf("ERROR: SetString failed with %s", err)
+ }
+ }
+
+ if get {
+ if flag.NArg() != 1 {
+ log.Fatalf("ERROR: Please provide guestinfo key (eg; -get foo)")
+ }
+ if out, err := config.String(flag.Arg(0), ""); err != nil {
+ log.Fatalf("ERROR: String failed with %s", err)
+ } else {
+ fmt.Printf("%s\n", out)
+ }
+ }
+
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/message/log.go b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/message/log.go
new file mode 100644
index 00000000..3bb96f2e
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/message/log.go
@@ -0,0 +1,61 @@
+// Copyright 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 message
+
+import "log"
+
+var DefaultLogger Logger
+
+type Logger interface {
+ Errorf(format string, args ...interface{})
+ Debugf(format string, args ...interface{})
+ Infof(format string, args ...interface{})
+}
+
+func init() {
+ DefaultLogger = &logger{}
+}
+
+type logger struct {
+ DebugLevel bool
+}
+
+func (l *logger) Errorf(format string, args ...interface{}) {
+ log.Printf(format, args...)
+}
+
+func (l *logger) Debugf(format string, args ...interface{}) {
+ if !l.DebugLevel {
+ return
+ }
+
+ log.Printf(format, args...)
+}
+
+func (l *logger) Infof(format string, args ...interface{}) {
+ log.Printf(format, args...)
+}
+
+func Errorf(format string, args ...interface{}) {
+ DefaultLogger.Errorf(format, args...)
+}
+
+func Debugf(format string, args ...interface{}) {
+ DefaultLogger.Debugf(format, args...)
+}
+
+func Infof(format string, args ...interface{}) {
+ DefaultLogger.Infof(format, args...)
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/message/message.go b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/message/message.go
new file mode 100644
index 00000000..a6261920
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/message/message.go
@@ -0,0 +1,334 @@
+// Copyright 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 message
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "unsafe"
+
+ "github.com/vmware/vmw-guestinfo/bdoor"
+)
+
+const (
+ messageTypeOpen = iota
+ messageTypeSendSize
+ messageTypeSendPayload
+ messageTypeReceiveSize
+ messageTypeReceivePayload
+ messageTypeReceiveStatus
+ messageTypeClose
+
+ messageStatusFail = uint16(0x0000)
+ messageStatusSuccess = uint16(0x0001)
+ messageStatusDoRecieve = uint16(0x0002)
+ messageStatusCheckPoint = uint16(0x0010)
+ messageStatusHighBW = uint16(0x0080)
+)
+
+var (
+ // ErrChannelOpen represents a failure to open a channel
+ ErrChannelOpen = errors.New("could not open channel")
+ // ErrChannelClose represents a failure to close a channel
+ ErrChannelClose = errors.New("could not close channel")
+ // ErrRpciSend represents a failure to send a message
+ ErrRpciSend = errors.New("unable to send RPCI command")
+ // ErrRpciReceive represents a failure to receive a message
+ ErrRpciReceive = errors.New("unable to receive RPCI command result")
+)
+
+type Channel struct {
+ id uint16
+
+ forceLowBW bool
+ buf []byte
+
+ cookie bdoor.UInt64
+}
+
+// NewChannel opens a new Channel
+func NewChannel(proto uint32) (*Channel, error) {
+ flags := bdoor.CommandFlagCookie
+
+retry:
+ bp := &bdoor.BackdoorProto{}
+
+ bp.BX.AsUInt32().SetWord(proto | flags)
+ bp.CX.AsUInt32().High = messageTypeOpen
+ bp.CX.AsUInt32().Low = bdoor.CommandMessage
+
+ out := bp.InOut()
+ if (out.CX.AsUInt32().High & messageStatusSuccess) == 0 {
+ if flags != 0 {
+ flags = 0
+ goto retry
+ }
+
+ Errorf("Message: Unable to open communication channel")
+ return nil, ErrChannelOpen
+ }
+
+ ch := &Channel{}
+ ch.id = out.DX.AsUInt32().High
+ ch.cookie.High.SetWord(out.SI.AsUInt32().Word())
+ ch.cookie.Low.SetWord(out.DI.AsUInt32().Word())
+
+ Debugf("Opened channel %d", ch.id)
+ return ch, nil
+}
+
+func (c *Channel) Close() error {
+ bp := &bdoor.BackdoorProto{}
+
+ bp.CX.AsUInt32().High = messageTypeClose
+ bp.CX.AsUInt32().Low = bdoor.CommandMessage
+
+ bp.DX.AsUInt32().High = c.id
+ bp.SI.AsUInt32().SetWord(c.cookie.High.Word())
+ bp.DI.AsUInt32().SetWord(c.cookie.Low.Word())
+
+ out := bp.InOut()
+ if (out.CX.AsUInt32().High & messageStatusSuccess) == 0 {
+ Errorf("Message: Unable to close communication channel %d", c.id)
+ return ErrChannelClose
+ }
+
+ Debugf("Closed channel %d", c.id)
+ return nil
+}
+
+func (c *Channel) Send(buf []byte) error {
+retry:
+ bp := &bdoor.BackdoorProto{}
+ bp.CX.AsUInt32().High = messageTypeSendSize
+ bp.CX.AsUInt32().Low = bdoor.CommandMessage
+
+ bp.DX.AsUInt32().High = c.id
+ bp.SI.AsUInt32().SetWord(c.cookie.High.Word())
+ bp.DI.AsUInt32().SetWord(c.cookie.Low.Word())
+
+ bp.BX.AsUInt32().SetWord(uint32(len(buf)))
+
+ // send the size
+ out := bp.InOut()
+ if (out.CX.AsUInt32().High & messageStatusSuccess) == 0 {
+ Errorf("Message: Unable to send a message over the communication channel %d", c.id)
+ return ErrRpciSend
+ }
+
+ // size of buf 0 is fine, just return
+ if len(buf) == 0 {
+ return nil
+ }
+
+ if !c.forceLowBW && (out.CX.AsUInt32().High&messageStatusHighBW) == messageStatusHighBW {
+ hbbp := &bdoor.BackdoorProto{}
+
+ hbbp.BX.AsUInt32().Low = bdoor.CommandHighBWMessage
+ hbbp.BX.AsUInt32().High = messageStatusSuccess
+ hbbp.DX.AsUInt32().High = c.id
+ hbbp.BP.AsUInt32().SetWord(c.cookie.High.Word())
+ hbbp.DI.AsUInt32().SetWord(c.cookie.Low.Word())
+ hbbp.CX.AsUInt32().SetWord(uint32(len(buf)))
+ hbbp.SI.SetPointer(unsafe.Pointer(&buf[0]))
+
+ out := hbbp.HighBandwidthOut()
+ if (out.BX.AsUInt32().High & messageStatusSuccess) == 0 {
+ if (out.BX.AsUInt32().High & messageStatusCheckPoint) != 0 {
+ Debugf("A checkpoint occurred. Retrying the operation")
+ goto retry
+ }
+
+ Errorf("Message: Unable to send a message over the communication channel %d", c.id)
+ return ErrRpciSend
+ }
+ } else {
+ bp.CX.AsUInt32().High = messageTypeSendPayload
+
+ bbuf := bytes.NewBuffer(buf)
+ for {
+ // read 4 bytes at a time
+ words := bbuf.Next(4)
+ if len(words) == 0 {
+ break
+ }
+
+ Debugf("sending %q over %d", string(words), c.id)
+ switch len(words) {
+ case 3:
+ bp.BX.AsUInt32().SetWord(binary.LittleEndian.Uint32([]byte{0x0, words[2], words[1], words[0]}))
+ case 2:
+ bp.BX.AsUInt32().SetWord(uint32(binary.LittleEndian.Uint16(words)))
+ case 1:
+ bp.BX.AsUInt32().SetWord(uint32(words[0]))
+ default:
+ bp.BX.AsUInt32().SetWord(binary.LittleEndian.Uint32(words))
+ }
+
+ out = bp.InOut()
+ if (out.CX.AsUInt32().High & messageStatusSuccess) == 0 {
+ Errorf("Message: Unable to send a message over the communication channel %d", c.id)
+ return ErrRpciSend
+ }
+ }
+ }
+
+ return nil
+}
+
+func (c *Channel) Receive() ([]byte, error) {
+retry:
+ var err error
+ bp := &bdoor.BackdoorProto{}
+ bp.CX.AsUInt32().High = messageTypeReceiveSize
+ bp.CX.AsUInt32().Low = bdoor.CommandMessage
+
+ bp.DX.AsUInt32().High = c.id
+ bp.SI.AsUInt32().SetWord(c.cookie.High.Word())
+ bp.DI.AsUInt32().SetWord(c.cookie.Low.Word())
+
+ out := bp.InOut()
+ if (out.CX.AsUInt32().High & messageStatusSuccess) == 0 {
+ Errorf("Message: Unable to poll for messages over the communication channel %d", c.id)
+ return nil, ErrRpciReceive
+ }
+
+ if (out.CX.AsUInt32().High & messageStatusDoRecieve) == 0 {
+ Debugf("No message to retrieve")
+ return nil, nil
+ }
+
+ // Receive the size.
+ if out.DX.AsUInt32().High != messageTypeSendSize {
+ Errorf("Message: Protocol error. Expected a MESSAGE_TYPE_SENDSIZE request from vmware")
+ return nil, ErrRpciReceive
+ }
+
+ size := out.BX.Value()
+
+ var buf []byte
+
+ if size != 0 {
+ if !c.forceLowBW && (out.CX.AsUInt32().High&messageStatusHighBW == messageStatusHighBW) {
+ buf = make([]byte, size)
+
+ hbbp := &bdoor.BackdoorProto{}
+
+ hbbp.BX.AsUInt32().Low = bdoor.CommandHighBWMessage
+ hbbp.BX.AsUInt32().High = messageStatusSuccess
+ hbbp.DX.AsUInt32().High = c.id
+ hbbp.SI.AsUInt32().SetWord(c.cookie.High.Word())
+ hbbp.BP.AsUInt32().SetWord(c.cookie.Low.Word())
+ hbbp.CX.AsUInt32().SetWord(uint32(len(buf)))
+ hbbp.DI.SetPointer(unsafe.Pointer(&buf[0]))
+
+ out := hbbp.HighBandwidthIn()
+ if (out.BX.AsUInt32().High & messageStatusSuccess) == 0 {
+ Errorf("Message: Unable to send a message over the communication channel %d", c.id)
+ c.reply(messageTypeReceivePayload, messageStatusFail)
+ return nil, ErrRpciReceive
+ }
+ } else {
+ b := bytes.NewBuffer(make([]byte, 0, size))
+
+ for {
+ if size == 0 {
+ break
+ }
+
+ bp.CX.AsUInt32().High = messageTypeReceivePayload
+ bp.BX.AsUInt32().Low = messageStatusSuccess
+
+ out = bp.InOut()
+ if (out.CX.AsUInt32().High & messageStatusSuccess) == 0 {
+ if (out.CX.AsUInt32().High & messageStatusCheckPoint) != 0 {
+ Debugf("A checkpoint occurred. Retrying the operation")
+ goto retry
+ }
+
+ Errorf("Message: Unable to receive a message over the communication channel %d", c.id)
+ c.reply(messageTypeReceivePayload, messageStatusFail)
+ return nil, ErrRpciReceive
+ }
+
+ if out.DX.AsUInt32().High != messageTypeSendPayload {
+ Errorf("Message: Protocol error. Expected a MESSAGE_TYPE_SENDPAYLOAD from vmware")
+ c.reply(messageTypeReceivePayload, messageStatusFail)
+ return nil, ErrRpciReceive
+ }
+
+ Debugf("Received %#v", out.BX.AsUInt32().Word())
+
+ switch size {
+ case 1:
+ err = binary.Write(b, binary.LittleEndian, uint8(out.BX.AsUInt32().Low))
+ size = size - 1
+
+ case 2:
+ err = binary.Write(b, binary.LittleEndian, uint16(out.BX.AsUInt32().Low))
+ size = size - 2
+
+ case 3:
+ err = binary.Write(b, binary.LittleEndian, uint16(out.BX.AsUInt32().Low))
+ if err != nil {
+ c.reply(messageTypeReceivePayload, messageStatusFail)
+ return nil, ErrRpciReceive
+ }
+ err = binary.Write(b, binary.LittleEndian, uint8(out.BX.AsUInt32().High))
+ size = size - 3
+
+ default:
+ err = binary.Write(b, binary.LittleEndian, out.BX.AsUInt32().Word())
+ size = size - 4
+ }
+
+ if err != nil {
+ Errorf(err.Error())
+ c.reply(messageTypeReceivePayload, messageStatusFail)
+ return nil, ErrRpciReceive
+ }
+ }
+
+ buf = b.Bytes()
+ }
+ }
+
+ c.reply(messageTypeReceiveStatus, messageStatusSuccess)
+
+ return buf, nil
+}
+
+func (c *Channel) reply(messageType, messageStatus uint16) {
+ bp := &bdoor.BackdoorProto{}
+
+ bp.BX.AsUInt32().Low = messageStatus
+ bp.CX.AsUInt32().High = messageType
+ bp.CX.AsUInt32().Low = bdoor.CommandMessage
+ bp.DX.AsUInt32().High = c.id
+ bp.SI.AsUInt32().SetWord(c.cookie.High.Word())
+ bp.DI.AsUInt32().SetWord(c.cookie.Low.Word())
+
+ out := bp.InOut()
+
+ /* OUT: Status */
+ if (out.CX.AsUInt32().High & messageStatusSuccess) == 0 {
+ if messageStatus == messageStatusSuccess {
+ Errorf("reply Message: Unable to send a message over the communication channel %d", c.id)
+ } else {
+ Errorf("reply Message: Unable to signal an error of reception over the communication channel %d", c.id)
+ }
+ }
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/rpcout/rpcout.go b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/rpcout/rpcout.go
new file mode 100644
index 00000000..3b5879b4
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/rpcout/rpcout.go
@@ -0,0 +1,93 @@
+// Copyright 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 rpcout
+
+import (
+ "errors"
+ "fmt"
+
+ "github.com/vmware/vmw-guestinfo/message"
+)
+
+// ErrRpciFormat represents an invalid result format
+var ErrRpciFormat = errors.New("invalid format for RPCI command result")
+
+const rpciProtocolNum uint32 = 0x49435052
+
+// SendOne is a command-oriented wrapper for SendOneRaw
+func SendOne(format string, a ...interface{}) (reply []byte, ok bool, err error) {
+ request := fmt.Sprintf(format, a...)
+ return SendOneRaw([]byte(request))
+}
+
+// SendOneRaw uses a throw-away RPCOut to send a request
+func SendOneRaw(request []byte) (reply []byte, ok bool, err error) {
+ out := &RPCOut{}
+ if err = out.Start(); err != nil {
+ return
+ }
+ if reply, ok, err = out.Send(request); err != nil {
+ return
+ }
+ if err = out.Stop(); err != nil {
+ return
+ }
+ return
+}
+
+// RPCOut is an ougoing connection from the VM to the hypervisor
+type RPCOut struct {
+ channel *message.Channel
+}
+
+// Start opens the connection
+func (out *RPCOut) Start() error {
+ channel, err := message.NewChannel(rpciProtocolNum)
+ if err != nil {
+ return err
+ }
+ out.channel = channel
+ return nil
+}
+
+// Stop closes the connection
+func (out *RPCOut) Stop() error {
+ err := out.channel.Close()
+ out.channel = nil
+ return err
+}
+
+// Send emits a request and receives a response
+func (out *RPCOut) Send(request []byte) (reply []byte, ok bool, err error) {
+ if err = out.channel.Send(request); err != nil {
+ return
+ }
+
+ var resp []byte
+ if resp, err = out.channel.Receive(); err != nil {
+ return
+ }
+
+ switch string(resp[:2]) {
+ case "0 ":
+ reply = resp[2:]
+ case "1 ":
+ reply = resp[2:]
+ ok = true
+ default:
+ err = ErrRpciFormat
+ }
+ return
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/rpcvmx/rpcvmx.go b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/rpcvmx/rpcvmx.go
new file mode 100644
index 00000000..a832ad7f
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/rpcvmx/rpcvmx.go
@@ -0,0 +1,101 @@
+// Copyright 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 rpcvmx
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "github.com/vmware/vmw-guestinfo/rpcout"
+)
+
+const (
+ prefix = "guestinfo"
+)
+
+// Config gives access to the vmx config through the VMware backdoor
+type Config struct{}
+
+// NewConfig creates a new Config object
+func NewConfig() *Config {
+ return &Config{}
+}
+
+// String returns the config string in the guestinfo.* namespace
+func (c *Config) String(key string, defaultValue string) (string, error) {
+ // add "guestinfo." prefix if missing
+ if !strings.HasPrefix(key, prefix) {
+ key = fmt.Sprintf("%s.%s", prefix, key)
+ }
+
+ out, ok, err := rpcout.SendOne("info-get %s", key)
+ if err != nil {
+ return "", err
+ } else if !ok {
+ return defaultValue, nil
+ }
+ return string(out), nil
+}
+
+// Bool returns the config boolean in the guestinfo.* namespace
+func (c *Config) Bool(key string, defaultValue bool) (bool, error) {
+ val, err := c.String(key, fmt.Sprintf("%t", defaultValue))
+ if err != nil {
+ return false, err
+ }
+ res, err := strconv.ParseBool(val)
+ if err != nil {
+ return defaultValue, nil
+ }
+ return res, nil
+}
+
+// Int returns the config integer in the guestinfo.* namespace
+func (c *Config) Int(key string, defaultValue int) (int, error) {
+ val, err := c.String(key, "")
+ if err != nil {
+ return 0, err
+ }
+ res, err := strconv.Atoi(val)
+ if err != nil {
+ return defaultValue, nil
+ }
+ return res, nil
+}
+
+// SetString sets the guestinfo.KEY with the string VALUE
+func (c *Config) SetString(key string, value string) error {
+ // add "guestinfo." prefix if missing
+ if !strings.HasPrefix(key, prefix) {
+ key = fmt.Sprintf("%s.%s", prefix, key)
+ }
+
+ _, _, err := rpcout.SendOne("info-set %s %s", key, value)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// SetString sets the guestinfo.KEY with the bool VALUE
+func (c *Config) SetBool(key string, value bool) error {
+ return c.SetString(key, strconv.FormatBool(value))
+}
+
+// SetString sets the guestinfo.KEY with the int VALUE
+func (c *Config) SetInt(key string, value int) error {
+ return c.SetString(key, strconv.Itoa(value))
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/util/util.go b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/util/util.go
new file mode 100644
index 00000000..7445c0b3
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/util/util.go
@@ -0,0 +1,58 @@
+// Copyright 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 util
+
+import (
+ "reflect"
+ "runtime"
+ "testing"
+)
+
+// Test utilities.
+
+func AssertEqual(t *testing.T, a interface{}, b interface{}) bool {
+ if !reflect.DeepEqual(a, b) {
+ Fail(t)
+ return false
+ }
+
+ return true
+}
+
+func AssertNoError(t *testing.T, err error) bool {
+ if err != nil {
+ t.Logf("error :%s", err.Error())
+ Fail(t)
+ return false
+ }
+
+ return true
+}
+
+func AssertNotNil(t *testing.T, a interface{}) bool {
+ val := reflect.ValueOf(a)
+ if val.IsNil() {
+ Fail(t)
+ return false
+ }
+
+ return true
+}
+
+func Fail(t *testing.T) {
+ _, file, line, _ := runtime.Caller(2)
+ t.Logf("FAIL on %s:%d", file, line)
+ t.Fail()
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/vmcheck/vmcheck.go b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/vmcheck/vmcheck.go
new file mode 100644
index 00000000..c46cc5e4
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/vmcheck/vmcheck.go
@@ -0,0 +1,83 @@
+// Copyright 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 vmcheck
+
+import (
+ "encoding/binary"
+
+ "github.com/vmware/vmw-guestinfo/bdoor"
+)
+
+// From https://github.com/intel-go/cpuid/blob/master/cpuidlow_amd64.s
+// Get the CPU ID low level leaf values.
+func cpuid_low(arg1, arg2 uint32) (eax, ebx, ecx, edx uint32)
+
+// IsVirtualWorld returns true if running in a VM and the backdoor is available.
+func IsVirtualWorld() (bool, error) {
+ // Test the HV bit is set
+ if !IsVirtualCPU() {
+ return false, nil
+ }
+
+ // Test if backdoor port is available.
+ if isVM, err := hypervisorPortCheck(); err != nil || !isVM {
+ return isVM, err
+ }
+
+ return true, nil
+}
+
+// hypervisorPortCheck tests the availability of the HV port.
+func hypervisorPortCheck() (bool, error) {
+ // Privilege level 3 to access all ports above 0x3ff
+ if err := openPortsAccess(); err != nil {
+ return false, err
+ }
+
+ p := &bdoor.BackdoorProto{}
+
+ p.CX.AsUInt32().SetWord(bdoor.CommandGetVersion)
+ out := p.InOut()
+ // if there is no device, we get back all 1s
+ return (0xffffffff != out.AX.AsUInt32().Word()) && (0 != out.AX.AsUInt32().Word()), nil
+}
+
+// IsVirtualCPU checks if the cpu is a virtual CPU running on ESX. It checks for
+// the HV bit in the ECX register of the CPUID leaf 0x1. Intel and AMD CPUs
+// reserve this bit to indicate if the CPU is running in a HV. See
+// https://en.wikipedia.org/wiki/CPUID#EAX.3D1:_Processor_Info_and_Feature_Bits
+// for details. If this bit is set, the reserved cpuid levels are used to pass
+// information from the HV to the guest. In ESX, this is the repeating string
+// "VMwareVMware".
+func IsVirtualCPU() bool {
+ HV := uint32(1 << 31)
+ _, _, c, _ := cpuid_low(0x1, 0)
+ if (c & HV) != HV {
+ return false
+ }
+
+ _, b, c, d := cpuid_low(0x40000000, 0)
+
+ buf := make([]byte, 12)
+ binary.LittleEndian.PutUint32(buf, b)
+ binary.LittleEndian.PutUint32(buf[4:], c)
+ binary.LittleEndian.PutUint32(buf[8:], d)
+
+ if string(buf) != "VMwareVMware" {
+ return false
+ }
+
+ return true
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/vmcheck/vmcheck_386.s b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/vmcheck/vmcheck_386.s
new file mode 100644
index 00000000..c029ece2
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/vmcheck/vmcheck_386.s
@@ -0,0 +1,13 @@
+#include "textflag.h"
+
+// From https://github.com/intel-go/cpuid/blob/master/cpuidlow_amd64.s
+// func cpuid_low(arg1, arg2 uint32) (eax, ebx, ecx, edx uint32)
+TEXT ·cpuid_low(SB), NOSPLIT, $0-24
+ MOVL arg1+0(FP), AX
+ MOVL arg2+4(FP), CX
+ CPUID
+ MOVL AX, eax+8(FP)
+ MOVL BX, ebx+12(FP)
+ MOVL CX, ecx+16(FP)
+ MOVL DX, edx+20(FP)
+ RET
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/vmcheck/vmcheck_amd64.s b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/vmcheck/vmcheck_amd64.s
new file mode 100644
index 00000000..c029ece2
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/vmcheck/vmcheck_amd64.s
@@ -0,0 +1,13 @@
+#include "textflag.h"
+
+// From https://github.com/intel-go/cpuid/blob/master/cpuidlow_amd64.s
+// func cpuid_low(arg1, arg2 uint32) (eax, ebx, ecx, edx uint32)
+TEXT ·cpuid_low(SB), NOSPLIT, $0-24
+ MOVL arg1+0(FP), AX
+ MOVL arg2+4(FP), CX
+ CPUID
+ MOVL AX, eax+8(FP)
+ MOVL BX, ebx+12(FP)
+ MOVL CX, ecx+16(FP)
+ MOVL DX, edx+20(FP)
+ RET
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/vmcheck/vmcheck_general.go b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/vmcheck/vmcheck_general.go
new file mode 100644
index 00000000..1e9217c9
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/vmcheck/vmcheck_general.go
@@ -0,0 +1,23 @@
+// Copyright 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.
+
+// +build !linux
+
+package vmcheck
+
+// probably not gonna work. Instead, implement a platform-specific variant, and
+// add the platform to above build flags
+func openPortsAccess() error {
+ return nil
+}
diff --git a/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/vmcheck/vmcheck_linux.go b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/vmcheck/vmcheck_linux.go
new file mode 100644
index 00000000..46460f9a
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vendor/github.com/vmware/vmw-guestinfo/vmcheck/vmcheck_linux.go
@@ -0,0 +1,22 @@
+// Copyright 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 vmcheck
+
+import "syscall"
+
+func openPortsAccess() error {
+ // Privilege level 3 to access all ports above 0x3ff
+ return syscall.Iopl(3)
+}
diff --git a/vendor/github.com/vmware/govmomi/view/container_view.go b/vendor/github.com/vmware/govmomi/view/container_view.go
new file mode 100644
index 00000000..0e3268b8
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/view/container_view.go
@@ -0,0 +1,130 @@
+/*
+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 view
+
+import (
+ "context"
+
+ "github.com/vmware/govmomi/property"
+ "github.com/vmware/govmomi/vim25"
+ "github.com/vmware/govmomi/vim25/mo"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type ContainerView struct {
+ ManagedObjectView
+}
+
+func NewContainerView(c *vim25.Client, ref types.ManagedObjectReference) *ContainerView {
+ return &ContainerView{
+ ManagedObjectView: *NewManagedObjectView(c, ref),
+ }
+}
+
+// Retrieve populates dst as property.Collector.Retrieve does, for all entities in the view of types specified by kind.
+func (v ContainerView) Retrieve(ctx context.Context, kind []string, ps []string, dst interface{}) error {
+ pc := property.DefaultCollector(v.Client())
+
+ ospec := types.ObjectSpec{
+ Obj: v.Reference(),
+ Skip: types.NewBool(true),
+ SelectSet: []types.BaseSelectionSpec{
+ &types.TraversalSpec{
+ Type: v.Reference().Type,
+ Path: "view",
+ },
+ },
+ }
+
+ var pspec []types.PropertySpec
+
+ if len(kind) == 0 {
+ kind = []string{"ManagedEntity"}
+ }
+
+ for _, t := range kind {
+ spec := types.PropertySpec{
+ Type: t,
+ }
+
+ if len(ps) == 0 {
+ spec.All = types.NewBool(true)
+ } else {
+ spec.PathSet = ps
+ }
+
+ pspec = append(pspec, spec)
+ }
+
+ req := types.RetrieveProperties{
+ SpecSet: []types.PropertyFilterSpec{
+ {
+ ObjectSet: []types.ObjectSpec{ospec},
+ PropSet: pspec,
+ },
+ },
+ }
+
+ res, err := pc.RetrieveProperties(ctx, req)
+ if err != nil {
+ return err
+ }
+
+ if d, ok := dst.(*[]types.ObjectContent); ok {
+ *d = res.Returnval
+ return nil
+ }
+
+ return mo.LoadRetrievePropertiesResponse(res, dst)
+}
+
+// RetrieveWithFilter populates dst as Retrieve does, but only for entities matching the given filter.
+func (v ContainerView) RetrieveWithFilter(ctx context.Context, kind []string, ps []string, dst interface{}, filter property.Filter) error {
+ if len(filter) == 0 {
+ return v.Retrieve(ctx, kind, ps, dst)
+ }
+
+ var content []types.ObjectContent
+
+ err := v.Retrieve(ctx, kind, filter.Keys(), &content)
+ if err != nil {
+ return err
+ }
+
+ objs := filter.MatchObjectContent(content)
+
+ pc := property.DefaultCollector(v.Client())
+
+ return pc.Retrieve(ctx, objs, ps, dst)
+}
+
+// Find returns object references for entities of type kind, matching the given filter.
+func (v ContainerView) Find(ctx context.Context, kind []string, filter property.Filter) ([]types.ManagedObjectReference, error) {
+ if len(filter) == 0 {
+ // Ensure we have at least 1 filter to avoid retrieving all properties.
+ filter = property.Filter{"name": "*"}
+ }
+
+ var content []types.ObjectContent
+
+ err := v.Retrieve(ctx, kind, filter.Keys(), &content)
+ if err != nil {
+ return nil, err
+ }
+
+ return filter.MatchObjectContent(content), nil
+}
diff --git a/vendor/github.com/vmware/govmomi/view/list_view.go b/vendor/github.com/vmware/govmomi/view/list_view.go
index 145d4dc5..e8cfb504 100644
--- a/vendor/github.com/vmware/govmomi/view/list_view.go
+++ b/vendor/github.com/vmware/govmomi/view/list_view.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2015 VMware, Inc. All Rights Reserved.
+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.
@@ -17,17 +17,46 @@ limitations under the License.
package view
import (
- "github.com/vmware/govmomi/object"
+ "context"
+
"github.com/vmware/govmomi/vim25"
+ "github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type ListView struct {
- *object.ListView
+ ManagedObjectView
}
func NewListView(c *vim25.Client, ref types.ManagedObjectReference) *ListView {
return &ListView{
- ListView: object.NewListView(c, ref),
+ ManagedObjectView: *NewManagedObjectView(c, ref),
+ }
+}
+
+func (v ListView) Add(ctx context.Context, refs []types.ManagedObjectReference) error {
+ req := types.ModifyListView{
+ This: v.Reference(),
+ Add: refs,
+ }
+ _, err := methods.ModifyListView(ctx, v.Client(), &req)
+ return err
+}
+
+func (v ListView) Remove(ctx context.Context, refs []types.ManagedObjectReference) error {
+ req := types.ModifyListView{
+ This: v.Reference(),
+ Remove: refs,
+ }
+ _, err := methods.ModifyListView(ctx, v.Client(), &req)
+ return err
+}
+
+func (v ListView) Reset(ctx context.Context, refs []types.ManagedObjectReference) error {
+ req := types.ResetListView{
+ This: v.Reference(),
+ Obj: refs,
}
+ _, err := methods.ResetListView(ctx, v.Client(), &req)
+ return err
}
diff --git a/vendor/github.com/vmware/govmomi/view/managed_object_view.go b/vendor/github.com/vmware/govmomi/view/managed_object_view.go
new file mode 100644
index 00000000..805c8643
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/view/managed_object_view.go
@@ -0,0 +1,52 @@
+/*
+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 view
+
+import (
+ "context"
+
+ "github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/vim25"
+ "github.com/vmware/govmomi/vim25/methods"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+type ManagedObjectView struct {
+ object.Common
+}
+
+func NewManagedObjectView(c *vim25.Client, ref types.ManagedObjectReference) *ManagedObjectView {
+ return &ManagedObjectView{
+ Common: object.NewCommon(c, ref),
+ }
+}
+
+func (v *ManagedObjectView) TraversalSpec() *types.TraversalSpec {
+ return &types.TraversalSpec{
+ Path: "view",
+ Type: v.Reference().Type,
+ }
+}
+
+func (v *ManagedObjectView) Destroy(ctx context.Context) error {
+ req := types.DestroyView{
+ This: v.Reference(),
+ }
+
+ _, err := methods.DestroyView(ctx, v.Client(), &req)
+ return err
+}
diff --git a/vendor/github.com/vmware/govmomi/view/manager.go b/vendor/github.com/vmware/govmomi/view/manager.go
index 7a227eaa..d44def0c 100644
--- a/vendor/github.com/vmware/govmomi/view/manager.go
+++ b/vendor/github.com/vmware/govmomi/view/manager.go
@@ -50,3 +50,20 @@ func (m Manager) CreateListView(ctx context.Context, objects []types.ManagedObje
return NewListView(m.Client(), res.Returnval), nil
}
+
+func (m Manager) CreateContainerView(ctx context.Context, container types.ManagedObjectReference, managedObjectTypes []string, recursive bool) (*ContainerView, error) {
+
+ req := types.CreateContainerView{
+ This: m.Common.Reference(),
+ Container: container,
+ Recursive: recursive,
+ Type: managedObjectTypes,
+ }
+
+ res, err := methods.CreateContainerView(ctx, m.Client(), &req)
+ if err != nil {
+ return nil, err
+ }
+
+ return NewContainerView(m.Client(), res.Returnval), nil
+}
diff --git a/vendor/github.com/vmware/govmomi/view/task_view.go b/vendor/github.com/vmware/govmomi/view/task_view.go
new file mode 100644
index 00000000..68f62f8d
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/view/task_view.go
@@ -0,0 +1,125 @@
+/*
+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 view
+
+import (
+ "context"
+
+ "github.com/vmware/govmomi/property"
+ "github.com/vmware/govmomi/vim25/types"
+)
+
+// TaskView extends ListView such that it can follow a ManagedEntity's recentTask updates.
+type TaskView struct {
+ *ListView
+
+ Follow bool
+
+ Watch *types.ManagedObjectReference
+}
+
+// CreateTaskView creates a new ListView that optionally watches for a ManagedEntity's recentTask updates.
+func (m Manager) CreateTaskView(ctx context.Context, watch *types.ManagedObjectReference) (*TaskView, error) {
+ l, err := m.CreateListView(ctx, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ tv := &TaskView{
+ ListView: l,
+ Watch: watch,
+ }
+
+ return tv, nil
+}
+
+// Collect calls function f for each Task update.
+func (v TaskView) Collect(ctx context.Context, f func([]types.TaskInfo)) error {
+ // Using TaskHistoryCollector would be less clunky, but it isn't supported on ESX at all.
+ ref := v.Reference()
+ filter := new(property.WaitFilter).Add(ref, "Task", []string{"info"}, v.TraversalSpec())
+
+ if v.Watch != nil {
+ filter.Add(*v.Watch, v.Watch.Type, []string{"recentTask"})
+ }
+
+ pc := property.DefaultCollector(v.Client())
+
+ completed := make(map[string]bool)
+
+ return property.WaitForUpdates(ctx, pc, filter, func(updates []types.ObjectUpdate) bool {
+ var infos []types.TaskInfo
+ var prune []types.ManagedObjectReference
+ var tasks []types.ManagedObjectReference
+ var reset func()
+
+ for _, update := range updates {
+ for _, change := range update.ChangeSet {
+ if change.Name == "recentTask" {
+ tasks = change.Val.(types.ArrayOfManagedObjectReference).ManagedObjectReference
+ if len(tasks) != 0 {
+ reset = func() {
+ _ = v.Reset(ctx, tasks)
+
+ // Remember any tasks we've reported as complete already,
+ // to avoid reporting multiple times when Reset is triggered.
+ rtasks := make(map[string]bool)
+ for i := range tasks {
+ if _, ok := completed[tasks[i].Value]; ok {
+ rtasks[tasks[i].Value] = true
+ }
+ }
+ completed = rtasks
+ }
+ }
+
+ continue
+ }
+
+ info, ok := change.Val.(types.TaskInfo)
+ if !ok {
+ continue
+ }
+
+ if !completed[info.Task.Value] {
+ infos = append(infos, info)
+ }
+
+ if v.Follow && info.CompleteTime != nil {
+ prune = append(prune, info.Task)
+ completed[info.Task.Value] = true
+ }
+ }
+ }
+
+ if len(infos) != 0 {
+ f(infos)
+ }
+
+ if reset != nil {
+ reset()
+ } else if len(prune) != 0 {
+ _ = v.Remove(ctx, prune)
+ }
+
+ if len(tasks) != 0 && len(infos) == 0 {
+ return false
+ }
+
+ return !v.Follow
+ })
+}
diff --git a/vendor/github.com/vmware/govmomi/vim25/methods/methods.go b/vendor/github.com/vmware/govmomi/vim25/methods/methods.go
index 79c49435..0895a81c 100644
--- a/vendor/github.com/vmware/govmomi/vim25/methods/methods.go
+++ b/vendor/github.com/vmware/govmomi/vim25/methods/methods.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
+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.
diff --git a/vendor/github.com/vmware/govmomi/vim25/mo/ancestors.go b/vendor/github.com/vmware/govmomi/vim25/mo/ancestors.go
index 86a3a69f..d3da5b18 100644
--- a/vendor/github.com/vmware/govmomi/vim25/mo/ancestors.go
+++ b/vendor/github.com/vmware/govmomi/vim25/mo/ancestors.go
@@ -104,6 +104,8 @@ func Ancestors(ctx context.Context, rt soap.RoundTripper, pc, obj types.ManagedO
me.Name = x.Name
case DistributedVirtualPortgroup:
me.Name = x.Name
+ case OpaqueNetwork:
+ me.Name = x.Name
default:
// ManagedEntity always has a Name, if we hit this point we missed a case above.
panic(fmt.Sprintf("%#v Name is empty", me.Reference()))
diff --git a/vendor/github.com/vmware/govmomi/vim25/mo/mo.go b/vendor/github.com/vmware/govmomi/vim25/mo/mo.go
index 0764eb49..ede6e44d 100644
--- a/vendor/github.com/vmware/govmomi/vim25/mo/mo.go
+++ b/vendor/github.com/vmware/govmomi/vim25/mo/mo.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
+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.
@@ -150,6 +150,30 @@ func init() {
t["ContainerView"] = reflect.TypeOf((*ContainerView)(nil)).Elem()
}
+type CryptoManager struct {
+ Self types.ManagedObjectReference
+
+ Enabled bool `mo:"enabled"`
+}
+
+func (m CryptoManager) Reference() types.ManagedObjectReference {
+ return m.Self
+}
+
+func init() {
+ t["CryptoManager"] = reflect.TypeOf((*CryptoManager)(nil)).Elem()
+}
+
+type CryptoManagerKmip struct {
+ CryptoManager
+
+ KmipServers []types.KmipClusterInfo `mo:"kmipServers"`
+}
+
+func init() {
+ t["CryptoManagerKmip"] = reflect.TypeOf((*CryptoManagerKmip)(nil)).Elem()
+}
+
type CustomFieldsManager struct {
Self types.ManagedObjectReference
@@ -356,6 +380,34 @@ func init() {
t["ExtensionManager"] = reflect.TypeOf((*ExtensionManager)(nil)).Elem()
}
+type FailoverClusterConfigurator struct {
+ Self types.ManagedObjectReference
+
+ DisabledConfigureMethod []string `mo:"disabledConfigureMethod"`
+}
+
+func (m FailoverClusterConfigurator) Reference() types.ManagedObjectReference {
+ return m.Self
+}
+
+func init() {
+ t["FailoverClusterConfigurator"] = reflect.TypeOf((*FailoverClusterConfigurator)(nil)).Elem()
+}
+
+type FailoverClusterManager struct {
+ Self types.ManagedObjectReference
+
+ DisabledClusterMethod []string `mo:"disabledClusterMethod"`
+}
+
+func (m FailoverClusterManager) Reference() types.ManagedObjectReference {
+ return m.Self
+}
+
+func init() {
+ t["FailoverClusterManager"] = reflect.TypeOf((*FailoverClusterManager)(nil)).Elem()
+}
+
type FileManager struct {
Self types.ManagedObjectReference
}
@@ -461,6 +513,18 @@ func init() {
t["GuestWindowsRegistryManager"] = reflect.TypeOf((*GuestWindowsRegistryManager)(nil)).Elem()
}
+type HealthUpdateManager struct {
+ Self types.ManagedObjectReference
+}
+
+func (m HealthUpdateManager) Reference() types.ManagedObjectReference {
+ return m.Self
+}
+
+func init() {
+ t["HealthUpdateManager"] = reflect.TypeOf((*HealthUpdateManager)(nil)).Elem()
+}
+
type HistoryCollector struct {
Self types.ManagedObjectReference
@@ -695,8 +759,9 @@ func init() {
type HostGraphicsManager struct {
ExtensibleManagedObject
- GraphicsInfo []types.HostGraphicsInfo `mo:"graphicsInfo"`
- SharedPassthruGpuTypes []string `mo:"sharedPassthruGpuTypes"`
+ GraphicsInfo []types.HostGraphicsInfo `mo:"graphicsInfo"`
+ GraphicsConfig *types.HostGraphicsConfig `mo:"graphicsConfig"`
+ SharedPassthruGpuTypes []string `mo:"sharedPassthruGpuTypes"`
}
func init() {
@@ -803,7 +868,8 @@ func init() {
type HostPciPassthruSystem struct {
ExtensibleManagedObject
- PciPassthruInfo []types.BaseHostPciPassthruInfo `mo:"pciPassthruInfo"`
+ PciPassthruInfo []types.BaseHostPciPassthruInfo `mo:"pciPassthruInfo"`
+ SriovDevicePoolInfo []types.BaseHostSriovDevicePoolInfo `mo:"sriovDevicePoolInfo"`
}
func init() {
@@ -868,6 +934,18 @@ func init() {
t["HostSnmpSystem"] = reflect.TypeOf((*HostSnmpSystem)(nil)).Elem()
}
+type HostSpecificationManager struct {
+ Self types.ManagedObjectReference
+}
+
+func (m HostSpecificationManager) Reference() types.ManagedObjectReference {
+ return m.Self
+}
+
+func init() {
+ t["HostSpecificationManager"] = reflect.TypeOf((*HostSpecificationManager)(nil)).Elem()
+}
+
type HostStorageSystem struct {
ExtensibleManagedObject
@@ -931,6 +1009,14 @@ func init() {
t["HostVMotionSystem"] = reflect.TypeOf((*HostVMotionSystem)(nil)).Elem()
}
+type HostVStorageObjectManager struct {
+ VStorageObjectManagerBase
+}
+
+func init() {
+ t["HostVStorageObjectManager"] = reflect.TypeOf((*HostVStorageObjectManager)(nil)).Elem()
+}
+
type HostVirtualNicManager struct {
ExtensibleManagedObject
@@ -984,18 +1070,6 @@ func init() {
t["HttpNfcLease"] = reflect.TypeOf((*HttpNfcLease)(nil)).Elem()
}
-type InternalDynamicTypeManager struct {
- Self types.ManagedObjectReference
-}
-
-func (m InternalDynamicTypeManager) Reference() types.ManagedObjectReference {
- return m.Self
-}
-
-func init() {
- t["InternalDynamicTypeManager"] = reflect.TypeOf((*InternalDynamicTypeManager)(nil)).Elem()
-}
-
type InventoryView struct {
ManagedObjectView
}
@@ -1163,6 +1237,9 @@ func init() {
type OpaqueNetwork struct {
Network
+
+ Capability *types.OpaqueNetworkCapability `mo:"capability"`
+ ExtraConfig []types.BaseOptionValue `mo:"extraConfig"`
}
func init() {
@@ -1302,18 +1379,6 @@ func init() {
t["PropertyFilter"] = reflect.TypeOf((*PropertyFilter)(nil)).Elem()
}
-type ReflectManagedMethodExecuter struct {
- Self types.ManagedObjectReference
-}
-
-func (m ReflectManagedMethodExecuter) Reference() types.ManagedObjectReference {
- return m.Self
-}
-
-func init() {
- t["ReflectManagedMethodExecuter"] = reflect.TypeOf((*ReflectManagedMethodExecuter)(nil)).Elem()
-}
-
type ResourcePlanningManager struct {
Self types.ManagedObjectReference
}
@@ -1520,6 +1585,26 @@ func init() {
t["UserDirectory"] = reflect.TypeOf((*UserDirectory)(nil)).Elem()
}
+type VStorageObjectManagerBase struct {
+ Self types.ManagedObjectReference
+}
+
+func (m VStorageObjectManagerBase) Reference() types.ManagedObjectReference {
+ return m.Self
+}
+
+func init() {
+ t["VStorageObjectManagerBase"] = reflect.TypeOf((*VStorageObjectManagerBase)(nil)).Elem()
+}
+
+type VcenterVStorageObjectManager struct {
+ VStorageObjectManagerBase
+}
+
+func init() {
+ t["VcenterVStorageObjectManager"] = reflect.TypeOf((*VcenterVStorageObjectManager)(nil)).Elem()
+}
+
type View struct {
Self types.ManagedObjectReference
}
diff --git a/vendor/github.com/vmware/govmomi/vim25/soap/client.go b/vendor/github.com/vmware/govmomi/vim25/soap/client.go
index e89ffc81..8747e07b 100644
--- a/vendor/github.com/vmware/govmomi/vim25/soap/client.go
+++ b/vendor/github.com/vmware/govmomi/vim25/soap/client.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
+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.
@@ -58,6 +58,10 @@ const (
DefaultMinVimVersion = "5.5"
)
+type header struct {
+ Cookie string `xml:"vcSessionCookie,omitempty"`
+}
+
type Client struct {
http.Client
@@ -73,6 +77,8 @@ type Client struct {
Namespace string // Vim namespace
Version string // Vim version
UserAgent string
+
+ header *header
}
var schemeMatch = regexp.MustCompile(`^\w+://`)
@@ -147,6 +153,32 @@ func NewClient(u *url.URL, insecure bool) *Client {
return &c
}
+// NewServiceClient creates a NewClient with the given URL.Path and namespace.
+func (c *Client) NewServiceClient(path string, namespace string) *Client {
+ u := c.URL()
+ u.Path = path
+
+ client := NewClient(u, c.k)
+
+ client.Namespace = namespace
+
+ // Copy the cookies
+ client.Client.Jar.SetCookies(u, c.Client.Jar.Cookies(u))
+
+ // Set SOAP Header cookie
+ for _, cookie := range client.Jar.Cookies(u) {
+ if cookie.Name == "vmware_soap_session" {
+ client.header = &header{
+ Cookie: cookie.Value,
+ }
+
+ break
+ }
+ }
+
+ return client
+}
+
// SetRootCAs defines the set of root certificate authorities
// that clients use when verifying server certificates.
// By default TLS uses the host's root CA set.
@@ -401,6 +433,8 @@ func (c *Client) RoundTrip(ctx context.Context, reqBody, resBody HasFault) error
reqEnv := Envelope{Body: reqBody}
resEnv := Envelope{Body: resBody}
+ reqEnv.Header = c.header
+
// Create debugging context for this round trip
d := c.d.newRoundTrip()
if d.enabled() {
@@ -621,33 +655,24 @@ func (c *Client) Download(u *url.URL, param *Download) (io.ReadCloser, int64, er
return nil, 0, err
}
- return res.Body, res.ContentLength, nil
+ r := res.Body
+
+ return r, res.ContentLength, nil
}
-// DownloadFile GETs the given URL to a local file
-func (c *Client) DownloadFile(file string, u *url.URL, param *Download) error {
+func (c *Client) WriteFile(file string, src io.Reader, size int64, s progress.Sinker) error {
var err error
- if param == nil {
- param = &DefaultDownload
- }
- rc, contentLength, err := c.Download(u, param)
- if err != nil {
- return err
- }
- defer rc.Close()
-
- var r io.Reader = rc
+ r := src
fh, err := os.Create(file)
if err != nil {
return err
}
- defer fh.Close()
- if param.Progress != nil {
- pr := progress.NewReader(param.Progress, r, contentLength)
- r = pr
+ if s != nil {
+ pr := progress.NewReader(s, src, size)
+ src = pr
// Mark progress reader as done when returning from this function.
defer func() {
@@ -656,16 +681,27 @@ func (c *Client) DownloadFile(file string, u *url.URL, param *Download) error {
}
_, err = io.Copy(fh, r)
- if err != nil {
- return err
+
+ cerr := fh.Close()
+
+ if err == nil {
+ err = cerr
}
- // Assign error before returning so that it gets picked up by the deferred
- // function marking the progress reader as done.
- err = fh.Close()
+ return err
+}
+
+// DownloadFile GETs the given URL to a local file
+func (c *Client) DownloadFile(file string, u *url.URL, param *Download) error {
+ var err error
+ if param == nil {
+ param = &DefaultDownload
+ }
+
+ rc, contentLength, err := c.Download(u, param)
if err != nil {
return err
}
- return nil
+ return c.WriteFile(file, rc, contentLength, param.Progress)
}
diff --git a/vendor/github.com/vmware/govmomi/vim25/soap/error.go b/vendor/github.com/vmware/govmomi/vim25/soap/error.go
index 0408e7bf..d8920852 100644
--- a/vendor/github.com/vmware/govmomi/vim25/soap/error.go
+++ b/vendor/github.com/vmware/govmomi/vim25/soap/error.go
@@ -36,7 +36,13 @@ type soapFaultError struct {
}
func (s soapFaultError) Error() string {
- return fmt.Sprintf("%s: %s", s.fault.Code, s.fault.String)
+ msg := s.fault.String
+
+ if msg == "" {
+ msg = reflect.TypeOf(s.fault.Detail.Fault).Name()
+ }
+
+ return fmt.Sprintf("%s: %s", s.fault.Code, msg)
}
type vimFaultError struct {
diff --git a/vendor/github.com/vmware/govmomi/vim25/soap/soap.go b/vendor/github.com/vmware/govmomi/vim25/soap/soap.go
index ea35e77a..a8baa012 100644
--- a/vendor/github.com/vmware/govmomi/vim25/soap/soap.go
+++ b/vendor/github.com/vmware/govmomi/vim25/soap/soap.go
@@ -22,15 +22,11 @@ import (
)
type Envelope struct {
- XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"`
- Header *Header `xml:",omitempty"`
+ XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"`
+ Header interface{} `xml:",omitempty"`
Body interface{}
}
-type Header struct {
- XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Header"`
-}
-
type Fault struct {
XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault"`
Code string `xml:"faultcode"`
diff --git a/vendor/github.com/vmware/govmomi/vim25/types/enum.go b/vendor/github.com/vmware/govmomi/vim25/types/enum.go
index 1db935ef..02f7f3cb 100644
--- a/vendor/github.com/vmware/govmomi/vim25/types/enum.go
+++ b/vendor/github.com/vmware/govmomi/vim25/types/enum.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
+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.
diff --git a/vendor/github.com/vmware/govmomi/vim25/types/helpers.go b/vendor/github.com/vmware/govmomi/vim25/types/helpers.go
index 7b72358b..2364ed42 100644
--- a/vendor/github.com/vmware/govmomi/vim25/types/helpers.go
+++ b/vendor/github.com/vmware/govmomi/vim25/types/helpers.go
@@ -46,3 +46,7 @@ func (r *ManagedObjectReference) FromString(o string) bool {
return true
}
+
+func (c *PerfCounterInfo) Name() string {
+ return c.GroupInfo.GetElementDescription().Key + "." + c.NameInfo.GetElementDescription().Key + "." + string(c.RollupType)
+}
diff --git a/vendor/github.com/vmware/govmomi/vim25/types/if.go b/vendor/github.com/vmware/govmomi/vim25/types/if.go
index 5ae275c6..dbf594cf 100644
--- a/vendor/github.com/vmware/govmomi/vim25/types/if.go
+++ b/vendor/github.com/vmware/govmomi/vim25/types/if.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
+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.
diff --git a/vendor/github.com/vmware/govmomi/vim25/types/registry.go b/vendor/github.com/vmware/govmomi/vim25/types/registry.go
index 8f238088..ff7c302d 100644
--- a/vendor/github.com/vmware/govmomi/vim25/types/registry.go
+++ b/vendor/github.com/vmware/govmomi/vim25/types/registry.go
@@ -16,15 +16,28 @@ limitations under the License.
package types
-import "reflect"
+import (
+ "reflect"
+ "strings"
+)
var t = map[string]reflect.Type{}
+func Add(name string, kind reflect.Type) {
+ t[name] = kind
+}
+
type Func func(string) (reflect.Type, bool)
func TypeFunc() Func {
return func(name string) (reflect.Type, bool) {
typ, ok := t[name]
+ if !ok {
+ // The /sdk endpoint does not prefix types with the namespace,
+ // but extension endpoints, such as /pbm/sdk do.
+ name = strings.TrimPrefix(name, "vim25:")
+ typ, ok = t[name]
+ }
return typ, ok
}
}
diff --git a/vendor/github.com/vmware/govmomi/vim25/types/types.go b/vendor/github.com/vmware/govmomi/vim25/types/types.go
index ffb4606c..cb703582 100644
--- a/vendor/github.com/vmware/govmomi/vim25/types/types.go
+++ b/vendor/github.com/vmware/govmomi/vim25/types/types.go
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
+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.
@@ -18341,9 +18341,9 @@ func init() {
type GuestPosixFileAttributes struct {
GuestFileAttributes
- OwnerId int32 `xml:"ownerId,omitempty"`
- GroupId int32 `xml:"groupId,omitempty"`
- Permissions int64 `xml:"permissions,omitempty"`
+ OwnerId *int32 `xml:"ownerId"`
+ GroupId *int32 `xml:"groupId"`
+ Permissions int64 `xml:"permissions,omitempty"`
}
func init() {
@@ -28546,7 +28546,7 @@ func init() {
type MethodActionArgument struct {
DynamicData
- Value AnyType `xml:"value,omitempty,typeattr"`
+ Value AnyType `xml:"value,typeattr"`
}
func init() {
@@ -31074,7 +31074,7 @@ type OptionValue struct {
DynamicData
Key string `xml:"key"`
- Value AnyType `xml:"value,omitempty,typeattr"`
+ Value AnyType `xml:"value,typeattr"`
}
func init() {
@@ -53154,8 +53154,8 @@ type WaitForUpdatesResponse struct {
type WaitOptions struct {
DynamicData
- MaxWaitSeconds int32 `xml:"maxWaitSeconds,omitempty"`
- MaxObjectUpdates int32 `xml:"maxObjectUpdates,omitempty"`
+ MaxWaitSeconds *int32 `xml:"maxWaitSeconds"`
+ MaxObjectUpdates int32 `xml:"maxObjectUpdates,omitempty"`
}
func init() {
diff --git a/vendor/github.com/vmware/govmomi/vim25/xml/extras.go b/vendor/github.com/vmware/govmomi/vim25/xml/extras.go
index 3b7f44b0..9a15b7c8 100644
--- a/vendor/github.com/vmware/govmomi/vim25/xml/extras.go
+++ b/vendor/github.com/vmware/govmomi/vim25/xml/extras.go
@@ -23,6 +23,8 @@ import (
var xmlSchemaInstance = Name{Space: "http://www.w3.org/2001/XMLSchema-instance", Local: "type"}
+var xsiType = Name{Space: "xsi", Local: "type"}
+
var stringToTypeMap = map[string]reflect.Type{
"xsd:boolean": reflect.TypeOf((*bool)(nil)).Elem(),
"xsd:byte": reflect.TypeOf((*int8)(nil)).Elem(),
diff --git a/vendor/github.com/vmware/govmomi/vim25/xml/read.go b/vendor/github.com/vmware/govmomi/vim25/xml/read.go
index 5b407b79..fe35fce6 100644
--- a/vendor/github.com/vmware/govmomi/vim25/xml/read.go
+++ b/vendor/github.com/vmware/govmomi/vim25/xml/read.go
@@ -272,13 +272,15 @@ var (
func (p *Decoder) typeForElement(val reflect.Value, start *StartElement) reflect.Type {
t := ""
for i, a := range start.Attr {
- if a.Name == xmlSchemaInstance {
+ if a.Name == xmlSchemaInstance || a.Name == xsiType {
t = a.Value
// HACK: ensure xsi:type is last in the list to avoid using that value for
// a "type" attribute, such as ManagedObjectReference.Type for example.
// Note that xsi:type is already the last attribute in VC/ESX responses.
// This is only an issue with govmomi simulator generated responses.
// Proper fix will require finding a few needles in this xml package haystack.
+ // Note: govmomi uses xmlSchemaInstance, other clients (e.g. rbvmomi) use xsiType.
+ // They are the same thing to XML parsers, but not to this hack here.
x := len(start.Attr) - 1
if i != x {
start.Attr[i] = start.Attr[x]
diff --git a/vendor/github.com/vmware/govmomi/vmdk/import.go b/vendor/github.com/vmware/govmomi/vmdk/import.go
new file mode 100644
index 00000000..64301f0d
--- /dev/null
+++ b/vendor/github.com/vmware/govmomi/vmdk/import.go
@@ -0,0 +1,335 @@
+/*
+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(name)
+ if err != nil {
+ return nil, err
+ }
+
+ var di info
+
+ var buf bytes.Buffer
+
+ _, err = io.CopyN(&buf, f, int64(binary.Size(di.Header)))
+
+ fi, _ := f.Stat()
+
+ _ = 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 = `
+
+
+
+
+
+ Virtual disk information
+
+
+
+ A virtual machine
+ {{ .ImportName }}
+
+ The kind of installed guest operating system
+
+
+ Virtual hardware requirements
+
+ Virtual Hardware Family
+ 0
+ {{ .ImportName }}
+ vmx-07
+
+ -
+ hertz * 10^6
+ Number of Virtual CPUs
+ 1 virtual CPU(s)
+ 1
+ 3
+ 1
+
+ -
+ byte * 2^20
+ Memory Size
+ 1024MB of memory
+ 2
+ 4
+ 1024
+
+ -
+ 0
+ SCSI Controller
+ SCSI Controller 0
+ 3
+ VirtualSCSI
+ 6
+
+ -
+ 0
+ Hard Disk 1
+ ovf:/disk/vmdisk1
+ 9
+ 3
+ 17
+
+
+
+
+`
+
+// 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(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)
+
+ _ = 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)
+}
diff --git a/vendor/golang.org/x/crypto/ssh/agent/client.go b/vendor/golang.org/x/crypto/ssh/agent/client.go
index ecfd7c58..dce7682f 100644
--- a/vendor/golang.org/x/crypto/ssh/agent/client.go
+++ b/vendor/golang.org/x/crypto/ssh/agent/client.go
@@ -57,6 +57,17 @@ type Agent interface {
Signers() ([]ssh.Signer, error)
}
+// ConstraintExtension describes an optional constraint defined by users.
+type ConstraintExtension struct {
+ // ExtensionName consist of a UTF-8 string suffixed by the
+ // implementation domain following the naming scheme defined
+ // in Section 4.2 of [RFC4251], e.g. "foo@example.com".
+ ExtensionName string
+ // ExtensionDetails contains the actual content of the extended
+ // constraint.
+ ExtensionDetails []byte
+}
+
// AddedKey describes an SSH key to be added to an Agent.
type AddedKey struct {
// PrivateKey must be a *rsa.PrivateKey, *dsa.PrivateKey or
@@ -73,6 +84,9 @@ type AddedKey struct {
// ConfirmBeforeUse, if true, requests that the agent confirm with the
// user before each use of this key.
ConfirmBeforeUse bool
+ // ConstraintExtensions are the experimental or private-use constraints
+ // defined by users.
+ ConstraintExtensions []ConstraintExtension
}
// See [PROTOCOL.agent], section 3.
@@ -94,8 +108,9 @@ const (
agentAddSmartcardKeyConstrained = 26
// 3.7 Key constraint identifiers
- agentConstrainLifetime = 1
- agentConstrainConfirm = 2
+ agentConstrainLifetime = 1
+ agentConstrainConfirm = 2
+ agentConstrainExtension = 3
)
// maxAgentResponseBytes is the maximum agent reply size that is accepted. This
@@ -151,6 +166,19 @@ type publicKey struct {
Rest []byte `ssh:"rest"`
}
+// 3.7 Key constraint identifiers
+type constrainLifetimeAgentMsg struct {
+ LifetimeSecs uint32 `sshtype:"1"`
+}
+
+type constrainExtensionAgentMsg struct {
+ ExtensionName string `sshtype:"3"`
+ ExtensionDetails []byte
+
+ // Rest is a field used for parsing, not part of message
+ Rest []byte `ssh:"rest"`
+}
+
// Key represents a protocol 2 public key as defined in
// [PROTOCOL.agent], section 2.5.2.
type Key struct {
@@ -542,11 +570,7 @@ func (c *client) Add(key AddedKey) error {
var constraints []byte
if secs := key.LifetimeSecs; secs != 0 {
- constraints = append(constraints, agentConstrainLifetime)
-
- var secsBytes [4]byte
- binary.BigEndian.PutUint32(secsBytes[:], secs)
- constraints = append(constraints, secsBytes[:]...)
+ constraints = append(constraints, ssh.Marshal(constrainLifetimeAgentMsg{secs})...)
}
if key.ConfirmBeforeUse {
diff --git a/vendor/golang.org/x/crypto/ssh/agent/server.go b/vendor/golang.org/x/crypto/ssh/agent/server.go
index 68a333fa..321e48a2 100644
--- a/vendor/golang.org/x/crypto/ssh/agent/server.go
+++ b/vendor/golang.org/x/crypto/ssh/agent/server.go
@@ -106,7 +106,7 @@ func (s *server) processRequest(data []byte) (interface{}, error) {
return nil, s.agent.Lock(req.Passphrase)
case agentUnlock:
- var req agentLockMsg
+ var req agentUnlockMsg
if err := ssh.Unmarshal(data, &req); err != nil {
return nil, err
}
@@ -155,6 +155,44 @@ func (s *server) processRequest(data []byte) (interface{}, error) {
return nil, fmt.Errorf("unknown opcode %d", data[0])
}
+func parseConstraints(constraints []byte) (lifetimeSecs uint32, confirmBeforeUse bool, extensions []ConstraintExtension, err error) {
+ for len(constraints) != 0 {
+ switch constraints[0] {
+ case agentConstrainLifetime:
+ lifetimeSecs = binary.BigEndian.Uint32(constraints[1:5])
+ constraints = constraints[5:]
+ case agentConstrainConfirm:
+ confirmBeforeUse = true
+ constraints = constraints[1:]
+ case agentConstrainExtension:
+ var msg constrainExtensionAgentMsg
+ if err = ssh.Unmarshal(constraints, &msg); err != nil {
+ return 0, false, nil, err
+ }
+ extensions = append(extensions, ConstraintExtension{
+ ExtensionName: msg.ExtensionName,
+ ExtensionDetails: msg.ExtensionDetails,
+ })
+ constraints = msg.Rest
+ default:
+ return 0, false, nil, fmt.Errorf("unknown constraint type: %d", constraints[0])
+ }
+ }
+ return
+}
+
+func setConstraints(key *AddedKey, constraintBytes []byte) error {
+ lifetimeSecs, confirmBeforeUse, constraintExtensions, err := parseConstraints(constraintBytes)
+ if err != nil {
+ return err
+ }
+
+ key.LifetimeSecs = lifetimeSecs
+ key.ConfirmBeforeUse = confirmBeforeUse
+ key.ConstraintExtensions = constraintExtensions
+ return nil
+}
+
func parseRSAKey(req []byte) (*AddedKey, error) {
var k rsaKeyMsg
if err := ssh.Unmarshal(req, &k); err != nil {
@@ -173,7 +211,11 @@ func parseRSAKey(req []byte) (*AddedKey, error) {
}
priv.Precompute()
- return &AddedKey{PrivateKey: priv, Comment: k.Comments}, nil
+ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
}
func parseEd25519Key(req []byte) (*AddedKey, error) {
@@ -182,7 +224,12 @@ func parseEd25519Key(req []byte) (*AddedKey, error) {
return nil, err
}
priv := ed25519.PrivateKey(k.Priv)
- return &AddedKey{PrivateKey: &priv, Comment: k.Comments}, nil
+
+ addedKey := &AddedKey{PrivateKey: &priv, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
}
func parseDSAKey(req []byte) (*AddedKey, error) {
@@ -202,7 +249,11 @@ func parseDSAKey(req []byte) (*AddedKey, error) {
X: k.X,
}
- return &AddedKey{PrivateKey: priv, Comment: k.Comments}, nil
+ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
}
func unmarshalECDSA(curveName string, keyBytes []byte, privScalar *big.Int) (priv *ecdsa.PrivateKey, err error) {
@@ -243,7 +294,12 @@ func parseEd25519Cert(req []byte) (*AddedKey, error) {
if !ok {
return nil, errors.New("agent: bad ED25519 certificate")
}
- return &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}, nil
+
+ addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
}
func parseECDSAKey(req []byte) (*AddedKey, error) {
@@ -257,7 +313,11 @@ func parseECDSAKey(req []byte) (*AddedKey, error) {
return nil, err
}
- return &AddedKey{PrivateKey: priv, Comment: k.Comments}, nil
+ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
}
func parseRSACert(req []byte) (*AddedKey, error) {
@@ -300,7 +360,11 @@ func parseRSACert(req []byte) (*AddedKey, error) {
}
priv.Precompute()
- return &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}, nil
+ addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
}
func parseDSACert(req []byte) (*AddedKey, error) {
@@ -338,7 +402,11 @@ func parseDSACert(req []byte) (*AddedKey, error) {
X: k.X,
}
- return &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}, nil
+ addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
}
func parseECDSACert(req []byte) (*AddedKey, error) {
@@ -371,7 +439,11 @@ func parseECDSACert(req []byte) (*AddedKey, error) {
return nil, err
}
- return &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}, nil
+ addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
}
func (s *server) insertIdentity(req []byte) error {
diff --git a/vendor/golang.org/x/crypto/ssh/buffer.go b/vendor/golang.org/x/crypto/ssh/buffer.go
index 6931b511..1ab07d07 100644
--- a/vendor/golang.org/x/crypto/ssh/buffer.go
+++ b/vendor/golang.org/x/crypto/ssh/buffer.go
@@ -51,13 +51,12 @@ func (b *buffer) write(buf []byte) {
}
// eof closes the buffer. Reads from the buffer once all
-// the data has been consumed will receive os.EOF.
-func (b *buffer) eof() error {
+// the data has been consumed will receive io.EOF.
+func (b *buffer) eof() {
b.Cond.L.Lock()
b.closed = true
b.Cond.Signal()
b.Cond.L.Unlock()
- return nil
}
// Read reads data from the internal buffer in buf. Reads will block
diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go
index 6331c94d..b1f02207 100644
--- a/vendor/golang.org/x/crypto/ssh/certs.go
+++ b/vendor/golang.org/x/crypto/ssh/certs.go
@@ -251,10 +251,18 @@ type CertChecker struct {
// for user certificates.
SupportedCriticalOptions []string
- // IsAuthority should return true if the key is recognized as
- // an authority. This allows for certificates to be signed by other
- // certificates.
- IsAuthority func(auth PublicKey) bool
+ // IsUserAuthority should return true if the key is recognized as an
+ // authority for the given user certificate. This allows for
+ // certificates to be signed by other certificates. This must be set
+ // if this CertChecker will be checking user certificates.
+ IsUserAuthority func(auth PublicKey) bool
+
+ // IsHostAuthority should report whether the key is recognized as
+ // an authority for this host. This allows for certificates to be
+ // signed by other keys, and for those other keys to only be valid
+ // signers for particular hostnames. This must be set if this
+ // CertChecker will be checking host certificates.
+ IsHostAuthority func(auth PublicKey, address string) bool
// Clock is used for verifying time stamps. If nil, time.Now
// is used.
@@ -268,7 +276,7 @@ type CertChecker struct {
// HostKeyFallback is called when CertChecker.CheckHostKey encounters a
// public key that is not a certificate. It must implement host key
// validation or else, if nil, all such keys are rejected.
- HostKeyFallback func(addr string, remote net.Addr, key PublicKey) error
+ HostKeyFallback HostKeyCallback
// IsRevoked is called for each certificate so that revocation checking
// can be implemented. It should return true if the given certificate
@@ -290,8 +298,17 @@ func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey)
if cert.CertType != HostCert {
return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType)
}
+ if !c.IsHostAuthority(cert.SignatureKey, addr) {
+ return fmt.Errorf("ssh: no authorities for hostname: %v", addr)
+ }
+
+ hostname, _, err := net.SplitHostPort(addr)
+ if err != nil {
+ return err
+ }
- return c.CheckCert(addr, cert)
+ // Pass hostname only as principal for host certificates (consistent with OpenSSH)
+ return c.CheckCert(hostname, cert)
}
// Authenticate checks a user certificate. Authenticate can be used as
@@ -308,6 +325,9 @@ func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permis
if cert.CertType != UserCert {
return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType)
}
+ if !c.IsUserAuthority(cert.SignatureKey) {
+ return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority")
+ }
if err := c.CheckCert(conn.User(), cert); err != nil {
return nil, err
@@ -356,10 +376,6 @@ func (c *CertChecker) CheckCert(principal string, cert *Certificate) error {
}
}
- if !c.IsAuthority(cert.SignatureKey) {
- return fmt.Errorf("ssh: certificate signed by unrecognized authority")
- }
-
clock := c.Clock
if clock == nil {
clock = time.Now
diff --git a/vendor/golang.org/x/crypto/ssh/channel.go b/vendor/golang.org/x/crypto/ssh/channel.go
index 6d709b50..195530ea 100644
--- a/vendor/golang.org/x/crypto/ssh/channel.go
+++ b/vendor/golang.org/x/crypto/ssh/channel.go
@@ -461,8 +461,8 @@ func (m *mux) newChannel(chanType string, direction channelDirection, extraData
pending: newBuffer(),
extPending: newBuffer(),
direction: direction,
- incomingRequests: make(chan *Request, 16),
- msg: make(chan interface{}, 16),
+ incomingRequests: make(chan *Request, chanSize),
+ msg: make(chan interface{}, chanSize),
chanType: chanType,
extraData: extraData,
mux: m,
diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go
index 34d3917c..aed2b1f0 100644
--- a/vendor/golang.org/x/crypto/ssh/cipher.go
+++ b/vendor/golang.org/x/crypto/ssh/cipher.go
@@ -135,6 +135,7 @@ const prefixLen = 5
type streamPacketCipher struct {
mac hash.Hash
cipher cipher.Stream
+ etm bool
// The following members are to avoid per-packet allocations.
prefix [prefixLen]byte
@@ -150,7 +151,14 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
return nil, err
}
- s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
+ var encryptedPaddingLength [1]byte
+ if s.mac != nil && s.etm {
+ copy(encryptedPaddingLength[:], s.prefix[4:5])
+ s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
+ } else {
+ s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
+ }
+
length := binary.BigEndian.Uint32(s.prefix[0:4])
paddingLength := uint32(s.prefix[4])
@@ -159,7 +167,12 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
s.mac.Reset()
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
s.mac.Write(s.seqNumBytes[:])
- s.mac.Write(s.prefix[:])
+ if s.etm {
+ s.mac.Write(s.prefix[:4])
+ s.mac.Write(encryptedPaddingLength[:])
+ } else {
+ s.mac.Write(s.prefix[:])
+ }
macSize = uint32(s.mac.Size())
}
@@ -184,10 +197,17 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
}
mac := s.packetData[length-1:]
data := s.packetData[:length-1]
+
+ if s.mac != nil && s.etm {
+ s.mac.Write(data)
+ }
+
s.cipher.XORKeyStream(data, data)
if s.mac != nil {
- s.mac.Write(data)
+ if !s.etm {
+ s.mac.Write(data)
+ }
s.macResult = s.mac.Sum(s.macResult[:0])
if subtle.ConstantTimeCompare(s.macResult, mac) != 1 {
return nil, errors.New("ssh: MAC failure")
@@ -203,7 +223,13 @@ func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Rea
return errors.New("ssh: packet too large")
}
- paddingLength := packetSizeMultiple - (prefixLen+len(packet))%packetSizeMultiple
+ aadlen := 0
+ if s.mac != nil && s.etm {
+ // packet length is not encrypted for EtM modes
+ aadlen = 4
+ }
+
+ paddingLength := packetSizeMultiple - (prefixLen+len(packet)-aadlen)%packetSizeMultiple
if paddingLength < 4 {
paddingLength += packetSizeMultiple
}
@@ -220,15 +246,37 @@ func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Rea
s.mac.Reset()
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
s.mac.Write(s.seqNumBytes[:])
+
+ if s.etm {
+ // For EtM algorithms, the packet length must stay unencrypted,
+ // but the following data (padding length) must be encrypted
+ s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
+ }
+
s.mac.Write(s.prefix[:])
- s.mac.Write(packet)
- s.mac.Write(padding)
+
+ if !s.etm {
+ // For non-EtM algorithms, the algorithm is applied on unencrypted data
+ s.mac.Write(packet)
+ s.mac.Write(padding)
+ }
+ }
+
+ if !(s.mac != nil && s.etm) {
+ // For EtM algorithms, the padding length has already been encrypted
+ // and the packet length must remain unencrypted
+ s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
}
- s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
s.cipher.XORKeyStream(packet, packet)
s.cipher.XORKeyStream(padding, padding)
+ if s.mac != nil && s.etm {
+ // For EtM algorithms, packet and padding must be encrypted
+ s.mac.Write(packet)
+ s.mac.Write(padding)
+ }
+
if _, err := w.Write(s.prefix[:]); err != nil {
return err
}
@@ -256,7 +304,7 @@ type gcmCipher struct {
buf []byte
}
-func newGCMCipher(iv, key, macKey []byte) (packetCipher, error) {
+func newGCMCipher(iv, key []byte) (packetCipher, error) {
c, err := aes.NewCipher(key)
if err != nil {
return nil, err
@@ -344,7 +392,9 @@ func (c *gcmCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
c.incIV()
padding := plain[0]
- if padding < 4 || padding >= 20 {
+ if padding < 4 {
+ // padding is a byte, so it automatically satisfies
+ // the maximum size, which is 255.
return nil, fmt.Errorf("ssh: illegal padding %d", padding)
}
diff --git a/vendor/golang.org/x/crypto/ssh/client.go b/vendor/golang.org/x/crypto/ssh/client.go
index 0212a20c..6fd19945 100644
--- a/vendor/golang.org/x/crypto/ssh/client.go
+++ b/vendor/golang.org/x/crypto/ssh/client.go
@@ -5,15 +5,17 @@
package ssh
import (
+ "bytes"
"errors"
"fmt"
"net"
+ "os"
"sync"
"time"
)
// Client implements a traditional SSH client that supports shells,
-// subprocesses, port forwarding and tunneled dialing.
+// subprocesses, TCP port/streamlocal forwarding and tunneled dialing.
type Client struct {
Conn
@@ -40,7 +42,7 @@ func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel {
return nil
}
- ch = make(chan NewChannel, 16)
+ ch = make(chan NewChannel, chanSize)
c.channelHandlers[channelType] = ch
return ch
}
@@ -59,6 +61,7 @@ func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client {
conn.forwards.closeAll()
}()
go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip"))
+ go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-streamlocal@openssh.com"))
return conn
}
@@ -68,6 +71,11 @@ func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client {
func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) {
fullConf := *config
fullConf.SetDefaults()
+ if fullConf.HostKeyCallback == nil {
+ c.Close()
+ return nil, nil, nil, errors.New("ssh: must specify HostKeyCallback")
+ }
+
conn := &connection{
sshConn: sshConn{conn: c},
}
@@ -97,13 +105,11 @@ func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) e
c.transport = newClientTransport(
newTransport(c.sshConn.conn, config.Rand, true /* is client */),
c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr())
- if err := c.transport.requestInitialKeyChange(); err != nil {
+ if err := c.transport.waitSession(); err != nil {
return err
}
- // We just did the key change, so the session ID is established.
c.sessionID = c.transport.getSessionID()
-
return c.clientAuthenticate(config)
}
@@ -175,6 +181,17 @@ func Dial(network, addr string, config *ClientConfig) (*Client, error) {
return NewClient(c, chans, reqs), nil
}
+// HostKeyCallback is the function type used for verifying server
+// keys. A HostKeyCallback must return nil if the host key is OK, or
+// an error to reject it. It receives the hostname as passed to Dial
+// or NewClientConn. The remote address is the RemoteAddr of the
+// net.Conn underlying the the SSH connection.
+type HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
+
+// BannerCallback is the function type used for treat the banner sent by
+// the server. A BannerCallback receives the message sent by the remote server.
+type BannerCallback func(message string) error
+
// A ClientConfig structure is used to configure a Client. It must not be
// modified after having been passed to an SSH function.
type ClientConfig struct {
@@ -190,10 +207,18 @@ type ClientConfig struct {
// be used during authentication.
Auth []AuthMethod
- // HostKeyCallback, if not nil, is called during the cryptographic
- // handshake to validate the server's host key. A nil HostKeyCallback
- // implies that all host keys are accepted.
- HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
+ // HostKeyCallback is called during the cryptographic
+ // handshake to validate the server's host key. The client
+ // configuration must supply this callback for the connection
+ // to succeed. The functions InsecureIgnoreHostKey or
+ // FixedHostKey can be used for simplistic host key checks.
+ HostKeyCallback HostKeyCallback
+
+ // BannerCallback is called during the SSH dance to display a custom
+ // server's message. The client configuration can supply this callback to
+ // handle it as wished. The function BannerDisplayStderr can be used for
+ // simplistic display on Stderr.
+ BannerCallback BannerCallback
// ClientVersion contains the version identification string that will
// be used for the connection. If empty, a reasonable default is used.
@@ -211,3 +236,43 @@ type ClientConfig struct {
// A Timeout of zero means no timeout.
Timeout time.Duration
}
+
+// InsecureIgnoreHostKey returns a function that can be used for
+// ClientConfig.HostKeyCallback to accept any host key. It should
+// not be used for production code.
+func InsecureIgnoreHostKey() HostKeyCallback {
+ return func(hostname string, remote net.Addr, key PublicKey) error {
+ return nil
+ }
+}
+
+type fixedHostKey struct {
+ key PublicKey
+}
+
+func (f *fixedHostKey) check(hostname string, remote net.Addr, key PublicKey) error {
+ if f.key == nil {
+ return fmt.Errorf("ssh: required host key was nil")
+ }
+ if !bytes.Equal(key.Marshal(), f.key.Marshal()) {
+ return fmt.Errorf("ssh: host key mismatch")
+ }
+ return nil
+}
+
+// FixedHostKey returns a function for use in
+// ClientConfig.HostKeyCallback to accept only a specific host key.
+func FixedHostKey(key PublicKey) HostKeyCallback {
+ hk := &fixedHostKey{key}
+ return hk.check
+}
+
+// BannerDisplayStderr returns a function that can be used for
+// ClientConfig.BannerCallback to display banners on os.Stderr.
+func BannerDisplayStderr() BannerCallback {
+ return func(banner string) error {
+ _, err := os.Stderr.WriteString(banner)
+
+ return err
+ }
+}
diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go
index 294af0d4..a1252cb9 100644
--- a/vendor/golang.org/x/crypto/ssh/client_auth.go
+++ b/vendor/golang.org/x/crypto/ssh/client_auth.go
@@ -30,8 +30,10 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
// then any untried methods suggested by the server.
tried := make(map[string]bool)
var lastMethods []string
+
+ sessionID := c.transport.getSessionID()
for auth := AuthMethod(new(noneAuth)); auth != nil; {
- ok, methods, err := auth.auth(c.transport.getSessionID(), config.User, c.transport, config.Rand)
+ ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand)
if err != nil {
return err
}
@@ -177,31 +179,26 @@ func (cb publicKeyCallback) method() string {
}
func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
- // Authentication is performed in two stages. The first stage sends an
- // enquiry to test if each key is acceptable to the remote. The second
- // stage attempts to authenticate with the valid keys obtained in the
- // first stage.
+ // Authentication is performed by sending an enquiry to test if a key is
+ // acceptable to the remote. If the key is acceptable, the client will
+ // attempt to authenticate with the valid key. If not the client will repeat
+ // the process with the remaining keys.
signers, err := cb()
if err != nil {
return false, nil, err
}
- var validKeys []Signer
+ var methods []string
for _, signer := range signers {
- if ok, err := validateKey(signer.PublicKey(), user, c); ok {
- validKeys = append(validKeys, signer)
- } else {
- if err != nil {
- return false, nil, err
- }
+ ok, err := validateKey(signer.PublicKey(), user, c)
+ if err != nil {
+ return false, nil, err
+ }
+ if !ok {
+ continue
}
- }
- // methods that may continue if this auth is not successful.
- var methods []string
- for _, signer := range validKeys {
pub := signer.PublicKey()
-
pubKey := pub.Marshal()
sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{
User: user,
@@ -234,13 +231,29 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
if err != nil {
return false, nil, err
}
- if success {
+
+ // If authentication succeeds or the list of available methods does not
+ // contain the "publickey" method, do not attempt to authenticate with any
+ // other keys. According to RFC 4252 Section 7, the latter can occur when
+ // additional authentication methods are required.
+ if success || !containsMethod(methods, cb.method()) {
return success, methods, err
}
}
+
return false, methods, nil
}
+func containsMethod(methods []string, method string) bool {
+ for _, m := range methods {
+ if m == method {
+ return true
+ }
+ }
+
+ return false
+}
+
// validateKey validates the key provided is acceptable to the server.
func validateKey(key PublicKey, user string, c packetConn) (bool, error) {
pubKey := key.Marshal()
@@ -270,7 +283,9 @@ func confirmKeyAck(key PublicKey, c packetConn) (bool, error) {
}
switch packet[0] {
case msgUserAuthBanner:
- // TODO(gpaul): add callback to present the banner to the user
+ if err := handleBannerResponse(c, packet); err != nil {
+ return false, err
+ }
case msgUserAuthPubKeyOk:
var msg userAuthPubKeyOkMsg
if err := Unmarshal(packet, &msg); err != nil {
@@ -312,7 +327,9 @@ func handleAuthResponse(c packetConn) (bool, []string, error) {
switch packet[0] {
case msgUserAuthBanner:
- // TODO: add callback to present the banner to the user
+ if err := handleBannerResponse(c, packet); err != nil {
+ return false, nil, err
+ }
case msgUserAuthFailure:
var msg userAuthFailureMsg
if err := Unmarshal(packet, &msg); err != nil {
@@ -327,6 +344,24 @@ func handleAuthResponse(c packetConn) (bool, []string, error) {
}
}
+func handleBannerResponse(c packetConn, packet []byte) error {
+ var msg userAuthBannerMsg
+ if err := Unmarshal(packet, &msg); err != nil {
+ return err
+ }
+
+ transport, ok := c.(*handshakeTransport)
+ if !ok {
+ return nil
+ }
+
+ if transport.bannerCallback != nil {
+ return transport.bannerCallback(msg.Message)
+ }
+
+ return nil
+}
+
// KeyboardInteractiveChallenge should print questions, optionally
// disabling echoing (e.g. for passwords), and return all the answers.
// Challenge may be called multiple times in a single session. After
@@ -336,7 +371,7 @@ func handleAuthResponse(c packetConn) (bool, []string, error) {
// both CLI and GUI environments.
type KeyboardInteractiveChallenge func(user, instruction string, questions []string, echos []bool) (answers []string, err error)
-// KeyboardInteractive returns a AuthMethod using a prompt/response
+// KeyboardInteractive returns an AuthMethod using a prompt/response
// sequence controlled by the server.
func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod {
return challenge
@@ -372,7 +407,9 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
// like handleAuthResponse, but with less options.
switch packet[0] {
case msgUserAuthBanner:
- // TODO: Print banners during userauth.
+ if err := handleBannerResponse(c, packet); err != nil {
+ return false, nil, err
+ }
continue
case msgUserAuthInfoRequest:
// OK
diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go
index 2c72ab54..dc39e4d2 100644
--- a/vendor/golang.org/x/crypto/ssh/common.go
+++ b/vendor/golang.org/x/crypto/ssh/common.go
@@ -9,6 +9,7 @@ import (
"crypto/rand"
"fmt"
"io"
+ "math"
"sync"
_ "crypto/sha1"
@@ -40,7 +41,7 @@ var supportedKexAlgos = []string{
kexAlgoDH14SHA1, kexAlgoDH1SHA1,
}
-// supportedKexAlgos specifies the supported host-key algorithms (i.e. methods
+// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
// of authenticating servers) in preference order.
var supportedHostKeyAlgos = []string{
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
@@ -56,7 +57,7 @@ var supportedHostKeyAlgos = []string{
// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed
// because they have reached the end of their useful life.
var supportedMACs = []string{
- "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
+ "hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
}
var supportedCompressions = []string{compressionNone}
@@ -104,6 +105,21 @@ type directionAlgorithms struct {
Compression string
}
+// rekeyBytes returns a rekeying intervals in bytes.
+func (a *directionAlgorithms) rekeyBytes() int64 {
+ // According to RFC4344 block ciphers should rekey after
+ // 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is
+ // 128.
+ switch a.Cipher {
+ case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcmCipherID, aes128cbcID:
+ return 16 * (1 << 32)
+
+ }
+
+ // For others, stick with RFC4253 recommendation to rekey after 1 Gb of data.
+ return 1 << 30
+}
+
type algorithms struct {
kex string
hostKey string
@@ -171,7 +187,7 @@ type Config struct {
// The maximum number of bytes sent or received after which a
// new key is negotiated. It must be at least 256. If
- // unspecified, 1 gigabyte is used.
+ // unspecified, a size suitable for the chosen cipher is used.
RekeyThreshold uint64
// The allowed key exchanges algorithms. If unspecified then a
@@ -215,11 +231,12 @@ func (c *Config) SetDefaults() {
}
if c.RekeyThreshold == 0 {
- // RFC 4253, section 9 suggests rekeying after 1G.
- c.RekeyThreshold = 1 << 30
- }
- if c.RekeyThreshold < minRekeyThreshold {
+ // cipher specific default
+ } else if c.RekeyThreshold < minRekeyThreshold {
c.RekeyThreshold = minRekeyThreshold
+ } else if c.RekeyThreshold >= math.MaxInt64 {
+ // Avoid weirdness if somebody uses -1 as a threshold.
+ c.RekeyThreshold = math.MaxInt64
}
}
diff --git a/vendor/golang.org/x/crypto/ssh/connection.go b/vendor/golang.org/x/crypto/ssh/connection.go
index e786f2f9..fd6b0681 100644
--- a/vendor/golang.org/x/crypto/ssh/connection.go
+++ b/vendor/golang.org/x/crypto/ssh/connection.go
@@ -25,7 +25,7 @@ type ConnMetadata interface {
// User returns the user ID for this connection.
User() string
- // SessionID returns the sesson hash, also denoted by H.
+ // SessionID returns the session hash, also denoted by H.
SessionID() []byte
// ClientVersion returns the client's version string as hashed
diff --git a/vendor/golang.org/x/crypto/ssh/doc.go b/vendor/golang.org/x/crypto/ssh/doc.go
index d6be8946..67b7322c 100644
--- a/vendor/golang.org/x/crypto/ssh/doc.go
+++ b/vendor/golang.org/x/crypto/ssh/doc.go
@@ -14,5 +14,8 @@ others.
References:
[PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD
[SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
+
+This package does not fall under the stability promise of the Go language itself,
+so its API may be changed when pressing needs arise.
*/
package ssh // import "golang.org/x/crypto/ssh"
diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go
index 37d42e47..4f7912ec 100644
--- a/vendor/golang.org/x/crypto/ssh/handshake.go
+++ b/vendor/golang.org/x/crypto/ssh/handshake.go
@@ -19,6 +19,11 @@ import (
// messages are wrong when using ECDH.
const debugHandshake = false
+// chanSize sets the amount of buffering SSH connections. This is
+// primarily for testing: setting chanSize=0 uncovers deadlocks more
+// quickly.
+const chanSize = 16
+
// keyingTransport is a packet based transport that supports key
// changes. It need not be thread-safe. It should pass through
// msgNewKeys in both directions.
@@ -53,34 +58,65 @@ type handshakeTransport struct {
incoming chan []byte
readError error
+ mu sync.Mutex
+ writeError error
+ sentInitPacket []byte
+ sentInitMsg *kexInitMsg
+ pendingPackets [][]byte // Used when a key exchange is in progress.
+
+ // If the read loop wants to schedule a kex, it pings this
+ // channel, and the write loop will send out a kex
+ // message.
+ requestKex chan struct{}
+
+ // If the other side requests or confirms a kex, its kexInit
+ // packet is sent here for the write loop to find it.
+ startKex chan *pendingKex
+
// data for host key checking
- hostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
+ hostKeyCallback HostKeyCallback
dialAddress string
remoteAddr net.Addr
- readSinceKex uint64
+ // bannerCallback is non-empty if we are the client and it has been set in
+ // ClientConfig. In that case it is called during the user authentication
+ // dance to handle a custom server's message.
+ bannerCallback BannerCallback
+
+ // Algorithms agreed in the last key exchange.
+ algorithms *algorithms
- // Protects the writing side of the connection
- mu sync.Mutex
- cond *sync.Cond
- sentInitPacket []byte
- sentInitMsg *kexInitMsg
- writtenSinceKex uint64
- writeError error
+ readPacketsLeft uint32
+ readBytesLeft int64
+
+ writePacketsLeft uint32
+ writeBytesLeft int64
// The session ID or nil if first kex did not complete yet.
sessionID []byte
}
+type pendingKex struct {
+ otherInit []byte
+ done chan error
+}
+
func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport {
t := &handshakeTransport{
conn: conn,
serverVersion: serverVersion,
clientVersion: clientVersion,
- incoming: make(chan []byte, 16),
- config: config,
+ incoming: make(chan []byte, chanSize),
+ requestKex: make(chan struct{}, 1),
+ startKex: make(chan *pendingKex, 1),
+
+ config: config,
}
- t.cond = sync.NewCond(&t.mu)
+ t.resetReadThresholds()
+ t.resetWriteThresholds()
+
+ // We always start with a mandatory key exchange.
+ t.requestKex <- struct{}{}
return t
}
@@ -89,12 +125,14 @@ func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byt
t.dialAddress = dialAddr
t.remoteAddr = addr
t.hostKeyCallback = config.HostKeyCallback
+ t.bannerCallback = config.BannerCallback
if config.HostKeyAlgorithms != nil {
t.hostKeyAlgorithms = config.HostKeyAlgorithms
} else {
t.hostKeyAlgorithms = supportedHostKeyAlgos
}
go t.readLoop()
+ go t.kexLoop()
return t
}
@@ -102,6 +140,7 @@ func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byt
t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
t.hostKeys = config.hostKeys
go t.readLoop()
+ go t.kexLoop()
return t
}
@@ -109,6 +148,20 @@ func (t *handshakeTransport) getSessionID() []byte {
return t.sessionID
}
+// waitSession waits for the session to be established. This should be
+// the first thing to call after instantiating handshakeTransport.
+func (t *handshakeTransport) waitSession() error {
+ p, err := t.readPacket()
+ if err != nil {
+ return err
+ }
+ if p[0] != msgNewKeys {
+ return fmt.Errorf("ssh: first packet should be msgNewKeys")
+ }
+
+ return nil
+}
+
func (t *handshakeTransport) id() string {
if len(t.hostKeys) > 0 {
return "server"
@@ -116,6 +169,20 @@ func (t *handshakeTransport) id() string {
return "client"
}
+func (t *handshakeTransport) printPacket(p []byte, write bool) {
+ action := "got"
+ if write {
+ action = "sent"
+ }
+
+ if p[0] == msgChannelData || p[0] == msgChannelExtendedData {
+ log.Printf("%s %s data (packet %d bytes)", t.id(), action, len(p))
+ } else {
+ msg, err := decode(p)
+ log.Printf("%s %s %T %v (%v)", t.id(), action, msg, msg, err)
+ }
+}
+
func (t *handshakeTransport) readPacket() ([]byte, error) {
p, ok := <-t.incoming
if !ok {
@@ -125,8 +192,10 @@ func (t *handshakeTransport) readPacket() ([]byte, error) {
}
func (t *handshakeTransport) readLoop() {
+ first := true
for {
- p, err := t.readOnePacket()
+ p, err := t.readOnePacket(first)
+ first = false
if err != nil {
t.readError = err
close(t.incoming)
@@ -138,67 +207,217 @@ func (t *handshakeTransport) readLoop() {
t.incoming <- p
}
- // If we can't read, declare the writing part dead too.
+ // Stop writers too.
+ t.recordWriteError(t.readError)
+
+ // Unblock the writer should it wait for this.
+ close(t.startKex)
+
+ // Don't close t.requestKex; it's also written to from writePacket.
+}
+
+func (t *handshakeTransport) pushPacket(p []byte) error {
+ if debugHandshake {
+ t.printPacket(p, true)
+ }
+ return t.conn.writePacket(p)
+}
+
+func (t *handshakeTransport) getWriteError() error {
t.mu.Lock()
defer t.mu.Unlock()
- if t.writeError == nil {
- t.writeError = t.readError
+ return t.writeError
+}
+
+func (t *handshakeTransport) recordWriteError(err error) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ if t.writeError == nil && err != nil {
+ t.writeError = err
}
- t.cond.Broadcast()
}
-func (t *handshakeTransport) readOnePacket() ([]byte, error) {
- if t.readSinceKex > t.config.RekeyThreshold {
- if err := t.requestKeyChange(); err != nil {
- return nil, err
+func (t *handshakeTransport) requestKeyExchange() {
+ select {
+ case t.requestKex <- struct{}{}:
+ default:
+ // something already requested a kex, so do nothing.
+ }
+}
+
+func (t *handshakeTransport) resetWriteThresholds() {
+ t.writePacketsLeft = packetRekeyThreshold
+ if t.config.RekeyThreshold > 0 {
+ t.writeBytesLeft = int64(t.config.RekeyThreshold)
+ } else if t.algorithms != nil {
+ t.writeBytesLeft = t.algorithms.w.rekeyBytes()
+ } else {
+ t.writeBytesLeft = 1 << 30
+ }
+}
+
+func (t *handshakeTransport) kexLoop() {
+
+write:
+ for t.getWriteError() == nil {
+ var request *pendingKex
+ var sent bool
+
+ for request == nil || !sent {
+ var ok bool
+ select {
+ case request, ok = <-t.startKex:
+ if !ok {
+ break write
+ }
+ case <-t.requestKex:
+ break
+ }
+
+ if !sent {
+ if err := t.sendKexInit(); err != nil {
+ t.recordWriteError(err)
+ break
+ }
+ sent = true
+ }
+ }
+
+ if err := t.getWriteError(); err != nil {
+ if request != nil {
+ request.done <- err
+ }
+ break
+ }
+
+ // We're not servicing t.requestKex, but that is OK:
+ // we never block on sending to t.requestKex.
+
+ // We're not servicing t.startKex, but the remote end
+ // has just sent us a kexInitMsg, so it can't send
+ // another key change request, until we close the done
+ // channel on the pendingKex request.
+
+ err := t.enterKeyExchange(request.otherInit)
+
+ t.mu.Lock()
+ t.writeError = err
+ t.sentInitPacket = nil
+ t.sentInitMsg = nil
+
+ t.resetWriteThresholds()
+
+ // we have completed the key exchange. Since the
+ // reader is still blocked, it is safe to clear out
+ // the requestKex channel. This avoids the situation
+ // where: 1) we consumed our own request for the
+ // initial kex, and 2) the kex from the remote side
+ // caused another send on the requestKex channel,
+ clear:
+ for {
+ select {
+ case <-t.requestKex:
+ //
+ default:
+ break clear
+ }
}
+
+ request.done <- t.writeError
+
+ // kex finished. Push packets that we received while
+ // the kex was in progress. Don't look at t.startKex
+ // and don't increment writtenSinceKex: if we trigger
+ // another kex while we are still busy with the last
+ // one, things will become very confusing.
+ for _, p := range t.pendingPackets {
+ t.writeError = t.pushPacket(p)
+ if t.writeError != nil {
+ break
+ }
+ }
+ t.pendingPackets = t.pendingPackets[:0]
+ t.mu.Unlock()
}
+ // drain startKex channel. We don't service t.requestKex
+ // because nobody does blocking sends there.
+ go func() {
+ for init := range t.startKex {
+ init.done <- t.writeError
+ }
+ }()
+
+ // Unblock reader.
+ t.conn.Close()
+}
+
+// The protocol uses uint32 for packet counters, so we can't let them
+// reach 1<<32. We will actually read and write more packets than
+// this, though: the other side may send more packets, and after we
+// hit this limit on writing we will send a few more packets for the
+// key exchange itself.
+const packetRekeyThreshold = (1 << 31)
+
+func (t *handshakeTransport) resetReadThresholds() {
+ t.readPacketsLeft = packetRekeyThreshold
+ if t.config.RekeyThreshold > 0 {
+ t.readBytesLeft = int64(t.config.RekeyThreshold)
+ } else if t.algorithms != nil {
+ t.readBytesLeft = t.algorithms.r.rekeyBytes()
+ } else {
+ t.readBytesLeft = 1 << 30
+ }
+}
+
+func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
p, err := t.conn.readPacket()
if err != nil {
return nil, err
}
- t.readSinceKex += uint64(len(p))
+ if t.readPacketsLeft > 0 {
+ t.readPacketsLeft--
+ } else {
+ t.requestKeyExchange()
+ }
+
+ if t.readBytesLeft > 0 {
+ t.readBytesLeft -= int64(len(p))
+ } else {
+ t.requestKeyExchange()
+ }
+
if debugHandshake {
- if p[0] == msgChannelData || p[0] == msgChannelExtendedData {
- log.Printf("%s got data (packet %d bytes)", t.id(), len(p))
- } else {
- msg, err := decode(p)
- log.Printf("%s got %T %v (%v)", t.id(), msg, msg, err)
- }
+ t.printPacket(p, false)
}
+
+ if first && p[0] != msgKexInit {
+ return nil, fmt.Errorf("ssh: first packet should be msgKexInit")
+ }
+
if p[0] != msgKexInit {
return p, nil
}
- t.mu.Lock()
-
firstKex := t.sessionID == nil
- err = t.enterKeyExchangeLocked(p)
- if err != nil {
- // drop connection
- t.conn.Close()
- t.writeError = err
+ kex := pendingKex{
+ done: make(chan error, 1),
+ otherInit: p,
}
+ t.startKex <- &kex
+ err = <-kex.done
if debugHandshake {
log.Printf("%s exited key exchange (first %v), err %v", t.id(), firstKex, err)
}
- // Unblock writers.
- t.sentInitMsg = nil
- t.sentInitPacket = nil
- t.cond.Broadcast()
- t.writtenSinceKex = 0
- t.mu.Unlock()
-
if err != nil {
return nil, err
}
- t.readSinceKex = 0
+ t.resetReadThresholds()
// By default, a key exchange is hidden from higher layers by
// translating it into msgIgnore.
@@ -213,61 +432,16 @@ func (t *handshakeTransport) readOnePacket() ([]byte, error) {
return successPacket, nil
}
-// keyChangeCategory describes whether a key exchange is the first on a
-// connection, or a subsequent one.
-type keyChangeCategory bool
-
-const (
- firstKeyExchange keyChangeCategory = true
- subsequentKeyExchange keyChangeCategory = false
-)
-
-// sendKexInit sends a key change message, and returns the message
-// that was sent. After initiating the key change, all writes will be
-// blocked until the change is done, and a failed key change will
-// close the underlying transport. This function is safe for
-// concurrent use by multiple goroutines.
-func (t *handshakeTransport) sendKexInit(isFirst keyChangeCategory) error {
- var err error
-
+// sendKexInit sends a key change message.
+func (t *handshakeTransport) sendKexInit() error {
t.mu.Lock()
- // If this is the initial key change, but we already have a sessionID,
- // then do nothing because the key exchange has already completed
- // asynchronously.
- if !isFirst || t.sessionID == nil {
- _, _, err = t.sendKexInitLocked(isFirst)
- }
- t.mu.Unlock()
- if err != nil {
- return err
- }
- if isFirst {
- if packet, err := t.readPacket(); err != nil {
- return err
- } else if packet[0] != msgNewKeys {
- return unexpectedMessageError(msgNewKeys, packet[0])
- }
- }
- return nil
-}
-
-func (t *handshakeTransport) requestInitialKeyChange() error {
- return t.sendKexInit(firstKeyExchange)
-}
-
-func (t *handshakeTransport) requestKeyChange() error {
- return t.sendKexInit(subsequentKeyExchange)
-}
-
-// sendKexInitLocked sends a key change message. t.mu must be locked
-// while this happens.
-func (t *handshakeTransport) sendKexInitLocked(isFirst keyChangeCategory) (*kexInitMsg, []byte, error) {
- // kexInits may be sent either in response to the other side,
- // or because our side wants to initiate a key change, so we
- // may have already sent a kexInit. In that case, don't send a
- // second kexInit.
+ defer t.mu.Unlock()
if t.sentInitMsg != nil {
- return t.sentInitMsg, t.sentInitPacket, nil
+ // kexInits may be sent either in response to the other side,
+ // or because our side wants to initiate a key change, so we
+ // may have already sent a kexInit. In that case, don't send a
+ // second kexInit.
+ return nil
}
msg := &kexInitMsg{
@@ -295,53 +469,65 @@ func (t *handshakeTransport) sendKexInitLocked(isFirst keyChangeCategory) (*kexI
packetCopy := make([]byte, len(packet))
copy(packetCopy, packet)
- if err := t.conn.writePacket(packetCopy); err != nil {
- return nil, nil, err
+ if err := t.pushPacket(packetCopy); err != nil {
+ return err
}
t.sentInitMsg = msg
t.sentInitPacket = packet
- return msg, packet, nil
+
+ return nil
}
func (t *handshakeTransport) writePacket(p []byte) error {
+ switch p[0] {
+ case msgKexInit:
+ return errors.New("ssh: only handshakeTransport can send kexInit")
+ case msgNewKeys:
+ return errors.New("ssh: only handshakeTransport can send newKeys")
+ }
+
t.mu.Lock()
defer t.mu.Unlock()
+ if t.writeError != nil {
+ return t.writeError
+ }
- if t.writtenSinceKex > t.config.RekeyThreshold {
- t.sendKexInitLocked(subsequentKeyExchange)
+ if t.sentInitMsg != nil {
+ // Copy the packet so the writer can reuse the buffer.
+ cp := make([]byte, len(p))
+ copy(cp, p)
+ t.pendingPackets = append(t.pendingPackets, cp)
+ return nil
}
- for t.sentInitMsg != nil && t.writeError == nil {
- t.cond.Wait()
+
+ if t.writeBytesLeft > 0 {
+ t.writeBytesLeft -= int64(len(p))
+ } else {
+ t.requestKeyExchange()
}
- if t.writeError != nil {
- return t.writeError
+
+ if t.writePacketsLeft > 0 {
+ t.writePacketsLeft--
+ } else {
+ t.requestKeyExchange()
}
- t.writtenSinceKex += uint64(len(p))
- switch p[0] {
- case msgKexInit:
- return errors.New("ssh: only handshakeTransport can send kexInit")
- case msgNewKeys:
- return errors.New("ssh: only handshakeTransport can send newKeys")
- default:
- return t.conn.writePacket(p)
+ if err := t.pushPacket(p); err != nil {
+ t.writeError = err
}
+
+ return nil
}
func (t *handshakeTransport) Close() error {
return t.conn.Close()
}
-// enterKeyExchange runs the key exchange. t.mu must be held while running this.
-func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) error {
+func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
if debugHandshake {
log.Printf("%s entered key exchange", t.id())
}
- myInit, myInitPacket, err := t.sendKexInitLocked(subsequentKeyExchange)
- if err != nil {
- return err
- }
otherInit := &kexInitMsg{}
if err := Unmarshal(otherInitPacket, otherInit); err != nil {
@@ -352,20 +538,20 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro
clientVersion: t.clientVersion,
serverVersion: t.serverVersion,
clientKexInit: otherInitPacket,
- serverKexInit: myInitPacket,
+ serverKexInit: t.sentInitPacket,
}
clientInit := otherInit
- serverInit := myInit
+ serverInit := t.sentInitMsg
if len(t.hostKeys) == 0 {
- clientInit = myInit
- serverInit = otherInit
+ clientInit, serverInit = serverInit, clientInit
- magics.clientKexInit = myInitPacket
+ magics.clientKexInit = t.sentInitPacket
magics.serverKexInit = otherInitPacket
}
- algs, err := findAgreedAlgorithms(clientInit, serverInit)
+ var err error
+ t.algorithms, err = findAgreedAlgorithms(clientInit, serverInit)
if err != nil {
return err
}
@@ -388,16 +574,16 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro
}
}
- kex, ok := kexAlgoMap[algs.kex]
+ kex, ok := kexAlgoMap[t.algorithms.kex]
if !ok {
- return fmt.Errorf("ssh: unexpected key exchange algorithm %v", algs.kex)
+ return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.kex)
}
var result *kexResult
if len(t.hostKeys) > 0 {
- result, err = t.server(kex, algs, &magics)
+ result, err = t.server(kex, t.algorithms, &magics)
} else {
- result, err = t.client(kex, algs, &magics)
+ result, err = t.client(kex, t.algorithms, &magics)
}
if err != nil {
@@ -409,7 +595,9 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro
}
result.SessionID = t.sessionID
- t.conn.prepareKeyChange(algs, result)
+ if err := t.conn.prepareKeyChange(t.algorithms, result); err != nil {
+ return err
+ }
if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
return err
}
@@ -449,11 +637,9 @@ func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *
return nil, err
}
- if t.hostKeyCallback != nil {
- err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey)
- if err != nil {
- return nil, err
- }
+ err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey)
+ if err != nil {
+ return nil, err
}
return result, nil
diff --git a/vendor/golang.org/x/crypto/ssh/kex.go b/vendor/golang.org/x/crypto/ssh/kex.go
index c87fbebf..f91c2770 100644
--- a/vendor/golang.org/x/crypto/ssh/kex.go
+++ b/vendor/golang.org/x/crypto/ssh/kex.go
@@ -383,8 +383,8 @@ func init() {
// 4253 and Oakley Group 2 in RFC 2409.
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
- g: new(big.Int).SetInt64(2),
- p: p,
+ g: new(big.Int).SetInt64(2),
+ p: p,
pMinus1: new(big.Int).Sub(p, bigOne),
}
@@ -393,8 +393,8 @@ func init() {
p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
- g: new(big.Int).SetInt64(2),
- p: p,
+ g: new(big.Int).SetInt64(2),
+ p: p,
pMinus1: new(big.Int).Sub(p, bigOne),
}
diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go
index 21f7d0d2..b682c174 100644
--- a/vendor/golang.org/x/crypto/ssh/keys.go
+++ b/vendor/golang.org/x/crypto/ssh/keys.go
@@ -367,6 +367,17 @@ func (r *dsaPublicKey) Type() string {
return "ssh-dss"
}
+func checkDSAParams(param *dsa.Parameters) error {
+ // SSH specifies FIPS 186-2, which only provided a single size
+ // (1024 bits) DSA key. FIPS 186-3 allows for larger key
+ // sizes, which would confuse SSH.
+ if l := param.P.BitLen(); l != 1024 {
+ return fmt.Errorf("ssh: unsupported DSA key size %d", l)
+ }
+
+ return nil
+}
+
// parseDSA parses an DSA key according to RFC 4253, section 6.6.
func parseDSA(in []byte) (out PublicKey, rest []byte, err error) {
var w struct {
@@ -377,13 +388,18 @@ func parseDSA(in []byte) (out PublicKey, rest []byte, err error) {
return nil, nil, err
}
+ param := dsa.Parameters{
+ P: w.P,
+ Q: w.Q,
+ G: w.G,
+ }
+ if err := checkDSAParams(¶m); err != nil {
+ return nil, nil, err
+ }
+
key := &dsaPublicKey{
- Parameters: dsa.Parameters{
- P: w.P,
- Q: w.Q,
- G: w.G,
- },
- Y: w.Y,
+ Parameters: param,
+ Y: w.Y,
}
return key, w.Rest, nil
}
@@ -630,19 +646,28 @@ func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey {
}
// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey,
-// *ecdsa.PrivateKey or any other crypto.Signer and returns a corresponding
-// Signer instance. ECDSA keys must use P-256, P-384 or P-521.
+// *ecdsa.PrivateKey or any other crypto.Signer and returns a
+// corresponding Signer instance. ECDSA keys must use P-256, P-384 or
+// P-521. DSA keys must use parameter size L1024N160.
func NewSignerFromKey(key interface{}) (Signer, error) {
switch key := key.(type) {
case crypto.Signer:
return NewSignerFromSigner(key)
case *dsa.PrivateKey:
- return &dsaPrivateKey{key}, nil
+ return newDSAPrivateKey(key)
default:
return nil, fmt.Errorf("ssh: unsupported key type %T", key)
}
}
+func newDSAPrivateKey(key *dsa.PrivateKey) (Signer, error) {
+ if err := checkDSAParams(&key.PublicKey.Parameters); err != nil {
+ return nil, err
+ }
+
+ return &dsaPrivateKey{key}, nil
+}
+
type wrappedSigner struct {
signer crypto.Signer
pubKey PublicKey
@@ -756,6 +781,18 @@ func ParsePrivateKey(pemBytes []byte) (Signer, error) {
return NewSignerFromKey(key)
}
+// ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private
+// key and passphrase. It supports the same keys as
+// ParseRawPrivateKeyWithPassphrase.
+func ParsePrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (Signer, error) {
+ key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase)
+ if err != nil {
+ return nil, err
+ }
+
+ return NewSignerFromKey(key)
+}
+
// encryptedBlock tells whether a private key is
// encrypted by examining its Proc-Type header
// for a mention of ENCRYPTED
@@ -790,6 +827,43 @@ func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
}
}
+// ParseRawPrivateKeyWithPassphrase returns a private key decrypted with
+// passphrase from a PEM encoded private key. If wrong passphrase, return
+// x509.IncorrectPasswordError.
+func ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (interface{}, error) {
+ block, _ := pem.Decode(pemBytes)
+ if block == nil {
+ return nil, errors.New("ssh: no key found")
+ }
+ buf := block.Bytes
+
+ if encryptedBlock(block) {
+ if x509.IsEncryptedPEMBlock(block) {
+ var err error
+ buf, err = x509.DecryptPEMBlock(block, passPhrase)
+ if err != nil {
+ if err == x509.IncorrectPasswordError {
+ return nil, err
+ }
+ return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err)
+ }
+ }
+ }
+
+ switch block.Type {
+ case "RSA PRIVATE KEY":
+ return x509.ParsePKCS1PrivateKey(buf)
+ case "EC PRIVATE KEY":
+ return x509.ParseECPrivateKey(buf)
+ case "DSA PRIVATE KEY":
+ return ParseDSAPrivateKey(buf)
+ case "OPENSSH PRIVATE KEY":
+ return parseOpenSSHPrivateKey(buf)
+ default:
+ return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
+ }
+}
+
// ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as
// specified by the OpenSSL DSA man page.
func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
@@ -798,8 +872,8 @@ func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
P *big.Int
Q *big.Int
G *big.Int
- Priv *big.Int
Pub *big.Int
+ Priv *big.Int
}
rest, err := asn1.Unmarshal(der, &k)
if err != nil {
@@ -816,15 +890,15 @@ func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
Q: k.Q,
G: k.G,
},
- Y: k.Priv,
+ Y: k.Pub,
},
- X: k.Pub,
+ X: k.Priv,
}, nil
}
// Implemented based on the documentation at
// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
-func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) {
+func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) {
magic := append([]byte("openssh-key-v1"), 0)
if !bytes.Equal(magic, key[0:len(magic)]) {
return nil, errors.New("ssh: invalid openssh private key format")
@@ -844,14 +918,15 @@ func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) {
return nil, err
}
+ if w.KdfName != "none" || w.CipherName != "none" {
+ return nil, errors.New("ssh: cannot decode encrypted private keys")
+ }
+
pk1 := struct {
Check1 uint32
Check2 uint32
Keytype string
- Pub []byte
- Priv []byte
- Comment string
- Pad []byte `ssh:"rest"`
+ Rest []byte `ssh:"rest"`
}{}
if err := Unmarshal(w.PrivKeyBlock, &pk1); err != nil {
@@ -862,24 +937,75 @@ func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) {
return nil, errors.New("ssh: checkint mismatch")
}
- // we only handle ed25519 keys currently
- if pk1.Keytype != KeyAlgoED25519 {
- return nil, errors.New("ssh: unhandled key type")
- }
+ // we only handle ed25519 and rsa keys currently
+ switch pk1.Keytype {
+ case KeyAlgoRSA:
+ // https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773
+ key := struct {
+ N *big.Int
+ E *big.Int
+ D *big.Int
+ Iqmp *big.Int
+ P *big.Int
+ Q *big.Int
+ Comment string
+ Pad []byte `ssh:"rest"`
+ }{}
+
+ if err := Unmarshal(pk1.Rest, &key); err != nil {
+ return nil, err
+ }
- for i, b := range pk1.Pad {
- if int(b) != i+1 {
- return nil, errors.New("ssh: padding not as expected")
+ for i, b := range key.Pad {
+ if int(b) != i+1 {
+ return nil, errors.New("ssh: padding not as expected")
+ }
}
- }
- if len(pk1.Priv) != ed25519.PrivateKeySize {
- return nil, errors.New("ssh: private key unexpected length")
- }
+ pk := &rsa.PrivateKey{
+ PublicKey: rsa.PublicKey{
+ N: key.N,
+ E: int(key.E.Int64()),
+ },
+ D: key.D,
+ Primes: []*big.Int{key.P, key.Q},
+ }
+
+ if err := pk.Validate(); err != nil {
+ return nil, err
+ }
+
+ pk.Precompute()
+
+ return pk, nil
+ case KeyAlgoED25519:
+ key := struct {
+ Pub []byte
+ Priv []byte
+ Comment string
+ Pad []byte `ssh:"rest"`
+ }{}
+
+ if err := Unmarshal(pk1.Rest, &key); err != nil {
+ return nil, err
+ }
+
+ if len(key.Priv) != ed25519.PrivateKeySize {
+ return nil, errors.New("ssh: private key unexpected length")
+ }
- pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
- copy(pk, pk1.Priv)
- return &pk, nil
+ for i, b := range key.Pad {
+ if int(b) != i+1 {
+ return nil, errors.New("ssh: padding not as expected")
+ }
+ }
+
+ pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
+ copy(pk, key.Priv)
+ return &pk, nil
+ default:
+ return nil, errors.New("ssh: unhandled key type")
+ }
}
// FingerprintLegacyMD5 returns the user presentation of the key's
diff --git a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go
new file mode 100644
index 00000000..ea92b298
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go
@@ -0,0 +1,546 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package knownhosts implements a parser for the OpenSSH
+// known_hosts host key database.
+package knownhosts
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/hmac"
+ "crypto/rand"
+ "crypto/sha1"
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "os"
+ "strings"
+
+ "golang.org/x/crypto/ssh"
+)
+
+// See the sshd manpage
+// (http://man.openbsd.org/sshd#SSH_KNOWN_HOSTS_FILE_FORMAT) for
+// background.
+
+type addr struct{ host, port string }
+
+func (a *addr) String() string {
+ h := a.host
+ if strings.Contains(h, ":") {
+ h = "[" + h + "]"
+ }
+ return h + ":" + a.port
+}
+
+type matcher interface {
+ match([]addr) bool
+}
+
+type hostPattern struct {
+ negate bool
+ addr addr
+}
+
+func (p *hostPattern) String() string {
+ n := ""
+ if p.negate {
+ n = "!"
+ }
+
+ return n + p.addr.String()
+}
+
+type hostPatterns []hostPattern
+
+func (ps hostPatterns) match(addrs []addr) bool {
+ matched := false
+ for _, p := range ps {
+ for _, a := range addrs {
+ m := p.match(a)
+ if !m {
+ continue
+ }
+ if p.negate {
+ return false
+ }
+ matched = true
+ }
+ }
+ return matched
+}
+
+// See
+// https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/addrmatch.c
+// The matching of * has no regard for separators, unlike filesystem globs
+func wildcardMatch(pat []byte, str []byte) bool {
+ for {
+ if len(pat) == 0 {
+ return len(str) == 0
+ }
+ if len(str) == 0 {
+ return false
+ }
+
+ if pat[0] == '*' {
+ if len(pat) == 1 {
+ return true
+ }
+
+ for j := range str {
+ if wildcardMatch(pat[1:], str[j:]) {
+ return true
+ }
+ }
+ return false
+ }
+
+ if pat[0] == '?' || pat[0] == str[0] {
+ pat = pat[1:]
+ str = str[1:]
+ } else {
+ return false
+ }
+ }
+}
+
+func (l *hostPattern) match(a addr) bool {
+ return wildcardMatch([]byte(l.addr.host), []byte(a.host)) && l.addr.port == a.port
+}
+
+type keyDBLine struct {
+ cert bool
+ matcher matcher
+ knownKey KnownKey
+}
+
+func serialize(k ssh.PublicKey) string {
+ return k.Type() + " " + base64.StdEncoding.EncodeToString(k.Marshal())
+}
+
+func (l *keyDBLine) match(addrs []addr) bool {
+ return l.matcher.match(addrs)
+}
+
+type hostKeyDB struct {
+ // Serialized version of revoked keys
+ revoked map[string]*KnownKey
+ lines []keyDBLine
+}
+
+func newHostKeyDB() *hostKeyDB {
+ db := &hostKeyDB{
+ revoked: make(map[string]*KnownKey),
+ }
+
+ return db
+}
+
+func keyEq(a, b ssh.PublicKey) bool {
+ return bytes.Equal(a.Marshal(), b.Marshal())
+}
+
+// IsAuthorityForHost can be used as a callback in ssh.CertChecker
+func (db *hostKeyDB) IsHostAuthority(remote ssh.PublicKey, address string) bool {
+ h, p, err := net.SplitHostPort(address)
+ if err != nil {
+ return false
+ }
+ a := addr{host: h, port: p}
+
+ for _, l := range db.lines {
+ if l.cert && keyEq(l.knownKey.Key, remote) && l.match([]addr{a}) {
+ return true
+ }
+ }
+ return false
+}
+
+// IsRevoked can be used as a callback in ssh.CertChecker
+func (db *hostKeyDB) IsRevoked(key *ssh.Certificate) bool {
+ _, ok := db.revoked[string(key.Marshal())]
+ return ok
+}
+
+const markerCert = "@cert-authority"
+const markerRevoked = "@revoked"
+
+func nextWord(line []byte) (string, []byte) {
+ i := bytes.IndexAny(line, "\t ")
+ if i == -1 {
+ return string(line), nil
+ }
+
+ return string(line[:i]), bytes.TrimSpace(line[i:])
+}
+
+func parseLine(line []byte) (marker, host string, key ssh.PublicKey, err error) {
+ if w, next := nextWord(line); w == markerCert || w == markerRevoked {
+ marker = w
+ line = next
+ }
+
+ host, line = nextWord(line)
+ if len(line) == 0 {
+ return "", "", nil, errors.New("knownhosts: missing host pattern")
+ }
+
+ // ignore the keytype as it's in the key blob anyway.
+ _, line = nextWord(line)
+ if len(line) == 0 {
+ return "", "", nil, errors.New("knownhosts: missing key type pattern")
+ }
+
+ keyBlob, _ := nextWord(line)
+
+ keyBytes, err := base64.StdEncoding.DecodeString(keyBlob)
+ if err != nil {
+ return "", "", nil, err
+ }
+ key, err = ssh.ParsePublicKey(keyBytes)
+ if err != nil {
+ return "", "", nil, err
+ }
+
+ return marker, host, key, nil
+}
+
+func (db *hostKeyDB) parseLine(line []byte, filename string, linenum int) error {
+ marker, pattern, key, err := parseLine(line)
+ if err != nil {
+ return err
+ }
+
+ if marker == markerRevoked {
+ db.revoked[string(key.Marshal())] = &KnownKey{
+ Key: key,
+ Filename: filename,
+ Line: linenum,
+ }
+
+ return nil
+ }
+
+ entry := keyDBLine{
+ cert: marker == markerCert,
+ knownKey: KnownKey{
+ Filename: filename,
+ Line: linenum,
+ Key: key,
+ },
+ }
+
+ if pattern[0] == '|' {
+ entry.matcher, err = newHashedHost(pattern)
+ } else {
+ entry.matcher, err = newHostnameMatcher(pattern)
+ }
+
+ if err != nil {
+ return err
+ }
+
+ db.lines = append(db.lines, entry)
+ return nil
+}
+
+func newHostnameMatcher(pattern string) (matcher, error) {
+ var hps hostPatterns
+ for _, p := range strings.Split(pattern, ",") {
+ if len(p) == 0 {
+ continue
+ }
+
+ var a addr
+ var negate bool
+ if p[0] == '!' {
+ negate = true
+ p = p[1:]
+ }
+
+ if len(p) == 0 {
+ return nil, errors.New("knownhosts: negation without following hostname")
+ }
+
+ var err error
+ if p[0] == '[' {
+ a.host, a.port, err = net.SplitHostPort(p)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ a.host, a.port, err = net.SplitHostPort(p)
+ if err != nil {
+ a.host = p
+ a.port = "22"
+ }
+ }
+ hps = append(hps, hostPattern{
+ negate: negate,
+ addr: a,
+ })
+ }
+ return hps, nil
+}
+
+// KnownKey represents a key declared in a known_hosts file.
+type KnownKey struct {
+ Key ssh.PublicKey
+ Filename string
+ Line int
+}
+
+func (k *KnownKey) String() string {
+ return fmt.Sprintf("%s:%d: %s", k.Filename, k.Line, serialize(k.Key))
+}
+
+// KeyError is returned if we did not find the key in the host key
+// database, or there was a mismatch. Typically, in batch
+// applications, this should be interpreted as failure. Interactive
+// applications can offer an interactive prompt to the user.
+type KeyError struct {
+ // Want holds the accepted host keys. For each key algorithm,
+ // there can be one hostkey. If Want is empty, the host is
+ // unknown. If Want is non-empty, there was a mismatch, which
+ // can signify a MITM attack.
+ Want []KnownKey
+}
+
+func (u *KeyError) Error() string {
+ if len(u.Want) == 0 {
+ return "knownhosts: key is unknown"
+ }
+ return "knownhosts: key mismatch"
+}
+
+// RevokedError is returned if we found a key that was revoked.
+type RevokedError struct {
+ Revoked KnownKey
+}
+
+func (r *RevokedError) Error() string {
+ return "knownhosts: key is revoked"
+}
+
+// check checks a key against the host database. This should not be
+// used for verifying certificates.
+func (db *hostKeyDB) check(address string, remote net.Addr, remoteKey ssh.PublicKey) error {
+ if revoked := db.revoked[string(remoteKey.Marshal())]; revoked != nil {
+ return &RevokedError{Revoked: *revoked}
+ }
+
+ host, port, err := net.SplitHostPort(remote.String())
+ if err != nil {
+ return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", remote, err)
+ }
+
+ addrs := []addr{
+ {host, port},
+ }
+
+ if address != "" {
+ host, port, err := net.SplitHostPort(address)
+ if err != nil {
+ return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", address, err)
+ }
+
+ addrs = append(addrs, addr{host, port})
+ }
+
+ return db.checkAddrs(addrs, remoteKey)
+}
+
+// checkAddrs checks if we can find the given public key for any of
+// the given addresses. If we only find an entry for the IP address,
+// or only the hostname, then this still succeeds.
+func (db *hostKeyDB) checkAddrs(addrs []addr, remoteKey ssh.PublicKey) error {
+ // TODO(hanwen): are these the right semantics? What if there
+ // is just a key for the IP address, but not for the
+ // hostname?
+
+ // Algorithm => key.
+ knownKeys := map[string]KnownKey{}
+ for _, l := range db.lines {
+ if l.match(addrs) {
+ typ := l.knownKey.Key.Type()
+ if _, ok := knownKeys[typ]; !ok {
+ knownKeys[typ] = l.knownKey
+ }
+ }
+ }
+
+ keyErr := &KeyError{}
+ for _, v := range knownKeys {
+ keyErr.Want = append(keyErr.Want, v)
+ }
+
+ // Unknown remote host.
+ if len(knownKeys) == 0 {
+ return keyErr
+ }
+
+ // If the remote host starts using a different, unknown key type, we
+ // also interpret that as a mismatch.
+ if known, ok := knownKeys[remoteKey.Type()]; !ok || !keyEq(known.Key, remoteKey) {
+ return keyErr
+ }
+
+ return nil
+}
+
+// The Read function parses file contents.
+func (db *hostKeyDB) Read(r io.Reader, filename string) error {
+ scanner := bufio.NewScanner(r)
+
+ lineNum := 0
+ for scanner.Scan() {
+ lineNum++
+ line := scanner.Bytes()
+ line = bytes.TrimSpace(line)
+ if len(line) == 0 || line[0] == '#' {
+ continue
+ }
+
+ if err := db.parseLine(line, filename, lineNum); err != nil {
+ return fmt.Errorf("knownhosts: %s:%d: %v", filename, lineNum, err)
+ }
+ }
+ return scanner.Err()
+}
+
+// New creates a host key callback from the given OpenSSH host key
+// files. The returned callback is for use in
+// ssh.ClientConfig.HostKeyCallback. Hashed hostnames are not supported.
+func New(files ...string) (ssh.HostKeyCallback, error) {
+ db := newHostKeyDB()
+ for _, fn := range files {
+ f, err := os.Open(fn)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ if err := db.Read(f, fn); err != nil {
+ return nil, err
+ }
+ }
+
+ var certChecker ssh.CertChecker
+ certChecker.IsHostAuthority = db.IsHostAuthority
+ certChecker.IsRevoked = db.IsRevoked
+ certChecker.HostKeyFallback = db.check
+
+ return certChecker.CheckHostKey, nil
+}
+
+// Normalize normalizes an address into the form used in known_hosts
+func Normalize(address string) string {
+ host, port, err := net.SplitHostPort(address)
+ if err != nil {
+ host = address
+ port = "22"
+ }
+ entry := host
+ if port != "22" {
+ entry = "[" + entry + "]:" + port
+ } else if strings.Contains(host, ":") && !strings.HasPrefix(host, "[") {
+ entry = "[" + entry + "]"
+ }
+ return entry
+}
+
+// Line returns a line to add append to the known_hosts files.
+func Line(addresses []string, key ssh.PublicKey) string {
+ var trimmed []string
+ for _, a := range addresses {
+ trimmed = append(trimmed, Normalize(a))
+ }
+
+ return strings.Join(trimmed, ",") + " " + serialize(key)
+}
+
+// HashHostname hashes the given hostname. The hostname is not
+// normalized before hashing.
+func HashHostname(hostname string) string {
+ // TODO(hanwen): check if we can safely normalize this always.
+ salt := make([]byte, sha1.Size)
+
+ _, err := rand.Read(salt)
+ if err != nil {
+ panic(fmt.Sprintf("crypto/rand failure %v", err))
+ }
+
+ hash := hashHost(hostname, salt)
+ return encodeHash(sha1HashType, salt, hash)
+}
+
+func decodeHash(encoded string) (hashType string, salt, hash []byte, err error) {
+ if len(encoded) == 0 || encoded[0] != '|' {
+ err = errors.New("knownhosts: hashed host must start with '|'")
+ return
+ }
+ components := strings.Split(encoded, "|")
+ if len(components) != 4 {
+ err = fmt.Errorf("knownhosts: got %d components, want 3", len(components))
+ return
+ }
+
+ hashType = components[1]
+ if salt, err = base64.StdEncoding.DecodeString(components[2]); err != nil {
+ return
+ }
+ if hash, err = base64.StdEncoding.DecodeString(components[3]); err != nil {
+ return
+ }
+ return
+}
+
+func encodeHash(typ string, salt []byte, hash []byte) string {
+ return strings.Join([]string{"",
+ typ,
+ base64.StdEncoding.EncodeToString(salt),
+ base64.StdEncoding.EncodeToString(hash),
+ }, "|")
+}
+
+// See https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/hostfile.c#120
+func hashHost(hostname string, salt []byte) []byte {
+ mac := hmac.New(sha1.New, salt)
+ mac.Write([]byte(hostname))
+ return mac.Sum(nil)
+}
+
+type hashedHost struct {
+ salt []byte
+ hash []byte
+}
+
+const sha1HashType = "1"
+
+func newHashedHost(encoded string) (*hashedHost, error) {
+ typ, salt, hash, err := decodeHash(encoded)
+ if err != nil {
+ return nil, err
+ }
+
+ // The type field seems for future algorithm agility, but it's
+ // actually hardcoded in openssh currently, see
+ // https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/hostfile.c#120
+ if typ != sha1HashType {
+ return nil, fmt.Errorf("knownhosts: got hash type %s, must be '1'", typ)
+ }
+
+ return &hashedHost{salt: salt, hash: hash}, nil
+}
+
+func (h *hashedHost) match(addrs []addr) bool {
+ for _, a := range addrs {
+ if bytes.Equal(hashHost(Normalize(a.String()), h.salt), h.hash) {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vendor/golang.org/x/crypto/ssh/mac.go b/vendor/golang.org/x/crypto/ssh/mac.go
index 07744ad6..c07a0628 100644
--- a/vendor/golang.org/x/crypto/ssh/mac.go
+++ b/vendor/golang.org/x/crypto/ssh/mac.go
@@ -15,6 +15,7 @@ import (
type macMode struct {
keySize int
+ etm bool
new func(key []byte) hash.Hash
}
@@ -45,13 +46,16 @@ func (t truncatingMAC) Size() int {
func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
var macModes = map[string]*macMode{
- "hmac-sha2-256": {32, func(key []byte) hash.Hash {
+ "hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash {
return hmac.New(sha256.New, key)
}},
- "hmac-sha1": {20, func(key []byte) hash.Hash {
+ "hmac-sha2-256": {32, false, func(key []byte) hash.Hash {
+ return hmac.New(sha256.New, key)
+ }},
+ "hmac-sha1": {20, false, func(key []byte) hash.Hash {
return hmac.New(sha1.New, key)
}},
- "hmac-sha1-96": {20, func(key []byte) hash.Hash {
+ "hmac-sha1-96": {20, false, func(key []byte) hash.Hash {
return truncatingMAC{12, hmac.New(sha1.New, key)}
}},
}
diff --git a/vendor/golang.org/x/crypto/ssh/messages.go b/vendor/golang.org/x/crypto/ssh/messages.go
index e6ecd3af..c96e1bec 100644
--- a/vendor/golang.org/x/crypto/ssh/messages.go
+++ b/vendor/golang.org/x/crypto/ssh/messages.go
@@ -23,10 +23,6 @@ const (
msgUnimplemented = 3
msgDebug = 4
msgNewKeys = 21
-
- // Standard authentication messages
- msgUserAuthSuccess = 52
- msgUserAuthBanner = 53
)
// SSH messages:
@@ -137,6 +133,18 @@ type userAuthFailureMsg struct {
PartialSuccess bool
}
+// See RFC 4252, section 5.1
+const msgUserAuthSuccess = 52
+
+// See RFC 4252, section 5.4
+const msgUserAuthBanner = 53
+
+type userAuthBannerMsg struct {
+ Message string `sshtype:"53"`
+ // unused, but required to allow message parsing
+ Language string
+}
+
// See RFC 4256, section 3.2
const msgUserAuthInfoRequest = 60
const msgUserAuthInfoResponse = 61
diff --git a/vendor/golang.org/x/crypto/ssh/mux.go b/vendor/golang.org/x/crypto/ssh/mux.go
index f3a3ddd7..27a527c1 100644
--- a/vendor/golang.org/x/crypto/ssh/mux.go
+++ b/vendor/golang.org/x/crypto/ssh/mux.go
@@ -116,9 +116,9 @@ func (m *mux) Wait() error {
func newMux(p packetConn) *mux {
m := &mux{
conn: p,
- incomingChannels: make(chan NewChannel, 16),
+ incomingChannels: make(chan NewChannel, chanSize),
globalResponses: make(chan interface{}, 1),
- incomingRequests: make(chan *Request, 16),
+ incomingRequests: make(chan *Request, chanSize),
errCond: newCond(),
}
if debugMux {
diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go
index 37df1b30..148d2cb2 100644
--- a/vendor/golang.org/x/crypto/ssh/server.go
+++ b/vendor/golang.org/x/crypto/ssh/server.go
@@ -10,26 +10,38 @@ import (
"fmt"
"io"
"net"
+ "strings"
)
// The Permissions type holds fine-grained permissions that are
-// specific to a user or a specific authentication method for a
-// user. Permissions, except for "source-address", must be enforced in
-// the server application layer, after successful authentication. The
-// Permissions are passed on in ServerConn so a server implementation
-// can honor them.
+// specific to a user or a specific authentication method for a user.
+// The Permissions value for a successful authentication attempt is
+// available in ServerConn, so it can be used to pass information from
+// the user-authentication phase to the application layer.
type Permissions struct {
- // Critical options restrict default permissions. Common
- // restrictions are "source-address" and "force-command". If
- // the server cannot enforce the restriction, or does not
- // recognize it, the user should not authenticate.
+ // CriticalOptions indicate restrictions to the default
+ // permissions, and are typically used in conjunction with
+ // user certificates. The standard for SSH certificates
+ // defines "force-command" (only allow the given command to
+ // execute) and "source-address" (only allow connections from
+ // the given address). The SSH package currently only enforces
+ // the "source-address" critical option. It is up to server
+ // implementations to enforce other critical options, such as
+ // "force-command", by checking them after the SSH handshake
+ // is successful. In general, SSH servers should reject
+ // connections that specify critical options that are unknown
+ // or not supported.
CriticalOptions map[string]string
// Extensions are extra functionality that the server may
- // offer on authenticated connections. Common extensions are
- // "permit-agent-forwarding", "permit-X11-forwarding". Lack of
- // support for an extension does not preclude authenticating a
- // user.
+ // offer on authenticated connections. Lack of support for an
+ // extension does not preclude authenticating a user. Common
+ // extensions are "permit-agent-forwarding",
+ // "permit-X11-forwarding". The Go SSH library currently does
+ // not act on any extension, and it is up to server
+ // implementations to honor them. Extensions can be used to
+ // pass data from the authentication callbacks to the server
+ // application layer.
Extensions map[string]string
}
@@ -44,13 +56,24 @@ type ServerConfig struct {
// authenticating.
NoClientAuth bool
+ // MaxAuthTries specifies the maximum number of authentication attempts
+ // permitted per connection. If set to a negative number, the number of
+ // attempts are unlimited. If set to zero, the number of attempts are limited
+ // to 6.
+ MaxAuthTries int
+
// PasswordCallback, if non-nil, is called when a user
// attempts to authenticate using a password.
PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error)
- // PublicKeyCallback, if non-nil, is called when a client attempts public
- // key authentication. It must return true if the given public key is
- // valid for the given user. For example, see CertChecker.Authenticate.
+ // PublicKeyCallback, if non-nil, is called when a client
+ // offers a public key for authentication. It must return a nil error
+ // if the given public key can be used to authenticate the
+ // given user. For example, see CertChecker.Authenticate. A
+ // call to this function does not guarantee that the key
+ // offered is in fact used to authenticate. To record any data
+ // depending on the public key, store it inside a
+ // Permissions.Extensions entry.
PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
// KeyboardInteractiveCallback, if non-nil, is called when
@@ -72,6 +95,10 @@ type ServerConfig struct {
// Note that RFC 4253 section 4.2 requires that this string start with
// "SSH-2.0-".
ServerVersion string
+
+ // BannerCallback, if present, is called and the return string is sent to
+ // the client after key exchange completed but before authentication.
+ BannerCallback func(conn ConnMetadata) string
}
// AddHostKey adds a private key as a host key. If an existing host
@@ -142,6 +169,10 @@ type ServerConn struct {
func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) {
fullConf := *config
fullConf.SetDefaults()
+ if fullConf.MaxAuthTries == 0 {
+ fullConf.MaxAuthTries = 6
+ }
+
s := &connection{
sshConn: sshConn{conn: c},
}
@@ -188,7 +219,7 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */)
s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config)
- if err := s.transport.requestInitialKeyChange(); err != nil {
+ if err := s.transport.waitSession(); err != nil {
return nil, err
}
@@ -231,7 +262,7 @@ func isAcceptableAlgo(algo string) bool {
return false
}
-func checkSourceAddress(addr net.Addr, sourceAddr string) error {
+func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
if addr == nil {
return errors.New("ssh: no address known for client, but source-address match required")
}
@@ -241,33 +272,71 @@ func checkSourceAddress(addr net.Addr, sourceAddr string) error {
return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr)
}
- if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
- if bytes.Equal(allowedIP, tcpAddr.IP) {
- return nil
- }
- } else {
- _, ipNet, err := net.ParseCIDR(sourceAddr)
- if err != nil {
- return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err)
- }
+ for _, sourceAddr := range strings.Split(sourceAddrs, ",") {
+ if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
+ if allowedIP.Equal(tcpAddr.IP) {
+ return nil
+ }
+ } else {
+ _, ipNet, err := net.ParseCIDR(sourceAddr)
+ if err != nil {
+ return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err)
+ }
- if ipNet.Contains(tcpAddr.IP) {
- return nil
+ if ipNet.Contains(tcpAddr.IP) {
+ return nil
+ }
}
}
return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr)
}
+// ServerAuthError implements the error interface. It appends any authentication
+// errors that may occur, and is returned if all of the authentication methods
+// provided by the user failed to authenticate.
+type ServerAuthError struct {
+ // Errors contains authentication errors returned by the authentication
+ // callback methods.
+ Errors []error
+}
+
+func (l ServerAuthError) Error() string {
+ var errs []string
+ for _, err := range l.Errors {
+ errs = append(errs, err.Error())
+ }
+ return "[" + strings.Join(errs, ", ") + "]"
+}
+
func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) {
- var err error
+ sessionID := s.transport.getSessionID()
var cache pubKeyCache
var perms *Permissions
+ authFailures := 0
+ var authErrs []error
+
userAuthLoop:
for {
+ if authFailures >= config.MaxAuthTries && config.MaxAuthTries > 0 {
+ discMsg := &disconnectMsg{
+ Reason: 2,
+ Message: "too many authentication failures",
+ }
+
+ if err := s.transport.writePacket(Marshal(discMsg)); err != nil {
+ return nil, err
+ }
+
+ return nil, discMsg
+ }
+
var userAuthReq userAuthRequestMsg
if packet, err := s.transport.readPacket(); err != nil {
+ if err == io.EOF {
+ return nil, &ServerAuthError{Errors: authErrs}
+ }
return nil, err
} else if err = Unmarshal(packet, &userAuthReq); err != nil {
return nil, err
@@ -278,6 +347,19 @@ userAuthLoop:
}
s.user = userAuthReq.User
+
+ if authFailures == 0 && config.BannerCallback != nil {
+ msg := config.BannerCallback(s)
+ if msg != "" {
+ bannerMsg := &userAuthBannerMsg{
+ Message: msg,
+ }
+ if err := s.transport.writePacket(Marshal(bannerMsg)); err != nil {
+ return nil, err
+ }
+ }
+ }
+
perms = nil
authErr := errors.New("no auth passed yet")
@@ -286,6 +368,11 @@ userAuthLoop:
if config.NoClientAuth {
authErr = nil
}
+
+ // allow initial attempt of 'none' without penalty
+ if authFailures == 0 {
+ authFailures--
+ }
case "password":
if config.PasswordCallback == nil {
authErr = errors.New("ssh: password auth not configured")
@@ -357,6 +444,7 @@ userAuthLoop:
if isQuery {
// The client can query if the given public key
// would be okay.
+
if len(payload) > 0 {
return nil, parseError(msgUserAuthRequest)
}
@@ -385,7 +473,7 @@ userAuthLoop:
if !isAcceptableAlgo(sig.Format) {
break
}
- signedData := buildDataSignedForAuth(s.transport.getSessionID(), userAuthReq, algoBytes, pubKeyData)
+ signedData := buildDataSignedForAuth(sessionID, userAuthReq, algoBytes, pubKeyData)
if err := pubKey.Verify(signedData, sig); err != nil {
return nil, err
@@ -398,6 +486,8 @@ userAuthLoop:
authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method)
}
+ authErrs = append(authErrs, authErr)
+
if config.AuthLogCallback != nil {
config.AuthLogCallback(s, userAuthReq.Method, authErr)
}
@@ -406,6 +496,8 @@ userAuthLoop:
break userAuthLoop
}
+ authFailures++
+
var failureMsg userAuthFailureMsg
if config.PasswordCallback != nil {
failureMsg.Methods = append(failureMsg.Methods, "password")
@@ -421,12 +513,12 @@ userAuthLoop:
return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
}
- if err = s.transport.writePacket(Marshal(&failureMsg)); err != nil {
+ if err := s.transport.writePacket(Marshal(&failureMsg)); err != nil {
return nil, err
}
}
- if err = s.transport.writePacket([]byte{msgUserAuthSuccess}); err != nil {
+ if err := s.transport.writePacket([]byte{msgUserAuthSuccess}); err != nil {
return nil, err
}
return perms, nil
diff --git a/vendor/golang.org/x/crypto/ssh/session.go b/vendor/golang.org/x/crypto/ssh/session.go
index 17e2aa85..cc06e03f 100644
--- a/vendor/golang.org/x/crypto/ssh/session.go
+++ b/vendor/golang.org/x/crypto/ssh/session.go
@@ -231,6 +231,26 @@ func (s *Session) RequestSubsystem(subsystem string) error {
return err
}
+// RFC 4254 Section 6.7.
+type ptyWindowChangeMsg struct {
+ Columns uint32
+ Rows uint32
+ Width uint32
+ Height uint32
+}
+
+// WindowChange informs the remote host about a terminal window dimension change to h rows and w columns.
+func (s *Session) WindowChange(h, w int) error {
+ req := ptyWindowChangeMsg{
+ Columns: uint32(w),
+ Rows: uint32(h),
+ Width: uint32(w * 8),
+ Height: uint32(h * 8),
+ }
+ _, err := s.ch.SendRequest("window-change", false, Marshal(&req))
+ return err
+}
+
// RFC 4254 Section 6.9.
type signalMsg struct {
Signal string
diff --git a/vendor/golang.org/x/crypto/ssh/streamlocal.go b/vendor/golang.org/x/crypto/ssh/streamlocal.go
new file mode 100644
index 00000000..a2dccc64
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/streamlocal.go
@@ -0,0 +1,115 @@
+package ssh
+
+import (
+ "errors"
+ "io"
+ "net"
+)
+
+// streamLocalChannelOpenDirectMsg is a struct used for SSH_MSG_CHANNEL_OPEN message
+// with "direct-streamlocal@openssh.com" string.
+//
+// See openssh-portable/PROTOCOL, section 2.4. connection: Unix domain socket forwarding
+// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL#L235
+type streamLocalChannelOpenDirectMsg struct {
+ socketPath string
+ reserved0 string
+ reserved1 uint32
+}
+
+// forwardedStreamLocalPayload is a struct used for SSH_MSG_CHANNEL_OPEN message
+// with "forwarded-streamlocal@openssh.com" string.
+type forwardedStreamLocalPayload struct {
+ SocketPath string
+ Reserved0 string
+}
+
+// streamLocalChannelForwardMsg is a struct used for SSH2_MSG_GLOBAL_REQUEST message
+// with "streamlocal-forward@openssh.com"/"cancel-streamlocal-forward@openssh.com" string.
+type streamLocalChannelForwardMsg struct {
+ socketPath string
+}
+
+// ListenUnix is similar to ListenTCP but uses a Unix domain socket.
+func (c *Client) ListenUnix(socketPath string) (net.Listener, error) {
+ m := streamLocalChannelForwardMsg{
+ socketPath,
+ }
+ // send message
+ ok, _, err := c.SendRequest("streamlocal-forward@openssh.com", true, Marshal(&m))
+ if err != nil {
+ return nil, err
+ }
+ if !ok {
+ return nil, errors.New("ssh: streamlocal-forward@openssh.com request denied by peer")
+ }
+ ch := c.forwards.add(&net.UnixAddr{Name: socketPath, Net: "unix"})
+
+ return &unixListener{socketPath, c, ch}, nil
+}
+
+func (c *Client) dialStreamLocal(socketPath string) (Channel, error) {
+ msg := streamLocalChannelOpenDirectMsg{
+ socketPath: socketPath,
+ }
+ ch, in, err := c.OpenChannel("direct-streamlocal@openssh.com", Marshal(&msg))
+ if err != nil {
+ return nil, err
+ }
+ go DiscardRequests(in)
+ return ch, err
+}
+
+type unixListener struct {
+ socketPath string
+
+ conn *Client
+ in <-chan forward
+}
+
+// Accept waits for and returns the next connection to the listener.
+func (l *unixListener) Accept() (net.Conn, error) {
+ s, ok := <-l.in
+ if !ok {
+ return nil, io.EOF
+ }
+ ch, incoming, err := s.newCh.Accept()
+ if err != nil {
+ return nil, err
+ }
+ go DiscardRequests(incoming)
+
+ return &chanConn{
+ Channel: ch,
+ laddr: &net.UnixAddr{
+ Name: l.socketPath,
+ Net: "unix",
+ },
+ raddr: &net.UnixAddr{
+ Name: "@",
+ Net: "unix",
+ },
+ }, nil
+}
+
+// Close closes the listener.
+func (l *unixListener) Close() error {
+ // this also closes the listener.
+ l.conn.forwards.remove(&net.UnixAddr{Name: l.socketPath, Net: "unix"})
+ m := streamLocalChannelForwardMsg{
+ l.socketPath,
+ }
+ ok, _, err := l.conn.SendRequest("cancel-streamlocal-forward@openssh.com", true, Marshal(&m))
+ if err == nil && !ok {
+ err = errors.New("ssh: cancel-streamlocal-forward@openssh.com failed")
+ }
+ return err
+}
+
+// Addr returns the listener's network address.
+func (l *unixListener) Addr() net.Addr {
+ return &net.UnixAddr{
+ Name: l.socketPath,
+ Net: "unix",
+ }
+}
diff --git a/vendor/golang.org/x/crypto/ssh/tcpip.go b/vendor/golang.org/x/crypto/ssh/tcpip.go
index 6151241f..acf17175 100644
--- a/vendor/golang.org/x/crypto/ssh/tcpip.go
+++ b/vendor/golang.org/x/crypto/ssh/tcpip.go
@@ -20,12 +20,20 @@ import (
// addr. Incoming connections will be available by calling Accept on
// the returned net.Listener. The listener must be serviced, or the
// SSH connection may hang.
+// N must be "tcp", "tcp4", "tcp6", or "unix".
func (c *Client) Listen(n, addr string) (net.Listener, error) {
- laddr, err := net.ResolveTCPAddr(n, addr)
- if err != nil {
- return nil, err
+ switch n {
+ case "tcp", "tcp4", "tcp6":
+ laddr, err := net.ResolveTCPAddr(n, addr)
+ if err != nil {
+ return nil, err
+ }
+ return c.ListenTCP(laddr)
+ case "unix":
+ return c.ListenUnix(addr)
+ default:
+ return nil, fmt.Errorf("ssh: unsupported protocol: %s", n)
}
- return c.ListenTCP(laddr)
}
// Automatic port allocation is broken with OpenSSH before 6.0. See
@@ -116,7 +124,7 @@ func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) {
}
// Register this forward, using the port number we obtained.
- ch := c.forwards.add(*laddr)
+ ch := c.forwards.add(laddr)
return &tcpListener{laddr, c, ch}, nil
}
@@ -131,7 +139,7 @@ type forwardList struct {
// forwardEntry represents an established mapping of a laddr on a
// remote ssh server to a channel connected to a tcpListener.
type forwardEntry struct {
- laddr net.TCPAddr
+ laddr net.Addr
c chan forward
}
@@ -139,16 +147,16 @@ type forwardEntry struct {
// arguments to add/remove/lookup should be address as specified in
// the original forward-request.
type forward struct {
- newCh NewChannel // the ssh client channel underlying this forward
- raddr *net.TCPAddr // the raddr of the incoming connection
+ newCh NewChannel // the ssh client channel underlying this forward
+ raddr net.Addr // the raddr of the incoming connection
}
-func (l *forwardList) add(addr net.TCPAddr) chan forward {
+func (l *forwardList) add(addr net.Addr) chan forward {
l.Lock()
defer l.Unlock()
f := forwardEntry{
- addr,
- make(chan forward, 1),
+ laddr: addr,
+ c: make(chan forward, 1),
}
l.entries = append(l.entries, f)
return f.c
@@ -176,44 +184,69 @@ func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) {
func (l *forwardList) handleChannels(in <-chan NewChannel) {
for ch := range in {
- var payload forwardedTCPPayload
- if err := Unmarshal(ch.ExtraData(), &payload); err != nil {
- ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error())
- continue
+ var (
+ laddr net.Addr
+ raddr net.Addr
+ err error
+ )
+ switch channelType := ch.ChannelType(); channelType {
+ case "forwarded-tcpip":
+ var payload forwardedTCPPayload
+ if err = Unmarshal(ch.ExtraData(), &payload); err != nil {
+ ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error())
+ continue
+ }
+
+ // RFC 4254 section 7.2 specifies that incoming
+ // addresses should list the address, in string
+ // format. It is implied that this should be an IP
+ // address, as it would be impossible to connect to it
+ // otherwise.
+ laddr, err = parseTCPAddr(payload.Addr, payload.Port)
+ if err != nil {
+ ch.Reject(ConnectionFailed, err.Error())
+ continue
+ }
+ raddr, err = parseTCPAddr(payload.OriginAddr, payload.OriginPort)
+ if err != nil {
+ ch.Reject(ConnectionFailed, err.Error())
+ continue
+ }
+
+ case "forwarded-streamlocal@openssh.com":
+ var payload forwardedStreamLocalPayload
+ if err = Unmarshal(ch.ExtraData(), &payload); err != nil {
+ ch.Reject(ConnectionFailed, "could not parse forwarded-streamlocal@openssh.com payload: "+err.Error())
+ continue
+ }
+ laddr = &net.UnixAddr{
+ Name: payload.SocketPath,
+ Net: "unix",
+ }
+ raddr = &net.UnixAddr{
+ Name: "@",
+ Net: "unix",
+ }
+ default:
+ panic(fmt.Errorf("ssh: unknown channel type %s", channelType))
}
-
- // RFC 4254 section 7.2 specifies that incoming
- // addresses should list the address, in string
- // format. It is implied that this should be an IP
- // address, as it would be impossible to connect to it
- // otherwise.
- laddr, err := parseTCPAddr(payload.Addr, payload.Port)
- if err != nil {
- ch.Reject(ConnectionFailed, err.Error())
- continue
- }
- raddr, err := parseTCPAddr(payload.OriginAddr, payload.OriginPort)
- if err != nil {
- ch.Reject(ConnectionFailed, err.Error())
- continue
- }
-
- if ok := l.forward(*laddr, *raddr, ch); !ok {
+ if ok := l.forward(laddr, raddr, ch); !ok {
// Section 7.2, implementations MUST reject spurious incoming
// connections.
ch.Reject(Prohibited, "no forward for address")
continue
}
+
}
}
// remove removes the forward entry, and the channel feeding its
// listener.
-func (l *forwardList) remove(addr net.TCPAddr) {
+func (l *forwardList) remove(addr net.Addr) {
l.Lock()
defer l.Unlock()
for i, f := range l.entries {
- if addr.IP.Equal(f.laddr.IP) && addr.Port == f.laddr.Port {
+ if addr.Network() == f.laddr.Network() && addr.String() == f.laddr.String() {
l.entries = append(l.entries[:i], l.entries[i+1:]...)
close(f.c)
return
@@ -231,12 +264,12 @@ func (l *forwardList) closeAll() {
l.entries = nil
}
-func (l *forwardList) forward(laddr, raddr net.TCPAddr, ch NewChannel) bool {
+func (l *forwardList) forward(laddr, raddr net.Addr, ch NewChannel) bool {
l.Lock()
defer l.Unlock()
for _, f := range l.entries {
- if laddr.IP.Equal(f.laddr.IP) && laddr.Port == f.laddr.Port {
- f.c <- forward{ch, &raddr}
+ if laddr.Network() == f.laddr.Network() && laddr.String() == f.laddr.String() {
+ f.c <- forward{newCh: ch, raddr: raddr}
return true
}
}
@@ -262,7 +295,7 @@ func (l *tcpListener) Accept() (net.Conn, error) {
}
go DiscardRequests(incoming)
- return &tcpChanConn{
+ return &chanConn{
Channel: ch,
laddr: l.laddr,
raddr: s.raddr,
@@ -277,7 +310,7 @@ func (l *tcpListener) Close() error {
}
// this also closes the listener.
- l.conn.forwards.remove(*l.laddr)
+ l.conn.forwards.remove(l.laddr)
ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m))
if err == nil && !ok {
err = errors.New("ssh: cancel-tcpip-forward failed")
@@ -293,29 +326,52 @@ func (l *tcpListener) Addr() net.Addr {
// Dial initiates a connection to the addr from the remote host.
// The resulting connection has a zero LocalAddr() and RemoteAddr().
func (c *Client) Dial(n, addr string) (net.Conn, error) {
- // Parse the address into host and numeric port.
- host, portString, err := net.SplitHostPort(addr)
- if err != nil {
- return nil, err
- }
- port, err := strconv.ParseUint(portString, 10, 16)
- if err != nil {
- return nil, err
- }
- // Use a zero address for local and remote address.
- zeroAddr := &net.TCPAddr{
- IP: net.IPv4zero,
- Port: 0,
- }
- ch, err := c.dial(net.IPv4zero.String(), 0, host, int(port))
- if err != nil {
- return nil, err
+ var ch Channel
+ switch n {
+ case "tcp", "tcp4", "tcp6":
+ // Parse the address into host and numeric port.
+ host, portString, err := net.SplitHostPort(addr)
+ if err != nil {
+ return nil, err
+ }
+ port, err := strconv.ParseUint(portString, 10, 16)
+ if err != nil {
+ return nil, err
+ }
+ ch, err = c.dial(net.IPv4zero.String(), 0, host, int(port))
+ if err != nil {
+ return nil, err
+ }
+ // Use a zero address for local and remote address.
+ zeroAddr := &net.TCPAddr{
+ IP: net.IPv4zero,
+ Port: 0,
+ }
+ return &chanConn{
+ Channel: ch,
+ laddr: zeroAddr,
+ raddr: zeroAddr,
+ }, nil
+ case "unix":
+ var err error
+ ch, err = c.dialStreamLocal(addr)
+ if err != nil {
+ return nil, err
+ }
+ return &chanConn{
+ Channel: ch,
+ laddr: &net.UnixAddr{
+ Name: "@",
+ Net: "unix",
+ },
+ raddr: &net.UnixAddr{
+ Name: addr,
+ Net: "unix",
+ },
+ }, nil
+ default:
+ return nil, fmt.Errorf("ssh: unsupported protocol: %s", n)
}
- return &tcpChanConn{
- Channel: ch,
- laddr: zeroAddr,
- raddr: zeroAddr,
- }, nil
}
// DialTCP connects to the remote address raddr on the network net,
@@ -332,7 +388,7 @@ func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error)
if err != nil {
return nil, err
}
- return &tcpChanConn{
+ return &chanConn{
Channel: ch,
laddr: laddr,
raddr: raddr,
@@ -366,26 +422,26 @@ type tcpChan struct {
Channel // the backing channel
}
-// tcpChanConn fulfills the net.Conn interface without
+// chanConn fulfills the net.Conn interface without
// the tcpChan having to hold laddr or raddr directly.
-type tcpChanConn struct {
+type chanConn struct {
Channel
laddr, raddr net.Addr
}
// LocalAddr returns the local network address.
-func (t *tcpChanConn) LocalAddr() net.Addr {
+func (t *chanConn) LocalAddr() net.Addr {
return t.laddr
}
// RemoteAddr returns the remote network address.
-func (t *tcpChanConn) RemoteAddr() net.Addr {
+func (t *chanConn) RemoteAddr() net.Addr {
return t.raddr
}
// SetDeadline sets the read and write deadlines associated
// with the connection.
-func (t *tcpChanConn) SetDeadline(deadline time.Time) error {
+func (t *chanConn) SetDeadline(deadline time.Time) error {
if err := t.SetReadDeadline(deadline); err != nil {
return err
}
@@ -396,12 +452,14 @@ func (t *tcpChanConn) SetDeadline(deadline time.Time) error {
// A zero value for t means Read will not time out.
// After the deadline, the error from Read will implement net.Error
// with Timeout() == true.
-func (t *tcpChanConn) SetReadDeadline(deadline time.Time) error {
+func (t *chanConn) SetReadDeadline(deadline time.Time) error {
+ // for compatibility with previous version,
+ // the error message contains "tcpChan"
return errors.New("ssh: tcpChan: deadline not supported")
}
// SetWriteDeadline exists to satisfy the net.Conn interface
// but is not implemented by this type. It always returns an error.
-func (t *tcpChanConn) SetWriteDeadline(deadline time.Time) error {
+func (t *chanConn) SetWriteDeadline(deadline time.Time) error {
return errors.New("ssh: tcpChan: deadline not supported")
}
diff --git a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go
index 741eeb13..18379a93 100644
--- a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go
+++ b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go
@@ -132,8 +132,11 @@ const (
keyPasteEnd
)
-var pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'}
-var pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'}
+var (
+ crlf = []byte{'\r', '\n'}
+ pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'}
+ pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'}
+)
// bytesToKey tries to parse a key sequence from b. If successful, it returns
// the key and the remainder of the input. Otherwise it returns utf8.RuneError.
@@ -333,7 +336,7 @@ func (t *Terminal) advanceCursor(places int) {
// So, if we are stopping at the end of a line, we
// need to write a newline so that our cursor can be
// advanced to the next line.
- t.outBuf = append(t.outBuf, '\n')
+ t.outBuf = append(t.outBuf, '\r', '\n')
}
}
@@ -593,6 +596,35 @@ func (t *Terminal) writeLine(line []rune) {
}
}
+// writeWithCRLF writes buf to w but replaces all occurrences of \n with \r\n.
+func writeWithCRLF(w io.Writer, buf []byte) (n int, err error) {
+ for len(buf) > 0 {
+ i := bytes.IndexByte(buf, '\n')
+ todo := len(buf)
+ if i >= 0 {
+ todo = i
+ }
+
+ var nn int
+ nn, err = w.Write(buf[:todo])
+ n += nn
+ if err != nil {
+ return n, err
+ }
+ buf = buf[todo:]
+
+ if i >= 0 {
+ if _, err = w.Write(crlf); err != nil {
+ return n, err
+ }
+ n += 1
+ buf = buf[1:]
+ }
+ }
+
+ return n, nil
+}
+
func (t *Terminal) Write(buf []byte) (n int, err error) {
t.lock.Lock()
defer t.lock.Unlock()
@@ -600,7 +632,7 @@ func (t *Terminal) Write(buf []byte) (n int, err error) {
if t.cursorX == 0 && t.cursorY == 0 {
// This is the easy case: there's nothing on the screen that we
// have to move out of the way.
- return t.c.Write(buf)
+ return writeWithCRLF(t.c, buf)
}
// We have a prompt and possibly user input on the screen. We
@@ -620,7 +652,7 @@ func (t *Terminal) Write(buf []byte) (n int, err error) {
}
t.outBuf = t.outBuf[:0]
- if n, err = t.c.Write(buf); err != nil {
+ if n, err = writeWithCRLF(t.c, buf); err != nil {
return
}
@@ -740,8 +772,6 @@ func (t *Terminal) readLine() (line string, err error) {
t.remainder = t.inBuf[:n+len(t.remainder)]
}
-
- panic("unreachable") // for Go 1.0.
}
// SetPrompt sets the prompt to be used when reading subsequent lines.
@@ -890,3 +920,32 @@ func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) {
}
return s.entries[index], true
}
+
+// readPasswordLine reads from reader until it finds \n or io.EOF.
+// The slice returned does not include the \n.
+// readPasswordLine also ignores any \r it finds.
+func readPasswordLine(reader io.Reader) ([]byte, error) {
+ var buf [1]byte
+ var ret []byte
+
+ for {
+ n, err := reader.Read(buf[:])
+ if n > 0 {
+ switch buf[0] {
+ case '\n':
+ return ret, nil
+ case '\r':
+ // remove \r from passwords on Windows
+ default:
+ ret = append(ret, buf[0])
+ }
+ continue
+ }
+ if err != nil {
+ if err == io.EOF && len(ret) > 0 {
+ return ret, nil
+ }
+ return ret, err
+ }
+ }
+}
diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util.go b/vendor/golang.org/x/crypto/ssh/terminal/util.go
index c869213e..02dad484 100644
--- a/vendor/golang.org/x/crypto/ssh/terminal/util.go
+++ b/vendor/golang.org/x/crypto/ssh/terminal/util.go
@@ -17,41 +17,41 @@
package terminal // import "golang.org/x/crypto/ssh/terminal"
import (
- "io"
- "syscall"
- "unsafe"
+ "golang.org/x/sys/unix"
)
// State contains the state of a terminal.
type State struct {
- termios syscall.Termios
+ termios unix.Termios
}
// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd int) bool {
- var termios syscall.Termios
- _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
- return err == 0
+ _, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
+ return err == nil
}
// MakeRaw put the terminal connected to the given file descriptor into raw
// mode and returns the previous state of the terminal so that it can be
// restored.
func MakeRaw(fd int) (*State, error) {
- var oldState State
- if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 {
+ termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
+ if err != nil {
return nil, err
}
- newState := oldState.termios
+ oldState := State{termios: *termios}
+
// This attempts to replicate the behaviour documented for cfmakeraw in
// the termios(3) manpage.
- newState.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON
- newState.Oflag &^= syscall.OPOST
- newState.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN
- newState.Cflag &^= syscall.CSIZE | syscall.PARENB
- newState.Cflag |= syscall.CS8
- if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
+ termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
+ termios.Oflag &^= unix.OPOST
+ termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
+ termios.Cflag &^= unix.CSIZE | unix.PARENB
+ termios.Cflag |= unix.CS8
+ termios.Cc[unix.VMIN] = 1
+ termios.Cc[unix.VTIME] = 0
+ if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil {
return nil, err
}
@@ -61,73 +61,56 @@ func MakeRaw(fd int) (*State, error) {
// GetState returns the current state of a terminal which may be useful to
// restore the terminal after a signal.
func GetState(fd int) (*State, error) {
- var oldState State
- if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 {
+ termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
+ if err != nil {
return nil, err
}
- return &oldState, nil
+ return &State{termios: *termios}, nil
}
// Restore restores the terminal connected to the given file descriptor to a
// previous state.
func Restore(fd int, state *State) error {
- _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0)
- return err
+ return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios)
}
// GetSize returns the dimensions of the given terminal.
func GetSize(fd int) (width, height int, err error) {
- var dimensions [4]uint16
-
- if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 {
+ ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
+ if err != nil {
return -1, -1, err
}
- return int(dimensions[1]), int(dimensions[0]), nil
+ return int(ws.Col), int(ws.Row), nil
+}
+
+// passwordReader is an io.Reader that reads from a specific file descriptor.
+type passwordReader int
+
+func (r passwordReader) Read(buf []byte) (int, error) {
+ return unix.Read(int(r), buf)
}
// ReadPassword reads a line of input from a terminal without local echo. This
// is commonly used for inputting passwords and other sensitive data. The slice
// returned does not include the \n.
func ReadPassword(fd int) ([]byte, error) {
- var oldState syscall.Termios
- if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); err != 0 {
+ termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
+ if err != nil {
return nil, err
}
- newState := oldState
- newState.Lflag &^= syscall.ECHO
- newState.Lflag |= syscall.ICANON | syscall.ISIG
- newState.Iflag |= syscall.ICRNL
- if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
+ newState := *termios
+ newState.Lflag &^= unix.ECHO
+ newState.Lflag |= unix.ICANON | unix.ISIG
+ newState.Iflag |= unix.ICRNL
+ if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil {
return nil, err
}
defer func() {
- syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0)
+ unix.IoctlSetTermios(fd, ioctlWriteTermios, termios)
}()
- var buf [16]byte
- var ret []byte
- for {
- n, err := syscall.Read(fd, buf[:])
- if err != nil {
- return nil, err
- }
- if n == 0 {
- if len(ret) == 0 {
- return nil, io.EOF
- }
- break
- }
- if buf[n-1] == '\n' {
- n--
- }
- ret = append(ret, buf[:n]...)
- if n < len(buf) {
- break
- }
- }
-
- return ret, nil
+ return readPasswordLine(passwordReader(fd))
}
diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go b/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go
index 9c1ffd14..cb23a590 100644
--- a/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go
+++ b/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go
@@ -6,7 +6,7 @@
package terminal
-import "syscall"
+import "golang.org/x/sys/unix"
-const ioctlReadTermios = syscall.TIOCGETA
-const ioctlWriteTermios = syscall.TIOCSETA
+const ioctlReadTermios = unix.TIOCGETA
+const ioctlWriteTermios = unix.TIOCSETA
diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go b/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go
index 5883b22d..5fadfe8a 100644
--- a/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go
+++ b/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go
@@ -4,8 +4,7 @@
package terminal
-// These constants are declared here, rather than importing
-// them from the syscall package as some syscall packages, even
-// on linux, for example gccgo, do not declare them.
-const ioctlReadTermios = 0x5401 // syscall.TCGETS
-const ioctlWriteTermios = 0x5402 // syscall.TCSETS
+import "golang.org/x/sys/unix"
+
+const ioctlReadTermios = unix.TCGETS
+const ioctlWriteTermios = unix.TCSETS
diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go b/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go
index 07eb5edd..a2e1b57d 100644
--- a/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go
+++ b/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go
@@ -14,14 +14,12 @@ import (
// State contains the state of a terminal.
type State struct {
- termios syscall.Termios
+ state *unix.Termios
}
// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd int) bool {
- // see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c
- var termio unix.Termio
- err := unix.IoctlSetTermio(fd, unix.TCGETA, &termio)
+ _, err := unix.IoctlGetTermio(fd, unix.TCGETA)
return err == nil
}
@@ -71,3 +69,60 @@ func ReadPassword(fd int) ([]byte, error) {
return ret, nil
}
+
+// MakeRaw puts the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+// see http://cr.illumos.org/~webrev/andy_js/1060/
+func MakeRaw(fd int) (*State, error) {
+ oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS)
+ if err != nil {
+ return nil, err
+ }
+ oldTermios := *oldTermiosPtr
+
+ newTermios := oldTermios
+ newTermios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON
+ newTermios.Oflag &^= syscall.OPOST
+ newTermios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN
+ newTermios.Cflag &^= syscall.CSIZE | syscall.PARENB
+ newTermios.Cflag |= syscall.CS8
+ newTermios.Cc[unix.VMIN] = 1
+ newTermios.Cc[unix.VTIME] = 0
+
+ if err := unix.IoctlSetTermios(fd, unix.TCSETS, &newTermios); err != nil {
+ return nil, err
+ }
+
+ return &State{
+ state: oldTermiosPtr,
+ }, nil
+}
+
+// Restore restores the terminal connected to the given file descriptor to a
+// previous state.
+func Restore(fd int, oldState *State) error {
+ return unix.IoctlSetTermios(fd, unix.TCSETS, oldState.state)
+}
+
+// GetState returns the current state of a terminal which may be useful to
+// restore the terminal after a signal.
+func GetState(fd int) (*State, error) {
+ oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS)
+ if err != nil {
+ return nil, err
+ }
+
+ return &State{
+ state: oldTermiosPtr,
+ }, nil
+}
+
+// GetSize returns the dimensions of the given terminal.
+func GetSize(fd int) (width, height int, err error) {
+ ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
+ if err != nil {
+ return 0, 0, err
+ }
+ return int(ws.Col), int(ws.Row), nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
index ae9fa9ec..60979ccd 100644
--- a/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
+++ b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
@@ -17,54 +17,7 @@
package terminal
import (
- "io"
- "syscall"
- "unsafe"
-)
-
-const (
- enableLineInput = 2
- enableEchoInput = 4
- enableProcessedInput = 1
- enableWindowInput = 8
- enableMouseInput = 16
- enableInsertMode = 32
- enableQuickEditMode = 64
- enableExtendedFlags = 128
- enableAutoPosition = 256
- enableProcessedOutput = 1
- enableWrapAtEolOutput = 2
-)
-
-var kernel32 = syscall.NewLazyDLL("kernel32.dll")
-
-var (
- procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
- procSetConsoleMode = kernel32.NewProc("SetConsoleMode")
- procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
-)
-
-type (
- short int16
- word uint16
-
- coord struct {
- x short
- y short
- }
- smallRect struct {
- left short
- top short
- right short
- bottom short
- }
- consoleScreenBufferInfo struct {
- size coord
- cursorPosition coord
- attributes word
- window smallRect
- maximumWindowSize coord
- }
+ "golang.org/x/sys/windows"
)
type State struct {
@@ -74,8 +27,8 @@ type State struct {
// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd int) bool {
var st uint32
- r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
- return r != 0 && e == 0
+ err := windows.GetConsoleMode(windows.Handle(fd), &st)
+ return err == nil
}
// MakeRaw put the terminal connected to the given file descriptor into raw
@@ -83,14 +36,12 @@ func IsTerminal(fd int) bool {
// restored.
func MakeRaw(fd int) (*State, error) {
var st uint32
- _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
- if e != 0 {
- return nil, error(e)
+ if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
+ return nil, err
}
- raw := st &^ (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput)
- _, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(raw), 0)
- if e != 0 {
- return nil, error(e)
+ raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
+ if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil {
+ return nil, err
}
return &State{st}, nil
}
@@ -99,9 +50,8 @@ func MakeRaw(fd int) (*State, error) {
// restore the terminal after a signal.
func GetState(fd int) (*State, error) {
var st uint32
- _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
- if e != 0 {
- return nil, error(e)
+ if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
+ return nil, err
}
return &State{st}, nil
}
@@ -109,18 +59,23 @@ func GetState(fd int) (*State, error) {
// Restore restores the terminal connected to the given file descriptor to a
// previous state.
func Restore(fd int, state *State) error {
- _, _, err := syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(state.mode), 0)
- return err
+ return windows.SetConsoleMode(windows.Handle(fd), state.mode)
}
// GetSize returns the dimensions of the given terminal.
func GetSize(fd int) (width, height int, err error) {
- var info consoleScreenBufferInfo
- _, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&info)), 0)
- if e != 0 {
- return 0, 0, error(e)
+ var info windows.ConsoleScreenBufferInfo
+ if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
+ return 0, 0, err
}
- return int(info.size.x), int(info.size.y), nil
+ return int(info.Size.X), int(info.Size.Y), nil
+}
+
+// passwordReader is an io.Reader that reads from a specific Windows HANDLE.
+type passwordReader int
+
+func (r passwordReader) Read(buf []byte) (int, error) {
+ return windows.Read(windows.Handle(r), buf)
}
// ReadPassword reads a line of input from a terminal without local echo. This
@@ -128,47 +83,20 @@ func GetSize(fd int) (width, height int, err error) {
// returned does not include the \n.
func ReadPassword(fd int) ([]byte, error) {
var st uint32
- _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
- if e != 0 {
- return nil, error(e)
+ if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
+ return nil, err
}
old := st
- st &^= (enableEchoInput)
- st |= (enableProcessedInput | enableLineInput | enableProcessedOutput)
- _, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(st), 0)
- if e != 0 {
- return nil, error(e)
+ st &^= (windows.ENABLE_ECHO_INPUT)
+ st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
+ if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil {
+ return nil, err
}
defer func() {
- syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(old), 0)
+ windows.SetConsoleMode(windows.Handle(fd), old)
}()
- var buf [16]byte
- var ret []byte
- for {
- n, err := syscall.Read(syscall.Handle(fd), buf[:])
- if err != nil {
- return nil, err
- }
- if n == 0 {
- if len(ret) == 0 {
- return nil, io.EOF
- }
- break
- }
- if buf[n-1] == '\n' {
- n--
- }
- if n > 0 && buf[n-1] == '\r' {
- n--
- }
- ret = append(ret, buf[:n]...)
- if n < len(buf) {
- break
- }
- }
-
- return ret, nil
+ return readPasswordLine(passwordReader(fd))
}
diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go
index 62fba629..ab2b8876 100644
--- a/vendor/golang.org/x/crypto/ssh/transport.go
+++ b/vendor/golang.org/x/crypto/ssh/transport.go
@@ -8,8 +8,13 @@ import (
"bufio"
"errors"
"io"
+ "log"
)
+// debugTransport if set, will print packet types as they go over the
+// wire. No message decoding is done, to minimize the impact on timing.
+const debugTransport = false
+
const (
gcmCipherID = "aes128-gcm@openssh.com"
aes128cbcID = "aes128-cbc"
@@ -22,7 +27,9 @@ type packetConn interface {
// Encrypt and send a packet of data to the remote peer.
writePacket(packet []byte) error
- // Read a packet from the connection
+ // Read a packet from the connection. The read is blocking,
+ // i.e. if error is nil, then the returned byte slice is
+ // always non-empty.
readPacket() ([]byte, error)
// Close closes the write-side of the connection.
@@ -38,7 +45,7 @@ type transport struct {
bufReader *bufio.Reader
bufWriter *bufio.Writer
rand io.Reader
-
+ isClient bool
io.Closer
}
@@ -84,9 +91,38 @@ func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) err
return nil
}
+func (t *transport) printPacket(p []byte, write bool) {
+ if len(p) == 0 {
+ return
+ }
+ who := "server"
+ if t.isClient {
+ who = "client"
+ }
+ what := "read"
+ if write {
+ what = "write"
+ }
+
+ log.Println(what, who, p[0])
+}
+
// Read and decrypt next packet.
-func (t *transport) readPacket() ([]byte, error) {
- return t.reader.readPacket(t.bufReader)
+func (t *transport) readPacket() (p []byte, err error) {
+ for {
+ p, err = t.reader.readPacket(t.bufReader)
+ if err != nil {
+ break
+ }
+ if len(p) == 0 || (p[0] != msgIgnore && p[0] != msgDebug) {
+ break
+ }
+ }
+ if debugTransport {
+ t.printPacket(p, false)
+ }
+
+ return p, err
}
func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
@@ -129,6 +165,9 @@ func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
}
func (t *transport) writePacket(packet []byte) error {
+ if debugTransport {
+ t.printPacket(packet, true)
+ }
return t.writer.writePacket(t.bufWriter, t.rand, packet)
}
@@ -169,6 +208,8 @@ func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool) *transp
},
Closer: rwc,
}
+ t.isClient = isClient
+
if isClient {
t.reader.dir = serverKeys
t.writer.dir = clientKeys
@@ -213,7 +254,7 @@ func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (pac
iv, key, macKey := generateKeys(d, algs, kex)
if algs.Cipher == gcmCipherID {
- return newGCMCipher(iv, key, macKey)
+ return newGCMCipher(iv, key)
}
if algs.Cipher == aes128cbcID {
@@ -226,6 +267,7 @@ func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (pac
c := &streamPacketCipher{
mac: macModes[algs.MAC].new(macKey),
+ etm: macModes[algs.MAC].etm,
}
c.macResult = make([]byte, c.mac.Size())
diff --git a/vendor/golang.org/x/net/http2/h2demo/h2demo.go b/vendor/golang.org/x/net/http2/h2demo/h2demo.go
new file mode 100644
index 00000000..980b6d67
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/h2demo/h2demo.go
@@ -0,0 +1,486 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build h2demo
+
+package main
+
+import (
+ "bytes"
+ "crypto/tls"
+ "flag"
+ "fmt"
+ "hash/crc32"
+ "image"
+ "image/jpeg"
+ "io"
+ "io/ioutil"
+ "log"
+ "net"
+ "net/http"
+ "os"
+ "path"
+ "regexp"
+ "runtime"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "go4.org/syncutil/singleflight"
+ "golang.org/x/crypto/acme/autocert"
+ "golang.org/x/net/http2"
+)
+
+var (
+ prod = flag.Bool("prod", false, "Whether to configure itself to be the production http2.golang.org server.")
+
+ httpsAddr = flag.String("https_addr", "localhost:4430", "TLS address to listen on ('host:port' or ':port'). Required.")
+ httpAddr = flag.String("http_addr", "", "Plain HTTP address to listen on ('host:port', or ':port'). Empty means no HTTP.")
+
+ hostHTTP = flag.String("http_host", "", "Optional host or host:port to use for http:// links to this service. By default, this is implied from -http_addr.")
+ hostHTTPS = flag.String("https_host", "", "Optional host or host:port to use for http:// links to this service. By default, this is implied from -https_addr.")
+)
+
+func homeOldHTTP(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, `
+
+Go + HTTP/2
+Welcome to the Go language's HTTP/2 demo & interop server.
+Unfortunately, you're not using HTTP/2 right now. To do so:
+
+ - Use Firefox Nightly or go to about:config and enable "network.http.spdy.enabled.http2draft"
+ - Use Google Chrome Canary and/or go to chrome://flags/#enable-spdy4 to Enable SPDY/4 (Chrome's name for HTTP/2)
+
+See code & instructions for connecting at https://github.com/golang/net/tree/master/http2.
+
+`)
+}
+
+func home(w http.ResponseWriter, r *http.Request) {
+ if r.URL.Path != "/" {
+ http.NotFound(w, r)
+ return
+ }
+ io.WriteString(w, `
+
+Go + HTTP/2
+
+Welcome to the Go language's HTTP/2 demo & interop server.
+
+Congratulations, you're using HTTP/2 right now.
+
+This server exists for others in the HTTP/2 community to test their HTTP/2 client implementations and point out flaws in our server.
+
+
+The code is at golang.org/x/net/http2 and
+is used transparently by the Go standard library from Go 1.6 and later.
+
+
+Contact info: bradfitz@golang.org, or file a bug.
+
+Handlers for testing
+
+ - GET /reqinfo to dump the request + headers received
+ - GET /clockstream streams the current time every second
+ - GET /gophertiles to see a page with a bunch of images
+ - GET /file/gopher.png for a small file (does If-Modified-Since, Content-Range, etc)
+ - GET /file/go.src.tar.gz for a larger file (~10 MB)
+ - GET /redirect to redirect back to / (this page)
+ - GET /goroutines to see all active goroutines in this server
+ - PUT something to /crc32 to get a count of number of bytes and its CRC-32
+ - PUT something to /ECHO and it will be streamed back to you capitalized
+
+
+`)
+}
+
+func reqInfoHandler(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "text/plain")
+ fmt.Fprintf(w, "Method: %s\n", r.Method)
+ fmt.Fprintf(w, "Protocol: %s\n", r.Proto)
+ fmt.Fprintf(w, "Host: %s\n", r.Host)
+ fmt.Fprintf(w, "RemoteAddr: %s\n", r.RemoteAddr)
+ fmt.Fprintf(w, "RequestURI: %q\n", r.RequestURI)
+ fmt.Fprintf(w, "URL: %#v\n", r.URL)
+ fmt.Fprintf(w, "Body.ContentLength: %d (-1 means unknown)\n", r.ContentLength)
+ fmt.Fprintf(w, "Close: %v (relevant for HTTP/1 only)\n", r.Close)
+ fmt.Fprintf(w, "TLS: %#v\n", r.TLS)
+ fmt.Fprintf(w, "\nHeaders:\n")
+ r.Header.Write(w)
+}
+
+func crcHandler(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "PUT" {
+ http.Error(w, "PUT required.", 400)
+ return
+ }
+ crc := crc32.NewIEEE()
+ n, err := io.Copy(crc, r.Body)
+ if err == nil {
+ w.Header().Set("Content-Type", "text/plain")
+ fmt.Fprintf(w, "bytes=%d, CRC32=%x", n, crc.Sum(nil))
+ }
+}
+
+type capitalizeReader struct {
+ r io.Reader
+}
+
+func (cr capitalizeReader) Read(p []byte) (n int, err error) {
+ n, err = cr.r.Read(p)
+ for i, b := range p[:n] {
+ if b >= 'a' && b <= 'z' {
+ p[i] = b - ('a' - 'A')
+ }
+ }
+ return
+}
+
+type flushWriter struct {
+ w io.Writer
+}
+
+func (fw flushWriter) Write(p []byte) (n int, err error) {
+ n, err = fw.w.Write(p)
+ if f, ok := fw.w.(http.Flusher); ok {
+ f.Flush()
+ }
+ return
+}
+
+func echoCapitalHandler(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "PUT" {
+ http.Error(w, "PUT required.", 400)
+ return
+ }
+ io.Copy(flushWriter{w}, capitalizeReader{r.Body})
+}
+
+var (
+ fsGrp singleflight.Group
+ fsMu sync.Mutex // guards fsCache
+ fsCache = map[string]http.Handler{}
+)
+
+// fileServer returns a file-serving handler that proxies URL.
+// It lazily fetches URL on the first access and caches its contents forever.
+func fileServer(url string) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ hi, err := fsGrp.Do(url, func() (interface{}, error) {
+ fsMu.Lock()
+ if h, ok := fsCache[url]; ok {
+ fsMu.Unlock()
+ return h, nil
+ }
+ fsMu.Unlock()
+
+ res, err := http.Get(url)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ modTime := time.Now()
+ var h http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ http.ServeContent(w, r, path.Base(url), modTime, bytes.NewReader(slurp))
+ })
+ fsMu.Lock()
+ fsCache[url] = h
+ fsMu.Unlock()
+ return h, nil
+ })
+ if err != nil {
+ http.Error(w, err.Error(), 500)
+ return
+ }
+ hi.(http.Handler).ServeHTTP(w, r)
+ })
+}
+
+func clockStreamHandler(w http.ResponseWriter, r *http.Request) {
+ clientGone := w.(http.CloseNotifier).CloseNotify()
+ w.Header().Set("Content-Type", "text/plain")
+ ticker := time.NewTicker(1 * time.Second)
+ defer ticker.Stop()
+ fmt.Fprintf(w, "# ~1KB of junk to force browsers to start rendering immediately: \n")
+ io.WriteString(w, strings.Repeat("# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n", 13))
+
+ for {
+ fmt.Fprintf(w, "%v\n", time.Now())
+ w.(http.Flusher).Flush()
+ select {
+ case <-ticker.C:
+ case <-clientGone:
+ log.Printf("Client %v disconnected from the clock", r.RemoteAddr)
+ return
+ }
+ }
+}
+
+func registerHandlers() {
+ tiles := newGopherTilesHandler()
+
+ mux2 := http.NewServeMux()
+ http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ if r.TLS == nil {
+ if r.URL.Path == "/gophertiles" {
+ tiles.ServeHTTP(w, r)
+ return
+ }
+ http.Redirect(w, r, "https://"+httpsHost()+"/", http.StatusFound)
+ return
+ }
+ if r.ProtoMajor == 1 {
+ if r.URL.Path == "/reqinfo" {
+ reqInfoHandler(w, r)
+ return
+ }
+ homeOldHTTP(w, r)
+ return
+ }
+ mux2.ServeHTTP(w, r)
+ })
+ mux2.HandleFunc("/", home)
+ mux2.Handle("/file/gopher.png", fileServer("https://golang.org/doc/gopher/frontpage.png"))
+ mux2.Handle("/file/go.src.tar.gz", fileServer("https://storage.googleapis.com/golang/go1.4.1.src.tar.gz"))
+ mux2.HandleFunc("/reqinfo", reqInfoHandler)
+ mux2.HandleFunc("/crc32", crcHandler)
+ mux2.HandleFunc("/ECHO", echoCapitalHandler)
+ mux2.HandleFunc("/clockstream", clockStreamHandler)
+ mux2.Handle("/gophertiles", tiles)
+ mux2.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) {
+ http.Redirect(w, r, "/", http.StatusFound)
+ })
+ stripHomedir := regexp.MustCompile(`/(Users|home)/\w+`)
+ mux2.HandleFunc("/goroutines", func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+ buf := make([]byte, 2<<20)
+ w.Write(stripHomedir.ReplaceAll(buf[:runtime.Stack(buf, true)], nil))
+ })
+}
+
+func newGopherTilesHandler() http.Handler {
+ const gopherURL = "https://blog.golang.org/go-programming-language-turns-two_gophers.jpg"
+ res, err := http.Get(gopherURL)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if res.StatusCode != 200 {
+ log.Fatalf("Error fetching %s: %v", gopherURL, res.Status)
+ }
+ slurp, err := ioutil.ReadAll(res.Body)
+ res.Body.Close()
+ if err != nil {
+ log.Fatal(err)
+ }
+ im, err := jpeg.Decode(bytes.NewReader(slurp))
+ if err != nil {
+ if len(slurp) > 1024 {
+ slurp = slurp[:1024]
+ }
+ log.Fatalf("Failed to decode gopher image: %v (got %q)", err, slurp)
+ }
+
+ type subImager interface {
+ SubImage(image.Rectangle) image.Image
+ }
+ const tileSize = 32
+ xt := im.Bounds().Max.X / tileSize
+ yt := im.Bounds().Max.Y / tileSize
+ var tile [][][]byte // y -> x -> jpeg bytes
+ for yi := 0; yi < yt; yi++ {
+ var row [][]byte
+ for xi := 0; xi < xt; xi++ {
+ si := im.(subImager).SubImage(image.Rectangle{
+ Min: image.Point{xi * tileSize, yi * tileSize},
+ Max: image.Point{(xi + 1) * tileSize, (yi + 1) * tileSize},
+ })
+ buf := new(bytes.Buffer)
+ if err := jpeg.Encode(buf, si, &jpeg.Options{Quality: 90}); err != nil {
+ log.Fatal(err)
+ }
+ row = append(row, buf.Bytes())
+ }
+ tile = append(tile, row)
+ }
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ ms, _ := strconv.Atoi(r.FormValue("latency"))
+ const nanosPerMilli = 1e6
+ if r.FormValue("x") != "" {
+ x, _ := strconv.Atoi(r.FormValue("x"))
+ y, _ := strconv.Atoi(r.FormValue("y"))
+ if ms <= 1000 {
+ time.Sleep(time.Duration(ms) * nanosPerMilli)
+ }
+ if x >= 0 && x < xt && y >= 0 && y < yt {
+ http.ServeContent(w, r, "", time.Time{}, bytes.NewReader(tile[y][x]))
+ return
+ }
+ }
+ io.WriteString(w, "")
+ fmt.Fprintf(w, "A grid of %d tiled images is below. Compare:", xt*yt)
+ for _, ms := range []int{0, 30, 200, 1000} {
+ d := time.Duration(ms) * nanosPerMilli
+ fmt.Fprintf(w, "[HTTP/2, %v latency] [HTTP/1, %v latency]
\n",
+ httpsHost(), ms, d,
+ httpHost(), ms, d,
+ )
+ }
+ io.WriteString(w, "
\n")
+ cacheBust := time.Now().UnixNano()
+ for y := 0; y < yt; y++ {
+ for x := 0; x < xt; x++ {
+ fmt.Fprintf(w, "
",
+ tileSize, tileSize, x, y, cacheBust, ms)
+ }
+ io.WriteString(w, "
\n")
+ }
+ io.WriteString(w, `
+
+
<< Back to Go HTTP/2 demo server`)
+ })
+}
+
+func httpsHost() string {
+ if *hostHTTPS != "" {
+ return *hostHTTPS
+ }
+ if v := *httpsAddr; strings.HasPrefix(v, ":") {
+ return "localhost" + v
+ } else {
+ return v
+ }
+}
+
+func httpHost() string {
+ if *hostHTTP != "" {
+ return *hostHTTP
+ }
+ if v := *httpAddr; strings.HasPrefix(v, ":") {
+ return "localhost" + v
+ } else {
+ return v
+ }
+}
+
+func serveProdTLS() error {
+ const cacheDir = "/var/cache/autocert"
+ if err := os.MkdirAll(cacheDir, 0700); err != nil {
+ return err
+ }
+ m := autocert.Manager{
+ Cache: autocert.DirCache(cacheDir),
+ Prompt: autocert.AcceptTOS,
+ HostPolicy: autocert.HostWhitelist("http2.golang.org"),
+ }
+ srv := &http.Server{
+ TLSConfig: &tls.Config{
+ GetCertificate: m.GetCertificate,
+ },
+ }
+ http2.ConfigureServer(srv, &http2.Server{})
+ ln, err := net.Listen("tcp", ":443")
+ if err != nil {
+ return err
+ }
+ return srv.Serve(tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, srv.TLSConfig))
+}
+
+type tcpKeepAliveListener struct {
+ *net.TCPListener
+}
+
+func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
+ tc, err := ln.AcceptTCP()
+ if err != nil {
+ return
+ }
+ tc.SetKeepAlive(true)
+ tc.SetKeepAlivePeriod(3 * time.Minute)
+ return tc, nil
+}
+
+func serveProd() error {
+ errc := make(chan error, 2)
+ go func() { errc <- http.ListenAndServe(":80", nil) }()
+ go func() { errc <- serveProdTLS() }()
+ return <-errc
+}
+
+const idleTimeout = 5 * time.Minute
+const activeTimeout = 10 * time.Minute
+
+// TODO: put this into the standard library and actually send
+// PING frames and GOAWAY, etc: golang.org/issue/14204
+func idleTimeoutHook() func(net.Conn, http.ConnState) {
+ var mu sync.Mutex
+ m := map[net.Conn]*time.Timer{}
+ return func(c net.Conn, cs http.ConnState) {
+ mu.Lock()
+ defer mu.Unlock()
+ if t, ok := m[c]; ok {
+ delete(m, c)
+ t.Stop()
+ }
+ var d time.Duration
+ switch cs {
+ case http.StateNew, http.StateIdle:
+ d = idleTimeout
+ case http.StateActive:
+ d = activeTimeout
+ default:
+ return
+ }
+ m[c] = time.AfterFunc(d, func() {
+ log.Printf("closing idle conn %v after %v", c.RemoteAddr(), d)
+ go c.Close()
+ })
+ }
+}
+
+func main() {
+ var srv http.Server
+ flag.BoolVar(&http2.VerboseLogs, "verbose", false, "Verbose HTTP/2 debugging.")
+ flag.Parse()
+ srv.Addr = *httpsAddr
+ srv.ConnState = idleTimeoutHook()
+
+ registerHandlers()
+
+ if *prod {
+ *hostHTTP = "http2.golang.org"
+ *hostHTTPS = "http2.golang.org"
+ log.Fatal(serveProd())
+ }
+
+ url := "https://" + httpsHost() + "/"
+ log.Printf("Listening on " + url)
+ http2.ConfigureServer(&srv, &http2.Server{})
+
+ if *httpAddr != "" {
+ go func() {
+ log.Printf("Listening on http://" + httpHost() + "/ (for unencrypted HTTP/1)")
+ log.Fatal(http.ListenAndServe(*httpAddr, nil))
+ }()
+ }
+
+ go func() {
+ log.Fatal(srv.ListenAndServeTLS("server.crt", "server.key"))
+ }()
+ select {}
+}
diff --git a/vendor/golang.org/x/net/http2/h2demo/launch.go b/vendor/golang.org/x/net/http2/h2demo/launch.go
new file mode 100644
index 00000000..df0866a3
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/h2demo/launch.go
@@ -0,0 +1,302 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "os"
+ "strings"
+ "time"
+
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/google"
+ compute "google.golang.org/api/compute/v1"
+)
+
+var (
+ proj = flag.String("project", "symbolic-datum-552", "name of Project")
+ zone = flag.String("zone", "us-central1-a", "GCE zone")
+ mach = flag.String("machinetype", "n1-standard-1", "Machine type")
+ instName = flag.String("instance_name", "http2-demo", "Name of VM instance.")
+ sshPub = flag.String("ssh_public_key", "", "ssh public key file to authorize. Can modify later in Google's web UI anyway.")
+ staticIP = flag.String("static_ip", "130.211.116.44", "Static IP to use. If empty, automatic.")
+
+ writeObject = flag.String("write_object", "", "If non-empty, a VM isn't created and the flag value is Google Cloud Storage bucket/object to write. The contents from stdin.")
+ publicObject = flag.Bool("write_object_is_public", false, "Whether the object created by --write_object should be public.")
+)
+
+func readFile(v string) string {
+ slurp, err := ioutil.ReadFile(v)
+ if err != nil {
+ log.Fatalf("Error reading %s: %v", v, err)
+ }
+ return strings.TrimSpace(string(slurp))
+}
+
+var config = &oauth2.Config{
+ // The client-id and secret should be for an "Installed Application" when using
+ // the CLI. Later we'll use a web application with a callback.
+ ClientID: readFile("client-id.dat"),
+ ClientSecret: readFile("client-secret.dat"),
+ Endpoint: google.Endpoint,
+ Scopes: []string{
+ compute.DevstorageFullControlScope,
+ compute.ComputeScope,
+ "https://www.googleapis.com/auth/sqlservice",
+ "https://www.googleapis.com/auth/sqlservice.admin",
+ },
+ RedirectURL: "urn:ietf:wg:oauth:2.0:oob",
+}
+
+const baseConfig = `#cloud-config
+coreos:
+ units:
+ - name: h2demo.service
+ command: start
+ content: |
+ [Unit]
+ Description=HTTP2 Demo
+
+ [Service]
+ ExecStartPre=/bin/bash -c 'mkdir -p /opt/bin && curl -s -o /opt/bin/h2demo http://storage.googleapis.com/http2-demo-server-tls/h2demo && chmod +x /opt/bin/h2demo'
+ ExecStart=/opt/bin/h2demo --prod
+ RestartSec=5s
+ Restart=always
+ Type=simple
+
+ [Install]
+ WantedBy=multi-user.target
+`
+
+func main() {
+ flag.Parse()
+ if *proj == "" {
+ log.Fatalf("Missing --project flag")
+ }
+ prefix := "https://www.googleapis.com/compute/v1/projects/" + *proj
+ machType := prefix + "/zones/" + *zone + "/machineTypes/" + *mach
+
+ const tokenFileName = "token.dat"
+ tokenFile := tokenCacheFile(tokenFileName)
+ tokenSource := oauth2.ReuseTokenSource(nil, tokenFile)
+ token, err := tokenSource.Token()
+ if err != nil {
+ if *writeObject != "" {
+ log.Fatalf("Can't use --write_object without a valid token.dat file already cached.")
+ }
+ log.Printf("Error getting token from %s: %v", tokenFileName, err)
+ log.Printf("Get auth code from %v", config.AuthCodeURL("my-state"))
+ fmt.Print("\nEnter auth code: ")
+ sc := bufio.NewScanner(os.Stdin)
+ sc.Scan()
+ authCode := strings.TrimSpace(sc.Text())
+ token, err = config.Exchange(oauth2.NoContext, authCode)
+ if err != nil {
+ log.Fatalf("Error exchanging auth code for a token: %v", err)
+ }
+ if err := tokenFile.WriteToken(token); err != nil {
+ log.Fatalf("Error writing to %s: %v", tokenFileName, err)
+ }
+ tokenSource = oauth2.ReuseTokenSource(token, nil)
+ }
+
+ oauthClient := oauth2.NewClient(oauth2.NoContext, tokenSource)
+
+ if *writeObject != "" {
+ writeCloudStorageObject(oauthClient)
+ return
+ }
+
+ computeService, _ := compute.New(oauthClient)
+
+ natIP := *staticIP
+ if natIP == "" {
+ // Try to find it by name.
+ aggAddrList, err := computeService.Addresses.AggregatedList(*proj).Do()
+ if err != nil {
+ log.Fatal(err)
+ }
+ // http://godoc.org/code.google.com/p/google-api-go-client/compute/v1#AddressAggregatedList
+ IPLoop:
+ for _, asl := range aggAddrList.Items {
+ for _, addr := range asl.Addresses {
+ if addr.Name == *instName+"-ip" && addr.Status == "RESERVED" {
+ natIP = addr.Address
+ break IPLoop
+ }
+ }
+ }
+ }
+
+ cloudConfig := baseConfig
+ if *sshPub != "" {
+ key := strings.TrimSpace(readFile(*sshPub))
+ cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n - %s\n", key)
+ }
+ if os.Getenv("USER") == "bradfitz" {
+ cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n - %s\n", "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwks9dwWKlRC+73gRbvYtVg0vdCwDSuIlyt4z6xa/YU/jTDynM4R4W10hm2tPjy8iR1k8XhDv4/qdxe6m07NjG/By1tkmGpm1mGwho4Pr5kbAAy/Qg+NLCSdAYnnE00FQEcFOC15GFVMOW2AzDGKisReohwH9eIzHPzdYQNPRWXE= bradfitz@papag.bradfitz.com")
+ }
+ const maxCloudConfig = 32 << 10 // per compute API docs
+ if len(cloudConfig) > maxCloudConfig {
+ log.Fatalf("cloud config length of %d bytes is over %d byte limit", len(cloudConfig), maxCloudConfig)
+ }
+
+ instance := &compute.Instance{
+ Name: *instName,
+ Description: "Go Builder",
+ MachineType: machType,
+ Disks: []*compute.AttachedDisk{instanceDisk(computeService)},
+ Tags: &compute.Tags{
+ Items: []string{"http-server", "https-server"},
+ },
+ Metadata: &compute.Metadata{
+ Items: []*compute.MetadataItems{
+ {
+ Key: "user-data",
+ Value: &cloudConfig,
+ },
+ },
+ },
+ NetworkInterfaces: []*compute.NetworkInterface{
+ {
+ AccessConfigs: []*compute.AccessConfig{
+ {
+ Type: "ONE_TO_ONE_NAT",
+ Name: "External NAT",
+ NatIP: natIP,
+ },
+ },
+ Network: prefix + "/global/networks/default",
+ },
+ },
+ ServiceAccounts: []*compute.ServiceAccount{
+ {
+ Email: "default",
+ Scopes: []string{
+ compute.DevstorageFullControlScope,
+ compute.ComputeScope,
+ },
+ },
+ },
+ }
+
+ log.Printf("Creating instance...")
+ op, err := computeService.Instances.Insert(*proj, *zone, instance).Do()
+ if err != nil {
+ log.Fatalf("Failed to create instance: %v", err)
+ }
+ opName := op.Name
+ log.Printf("Created. Waiting on operation %v", opName)
+OpLoop:
+ for {
+ time.Sleep(2 * time.Second)
+ op, err := computeService.ZoneOperations.Get(*proj, *zone, opName).Do()
+ if err != nil {
+ log.Fatalf("Failed to get op %s: %v", opName, err)
+ }
+ switch op.Status {
+ case "PENDING", "RUNNING":
+ log.Printf("Waiting on operation %v", opName)
+ continue
+ case "DONE":
+ if op.Error != nil {
+ for _, operr := range op.Error.Errors {
+ log.Printf("Error: %+v", operr)
+ }
+ log.Fatalf("Failed to start.")
+ }
+ log.Printf("Success. %+v", op)
+ break OpLoop
+ default:
+ log.Fatalf("Unknown status %q: %+v", op.Status, op)
+ }
+ }
+
+ inst, err := computeService.Instances.Get(*proj, *zone, *instName).Do()
+ if err != nil {
+ log.Fatalf("Error getting instance after creation: %v", err)
+ }
+ ij, _ := json.MarshalIndent(inst, "", " ")
+ log.Printf("Instance: %s", ij)
+}
+
+func instanceDisk(svc *compute.Service) *compute.AttachedDisk {
+ const imageURL = "https://www.googleapis.com/compute/v1/projects/coreos-cloud/global/images/coreos-stable-444-5-0-v20141016"
+ diskName := *instName + "-disk"
+
+ return &compute.AttachedDisk{
+ AutoDelete: true,
+ Boot: true,
+ Type: "PERSISTENT",
+ InitializeParams: &compute.AttachedDiskInitializeParams{
+ DiskName: diskName,
+ SourceImage: imageURL,
+ DiskSizeGb: 50,
+ },
+ }
+}
+
+func writeCloudStorageObject(httpClient *http.Client) {
+ content := os.Stdin
+ const maxSlurp = 1 << 20
+ var buf bytes.Buffer
+ n, err := io.CopyN(&buf, content, maxSlurp)
+ if err != nil && err != io.EOF {
+ log.Fatalf("Error reading from stdin: %v, %v", n, err)
+ }
+ contentType := http.DetectContentType(buf.Bytes())
+
+ req, err := http.NewRequest("PUT", "https://storage.googleapis.com/"+*writeObject, io.MultiReader(&buf, content))
+ if err != nil {
+ log.Fatal(err)
+ }
+ req.Header.Set("x-goog-api-version", "2")
+ if *publicObject {
+ req.Header.Set("x-goog-acl", "public-read")
+ }
+ req.Header.Set("Content-Type", contentType)
+ res, err := httpClient.Do(req)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if res.StatusCode != 200 {
+ res.Write(os.Stderr)
+ log.Fatalf("Failed.")
+ }
+ log.Printf("Success.")
+ os.Exit(0)
+}
+
+type tokenCacheFile string
+
+func (f tokenCacheFile) Token() (*oauth2.Token, error) {
+ slurp, err := ioutil.ReadFile(string(f))
+ if err != nil {
+ return nil, err
+ }
+ t := new(oauth2.Token)
+ if err := json.Unmarshal(slurp, t); err != nil {
+ return nil, err
+ }
+ return t, nil
+}
+
+func (f tokenCacheFile) WriteToken(t *oauth2.Token) error {
+ jt, err := json.Marshal(t)
+ if err != nil {
+ return err
+ }
+ return ioutil.WriteFile(string(f), jt, 0600)
+}
diff --git a/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go b/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go
index 1b649560..26bc838d 100644
--- a/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go
+++ b/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go
@@ -23,7 +23,7 @@ import (
"golang.org/x/oauth2/internal"
)
-// Client Credentials Config describes a 2-legged OAuth2 flow, with both the
+// Config describes a 2-legged OAuth2 flow, with both the
// client application information and the server's endpoint URLs.
type Config struct {
// ClientID is the application's ID.
diff --git a/vendor/golang.org/x/oauth2/google/sdk.go b/vendor/golang.org/x/oauth2/google/sdk.go
index d29a3bb9..bdc18084 100644
--- a/vendor/golang.org/x/oauth2/google/sdk.go
+++ b/vendor/golang.org/x/oauth2/google/sdk.go
@@ -160,9 +160,13 @@ var sdkConfigPath = func() (string, error) {
}
func guessUnixHomeDir() string {
- usr, err := user.Current()
- if err == nil {
- return usr.HomeDir
+ // Prefer $HOME over user.Current due to glibc bug: golang.org/issue/13470
+ if v := os.Getenv("HOME"); v != "" {
+ return v
}
- return os.Getenv("HOME")
+ // Else, fall back to user.Current:
+ if u, err := user.Current(); err == nil {
+ return u.HomeDir
+ }
+ return ""
}
diff --git a/vendor/golang.org/x/oauth2/internal/oauth2.go b/vendor/golang.org/x/oauth2/internal/oauth2.go
index fbe1028d..e31541b3 100644
--- a/vendor/golang.org/x/oauth2/internal/oauth2.go
+++ b/vendor/golang.org/x/oauth2/internal/oauth2.go
@@ -42,7 +42,7 @@ func ParseKey(key []byte) (*rsa.PrivateKey, error) {
func ParseINI(ini io.Reader) (map[string]map[string]string, error) {
result := map[string]map[string]string{
- "": map[string]string{}, // root section
+ "": {}, // root section
}
scanner := bufio.NewScanner(ini)
currentSection := ""
diff --git a/vendor/golang.org/x/oauth2/internal/token.go b/vendor/golang.org/x/oauth2/internal/token.go
index 18328a0d..ba90a341 100644
--- a/vendor/golang.org/x/oauth2/internal/token.go
+++ b/vendor/golang.org/x/oauth2/internal/token.go
@@ -91,6 +91,7 @@ func (e *expirationTime) UnmarshalJSON(b []byte) error {
var brokenAuthHeaderProviders = []string{
"https://accounts.google.com/",
+ "https://api.codeswholesale.com/oauth/token",
"https://api.dropbox.com/",
"https://api.dropboxapi.com/",
"https://api.instagram.com/",
@@ -101,6 +102,7 @@ var brokenAuthHeaderProviders = []string{
"https://api.twitch.tv/",
"https://app.box.com/",
"https://connect.stripe.com/",
+ "https://graph.facebook.com", // see https://github.com/golang/oauth2/issues/214
"https://login.microsoftonline.com/",
"https://login.salesforce.com/",
"https://oauth.sandbox.trainingpeaks.com/",
@@ -117,6 +119,7 @@ var brokenAuthHeaderProviders = []string{
"https://www.strava.com/oauth/",
"https://www.wunderlist.com/oauth/",
"https://api.patreon.com/",
+ "https://sandbox.codeswholesale.com/oauth/token",
}
func RegisterBrokenAuthHeaderProvider(tokenURL string) {
@@ -151,9 +154,9 @@ func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string,
if err != nil {
return nil, err
}
- v.Set("client_id", clientID)
bustedAuth := !providerAuthHeaderWorks(tokenURL)
if bustedAuth && clientSecret != "" {
+ v.Set("client_id", clientID)
v.Set("client_secret", clientSecret)
}
req, err := http.NewRequest("POST", tokenURL, strings.NewReader(v.Encode()))
diff --git a/vendor/golang.org/x/oauth2/jwt/jwt.go b/vendor/golang.org/x/oauth2/jwt/jwt.go
index f4b9523e..e016db42 100644
--- a/vendor/golang.org/x/oauth2/jwt/jwt.go
+++ b/vendor/golang.org/x/oauth2/jwt/jwt.go
@@ -105,7 +105,9 @@ func (js jwtSource) Token() (*oauth2.Token, error) {
if t := js.conf.Expires; t > 0 {
claimSet.Exp = time.Now().Add(t).Unix()
}
- payload, err := jws.Encode(defaultHeader, claimSet, pk)
+ h := *defaultHeader
+ h.KeyID = js.conf.PrivateKeyID
+ payload, err := jws.Encode(&h, claimSet, pk)
if err != nil {
return nil, err
}
diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go
index 7b06bfe1..3e4835d7 100644
--- a/vendor/golang.org/x/oauth2/oauth2.go
+++ b/vendor/golang.org/x/oauth2/oauth2.go
@@ -180,7 +180,6 @@ func (c *Config) Exchange(ctx context.Context, code string) (*Token, error) {
"grant_type": {"authorization_code"},
"code": {code},
"redirect_uri": internal.CondVal(c.RedirectURL),
- "scope": internal.CondVal(strings.Join(c.Scopes, " ")),
})
}
diff --git a/vendor/gopkg.in/yaml.v2/decode.go b/vendor/gopkg.in/yaml.v2/decode.go
index a033516c..085cddc4 100644
--- a/vendor/gopkg.in/yaml.v2/decode.go
+++ b/vendor/gopkg.in/yaml.v2/decode.go
@@ -120,6 +120,7 @@ func (p *parser) parse() *node {
default:
panic("attempted to parse unknown event: " + strconv.Itoa(int(p.event.typ)))
}
+ panic("unreachable")
}
func (p *parser) node(kind int) *node {
diff --git a/vendor/gopkg.in/yaml.v2/emitterc.go b/vendor/gopkg.in/yaml.v2/emitterc.go
index 6ecdcb3c..2befd553 100644
--- a/vendor/gopkg.in/yaml.v2/emitterc.go
+++ b/vendor/gopkg.in/yaml.v2/emitterc.go
@@ -666,6 +666,7 @@ func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t,
return yaml_emitter_set_emitter_error(emitter,
"expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS")
}
+ return false
}
// Expect ALIAS.
diff --git a/vendor/gopkg.in/yaml.v2/parserc.go b/vendor/gopkg.in/yaml.v2/parserc.go
index 81d05dfe..0a7037ad 100644
--- a/vendor/gopkg.in/yaml.v2/parserc.go
+++ b/vendor/gopkg.in/yaml.v2/parserc.go
@@ -166,6 +166,7 @@ func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool
default:
panic("invalid parser state")
}
+ return false
}
// Parse the production:
diff --git a/vendor/manifest b/vendor/manifest
index f1f10f40..ccd15228 100644
--- a/vendor/manifest
+++ b/vendor/manifest
@@ -224,7 +224,7 @@
"importpath": "github.com/vmware/govmomi",
"repository": "https://github.com/vmware/govmomi",
"vcs": "git",
- "revision": "c8df70bf7e64cb14c5305f4e16597c501a2eba8b",
+ "revision": "17b8c9ccb7f8c7b015d44c4ea39305c970a7bf31",
"branch": "HEAD",
"notests": true
},
@@ -268,7 +268,7 @@
"importpath": "golang.org/x/crypto/ssh",
"repository": "https://go.googlesource.com/crypto",
"vcs": "git",
- "revision": "8a549a1948fc5271eb24f36dcb0d3b47dec75a16",
+ "revision": "9f005a07e0d31d45e6656d241bb5c0f2efd4bc94",
"branch": "master",
"path": "/ssh",
"notests": true
@@ -322,7 +322,7 @@
"importpath": "golang.org/x/oauth2",
"repository": "https://go.googlesource.com/oauth2",
"vcs": "git",
- "revision": "f6093e37b6cb4092101a298aba5d794eb570757f",
+ "revision": "b9780ec78894ab900c062d58ee3076cd9b2a4501",
"branch": "master",
"notests": true
},
diff --git a/virtualmachine/aws/util.go b/virtualmachine/aws/util.go
index 833966db..6a9fd938 100644
--- a/virtualmachine/aws/util.go
+++ b/virtualmachine/aws/util.go
@@ -25,7 +25,6 @@ const (
defaultInstanceType = "t2.micro"
defaultAMI = "ami-5189a661" // ubuntu free tier
defaultVolumeSize = 8 // GB
- defaultDeviceName = "/dev/sda1"
defaultVolumeType = "gp2"
// RegionEnv is the env var for the AWS region.
diff --git a/virtualmachine/aws/vm.go b/virtualmachine/aws/vm.go
index 3173b328..f7c4991b 100644
--- a/virtualmachine/aws/vm.go
+++ b/virtualmachine/aws/vm.go
@@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"net"
+ "sync"
"time"
"github.com/apcera/libretto/ssh"
@@ -32,17 +33,19 @@ const (
StatePending = "pending"
)
-// SSHTimeout is the maximum time to wait before failing to GetSSH. This is not
-// thread-safe.
-var SSHTimeout = 5 * time.Minute
-
var (
+ // SSHTimeout is the maximum time to wait before failing to GetSSH. This is
+ // not thread-safe.
+ SSHTimeout = 5 * time.Minute
+
// This ensures that aws.VM implements the virtualmachine.VirtualMachine
// interface at compile time.
_ virtualmachine.VirtualMachine = (*VM)(nil)
- // limiter rate limits channel to prevent saturating AWS API limits.
- limiter = time.Tick(time.Millisecond * 500)
+ // nextProvision is the wall time when the next call to Provision will be
+ // allowed to proceed. This is part of the rate limiting system.
+ nextProvision time.Time
+ mu sync.Mutex
)
var (
@@ -254,7 +257,8 @@ func (vm *VM) SetTags(tags map[string]string) error {
// there was a problem during creation, if there was a problem adding a tag, or
// if the VM takes too long to enter "running" state.
func (vm *VM) Provision() error {
- <-limiter
+ wait() // Avoid the AWS rate limit.
+
svc, err := getService(vm.Region)
if err != nil {
return fmt.Errorf("failed to get AWS service: %v", err)
@@ -288,6 +292,50 @@ func (vm *VM) Provision() error {
return nil
}
+// wait implements a rate limiter that prevents more than one call every
+// 0.5s. The maximum time that the caller can be delayed is 1m.
+func wait() {
+ const maxWait = 1 * time.Minute
+
+ now := time.Now().UTC()
+ mu.Lock()
+ wait := getWaitTime(now, maxWait)
+ mu.Unlock()
+
+ time.Sleep(wait)
+
+ interval := 500 * time.Millisecond
+ if wait == maxWait {
+ interval = maxWait
+ }
+
+ mu.Lock()
+ defer mu.Unlock()
+ if now.Before(nextProvision) {
+ nextProvision = nextProvision.Add(interval)
+ return
+ }
+ now = time.Now().UTC()
+ nextProvision = now.Add(interval)
+}
+
+// getWaitTime computes the duration to sleep before the caller of wait() is
+// allowed to proceed. Every concurrent call adds 0.5s to the time the
+// subsequent caller must wait, up to a maximum of 1 minute.
+func getWaitTime(now time.Time, maxWait time.Duration) time.Duration {
+ wait := nextProvision.Sub(now) // might be negative
+
+ // When the system clock falls back an hour, the wait time might be an hour.
+ // This sanity check prevents this error.
+ if wait > maxWait {
+ return maxWait
+ }
+ if wait < 0 {
+ return 0
+ }
+ return wait
+}
+
// GetIPs returns a slice of IP addresses assigned to the VM. The PublicIP or
// PrivateIP consts can be used to retrieve respective IP address type. It
// returns nil if there was an error obtaining the IPs.
diff --git a/virtualmachine/azure/arm/templates.go b/virtualmachine/azure/arm/templates.go
index 1a333aa1..a8cf839d 100644
--- a/virtualmachine/azure/arm/templates.go
+++ b/virtualmachine/azure/arm/templates.go
@@ -25,7 +25,7 @@ const Linux = `{
},
"nic": {
"type": "string"
- },
+ },
"os_file": {
"type": "string"
},
@@ -144,7 +144,7 @@ const Linux = `{
"computerName": "[parameters('vm_name')]",
"adminUsername": "[parameters('username')]",
"linuxConfiguration": {
- "disablePasswordAuthentication": "true",
+ "disablePasswordAuthentication": true,
"ssh": {
"publicKeys": [
{
@@ -181,7 +181,7 @@ const Linux = `{
},
"diagnosticsProfile": {
"bootDiagnostics": {
- "enabled": "false"
+ "enabled": false
}
}
}
diff --git a/virtualmachine/azure/arm/util.go b/virtualmachine/azure/arm/util.go
index 5599042d..8c25ca4b 100644
--- a/virtualmachine/azure/arm/util.go
+++ b/virtualmachine/azure/arm/util.go
@@ -16,17 +16,19 @@ import (
"github.com/Azure/azure-sdk-for-go/arm/network"
"github.com/Azure/azure-sdk-for-go/arm/resources/resources"
"github.com/Azure/azure-sdk-for-go/storage"
+ "github.com/Azure/go-autorest/autorest"
+ "github.com/Azure/go-autorest/autorest/adal"
"github.com/Azure/go-autorest/autorest/azure"
)
// getServicePrincipalToken retrieves a new ServicePrincipalToken using values of the
// passed credentials map.
-func getServicePrincipalToken(creds *OAuthCredentials, scope string) (*azure.ServicePrincipalToken, error) {
- oauthConfig, err := azure.PublicCloud.OAuthConfigForTenant(creds.TenantID)
+func getServicePrincipalToken(creds *OAuthCredentials, scope string) (*adal.ServicePrincipalToken, error) {
+ oauthConfig, err := adal.NewOAuthConfig(azure.PublicCloud.ActiveDirectoryEndpoint, creds.TenantID)
if err != nil {
return nil, err
}
- return azure.NewServicePrincipalToken(*oauthConfig, creds.ClientID, creds.ClientSecret, scope)
+ return adal.NewServicePrincipalToken(*oauthConfig, creds.ClientID, creds.ClientSecret, scope)
}
type armParameter struct {
@@ -146,8 +148,8 @@ func validateVM(vm *VM) error {
// deploy deploys the given VM based on the default Linux arm template over the
// VM's resource group.
func (vm *VM) deploy() error {
- // Set up the authorizer
- authorizer, err := getServicePrincipalToken(&vm.Creds, azure.PublicCloud.ResourceManagerEndpoint)
+ // Get the auth token.
+ tok, err := getServicePrincipalToken(&vm.Creds, azure.PublicCloud.ResourceManagerEndpoint)
if err != nil {
return err
}
@@ -161,10 +163,10 @@ func (vm *VM) deploy() error {
// Create and send the deployment to the resource group
deploymentsClient := resources.NewDeploymentsClient(vm.Creds.SubscriptionID)
- deploymentsClient.Authorizer = authorizer
+ deploymentsClient.Authorizer = autorest.NewBearerAuthorizer(tok)
- _, err = deploymentsClient.CreateOrUpdate(vm.ResourceGroup, vm.DeploymentName, *deployment, nil)
- if err != nil {
+ _, errc := deploymentsClient.CreateOrUpdate(vm.ResourceGroup, vm.DeploymentName, *deployment, nil)
+ if err := <-errc; err != nil {
return err
}
@@ -187,7 +189,7 @@ func (vm *VM) deploy() error {
}
// getPublicIP returns the public IP of the given VM, if exists one.
-func (vm *VM) getPublicIP(authorizer *azure.ServicePrincipalToken) (net.IP, error) {
+func (vm *VM) getPublicIP(authorizer autorest.Authorizer) (net.IP, error) {
publicIPAddressesClient := network.NewPublicIPAddressesClient(vm.Creds.SubscriptionID)
publicIPAddressesClient.Authorizer = authorizer
@@ -196,92 +198,109 @@ func (vm *VM) getPublicIP(authorizer *azure.ServicePrincipalToken) (net.IP, erro
return nil, err
}
- if resPublicIP.Properties == nil || resPublicIP.Properties.IPAddress == nil ||
- *resPublicIP.Properties.IPAddress == "" {
+ if resPublicIP.PublicIPAddressPropertiesFormat == nil || resPublicIP.PublicIPAddressPropertiesFormat.IPAddress == nil ||
+ *resPublicIP.PublicIPAddressPropertiesFormat.IPAddress == "" {
return nil, fmt.Errorf("VM has no public IP address")
}
- return net.ParseIP(*resPublicIP.Properties.IPAddress), nil
+ return net.ParseIP(*resPublicIP.PublicIPAddressPropertiesFormat.IPAddress), nil
}
// getPrivateIP returns the private IP of the given VM, if exists one.
-func (vm *VM) getPrivateIP(authorizer *azure.ServicePrincipalToken) (net.IP, error) {
+func (vm *VM) getPrivateIP(authorizer autorest.Authorizer) (net.IP, error) {
interfaceClient := network.NewInterfacesClient(vm.Creds.SubscriptionID)
interfaceClient.Authorizer = authorizer
- resPrivateIP, err := interfaceClient.Get(vm.ResourceGroup, vm.Nic, "")
+ iface, err := interfaceClient.Get(vm.ResourceGroup, vm.Nic, "")
if err != nil {
return nil, err
}
- if resPrivateIP.Properties == nil || resPrivateIP.Properties.IPConfigurations == nil ||
- len(*resPrivateIP.Properties.IPConfigurations) == 0 {
+ if iface.InterfacePropertiesFormat == nil || iface.InterfacePropertiesFormat.IPConfigurations == nil ||
+ len(*iface.InterfacePropertiesFormat.IPConfigurations) == 0 {
return nil, fmt.Errorf("VM has no private IP address")
}
- ipConfigs := *resPrivateIP.Properties.IPConfigurations
+ ipConfigs := *iface.InterfacePropertiesFormat.IPConfigurations
if len(ipConfigs) > 1 {
return nil, fmt.Errorf("VM has multiple private IP addresses")
}
- return net.ParseIP(*ipConfigs[0].Properties.PrivateIPAddress), nil
+ return net.ParseIP(*ipConfigs[0].InterfaceIPConfigurationPropertiesFormat.PrivateIPAddress), nil
}
// deleteOSFile deletes the OS file from the VM's storage account, returns an error if the operation
// does not succeed.
-func (vm *VM) deleteVMFiles(authorizer *azure.ServicePrincipalToken) error {
+func (vm *VM) deleteVMFiles(authorizer autorest.Authorizer) error {
storageAccountsClient := armStorage.NewAccountsClient(vm.Creds.SubscriptionID)
storageAccountsClient.Authorizer = authorizer
- accountKeys, err := storageAccountsClient.ListKeys(vm.ResourceGroup, vm.StorageAccount)
+ result, err := storageAccountsClient.ListKeys(vm.ResourceGroup, vm.StorageAccount)
if err != nil {
return err
}
- storageClient, err := storage.NewBasicClient(vm.StorageAccount, *accountKeys.Key1)
+ accountKeys := result.Keys
+ if accountKeys == nil || len(*accountKeys) == 0 {
+ return fmt.Errorf("no account keys for storage account %q", vm.StorageAccount)
+ }
+
+ accountKey := *(*accountKeys)[0].Value
+ storageClient, err := storage.NewBasicClient(vm.StorageAccount, accountKey)
if err != nil {
return err
}
+ // Get a reference to the OS file.
blobStorageClient := storageClient.GetBlobService()
- err = blobStorageClient.DeleteBlob(vm.StorageContainer, vm.OsFile, nil)
- if err != nil {
+ container := blobStorageClient.GetContainerReference(vm.StorageContainer)
+ osFileBlob := container.GetBlobReference(vm.OsFile)
+
+ // Delete the OS file.
+ opts := &storage.DeleteBlobOptions{Timeout: 30} // 30s timeout
+ err = osFileBlob.Delete(opts)
+
+ if vm.DiskSize <= 0 {
return err
}
- if vm.DiskSize <= 0 {
- return nil
+
+ // Delete the disk file.
+ diskFileBlob := container.GetBlobReference(vm.DiskFile)
+ diskFileErr := diskFileBlob.Delete(opts)
+ if err != nil {
+ return fmt.Errorf("failed to delete OS file and disk file: %v, %v", err, diskFileErr)
}
- return blobStorageClient.DeleteBlob(vm.StorageContainer, vm.DiskFile, nil)
+ return diskFileErr
}
// deleteNic deletes the network interface for the given VM from the VM's resource group, returns an error
// if the operation does not succeed.
-func (vm *VM) deleteNic(authorizer *azure.ServicePrincipalToken) error {
+func (vm *VM) deleteNic(authorizer autorest.Authorizer) error {
interfaceClient := network.NewInterfacesClient(vm.Creds.SubscriptionID)
interfaceClient.Authorizer = authorizer
- _, err := interfaceClient.Delete(vm.ResourceGroup, vm.Nic, nil)
- return err
+ _, errc := interfaceClient.Delete(vm.ResourceGroup, vm.Nic, nil)
+ return <-errc
}
// deletePublicIP deletes the reserved Public IP of the given VM from the VM's resource group, returns an error
// if the operation does not succeed.
-func (vm *VM) deletePublicIP(authorizer *azure.ServicePrincipalToken) error {
+func (vm *VM) deletePublicIP(authorizer autorest.Authorizer) error {
// Delete the Public IP of this VM
publicIPAddressesClient := network.NewPublicIPAddressesClient(vm.Creds.SubscriptionID)
publicIPAddressesClient.Authorizer = authorizer
- _, err := publicIPAddressesClient.Delete(vm.ResourceGroup, vm.PublicIP, nil)
- return err
+ _, errc := publicIPAddressesClient.Delete(vm.ResourceGroup, vm.PublicIP, nil)
+ return <-errc
}
// deleteDeployment deletes the deployed azure arm template for this vm.
-func (vm *VM) deleteDeployment(authorizer *azure.ServicePrincipalToken) error {
+func (vm *VM) deleteDeployment(authorizer autorest.Authorizer) error {
// Get the deployments client
deploymentsClient := resources.NewDeploymentsClient(vm.Creds.SubscriptionID)
deploymentsClient.Authorizer = authorizer
// Delete the deployment
- _, err := deploymentsClient.Delete(vm.ResourceGroup, vm.DeploymentName, nil)
- return err
+ _, errc := deploymentsClient.Delete(vm.ResourceGroup, vm.DeploymentName, nil)
+ return <-errc
}
func createDeployment(template string, params armParameters) (*resources.Deployment, error) {
diff --git a/virtualmachine/azure/arm/vm.go b/virtualmachine/azure/arm/vm.go
index 2eced98b..5be8680a 100644
--- a/virtualmachine/azure/arm/vm.go
+++ b/virtualmachine/azure/arm/vm.go
@@ -15,6 +15,7 @@ import (
lvm "github.com/apcera/libretto/virtualmachine"
"github.com/Azure/azure-sdk-for-go/arm/compute"
+ "github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
@@ -114,7 +115,7 @@ func (vm *VM) Provision() error {
}
// Set up private members of the VM
- tempName := fmt.Sprintf("%s", randStringRunes(5))
+ tempName := randStringRunes(5)
if vm.OsFile == "" {
vm.OsFile = tempName + "-os-disk.vhd"
}
@@ -131,10 +132,11 @@ func (vm *VM) Provision() error {
vm.DeploymentName = tempName + "-deploy"
}
- // Create and send the deployment
- vm.deploy()
+ err = vm.deploy()
+ if err != nil {
+ return err
+ }
- // Use GetSSH to try to connect to machine
cli, err := vm.GetSSH(ssh.Options{KeepAlive: 2})
if err != nil {
return err
@@ -147,11 +149,12 @@ func (vm *VM) Provision() error {
func (vm *VM) GetIPs() ([]net.IP, error) {
ips := make([]net.IP, 2)
- // Set up the authorizer
- authorizer, err := getServicePrincipalToken(&vm.Creds, azure.PublicCloud.ResourceManagerEndpoint)
+ // Set up the auth token.
+ tok, err := getServicePrincipalToken(&vm.Creds, azure.PublicCloud.ResourceManagerEndpoint)
if err != nil {
return nil, err
}
+ authorizer := autorest.NewBearerAuthorizer(tok)
// Get the Public IP
ip, err := vm.getPublicIP(authorizer)
@@ -193,10 +196,11 @@ func (vm *VM) GetSSH(options ssh.Options) (ssh.Client, error) {
// "stopped"
func (vm *VM) GetState() (string, error) {
// Set up the authorizer
- authorizer, err := getServicePrincipalToken(&vm.Creds, azure.PublicCloud.ResourceManagerEndpoint)
+ tok, err := getServicePrincipalToken(&vm.Creds, azure.PublicCloud.ResourceManagerEndpoint)
if err != nil {
return "", err
}
+ authorizer := autorest.NewBearerAuthorizer(tok)
virtualMachinesClient := compute.NewVirtualMachinesClient(vm.Creds.SubscriptionID)
virtualMachinesClient.Authorizer = authorizer
@@ -206,8 +210,8 @@ func (vm *VM) GetState() (string, error) {
return "", e
}
- if r.Properties != nil && r.Properties.InstanceView != nil && len(*r.Properties.InstanceView.Statuses) > 1 {
- state := *(*r.Properties.InstanceView.Statuses)[1].DisplayStatus
+ if r.VirtualMachineProperties != nil && r.VirtualMachineProperties.InstanceView != nil && len(*r.VirtualMachineProperties.InstanceView.Statuses) > 1 {
+ state := *(*r.VirtualMachineProperties.InstanceView.Statuses)[1].DisplayStatus
return translateState(state), e
}
@@ -217,17 +221,18 @@ func (vm *VM) GetState() (string, error) {
// Destroy deletes the VM on Azure.
func (vm *VM) Destroy() error {
// Set up the authorizer
- authorizer, err := getServicePrincipalToken(&vm.Creds, azure.PublicCloud.ResourceManagerEndpoint)
+ tok, err := getServicePrincipalToken(&vm.Creds, azure.PublicCloud.ResourceManagerEndpoint)
if err != nil {
return err
}
+ authorizer := autorest.NewBearerAuthorizer(tok)
// Delete the VM
virtualMachinesClient := compute.NewVirtualMachinesClient(vm.Creds.SubscriptionID)
virtualMachinesClient.Authorizer = authorizer
- _, err = virtualMachinesClient.Delete(vm.ResourceGroup, vm.Name, nil)
- if err != nil {
+ _, errc := virtualMachinesClient.Delete(vm.ResourceGroup, vm.Name, nil)
+ if err := <-errc; err != nil {
return err
}
@@ -295,17 +300,18 @@ func (vm *VM) Destroy() error {
// Halt shuts down the VM.
func (vm *VM) Halt() error {
// Set up the authorizer
- authorizer, err := getServicePrincipalToken(&vm.Creds, azure.PublicCloud.ResourceManagerEndpoint)
+ tok, err := getServicePrincipalToken(&vm.Creds, azure.PublicCloud.ResourceManagerEndpoint)
if err != nil {
return err
}
+ authorizer := autorest.NewBearerAuthorizer(tok)
// Poweroff the VM
virtualMachinesClient := compute.NewVirtualMachinesClient(vm.Creds.SubscriptionID)
virtualMachinesClient.Authorizer = authorizer
- _, err = virtualMachinesClient.PowerOff(vm.ResourceGroup, vm.Name, nil)
- if err != nil {
+ _, errc := virtualMachinesClient.PowerOff(vm.ResourceGroup, vm.Name, nil)
+ if err := <-errc; err != nil {
return err
}
@@ -327,17 +333,18 @@ func (vm *VM) Halt() error {
// Start boots a stopped VM.
func (vm *VM) Start() error {
// Set up the authorizer
- authorizer, err := getServicePrincipalToken(&vm.Creds, azure.PublicCloud.ResourceManagerEndpoint)
+ tok, err := getServicePrincipalToken(&vm.Creds, azure.PublicCloud.ResourceManagerEndpoint)
if err != nil {
return err
}
+ authorizer := autorest.NewBearerAuthorizer(tok)
// Start the VM
virtualMachinesClient := compute.NewVirtualMachinesClient(vm.Creds.SubscriptionID)
virtualMachinesClient.Authorizer = authorizer
- _, err = virtualMachinesClient.Start(vm.ResourceGroup, vm.Name, nil)
- if err != nil {
+ _, errc := virtualMachinesClient.Start(vm.ResourceGroup, vm.Name, nil)
+ if err := <-errc; err != nil {
return err
}
diff --git a/virtualmachine/azure/management/util.go b/virtualmachine/azure/management/util.go
index 52ed8481..c812ba9b 100644
--- a/virtualmachine/azure/management/util.go
+++ b/virtualmachine/azure/management/util.go
@@ -6,7 +6,6 @@ import (
"encoding/base64"
"fmt"
"sync"
- "time"
lvm "github.com/apcera/libretto/virtualmachine"
@@ -146,23 +145,6 @@ func (vm *VM) serviceExist(services []hostedservice.HostedService) bool {
return false
}
-// waitForReady waits for the VM to go into the desired state.
-func (vm *VM) waitForReady(timeout int, targetState string) error {
- for i := 0; i < timeout; i++ {
- state, err := vm.GetState()
- if err != nil {
- return err
- }
-
- if state == targetState {
- return nil
- }
-
- time.Sleep(1 * time.Second)
- }
- return fmt.Errorf(errMsgTimeout, virtualmachine.DeploymentStatusRunning)
-}
-
func (vm *VM) getDeploymentOptions() virtualmachine.CreateDeploymentOptions {
vnn := vm.DeployOptions.VirtualNetworkName
if vnn == "" {
diff --git a/virtualmachine/azure/management/vm.go b/virtualmachine/azure/management/vm.go
index 72ee4e46..629670e8 100644
--- a/virtualmachine/azure/management/vm.go
+++ b/virtualmachine/azure/management/vm.go
@@ -24,9 +24,7 @@ const (
PrivateIP = 1
errGetClient = "Error to retrieve Azure client %s"
- errGetDeployment = "Error to provision Azure VM %s"
errGetListService = "Error to list hosted services %s"
- errMsgTimeout = "Time out waiting for instance to %s"
errProvisionVM = "Error to provision Azure VM %s"
)
diff --git a/virtualmachine/exoscale/util.go b/virtualmachine/exoscale/util.go
index 67bfa71d..537d3336 100644
--- a/virtualmachine/exoscale/util.go
+++ b/virtualmachine/exoscale/util.go
@@ -8,7 +8,7 @@ import (
"strings"
"time"
- "github.com/pyr/egoscale/src/egoscale"
+ "github.com/pyr/egoscale"
)
func (vm *VM) getExoClient() *egoscale.Client {
diff --git a/virtualmachine/exoscale/vm.go b/virtualmachine/exoscale/vm.go
index 11720b95..0c41e70e 100644
--- a/virtualmachine/exoscale/vm.go
+++ b/virtualmachine/exoscale/vm.go
@@ -11,7 +11,7 @@ import (
"github.com/apcera/libretto/ssh"
"github.com/apcera/libretto/util"
"github.com/apcera/libretto/virtualmachine"
- "github.com/pyr/egoscale/src/egoscale"
+ "github.com/pyr/egoscale"
)
// VM represents an Exoscale virtual machine.
diff --git a/virtualmachine/gcp/util.go b/virtualmachine/gcp/util.go
index e6f7b781..b1e1bcb3 100644
--- a/virtualmachine/gcp/util.go
+++ b/virtualmachine/gcp/util.go
@@ -3,6 +3,7 @@
package gcp
import (
+ "context"
"encoding/json"
"errors"
"fmt"
@@ -12,14 +13,13 @@ import (
"os"
"strings"
"time"
- "context"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"golang.org/x/oauth2/jwt"
- googlecloud "google.golang.org/api/compute/v1"
googleresourcemanager "google.golang.org/api/cloudresourcemanager/v1"
+ googlecloud "google.golang.org/api/compute/v1"
)
var (
@@ -102,7 +102,7 @@ func (vm *VM) getService() (*googleService, error) {
Scopes: vm.Scopes,
TokenURL: tokenURL,
}
- client = config.Client(oauth2.NoContext)
+ client = config.Client(context.Background())
} else {
client = &http.Client{
Timeout: time.Duration(30 * time.Second),
@@ -724,7 +724,7 @@ func (svc *googleService) removeFirewallRules() error {
newRules[indexEndp].Ports[indPort] = ""
newRules[indexEndp].Ports = append(
newRules[indexEndp].Ports[:indPort],
- newRules[indexEndp].Ports[indPort+1:]...
+ newRules[indexEndp].Ports[indPort+1:]...,
)
// Set the index back by one because we have
// shifted elements from indP onwards to left
diff --git a/virtualmachine/openstack/util.go b/virtualmachine/openstack/util.go
index 64bb0992..04f6ce6b 100644
--- a/virtualmachine/openstack/util.go
+++ b/virtualmachine/openstack/util.go
@@ -14,12 +14,12 @@ import (
"strings"
"time"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack"
- "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach"
- "github.com/rackspace/gophercloud/openstack/compute/v2/images"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack"
+ "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/images"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/apcera/libretto/ssh"
lvm "github.com/apcera/libretto/virtualmachine"
@@ -505,32 +505,11 @@ func deattachAndDeleteVolume(vm *VM) error {
return nil
}
-// Delete the instance
-func deleteVM(client *gophercloud.ServiceClient, vm *VM) error {
- err := servers.Delete(client, vm.InstanceID).ExtractErr()
+// deleteVM deletes the instance.
+func deleteVM(client *gophercloud.ServiceClient, vmID string) error {
+ err := servers.Delete(client, vmID).ExtractErr()
if err != nil {
- return fmt.Errorf("failed to destroy the vm: %s", err)
- }
-
- // Wait until its status becomes nil within ActionTimeout seconds.
- var server *servers.Server
- for i := 0; i < ActionTimeout; i++ {
- server, err = getServer(vm)
- if err != nil {
- return err
- }
-
- if server == nil {
- break
- } else if server.Status == StateError {
- return fmt.Errorf("error on destroying the vm")
- }
-
- time.Sleep(1 * time.Second)
- }
-
- if server != nil {
- return ErrActionTimeout
+ return fmt.Errorf("failed to destroy vm %s: %s", vmID, err)
}
return nil
}
diff --git a/virtualmachine/openstack/vm.go b/virtualmachine/openstack/vm.go
index 59739285..10b3ff05 100644
--- a/virtualmachine/openstack/vm.go
+++ b/virtualmachine/openstack/vm.go
@@ -3,6 +3,7 @@
package openstack
import (
+ "encoding/json"
"errors"
"fmt"
"net"
@@ -11,12 +12,12 @@ import (
"github.com/apcera/libretto/ssh"
"github.com/apcera/libretto/util"
lvm "github.com/apcera/libretto/virtualmachine"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip"
- ss "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop"
- "github.com/rackspace/gophercloud/openstack/compute/v2/flavors"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips"
+ ss "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/startstop"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
)
// Compiler will complain if openstack.VM doesn't implement VirtualMachine interface.
@@ -142,7 +143,8 @@ type VM struct {
Volume Volume
// UUID of this instance (server). Set after provisioning
- InstanceID string // optional
+ InstanceID string
+
// Instance Name of the VM (optional)
Name string
@@ -153,7 +155,7 @@ type VM struct {
// to the VM.
FloatingIPPool string
// FloatingIP is the object that stores the necessary floating ip information for this VM
- FloatingIP *floatingip.FloatingIP
+ FloatingIP *floatingips.FloatingIP
// SecurityGroup represents the name of the security group to which this VM should belong
SecurityGroup string
@@ -174,6 +176,91 @@ type VM struct {
computeClient *gophercloud.ServiceClient
}
+// MarshalJSON serializes the VM object to JSON. It includes the FloatingIP.ID
+// field which would otherwise be omitted. We can't delete the floating IPs
+// during a Destroy() call without knowing the floating IP ID.
+func (vm *VM) MarshalJSON() ([]byte, error) {
+ // Make an alias of the VM type to avoid infinite recursion. This works
+ // because the alias does not have a MarshalJSON() method.
+ type (
+ // credsAlias prevents a mutex in ssh.Credentials from being copied.
+ credsAlias struct {
+ SSHUser string
+ SSHPassword string
+ SSHPrivateKey string
+ }
+ vmAlias struct {
+ IdentityEndpoint string
+ Username string
+ Password string
+ Region string
+ TenantName string
+ FlavorName string
+ ImageID string
+ ImageMetadata ImageMetadata
+ ImagePath string
+ Volume Volume
+ InstanceID string
+ Name string
+ Networks []string
+ FloatingIPPool string
+ FloatingIP *floatingips.FloatingIP
+ SecurityGroup string
+ UserData []byte
+ AdminPassword string
+ Credentials credsAlias
+ }
+ )
+
+ // Creating the alias in this way avoids copying the mutex in
+ // ssh.Credentials, which go vet doesn't like.
+ alias := vmAlias{
+ IdentityEndpoint: vm.IdentityEndpoint,
+ Username: vm.Username,
+ Password: vm.Password,
+ Region: vm.Region,
+ TenantName: vm.TenantName,
+ FlavorName: vm.FlavorName,
+ ImageID: vm.ImageID,
+ ImageMetadata: vm.ImageMetadata,
+ ImagePath: vm.ImagePath,
+ Volume: vm.Volume,
+ InstanceID: vm.InstanceID,
+ Name: vm.Name,
+ Networks: vm.Networks,
+ FloatingIPPool: vm.FloatingIPPool,
+ FloatingIP: vm.FloatingIP,
+ SecurityGroup: vm.SecurityGroup,
+ UserData: vm.UserData,
+ AdminPassword: vm.AdminPassword,
+ Credentials: credsAlias{
+ SSHUser: vm.Credentials.SSHUser,
+ SSHPassword: vm.Credentials.SSHPassword,
+ SSHPrivateKey: vm.Credentials.SSHPrivateKey,
+ },
+ }
+
+ b, err := json.Marshal(alias)
+ if err != nil {
+ return nil, err
+ }
+
+ // We have vm serialized to JSON, but it's missing the floating IP ID.
+ // Unmarshal it into a map[string]interface{}, add the floating IP ID back
+ // in, then serialize it again.
+ var temp interface{}
+ err = json.Unmarshal(b, &temp)
+ if err != nil {
+ return nil, err
+ }
+
+ m := temp.(map[string]interface{})
+ fip := m["FloatingIP"].(map[string]interface{})
+ fip["id"] = vm.FloatingIP.ID
+
+ return json.Marshal(m)
+}
+
// GetName returns the name of the virtual machine
func (vm *VM) GetName() string {
return vm.Name
@@ -262,7 +349,7 @@ func (vm *VM) Provision() error {
return cleanup(fmt.Errorf("empty floating IP pool"))
}
- fip, err := floatingip.Create(client, &floatingip.CreateOpts{
+ fip, err := floatingips.Create(client, &floatingips.CreateOpts{
Pool: vm.FloatingIPPool,
}).Extract()
@@ -270,9 +357,9 @@ func (vm *VM) Provision() error {
return cleanup(fmt.Errorf("unable to create a floating ip: %s", err))
}
- err = floatingip.Associate(client, server.ID, fip.IP).ExtractErr()
+ err = floatingips.AssociateInstance(client, server.ID, floatingips.AssociateOpts{FloatingIP: fip.IP}).ExtractErr()
if err != nil {
- errFipDelete := floatingip.Delete(client, fip.ID).ExtractErr()
+ errFipDelete := floatingips.Delete(client, fip.ID).ExtractErr()
err = fmt.Errorf("%s %s", err, errFipDelete)
return cleanup(fmt.Errorf("unable to associate a floating ip: %s", err))
}
@@ -300,9 +387,7 @@ func (vm *VM) Provision() error {
// returns nil if there was an error obtaining the IPs.
func (vm *VM) GetIPs() ([]net.IP, error) {
server, err := getServer(vm)
- if err != nil {
- }
- if server == nil {
+ if server == nil || err != nil {
// Probably need to call Provision first.
return nil, err
}
@@ -352,11 +437,11 @@ func (vm *VM) Destroy() error {
// Delete the floating IP first before destroying the VM
var errors []error
if vm.FloatingIP != nil {
- err = floatingip.Disassociate(client, vm.InstanceID, vm.FloatingIP.IP).ExtractErr()
+ err = floatingips.DisassociateInstance(client, vm.InstanceID, floatingips.DisassociateOpts{FloatingIP: vm.FloatingIP.IP}).ExtractErr()
if err != nil {
errors = append(errors, fmt.Errorf("unable to disassociate floating ip from instance: %s", err))
} else {
- err = floatingip.Delete(client, vm.FloatingIP.ID).ExtractErr()
+ err = floatingips.Delete(client, vm.FloatingIP.ID).ExtractErr()
if err != nil {
errors = append(errors, fmt.Errorf("unable to delete floating ip: %s", err))
}
@@ -372,7 +457,7 @@ func (vm *VM) Destroy() error {
}
// Delete the instance
- err = deleteVM(client, vm)
+ err = deleteVM(client, vm.InstanceID)
if err != nil {
errors = append(errors, err)
}
diff --git a/virtualmachine/virtualbox/util.go b/virtualmachine/virtualbox/util.go
index e37c4919..70f7261b 100644
--- a/virtualmachine/virtualbox/util.go
+++ b/virtualmachine/virtualbox/util.go
@@ -155,10 +155,9 @@ func (vm *VM) requestIPs() []net.IP {
}
func (vm *VM) waitUntilReady() error {
- // Check if the vm already has ips before starting the vm
- // If it does then wait until the timestamp for at least one of them changes.
- var ips []net.IP
- ips = vm.requestIPs()
+ // Check if the VM already has IPs before starting the VM. If it does then
+ // wait until the timestamp for at least one of the changes.
+ ips := vm.requestIPs()
timestamps := map[string]string{}
for k, v := range vm.ipUpdate {
timestamps[k] = v
diff --git a/virtualmachine/virtualbox/vm.go b/virtualmachine/virtualbox/vm.go
index 6b957bb9..9dd742ab 100644
--- a/virtualmachine/virtualbox/vm.go
+++ b/virtualmachine/virtualbox/vm.go
@@ -40,7 +40,6 @@ type NIC struct {
Idx int
Backing Backing
BackingDevice string
- runner Runner
}
// Runner is an encapsulation around the vmrun utility.
@@ -174,7 +173,7 @@ func (vm *VM) GetIPs() ([]net.IP, error) {
// GetState gets the power state of the VM being serviced by this driver.
func (vm *VM) GetState() (string, error) {
- stdout, err := runner.RunCombinedError("showvminfo", fmt.Sprintf("%s", vm.Name))
+ stdout, err := runner.RunCombinedError("showvminfo", vm.Name)
if err != nil {
return "", lvm.WrapErrors(lvm.ErrVMInfoFailed, err)
}
@@ -193,7 +192,7 @@ func (vm *VM) GetState() (string, error) {
// GetInterfaces gets all the network cards attached to this VM
func (vm *VM) GetInterfaces() ([]NIC, error) {
nics := []NIC{}
- stdout, err := runner.RunCombinedError("showvminfo", fmt.Sprintf("%s", vm.Name))
+ stdout, err := runner.RunCombinedError("showvminfo", vm.Name)
if err != nil {
return nil, err
}
@@ -244,7 +243,7 @@ func (vm *VM) Provision() error {
// See comment on mutex definition for details.
createMutex.Lock()
- _, err = runner.RunCombinedError("import", vm.Src, "--vsys", "0", "--vmname", fmt.Sprintf("%s", vm.Name))
+ _, err = runner.RunCombinedError("import", vm.Src, "--vsys", "0", "--vmname", vm.Name)
createMutex.Unlock()
if err != nil {
return err
diff --git a/virtualmachine/vmrun/util.go b/virtualmachine/vmrun/util.go
index 61f28d1f..b4d4ee2d 100644
--- a/virtualmachine/vmrun/util.go
+++ b/virtualmachine/vmrun/util.go
@@ -3,6 +3,7 @@
package vmrun
import (
+ "fmt"
"io"
"os"
"path/filepath"
@@ -19,9 +20,17 @@ func copyDir(src string, dest string) error {
return err
}
- dir, _ := os.Open(src)
+ dir, err := os.Open(src)
+ if err != nil {
+ return err
+ }
+ defer dir.Close()
+
// Pass -1 to Readdir to make it read everything into a single slice
children, err := dir.Readdir(-1)
+ if err != nil {
+ return fmt.Errorf("failed to read files from directory %q: %v", src, err)
+ }
for _, child := range children {
newSrc := filepath.Join(src, child.Name())
diff --git a/virtualmachine/vmrun/vm.go b/virtualmachine/vmrun/vm.go
index 357517d6..c0d67f47 100644
--- a/virtualmachine/vmrun/vm.go
+++ b/virtualmachine/vmrun/vm.go
@@ -324,7 +324,11 @@ func (vm *VM) Provision() error {
return err
}
- runVMware()
+ _, _, err = runVMware()
+ if err != nil {
+ return err
+ }
+
return vm.waitUntilReady()
}
diff --git a/virtualmachine/vsphere/util.go b/virtualmachine/vsphere/util.go
index 443894bb..f71ff555 100644
--- a/virtualmachine/vsphere/util.go
+++ b/virtualmachine/vsphere/util.go
@@ -24,6 +24,7 @@ import (
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/object"
+ "github.com/vmware/govmomi/ovf"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/mo"
@@ -1423,7 +1424,7 @@ var uploadTemplate = func(vm *VM, dcMo *mo.Datacenter, selectedDatastore string)
PropertyMapping: nil,
}
- ovfManager := object.NewOvfManager(vm.client.Client)
+ ovfManager := ovf.NewManager(vm.client.Client)
rpo := object.NewResourcePool(vm.client.Client, l.ResourcePool)
specResult, err := ovfManager.CreateImportSpec(vm.ctx, ovfContent, rpo,
diff --git a/virtualmachine/vsphere/vm.go b/virtualmachine/vsphere/vm.go
index a5756388..bbd018ab 100644
--- a/virtualmachine/vsphere/vm.go
+++ b/virtualmachine/vsphere/vm.go
@@ -22,8 +22,8 @@ import (
lvm "github.com/apcera/libretto/virtualmachine"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/find"
+ "github.com/vmware/govmomi/nfc"
"github.com/vmware/govmomi/object"
- "github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
@@ -64,7 +64,7 @@ func (v vmwareFinder) NetworkList(c context.Context, p string) ([]object.Network
}
// NewLease creates a VMwareLease.
-var NewLease = func(ctx context.Context, lease *object.HttpNfcLease) Lease {
+var NewLease = func(ctx context.Context, lease *nfc.Lease) Lease {
return VMwareLease{
Ctx: ctx,
Lease: lease,
@@ -74,23 +74,23 @@ var NewLease = func(ctx context.Context, lease *object.HttpNfcLease) Lease {
// VMwareLease implements the Lease interface.
type VMwareLease struct {
Ctx context.Context
- Lease *object.HttpNfcLease
+ Lease *nfc.Lease
}
-// HTTPNfcLeaseProgress takes a percentage as an int and sets that percentage as
-// the completed percent.
-func (v VMwareLease) HTTPNfcLeaseProgress(p int32) {
- v.Lease.HttpNfcLeaseProgress(v.Ctx, p)
+// Progress takes a percentage as an int and sets that percentage as the
+// completed percent.
+func (v VMwareLease) Progress(p int) {
+ v.Lease.Progress(v.Ctx, int32(p))
}
// Wait waits for the underlying lease to finish.
-func (v VMwareLease) Wait() (*types.HttpNfcLeaseInfo, error) {
- return v.Lease.Wait(v.Ctx)
+func (v VMwareLease) Wait() (*nfc.LeaseInfo, error) {
+ return v.Lease.Wait(v.Ctx, nil)
}
// Complete marks the underlying lease as complete.
func (v VMwareLease) Complete() error {
- return v.Lease.HttpNfcLeaseComplete(v.Ctx)
+ return v.Lease.Complete(v.Ctx)
}
type Datastore struct {
@@ -258,7 +258,7 @@ func (r ReadProgress) StartProgress() {
r.wg.Add(1)
go func() {
var bytesReceived int64
- var percent int32
+ var percent int
tick := time.NewTicker(5 * time.Second)
defer tick.Stop()
defer r.wg.Done()
@@ -266,10 +266,10 @@ func (r ReadProgress) StartProgress() {
select {
case b := <-r.ch:
bytesReceived += b
- percent = int32((float32(bytesReceived) / float32(r.TotalBytes)) * 100)
+ percent = int((float32(bytesReceived) / float32(r.TotalBytes)) * 100)
case <-tick.C:
// TODO: Preet This can return an error as well, should return it
- r.Lease.HTTPNfcLeaseProgress(percent)
+ r.Lease.Progress(percent)
if percent == 100 {
return
}
@@ -443,18 +443,6 @@ type finder interface {
SetDatacenter(*object.Datacenter) *find.Finder
}
-type vmwareCollector struct {
- collector *property.Collector
-}
-
-func (v vmwareCollector) RetrieveOne(c context.Context, mor types.ManagedObjectReference, ps []string, dst interface{}) error {
- return v.collector.RetrieveOne(c, mor, ps, dst)
-}
-
-func (v vmwareCollector) Retrieve(c context.Context, mor []types.ManagedObjectReference, ps []string, dst interface{}) error {
- return v.collector.Retrieve(c, mor, ps, dst)
-}
-
type location struct {
Host types.ManagedObjectReference
ResourcePool types.ManagedObjectReference
@@ -473,10 +461,10 @@ type Destination struct {
HostSystem string
}
-// Lease represents a type that wraps around a HTTPNfcLease
+// Lease represents a type that wraps around a nfc.Lease
type Lease interface {
- HTTPNfcLeaseProgress(int32)
- Wait() (*types.HttpNfcLeaseInfo, error)
+ Progress(int)
+ Wait() (*nfc.LeaseInfo, error)
Complete() error
}
@@ -580,7 +568,10 @@ func (vm *VM) Provision() (err error) {
}
// Cancel the sdk context
- defer vm.cancel()
+ defer func() {
+ vm.client.Logout(vm.ctx)
+ vm.cancel()
+ }()
// Get a reference to the datacenter with host and vm folders populated
dcMo, err := GetDatacenter(vm)
@@ -791,7 +782,10 @@ func (vm *VM) GetIPsAndId() ([]net.IP, string, error) {
if err := SetupSession(vm); err != nil {
return nil, "", err
}
- defer vm.cancel()
+ defer func() {
+ vm.client.Logout(vm.ctx)
+ vm.cancel()
+ }()
// Get a reference to the datacenter with host and vm folders populated
dcMo, err := GetDatacenter(vm)
@@ -818,7 +812,10 @@ func (vm *VM) Destroy() (err error) {
if err := SetupSession(vm); err != nil {
return err
}
- defer vm.cancel()
+ defer func() {
+ vm.client.Logout(vm.ctx)
+ vm.cancel()
+ }()
// Get a reference to the datacenter with host and vm folders populated
dcMo, err := GetDatacenter(vm)
@@ -998,8 +995,10 @@ func (vm *VM) GetState() (state string, err error) {
if err := SetupSession(vm); err != nil {
return "", lvm.ErrVMInfoFailed
}
- defer vm.cancel()
-
+ defer func() {
+ vm.client.Logout(vm.ctx)
+ vm.cancel()
+ }()
state, err = getState(vm)
if err != nil {
return "", err
@@ -1021,7 +1020,11 @@ func (vm *VM) Suspend() (err error) {
if err := SetupSession(vm); err != nil {
return err
}
- defer vm.cancel()
+
+ defer func() {
+ vm.client.Logout(vm.ctx)
+ vm.cancel()
+ }()
// Get a reference to the datacenter with host and vm folders populated
dcMo, err := GetDatacenter(vm)
@@ -1052,7 +1055,11 @@ func (vm *VM) Halt() (err error) {
if err := SetupSession(vm); err != nil {
return err
}
- defer vm.cancel()
+ defer func() {
+ vm.client.Logout(vm.ctx)
+ vm.cancel()
+ }()
+
return halt(vm)
}
@@ -1079,7 +1086,11 @@ func (vm *VM) Start() (err error) {
if err := SetupSession(vm); err != nil {
return err
}
- defer vm.cancel()
+ defer func() {
+ vm.client.Logout(vm.ctx)
+ vm.cancel()
+ }()
+
return start(vm)
}
diff --git a/virtualmachine/vsphere/vm_test.go b/virtualmachine/vsphere/vm_test.go
index 70682780..292eb6c9 100644
--- a/virtualmachine/vsphere/vm_test.go
+++ b/virtualmachine/vsphere/vm_test.go
@@ -3,6 +3,7 @@
package vsphere
import (
+ "context"
"errors"
"fmt"
"io"
@@ -12,10 +13,9 @@ import (
"strings"
"testing"
- "golang.org/x/net/context"
-
"github.com/apcera/libretto/virtualmachine"
"github.com/vmware/govmomi"
+ "github.com/vmware/govmomi/nfc"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25"
@@ -58,11 +58,11 @@ type mockCollector struct {
type mockLease struct {
MockLeaseProgress func(p int)
- MockWait func() (*types.HttpNfcLeaseInfo, error)
+ MockWait func() (*nfc.LeaseInfo, error)
MockComplete func() error
}
-func (m mockLease) HTTPNfcLeaseProgress(p int) {
+func (m mockLease) Progress(p int) {
if m.MockLeaseProgress != nil {
m.MockLeaseProgress(p)
}
@@ -75,7 +75,7 @@ func (m mockLease) Complete() error {
return nil
}
-func (m mockLease) Wait() (*types.HttpNfcLeaseInfo, error) {
+func (m mockLease) Wait() (*nfc.LeaseInfo, error) {
if m.MockWait != nil {
return m.MockWait()
}
@@ -547,7 +547,7 @@ func TestResetUnitNumbers(t *testing.T) {
vmSpec.ConfigSpec.DeviceChange = []types.BaseVirtualDeviceConfigSpec{
&types.VirtualDeviceConfigSpec{
Device: &types.VirtualDevice{
- UnitNumber: 0,
+ UnitNumber: new(int32),
},
},
}
@@ -558,14 +558,14 @@ func TestResetUnitNumbers(t *testing.T) {
if len(s.DeviceChange) != 1 {
t.Fatalf("Expected only one device, got: %d", len(s.DeviceChange))
}
- if n := s.DeviceChange[0].GetVirtualDeviceConfigSpec().Device.GetVirtualDevice().UnitNumber; n != -1 {
+ if n := s.DeviceChange[0].GetVirtualDeviceConfigSpec().Device.GetVirtualDevice().UnitNumber; *n != -1 {
t.Fatalf("Expected to get -1 for the unit number, got: %d", n)
}
}
func TestUploadOvfLeaseWaitError(t *testing.T) {
l := mockLease{
- MockWait: func() (*types.HttpNfcLeaseInfo, error) {
+ MockWait: func() (*nfc.LeaseInfo, error) {
return nil, fmt.Errorf("Error waiting on the nfc lease")
},
}
@@ -577,133 +577,6 @@ func TestUploadOvfLeaseWaitError(t *testing.T) {
}
}
-func TestUploadOvfOpenError(t *testing.T) {
- l := mockLease{
- MockWait: func() (*types.HttpNfcLeaseInfo, error) {
- li := types.HttpNfcLeaseInfo{
- DeviceUrl: []types.HttpNfcLeaseDeviceUrl{
- {
- Url: "http://*/",
- },
- },
- }
- return &li, nil
- },
- }
- var oldOpen = open
- defer func() {
- open = oldOpen
- }()
- expectedError := "failed to open file"
- open = func(name string) (file *os.File, err error) {
- return nil, fmt.Errorf(expectedError)
- }
- vm := VM{}
- sr := types.OvfCreateImportSpecResult{
- FileItem: []types.OvfFileItem{
- {},
- },
- }
- err := uploadOvf(&vm, &sr, l)
- if err.Error() != expectedError {
- t.Fatalf("Expected to get an error %s, got: %s", expectedError, err)
- }
-}
-
-func TestUploadOvfCreateRequestError(t *testing.T) {
- l := mockLease{
- MockWait: func() (*types.HttpNfcLeaseInfo, error) {
- li := types.HttpNfcLeaseInfo{
- DeviceUrl: []types.HttpNfcLeaseDeviceUrl{
- {
- Url: "http://*/",
- },
- },
- }
- return &li, nil
- },
- }
- fileName := "test"
- var oldOpen = open
- var oldCreateRequest = createRequest
- defer func() {
- open = oldOpen
- createRequest = oldCreateRequest
- }()
- expectedError := "failed to create request"
- open = func(name string) (file *os.File, err error) {
- return os.Create(fileName)
- }
- createRequest = func(r io.Reader, method string, insecure bool, length int64, url string, contentType string) error {
- return fmt.Errorf(expectedError)
- }
- defer func() {
- err := os.RemoveAll(fileName)
- if err != nil {
- panic("Unable to remove temp file for test")
- }
- }()
- vm := VM{}
- sr := types.OvfCreateImportSpecResult{
- FileItem: []types.OvfFileItem{
- {},
- },
- }
- err := uploadOvf(&vm, &sr, l)
- if err.Error() != expectedError {
- t.Fatalf("Expected to get an error %s, got: %s", expectedError, err)
- }
-}
-
-func TestUploadOvfHappyPath(t *testing.T) {
- l := mockLease{
- MockWait: func() (*types.HttpNfcLeaseInfo, error) {
- li := types.HttpNfcLeaseInfo{
- DeviceUrl: []types.HttpNfcLeaseDeviceUrl{
- {
- Url: "http://*/",
- },
- },
- }
- return &li, nil
- },
- }
- fileName := "test"
- var oldOpen = open
- var oldCreateRequest = createRequest
- var oldNewProgressReader = NewProgressReader
- defer func() {
- open = oldOpen
- createRequest = oldCreateRequest
- NewProgressReader = oldNewProgressReader
- }()
- open = func(name string) (file *os.File, err error) {
- return os.Create(fileName)
- }
- createRequest = func(r io.Reader, method string, insecure bool, length int64, url string, contentType string) error {
- return nil
- }
- NewProgressReader = func(r io.Reader, t int64, l Lease) ProgressReader {
- return mockProgressReader{}
- }
- defer func() {
- err := os.RemoveAll(fileName)
- if err != nil {
- panic("Unable to remove temp file for test")
- }
- }()
- vm := VM{}
- sr := types.OvfCreateImportSpecResult{
- FileItem: []types.OvfFileItem{
- {},
- },
- }
- err := uploadOvf(&vm, &sr, l)
- if err != nil {
- t.Fatalf("Expected to get no error, got: %s", err)
- }
-}
-
func TestCreateRequestNewRequestError(t *testing.T) {
errProtocol := `unsupported protocol scheme ""`
err := createRequest(mockProgressReader{}, "foo", true, 0, "", "foo")