github.com/vmware/govmomi@v0.51.0/property/wait.go (about) 1 // © Broadcom. All Rights Reserved. 2 // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 3 // SPDX-License-Identifier: Apache-2.0 4 5 package property 6 7 import ( 8 "context" 9 "fmt" 10 11 "github.com/vmware/govmomi/vim25/types" 12 ) 13 14 // WaitOptions defines options for a property collector's WaitForUpdatesEx 15 // method. 16 type WaitOptions struct { 17 Options *types.WaitOptions 18 PropagateMissing bool 19 Truncated bool 20 } 21 22 // WaitFilter provides helpers to construct a types.CreateFilter for use with property.Wait 23 type WaitFilter struct { 24 types.CreateFilter 25 WaitOptions 26 } 27 28 // Add a new ObjectSpec and PropertySpec to the WaitFilter 29 func (f *WaitFilter) Add(obj types.ManagedObjectReference, kind string, ps []string, set ...types.BaseSelectionSpec) *WaitFilter { 30 spec := types.ObjectSpec{ 31 Obj: obj, 32 SelectSet: set, 33 } 34 35 pset := types.PropertySpec{ 36 Type: kind, 37 PathSet: ps, 38 } 39 40 if len(ps) == 0 { 41 pset.All = types.NewBool(true) 42 } 43 44 f.Spec.ObjectSet = append(f.Spec.ObjectSet, spec) 45 46 f.Spec.PropSet = append(f.Spec.PropSet, pset) 47 48 return f 49 } 50 51 // Wait creates a new WaitFilter and calls the specified function for each ObjectUpdate via WaitForUpdates 52 func Wait(ctx context.Context, c *Collector, obj types.ManagedObjectReference, ps []string, f func([]types.PropertyChange) bool) error { 53 filter := new(WaitFilter).Add(obj, obj.Type, ps) 54 55 return WaitForUpdates(ctx, c, filter, func(updates []types.ObjectUpdate) bool { 56 for _, update := range updates { 57 if f(update.ChangeSet) { 58 return true 59 } 60 } 61 62 return false 63 }) 64 } 65 66 // WaitForUpdates waits for any of the specified properties of the specified 67 // managed object to change. It calls the specified function for every update it 68 // receives. If this function returns false, it continues waiting for 69 // subsequent updates. If this function returns true, it stops waiting and 70 // returns. 71 // 72 // To only receive updates for the specified managed object, the function 73 // creates a new property collector and calls CreateFilter. A new property 74 // collector is required because filters can only be added, not removed. 75 // 76 // If the Context is canceled, a call to CancelWaitForUpdates() is made and its 77 // error value is returned. The newly created collector is destroyed before this 78 // function returns (both in case of success or error). 79 // 80 // By default, ObjectUpdate.MissingSet faults are not propagated to the returned 81 // error, set WaitFilter.PropagateMissing=true to enable MissingSet fault 82 // propagation. 83 func WaitForUpdates( 84 ctx context.Context, 85 c *Collector, 86 filter *WaitFilter, 87 onUpdatesFn func([]types.ObjectUpdate) bool) (result error) { 88 89 pc, err := c.Create(ctx) 90 if err != nil { 91 return err 92 } 93 94 // Attempt to destroy the collector using the background context, as the 95 // specified context may have timed out or have been canceled. 96 defer func() { 97 if err := pc.Destroy(context.Background()); err != nil { 98 if result == nil { 99 result = err 100 } else { 101 result = fmt.Errorf( 102 "destroy property collector failed with %s after failing to wait for updates: %w", 103 err, 104 result) 105 } 106 } 107 }() 108 109 // Create a property filter for the property collector. 110 if _, err := pc.CreateFilter(ctx, filter.CreateFilter); err != nil { 111 return err 112 } 113 114 return pc.WaitForUpdatesEx(ctx, &filter.WaitOptions, onUpdatesFn) 115 } 116 117 // WaitForUpdates waits for any of the specified properties of the specified 118 // managed object to change. It calls the specified function for every update it 119 // receives. If this function returns false, it continues waiting for 120 // subsequent updates. If this function returns true, it stops waiting and 121 // returns. 122 // 123 // If the Context is canceled, a call to CancelWaitForUpdates() is made and its 124 // error value is returned. 125 // 126 // By default, ObjectUpdate.MissingSet faults are not propagated to the returned 127 // error, set WaitFilter.PropagateMissing=true to enable MissingSet fault 128 // propagation. 129 func WaitForUpdatesEx( 130 ctx context.Context, 131 pc *Collector, 132 filter *WaitFilter, 133 onUpdatesFn func([]types.ObjectUpdate) bool) (result error) { 134 135 // Create a property filter for the property collector. 136 pf, err := pc.CreateFilter(ctx, filter.CreateFilter) 137 if err != nil { 138 return err 139 } 140 141 // Destroy the filter using the background context, as the specified context 142 // may have timed out or have been canceled. 143 defer func() { 144 if err := pf.Destroy(context.Background()); err != nil { 145 if result == nil { 146 result = err 147 } else { 148 result = fmt.Errorf( 149 "destroy property filter failed with %s after failing to wait for updates: %w", 150 err, 151 result) 152 } 153 } 154 155 }() 156 157 return pc.WaitForUpdatesEx(ctx, &filter.WaitOptions, onUpdatesFn) 158 }