Blame vendor/github.com/vmware/govmomi/view/task_view.go

Packit Service 4d2de5
/*
Packit Service 4d2de5
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Packit Service 4d2de5
Packit Service 4d2de5
Licensed under the Apache License, Version 2.0 (the "License");
Packit Service 4d2de5
you may not use this file except in compliance with the License.
Packit Service 4d2de5
You may obtain a copy of the License at
Packit Service 4d2de5
Packit Service 4d2de5
    http://www.apache.org/licenses/LICENSE-2.0
Packit Service 4d2de5
Packit Service 4d2de5
Unless required by applicable law or agreed to in writing, software
Packit Service 4d2de5
distributed under the License is distributed on an "AS IS" BASIS,
Packit Service 4d2de5
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit Service 4d2de5
See the License for the specific language governing permissions and
Packit Service 4d2de5
limitations under the License.
Packit Service 4d2de5
*/
Packit Service 4d2de5
Packit Service 4d2de5
package view
Packit Service 4d2de5
Packit Service 4d2de5
import (
Packit Service 4d2de5
	"context"
Packit Service 4d2de5
Packit Service 4d2de5
	"github.com/vmware/govmomi/property"
Packit Service 4d2de5
	"github.com/vmware/govmomi/vim25/types"
Packit Service 4d2de5
)
Packit Service 4d2de5
Packit Service 4d2de5
// TaskView extends ListView such that it can follow a ManagedEntity's recentTask updates.
Packit Service 4d2de5
type TaskView struct {
Packit Service 4d2de5
	*ListView
Packit Service 4d2de5
Packit Service 4d2de5
	Follow bool
Packit Service 4d2de5
Packit Service 4d2de5
	Watch *types.ManagedObjectReference
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
// CreateTaskView creates a new ListView that optionally watches for a ManagedEntity's recentTask updates.
Packit Service 4d2de5
func (m Manager) CreateTaskView(ctx context.Context, watch *types.ManagedObjectReference) (*TaskView, error) {
Packit Service 4d2de5
	l, err := m.CreateListView(ctx, nil)
Packit Service 4d2de5
	if err != nil {
Packit Service 4d2de5
		return nil, err
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	tv := &TaskView{
Packit Service 4d2de5
		ListView: l,
Packit Service 4d2de5
		Watch:    watch,
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	return tv, nil
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
// Collect calls function f for each Task update.
Packit Service 4d2de5
func (v TaskView) Collect(ctx context.Context, f func([]types.TaskInfo)) error {
Packit Service 4d2de5
	// Using TaskHistoryCollector would be less clunky, but it isn't supported on ESX at all.
Packit Service 4d2de5
	ref := v.Reference()
Packit Service 4d2de5
	filter := new(property.WaitFilter).Add(ref, "Task", []string{"info"}, v.TraversalSpec())
Packit Service 4d2de5
Packit Service 4d2de5
	if v.Watch != nil {
Packit Service 4d2de5
		filter.Add(*v.Watch, v.Watch.Type, []string{"recentTask"})
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	pc := property.DefaultCollector(v.Client())
Packit Service 4d2de5
Packit Service 4d2de5
	completed := make(map[string]bool)
Packit Service 4d2de5
Packit Service 4d2de5
	return property.WaitForUpdates(ctx, pc, filter, func(updates []types.ObjectUpdate) bool {
Packit Service 4d2de5
		var infos []types.TaskInfo
Packit Service 4d2de5
		var prune []types.ManagedObjectReference
Packit Service 4d2de5
		var tasks []types.ManagedObjectReference
Packit Service 4d2de5
		var reset func()
Packit Service 4d2de5
Packit Service 4d2de5
		for _, update := range updates {
Packit Service 4d2de5
			for _, change := range update.ChangeSet {
Packit Service 4d2de5
				if change.Name == "recentTask" {
Packit Service 4d2de5
					tasks = change.Val.(types.ArrayOfManagedObjectReference).ManagedObjectReference
Packit Service 4d2de5
					if len(tasks) != 0 {
Packit Service 4d2de5
						reset = func() {
Packit Service 4d2de5
							_ = v.Reset(ctx, tasks)
Packit Service 4d2de5
Packit Service 4d2de5
							// Remember any tasks we've reported as complete already,
Packit Service 4d2de5
							// to avoid reporting multiple times when Reset is triggered.
Packit Service 4d2de5
							rtasks := make(map[string]bool)
Packit Service 4d2de5
							for i := range tasks {
Packit Service 4d2de5
								if _, ok := completed[tasks[i].Value]; ok {
Packit Service 4d2de5
									rtasks[tasks[i].Value] = true
Packit Service 4d2de5
								}
Packit Service 4d2de5
							}
Packit Service 4d2de5
							completed = rtasks
Packit Service 4d2de5
						}
Packit Service 4d2de5
					}
Packit Service 4d2de5
Packit Service 4d2de5
					continue
Packit Service 4d2de5
				}
Packit Service 4d2de5
Packit Service 4d2de5
				info, ok := change.Val.(types.TaskInfo)
Packit Service 4d2de5
				if !ok {
Packit Service 4d2de5
					continue
Packit Service 4d2de5
				}
Packit Service 4d2de5
Packit Service 4d2de5
				if !completed[info.Task.Value] {
Packit Service 4d2de5
					infos = append(infos, info)
Packit Service 4d2de5
				}
Packit Service 4d2de5
Packit Service 4d2de5
				if v.Follow && info.CompleteTime != nil {
Packit Service 4d2de5
					prune = append(prune, info.Task)
Packit Service 4d2de5
					completed[info.Task.Value] = true
Packit Service 4d2de5
				}
Packit Service 4d2de5
			}
Packit Service 4d2de5
		}
Packit Service 4d2de5
Packit Service 4d2de5
		if len(infos) != 0 {
Packit Service 4d2de5
			f(infos)
Packit Service 4d2de5
		}
Packit Service 4d2de5
Packit Service 4d2de5
		if reset != nil {
Packit Service 4d2de5
			reset()
Packit Service 4d2de5
		} else if len(prune) != 0 {
Packit Service 4d2de5
			_ = v.Remove(ctx, prune)
Packit Service 4d2de5
		}
Packit Service 4d2de5
Packit Service 4d2de5
		if len(tasks) != 0 && len(infos) == 0 {
Packit Service 4d2de5
			return false
Packit Service 4d2de5
		}
Packit Service 4d2de5
Packit Service 4d2de5
		return !v.Follow
Packit Service 4d2de5
	})
Packit Service 4d2de5
}