// © Broadcom. All Rights Reserved. // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. // SPDX-License-Identifier: Apache-2.0 package object import ( "context" "fmt" "github.com/vmware/govmomi/property" "github.com/vmware/govmomi/task" "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/progress" "github.com/vmware/govmomi/vim25/types" ) // Task is a convenience wrapper around task.Task that keeps a reference to // the client that was used to create it. This allows users to call the Wait() // function with only a context parameter, instead of a context parameter, a // soap.RoundTripper, and reference to the root property collector. type Task struct { Common } func NewTask(c *vim25.Client, ref types.ManagedObjectReference) *Task { t := Task{ Common: NewCommon(c, ref), } return &t } // Wait waits for a task to complete. // NOTE: This method create a thread-safe PropertyCollector instance per-call, so it is thread safe. // The downside of this approach is the additional resource usage on the vCenter side for each call. func (t *Task) Wait(ctx context.Context) error { _, err := t.WaitForResult(ctx, nil) return err } // WaitForResult wait for a task to complete. // NOTE: This method create a thread-safe PropertyCollector instance per-call, so it is thread safe. // The downside of this approach is the additional resource usage on the vCenter side for each call. func (t *Task) WaitForResult(ctx context.Context, s ...progress.Sinker) (taskInfo *types.TaskInfo, result error) { var pr progress.Sinker if len(s) == 1 { pr = s[0] } p, err := property.DefaultCollector(t.c).Create(ctx) if err != nil { return nil, err } // Attempt to destroy the collector using the background context, as the // specified context may have timed out or have been canceled. defer func() { if err := p.Destroy(context.Background()); err != nil { if result == nil { result = err } else { result = fmt.Errorf( "destroy property collector failed with %s after failing to wait for updates: %w", err, result) } } }() return task.WaitEx(ctx, t.Reference(), p, pr) } // WaitEx waits for a task to complete. // NOTE: This method use the same PropertyCollector instance in each call, thus reducing resource usage on the vCenter side. // The downside of this approach is that this method is not thread safe. func (t *Task) WaitEx(ctx context.Context) error { _, err := t.WaitForResultEx(ctx, nil) return err } // WaitForResultEx waits for a task to complete. // NOTE: This method use the same PropertyCollector instance in each call, thus reducing resource usage on the vCenter side. // The downside of this approach is that this method is not thread safe. func (t *Task) WaitForResultEx(ctx context.Context, s ...progress.Sinker) (*types.TaskInfo, error) { var pr progress.Sinker if len(s) == 1 { pr = s[0] } p := property.DefaultCollector(t.c) return task.WaitEx(ctx, t.Reference(), p, pr) } func (t *Task) Cancel(ctx context.Context) error { _, err := methods.CancelTask(ctx, t.Client(), &types.CancelTask{ This: t.Reference(), }) return err } // SetState sets task state and optionally sets results or fault, as appropriate for state. func (t *Task) SetState(ctx context.Context, state types.TaskInfoState, result types.AnyType, fault *types.LocalizedMethodFault) error { req := types.SetTaskState{ This: t.Reference(), State: state, Result: result, Fault: fault, } _, err := methods.SetTaskState(ctx, t.Common.Client(), &req) return err } // SetDescription updates task description to describe the current phase of the task. func (t *Task) SetDescription(ctx context.Context, description types.LocalizableMessage) error { req := types.SetTaskDescription{ This: t.Reference(), Description: description, } _, err := methods.SetTaskDescription(ctx, t.Common.Client(), &req) return err } // UpdateProgress Sets percentage done for this task and recalculates overall percentage done. // If a percentDone value of less than zero or greater than 100 is specified, // a value of zero or 100 respectively is used. func (t *Task) UpdateProgress(ctx context.Context, percentDone int) error { req := types.UpdateProgress{ This: t.Reference(), PercentDone: int32(percentDone), } _, err := methods.UpdateProgress(ctx, t.Common.Client(), &req) return err }