Update vmware/govmomi godeps

This commit is contained in:
Doug MacEachern
2017-11-16 20:13:29 -08:00
parent 8a9954d471
commit 09da53c8e9
125 changed files with 26926 additions and 934 deletions

View File

@@ -1 +0,0 @@
eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.kK6pryC8R-O1R0Gj9ydLvQuIZlcYLGze23WdW7xbpiEEKdz6nweJrMm7ysy8lgu1tM47JVo19p2_b26bNKSQshCUOETvd7Hb2UMZOjnyUnqdyAAyoi6UkIquXfUUbHTNS0iMxwSxxW9KMp2GXNq8-o6T8xQZTDirBJFKKd8ZNUasTaoa5j8U9IfdR1aCavTBuOhvk8IVs-jSbY5TVJMJiE0IOPXois7aRJ6uAiANQBk9VKLegEcZD_qAewecXHDsHi-u0jbmg3o3PPaJaK_Qv5dsPlR2M-E2kE3AGUn0-zn5zYRngoAZ8WZr2O4GvLdltJKq9i2z7jOrdOzzRcDRow.96qvwl_E1Hj15u7Q.hWs-jQ8FsqQFD7pE9N-UEP1BWQ9rsJIcCaPvQRIp8Fukm_vvlw9YEaEq0ERLrsUWsJWpd1ca8_h8x7xD6f_d5YppwRqRHIeGIsdBOTMhNs0lG8ikkQXLat-UroCpy8EC17nuUtDE2E2Kdxrk4Cdd6Bk-dKk0Ta4w3Ud0YBKa.P8zrO7xizgv0i98eVWWzEg

View File

@@ -1,17 +0,0 @@
clone:
tags: true
path: github.com/vmware/govmomi
build:
image: golang:1.7
pull: true
environment:
- GOVC_TEST_URL=$$GOVC_TEST_URL
- GOVC_INSECURE=1
- VCA=1
commands:
- make all install
- git clone https://github.com/sstephenson/bats.git /tmp/bats
- /tmp/bats/install.sh /usr/local
- apt-get -qq update && apt-get install -yqq uuid-runtime bsdmainutils jq
- govc/test/images/update.sh
- bats govc/test

View File

@@ -13,4 +13,7 @@ Pieter Noordhuis <pnoordhuis@vmware.com> <pcnoordhuis@gmail.com>
Takaaki Furukawa <takaaki.frkw@gmail.com> takaaki.furukawa <takaaki.furukawa@mail.rakuten.com>
Takaaki Furukawa <takaaki.frkw@gmail.com> tkak <takaaki.frkw@gmail.com>
Vadim Egorov <vegorov@vmware.com> <egorovv@gmail.com>
Anfernee Yongkun Gui <agui@vmware.com> <anfernee.gui@gmail.com>
Anfernee Yongkun Gui <agui@vmware.com> Yongkun Anfernee Gui <agui@vmware.com>
Zach Tucker <ztucker@vmware.com> <jzt@users.noreply.github.com>
Zee Yang <zeey@vmware.com> <zee.yang@gmail.com>

View File

@@ -3,7 +3,7 @@ sudo: false
language: go
go:
- 1.7
- 1.8
before_install:
- make vendor

View File

@@ -27,10 +27,12 @@ filegroup(
":package-srcs",
"//vendor/github.com/vmware/govmomi/find:all-srcs",
"//vendor/github.com/vmware/govmomi/list:all-srcs",
"//vendor/github.com/vmware/govmomi/nfc:all-srcs",
"//vendor/github.com/vmware/govmomi/object:all-srcs",
"//vendor/github.com/vmware/govmomi/pbm:all-srcs",
"//vendor/github.com/vmware/govmomi/property:all-srcs",
"//vendor/github.com/vmware/govmomi/session:all-srcs",
"//vendor/github.com/vmware/govmomi/simulator:all-srcs",
"//vendor/github.com/vmware/govmomi/task:all-srcs",
"//vendor/github.com/vmware/govmomi/vim25:all-srcs",
],

View File

@@ -1,5 +1,36 @@
# changelog
### 0.16.0 (2017-11-08)
* Add support for SOAP request operation ID header
* Moved ovf helpers from govc import.ovf command to ovf and nfc packages
* Added guest/toolbox (client) package
* Added toolbox package and toolbox command
* Added simulator package and vcsim command
### 0.15.0 (2017-06-19)
* WaitOptions.MaxWaitSeconds is now optional
* Support removal of ExtraConfig entries
* GuestPosixFileAttributes OwnerId and GroupId fields are now pointers,
rather than omitempty ints to allow chown with root uid:gid
* Updated examples/ using view package
* Add DatastoreFile.TailFunc method
* Export VirtualMachine.FindSnapshot method
* Add AuthorizationManager {Enable,Disable}Methods
* Add PBM client
### 0.14.0 (2017-04-08)
* Add view.ContainerView type and methods

View File

