retrieve.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. Copyright (c) 2014-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 mo
  14. import (
  15. "context"
  16. "reflect"
  17. "github.com/vmware/govmomi/vim25/methods"
  18. "github.com/vmware/govmomi/vim25/soap"
  19. "github.com/vmware/govmomi/vim25/types"
  20. )
  21. func ignoreMissingProperty(ref types.ManagedObjectReference, p types.MissingProperty) bool {
  22. switch ref.Type {
  23. case "VirtualMachine":
  24. switch p.Path {
  25. case "environmentBrowser":
  26. // See https://github.com/vmware/govmomi/pull/242
  27. return true
  28. case "alarmActionsEnabled":
  29. // Seen with vApp child VM
  30. return true
  31. }
  32. }
  33. return false
  34. }
  35. // ObjectContentToType loads an ObjectContent value into the value it
  36. // represents. If the ObjectContent value has a non-empty 'MissingSet' field,
  37. // it returns the first fault it finds there as error. If the 'MissingSet'
  38. // field is empty, it returns a pointer to a reflect.Value. It handles contain
  39. // nested properties, such as 'guest.ipAddress' or 'config.hardware'.
  40. func ObjectContentToType(o types.ObjectContent) (interface{}, error) {
  41. // Expect no properties in the missing set
  42. for _, p := range o.MissingSet {
  43. if ignoreMissingProperty(o.Obj, p) {
  44. continue
  45. }
  46. return nil, soap.WrapVimFault(p.Fault.Fault)
  47. }
  48. ti := typeInfoForType(o.Obj.Type)
  49. v, err := ti.LoadFromObjectContent(o)
  50. if err != nil {
  51. return nil, err
  52. }
  53. return v.Elem().Interface(), nil
  54. }
  55. // ApplyPropertyChange converts the response of a call to WaitForUpdates
  56. // and applies it to the given managed object.
  57. func ApplyPropertyChange(obj Reference, changes []types.PropertyChange) {
  58. t := typeInfoForType(obj.Reference().Type)
  59. v := reflect.ValueOf(obj)
  60. for _, p := range changes {
  61. rv, ok := t.props[p.Name]
  62. if !ok {
  63. continue
  64. }
  65. assignValue(v, rv, reflect.ValueOf(p.Val))
  66. }
  67. }
  68. // LoadRetrievePropertiesResponse converts the response of a call to
  69. // RetrieveProperties to one or more managed objects.
  70. func LoadRetrievePropertiesResponse(res *types.RetrievePropertiesResponse, dst interface{}) error {
  71. rt := reflect.TypeOf(dst)
  72. if rt == nil || rt.Kind() != reflect.Ptr {
  73. panic("need pointer")
  74. }
  75. rv := reflect.ValueOf(dst).Elem()
  76. if !rv.CanSet() {
  77. panic("cannot set dst")
  78. }
  79. isSlice := false
  80. switch rt.Elem().Kind() {
  81. case reflect.Struct:
  82. case reflect.Slice:
  83. isSlice = true
  84. default:
  85. panic("unexpected type")
  86. }
  87. if isSlice {
  88. for _, p := range res.Returnval {
  89. v, err := ObjectContentToType(p)
  90. if err != nil {
  91. return err
  92. }
  93. vt := reflect.TypeOf(v)
  94. if !rv.Type().AssignableTo(vt) {
  95. // For example: dst is []ManagedEntity, res is []HostSystem
  96. if field, ok := vt.FieldByName(rt.Elem().Elem().Name()); ok && field.Anonymous {
  97. rv.Set(reflect.Append(rv, reflect.ValueOf(v).FieldByIndex(field.Index)))
  98. continue
  99. }
  100. }
  101. rv.Set(reflect.Append(rv, reflect.ValueOf(v)))
  102. }
  103. } else {
  104. switch len(res.Returnval) {
  105. case 0:
  106. case 1:
  107. v, err := ObjectContentToType(res.Returnval[0])
  108. if err != nil {
  109. return err
  110. }
  111. vt := reflect.TypeOf(v)
  112. if !rv.Type().AssignableTo(vt) {
  113. // For example: dst is ComputeResource, res is ClusterComputeResource
  114. if field, ok := vt.FieldByName(rt.Elem().Name()); ok && field.Anonymous {
  115. rv.Set(reflect.ValueOf(v).FieldByIndex(field.Index))
  116. return nil
  117. }
  118. }
  119. rv.Set(reflect.ValueOf(v))
  120. default:
  121. // If dst is not a slice, expect to receive 0 or 1 results
  122. panic("more than 1 result")
  123. }
  124. }
  125. return nil
  126. }
  127. // RetrievePropertiesForRequest calls the RetrieveProperties method with the
  128. // specified request and decodes the response struct into the value pointed to
  129. // by dst.
  130. func RetrievePropertiesForRequest(ctx context.Context, r soap.RoundTripper, req types.RetrieveProperties, dst interface{}) error {
  131. res, err := methods.RetrieveProperties(ctx, r, &req)
  132. if err != nil {
  133. return err
  134. }
  135. return LoadRetrievePropertiesResponse(res, dst)
  136. }
  137. // RetrieveProperties retrieves the properties of the managed object specified
  138. // as obj and decodes the response struct into the value pointed to by dst.
  139. func RetrieveProperties(ctx context.Context, r soap.RoundTripper, pc, obj types.ManagedObjectReference, dst interface{}) error {
  140. req := types.RetrieveProperties{
  141. This: pc,
  142. SpecSet: []types.PropertyFilterSpec{
  143. {
  144. ObjectSet: []types.ObjectSpec{
  145. {
  146. Obj: obj,
  147. Skip: types.NewBool(false),
  148. },
  149. },
  150. PropSet: []types.PropertySpec{
  151. {
  152. All: types.NewBool(true),
  153. Type: obj.Type,
  154. },
  155. },
  156. },
  157. },
  158. }
  159. return RetrievePropertiesForRequest(ctx, r, req, dst)
  160. }