Update vmware/govmomi godeps

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

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

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

View File

@@ -0,0 +1,257 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"strings"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/simulator/esx"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type AuthorizationManager struct {
mo.AuthorizationManager
permissions map[types.ManagedObjectReference][]types.Permission
privileges map[string]struct{}
system []string
nextID int32
}
func NewAuthorizationManager(ref types.ManagedObjectReference) object.Reference {
m := &AuthorizationManager{}
m.Self = ref
m.RoleList = esx.RoleList
m.permissions = make(map[types.ManagedObjectReference][]types.Permission)
l := object.AuthorizationRoleList(m.RoleList)
m.system = l.ByName("ReadOnly").Privilege
admin := l.ByName("Admin")
m.privileges = make(map[string]struct{}, len(admin.Privilege))
for _, id := range admin.Privilege {
m.privileges[id] = struct{}{}
}
root := Map.content().RootFolder
for _, u := range DefaultUserGroup {
m.permissions[root] = append(m.permissions[root], types.Permission{
Entity: &root,
Principal: u.Principal,
Group: u.Group,
RoleId: admin.RoleId,
Propagate: true,
})
}
return m
}
func (m *AuthorizationManager) RetrieveEntityPermissions(req *types.RetrieveEntityPermissions) soap.HasFault {
e := Map.Get(req.Entity).(mo.Entity)
p := m.permissions[e.Reference()]
if req.Inherited {
for {
parent := e.Entity().Parent
if parent == nil {
break
}
e = Map.Get(parent.Reference()).(mo.Entity)
p = append(p, m.permissions[e.Reference()]...)
}
}
return &methods.RetrieveEntityPermissionsBody{
Res: &types.RetrieveEntityPermissionsResponse{
Returnval: p,
},
}
}
func (m *AuthorizationManager) RetrieveAllPermissions(req *types.RetrieveAllPermissions) soap.HasFault {
var p []types.Permission
for _, v := range m.permissions {
p = append(p, v...)
}
return &methods.RetrieveAllPermissionsBody{
Res: &types.RetrieveAllPermissionsResponse{
Returnval: p,
},
}
}
func (m *AuthorizationManager) RemoveEntityPermission(req *types.RemoveEntityPermission) soap.HasFault {
var p []types.Permission
for _, v := range m.permissions[req.Entity] {
if v.Group == req.IsGroup && v.Principal == req.User {
continue
}
p = append(p, v)
}
m.permissions[req.Entity] = p
return &methods.RemoveEntityPermissionBody{
Res: &types.RemoveEntityPermissionResponse{},
}
}
func (m *AuthorizationManager) SetEntityPermissions(req *types.SetEntityPermissions) soap.HasFault {
m.permissions[req.Entity] = req.Permission
return &methods.SetEntityPermissionsBody{
Res: &types.SetEntityPermissionsResponse{},
}
}
func (m *AuthorizationManager) RetrieveRolePermissions(req *types.RetrieveRolePermissions) soap.HasFault {
var p []types.Permission
for _, set := range m.permissions {
for _, v := range set {
if v.RoleId == req.RoleId {
p = append(p, v)
}
}
}
return &methods.RetrieveRolePermissionsBody{
Res: &types.RetrieveRolePermissionsResponse{
Returnval: p,
},
}
}
func (m *AuthorizationManager) AddAuthorizationRole(req *types.AddAuthorizationRole) soap.HasFault {
body := &methods.AddAuthorizationRoleBody{}
for _, role := range m.RoleList {
if role.Name == req.Name {
body.Fault_ = Fault("", &types.AlreadyExists{})
return body
}
}
ids, err := m.privIDs(req.PrivIds)
if err != nil {
body.Fault_ = err
return body
}
m.RoleList = append(m.RoleList, types.AuthorizationRole{
Info: &types.Description{
Label: req.Name,
Summary: req.Name,
},
RoleId: m.nextID,
Privilege: ids,
Name: req.Name,
System: false,
})
m.nextID++
body.Res = &types.AddAuthorizationRoleResponse{}
return body
}
func (m *AuthorizationManager) UpdateAuthorizationRole(req *types.UpdateAuthorizationRole) soap.HasFault {
body := &methods.UpdateAuthorizationRoleBody{}
for _, role := range m.RoleList {
if role.Name == req.NewName && role.RoleId != req.RoleId {
body.Fault_ = Fault("", &types.AlreadyExists{})
return body
}
}
for i, role := range m.RoleList {
if role.RoleId == req.RoleId {
if len(req.PrivIds) != 0 {
ids, err := m.privIDs(req.PrivIds)
if err != nil {
body.Fault_ = err
return body
}
m.RoleList[i].Privilege = ids
}
m.RoleList[i].Name = req.NewName
body.Res = &types.UpdateAuthorizationRoleResponse{}
return body
}
}
body.Fault_ = Fault("", &types.NotFound{})
return body
}
func (m *AuthorizationManager) RemoveAuthorizationRole(req *types.RemoveAuthorizationRole) soap.HasFault {
body := &methods.RemoveAuthorizationRoleBody{}
for i, role := range m.RoleList {
if role.RoleId == req.RoleId {
m.RoleList = append(m.RoleList[:i], m.RoleList[i+1:]...)
body.Res = &types.RemoveAuthorizationRoleResponse{}
return body
}
}
body.Fault_ = Fault("", &types.NotFound{})
return body
}
func (m *AuthorizationManager) privIDs(ids []string) ([]string, *soap.Fault) {
system := make(map[string]struct{}, len(m.system))
for _, id := range ids {
if _, ok := m.privileges[id]; !ok {
return nil, Fault("", &types.InvalidArgument{InvalidProperty: "privIds"})
}
if strings.HasPrefix(id, "System.") {
system[id] = struct{}{}
}
}
for _, id := range m.system {
if _, ok := system[id]; ok {
continue
}
ids = append(ids, id)
}
return ids, nil
}

View File

@@ -0,0 +1,98 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"github.com/vmware/govmomi/simulator/esx"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type ClusterComputeResource struct {
mo.ClusterComputeResource
}
type addHost struct {
*ClusterComputeResource
req *types.AddHost_Task
}
func (add *addHost) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
spec := add.req.Spec
if spec.HostName == "" {
return nil, &types.NoHost{}
}
host := NewHostSystem(esx.HostSystem)
host.Summary.Config.Name = spec.HostName
host.Name = host.Summary.Config.Name
host.Runtime.ConnectionState = types.HostSystemConnectionStateDisconnected
cr := add.ClusterComputeResource
Map.PutEntity(cr, Map.NewEntity(host))
cr.Host = append(cr.Host, host.Reference())
if add.req.AsConnected {
host.Runtime.ConnectionState = types.HostSystemConnectionStateConnected
}
addComputeResource(add.ClusterComputeResource.Summary.GetComputeResourceSummary(), host)
return host.Reference(), nil
}
func (c *ClusterComputeResource) AddHostTask(add *types.AddHost_Task) soap.HasFault {
return &methods.AddHost_TaskBody{
Res: &types.AddHost_TaskResponse{
Returnval: NewTask(&addHost{c, add}).Run(),
},
}
}
func CreateClusterComputeResource(f *Folder, name string, spec types.ClusterConfigSpecEx) (*ClusterComputeResource, types.BaseMethodFault) {
if e := Map.FindByName(name, f.ChildEntity); e != nil {
return nil, &types.DuplicateName{
Name: e.Entity().Name,
Object: e.Reference(),
}
}
cluster := &ClusterComputeResource{}
cluster.Name = name
cluster.Summary = &types.ClusterComputeResourceSummary{
UsageSummary: new(types.ClusterUsageSummary),
}
config := &types.ClusterConfigInfoEx{}
cluster.ConfigurationEx = config
config.DrsConfig.Enabled = types.NewBool(true)
pool := NewResourcePool()
Map.PutEntity(cluster, Map.NewEntity(pool))
cluster.ResourcePool = &pool.Self
f.putChild(cluster)
pool.Owner = cluster.Self
return cluster, nil
}

View File

@@ -0,0 +1,111 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type CustomFieldsManager struct {
mo.CustomFieldsManager
nextKey int32
}
func NewCustomFieldsManager(ref types.ManagedObjectReference) object.Reference {
m := &CustomFieldsManager{}
m.Self = ref
return m
}
func (c *CustomFieldsManager) find(key int32) (int, *types.CustomFieldDef) {
for i, field := range c.Field {
if field.Key == key {
return i, &c.Field[i]
}
}
return -1, nil
}
func (c *CustomFieldsManager) AddCustomFieldDef(req *types.AddCustomFieldDef) soap.HasFault {
body := &methods.AddCustomFieldDefBody{}
def := types.CustomFieldDef{
Key: c.nextKey,
Name: req.Name,
ManagedObjectType: req.MoType,
Type: req.MoType,
FieldDefPrivileges: req.FieldDefPolicy,
FieldInstancePrivileges: req.FieldPolicy,
}
c.Field = append(c.Field, def)
c.nextKey++
body.Res = &types.AddCustomFieldDefResponse{
Returnval: def,
}
return body
}
func (c *CustomFieldsManager) RemoveCustomFieldDef(req *types.RemoveCustomFieldDef) soap.HasFault {
body := &methods.RemoveCustomFieldDefBody{}
i, field := c.find(req.Key)
if field == nil {
body.Fault_ = Fault("", &types.NotFound{})
return body
}
c.Field = append(c.Field[:i], c.Field[i+1:]...)
body.Res = &types.RemoveCustomFieldDefResponse{}
return body
}
func (c *CustomFieldsManager) RenameCustomFieldDef(req *types.RenameCustomFieldDef) soap.HasFault {
body := &methods.RenameCustomFieldDefBody{}
_, field := c.find(req.Key)
if field == nil {
body.Fault_ = Fault("", &types.NotFound{})
return body
}
field.Name = req.Name
body.Res = &types.RenameCustomFieldDefResponse{}
return body
}
func (c *CustomFieldsManager) SetField(req *types.SetField) soap.HasFault {
body := &methods.SetFieldBody{}
entity := Map.Get(req.Entity).(mo.Entity).Entity()
entity.CustomValue = append(entity.CustomValue, &types.CustomFieldStringValue{
CustomFieldValue: types.CustomFieldValue{Key: req.Key},
Value: req.Value,
})
body.Res = &types.SetFieldResponse{}
return body
}

View File

@@ -0,0 +1,76 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"strings"
"github.com/vmware/govmomi/simulator/esx"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
// Create Datacenter Folders.
// Every Datacenter has 4 inventory Folders: Vm, Host, Datastore and Network.
// The ESX folder child types are limited to 1 type.
// The VC folders have additional child types, including nested folders.
func createDatacenterFolders(dc *mo.Datacenter, isVC bool) {
folders := []struct {
ref *types.ManagedObjectReference
name string
types []string
}{
{&dc.VmFolder, "vm", []string{"VirtualMachine", "VirtualApp", "Folder"}},
{&dc.HostFolder, "host", []string{"ComputeResource", "Folder"}},
{&dc.DatastoreFolder, "datastore", []string{"Datastore", "StoragePod", "Folder"}},
{&dc.NetworkFolder, "network", []string{"Network", "DistributedVirtualSwitch", "Folder"}},
}
for _, f := range folders {
folder := &Folder{}
folder.Name = f.name
if isVC {
folder.ChildType = f.types
e := Map.PutEntity(dc, folder)
// propagate the generated morefs to Datacenter
ref := e.Reference()
f.ref.Type = ref.Type
f.ref.Value = ref.Value
} else {
folder.ChildType = f.types[:1]
folder.Self = *f.ref
Map.PutEntity(dc, folder)
}
}
net := Map.Get(dc.NetworkFolder).(*Folder)
for _, ref := range esx.Datacenter.Network {
// Add VM Network by default to each Datacenter
network := &mo.Network{}
network.Self = ref
network.Name = strings.Split(ref.Value, "-")[1]
network.Entity().Name = network.Name
if isVC {
network.Self.Value = "" // we want a different moid per-DC
}
net.putChild(network)
}
}

View File

@@ -0,0 +1,59 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"time"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type Datastore struct {
mo.Datastore
}
func parseDatastorePath(dsPath string) (*object.DatastorePath, types.BaseMethodFault) {
var p object.DatastorePath
if p.FromString(dsPath) {
return &p, nil
}
return nil, &types.InvalidDatastorePath{DatastorePath: dsPath}
}
func (ds *Datastore) RefreshDatastore(*types.RefreshDatastore) soap.HasFault {
r := &methods.RefreshDatastoreBody{}
err := ds.stat()
if err != nil {
r.Fault_ = Fault(err.Error(), &types.HostConfigFault{})
return r
}
info := ds.Info.GetDatastoreInfo()
now := time.Now()
info.Timestamp = &now
return r
}

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

@@ -0,0 +1,22 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Package simulator is a mock framework for the vSphere API.
See also: https://github.com/vmware/govmomi/blob/master/vcsim/README.md
*/
package simulator

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

@@ -0,0 +1,187 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type DistributedVirtualSwitch struct {
mo.DistributedVirtualSwitch
}
func (s *DistributedVirtualSwitch) AddDVPortgroupTask(c *types.AddDVPortgroup_Task) soap.HasFault {
task := CreateTask(s, "addDVPortgroup", func(t *Task) (types.AnyType, types.BaseMethodFault) {
f := Map.getEntityParent(s, "Folder").(*Folder)
for _, spec := range c.Spec {
pg := &DistributedVirtualPortgroup{}
pg.Name = spec.Name
pg.Entity().Name = pg.Name
if obj := Map.FindByName(pg.Name, f.ChildEntity); obj != nil {
return nil, &types.DuplicateName{
Name: pg.Name,
Object: obj.Reference(),
}
}
f.putChild(pg)
pg.Key = pg.Self.Value
pg.Config = types.DVPortgroupConfigInfo{
Key: pg.Key,
Name: pg.Name,
NumPorts: spec.NumPorts,
DistributedVirtualSwitch: &s.Self,
DefaultPortConfig: spec.DefaultPortConfig,
Description: spec.Description,
Type: spec.Type,
Policy: spec.Policy,
PortNameFormat: spec.PortNameFormat,
Scope: spec.Scope,
VendorSpecificConfig: spec.VendorSpecificConfig,
ConfigVersion: spec.ConfigVersion,
AutoExpand: spec.AutoExpand,
VmVnicNetworkResourcePoolKey: spec.VmVnicNetworkResourcePoolKey,
}
s.Portgroup = append(s.Portgroup, pg.Self)
s.Summary.PortgroupName = append(s.Summary.PortgroupName, pg.Name)
for _, h := range s.Summary.HostMember {
pg.Host = AddReference(h, pg.Host)
host := Map.Get(h).(*HostSystem)
host.Network = append(host.Network, pg.Reference())
}
}
return nil, nil
})
return &methods.AddDVPortgroup_TaskBody{
Res: &types.AddDVPortgroup_TaskResponse{
Returnval: task.Run(),
},
}
}
func (s *DistributedVirtualSwitch) ReconfigureDvsTask(req *types.ReconfigureDvs_Task) soap.HasFault {
task := CreateTask(s, "reconfigureDvs", func(t *Task) (types.AnyType, types.BaseMethodFault) {
spec := req.Spec.GetDVSConfigSpec()
for _, member := range spec.Host {
h := Map.Get(member.Host)
if h == nil {
return nil, &types.ManagedObjectNotFound{Obj: member.Host}
}
host := h.(*HostSystem)
switch types.ConfigSpecOperation(member.Operation) {
case types.ConfigSpecOperationAdd:
if FindReference(host.Network, s.Self) != nil {
return nil, &types.AlreadyExists{Name: host.Name}
}
host.Network = append(host.Network, s.Self)
host.Network = append(host.Network, s.Portgroup...)
s.Summary.HostMember = append(s.Summary.HostMember, member.Host)
for _, ref := range s.Portgroup {
pg := Map.Get(ref).(*DistributedVirtualPortgroup)
pg.Host = AddReference(member.Host, pg.Host)
}
case types.ConfigSpecOperationRemove:
if pg := FindReference(host.Network, s.Portgroup...); pg != nil {
return nil, &types.ResourceInUse{
Type: pg.Type,
Name: pg.Value,
}
}
host.Network = RemoveReference(s.Self, host.Network)
s.Summary.HostMember = RemoveReference(s.Self, s.Summary.HostMember)
case types.ConfigSpecOperationEdit:
return nil, &types.NotSupported{}
}
}
return nil, nil
})
return &methods.ReconfigureDvs_TaskBody{
Res: &types.ReconfigureDvs_TaskResponse{
Returnval: task.Run(),
},
}
}
func (s *DistributedVirtualSwitch) FetchDVPorts(req *types.FetchDVPorts) soap.HasFault {
body := &methods.FetchDVPortsBody{}
body.Res = &types.FetchDVPortsResponse{
Returnval: s.dvPortgroups(req.Criteria),
}
return body
}
func (s *DistributedVirtualSwitch) DestroyTask(req *types.Destroy_Task) soap.HasFault {
task := CreateTask(s, "destroy", func(t *Task) (types.AnyType, types.BaseMethodFault) {
f := Map.getEntityParent(s, "Folder").(*Folder)
f.removeChild(s.Reference())
return nil, nil
})
return &methods.Destroy_TaskBody{
Res: &types.Destroy_TaskResponse{
Returnval: task.Run(),
},
}
}
func (s *DistributedVirtualSwitch) dvPortgroups(_ *types.DistributedVirtualSwitchPortCriteria) []types.DistributedVirtualPort {
// TODO(agui): Filter is not implemented yet
var res []types.DistributedVirtualPort
for _, ref := range s.Portgroup {
pg := Map.Get(ref).(*DistributedVirtualPortgroup)
res = append(res, types.DistributedVirtualPort{
DvsUuid: s.Uuid,
Key: pg.Key,
Config: types.DVPortConfigInfo{
Setting: pg.Config.DefaultPortConfig,
},
})
if pg.PortKeys == nil {
continue
}
for _, key := range pg.PortKeys {
res = append(res, types.DistributedVirtualPort{
DvsUuid: s.Uuid,
Key: key,
Config: types.DVPortConfigInfo{
Setting: pg.Config.DefaultPortConfig,
},
})
}
}
return res
}

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