@@ -17,6 +17,16 @@ git remote add $USER git@github.com:$USER/govmomi.git
git fetch $USER
```
## Installing from source
Compile the govmomi libraries and install govc using:
``` shell
go install -v github.com/vmware/govmomi/govc
```
Note that **govc/build.sh** is only used for building release binaries.
## Contribution flow
This is a rough outline of what a contributor's workflow looks like:

View File

@@ -3,12 +3,20 @@
# This script is generated by contributors.sh
#
Abhijeet Kasurde <akasurde@redhat.com>
abrarshivani <abrarshivani@users.noreply.github.com>
Adam Shannon <adamkshannon@gmail.com>
Alvaro Miranda <kikitux@gmail.com>
amandahla <amanda.andrade@serpro.gov.br>
Amit Bathla <abathla@.vmware.com>
amit bezalel <amit.bezalel@hpe.com>
Andrew Chin <andrew@andrewtchin.com>
Anfernee Yongkun Gui <agui@vmware.com>
aniketGslab <aniket.shinde@gslab.com>
Arran Walker <arran.walker@zopa.com>
Aryeh Weinreb <aryehweinreb@gmail.com>
Austin Parker <aparker@apprenda.com>
Balu Dontu <bdontu@vmware.com>
bastienbc <bastien.barbe.creuly@gmail.com>
Bob Killen <killen.bob@gmail.com>
Brad Fitzpatrick <bradfitz@golang.org>
@@ -35,8 +43,10 @@ gthombare <gthombare@vmware.com>
Hasan Mahmood <mahmoodh@vmware.com>
Henrik Hodne <henrik@travis-ci.com>
Isaac Rodman <isaac@eyz.us>
Ivan Porto Carrero <icarrero@vmware.com>
Jason Kincl <jkincl@gmail.com>
Jeremy Canady <jcanady@jackhenry.com>
João Pereira <joaodrp@gmail.com>
Louie Jiang <jiangl@vmware.com>
Marc Carmier <mcarmier@gmail.com>
Mevan Samaratunga <mevansam@gmail.com>
@@ -47,7 +57,9 @@ S.Çağlar Onur <conur@vmware.com>
Sergey Ignatov <sergey.ignatov@jetbrains.com>
Steve Purcell <steve@sanityinc.com>
Takaaki Furukawa <takaaki.frkw@gmail.com>
tanishi <tanishi503@gmail.com>
Ted Zlatanov <tzz@lifelogs.com>
Thibaut Ackermann <thibaut.ackermann@alcatel-lucent.com>
Vadim Egorov <vegorov@vmware.com>
Yang Yang <yangy@vmware.com>
Yuya Kusakabe <yuya.kusakabe@gmail.com>

View File

@@ -11,13 +11,19 @@ goimports:
govet:
@echo checking go vet...
@go tool vet -structtags=false -methods=false .
test:
go test -v $(TEST_OPTS) ./...
@go tool vet -structtags=false -methods=false $$(find . -mindepth 1 -maxdepth 1 -type d -not -name vendor)
install:
go install github.com/vmware/govmomi/govc
go install -v github.com/vmware/govmomi/govc
go install -v github.com/vmware/govmomi/vcsim
go-test:
go test -v $(TEST_OPTS) ./...
govc-test: install
(cd govc/test && ./vendor/github.com/sstephenson/bats/libexec/bats -t .)
test: go-test govc-test
doc: install
./govc/usage.sh > ./govc/USAGE.md

View File

@@ -5,14 +5,19 @@
A Go library for interacting with VMware vSphere APIs (ESXi and/or vCenter).
For `govc`, a CLI built on top of govmomi, check out the [govc](./govc) directory and [USAGE](./govc/USAGE.md) document.
In addition to the vSphere API client, this repository includes:
* [govc](./govc) - vSphere CLI
* [vcsim](./vcsim) - vSphere API mock framework
* [toolbox](./toolbox) - VM guest tools framework
## Compatibility
This library is built for and tested against ESXi and vCenter 5.5, 6.0 and 6.5.
This library is built for and tested against ESXi and vCenter 6.0 and 6.5.
If you're able to use it against older versions of ESXi and/or vCenter, please
leave a note and we'll include it in this compatibility list.
It should work with versions 5.5 and 5.1, but neither are officially supported.
## Documentation
@@ -23,19 +28,14 @@ The code in the `govmomi` package is a wrapper for the code that is generated fr
It primarily provides convenience functions for working with the vSphere API.
See [godoc.org][godoc] for documentation.
[apiref]:http://pubs.vmware.com/vsphere-60/index.jsp#com.vmware.wssdk.apiref.doc/right-pane.html
[apiref]:http://pubs.vmware.com/vsphere-6-5/index.jsp#com.vmware.wssdk.apiref.doc/right-pane.html
[godoc]:http://godoc.org/github.com/vmware/govmomi
[drone]:https://drone.io
[dronesrc]:https://github.com/drone/drone
[dronecli]:http://readme.drone.io/devs/cli/
#### Building with CI
Merges to this repository will trigger builds in both Travis and [Drone][drone].
## Installation
To build locally with Drone:
- Ensure that you have Docker 1.6 or higher installed.
- Install the [Drone command line tools][dronecli].
- Run `drone exec` from within the root directory of the govmomi repository.
```sh
go get -u github.com/vmware/govmomi
```
## Discussion
@@ -53,9 +53,17 @@ Refer to the [CHANGELOG](CHANGELOG.md) for version to version changes.
* [Docker Machine](https://github.com/docker/machine/tree/master/drivers/vmwarevsphere)
* [Docker InfraKit](https://github.com/docker/infrakit/tree/master/pkg/provider/vsphere)
* [Docker LinuxKit](https://github.com/linuxkit/linuxkit/tree/master/src/cmd/linuxkit)
* [Kubernetes](https://github.com/kubernetes/kubernetes/tree/master/pkg/cloudprovider/providers/vsphere)
* [Terraform](https://github.com/hashicorp/terraform/tree/master/builtin/providers/vsphere)
* [Kubernetes kops](https://github.com/kubernetes/kops/tree/master/upup/pkg/fi/cloudup/vsphere)
* [Terraform](https://github.com/terraform-providers/terraform-provider-vsphere)
* [Packer](https://github.com/jetbrains-infra/packer-builder-vsphere)
* [VMware VIC Engine](https://github.com/vmware/vic)

View File

@@ -20,6 +20,7 @@ import (
"context"
"os"
"path"
"strings"
"github.com/vmware/govmomi/list"
"github.com/vmware/govmomi/object"
@@ -177,6 +178,7 @@ func (r recurser) List(ctx context.Context, s *spec, root list.Element, parts []
return in, nil
}
all := parts
pattern := parts[0]
parts = parts[1:]
@@ -188,6 +190,12 @@ func (r recurser) List(ctx context.Context, s *spec, root list.Element, parts []
}
if !matched {
matched = strings.HasSuffix(e.Path, "/"+path.Join(all...))
if matched {
// name contains a '/'
out = append(out, e)
}
continue
}

34
vendor/github.com/vmware/govmomi/nfc/BUILD generated vendored Normal file
View File

@@ -0,0 +1,34 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"lease.go",
"lease_updater.go",
],
importpath = "github.com/vmware/govmomi/nfc",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/vmware/govmomi/property:go_default_library",
"//vendor/github.com/vmware/govmomi/vim25:go_default_library",
"//vendor/github.com/vmware/govmomi/vim25/methods:go_default_library",
"//vendor/github.com/vmware/govmomi/vim25/mo:go_default_library",
"//vendor/github.com/vmware/govmomi/vim25/progress:go_default_library",
"//vendor/github.com/vmware/govmomi/vim25/soap:go_default_library",
"//vendor/github.com/vmware/govmomi/vim25/types:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

238
vendor/github.com/vmware/govmomi/nfc/lease.go generated vendored Normal file
View File

@@ -0,0 +1,238 @@
/*
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"
"path"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/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)
}
if len(items) == 0 {
// this is an export
item := types.OvfFileItem{
DeviceId: device.Key,
Path: device.TargetId,
Size: device.FileSize,
}
if item.Size == 0 {
item.Size = li.TotalDiskCapacityInKB * 1024
}
if item.Path == "" {
item.Path = path.Base(device.Url)
}
info.Items = append(info.Items, NewFileItem(u, item))
continue
}
// this is an import
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)
}
func (l *Lease) DownloadFile(ctx context.Context, file string, item FileItem, opts soap.Download) error {
if opts.Progress == nil {
opts.Progress = item
} else {
opts.Progress = progress.Tee(item, opts.Progress)
}
return l.c.DownloadFile(file, item.URL, &opts)
}

146
vendor/github.com/vmware/govmomi/nfc/lease_updater.go generated vendored Normal file
View File

@@ -0,0 +1,146 @@
/*
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 nfc
import (
"context"
"log"
"net/url"
"sync"
"sync/atomic"
"time"
"github.com/vmware/govmomi/vim25/progress"
"github.com/vmware/govmomi/vim25/types"
)
type FileItem struct {
types.OvfFileItem
URL *url.URL
ch 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
}
// File converts the FileItem.OvfFileItem to an OvfFile
func (o FileItem) File() types.OvfFile {
return types.OvfFile{
DeviceId: o.DeviceId,
Path: o.Path,
Size: o.Size,
}
}
type LeaseUpdater struct {
lease *Lease
pos int64 // Number of bytes
total int64 // Total number of bytes
done chan struct{} // When lease updater should stop
wg sync.WaitGroup // Track when update loop is done
}
func newLeaseUpdater(ctx context.Context, lease *Lease, info *LeaseInfo) *LeaseUpdater {
l := LeaseUpdater{
lease: lease,
done: make(chan struct{}),
}
for _, item := range info.Items {
l.total += item.Size
go l.waitForProgress(item)
}
// Kickstart update loop
l.wg.Add(1)
go l.run()
return &l
}
func (l *LeaseUpdater) waitForProgress(item FileItem) {
var pos, total int64
total = item.Size
for {
select {
case <-l.done:
return
case p, ok := <-item.ch:
// Return in case of error
if ok && p.Error() != nil {
return
}
if !ok {
// Last element on the channel, add to total
atomic.AddInt64(&l.pos, total-pos)
return
}
// Approximate progress in number of bytes
x := int64(float32(total) * (p.Percentage() / 100.0))
atomic.AddInt64(&l.pos, x-pos)
pos = x
}
}
}
func (l *LeaseUpdater) run() {
defer l.wg.Done()
tick := time.NewTicker(2 * time.Second)
defer tick.Stop()
for {
select {
case <-l.done:
return
case <-tick.C:
// From the vim api HttpNfcLeaseProgress(percent) doc, percent ==
// "Completion status represented as an integer in the 0-100 range."
// 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.Progress(context.TODO(), percent)
if err != nil {
log.Printf("NFC lease progress: %s", err)
return
}
}
}
}
func (l *LeaseUpdater) Done() {
close(l.done)
l.wg.Wait()
}

View File

@@ -38,13 +38,11 @@ go_library(
"host_virtual_nic_manager.go",
"host_vsan_internal_system.go",
"host_vsan_system.go",
"http_nfc_lease.go",
"namespace_manager.go",
"network.go",
"network_reference.go",
"opaque_network.go",
"option_manager.go",
"ovf_manager.go",
"resource_pool.go",
"search_index.go",
"storage_pod.go",
@@ -61,6 +59,7 @@ go_library(
importpath = "github.com/vmware/govmomi/object",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/vmware/govmomi/nfc:go_default_library",
"//vendor/github.com/vmware/govmomi/property:go_default_library",
"//vendor/github.com/vmware/govmomi/session:go_default_library",
"//vendor/github.com/vmware/govmomi/task:go_default_library",

View File

@@ -80,17 +80,24 @@ 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
}
return o.Name, nil
if o.Name != "" {
return o.Name, nil
}
// Network has its own "name" field...
var n mo.Network
err = c.Properties(ctx, c.Reference(), []string{"name"}, &n)
if err != nil {
return "", err
}
return n.Name, nil
}
func (c Common) Properties(ctx context.Context, r types.ManagedObjectReference, ps []string, dst interface{}) error {

View File

@@ -102,7 +102,9 @@ func (m CustomFieldsManager) Set(ctx context.Context, entity types.ManagedObject
return err
}
func (m CustomFieldsManager) Field(ctx context.Context) ([]types.CustomFieldDef, error) {
type CustomFieldDefList []types.CustomFieldDef
func (m CustomFieldsManager) Field(ctx context.Context) (CustomFieldDefList, error) {
var fm mo.CustomFieldsManager
err := m.Properties(ctx, m.Reference(), []string{"field"}, &fm)
@@ -113,19 +115,19 @@ func (m CustomFieldsManager) Field(ctx context.Context) ([]types.CustomFieldDef,
return fm.Field, nil
}
func (m CustomFieldsManager) FindKey(ctx context.Context, key string) (int32, error) {
func (m CustomFieldsManager) FindKey(ctx context.Context, name string) (int32, error) {
field, err := m.Field(ctx)
if err != nil {
return -1, err
}
for _, def := range field {
if def.Name == key {
if def.Name == name {
return def.Key, nil
}
}
k, err := strconv.Atoi(key)
k, err := strconv.Atoi(name)
if err == nil {
// assume literal int key
return int32(k), nil
@@ -133,3 +135,12 @@ func (m CustomFieldsManager) FindKey(ctx context.Context, key string) (int32, er
return -1, ErrKeyNameNotFound
}
func (l CustomFieldDefList) ByKey(key int32) *types.CustomFieldDef {
for _, def := range l {
if def.Key == key {
return &def
}
}
return nil
}

View File

@@ -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.
@@ -387,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,
}
}

View File

@@ -97,6 +97,25 @@ func (m *DatastoreFileManager) DeleteVirtualDisk(ctx context.Context, name strin
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

View File

@@ -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"
}

View File

@@ -38,7 +38,7 @@ func NewDistributedVirtualPortgroup(c *vim25.Client, ref types.ManagedObjectRefe
// EthernetCardBackingInfo returns the VirtualDeviceBackingInfo for this DistributedVirtualPortgroup
func (p DistributedVirtualPortgroup) EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) {
var dvp mo.DistributedVirtualPortgroup
var dvs mo.VmwareDistributedVirtualSwitch // TODO: should be mo.BaseDistributedVirtualSwitch
var dvs mo.DistributedVirtualSwitch
if err := p.Properties(ctx, p.Reference(), []string{"key", "config.distributedVirtualSwitch"}, &dvp); err != nil {
return nil, err

View File

@@ -65,3 +65,15 @@ func (s DistributedVirtualSwitch) AddPortgroup(ctx context.Context, spec []types
return NewTask(s.Client(), res.Returnval), nil
}
func (s DistributedVirtualSwitch) FetchDVPorts(ctx context.Context) ([]types.DistributedVirtualPort, error) {
req := &types.FetchDVPorts{
This: s.Reference(),
}
res, err := methods.FetchDVPorts(ctx, s.Client(), req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}

View File

@@ -88,6 +88,15 @@ func (s HostStorageSystem) RescanAllHba(ctx context.Context) error {
return err
}
func (s HostStorageSystem) Refresh(ctx context.Context) error {
req := types.RefreshStorageSystem{
This: s.Reference(),
}
_, err := methods.RefreshStorageSystem(ctx, s.c, &req)
return err
}
func (s HostStorageSystem) MarkAsSsd(ctx context.Context, uuid string) (*Task, error) {
req := types.MarkAsSsd_Task{
This: s.Reference(),

View File

@@ -42,7 +42,7 @@ func (m HostVsanInternalSystem) QueryVsanObjectUuidsByFilter(ctx context.Context
req := types.QueryVsanObjectUuidsByFilter{
This: m.Reference(),
Uuids: uuids,
Limit: limit,
Limit: &limit,
Version: version,
}

View File

@@ -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)
}

View File

@@ -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,
},
}

View File

@@ -1,104 +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 OvfManager struct {
Common
}
func NewOvfManager(c *vim25.Client) *OvfManager {
o := OvfManager{
Common: NewCommon(c, *c.ServiceContent.OvfManager),
}
return &o
}
// CreateDescriptor wraps methods.CreateDescriptor
func (o OvfManager) CreateDescriptor(ctx context.Context, obj Reference, cdp types.OvfCreateDescriptorParams) (*types.OvfCreateDescriptorResult, error) {
req := types.CreateDescriptor{
This: o.Reference(),
Obj: obj.Reference(),
Cdp: cdp,
}
res, err := methods.CreateDescriptor(ctx, o.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
// CreateImportSpec wraps methods.CreateImportSpec
func (o OvfManager) CreateImportSpec(ctx context.Context, ovfDescriptor string, resourcePool Reference, datastore Reference, cisp types.OvfCreateImportSpecParams) (*types.OvfCreateImportSpecResult, error) {
req := types.CreateImportSpec{
This: o.Reference(),
OvfDescriptor: ovfDescriptor,
ResourcePool: resourcePool.Reference(),
Datastore: datastore.Reference(),
Cisp: cisp,
}
res, err := methods.CreateImportSpec(ctx, o.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
// ParseDescriptor wraps methods.ParseDescriptor
func (o OvfManager) ParseDescriptor(ctx context.Context, ovfDescriptor string, pdp types.OvfParseDescriptorParams) (*types.OvfParseDescriptorResult, error) {
req := types.ParseDescriptor{
This: o.Reference(),
OvfDescriptor: ovfDescriptor,
Pdp: pdp,
}
res, err := methods.ParseDescriptor(ctx, o.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
// ValidateHost wraps methods.ValidateHost
func (o OvfManager) ValidateHost(ctx context.Context, ovfDescriptor string, host Reference, vhp types.OvfValidateHostParams) (*types.OvfValidateHostResult, error) {
req := types.ValidateHost{
This: o.Reference(),
OvfDescriptor: ovfDescriptor,
Host: host.Reference(),
Vhp: vhp,
}
res, err := methods.ValidateHost(ctx, o.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}

View File

@@ -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) {

View File

@@ -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
}

View File

@@ -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.
@@ -30,6 +30,7 @@ import (
// Type values for use in BootOrder
const (
DeviceTypeNone = "-"
DeviceTypeCdrom = "cdrom"
DeviceTypeDisk = "disk"
DeviceTypeEthernet = "ethernet"
@@ -754,6 +755,9 @@ func (l VirtualDeviceList) PrimaryMacAddress() string {
// convert a BaseVirtualDevice to a BaseVirtualMachineBootOptionsBootableDevice
var bootableDevices = map[string]func(device types.BaseVirtualDevice) types.BaseVirtualMachineBootOptionsBootableDevice{
DeviceTypeNone: func(types.BaseVirtualDevice) types.BaseVirtualMachineBootOptionsBootableDevice {
return &types.VirtualMachineBootOptionsBootableDevice{}
},
DeviceTypeCdrom: func(types.BaseVirtualDevice) types.BaseVirtualMachineBootOptionsBootableDevice {
return &types.VirtualMachineBootOptionsBootableCdromDevice{}
},
@@ -773,17 +777,23 @@ var bootableDevices = map[string]func(device types.BaseVirtualDevice) types.Base
}
// BootOrder returns a list of devices which can be used to set boot order via VirtualMachine.SetBootOptions.
// The order can any of "ethernet", "cdrom", "floppy" or "disk" or by specific device name.
// The order can be any of "ethernet", "cdrom", "floppy" or "disk" or by specific device name.
// A value of "-" will clear the existing boot order on the VC/ESX side.
func (l VirtualDeviceList) BootOrder(order []string) []types.BaseVirtualMachineBootOptionsBootableDevice {
var devices []types.BaseVirtualMachineBootOptionsBootableDevice
for _, name := range order {
if kind, ok := bootableDevices[name]; ok {
if name == DeviceTypeNone {
// Not covered in the API docs, nor obvious, but this clears the boot order on the VC/ESX side.
devices = append(devices, new(types.VirtualMachineBootOptionsBootableDevice))
continue
}
for _, device := range l {
if l.Type(device) == name {
devices = append(devices, kind(device))
}
}
continue
}

View File

@@ -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.
@@ -23,6 +23,7 @@ import (
"net"
"path"
"github.com/vmware/govmomi/nfc"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
@@ -464,6 +465,20 @@ func (v VirtualMachine) Answer(ctx context.Context, id, answer string) error {
return nil
}
func (v VirtualMachine) AcquireTicket(ctx context.Context, kind string) (*types.VirtualMachineTicket, error) {
req := types.AcquireTicket{
This: v.Reference(),
TicketType: kind,
}
res, err := methods.AcquireTicket(ctx, v.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
// CreateSnapshot creates a new snapshot of a virtual machine.
func (v VirtualMachine) CreateSnapshot(ctx context.Context, name string, description string, memory bool, quiesce bool) (*Task, error) {
req := types.CreateSnapshot_Task{
@@ -497,7 +512,7 @@ func (v VirtualMachine) RemoveAllSnapshot(ctx context.Context, consolidate *bool
return NewTask(v.c, res.Returnval), nil
}
type snapshotMap map[string][]Reference
type snapshotMap map[string][]types.ManagedObjectReference
func (m snapshotMap) add(parent string, tree []types.VirtualMachineSnapshotTree) {
for i, st := range tree {
@@ -511,18 +526,18 @@ func (m snapshotMap) add(parent string, tree []types.VirtualMachineSnapshotTree)
}
for _, name := range names {
m[name] = append(m[name], &tree[i].Snapshot)
m[name] = append(m[name], tree[i].Snapshot)
}
m.add(sname, st.ChildSnapshotList)
}
}
// 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) (*types.ManagedObjectReference, error) {
var o mo.VirtualMachine
err := v.Properties(ctx, v.Reference(), []string{"snapshot"}, &o)
@@ -542,7 +557,7 @@ func (v VirtualMachine) findSnapshot(ctx context.Context, name string) (Referenc
case 0:
return nil, fmt.Errorf("snapshot %q not found", name)
case 1:
return s[0], nil
return &s[0], nil
default:
return nil, fmt.Errorf("%q resolves to %d snapshots", name, len(s))
}
@@ -550,7 +565,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 +601,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
}
@@ -757,3 +772,30 @@ func (v VirtualMachine) UpgradeTools(ctx context.Context, options string) (*Task
return NewTask(v.c, res.Returnval), nil
}
func (v VirtualMachine) Export(ctx context.Context) (*nfc.Lease, error) {
req := types.ExportVm{
This: v.Reference(),
}
res, err := methods.ExportVm(ctx, v.Client(), &req)
if err != nil {
return nil, err
}
return nfc.NewLease(v.c, res.Returnval), nil
}
func (v VirtualMachine) UpgradeVM(ctx context.Context, version string) (*Task, error) {
req := types.UpgradeVM_Task{
This: v.Reference(),
Version: version,
}
res, err := methods.UpgradeVM_Task(ctx, v.Client(), &req)
if err != nil {
return nil, err
}
return NewTask(v.c, res.Returnval), nil
}

View File

@@ -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

View File

@@ -18,7 +18,7 @@ package property
import (
"fmt"
"path/filepath"
"path"
"reflect"
"strconv"
"strings"
@@ -103,7 +103,11 @@ func (f Filter) MatchProperty(prop types.DynamicProperty) bool {
switch pval := prop.Val.(type) {
case string:
m, _ := filepath.Match(match.(string), pval)
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)

View File

@@ -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,7 +22,50 @@ import (
"github.com/vmware/govmomi/vim25/types"
)
// Wait waits for any of the specified properties of the specified managed
// WaitFilter provides helpers to construct a types.CreateFilter for use with property.Wait
type WaitFilter struct {
types.CreateFilter
}
// 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,
}
pset := types.PropertySpec{
Type: kind,
PathSet: ps,
}
if len(ps) == 0 {
pset.All = types.NewBool(true)
}
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
})
}
// 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
@@ -35,7 +78,7 @@ import (
// 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 {
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
@@ -45,91 +88,13 @@ func Wait(ctx context.Context, c *Collector, obj types.ManagedObjectReference, p
// specified context may have timed out or have been cancelled.
defer p.Destroy(context.Background())
req := types.CreateFilter{
Spec: types.PropertyFilterSpec{
ObjectSet: []types.ObjectSpec{
{
Obj: obj,
},
},
PropSet: []types.PropertySpec{
{
PathSet: ps,
Type: obj.Type,
},
},
},
}
if len(ps) == 0 {
req.Spec.PropSet[0].All = types.NewBool(true)
}
err = p.CreateFilter(ctx, req)
if err != nil {
return err
}
return waitLoop(ctx, p, func(_ types.ManagedObjectReference, pc []types.PropertyChange) bool {
return f(pc)
})
}
// WaitForView waits for any of the specified properties of the managed
// objects in the View to change. It calls the specified function for every update it
// receives. If this function returns false, it continues waiting for
// subsequent updates. If this function returns true, it stops waiting and
// returns.
//
// To only receive updates for the View's specified managed objects, the function
// creates a new property collector and calls CreateFilter. A new property
// collector is required because filters can only be added, not removed.
//
// The newly created collector is destroyed before this function returns (both
// in case of success or error).
//
// The code assumes that all objects in the View are the same type
func WaitForView(ctx context.Context, c *Collector, view types.ManagedObjectReference, obj types.ManagedObjectReference, ps []string, f func(types.ManagedObjectReference, []types.PropertyChange) bool) error {
p, err := c.Create(ctx)
err = p.CreateFilter(ctx, filter.CreateFilter)
if err != nil {
return err
}
// Attempt to destroy the collector using the background context, as the
// specified context may have timed out or have been cancelled.
defer p.Destroy(context.Background())
req := types.CreateFilter{
Spec: types.PropertyFilterSpec{
ObjectSet: []types.ObjectSpec{
{
Obj: view,
SelectSet: []types.BaseSelectionSpec{
&types.TraversalSpec{
SelectionSpec: types.SelectionSpec{
Name: "traverseEntities",
},
Path: "view",
Type: view.Type}},
},
},
PropSet: []types.PropertySpec{
{
Type: obj.Type,
PathSet: ps,
},
},
}}
err = p.CreateFilter(ctx, req)
if err != nil {
return err
}
return waitLoop(ctx, p, f)
}
func waitLoop(ctx context.Context, c *Collector, f func(types.ManagedObjectReference, []types.PropertyChange) bool) error {
for version := ""; ; {
res, err := c.WaitForUpdates(ctx, version)
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
}
}
}
}

View File

@@ -199,3 +199,31 @@ func (sm *Manager) AcquireLocalTicket(ctx context.Context, userName string) (*ty
return &res.Returnval, nil
}
func (sm *Manager) AcquireCloneTicket(ctx context.Context) (string, error) {
req := types.AcquireCloneTicket{
This: sm.Reference(),
}
res, err := methods.AcquireCloneTicket(ctx, sm.client, &req)
if err != nil {
return "", err
}
return res.Returnval, nil
}
func (sm *Manager) CloneSession(ctx context.Context, ticket string) error {
req := types.CloneSession{
This: sm.Reference(),
CloneTicket: ticket,
}
res, err := methods.CloneSession(ctx, sm.client, &req)
if err != nil {
return err
}
sm.userSession = &res.Returnval
return nil
}

84
vendor/github.com/vmware/govmomi/simulator/BUILD generated vendored Normal file
View File

@@ -0,0 +1,84 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"authorization_manager.go",
"cluster_compute_resource.go",
"custom_fields_manager.go",
"datacenter.go",
"datastore.go",
"doc.go",
"dvs.go",
"entity.go",
"file_manager.go",
"folder.go",
"guest_id.go",
"host_datastore_browser.go",
"host_datastore_system.go",
"host_firewall_system.go",
"host_network_system.go",
"host_system.go",
"ip_pool_manager.go",
"license_manager.go",
"model.go",
"option_manager.go",
"os_unix.go",
"performance_manager.go",
"portgroup.go",
"property_collector.go",
"property_filter.go",
"registry.go",
"resource_pool.go",
"search_index.go",
"service_instance.go",
"session_manager.go",
"simulator.go",
"snapshot.go",
"task.go",
"task_manager.go",
"user_directory.go",
"view_manager.go",
"virtual_disk_manager.go",
"virtual_machine.go",
] + select({
"@io_bazel_rules_go//go/platform:windows": [
"os_windows.go",
],
"//conditions:default": [],
}),
importpath = "github.com/vmware/govmomi/simulator",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/google/uuid:go_default_library",
"//vendor/github.com/vmware/govmomi/find:go_default_library",
"//vendor/github.com/vmware/govmomi/object:go_default_library",
"//vendor/github.com/vmware/govmomi/session:go_default_library",
"//vendor/github.com/vmware/govmomi/simulator/esx:go_default_library",
"//vendor/github.com/vmware/govmomi/simulator/vpx:go_default_library",
"//vendor/github.com/vmware/govmomi/vim25:go_default_library",
"//vendor/github.com/vmware/govmomi/vim25/methods:go_default_library",
"//vendor/github.com/vmware/govmomi/vim25/mo:go_default_library",
"//vendor/github.com/vmware/govmomi/vim25/soap:go_default_library",
"//vendor/github.com/vmware/govmomi/vim25/types:go_default_library",
"//vendor/github.com/vmware/govmomi/vim25/xml:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/github.com/vmware/govmomi/simulator/esx:all-srcs",
"//vendor/github.com/vmware/govmomi/simulator/vpx:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -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 (
"strings"
"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 AuthorizationManager struct {
mo.AuthorizationManager
permissions map[types.ManagedObjectReference][]types.Permission
privileges map[string]struct{}
system []string
nextID int32
}
func NewAuthorizationManager(ref types.ManagedObjectReference) object.Reference {
m := &AuthorizationManager{}
m.Self = ref
m.RoleList = esx.RoleList
m.permissions = make(map[types.ManagedObjectReference][]types.Permission)
l := object.AuthorizationRoleList(m.RoleList)
m.system = l.ByName("ReadOnly").Privilege
admin := l.ByName("Admin")
m.privileges = make(map[string]struct{}, len(admin.Privilege))
for _, id := range admin.Privilege {
m.privileges[id] = struct{}{}
}
root := Map.content().RootFolder
for _, u := range DefaultUserGroup {
m.permissions[root] = append(m.permissions[root], types.Permission{
Entity: &root,
Principal: u.Principal,
Group: u.Group,
RoleId: admin.RoleId,
Propagate: true,
})
}
return m
}
func (m *AuthorizationManager) RetrieveEntityPermissions(req *types.RetrieveEntityPermissions) soap.HasFault {
e := Map.Get(req.Entity).(mo.Entity)
p := m.permissions[e.Reference()]
if req.Inherited {
for {
parent := e.Entity().Parent
if parent == nil {
break
}
e = Map.Get(parent.Reference()).(mo.Entity)
p = append(p, m.permissions[e.Reference()]...)
}
}
return &methods.RetrieveEntityPermissionsBody{
Res: &types.RetrieveEntityPermissionsResponse{
Returnval: p,
},
}
}
func (m *AuthorizationManager) RetrieveAllPermissions(req *types.RetrieveAllPermissions) soap.HasFault {
var p []types.Permission
for _, v := range m.permissions {
p = append(p, v...)
}
return &methods.RetrieveAllPermissionsBody{
Res: &types.RetrieveAllPermissionsResponse{
Returnval: p,
},
}
}
func (m *AuthorizationManager) RemoveEntityPermission(req *types.RemoveEntityPermission) soap.HasFault {
var p []types.Permission
for _, v := range m.permissions[req.Entity] {
if v.Group == req.IsGroup && v.Principal == req.User {
continue
}
p = append(p, v)
}
m.permissions[req.Entity] = p
return &methods.RemoveEntityPermissionBody{
Res: &types.RemoveEntityPermissionResponse{},
}
}
func (m *AuthorizationManager) SetEntityPermissions(req *types.SetEntityPermissions) soap.HasFault {
m.permissions[req.Entity] = req.Permission
return &methods.SetEntityPermissionsBody{
Res: &types.SetEntityPermissionsResponse{},
}
}
func (m *AuthorizationManager) RetrieveRolePermissions(req *types.RetrieveRolePermissions) soap.HasFault {
var p []types.Permission
for _, set := range m.permissions {
for _, v := range set {
if v.RoleId == req.RoleId {
p = append(p, v)
}
}
}
return &methods.RetrieveRolePermissionsBody{
Res: &types.RetrieveRolePermissionsResponse{
Returnval: p,
},
}
}
func (m *AuthorizationManager) AddAuthorizationRole(req *types.AddAuthorizationRole) soap.HasFault {
body := &methods.AddAuthorizationRoleBody{}
for _, role := range m.RoleList {
if role.Name == req.Name {
body.Fault_ = Fault("", &types.AlreadyExists{})
return body
}
}
ids, err := m.privIDs(req.PrivIds)
if err != nil {
body.Fault_ = err
return body
}
m.RoleList = append(m.RoleList, types.AuthorizationRole{
Info: &types.Description{
Label: req.Name,
Summary: req.Name,
},
RoleId: m.nextID,
Privilege: ids,
Name: req.Name,
System: false,
})
m.nextID++
body.Res = &types.AddAuthorizationRoleResponse{}
return body
}
func (m *AuthorizationManager) UpdateAuthorizationRole(req *types.UpdateAuthorizationRole) soap.HasFault {
body := &methods.UpdateAuthorizationRoleBody{}
for _, role := range m.RoleList {
if role.Name == req.NewName && role.RoleId != req.RoleId {
body.Fault_ = Fault("", &types.AlreadyExists{})
return body
}
}
for i, role := range m.RoleList {
if role.RoleId == req.RoleId {
if len(req.PrivIds) != 0 {
ids, err := m.privIDs(req.PrivIds)
if err != nil {
body.Fault_ = err
return body
}
m.RoleList[i].Privilege = ids
}
m.RoleList[i].Name = req.NewName
body.Res = &types.UpdateAuthorizationRoleResponse{}
return body
}
}
body.Fault_ = Fault("", &types.NotFound{})
return body
}
func (m *AuthorizationManager) RemoveAuthorizationRole(req *types.RemoveAuthorizationRole) soap.HasFault {
body := &methods.RemoveAuthorizationRoleBody{}
for i, role := range m.RoleList {
if role.RoleId == req.RoleId {
m.RoleList = append(m.RoleList[:i], m.RoleList[i+1:]...)
body.Res = &types.RemoveAuthorizationRoleResponse{}
return body
}
}
body.Fault_ = Fault("", &types.NotFound{})
return body
}
func (m *AuthorizationManager) privIDs(ids []string) ([]string, *soap.Fault) {
system := make(map[string]struct{}, len(m.system))
for _, id := range ids {
if _, ok := m.privileges[id]; !ok {
return nil, Fault("", &types.InvalidArgument{InvalidProperty: "privIds"})
}
if strings.HasPrefix(id, "System.") {
system[id] = struct{}{}
}
}
for _, id := range m.system {
if _, ok := system[id]; ok {
continue
}
ids = append(ids, id)
}
return ids, nil
}

View File

@@ -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 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
}
addComputeResource(add.ClusterComputeResource.Summary.GetComputeResourceSummary(), host)
return host.Reference(), nil
}
func (c *ClusterComputeResource) AddHostTask(add *types.AddHost_Task) soap.HasFault {
return &methods.AddHost_TaskBody{
Res: &types.AddHost_TaskResponse{
Returnval: NewTask(&addHost{c, add}).Run(),
},
}
}
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
cluster.Summary = &types.ClusterComputeResourceSummary{
UsageSummary: new(types.ClusterUsageSummary),
}
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
}

View File

@@ -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 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"
)
type CustomFieldsManager struct {
mo.CustomFieldsManager
nextKey int32
}
func NewCustomFieldsManager(ref types.ManagedObjectReference) object.Reference {
m := &CustomFieldsManager{}
m.Self = ref
return m
}
func (c *CustomFieldsManager) find(key int32) (int, *types.CustomFieldDef) {
for i, field := range c.Field {
if field.Key == key {
return i, &c.Field[i]
}
}
return -1, nil
}
func (c *CustomFieldsManager) AddCustomFieldDef(req *types.AddCustomFieldDef) soap.HasFault {
body := &methods.AddCustomFieldDefBody{}
def := types.CustomFieldDef{
Key: c.nextKey,
Name: req.Name,
ManagedObjectType: req.MoType,
Type: req.MoType,
FieldDefPrivileges: req.FieldDefPolicy,
FieldInstancePrivileges: req.FieldPolicy,
}
c.Field = append(c.Field, def)
c.nextKey++
body.Res = &types.AddCustomFieldDefResponse{
Returnval: def,
}
return body
}
func (c *CustomFieldsManager) RemoveCustomFieldDef(req *types.RemoveCustomFieldDef) soap.HasFault {
body := &methods.RemoveCustomFieldDefBody{}
i, field := c.find(req.Key)
if field == nil {
body.Fault_ = Fault("", &types.NotFound{})
return body
}
c.Field = append(c.Field[:i], c.Field[i+1:]...)
body.Res = &types.RemoveCustomFieldDefResponse{}
return body
}
func (c *CustomFieldsManager) RenameCustomFieldDef(req *types.RenameCustomFieldDef) soap.HasFault {
body := &methods.RenameCustomFieldDefBody{}
_, field := c.find(req.Key)
if field == nil {
body.Fault_ = Fault("", &types.NotFound{})
return body
}
field.Name = req.Name
body.Res = &types.RenameCustomFieldDefResponse{}
return body
}
func (c *CustomFieldsManager) SetField(req *types.SetField) soap.HasFault {
body := &methods.SetFieldBody{}
entity := Map.Get(req.Entity).(mo.Entity).Entity()
entity.CustomValue = append(entity.CustomValue, &types.CustomFieldStringValue{
CustomFieldValue: types.CustomFieldValue{Key: req.Key},
Value: req.Value,
})
body.Res = &types.SetFieldResponse{}
return body
}

View File

@@ -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)
}
}

View File

@@ -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 (
"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{}
err := ds.stat()
if err != nil {
r.Fault_ = Fault(err.Error(), &types.HostConfigFault{})
return r
}
info := ds.Info.GetDatastoreInfo()
now := time.Now()
info.Timestamp = &now
return r
}

22
vendor/github.com/vmware/govmomi/simulator/doc.go generated vendored Normal file
View File

@@ -0,0 +1,22 @@
/*
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 is a mock framework for the vSphere API.
See also: https://github.com/vmware/govmomi/blob/master/vcsim/README.md
*/
package simulator

187
vendor/github.com/vmware/govmomi/simulator/dvs.go generated vendored Normal file
View File

@@ -0,0 +1,187 @@
/*
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 DistributedVirtualSwitch struct {
mo.DistributedVirtualSwitch
}
func (s *DistributedVirtualSwitch) 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 := &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 = types.DVPortgroupConfigInfo{
Key: pg.Key,
Name: pg.Name,
NumPorts: spec.NumPorts,
DistributedVirtualSwitch: &s.Self,
DefaultPortConfig: spec.DefaultPortConfig,
Description: spec.Description,
Type: spec.Type,
Policy: spec.Policy,
PortNameFormat: spec.PortNameFormat,
Scope: spec.Scope,
VendorSpecificConfig: spec.VendorSpecificConfig,
ConfigVersion: spec.ConfigVersion,
AutoExpand: spec.AutoExpand,
VmVnicNetworkResourcePoolKey: spec.VmVnicNetworkResourcePoolKey,
}
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
})
return &methods.AddDVPortgroup_TaskBody{
Res: &types.AddDVPortgroup_TaskResponse{
Returnval: task.Run(),
},
}
}
func (s *DistributedVirtualSwitch) 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).(*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
})
return &methods.ReconfigureDvs_TaskBody{
Res: &types.ReconfigureDvs_TaskResponse{
Returnval: task.Run(),
},
}
}
func (s *DistributedVirtualSwitch) FetchDVPorts(req *types.FetchDVPorts) soap.HasFault {
body := &methods.FetchDVPortsBody{}
body.Res = &types.FetchDVPortsResponse{
Returnval: s.dvPortgroups(req.Criteria),
}
return body
}
func (s *DistributedVirtualSwitch) DestroyTask(req *types.Destroy_Task) soap.HasFault {
task := CreateTask(s, "destroy", func(t *Task) (types.AnyType, types.BaseMethodFault) {
f := Map.getEntityParent(s, "Folder").(*Folder)
f.removeChild(s.Reference())
return nil, nil
})
return &methods.Destroy_TaskBody{
Res: &types.Destroy_TaskResponse{
Returnval: task.Run(),
},
}
}
func (s *DistributedVirtualSwitch) dvPortgroups(_ *types.DistributedVirtualSwitchPortCriteria) []types.DistributedVirtualPort {
// TODO(agui): Filter is not implemented yet
var res []types.DistributedVirtualPort
for _, ref := range s.Portgroup {
pg := Map.Get(ref).(*DistributedVirtualPortgroup)
res = append(res, types.DistributedVirtualPort{
DvsUuid: s.Uuid,
Key: pg.Key,
Config: types.DVPortConfigInfo{
Setting: pg.Config.DefaultPortConfig,
},
})
if pg.PortKeys == nil {
continue
}
for _, key := range pg.PortKeys {
res = append(res, types.DistributedVirtualPort{
DvsUuid: s.Uuid,
Key: key,
Config: types.DVPortConfigInfo{
Setting: pg.Config.DefaultPortConfig,
},
})
}
}
return res
}

46
vendor/github.com/vmware/govmomi/simulator/entity.go generated vendored Normal file
View File

@@ -0,0 +1,46 @@
/*
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
})
return &methods.Rename_TaskBody{
Res: &types.Rename_TaskResponse{
Returnval: task.Run(),
},
}
}

41
vendor/github.com/vmware/govmomi/simulator/esx/BUILD generated vendored Normal file
View File

@@ -0,0 +1,41 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"authorization_manager.go",
"datacenter.go",
"doc.go",
"host_config_info.go",
"host_firewall_system.go",
"host_hardware_info.go",
"host_storage_device_info.go",
"host_system.go",
"performance_manager.go",
"resource_pool.go",
"root_folder.go",
"service_content.go",
"setting.go",
"virtual_device.go",
],
importpath = "github.com/vmware/govmomi/simulator/esx",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/vmware/govmomi/vim25/mo:go_default_library",
"//vendor/github.com/vmware/govmomi/vim25/types:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

File diff suppressed because one or more lines are too long

View File

@@ -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 esx
import (
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
// Datacenter is the default template for Datacenter properties.
// Capture method:
// govc datacenter.info -dump
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{},
}

20
vendor/github.com/vmware/govmomi/simulator/esx/doc.go generated vendored Normal file
View File

@@ -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 ... -dump`.
*/
package esx

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,864 @@
/*
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"
)
// HostHardwareInfo is the default template for the HostSystem hardware property.
// Capture method:
// govc object.collect -s -dump HostSystem:ha-host hardware
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
}

View File

@@ -0,0 +1,346 @@
/*
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"
// HostStorageDeviceInfo is the default template for the HostSystem config.storageDevice property.
// Capture method:
// govc object.collect -s -dump HostSystem:ha-host config.storageDevice
var HostStorageDeviceInfo = types.HostStorageDeviceInfo{
HostBusAdapter: []types.BaseHostHostBusAdapter{
&types.HostParallelScsiHba{
HostHostBusAdapter: types.HostHostBusAdapter{
Key: "key-vim.host.ParallelScsiHba-vmhba0",
Device: "vmhba0",
Bus: 3,
Status: "unknown",
Model: "PVSCSI SCSI Controller",
Driver: "pvscsi",
Pci: "0000:03:00.0",
},
},
&types.HostBlockHba{
HostHostBusAdapter: types.HostHostBusAdapter{
Key: "key-vim.host.BlockHba-vmhba1",
Device: "vmhba1",
Bus: 0,
Status: "unknown",
Model: "PIIX4 for 430TX/440BX/MX IDE Controller",
Driver: "vmkata",
Pci: "0000:00:07.1",
},
},
&types.HostBlockHba{
HostHostBusAdapter: types.HostHostBusAdapter{
Key: "key-vim.host.BlockHba-vmhba64",
Device: "vmhba64",
Bus: 0,
Status: "unknown",
Model: "PIIX4 for 430TX/440BX/MX IDE Controller",
Driver: "vmkata",
Pci: "0000:00:07.1",
},
},
},
ScsiLun: []types.BaseScsiLun{
&types.ScsiLun{
HostDevice: types.HostDevice{
DeviceName: "/vmfs/devices/cdrom/mpx.vmhba1:C0:T0:L0",
DeviceType: "cdrom",
},
Key: "key-vim.host.ScsiLun-0005000000766d686261313a303a30",
Uuid: "0005000000766d686261313a303a30",
Descriptor: []types.ScsiLunDescriptor{
{
Quality: "lowQuality",
Id: "mpx.vmhba1:C0:T0:L0",
},
{
Quality: "lowQuality",
Id: "vml.0005000000766d686261313a303a30",
},
{
Quality: "lowQuality",
Id: "0005000000766d686261313a303a30",
},
},
CanonicalName: "mpx.vmhba1:C0:T0:L0",
DisplayName: "Local NECVMWar CD-ROM (mpx.vmhba1:C0:T0:L0)",
LunType: "cdrom",
Vendor: "NECVMWar",
Model: "VMware IDE CDR00",
Revision: "1.00",
ScsiLevel: 5,
SerialNumber: "unavailable",
DurableName: (*types.ScsiLunDurableName)(nil),
AlternateName: []types.ScsiLunDurableName{
{
Namespace: "GENERIC_VPD",
NamespaceId: 0x5,
Data: []uint8{0x2d, 0x37, 0x39},
},
{
Namespace: "GENERIC_VPD",
NamespaceId: 0x5,
Data: []uint8{0x30},
},
},
StandardInquiry: []uint8{0x30},
QueueDepth: 0,
OperationalState: []string{"ok"},
Capabilities: &types.ScsiLunCapabilities{},
VStorageSupport: "vStorageUnsupported",
ProtocolEndpoint: types.NewBool(false),
},
&types.HostScsiDisk{
ScsiLun: types.ScsiLun{
HostDevice: types.HostDevice{
DeviceName: "/vmfs/devices/disks/mpx.vmhba0:C0:T0:L0",
DeviceType: "disk",
},
Key: "key-vim.host.ScsiDisk-0000000000766d686261303a303a30",
Uuid: "0000000000766d686261303a303a30",
Descriptor: []types.ScsiLunDescriptor{
{
Quality: "lowQuality",
Id: "mpx.vmhba0:C0:T0:L0",
},
{
Quality: "lowQuality",
Id: "vml.0000000000766d686261303a303a30",
},
{
Quality: "lowQuality",
Id: "0000000000766d686261303a303a30",
},
},
CanonicalName: "mpx.vmhba0:C0:T0:L0",
DisplayName: "Local VMware, Disk (mpx.vmhba0:C0:T0:L0)",
LunType: "disk",
Vendor: "VMware, ",
Model: "VMware Virtual S",
Revision: "1.0 ",
ScsiLevel: 2,
SerialNumber: "unavailable",
DurableName: (*types.ScsiLunDurableName)(nil),
AlternateName: []types.ScsiLunDurableName{
{
Namespace: "GENERIC_VPD",
NamespaceId: 0x5,
Data: []uint8{0x2d, 0x37, 0x39},
},
{
Namespace: "GENERIC_VPD",
NamespaceId: 0x5,
Data: []uint8{0x30},
},
},
StandardInquiry: []uint8{0x30},
QueueDepth: 1024,
OperationalState: []string{"ok"},
Capabilities: &types.ScsiLunCapabilities{},
VStorageSupport: "vStorageUnsupported",
ProtocolEndpoint: types.NewBool(false),
},
Capacity: types.HostDiskDimensionsLba{
BlockSize: 512,
Block: 67108864,
},
DevicePath: "/vmfs/devices/disks/mpx.vmhba0:C0:T0:L0",
Ssd: types.NewBool(true),
LocalDisk: types.NewBool(true),
PhysicalLocation: nil,
EmulatedDIXDIFEnabled: types.NewBool(false),
VsanDiskInfo: (*types.VsanHostVsanDiskInfo)(nil),
ScsiDiskType: "native512",
},
},
ScsiTopology: &types.HostScsiTopology{
Adapter: []types.HostScsiTopologyInterface{
{
Key: "key-vim.host.ScsiTopology.Interface-vmhba0",
Adapter: "key-vim.host.ParallelScsiHba-vmhba0",
Target: []types.HostScsiTopologyTarget{
{
Key: "key-vim.host.ScsiTopology.Target-vmhba0:0:0",
Target: 0,
Lun: []types.HostScsiTopologyLun{
{
Key: "key-vim.host.ScsiTopology.Lun-0000000000766d686261303a303a30",
Lun: 0,
ScsiLun: "key-vim.host.ScsiDisk-0000000000766d686261303a303a30",
},
},
Transport: &types.HostParallelScsiTargetTransport{},
},
},
},
{
Key: "key-vim.host.ScsiTopology.Interface-vmhba1",
Adapter: "key-vim.host.BlockHba-vmhba1",
Target: []types.HostScsiTopologyTarget{
{
Key: "key-vim.host.ScsiTopology.Target-vmhba1:0:0",
Target: 0,
Lun: []types.HostScsiTopologyLun{
{
Key: "key-vim.host.ScsiTopology.Lun-0005000000766d686261313a303a30",
Lun: 0,
ScsiLun: "key-vim.host.ScsiLun-0005000000766d686261313a303a30",
},
},
Transport: &types.HostBlockAdapterTargetTransport{},
},
},
},
{
Key: "key-vim.host.ScsiTopology.Interface-vmhba64",
Adapter: "key-vim.host.BlockHba-vmhba64",
Target: nil,
},
},
},
MultipathInfo: &types.HostMultipathInfo{
Lun: []types.HostMultipathInfoLogicalUnit{
{
Key: "key-vim.host.MultipathInfo.LogicalUnit-0005000000766d686261313a303a30",
Id: "0005000000766d686261313a303a30",
Lun: "key-vim.host.ScsiLun-0005000000766d686261313a303a30",
Path: []types.HostMultipathInfoPath{
{
Key: "key-vim.host.MultipathInfo.Path-vmhba1:C0:T0:L0",
Name: "vmhba1:C0:T0:L0",
PathState: "active",
State: "active",
IsWorkingPath: types.NewBool(true),
Adapter: "key-vim.host.BlockHba-vmhba1",
Lun: "key-vim.host.MultipathInfo.LogicalUnit-0005000000766d686261313a303a30",
Transport: &types.HostBlockAdapterTargetTransport{},
},
},
Policy: &types.HostMultipathInfoFixedLogicalUnitPolicy{
HostMultipathInfoLogicalUnitPolicy: types.HostMultipathInfoLogicalUnitPolicy{
Policy: "VMW_PSP_FIXED",
},
Prefer: "vmhba1:C0:T0:L0",
},
StorageArrayTypePolicy: &types.HostMultipathInfoLogicalUnitStorageArrayTypePolicy{
Policy: "VMW_SATP_LOCAL",
},
},
{
Key: "key-vim.host.MultipathInfo.LogicalUnit-0000000000766d686261303a303a30",
Id: "0000000000766d686261303a303a30",
Lun: "key-vim.host.ScsiDisk-0000000000766d686261303a303a30",
Path: []types.HostMultipathInfoPath{
{
Key: "key-vim.host.MultipathInfo.Path-vmhba0:C0:T0:L0",
Name: "vmhba0:C0:T0:L0",
PathState: "active",
State: "active",
IsWorkingPath: types.NewBool(true),
Adapter: "key-vim.host.ParallelScsiHba-vmhba0",
Lun: "key-vim.host.MultipathInfo.LogicalUnit-0000000000766d686261303a303a30",
Transport: &types.HostParallelScsiTargetTransport{},
},
},
Policy: &types.HostMultipathInfoFixedLogicalUnitPolicy{
HostMultipathInfoLogicalUnitPolicy: types.HostMultipathInfoLogicalUnitPolicy{
Policy: "VMW_PSP_FIXED",
},
Prefer: "vmhba0:C0:T0:L0",
},
StorageArrayTypePolicy: &types.HostMultipathInfoLogicalUnitStorageArrayTypePolicy{
Policy: "VMW_SATP_LOCAL",
},
},
},
},
PlugStoreTopology: &types.HostPlugStoreTopology{
Adapter: []types.HostPlugStoreTopologyAdapter{
{
Key: "key-vim.host.PlugStoreTopology.Adapter-vmhba0",
Adapter: "key-vim.host.ParallelScsiHba-vmhba0",
Path: []string{"key-vim.host.PlugStoreTopology.Path-vmhba0:C0:T0:L0"},
},
{
Key: "key-vim.host.PlugStoreTopology.Adapter-vmhba1",
Adapter: "key-vim.host.BlockHba-vmhba1",
Path: []string{"key-vim.host.PlugStoreTopology.Path-vmhba1:C0:T0:L0"},
},
{
Key: "key-vim.host.PlugStoreTopology.Adapter-vmhba64",
Adapter: "key-vim.host.BlockHba-vmhba64",
Path: nil,
},
},
Path: []types.HostPlugStoreTopologyPath{
{
Key: "key-vim.host.PlugStoreTopology.Path-vmhba0:C0:T0:L0",
Name: "vmhba0:C0:T0:L0",
ChannelNumber: 0,
TargetNumber: 0,
LunNumber: 0,
Adapter: "key-vim.host.PlugStoreTopology.Adapter-vmhba0",
Target: "key-vim.host.PlugStoreTopology.Target-pscsi.0:0",
Device: "key-vim.host.PlugStoreTopology.Device-0000000000766d686261303a303a30",
},
{
Key: "key-vim.host.PlugStoreTopology.Path-vmhba1:C0:T0:L0",
Name: "vmhba1:C0:T0:L0",
ChannelNumber: 0,
TargetNumber: 0,
LunNumber: 0,
Adapter: "key-vim.host.PlugStoreTopology.Adapter-vmhba1",
Target: "key-vim.host.PlugStoreTopology.Target-ide.0:0",
Device: "key-vim.host.PlugStoreTopology.Device-0005000000766d686261313a303a30",
},
},
Target: []types.HostPlugStoreTopologyTarget{
{
Key: "key-vim.host.PlugStoreTopology.Target-pscsi.0:0",
Transport: &types.HostParallelScsiTargetTransport{},
},
{
Key: "key-vim.host.PlugStoreTopology.Target-ide.0:0",
Transport: &types.HostBlockAdapterTargetTransport{},
},
},
Device: []types.HostPlugStoreTopologyDevice{
{
Key: "key-vim.host.PlugStoreTopology.Device-0005000000766d686261313a303a30",
Lun: "key-vim.host.ScsiLun-0005000000766d686261313a303a30",
Path: []string{"key-vim.host.PlugStoreTopology.Path-vmhba1:C0:T0:L0"},
},
{
Key: "key-vim.host.PlugStoreTopology.Device-0000000000766d686261303a303a30",
Lun: "key-vim.host.ScsiDisk-0000000000766d686261303a303a30",
Path: []string{"key-vim.host.PlugStoreTopology.Path-vmhba0:C0:T0:L0"},
},
},
Plugin: []types.HostPlugStoreTopologyPlugin{
{
Key: "key-vim.host.PlugStoreTopology.Plugin-NMP",
Name: "NMP",
Device: []string{"key-vim.host.PlugStoreTopology.Device-0005000000766d686261313a303a30", "key-vim.host.PlugStoreTopology.Device-0000000000766d686261303a303a30"},
ClaimedPath: []string{"key-vim.host.PlugStoreTopology.Path-vmhba0:C0:T0:L0", "key-vim.host.PlugStoreTopology.Path-vmhba1:C0:T0:L0"},
},
},
},
SoftwareInternetScsiEnabled: false,
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,165 @@
/*
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"
)
// ResourcePool is the default template for ResourcePool properties.
// Capture method:
// govc pool.info "*" -dump
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: types.NewInt64(4121),
ExpandableReservation: types.NewBool(false),
Limit: types.NewInt64(4121),
Shares: &types.SharesInfo{
DynamicData: types.DynamicData{},
Shares: 9000,
Level: "custom",
},
OverheadLimit: nil,
},
MemoryAllocation: types.ResourceAllocationInfo{
DynamicData: types.DynamicData{},
Reservation: types.NewInt64(961),
ExpandableReservation: types.NewBool(false),
Limit: types.NewInt64(961),
Shares: &types.SharesInfo{
DynamicData: types.DynamicData{},
Shares: 9000,
Level: "custom",
},
OverheadLimit: nil,
},
},
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: types.NewInt64(4121),
ExpandableReservation: types.NewBool(false),
Limit: types.NewInt64(4121),
Shares: &types.SharesInfo{
DynamicData: types.DynamicData{},
Shares: 9000,
Level: "custom",
},
OverheadLimit: nil,
},
MemoryAllocation: types.ResourceAllocationInfo{
DynamicData: types.DynamicData{},
Reservation: types.NewInt64(961),
ExpandableReservation: types.NewBool(false),
Limit: types.NewInt64(961),
Shares: &types.SharesInfo{
DynamicData: types.DynamicData{},
Shares: 9000,
Level: "custom",
},
OverheadLimit: nil,
},
},
ChildConfiguration: nil,
}

View File

@@ -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 esx
import (
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
// RootFolder is the default template for the ServiceContent rootFolder property.
// Capture method:
// govc folder.info -dump /
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,
}

View File

@@ -0,0 +1,86 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package esx
import "github.com/vmware/govmomi/vim25/types"
// ServiceContent is the default template for the ServiceInstance content property.
// Capture method:
// govc object.collect -s -dump - content
var ServiceContent = types.ServiceContent{
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{
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",
},
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),
VStorageObjectManager: &types.ManagedObjectReference{Type: "HostVStorageObjectManager", Value: "ha-vstorage-object-manager"},
HostSpecManager: (*types.ManagedObjectReference)(nil),
CryptoManager: &types.ManagedObjectReference{Type: "CryptoManager", Value: "ha-crypto-manager"},
HealthUpdateManager: (*types.ManagedObjectReference)(nil),
FailoverClusterConfigurator: (*types.ManagedObjectReference)(nil),
FailoverClusterManager: (*types.ManagedObjectReference)(nil),
}

View File

@@ -0,0 +1,30 @@
/*
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
// Capture method:
// govc object.collect -s -dump $(govc object.collect -s HostSystem:ha-host configManager.advancedOption) setting
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",
},
}

View File

@@ -0,0 +1,242 @@
/*
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
// Capture method:
// govc vm.create foo
// govc object.collect -s -dump vm/foo config.hardware.device
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: types.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: types.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: types.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: types.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: types.NewInt32(7),
},
AddressType: "generated",
MacAddress: "",
WakeOnLanEnabled: types.NewBool(true),
},
}

View File

@@ -0,0 +1,251 @@
/*
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)
})
return &methods.DeleteDatastoreFile_TaskBody{
Res: &types.DeleteDatastoreFile_TaskResponse{
Returnval: task.Run(),
},
}
}
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)
})
return &methods.MoveDatastoreFile_TaskBody{
Res: &types.MoveDatastoreFile_TaskResponse{
Returnval: task.Run(),
},
}
}
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)
})
return &methods.CopyDatastoreFile_TaskBody{
Res: &types.CopyDatastoreFile_TaskResponse{
Returnval: task.Run(),
},
}
}

471
vendor/github.com/vmware/govmomi/simulator/folder.go generated vendored Normal file
View File

@@ -0,0 +1,471 @@
/*
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 networkSummary(n *mo.Network) *types.NetworkSummary {
return &types.NetworkSummary{
Network: &n.Self,
Name: n.Name,
Accessible: true,
}
}
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)
switch e := o.(type) {
case *mo.Network:
e.Summary = networkSummary(e)
case *mo.OpaqueNetwork:
e.Summary = networkSummary(&e.Network)
case *DistributedVirtualPortgroup:
e.Summary = networkSummary(&e.Network)
}
}
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") {
r.Res = &types.AddStandaloneHost_TaskResponse{
Returnval: NewTask(&addStandaloneHost{f, a}).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.Guest = &types.GuestInfo{
ToolsStatus: types.VirtualMachineToolsStatusToolsNotInstalled,
ToolsVersion: "0",
}
vm.Summary.Guest = &types.VirtualMachineGuestSummary{
ToolsStatus: vm.Guest.ToolsStatus,
}
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 {
return &methods.CreateVM_TaskBody{
Res: &types.CreateVM_TaskResponse{
Returnval: NewTask(&createVM{f, c, false}).Run(),
},
}
}
type registerVM struct {
*Folder
req *types.RegisterVM_Task
}
func (c *registerVM) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
host := c.req.Host
pool := c.req.Pool
if c.req.AsTemplate {
if host == nil {
return nil, &types.InvalidArgument{InvalidProperty: "host"}
} else if pool != nil {
return nil, &types.InvalidArgument{InvalidProperty: "pool"}
}
pool = hostParent(&Map.Get(*host).(*HostSystem).HostSystem).ResourcePool
} else {
if pool == nil {
return nil, &types.InvalidArgument{InvalidProperty: "pool"}
}
}
if c.req.Path == "" {
return nil, &types.InvalidArgument{InvalidProperty: "path"}
}
s := Map.SearchIndex()
r := s.FindByDatastorePath(&types.FindByDatastorePath{
This: s.Reference(),
Path: c.req.Path,
Datacenter: Map.getEntityDatacenter(c.Folder).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: *pool,
Host: 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 {
return &methods.RegisterVM_TaskBody{
Res: &types.RegisterVM_TaskResponse{
Returnval: NewTask(&registerVM{f, c}).Run(),
},
}
}
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
})
return &methods.MoveIntoFolder_TaskBody{
Res: &types.MoveIntoFolder_TaskResponse{
Returnval: task.Run(),
},
}
}
func (f *Folder) CreateDVSTask(req *types.CreateDVS_Task) soap.HasFault {
task := CreateTask(f, "createDVS", func(t *Task) (types.AnyType, types.BaseMethodFault) {
spec := req.Spec.ConfigSpec.GetDVSConfigSpec()
dvs := &DistributedVirtualSwitch{}
dvs.Name = spec.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)
dvs.Summary = types.DVSSummary{
Name: dvs.Name,
Uuid: dvs.Uuid,
NumPorts: spec.NumStandalonePorts,
ProductInfo: req.Spec.ProductInfo,
Description: spec.Description,
}
if dvs.Summary.ProductInfo == nil {
product := Map.content().About
dvs.Summary.ProductInfo = &types.DistributedVirtualSwitchProductSpec{
Name: "DVS",
Vendor: product.Vendor,
Version: product.Version,
Build: product.Build,
ForwardingClass: "etherswitch",
}
}
return dvs.Reference(), nil
})
return &methods.CreateDVS_TaskBody{
Res: &types.CreateDVS_TaskResponse{
Returnval: task.Run(),
},
}
}
func (f *Folder) RenameTask(r *types.Rename_Task) soap.HasFault {
return RenameTask(f, r)
}

171
vendor/github.com/vmware/govmomi/simulator/guest_id.go generated vendored Normal file
View File

@@ -0,0 +1,171 @@
/*
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/types"
// GuestID is the list of valid types.VirtualMachineGuestOsIdentifier
var GuestID = []types.VirtualMachineGuestOsIdentifier{
types.VirtualMachineGuestOsIdentifierDosGuest,
types.VirtualMachineGuestOsIdentifierWin31Guest,
types.VirtualMachineGuestOsIdentifierWin95Guest,
types.VirtualMachineGuestOsIdentifierWin98Guest,
types.VirtualMachineGuestOsIdentifierWinMeGuest,
types.VirtualMachineGuestOsIdentifierWinNTGuest,
types.VirtualMachineGuestOsIdentifierWin2000ProGuest,
types.VirtualMachineGuestOsIdentifierWin2000ServGuest,
types.VirtualMachineGuestOsIdentifierWin2000AdvServGuest,
types.VirtualMachineGuestOsIdentifierWinXPHomeGuest,
types.VirtualMachineGuestOsIdentifierWinXPProGuest,
types.VirtualMachineGuestOsIdentifierWinXPPro64Guest,
types.VirtualMachineGuestOsIdentifierWinNetWebGuest,
types.VirtualMachineGuestOsIdentifierWinNetStandardGuest,
types.VirtualMachineGuestOsIdentifierWinNetEnterpriseGuest,
types.VirtualMachineGuestOsIdentifierWinNetDatacenterGuest,
types.VirtualMachineGuestOsIdentifierWinNetBusinessGuest,
types.VirtualMachineGuestOsIdentifierWinNetStandard64Guest,
types.VirtualMachineGuestOsIdentifierWinNetEnterprise64Guest,
types.VirtualMachineGuestOsIdentifierWinLonghornGuest,
types.VirtualMachineGuestOsIdentifierWinLonghorn64Guest,
types.VirtualMachineGuestOsIdentifierWinNetDatacenter64Guest,
types.VirtualMachineGuestOsIdentifierWinVistaGuest,
types.VirtualMachineGuestOsIdentifierWinVista64Guest,
types.VirtualMachineGuestOsIdentifierWindows7Guest,
types.VirtualMachineGuestOsIdentifierWindows7_64Guest,
types.VirtualMachineGuestOsIdentifierWindows7Server64Guest,
types.VirtualMachineGuestOsIdentifierWindows8Guest,
types.VirtualMachineGuestOsIdentifierWindows8_64Guest,
types.VirtualMachineGuestOsIdentifierWindows8Server64Guest,
types.VirtualMachineGuestOsIdentifierWindows9Guest,
types.VirtualMachineGuestOsIdentifierWindows9_64Guest,
types.VirtualMachineGuestOsIdentifierWindows9Server64Guest,
types.VirtualMachineGuestOsIdentifierWindowsHyperVGuest,
types.VirtualMachineGuestOsIdentifierFreebsdGuest,
types.VirtualMachineGuestOsIdentifierFreebsd64Guest,
types.VirtualMachineGuestOsIdentifierRedhatGuest,
types.VirtualMachineGuestOsIdentifierRhel2Guest,
types.VirtualMachineGuestOsIdentifierRhel3Guest,
types.VirtualMachineGuestOsIdentifierRhel3_64Guest,
types.VirtualMachineGuestOsIdentifierRhel4Guest,
types.VirtualMachineGuestOsIdentifierRhel4_64Guest,
types.VirtualMachineGuestOsIdentifierRhel5Guest,
types.VirtualMachineGuestOsIdentifierRhel5_64Guest,
types.VirtualMachineGuestOsIdentifierRhel6Guest,
types.VirtualMachineGuestOsIdentifierRhel6_64Guest,
types.VirtualMachineGuestOsIdentifierRhel7Guest,
types.VirtualMachineGuestOsIdentifierRhel7_64Guest,
types.VirtualMachineGuestOsIdentifierCentosGuest,
types.VirtualMachineGuestOsIdentifierCentos64Guest,
types.VirtualMachineGuestOsIdentifierCentos6Guest,
types.VirtualMachineGuestOsIdentifierCentos6_64Guest,
types.VirtualMachineGuestOsIdentifierCentos7Guest,
types.VirtualMachineGuestOsIdentifierCentos7_64Guest,
types.VirtualMachineGuestOsIdentifierOracleLinuxGuest,
types.VirtualMachineGuestOsIdentifierOracleLinux64Guest,
types.VirtualMachineGuestOsIdentifierOracleLinux6Guest,
types.VirtualMachineGuestOsIdentifierOracleLinux6_64Guest,
types.VirtualMachineGuestOsIdentifierOracleLinux7Guest,
types.VirtualMachineGuestOsIdentifierOracleLinux7_64Guest,
types.VirtualMachineGuestOsIdentifierSuseGuest,
types.VirtualMachineGuestOsIdentifierSuse64Guest,
types.VirtualMachineGuestOsIdentifierSlesGuest,
types.VirtualMachineGuestOsIdentifierSles64Guest,
types.VirtualMachineGuestOsIdentifierSles10Guest,
types.VirtualMachineGuestOsIdentifierSles10_64Guest,
types.VirtualMachineGuestOsIdentifierSles11Guest,
types.VirtualMachineGuestOsIdentifierSles11_64Guest,
types.VirtualMachineGuestOsIdentifierSles12Guest,
types.VirtualMachineGuestOsIdentifierSles12_64Guest,
types.VirtualMachineGuestOsIdentifierNld9Guest,
types.VirtualMachineGuestOsIdentifierOesGuest,
types.VirtualMachineGuestOsIdentifierSjdsGuest,
types.VirtualMachineGuestOsIdentifierMandrakeGuest,
types.VirtualMachineGuestOsIdentifierMandrivaGuest,
types.VirtualMachineGuestOsIdentifierMandriva64Guest,
types.VirtualMachineGuestOsIdentifierTurboLinuxGuest,
types.VirtualMachineGuestOsIdentifierTurboLinux64Guest,
types.VirtualMachineGuestOsIdentifierUbuntuGuest,
types.VirtualMachineGuestOsIdentifierUbuntu64Guest,
types.VirtualMachineGuestOsIdentifierDebian4Guest,
types.VirtualMachineGuestOsIdentifierDebian4_64Guest,
types.VirtualMachineGuestOsIdentifierDebian5Guest,
types.VirtualMachineGuestOsIdentifierDebian5_64Guest,
types.VirtualMachineGuestOsIdentifierDebian6Guest,
types.VirtualMachineGuestOsIdentifierDebian6_64Guest,
types.VirtualMachineGuestOsIdentifierDebian7Guest,
types.VirtualMachineGuestOsIdentifierDebian7_64Guest,
types.VirtualMachineGuestOsIdentifierDebian8Guest,
types.VirtualMachineGuestOsIdentifierDebian8_64Guest,
types.VirtualMachineGuestOsIdentifierDebian9Guest,
types.VirtualMachineGuestOsIdentifierDebian9_64Guest,
types.VirtualMachineGuestOsIdentifierDebian10Guest,
types.VirtualMachineGuestOsIdentifierDebian10_64Guest,
types.VirtualMachineGuestOsIdentifierAsianux3Guest,
types.VirtualMachineGuestOsIdentifierAsianux3_64Guest,
types.VirtualMachineGuestOsIdentifierAsianux4Guest,
types.VirtualMachineGuestOsIdentifierAsianux4_64Guest,
types.VirtualMachineGuestOsIdentifierAsianux5_64Guest,
types.VirtualMachineGuestOsIdentifierAsianux7_64Guest,
types.VirtualMachineGuestOsIdentifierOpensuseGuest,
types.VirtualMachineGuestOsIdentifierOpensuse64Guest,
types.VirtualMachineGuestOsIdentifierFedoraGuest,
types.VirtualMachineGuestOsIdentifierFedora64Guest,
types.VirtualMachineGuestOsIdentifierCoreos64Guest,
types.VirtualMachineGuestOsIdentifierVmwarePhoton64Guest,
types.VirtualMachineGuestOsIdentifierOther24xLinuxGuest,
types.VirtualMachineGuestOsIdentifierOther26xLinuxGuest,
types.VirtualMachineGuestOsIdentifierOtherLinuxGuest,
types.VirtualMachineGuestOsIdentifierOther3xLinuxGuest,
types.VirtualMachineGuestOsIdentifierGenericLinuxGuest,
types.VirtualMachineGuestOsIdentifierOther24xLinux64Guest,
types.VirtualMachineGuestOsIdentifierOther26xLinux64Guest,
types.VirtualMachineGuestOsIdentifierOther3xLinux64Guest,
types.VirtualMachineGuestOsIdentifierOtherLinux64Guest,
types.VirtualMachineGuestOsIdentifierSolaris6Guest,
types.VirtualMachineGuestOsIdentifierSolaris7Guest,
types.VirtualMachineGuestOsIdentifierSolaris8Guest,
types.VirtualMachineGuestOsIdentifierSolaris9Guest,
types.VirtualMachineGuestOsIdentifierSolaris10Guest,
types.VirtualMachineGuestOsIdentifierSolaris10_64Guest,
types.VirtualMachineGuestOsIdentifierSolaris11_64Guest,
types.VirtualMachineGuestOsIdentifierOs2Guest,
types.VirtualMachineGuestOsIdentifierEComStationGuest,
types.VirtualMachineGuestOsIdentifierEComStation2Guest,
types.VirtualMachineGuestOsIdentifierNetware4Guest,
types.VirtualMachineGuestOsIdentifierNetware5Guest,
types.VirtualMachineGuestOsIdentifierNetware6Guest,
types.VirtualMachineGuestOsIdentifierOpenServer5Guest,
types.VirtualMachineGuestOsIdentifierOpenServer6Guest,
types.VirtualMachineGuestOsIdentifierUnixWare7Guest,
types.VirtualMachineGuestOsIdentifierDarwinGuest,
types.VirtualMachineGuestOsIdentifierDarwin64Guest,
types.VirtualMachineGuestOsIdentifierDarwin10Guest,
types.VirtualMachineGuestOsIdentifierDarwin10_64Guest,
types.VirtualMachineGuestOsIdentifierDarwin11Guest,
types.VirtualMachineGuestOsIdentifierDarwin11_64Guest,
types.VirtualMachineGuestOsIdentifierDarwin12_64Guest,
types.VirtualMachineGuestOsIdentifierDarwin13_64Guest,
types.VirtualMachineGuestOsIdentifierDarwin14_64Guest,
types.VirtualMachineGuestOsIdentifierDarwin15_64Guest,
types.VirtualMachineGuestOsIdentifierDarwin16_64Guest,
types.VirtualMachineGuestOsIdentifierVmkernelGuest,
types.VirtualMachineGuestOsIdentifierVmkernel5Guest,
types.VirtualMachineGuestOsIdentifierVmkernel6Guest,
types.VirtualMachineGuestOsIdentifierVmkernel65Guest,
types.VirtualMachineGuestOsIdentifierOtherGuest,
types.VirtualMachineGuestOsIdentifierOtherGuest64,
}

35
vendor/github.com/vmware/govmomi/simulator/guest_id.sh generated vendored Executable file
View File

@@ -0,0 +1,35 @@
#!/bin/bash -e
pushd "$(dirname "$0")" >/dev/null
{
cat <<EOF
/*
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
// GuestID is the list of valid types.VirtualMachineGuestOsIdentifier
var GuestID = []types.VirtualMachineGuestOsIdentifier{
EOF
ids=($(grep 'VirtualMachineGuestOsIdentifier(' ../vim25/types/enum.go | grep = | awk '{print $1}'))
printf "types.%s,\n" "${ids[@]}"
echo "}"
} > guest_id.go
goimports -w guest_id.go

View File

@@ -0,0 +1,254 @@
/*
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,
})
return &methods.SearchDatastore_TaskBody{
Res: &types.SearchDatastore_TaskResponse{
Returnval: task.Run(),
},
}
}
func (b *HostDatastoreBrowser) SearchDatastoreSubFoldersTask(s *types.SearchDatastoreSubFolders_Task) soap.HasFault {
task := NewTask(&searchDatastore{
HostDatastoreBrowser: b,
DatastorePath: s.DatastorePath,
SearchSpec: s.SearchSpec,
recurse: true,
})
return &methods.SearchDatastoreSubFolders_TaskBody{
Res: &types.SearchDatastoreSubFolders_TaskResponse{
Returnval: task.Run(),
},
}
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -0,0 +1,171 @@
/*
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
}
func (s *HostNetworkSystem) UpdateNetworkConfig(req *types.UpdateNetworkConfig) soap.HasFault {
s.NetworkConfig = &req.Config
return &methods.UpdateNetworkConfigBody{
Res: &types.UpdateNetworkConfigResponse{
Returnval: types.HostNetworkConfigResult{},
},
}
}

View File

@@ -0,0 +1,180 @@
/*
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/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type HostSystem struct {
mo.HostSystem
}
func NewHostSystem(host mo.HostSystem) *HostSystem {
now := time.Now()
hs := &HostSystem{
HostSystem: host,
}
hs.Name = hs.Summary.Config.Name
hs.Summary.Runtime = &hs.Runtime
hs.Summary.Runtime.BootTime = &now
id := uuid.New().String()
hardware := *host.Summary.Hardware
hs.Summary.Hardware = &hardware
hs.Summary.Hardware.Uuid = id
info := *esx.HostHardwareInfo
info.SystemInfo.Uuid = id
hs.Hardware = &info
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
}
}
func addComputeResource(s *types.ComputeResourceSummary, h *HostSystem) {
s.TotalCpu += h.Summary.Hardware.CpuMhz
s.TotalMemory += h.Summary.Hardware.MemorySize
s.NumCpuCores += h.Summary.Hardware.NumCpuCores
s.NumCpuThreads += h.Summary.Hardware.NumCpuThreads
s.EffectiveCpu += h.Summary.Hardware.CpuMhz
s.EffectiveMemory += h.Summary.Hardware.MemorySize
s.NumHosts++
s.NumEffectiveHosts++
s.OverallStatus = types.ManagedEntityStatusGreen
}
// 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)
summary := new(types.ComputeResourceSummary)
addComputeResource(summary, host)
cr := &mo.ComputeResource{Summary: summary}
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
summary := new(types.ComputeResourceSummary)
addComputeResource(summary, host)
cr := &mo.ComputeResource{Summary: summary}
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
}
func (h *HostSystem) EnterMaintenanceModeTask(spec *types.EnterMaintenanceMode_Task) soap.HasFault {
task := CreateTask(h, "enterMaintenanceMode", func(t *Task) (types.AnyType, types.BaseMethodFault) {
h.Runtime.InMaintenanceMode = true
return nil, nil
})
return &methods.EnterMaintenanceMode_TaskBody{
Res: &types.EnterMaintenanceMode_TaskResponse{
Returnval: task.Run(),
},
}
}
func (h *HostSystem) ExitMaintenanceModeTask(spec *types.ExitMaintenanceMode_Task) soap.HasFault {
task := CreateTask(h, "exitMaintenanceMode", func(t *Task) (types.AnyType, types.BaseMethodFault) {
h.Runtime.InMaintenanceMode = false
return nil, nil
})
return &methods.ExitMaintenanceMode_TaskBody{
Res: &types.ExitMaintenanceMode_TaskResponse{
Returnval: task.Run(),
},
}
}

View File

@@ -0,0 +1,392 @@
/*
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"
"fmt"
"net"
"strconv"
"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"
)
var ipPool = MustNewIpPool(&types.IpPool{
Id: 1,
Name: "ip-pool",
AvailableIpv4Addresses: 250,
AvailableIpv6Addresses: 250,
AllocatedIpv6Addresses: 0,
AllocatedIpv4Addresses: 0,
Ipv4Config: &types.IpPoolIpPoolConfigInfo{
Netmask: "10.10.10.255",
Gateway: "10.10.10.1",
SubnetAddress: "10.10.10.0",
Range: "10.10.10.2#250",
},
Ipv6Config: &types.IpPoolIpPoolConfigInfo{
Netmask: "2001:4860:0:2001::ff",
Gateway: "2001:4860:0:2001::1",
SubnetAddress: "2001:4860:0:2001::0",
Range: "2001:4860:0:2001::2#250",
},
})
// IpPoolManager implements a simple IP Pool manager in which all pools are shared
// across different datacenters.
type IpPoolManager struct {
mo.IpPoolManager
pools map[int32]*IpPool
nextPoolId int32
}
func NewIpPoolManager(ref types.ManagedObjectReference) *IpPoolManager {
m := &IpPoolManager{}
m.Self = ref
m.pools = map[int32]*IpPool{
1: ipPool,
}
m.nextPoolId = 2
return m
}
func (m *IpPoolManager) CreateIpPool(req *types.CreateIpPool) soap.HasFault {
body := &methods.CreateIpPoolBody{}
id := m.nextPoolId
var err error
m.pools[id], err = NewIpPool(&req.Pool)
if err != nil {
body.Fault_ = Fault("", &types.RuntimeFault{})
return body
}
m.nextPoolId++
body.Res = &types.CreateIpPoolResponse{
Returnval: id,
}
return body
}
func (m *IpPoolManager) DestroyIpPool(req *types.DestroyIpPool) soap.HasFault {
delete(m.pools, req.Id)
return &methods.DestroyIpPoolBody{
Res: &types.DestroyIpPoolResponse{},
}
}
func (m *IpPoolManager) QueryIpPools(req *types.QueryIpPools) soap.HasFault {
pools := []types.IpPool{}
for i := int32(1); i < m.nextPoolId; i++ {
if p, ok := m.pools[i]; ok {
pools = append(pools, *p.config)
}
}
return &methods.QueryIpPoolsBody{
Res: &types.QueryIpPoolsResponse{
Returnval: pools,
},
}
}
func (m *IpPoolManager) UpdateIpPool(req *types.UpdateIpPool) soap.HasFault {
body := &methods.UpdateIpPoolBody{}
var pool *IpPool
var err error
var ok bool
if pool, ok = m.pools[req.Pool.Id]; !ok {
body.Fault_ = Fault("", &types.NotFoundFault{})
return body
}
if pool.config.AllocatedIpv4Addresses+pool.config.AllocatedIpv6Addresses != 0 {
body.Fault_ = Fault("update a pool has been used is not supported", &types.RuntimeFault{})
return body
}
m.pools[req.Pool.Id], err = NewIpPool(&req.Pool)
if err != nil {
body.Fault_ = Fault(err.Error(), &types.RuntimeFault{})
return body
}
body.Res = &types.UpdateIpPoolResponse{}
return body
}
func (m *IpPoolManager) AllocateIpv4Address(req *types.AllocateIpv4Address) soap.HasFault {
body := &methods.AllocateIpv4AddressBody{}
pool, ok := m.pools[req.PoolId]
if !ok {
body.Fault_ = Fault("", &types.InvalidArgument{})
return body
}
ip, err := pool.AllocateIPv4(req.AllocationId)
if err != nil {
body.Fault_ = Fault(err.Error(), &types.RuntimeFault{})
return body
}
body.Res = &types.AllocateIpv4AddressResponse{
Returnval: ip,
}
return body
}
func (m *IpPoolManager) AllocateIpv6Address(req *types.AllocateIpv6Address) soap.HasFault {
body := &methods.AllocateIpv6AddressBody{}
pool, ok := m.pools[req.PoolId]
if !ok {
body.Fault_ = Fault("", &types.InvalidArgument{})
return body
}
ip, err := pool.AllocateIpv6(req.AllocationId)
if err != nil {
body.Fault_ = Fault(err.Error(), &types.RuntimeFault{})
return body
}
body.Res = &types.AllocateIpv6AddressResponse{
Returnval: ip,
}
return body
}
func (m *IpPoolManager) ReleaseIpAllocation(req *types.ReleaseIpAllocation) soap.HasFault {
body := &methods.ReleaseIpAllocationBody{}
pool, ok := m.pools[req.PoolId]
if !ok {
body.Fault_ = Fault("", &types.InvalidArgument{})
return body
}
pool.ReleaseIpv4(req.AllocationId)
pool.ReleaseIpv6(req.AllocationId)
body.Res = &types.ReleaseIpAllocationResponse{}
return body
}
func (m *IpPoolManager) QueryIPAllocations(req *types.QueryIPAllocations) soap.HasFault {
body := &methods.QueryIPAllocationsBody{}
pool, ok := m.pools[req.PoolId]
if !ok {
body.Fault_ = Fault("", &types.InvalidArgument{})
return body
}
body.Res = &types.QueryIPAllocationsResponse{}
ipv4, ok := pool.ipv4Allocation[req.ExtensionKey]
if ok {
body.Res.Returnval = append(body.Res.Returnval, types.IpPoolManagerIpAllocation{
IpAddress: ipv4,
AllocationId: req.ExtensionKey,
})
}
ipv6, ok := pool.ipv6Allocation[req.ExtensionKey]
if ok {
body.Res.Returnval = append(body.Res.Returnval, types.IpPoolManagerIpAllocation{
IpAddress: ipv6,
AllocationId: req.ExtensionKey,
})
}
return body
}
var (
errNoIpAvailable = errors.New("no ip address available")
errInvalidAllocation = errors.New("allocation id not recognized")
)
type IpPool struct {
config *types.IpPool
ipv4Allocation map[string]string
ipv6Allocation map[string]string
ipv4Pool []string
ipv6Pool []string
}
func MustNewIpPool(config *types.IpPool) *IpPool {
pool, err := NewIpPool(config)
if err != nil {
panic(err)
}
return pool
}
func NewIpPool(config *types.IpPool) (*IpPool, error) {
pool := &IpPool{
config: config,
ipv4Allocation: make(map[string]string),
ipv6Allocation: make(map[string]string),
}
return pool, pool.init()
}
func (p *IpPool) init() error {
// IPv4 range
if p.config.Ipv4Config != nil {
ranges := strings.Split(p.config.Ipv4Config.Range, ",")
for _, r := range ranges {
sp := strings.Split(r, "#")
if len(sp) != 2 {
return fmt.Errorf("format of range should be ip#number; got %q", r)
}
ip := net.ParseIP(strings.TrimSpace(sp[0])).To4()
if ip == nil {
return fmt.Errorf("bad ip format: %q", sp[0])
}
length, err := strconv.Atoi(sp[1])
if err != nil {
return err
}
for i := 0; i < length; i++ {
p.ipv4Pool = append(p.ipv4Pool, net.IPv4(ip[0], ip[1], ip[2], ip[3]+byte(i)).String())
}
}
}
// IPv6 range
if p.config.Ipv6Config != nil {
ranges := strings.Split(p.config.Ipv6Config.Range, ",")
for _, r := range ranges {
sp := strings.Split(r, "#")
if len(sp) != 2 {
return fmt.Errorf("format of range should be ip#number; got %q", r)
}
ip := net.ParseIP(strings.TrimSpace(sp[0])).To16()
if ip == nil {
return fmt.Errorf("bad ip format: %q", sp[0])
}
length, err := strconv.Atoi(sp[1])
if err != nil {
return err
}
for i := 0; i < length; i++ {
var ipv6 [16]byte
copy(ipv6[:], ip)
ipv6[15] += byte(i)
p.ipv6Pool = append(p.ipv6Pool, net.IP(ipv6[:]).String())
}
}
}
return nil
}
func (p *IpPool) AllocateIPv4(allocation string) (string, error) {
if ip, ok := p.ipv4Allocation[allocation]; ok {
return ip, nil
}
l := len(p.ipv4Pool)
if l == 0 {
return "", errNoIpAvailable
}
ip := p.ipv4Pool[l-1]
p.config.AvailableIpv4Addresses--
p.config.AllocatedIpv4Addresses++
p.ipv4Pool = p.ipv4Pool[:l-1]
p.ipv4Allocation[allocation] = ip
return ip, nil
}
func (p *IpPool) ReleaseIpv4(allocation string) error {
ip, ok := p.ipv4Allocation[allocation]
if !ok {
return errInvalidAllocation
}
delete(p.ipv4Allocation, allocation)
p.config.AvailableIpv4Addresses++
p.config.AllocatedIpv4Addresses--
p.ipv4Pool = append(p.ipv4Pool, ip)
return nil
}
func (p *IpPool) AllocateIpv6(allocation string) (string, error) {
if ip, ok := p.ipv6Allocation[allocation]; ok {
return ip, nil
}
l := len(p.ipv6Pool)
if l == 0 {
return "", errNoIpAvailable
}
ip := p.ipv6Pool[l-1]
p.config.AvailableIpv6Addresses--
p.config.AllocatedIpv6Addresses++
p.ipv6Pool = p.ipv6Pool[:l-1]
p.ipv6Allocation[allocation] = ip
return ip, nil
}
func (p *IpPool) ReleaseIpv6(allocation string) error {
ip, ok := p.ipv6Allocation[allocation]
if !ok {
return errInvalidAllocation
}
delete(p.ipv6Allocation, allocation)
p.config.AvailableIpv6Addresses++
p.config.AllocatedIpv6Addresses--
p.ipv6Pool = append(p.ipv6Pool, ip)
return nil
}

View File

@@ -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.
*/
// 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
}
func (m *LicenseManager) AddLicense(req *types.AddLicense) soap.HasFault {
body := &methods.AddLicenseBody{
Res: &types.AddLicenseResponse{},
}
for _, license := range m.Licenses {
if license.LicenseKey == req.LicenseKey {
body.Res.Returnval = licenseInfo(license.LicenseKey, license.Labels)
return body
}
}
m.Licenses = append(m.Licenses, types.LicenseManagerLicenseInfo{
LicenseKey: req.LicenseKey,
Labels: req.Labels,
})
body.Res.Returnval = licenseInfo(req.LicenseKey, req.Labels)
return body
}
func (m *LicenseManager) RemoveLicense(req *types.RemoveLicense) soap.HasFault {
body := &methods.RemoveLicenseBody{
Res: &types.RemoveLicenseResponse{},
}
for i, license := range m.Licenses {
if req.LicenseKey == license.LicenseKey {
m.Licenses = append(m.Licenses[:i], m.Licenses[i+1:]...)
return body
}
}
return body
}
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
}
func licenseInfo(key string, labels []types.KeyValue) types.LicenseManagerLicenseInfo {
info := EvalLicense
info.LicenseKey = key
info.Labels = labels
return info
}

