diff options
Diffstat (limited to 'vendor/github.com/mitchellh/packer/vendor/github.com/vmware/govmomi/task/wait.go')
-rw-r--r-- | vendor/github.com/mitchellh/packer/vendor/github.com/vmware/govmomi/task/wait.go | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/vendor/github.com/mitchellh/packer/vendor/github.com/vmware/govmomi/task/wait.go b/vendor/github.com/mitchellh/packer/vendor/github.com/vmware/govmomi/task/wait.go new file mode 100644 index 00000000..19fee538 --- /dev/null +++ b/vendor/github.com/mitchellh/packer/vendor/github.com/vmware/govmomi/task/wait.go @@ -0,0 +1,132 @@ +/* +Copyright (c) 2015 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package task + +import ( + "context" + + "github.com/vmware/govmomi/property" + "github.com/vmware/govmomi/vim25/progress" + "github.com/vmware/govmomi/vim25/types" +) + +type taskProgress struct { + info *types.TaskInfo +} + +func (t taskProgress) Percentage() float32 { + return float32(t.info.Progress) +} + +func (t taskProgress) Detail() string { + return "" +} + +func (t taskProgress) Error() error { + if t.info.Error != nil { + return Error{t.info.Error} + } + + return nil +} + +type taskCallback struct { + ch chan<- progress.Report + info *types.TaskInfo + err error +} + +func (t *taskCallback) fn(pc []types.PropertyChange) bool { + for _, c := range pc { + if c.Name != "info" { + continue + } + + if c.Op != types.PropertyChangeOpAssign { + continue + } + + if c.Val == nil { + continue + } + + ti := c.Val.(types.TaskInfo) + t.info = &ti + } + + // t.info could be nil if pc can't satify the rules above + if t.info == nil { + return false + } + + pr := taskProgress{t.info} + + // Store copy of error, so Wait() can return it as well. + t.err = pr.Error() + + switch t.info.State { + case types.TaskInfoStateQueued, types.TaskInfoStateRunning: + if t.ch != nil { + // Don't care if this is dropped + select { + case t.ch <- pr: + default: + } + } + return false + case types.TaskInfoStateSuccess, types.TaskInfoStateError: + if t.ch != nil { + // Last one must always be delivered + t.ch <- pr + } + return true + default: + panic("unknown state: " + t.info.State) + } +} + +// Wait waits for a task to finish with either success or failure. It does so +// by waiting for the "info" property of task managed object to change. The +// function returns when it finds the task in the "success" or "error" state. +// In the former case, the return value is nil. In the latter case the return +// value is an instance of this package's Error struct. +// +// Any error returned while waiting for property changes causes the function to +// return immediately and propagate the error. +// +// If the progress.Sinker argument is specified, any progress updates for the +// task are sent here. The completion percentage is passed through directly. +// The detail for the progress update is set to an empty string. If the task +// finishes in the error state, the error instance is passed through as well. +// Note that this error is the same error that is returned by this function. +// +func Wait(ctx context.Context, ref types.ManagedObjectReference, pc *property.Collector, s progress.Sinker) (*types.TaskInfo, error) { + cb := &taskCallback{} + + // Include progress sink if specified + if s != nil { + cb.ch = s.Sink() + defer close(cb.ch) + } + + err := property.Wait(ctx, pc, ref, []string{"info"}, cb.fn) + if err != nil { + return nil, err + } + + return cb.info, cb.err +} |