Skip to content

Commit

Permalink
Merge pull request #39 from JocelynBerrendonner/master
Browse files Browse the repository at this point in the history
Fixing an issue where CIM_ConcreteJob would timeout instead of returning an error on failure
  • Loading branch information
JocelynBerrendonner authored Sep 11, 2020
2 parents 0c22d00 + 92f7fda commit 528f64e
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 7 deletions.
1 change: 1 addition & 0 deletions pkg/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package errors

import (
"errors"

perrors "github.com/pkg/errors"
)

Expand Down
30 changes: 27 additions & 3 deletions pkg/virtualization/core/job/virtualsystemjob.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,12 @@ func (vmjob *VirtualSystemJob) WaitForPercentComplete(percentComplete, timeoutSe
time.Sleep(100 * time.Millisecond)
// If we have waited enough time, break
if time.Since(start) > (time.Duration(timeoutSeconds) * time.Second) {
break
state, err2 := vmjob.getPropertyJobStateFixed()
if err2 != nil {
state = 0
}
exception := vmjob.GetException()
return errors.Wrapf(errors.Timedout, "WaitForPercentComplete timeout. Current state: [%v], Exception: [%v]", state, exception)
}
}

Expand Down Expand Up @@ -104,12 +109,31 @@ func (vmjob *VirtualSystemJob) PercentComplete() (uint16, error) {
return uint16(retValue.(int32)), nil
}

// GetJobState gets the value of JobState for the instance
// TODO: this is a fixed version of the CIM_ConcreteJob GetPropertyJobState() call.
// We forked the code to allow for a temporary fix until we re-generate the auto-generated CIM_ConcreteJob with the proper fixes.
// Remove the getPropertyJobStateFixed call once the base code is working.
func (vmjob *VirtualSystemJob) getPropertyJobStateFixed() (value v2.ConcreteJob_JobState, err error) {
retValue, err := vmjob.GetProperty("JobState")
if err != nil {
return
}

valueint, ok := retValue.(int32)
if !ok {
panic(fmt.Sprintf("JobState interface was type-casted to the wrong type. Correct type is: %T", retValue))
}
value = v2.ConcreteJob_JobState(valueint)

return
}

func (vmjob *VirtualSystemJob) IsComplete() bool {
err := vmjob.Refresh()
if err != nil {

}
state, err := vmjob.GetPropertyJobState()
state, err := vmjob.getPropertyJobStateFixed()
if err != nil {
return false
}
Expand Down Expand Up @@ -138,7 +162,7 @@ func (vmjob *VirtualSystemJob) IsComplete() bool {

func (vmjob *VirtualSystemJob) GetException() error {
vmjob.Refresh()
state, err := vmjob.GetPropertyJobState()
state, err := vmjob.getPropertyJobStateFixed()
if err != nil {
return err
}
Expand Down
53 changes: 51 additions & 2 deletions pkg/virtualization/core/virtualsystem/virtualmachine.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,43 @@ func (vm *VirtualMachine) State() (state VirtualMachineState, err error) {
return VirtualMachineState(intstate), nil
}

func (vm *VirtualMachine) StatusDescriptions() ([]string, error) {
err := vm.Refresh()
if err != nil {
return nil, err
}

retValue, err := vm.GetProperty("StatusDescriptions")
if err != nil {
return nil, err
}

var statuses []string
for _, status := range retValue.([]interface{}) {
statuses = append(statuses, status.(string))
}

return statuses, nil
}

func (vm *VirtualMachine) Status() (string, error) {
err := vm.Refresh()
if err != nil {
return "", err
}

retValue, err := vm.GetProperty("Status")
if err != nil {
return "", err
}
status, ok := retValue.(string)
if !ok {
return "", errors.Wrapf(errors.Failed, "Failed to get status for this VM [%+v]", retValue)
}

return status, nil
}

// Stop Virtual Machine
func (vm *VirtualMachine) Stop(force bool) error {
return vm.ChangeState(Off, v2.ConcreteJob_JobType_Power_Off_Virtual_Machine)
Expand Down Expand Up @@ -162,8 +199,20 @@ func (vm *VirtualMachine) WaitForState(state VirtualMachineState, timeoutSeconds

// If we have waited enough time, break
if time.Since(start) > (time.Duration(timeoutSeconds) * time.Second) {
err = errors.Wrapf(errors.Timedout, "WaitForState timeout")
break
vmState, err2 := vm.State()
if err2 != nil {
vmState = Unknown
}
status, err2 := vm.Status()
if err2 != nil {
status = fmt.Sprintf("Unknown (error retreiving the status [%+v])", err2)
}
statusDescriptions, err2 := vm.StatusDescriptions()
if err2 != nil {
statusDescriptions = []string{fmt.Sprintf("Unknown (error retreiving the status descriptions [%+v])", err2)}
}
err = errors.Wrapf(errors.Timedout, "WaitForState timeout. Current state: [%v], status: [%v], status descriptions: [%v]", vmState, status, statusDescriptions)
return err
}
}

Expand Down
7 changes: 5 additions & 2 deletions pkg/wmiinstance/WmiJob.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ func (job *WmiJob) JobType() (value int32, err error) {
// WaitForPercentComplete waits for the percentComplete or timeout
func (job *WmiJob) WaitForPercentComplete(percentComplete, timeoutSeconds uint16) error {
start := time.Now()

// Run the loop, only if the job is actually running
for !job.IsComplete() {
pComplete, err := job.PercentComplete()
Expand All @@ -90,9 +91,11 @@ func (job *WmiJob) WaitForPercentComplete(percentComplete, timeoutSeconds uint16
break
}
time.Sleep(100 * time.Millisecond)
// If we have waited enough time, break
// If we have waited enough time, return with a timeout error
if time.Since(start) > (time.Duration(timeoutSeconds) * time.Second) {
break
state := job.GetJobState()
exception := job.GetException()
return errors.Wrapf(errors.Timedout, "WaitForPercentComplete timeout. Current state: [%v], Exception: [%v]", state, exception)
}
}

Expand Down

0 comments on commit 528f64e

Please sign in to comment.