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 }