@@ -0,0 +1,46 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
func RenameTask(e mo.Entity, r *types.Rename_Task) soap.HasFault {
task := CreateTask(e, "rename", func(t *Task) (types.AnyType, types.BaseMethodFault) {
obj := Map.Get(r.This).(mo.Entity).Entity()
if parent, ok := Map.Get(*obj.Parent).(*Folder); ok {
if Map.FindByName(r.NewName, parent.ChildEntity) != nil {
return nil, &types.InvalidArgument{InvalidProperty: "name"}
}
}
obj.Name = r.NewName
return nil, nil
})
return &methods.Rename_TaskBody{
Res: &types.Rename_TaskResponse{
Returnval: task.Run(),
},
}
}

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

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

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,60 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package esx
import (
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
// Datacenter is the default template for Datacenter properties.
// Capture method:
// govc datacenter.info -dump
var Datacenter = mo.Datacenter{
ManagedEntity: mo.ManagedEntity{
ExtensibleManagedObject: mo.ExtensibleManagedObject{
Self: types.ManagedObjectReference{Type: "Datacenter", Value: "ha-datacenter"},
Value: nil,
AvailableField: nil,
},
Parent: (*types.ManagedObjectReference)(nil),
CustomValue: nil,
OverallStatus: "",
ConfigStatus: "",
ConfigIssue: nil,
EffectiveRole: nil,
Permission: nil,
Name: "ha-datacenter",
DisabledMethod: nil,
RecentTask: nil,
DeclaredAlarmState: nil,
TriggeredAlarmState: nil,
AlarmActionsEnabled: (*bool)(nil),
Tag: nil,
},
VmFolder: types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-vm"},
HostFolder: types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-host"},
DatastoreFolder: types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-datastore"},
NetworkFolder: types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-network"},
Datastore: []types.ManagedObjectReference{
{Type: "Datastore", Value: "57089c25-85e3ccd4-17b6-000c29d0beb3"},
},
Network: []types.ManagedObjectReference{
{Type: "Network", Value: "HaNetwork-VM Network"},
},
Configuration: types.DatacenterConfigInfo{},
}

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

@@ -0,0 +1,20 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Package esx contains SOAP responses from an ESX server, captured using `govc ... -dump`.
*/
package esx

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,864 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package esx
import (
"time"
"github.com/vmware/govmomi/vim25/types"
)
// HostHardwareInfo is the default template for the HostSystem hardware property.
// Capture method:
// govc object.collect -s -dump HostSystem:ha-host hardware
var HostHardwareInfo = &types.HostHardwareInfo{
SystemInfo: types.HostSystemInfo{
Vendor: "VMware, Inc.",
Model: "VMware Virtual Platform",
Uuid: "e88d4d56-9f1e-3ea1-71fa-13a8e1a7fd70",
OtherIdentifyingInfo: []types.HostSystemIdentificationInfo{
{
IdentifierValue: " No Asset Tag",
IdentifierType: &types.ElementDescription{
Description: types.Description{
Label: "Asset Tag",
Summary: "Asset tag of the system",
},
Key: "AssetTag",
},
},
{
IdentifierValue: "[MS_VM_CERT/SHA1/27d66596a61c48dd3dc7216fd715126e33f59ae7]",
IdentifierType: &types.ElementDescription{
Description: types.Description{
Label: "OEM specific string",
Summary: "OEM specific string",
},
Key: "OemSpecificString",
},
},
{
IdentifierValue: "Welcome to the Virtual Machine",
IdentifierType: &types.ElementDescription{
Description: types.Description{
Label: "OEM specific string",
Summary: "OEM specific string",
},
Key: "OemSpecificString",
},
},
{
IdentifierValue: "VMware-56 4d 8d e8 1e 9f a1 3e-71 fa 13 a8 e1 a7 fd 70",
IdentifierType: &types.ElementDescription{
Description: types.Description{
Label: "Service tag",
Summary: "Service tag of the system",
},
Key: "ServiceTag",
},
},
},
},
CpuPowerManagementInfo: &types.HostCpuPowerManagementInfo{
CurrentPolicy: "Balanced",
HardwareSupport: "",
},
CpuInfo: types.HostCpuInfo{
NumCpuPackages: 2,
NumCpuCores: 2,
NumCpuThreads: 2,
Hz: 3591345000,
},
CpuPkg: []types.HostCpuPackage{
{
Index: 0,
Vendor: "intel",
Hz: 3591345000,
BusHz: 115849838,
Description: "Intel(R) Xeon(R) CPU E5-1620 0 @ 3.60GHz",
ThreadId: []int16{0},
CpuFeature: []types.HostCpuIdInfo{
{
Level: 0,
Vendor: "",
Eax: "0000:0000:0000:0000:0000:0000:0000:1101",
Ebx: "0111:0101:0110:1110:0110:0101:0100:0111",
Ecx: "0110:1100:0110:0101:0111:0100:0110:1110",
Edx: "0100:1001:0110:0101:0110:1110:0110:1001",
},
{
Level: 1,
Vendor: "",
Eax: "0000:0000:0000:0010:0000:0110:1101:0111",
Ebx: "0000:0000:0000:0001:0000:1000:0000:0000",
Ecx: "1001:0111:1011:1010:0010:0010:0010:1011",
Edx: "0000:1111:1010:1011:1111:1011:1111:1111",
},
{
Level: -2147483648,
Vendor: "",
Eax: "1000:0000:0000:0000:0000:0000:0000:1000",
Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
Ecx: "0000:0000:0000:0000:0000:0000:0000:0000",
Edx: "0000:0000:0000:0000:0000:0000:0000:0000",
},
{
Level: -2147483647,
Vendor: "",
Eax: "0000:0000:0000:0000:0000:0000:0000:0000",
Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
Ecx: "0000:0000:0000:0000:0000:0000:0000:0001",
Edx: "0010:1000:0001:0000:0000:1000:0000:0000",
},
{
Level: -2147483640,
Vendor: "",
Eax: "0000:0000:0000:0000:0011:0000:0010:1010",
Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
Ecx: "0000:0000:0000:0000:0000:0000:0000:0000",
Edx: "0000:0000:0000:0000:0000:0000:0000:0000",
},
},
},
{
Index: 1,
Vendor: "intel",
Hz: 3591345000,
BusHz: 115849838,
Description: "Intel(R) Xeon(R) CPU E5-1620 0 @ 3.60GHz",
ThreadId: []int16{1},
CpuFeature: []types.HostCpuIdInfo{
{
Level: 0,
Vendor: "",
Eax: "0000:0000:0000:0000:0000:0000:0000:1101",
Ebx: "0111:0101:0110:1110:0110:0101:0100:0111",
Ecx: "0110:1100:0110:0101:0111:0100:0110:1110",
Edx: "0100:1001:0110:0101:0110:1110:0110:1001",
},
{
Level: 1,
Vendor: "",
Eax: "0000:0000:0000:0010:0000:0110:1101:0111",
Ebx: "0000:0010:0000:0001:0000:1000:0000:0000",
Ecx: "1001:0111:1011:1010:0010:0010:0010:1011",
Edx: "0000:1111:1010:1011:1111:1011:1111:1111",
},
{
Level: -2147483648,
Vendor: "",
Eax: "1000:0000:0000:0000:0000:0000:0000:1000",
Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
Ecx: "0000:0000:0000:0000:0000:0000:0000:0000",
Edx: "0000:0000:0000:0000:0000:0000:0000:0000",
},
{
Level: -2147483647,
Vendor: "",
Eax: "0000:0000:0000:0000:0000:0000:0000:0000",
Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
Ecx: "0000:0000:0000:0000:0000:0000:0000:0001",
Edx: "0010:1000:0001:0000:0000:1000:0000:0000",
},
{
Level: -2147483640,
Vendor: "",
Eax: "0000:0000:0000:0000:0011:0000:0010:1010",
Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
Ecx: "0000:0000:0000:0000:0000:0000:0000:0000",
Edx: "0000:0000:0000:0000:0000:0000:0000:0000",
},
},
},
},
MemorySize: 4294430720,
NumaInfo: &types.HostNumaInfo{
Type: "NUMA",
NumNodes: 1,
NumaNode: []types.HostNumaNode{
{
TypeId: 0x0,
CpuID: []int16{1, 0},
MemoryRangeBegin: 4294967296,
MemoryRangeLength: 1073741824,
},
},
},
SmcPresent: types.NewBool(false),
PciDevice: []types.HostPciDevice{
{
Id: "0000:00:00.0",
ClassId: 1536,
Bus: 0x0,
Slot: 0x0,
Function: 0x0,
VendorId: -32634,
SubVendorId: 5549,
VendorName: "Intel Corporation",
DeviceId: 29072,
SubDeviceId: 6518,
ParentBridge: "",
DeviceName: "Virtual Machine Chipset",
},
{
Id: "0000:00:01.0",
ClassId: 1540,
Bus: 0x0,
Slot: 0x1,
Function: 0x0,
VendorId: -32634,
SubVendorId: 0,
VendorName: "Intel Corporation",
DeviceId: 29073,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "440BX/ZX/DX - 82443BX/ZX/DX AGP bridge",
},
{
Id: "0000:00:07.0",
ClassId: 1537,
Bus: 0x0,
Slot: 0x7,
Function: 0x0,
VendorId: -32634,
SubVendorId: 5549,
VendorName: "Intel Corporation",
DeviceId: 28944,
SubDeviceId: 6518,
ParentBridge: "",
DeviceName: "Virtual Machine Chipset",
},
{
Id: "0000:00:07.1",
ClassId: 257,
Bus: 0x0,
Slot: 0x7,
Function: 0x1,
VendorId: -32634,
SubVendorId: 5549,
VendorName: "Intel Corporation",
DeviceId: 28945,
SubDeviceId: 6518,
ParentBridge: "",
DeviceName: "PIIX4 for 430TX/440BX/MX IDE Controller",
},
{
Id: "0000:00:07.3",
ClassId: 1664,
Bus: 0x0,
Slot: 0x7,
Function: 0x3,
VendorId: -32634,
SubVendorId: 5549,
VendorName: "Intel Corporation",
DeviceId: 28947,
SubDeviceId: 6518,
ParentBridge: "",
DeviceName: "Virtual Machine Chipset",
},
{
Id: "0000:00:07.7",
ClassId: 2176,
Bus: 0x0,
Slot: 0x7,
Function: 0x7,
VendorId: 5549,
SubVendorId: 5549,
VendorName: "VMware",
DeviceId: 1856,
SubDeviceId: 1856,
ParentBridge: "",
DeviceName: "Virtual Machine Communication Interface",
},
{
Id: "0000:00:0f.0",
ClassId: 768,
Bus: 0x0,
Slot: 0xf,
Function: 0x0,
VendorId: 5549,
SubVendorId: 5549,
VendorName: "VMware",
DeviceId: 1029,
SubDeviceId: 1029,
ParentBridge: "",
DeviceName: "SVGA II Adapter",
},
{
Id: "0000:00:11.0",
ClassId: 1540,
Bus: 0x0,
Slot: 0x11,
Function: 0x0,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1936,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI bridge",
},
{
Id: "0000:00:15.0",
ClassId: 1540,
Bus: 0x0,
Slot: 0x15,
Function: 0x0,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:15.1",
ClassId: 1540,
Bus: 0x0,
Slot: 0x15,
Function: 0x1,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:15.2",
ClassId: 1540,
Bus: 0x0,
Slot: 0x15,
Function: 0x2,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:15.3",
ClassId: 1540,
Bus: 0x0,
Slot: 0x15,
Function: 0x3,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:15.4",
ClassId: 1540,
Bus: 0x0,
Slot: 0x15,
Function: 0x4,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:15.5",
ClassId: 1540,
Bus: 0x0,
Slot: 0x15,
Function: 0x5,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:15.6",
ClassId: 1540,
Bus: 0x0,
Slot: 0x15,
Function: 0x6,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:15.7",
ClassId: 1540,
Bus: 0x0,
Slot: 0x15,
Function: 0x7,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:16.0",
ClassId: 1540,
Bus: 0x0,
Slot: 0x16,
Function: 0x0,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:16.1",
ClassId: 1540,
Bus: 0x0,
Slot: 0x16,
Function: 0x1,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:16.2",
ClassId: 1540,
Bus: 0x0,
Slot: 0x16,
Function: 0x2,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:16.3",
ClassId: 1540,
Bus: 0x0,
Slot: 0x16,
Function: 0x3,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:16.4",
ClassId: 1540,
Bus: 0x0,
Slot: 0x16,
Function: 0x4,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:16.5",
ClassId: 1540,
Bus: 0x0,
Slot: 0x16,
Function: 0x5,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:16.6",
ClassId: 1540,
Bus: 0x0,
Slot: 0x16,
Function: 0x6,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:16.7",
ClassId: 1540,
Bus: 0x0,
Slot: 0x16,
Function: 0x7,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:17.0",
ClassId: 1540,
Bus: 0x0,
Slot: 0x17,
Function: 0x0,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:17.1",
ClassId: 1540,
Bus: 0x0,
Slot: 0x17,
Function: 0x1,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:17.2",
ClassId: 1540,
Bus: 0x0,
Slot: 0x17,
Function: 0x2,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:17.3",
ClassId: 1540,
Bus: 0x0,
Slot: 0x17,
Function: 0x3,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:17.4",
ClassId: 1540,
Bus: 0x0,
Slot: 0x17,
Function: 0x4,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:17.5",
ClassId: 1540,
Bus: 0x0,
Slot: 0x17,
Function: 0x5,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:17.6",
ClassId: 1540,
Bus: 0x0,
Slot: 0x17,
Function: 0x6,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:17.7",
ClassId: 1540,
Bus: 0x0,
Slot: 0x17,
Function: 0x7,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:18.0",
ClassId: 1540,
Bus: 0x0,
Slot: 0x18,
Function: 0x0,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:18.1",
ClassId: 1540,
Bus: 0x0,
Slot: 0x18,
Function: 0x1,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:18.2",
ClassId: 1540,
Bus: 0x0,
Slot: 0x18,
Function: 0x2,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:18.3",
ClassId: 1540,
Bus: 0x0,
Slot: 0x18,
Function: 0x3,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:18.4",
ClassId: 1540,
Bus: 0x0,
Slot: 0x18,
Function: 0x4,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:18.5",
ClassId: 1540,
Bus: 0x0,
Slot: 0x18,
Function: 0x5,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:18.6",
ClassId: 1540,
Bus: 0x0,
Slot: 0x18,
Function: 0x6,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:00:18.7",
ClassId: 1540,
Bus: 0x0,
Slot: 0x18,
Function: 0x7,
VendorId: 5549,
SubVendorId: 0,
VendorName: "VMware",
DeviceId: 1952,
SubDeviceId: 0,
ParentBridge: "",
DeviceName: "PCI Express Root Port",
},
{
Id: "0000:03:00.0",
ClassId: 263,
Bus: 0x3,
Slot: 0x0,
Function: 0x0,
VendorId: 5549,
SubVendorId: 5549,
VendorName: "VMware",
DeviceId: 1984,
SubDeviceId: 1984,
ParentBridge: "0000:00:15.0",
DeviceName: "PVSCSI SCSI Controller",
},
{
Id: "0000:0b:00.0",
ClassId: 512,
Bus: 0xb,
Slot: 0x0,
Function: 0x0,
VendorId: 5549,
SubVendorId: 5549,
VendorName: "VMware Inc.",
DeviceId: 1968,
SubDeviceId: 1968,
ParentBridge: "0000:00:16.0",
DeviceName: "vmxnet3 Virtual Ethernet Controller",
},
{
Id: "0000:13:00.0",
ClassId: 512,
Bus: 0x13,
Slot: 0x0,
Function: 0x0,
VendorId: 5549,
SubVendorId: 5549,
VendorName: "VMware Inc.",
DeviceId: 1968,
SubDeviceId: 1968,
ParentBridge: "0000:00:17.0",
DeviceName: "vmxnet3 Virtual Ethernet Controller",
},
},
CpuFeature: []types.HostCpuIdInfo{
{
Level: 0,
Vendor: "",
Eax: "0000:0000:0000:0000:0000:0000:0000:1101",
Ebx: "0111:0101:0110:1110:0110:0101:0100:0111",
Ecx: "0110:1100:0110:0101:0111:0100:0110:1110",
Edx: "0100:1001:0110:0101:0110:1110:0110:1001",
},
{
Level: 1,
Vendor: "",
Eax: "0000:0000:0000:0010:0000:0110:1101:0111",
Ebx: "0000:0000:0000:0001:0000:1000:0000:0000",
Ecx: "1001:0111:1011:1010:0010:0010:0010:1011",
Edx: "0000:1111:1010:1011:1111:1011:1111:1111",
},
{
Level: -2147483648,
Vendor: "",
Eax: "1000:0000:0000:0000:0000:0000:0000:1000",
Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
Ecx: "0000:0000:0000:0000:0000:0000:0000:0000",
Edx: "0000:0000:0000:0000:0000:0000:0000:0000",
},
{
Level: -2147483647,
Vendor: "",
Eax: "0000:0000:0000:0000:0000:0000:0000:0000",
Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
Ecx: "0000:0000:0000:0000:0000:0000:0000:0001",
Edx: "0010:1000:0001:0000:0000:1000:0000:0000",
},
{
Level: -2147483640,
Vendor: "",
Eax: "0000:0000:0000:0000:0011:0000:0010:1010",
Ebx: "0000:0000:0000:0000:0000:0000:0000:0000",
Ecx: "0000:0000:0000:0000:0000:0000:0000:0000",
Edx: "0000:0000:0000:0000:0000:0000:0000:0000",
},
},
BiosInfo: &types.HostBIOSInfo{
BiosVersion: "6.00",
ReleaseDate: nil,
Vendor: "",
MajorRelease: 0,
MinorRelease: 0,
FirmwareMajorRelease: 0,
FirmwareMinorRelease: 0,
},
ReliableMemoryInfo: &types.HostReliableMemoryInfo{},
}
func init() {
date, _ := time.Parse("2006-01-02", "2015-07-02")
HostHardwareInfo.BiosInfo.ReleaseDate = &date
}

View File

@@ -0,0 +1,346 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package esx
import "github.com/vmware/govmomi/vim25/types"
// HostStorageDeviceInfo is the default template for the HostSystem config.storageDevice property.
// Capture method:
// govc object.collect -s -dump HostSystem:ha-host config.storageDevice
var HostStorageDeviceInfo = types.HostStorageDeviceInfo{
HostBusAdapter: []types.BaseHostHostBusAdapter{
&types.HostParallelScsiHba{
HostHostBusAdapter: types.HostHostBusAdapter{
Key: "key-vim.host.ParallelScsiHba-vmhba0",
Device: "vmhba0",
Bus: 3,
Status: "unknown",
Model: "PVSCSI SCSI Controller",
Driver: "pvscsi",
Pci: "0000:03:00.0",
},
},
&types.HostBlockHba{
HostHostBusAdapter: types.HostHostBusAdapter{
Key: "key-vim.host.BlockHba-vmhba1",
Device: "vmhba1",
Bus: 0,
Status: "unknown",
Model: "PIIX4 for 430TX/440BX/MX IDE Controller",
Driver: "vmkata",
Pci: "0000:00:07.1",
},
},
&types.HostBlockHba{
HostHostBusAdapter: types.HostHostBusAdapter{
Key: "key-vim.host.BlockHba-vmhba64",
Device: "vmhba64",
Bus: 0,
Status: "unknown",
Model: "PIIX4 for 430TX/440BX/MX IDE Controller",
Driver: "vmkata",
Pci: "0000:00:07.1",
},
},
},
ScsiLun: []types.BaseScsiLun{
&types.ScsiLun{
HostDevice: types.HostDevice{
DeviceName: "/vmfs/devices/cdrom/mpx.vmhba1:C0:T0:L0",
DeviceType: "cdrom",
},
Key: "key-vim.host.ScsiLun-0005000000766d686261313a303a30",
Uuid: "0005000000766d686261313a303a30",
Descriptor: []types.ScsiLunDescriptor{
{
Quality: "lowQuality",
Id: "mpx.vmhba1:C0:T0:L0",
},
{
Quality: "lowQuality",
Id: "vml.0005000000766d686261313a303a30",
},
{
Quality: "lowQuality",
Id: "0005000000766d686261313a303a30",
},
},
CanonicalName: "mpx.vmhba1:C0:T0:L0",
DisplayName: "Local NECVMWar CD-ROM (mpx.vmhba1:C0:T0:L0)",
LunType: "cdrom",
Vendor: "NECVMWar",
Model: "VMware IDE CDR00",
Revision: "1.00",
ScsiLevel: 5,
SerialNumber: "unavailable",
DurableName: (*types.ScsiLunDurableName)(nil),
AlternateName: []types.ScsiLunDurableName{
{
Namespace: "GENERIC_VPD",
NamespaceId: 0x5,
Data: []uint8{0x2d, 0x37, 0x39},
},
{
Namespace: "GENERIC_VPD",
NamespaceId: 0x5,
Data: []uint8{0x30},
},
},
StandardInquiry: []uint8{0x30},
QueueDepth: 0,
OperationalState: []string{"ok"},
Capabilities: &types.ScsiLunCapabilities{},
VStorageSupport: "vStorageUnsupported",
ProtocolEndpoint: types.NewBool(false),
},
&types.HostScsiDisk{
ScsiLun: types.ScsiLun{
HostDevice: types.HostDevice{
DeviceName: "/vmfs/devices/disks/mpx.vmhba0:C0:T0:L0",
DeviceType: "disk",
},
Key: "key-vim.host.ScsiDisk-0000000000766d686261303a303a30",
Uuid: "0000000000766d686261303a303a30",
Descriptor: []types.ScsiLunDescriptor{
{
Quality: "lowQuality",
Id: "mpx.vmhba0:C0:T0:L0",
},
{
Quality: "lowQuality",
Id: "vml.0000000000766d686261303a303a30",
},
{
Quality: "lowQuality",
Id: "0000000000766d686261303a303a30",
},
},
CanonicalName: "mpx.vmhba0:C0:T0:L0",
DisplayName: "Local VMware, Disk (mpx.vmhba0:C0:T0:L0)",
LunType: "disk",
Vendor: "VMware, ",
Model: "VMware Virtual S",
Revision: "1.0 ",
ScsiLevel: 2,
SerialNumber: "unavailable",
DurableName: (*types.ScsiLunDurableName)(nil),
AlternateName: []types.ScsiLunDurableName{
{
Namespace: "GENERIC_VPD",
NamespaceId: 0x5,
Data: []uint8{0x2d, 0x37, 0x39},
},
{
Namespace: "GENERIC_VPD",
NamespaceId: 0x5,
Data: []uint8{0x30},
},
},
StandardInquiry: []uint8{0x30},
QueueDepth: 1024,
OperationalState: []string{"ok"},
Capabilities: &types.ScsiLunCapabilities{},
VStorageSupport: "vStorageUnsupported",
ProtocolEndpoint: types.NewBool(false),
},
Capacity: types.HostDiskDimensionsLba{
BlockSize: 512,
Block: 67108864,
},
DevicePath: "/vmfs/devices/disks/mpx.vmhba0:C0:T0:L0",
Ssd: types.NewBool(true),
LocalDisk: types.NewBool(true),
PhysicalLocation: nil,
EmulatedDIXDIFEnabled: types.NewBool(false),
VsanDiskInfo: (*types.VsanHostVsanDiskInfo)(nil),
ScsiDiskType: "native512",
},
},
ScsiTopology: &types.HostScsiTopology{
Adapter: []types.HostScsiTopologyInterface{
{
Key: "key-vim.host.ScsiTopology.Interface-vmhba0",
Adapter: "key-vim.host.ParallelScsiHba-vmhba0",
Target: []types.HostScsiTopologyTarget{
{
Key: "key-vim.host.ScsiTopology.Target-vmhba0:0:0",
Target: 0,
Lun: []types.HostScsiTopologyLun{
{
Key: "key-vim.host.ScsiTopology.Lun-0000000000766d686261303a303a30",
Lun: 0,
ScsiLun: "key-vim.host.ScsiDisk-0000000000766d686261303a303a30",
},
},
Transport: &types.HostParallelScsiTargetTransport{},
},
},
},
{
Key: "key-vim.host.ScsiTopology.Interface-vmhba1",
Adapter: "key-vim.host.BlockHba-vmhba1",
Target: []types.HostScsiTopologyTarget{
{
Key: "key-vim.host.ScsiTopology.Target-vmhba1:0:0",
Target: 0,
Lun: []types.HostScsiTopologyLun{
{
Key: "key-vim.host.ScsiTopology.Lun-0005000000766d686261313a303a30",
Lun: 0,
ScsiLun: "key-vim.host.ScsiLun-0005000000766d686261313a303a30",
},
},
Transport: &types.HostBlockAdapterTargetTransport{},
},
},
},
{
Key: "key-vim.host.ScsiTopology.Interface-vmhba64",
Adapter: "key-vim.host.BlockHba-vmhba64",
Target: nil,
},
},
},
MultipathInfo: &types.HostMultipathInfo{
Lun: []types.HostMultipathInfoLogicalUnit{
{
Key: "key-vim.host.MultipathInfo.LogicalUnit-0005000000766d686261313a303a30",
Id: "0005000000766d686261313a303a30",
Lun: "key-vim.host.ScsiLun-0005000000766d686261313a303a30",
Path: []types.HostMultipathInfoPath{
{
Key: "key-vim.host.MultipathInfo.Path-vmhba1:C0:T0:L0",
Name: "vmhba1:C0:T0:L0",
PathState: "active",
State: "active",
IsWorkingPath: types.NewBool(true),
Adapter: "key-vim.host.BlockHba-vmhba1",
Lun: "key-vim.host.MultipathInfo.LogicalUnit-0005000000766d686261313a303a30",
Transport: &types.HostBlockAdapterTargetTransport{},
},
},
Policy: &types.HostMultipathInfoFixedLogicalUnitPolicy{
HostMultipathInfoLogicalUnitPolicy: types.HostMultipathInfoLogicalUnitPolicy{
Policy: "VMW_PSP_FIXED",
},
Prefer: "vmhba1:C0:T0:L0",
},
StorageArrayTypePolicy: &types.HostMultipathInfoLogicalUnitStorageArrayTypePolicy{
Policy: "VMW_SATP_LOCAL",
},
},
{
Key: "key-vim.host.MultipathInfo.LogicalUnit-0000000000766d686261303a303a30",
Id: "0000000000766d686261303a303a30",
Lun: "key-vim.host.ScsiDisk-0000000000766d686261303a303a30",
Path: []types.HostMultipathInfoPath{
{
Key: "key-vim.host.MultipathInfo.Path-vmhba0:C0:T0:L0",
Name: "vmhba0:C0:T0:L0",
PathState: "active",
State: "active",
IsWorkingPath: types.NewBool(true),
Adapter: "key-vim.host.ParallelScsiHba-vmhba0",
Lun: "key-vim.host.MultipathInfo.LogicalUnit-0000000000766d686261303a303a30",
Transport: &types.HostParallelScsiTargetTransport{},
},
},
Policy: &types.HostMultipathInfoFixedLogicalUnitPolicy{
HostMultipathInfoLogicalUnitPolicy: types.HostMultipathInfoLogicalUnitPolicy{
Policy: "VMW_PSP_FIXED",
},
Prefer: "vmhba0:C0:T0:L0",
},
StorageArrayTypePolicy: &types.HostMultipathInfoLogicalUnitStorageArrayTypePolicy{
Policy: "VMW_SATP_LOCAL",
},
},
},
},
PlugStoreTopology: &types.HostPlugStoreTopology{
Adapter: []types.HostPlugStoreTopologyAdapter{
{
Key: "key-vim.host.PlugStoreTopology.Adapter-vmhba0",
Adapter: "key-vim.host.ParallelScsiHba-vmhba0",
Path: []string{"key-vim.host.PlugStoreTopology.Path-vmhba0:C0:T0:L0"},
},
{
Key: "key-vim.host.PlugStoreTopology.Adapter-vmhba1",
Adapter: "key-vim.host.BlockHba-vmhba1",
Path: []string{"key-vim.host.PlugStoreTopology.Path-vmhba1:C0:T0:L0"},
},
{
Key: "key-vim.host.PlugStoreTopology.Adapter-vmhba64",
Adapter: "key-vim.host.BlockHba-vmhba64",
Path: nil,
},
},
Path: []types.HostPlugStoreTopologyPath{
{
Key: "key-vim.host.PlugStoreTopology.Path-vmhba0:C0:T0:L0",
Name: "vmhba0:C0:T0:L0",
ChannelNumber: 0,
TargetNumber: 0,
LunNumber: 0,
Adapter: "key-vim.host.PlugStoreTopology.Adapter-vmhba0",
Target: "key-vim.host.PlugStoreTopology.Target-pscsi.0:0",
Device: "key-vim.host.PlugStoreTopology.Device-0000000000766d686261303a303a30",
},
{
Key: "key-vim.host.PlugStoreTopology.Path-vmhba1:C0:T0:L0",
Name: "vmhba1:C0:T0:L0",
ChannelNumber: 0,
TargetNumber: 0,
LunNumber: 0,
Adapter: "key-vim.host.PlugStoreTopology.Adapter-vmhba1",
Target: "key-vim.host.PlugStoreTopology.Target-ide.0:0",
Device: "key-vim.host.PlugStoreTopology.Device-0005000000766d686261313a303a30",
},
},
Target: []types.HostPlugStoreTopologyTarget{
{
Key: "key-vim.host.PlugStoreTopology.Target-pscsi.0:0",
Transport: &types.HostParallelScsiTargetTransport{},
},
{
Key: "key-vim.host.PlugStoreTopology.Target-ide.0:0",
Transport: &types.HostBlockAdapterTargetTransport{},
},
},
Device: []types.HostPlugStoreTopologyDevice{
{
Key: "key-vim.host.PlugStoreTopology.Device-0005000000766d686261313a303a30",
Lun: "key-vim.host.ScsiLun-0005000000766d686261313a303a30",
Path: []string{"key-vim.host.PlugStoreTopology.Path-vmhba1:C0:T0:L0"},
},
{
Key: "key-vim.host.PlugStoreTopology.Device-0000000000766d686261303a303a30",
Lun: "key-vim.host.ScsiDisk-0000000000766d686261303a303a30",
Path: []string{"key-vim.host.PlugStoreTopology.Path-vmhba0:C0:T0:L0"},
},
},
Plugin: []types.HostPlugStoreTopologyPlugin{
{
Key: "key-vim.host.PlugStoreTopology.Plugin-NMP",
Name: "NMP",
Device: []string{"key-vim.host.PlugStoreTopology.Device-0005000000766d686261313a303a30", "key-vim.host.PlugStoreTopology.Device-0000000000766d686261303a303a30"},
ClaimedPath: []string{"key-vim.host.PlugStoreTopology.Path-vmhba0:C0:T0:L0", "key-vim.host.PlugStoreTopology.Path-vmhba1:C0:T0:L0"},
},
},
},
SoftwareInternetScsiEnabled: false,
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,165 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package esx
import (
"time"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
// ResourcePool is the default template for ResourcePool properties.
// Capture method:
// govc pool.info "*" -dump
var ResourcePool = mo.ResourcePool{
ManagedEntity: mo.ManagedEntity{
ExtensibleManagedObject: mo.ExtensibleManagedObject{
Self: types.ManagedObjectReference{Type: "ResourcePool", Value: "ha-root-pool"},
Value: nil,
AvailableField: nil,
},
Parent: &types.ManagedObjectReference{Type: "ComputeResource", Value: "ha-compute-res"},
CustomValue: nil,
OverallStatus: "green",
ConfigStatus: "green",
ConfigIssue: nil,
EffectiveRole: []int32{-1},
Permission: nil,
Name: "Resources",
DisabledMethod: []string{"CreateVApp", "CreateChildVM_Task"},
RecentTask: nil,
DeclaredAlarmState: nil,
TriggeredAlarmState: nil,
AlarmActionsEnabled: (*bool)(nil),
Tag: nil,
},
Summary: &types.ResourcePoolSummary{
DynamicData: types.DynamicData{},
Name: "Resources",
Config: types.ResourceConfigSpec{
DynamicData: types.DynamicData{},
Entity: &types.ManagedObjectReference{Type: "ResourcePool", Value: "ha-root-pool"},
ChangeVersion: "",
LastModified: (*time.Time)(nil),
CpuAllocation: types.ResourceAllocationInfo{
DynamicData: types.DynamicData{},
Reservation: types.NewInt64(4121),
ExpandableReservation: types.NewBool(false),
Limit: types.NewInt64(4121),
Shares: &types.SharesInfo{
DynamicData: types.DynamicData{},
Shares: 9000,
Level: "custom",
},
OverheadLimit: nil,
},
MemoryAllocation: types.ResourceAllocationInfo{
DynamicData: types.DynamicData{},
Reservation: types.NewInt64(961),
ExpandableReservation: types.NewBool(false),
Limit: types.NewInt64(961),
Shares: &types.SharesInfo{
DynamicData: types.DynamicData{},
Shares: 9000,
Level: "custom",
},
OverheadLimit: nil,
},
},
Runtime: types.ResourcePoolRuntimeInfo{
DynamicData: types.DynamicData{},
Memory: types.ResourcePoolResourceUsage{
DynamicData: types.DynamicData{},
ReservationUsed: 0,
ReservationUsedForVm: 0,
UnreservedForPool: 1007681536,
UnreservedForVm: 1007681536,
OverallUsage: 0,
MaxUsage: 1007681536,
},
Cpu: types.ResourcePoolResourceUsage{
DynamicData: types.DynamicData{},
ReservationUsed: 0,
ReservationUsedForVm: 0,
UnreservedForPool: 4121,
UnreservedForVm: 4121,
OverallUsage: 0,
MaxUsage: 4121,
},
OverallStatus: "green",
},
QuickStats: (*types.ResourcePoolQuickStats)(nil),
ConfiguredMemoryMB: 0,
},
Runtime: types.ResourcePoolRuntimeInfo{
DynamicData: types.DynamicData{},
Memory: types.ResourcePoolResourceUsage{
DynamicData: types.DynamicData{},
ReservationUsed: 0,
ReservationUsedForVm: 0,
UnreservedForPool: 1007681536,
UnreservedForVm: 1007681536,
OverallUsage: 0,
MaxUsage: 1007681536,
},
Cpu: types.ResourcePoolResourceUsage{
DynamicData: types.DynamicData{},
ReservationUsed: 0,
ReservationUsedForVm: 0,
UnreservedForPool: 4121,
UnreservedForVm: 4121,
OverallUsage: 0,
MaxUsage: 4121,
},
OverallStatus: "green",
},
Owner: types.ManagedObjectReference{Type: "ComputeResource", Value: "ha-compute-res"},
ResourcePool: nil,
Vm: nil,
Config: types.ResourceConfigSpec{
DynamicData: types.DynamicData{},
Entity: &types.ManagedObjectReference{Type: "ResourcePool", Value: "ha-root-pool"},
ChangeVersion: "",
LastModified: (*time.Time)(nil),
CpuAllocation: types.ResourceAllocationInfo{
DynamicData: types.DynamicData{},
Reservation: types.NewInt64(4121),
ExpandableReservation: types.NewBool(false),
Limit: types.NewInt64(4121),
Shares: &types.SharesInfo{
DynamicData: types.DynamicData{},
Shares: 9000,
Level: "custom",
},
OverheadLimit: nil,
},
MemoryAllocation: types.ResourceAllocationInfo{
DynamicData: types.DynamicData{},
Reservation: types.NewInt64(961),
ExpandableReservation: types.NewBool(false),
Limit: types.NewInt64(961),
Shares: &types.SharesInfo{
DynamicData: types.DynamicData{},
Shares: 9000,
Level: "custom",
},
OverheadLimit: nil,
},
},
ChildConfiguration: nil,
}

View File

@@ -0,0 +1,76 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package esx
import (
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
// RootFolder is the default template for the ServiceContent rootFolder property.
// Capture method:
// govc folder.info -dump /
var RootFolder = mo.Folder{
ManagedEntity: mo.ManagedEntity{
ExtensibleManagedObject: mo.ExtensibleManagedObject{
Self: types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-root"},
Value: nil,
AvailableField: nil,
},
Parent: (*types.ManagedObjectReference)(nil),
CustomValue: nil,
OverallStatus: "green",
ConfigStatus: "green",
ConfigIssue: nil,
EffectiveRole: []int32{-1},
Permission: []types.Permission{
{
DynamicData: types.DynamicData{},
Entity: &types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-root"},
Principal: "vpxuser",
Group: false,
RoleId: -1,
Propagate: true,
},
{
DynamicData: types.DynamicData{},
Entity: &types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-root"},
Principal: "dcui",
Group: false,
RoleId: -1,
Propagate: true,
},
{
DynamicData: types.DynamicData{},
Entity: &types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-root"},
Principal: "root",
Group: false,
RoleId: -1,
Propagate: true,
},
},
Name: "ha-folder-root",
DisabledMethod: nil,
RecentTask: nil,
DeclaredAlarmState: nil,
TriggeredAlarmState: nil,
AlarmActionsEnabled: (*bool)(nil),
Tag: nil,
},
ChildType: []string{"Datacenter"},
ChildEntity: nil,
}

View File

@@ -0,0 +1,86 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package esx
import "github.com/vmware/govmomi/vim25/types"
// ServiceContent is the default template for the ServiceInstance content property.
// Capture method:
// govc object.collect -s -dump - content
var ServiceContent = types.ServiceContent{
RootFolder: types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-root"},
PropertyCollector: types.ManagedObjectReference{Type: "PropertyCollector", Value: "ha-property-collector"},
ViewManager: &types.ManagedObjectReference{Type: "ViewManager", Value: "ViewManager"},
About: types.AboutInfo{
Name: "VMware ESXi",
FullName: "VMware ESXi 6.5.0 build-5969303",
Vendor: "VMware, Inc.",
Version: "6.5.0",
Build: "5969303",
LocaleVersion: "INTL",
LocaleBuild: "000",
OsType: "vmnix-x86",
ProductLineId: "embeddedEsx",
ApiType: "HostAgent",
ApiVersion: "6.5",
InstanceUuid: "",
LicenseProductName: "VMware ESX Server",
LicenseProductVersion: "6.0",
},
Setting: &types.ManagedObjectReference{Type: "OptionManager", Value: "HostAgentSettings"},
UserDirectory: &types.ManagedObjectReference{Type: "UserDirectory", Value: "ha-user-directory"},
SessionManager: &types.ManagedObjectReference{Type: "SessionManager", Value: "ha-sessionmgr"},
AuthorizationManager: &types.ManagedObjectReference{Type: "AuthorizationManager", Value: "ha-authmgr"},
ServiceManager: &types.ManagedObjectReference{Type: "ServiceManager", Value: "ha-servicemanager"},
PerfManager: &types.ManagedObjectReference{Type: "PerformanceManager", Value: "ha-perfmgr"},
ScheduledTaskManager: (*types.ManagedObjectReference)(nil),
AlarmManager: (*types.ManagedObjectReference)(nil),
EventManager: &types.ManagedObjectReference{Type: "EventManager", Value: "ha-eventmgr"},
TaskManager: &types.ManagedObjectReference{Type: "TaskManager", Value: "ha-taskmgr"},
ExtensionManager: (*types.ManagedObjectReference)(nil),
CustomizationSpecManager: (*types.ManagedObjectReference)(nil),
CustomFieldsManager: (*types.ManagedObjectReference)(nil),
AccountManager: &types.ManagedObjectReference{Type: "HostLocalAccountManager", Value: "ha-localacctmgr"},
DiagnosticManager: &types.ManagedObjectReference{Type: "DiagnosticManager", Value: "ha-diagnosticmgr"},
LicenseManager: &types.ManagedObjectReference{Type: "LicenseManager", Value: "ha-license-manager"},
SearchIndex: &types.ManagedObjectReference{Type: "SearchIndex", Value: "ha-searchindex"},
FileManager: &types.ManagedObjectReference{Type: "FileManager", Value: "ha-nfc-file-manager"},
DatastoreNamespaceManager: &types.ManagedObjectReference{Type: "DatastoreNamespaceManager", Value: "ha-datastore-namespace-manager"},
VirtualDiskManager: &types.ManagedObjectReference{Type: "VirtualDiskManager", Value: "ha-vdiskmanager"},
VirtualizationManager: (*types.ManagedObjectReference)(nil),
SnmpSystem: (*types.ManagedObjectReference)(nil),
VmProvisioningChecker: (*types.ManagedObjectReference)(nil),
VmCompatibilityChecker: (*types.ManagedObjectReference)(nil),
OvfManager: &types.ManagedObjectReference{Type: "OvfManager", Value: "ha-ovf-manager"},
IpPoolManager: (*types.ManagedObjectReference)(nil),
DvSwitchManager: &types.ManagedObjectReference{Type: "DistributedVirtualSwitchManager", Value: "ha-dvsmanager"},
HostProfileManager: (*types.ManagedObjectReference)(nil),
ClusterProfileManager: (*types.ManagedObjectReference)(nil),
ComplianceManager: (*types.ManagedObjectReference)(nil),
LocalizationManager: &types.ManagedObjectReference{Type: "LocalizationManager", Value: "ha-l10n-manager"},
StorageResourceManager: &types.ManagedObjectReference{Type: "StorageResourceManager", Value: "ha-storage-resource-manager"},
GuestOperationsManager: &types.ManagedObjectReference{Type: "GuestOperationsManager", Value: "ha-guest-operations-manager"},
OverheadMemoryManager: (*types.ManagedObjectReference)(nil),
CertificateManager: (*types.ManagedObjectReference)(nil),
IoFilterManager: (*types.ManagedObjectReference)(nil),
VStorageObjectManager: &types.ManagedObjectReference{Type: "HostVStorageObjectManager", Value: "ha-vstorage-object-manager"},
HostSpecManager: (*types.ManagedObjectReference)(nil),
CryptoManager: &types.ManagedObjectReference{Type: "CryptoManager", Value: "ha-crypto-manager"},
HealthUpdateManager: (*types.ManagedObjectReference)(nil),
FailoverClusterConfigurator: (*types.ManagedObjectReference)(nil),
FailoverClusterManager: (*types.ManagedObjectReference)(nil),
}

View File

@@ -0,0 +1,30 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package esx
import "github.com/vmware/govmomi/vim25/types"
// Setting is captured from ESX's HostSystem.configManager.advancedOption
// Capture method:
// govc object.collect -s -dump $(govc object.collect -s HostSystem:ha-host configManager.advancedOption) setting
var Setting = []types.BaseOptionValue{
// This list is currently pruned to include a single option for testing
&types.OptionValue{
Key: "Config.HostAgent.log.level",
Value: "info",
},
}

View File

@@ -0,0 +1,242 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package esx
import "github.com/vmware/govmomi/vim25/types"
// VirtualDevice is the default set of VirtualDevice types created for a VirtualMachine
// Capture method:
// govc vm.create foo
// govc object.collect -s -dump vm/foo config.hardware.device
var VirtualDevice = []types.BaseVirtualDevice{
&types.VirtualIDEController{
VirtualController: types.VirtualController{
VirtualDevice: types.VirtualDevice{
DynamicData: types.DynamicData{},
Key: 200,
DeviceInfo: &types.Description{
DynamicData: types.DynamicData{},
Label: "IDE 0",
Summary: "IDE 0",
},
Backing: nil,
Connectable: (*types.VirtualDeviceConnectInfo)(nil),
SlotInfo: nil,
ControllerKey: 0,
UnitNumber: (*int32)(nil),
},
BusNumber: 0,
Device: nil,
},
},
&types.VirtualIDEController{
VirtualController: types.VirtualController{
VirtualDevice: types.VirtualDevice{
DynamicData: types.DynamicData{},
Key: 201,
DeviceInfo: &types.Description{
DynamicData: types.DynamicData{},
Label: "IDE 1",
Summary: "IDE 1",
},
Backing: nil,
Connectable: (*types.VirtualDeviceConnectInfo)(nil),
SlotInfo: nil,
ControllerKey: 0,
UnitNumber: (*int32)(nil),
},
BusNumber: 1,
Device: nil,
},
},
&types.VirtualPS2Controller{
VirtualController: types.VirtualController{
VirtualDevice: types.VirtualDevice{
DynamicData: types.DynamicData{},
Key: 300,
DeviceInfo: &types.Description{
DynamicData: types.DynamicData{},
Label: "PS2 controller 0",
Summary: "PS2 controller 0",
},
Backing: nil,
Connectable: (*types.VirtualDeviceConnectInfo)(nil),
SlotInfo: nil,
ControllerKey: 0,
UnitNumber: (*int32)(nil),
},
BusNumber: 0,
Device: []int32{600, 700},
},
},
&types.VirtualPCIController{
VirtualController: types.VirtualController{
VirtualDevice: types.VirtualDevice{
DynamicData: types.DynamicData{},
Key: 100,
DeviceInfo: &types.Description{
DynamicData: types.DynamicData{},
Label: "PCI controller 0",
Summary: "PCI controller 0",
},
Backing: nil,
Connectable: (*types.VirtualDeviceConnectInfo)(nil),
SlotInfo: nil,
ControllerKey: 0,
UnitNumber: (*int32)(nil),
},
BusNumber: 0,
Device: []int32{500, 12000},
},
},
&types.VirtualSIOController{
VirtualController: types.VirtualController{
VirtualDevice: types.VirtualDevice{
DynamicData: types.DynamicData{},
Key: 400,
DeviceInfo: &types.Description{
DynamicData: types.DynamicData{},
Label: "SIO controller 0",
Summary: "SIO controller 0",
},
Backing: nil,
Connectable: (*types.VirtualDeviceConnectInfo)(nil),
SlotInfo: nil,
ControllerKey: 0,
UnitNumber: (*int32)(nil),
},
BusNumber: 0,
Device: nil,
},
},
&types.VirtualKeyboard{
VirtualDevice: types.VirtualDevice{
DynamicData: types.DynamicData{},
Key: 600,
DeviceInfo: &types.Description{
DynamicData: types.DynamicData{},
Label: "Keyboard ",
Summary: "Keyboard",
},
Backing: nil,
Connectable: (*types.VirtualDeviceConnectInfo)(nil),
SlotInfo: nil,
ControllerKey: 300,
UnitNumber: types.NewInt32(0),
},
},
&types.VirtualPointingDevice{
VirtualDevice: types.VirtualDevice{
DynamicData: types.DynamicData{},
Key: 700,
DeviceInfo: &types.Description{
DynamicData: types.DynamicData{},
Label: "Pointing device",
Summary: "Pointing device; Device",
},
Backing: &types.VirtualPointingDeviceDeviceBackingInfo{
VirtualDeviceDeviceBackingInfo: types.VirtualDeviceDeviceBackingInfo{
VirtualDeviceBackingInfo: types.VirtualDeviceBackingInfo{},
DeviceName: "",
UseAutoDetect: types.NewBool(false),
},
HostPointingDevice: "autodetect",
},
Connectable: (*types.VirtualDeviceConnectInfo)(nil),
SlotInfo: nil,
ControllerKey: 300,
UnitNumber: types.NewInt32(1),
},
},
&types.VirtualMachineVideoCard{
VirtualDevice: types.VirtualDevice{
DynamicData: types.DynamicData{},
Key: 500,
DeviceInfo: &types.Description{
DynamicData: types.DynamicData{},
Label: "Video card ",
Summary: "Video card",
},
Backing: nil,
Connectable: (*types.VirtualDeviceConnectInfo)(nil),
SlotInfo: nil,
ControllerKey: 100,
UnitNumber: types.NewInt32(0),
},
VideoRamSizeInKB: 4096,
NumDisplays: 1,
UseAutoDetect: types.NewBool(false),
Enable3DSupport: types.NewBool(false),
Use3dRenderer: "automatic",
GraphicsMemorySizeInKB: 262144,
},
&types.VirtualMachineVMCIDevice{
VirtualDevice: types.VirtualDevice{
DynamicData: types.DynamicData{},
Key: 12000,
DeviceInfo: &types.Description{
DynamicData: types.DynamicData{},
Label: "VMCI device",
Summary: "Device on the virtual machine PCI bus that provides support for the virtual machine communication interface",
},
Backing: nil,
Connectable: (*types.VirtualDeviceConnectInfo)(nil),
SlotInfo: nil,
ControllerKey: 100,
UnitNumber: types.NewInt32(17),
},
Id: -1,
AllowUnrestrictedCommunication: types.NewBool(false),
FilterEnable: types.NewBool(true),
FilterInfo: (*types.VirtualMachineVMCIDeviceFilterInfo)(nil),
},
}
// EthernetCard template for types.VirtualEthernetCard
var EthernetCard = types.VirtualE1000{
VirtualEthernetCard: types.VirtualEthernetCard{
VirtualDevice: types.VirtualDevice{
DynamicData: types.DynamicData{},
Key: 4000,
Backing: &types.VirtualEthernetCardNetworkBackingInfo{
VirtualDeviceDeviceBackingInfo: types.VirtualDeviceDeviceBackingInfo{
VirtualDeviceBackingInfo: types.VirtualDeviceBackingInfo{},
DeviceName: "VM Network",
UseAutoDetect: types.NewBool(false),
},
Network: (*types.ManagedObjectReference)(nil),
InPassthroughMode: types.NewBool(false),
},
Connectable: &types.VirtualDeviceConnectInfo{
DynamicData: types.DynamicData{},
StartConnected: true,
AllowGuestControl: true,
Connected: false,
Status: "untried",
},
SlotInfo: &types.VirtualDevicePciBusSlotInfo{
VirtualDeviceBusSlotInfo: types.VirtualDeviceBusSlotInfo{},
PciSlotNumber: 32,
},
ControllerKey: 100,
UnitNumber: types.NewInt32(7),
},
AddressType: "generated",
MacAddress: "",
WakeOnLanEnabled: types.NewBool(true),
},
}

View File

@@ -0,0 +1,251 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"io"
"os"
"path"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/simulator/esx"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type FileManager struct {
mo.FileManager
}
func NewFileManager(ref types.ManagedObjectReference) object.Reference {
m := &FileManager{}
m.Self = ref
return m
}
func (f *FileManager) findDatastore(ref mo.Reference, name string) (*Datastore, types.BaseMethodFault) {
var refs []types.ManagedObjectReference
switch obj := ref.(type) {
case *Folder:
refs = obj.ChildEntity
case *StoragePod:
refs = obj.ChildEntity
}
for _, ref := range refs {
switch obj := Map.Get(ref).(type) {
case *Datastore:
if obj.Name == name {
return obj, nil
}
case *Folder, *StoragePod:
ds, _ := f.findDatastore(obj, name)
if ds != nil {
return ds, nil
}
}
}
return nil, &types.InvalidDatastore{Name: name}
}
func (f *FileManager) resolve(dc *types.ManagedObjectReference, name string) (string, types.BaseMethodFault) {
p, fault := parseDatastorePath(name)
if fault != nil {
return "", fault
}
if dc == nil {
if Map.IsESX() {
dc = &esx.Datacenter.Self
} else {
return "", &types.InvalidArgument{InvalidProperty: "dc"}
}
}
folder := Map.Get(*dc).(*mo.Datacenter).DatastoreFolder
ds, fault := f.findDatastore(Map.Get(folder), p.Datastore)
if fault != nil {
return "", fault
}
dir := ds.Info.GetDatastoreInfo().Url
return path.Join(dir, p.Path), nil
}
func (f *FileManager) fault(name string, err error, fault types.BaseFileFault) types.BaseMethodFault {
switch {
case os.IsNotExist(err):
fault = new(types.FileNotFound)
case os.IsExist(err):
fault = new(types.FileAlreadyExists)
}
fault.GetFileFault().File = name
return fault.(types.BaseMethodFault)
}
func (f *FileManager) deleteDatastoreFile(req *types.DeleteDatastoreFile_Task) types.BaseMethodFault {
file, fault := f.resolve(req.Datacenter, req.Name)
if fault != nil {
return fault
}
_, err := os.Stat(file)
if err != nil {
if os.IsNotExist(err) {
return f.fault(file, err, new(types.CannotDeleteFile))
}
}
err = os.RemoveAll(file)
if err != nil {
return f.fault(file, err, new(types.CannotDeleteFile))
}
return nil
}
func (f *FileManager) DeleteDatastoreFileTask(req *types.DeleteDatastoreFile_Task) soap.HasFault {
task := CreateTask(f, "deleteDatastoreFile", func(*Task) (types.AnyType, types.BaseMethodFault) {
return nil, f.deleteDatastoreFile(req)
})
return &methods.DeleteDatastoreFile_TaskBody{
Res: &types.DeleteDatastoreFile_TaskResponse{
Returnval: task.Run(),
},
}
}
func (f *FileManager) MakeDirectory(req *types.MakeDirectory) soap.HasFault {
body := &methods.MakeDirectoryBody{}
name, fault := f.resolve(req.Datacenter, req.Name)
if fault != nil {
body.Fault_ = Fault("", fault)
return body
}
mkdir := os.Mkdir
if isTrue(req.CreateParentDirectories) {
mkdir = os.MkdirAll
}
err := mkdir(name, 0700)
if err != nil {
fault = f.fault(req.Name, err, new(types.CannotCreateFile))
body.Fault_ = Fault(err.Error(), fault)
return body
}
return body
}
func (f *FileManager) moveDatastoreFile(req *types.MoveDatastoreFile_Task) types.BaseMethodFault {
src, fault := f.resolve(req.SourceDatacenter, req.SourceName)
if fault != nil {
return fault
}
dst, fault := f.resolve(req.DestinationDatacenter, req.DestinationName)
if fault != nil {
return fault
}
if !isTrue(req.Force) {
_, err := os.Stat(dst)
if err == nil {
return f.fault(dst, nil, new(types.FileAlreadyExistsFault))
}
}
err := os.Rename(src, dst)
if err != nil {
return f.fault(src, err, new(types.CannotAccessFile))
}
return nil
}
func (f *FileManager) MoveDatastoreFileTask(req *types.MoveDatastoreFile_Task) soap.HasFault {
task := CreateTask(f, "moveDatastoreFile", func(*Task) (types.AnyType, types.BaseMethodFault) {
return nil, f.moveDatastoreFile(req)
})
return &methods.MoveDatastoreFile_TaskBody{
Res: &types.MoveDatastoreFile_TaskResponse{
Returnval: task.Run(),
},
}
}
func (f *FileManager) copyDatastoreFile(req *types.CopyDatastoreFile_Task) types.BaseMethodFault {
src, fault := f.resolve(req.SourceDatacenter, req.SourceName)
if fault != nil {
return fault
}
dst, fault := f.resolve(req.DestinationDatacenter, req.DestinationName)
if fault != nil {
return fault
}
if !isTrue(req.Force) {
_, err := os.Stat(dst)
if err == nil {
return f.fault(dst, nil, new(types.FileAlreadyExistsFault))
}
}
r, err := os.Open(src)
if err != nil {
return f.fault(dst, err, new(types.CannotAccessFile))
}
defer r.Close()
w, err := os.Create(dst)
if err != nil {
return f.fault(dst, err, new(types.CannotCreateFile))
}
defer w.Close()
if _, err = io.Copy(w, r); err != nil {
return f.fault(dst, err, new(types.CannotCreateFile))
}
return nil
}
func (f *FileManager) CopyDatastoreFileTask(req *types.CopyDatastoreFile_Task) soap.HasFault {
task := CreateTask(f, "copyDatastoreFile", func(*Task) (types.AnyType, types.BaseMethodFault) {
return nil, f.copyDatastoreFile(req)
})
return &methods.CopyDatastoreFile_TaskBody{
Res: &types.CopyDatastoreFile_TaskResponse{
Returnval: task.Run(),
},
}
}

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

@@ -0,0 +1,471 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"fmt"
"math/rand"
"path"
"sync"
"github.com/google/uuid"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type Folder struct {
mo.Folder
m sync.Mutex
}
// update references when objects are added/removed from a Folder
func (f *Folder) update(o mo.Reference, u func(types.ManagedObjectReference, []types.ManagedObjectReference) []types.ManagedObjectReference) {
ref := o.Reference()
if f.Parent == nil {
return // this is the root folder
}
switch ref.Type {
case "Datacenter", "Folder":
return // nothing to update
}
dc := Map.getEntityDatacenter(f)
switch ref.Type {
case "Network", "DistributedVirtualSwitch", "DistributedVirtualPortgroup":
dc.Network = u(ref, dc.Network)
case "Datastore":
dc.Datastore = u(ref, dc.Datastore)
}
}
func networkSummary(n *mo.Network) *types.NetworkSummary {
return &types.NetworkSummary{
Network: &n.Self,
Name: n.Name,
Accessible: true,
}
}
func (f *Folder) putChild(o mo.Entity) {
Map.PutEntity(f, o)
f.m.Lock()
defer f.m.Unlock()
f.ChildEntity = AddReference(o.Reference(), f.ChildEntity)
f.update(o, AddReference)
switch e := o.(type) {
case *mo.Network:
e.Summary = networkSummary(e)
case *mo.OpaqueNetwork:
e.Summary = networkSummary(&e.Network)
case *DistributedVirtualPortgroup:
e.Summary = networkSummary(&e.Network)
}
}
func (f *Folder) removeChild(o mo.Reference) {
Map.Remove(o.Reference())
f.m.Lock()
defer f.m.Unlock()
f.ChildEntity = RemoveReference(o.Reference(), f.ChildEntity)
f.update(o, RemoveReference)
}
func (f *Folder) hasChildType(kind string) bool {
for _, t := range f.ChildType {
if t == kind {
return true
}
}
return false
}
func (f *Folder) typeNotSupported() *soap.Fault {
return Fault(fmt.Sprintf("%s supports types: %#v", f.Self, f.ChildType), &types.NotSupported{})
}
type addStandaloneHost struct {
*Folder
req *types.AddStandaloneHost_Task
}
func (add *addStandaloneHost) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
host, err := CreateStandaloneHost(add.Folder, add.req.Spec)
if err != nil {
return nil, err
}
if add.req.AddConnected {
host.Runtime.ConnectionState = types.HostSystemConnectionStateConnected
}
return host.Reference(), nil
}
func (f *Folder) AddStandaloneHostTask(a *types.AddStandaloneHost_Task) soap.HasFault {
r := &methods.AddStandaloneHost_TaskBody{}
if f.hasChildType("ComputeResource") && f.hasChildType("Folder") {
r.Res = &types.AddStandaloneHost_TaskResponse{
Returnval: NewTask(&addStandaloneHost{f, a}).Run(),
}
} else {
r.Fault_ = f.typeNotSupported()
}
return r
}
func (f *Folder) CreateFolder(c *types.CreateFolder) soap.HasFault {
r := &methods.CreateFolderBody{}
if f.hasChildType("Folder") {
folder := &Folder{}
folder.Name = c.Name
folder.ChildType = f.ChildType
f.putChild(folder)
r.Res = &types.CreateFolderResponse{
Returnval: folder.Self,
}
} else {
r.Fault_ = f.typeNotSupported()
}
return r
}
// StoragePod aka "Datastore Cluster"
type StoragePod struct {
mo.StoragePod
}
func (f *Folder) CreateStoragePod(c *types.CreateStoragePod) soap.HasFault {
r := &methods.CreateStoragePodBody{}
if f.hasChildType("StoragePod") {
pod := &StoragePod{}
pod.Name = c.Name
pod.ChildType = []string{"Datastore"}
f.putChild(pod)
r.Res = &types.CreateStoragePodResponse{
Returnval: pod.Self,
}
} else {
r.Fault_ = f.typeNotSupported()
}
return r
}
func (p *StoragePod) MoveIntoFolderTask(c *types.MoveIntoFolder_Task) soap.HasFault {
return (&Folder{Folder: p.Folder}).MoveIntoFolderTask(c)
}
func (f *Folder) CreateDatacenter(c *types.CreateDatacenter) soap.HasFault {
r := &methods.CreateDatacenterBody{}
if f.hasChildType("Datacenter") && f.hasChildType("Folder") {
dc := &mo.Datacenter{}
dc.Name = c.Name
f.putChild(dc)
createDatacenterFolders(dc, true)
r.Res = &types.CreateDatacenterResponse{
Returnval: dc.Self,
}
} else {
r.Fault_ = f.typeNotSupported()
}
return r
}
func (f *Folder) CreateClusterEx(c *types.CreateClusterEx) soap.HasFault {
r := &methods.CreateClusterExBody{}
if f.hasChildType("ComputeResource") && f.hasChildType("Folder") {
cluster, err := CreateClusterComputeResource(f, c.Name, c.Spec)
if err != nil {
r.Fault_ = Fault("", err)
return r
}
r.Res = &types.CreateClusterExResponse{
Returnval: cluster.Self,
}
} else {
r.Fault_ = f.typeNotSupported()
}
return r
}
type createVM struct {
*Folder
req *types.CreateVM_Task
register bool
}
func (c *createVM) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
vm, err := NewVirtualMachine(c.Folder.Self, &c.req.Config)
if err != nil {
return nil, err
}
vm.ResourcePool = &c.req.Pool
if c.req.Host == nil {
var hosts []types.ManagedObjectReference
pool := Map.Get(c.req.Pool).(mo.Entity)
switch cr := Map.getEntityComputeResource(pool).(type) {
case *mo.ComputeResource:
hosts = cr.Host
case *ClusterComputeResource:
hosts = cr.Host
}
// Assuming for now that all hosts have access to the datastore
host := hosts[rand.Intn(len(hosts))]
vm.Runtime.Host = &host
} else {
vm.Runtime.Host = c.req.Host
}
vm.Guest = &types.GuestInfo{
ToolsStatus: types.VirtualMachineToolsStatusToolsNotInstalled,
ToolsVersion: "0",
}
vm.Summary.Guest = &types.VirtualMachineGuestSummary{
ToolsStatus: vm.Guest.ToolsStatus,
}
vm.Summary.Config.VmPathName = vm.Config.Files.VmPathName
vm.Summary.Runtime.Host = vm.Runtime.Host
err = vm.create(&c.req.Config, c.register)
if err != nil {
return nil, err
}
c.Folder.putChild(vm)
host := Map.Get(*vm.Runtime.Host).(*HostSystem)
host.Vm = append(host.Vm, vm.Self)
for i := range vm.Datastore {
ds := Map.Get(vm.Datastore[i]).(*Datastore)
ds.Vm = append(ds.Vm, vm.Self)
}
switch rp := Map.Get(*vm.ResourcePool).(type) {
case *ResourcePool:
rp.Vm = append(rp.Vm, vm.Self)
case *VirtualApp:
rp.Vm = append(rp.Vm, vm.Self)
}
return vm.Reference(), nil
}
func (f *Folder) CreateVMTask(c *types.CreateVM_Task) soap.HasFault {
return &methods.CreateVM_TaskBody{
Res: &types.CreateVM_TaskResponse{
Returnval: NewTask(&createVM{f, c, false}).Run(),
},
}
}
type registerVM struct {
*Folder
req *types.RegisterVM_Task
}
func (c *registerVM) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
host := c.req.Host
pool := c.req.Pool
if c.req.AsTemplate {
if host == nil {
return nil, &types.InvalidArgument{InvalidProperty: "host"}
} else if pool != nil {
return nil, &types.InvalidArgument{InvalidProperty: "pool"}
}
pool = hostParent(&Map.Get(*host).(*HostSystem).HostSystem).ResourcePool
} else {
if pool == nil {
return nil, &types.InvalidArgument{InvalidProperty: "pool"}
}
}
if c.req.Path == "" {
return nil, &types.InvalidArgument{InvalidProperty: "path"}
}
s := Map.SearchIndex()
r := s.FindByDatastorePath(&types.FindByDatastorePath{
This: s.Reference(),
Path: c.req.Path,
Datacenter: Map.getEntityDatacenter(c.Folder).Reference(),
})
if ref := r.(*methods.FindByDatastorePathBody).Res.Returnval; ref != nil {
return nil, &types.AlreadyExists{Name: ref.Value}
}
if c.req.Name == "" {
p, err := parseDatastorePath(c.req.Path)
if err != nil {
return nil, err
}
c.req.Name = path.Dir(p.Path)
}
create := NewTask(&createVM{
Folder: c.Folder,
register: true,
req: &types.CreateVM_Task{
This: c.Folder.Reference(),
Config: types.VirtualMachineConfigSpec{
Name: c.req.Name,
Files: &types.VirtualMachineFileInfo{
VmPathName: c.req.Path,
},
},
Pool: *pool,
Host: host,
},
})
create.Run()
if create.Info.Error != nil {
return nil, create.Info.Error.Fault
}
return create.Info.Result, nil
}
func (f *Folder) RegisterVMTask(c *types.RegisterVM_Task) soap.HasFault {
return &methods.RegisterVM_TaskBody{
Res: &types.RegisterVM_TaskResponse{
Returnval: NewTask(&registerVM{f, c}).Run(),
},
}
}
func (f *Folder) MoveIntoFolderTask(c *types.MoveIntoFolder_Task) soap.HasFault {
task := CreateTask(f, "moveIntoFolder", func(t *Task) (types.AnyType, types.BaseMethodFault) {
for _, ref := range c.List {
obj := Map.Get(ref).(mo.Entity)
parent, ok := Map.Get(*(obj.Entity()).Parent).(*Folder)
if !ok || !f.hasChildType(ref.Type) {
return nil, &types.NotSupported{}
}
parent.removeChild(ref)
f.putChild(obj)
}
return nil, nil
})
return &methods.MoveIntoFolder_TaskBody{
Res: &types.MoveIntoFolder_TaskResponse{
Returnval: task.Run(),
},
}
}
func (f *Folder) CreateDVSTask(req *types.CreateDVS_Task) soap.HasFault {
task := CreateTask(f, "createDVS", func(t *Task) (types.AnyType, types.BaseMethodFault) {
spec := req.Spec.ConfigSpec.GetDVSConfigSpec()
dvs := &DistributedVirtualSwitch{}
dvs.Name = spec.Name
dvs.Entity().Name = dvs.Name
if Map.FindByName(dvs.Name, f.ChildEntity) != nil {
return nil, &types.InvalidArgument{InvalidProperty: "name"}
}
dvs.Uuid = uuid.New().String()
f.putChild(dvs)
dvs.Summary = types.DVSSummary{
Name: dvs.Name,
Uuid: dvs.Uuid,
NumPorts: spec.NumStandalonePorts,
ProductInfo: req.Spec.ProductInfo,
Description: spec.Description,
}
if dvs.Summary.ProductInfo == nil {
product := Map.content().About
dvs.Summary.ProductInfo = &types.DistributedVirtualSwitchProductSpec{
Name: "DVS",
Vendor: product.Vendor,
Version: product.Version,
Build: product.Build,
ForwardingClass: "etherswitch",
}
}
return dvs.Reference(), nil
})
return &methods.CreateDVS_TaskBody{
Res: &types.CreateDVS_TaskResponse{
Returnval: task.Run(),
},
}
}
func (f *Folder) RenameTask(r *types.Rename_Task) soap.HasFault {
return RenameTask(f, r)
}

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

