github.com/vmware/go-vcloud-director/v2@v2.24.0/govcd/ejecttask.go (about)

     1  /*
     2   * Copyright 2019 VMware, Inc.  All rights reserved.  Licensed under the Apache v2 License.
     3   */
     4  
     5  package govcd
     6  
     7  import (
     8  	"fmt"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/vmware/go-vcloud-director/v2/types/v56"
    13  )
    14  
    15  type EjectTask struct {
    16  	*Task
    17  	vm *VM
    18  }
    19  
    20  var timeBetweenRefresh = 3 * time.Second
    21  
    22  // Question Message from vCD API
    23  const questionMessage = "Disconnect anyway and override the lock?"
    24  
    25  // Creates wrapped Task which is dedicated for eject media functionality and
    26  // provides additional functionality to answer VM questions
    27  func NewEjectTask(task *Task, vm *VM) *EjectTask {
    28  	return &EjectTask{
    29  		task,
    30  		vm,
    31  	}
    32  }
    33  
    34  // Checks the status of the task every 3 seconds and returns when the
    35  // eject task is either completed or failed
    36  func (ejectTask *EjectTask) WaitTaskCompletion(isAnswerYes bool) error {
    37  	return ejectTask.WaitInspectTaskCompletion(isAnswerYes, timeBetweenRefresh)
    38  }
    39  
    40  // function which handles answers for ejecting
    41  func (ejectTask *EjectTask) WaitInspectTaskCompletion(isAnswerYes bool, delay time.Duration) error {
    42  
    43  	if ejectTask.Task == nil {
    44  		return fmt.Errorf("cannot refresh, Object is empty")
    45  	}
    46  
    47  	for {
    48  		err := ejectTask.Refresh()
    49  		if err != nil {
    50  			return fmt.Errorf("error retrieving task: %s", err)
    51  		}
    52  
    53  		// If task is not in a waiting status we're done, check if there's an error and return it.
    54  		if ejectTask.Task.Task.Status != "queued" && ejectTask.Task.Task.Status != "preRunning" && ejectTask.Task.Task.Status != "running" {
    55  			if ejectTask.Task.Task.Status == "error" {
    56  				return fmt.Errorf("task did not complete succesfully: %s", ejectTask.Task.Task.Error.Message)
    57  			}
    58  			return nil
    59  		}
    60  
    61  		question, err := ejectTask.vm.GetQuestion()
    62  		if err != nil {
    63  			return fmt.Errorf("task did not complete succesfully: %s, quering question for VM failed: %s", ejectTask.Task.Task.Description, err.Error())
    64  		}
    65  
    66  		if question.QuestionId != "" && strings.Contains(question.Question, questionMessage) {
    67  			var choiceToUse *types.VmQuestionAnswerChoiceType
    68  			for _, choice := range question.Choices {
    69  				if isAnswerYes {
    70  					if strings.Contains(choice.Text, "yes") {
    71  						choiceToUse = choice
    72  					}
    73  				} else {
    74  					if strings.Contains(choice.Text, "no") {
    75  						choiceToUse = choice
    76  					}
    77  				}
    78  			}
    79  
    80  			if choiceToUse != nil {
    81  				err = ejectTask.vm.AnswerQuestion(question.QuestionId, choiceToUse.Id)
    82  				if err != nil {
    83  					return fmt.Errorf("task did not complete succesfully: %s, answering question for eject in VM failed: %s", ejectTask.Task.Task.Description, err.Error())
    84  				}
    85  			}
    86  
    87  		}
    88  
    89  		// Sleep for a given period and try again.
    90  		time.Sleep(delay)
    91  	}
    92  }