view_manager.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /*
  2. Copyright (c) 2017 VMware, Inc. All Rights Reserved.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package simulator
  14. import (
  15. "reflect"
  16. "github.com/vmware/govmomi/object"
  17. "github.com/vmware/govmomi/vim25/methods"
  18. "github.com/vmware/govmomi/vim25/mo"
  19. "github.com/vmware/govmomi/vim25/soap"
  20. "github.com/vmware/govmomi/vim25/types"
  21. )
  22. type ViewManager struct {
  23. mo.ViewManager
  24. entities map[string]bool
  25. }
  26. var entities = []struct {
  27. Type reflect.Type
  28. Container bool
  29. }{
  30. {reflect.TypeOf((*mo.ManagedEntity)(nil)).Elem(), true},
  31. {reflect.TypeOf((*mo.Folder)(nil)).Elem(), true},
  32. {reflect.TypeOf((*mo.StoragePod)(nil)).Elem(), true},
  33. {reflect.TypeOf((*mo.Datacenter)(nil)).Elem(), true},
  34. {reflect.TypeOf((*mo.ComputeResource)(nil)).Elem(), true},
  35. {reflect.TypeOf((*mo.ClusterComputeResource)(nil)).Elem(), true},
  36. {reflect.TypeOf((*mo.HostSystem)(nil)).Elem(), true},
  37. {reflect.TypeOf((*mo.ResourcePool)(nil)).Elem(), true},
  38. {reflect.TypeOf((*mo.VirtualApp)(nil)).Elem(), true},
  39. {reflect.TypeOf((*mo.VirtualMachine)(nil)).Elem(), false},
  40. {reflect.TypeOf((*mo.Datastore)(nil)).Elem(), false},
  41. {reflect.TypeOf((*mo.Network)(nil)).Elem(), false},
  42. {reflect.TypeOf((*mo.OpaqueNetwork)(nil)).Elem(), false},
  43. {reflect.TypeOf((*mo.DistributedVirtualPortgroup)(nil)).Elem(), false},
  44. {reflect.TypeOf((*mo.DistributedVirtualSwitch)(nil)).Elem(), false},
  45. {reflect.TypeOf((*mo.VmwareDistributedVirtualSwitch)(nil)).Elem(), false},
  46. }
  47. func NewViewManager(ref types.ManagedObjectReference) object.Reference {
  48. s := &ViewManager{
  49. entities: make(map[string]bool),
  50. }
  51. s.Self = ref
  52. for _, e := range entities {
  53. s.entities[e.Type.Name()] = e.Container
  54. }
  55. return s
  56. }
  57. func destroyView(ref types.ManagedObjectReference) soap.HasFault {
  58. m := Map.ViewManager()
  59. RemoveReference(&m.ViewList, ref)
  60. return &methods.DestroyViewBody{
  61. Res: &types.DestroyViewResponse{},
  62. }
  63. }
  64. func (m *ViewManager) CreateContainerView(ctx *Context, req *types.CreateContainerView) soap.HasFault {
  65. body := &methods.CreateContainerViewBody{}
  66. root := Map.Get(req.Container)
  67. if root == nil {
  68. body.Fault_ = Fault("", &types.ManagedObjectNotFound{Obj: req.Container})
  69. return body
  70. }
  71. if m.entities[root.Reference().Type] != true {
  72. body.Fault_ = Fault("", &types.InvalidArgument{InvalidProperty: "container"})
  73. return body
  74. }
  75. container := &ContainerView{
  76. mo.ContainerView{
  77. Container: root.Reference(),
  78. Recursive: req.Recursive,
  79. Type: req.Type,
  80. },
  81. make(map[string]bool),
  82. }
  83. for _, ctype := range container.Type {
  84. if _, ok := m.entities[ctype]; !ok {
  85. body.Fault_ = Fault("", &types.InvalidArgument{InvalidProperty: "type"})
  86. return body
  87. }
  88. container.types[ctype] = true
  89. for _, e := range entities {
  90. // Check for embedded types
  91. if f, ok := e.Type.FieldByName(ctype); ok && f.Anonymous {
  92. container.types[e.Type.Name()] = true
  93. }
  94. }
  95. }
  96. ctx.Session.Put(container)
  97. m.ViewList = append(m.ViewList, container.Reference())
  98. body.Res = &types.CreateContainerViewResponse{
  99. Returnval: container.Self,
  100. }
  101. seen := make(map[types.ManagedObjectReference]bool)
  102. container.add(root, seen)
  103. return body
  104. }
  105. type ContainerView struct {
  106. mo.ContainerView
  107. types map[string]bool
  108. }
  109. func (v *ContainerView) DestroyView(ctx *Context, c *types.DestroyView) soap.HasFault {
  110. ctx.Session.Remove(c.This)
  111. return destroyView(c.This)
  112. }
  113. func (v *ContainerView) include(o types.ManagedObjectReference) bool {
  114. if len(v.types) == 0 {
  115. return true
  116. }
  117. return v.types[o.Type]
  118. }
  119. func walk(root mo.Reference, f func(child types.ManagedObjectReference)) {
  120. var children []types.ManagedObjectReference
  121. switch e := root.(type) {
  122. case *Datacenter:
  123. children = []types.ManagedObjectReference{e.VmFolder, e.HostFolder, e.DatastoreFolder, e.NetworkFolder}
  124. case *Folder:
  125. children = e.ChildEntity
  126. case *mo.ComputeResource:
  127. children = e.Host
  128. children = append(children, *e.ResourcePool)
  129. case *ClusterComputeResource:
  130. children = e.Host
  131. children = append(children, *e.ResourcePool)
  132. case *ResourcePool:
  133. children = e.ResourcePool.ResourcePool
  134. children = append(children, e.Vm...)
  135. case *VirtualApp:
  136. children = e.ResourcePool.ResourcePool
  137. children = append(children, e.Vm...)
  138. case *HostSystem:
  139. children = e.Vm
  140. }
  141. for _, child := range children {
  142. f(child)
  143. }
  144. }
  145. func (v *ContainerView) add(root mo.Reference, seen map[types.ManagedObjectReference]bool) {
  146. walk(root, func(child types.ManagedObjectReference) {
  147. if v.include(child) {
  148. if seen[child] == false {
  149. seen[child] = true
  150. v.View = append(v.View, child)
  151. }
  152. }
  153. if v.Recursive {
  154. v.add(Map.Get(child), seen)
  155. }
  156. })
  157. }
  158. func (m *ViewManager) CreateListView(ctx *Context, req *types.CreateListView) soap.HasFault {
  159. body := new(methods.CreateListViewBody)
  160. list := new(ListView)
  161. if err := list.add(req.Obj); err != nil {
  162. body.Fault_ = Fault("", err)
  163. return body
  164. }
  165. ctx.Session.Put(list)
  166. body.Res = &types.CreateListViewResponse{
  167. Returnval: list.Self,
  168. }
  169. return body
  170. }
  171. type ListView struct {
  172. mo.ListView
  173. }
  174. func (v *ListView) update() {
  175. Map.Update(v, []types.PropertyChange{{Name: "view", Val: v.View}})
  176. }
  177. func (v *ListView) add(refs []types.ManagedObjectReference) *types.ManagedObjectNotFound {
  178. for _, ref := range refs {
  179. obj := Map.Get(ref)
  180. if obj == nil {
  181. return &types.ManagedObjectNotFound{Obj: ref}
  182. }
  183. v.View = append(v.View, ref)
  184. }
  185. return nil
  186. }
  187. func (v *ListView) DestroyView(ctx *Context, c *types.DestroyView) soap.HasFault {
  188. ctx.Session.Remove(c.This)
  189. return destroyView(c.This)
  190. }
  191. func (v *ListView) ModifyListView(req *types.ModifyListView) soap.HasFault {
  192. body := new(methods.ModifyListViewBody)
  193. for _, ref := range req.Remove {
  194. RemoveReference(&v.View, ref)
  195. }
  196. if err := v.add(req.Add); err != nil {
  197. body.Fault_ = Fault("", err)
  198. return body
  199. }
  200. body.Res = new(types.ModifyListViewResponse)
  201. if len(req.Remove) != 0 || len(req.Add) != 0 {
  202. v.update()
  203. }
  204. return body
  205. }
  206. func (v *ListView) ResetListView(req *types.ResetListView) soap.HasFault {
  207. body := new(methods.ResetListViewBody)
  208. v.View = nil
  209. if err := v.add(req.Obj); err != nil {
  210. body.Fault_ = Fault("", err)
  211. return body
  212. }
  213. body.Res = new(types.ResetListViewResponse)
  214. v.update()
  215. return body
  216. }