@@ -0,0 +1,171 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import "github.com/vmware/govmomi/vim25/types"
// GuestID is the list of valid types.VirtualMachineGuestOsIdentifier
var GuestID = []types.VirtualMachineGuestOsIdentifier{
types.VirtualMachineGuestOsIdentifierDosGuest,
types.VirtualMachineGuestOsIdentifierWin31Guest,
types.VirtualMachineGuestOsIdentifierWin95Guest,
types.VirtualMachineGuestOsIdentifierWin98Guest,
types.VirtualMachineGuestOsIdentifierWinMeGuest,
types.VirtualMachineGuestOsIdentifierWinNTGuest,
types.VirtualMachineGuestOsIdentifierWin2000ProGuest,
types.VirtualMachineGuestOsIdentifierWin2000ServGuest,
types.VirtualMachineGuestOsIdentifierWin2000AdvServGuest,
types.VirtualMachineGuestOsIdentifierWinXPHomeGuest,
types.VirtualMachineGuestOsIdentifierWinXPProGuest,
types.VirtualMachineGuestOsIdentifierWinXPPro64Guest,
types.VirtualMachineGuestOsIdentifierWinNetWebGuest,
types.VirtualMachineGuestOsIdentifierWinNetStandardGuest,
types.VirtualMachineGuestOsIdentifierWinNetEnterpriseGuest,
types.VirtualMachineGuestOsIdentifierWinNetDatacenterGuest,
types.VirtualMachineGuestOsIdentifierWinNetBusinessGuest,
types.VirtualMachineGuestOsIdentifierWinNetStandard64Guest,
types.VirtualMachineGuestOsIdentifierWinNetEnterprise64Guest,
types.VirtualMachineGuestOsIdentifierWinLonghornGuest,
types.VirtualMachineGuestOsIdentifierWinLonghorn64Guest,
types.VirtualMachineGuestOsIdentifierWinNetDatacenter64Guest,
types.VirtualMachineGuestOsIdentifierWinVistaGuest,
types.VirtualMachineGuestOsIdentifierWinVista64Guest,
types.VirtualMachineGuestOsIdentifierWindows7Guest,
types.VirtualMachineGuestOsIdentifierWindows7_64Guest,
types.VirtualMachineGuestOsIdentifierWindows7Server64Guest,
types.VirtualMachineGuestOsIdentifierWindows8Guest,
types.VirtualMachineGuestOsIdentifierWindows8_64Guest,
types.VirtualMachineGuestOsIdentifierWindows8Server64Guest,
types.VirtualMachineGuestOsIdentifierWindows9Guest,
types.VirtualMachineGuestOsIdentifierWindows9_64Guest,
types.VirtualMachineGuestOsIdentifierWindows9Server64Guest,
types.VirtualMachineGuestOsIdentifierWindowsHyperVGuest,
types.VirtualMachineGuestOsIdentifierFreebsdGuest,
types.VirtualMachineGuestOsIdentifierFreebsd64Guest,
types.VirtualMachineGuestOsIdentifierRedhatGuest,
types.VirtualMachineGuestOsIdentifierRhel2Guest,
types.VirtualMachineGuestOsIdentifierRhel3Guest,
types.VirtualMachineGuestOsIdentifierRhel3_64Guest,
types.VirtualMachineGuestOsIdentifierRhel4Guest,
types.VirtualMachineGuestOsIdentifierRhel4_64Guest,
types.VirtualMachineGuestOsIdentifierRhel5Guest,
types.VirtualMachineGuestOsIdentifierRhel5_64Guest,
types.VirtualMachineGuestOsIdentifierRhel6Guest,
types.VirtualMachineGuestOsIdentifierRhel6_64Guest,
types.VirtualMachineGuestOsIdentifierRhel7Guest,
types.VirtualMachineGuestOsIdentifierRhel7_64Guest,
types.VirtualMachineGuestOsIdentifierCentosGuest,
types.VirtualMachineGuestOsIdentifierCentos64Guest,
types.VirtualMachineGuestOsIdentifierCentos6Guest,
types.VirtualMachineGuestOsIdentifierCentos6_64Guest,
types.VirtualMachineGuestOsIdentifierCentos7Guest,
types.VirtualMachineGuestOsIdentifierCentos7_64Guest,
types.VirtualMachineGuestOsIdentifierOracleLinuxGuest,
types.VirtualMachineGuestOsIdentifierOracleLinux64Guest,
types.VirtualMachineGuestOsIdentifierOracleLinux6Guest,
types.VirtualMachineGuestOsIdentifierOracleLinux6_64Guest,
types.VirtualMachineGuestOsIdentifierOracleLinux7Guest,
types.VirtualMachineGuestOsIdentifierOracleLinux7_64Guest,
types.VirtualMachineGuestOsIdentifierSuseGuest,
types.VirtualMachineGuestOsIdentifierSuse64Guest,
types.VirtualMachineGuestOsIdentifierSlesGuest,
types.VirtualMachineGuestOsIdentifierSles64Guest,
types.VirtualMachineGuestOsIdentifierSles10Guest,
types.VirtualMachineGuestOsIdentifierSles10_64Guest,
types.VirtualMachineGuestOsIdentifierSles11Guest,
types.VirtualMachineGuestOsIdentifierSles11_64Guest,
types.VirtualMachineGuestOsIdentifierSles12Guest,
types.VirtualMachineGuestOsIdentifierSles12_64Guest,
types.VirtualMachineGuestOsIdentifierNld9Guest,
types.VirtualMachineGuestOsIdentifierOesGuest,
types.VirtualMachineGuestOsIdentifierSjdsGuest,
types.VirtualMachineGuestOsIdentifierMandrakeGuest,
types.VirtualMachineGuestOsIdentifierMandrivaGuest,
types.VirtualMachineGuestOsIdentifierMandriva64Guest,
types.VirtualMachineGuestOsIdentifierTurboLinuxGuest,
types.VirtualMachineGuestOsIdentifierTurboLinux64Guest,
types.VirtualMachineGuestOsIdentifierUbuntuGuest,
types.VirtualMachineGuestOsIdentifierUbuntu64Guest,
types.VirtualMachineGuestOsIdentifierDebian4Guest,
types.VirtualMachineGuestOsIdentifierDebian4_64Guest,
types.VirtualMachineGuestOsIdentifierDebian5Guest,
types.VirtualMachineGuestOsIdentifierDebian5_64Guest,
types.VirtualMachineGuestOsIdentifierDebian6Guest,
types.VirtualMachineGuestOsIdentifierDebian6_64Guest,
types.VirtualMachineGuestOsIdentifierDebian7Guest,
types.VirtualMachineGuestOsIdentifierDebian7_64Guest,
types.VirtualMachineGuestOsIdentifierDebian8Guest,
types.VirtualMachineGuestOsIdentifierDebian8_64Guest,
types.VirtualMachineGuestOsIdentifierDebian9Guest,
types.VirtualMachineGuestOsIdentifierDebian9_64Guest,
types.VirtualMachineGuestOsIdentifierDebian10Guest,
types.VirtualMachineGuestOsIdentifierDebian10_64Guest,
types.VirtualMachineGuestOsIdentifierAsianux3Guest,
types.VirtualMachineGuestOsIdentifierAsianux3_64Guest,
types.VirtualMachineGuestOsIdentifierAsianux4Guest,
types.VirtualMachineGuestOsIdentifierAsianux4_64Guest,
types.VirtualMachineGuestOsIdentifierAsianux5_64Guest,
types.VirtualMachineGuestOsIdentifierAsianux7_64Guest,
types.VirtualMachineGuestOsIdentifierOpensuseGuest,
types.VirtualMachineGuestOsIdentifierOpensuse64Guest,
types.VirtualMachineGuestOsIdentifierFedoraGuest,
types.VirtualMachineGuestOsIdentifierFedora64Guest,
types.VirtualMachineGuestOsIdentifierCoreos64Guest,
types.VirtualMachineGuestOsIdentifierVmwarePhoton64Guest,
types.VirtualMachineGuestOsIdentifierOther24xLinuxGuest,
types.VirtualMachineGuestOsIdentifierOther26xLinuxGuest,
types.VirtualMachineGuestOsIdentifierOtherLinuxGuest,
types.VirtualMachineGuestOsIdentifierOther3xLinuxGuest,
types.VirtualMachineGuestOsIdentifierGenericLinuxGuest,
types.VirtualMachineGuestOsIdentifierOther24xLinux64Guest,
types.VirtualMachineGuestOsIdentifierOther26xLinux64Guest,
types.VirtualMachineGuestOsIdentifierOther3xLinux64Guest,
types.VirtualMachineGuestOsIdentifierOtherLinux64Guest,
types.VirtualMachineGuestOsIdentifierSolaris6Guest,
types.VirtualMachineGuestOsIdentifierSolaris7Guest,
types.VirtualMachineGuestOsIdentifierSolaris8Guest,
types.VirtualMachineGuestOsIdentifierSolaris9Guest,
types.VirtualMachineGuestOsIdentifierSolaris10Guest,
types.VirtualMachineGuestOsIdentifierSolaris10_64Guest,
types.VirtualMachineGuestOsIdentifierSolaris11_64Guest,
types.VirtualMachineGuestOsIdentifierOs2Guest,
types.VirtualMachineGuestOsIdentifierEComStationGuest,
types.VirtualMachineGuestOsIdentifierEComStation2Guest,
types.VirtualMachineGuestOsIdentifierNetware4Guest,
types.VirtualMachineGuestOsIdentifierNetware5Guest,
types.VirtualMachineGuestOsIdentifierNetware6Guest,
types.VirtualMachineGuestOsIdentifierOpenServer5Guest,
types.VirtualMachineGuestOsIdentifierOpenServer6Guest,
types.VirtualMachineGuestOsIdentifierUnixWare7Guest,
types.VirtualMachineGuestOsIdentifierDarwinGuest,
types.VirtualMachineGuestOsIdentifierDarwin64Guest,
types.VirtualMachineGuestOsIdentifierDarwin10Guest,
types.VirtualMachineGuestOsIdentifierDarwin10_64Guest,
types.VirtualMachineGuestOsIdentifierDarwin11Guest,
types.VirtualMachineGuestOsIdentifierDarwin11_64Guest,
types.VirtualMachineGuestOsIdentifierDarwin12_64Guest,
types.VirtualMachineGuestOsIdentifierDarwin13_64Guest,
types.VirtualMachineGuestOsIdentifierDarwin14_64Guest,
types.VirtualMachineGuestOsIdentifierDarwin15_64Guest,
types.VirtualMachineGuestOsIdentifierDarwin16_64Guest,
types.VirtualMachineGuestOsIdentifierVmkernelGuest,
types.VirtualMachineGuestOsIdentifierVmkernel5Guest,
types.VirtualMachineGuestOsIdentifierVmkernel6Guest,
types.VirtualMachineGuestOsIdentifierVmkernel65Guest,
types.VirtualMachineGuestOsIdentifierOtherGuest,
types.VirtualMachineGuestOsIdentifierOtherGuest64,
}

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

