resource_pool.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  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. "fmt"
  16. "strings"
  17. "github.com/vmware/govmomi/simulator/esx"
  18. "github.com/vmware/govmomi/vim25/methods"
  19. "github.com/vmware/govmomi/vim25/mo"
  20. "github.com/vmware/govmomi/vim25/soap"
  21. "github.com/vmware/govmomi/vim25/types"
  22. )
  23. type ResourcePool struct {
  24. mo.ResourcePool
  25. }
  26. func NewResourcePool() *ResourcePool {
  27. pool := &ResourcePool{
  28. ResourcePool: esx.ResourcePool,
  29. }
  30. if Map.IsVPX() {
  31. pool.DisabledMethod = nil // Enable VApp methods for VC
  32. }
  33. return pool
  34. }
  35. func allResourceFieldsSet(info *types.ResourceAllocationInfo) bool {
  36. return info.Reservation != nil &&
  37. info.Limit != nil &&
  38. info.ExpandableReservation != nil &&
  39. info.Shares != nil
  40. }
  41. func allResourceFieldsValid(info *types.ResourceAllocationInfo) bool {
  42. if info.Reservation != nil {
  43. if *info.Reservation < 0 {
  44. return false
  45. }
  46. }
  47. if info.Limit != nil {
  48. if *info.Limit < -1 {
  49. return false
  50. }
  51. }
  52. if info.Shares != nil {
  53. if info.Shares.Level == types.SharesLevelCustom {
  54. if info.Shares.Shares < 0 {
  55. return false
  56. }
  57. }
  58. }
  59. if info.OverheadLimit != nil {
  60. return false
  61. }
  62. return true
  63. }
  64. func (p *ResourcePool) createChild(name string, spec types.ResourceConfigSpec) (*ResourcePool, *soap.Fault) {
  65. if e := Map.FindByName(name, p.ResourcePool.ResourcePool); e != nil {
  66. return nil, Fault("", &types.DuplicateName{
  67. Name: e.Entity().Name,
  68. Object: e.Reference(),
  69. })
  70. }
  71. if !(allResourceFieldsSet(&spec.CpuAllocation) && allResourceFieldsValid(&spec.CpuAllocation)) {
  72. return nil, Fault("", &types.InvalidArgument{
  73. InvalidProperty: "spec.cpuAllocation",
  74. })
  75. }
  76. if !(allResourceFieldsSet(&spec.MemoryAllocation) && allResourceFieldsValid(&spec.MemoryAllocation)) {
  77. return nil, Fault("", &types.InvalidArgument{
  78. InvalidProperty: "spec.memoryAllocation",
  79. })
  80. }
  81. child := NewResourcePool()
  82. child.Name = name
  83. child.Owner = p.Owner
  84. child.Summary.GetResourcePoolSummary().Name = name
  85. child.Config.CpuAllocation = spec.CpuAllocation
  86. child.Config.MemoryAllocation = spec.MemoryAllocation
  87. child.Config.Entity = spec.Entity
  88. return child, nil
  89. }
  90. func (p *ResourcePool) CreateResourcePool(c *types.CreateResourcePool) soap.HasFault {
  91. body := &methods.CreateResourcePoolBody{}
  92. child, err := p.createChild(c.Name, c.Spec)
  93. if err != nil {
  94. body.Fault_ = err
  95. return body
  96. }
  97. Map.PutEntity(p, Map.NewEntity(child))
  98. p.ResourcePool.ResourcePool = append(p.ResourcePool.ResourcePool, child.Reference())
  99. body.Res = &types.CreateResourcePoolResponse{
  100. Returnval: child.Reference(),
  101. }
  102. return body
  103. }
  104. func updateResourceAllocation(kind string, src, dst *types.ResourceAllocationInfo) types.BaseMethodFault {
  105. if !allResourceFieldsValid(src) {
  106. return &types.InvalidArgument{
  107. InvalidProperty: fmt.Sprintf("spec.%sAllocation", kind),
  108. }
  109. }
  110. if src.Reservation != nil {
  111. dst.Reservation = src.Reservation
  112. }
  113. if src.Limit != nil {
  114. dst.Limit = src.Limit
  115. }
  116. if src.Shares != nil {
  117. dst.Shares = src.Shares
  118. }
  119. return nil
  120. }
  121. func (p *ResourcePool) UpdateConfig(c *types.UpdateConfig) soap.HasFault {
  122. body := &methods.UpdateConfigBody{}
  123. if c.Name != "" {
  124. if e := Map.FindByName(c.Name, p.ResourcePool.ResourcePool); e != nil {
  125. body.Fault_ = Fault("", &types.DuplicateName{
  126. Name: e.Entity().Name,
  127. Object: e.Reference(),
  128. })
  129. return body
  130. }
  131. p.Name = c.Name
  132. }
  133. spec := c.Config
  134. if spec != nil {
  135. if err := updateResourceAllocation("memory", &spec.MemoryAllocation, &p.Config.MemoryAllocation); err != nil {
  136. body.Fault_ = Fault("", err)
  137. return body
  138. }
  139. if err := updateResourceAllocation("cpu", &spec.CpuAllocation, &p.Config.CpuAllocation); err != nil {
  140. body.Fault_ = Fault("", err)
  141. return body
  142. }
  143. }
  144. body.Res = &types.UpdateConfigResponse{}
  145. return body
  146. }
  147. type VirtualApp struct {
  148. mo.VirtualApp
  149. }
  150. func NewVAppConfigSpec() types.VAppConfigSpec {
  151. spec := types.VAppConfigSpec{
  152. Annotation: "vcsim",
  153. VmConfigSpec: types.VmConfigSpec{
  154. Product: []types.VAppProductSpec{
  155. {
  156. Info: &types.VAppProductInfo{
  157. Name: "vcsim",
  158. Vendor: "VMware",
  159. VendorUrl: "http://www.vmware.com/",
  160. Version: "0.1",
  161. },
  162. ArrayUpdateSpec: types.ArrayUpdateSpec{
  163. Operation: types.ArrayUpdateOperationAdd,
  164. },
  165. },
  166. },
  167. },
  168. }
  169. return spec
  170. }
  171. func (p *ResourcePool) CreateVApp(req *types.CreateVApp) soap.HasFault {
  172. body := &methods.CreateVAppBody{}
  173. pool, err := p.createChild(req.Name, req.ResSpec)
  174. if err != nil {
  175. body.Fault_ = err
  176. return body
  177. }
  178. child := &VirtualApp{}
  179. child.ResourcePool = pool.ResourcePool
  180. child.Self.Type = "VirtualApp"
  181. child.ParentFolder = req.VmFolder
  182. if child.ParentFolder == nil {
  183. folder := Map.getEntityDatacenter(p).VmFolder
  184. child.ParentFolder = &folder
  185. }
  186. child.VAppConfig = &types.VAppConfigInfo{
  187. VmConfigInfo: types.VmConfigInfo{},
  188. Annotation: req.ConfigSpec.Annotation,
  189. }
  190. for _, product := range req.ConfigSpec.Product {
  191. child.VAppConfig.Product = append(child.VAppConfig.Product, *product.Info)
  192. }
  193. Map.PutEntity(p, Map.NewEntity(child))
  194. p.ResourcePool.ResourcePool = append(p.ResourcePool.ResourcePool, child.Reference())
  195. body.Res = &types.CreateVAppResponse{
  196. Returnval: child.Reference(),
  197. }
  198. return body
  199. }
  200. func (a *VirtualApp) CreateChildVMTask(ctx *Context, req *types.CreateChildVM_Task) soap.HasFault {
  201. ctx.Caller = &a.Self
  202. body := &methods.CreateChildVM_TaskBody{}
  203. folder := Map.Get(*a.ParentFolder).(*Folder)
  204. res := folder.CreateVMTask(ctx, &types.CreateVM_Task{
  205. This: folder.Self,
  206. Config: req.Config,
  207. Host: req.Host,
  208. Pool: req.This,
  209. })
  210. body.Res = &types.CreateChildVM_TaskResponse{
  211. Returnval: res.(*methods.CreateVM_TaskBody).Res.Returnval,
  212. }
  213. return body
  214. }
  215. func (a *VirtualApp) DestroyTask(req *types.Destroy_Task) soap.HasFault {
  216. return (&ResourcePool{ResourcePool: a.ResourcePool}).DestroyTask(req)
  217. }
  218. func (p *ResourcePool) DestroyTask(req *types.Destroy_Task) soap.HasFault {
  219. task := CreateTask(p, "destroy", func(t *Task) (types.AnyType, types.BaseMethodFault) {
  220. if strings.HasSuffix(p.Parent.Type, "ComputeResource") {
  221. // Can't destroy the root pool
  222. return nil, &types.InvalidArgument{}
  223. }
  224. pp := Map.Get(*p.Parent).(*ResourcePool)
  225. parent := &pp.ResourcePool
  226. // Remove child reference from rp
  227. Map.RemoveReference(parent, &parent.ResourcePool, req.This)
  228. // The grandchildren become children of the parent (rp)
  229. Map.AppendReference(parent, &parent.ResourcePool, p.ResourcePool.ResourcePool...)
  230. // And VMs move to the parent
  231. vms := p.ResourcePool.Vm
  232. for _, ref := range vms {
  233. vm := Map.Get(ref).(*VirtualMachine)
  234. Map.WithLock(vm, func() { vm.ResourcePool = &parent.Self })
  235. }
  236. Map.AppendReference(parent, &parent.Vm, vms...)
  237. Map.Remove(req.This)
  238. return nil, nil
  239. })
  240. return &methods.Destroy_TaskBody{
  241. Res: &types.Destroy_TaskResponse{
  242. Returnval: task.Run(),
  243. },
  244. }
  245. }