123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- package hcsshim
- import (
- "fmt"
- "syscall"
- "github.com/Microsoft/hcsshim/internal/hns"
- "github.com/Microsoft/hcsshim/internal/hcs"
- "github.com/Microsoft/hcsshim/internal/hcserror"
- )
- var (
- // ErrComputeSystemDoesNotExist is an error encountered when the container being operated on no longer exists = hcs.exist
- ErrComputeSystemDoesNotExist = hcs.ErrComputeSystemDoesNotExist
- // ErrElementNotFound is an error encountered when the object being referenced does not exist
- ErrElementNotFound = hcs.ErrElementNotFound
- // ErrElementNotFound is an error encountered when the object being referenced does not exist
- ErrNotSupported = hcs.ErrNotSupported
- // ErrInvalidData is an error encountered when the request being sent to hcs is invalid/unsupported
- // decimal -2147024883 / hex 0x8007000d
- ErrInvalidData = hcs.ErrInvalidData
- // ErrHandleClose is an error encountered when the handle generating the notification being waited on has been closed
- ErrHandleClose = hcs.ErrHandleClose
- // ErrAlreadyClosed is an error encountered when using a handle that has been closed by the Close method
- ErrAlreadyClosed = hcs.ErrAlreadyClosed
- // ErrInvalidNotificationType is an error encountered when an invalid notification type is used
- ErrInvalidNotificationType = hcs.ErrInvalidNotificationType
- // ErrInvalidProcessState is an error encountered when the process is not in a valid state for the requested operation
- ErrInvalidProcessState = hcs.ErrInvalidProcessState
- // ErrTimeout is an error encountered when waiting on a notification times out
- ErrTimeout = hcs.ErrTimeout
- // ErrUnexpectedContainerExit is the error encountered when a container exits while waiting for
- // a different expected notification
- ErrUnexpectedContainerExit = hcs.ErrUnexpectedContainerExit
- // ErrUnexpectedProcessAbort is the error encountered when communication with the compute service
- // is lost while waiting for a notification
- ErrUnexpectedProcessAbort = hcs.ErrUnexpectedProcessAbort
- // ErrUnexpectedValue is an error encountered when hcs returns an invalid value
- ErrUnexpectedValue = hcs.ErrUnexpectedValue
- // ErrVmcomputeAlreadyStopped is an error encountered when a shutdown or terminate request is made on a stopped container
- ErrVmcomputeAlreadyStopped = hcs.ErrVmcomputeAlreadyStopped
- // ErrVmcomputeOperationPending is an error encountered when the operation is being completed asynchronously
- ErrVmcomputeOperationPending = hcs.ErrVmcomputeOperationPending
- // ErrVmcomputeOperationInvalidState is an error encountered when the compute system is not in a valid state for the requested operation
- ErrVmcomputeOperationInvalidState = hcs.ErrVmcomputeOperationInvalidState
- // ErrProcNotFound is an error encountered when the the process cannot be found
- ErrProcNotFound = hcs.ErrProcNotFound
- // ErrVmcomputeOperationAccessIsDenied is an error which can be encountered when enumerating compute systems in RS1/RS2
- // builds when the underlying silo might be in the process of terminating. HCS was fixed in RS3.
- ErrVmcomputeOperationAccessIsDenied = hcs.ErrVmcomputeOperationAccessIsDenied
- // ErrVmcomputeInvalidJSON is an error encountered when the compute system does not support/understand the messages sent by management
- ErrVmcomputeInvalidJSON = hcs.ErrVmcomputeInvalidJSON
- // ErrVmcomputeUnknownMessage is an error encountered guest compute system doesn't support the message
- ErrVmcomputeUnknownMessage = hcs.ErrVmcomputeUnknownMessage
- // ErrNotSupported is an error encountered when hcs doesn't support the request
- ErrPlatformNotSupported = hcs.ErrPlatformNotSupported
- )
- type EndpointNotFoundError = hns.EndpointNotFoundError
- type NetworkNotFoundError = hns.NetworkNotFoundError
- // ProcessError is an error encountered in HCS during an operation on a Process object
- type ProcessError struct {
- Process *process
- Operation string
- ExtraInfo string
- Err error
- Events []hcs.ErrorEvent
- }
- // ContainerError is an error encountered in HCS during an operation on a Container object
- type ContainerError struct {
- Container *container
- Operation string
- ExtraInfo string
- Err error
- Events []hcs.ErrorEvent
- }
- func (e *ContainerError) Error() string {
- if e == nil {
- return "<nil>"
- }
- if e.Container == nil {
- return "unexpected nil container for error: " + e.Err.Error()
- }
- s := "container " + e.Container.system.ID()
- if e.Operation != "" {
- s += " encountered an error during " + e.Operation
- }
- switch e.Err.(type) {
- case nil:
- break
- case syscall.Errno:
- s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, hcserror.Win32FromError(e.Err))
- default:
- s += fmt.Sprintf(": %s", e.Err.Error())
- }
- for _, ev := range e.Events {
- s += "\n" + ev.String()
- }
- if e.ExtraInfo != "" {
- s += " extra info: " + e.ExtraInfo
- }
- return s
- }
- func makeContainerError(container *container, operation string, extraInfo string, err error) error {
- // Don't double wrap errors
- if _, ok := err.(*ContainerError); ok {
- return err
- }
- containerError := &ContainerError{Container: container, Operation: operation, ExtraInfo: extraInfo, Err: err}
- return containerError
- }
- func (e *ProcessError) Error() string {
- if e == nil {
- return "<nil>"
- }
- if e.Process == nil {
- return "Unexpected nil process for error: " + e.Err.Error()
- }
- s := fmt.Sprintf("process %d in container %s", e.Process.p.Pid(), e.Process.p.SystemID())
- if e.Operation != "" {
- s += " encountered an error during " + e.Operation
- }
- switch e.Err.(type) {
- case nil:
- break
- case syscall.Errno:
- s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, hcserror.Win32FromError(e.Err))
- default:
- s += fmt.Sprintf(": %s", e.Err.Error())
- }
- for _, ev := range e.Events {
- s += "\n" + ev.String()
- }
- return s
- }
- func makeProcessError(process *process, operation string, extraInfo string, err error) error {
- // Don't double wrap errors
- if _, ok := err.(*ProcessError); ok {
- return err
- }
- processError := &ProcessError{Process: process, Operation: operation, ExtraInfo: extraInfo, Err: err}
- return processError
- }
- // IsNotExist checks if an error is caused by the Container or Process not existing.
- // Note: Currently, ErrElementNotFound can mean that a Process has either
- // already exited, or does not exist. Both IsAlreadyStopped and IsNotExist
- // will currently return true when the error is ErrElementNotFound or ErrProcNotFound.
- func IsNotExist(err error) bool {
- if _, ok := err.(EndpointNotFoundError); ok {
- return true
- }
- if _, ok := err.(NetworkNotFoundError); ok {
- return true
- }
- return hcs.IsNotExist(getInnerError(err))
- }
- // IsAlreadyClosed checks if an error is caused by the Container or Process having been
- // already closed by a call to the Close() method.
- func IsAlreadyClosed(err error) bool {
- return hcs.IsAlreadyClosed(getInnerError(err))
- }
- // IsPending returns a boolean indicating whether the error is that
- // the requested operation is being completed in the background.
- func IsPending(err error) bool {
- return hcs.IsPending(getInnerError(err))
- }
- // IsTimeout returns a boolean indicating whether the error is caused by
- // a timeout waiting for the operation to complete.
- func IsTimeout(err error) bool {
- return hcs.IsTimeout(getInnerError(err))
- }
- // IsAlreadyStopped returns a boolean indicating whether the error is caused by
- // a Container or Process being already stopped.
- // Note: Currently, ErrElementNotFound can mean that a Process has either
- // already exited, or does not exist. Both IsAlreadyStopped and IsNotExist
- // will currently return true when the error is ErrElementNotFound or ErrProcNotFound.
- func IsAlreadyStopped(err error) bool {
- return hcs.IsAlreadyStopped(getInnerError(err))
- }
- // IsNotSupported returns a boolean indicating whether the error is caused by
- // unsupported platform requests
- // Note: Currently Unsupported platform requests can be mean either
- // ErrVmcomputeInvalidJSON, ErrInvalidData, ErrNotSupported or ErrVmcomputeUnknownMessage
- // is thrown from the Platform
- func IsNotSupported(err error) bool {
- return hcs.IsNotSupported(getInnerError(err))
- }
- func getInnerError(err error) error {
- switch pe := err.(type) {
- case nil:
- return nil
- case *ContainerError:
- err = pe.Err
- case *ProcessError:
- err = pe.Err
- }
- return err
- }
- func convertSystemError(err error, c *container) error {
- if serr, ok := err.(*hcs.SystemError); ok {
- return &ContainerError{Container: c, Operation: serr.Op, ExtraInfo: serr.Extra, Err: serr.Err, Events: serr.Events}
- }
- return err
- }
- func convertProcessError(err error, p *process) error {
- if perr, ok := err.(*hcs.ProcessError); ok {
- return &ProcessError{Process: p, Operation: perr.Op, Err: perr.Err, Events: perr.Events}
- }
- return err
- }
|