collector.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*
  2. Copyright (c) 2015 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 property
  14. import (
  15. "context"
  16. "errors"
  17. "github.com/vmware/govmomi/vim25"
  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. // Collector models the PropertyCollector managed object.
  24. //
  25. // For more information, see:
  26. // http://pubs.vmware.com/vsphere-60/index.jsp?topic=%2Fcom.vmware.wssdk.apiref.doc%2Fvmodl.query.PropertyCollector.html
  27. //
  28. type Collector struct {
  29. roundTripper soap.RoundTripper
  30. reference types.ManagedObjectReference
  31. }
  32. // DefaultCollector returns the session's default property collector.
  33. func DefaultCollector(c *vim25.Client) *Collector {
  34. p := Collector{
  35. roundTripper: c,
  36. reference: c.ServiceContent.PropertyCollector,
  37. }
  38. return &p
  39. }
  40. func (p Collector) Reference() types.ManagedObjectReference {
  41. return p.reference
  42. }
  43. // Create creates a new session-specific Collector that can be used to
  44. // retrieve property updates independent of any other Collector.
  45. func (p *Collector) Create(ctx context.Context) (*Collector, error) {
  46. req := types.CreatePropertyCollector{
  47. This: p.Reference(),
  48. }
  49. res, err := methods.CreatePropertyCollector(ctx, p.roundTripper, &req)
  50. if err != nil {
  51. return nil, err
  52. }
  53. newp := Collector{
  54. roundTripper: p.roundTripper,
  55. reference: res.Returnval,
  56. }
  57. return &newp, nil
  58. }
  59. // Destroy destroys this Collector.
  60. func (p *Collector) Destroy(ctx context.Context) error {
  61. req := types.DestroyPropertyCollector{
  62. This: p.Reference(),
  63. }
  64. _, err := methods.DestroyPropertyCollector(ctx, p.roundTripper, &req)
  65. if err != nil {
  66. return err
  67. }
  68. p.reference = types.ManagedObjectReference{}
  69. return nil
  70. }
  71. func (p *Collector) CreateFilter(ctx context.Context, req types.CreateFilter) error {
  72. req.This = p.Reference()
  73. _, err := methods.CreateFilter(ctx, p.roundTripper, &req)
  74. if err != nil {
  75. return err
  76. }
  77. return nil
  78. }
  79. func (p *Collector) WaitForUpdates(ctx context.Context, v string) (*types.UpdateSet, error) {
  80. req := types.WaitForUpdatesEx{
  81. This: p.Reference(),
  82. Version: v,
  83. }
  84. res, err := methods.WaitForUpdatesEx(ctx, p.roundTripper, &req)
  85. if err != nil {
  86. return nil, err
  87. }
  88. return res.Returnval, nil
  89. }
  90. func (p *Collector) CancelWaitForUpdates(ctx context.Context) error {
  91. req := &types.CancelWaitForUpdates{This: p.Reference()}
  92. _, err := methods.CancelWaitForUpdates(ctx, p.roundTripper, req)
  93. return err
  94. }
  95. func (p *Collector) RetrieveProperties(ctx context.Context, req types.RetrieveProperties) (*types.RetrievePropertiesResponse, error) {
  96. req.This = p.Reference()
  97. return methods.RetrieveProperties(ctx, p.roundTripper, &req)
  98. }
  99. // Retrieve loads properties for a slice of managed objects. The dst argument
  100. // must be a pointer to a []interface{}, which is populated with the instances
  101. // of the specified managed objects, with the relevant properties filled in. If
  102. // the properties slice is nil, all properties are loaded.
  103. // Note that pointer types are optional fields that may be left as a nil value.
  104. // The caller should check such fields for a nil value before dereferencing.
  105. func (p *Collector) Retrieve(ctx context.Context, objs []types.ManagedObjectReference, ps []string, dst interface{}) error {
  106. if len(objs) == 0 {
  107. return errors.New("object references is empty")
  108. }
  109. kinds := make(map[string]bool)
  110. var propSet []types.PropertySpec
  111. var objectSet []types.ObjectSpec
  112. for _, obj := range objs {
  113. if _, ok := kinds[obj.Type]; !ok {
  114. spec := types.PropertySpec{
  115. Type: obj.Type,
  116. }
  117. if ps == nil {
  118. spec.All = types.NewBool(true)
  119. } else {
  120. spec.PathSet = ps
  121. }
  122. propSet = append(propSet, spec)
  123. kinds[obj.Type] = true
  124. }
  125. objectSpec := types.ObjectSpec{
  126. Obj: obj,
  127. Skip: types.NewBool(false),
  128. }
  129. objectSet = append(objectSet, objectSpec)
  130. }
  131. req := types.RetrieveProperties{
  132. SpecSet: []types.PropertyFilterSpec{
  133. {
  134. ObjectSet: objectSet,
  135. PropSet: propSet,
  136. },
  137. },
  138. }
  139. res, err := p.RetrieveProperties(ctx, req)
  140. if err != nil {
  141. return err
  142. }
  143. if d, ok := dst.(*[]types.ObjectContent); ok {
  144. *d = res.Returnval
  145. return nil
  146. }
  147. return mo.LoadRetrievePropertiesResponse(res, dst)
  148. }
  149. // RetrieveWithFilter populates dst as Retrieve does, but only for entities matching the given filter.
  150. func (p *Collector) RetrieveWithFilter(ctx context.Context, objs []types.ManagedObjectReference, ps []string, dst interface{}, filter Filter) error {
  151. if len(filter) == 0 {
  152. return p.Retrieve(ctx, objs, ps, dst)
  153. }
  154. var content []types.ObjectContent
  155. err := p.Retrieve(ctx, objs, filter.Keys(), &content)
  156. if err != nil {
  157. return err
  158. }
  159. objs = filter.MatchObjectContent(content)
  160. if len(objs) == 0 {
  161. return nil
  162. }
  163. return p.Retrieve(ctx, objs, ps, dst)
  164. }
  165. // RetrieveOne calls Retrieve with a single managed object reference via Collector.Retrieve().
  166. func (p *Collector) RetrieveOne(ctx context.Context, obj types.ManagedObjectReference, ps []string, dst interface{}) error {
  167. var objs = []types.ManagedObjectReference{obj}
  168. return p.Retrieve(ctx, objs, ps, dst)
  169. }