@@ -0,0 +1,35 @@
#!/bin/bash -e
pushd "$(dirname "$0")" >/dev/null
{
cat <<EOF
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
// GuestID is the list of valid types.VirtualMachineGuestOsIdentifier
var GuestID = []types.VirtualMachineGuestOsIdentifier{
EOF
ids=($(grep 'VirtualMachineGuestOsIdentifier(' ../vim25/types/enum.go | grep = | awk '{print $1}'))
printf "types.%s,\n" "${ids[@]}"
echo "}"
} > guest_id.go
goimports -w guest_id.go

View File

@@ -0,0 +1,254 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"io/ioutil"
"log"
"os"
"path"
"strings"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type HostDatastoreBrowser struct {
mo.HostDatastoreBrowser
}
type searchDatastore struct {
*HostDatastoreBrowser
DatastorePath string
SearchSpec *types.HostDatastoreBrowserSearchSpec
res []types.HostDatastoreBrowserSearchResults
recurse bool
}
func (s *searchDatastore) addFile(file os.FileInfo, res *types.HostDatastoreBrowserSearchResults) {
details := s.SearchSpec.Details
if details == nil {
details = new(types.FileQueryFlags)
}
name := file.Name()
info := types.FileInfo{
Path: name,
}
var finfo types.BaseFileInfo = &info
if details.FileSize {
info.FileSize = file.Size()
}
if details.Modification {
mtime := file.ModTime()
info.Modification = &mtime
}
if isTrue(details.FileOwner) {
// Assume for now this process created all files in the datastore
user := os.Getenv("USER")
info.Owner = user
}
if file.IsDir() {
finfo = &types.FolderFileInfo{FileInfo: info}
} else if details.FileType {
switch path.Ext(name) {
case ".img":
finfo = &types.FloppyImageFileInfo{FileInfo: info}
case ".iso":
finfo = &types.IsoImageFileInfo{FileInfo: info}
case ".log":
finfo = &types.VmLogFileInfo{FileInfo: info}
case ".nvram":
finfo = &types.VmNvramFileInfo{FileInfo: info}
case ".vmdk":
// TODO: lookup device to set other fields
finfo = &types.VmDiskFileInfo{FileInfo: info}
case ".vmx":
finfo = &types.VmConfigFileInfo{FileInfo: info}
}
}
res.File = append(res.File, finfo)
}
func (s *searchDatastore) queryMatch(file os.FileInfo) bool {
if len(s.SearchSpec.Query) == 0 {
return true
}
name := file.Name()
ext := path.Ext(name)
for _, q := range s.SearchSpec.Query {
switch q.(type) {
case *types.FileQuery:
return true
case *types.FolderFileQuery:
if file.IsDir() {
return true
}
case *types.FloppyImageFileQuery:
if ext == ".img" {
return true
}
case *types.IsoImageFileQuery:
if ext == ".iso" {
return true
}
case *types.VmConfigFileQuery:
if ext == ".vmx" {
// TODO: check Filter and Details fields
return true
}
case *types.VmDiskFileQuery:
if ext == ".vmdk" {
if strings.HasSuffix(name, "-flat.vmdk") {
// only matches the descriptor, not the backing file(s)
return false
}
// TODO: check Filter and Details fields
return true
}
case *types.VmLogFileQuery:
if ext == ".log" {
return strings.HasPrefix(name, "vmware")
}
case *types.VmNvramFileQuery:
if ext == ".nvram" {
return true
}
case *types.VmSnapshotFileQuery:
if ext == ".vmsn" {
return true
}
}
}
return false
}
func (s *searchDatastore) search(ds *types.ManagedObjectReference, folder string, dir string) error {
files, err := ioutil.ReadDir(dir)
if err != nil {
log.Printf("search %s: %s", dir, err)
return err
}
res := types.HostDatastoreBrowserSearchResults{
Datastore: ds,
FolderPath: folder,
}
for _, file := range files {
name := file.Name()
if s.queryMatch(file) {
for _, m := range s.SearchSpec.MatchPattern {
if ok, _ := path.Match(m, name); ok {
s.addFile(file, &res)
break
}
}
}
if s.recurse && file.IsDir() {
_ = s.search(ds, path.Join(folder, name), path.Join(dir, name))
}
}
s.res = append(s.res, res)
return nil
}
func (s *searchDatastore) Run(Task *Task) (types.AnyType, types.BaseMethodFault) {
p, fault := parseDatastorePath(s.DatastorePath)
if fault != nil {
return nil, fault
}
ref := Map.FindByName(p.Datastore, s.Datastore)
if ref == nil {
return nil, &types.InvalidDatastore{Name: p.Datastore}
}
ds := ref.(*Datastore)
dir := path.Join(ds.Info.GetDatastoreInfo().Url, p.Path)
err := s.search(&ds.Self, s.DatastorePath, dir)
if err != nil {
ff := types.FileFault{
File: p.Path,
}
if os.IsNotExist(err) {
return nil, &types.FileNotFound{FileFault: ff}
}
return nil, &types.InvalidArgument{InvalidProperty: p.Path}
}
if s.recurse {
return types.ArrayOfHostDatastoreBrowserSearchResults{
HostDatastoreBrowserSearchResults: s.res,
}, nil
}
return s.res[0], nil
}
func (b *HostDatastoreBrowser) SearchDatastoreTask(s *types.SearchDatastore_Task) soap.HasFault {
task := NewTask(&searchDatastore{
HostDatastoreBrowser: b,
DatastorePath: s.DatastorePath,
SearchSpec: s.SearchSpec,
})
return &methods.SearchDatastore_TaskBody{
Res: &types.SearchDatastore_TaskResponse{
Returnval: task.Run(),
},
}
}
func (b *HostDatastoreBrowser) SearchDatastoreSubFoldersTask(s *types.SearchDatastoreSubFolders_Task) soap.HasFault {
task := NewTask(&searchDatastore{
HostDatastoreBrowser: b,
DatastorePath: s.DatastorePath,
SearchSpec: s.SearchSpec,
recurse: true,
})
return &methods.SearchDatastoreSubFolders_TaskBody{
Res: &types.SearchDatastoreSubFolders_TaskResponse{
Returnval: task.Run(),
},
}
}

View File

@@ -0,0 +1,161 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"os"
"path"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type HostDatastoreSystem struct {
mo.HostDatastoreSystem
Host *mo.HostSystem
}
func (dss *HostDatastoreSystem) add(ds *Datastore) *soap.Fault {
info := ds.Info.GetDatastoreInfo()
info.Name = ds.Name
if e := Map.FindByName(ds.Name, dss.Datastore); e != nil {
return Fault(e.Reference().Value, &types.DuplicateName{
Name: ds.Name,
Object: e.Reference(),
})
}
fi, err := os.Stat(info.Url)
if err == nil && !fi.IsDir() {
err = os.ErrInvalid
}
if err != nil {
switch {
case os.IsNotExist(err):
return Fault(err.Error(), &types.NotFound{})
default:
return Fault(err.Error(), &types.HostConfigFault{})
}
}
folder := Map.getEntityFolder(dss.Host, "datastore")
ds.Self.Type = typeName(ds)
// Datastore is the only type where create methods do not include the parent (Folder in this case),
// but we need the moref to be unique per DC/datastoreFolder, but not per-HostSystem.
ds.Self.Value += "@" + folder.Self.Value
// TODO: name should be made unique in the case of Local ds type
ds.Summary.Datastore = &ds.Self
ds.Summary.Name = ds.Name
ds.Summary.Url = info.Url
dss.Datastore = append(dss.Datastore, ds.Self)
dss.Host.Datastore = dss.Datastore
parent := hostParent(dss.Host)
parent.Datastore = AddReference(ds.Self, parent.Datastore)
browser := &HostDatastoreBrowser{}
browser.Datastore = dss.Datastore
ds.Browser = Map.Put(browser).Reference()
folder.putChild(ds)
return nil
}
func (dss *HostDatastoreSystem) CreateLocalDatastore(c *types.CreateLocalDatastore) soap.HasFault {
r := &methods.CreateLocalDatastoreBody{}
ds := &Datastore{}
ds.Name = c.Name
ds.Self.Value = c.Path
ds.Info = &types.LocalDatastoreInfo{
DatastoreInfo: types.DatastoreInfo{
Name: c.Name,
Url: c.Path,
},
Path: c.Path,
}
ds.Summary.Type = "local"
if err := dss.add(ds); err != nil {
r.Fault_ = err
return r
}
ds.Host = append(ds.Host, types.DatastoreHostMount{
Key: dss.Host.Reference(),
MountInfo: types.HostMountInfo{
AccessMode: string(types.HostMountModeReadWrite),
Mounted: types.NewBool(true),
Accessible: types.NewBool(true),
},
})
_ = ds.RefreshDatastore(&types.RefreshDatastore{This: ds.Self})
r.Res = &types.CreateLocalDatastoreResponse{
Returnval: ds.Self,
}
return r
}
func (dss *HostDatastoreSystem) CreateNasDatastore(c *types.CreateNasDatastore) soap.HasFault {
r := &methods.CreateNasDatastoreBody{}
ds := &Datastore{}
ds.Name = path.Base(c.Spec.LocalPath)
ds.Self.Value = c.Spec.RemoteHost + ":" + c.Spec.RemotePath
ds.Info = &types.NasDatastoreInfo{
DatastoreInfo: types.DatastoreInfo{
Url: c.Spec.LocalPath,
},
Nas: &types.HostNasVolume{
HostFileSystemVolume: types.HostFileSystemVolume{
Name: c.Spec.LocalPath,
Type: c.Spec.Type,
},
RemoteHost: c.Spec.RemoteHost,
RemotePath: c.Spec.RemotePath,
},
}
ds.Summary.Type = c.Spec.Type
if err := dss.add(ds); err != nil {
r.Fault_ = err
return r
}
_ = ds.RefreshDatastore(&types.RefreshDatastore{This: ds.Self})
r.Res = &types.CreateNasDatastoreResponse{
Returnval: ds.Self,
}
return r
}

View File

@@ -0,0 +1,87 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"github.com/vmware/govmomi/simulator/esx"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type HostFirewallSystem struct {
mo.HostFirewallSystem
}
func NewHostFirewallSystem(_ *mo.HostSystem) *HostFirewallSystem {
info := esx.HostFirewallInfo
return &HostFirewallSystem{
HostFirewallSystem: mo.HostFirewallSystem{
FirewallInfo: &info,
},
}
}
func DisableRuleset(info *types.HostFirewallInfo, id string) bool {
for i := range info.Ruleset {
if info.Ruleset[i].Key == id {
info.Ruleset[i].Enabled = false
return true
}
}
return false
}
func (s *HostFirewallSystem) DisableRuleset(req *types.DisableRuleset) soap.HasFault {
body := &methods.DisableRulesetBody{}
if DisableRuleset(s.HostFirewallSystem.FirewallInfo, req.Id) {
body.Res = new(types.DisableRulesetResponse)
return body
}
body.Fault_ = Fault("", &types.NotFound{})
return body
}
func EnableRuleset(info *types.HostFirewallInfo, id string) bool {
for i := range info.Ruleset {
if info.Ruleset[i].Key == id {
info.Ruleset[i].Enabled = true
return true
}
}
return false
}
func (s *HostFirewallSystem) EnableRuleset(req *types.EnableRuleset) soap.HasFault {
body := &methods.EnableRulesetBody{}
if EnableRuleset(s.HostFirewallSystem.FirewallInfo, req.Id) {
body.Res = new(types.EnableRulesetResponse)
return body
}
body.Fault_ = Fault("", &types.NotFound{})
return body
}

View File

@@ -0,0 +1,171 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type HostNetworkSystem struct {
mo.HostNetworkSystem
Host *mo.HostSystem
}
func NewHostNetworkSystem(host *mo.HostSystem) *HostNetworkSystem {
return &HostNetworkSystem{
Host: host,
HostNetworkSystem: mo.HostNetworkSystem{
NetworkInfo: &types.HostNetworkInfo{
Vswitch: []types.HostVirtualSwitch{
{
Name: "vSwitch0",
Portgroup: []string{"VM Network"},
},
},
},
},
}
}
func (s *HostNetworkSystem) folder() *Folder {
f := Map.getEntityDatacenter(s.Host).NetworkFolder
return Map.Get(f).(*Folder)
}
func (s *HostNetworkSystem) AddVirtualSwitch(c *types.AddVirtualSwitch) soap.HasFault {
r := &methods.AddVirtualSwitchBody{}
for _, vswitch := range s.NetworkInfo.Vswitch {
if vswitch.Name == c.VswitchName {
r.Fault_ = Fault("", &types.AlreadyExists{Name: c.VswitchName})
return r
}
}
s.NetworkInfo.Vswitch = append(s.NetworkInfo.Vswitch, types.HostVirtualSwitch{
Name: c.VswitchName,
})
r.Res = &types.AddVirtualSwitchResponse{}
return r
}
func (s *HostNetworkSystem) RemoveVirtualSwitch(c *types.RemoveVirtualSwitch) soap.HasFault {
r := &methods.RemoveVirtualSwitchBody{}
vs := s.NetworkInfo.Vswitch
for i, v := range vs {
if v.Name == c.VswitchName {
s.NetworkInfo.Vswitch = append(vs[:i], vs[i+1:]...)
r.Res = &types.RemoveVirtualSwitchResponse{}
return r
}
}
r.Fault_ = Fault("", &types.NotFound{})
return r
}
func (s *HostNetworkSystem) AddPortGroup(c *types.AddPortGroup) soap.HasFault {
var vswitch *types.HostVirtualSwitch
r := &methods.AddPortGroupBody{}
if c.Portgrp.Name == "" {
r.Fault_ = Fault("", &types.InvalidArgument{InvalidProperty: "name"})
return r
}
for i := range s.NetworkInfo.Vswitch {
if s.NetworkInfo.Vswitch[i].Name == c.Portgrp.VswitchName {
vswitch = &s.NetworkInfo.Vswitch[i]
break
}
}
if vswitch == nil {
r.Fault_ = Fault("", &types.NotFound{})
return r
}
network := &mo.Network{}
network.Name = c.Portgrp.Name
network.Entity().Name = network.Name
folder := s.folder()
if obj := Map.FindByName(c.Portgrp.Name, folder.ChildEntity); obj != nil {
r.Fault_ = Fault("", &types.DuplicateName{
Name: c.Portgrp.Name,
Object: obj.Reference(),
})
return r
}
folder.putChild(network)
vswitch.Portgroup = append(vswitch.Portgroup, c.Portgrp.Name)
r.Res = &types.AddPortGroupResponse{}
return r
}
func (s *HostNetworkSystem) RemovePortGroup(c *types.RemovePortGroup) soap.HasFault {
var vswitch *types.HostVirtualSwitch
r := &methods.RemovePortGroupBody{}
for i, v := range s.NetworkInfo.Vswitch {
for j, pg := range v.Portgroup {
if pg == c.PgName {
vswitch = &s.NetworkInfo.Vswitch[i]
vswitch.Portgroup = append(vswitch.Portgroup[:j], vswitch.Portgroup[j+1:]...)
}
}
}
if vswitch == nil {
r.Fault_ = Fault("", &types.NotFound{})
return r
}
folder := s.folder()
e := Map.FindByName(c.PgName, folder.ChildEntity)
folder.removeChild(e.Reference())
r.Res = &types.RemovePortGroupResponse{}
return r
}
func (s *HostNetworkSystem) UpdateNetworkConfig(req *types.UpdateNetworkConfig) soap.HasFault {
s.NetworkConfig = &req.Config
return &methods.UpdateNetworkConfigBody{
Res: &types.UpdateNetworkConfigResponse{
Returnval: types.HostNetworkConfigResult{},
},
}
}

View File

@@ -0,0 +1,180 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"time"
"github.com/google/uuid"
"github.com/vmware/govmomi/simulator/esx"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type HostSystem struct {
mo.HostSystem
}
func NewHostSystem(host mo.HostSystem) *HostSystem {
now := time.Now()
hs := &HostSystem{
HostSystem: host,
}
hs.Name = hs.Summary.Config.Name
hs.Summary.Runtime = &hs.Runtime
hs.Summary.Runtime.BootTime = &now
id := uuid.New().String()
hardware := *host.Summary.Hardware
hs.Summary.Hardware = &hardware
hs.Summary.Hardware.Uuid = id
info := *esx.HostHardwareInfo
info.SystemInfo.Uuid = id
hs.Hardware = &info
config := []struct {
ref **types.ManagedObjectReference
obj mo.Reference
}{
{&hs.ConfigManager.DatastoreSystem, &HostDatastoreSystem{Host: &hs.HostSystem}},
{&hs.ConfigManager.NetworkSystem, NewHostNetworkSystem(&hs.HostSystem)},
{&hs.ConfigManager.AdvancedOption, NewOptionManager(nil, esx.Setting)},
{&hs.ConfigManager.FirewallSystem, NewHostFirewallSystem(&hs.HostSystem)},
}
for _, c := range config {
ref := Map.Put(c.obj).Reference()
*c.ref = &ref
}
return hs
}
func hostParent(host *mo.HostSystem) *mo.ComputeResource {
switch parent := Map.Get(*host.Parent).(type) {
case *mo.ComputeResource:
return parent
case *ClusterComputeResource:
return &parent.ComputeResource
default:
return nil
}
}
func addComputeResource(s *types.ComputeResourceSummary, h *HostSystem) {
s.TotalCpu += h.Summary.Hardware.CpuMhz
s.TotalMemory += h.Summary.Hardware.MemorySize
s.NumCpuCores += h.Summary.Hardware.NumCpuCores
s.NumCpuThreads += h.Summary.Hardware.NumCpuThreads
s.EffectiveCpu += h.Summary.Hardware.CpuMhz
s.EffectiveMemory += h.Summary.Hardware.MemorySize
s.NumHosts++
s.NumEffectiveHosts++
s.OverallStatus = types.ManagedEntityStatusGreen
}
// CreateDefaultESX creates a standalone ESX
// Adds objects of type: Datacenter, Network, ComputeResource, ResourcePool and HostSystem
func CreateDefaultESX(f *Folder) {
dc := &esx.Datacenter
f.putChild(dc)
createDatacenterFolders(dc, false)
host := NewHostSystem(esx.HostSystem)
summary := new(types.ComputeResourceSummary)
addComputeResource(summary, host)
cr := &mo.ComputeResource{Summary: summary}
cr.Self = *host.Parent
cr.Name = host.Name
cr.Host = append(cr.Host, host.Reference())
Map.PutEntity(cr, host)
pool := NewResourcePool()
cr.ResourcePool = &pool.Self
Map.PutEntity(cr, pool)
pool.Owner = cr.Self
Map.Get(dc.HostFolder).(*Folder).putChild(cr)
}
// CreateStandaloneHost uses esx.HostSystem as a template, applying the given spec
// and creating the ComputeResource parent and ResourcePool sibling.
func CreateStandaloneHost(f *Folder, spec types.HostConnectSpec) (*HostSystem, types.BaseMethodFault) {
if spec.HostName == "" {
return nil, &types.NoHost{}
}
pool := NewResourcePool()
host := NewHostSystem(esx.HostSystem)
host.Summary.Config.Name = spec.HostName
host.Name = host.Summary.Config.Name
host.Runtime.ConnectionState = types.HostSystemConnectionStateDisconnected
summary := new(types.ComputeResourceSummary)
addComputeResource(summary, host)
cr := &mo.ComputeResource{Summary: summary}
Map.PutEntity(cr, Map.NewEntity(host))
Map.PutEntity(cr, Map.NewEntity(pool))
cr.Name = host.Name
cr.Host = append(cr.Host, host.Reference())
cr.ResourcePool = &pool.Self
f.putChild(cr)
pool.Owner = cr.Self
return host, nil
}
func (h *HostSystem) EnterMaintenanceModeTask(spec *types.EnterMaintenanceMode_Task) soap.HasFault {
task := CreateTask(h, "enterMaintenanceMode", func(t *Task) (types.AnyType, types.BaseMethodFault) {
h.Runtime.InMaintenanceMode = true
return nil, nil
})
return &methods.EnterMaintenanceMode_TaskBody{
Res: &types.EnterMaintenanceMode_TaskResponse{
Returnval: task.Run(),
},
}
}
func (h *HostSystem) ExitMaintenanceModeTask(spec *types.ExitMaintenanceMode_Task) soap.HasFault {
task := CreateTask(h, "exitMaintenanceMode", func(t *Task) (types.AnyType, types.BaseMethodFault) {
h.Runtime.InMaintenanceMode = false
return nil, nil
})
return &methods.ExitMaintenanceMode_TaskBody{
Res: &types.ExitMaintenanceMode_TaskResponse{
Returnval: task.Run(),
},
}
}

View File

@@ -0,0 +1,392 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"errors"
"fmt"
"net"
"strconv"
"strings"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
var ipPool = MustNewIpPool(&types.IpPool{
Id: 1,
Name: "ip-pool",
AvailableIpv4Addresses: 250,
AvailableIpv6Addresses: 250,
AllocatedIpv6Addresses: 0,
AllocatedIpv4Addresses: 0,
Ipv4Config: &types.IpPoolIpPoolConfigInfo{
Netmask: "10.10.10.255",
Gateway: "10.10.10.1",
SubnetAddress: "10.10.10.0",
Range: "10.10.10.2#250",
},
Ipv6Config: &types.IpPoolIpPoolConfigInfo{
Netmask: "2001:4860:0:2001::ff",
Gateway: "2001:4860:0:2001::1",
SubnetAddress: "2001:4860:0:2001::0",
Range: "2001:4860:0:2001::2#250",
},
})
// IpPoolManager implements a simple IP Pool manager in which all pools are shared
// across different datacenters.
type IpPoolManager struct {
mo.IpPoolManager
pools map[int32]*IpPool
nextPoolId int32
}
func NewIpPoolManager(ref types.ManagedObjectReference) *IpPoolManager {
m := &IpPoolManager{}
m.Self = ref
m.pools = map[int32]*IpPool{
1: ipPool,
}
m.nextPoolId = 2
return m
}
func (m *IpPoolManager) CreateIpPool(req *types.CreateIpPool) soap.HasFault {
body := &methods.CreateIpPoolBody{}
id := m.nextPoolId
var err error
m.pools[id], err = NewIpPool(&req.Pool)
if err != nil {
body.Fault_ = Fault("", &types.RuntimeFault{})
return body
}
m.nextPoolId++
body.Res = &types.CreateIpPoolResponse{
Returnval: id,
}
return body
}
func (m *IpPoolManager) DestroyIpPool(req *types.DestroyIpPool) soap.HasFault {
delete(m.pools, req.Id)
return &methods.DestroyIpPoolBody{
Res: &types.DestroyIpPoolResponse{},
}
}
func (m *IpPoolManager) QueryIpPools(req *types.QueryIpPools) soap.HasFault {
pools := []types.IpPool{}
for i := int32(1); i < m.nextPoolId; i++ {
if p, ok := m.pools[i]; ok {
pools = append(pools, *p.config)
}
}
return &methods.QueryIpPoolsBody{
Res: &types.QueryIpPoolsResponse{
Returnval: pools,
},
}
}
func (m *IpPoolManager) UpdateIpPool(req *types.UpdateIpPool) soap.HasFault {
body := &methods.UpdateIpPoolBody{}
var pool *IpPool
var err error
var ok bool
if pool, ok = m.pools[req.Pool.Id]; !ok {
body.Fault_ = Fault("", &types.NotFoundFault{})
return body
}
if pool.config.AllocatedIpv4Addresses+pool.config.AllocatedIpv6Addresses != 0 {
body.Fault_ = Fault("update a pool has been used is not supported", &types.RuntimeFault{})
return body
}
m.pools[req.Pool.Id], err = NewIpPool(&req.Pool)
if err != nil {
body.Fault_ = Fault(err.Error(), &types.RuntimeFault{})
return body
}
body.Res = &types.UpdateIpPoolResponse{}
return body
}
func (m *IpPoolManager) AllocateIpv4Address(req *types.AllocateIpv4Address) soap.HasFault {
body := &methods.AllocateIpv4AddressBody{}
pool, ok := m.pools[req.PoolId]
if !ok {
body.Fault_ = Fault("", &types.InvalidArgument{})
return body
}
ip, err := pool.AllocateIPv4(req.AllocationId)
if err != nil {
body.Fault_ = Fault(err.Error(), &types.RuntimeFault{})
return body
}
body.Res = &types.AllocateIpv4AddressResponse{
Returnval: ip,
}
return body
}
func (m *IpPoolManager) AllocateIpv6Address(req *types.AllocateIpv6Address) soap.HasFault {
body := &methods.AllocateIpv6AddressBody{}
pool, ok := m.pools[req.PoolId]
if !ok {
body.Fault_ = Fault("", &types.InvalidArgument{})
return body
}
ip, err := pool.AllocateIpv6(req.AllocationId)
if err != nil {
body.Fault_ = Fault(err.Error(), &types.RuntimeFault{})
return body
}
body.Res = &types.AllocateIpv6AddressResponse{
Returnval: ip,
}
return body
}
func (m *IpPoolManager) ReleaseIpAllocation(req *types.ReleaseIpAllocation) soap.HasFault {
body := &methods.ReleaseIpAllocationBody{}
pool, ok := m.pools[req.PoolId]
if !ok {
body.Fault_ = Fault("", &types.InvalidArgument{})
return body
}
pool.ReleaseIpv4(req.AllocationId)
pool.ReleaseIpv6(req.AllocationId)
body.Res = &types.ReleaseIpAllocationResponse{}
return body
}
func (m *IpPoolManager) QueryIPAllocations(req *types.QueryIPAllocations) soap.HasFault {
body := &methods.QueryIPAllocationsBody{}
pool, ok := m.pools[req.PoolId]
if !ok {
body.Fault_ = Fault("", &types.InvalidArgument{})
return body
}
body.Res = &types.QueryIPAllocationsResponse{}
ipv4, ok := pool.ipv4Allocation[req.ExtensionKey]
if ok {
body.Res.Returnval = append(body.Res.Returnval, types.IpPoolManagerIpAllocation{
IpAddress: ipv4,
AllocationId: req.ExtensionKey,
})
}
ipv6, ok := pool.ipv6Allocation[req.ExtensionKey]
if ok {
body.Res.Returnval = append(body.Res.Returnval, types.IpPoolManagerIpAllocation{
IpAddress: ipv6,
AllocationId: req.ExtensionKey,
})
}
return body
}
var (
errNoIpAvailable = errors.New("no ip address available")
errInvalidAllocation = errors.New("allocation id not recognized")
)
type IpPool struct {
config *types.IpPool
ipv4Allocation map[string]string
ipv6Allocation map[string]string
ipv4Pool []string
ipv6Pool []string
}
func MustNewIpPool(config *types.IpPool) *IpPool {
pool, err := NewIpPool(config)
if err != nil {
panic(err)
}
return pool
}
func NewIpPool(config *types.IpPool) (*IpPool, error) {
pool := &IpPool{
config: config,
ipv4Allocation: make(map[string]string),
ipv6Allocation: make(map[string]string),
}
return pool, pool.init()
}
func (p *IpPool) init() error {
// IPv4 range
if p.config.Ipv4Config != nil {
ranges := strings.Split(p.config.Ipv4Config.Range, ",")
for _, r := range ranges {
sp := strings.Split(r, "#")
if len(sp) != 2 {
return fmt.Errorf("format of range should be ip#number; got %q", r)
}
ip := net.ParseIP(strings.TrimSpace(sp[0])).To4()
if ip == nil {
return fmt.Errorf("bad ip format: %q", sp[0])
}
length, err := strconv.Atoi(sp[1])
if err != nil {
return err
}
for i := 0; i < length; i++ {
p.ipv4Pool = append(p.ipv4Pool, net.IPv4(ip[0], ip[1], ip[2], ip[3]+byte(i)).String())
}
}
}
// IPv6 range
if p.config.Ipv6Config != nil {
ranges := strings.Split(p.config.Ipv6Config.Range, ",")
for _, r := range ranges {
sp := strings.Split(r, "#")
if len(sp) != 2 {
return fmt.Errorf("format of range should be ip#number; got %q", r)
}
ip := net.ParseIP(strings.TrimSpace(sp[0])).To16()
if ip == nil {
return fmt.Errorf("bad ip format: %q", sp[0])
}
length, err := strconv.Atoi(sp[1])
if err != nil {
return err
}
for i := 0; i < length; i++ {
var ipv6 [16]byte
copy(ipv6[:], ip)
ipv6[15] += byte(i)
p.ipv6Pool = append(p.ipv6Pool, net.IP(ipv6[:]).String())
}
}
}
return nil
}
func (p *IpPool) AllocateIPv4(allocation string) (string, error) {
if ip, ok := p.ipv4Allocation[allocation]; ok {
return ip, nil
}
l := len(p.ipv4Pool)
if l == 0 {
return "", errNoIpAvailable
}
ip := p.ipv4Pool[l-1]
p.config.AvailableIpv4Addresses--
p.config.AllocatedIpv4Addresses++
p.ipv4Pool = p.ipv4Pool[:l-1]
p.ipv4Allocation[allocation] = ip
return ip, nil
}
func (p *IpPool) ReleaseIpv4(allocation string) error {
ip, ok := p.ipv4Allocation[allocation]
if !ok {
return errInvalidAllocation
}
delete(p.ipv4Allocation, allocation)
p.config.AvailableIpv4Addresses++
p.config.AllocatedIpv4Addresses--
p.ipv4Pool = append(p.ipv4Pool, ip)
return nil
}
func (p *IpPool) AllocateIpv6(allocation string) (string, error) {
if ip, ok := p.ipv6Allocation[allocation]; ok {
return ip, nil
}
l := len(p.ipv6Pool)
if l == 0 {
return "", errNoIpAvailable
}
ip := p.ipv6Pool[l-1]
p.config.AvailableIpv6Addresses--
p.config.AllocatedIpv6Addresses++
p.ipv6Pool = p.ipv6Pool[:l-1]
p.ipv6Allocation[allocation] = ip
return ip, nil
}
func (p *IpPool) ReleaseIpv6(allocation string) error {
ip, ok := p.ipv6Allocation[allocation]
if !ok {
return errInvalidAllocation
}
delete(p.ipv6Allocation, allocation)
p.config.AvailableIpv6Addresses++
p.config.AllocatedIpv6Addresses--
p.ipv6Pool = append(p.ipv6Pool, ip)
return nil
}

View File

@@ -0,0 +1,156 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Copyright 2017 VMware, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package simulator
import (
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
// EvalLicense is the default license
var EvalLicense = types.LicenseManagerLicenseInfo{
LicenseKey: "00000-00000-00000-00000-00000",
EditionKey: "eval",
Name: "Evaluation Mode",
Properties: []types.KeyAnyValue{
{
Key: "feature",
Value: types.KeyValue{
Key: "serialuri:2",
Value: "Remote virtual Serial Port Concentrator",
},
},
{
Key: "feature",
Value: types.KeyValue{
Key: "dvs",
Value: "vSphere Distributed Switch",
},
},
},
}
type LicenseManager struct {
mo.LicenseManager
}
func NewLicenseManager(ref types.ManagedObjectReference) object.Reference {
m := &LicenseManager{}
m.Self = ref
m.Licenses = []types.LicenseManagerLicenseInfo{EvalLicense}
if Map.IsVPX() {
am := Map.Put(&LicenseAssignmentManager{}).Reference()
m.LicenseAssignmentManager = &am
}
return m
}
func (m *LicenseManager) AddLicense(req *types.AddLicense) soap.HasFault {
body := &methods.AddLicenseBody{
Res: &types.AddLicenseResponse{},
}
for _, license := range m.Licenses {
if license.LicenseKey == req.LicenseKey {
body.Res.Returnval = licenseInfo(license.LicenseKey, license.Labels)
return body
}
}
m.Licenses = append(m.Licenses, types.LicenseManagerLicenseInfo{
LicenseKey: req.LicenseKey,
Labels: req.Labels,
})
body.Res.Returnval = licenseInfo(req.LicenseKey, req.Labels)
return body
}
func (m *LicenseManager) RemoveLicense(req *types.RemoveLicense) soap.HasFault {
body := &methods.RemoveLicenseBody{
Res: &types.RemoveLicenseResponse{},
}
for i, license := range m.Licenses {
if req.LicenseKey == license.LicenseKey {
m.Licenses = append(m.Licenses[:i], m.Licenses[i+1:]...)
return body
}
}
return body
}
type LicenseAssignmentManager struct {
mo.LicenseAssignmentManager
}
func (m *LicenseAssignmentManager) QueryAssignedLicenses(req *types.QueryAssignedLicenses) soap.HasFault {
body := &methods.QueryAssignedLicensesBody{
Res: &types.QueryAssignedLicensesResponse{},
}
// EntityId can be a HostSystem or the vCenter InstanceUuid
if req.EntityId != "" {
if req.EntityId != Map.content().About.InstanceUuid {
id := types.ManagedObjectReference{
Type: "HostSystem",
Value: req.EntityId,
}
if Map.Get(id) == nil {
return body
}
}
}
body.Res.Returnval = []types.LicenseAssignmentManagerLicenseAssignment{
{
EntityId: req.EntityId,
AssignedLicense: EvalLicense,
},
}
return body
}
func licenseInfo(key string, labels []types.KeyValue) types.LicenseManagerLicenseInfo {
info := EvalLicense
info.LicenseKey = key
info.Labels = labels
return info
}

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

@@ -0,0 +1,484 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"context"
"fmt"
"io/ioutil"
"os"
"path"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/simulator/esx"
"github.com/vmware/govmomi/simulator/vpx"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
// Model is used to populate a Model with an initial set of managed entities.
// This is a simple helper for tests running against a simulator, to populate an inventory
// with commonly used models.
type Model struct {
Service *Service
ServiceContent types.ServiceContent
RootFolder mo.Folder
// Autostart will power on Model created VMs when true
Autostart bool
// Datacenter specifies the number of Datacenter entities to create
Datacenter int
// Portgroup specifies the number of DistributedVirtualPortgroup entities to create per Datacenter
Portgroup int
// Host specifies the number of standalone HostSystems entities to create per Datacenter
Host int
// Cluster specifies the number of ClusterComputeResource entities to create per Datacenter
Cluster int
// ClusterHost specifies the number of HostSystems entities to create within a Cluster
ClusterHost int
// Pool specifies the number of ResourcePool entities to create per Cluster
Pool int
// Datastore specifies the number of Datastore entities to create
// Each Datastore will have temporary local file storage and will be mounted
// on every HostSystem created by the ModelConfig
Datastore int
// Machine specifies the number of VirtualMachine entities to create per ResourcePool
Machine int
// Folder specifies the number of Datacenter to place within a Folder.
// This includes a folder for the Datacenter itself and its host, vm, network and datastore folders.
// All resources for the Datacenter are placed within these folders, rather than the top-level folders.
Folder int
// App specifies the number of VirtualApp to create per Cluster
App int
// Pod specifies the number of StoragePod to create per Cluster
Pod int
// total number of inventory objects, set by Count()
total int
dirs []string
}
// ESX is the default Model for a standalone ESX instance
func ESX() *Model {
return &Model{
ServiceContent: esx.ServiceContent,
RootFolder: esx.RootFolder,
Autostart: true,
Datastore: 1,
Machine: 2,
}
}
// VPX is the default Model for a vCenter instance
func VPX() *Model {
return &Model{
ServiceContent: vpx.ServiceContent,
RootFolder: vpx.RootFolder,
Autostart: true,
Datacenter: 1,
Portgroup: 1,
Host: 1,
Cluster: 1,
ClusterHost: 3,
Datastore: 1,
Machine: 2,
}
}
// Count returns a Model with total number of each existing type
func (m *Model) Count() Model {
count := Model{}
for ref, obj := range Map.objects {
if _, ok := obj.(mo.Entity); !ok {
continue
}
count.total++
switch ref.Type {
case "Datacenter":
count.Datacenter++
case "DistributedVirtualPortgroup":
count.Portgroup++
case "ClusterComputeResource":
count.Cluster++
case "Datastore":
count.Datastore++
case "HostSystem":
count.Host++
case "VirtualMachine":
count.Machine++
case "ResourcePool":
count.Pool++
case "VirtualApp":
count.App++
case "Folder":
count.Folder++
case "StoragePod":
count.Pod++
}
}
return count
}
func (*Model) fmtName(prefix string, num int) string {
return fmt.Sprintf("%s%d", prefix, num)
}
// Create populates the Model with the given ModelConfig
func (m *Model) Create() error {
m.Service = New(NewServiceInstance(m.ServiceContent, m.RootFolder))
ctx := context.Background()
client := m.Service.client
root := object.NewRootFolder(client)
// After all hosts are created, this var is used to mount the host datastores.
var hosts []*object.HostSystem
// We need to defer VM creation until after the datastores are created.
var vms []func() error
// 1 DVS per DC, added to all hosts
var dvs *object.DistributedVirtualSwitch
// 1 NIC per VM, backed by a DVPG if Model.Portgroup > 0
vmnet := esx.EthernetCard.Backing
// addHost adds a cluster host or a stanalone host.
addHost := func(name string, f func(types.HostConnectSpec) (*object.Task, error)) (*object.HostSystem, error) {
spec := types.HostConnectSpec{
HostName: name,
}
task, err := f(spec)
if err != nil {
return nil, err
}
info, err := task.WaitForResult(context.Background(), nil)
if err != nil {
return nil, err
}
host := object.NewHostSystem(client, info.Result.(types.ManagedObjectReference))
hosts = append(hosts, host)
if dvs != nil {
config := &types.DVSConfigSpec{
Host: []types.DistributedVirtualSwitchHostMemberConfigSpec{{
Operation: string(types.ConfigSpecOperationAdd),
Host: host.Reference(),
}},
}
_, _ = dvs.Reconfigure(ctx, config)
}
return host, nil
}
// addMachine returns a func to create a VM.
addMachine := func(prefix string, host *object.HostSystem, pool *object.ResourcePool, folders *object.DatacenterFolders) {
nic := esx.EthernetCard
nic.Backing = vmnet
ds := types.ManagedObjectReference{}
f := func() error {
for i := 0; i < m.Machine; i++ {
name := m.fmtName(prefix+"_VM", i)
config := types.VirtualMachineConfigSpec{
Name: name,
GuestId: string(types.VirtualMachineGuestOsIdentifierOtherGuest),
Files: &types.VirtualMachineFileInfo{
VmPathName: "[LocalDS_0]",
},
}
if pool == nil {
pool, _ = host.ResourcePool(ctx)
}
var devices object.VirtualDeviceList
scsi, _ := devices.CreateSCSIController("pvscsi")
ide, _ := devices.CreateIDEController()
cdrom, _ := devices.CreateCdrom(ide.(*types.VirtualIDEController))
disk := devices.CreateDisk(scsi.(types.BaseVirtualController), ds,
config.Files.VmPathName+" "+path.Join(name, "disk1.vmdk"))
devices = append(devices, scsi, cdrom, disk, &nic)
config.DeviceChange, _ = devices.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd)
task, err := folders.VmFolder.CreateVM(ctx, config, pool, host)
if err != nil {
return err
}
info, err := task.WaitForResult(ctx, nil)
if err != nil {
return err
}
vm := object.NewVirtualMachine(client, info.Result.(types.ManagedObjectReference))
if m.Autostart {
_, _ = vm.PowerOn(ctx)
}
}
return nil
}
vms = append(vms, f)
}
nfolder := 0
for ndc := 0; ndc < m.Datacenter; ndc++ {
dcName := m.fmtName("DC", ndc)
folder := root
fName := m.fmtName("F", nfolder)
// If Datacenter > Folder, don't create folders for the first N DCs.
if nfolder < m.Folder && ndc >= (m.Datacenter-m.Folder) {
f, err := folder.CreateFolder(ctx, fName)
if err != nil {
return err
}
folder = f
}
dc, err := folder.CreateDatacenter(ctx, dcName)
if err != nil {
return err
}
folders, err := dc.Folders(ctx)
if err != nil {
return err
}
if m.Pod > 0 {
for pod := 0; pod < m.Pod; pod++ {
_, _ = folders.DatastoreFolder.CreateStoragePod(ctx, m.fmtName(dcName+"_POD", pod))
}
}
if folder != root {
// Create sub-folders and use them to create any resources that follow
subs := []**object.Folder{&folders.DatastoreFolder, &folders.HostFolder, &folders.NetworkFolder, &folders.VmFolder}
for _, sub := range subs {
f, err := (*sub).CreateFolder(ctx, fName)
if err != nil {
return err
}
*sub = f
}
nfolder++
}
if m.Portgroup > 0 {
var spec types.DVSCreateSpec
spec.ConfigSpec = &types.VMwareDVSConfigSpec{}
spec.ConfigSpec.GetDVSConfigSpec().Name = m.fmtName("DVS", 0)
task, err := folders.NetworkFolder.CreateDVS(ctx, spec)
if err != nil {
return err
}
info, err := task.WaitForResult(ctx, nil)
if err != nil {
return err
}
dvs = object.NewDistributedVirtualSwitch(client, info.Result.(types.ManagedObjectReference))
for npg := 0; npg < m.Portgroup; npg++ {
name := m.fmtName(dcName+"_DVPG", npg)
task, err = dvs.AddPortgroup(ctx, []types.DVPortgroupConfigSpec{{Name: name}})
if err != nil {
return err
}
err = task.Wait(ctx)
if err != nil {
return err
}
// Use the 1st DVPG for the VMs eth0 backing
if npg == 0 {
// AddPortgroup_Task does not return the moid, so we look it up by name
net := Map.Get(folders.NetworkFolder.Reference()).(*Folder)
pg := Map.FindByName(name, net.ChildEntity)
vmnet, _ = object.NewDistributedVirtualPortgroup(client, pg.Reference()).EthernetCardBackingInfo(ctx)
}
}
}
for nhost := 0; nhost < m.Host; nhost++ {
name := m.fmtName(dcName+"_H", nhost)
host, err := addHost(name, func(spec types.HostConnectSpec) (*object.Task, error) {
return folders.HostFolder.AddStandaloneHost(ctx, spec, true, nil, nil)
})
if err != nil {
return err
}
addMachine(name, host, nil, folders)
}
for ncluster := 0; ncluster < m.Cluster; ncluster++ {
clusterName := m.fmtName(dcName+"_C", ncluster)
cluster, err := folders.HostFolder.CreateCluster(ctx, clusterName, types.ClusterConfigSpecEx{})
if err != nil {
return err
}
for nhost := 0; nhost < m.ClusterHost; nhost++ {
name := m.fmtName(clusterName+"_H", nhost)
_, err = addHost(name, func(spec types.HostConnectSpec) (*object.Task, error) {
return cluster.AddHost(ctx, spec, true, nil, nil)
})
if err != nil {
return err
}
}
pool, err := cluster.ResourcePool(ctx)
if err != nil {
return err
}
prefix := clusterName + "_RP"
addMachine(prefix+"0", nil, pool, folders)
for npool := 1; npool <= m.Pool; npool++ {
spec := types.DefaultResourceConfigSpec()
_, err = pool.Create(ctx, m.fmtName(prefix, npool), spec)
if err != nil {
return err
}
}
prefix = clusterName + "_APP"
for napp := 0; napp < m.App; napp++ {
rspec := types.DefaultResourceConfigSpec()
vspec := NewVAppConfigSpec()
name := m.fmtName(prefix, napp)
vapp, err := pool.CreateVApp(ctx, name, rspec, vspec, nil)
if err != nil {
return err
}
addMachine(name, nil, vapp.ResourcePool, folders)
}
}
}
if m.ServiceContent.RootFolder == esx.RootFolder.Reference() {
// ESX model
host := object.NewHostSystem(client, esx.HostSystem.Reference())
hosts = append(hosts, host)
dc := object.NewDatacenter(client, esx.Datacenter.Reference())
folders, err := dc.Folders(ctx)
if err != nil {
return err
}
addMachine(host.Reference().Value, host, nil, folders)
}
for i := 0; i < m.Datastore; i++ {
err := m.createLocalDatastore(m.fmtName("LocalDS_", i), hosts)
if err != nil {
return err
}
}
for _, createVM := range vms {
err := createVM()
if err != nil {
return err
}
}
return nil
}
var tempDir = func() (string, error) {
return ioutil.TempDir("", "govcsim-")
}
func (m *Model) createLocalDatastore(name string, hosts []*object.HostSystem) error {
ctx := context.Background()
dir, err := tempDir()
if err != nil {
return err
}
m.dirs = append(m.dirs, dir)
for _, host := range hosts {
dss, err := host.ConfigManager().DatastoreSystem(ctx)
if err != nil {
return err
}
_, err = dss.CreateLocalDatastore(ctx, name, dir)
if err != nil {
return err
}
}
return nil
}
// Remove cleans up items created by the Model, such as local datastore directories
func (m *Model) Remove() {
for _, dir := range m.dirs {
_ = os.RemoveAll(dir)
}
}

View File

@@ -0,0 +1,59 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"strings"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type OptionManager struct {
mo.OptionManager
}
func NewOptionManager(ref *types.ManagedObjectReference, setting []types.BaseOptionValue) object.Reference {
s := &OptionManager{}
if ref != nil {
s.Self = *ref
}
s.Setting = setting
return s
}
func (m *OptionManager) QueryOptions(req *types.QueryOptions) soap.HasFault {
body := &methods.QueryOptionsBody{}
res := &types.QueryOptionsResponse{}
for _, opt := range m.Setting {
if strings.HasPrefix(opt.GetOptionValue().Key, req.Name) {
res.Returnval = append(res.Returnval, opt)
}
}
if len(res.Returnval) == 0 {
body.Fault_ = Fault("", &types.InvalidName{Name: req.Name})
} else {
body.Res = res
}
return body
}

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

@@ -0,0 +1,38 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import "syscall"
func (ds *Datastore) stat() error {
info := ds.Info.GetDatastoreInfo()
var stat syscall.Statfs_t
err := syscall.Statfs(info.Url, &stat)
if err != nil {
return err
}
bsize := uint64(stat.Bsize) / 512
info.FreeSpace = int64(stat.Bfree*bsize) >> 1
ds.Summary.FreeSpace = info.FreeSpace
ds.Summary.Capacity = int64(stat.Blocks*bsize) >> 1
return nil
}

View File

@@ -0,0 +1,26 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import "os"
func (ds *Datastore) stat() error {
info := ds.Info.GetDatastoreInfo()
_, err := os.Stat(info.Url)
return err
}

View File

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

View File

@@ -0,0 +1,82 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type DistributedVirtualPortgroup struct {
mo.DistributedVirtualPortgroup
}
func (s *DistributedVirtualPortgroup) ReconfigureDVPortgroupTask(req *types.ReconfigureDVPortgroup_Task) soap.HasFault {
task := CreateTask(s, "reconfigureDvPortgroup", func(t *Task) (types.AnyType, types.BaseMethodFault) {
s.Config.DefaultPortConfig = req.Spec.DefaultPortConfig
s.Config.NumPorts = req.Spec.NumPorts
s.Config.AutoExpand = req.Spec.AutoExpand
s.Config.Type = req.Spec.Type
s.Config.Description = req.Spec.Description
s.Config.DynamicData = req.Spec.DynamicData
s.Config.Name = req.Spec.Name
s.Config.Policy = req.Spec.Policy
s.Config.PortNameFormat = req.Spec.PortNameFormat
s.Config.VmVnicNetworkResourcePoolKey = req.Spec.VmVnicNetworkResourcePoolKey
return nil, nil
})
return &methods.ReconfigureDVPortgroup_TaskBody{
Res: &types.ReconfigureDVPortgroup_TaskResponse{
Returnval: task.Run(),
},
}
}
func (s *DistributedVirtualPortgroup) DestroyTask(req *types.Destroy_Task) soap.HasFault {
task := CreateTask(s, "destroy", func(t *Task) (types.AnyType, types.BaseMethodFault) {
vswitch := Map.Get(*s.Config.DistributedVirtualSwitch).(*DistributedVirtualSwitch)
for i, pg := range vswitch.Portgroup {
if pg.Reference() == s.Reference() {
vswitch.Portgroup = append(vswitch.Portgroup[:i], vswitch.Portgroup[i+1:]...)
break
}
}
f := Map.getEntityParent(vswitch, "Folder").(*Folder)
f.removeChild(s.Reference())
for i, name := range vswitch.Summary.PortgroupName {
if name == s.Name {
vswitch.Summary.PortgroupName = append(vswitch.Summary.PortgroupName[:i],
vswitch.Summary.PortgroupName[i+1:]...)
}
}
return nil, nil
})
return &methods.Destroy_TaskBody{
Res: &types.Destroy_TaskResponse{
Returnval: task.Run(),
},
}
}

View File

@@ -0,0 +1,548 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"errors"
"log"
"path"
"reflect"
"strings"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type PropertyCollector struct {
mo.PropertyCollector
}
func NewPropertyCollector(ref types.ManagedObjectReference) object.Reference {
s := &PropertyCollector{}
s.Self = ref
return s
}
var errMissingField = errors.New("missing field")
var errEmptyField = errors.New("empty field")
func getObject(ref types.ManagedObjectReference) (reflect.Value, bool) {
obj := Map.Get(ref)
if obj == nil {
return reflect.Value{}, false
}
rval := reflect.ValueOf(obj).Elem()
rtype := rval.Type()
// PropertyCollector is for Managed Object types only (package mo).
// If the registry object is not in the mo package, assume it is a wrapper
// type where the first field is an embedded mo type.
// We need to dig out the mo type for PropSet.All to work properly and
// for the case where the type has a field of the same name, for example:
// mo.ResourcePool.ResourcePool
for {
if path.Base(rtype.PkgPath()) != "mo" {
if rtype.Kind() != reflect.Struct || rtype.NumField() == 0 {
log.Printf("%#v does not have an embedded mo type", ref)
return reflect.Value{}, false
}
rval = rval.Field(0)
rtype = rval.Type()
} else {
break
}
}
return rval, true
}
func fieldValueInterface(f reflect.StructField, rval reflect.Value) interface{} {
if rval.Kind() == reflect.Ptr {
rval = rval.Elem()
}
pval := rval.Interface()
if rval.Kind() == reflect.Slice {
// Convert slice to types.ArrayOf*
switch v := pval.(type) {
case []string:
pval = &types.ArrayOfString{
String: v,
}
case []int32:
pval = &types.ArrayOfInt{
Int: v,
}
default:
kind := f.Type.Elem().Name()
// Remove govmomi interface prefix name
if strings.HasPrefix(kind, "Base") {
kind = kind[4:]
}
akind, _ := typeFunc("ArrayOf" + kind)
a := reflect.New(akind)
a.Elem().FieldByName(kind).Set(rval)
pval = a.Interface()
}
}
return pval
}
func fieldValue(rval reflect.Value, p string) (interface{}, error) {
var value interface{}
fields := strings.Split(p, ".")
for i, name := range fields {
kind := rval.Type().Kind()
if kind == reflect.Interface {
if rval.IsNil() {
continue
}
rval = rval.Elem()
kind = rval.Type().Kind()
}
if kind == reflect.Ptr {
if rval.IsNil() {
continue
}
rval = rval.Elem()
}
x := ucFirst(name)
val := rval.FieldByName(x)
if !val.IsValid() {
return nil, errMissingField
}
if isEmpty(val) {
return nil, errEmptyField
}
if i == len(fields)-1 {
ftype, _ := rval.Type().FieldByName(x)
value = fieldValueInterface(ftype, val)
break
}
rval = val
}
return value, nil
}
func fieldRefs(f interface{}) []types.ManagedObjectReference {
switch fv := f.(type) {
case types.ManagedObjectReference:
return []types.ManagedObjectReference{fv}
case *types.ArrayOfManagedObjectReference:
return fv.ManagedObjectReference
case nil:
// empty field
}
return nil
}
func isEmpty(rval reflect.Value) bool {
switch rval.Kind() {
case reflect.Ptr:
return rval.IsNil()
case reflect.String, reflect.Slice:
return rval.Len() == 0
}
return false
}
func isTrue(v *bool) bool {
return v != nil && *v
}
func isFalse(v *bool) bool {
return v == nil || *v == false
}
func lcFirst(s string) string {
return strings.ToLower(s[:1]) + s[1:]
}
func ucFirst(s string) string {
return strings.ToUpper(s[:1]) + s[1:]
}
type retrieveResult struct {
*types.RetrieveResult
req *types.RetrievePropertiesEx
collected map[types.ManagedObjectReference]bool
specs map[string]*types.TraversalSpec
}
func (rr *retrieveResult) collectAll(rval reflect.Value, rtype reflect.Type, content *types.ObjectContent) {
for i := 0; i < rval.NumField(); i++ {
val := rval.Field(i)
f := rtype.Field(i)
if isEmpty(val) || f.Name == "Self" {
continue
}
if f.Anonymous {
// recurse into embedded field
rr.collectAll(val, f.Type, content)
continue
}
content.PropSet = append(content.PropSet, types.DynamicProperty{
Name: lcFirst(f.Name),
Val: fieldValueInterface(f, val),
})
}
}
func (rr *retrieveResult) collectFields(rval reflect.Value, fields []string, content *types.ObjectContent) {
seen := make(map[string]bool)
for i := range content.PropSet {
seen[content.PropSet[i].Name] = true // mark any already collected via embedded field
}
for _, name := range fields {
if seen[name] {
// rvc 'ls' includes the "name" property twice, then fails with no error message or stack trace
// in RbVmomi::VIM::ObjectContent.to_hash_uncached when it sees the 2nd "name" property.
continue
}
seen[name] = true
val, err := fieldValue(rval, name)
if err == nil {
prop := types.DynamicProperty{
Name: name,
Val: val,
}
content.PropSet = append(content.PropSet, prop)
continue
}
switch err {
case errEmptyField:
// ok
case errMissingField:
content.MissingSet = append(content.MissingSet, types.MissingProperty{
Path: name,
Fault: types.LocalizedMethodFault{Fault: &types.InvalidProperty{
Name: name,
}},
})
}
}
}
func (rr *retrieveResult) collect(ref types.ManagedObjectReference) {
if rr.collected[ref] {
return
}
content := types.ObjectContent{
Obj: ref,
}
rval, ok := getObject(ref)
if !ok {
// Possible if a test uses Map.Remove instead of Destroy_Task
log.Printf("object %s no longer exists", ref)
return
}
rtype := rval.Type()
for _, spec := range rr.req.SpecSet {
for _, p := range spec.PropSet {
if p.Type != ref.Type {
// e.g. ManagedEntity, ComputeResource
field, ok := rtype.FieldByName(p.Type)
if !(ok && field.Anonymous) {
continue
}
}
if isTrue(p.All) {
rr.collectAll(rval, rtype, &content)
continue
}
rr.collectFields(rval, p.PathSet, &content)
}
}
if len(content.PropSet) != 0 || len(content.MissingSet) != 0 {
rr.Objects = append(rr.Objects, content)
}
rr.collected[ref] = true
}
func (rr *retrieveResult) selectSet(obj reflect.Value, s []types.BaseSelectionSpec, refs *[]types.ManagedObjectReference) types.BaseMethodFault {
for _, ss := range s {
ts, ok := ss.(*types.TraversalSpec)
if ok {
if ts.Name != "" {
rr.specs[ts.Name] = ts
}
}
}
for _, ss := range s {
ts, ok := ss.(*types.TraversalSpec)
if !ok {
ts = rr.specs[ss.GetSelectionSpec().Name]
if ts == nil {
return &types.InvalidArgument{InvalidProperty: "undefined TraversalSpec name"}
}
}
f, _ := fieldValue(obj, ts.Path)
for _, ref := range fieldRefs(f) {
if isFalse(ts.Skip) {
*refs = append(*refs, ref)
}
rval, ok := getObject(ref)
if ok {
if err := rr.selectSet(rval, ts.SelectSet, refs); err != nil {
return err
}
}
}
}
return nil
}
func (pc *PropertyCollector) collect(r *types.RetrievePropertiesEx) (*types.RetrieveResult, types.BaseMethodFault) {
var refs []types.ManagedObjectReference
rr := &retrieveResult{
RetrieveResult: &types.RetrieveResult{},
req: r,
collected: make(map[types.ManagedObjectReference]bool),
specs: make(map[string]*types.TraversalSpec),
}
// Select object references
for _, spec := range r.SpecSet {
for _, o := range spec.ObjectSet {
rval, ok := getObject(o.Obj)
if !ok {
if isFalse(spec.ReportMissingObjectsInResults) {
return nil, &types.ManagedObjectNotFound{Obj: o.Obj}
}
continue
}
if o.SelectSet == nil || isFalse(o.Skip) {
refs = append(refs, o.Obj)
}
if err := rr.selectSet(rval, o.SelectSet, &refs); err != nil {
return nil, err
}
}
}
for _, ref := range refs {
rr.collect(ref)
}
return rr.RetrieveResult, nil
}
func (pc *PropertyCollector) CreateFilter(c *types.CreateFilter) soap.HasFault {
body := &methods.CreateFilterBody{}
filter := &PropertyFilter{pc: pc}
filter.PartialUpdates = c.PartialUpdates
filter.Spec = c.Spec
pc.Filter = append(pc.Filter, Map.Put(filter).Reference())
body.Res = &types.CreateFilterResponse{
Returnval: filter.Self,
}
return body
}
func (pc *PropertyCollector) CreatePropertyCollector(c *types.CreatePropertyCollector) soap.HasFault {
body := &methods.CreatePropertyCollectorBody{}
cpc := &PropertyCollector{}
body.Res = &types.CreatePropertyCollectorResponse{
Returnval: Map.Put(cpc).Reference(),
}
return body
}
func (pc *PropertyCollector) DestroyPropertyCollector(c *types.DestroyPropertyCollector) soap.HasFault {
body := &methods.DestroyPropertyCollectorBody{}
for _, ref := range pc.Filter {
filter := Map.Get(ref).(*PropertyFilter)
filter.DestroyPropertyFilter(&types.DestroyPropertyFilter{This: ref})
}
Map.Remove(c.This)
body.Res = &types.DestroyPropertyCollectorResponse{}
return body
}
func (pc *PropertyCollector) RetrievePropertiesEx(r *types.RetrievePropertiesEx) soap.HasFault {
body := &methods.RetrievePropertiesExBody{}
res, fault := pc.collect(r)
if fault != nil {
body.Fault_ = Fault("", fault)
} else {
body.Res = &types.RetrievePropertiesExResponse{
Returnval: res,
}
}
return body
}
// RetrieveProperties is deprecated, but govmomi is still using it at the moment.
func (pc *PropertyCollector) RetrieveProperties(r *types.RetrieveProperties) soap.HasFault {
body := &methods.RetrievePropertiesBody{}
res := pc.RetrievePropertiesEx(&types.RetrievePropertiesEx{
This: r.This,
SpecSet: r.SpecSet,
})
if res.Fault() != nil {
body.Fault_ = res.Fault()
} else {
body.Res = &types.RetrievePropertiesResponse{
Returnval: res.(*methods.RetrievePropertiesExBody).Res.Returnval.Objects,
}
}
return body
}
func (pc *PropertyCollector) CancelWaitForUpdates(r *types.CancelWaitForUpdates) soap.HasFault {
return &methods.CancelWaitForUpdatesBody{Res: new(types.CancelWaitForUpdatesResponse)}
}
func (pc *PropertyCollector) WaitForUpdatesEx(r *types.WaitForUpdatesEx) soap.HasFault {
body := &methods.WaitForUpdatesExBody{}
// At the moment we need to support Task completion. Handlers can simply set the Task
// state before returning and the non-incremental update is enough for the client.
// We can wait for incremental updates to simulate timeouts, etc.
if r.Version != "" {
body.Fault_ = Fault("incremental updates not supported yet", &types.NotSupported{})
return body
}
update := &types.UpdateSet{
Version: "-",
}
for _, ref := range pc.Filter {
filter := Map.Get(ref).(*PropertyFilter)
r := &types.RetrievePropertiesEx{}
r.SpecSet = append(r.SpecSet, filter.Spec)
res, fault := pc.collect(r)
if fault != nil {
body.Fault_ = Fault("", fault)
return body
}
fu := types.PropertyFilterUpdate{
Filter: ref,
}
for _, o := range res.Objects {
ou := types.ObjectUpdate{
Obj: o.Obj,
Kind: types.ObjectUpdateKindEnter,
}
for _, p := range o.PropSet {
ou.ChangeSet = append(ou.ChangeSet, types.PropertyChange{
Op: types.PropertyChangeOpAssign,
Name: p.Name,
Val: p.Val,
})
}
fu.ObjectSet = append(fu.ObjectSet, ou)
}
update.FilterSet = append(update.FilterSet, fu)
}
body.Res = &types.WaitForUpdatesExResponse{
Returnval: update,
}
return body
}
// WaitForUpdates is deprecated, but pyvmomi is still using it at the moment.
func (pc *PropertyCollector) WaitForUpdates(r *types.WaitForUpdates) soap.HasFault {
body := &methods.WaitForUpdatesBody{}
res := pc.WaitForUpdatesEx(&types.WaitForUpdatesEx{
This: r.This,
Version: r.Version,
})
if res.Fault() != nil {
body.Fault_ = res.Fault()
} else {
body.Res = &types.WaitForUpdatesResponse{
Returnval: *res.(*methods.WaitForUpdatesExBody).Res.Returnval,
}
}
return body
}

View File

@@ -0,0 +1,42 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type PropertyFilter struct {
mo.PropertyFilter
pc *PropertyCollector
}
func (f *PropertyFilter) DestroyPropertyFilter(c *types.DestroyPropertyFilter) soap.HasFault {
body := &methods.DestroyPropertyFilterBody{}
f.pc.Filter = RemoveReference(c.This, f.pc.Filter)
Map.Remove(c.This)
body.Res = &types.DestroyPropertyFilterResponse{}
return body
}

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

@@ -0,0 +1,338 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"fmt"
"reflect"
"strings"
"sync"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
// This is a map from a reference type name to a reference value name prefix.
// It's a convention that VirtualCenter follows. The map is not complete, but
// it should cover the most popular objects.
var refValueMap = map[string]string{
"DistributedVirtualPortgroup": "dvportgroup",
"EnvironmentBrowser": "envbrowser",
"HostSystem": "host",
"ResourcePool": "resgroup",
"VirtualMachine": "vm",
"VirtualMachineSnapshot": "snapshot",
"VmwareDistributedVirtualSwitch": "dvs",
}
// Map is the default Registry instance.
var Map = NewRegistry()
// RegisterObject interface supports callbacks when objects are added and removed from the Registry
type RegisterObject interface {
mo.Reference
PutObject(mo.Reference)
RemoveObject(types.ManagedObjectReference)
}
// Registry manages a map of mo.Reference objects
type Registry struct {
m sync.Mutex
objects map[types.ManagedObjectReference]mo.Reference
handlers map[types.ManagedObjectReference]RegisterObject
counter int
}
// NewRegistry creates a new instances of Registry
func NewRegistry() *Registry {
r := &Registry{
objects: make(map[types.ManagedObjectReference]mo.Reference),
handlers: make(map[types.ManagedObjectReference]RegisterObject),
}
return r
}
// typeName returns the type of the given object.
func typeName(item mo.Reference) string {
return reflect.TypeOf(item).Elem().Name()
}
// valuePrefix returns the value name prefix of a given object
func valuePrefix(typeName string) string {
if v, ok := refValueMap[typeName]; ok {
return v
}
return strings.ToLower(typeName)
}
// newReference returns a new MOR, where Type defaults to type of the given item
// and Value defaults to a unique id for the given type.
func (r *Registry) newReference(item mo.Reference) types.ManagedObjectReference {
ref := item.Reference()
if ref.Type == "" {
ref.Type = typeName(item)
}
if ref.Value == "" {
r.counter++
ref.Value = fmt.Sprintf("%s-%d", valuePrefix(ref.Type), r.counter)
}
return ref
}
// AddHandler adds a RegisterObject handler to the Registry.
func (r *Registry) AddHandler(h RegisterObject) {
r.handlers[h.Reference()] = h
}
// NewEntity sets Entity().Self with a new, unique Value.
// Useful for creating object instances from templates.
func (r *Registry) NewEntity(item mo.Entity) mo.Entity {
e := item.Entity()
e.Self.Value = ""
e.Self = r.newReference(item)
return item
}
// PutEntity sets item.Parent to that of parent.Self before adding item to the Registry.
func (r *Registry) PutEntity(parent mo.Entity, item mo.Entity) mo.Entity {
e := item.Entity()
if parent != nil {
e.Parent = &parent.Entity().Self
}
r.Put(item)
return item
}
// Get returns the object for the given reference.
func (r *Registry) Get(ref types.ManagedObjectReference) mo.Reference {
r.m.Lock()
defer r.m.Unlock()
return r.objects[ref]
}
// Any returns the first instance of entity type specified by kind.
func (r *Registry) Any(kind string) mo.Entity {
r.m.Lock()
defer r.m.Unlock()
for ref, val := range r.objects {
if ref.Type == kind {
return val.(mo.Entity)
}
}
return nil
}
// Put adds a new object to Registry, generating a ManagedObjectReference if not already set.
func (r *Registry) Put(item mo.Reference) mo.Reference {
r.m.Lock()
defer r.m.Unlock()
ref := item.Reference()
if ref.Type == "" || ref.Value == "" {
ref = r.newReference(item)
// mo.Reference() returns a value, not a pointer so use reflect to set the Self field
reflect.ValueOf(item).Elem().FieldByName("Self").Set(reflect.ValueOf(ref))
}
if me, ok := item.(mo.Entity); ok {
me.Entity().ConfigStatus = types.ManagedEntityStatusGreen
me.Entity().OverallStatus = types.ManagedEntityStatusGreen
me.Entity().EffectiveRole = []int32{-1} // Admin
}
r.objects[ref] = item
for _, h := range r.handlers {
h.PutObject(item)
}
return item
}
// Remove removes an object from the Registry.
func (r *Registry) Remove(item types.ManagedObjectReference) {
r.m.Lock()
defer r.m.Unlock()
for _, h := range r.handlers {
h.RemoveObject(item)
}
delete(r.objects, item)
delete(r.handlers, item)
}
// getEntityParent traverses up the inventory and returns the first object of type kind.
// If no object of type kind is found, the method will panic when it reaches the
// inventory root Folder where the Parent field is nil.
func (r *Registry) getEntityParent(item mo.Entity, kind string) mo.Entity {
for {
parent := item.Entity().Parent
item = r.Get(*parent).(mo.Entity)
if item.Reference().Type == kind {
return item
}
}
}
// getEntityDatacenter returns the Datacenter containing the given item
func (r *Registry) getEntityDatacenter(item mo.Entity) *mo.Datacenter {
return r.getEntityParent(item, "Datacenter").(*mo.Datacenter)
}
func (r *Registry) getEntityFolder(item mo.Entity, kind string) *Folder {
dc := Map.getEntityDatacenter(item)
var ref types.ManagedObjectReference
switch kind {
case "datastore":
ref = dc.DatastoreFolder
}
folder := r.Get(ref).(*Folder)
// If Model was created with Folder option, use that Folder; else use top-level folder
for _, child := range folder.ChildEntity {
if child.Type == "Folder" {
folder = Map.Get(child).(*Folder)
break
}
}
return folder
}
// getEntityComputeResource returns the ComputeResource parent for the given item.
// A ResourcePool for example may have N Parents of type ResourcePool, but the top
// most Parent pool is always a ComputeResource child.
func (r *Registry) getEntityComputeResource(item mo.Entity) mo.Entity {
for {
parent := item.Entity().Parent
item = r.Get(*parent).(mo.Entity)
switch item.Reference().Type {
case "ComputeResource":
return item
case "ClusterComputeResource":
return item
}
}
}
// FindByName returns the first mo.Entity of the given refs whose Name field is equal to the given name.
// If there is no match, nil is returned.
// This method is useful for cases where objects are required to have a unique name, such as Datastore with
// a HostStorageSystem or HostSystem within a ClusterComputeResource.
func (r *Registry) FindByName(name string, refs []types.ManagedObjectReference) mo.Entity {
for _, ref := range refs {
if e, ok := r.Get(ref).(mo.Entity); ok {
if name == e.Entity().Name {
return e
}
}
}
return nil
}
// FindReference returns the 1st match found in refs, or nil if not found.
func FindReference(refs []types.ManagedObjectReference, match ...types.ManagedObjectReference) *types.ManagedObjectReference {
for _, ref := range refs {
for _, m := range match {
if ref == m {
return &ref
}
}
}
return nil
}
// RemoveReference returns a slice with ref removed from refs
func RemoveReference(ref types.ManagedObjectReference, refs []types.ManagedObjectReference) []types.ManagedObjectReference {
var result []types.ManagedObjectReference
for i, r := range refs {
if r == ref {
result = append(result, refs[i+1:]...)
break
}
result = append(result, r)
}
return result
}
// AddReference returns a slice with ref appended if not already in refs.
func AddReference(ref types.ManagedObjectReference, refs []types.ManagedObjectReference) []types.ManagedObjectReference {
if FindReference(refs, ref) == nil {
return append(refs, ref)
}
return refs
}
func (r *Registry) content() types.ServiceContent {
return r.Get(methods.ServiceInstance).(*ServiceInstance).Content
}
// IsESX returns true if this Registry maps an ESX model
func (r *Registry) IsESX() bool {
return r.content().About.ApiType == "HostAgent"
}
// IsVPX returns true if this Registry maps a VPX model
func (r *Registry) IsVPX() bool {
return !r.IsESX()
}
// SearchIndex returns the SearchIndex singleton
func (r *Registry) SearchIndex() *SearchIndex {
return r.Get(r.content().SearchIndex.Reference()).(*SearchIndex)
}
// FileManager returns the FileManager singleton
func (r *Registry) FileManager() *FileManager {
return r.Get(r.content().FileManager.Reference()).(*FileManager)
}
// VirtualDiskManager returns the VirtualDiskManager singleton
func (r *Registry) VirtualDiskManager() *VirtualDiskManager {
return r.Get(r.content().VirtualDiskManager.Reference()).(*VirtualDiskManager)
}
// ViewManager returns the ViewManager singleton
func (r *Registry) ViewManager() *ViewManager {
return r.Get(r.content().ViewManager.Reference()).(*ViewManager)
}

View File

@@ -0,0 +1,312 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"fmt"
"strings"
"github.com/vmware/govmomi/simulator/esx"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type ResourcePool struct {
mo.ResourcePool
}
func NewResourcePool() *ResourcePool {
pool := &ResourcePool{
ResourcePool: esx.ResourcePool,
}
if Map.IsVPX() {
pool.DisabledMethod = nil // Enable VApp methods for VC
}
return pool
}
func allResourceFieldsSet(info *types.ResourceAllocationInfo) bool {
return info.Reservation != nil &&
info.Limit != nil &&
info.ExpandableReservation != nil &&
info.Shares != nil
}
func allResourceFieldsValid(info *types.ResourceAllocationInfo) bool {
if info.Reservation != nil {
if *info.Reservation < 0 {
return false
}
}
if info.Limit != nil {
if *info.Limit < -1 {
return false
}
}
if info.Shares != nil {
if info.Shares.Level == types.SharesLevelCustom {
if info.Shares.Shares < 0 {
return false
}
}
}
if info.OverheadLimit != nil {
return false
}
return true
}
func (p *ResourcePool) createChild(name string, spec types.ResourceConfigSpec) (*ResourcePool, *soap.Fault) {
if e := Map.FindByName(name, p.ResourcePool.ResourcePool); e != nil {
return nil, Fault("", &types.DuplicateName{
Name: e.Entity().Name,
Object: e.Reference(),
})
}
if !(allResourceFieldsSet(&spec.CpuAllocation) && allResourceFieldsValid(&spec.CpuAllocation)) {
return nil, Fault("", &types.InvalidArgument{
InvalidProperty: "spec.cpuAllocation",
})
}
if !(allResourceFieldsSet(&spec.MemoryAllocation) && allResourceFieldsValid(&spec.MemoryAllocation)) {
return nil, Fault("", &types.InvalidArgument{
InvalidProperty: "spec.memoryAllocation",
})
}
child := NewResourcePool()
child.Name = name
child.Owner = p.Owner
child.Summary.GetResourcePoolSummary().Name = name
child.Config.CpuAllocation = spec.CpuAllocation
child.Config.MemoryAllocation = spec.MemoryAllocation
child.Config.Entity = spec.Entity
return child, nil
}
func (p *ResourcePool) CreateResourcePool(c *types.CreateResourcePool) soap.HasFault {
body := &methods.CreateResourcePoolBody{}
child, err := p.createChild(c.Name, c.Spec)
if err != nil {
body.Fault_ = err
return body
}
Map.PutEntity(p, Map.NewEntity(child))
p.ResourcePool.ResourcePool = append(p.ResourcePool.ResourcePool, child.Reference())
body.Res = &types.CreateResourcePoolResponse{
Returnval: child.Reference(),
}
return body
}
func updateResourceAllocation(kind string, src, dst *types.ResourceAllocationInfo) types.BaseMethodFault {
if !allResourceFieldsValid(src) {
return &types.InvalidArgument{
InvalidProperty: fmt.Sprintf("spec.%sAllocation", kind),
}
}
if src.Reservation != nil {
dst.Reservation = src.Reservation
}
if src.Limit != nil {
dst.Limit = src.Limit
}
if src.Shares != nil {
dst.Shares = src.Shares
}
return nil
}
func (p *ResourcePool) UpdateConfig(c *types.UpdateConfig) soap.HasFault {
body := &methods.UpdateConfigBody{}
if c.Name != "" {
if e := Map.FindByName(c.Name, p.ResourcePool.ResourcePool); e != nil {
body.Fault_ = Fault("", &types.DuplicateName{
Name: e.Entity().Name,
Object: e.Reference(),
})
return body
}
p.Name = c.Name
}
spec := c.Config
if spec != nil {
if err := updateResourceAllocation("memory", &spec.MemoryAllocation, &p.Config.MemoryAllocation); err != nil {
body.Fault_ = Fault("", err)
return body
}
if err := updateResourceAllocation("cpu", &spec.CpuAllocation, &p.Config.CpuAllocation); err != nil {
body.Fault_ = Fault("", err)
return body
}
}
body.Res = &types.UpdateConfigResponse{}
return body
}
type VirtualApp struct {
mo.VirtualApp
}
func NewVAppConfigSpec() types.VAppConfigSpec {
spec := types.VAppConfigSpec{
Annotation: "vcsim",
VmConfigSpec: types.VmConfigSpec{
Product: []types.VAppProductSpec{
{
Info: &types.VAppProductInfo{
Name: "vcsim",
Vendor: "VMware",
VendorUrl: "http://www.vmware.com/",
Version: "0.1",
},
ArrayUpdateSpec: types.ArrayUpdateSpec{
Operation: types.ArrayUpdateOperationAdd,
},
},
},
},
}
return spec
}
func (p *ResourcePool) CreateVApp(req *types.CreateVApp) soap.HasFault {
body := &methods.CreateVAppBody{}
pool, err := p.createChild(req.Name, req.ResSpec)
if err != nil {
body.Fault_ = err
return body
}
child := &VirtualApp{}
child.ResourcePool = pool.ResourcePool
child.Self.Type = "VirtualApp"
child.ParentFolder = req.VmFolder
if child.ParentFolder == nil {
folder := Map.getEntityDatacenter(p).VmFolder
child.ParentFolder = &folder
}
child.VAppConfig = &types.VAppConfigInfo{
VmConfigInfo: types.VmConfigInfo{},
Annotation: req.ConfigSpec.Annotation,
}
for _, product := range req.ConfigSpec.Product {
child.VAppConfig.Product = append(child.VAppConfig.Product, *product.Info)
}
Map.PutEntity(p, Map.NewEntity(child))
p.ResourcePool.ResourcePool = append(p.ResourcePool.ResourcePool, child.Reference())
body.Res = &types.CreateVAppResponse{
Returnval: child.Reference(),
}
return body
}
func (a *VirtualApp) CreateChildVMTask(req *types.CreateChildVM_Task) soap.HasFault {
body := &methods.CreateChildVM_TaskBody{}
folder := Map.Get(*a.ParentFolder).(*Folder)
res := folder.CreateVMTask(&types.CreateVM_Task{
This: folder.Self,
Config: req.Config,
Host: req.Host,
Pool: req.This,
})
body.Res = &types.CreateChildVM_TaskResponse{
Returnval: res.(*methods.CreateVM_TaskBody).Res.Returnval,
}
return body
}
func (a *VirtualApp) DestroyTask(req *types.Destroy_Task) soap.HasFault {
return (&ResourcePool{ResourcePool: a.ResourcePool}).DestroyTask(req)
}
func (p *ResourcePool) DestroyTask(req *types.Destroy_Task) soap.HasFault {
task := CreateTask(p, "destroy", func(t *Task) (types.AnyType, types.BaseMethodFault) {
if strings.HasSuffix(p.Parent.Type, "ComputeResource") {
// Can't destroy the root pool
return nil, &types.InvalidArgument{}
}
pp := Map.Get(*p.Parent).(*ResourcePool)
parent := &pp.ResourcePool
// Remove child reference from rp
parent.ResourcePool = RemoveReference(req.This, parent.ResourcePool)
// The grandchildren become children of the parent (rp)
parent.ResourcePool = append(parent.ResourcePool, p.ResourcePool.ResourcePool...)
// And VMs move to the parent
vms := p.ResourcePool.Vm
for _, vm := range vms {
Map.Get(vm).(*VirtualMachine).ResourcePool = &parent.Self
}
parent.Vm = append(parent.Vm, vms...)
Map.Remove(req.This)
return nil, nil
})
return &methods.Destroy_TaskBody{
Res: &types.Destroy_TaskResponse{
Returnval: task.Run(),
},
}
}

View File

@@ -0,0 +1,155 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"strings"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type SearchIndex struct {
mo.SearchIndex
}
func NewSearchIndex(ref types.ManagedObjectReference) object.Reference {
m := &SearchIndex{}
m.Self = ref
return m
}
func (s *SearchIndex) FindByDatastorePath(r *types.FindByDatastorePath) soap.HasFault {
res := &methods.FindByDatastorePathBody{Res: new(types.FindByDatastorePathResponse)}
for ref, obj := range Map.objects {
vm, ok := obj.(*VirtualMachine)
if !ok {
continue
}
if vm.Config.Files.VmPathName == r.Path {
res.Res.Returnval = &ref
break
}
}
return res
}
func (s *SearchIndex) FindByInventoryPath(req *types.FindByInventoryPath) soap.HasFault {
body := &methods.FindByInventoryPathBody{Res: new(types.FindByInventoryPathResponse)}
path := strings.Split(req.InventoryPath, "/")
if len(path) <= 1 {
return body
}
root := Map.content().RootFolder
o := &root
for _, name := range path[1:] {
f := s.FindChild(&types.FindChild{Entity: *o, Name: name})
o = f.(*methods.FindChildBody).Res.Returnval
if o == nil {
break
}
}
body.Res.Returnval = o
return body
}
func (s *SearchIndex) FindChild(req *types.FindChild) soap.HasFault {
body := &methods.FindChildBody{}
obj := Map.Get(req.Entity)
if obj == nil {
body.Fault_ = Fault("", &types.ManagedObjectNotFound{Obj: req.Entity})
return body
}
body.Res = new(types.FindChildResponse)
var children []types.ManagedObjectReference
switch e := obj.(type) {
case *mo.Datacenter:
children = []types.ManagedObjectReference{e.VmFolder, e.HostFolder, e.DatastoreFolder, e.NetworkFolder}
case *Folder:
children = e.ChildEntity
case *mo.ComputeResource:
children = e.Host
children = append(children, *e.ResourcePool)
case *ClusterComputeResource:
children = e.Host
children = append(children, *e.ResourcePool)
case *ResourcePool:
children = e.ResourcePool.ResourcePool
children = append(children, e.Vm...)
case *VirtualApp:
children = e.ResourcePool.ResourcePool
children = append(children, e.Vm...)
}
match := Map.FindByName(req.Name, children)
if match != nil {
ref := match.Reference()
body.Res.Returnval = &ref
}
return body
}
func (s *SearchIndex) FindByUuid(req *types.FindByUuid) soap.HasFault {
body := &methods.FindByUuidBody{Res: new(types.FindByUuidResponse)}
if req.VmSearch {
// Find Virtual Machine using UUID
for ref, obj := range Map.objects {
vm, ok := obj.(*VirtualMachine)
if !ok {
continue
}
if vm.Config.Uuid == req.Uuid {
body.Res.Returnval = &ref
break
}
}
} else {
// Find Host System using UUID
for ref, obj := range Map.objects {
host, ok := obj.(*HostSystem)
if !ok {
continue
}
if host.Summary.Hardware.Uuid == req.Uuid {
body.Res.Returnval = &ref
break
}
}
}
return body
}

View File

@@ -0,0 +1,99 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"time"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/simulator/vpx"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type ServiceInstance struct {
mo.ServiceInstance
}
func NewServiceInstance(content types.ServiceContent, folder mo.Folder) *ServiceInstance {
Map = NewRegistry()
s := &ServiceInstance{}
s.Self = methods.ServiceInstance
s.Content = content
Map.Put(s)
f := &Folder{Folder: folder}
Map.Put(f)
var setting []types.BaseOptionValue
if content.About.ApiType == "HostAgent" {
CreateDefaultESX(f)
} else {
setting = vpx.Setting
}
objects := []object.Reference{
NewSessionManager(*s.Content.SessionManager),
NewAuthorizationManager(*s.Content.AuthorizationManager),
NewPerformanceManager(*s.Content.PerfManager),
NewPropertyCollector(s.Content.PropertyCollector),
NewFileManager(*s.Content.FileManager),
NewVirtualDiskManager(*s.Content.VirtualDiskManager),
NewLicenseManager(*s.Content.LicenseManager),
NewSearchIndex(*s.Content.SearchIndex),
NewViewManager(*s.Content.ViewManager),
NewTaskManager(*s.Content.TaskManager),
NewUserDirectory(*s.Content.UserDirectory),
NewOptionManager(s.Content.Setting, setting),
}
if s.Content.CustomFieldsManager != nil {
objects = append(objects, NewCustomFieldsManager(*s.Content.CustomFieldsManager))
}
if s.Content.IpPoolManager != nil {
objects = append(objects, NewIpPoolManager(*s.Content.IpPoolManager))
}
for _, o := range objects {
Map.Put(o)
}
return s
}
func (s *ServiceInstance) RetrieveServiceContent(*types.RetrieveServiceContent) soap.HasFault {
return &methods.RetrieveServiceContentBody{
Res: &types.RetrieveServiceContentResponse{
Returnval: s.Content,
},
}
}
func (*ServiceInstance) CurrentTime(*types.CurrentTime) soap.HasFault {
return &methods.CurrentTimeBody{
Res: &types.CurrentTimeResponse{
Returnval: time.Now(),
},
}
}

