diff options
Diffstat (limited to 'vendor/github.com/mitchellh/packer/vendor/github.com/vmware/govmomi/vim25/mo/retrieve.go')
-rw-r--r-- | vendor/github.com/mitchellh/packer/vendor/github.com/vmware/govmomi/vim25/mo/retrieve.go | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/vendor/github.com/mitchellh/packer/vendor/github.com/vmware/govmomi/vim25/mo/retrieve.go b/vendor/github.com/mitchellh/packer/vendor/github.com/vmware/govmomi/vim25/mo/retrieve.go new file mode 100644 index 00000000..e7ffc32c --- /dev/null +++ b/vendor/github.com/mitchellh/packer/vendor/github.com/vmware/govmomi/vim25/mo/retrieve.go @@ -0,0 +1,174 @@ +/* +Copyright (c) 2014-2015 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 mo + +import ( + "context" + "reflect" + + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/soap" + "github.com/vmware/govmomi/vim25/types" +) + +func ignoreMissingProperty(ref types.ManagedObjectReference, p types.MissingProperty) bool { + switch ref.Type { + case "VirtualMachine": + switch p.Path { + case "environmentBrowser": + // See https://github.com/vmware/govmomi/pull/242 + return true + case "alarmActionsEnabled": + // Seen with vApp child VM + return true + } + } + + return false +} + +// ObjectContentToType loads an ObjectContent value into the value it +// represents. If the ObjectContent value has a non-empty 'MissingSet' field, +// it returns the first fault it finds there as error. If the 'MissingSet' +// field is empty, it returns a pointer to a reflect.Value. It handles contain +// nested properties, such as 'guest.ipAddress' or 'config.hardware'. +func ObjectContentToType(o types.ObjectContent) (interface{}, error) { + // Expect no properties in the missing set + for _, p := range o.MissingSet { + if ignoreMissingProperty(o.Obj, p) { + continue + } + + return nil, soap.WrapVimFault(p.Fault.Fault) + } + + ti := typeInfoForType(o.Obj.Type) + v, err := ti.LoadFromObjectContent(o) + if err != nil { + return nil, err + } + + return v.Elem().Interface(), nil +} + +// LoadRetrievePropertiesResponse converts the response of a call to +// RetrieveProperties to one or more managed objects. +func LoadRetrievePropertiesResponse(res *types.RetrievePropertiesResponse, dst interface{}) error { + rt := reflect.TypeOf(dst) + if rt == nil || rt.Kind() != reflect.Ptr { + panic("need pointer") + } + + rv := reflect.ValueOf(dst).Elem() + if !rv.CanSet() { + panic("cannot set dst") + } + + isSlice := false + switch rt.Elem().Kind() { + case reflect.Struct: + case reflect.Slice: + isSlice = true + default: + panic("unexpected type") + } + + if isSlice { + for _, p := range res.Returnval { + v, err := ObjectContentToType(p) + if err != nil { + return err + } + + vt := reflect.TypeOf(v) + + if !rv.Type().AssignableTo(vt) { + // For example: dst is []ManagedEntity, res is []HostSystem + if field, ok := vt.FieldByName(rt.Elem().Elem().Name()); ok && field.Anonymous { + rv.Set(reflect.Append(rv, reflect.ValueOf(v).FieldByIndex(field.Index))) + continue + } + } + + rv.Set(reflect.Append(rv, reflect.ValueOf(v))) + } + } else { + switch len(res.Returnval) { + case 0: + case 1: + v, err := ObjectContentToType(res.Returnval[0]) + if err != nil { + return err + } + + vt := reflect.TypeOf(v) + + if !rv.Type().AssignableTo(vt) { + // For example: dst is ComputeResource, res is ClusterComputeResource + if field, ok := vt.FieldByName(rt.Elem().Name()); ok && field.Anonymous { + rv.Set(reflect.ValueOf(v).FieldByIndex(field.Index)) + return nil + } + } + + rv.Set(reflect.ValueOf(v)) + default: + // If dst is not a slice, expect to receive 0 or 1 results + panic("more than 1 result") + } + } + + return nil +} + +// RetrievePropertiesForRequest calls the RetrieveProperties method with the +// specified request and decodes the response struct into the value pointed to +// by dst. +func RetrievePropertiesForRequest(ctx context.Context, r soap.RoundTripper, req types.RetrieveProperties, dst interface{}) error { + res, err := methods.RetrieveProperties(ctx, r, &req) + if err != nil { + return err + } + + return LoadRetrievePropertiesResponse(res, dst) +} + +// RetrieveProperties retrieves the properties of the managed object specified +// as obj and decodes the response struct into the value pointed to by dst. +func RetrieveProperties(ctx context.Context, r soap.RoundTripper, pc, obj types.ManagedObjectReference, dst interface{}) error { + req := types.RetrieveProperties{ + This: pc, + SpecSet: []types.PropertyFilterSpec{ + { + ObjectSet: []types.ObjectSpec{ + { + Obj: obj, + Skip: types.NewBool(false), + }, + }, + PropSet: []types.PropertySpec{ + { + All: types.NewBool(true), + Type: obj.Type, + }, + }, + }, + }, + } + + return RetrievePropertiesForRequest(ctx, r, req, dst) +} |