github.com/vmware/govmomi@v0.51.0/object/task.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 object
     6  
     7  import (
     8  	"context"
     9  	"fmt"
    10  
    11  	"github.com/vmware/govmomi/property"
    12  	"github.com/vmware/govmomi/task"
    13  	"github.com/vmware/govmomi/vim25"
    14  	"github.com/vmware/govmomi/vim25/methods"
    15  	"github.com/vmware/govmomi/vim25/progress"
    16  	"github.com/vmware/govmomi/vim25/types"
    17  )
    18  
    19  // Task is a convenience wrapper around task.Task that keeps a reference to
    20  // the client that was used to create it. This allows users to call the Wait()
    21  // function with only a context parameter, instead of a context parameter, a
    22  // soap.RoundTripper, and reference to the root property collector.
    23  type Task struct {
    24  	Common
    25  }
    26  
    27  func NewTask(c *vim25.Client, ref types.ManagedObjectReference) *Task {
    28  	t := Task{
    29  		Common: NewCommon(c, ref),
    30  	}
    31  
    32  	return &t
    33  }
    34  
    35  // Wait waits for a task to complete.
    36  // NOTE: This method create a thread-safe PropertyCollector instance per-call, so it is thread safe.
    37  // The downside of this approach is the additional resource usage on the vCenter side for each call.
    38  func (t *Task) Wait(ctx context.Context) error {
    39  	_, err := t.WaitForResult(ctx, nil)
    40  	return err
    41  }
    42  
    43  // WaitForResult wait for a task to complete.
    44  // NOTE: This method create a thread-safe PropertyCollector instance per-call, so it is thread safe.
    45  // The downside of this approach is the additional resource usage on the vCenter side for each call.
    46  func (t *Task) WaitForResult(ctx context.Context, s ...progress.Sinker) (taskInfo *types.TaskInfo, result error) {
    47  	var pr progress.Sinker
    48  	if len(s) == 1 {
    49  		pr = s[0]
    50  	}
    51  	p, err := property.DefaultCollector(t.c).Create(ctx)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	// Attempt to destroy the collector using the background context, as the
    57  	// specified context may have timed out or have been canceled.
    58  	defer func() {
    59  		if err := p.Destroy(context.Background()); err != nil {
    60  			if result == nil {
    61  				result = err
    62  			} else {
    63  				result = fmt.Errorf(
    64  					"destroy property collector failed with %s after failing to wait for updates: %w",
    65  					err,
    66  					result)
    67  			}
    68  		}
    69  	}()
    70  
    71  	return task.WaitEx(ctx, t.Reference(), p, pr)
    72  }
    73  
    74  // WaitEx waits for a task to complete.
    75  // NOTE: This method use the same PropertyCollector instance in each call, thus reducing resource usage on the vCenter side.
    76  // The downside of this approach is that this method is not thread safe.
    77  func (t *Task) WaitEx(ctx context.Context) error {
    78  	_, err := t.WaitForResultEx(ctx, nil)
    79  	return err
    80  }
    81  
    82  // WaitForResultEx waits for a task to complete.
    83  // NOTE: This method use the same PropertyCollector instance in each call, thus reducing resource usage on the vCenter side.
    84  // The downside of this approach is that this method is not thread safe.
    85  func (t *Task) WaitForResultEx(ctx context.Context, s ...progress.Sinker) (*types.TaskInfo, error) {
    86  	var pr progress.Sinker
    87  	if len(s) == 1 {
    88  		pr = s[0]
    89  	}
    90  	p := property.DefaultCollector(t.c)
    91  	return task.WaitEx(ctx, t.Reference(), p, pr)
    92  }
    93  
    94  func (t *Task) Cancel(ctx context.Context) error {
    95  	_, err := methods.CancelTask(ctx, t.Client(), &types.CancelTask{
    96  		This: t.Reference(),
    97  	})
    98  
    99  	return err
   100  }
   101  
   102  // SetState sets task state and optionally sets results or fault, as appropriate for state.
   103  func (t *Task) SetState(ctx context.Context, state types.TaskInfoState, result types.AnyType, fault *types.LocalizedMethodFault) error {
   104  	req := types.SetTaskState{
   105  		This:   t.Reference(),
   106  		State:  state,
   107  		Result: result,
   108  		Fault:  fault,
   109  	}
   110  	_, err := methods.SetTaskState(ctx, t.Common.Client(), &req)
   111  	return err
   112  }
   113  
   114  // SetDescription updates task description to describe the current phase of the task.
   115  func (t *Task) SetDescription(ctx context.Context, description types.LocalizableMessage) error {
   116  	req := types.SetTaskDescription{
   117  		This:        t.Reference(),
   118  		Description: description,
   119  	}
   120  	_, err := methods.SetTaskDescription(ctx, t.Common.Client(), &req)
   121  	return err
   122  }
   123  
   124  // UpdateProgress Sets percentage done for this task and recalculates overall percentage done.
   125  // If a percentDone value of less than zero or greater than 100 is specified,
   126  // a value of zero or 100 respectively is used.
   127  func (t *Task) UpdateProgress(ctx context.Context, percentDone int) error {
   128  	req := types.UpdateProgress{
   129  		This:        t.Reference(),
   130  		PercentDone: int32(percentDone),
   131  	}
   132  	_, err := methods.UpdateProgress(ctx, t.Common.Client(), &req)
   133  	return err
   134  }