add vendoring with go dep

This commit is contained in:
Adrian Todorov
2017-10-25 20:52:40 +00:00
parent 704f4d20d1
commit a59409f16b
1627 changed files with 489673 additions and 0 deletions

View File

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

View File

@@ -0,0 +1,86 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type DisabledMethodRequest struct {
Method string `xml:"method"`
Reason string `xml:"reasonId"`
}
type disableMethodsRequest struct {
This types.ManagedObjectReference `xml:"_this"`
Entity []types.ManagedObjectReference `xml:"entity"`
Method []DisabledMethodRequest `xml:"method"`
Source string `xml:"sourceId"`
Scope bool `xml:"sessionScope,omitempty"`
}
type disableMethodsBody struct {
Req *disableMethodsRequest `xml:"urn:internalvim25 DisableMethods,omitempty"`
Res interface{} `xml:"urn:vim25 DisableMethodsResponse,omitempty"`
Err *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *disableMethodsBody) Fault() *soap.Fault { return b.Err }
func (m AuthorizationManager) DisableMethods(ctx context.Context, entity []types.ManagedObjectReference, method []DisabledMethodRequest, source string) error {
var reqBody, resBody disableMethodsBody
reqBody.Req = &disableMethodsRequest{
This: m.Reference(),
Entity: entity,
Method: method,
Source: source,
}
return m.Client().RoundTrip(ctx, &reqBody, &resBody)
}
type enableMethodsRequest struct {
This types.ManagedObjectReference `xml:"_this"`
Entity []types.ManagedObjectReference `xml:"entity"`
Method []string `xml:"method"`
Source string `xml:"sourceId"`
}
type enableMethodsBody struct {
Req *enableMethodsRequest `xml:"urn:internalvim25 EnableMethods,omitempty"`
Res interface{} `xml:"urn:vim25 EnableMethodsResponse,omitempty"`
Err *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *enableMethodsBody) Fault() *soap.Fault { return b.Err }
func (m AuthorizationManager) EnableMethods(ctx context.Context, entity []types.ManagedObjectReference, method []string, source string) error {
var reqBody, resBody enableMethodsBody
reqBody.Req = &enableMethodsRequest{
This: m.Reference(),
Entity: entity,
Method: method,
Source: source,
}
return m.Client().RoundTrip(ctx, &reqBody, &resBody)
}

View File

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

View File