484
vendor/github.com/vmware/govmomi/simulator/model.go generated vendored Normal file
View File

@@ -0,0 +1,484 @@
/*
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
// Autostart will power on Model created VMs when true
Autostart bool
// 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,
Autostart: true,
Datastore: 1,
Machine: 2,
}
}
// VPX is the default Model for a vCenter instance
func VPX() *Model {
return &Model{
ServiceContent: vpx.ServiceContent,
RootFolder: vpx.RootFolder,
Autostart: true,
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
}
info, err := task.WaitForResult(ctx, nil)
if err != nil {
return err
}
vm := object.NewVirtualMachine(client, info.Result.(types.ManagedObjectReference))
if m.Autostart {
_, _ = vm.PowerOn(ctx)
}
}
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 := types.DefaultResourceConfigSpec()
_, 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 := types.DefaultResourceConfigSpec()
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)
}
}

View File

@@ -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
}

38
vendor/github.com/vmware/govmomi/simulator/os_unix.go generated vendored Normal file
View File

@@ -0,0 +1,38 @@
/*
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 "syscall"
func (ds *Datastore) stat() error {
info := ds.Info.GetDatastoreInfo()
var stat syscall.Statfs_t
err := syscall.Statfs(info.Url, &stat)
if err != nil {
return err
}
bsize := uint64(stat.Bsize) / 512
info.FreeSpace = int64(stat.Bfree*bsize) >> 1
ds.Summary.FreeSpace = info.FreeSpace
ds.Summary.Capacity = int64(stat.Blocks*bsize) >> 1
return nil
}

View File

@@ -0,0 +1,26 @@
/*
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"
func (ds *Datastore) stat() error {
info := ds.Info.GetDatastoreInfo()
_, err := os.Stat(info.Url)
return err
}

View File

@@ -0,0 +1,35 @@
/*
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/simulator/esx"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type PerformanceManager struct {
mo.PerformanceManager
}
func NewPerformanceManager(ref types.ManagedObjectReference) object.Reference {
m := &PerformanceManager{}
m.Self = ref
m.PerfCounter = esx.PerfCounter
return m
}

View File

@@ -0,0 +1,82 @@
/*
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 DistributedVirtualPortgroup struct {
mo.DistributedVirtualPortgroup
}
func (s *DistributedVirtualPortgroup) ReconfigureDVPortgroupTask(req *types.ReconfigureDVPortgroup_Task) soap.HasFault {
task := CreateTask(s, "reconfigureDvPortgroup", func(t *Task) (types.AnyType, types.BaseMethodFault) {
s.Config.DefaultPortConfig = req.Spec.DefaultPortConfig
s.Config.NumPorts = req.Spec.NumPorts
s.Config.AutoExpand = req.Spec.AutoExpand
s.Config.Type = req.Spec.Type
s.Config.Description = req.Spec.Description
s.Config.DynamicData = req.Spec.DynamicData
s.Config.Name = req.Spec.Name
s.Config.Policy = req.Spec.Policy
s.Config.PortNameFormat = req.Spec.PortNameFormat
s.Config.VmVnicNetworkResourcePoolKey = req.Spec.VmVnicNetworkResourcePoolKey
return nil, nil
})
return &methods.ReconfigureDVPortgroup_TaskBody{
Res: &types.ReconfigureDVPortgroup_TaskResponse{
Returnval: task.Run(),
},
}
}
func (s *DistributedVirtualPortgroup) DestroyTask(req *types.Destroy_Task) soap.HasFault {
task := CreateTask(s, "destroy", func(t *Task) (types.AnyType, types.BaseMethodFault) {
vswitch := Map.Get(*s.Config.DistributedVirtualSwitch).(*DistributedVirtualSwitch)
for i, pg := range vswitch.Portgroup {
if pg.Reference() == s.Reference() {
vswitch.Portgroup = append(vswitch.Portgroup[:i], vswitch.Portgroup[i+1:]...)
break
}
}
f := Map.getEntityParent(vswitch, "Folder").(*Folder)
f.removeChild(s.Reference())
for i, name := range vswitch.Summary.PortgroupName {
if name == s.Name {
vswitch.Summary.PortgroupName = append(vswitch.Summary.PortgroupName[:i],
vswitch.Summary.PortgroupName[i+1:]...)
}
}
return nil, nil
})
return &methods.Destroy_TaskBody{
Res: &types.Destroy_TaskResponse{
Returnval: task.Run(),
},
}
}

View File

@@ -0,0 +1,548 @@
/*
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.Interface {
if rval.IsNil() {
continue
}
rval = rval.Elem()
kind = rval.Type().Kind()
}
if kind == reflect.Ptr {
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
}

View File

@@ -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
}

338
vendor/github.com/vmware/govmomi/simulator/registry.go generated vendored Normal file
View File

@@ -0,0 +1,338 @@
/*
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/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
// This is a map from a reference type name to a reference value name prefix.
// It's a convention that VirtualCenter follows. The map is not complete, but
// it should cover the most popular objects.
var refValueMap = map[string]string{
"DistributedVirtualPortgroup": "dvportgroup",
"EnvironmentBrowser": "envbrowser",
"HostSystem": "host",
"ResourcePool": "resgroup",
"VirtualMachine": "vm",
"VirtualMachineSnapshot": "snapshot",
"VmwareDistributedVirtualSwitch": "dvs",
}
// 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()
}
// valuePrefix returns the value name prefix of a given object
func valuePrefix(typeName string) string {
if v, ok := refValueMap[typeName]; ok {
return v
}
return strings.ToLower(typeName)
}
// 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", valuePrefix(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))
}
if me, ok := item.(mo.Entity); ok {
me.Entity().ConfigStatus = types.ManagedEntityStatusGreen
me.Entity().OverallStatus = types.ManagedEntityStatusGreen
me.Entity().EffectiveRole = []int32{-1} // Admin
}
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(methods.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)
}

View File

@@ -0,0 +1,312 @@
/*
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"
"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 allResourceFieldsSet(info *types.ResourceAllocationInfo) bool {
return info.Reservation != nil &&
info.Limit != nil &&
info.ExpandableReservation != nil &&
info.Shares != nil
}
func allResourceFieldsValid(info *types.ResourceAllocationInfo) bool {
if info.Reservation != nil {
if *info.Reservation < 0 {
return false
}
}
if info.Limit != nil {
if *info.Limit < -1 {
return false
}
}
if info.Shares != nil {
if info.Shares.Level == types.SharesLevelCustom {
if info.Shares.Shares < 0 {
return false
}
}
}
if info.OverheadLimit != nil {
return false
}
return true
}
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(),
})
}
if !(allResourceFieldsSet(&spec.CpuAllocation) && allResourceFieldsValid(&spec.CpuAllocation)) {
return nil, Fault("", &types.InvalidArgument{
InvalidProperty: "spec.cpuAllocation",
})
}
if !(allResourceFieldsSet(&spec.MemoryAllocation) && allResourceFieldsValid(&spec.MemoryAllocation)) {
return nil, Fault("", &types.InvalidArgument{
InvalidProperty: "spec.memoryAllocation",
})
}
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
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
}
func updateResourceAllocation(kind string, src, dst *types.ResourceAllocationInfo) types.BaseMethodFault {
if !allResourceFieldsValid(src) {
return &types.InvalidArgument{
InvalidProperty: fmt.Sprintf("spec.%sAllocation", kind),
}
}
if src.Reservation != nil {
dst.Reservation = src.Reservation
}
if src.Limit != nil {
dst.Limit = src.Limit
}
if src.Shares != nil {
dst.Shares = src.Shares
}
return nil
}
func (p *ResourcePool) UpdateConfig(c *types.UpdateConfig) soap.HasFault {
body := &methods.UpdateConfigBody{}
if c.Name != "" {
if e := Map.FindByName(c.Name, p.ResourcePool.ResourcePool); e != nil {
body.Fault_ = Fault("", &types.DuplicateName{
Name: e.Entity().Name,
Object: e.Reference(),
})
return body
}
p.Name = c.Name
}
spec := c.Config
if spec != nil {
if err := updateResourceAllocation("memory", &spec.MemoryAllocation, &p.Config.MemoryAllocation); err != nil {
body.Fault_ = Fault("", err)
return body
}
if err := updateResourceAllocation("cpu", &spec.CpuAllocation, &p.Config.CpuAllocation); err != nil {
body.Fault_ = Fault("", err)
return body
}
}
body.Res = &types.UpdateConfigResponse{}
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
})
return &methods.Destroy_TaskBody{
Res: &types.Destroy_TaskResponse{
Returnval: task.Run(),
},
}
}

View File

@@ -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
}

View File

@@ -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 (
"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
}
func NewServiceInstance(content types.ServiceContent, folder mo.Folder) *ServiceInstance {
Map = NewRegistry()
s := &ServiceInstance{}
s.Self = methods.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),
NewAuthorizationManager(*s.Content.AuthorizationManager),
NewPerformanceManager(*s.Content.PerfManager),
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),
NewUserDirectory(*s.Content.UserDirectory),
NewOptionManager(s.Content.Setting, setting),
}
if s.Content.CustomFieldsManager != nil {
objects = append(objects, NewCustomFieldsManager(*s.Content.CustomFieldsManager))
}
if s.Content.IpPoolManager != nil {
objects = append(objects, NewIpPoolManager(*s.Content.IpPoolManager))
}
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(),
},
}
}

View File

@@ -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{Res: new(types.LogoutResponse)}
}
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,
},
},
}
}

551
vendor/github.com/vmware/govmomi/simulator/simulator.go generated vendored Normal file
View File

@@ -0,0 +1,551 @@
/*
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"`
}
// soapFault is a copy of soap.Fault, with the same changes as soapEnvelope
type soapFault struct {
XMLName xml.Name `xml:"soapenv:Fault"`
Code string `xml:"faultcode"`
String string `xml:"faultstring"`
Detail struct {
Fault types.AnyType `xml:",any,typeattr"`
} `xml:"detail"`
}
// 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
var soapBody interface{}
method, err := UnmarshalBody(body)
if err != nil {
res = serverFault(err.Error())
} else {
res = s.call(method)
}
if f := res.Fault(); f != nil {
w.WriteHeader(http.StatusInternalServerError)
// the generated method/*Body structs use the '*soap.Fault' type,
// so we need our own Body type to use the modified '*soapFault' type.
soapBody = struct {
Fault *soapFault
}{
&soapFault{
Code: f.Code,
String: f.String,
Detail: f.Detail,
},
}
} else {
w.WriteHeader(http.StatusOK)
soapBody = res
}
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: soapBody,
})
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 + `<namespaces version="1.0">
<namespace>
<name>urn:vim25</name>
<version>6.5</version>
<priorVersions>
<version>6.0</version>
<version>5.5</version>
</priorVersions>
</namespace>
</namespaces>
`
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
}

68
vendor/github.com/vmware/govmomi/simulator/snapshot.go generated vendored Normal file
View File

@@ -0,0 +1,68 @@
/*
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 VirtualMachineSnapshot struct {
mo.VirtualMachineSnapshot
}
func (v *VirtualMachineSnapshot) RemoveSnapshotTask(req *types.RemoveSnapshot_Task) soap.HasFault {
task := CreateTask(v, "removeSnapshot", func(t *Task) (types.AnyType, types.BaseMethodFault) {
Map.Remove(req.This)
vm := Map.Get(v.Vm).(*VirtualMachine)
if vm.Snapshot.CurrentSnapshot != nil && *vm.Snapshot.CurrentSnapshot == req.This {
parent := findParentSnapshotInTree(vm.Snapshot.RootSnapshotList, req.This)
vm.Snapshot.CurrentSnapshot = parent
}
vm.Snapshot.RootSnapshotList = removeSnapshotInTree(vm.Snapshot.RootSnapshotList, req.This, req.RemoveChildren)
return nil, nil
})
return &methods.RemoveSnapshot_TaskBody{
Res: &types.RemoveSnapshot_TaskResponse{
Returnval: task.Run(),
},
}
}
func (v *VirtualMachineSnapshot) RevertToSnapshotTask(req *types.RevertToSnapshot_Task) soap.HasFault {
task := CreateTask(v, "revertToSnapshot", func(t *Task) (types.AnyType, types.BaseMethodFault) {
vm := Map.Get(v.Vm).(*VirtualMachine)
ref := v.Reference()
vm.Snapshot.CurrentSnapshot = &ref
return nil, nil
})
return &methods.RevertToSnapshot_TaskBody{
Res: &types.RevertToSnapshot_TaskResponse{
Returnval: task.Run(),
},
}
}

102
vendor/github.com/vmware/govmomi/simulator/task.go generated vendored Normal file
View File

@@ -0,0 +1,102 @@
/*
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() types.ManagedObjectReference {
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
}
return t.Self
}

View File

@@ -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) {
}

View File

@@ -0,0 +1,78 @@
/*
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"
)
var DefaultUserGroup = []*types.UserSearchResult{
{FullName: "root", Group: true, Principal: "root"},
{FullName: "root", Group: false, Principal: "root"},
{FullName: "administrator", Group: false, Principal: "admin"},
}
type UserDirectory struct {
mo.UserDirectory
userGroup []*types.UserSearchResult
}
func NewUserDirectory(ref types.ManagedObjectReference) object.Reference {
u := &UserDirectory{}
u.Self = ref
u.userGroup = DefaultUserGroup
return u
}
func (u *UserDirectory) RetrieveUserGroups(req *types.RetrieveUserGroups) soap.HasFault {
compare := compareFunc(req.SearchStr, req.ExactMatch)
var res []types.BaseUserSearchResult
for _, ug := range u.userGroup {
if req.FindUsers && !ug.Group || req.FindGroups && ug.Group {
if compare(ug.Principal) {
res = append(res, ug)
}
}
}
body := &methods.RetrieveUserGroupsBody{
Res: &types.RetrieveUserGroupsResponse{
Returnval: res,
},
}
return body
}
func compareFunc(compared string, exactly bool) func(string) bool {
return func(s string) bool {
if exactly {
return s == compared
}
return strings.Contains(strings.ToLower(s), strings.ToLower(compared))
}
}

View File

@@ -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))
}
}
}

View File

@@ -0,0 +1,193 @@
/*
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/google/uuid"
"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)
})
return &methods.CreateVirtualDisk_TaskBody{
Res: &types.CreateVirtualDisk_TaskResponse{
Returnval: task.Run(),
},
}
}
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
})
return &methods.DeleteVirtualDisk_TaskBody{
Res: &types.DeleteVirtualDisk_TaskResponse{
Returnval: task.Run(),
},
}
}
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
})
return &methods.MoveVirtualDisk_TaskBody{
Res: &types.MoveVirtualDisk_TaskResponse{
Returnval: task.Run(),
},
}
}
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
})
return &methods.CopyVirtualDisk_TaskBody{
Res: &types.CopyVirtualDisk_TaskResponse{
Returnval: task.Run(),
},
}
}
func (m *VirtualDiskManager) QueryVirtualDiskUuid(req *types.QueryVirtualDiskUuid) soap.HasFault {
body := new(methods.QueryVirtualDiskUuidBody)
fm := Map.FileManager()
file, fault := fm.resolve(req.Datacenter, req.Name)
if fault != nil {
body.Fault_ = Fault("", fault)
return body
}
_, err := os.Stat(file)
if err != nil {
fault = fm.fault(file, err, new(types.CannotAccessFile))
body.Fault_ = Fault("", fault)
return body
}
body.Res = &types.QueryVirtualDiskUuidResponse{
Returnval: uuid.NewSHA1(uuid.NameSpaceOID, []byte(file)).String(),
}
return body
}

View File

@@ -0,0 +1,885 @@
/*
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"
"sync/atomic"
"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
sid int32
}
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"}
}
rspec := types.DefaultResourceConfigSpec()
vm.Config = &types.VirtualMachineConfigInfo{
ExtraConfig: []types.BaseOptionValue{&types.OptionValue{Key: "govcsim", Value: "TRUE"}},
Tools: &types.ToolsConfigInfo{},
MemoryAllocation: &rspec.MemoryAllocation,
CpuAllocation: &rspec.CpuAllocation,
}
vm.Summary.Guest = &types.VirtualMachineGuestSummary{}
vm.Summary.Storage = &types.VirtualMachineStorageSummary{}
vm.Summary.Vm = &vm.Self
// 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 validateGuestID(id string) types.BaseMethodFault {
for _, x := range GuestID {
if id == string(x) {
return nil
}
}
return &types.InvalidArgument{InvalidProperty: "configSpec.guestId"}
}
func (vm *VirtualMachine) configure(spec *types.VirtualMachineConfigSpec) types.BaseMethodFault {
vm.apply(spec)
if spec.MemoryAllocation != nil {
if err := updateResourceAllocation("memory", spec.MemoryAllocation, vm.Config.MemoryAllocation); err != nil {
return err
}
}
if spec.CpuAllocation != nil {
if err := updateResourceAllocation("cpu", spec.CpuAllocation, vm.Config.CpuAllocation); err != nil {
return err
}
}
if spec.GuestId != "" {
if err := validateGuestID(spec.GuestId); err != nil {
return err
}
}
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:
info := b.GetVirtualDeviceFileBackingInfo()
if info.FileName == "" {
filename, err := vm.genVmdkPath()
if err != nil {
return err
}
info.FileName = filename
}
err := dm.createVirtualDisk(&types.CreateVirtualDisk_Task{
Datacenter: &dc.Self,
Name: info.FileName,
})
if err != nil {
return err
}
p, _ := parseDatastorePath(info.FileName)
info.Datastore = &types.ManagedObjectReference{
Type: "Datastore",
Value: p.Datastore,
}
}
}
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) genVmdkPath() (string, types.BaseMethodFault) {
vmdir := path.Dir(vm.Config.Files.VmPathName)
index := 0
for {
var filename string
if index == 0 {
filename = fmt.Sprintf("%s.vmdk", vm.Config.Name)
} else {
filename = fmt.Sprintf("%s_%d.vmdk", vm.Config.Name, index)
}
f, err := vm.createFile(vmdir, filename, false)
if err != nil {
switch err.(type) {
case *types.FileAlreadyExists:
index++
continue
default:
return "", err
}
}
_ = f.Close()
_ = os.Remove(f.Name())
return path.Join(vmdir, filename), nil
}
}
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 {
runner := &powerVMTask{vm, types.VirtualMachinePowerStatePoweredOn}
task := CreateTask(runner.Reference(), "powerOn", runner.Run)
return &methods.PowerOnVM_TaskBody{
Res: &types.PowerOnVM_TaskResponse{
Returnval: task.Run(),
},
}
}
func (vm *VirtualMachine) PowerOffVMTask(c *types.PowerOffVM_Task) soap.HasFault {
runner := &powerVMTask{vm, types.VirtualMachinePowerStatePoweredOff}
task := CreateTask(runner.Reference(), "powerOff", runner.Run)
return &methods.PowerOffVM_TaskBody{
Res: &types.PowerOffVM_TaskResponse{
Returnval: task.Run(),
},
}
}
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
})
return &methods.ReconfigVM_TaskBody{
Res: &types.ReconfigVM_TaskResponse{
Returnval: task.Run(),
},
}
}
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
})
return &methods.Destroy_TaskBody{
Res: &types.Destroy_TaskResponse{
Returnval: task.Run(),
},
}
}
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
})
return &methods.CloneVM_TaskBody{
Res: &types.CloneVM_TaskResponse{
Returnval: task.Run(),
},
}
}
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
})
return &methods.RelocateVM_TaskBody{
Res: &types.RelocateVM_TaskResponse{
Returnval: task.Run(),
},
}
}
func (vm *VirtualMachine) CreateSnapshotTask(req *types.CreateSnapshot_Task) soap.HasFault {
task := CreateTask(vm, "createSnapshot", func(t *Task) (types.AnyType, types.BaseMethodFault) {
if vm.Snapshot == nil {
vm.Snapshot = &types.VirtualMachineSnapshotInfo{}
}
snapshot := &VirtualMachineSnapshot{}
snapshot.Vm = vm.Reference()
snapshot.Config = *vm.Config
Map.Put(snapshot)
treeItem := types.VirtualMachineSnapshotTree{
Snapshot: snapshot.Self,
Vm: snapshot.Vm,
Name: req.Name,
Description: req.Description,
Id: atomic.AddInt32(&vm.sid, 1),
CreateTime: time.Now(),
State: vm.Runtime.PowerState,
Quiesced: req.Quiesce,
BackupManifest: "",
ReplaySupported: types.NewBool(false),
}
cur := vm.Snapshot.CurrentSnapshot
if cur != nil {
parent := Map.Get(*cur).(*VirtualMachineSnapshot)
parent.ChildSnapshot = append(parent.ChildSnapshot, snapshot.Self)
ss := findSnapshotInTree(vm.Snapshot.RootSnapshotList, *cur)
ss.ChildSnapshotList = append(ss.ChildSnapshotList, treeItem)
} else {
vm.Snapshot.RootSnapshotList = append(vm.Snapshot.RootSnapshotList, treeItem)
}
vm.Snapshot.CurrentSnapshot = &snapshot.Self
return nil, nil
})
return &methods.CreateSnapshot_TaskBody{
Res: &types.CreateSnapshot_TaskResponse{
Returnval: task.Run(),
},
}
}
func (vm *VirtualMachine) RevertToCurrentSnapshotTask(req *types.RevertToCurrentSnapshot_Task) soap.HasFault {
body := &methods.RevertToCurrentSnapshot_TaskBody{}
if vm.Snapshot == nil || vm.Snapshot.CurrentSnapshot == nil {
body.Fault_ = Fault("snapshot not found", &types.NotFound{})
return body
}
task := CreateTask(vm, "revertSnapshot", func(t *Task) (types.AnyType, types.BaseMethodFault) {
return nil, nil
})
body.Res = &types.RevertToCurrentSnapshot_TaskResponse{
Returnval: task.Run(),
}
return body
}
func (vm *VirtualMachine) RemoveAllSnapshotsTask(req *types.RemoveAllSnapshots_Task) soap.HasFault {
task := CreateTask(vm, "RemoveAllSnapshots", func(t *Task) (types.AnyType, types.BaseMethodFault) {
if vm.Snapshot == nil {
return nil, nil
}
refs := allSnapshotsInTree(vm.Snapshot.RootSnapshotList)
vm.Snapshot.CurrentSnapshot = nil
vm.Snapshot.RootSnapshotList = nil
for _, ref := range refs {
Map.Remove(ref)
}
return nil, nil
})
return &methods.RemoveAllSnapshots_TaskBody{
Res: &types.RemoveAllSnapshots_TaskResponse{
Returnval: task.Run(),
},
}
}
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
}
func findSnapshotInTree(tree []types.VirtualMachineSnapshotTree, ref types.ManagedObjectReference) *types.VirtualMachineSnapshotTree {
if tree == nil {
return nil
}
for i, ss := range tree {
if ss.Snapshot == ref {
return &tree[i]
}
target := findSnapshotInTree(ss.ChildSnapshotList, ref)
if target != nil {
return target
}
}
return nil
}
func findParentSnapshot(tree types.VirtualMachineSnapshotTree, ref types.ManagedObjectReference) *types.ManagedObjectReference {
for _, ss := range tree.ChildSnapshotList {
if ss.Snapshot == ref {
return &tree.Snapshot
}
res := findParentSnapshot(ss, ref)
if res != nil {
return res
}
}
return nil
}
func findParentSnapshotInTree(tree []types.VirtualMachineSnapshotTree, ref types.ManagedObjectReference) *types.ManagedObjectReference {
if tree == nil {
return nil
}
for _, ss := range tree {
res := findParentSnapshot(ss, ref)
if res != nil {
return res
}
}
return nil
}
func removeSnapshotInTree(tree []types.VirtualMachineSnapshotTree, ref types.ManagedObjectReference, removeChildren bool) []types.VirtualMachineSnapshotTree {
if tree == nil {
return tree
}
var result []types.VirtualMachineSnapshotTree
for _, ss := range tree {
if ss.Snapshot == ref {
if !removeChildren {
result = append(result, ss.ChildSnapshotList...)
}
} else {
ss.ChildSnapshotList = removeSnapshotInTree(ss.ChildSnapshotList, ref, removeChildren)
result = append(result, ss)
}
}
return result
}
func allSnapshotsInTree(tree []types.VirtualMachineSnapshotTree) []types.ManagedObjectReference {
var result []types.ManagedObjectReference
if tree == nil {
return result
}
for _, ss := range tree {
result = append(result, ss.Snapshot)
result = append(result, allSnapshotsInTree(ss.ChildSnapshotList)...)
}
return result
}

31
vendor/github.com/vmware/govmomi/simulator/vpx/BUILD generated vendored Normal file
View File

@@ -0,0 +1,31 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"root_folder.go",
"service_content.go",
"setting.go",
],
importpath = "github.com/vmware/govmomi/simulator/vpx",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/vmware/govmomi/vim25/mo:go_default_library",
"//vendor/github.com/vmware/govmomi/vim25/types:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

20
vendor/github.com/vmware/govmomi/simulator/vpx/doc.go generated vendored Normal file
View File

@@ -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 ... -dump`.
*/
package vpx