View File

@@ -0,0 +1,83 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"time"
"github.com/google/uuid"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/session"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type SessionManager struct {
mo.SessionManager
ServiceHostName string
}
func NewSessionManager(ref types.ManagedObjectReference) object.Reference {
s := &SessionManager{}
s.Self = ref
return s
}
func (s *SessionManager) Login(login *types.Login) soap.HasFault {
body := &methods.LoginBody{}
if login.Locale == "" {
login.Locale = session.Locale
}
if login.UserName == "" || login.Password == "" {
body.Fault_ = Fault("Login failure", &types.InvalidLogin{})
} else {
body.Res = &types.LoginResponse{
Returnval: types.UserSession{
Key: uuid.New().String(),
UserName: login.UserName,
FullName: login.UserName,
LoginTime: time.Now(),
LastActiveTime: time.Now(),
Locale: login.Locale,
MessageLocale: login.Locale,
},
}
}
return body
}
func (s *SessionManager) Logout(*types.Logout) soap.HasFault {
return &methods.LogoutBody{Res: new(types.LogoutResponse)}
}
func (s *SessionManager) AcquireGenericServiceTicket(ticket *types.AcquireGenericServiceTicket) soap.HasFault {
return &methods.AcquireGenericServiceTicketBody{
Res: &types.AcquireGenericServiceTicketResponse{
Returnval: types.SessionManagerGenericServiceTicket{
Id: uuid.New().String(),
HostName: s.ServiceHostName,
},
},
}
}

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

