Skip to content

Commit

Permalink
vcsim: handle traversal spec object updates
Browse files Browse the repository at this point in the history
See PropertyFilter.UpdateObject comment for details
  • Loading branch information
dougm committed Oct 4, 2024
1 parent fc91180 commit 2c49326
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 9 deletions.
12 changes: 6 additions & 6 deletions simulator/property_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ func (rr *retrieveResult) selectSet(ctx *Context, obj reflect.Value, s []types.B
return nil
}

func (pc *PropertyCollector) collect(ctx *Context, r *types.RetrievePropertiesEx) (*types.RetrieveResult, types.BaseMethodFault) {
func collect(ctx *Context, r *types.RetrievePropertiesEx) (*types.RetrieveResult, types.BaseMethodFault) {
var refs []types.ManagedObjectReference

rr := &retrieveResult{
Expand Down Expand Up @@ -574,6 +574,8 @@ func (pc *PropertyCollector) CreateFilter(ctx *Context, c *types.CreateFilter) s
Returnval: filter.Self,
}

ctx.Map.AddHandler(filter)

return body
}

Expand Down Expand Up @@ -666,7 +668,7 @@ func (pc *PropertyCollector) ContinueRetrievePropertiesEx(ctx *Context, r *types
func (pc *PropertyCollector) RetrievePropertiesEx(ctx *Context, r *types.RetrievePropertiesEx) soap.HasFault {
body := &methods.RetrievePropertiesExBody{}

res, fault := pc.collect(ctx, r)
res, fault := collect(ctx, r)

if fault != nil {
switch fault.(type) {
Expand Down Expand Up @@ -782,10 +784,7 @@ func (pc *PropertyCollector) apply(ctx *Context, update *types.UpdateSet) types.
for _, ref := range pc.Filter {
filter := ctx.Session.Get(ref).(*PropertyFilter)

r := &types.RetrievePropertiesEx{}
r.SpecSet = append(r.SpecSet, filter.Spec)

res, fault := pc.collect(ctx, r)
res, fault := filter.collect(ctx)
if fault != nil {
return fault
}
Expand Down Expand Up @@ -951,6 +950,7 @@ func (pc *PropertyCollector) WaitForUpdatesEx(ctx *Context, r *types.WaitForUpda

for _, f := range pc.Filter {
filter := ctx.Session.Get(f).(*PropertyFilter)
filter.update(ctx)
fu := types.PropertyFilterUpdate{Filter: f}

for _, update := range updates {
Expand Down
4 changes: 1 addition & 3 deletions simulator/property_collector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -822,8 +822,6 @@ func TestPropertyCollectorInvalidSpecName(t *testing.T) {
obj := Map.Put(new(Folder))
folderPutChild(SpoofContext(), &obj.(*Folder).Folder, new(Folder))

pc := &PropertyCollector{}

req := types.RetrievePropertiesEx{
SpecSet: []types.PropertyFilterSpec{
{
Expand Down Expand Up @@ -853,7 +851,7 @@ func TestPropertyCollectorInvalidSpecName(t *testing.T) {
},
}

_, err := pc.collect(SpoofContext(), &req)
_, err := collect(SpoofContext(), &req)
if err == nil {
t.Fatal("expected error")
}
Expand Down
36 changes: 36 additions & 0 deletions simulator/property_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,29 @@ type PropertyFilter struct {

pc *PropertyCollector
refs map[types.ManagedObjectReference]struct{}
sync bool
}

func (f *PropertyFilter) UpdateObject(o mo.Reference, changes []types.PropertyChange) {
// A PropertyFilter's traversal spec is "applied" on the initial call to WaitForUpdates,
// with matching objects tracked in the `refs` field.
// New and deleted objects matching the filter are accounted for within PropertyCollector.
// But when an object used for the traversal itself is updated (e.g. ListView),
// we need to update the tracked `refs` on the next call to WaitForUpdates.
ref := o.Reference()

for _, set := range f.Spec.ObjectSet {
if set.Obj == ref && len(set.SelectSet) != 0 {
f.sync = true
break
}
}
}

func (_ *PropertyFilter) PutObject(_ mo.Reference) {}

func (_ *PropertyFilter) RemoveObject(_ *Context, _ types.ManagedObjectReference) {}

func (f *PropertyFilter) DestroyPropertyFilter(ctx *Context, c *types.DestroyPropertyFilter) soap.HasFault {
body := &methods.DestroyPropertyFilterBody{}

Expand All @@ -45,6 +66,21 @@ func (f *PropertyFilter) DestroyPropertyFilter(ctx *Context, c *types.DestroyPro
return body
}

func (f *PropertyFilter) collect(ctx *Context) (*types.RetrieveResult, types.BaseMethodFault) {
req := &types.RetrievePropertiesEx{
SpecSet: []types.PropertyFilterSpec{f.Spec},
}
return collect(ctx, req)
}

func (f *PropertyFilter) update(ctx *Context) {
if f.sync {
f.sync = false
clear(f.refs)
_, _ = f.collect(ctx)
}
}

// matches returns true if the change matches one of the filter Spec.PropSet
func (f *PropertyFilter) matches(ctx *Context, ref types.ManagedObjectReference, change *types.PropertyChange) bool {
var kind reflect.Type
Expand Down

0 comments on commit 2c49326

Please sign in to comment.