@@ -0,0 +1,20 @@
/*
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
// ComputeResource should implement the Reference interface.
var _ Reference = ClusterComputeResource{}

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

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

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

@@ -0,0 +1,34 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import "testing"
func TestCommonName(t *testing.T) {
c := &Common{}
name := c.Name()
if name != "" {
t.Errorf("Name=%s", name)
}
c.InventoryPath = "/foo/bar"
name = c.Name()
if name != "bar" {
t.Errorf("Name=%s", name)
}
}

View File

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

View File

@@ -0,0 +1,20 @@
/*
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
// ComputeResource should implement the Reference interface.
var _ Reference = ComputeResource{}

View File

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

View File

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

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

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

View File

@@ -0,0 +1,20 @@
/*
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
// Datacenter should implement the Reference interface.
var _ Reference = Datacenter{}

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

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

View File

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

View File

@@ -0,0 +1,145 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"bufio"
"bytes"
"context"
"fmt"
"io"
"log"
"path"
"strings"
"github.com/vmware/govmomi/vim25/soap"
)
// DatastoreFileManager combines FileManager and VirtualDiskManager to manage files on a Datastore
type DatastoreFileManager struct {
Datacenter *Datacenter
Datastore *Datastore
FileManager *FileManager
VirtualDiskManager *VirtualDiskManager
Force bool
}
// NewFileManager creates a new instance of DatastoreFileManager
func (d Datastore) NewFileManager(dc *Datacenter, force bool) *DatastoreFileManager {
c := d.Client()
m := &DatastoreFileManager{
Datacenter: dc,
Datastore: &d,
FileManager: NewFileManager(c),
VirtualDiskManager: NewVirtualDiskManager(c),
Force: force,
}
return m
}
// Delete dispatches to the appropriate Delete method based on file name extension
func (m *DatastoreFileManager) Delete(ctx context.Context, name string) error {
switch path.Ext(name) {
case ".vmdk":
return m.DeleteVirtualDisk(ctx, name)
default:
return m.DeleteFile(ctx, name)
}
}
// DeleteFile calls FileManager.DeleteDatastoreFile
func (m *DatastoreFileManager) DeleteFile(ctx context.Context, name string) error {
p := m.Path(name)
task, err := m.FileManager.DeleteDatastoreFile(ctx, p.String(), m.Datacenter)
if err != nil {
return err
}
return task.Wait(ctx)
}
// DeleteVirtualDisk calls VirtualDiskManager.DeleteVirtualDisk
// Regardless of the Datastore type, DeleteVirtualDisk will fail if 'ddb.deletable=false',
// so if Force=true this method attempts to set 'ddb.deletable=true' before starting the delete task.
func (m *DatastoreFileManager) DeleteVirtualDisk(ctx context.Context, name string) error {
p := m.Path(name)
var merr error
if m.Force {
merr = m.markDiskAsDeletable(ctx, p)
}
task, err := m.VirtualDiskManager.DeleteVirtualDisk(ctx, p.String(), m.Datacenter)
if err != nil {
log.Printf("markDiskAsDeletable(%s): %s", p, merr)
return err
}
return task.Wait(ctx)
}
// Path converts path name to a DatastorePath
func (m *DatastoreFileManager) Path(name string) *DatastorePath {
var p DatastorePath
if !p.FromString(name) {
p.Path = name
p.Datastore = m.Datastore.Name()
}
return &p
}
func (m *DatastoreFileManager) markDiskAsDeletable(ctx context.Context, path *DatastorePath) error {
r, _, err := m.Datastore.Download(ctx, path.Path, &soap.DefaultDownload)
if err != nil {
return err
}
defer r.Close()
hasFlag := false
buf := new(bytes.Buffer)
s := bufio.NewScanner(&io.LimitedReader{R: r, N: 2048}) // should be only a few hundred bytes, limit to be sure
for s.Scan() {
line := s.Text()
if strings.HasPrefix(line, "ddb.deletable") {
hasFlag = true
continue
}
fmt.Fprintln(buf, line)
}
if err := s.Err(); err != nil {
return err // any error other than EOF
}
if !hasFlag {
return nil // already deletable, so leave as-is
}
// rewrite the .vmdk with ddb.deletable flag removed (the default is true)
return m.Datastore.Upload(ctx, buf, path.Path, &soap.DefaultUpload)
}

View File

@@ -0,0 +1,65 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"fmt"
"strings"
)
// DatastorePath contains the components of a datastore path.
type DatastorePath struct {
Datastore string
Path string
}
// FromString parses a datastore path.
// Returns true if the path could be parsed, false otherwise.
func (p *DatastorePath) FromString(s string) bool {
if len(s) == 0 {
return false
}
s = strings.TrimSpace(s)
if !strings.HasPrefix(s, "[") {
return false
}
s = s[1:]
ix := strings.Index(s, "]")
if ix < 0 {
return false
}
p.Datastore = s[:ix]
p.Path = strings.TrimSpace(s[ix+1:])
return true
}
// String formats a datastore path.
func (p *DatastorePath) String() string {
s := fmt.Sprintf("[%s]", p.Datastore)
if p.Path == "" {
return s
}
return strings.Join([]string{s, p.Path}, " ")
}

View File

@@ -0,0 +1,76 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import "testing"
func TestParseDatastorePath(t *testing.T) {
tests := []struct {
dsPath string
dsFile string
fail bool
}{
{"", "", true},
{"x", "", true},
{"[", "", true},
{"[nope", "", true},
{"[te st]", "", false},
{"[te st] foo", "foo", false},
{"[te st] foo/foo.vmx", "foo/foo.vmx", false},
{"[te st]foo bar/foo bar.vmx", "foo bar/foo bar.vmx", false},
{" [te st] bar/bar.vmx ", "bar/bar.vmx", false},
}
for _, test := range tests {
p := new(DatastorePath)
ok := p.FromString(test.dsPath)
if test.fail {
if ok {
t.Errorf("expected error for: %s", test.dsPath)
}
} else {
if !ok {
t.Errorf("failed to parse: %q", test.dsPath)
} else {
if test.dsFile != p.Path {
t.Errorf("dsFile=%s", p.Path)
}
if p.Datastore != "te st" {
t.Errorf("ds=%s", p.Datastore)
}
}
}
}
s := "[datastore1] foo/bar.vmdk"
p := new(DatastorePath)
ok := p.FromString(s)
if !ok {
t.Fatal(s)
}
if p.String() != s {
t.Fatal(p.String())
}
p.Path = ""
if p.String() != "[datastore1]" {
t.Fatal(p.String())
}
}

View File

@@ -0,0 +1,20 @@
/*
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
// Datastore should implement the Reference interface.
var _ Reference = Datastore{}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,23 @@
/*
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
// DistributedVirtualPortgroup should implement the Reference interface.
var _ Reference = DistributedVirtualPortgroup{}
// DistributedVirtualPortgroup should implement the NetworkReference interface.
var _ NetworkReference = DistributedVirtualPortgroup{}

View File

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

View File

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

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

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

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

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

20
vendor/github.com/vmware/govmomi/object/folder_test.go generated vendored Normal file
View File

@@ -0,0 +1,20 @@
/*
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
// Folder should implement the Reference interface.
var _ Reference = Folder{}

View File

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

View File

@@ -0,0 +1,65 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HostAccountManager struct {
Common
}
func NewHostAccountManager(c *vim25.Client, ref types.ManagedObjectReference) *HostAccountManager {
return &HostAccountManager{
Common: NewCommon(c, ref),
}
}
func (m HostAccountManager) Create(ctx context.Context, user *types.HostAccountSpec) error {
req := types.CreateUser{
This: m.Reference(),
User: user,
}
_, err := methods.CreateUser(ctx, m.Client(), &req)
return err
}
func (m HostAccountManager) Update(ctx context.Context, user *types.HostAccountSpec) error {
req := types.UpdateUser{
This: m.Reference(),
User: user,
}
_, err := methods.UpdateUser(ctx, m.Client(), &req)
return err
}
func (m HostAccountManager) Remove(ctx context.Context, userName string) error {
req := types.RemoveUser{
This: m.Reference(),
UserName: userName,
}
_, err := methods.RemoveUser(ctx, m.Client(), &req)
return err
}

View File

@@ -0,0 +1,250 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"fmt"
"io"
"net/url"
"strings"
"text/tabwriter"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
// HostCertificateInfo provides helpers for types.HostCertificateManagerCertificateInfo
type HostCertificateInfo struct {
types.HostCertificateManagerCertificateInfo
ThumbprintSHA1 string
ThumbprintSHA256 string
Err error
Certificate *x509.Certificate `json:"-"`
subjectName *pkix.Name
issuerName *pkix.Name
}
// FromCertificate converts x509.Certificate to HostCertificateInfo
func (info *HostCertificateInfo) FromCertificate(cert *x509.Certificate) *HostCertificateInfo {
info.Certificate = cert
info.subjectName = &cert.Subject
info.issuerName = &cert.Issuer
info.Issuer = info.fromName(info.issuerName)
info.NotBefore = &cert.NotBefore
info.NotAfter = &cert.NotAfter
info.Subject = info.fromName(info.subjectName)
info.ThumbprintSHA1 = soap.ThumbprintSHA1(cert)
// SHA-256 for info purposes only, API fields all use SHA-1
sum := sha256.Sum256(cert.Raw)
hex := make([]string, len(sum))
for i, b := range sum {
hex[i] = fmt.Sprintf("%02X", b)
}
info.ThumbprintSHA256 = strings.Join(hex, ":")
if info.Status == "" {
info.Status = string(types.HostCertificateManagerCertificateInfoCertificateStatusUnknown)
}
return info
}
// FromURL connects to the given URL.Host via tls.Dial with the given tls.Config and populates the HostCertificateInfo
// via tls.ConnectionState. If the certificate was verified with the given tls.Config, the Err field will be nil.
// Otherwise, Err will be set to the x509.UnknownAuthorityError or x509.HostnameError.
// If tls.Dial returns an error of any other type, that error is returned.
func (info *HostCertificateInfo) FromURL(u *url.URL, config *tls.Config) error {
addr := u.Host
if !(strings.LastIndex(addr, ":") > strings.LastIndex(addr, "]")) {
addr += ":443"
}
conn, err := tls.Dial("tcp", addr, config)
if err != nil {
switch err.(type) {
case x509.UnknownAuthorityError:
case x509.HostnameError:
default:
return err
}
info.Err = err
conn, err = tls.Dial("tcp", addr, &tls.Config{InsecureSkipVerify: true})
if err != nil {
return err
}
} else {
info.Status = string(types.HostCertificateManagerCertificateInfoCertificateStatusGood)
}
state := conn.ConnectionState()
_ = conn.Close()
info.FromCertificate(state.PeerCertificates[0])
return nil
}
var emailAddressOID = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}
func (info *HostCertificateInfo) fromName(name *pkix.Name) string {
var attrs []string
oids := map[string]string{
emailAddressOID.String(): "emailAddress",
}
for _, attr := range name.Names {
if key, ok := oids[attr.Type.String()]; ok {
attrs = append(attrs, fmt.Sprintf("%s=%s", key, attr.Value))
}
}
attrs = append(attrs, fmt.Sprintf("CN=%s", name.CommonName))
add := func(key string, vals []string) {
for _, val := range vals {
attrs = append(attrs, fmt.Sprintf("%s=%s", key, val))
}
}
elts := []struct {
key string
val []string
}{
{"OU", name.OrganizationalUnit},
{"O", name.Organization},
{"L", name.Locality},
{"ST", name.Province},
{"C", name.Country},
}
for _, elt := range elts {
add(elt.key, elt.val)
}
return strings.Join(attrs, ",")
}
func (info *HostCertificateInfo) toName(s string) *pkix.Name {
var name pkix.Name
for _, pair := range strings.Split(s, ",") {
attr := strings.SplitN(pair, "=", 2)
if len(attr) != 2 {
continue
}
v := attr[1]
switch strings.ToLower(attr[0]) {
case "cn":
name.CommonName = v
case "ou":
name.OrganizationalUnit = append(name.OrganizationalUnit, v)
case "o":
name.Organization = append(name.Organization, v)
case "l":
name.Locality = append(name.Locality, v)
case "st":
name.Province = append(name.Province, v)
case "c":
name.Country = append(name.Country, v)
case "emailaddress":
name.Names = append(name.Names, pkix.AttributeTypeAndValue{Type: emailAddressOID, Value: v})
}
}
return &name
}
// SubjectName parses Subject into a pkix.Name
func (info *HostCertificateInfo) SubjectName() *pkix.Name {
if info.subjectName != nil {
return info.subjectName
}
return info.toName(info.Subject)
}
// IssuerName parses Issuer into a pkix.Name
func (info *HostCertificateInfo) IssuerName() *pkix.Name {
if info.issuerName != nil {
return info.issuerName
}
return info.toName(info.Issuer)
}
// Write outputs info similar to the Chrome Certificate Viewer.
func (info *HostCertificateInfo) Write(w io.Writer) error {
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
s := func(val string) string {
if val != "" {
return val
}
return "<Not Part Of Certificate>"
}
ss := func(val []string) string {
return s(strings.Join(val, ","))
}
name := func(n *pkix.Name) {
fmt.Fprintf(tw, " Common Name (CN):\t%s\n", s(n.CommonName))
fmt.Fprintf(tw, " Organization (O):\t%s\n", ss(n.Organization))
fmt.Fprintf(tw, " Organizational Unit (OU):\t%s\n", ss(n.OrganizationalUnit))
}
status := info.Status
if info.Err != nil {
status = fmt.Sprintf("ERROR %s", info.Err)
}
fmt.Fprintf(tw, "Certificate Status:\t%s\n", status)
fmt.Fprintln(tw, "Issued To:\t")
name(info.SubjectName())
fmt.Fprintln(tw, "Issued By:\t")
name(info.IssuerName())
fmt.Fprintln(tw, "Validity Period:\t")
fmt.Fprintf(tw, " Issued On:\t%s\n", info.NotBefore)
fmt.Fprintf(tw, " Expires On:\t%s\n", info.NotAfter)
if info.ThumbprintSHA1 != "" {
fmt.Fprintln(tw, "Thumbprints:\t")
if info.ThumbprintSHA256 != "" {
fmt.Fprintf(tw, " SHA-256 Thumbprint:\t%s\n", info.ThumbprintSHA256)
}
fmt.Fprintf(tw, " SHA-1 Thumbprint:\t%s\n", info.ThumbprintSHA1)
}
return tw.Flush()
}

View File

@@ -0,0 +1,30 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import "testing"
func TestHostCertificateManagerCertificateInfo(t *testing.T) {
subject := "emailAddress=vmca@vmware.com,CN=w2-xlr8-autoroot-esx004.eng.vmware.com,OU=VMware Engineering,O=VMware,L=Palo Alto,ST=California,C=US"
var info HostCertificateInfo
name := info.toName(subject)
s := info.fromName(name)
if subject != s {
t.Errorf("%s != %s", s, subject)
}
}

View File

@@ -0,0 +1,162 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
// HostCertificateManager provides helper methods around the HostSystem.ConfigManager.CertificateManager
type HostCertificateManager struct {
Common
Host *HostSystem
}
// NewHostCertificateManager creates a new HostCertificateManager helper
func NewHostCertificateManager(c *vim25.Client, ref types.ManagedObjectReference, host types.ManagedObjectReference) *HostCertificateManager {
return &HostCertificateManager{
Common: NewCommon(c, ref),
Host: NewHostSystem(c, host),
}
}
// CertificateInfo wraps the host CertificateManager certificateInfo property with the HostCertificateInfo helper.
// The ThumbprintSHA1 field is set to HostSystem.Summary.Config.SslThumbprint if the host system is managed by a vCenter.
func (m HostCertificateManager) CertificateInfo(ctx context.Context) (*HostCertificateInfo, error) {
var hs mo.HostSystem
var cm mo.HostCertificateManager
pc := property.DefaultCollector(m.Client())
err := pc.RetrieveOne(ctx, m.Reference(), []string{"certificateInfo"}, &cm)
if err != nil {
return nil, err
}
_ = pc.RetrieveOne(ctx, m.Host.Reference(), []string{"summary.config.sslThumbprint"}, &hs)
return &HostCertificateInfo{
HostCertificateManagerCertificateInfo: cm.CertificateInfo,
ThumbprintSHA1: hs.Summary.Config.SslThumbprint,
}, nil
}
// GenerateCertificateSigningRequest requests the host system to generate a certificate-signing request (CSR) for itself.
// The CSR is then typically provided to a Certificate Authority to sign and issue the SSL certificate for the host system.
// Use InstallServerCertificate to import this certificate.
func (m HostCertificateManager) GenerateCertificateSigningRequest(ctx context.Context, useIPAddressAsCommonName bool) (string, error) {
req := types.GenerateCertificateSigningRequest{
This: m.Reference(),
UseIpAddressAsCommonName: useIPAddressAsCommonName,
}
res, err := methods.GenerateCertificateSigningRequest(ctx, m.Client(), &req)
if err != nil {
return "", err
}
return res.Returnval, nil
}
// GenerateCertificateSigningRequestByDn requests the host system to generate a certificate-signing request (CSR) for itself.
// Alternative version similar to GenerateCertificateSigningRequest but takes a Distinguished Name (DN) as a parameter.
func (m HostCertificateManager) GenerateCertificateSigningRequestByDn(ctx context.Context, distinguishedName string) (string, error) {
req := types.GenerateCertificateSigningRequestByDn{
This: m.Reference(),
DistinguishedName: distinguishedName,
}
res, err := methods.GenerateCertificateSigningRequestByDn(ctx, m.Client(), &req)
if err != nil {
return "", err
}
return res.Returnval, nil
}
// InstallServerCertificate imports the given SSL certificate to the host system.
func (m HostCertificateManager) InstallServerCertificate(ctx context.Context, cert string) error {
req := types.InstallServerCertificate{
This: m.Reference(),
Cert: cert,
}
_, err := methods.InstallServerCertificate(ctx, m.Client(), &req)
if err != nil {
return err
}
// NotifyAffectedService is internal, not exposing as we don't have a use case other than with InstallServerCertificate
// Without this call, hostd needs to be restarted to use the updated certificate
// Note: using Refresh as it has the same struct/signature, we just need to use different xml name tags
body := struct {
Req *types.Refresh `xml:"urn:vim25 NotifyAffectedServices,omitempty"`
Res *types.RefreshResponse `xml:"urn:vim25 NotifyAffectedServicesResponse,omitempty"`
methods.RefreshBody
}{
Req: &types.Refresh{This: m.Reference()},
}
return m.Client().RoundTrip(ctx, &body, &body)
}
// ListCACertificateRevocationLists returns the SSL CRLs of Certificate Authorities that are trusted by the host system.
func (m HostCertificateManager) ListCACertificateRevocationLists(ctx context.Context) ([]string, error) {
req := types.ListCACertificateRevocationLists{
This: m.Reference(),
}
res, err := methods.ListCACertificateRevocationLists(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
// ListCACertificates returns the SSL certificates of Certificate Authorities that are trusted by the host system.
func (m HostCertificateManager) ListCACertificates(ctx context.Context) ([]string, error) {
req := types.ListCACertificates{
This: m.Reference(),
}
res, err := methods.ListCACertificates(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
// ReplaceCACertificatesAndCRLs replaces the trusted CA certificates and CRL used by the host system.
// These determine whether the server can verify the identity of an external entity.
func (m HostCertificateManager) ReplaceCACertificatesAndCRLs(ctx context.Context, caCert []string, caCrl []string) error {
req := types.ReplaceCACertificatesAndCRLs{
This: m.Reference(),
CaCert: caCert,
CaCrl: caCrl,
}
_, err := methods.ReplaceCACertificatesAndCRLs(ctx, m.Client(), &req)
return err
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,69 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"time"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HostDateTimeSystem struct {
Common
}
func NewHostDateTimeSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostDateTimeSystem {
return &HostDateTimeSystem{
Common: NewCommon(c, ref),
}
}
func (s HostDateTimeSystem) UpdateConfig(ctx context.Context, config types.HostDateTimeConfig) error {
req := types.UpdateDateTimeConfig{
This: s.Reference(),
Config: config,
}
_, err := methods.UpdateDateTimeConfig(ctx, s.c, &req)
return err
}
func (s HostDateTimeSystem) Update(ctx context.Context, date time.Time) error {
req := types.UpdateDateTime{
This: s.Reference(),
DateTime: date,
}
_, err := methods.UpdateDateTime(ctx, s.c, &req)
return err
}
func (s HostDateTimeSystem) Query(ctx context.Context) (*time.Time, error) {
req := types.QueryDateTime{
This: s.Reference(),
}
res, err := methods.QueryDateTime(ctx, s.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}

View File

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

View File

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

View File

@@ -0,0 +1,88 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type HostServiceSystem struct {
Common
}
func NewHostServiceSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostServiceSystem {
return &HostServiceSystem{
Common: NewCommon(c, ref),
}
}
func (s HostServiceSystem) Service(ctx context.Context) ([]types.HostService, error) {
var ss mo.HostServiceSystem
err := s.Properties(ctx, s.Reference(), []string{"serviceInfo.service"}, &ss)
if err != nil {
return nil, err
}
return ss.ServiceInfo.Service, nil
}
func (s HostServiceSystem) Start(ctx context.Context, id string) error {
req := types.StartService{
This: s.Reference(),
Id: id,
}
_, err := methods.StartService(ctx, s.Client(), &req)
return err
}
func (s HostServiceSystem) Stop(ctx context.Context, id string) error {
req := types.StopService{
This: s.Reference(),
Id: id,
}
_, err := methods.StopService(ctx, s.Client(), &req)
return err
}
func (s HostServiceSystem) Restart(ctx context.Context, id string) error {
req := types.RestartService{
This: s.Reference(),
Id: id,
}
_, err := methods.RestartService(ctx, s.Client(), &req)
return err
}
func (s HostServiceSystem) UpdatePolicy(ctx context.Context, id string, policy string) error {
req := types.UpdateServicePolicy{
This: s.Reference(),
Id: id,
Policy: policy,
}
_, err := methods.UpdateServicePolicy(ctx, s.Client(), &req)
return err
}

View File

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

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

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

View File

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

View File

@@ -0,0 +1,117 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"encoding/json"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HostVsanInternalSystem struct {
Common
}
func NewHostVsanInternalSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostVsanInternalSystem {
m := HostVsanInternalSystem{
Common: NewCommon(c, ref),
}
return &m
}
// QueryVsanObjectUuidsByFilter returns vSAN DOM object uuids by filter.
func (m HostVsanInternalSystem) QueryVsanObjectUuidsByFilter(ctx context.Context, uuids []string, limit int32, version int32) ([]string, error) {
req := types.QueryVsanObjectUuidsByFilter{
This: m.Reference(),
Uuids: uuids,
Limit: limit,
Version: version,
}
res, err := methods.QueryVsanObjectUuidsByFilter(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
type VsanObjExtAttrs struct {
Type string `json:"Object type"`
Class string `json:"Object class"`
Size string `json:"Object size"`
Path string `json:"Object path"`
Name string `json:"User friendly name"`
}
func (a *VsanObjExtAttrs) DatastorePath(dir string) string {
l := len(dir)
path := a.Path
if len(path) >= l {
path = a.Path[l:]
}
if path != "" {
return path
}
return a.Name // vmnamespace
}
// GetVsanObjExtAttrs is internal and intended for troubleshooting/debugging situations in the field.
// WARNING: This API can be slow because we do IOs (reads) to all the objects.
func (m HostVsanInternalSystem) GetVsanObjExtAttrs(ctx context.Context, uuids []string) (map[string]VsanObjExtAttrs, error) {
req := types.GetVsanObjExtAttrs{
This: m.Reference(),
Uuids: uuids,
}
res, err := methods.GetVsanObjExtAttrs(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
var attrs map[string]VsanObjExtAttrs
err = json.Unmarshal([]byte(res.Returnval), &attrs)
return attrs, err
}
// DeleteVsanObjects is internal and intended for troubleshooting/debugging only.
// WARNING: This API can be slow because we do IOs to all the objects.
// DOM won't allow access to objects which have lost quorum. Such objects can be deleted with the optional "force" flag.
// These objects may however re-appear with quorum if the absent components come back (network partition gets resolved, etc.)
func (m HostVsanInternalSystem) DeleteVsanObjects(ctx context.Context, uuids []string, force *bool) ([]types.HostVsanInternalSystemDeleteVsanObjectsResult, error) {
req := types.DeleteVsanObjects{
This: m.Reference(),
Uuids: uuids,
Force: force,
}
res, err := methods.DeleteVsanObjects(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}

View File

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

View File

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

View File

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

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

@@ -0,0 +1,47 @@
/*
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/types"
)
type Network struct {
Common
}
func NewNetwork(c *vim25.Client, ref types.ManagedObjectReference) *Network {
return &Network{
Common: NewCommon(c, ref),
}
}
// EthernetCardBackingInfo returns the VirtualDeviceBackingInfo for this Network
func (n Network) EthernetCardBackingInfo(_ context.Context) (types.BaseVirtualDeviceBackingInfo, error) {
name := n.Name()
backing := &types.VirtualEthernetCardNetworkBackingInfo{
VirtualDeviceDeviceBackingInfo: types.VirtualDeviceDeviceBackingInfo{
DeviceName: name,
},
}
return backing, nil
}

View File

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

View File

@@ -0,0 +1,23 @@
/*
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
// Network should implement the Reference interface.
var _ Reference = Network{}
// Network should implement the NetworkReference interface.
var _ NetworkReference = Network{}

View File

@@ -0,0 +1,57 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"fmt"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type OpaqueNetwork struct {
Common
}
func NewOpaqueNetwork(c *vim25.Client, ref types.ManagedObjectReference) *OpaqueNetwork {
return &OpaqueNetwork{
Common: NewCommon(c, ref),
}
}
// EthernetCardBackingInfo returns the VirtualDeviceBackingInfo for this Network
func (n OpaqueNetwork) EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) {
var net mo.OpaqueNetwork
if err := n.Properties(ctx, n.Reference(), []string{"summary"}, &net); err != nil {
return nil, err
}
summary, ok := net.Summary.(*types.OpaqueNetworkSummary)
if !ok {
return nil, fmt.Errorf("%s unsupported network type: %T", n, net.Summary)
}
backing := &types.VirtualEthernetCardOpaqueNetworkBackingInfo{
OpaqueNetworkId: summary.OpaqueNetworkId,
OpaqueNetworkType: summary.OpaqueNetworkType,
}
return backing, nil
}

View File

@@ -0,0 +1,59 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type OptionManager struct {
Common
}
func NewOptionManager(c *vim25.Client, ref types.ManagedObjectReference) *OptionManager {
return &OptionManager{
Common: NewCommon(c, ref),
}
}
func (m OptionManager) Query(ctx context.Context, name string) ([]types.BaseOptionValue, error) {
req := types.QueryOptions{
This: m.Reference(),
Name: name,
}
res, err := methods.QueryOptions(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (m OptionManager) Update(ctx context.Context, value []types.BaseOptionValue) error {
req := types.UpdateOptions{
This: m.Reference(),
ChangedValue: value,
}
_, err := methods.UpdateOptions(ctx, m.Client(), &req)
return err
}

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

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

View File

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

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

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

View File

@@ -0,0 +1,155 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"fmt"
"reflect"
"testing"
"github.com/vmware/govmomi/test"
"github.com/vmware/govmomi/vim25/mo"
)
func TestSearch(t *testing.T) {
c := test.NewAuthenticatedClient(t)
s := NewSearchIndex(c)
ref, err := s.FindChild(context.Background(), NewRootFolder(c), "ha-datacenter")
if err != nil {
t.Fatal(err)
}
dc, ok := ref.(*Datacenter)
if !ok {
t.Errorf("Expected Datacenter: %#v", ref)
}
folders, err := dc.Folders(context.Background())
if err != nil {
t.Fatal(err)
}
ref, err = s.FindChild(context.Background(), folders.DatastoreFolder, "datastore1")
if err != nil {
t.Fatal(err)
}
_, ok = ref.(*Datastore)
if !ok {
t.Errorf("Expected Datastore: %#v", ref)
}
ref, err = s.FindByInventoryPath(context.Background(), "/ha-datacenter/network/VM Network")
if err != nil {
t.Fatal(err)
}
_, ok = ref.(*Network)
if !ok {
t.Errorf("Expected Network: %#v", ref)
}
crs, err := folders.HostFolder.Children(context.Background())
if err != nil {
if err != nil {
t.Fatal(err)
}
}
if len(crs) != 0 {
var cr mo.ComputeResource
ref = crs[0]
err = s.Properties(context.Background(), ref.Reference(), []string{"host"}, &cr)
if err != nil {
t.Fatal(err)
}
var host mo.HostSystem
ref = NewHostSystem(c, cr.Host[0])
err = s.Properties(context.Background(), ref.Reference(), []string{"name", "hardware", "config"}, &host)
if err != nil {
t.Fatal(err)
}
dnsConfig := host.Config.Network.DnsConfig.GetHostDnsConfig()
dnsName := fmt.Sprintf("%s.%s", dnsConfig.HostName, dnsConfig.DomainName)
shost, err := s.FindByDnsName(context.Background(), dc, dnsName, false)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(ref, shost) {
t.Errorf("%#v != %#v\n", ref, shost)
}
shost, err = s.FindByUuid(context.Background(), dc, host.Hardware.SystemInfo.Uuid, false, nil)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(ref, shost) {
t.Errorf("%#v != %#v\n", ref, shost)
}
}
vms, err := folders.VmFolder.Children(context.Background())
if err != nil {
t.Fatal(err)
}
if len(vms) != 0 {
var vm mo.VirtualMachine
ref = vms[0]
err = s.Properties(context.Background(), ref.Reference(), []string{"config", "guest"}, &vm)
if err != nil {
t.Fatal(err)
}
svm, err := s.FindByDatastorePath(context.Background(), dc, vm.Config.Files.VmPathName)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(ref, svm) {
t.Errorf("%#v != %#v\n", ref, svm)
}
svm, err = s.FindByUuid(context.Background(), dc, vm.Config.Uuid, true, nil)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(ref, svm) {
t.Errorf("%#v != %#v\n", ref, svm)
}
if vm.Guest.HostName != "" {
svm, err := s.FindByDnsName(context.Background(), dc, vm.Guest.HostName, true)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(ref, svm) {
t.Errorf("%#v != %#v\n", ref, svm)
}
}
if vm.Guest.IpAddress != "" {
svm, err := s.FindByIp(context.Background(), dc, vm.Guest.IpAddress, true)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(ref, svm) {
t.Errorf("%#v != %#v\n", ref, svm)
}
}
}
}

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

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

View File

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

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

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

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

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

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

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

View File

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

View File

@@ -0,0 +1,873 @@
/*
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 (
"math/rand"
"reflect"
"testing"
"github.com/vmware/govmomi/vim25/types"
)
func intPtrValue(val int32) *int32 {
return &val
}
var devices = VirtualDeviceList([]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: intPtrValue(0),
},
BusNumber: 0,
Device: []int32{3001, 3000},
},
},
&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: intPtrValue(0),
},
BusNumber: 1,
Device: []int32{3002},
},
},
&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: intPtrValue(0),
},
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: intPtrValue(0),
},
BusNumber: 0,
Device: []int32{500, 12000, 1000, 4000},
},
},
&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: intPtrValue(0),
},
BusNumber: 0,
Device: []int32{9000},
},
},
&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: intPtrValue(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{},
HostPointingDevice: "autodetect",
},
Connectable: (*types.VirtualDeviceConnectInfo)(nil),
SlotInfo: nil,
ControllerKey: 300,
UnitNumber: intPtrValue(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: intPtrValue(0),
},
VideoRamSizeInKB: 4096,
NumDisplays: 1,
UseAutoDetect: types.NewBool(false),
Enable3DSupport: types.NewBool(false),
Use3dRenderer: "automatic",
},
&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: &types.VirtualDevicePciBusSlotInfo{
VirtualDeviceBusSlotInfo: types.VirtualDeviceBusSlotInfo{},
PciSlotNumber: 33,
},
ControllerKey: 100,
UnitNumber: intPtrValue(17),
},
Id: 1754519335,
AllowUnrestrictedCommunication: types.NewBool(false),
},
&types.VirtualLsiLogicController{
VirtualSCSIController: types.VirtualSCSIController{
VirtualController: types.VirtualController{
VirtualDevice: types.VirtualDevice{
DynamicData: types.DynamicData{},
Key: 1000,
DeviceInfo: &types.Description{
DynamicData: types.DynamicData{},
Label: "SCSI controller 0",
Summary: "LSI Logic",
},
Backing: nil,
Connectable: (*types.VirtualDeviceConnectInfo)(nil),
SlotInfo: nil,
ControllerKey: 100,
UnitNumber: intPtrValue(3),
},
BusNumber: 0,
Device: nil,
},
HotAddRemove: types.NewBool(true),
SharedBus: "noSharing",
ScsiCtlrUnitNumber: 7,
},
},
&types.VirtualCdrom{
VirtualDevice: types.VirtualDevice{
DynamicData: types.DynamicData{},
Key: 3001,
DeviceInfo: &types.Description{
DynamicData: types.DynamicData{},
Label: "CD/DVD drive 1",
Summary: "ISO [datastore1] ttylinux-pc_i486-16.1.iso",
},
Backing: &types.VirtualCdromIsoBackingInfo{
VirtualDeviceFileBackingInfo: types.VirtualDeviceFileBackingInfo{
VirtualDeviceBackingInfo: types.VirtualDeviceBackingInfo{},
FileName: "[datastore1] foo.iso",
Datastore: &types.ManagedObjectReference{Type: "Datastore", Value: "53fe43cc-75dc5110-3643-000c2918dc41"},
BackingObjectId: "",
},
},
Connectable: &types.VirtualDeviceConnectInfo{
DynamicData: types.DynamicData{},
StartConnected: true,
AllowGuestControl: true,
Connected: false,
Status: "untried",
},
SlotInfo: nil,
ControllerKey: 200,
UnitNumber: intPtrValue(1),
},
},
&types.VirtualDisk{
VirtualDevice: types.VirtualDevice{
DynamicData: types.DynamicData{},
Key: 3000,
DeviceInfo: &types.Description{
DynamicData: types.DynamicData{},
Label: "Hard disk 1",
Summary: "30,720 KB",
},
Backing: &types.VirtualDiskFlatVer2BackingInfo{
VirtualDeviceFileBackingInfo: types.VirtualDeviceFileBackingInfo{
VirtualDeviceBackingInfo: types.VirtualDeviceBackingInfo{},
FileName: "[datastore1] bar/bar.vmdk",
Datastore: &types.ManagedObjectReference{Type: "Datastore", Value: "53fe43cc-75dc5110-3643-000c2918dc41"},
BackingObjectId: "3-3000-0",
},
DiskMode: "persistent",
Split: types.NewBool(false),
WriteThrough: types.NewBool(false),
ThinProvisioned: types.NewBool(false),
EagerlyScrub: types.NewBool(true),
Uuid: "6000C296-d0af-1209-1975-10c98eae10e4",
ContentId: "d46395062e2d1b1790985bdec573b211",
ChangeId: "",
Parent: &types.VirtualDiskFlatVer2BackingInfo{
VirtualDeviceFileBackingInfo: types.VirtualDeviceFileBackingInfo{
VirtualDeviceBackingInfo: types.VirtualDeviceBackingInfo{},
FileName: "[datastore1] ttylinux.vmdk",
Datastore: &types.ManagedObjectReference{Type: "Datastore", Value: "53fe43cc-75dc5110-3643-000c2918dc41"},
BackingObjectId: "3-3000-1",
},
DiskMode: "persistent",
Split: types.NewBool(false),
WriteThrough: types.NewBool(false),
ThinProvisioned: types.NewBool(false),
EagerlyScrub: types.NewBool(true),
Uuid: "6000C296-d0af-1209-1975-10c98eae10e4",
ContentId: "1c2dad9e1662219e962a620c6d238a7c",
ChangeId: "",
Parent: (*types.VirtualDiskFlatVer2BackingInfo)(nil),
DeltaDiskFormat: "",
DigestEnabled: types.NewBool(false),
DeltaGrainSize: 0,
},
DeltaDiskFormat: "redoLogFormat",
DigestEnabled: types.NewBool(false),
DeltaGrainSize: 0,
},
Connectable: (*types.VirtualDeviceConnectInfo)(nil),
SlotInfo: nil,
ControllerKey: 200,
UnitNumber: intPtrValue(0),
},
CapacityInKB: 30720,
CapacityInBytes: 31457280,
Shares: &types.SharesInfo{
DynamicData: types.DynamicData{},
Shares: 1000,
Level: "normal",
},
StorageIOAllocation: &types.StorageIOAllocationInfo{
DynamicData: types.DynamicData{},
Limit: -1,
Shares: &types.SharesInfo{
DynamicData: types.DynamicData{},
Shares: 1000,
Level: "normal",
},
Reservation: 0,
},
DiskObjectId: "3-3000",
VFlashCacheConfigInfo: (*types.VirtualDiskVFlashCacheConfigInfo)(nil),
},
&types.VirtualDisk{
VirtualDevice: types.VirtualDevice{
DynamicData: types.DynamicData{},
Key: 3002,
DeviceInfo: &types.Description{
DynamicData: types.DynamicData{},
Label: "Hard disk 2",
Summary: "10,000,000 KB",
},
Backing: &types.VirtualDiskFlatVer2BackingInfo{
VirtualDeviceFileBackingInfo: types.VirtualDeviceFileBackingInfo{
VirtualDeviceBackingInfo: types.VirtualDeviceBackingInfo{},
FileName: "[datastore1] bar/disk-201-0.vmdk",
Datastore: &types.ManagedObjectReference{Type: "Datastore", Value: "53fe43cc-75dc5110-3643-000c2918dc41"},
BackingObjectId: "3-3002-0",
},
DiskMode: "persistent",
Split: types.NewBool(false),
WriteThrough: types.NewBool(false),
ThinProvisioned: types.NewBool(true),
EagerlyScrub: types.NewBool(false),
Uuid: "6000C293-fde5-4457-5118-dd267ea992a7",
ContentId: "90399989b9d520eed6793ab0fffffffe",
ChangeId: "",
Parent: (*types.VirtualDiskFlatVer2BackingInfo)(nil),
DeltaDiskFormat: "",
DigestEnabled: types.NewBool(false),
DeltaGrainSize: 0,
},
Connectable: (*types.VirtualDeviceConnectInfo)(nil),
SlotInfo: nil,
ControllerKey: 201,
UnitNumber: intPtrValue(0),
},
CapacityInKB: 10000000,
CapacityInBytes: 10240000000,
Shares: &types.SharesInfo{
DynamicData: types.DynamicData{},
Shares: 1000,
Level: "normal",
},
StorageIOAllocation: &types.StorageIOAllocationInfo{
DynamicData: types.DynamicData{},
Limit: -1,
Shares: &types.SharesInfo{
DynamicData: types.DynamicData{},
Shares: 1000,
Level: "normal",
},
Reservation: 0,
},
DiskObjectId: "3-3002",
VFlashCacheConfigInfo: (*types.VirtualDiskVFlashCacheConfigInfo)(nil),
},
&types.VirtualE1000{
VirtualEthernetCard: types.VirtualEthernetCard{
VirtualDevice: types.VirtualDevice{
DynamicData: types.DynamicData{},
Key: 4000,
DeviceInfo: &types.Description{
DynamicData: types.DynamicData{},
Label: "Network adapter 1",
Summary: "VM Network",
},
Backing: &types.VirtualEthernetCardNetworkBackingInfo{
VirtualDeviceDeviceBackingInfo: types.VirtualDeviceDeviceBackingInfo{
VirtualDeviceBackingInfo: types.VirtualDeviceBackingInfo{},
DeviceName: "VM Network",
UseAutoDetect: types.NewBool(false),
},
Network: &types.ManagedObjectReference{Type: "Network", Value: "HaNetwork-VM Network"},
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: intPtrValue(7),
},
AddressType: "generated",
MacAddress: "00:0c:29:93:d7:27",
WakeOnLanEnabled: types.NewBool(true),
},
},
&types.VirtualSerialPort{
VirtualDevice: types.VirtualDevice{
DynamicData: types.DynamicData{},
Key: 9000,
DeviceInfo: &types.Description{
DynamicData: types.DynamicData{},
Label: "Serial port 1",
Summary: "Remote localhost:0",
},
Backing: &types.VirtualSerialPortURIBackingInfo{
VirtualDeviceURIBackingInfo: types.VirtualDeviceURIBackingInfo{
VirtualDeviceBackingInfo: types.VirtualDeviceBackingInfo{},
ServiceURI: "localhost:0",
Direction: "client",
ProxyURI: "",
},
},
Connectable: &types.VirtualDeviceConnectInfo{
DynamicData: types.DynamicData{},
StartConnected: true,
AllowGuestControl: true,
Connected: false,
Status: "untried",
},
SlotInfo: nil,
ControllerKey: 400,
UnitNumber: intPtrValue(0),
},
YieldOnPoll: true,
},
})
func TestSelectByType(t *testing.T) {
tests := []struct {
dtype types.BaseVirtualDevice
expect int
}{
{
(*types.VirtualCdrom)(nil),
1,
},
{
(*types.VirtualEthernetCard)(nil),
1,
},
{
(*types.VirtualDisk)(nil),
2,
},
{
(*types.VirtualController)(nil),
6,
},
{
(*types.VirtualIDEController)(nil),
2,
},
{
(*types.VirtualSCSIController)(nil),
1,
},
{
(*types.VirtualLsiLogicController)(nil),
1,
},
{
(*types.ParaVirtualSCSIController)(nil),
0,
},
}
for _, test := range tests {
d := devices.SelectByType(test.dtype)
if len(d) != test.expect {
t.Errorf("%#v has %d", test.dtype, len(devices))
}
}
}
func TestSelectByBackingInfo(t *testing.T) {
tests := []types.BaseVirtualDeviceBackingInfo{
&types.VirtualEthernetCardNetworkBackingInfo{
VirtualDeviceDeviceBackingInfo: types.VirtualDeviceDeviceBackingInfo{
DeviceName: "VM Network",
},
},
&types.VirtualDiskFlatVer2BackingInfo{
VirtualDeviceFileBackingInfo: types.VirtualDeviceFileBackingInfo{
FileName: "[datastore1] bar/bar.vmdk",
},
},
&types.VirtualDiskFlatVer2BackingInfo{
Parent: &types.VirtualDiskFlatVer2BackingInfo{
VirtualDeviceFileBackingInfo: types.VirtualDeviceFileBackingInfo{
FileName: "[datastore1] ttylinux.vmdk",
},
},
},
&types.VirtualCdromIsoBackingInfo{
VirtualDeviceFileBackingInfo: types.VirtualDeviceFileBackingInfo{
VirtualDeviceBackingInfo: types.VirtualDeviceBackingInfo{},
FileName: "[datastore1] foo.iso",
},
},
(*types.VirtualCdromIsoBackingInfo)(nil),
&types.VirtualSerialPortURIBackingInfo{
VirtualDeviceURIBackingInfo: types.VirtualDeviceURIBackingInfo{
VirtualDeviceBackingInfo: types.VirtualDeviceBackingInfo{},
ServiceURI: "localhost:0",
Direction: "client",
ProxyURI: "",
},
},
(*types.VirtualSerialPortURIBackingInfo)(nil),
}
for _, test := range tests {
l := devices.SelectByBackingInfo(test)
if len(l) != 1 {
t.Errorf("Expected 1, got %d: %#v", len(l), test)
}
}
// test selecting by backing type
tests = []types.BaseVirtualDeviceBackingInfo{
(*types.VirtualDiskFlatVer2BackingInfo)(nil),
}
for _, test := range tests {
l := devices.SelectByBackingInfo(test)
if len(l) != 2 {
t.Errorf("Expected 2, got %d: %#v", len(l), test)
}
}
}
func TestFind(t *testing.T) {
for _, device := range devices {
name := devices.Name(device)
d := devices.Find(name)
if name != devices.Name(d) {
t.Errorf("expected name: %s, got: %s", name, devices.Name(d))
}
}
d := devices.Find("enoent")
if d != nil {
t.Errorf("unexpected: %#v", d)
}
}
func TestFindController(t *testing.T) {
for _, name := range []string{"", "ide-200"} {
_, err := devices.FindIDEController(name)
if err != nil {
t.Error(err)
}
}
for _, name := range []string{"", "lsilogic-1000"} {
_, err := devices.FindSCSIController(name)
if err != nil {
t.Error(err)
}
}
fns := []func() error{
func() error {
_, err := devices.FindIDEController("lsilogic-1000")
return err
},
func() error {
_, err := devices.FindSCSIController("ide-200")
return err
},
}
for _, f := range fns {
err := f()
if err == nil {
t.Error("should fail")
}
}
}
func TestPickController(t *testing.T) {
list := devices
tests := []struct {
ctype types.BaseVirtualController
key int32
unit int32
}{
{
(*types.VirtualIDEController)(nil), 201, 1,
},
{
(*types.VirtualSCSIController)(nil), 1000, 0,
},
{
(*types.VirtualSCSIController)(nil), 1000, 1,
},
}
for _, test := range tests {
c := list.PickController(test.ctype).GetVirtualController()
key := c.Key
if key != test.key {
t.Errorf("expected controller key: %d, got: %d\n", test.key, key)
}
unit := list.newUnitNumber(c)
if unit != test.unit {
t.Errorf("expected unit number: %d, got: %d\n", test.unit, unit)
}
dev := &types.VirtualDevice{
Key: int32(rand.Int()),
UnitNumber: new(int32),
ControllerKey: key,
}
*dev.UnitNumber = unit
list = append(list, dev)
c.Device = append(c.Device, dev.Key)
}
if list.PickController((*types.VirtualIDEController)(nil)) != nil {
t.Error("should be nil")
}
if list.PickController((*types.VirtualSCSIController)(nil)) == nil {
t.Errorf("should not be nil")
}
}
func TestCreateSCSIController(t *testing.T) {
for _, l := range []VirtualDeviceList{SCSIControllerTypes(), devices} {
_, err := l.CreateSCSIController("enoent")
if err == nil {
t.Error("should fail")
}
for _, name := range []string{"", "scsi", "pvscsi", "buslogic", "lsilogic", "lsilogic-sas"} {
_, err = l.CreateSCSIController(name)
if err != nil {
t.Error(err)
}
}
}
}
func TestCreateEthernetCard(t *testing.T) {
_, err := EthernetCardTypes().CreateEthernetCard("enoent", nil)
if err == nil {
t.Error("should fail")
}
for _, name := range []string{"", "e1000", "e1000e", "vmxnet3"} {
_, err := EthernetCardTypes().CreateEthernetCard(name, nil)
if err != nil {
t.Error(err)
}
}
}
func TestCdrom(t *testing.T) {
c, err := devices.FindCdrom("")
if err != nil {
t.Error(err)
}
d := devices.Find(devices.Name(c))
if c.Key != d.GetVirtualDevice().Key {
t.Error("device key mismatch")
}
for _, name := range []string{"enoent", "ide-200"} {
c, err = devices.FindCdrom(name)
if err == nil {
t.Errorf("FindCdrom(%s) should fail", name)
}
}
c, err = devices.Select(func(device types.BaseVirtualDevice) bool {
if _, ok := device.(*types.VirtualCdrom); ok {
return false
}
return true
}).FindCdrom("")
if err == nil {
t.Error("FindCdrom('') should fail")
}
}
func TestSerialPort(t *testing.T) {
device, err := devices.CreateSerialPort()
if err != nil {
t.Error(err)
}
devices.ConnectSerialPort(device, "telnet://:33233", false, "")
}
func TestPrimaryMacAddress(t *testing.T) {
expect := "00:0c:29:93:d7:27"
mac := devices.PrimaryMacAddress()
if expect != mac {
t.Errorf("expected: %s, got: %s", expect, mac)
}
}
func TestBootOrder(t *testing.T) {
o := []string{DeviceTypeEthernet, DeviceTypeCdrom, DeviceTypeFloppy, DeviceTypeDisk}
list := devices
n := 4 // 1 ethernet, 1 cdrom, 2 disk
order := list.BootOrder(o)
if len(order) != n {
t.Errorf("expected %d boot devices, got: %d", n, len(order))
}
list = list.SelectBootOrder(order)
if len(list) != n {
t.Errorf("expected %d boot devices, got: %d", n, len(list))
}
// test lookup by name
var names []string
for _, x := range list {
names = append(names, list.Name(x))
}
order = list.BootOrder(names)
if len(order) != n {
t.Errorf("expected %d boot devices, got: %d", n, len(order))
}
if !reflect.DeepEqual(list, list.SelectBootOrder(order)) {
t.Error("boot order mismatch")
}
// remove disks
list = list.Select(func(device types.BaseVirtualDevice) bool {
if _, ok := device.(*types.VirtualDisk); ok {
return false
}
return true
})
n = 2 // 1 ethernet, 1 cdrom
order = list.BootOrder(o)
if len(order) != n {
t.Errorf("expected %d boot devices, got: %d", n, len(order))
}
if !reflect.DeepEqual(list, list.SelectBootOrder(order)) {
t.Error("boot order mismatch")
}
if len(list.BootOrder([]string{DeviceTypeDisk})) != 0 {
t.Error("expected 0 disks")
}
}
func TestName(t *testing.T) {
tests := []struct {
device types.BaseVirtualDevice
expect string
}{
{
&types.VirtualCdrom{},
"cdrom-0",
},
{
&types.VirtualDisk{},
"disk-0-0",
},
{
&types.VirtualFloppy{},
"floppy-0",
},
{
&types.VirtualIDEController{},
"ide-0",
},
{
&types.VirtualMachineVideoCard{},
"video-0",
},
{
&types.VirtualPointingDevice{},
"pointing-0",
},
{
&types.ParaVirtualSCSIController{},
"pvscsi-0",
},
{
&types.VirtualSerialPort{},
"serialport-0",
},
{
&types.VirtualE1000{
VirtualEthernetCard: types.VirtualEthernetCard{
VirtualDevice: types.VirtualDevice{
UnitNumber: intPtrValue(7),
},
},
},
"ethernet-0",
},
}
for _, test := range tests {
name := devices.Name(test.device)
if name != test.expect {
t.Errorf("expected: %s, got: %s", test.expect, name)
}
}
}
func TestChildDisk(t *testing.T) {
disks := devices.SelectByType((*types.VirtualDisk)(nil))
for _, disk := range disks {
child := disks.ChildDisk(disk.(*types.VirtualDisk))
name := child.Backing.(*types.VirtualDiskFlatVer2BackingInfo).VirtualDeviceFileBackingInfo.FileName
p := new(DatastorePath)
p.FromString(name)
if p.Datastore != "datastore1" {
t.Fatal(p.Datastore)
}
if p.Path != "" {
t.Fatal(p.Path)
}
}
}

View File

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

View File

@@ -0,0 +1,97 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"reflect"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
func init() {
types.Add("ArrayOfVirtualDiskInfo", reflect.TypeOf((*arrayOfVirtualDiskInfo)(nil)).Elem())
types.Add("VirtualDiskInfo", reflect.TypeOf((*VirtualDiskInfo)(nil)).Elem())
}
type arrayOfVirtualDiskInfo struct {
VirtualDiskInfo []VirtualDiskInfo `xml:"VirtualDiskInfo,omitempty"`
}
type queryVirtualDiskInfoTaskRequest struct {
This types.ManagedObjectReference `xml:"_this"`
Name string `xml:"name"`
Datacenter *types.ManagedObjectReference `xml:"datacenter,omitempty"`
IncludeParents bool `xml:"includeParents"`
}
type queryVirtualDiskInfoTaskResponse struct {
Returnval types.ManagedObjectReference `xml:"returnval"`
}
type queryVirtualDiskInfoTaskBody struct {
Req *queryVirtualDiskInfoTaskRequest `xml:"urn:internalvim25 QueryVirtualDiskInfo_Task,omitempty"`
Res *queryVirtualDiskInfoTaskResponse `xml:"urn:vim25 QueryVirtualDiskInfo_TaskResponse,omitempty"`
Err *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *queryVirtualDiskInfoTaskBody) Fault() *soap.Fault { return b.Err }
func queryVirtualDiskInfoTask(ctx context.Context, r soap.RoundTripper, req *queryVirtualDiskInfoTaskRequest) (*queryVirtualDiskInfoTaskResponse, error) {
var reqBody, resBody queryVirtualDiskInfoTaskBody
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
}
type VirtualDiskInfo struct {
Name string `xml:"unit>name"`
DiskType string `xml:"diskType"`
Parent string `xml:"parent,omitempty"`
}
func (m VirtualDiskManager) QueryVirtualDiskInfo(ctx context.Context, name string, dc *Datacenter, includeParents bool) ([]VirtualDiskInfo, error) {
req := queryVirtualDiskInfoTaskRequest{
This: m.Reference(),
Name: name,
IncludeParents: includeParents,
}
if dc != nil {
ref := dc.Reference()
req.Datacenter = &ref
}
res, err := queryVirtualDiskInfoTask(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
info, err := NewTask(m.Client(), res.Returnval).WaitForResult(ctx, nil)
if err != nil {
return nil, err
}
return info.Result.(arrayOfVirtualDiskInfo).VirtualDiskInfo, nil
}

View File

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

View File

@@ -0,0 +1,206 @@
/*
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 (
"testing"
"time"
"github.com/vmware/govmomi/vim25/types"
)
// VirtualMachine should implement the Reference interface.
var _ Reference = VirtualMachine{}
// pretty.Printf generated
var snapshot = &types.VirtualMachineSnapshotInfo{
DynamicData: types.DynamicData{},
CurrentSnapshot: &types.ManagedObjectReference{Type: "VirtualMachineSnapshot", Value: "2-snapshot-11"},
RootSnapshotList: []types.VirtualMachineSnapshotTree{
{
DynamicData: types.DynamicData{},
Snapshot: types.ManagedObjectReference{Type: "VirtualMachineSnapshot", Value: "2-snapshot-1"},
Vm: types.ManagedObjectReference{Type: "VirtualMachine", Value: "2"},
Name: "root",
Description: "",
Id: 1,
CreateTime: time.Now(),
State: "poweredOn",
Quiesced: false,
BackupManifest: "",
ChildSnapshotList: []types.VirtualMachineSnapshotTree{
{
DynamicData: types.DynamicData{},
Snapshot: types.ManagedObjectReference{Type: "VirtualMachineSnapshot", Value: "2-snapshot-2"},
Vm: types.ManagedObjectReference{Type: "VirtualMachine", Value: "2"},
Name: "child",
Description: "",
Id: 2,
CreateTime: time.Now(),
State: "poweredOn",
Quiesced: false,
BackupManifest: "",
ChildSnapshotList: nil,
ReplaySupported: types.NewBool(false),
},
{
DynamicData: types.DynamicData{},
Snapshot: types.ManagedObjectReference{Type: "VirtualMachineSnapshot", Value: "2-snapshot-3"},
Vm: types.ManagedObjectReference{Type: "VirtualMachine", Value: "2"},
Name: "child",
Description: "",
Id: 3,
CreateTime: time.Now(),
State: "poweredOn",
Quiesced: false,
BackupManifest: "",
ChildSnapshotList: []types.VirtualMachineSnapshotTree{
{
DynamicData: types.DynamicData{},
Snapshot: types.ManagedObjectReference{Type: "VirtualMachineSnapshot", Value: "2-snapshot-9"},
Vm: types.ManagedObjectReference{Type: "VirtualMachine", Value: "2"},
Name: "grandkid",
Description: "",
Id: 9,
CreateTime: time.Now(),
State: "poweredOn",
Quiesced: false,
BackupManifest: "",
ChildSnapshotList: []types.VirtualMachineSnapshotTree{
{
DynamicData: types.DynamicData{},
Snapshot: types.ManagedObjectReference{Type: "VirtualMachineSnapshot", Value: "2-snapshot-10"},
Vm: types.ManagedObjectReference{Type: "VirtualMachine", Value: "2"},
Name: "great",
Description: "",
Id: 10,
CreateTime: time.Now(),
State: "poweredOn",
Quiesced: false,
BackupManifest: "",
ChildSnapshotList: nil,
ReplaySupported: types.NewBool(false),
},
},
ReplaySupported: types.NewBool(false),
},
},
ReplaySupported: types.NewBool(false),
},
{
DynamicData: types.DynamicData{},
Snapshot: types.ManagedObjectReference{Type: "VirtualMachineSnapshot", Value: "2-snapshot-5"},
Vm: types.ManagedObjectReference{Type: "VirtualMachine", Value: "2"},
Name: "voodoo",
Description: "",
Id: 5,
CreateTime: time.Now(),
State: "poweredOn",
Quiesced: false,
BackupManifest: "",
ChildSnapshotList: []types.VirtualMachineSnapshotTree{
{
DynamicData: types.DynamicData{},
Snapshot: types.ManagedObjectReference{Type: "VirtualMachineSnapshot", Value: "2-snapshot-11"},
Vm: types.ManagedObjectReference{Type: "VirtualMachine", Value: "2"},
Name: "child",
Description: "",
Id: 11,
CreateTime: time.Now(),
State: "poweredOn",
Quiesced: false,
BackupManifest: "",
ChildSnapshotList: nil,
ReplaySupported: types.NewBool(false),
},
},
ReplaySupported: types.NewBool(false),
},
{
DynamicData: types.DynamicData{},
Snapshot: types.ManagedObjectReference{Type: "VirtualMachineSnapshot", Value: "2-snapshot-6"},
Vm: types.ManagedObjectReference{Type: "VirtualMachine", Value: "2"},
Name: "better",
Description: "",
Id: 6,
CreateTime: time.Now(),
State: "poweredOn",
Quiesced: false,
BackupManifest: "",
ChildSnapshotList: []types.VirtualMachineSnapshotTree{
{
DynamicData: types.DynamicData{},
Snapshot: types.ManagedObjectReference{Type: "VirtualMachineSnapshot", Value: "2-snapshot-7"},
Vm: types.ManagedObjectReference{Type: "VirtualMachine", Value: "2"},
Name: "best",
Description: "",
Id: 7,
CreateTime: time.Now(),
State: "poweredOn",
Quiesced: false,
BackupManifest: "",
ChildSnapshotList: []types.VirtualMachineSnapshotTree{
{
DynamicData: types.DynamicData{},
Snapshot: types.ManagedObjectReference{Type: "VirtualMachineSnapshot", Value: "2-snapshot-8"},
Vm: types.ManagedObjectReference{Type: "VirtualMachine", Value: "2"},
Name: "betterer",
Description: "",
Id: 8,
CreateTime: time.Now(),
State: "poweredOn",
Quiesced: false,
BackupManifest: "",
ChildSnapshotList: nil,
ReplaySupported: types.NewBool(false),
},
},
ReplaySupported: types.NewBool(false),
},
},
ReplaySupported: types.NewBool(false),
},
},
ReplaySupported: types.NewBool(false),
},
},
}
func TestVirtualMachineSnapshotMap(t *testing.T) {
m := make(snapshotMap)
m.add("", snapshot.RootSnapshotList)
tests := []struct {
name string
expect int
}{
{"enoent", 0},
{"root", 1},
{"child", 3},
{"root/child", 2},
{"root/voodoo/child", 1},
{"2-snapshot-6", 1},
}
for _, test := range tests {
s := m[test.name]
if len(s) != test.expect {
t.Errorf("%s: %d != %d", test.name, len(s), test.expect)
}
}
}

View File

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