@@ -0,0 +1,551 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"bytes"
"context"
"crypto/tls"
"crypto/x509"
"encoding/json"
"encoding/pem"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"net/http/httptest"
"net/url"
"os"
"path"
"reflect"
"sort"
"strings"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
"github.com/vmware/govmomi/vim25/xml"
)
// Trace when set to true, writes SOAP traffic to stderr
var Trace = false
// Method encapsulates a decoded SOAP client request
type Method struct {
Name string
This types.ManagedObjectReference
Body types.AnyType
}
// Service decodes incoming requests and dispatches to a Handler
type Service struct {
client *vim25.Client
readAll func(io.Reader) ([]byte, error)
TLS *tls.Config
}
// Server provides a simulator Service over HTTP
type Server struct {
*httptest.Server
URL *url.URL
caFile string
}
// New returns an initialized simulator Service instance
func New(instance *ServiceInstance) *Service {
s := &Service{
readAll: ioutil.ReadAll,
}
s.client, _ = vim25.NewClient(context.Background(), s)
return s
}
type serverFaultBody struct {
Reason *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *serverFaultBody) Fault() *soap.Fault { return b.Reason }
func serverFault(msg string) soap.HasFault {
return &serverFaultBody{Reason: Fault(msg, &types.InvalidRequest{})}
}
// Fault wraps the given message and fault in a soap.Fault
func Fault(msg string, fault types.BaseMethodFault) *soap.Fault {
f := &soap.Fault{
Code: "ServerFaultCode",
String: msg,
}
f.Detail.Fault = fault
return f
}
func (s *Service) call(method *Method) soap.HasFault {
handler := Map.Get(method.This)
if handler == nil {
msg := fmt.Sprintf("managed object not found: %s", method.This)
log.Print(msg)
fault := &types.ManagedObjectNotFound{Obj: method.This}
return &serverFaultBody{Reason: Fault(msg, fault)}
}
name := method.Name
if strings.HasSuffix(name, vTaskSuffix) {
// Make golint happy renaming "Foo_Task" -> "FooTask"
name = name[:len(name)-len(vTaskSuffix)] + sTaskSuffix
}
m := reflect.ValueOf(handler).MethodByName(name)
if !m.IsValid() {
msg := fmt.Sprintf("%s does not implement: %s", method.This, method.Name)
log.Print(msg)
fault := &types.MethodNotFound{Receiver: method.This, Method: method.Name}
return &serverFaultBody{Reason: Fault(msg, fault)}
}
if e, ok := handler.(mo.Entity); ok {
for _, dm := range e.Entity().DisabledMethod {
if name == dm {
msg := fmt.Sprintf("%s method is disabled: %s", method.This, method.Name)
fault := &types.MethodDisabled{}
return &serverFaultBody{Reason: Fault(msg, fault)}
}
}
}
res := m.Call([]reflect.Value{reflect.ValueOf(method.Body)})
return res[0].Interface().(soap.HasFault)
}
// RoundTrip implements the soap.RoundTripper interface in process.
// Rather than encode/decode SOAP over HTTP, this implementation uses reflection.
func (s *Service) RoundTrip(ctx context.Context, request, response soap.HasFault) error {
field := func(r soap.HasFault, name string) reflect.Value {
return reflect.ValueOf(r).Elem().FieldByName(name)
}
// Every struct passed to soap.RoundTrip has "Req" and "Res" fields
req := field(request, "Req")
// Every request has a "This" field.
this := req.Elem().FieldByName("This")
method := &Method{
Name: req.Elem().Type().Name(),
This: this.Interface().(types.ManagedObjectReference),
Body: req.Interface(),
}
res := s.call(method)
if err := res.Fault(); err != nil {
return soap.WrapSoapFault(err)
}
field(response, "Res").Set(field(res, "Res"))
return nil
}
// soapEnvelope is a copy of soap.Envelope, with namespace changed to "soapenv",
// and additional namespace attributes required by some client libraries.
// Go still has issues decoding with such a namespace, but encoding is ok.
type soapEnvelope struct {
XMLName xml.Name `xml:"soapenv:Envelope"`
Enc string `xml:"xmlns:soapenc,attr"`
Env string `xml:"xmlns:soapenv,attr"`
XSD string `xml:"xmlns:xsd,attr"`
XSI string `xml:"xmlns:xsi,attr"`
Body interface{} `xml:"soapenv:Body"`
}
// soapFault is a copy of soap.Fault, with the same changes as soapEnvelope
type soapFault struct {
XMLName xml.Name `xml:"soapenv:Fault"`
Code string `xml:"faultcode"`
String string `xml:"faultstring"`
Detail struct {
Fault types.AnyType `xml:",any,typeattr"`
} `xml:"detail"`
}
// About generates some info about the simulator.
func (s *Service) About(w http.ResponseWriter, r *http.Request) {
var about struct {
Methods []string
Types []string
}
seen := make(map[string]bool)
f := reflect.TypeOf((*soap.HasFault)(nil)).Elem()
for _, obj := range Map.objects {
kind := obj.Reference().Type
if seen[kind] {
continue
}
seen[kind] = true
about.Types = append(about.Types, kind)
t := reflect.TypeOf(obj)
for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i)
if seen[m.Name] {
continue
}
seen[m.Name] = true
if m.Type.NumIn() != 2 || m.Type.NumOut() != 1 || m.Type.Out(0) != f {
continue
}
about.Methods = append(about.Methods, strings.Replace(m.Name, "Task", "_Task", 1))
}
}
sort.Strings(about.Methods)
sort.Strings(about.Types)
w.Header().Set("Content-Type", "application/json")
enc := json.NewEncoder(w)
enc.SetIndent("", " ")
_ = enc.Encode(&about)
}
// ServeSDK implements the http.Handler interface
func (s *Service) ServeSDK(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
body, err := s.readAll(r.Body)
_ = r.Body.Close()
if err != nil {
log.Printf("error reading body: %s", err)
w.WriteHeader(http.StatusBadRequest)
return
}
if Trace {
fmt.Fprintf(os.Stderr, "Request: %s\n", string(body))
}
var res soap.HasFault
var soapBody interface{}
method, err := UnmarshalBody(body)
if err != nil {
res = serverFault(err.Error())
} else {
res = s.call(method)
}
if f := res.Fault(); f != nil {
w.WriteHeader(http.StatusInternalServerError)
// the generated method/*Body structs use the '*soap.Fault' type,
// so we need our own Body type to use the modified '*soapFault' type.
soapBody = struct {
Fault *soapFault
}{
&soapFault{
Code: f.Code,
String: f.String,
Detail: f.Detail,
},
}
} else {
w.WriteHeader(http.StatusOK)
soapBody = res
}
var out bytes.Buffer
fmt.Fprint(&out, xml.Header)
e := xml.NewEncoder(&out)
err = e.Encode(&soapEnvelope{
Enc: "http://schemas.xmlsoap.org/soap/encoding/",
Env: "http://schemas.xmlsoap.org/soap/envelope/",
XSD: "http://www.w3.org/2001/XMLSchema",
XSI: "http://www.w3.org/2001/XMLSchema-instance",
Body: soapBody,
})
if err == nil {
err = e.Flush()
}
if err != nil {
log.Printf("error encoding %s response: %s", method.Name, err)
return
}
if Trace {
fmt.Fprintf(os.Stderr, "Response: %s\n", out.String())
}
_, _ = w.Write(out.Bytes())
}
func (s *Service) findDatastore(query url.Values) (*Datastore, error) {
ctx := context.Background()
finder := find.NewFinder(s.client, false)
dc, err := finder.DatacenterOrDefault(ctx, query.Get("dcName"))
if err != nil {
return nil, err
}
finder.SetDatacenter(dc)
ds, err := finder.DatastoreOrDefault(ctx, query.Get("dsName"))
if err != nil {
return nil, err
}
return Map.Get(ds.Reference()).(*Datastore), nil
}
const folderPrefix = "/folder/"
// ServeDatastore handler for Datastore access via /folder path.
func (s *Service) ServeDatastore(w http.ResponseWriter, r *http.Request) {
ds, ferr := s.findDatastore(r.URL.Query())
if ferr != nil {
log.Printf("failed to locate datastore with query params: %s", r.URL.RawQuery)
w.WriteHeader(http.StatusNotFound)
return
}
file := strings.TrimPrefix(r.URL.Path, folderPrefix)
p := path.Join(ds.Info.GetDatastoreInfo().Url, file)
switch r.Method {
case "GET":
f, err := os.Open(p)
if err != nil {
log.Printf("failed to %s '%s': %s", r.Method, p, err)
w.WriteHeader(http.StatusNotFound)
return
}
defer f.Close()
_, _ = io.Copy(w, f)
case "POST":
_, err := os.Stat(p)
if err == nil {
// File exists
w.WriteHeader(http.StatusConflict)
return
}
// File does not exist, fallthrough to create via PUT logic
fallthrough
case "PUT":
f, err := os.Create(p)
if err != nil {
log.Printf("failed to %s '%s': %s", r.Method, p, err)
w.WriteHeader(http.StatusInternalServerError)
return
}
defer f.Close()
_, _ = io.Copy(f, r.Body)
default:
w.WriteHeader(http.StatusMethodNotAllowed)
}
}
// ServiceVersions handler for the /sdk/vimServiceVersions.xml path.
func (*Service) ServiceVersions(w http.ResponseWriter, r *http.Request) {
// pyvmomi depends on this
const versions = xml.Header + `<namespaces version="1.0">
<namespace>
<name>urn:vim25</name>
<version>6.5</version>
<priorVersions>
<version>6.0</version>
<version>5.5</version>
</priorVersions>
</namespace>
</namespaces>
`
fmt.Fprint(w, versions)
}
// NewServer returns an http Server instance for the given service
func (s *Service) NewServer() *Server {
mux := http.NewServeMux()
path := "/sdk"
mux.HandleFunc(path, s.ServeSDK)
mux.HandleFunc(path+"/vimServiceVersions.xml", s.ServiceVersions)
mux.HandleFunc(folderPrefix, s.ServeDatastore)
mux.HandleFunc("/about", s.About)
// Using NewUnstartedServer() instead of NewServer(),
// for use in main.go, where Start() blocks, we can still set ServiceHostName
ts := httptest.NewUnstartedServer(mux)
u := &url.URL{
Scheme: "http",
Host: ts.Listener.Addr().String(),
Path: path,
User: url.UserPassword("user", "pass"),
}
// Redirect clients to this http server, rather than HostSystem.Name
Map.Get(*s.client.ServiceContent.SessionManager).(*SessionManager).ServiceHostName = u.Host
if f := flag.Lookup("httptest.serve"); f != nil {
// Avoid the blocking behaviour of httptest.Server.Start() when this flag is set
_ = f.Value.Set("")
}
if s.TLS == nil {
ts.Start()
} else {
ts.TLS = s.TLS
ts.StartTLS()
u.Scheme += "s"
}
return &Server{
Server: ts,
URL: u,
}
}
// Certificate returns the TLS certificate for the Server if started with TLS enabled.
// This method will panic if TLS is not enabled for the server.
func (s *Server) Certificate() *x509.Certificate {
// By default httptest.StartTLS uses http/internal.LocalhostCert, which we can access here:
cert, _ := x509.ParseCertificate(s.TLS.Certificates[0].Certificate[0])
return cert
}
// CertificateInfo returns Server.Certificate() as object.HostCertificateInfo
func (s *Server) CertificateInfo() *object.HostCertificateInfo {
info := new(object.HostCertificateInfo)
info.FromCertificate(s.Certificate())
return info
}
// CertificateFile returns a file name, where the file contains the PEM encoded Server.Certificate.
// The temporary file is removed when Server.Close() is called.
func (s *Server) CertificateFile() (string, error) {
if s.caFile != "" {
return s.caFile, nil
}
f, err := ioutil.TempFile("", "vcsim-")
if err != nil {
return "", err
}
defer f.Close()
s.caFile = f.Name()
cert := s.Certificate()
return s.caFile, pem.Encode(f, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})
}
// Close shuts down the server and blocks until all outstanding
// requests on this server have completed.
func (s *Server) Close() {
s.Server.Close()
if s.caFile != "" {
_ = os.Remove(s.caFile)
}
}
var typeFunc = types.TypeFunc()
// UnmarshalBody extracts the Body from a soap.Envelope and unmarshals to the corresponding govmomi type
func UnmarshalBody(data []byte) (*Method, error) {
body := struct {
Content string `xml:",innerxml"`
}{}
req := soap.Envelope{
Body: &body,
}
err := xml.Unmarshal(data, &req)
if err != nil {
return nil, fmt.Errorf("xml.Unmarshal: %s", err)
}
decoder := xml.NewDecoder(bytes.NewReader([]byte(body.Content)))
decoder.TypeFunc = typeFunc // required to decode interface types
var start *xml.StartElement
for {
tok, derr := decoder.Token()
if derr != nil {
return nil, fmt.Errorf("decoding body: %s", err)
}
if t, ok := tok.(xml.StartElement); ok {
start = &t
break
}
}
kind := start.Name.Local
rtype, ok := typeFunc(kind)
if !ok {
return nil, fmt.Errorf("no vmomi type defined for '%s'", kind)
}
var val interface{}
if rtype != nil {
val = reflect.New(rtype).Interface()
}
err = decoder.DecodeElement(val, start)
if err != nil {
return nil, fmt.Errorf("decoding %s: %s", kind, err)
}
method := &Method{Name: kind, Body: val}
field := reflect.ValueOf(val).Elem().FieldByName("This")
method.This = field.Interface().(types.ManagedObjectReference)
return method, nil
}

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