View File

@@ -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,
}

View File

@@ -0,0 +1,86 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package vpx
import "github.com/vmware/govmomi/vim25/types"
// ServiceContent is the default template for the ServiceInstance content property.
// Capture method:
// govc object.collect -s -dump - content
var ServiceContent = types.ServiceContent{
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{
Name: "VMware vCenter Server",
FullName: "VMware vCenter Server 6.5.0 build-5973321",
Vendor: "VMware, Inc.",
Version: "6.5.0",
Build: "5973321",
LocaleVersion: "INTL",
LocaleBuild: "000",
OsType: "linux-x64",
ProductLineId: "vpx",
ApiType: "VirtualCenter",
ApiVersion: "6.5",
InstanceUuid: "dbed6e0c-bd88-4ef6-b594-21283e1c677f",
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: "OverheadMemoryManager"},
CertificateManager: &types.ManagedObjectReference{Type: "CertificateManager", Value: "certificateManager"},
IoFilterManager: &types.ManagedObjectReference{Type: "IoFilterManager", Value: "IoFilterManager"},
VStorageObjectManager: &types.ManagedObjectReference{Type: "VcenterVStorageObjectManager", Value: "VStorageObjectManager"},
HostSpecManager: &types.ManagedObjectReference{Type: "HostSpecificationManager", Value: "HostSpecificationManager"},
CryptoManager: &types.ManagedObjectReference{Type: "CryptoManagerKmip", Value: "CryptoManager"},
HealthUpdateManager: &types.ManagedObjectReference{Type: "HealthUpdateManager", Value: "HealthUpdateManager"},
FailoverClusterConfigurator: &types.ManagedObjectReference{Type: "FailoverClusterConfigurator", Value: "FailoverClusterConfigurator"},
FailoverClusterManager: &types.ManagedObjectReference{Type: "FailoverClusterManager", Value: "FailoverClusterManager"},
}

