errors.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. //go:build windows
  2. package hcsshim
  3. import (
  4. "fmt"
  5. "syscall"
  6. "github.com/Microsoft/hcsshim/internal/hns"
  7. "github.com/Microsoft/hcsshim/internal/hcs"
  8. "github.com/Microsoft/hcsshim/internal/hcserror"
  9. )
  10. var (
  11. // ErrComputeSystemDoesNotExist is an error encountered when the container being operated on no longer exists = hcs.exist
  12. ErrComputeSystemDoesNotExist = hcs.ErrComputeSystemDoesNotExist
  13. // ErrElementNotFound is an error encountered when the object being referenced does not exist
  14. ErrElementNotFound = hcs.ErrElementNotFound
  15. // ErrElementNotFound is an error encountered when the object being referenced does not exist
  16. ErrNotSupported = hcs.ErrNotSupported
  17. // ErrInvalidData is an error encountered when the request being sent to hcs is invalid/unsupported
  18. // decimal -2147024883 / hex 0x8007000d
  19. ErrInvalidData = hcs.ErrInvalidData
  20. // ErrHandleClose is an error encountered when the handle generating the notification being waited on has been closed
  21. ErrHandleClose = hcs.ErrHandleClose
  22. // ErrAlreadyClosed is an error encountered when using a handle that has been closed by the Close method
  23. ErrAlreadyClosed = hcs.ErrAlreadyClosed
  24. // ErrInvalidNotificationType is an error encountered when an invalid notification type is used
  25. ErrInvalidNotificationType = hcs.ErrInvalidNotificationType
  26. // ErrInvalidProcessState is an error encountered when the process is not in a valid state for the requested operation
  27. ErrInvalidProcessState = hcs.ErrInvalidProcessState
  28. // ErrTimeout is an error encountered when waiting on a notification times out
  29. ErrTimeout = hcs.ErrTimeout
  30. // ErrUnexpectedContainerExit is the error encountered when a container exits while waiting for
  31. // a different expected notification
  32. ErrUnexpectedContainerExit = hcs.ErrUnexpectedContainerExit
  33. // ErrUnexpectedProcessAbort is the error encountered when communication with the compute service
  34. // is lost while waiting for a notification
  35. ErrUnexpectedProcessAbort = hcs.ErrUnexpectedProcessAbort
  36. // ErrUnexpectedValue is an error encountered when hcs returns an invalid value
  37. ErrUnexpectedValue = hcs.ErrUnexpectedValue
  38. // ErrOperationDenied is an error when hcs attempts an operation that is explicitly denied
  39. ErrOperationDenied = hcs.ErrOperationDenied
  40. // ErrVmcomputeAlreadyStopped is an error encountered when a shutdown or terminate request is made on a stopped container
  41. ErrVmcomputeAlreadyStopped = hcs.ErrVmcomputeAlreadyStopped
  42. // ErrVmcomputeOperationPending is an error encountered when the operation is being completed asynchronously
  43. ErrVmcomputeOperationPending = hcs.ErrVmcomputeOperationPending
  44. // ErrVmcomputeOperationInvalidState is an error encountered when the compute system is not in a valid state for the requested operation
  45. ErrVmcomputeOperationInvalidState = hcs.ErrVmcomputeOperationInvalidState
  46. // ErrProcNotFound is an error encountered when a procedure look up fails.
  47. ErrProcNotFound = hcs.ErrProcNotFound
  48. // ErrVmcomputeOperationAccessIsDenied is an error which can be encountered when enumerating compute systems in RS1/RS2
  49. // builds when the underlying silo might be in the process of terminating. HCS was fixed in RS3.
  50. ErrVmcomputeOperationAccessIsDenied = hcs.ErrVmcomputeOperationAccessIsDenied
  51. // ErrVmcomputeInvalidJSON is an error encountered when the compute system does not support/understand the messages sent by management
  52. ErrVmcomputeInvalidJSON = hcs.ErrVmcomputeInvalidJSON
  53. // ErrVmcomputeUnknownMessage is an error encountered guest compute system doesn't support the message
  54. ErrVmcomputeUnknownMessage = hcs.ErrVmcomputeUnknownMessage
  55. // ErrNotSupported is an error encountered when hcs doesn't support the request
  56. ErrPlatformNotSupported = hcs.ErrPlatformNotSupported
  57. )
  58. type EndpointNotFoundError = hns.EndpointNotFoundError
  59. type NetworkNotFoundError = hns.NetworkNotFoundError
  60. // ProcessError is an error encountered in HCS during an operation on a Process object
  61. type ProcessError struct {
  62. Process *process
  63. Operation string
  64. Err error
  65. Events []hcs.ErrorEvent
  66. }
  67. // ContainerError is an error encountered in HCS during an operation on a Container object
  68. type ContainerError struct {
  69. Container *container
  70. Operation string
  71. Err error
  72. Events []hcs.ErrorEvent
  73. }
  74. func (e *ContainerError) Error() string {
  75. if e == nil {
  76. return "<nil>"
  77. }
  78. if e.Container == nil {
  79. return "unexpected nil container for error: " + e.Err.Error()
  80. }
  81. s := "container " + e.Container.system.ID()
  82. if e.Operation != "" {
  83. s += " encountered an error during " + e.Operation
  84. }
  85. switch e.Err.(type) {
  86. case nil:
  87. break
  88. case syscall.Errno:
  89. s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, hcserror.Win32FromError(e.Err))
  90. default:
  91. s += fmt.Sprintf(": %s", e.Err.Error())
  92. }
  93. for _, ev := range e.Events {
  94. s += "\n" + ev.String()
  95. }
  96. return s
  97. }
  98. func (e *ProcessError) Error() string {
  99. if e == nil {
  100. return "<nil>"
  101. }
  102. if e.Process == nil {
  103. return "Unexpected nil process for error: " + e.Err.Error()
  104. }
  105. s := fmt.Sprintf("process %d in container %s", e.Process.p.Pid(), e.Process.p.SystemID())
  106. if e.Operation != "" {
  107. s += " encountered an error during " + e.Operation
  108. }
  109. switch e.Err.(type) {
  110. case nil:
  111. break
  112. case syscall.Errno:
  113. s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, hcserror.Win32FromError(e.Err))
  114. default:
  115. s += fmt.Sprintf(": %s", e.Err.Error())
  116. }
  117. for _, ev := range e.Events {
  118. s += "\n" + ev.String()
  119. }
  120. return s
  121. }
  122. // IsNotExist checks if an error is caused by the Container or Process not existing.
  123. // Note: Currently, ErrElementNotFound can mean that a Process has either
  124. // already exited, or does not exist. Both IsAlreadyStopped and IsNotExist
  125. // will currently return true when the error is ErrElementNotFound.
  126. func IsNotExist(err error) bool {
  127. if _, ok := err.(EndpointNotFoundError); ok {
  128. return true
  129. }
  130. if _, ok := err.(NetworkNotFoundError); ok {
  131. return true
  132. }
  133. return hcs.IsNotExist(getInnerError(err))
  134. }
  135. // IsAlreadyClosed checks if an error is caused by the Container or Process having been
  136. // already closed by a call to the Close() method.
  137. func IsAlreadyClosed(err error) bool {
  138. return hcs.IsAlreadyClosed(getInnerError(err))
  139. }
  140. // IsPending returns a boolean indicating whether the error is that
  141. // the requested operation is being completed in the background.
  142. func IsPending(err error) bool {
  143. return hcs.IsPending(getInnerError(err))
  144. }
  145. // IsTimeout returns a boolean indicating whether the error is caused by
  146. // a timeout waiting for the operation to complete.
  147. func IsTimeout(err error) bool {
  148. return hcs.IsTimeout(getInnerError(err))
  149. }
  150. // IsAlreadyStopped returns a boolean indicating whether the error is caused by
  151. // a Container or Process being already stopped.
  152. // Note: Currently, ErrElementNotFound can mean that a Process has either
  153. // already exited, or does not exist. Both IsAlreadyStopped and IsNotExist
  154. // will currently return true when the error is ErrElementNotFound.
  155. func IsAlreadyStopped(err error) bool {
  156. return hcs.IsAlreadyStopped(getInnerError(err))
  157. }
  158. // IsNotSupported returns a boolean indicating whether the error is caused by
  159. // unsupported platform requests
  160. // Note: Currently Unsupported platform requests can be mean either
  161. // ErrVmcomputeInvalidJSON, ErrInvalidData, ErrNotSupported or ErrVmcomputeUnknownMessage
  162. // is thrown from the Platform
  163. func IsNotSupported(err error) bool {
  164. return hcs.IsNotSupported(getInnerError(err))
  165. }
  166. // IsOperationInvalidState returns true when err is caused by
  167. // `ErrVmcomputeOperationInvalidState`.
  168. func IsOperationInvalidState(err error) bool {
  169. return hcs.IsOperationInvalidState(getInnerError(err))
  170. }
  171. // IsAccessIsDenied returns true when err is caused by
  172. // `ErrVmcomputeOperationAccessIsDenied`.
  173. func IsAccessIsDenied(err error) bool {
  174. return hcs.IsAccessIsDenied(getInnerError(err))
  175. }
  176. func getInnerError(err error) error {
  177. switch pe := err.(type) {
  178. case nil:
  179. return nil
  180. case *ContainerError:
  181. err = pe.Err
  182. case *ProcessError:
  183. err = pe.Err
  184. }
  185. return err
  186. }
  187. func convertSystemError(err error, c *container) error {
  188. if serr, ok := err.(*hcs.SystemError); ok {
  189. return &ContainerError{Container: c, Operation: serr.Op, Err: serr.Err, Events: serr.Events}
  190. }
  191. return err
  192. }
  193. func convertProcessError(err error, p *process) error {
  194. if perr, ok := err.(*hcs.ProcessError); ok {
  195. return &ProcessError{Process: p, Operation: perr.Op, Err: perr.Err, Events: perr.Events}
  196. }
  197. return err
  198. }