@@ -0,0 +1,68 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type VirtualMachineSnapshot struct {
mo.VirtualMachineSnapshot
}
func (v *VirtualMachineSnapshot) RemoveSnapshotTask(req *types.RemoveSnapshot_Task) soap.HasFault {
task := CreateTask(v, "removeSnapshot", func(t *Task) (types.AnyType, types.BaseMethodFault) {
Map.Remove(req.This)
vm := Map.Get(v.Vm).(*VirtualMachine)
if vm.Snapshot.CurrentSnapshot != nil && *vm.Snapshot.CurrentSnapshot == req.This {
parent := findParentSnapshotInTree(vm.Snapshot.RootSnapshotList, req.This)
vm.Snapshot.CurrentSnapshot = parent
}
vm.Snapshot.RootSnapshotList = removeSnapshotInTree(vm.Snapshot.RootSnapshotList, req.This, req.RemoveChildren)
return nil, nil
})
return &methods.RemoveSnapshot_TaskBody{
Res: &types.RemoveSnapshot_TaskResponse{
Returnval: task.Run(),
},
}
}
func (v *VirtualMachineSnapshot) RevertToSnapshotTask(req *types.RevertToSnapshot_Task) soap.HasFault {
task := CreateTask(v, "revertToSnapshot", func(t *Task) (types.AnyType, types.BaseMethodFault) {
vm := Map.Get(v.Vm).(*VirtualMachine)
ref := v.Reference()
vm.Snapshot.CurrentSnapshot = &ref
return nil, nil
})
return &methods.RevertToSnapshot_TaskBody{
Res: &types.RevertToSnapshot_TaskResponse{
Returnval: task.Run(),
},
}
}

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

@@ -0,0 +1,102 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"fmt"
"reflect"
"strings"
"time"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
const vTaskSuffix = "_Task" // vmomi suffix
const sTaskSuffix = "Task" // simulator suffix (avoiding golint warning)
type Task struct {
mo.Task
Execute func(*Task) (types.AnyType, types.BaseMethodFault)
}
func NewTask(runner TaskRunner) *Task {
ref := runner.Reference()
name := reflect.TypeOf(runner).Elem().Name()
name = strings.Replace(name, "VM", "Vm", 1) // "VM" for the type to make go-lint happy, but "Vm" for the vmodl ID
return CreateTask(ref, name, runner.Run)
}
func CreateTask(e mo.Reference, name string, run func(*Task) (types.AnyType, types.BaseMethodFault)) *Task {
ref := e.Reference()
id := name
if strings.HasSuffix(id, sTaskSuffix) {
id = id[:len(id)-len(sTaskSuffix)]
name = id + vTaskSuffix
}
task := &Task{
Execute: run,
}
Map.Put(task)
task.Info.Key = task.Self.Value
task.Info.Task = task.Self
task.Info.Name = ucFirst(name)
task.Info.DescriptionId = fmt.Sprintf("%s.%s", ref.Type, id)
task.Info.Entity = &ref
task.Info.EntityName = ref.Value
task.Info.QueueTime = time.Now()
task.Info.State = types.TaskInfoStateQueued
return task
}
type TaskRunner interface {
mo.Reference
Run(*Task) (types.AnyType, types.BaseMethodFault)
}
func (t *Task) Run() types.ManagedObjectReference {
now := time.Now()
t.Info.StartTime = &now
t.Info.State = types.TaskInfoStateRunning
res, err := t.Execute(t)
now = time.Now()
t.Info.CompleteTime = &now
if err != nil {
t.Info.State = types.TaskInfoStateError
t.Info.Error = &types.LocalizedMethodFault{
Fault: err,
LocalizedMessage: fmt.Sprintf("%T", err),
}
} else {
t.Info.Result = res
t.Info.State = types.TaskInfoStateSuccess
}
return t.Self
}

View File

@@ -0,0 +1,52 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
var recentTaskMax = 200 // the VC limit
type TaskManager struct {
mo.TaskManager
}
func NewTaskManager(ref types.ManagedObjectReference) object.Reference {
s := &TaskManager{}
s.Self = ref
Map.AddHandler(s)
return s
}
func (m *TaskManager) PutObject(obj mo.Reference) {
ref := obj.Reference()
if ref.Type != "Task" {
return
}
m.RecentTask = append(m.RecentTask, ref)
if len(m.RecentTask) > recentTaskMax {
m.RecentTask = m.RecentTask[1:]
}
}
func (m *TaskManager) RemoveObject(_ types.ManagedObjectReference) {
}

View File

@@ -0,0 +1,78 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"strings"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
var DefaultUserGroup = []*types.UserSearchResult{
{FullName: "root", Group: true, Principal: "root"},
{FullName: "root", Group: false, Principal: "root"},
{FullName: "administrator", Group: false, Principal: "admin"},
}
type UserDirectory struct {
mo.UserDirectory
userGroup []*types.UserSearchResult
}
func NewUserDirectory(ref types.ManagedObjectReference) object.Reference {
u := &UserDirectory{}
u.Self = ref
u.userGroup = DefaultUserGroup
return u
}
func (u *UserDirectory) RetrieveUserGroups(req *types.RetrieveUserGroups) soap.HasFault {
compare := compareFunc(req.SearchStr, req.ExactMatch)
var res []types.BaseUserSearchResult
for _, ug := range u.userGroup {
if req.FindUsers && !ug.Group || req.FindGroups && ug.Group {
if compare(ug.Principal) {
res = append(res, ug)
}
}
}
body := &methods.RetrieveUserGroupsBody{
Res: &types.RetrieveUserGroupsResponse{
Returnval: res,
},
}
return body
}
func compareFunc(compared string, exactly bool) func(string) bool {
return func(s string) bool {
if exactly {
return s == compared
}
return strings.Contains(strings.ToLower(s), strings.ToLower(compared))
}
}

View File

@@ -0,0 +1,184 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"reflect"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type ViewManager struct {
mo.ViewManager
entities map[string]bool
}
var entities = []struct {
Type reflect.Type
Container bool
}{
{reflect.TypeOf((*mo.ManagedEntity)(nil)).Elem(), true},
{reflect.TypeOf((*mo.Folder)(nil)).Elem(), true},
{reflect.TypeOf((*mo.StoragePod)(nil)).Elem(), true},
{reflect.TypeOf((*mo.Datacenter)(nil)).Elem(), true},
{reflect.TypeOf((*mo.ComputeResource)(nil)).Elem(), true},
{reflect.TypeOf((*mo.ClusterComputeResource)(nil)).Elem(), true},
{reflect.TypeOf((*mo.HostSystem)(nil)).Elem(), true},
{reflect.TypeOf((*mo.ResourcePool)(nil)).Elem(), true},
{reflect.TypeOf((*mo.VirtualApp)(nil)).Elem(), true},
{reflect.TypeOf((*mo.VirtualMachine)(nil)).Elem(), false},
{reflect.TypeOf((*mo.Datastore)(nil)).Elem(), false},
{reflect.TypeOf((*mo.Network)(nil)).Elem(), false},
{reflect.TypeOf((*mo.OpaqueNetwork)(nil)).Elem(), false},
{reflect.TypeOf((*mo.DistributedVirtualPortgroup)(nil)).Elem(), false},
{reflect.TypeOf((*mo.DistributedVirtualSwitch)(nil)).Elem(), false},
{reflect.TypeOf((*mo.VmwareDistributedVirtualSwitch)(nil)).Elem(), false},
}
func NewViewManager(ref types.ManagedObjectReference) object.Reference {
s := &ViewManager{
entities: make(map[string]bool),
}
s.Self = ref
for _, e := range entities {
s.entities[e.Type.Name()] = e.Container
}
return s
}
func destroyView(ref types.ManagedObjectReference) soap.HasFault {
m := Map.ViewManager()
m.ViewList = RemoveReference(ref, m.ViewList)
return &methods.DestroyViewBody{
Res: &types.DestroyViewResponse{},
}
}
func (m *ViewManager) CreateContainerView(req *types.CreateContainerView) soap.HasFault {
body := &methods.CreateContainerViewBody{}
root := Map.Get(req.Container)
if root == nil {
body.Fault_ = Fault("", &types.ManagedObjectNotFound{Obj: req.Container})
return body
}
if m.entities[root.Reference().Type] != true {
body.Fault_ = Fault("", &types.InvalidArgument{InvalidProperty: "container"})
return body
}
container := &ContainerView{
mo.ContainerView{
Container: root.Reference(),
Recursive: req.Recursive,
Type: req.Type,
},
make(map[string]bool),
}
for _, ctype := range container.Type {
if _, ok := m.entities[ctype]; !ok {
body.Fault_ = Fault("", &types.InvalidArgument{InvalidProperty: "type"})
return body
}
container.types[ctype] = true
for _, e := range entities {
// Check for embedded types
if f, ok := e.Type.FieldByName(ctype); ok && f.Anonymous {
container.types[e.Type.Name()] = true
}
}
}
Map.Put(container)
m.ViewList = append(m.ViewList, container.Reference())
body.Res = &types.CreateContainerViewResponse{
Returnval: container.Self,
}
container.add(root)
return body
}
type ContainerView struct {
mo.ContainerView
types map[string]bool
}
func (v *ContainerView) DestroyView(c *types.DestroyView) soap.HasFault {
return destroyView(c.This)
}
func (v *ContainerView) include(o types.ManagedObjectReference) bool {
if len(v.types) == 0 {
return true
}
return v.types[o.Type]
}
func (v *ContainerView) add(root mo.Reference) {
var children []types.ManagedObjectReference
switch e := root.(type) {
case *mo.Datacenter:
children = []types.ManagedObjectReference{e.VmFolder, e.HostFolder, e.DatastoreFolder, e.NetworkFolder}
case *Folder:
children = e.ChildEntity
case *mo.ComputeResource:
children = e.Host
children = append(children, *e.ResourcePool)
case *ClusterComputeResource:
children = e.Host
children = append(children, *e.ResourcePool)
case *ResourcePool:
children = e.ResourcePool.ResourcePool
children = append(children, e.Vm...)
case *VirtualApp:
children = e.ResourcePool.ResourcePool
children = append(children, e.Vm...)
case *HostSystem:
children = e.Vm
}
for _, child := range children {
if v.include(child) {
v.View = AddReference(child, v.View)
}
if v.Recursive {
v.add(Map.Get(child))
}
}
}

View File

@@ -0,0 +1,193 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"os"
"strings"
"github.com/google/uuid"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type VirtualDiskManager struct {
mo.VirtualDiskManager
}
func NewVirtualDiskManager(ref types.ManagedObjectReference) object.Reference {
m := &VirtualDiskManager{}
m.Self = ref
return m
}
func (m *VirtualDiskManager) names(name string) []string {
return []string{
strings.Replace(name, ".vmdk", "-flat.vmdk", 1),
name,
}
}
func (m *VirtualDiskManager) createVirtualDisk(req *types.CreateVirtualDisk_Task) types.BaseMethodFault {
fm := Map.FileManager()
file, fault := fm.resolve(req.Datacenter, req.Name)
if fault != nil {
return fault
}
for _, name := range m.names(file) {
_, err := os.Stat(name)
if err == nil {
return fm.fault(name, nil, new(types.FileAlreadyExists))
}
f, err := os.Create(name)
if err != nil {
return fm.fault(name, err, new(types.CannotCreateFile))
}
_ = f.Close()
}
return nil
}
func (m *VirtualDiskManager) CreateVirtualDiskTask(req *types.CreateVirtualDisk_Task) soap.HasFault {
task := CreateTask(m, "createVirtualDisk", func(*Task) (types.AnyType, types.BaseMethodFault) {
return nil, m.createVirtualDisk(req)
})
return &methods.CreateVirtualDisk_TaskBody{
Res: &types.CreateVirtualDisk_TaskResponse{
Returnval: task.Run(),
},
}
}
func (m *VirtualDiskManager) DeleteVirtualDiskTask(req *types.DeleteVirtualDisk_Task) soap.HasFault {
task := CreateTask(m, "deleteVirtualDisk", func(*Task) (types.AnyType, types.BaseMethodFault) {
fm := Map.FileManager()
for _, name := range m.names(req.Name) {
err := fm.deleteDatastoreFile(&types.DeleteDatastoreFile_Task{
Name: name,
Datacenter: req.Datacenter,
})
if err != nil {
return nil, err
}
}
return nil, nil
})
return &methods.DeleteVirtualDisk_TaskBody{
Res: &types.DeleteVirtualDisk_TaskResponse{
Returnval: task.Run(),
},
}
}
func (m *VirtualDiskManager) MoveVirtualDiskTask(req *types.MoveVirtualDisk_Task) soap.HasFault {
task := CreateTask(m, "moveVirtualDisk", func(*Task) (types.AnyType, types.BaseMethodFault) {
fm := Map.FileManager()
dest := m.names(req.DestName)
for i, name := range m.names(req.SourceName) {
err := fm.moveDatastoreFile(&types.MoveDatastoreFile_Task{
SourceName: name,
SourceDatacenter: req.SourceDatacenter,
DestinationName: dest[i],
DestinationDatacenter: req.DestDatacenter,
Force: req.Force,
})
if err != nil {
return nil, err
}
}
return nil, nil
})
return &methods.MoveVirtualDisk_TaskBody{
Res: &types.MoveVirtualDisk_TaskResponse{
Returnval: task.Run(),
},
}
}
func (m *VirtualDiskManager) CopyVirtualDiskTask(req *types.CopyVirtualDisk_Task) soap.HasFault {
task := CreateTask(m, "copyVirtualDisk", func(*Task) (types.AnyType, types.BaseMethodFault) {
fm := Map.FileManager()
dest := m.names(req.DestName)
for i, name := range m.names(req.SourceName) {
err := fm.copyDatastoreFile(&types.CopyDatastoreFile_Task{
SourceName: name,
SourceDatacenter: req.SourceDatacenter,
DestinationName: dest[i],
DestinationDatacenter: req.DestDatacenter,
Force: req.Force,
})
if err != nil {
return nil, err
}
}
return nil, nil
})
return &methods.CopyVirtualDisk_TaskBody{
Res: &types.CopyVirtualDisk_TaskResponse{
Returnval: task.Run(),
},
}
}
func (m *VirtualDiskManager) QueryVirtualDiskUuid(req *types.QueryVirtualDiskUuid) soap.HasFault {
body := new(methods.QueryVirtualDiskUuidBody)
fm := Map.FileManager()
file, fault := fm.resolve(req.Datacenter, req.Name)
if fault != nil {
body.Fault_ = Fault("", fault)
return body
}
_, err := os.Stat(file)
if err != nil {
fault = fm.fault(file, err, new(types.CannotAccessFile))
body.Fault_ = Fault("", fault)
return body
}
body.Res = &types.QueryVirtualDiskUuidResponse{
Returnval: uuid.NewSHA1(uuid.NameSpaceOID, []byte(file)).String(),
}
return body
}

View File