View File

@@ -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",
},
}

View File

@@ -3,7 +3,6 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"internal.go",
"methods.go",
"service_content.go",
],

View File

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

View File

@@ -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.
@@ -60,6 +60,7 @@ const (
type header struct {
Cookie string `xml:"vcSessionCookie,omitempty"`
ID string `xml:"operationID,omitempty"`
}
type Client struct {
@@ -78,7 +79,7 @@ type Client struct {
Version string // Vim version
UserAgent string
header *header
cookie string
}
var schemeMatch = regexp.MustCompile(`^\w+://`)
@@ -168,10 +169,7 @@ func (c *Client) NewServiceClient(path string, namespace string) *Client {
// Set SOAP Header cookie
for _, cookie := range client.Jar.Cookies(u) {
if cookie.Name == "vmware_soap_session" {
client.header = &header{
Cookie: cookie.Value,
}
client.cookie = cookie.Value
break
}
}
@@ -433,7 +431,15 @@ func (c *Client) RoundTrip(ctx context.Context, reqBody, resBody HasFault) error
reqEnv := Envelope{Body: reqBody}
resEnv := Envelope{Body: resBody}
reqEnv.Header = c.header
h := &header{
Cookie: c.cookie,
}
if id, ok := ctx.Value(types.ID{}).(string); ok {
h.ID = id
}
reqEnv.Header = h
// Create debugging context for this round trip
d := c.d.newRoundTrip()
@@ -614,6 +620,7 @@ type Download struct {
Headers map[string]string
Ticket *http.Cookie
Progress progress.Sinker
Writer io.Writer
}
var DefaultDownload = Download{
@@ -655,7 +662,46 @@ 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
}
func (c *Client) WriteFile(file string, src io.Reader, size int64, s progress.Sinker, w io.Writer) error {
var err error
r := src
fh, err := os.Create(file)
if err != nil {
return err
}
if s != nil {
pr := progress.NewReader(s, src, size)
src = pr
// Mark progress reader as done when returning from this function.
defer func() {
pr.Done(err)
}()
}
if w == nil {
w = fh
} else {
w = io.MultiWriter(w, fh)
}
_, err = io.Copy(w, r)
cerr := fh.Close()
if err == nil {
err = cerr
}
return err
}
// DownloadFile GETs the given URL to a local file
@@ -669,37 +715,6 @@ func (c *Client) DownloadFile(file string, u *url.URL, param *Download) error {
if err != nil {
return err
}
defer rc.Close()
var r io.Reader = rc
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
// Mark progress reader as done when returning from this function.
defer func() {
pr.Done(err)
}()
}
_, err = io.Copy(fh, r)
if err != nil {
return err
}
// Assign error before returning so that it gets picked up by the deferred
// function marking the progress reader as done.
err = fh.Close()
if err != nil {
return err
}
return nil
return c.WriteFile(file, rc, contentLength, param.Progress, param.Writer)
}

View File

@@ -8,7 +8,6 @@ go_library(
"fault.go",
"helpers.go",
"if.go",
"internal.go",
"registry.go",
"types.go",
],

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