@@ -0,0 +1,885 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package simulator
import (
"fmt"
"io"
"log"
"net"
"os"
"path"
"strings"
"sync/atomic"
"time"
"github.com/google/uuid"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/simulator/esx"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type VirtualMachine struct {
mo.VirtualMachine
log *log.Logger
out io.Closer
sid int32
}
func NewVirtualMachine(parent types.ManagedObjectReference, spec *types.VirtualMachineConfigSpec) (*VirtualMachine, types.BaseMethodFault) {
vm := &VirtualMachine{}
vm.Parent = &parent
if spec.Name == "" {
return nil, &types.InvalidVmConfig{Property: "configSpec.name"}
}
if spec.Files == nil || spec.Files.VmPathName == "" {
return nil, &types.InvalidVmConfig{Property: "configSpec.files.vmPathName"}
}
rspec := types.DefaultResourceConfigSpec()
vm.Config = &types.VirtualMachineConfigInfo{
ExtraConfig: []types.BaseOptionValue{&types.OptionValue{Key: "govcsim", Value: "TRUE"}},
Tools: &types.ToolsConfigInfo{},
MemoryAllocation: &rspec.MemoryAllocation,
CpuAllocation: &rspec.CpuAllocation,
}
vm.Summary.Guest = &types.VirtualMachineGuestSummary{}
vm.Summary.Storage = &types.VirtualMachineStorageSummary{}
vm.Summary.Vm = &vm.Self
// Append VM Name as the directory name if not specified
if strings.HasSuffix(spec.Files.VmPathName, "]") { // e.g. "[datastore1]"
spec.Files.VmPathName += " " + spec.Name
}
if !strings.HasSuffix(spec.Files.VmPathName, ".vmx") {
spec.Files.VmPathName = path.Join(spec.Files.VmPathName, spec.Name+".vmx")
}
dsPath := path.Dir(spec.Files.VmPathName)
defaults := types.VirtualMachineConfigSpec{
NumCPUs: 1,
NumCoresPerSocket: 1,
MemoryMB: 32,
Uuid: uuid.New().String(),
Version: "vmx-11",
Files: &types.VirtualMachineFileInfo{
SnapshotDirectory: dsPath,
SuspendDirectory: dsPath,
LogDirectory: dsPath,
},
}
// Add the default devices
defaults.DeviceChange, _ = object.VirtualDeviceList(esx.VirtualDevice).ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd)
err := vm.configure(&defaults)
if err != nil {
return nil, err
}
vm.Runtime.PowerState = types.VirtualMachinePowerStatePoweredOff
vm.Runtime.ConnectionState = types.VirtualMachineConnectionStateConnected
vm.Summary.Runtime = vm.Runtime
vm.Summary.QuickStats.GuestHeartbeatStatus = types.ManagedEntityStatusGray
vm.Summary.OverallStatus = types.ManagedEntityStatusGreen
vm.ConfigStatus = types.ManagedEntityStatusGreen
return vm, nil
}
func (vm *VirtualMachine) apply(spec *types.VirtualMachineConfigSpec) {
if spec.Files == nil {
spec.Files = new(types.VirtualMachineFileInfo)
}
apply := []struct {
src string
dst *string
}{
{spec.Name, &vm.Name},
{spec.Name, &vm.Config.Name},
{spec.Name, &vm.Summary.Config.Name},
{spec.GuestId, &vm.Config.GuestId},
{spec.GuestId, &vm.Config.GuestFullName},
{spec.GuestId, &vm.Summary.Guest.GuestId},
{spec.GuestId, &vm.Summary.Config.GuestId},
{spec.GuestId, &vm.Summary.Config.GuestFullName},
{spec.Uuid, &vm.Config.Uuid},
{spec.Version, &vm.Config.Version},
{spec.Files.VmPathName, &vm.Config.Files.VmPathName},
{spec.Files.VmPathName, &vm.Summary.Config.VmPathName},
{spec.Files.SnapshotDirectory, &vm.Config.Files.SnapshotDirectory},
{spec.Files.LogDirectory, &vm.Config.Files.LogDirectory},
}
for _, f := range apply {
if f.src != "" {
*f.dst = f.src
}
}
if spec.MemoryMB != 0 {
vm.Config.Hardware.MemoryMB = int32(spec.MemoryMB)
vm.Summary.Config.MemorySizeMB = vm.Config.Hardware.MemoryMB
}
if spec.NumCPUs != 0 {
vm.Config.Hardware.NumCPU = spec.NumCPUs
vm.Summary.Config.NumCpu = vm.Config.Hardware.NumCPU
}
vm.Config.ExtraConfig = append(vm.Config.ExtraConfig, spec.ExtraConfig...)
vm.Config.Modified = time.Now()
vm.Summary.Config.Uuid = vm.Config.Uuid
}
func validateGuestID(id string) types.BaseMethodFault {
for _, x := range GuestID {
if id == string(x) {
return nil
}
}
return &types.InvalidArgument{InvalidProperty: "configSpec.guestId"}
}
func (vm *VirtualMachine) configure(spec *types.VirtualMachineConfigSpec) types.BaseMethodFault {
vm.apply(spec)
if spec.MemoryAllocation != nil {
if err := updateResourceAllocation("memory", spec.MemoryAllocation, vm.Config.MemoryAllocation); err != nil {
return err
}
}
if spec.CpuAllocation != nil {
if err := updateResourceAllocation("cpu", spec.CpuAllocation, vm.Config.CpuAllocation); err != nil {
return err
}
}
if spec.GuestId != "" {
if err := validateGuestID(spec.GuestId); err != nil {
return err
}
}
return vm.configureDevices(spec)
}
func (vm *VirtualMachine) useDatastore(name string) *Datastore {
host := Map.Get(*vm.Runtime.Host).(*HostSystem)
ds := Map.FindByName(name, host.Datastore).(*Datastore)
vm.Datastore = AddReference(ds.Self, vm.Datastore)
return ds
}
func (vm *VirtualMachine) setLog(w io.WriteCloser) {
vm.out = w
vm.log = log.New(w, "vmx ", log.Flags())
}
func (vm *VirtualMachine) createFile(spec string, name string, register bool) (*os.File, types.BaseMethodFault) {
p, fault := parseDatastorePath(spec)
if fault != nil {
return nil, fault
}
ds := vm.useDatastore(p.Datastore)
file := path.Join(ds.Info.GetDatastoreInfo().Url, p.Path)
if name != "" {
if path.Ext(file) != "" {
file = path.Dir(file)
}
file = path.Join(file, name)
}
if register {
f, err := os.Open(file)
if err != nil {
log.Printf("register %s: %s", vm.Reference(), err)
if os.IsNotExist(err) {
return nil, &types.NotFound{}
}
return nil, &types.InvalidArgument{}
}
return f, nil
}
dir := path.Dir(file)
_ = os.MkdirAll(dir, 0700)
_, err := os.Stat(file)
if err == nil {
return nil, &types.FileAlreadyExists{
FileFault: types.FileFault{
File: file,
},
}
}
f, err := os.Create(file)
if err != nil {
return nil, &types.FileFault{
File: file,
}
}
return f, nil
}
func (vm *VirtualMachine) create(spec *types.VirtualMachineConfigSpec, register bool) types.BaseMethodFault {
vm.apply(spec)
files := []struct {
spec string
name string
use func(w io.WriteCloser)
}{
{vm.Config.Files.VmPathName, "", nil},
{vm.Config.Files.VmPathName, fmt.Sprintf("%s.nvram", vm.Name), nil},
{vm.Config.Files.LogDirectory, "vmware.log", vm.setLog},
}
for _, file := range files {
f, err := vm.createFile(file.spec, file.name, register)
if err != nil {
return err
}
if file.use != nil {
file.use(f)
} else {
_ = f.Close()
}
}
vm.log.Print("created")
return vm.configureDevices(spec)
}
var vmwOUI = net.HardwareAddr([]byte{0x0, 0xc, 0x29})
// From http://pubs.vmware.com/vsphere-60/index.jsp?topic=%2Fcom.vmware.vsphere.networking.doc%2FGUID-DC7478FF-DC44-4625-9AD7-38208C56A552.html
// "The host generates generateMAC addresses that consists of the VMware OUI 00:0C:29 and the last three octets in hexadecimal
// format of the virtual machine UUID. The virtual machine UUID is based on a hash calculated by using the UUID of the
// ESXi physical machine and the path to the configuration file (.vmx) of the virtual machine."
func (vm *VirtualMachine) generateMAC() string {
id := uuid.New() // Random is fine for now.
offset := len(id) - len(vmwOUI)
mac := append(vmwOUI, id[offset:]...)
return mac.String()
}
func (vm *VirtualMachine) configureDevice(devices object.VirtualDeviceList, device types.BaseVirtualDevice) types.BaseMethodFault {
d := device.GetVirtualDevice()
var controller types.BaseVirtualController
if d.Key < 0 {
// Choose a unique key
if d.Key == -1 {
d.Key = devices.NewKey()
}
d.Key *= -1
for {
if devices.FindByKey(d.Key) == nil {
break
}
d.Key++
}
}
label := devices.Name(device)
summary := label
dc := Map.getEntityDatacenter(Map.Get(*vm.Parent).(mo.Entity))
dm := Map.VirtualDiskManager()
switch x := device.(type) {
case types.BaseVirtualEthernetCard:
controller = devices.PickController((*types.VirtualPCIController)(nil))
var net types.ManagedObjectReference
switch b := d.Backing.(type) {
case *types.VirtualEthernetCardNetworkBackingInfo:
summary = b.DeviceName
net = Map.FindByName(b.DeviceName, dc.Network).Reference()
b.Network = &net
case *types.VirtualEthernetCardDistributedVirtualPortBackingInfo:
summary = fmt.Sprintf("DVSwitch: %s", b.Port.SwitchUuid)
net.Type = "DistributedVirtualPortgroup"
net.Value = b.Port.PortgroupKey
}
vm.Network = append(vm.Network, net)
c := x.GetVirtualEthernetCard()
if c.MacAddress == "" {
c.MacAddress = vm.generateMAC()
}
case *types.VirtualDisk:
switch b := d.Backing.(type) {
case types.BaseVirtualDeviceFileBackingInfo:
info := b.GetVirtualDeviceFileBackingInfo()
if info.FileName == "" {
filename, err := vm.genVmdkPath()
if err != nil {
return err
}
info.FileName = filename
}
err := dm.createVirtualDisk(&types.CreateVirtualDisk_Task{
Datacenter: &dc.Self,
Name: info.FileName,
})
if err != nil {
return err
}
p, _ := parseDatastorePath(info.FileName)
info.Datastore = &types.ManagedObjectReference{
Type: "Datastore",
Value: p.Datastore,
}
}
}
if d.UnitNumber == nil && controller != nil {
devices.AssignController(device, controller)
}
if d.DeviceInfo == nil {
d.DeviceInfo = &types.Description{
Label: label,
Summary: summary,
}
}
return nil
}
func removeDevice(devices object.VirtualDeviceList, device types.BaseVirtualDevice) object.VirtualDeviceList {
var result object.VirtualDeviceList
for i, d := range devices {
if d.GetVirtualDevice().Key == device.GetVirtualDevice().Key {
result = append(result, devices[i+1:]...)
break
}
result = append(result, d)
}
return result
}
func (vm *VirtualMachine) genVmdkPath() (string, types.BaseMethodFault) {
vmdir := path.Dir(vm.Config.Files.VmPathName)
index := 0
for {
var filename string
if index == 0 {
filename = fmt.Sprintf("%s.vmdk", vm.Config.Name)
} else {
filename = fmt.Sprintf("%s_%d.vmdk", vm.Config.Name, index)
}
f, err := vm.createFile(vmdir, filename, false)
if err != nil {
switch err.(type) {
case *types.FileAlreadyExists:
index++
continue
default:
return "", err
}
}
_ = f.Close()
_ = os.Remove(f.Name())
return path.Join(vmdir, filename), nil
}
}
func (vm *VirtualMachine) configureDevices(spec *types.VirtualMachineConfigSpec) types.BaseMethodFault {
devices := object.VirtualDeviceList(vm.Config.Hardware.Device)
for i, change := range spec.DeviceChange {
dspec := change.GetVirtualDeviceConfigSpec()
device := dspec.Device.GetVirtualDevice()
invalid := &types.InvalidDeviceSpec{DeviceIndex: int32(i)}
switch dspec.Operation {
case types.VirtualDeviceConfigSpecOperationAdd:
if devices.FindByKey(device.Key) != nil {
if vm.Self.Value != "" { // moid isn't set until CreateVM is done
return invalid
}
// In this case, the CreateVM() spec included one of the default devices
devices = removeDevice(devices, device)
}
err := vm.configureDevice(devices, dspec.Device)
if err != nil {
return err
}
devices = append(devices, dspec.Device)
case types.VirtualDeviceConfigSpecOperationRemove:
devices = removeDevice(devices, dspec.Device)
}
}
vm.Config.Hardware.Device = []types.BaseVirtualDevice(devices)
return nil
}
type powerVMTask struct {
*VirtualMachine
state types.VirtualMachinePowerState
}
func (c *powerVMTask) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
c.log.Printf("running power task: requesting %s, existing %s",
c.state, c.VirtualMachine.Runtime.PowerState)
if c.VirtualMachine.Runtime.PowerState == c.state {
return nil, &types.InvalidPowerState{
RequestedState: c.state,
ExistingState: c.VirtualMachine.Runtime.PowerState,
}
}
c.VirtualMachine.Runtime.PowerState = c.state
c.VirtualMachine.Summary.Runtime.PowerState = c.state
bt := &c.VirtualMachine.Summary.Runtime.BootTime
if c.state == types.VirtualMachinePowerStatePoweredOn {
now := time.Now()
*bt = &now
} else {
*bt = nil
}
return nil, nil
}
func (vm *VirtualMachine) PowerOnVMTask(c *types.PowerOnVM_Task) soap.HasFault {
runner := &powerVMTask{vm, types.VirtualMachinePowerStatePoweredOn}
task := CreateTask(runner.Reference(), "powerOn", runner.Run)
return &methods.PowerOnVM_TaskBody{
Res: &types.PowerOnVM_TaskResponse{
Returnval: task.Run(),
},
}
}
func (vm *VirtualMachine) PowerOffVMTask(c *types.PowerOffVM_Task) soap.HasFault {
runner := &powerVMTask{vm, types.VirtualMachinePowerStatePoweredOff}
task := CreateTask(runner.Reference(), "powerOff", runner.Run)
return &methods.PowerOffVM_TaskBody{
Res: &types.PowerOffVM_TaskResponse{
Returnval: task.Run(),
},
}
}
func (vm *VirtualMachine) ReconfigVMTask(req *types.ReconfigVM_Task) soap.HasFault {
task := CreateTask(vm, "reconfigVm", func(t *Task) (types.AnyType, types.BaseMethodFault) {
err := vm.configure(&req.Spec)
if err != nil {
return nil, err
}
return nil, nil
})
return &methods.ReconfigVM_TaskBody{
Res: &types.ReconfigVM_TaskResponse{
Returnval: task.Run(),
},
}
}
func (vm *VirtualMachine) DestroyTask(req *types.Destroy_Task) soap.HasFault {
task := CreateTask(vm, "destroy", func(t *Task) (types.AnyType, types.BaseMethodFault) {
r := vm.UnregisterVM(&types.UnregisterVM{
This: req.This,
})
if r.Fault() != nil {
return nil, r.Fault().VimFault().(types.BaseMethodFault)
}
// Delete VM files from the datastore (ignoring result for now)
m := Map.FileManager()
dc := Map.getEntityDatacenter(vm).Reference()
_ = m.DeleteDatastoreFileTask(&types.DeleteDatastoreFile_Task{
This: m.Reference(),
Name: vm.Config.Files.LogDirectory,
Datacenter: &dc,
})
return nil, nil
})
return &methods.Destroy_TaskBody{
Res: &types.Destroy_TaskResponse{
Returnval: task.Run(),
},
}
}
func (vm *VirtualMachine) UnregisterVM(c *types.UnregisterVM) soap.HasFault {
r := &methods.UnregisterVMBody{}
if vm.Runtime.PowerState == types.VirtualMachinePowerStatePoweredOn {
r.Fault_ = Fault("", &types.InvalidPowerState{
RequestedState: types.VirtualMachinePowerStatePoweredOff,
ExistingState: vm.Runtime.PowerState,
})
return r
}
_ = vm.out.Close() // Close log fd
Map.getEntityParent(vm, "Folder").(*Folder).removeChild(c.This)
host := Map.Get(*vm.Runtime.Host).(*HostSystem)
host.Vm = RemoveReference(vm.Self, host.Vm)
switch pool := Map.Get(*vm.ResourcePool).(type) {
case *ResourcePool:
pool.Vm = RemoveReference(vm.Self, pool.Vm)
case *VirtualApp:
pool.Vm = RemoveReference(vm.Self, pool.Vm)
}
for i := range vm.Datastore {
ds := Map.Get(vm.Datastore[i]).(*Datastore)
ds.Vm = RemoveReference(vm.Self, ds.Vm)
}
r.Res = new(types.UnregisterVMResponse)
return r
}
func (vm *VirtualMachine) CloneVMTask(req *types.CloneVM_Task) soap.HasFault {
task := CreateTask(vm, "cloneVm", func(t *Task) (types.AnyType, types.BaseMethodFault) {
folder := Map.Get(req.Folder).(*Folder)
config := types.VirtualMachineConfigSpec{
Name: req.Name,
GuestId: vm.Config.GuestId,
Files: &types.VirtualMachineFileInfo{
VmPathName: strings.Replace(vm.Config.Files.VmPathName, vm.Name, req.Name, -1),
},
}
res := folder.CreateVMTask(&types.CreateVM_Task{
This: folder.Self,
Config: config,
Pool: *vm.ResourcePool,
})
ctask := Map.Get(res.(*methods.CreateVM_TaskBody).Res.Returnval).(*Task)
if ctask.Info.Error != nil {
return nil, ctask.Info.Error.Fault
}
return ctask.Info.Result.(types.ManagedObjectReference), nil
})
return &methods.CloneVM_TaskBody{
Res: &types.CloneVM_TaskResponse{
Returnval: task.Run(),
},
}
}
func (vm *VirtualMachine) RelocateVMTask(req *types.RelocateVM_Task) soap.HasFault {
task := CreateTask(vm, "relocateVm", func(t *Task) (types.AnyType, types.BaseMethodFault) {
if ref := req.Spec.Datastore; ref != nil {
ds := Map.Get(*ref).(*Datastore)
ds.Vm = RemoveReference(*ref, ds.Vm)
vm.Datastore = []types.ManagedObjectReference{*ref}
// TODO: migrate vm.Config.Files (and vm.Summary.Config.VmPathName)
}
if ref := req.Spec.Pool; ref != nil {
pool := Map.Get(*ref).(*ResourcePool)
pool.Vm = RemoveReference(*ref, pool.Vm)
vm.ResourcePool = ref
}
if ref := req.Spec.Host; ref != nil {
host := Map.Get(*ref).(*HostSystem)
host.Vm = RemoveReference(*ref, host.Vm)
vm.Runtime.Host = ref
}
return nil, nil
})
return &methods.RelocateVM_TaskBody{
Res: &types.RelocateVM_TaskResponse{
Returnval: task.Run(),
},
}
}
func (vm *VirtualMachine) CreateSnapshotTask(req *types.CreateSnapshot_Task) soap.HasFault {
task := CreateTask(vm, "createSnapshot", func(t *Task) (types.AnyType, types.BaseMethodFault) {
if vm.Snapshot == nil {
vm.Snapshot = &types.VirtualMachineSnapshotInfo{}
}
snapshot := &VirtualMachineSnapshot{}
snapshot.Vm = vm.Reference()
snapshot.Config = *vm.Config
Map.Put(snapshot)
treeItem := types.VirtualMachineSnapshotTree{
Snapshot: snapshot.Self,
Vm: snapshot.Vm,
Name: req.Name,
Description: req.Description,
Id: atomic.AddInt32(&vm.sid, 1),
CreateTime: time.Now(),
State: vm.Runtime.PowerState,
Quiesced: req.Quiesce,
BackupManifest: "",
ReplaySupported: types.NewBool(false),
}
cur := vm.Snapshot.CurrentSnapshot
if cur != nil {
parent := Map.Get(*cur).(*VirtualMachineSnapshot)
parent.ChildSnapshot = append(parent.ChildSnapshot, snapshot.Self)
ss := findSnapshotInTree(vm.Snapshot.RootSnapshotList, *cur)
ss.ChildSnapshotList = append(ss.ChildSnapshotList, treeItem)
} else {
vm.Snapshot.RootSnapshotList = append(vm.Snapshot.RootSnapshotList, treeItem)
}
vm.Snapshot.CurrentSnapshot = &snapshot.Self
return nil, nil
})
return &methods.CreateSnapshot_TaskBody{
Res: &types.CreateSnapshot_TaskResponse{
Returnval: task.Run(),
},
}
}
func (vm *VirtualMachine) RevertToCurrentSnapshotTask(req *types.RevertToCurrentSnapshot_Task) soap.HasFault {
body := &methods.RevertToCurrentSnapshot_TaskBody{}
if vm.Snapshot == nil || vm.Snapshot.CurrentSnapshot == nil {
body.Fault_ = Fault("snapshot not found", &types.NotFound{})
return body
}
task := CreateTask(vm, "revertSnapshot", func(t *Task) (types.AnyType, types.BaseMethodFault) {
return nil, nil
})
body.Res = &types.RevertToCurrentSnapshot_TaskResponse{
Returnval: task.Run(),
}
return body
}
func (vm *VirtualMachine) RemoveAllSnapshotsTask(req *types.RemoveAllSnapshots_Task) soap.HasFault {
task := CreateTask(vm, "RemoveAllSnapshots", func(t *Task) (types.AnyType, types.BaseMethodFault) {
if vm.Snapshot == nil {
return nil, nil
}
refs := allSnapshotsInTree(vm.Snapshot.RootSnapshotList)
vm.Snapshot.CurrentSnapshot = nil
vm.Snapshot.RootSnapshotList = nil
for _, ref := range refs {
Map.Remove(ref)
}
return nil, nil
})
return &methods.RemoveAllSnapshots_TaskBody{
Res: &types.RemoveAllSnapshots_TaskResponse{
Returnval: task.Run(),
},
}
}
func (vm *VirtualMachine) ShutdownGuest(c *types.ShutdownGuest) soap.HasFault {
r := &methods.ShutdownGuestBody{}
// should be poweron
if vm.Runtime.PowerState == types.VirtualMachinePowerStatePoweredOff {
r.Fault_ = Fault("", &types.InvalidPowerState{
RequestedState: types.VirtualMachinePowerStatePoweredOn,
ExistingState: vm.Runtime.PowerState,
})
return r
}
// change state
vm.Runtime.PowerState = types.VirtualMachinePowerStatePoweredOff
vm.Summary.Runtime.PowerState = types.VirtualMachinePowerStatePoweredOff
r.Res = new(types.ShutdownGuestResponse)
return r
}
func findSnapshotInTree(tree []types.VirtualMachineSnapshotTree, ref types.ManagedObjectReference) *types.VirtualMachineSnapshotTree {
if tree == nil {
return nil
}
for i, ss := range tree {
if ss.Snapshot == ref {
return &tree[i]
}
target := findSnapshotInTree(ss.ChildSnapshotList, ref)
if target != nil {
return target
}
}
return nil
}
func findParentSnapshot(tree types.VirtualMachineSnapshotTree, ref types.ManagedObjectReference) *types.ManagedObjectReference {
for _, ss := range tree.ChildSnapshotList {
if ss.Snapshot == ref {
return &tree.Snapshot
}
res := findParentSnapshot(ss, ref)
if res != nil {
return res
}
}
return nil
}
func findParentSnapshotInTree(tree []types.VirtualMachineSnapshotTree, ref types.ManagedObjectReference) *types.ManagedObjectReference {
if tree == nil {
return nil
}
for _, ss := range tree {
res := findParentSnapshot(ss, ref)
if res != nil {
return res
}
}
return nil
}
func removeSnapshotInTree(tree []types.VirtualMachineSnapshotTree, ref types.ManagedObjectReference, removeChildren bool) []types.VirtualMachineSnapshotTree {
if tree == nil {
return tree
}
var result []types.VirtualMachineSnapshotTree
for _, ss := range tree {
if ss.Snapshot == ref {
if !removeChildren {
result = append(result, ss.ChildSnapshotList...)
}
} else {
ss.ChildSnapshotList = removeSnapshotInTree(ss.ChildSnapshotList, ref, removeChildren)
result = append(result, ss)
}
}
return result
}
func allSnapshotsInTree(tree []types.VirtualMachineSnapshotTree) []types.ManagedObjectReference {
var result []types.ManagedObjectReference
if tree == nil {
return result
}
for _, ss := range tree {
result = append(result, ss.Snapshot)
result = append(result, allSnapshotsInTree(ss.ChildSnapshotList)...)
}
return result
}

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

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

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

@@ -0,0 +1,20 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Package vpx contains SOAP responses from a vCenter server, captured using `govc ... -dump`.
*/
package vpx

View File

@@ -0,0 +1,64 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package vpx
import (
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
var RootFolder = mo.Folder{
ManagedEntity: mo.ManagedEntity{
ExtensibleManagedObject: mo.ExtensibleManagedObject{
Self: types.ManagedObjectReference{Type: "Folder", Value: "group-d1"},
Value: nil,
AvailableField: nil,
},
Parent: (*types.ManagedObjectReference)(nil),
CustomValue: nil,
OverallStatus: "green",
ConfigStatus: "green",
ConfigIssue: nil,
EffectiveRole: []int32{-1},
Permission: []types.Permission{
{
DynamicData: types.DynamicData{},
Entity: &types.ManagedObjectReference{Type: "Folder", Value: "group-d1"},
Principal: "VSPHERE.LOCAL\\Administrator",
Group: false,
RoleId: -1,
Propagate: true,
},
{
DynamicData: types.DynamicData{},
Entity: &types.ManagedObjectReference{Type: "Folder", Value: "group-d1"},
Principal: "VSPHERE.LOCAL\\Administrators",
Group: true,
RoleId: -1,
Propagate: true,
},
},
Name: "Datacenters",
DisabledMethod: nil,
RecentTask: nil,
DeclaredAlarmState: nil,
AlarmActionsEnabled: (*bool)(nil),
Tag: nil,
},
ChildType: []string{"Folder", "Datacenter"},
ChildEntity: nil,
}

View File

@@ -0,0 +1,86 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package vpx
import "github.com/vmware/govmomi/vim25/types"
// ServiceContent is the default template for the ServiceInstance content property.
// Capture method:
// govc object.collect -s -dump - content
var ServiceContent = types.ServiceContent{
RootFolder: types.ManagedObjectReference{Type: "Folder", Value: "group-d1"},
PropertyCollector: types.ManagedObjectReference{Type: "PropertyCollector", Value: "propertyCollector"},
ViewManager: &types.ManagedObjectReference{Type: "ViewManager", Value: "ViewManager"},
About: types.AboutInfo{
Name: "VMware vCenter Server",
FullName: "VMware vCenter Server 6.5.0 build-5973321",
Vendor: "VMware, Inc.",
Version: "6.5.0",
Build: "5973321",
LocaleVersion: "INTL",
LocaleBuild: "000",
OsType: "linux-x64",
ProductLineId: "vpx",
ApiType: "VirtualCenter",
ApiVersion: "6.5",
InstanceUuid: "dbed6e0c-bd88-4ef6-b594-21283e1c677f",
LicenseProductName: "VMware VirtualCenter Server",
LicenseProductVersion: "6.0",
},
Setting: &types.ManagedObjectReference{Type: "OptionManager", Value: "VpxSettings"},
UserDirectory: &types.ManagedObjectReference{Type: "UserDirectory", Value: "UserDirectory"},
SessionManager: &types.ManagedObjectReference{Type: "SessionManager", Value: "SessionManager"},
AuthorizationManager: &types.ManagedObjectReference{Type: "AuthorizationManager", Value: "AuthorizationManager"},
ServiceManager: &types.ManagedObjectReference{Type: "ServiceManager", Value: "ServiceMgr"},
PerfManager: &types.ManagedObjectReference{Type: "PerformanceManager", Value: "PerfMgr"},
ScheduledTaskManager: &types.ManagedObjectReference{Type: "ScheduledTaskManager", Value: "ScheduledTaskManager"},
AlarmManager: &types.ManagedObjectReference{Type: "AlarmManager", Value: "AlarmManager"},
EventManager: &types.ManagedObjectReference{Type: "EventManager", Value: "EventManager"},
TaskManager: &types.ManagedObjectReference{Type: "TaskManager", Value: "TaskManager"},
ExtensionManager: &types.ManagedObjectReference{Type: "ExtensionManager", Value: "ExtensionManager"},
CustomizationSpecManager: &types.ManagedObjectReference{Type: "CustomizationSpecManager", Value: "CustomizationSpecManager"},
CustomFieldsManager: &types.ManagedObjectReference{Type: "CustomFieldsManager", Value: "CustomFieldsManager"},
AccountManager: (*types.ManagedObjectReference)(nil),
DiagnosticManager: &types.ManagedObjectReference{Type: "DiagnosticManager", Value: "DiagMgr"},
LicenseManager: &types.ManagedObjectReference{Type: "LicenseManager", Value: "LicenseManager"},
SearchIndex: &types.ManagedObjectReference{Type: "SearchIndex", Value: "SearchIndex"},
FileManager: &types.ManagedObjectReference{Type: "FileManager", Value: "FileManager"},
DatastoreNamespaceManager: &types.ManagedObjectReference{Type: "DatastoreNamespaceManager", Value: "DatastoreNamespaceManager"},
VirtualDiskManager: &types.ManagedObjectReference{Type: "VirtualDiskManager", Value: "virtualDiskManager"},
VirtualizationManager: (*types.ManagedObjectReference)(nil),
SnmpSystem: &types.ManagedObjectReference{Type: "HostSnmpSystem", Value: "SnmpSystem"},
VmProvisioningChecker: &types.ManagedObjectReference{Type: "VirtualMachineProvisioningChecker", Value: "ProvChecker"},
VmCompatibilityChecker: &types.ManagedObjectReference{Type: "VirtualMachineCompatibilityChecker", Value: "CompatChecker"},
OvfManager: &types.ManagedObjectReference{Type: "OvfManager", Value: "OvfManager"},
IpPoolManager: &types.ManagedObjectReference{Type: "IpPoolManager", Value: "IpPoolManager"},
DvSwitchManager: &types.ManagedObjectReference{Type: "DistributedVirtualSwitchManager", Value: "DVSManager"},
HostProfileManager: &types.ManagedObjectReference{Type: "HostProfileManager", Value: "HostProfileManager"},
ClusterProfileManager: &types.ManagedObjectReference{Type: "ClusterProfileManager", Value: "ClusterProfileManager"},
ComplianceManager: &types.ManagedObjectReference{Type: "ProfileComplianceManager", Value: "MoComplianceManager"},
LocalizationManager: &types.ManagedObjectReference{Type: "LocalizationManager", Value: "LocalizationManager"},
StorageResourceManager: &types.ManagedObjectReference{Type: "StorageResourceManager", Value: "StorageResourceManager"},
GuestOperationsManager: &types.ManagedObjectReference{Type: "GuestOperationsManager", Value: "guestOperationsManager"},
OverheadMemoryManager: &types.ManagedObjectReference{Type: "OverheadMemoryManager", Value: "OverheadMemoryManager"},
CertificateManager: &types.ManagedObjectReference{Type: "CertificateManager", Value: "certificateManager"},
IoFilterManager: &types.ManagedObjectReference{Type: "IoFilterManager", Value: "IoFilterManager"},
VStorageObjectManager: &types.ManagedObjectReference{Type: "VcenterVStorageObjectManager", Value: "VStorageObjectManager"},
HostSpecManager: &types.ManagedObjectReference{Type: "HostSpecificationManager", Value: "HostSpecificationManager"},
CryptoManager: &types.ManagedObjectReference{Type: "CryptoManagerKmip", Value: "CryptoManager"},
HealthUpdateManager: &types.ManagedObjectReference{Type: "HealthUpdateManager", Value: "HealthUpdateManager"},
FailoverClusterConfigurator: &types.ManagedObjectReference{Type: "FailoverClusterConfigurator", Value: "FailoverClusterConfigurator"},
FailoverClusterManager: &types.ManagedObjectReference{Type: "FailoverClusterManager", Value: "FailoverClusterManager"},
}

View File

@@ -0,0 +1,60 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package vpx
import "github.com/vmware/govmomi/vim25/types"
// Setting is captured from VC's ServiceContent.OptionManager.setting
var Setting = []types.BaseOptionValue{
// This list is currently pruned to include sso options only with sso.enabled set to false
&types.OptionValue{
Key: "config.vpxd.sso.sts.uri",
Value: "https://127.0.0.1/sts/STSService/vsphere.local",
},
&types.OptionValue{
Key: "config.vpxd.sso.solutionUser.privateKey",
Value: "/etc/vmware-vpx/ssl/vcsoluser.key",
},
&types.OptionValue{
Key: "config.vpxd.sso.solutionUser.name",
Value: "vpxd-b643d01c-928f-469b-96a5-d571d762a78e@vsphere.local",
},
&types.OptionValue{
Key: "config.vpxd.sso.solutionUser.certificate",
Value: "/etc/vmware-vpx/ssl/vcsoluser.crt",
},
&types.OptionValue{
Key: "config.vpxd.sso.groupcheck.uri",
Value: "https://127.0.0.1/sso-adminserver/sdk/vsphere.local",
},
&types.OptionValue{
Key: "config.vpxd.sso.enabled",
Value: "false",
},
&types.OptionValue{
Key: "config.vpxd.sso.default.isGroup",
Value: "false",
},
&types.OptionValue{
Key: "config.vpxd.sso.default.admin",
Value: "Administrator@vsphere.local",
},
&types.OptionValue{
Key: "config.vpxd.sso.admin.uri",
Value: "https://127.0.0.1/sso-adminserver/sdk/vsphere.local",
},
}