1// Package hcn is a shim for the Host Compute Networking (HCN) service, which manages networking for Windows Server 2// containers and Hyper-V containers. Previous to RS5, HCN was referred to as Host Networking Service (HNS). 3package hcn 4 5import ( 6 "errors" 7 "fmt" 8 9 "github.com/Microsoft/hcsshim/internal/hcs" 10 "github.com/Microsoft/hcsshim/internal/hcserror" 11 "github.com/Microsoft/hcsshim/internal/interop" 12 "github.com/sirupsen/logrus" 13) 14 15var ( 16 errInvalidNetworkID = errors.New("invalid network ID") 17 errInvalidEndpointID = errors.New("invalid endpoint ID") 18 errInvalidNamespaceID = errors.New("invalid namespace ID") 19 errInvalidLoadBalancerID = errors.New("invalid load balancer ID") 20 errInvalidRouteID = errors.New("invalid route ID") 21) 22 23func checkForErrors(methodName string, hr error, resultBuffer *uint16) error { 24 errorFound := false 25 26 if hr != nil { 27 errorFound = true 28 } 29 30 result := "" 31 if resultBuffer != nil { 32 result = interop.ConvertAndFreeCoTaskMemString(resultBuffer) 33 if result != "" { 34 errorFound = true 35 } 36 } 37 38 if errorFound { 39 returnError := new(hr, methodName, result) 40 logrus.Debugf(returnError.Error()) // HCN errors logged for debugging. 41 return returnError 42 } 43 44 return nil 45} 46 47type ErrorCode uint32 48 49// For common errors, define the error as it is in windows, so we can quickly determine it later 50const ( 51 ERROR_NOT_FOUND = 0x490 52 HCN_E_PORT_ALREADY_EXISTS ErrorCode = 0x803b0013 53) 54 55type HcnError struct { 56 *hcserror.HcsError 57 code ErrorCode 58} 59 60func (e *HcnError) Error() string { 61 return e.HcsError.Error() 62} 63 64func CheckErrorWithCode(err error, code ErrorCode) bool { 65 hcnError, ok := err.(*HcnError) 66 if ok { 67 return hcnError.code == code 68 } 69 return false 70} 71 72func IsElementNotFoundError(err error) bool { 73 return CheckErrorWithCode(err, ERROR_NOT_FOUND) 74} 75 76func IsPortAlreadyExistsError(err error) bool { 77 return CheckErrorWithCode(err, HCN_E_PORT_ALREADY_EXISTS) 78} 79 80func new(hr error, title string, rest string) error { 81 err := &HcnError{} 82 hcsError := hcserror.New(hr, title, rest) 83 err.HcsError = hcsError.(*hcserror.HcsError) 84 err.code = ErrorCode(hcserror.Win32FromError(hr)) 85 return err 86} 87 88// 89// Note that the below errors are not errors returned by hcn itself 90// we wish to seperate them as they are shim usage error 91// 92 93// NetworkNotFoundError results from a failed seach for a network by Id or Name 94type NetworkNotFoundError struct { 95 NetworkName string 96 NetworkID string 97} 98 99func (e NetworkNotFoundError) Error() string { 100 if e.NetworkName != "" { 101 return fmt.Sprintf("Network name %q not found", e.NetworkName) 102 } 103 return fmt.Sprintf("Network ID %q not found", e.NetworkID) 104} 105 106// EndpointNotFoundError results from a failed seach for an endpoint by Id or Name 107type EndpointNotFoundError struct { 108 EndpointName string 109 EndpointID string 110} 111 112func (e EndpointNotFoundError) Error() string { 113 if e.EndpointName != "" { 114 return fmt.Sprintf("Endpoint name %q not found", e.EndpointName) 115 } 116 return fmt.Sprintf("Endpoint ID %q not found", e.EndpointID) 117} 118 119// NamespaceNotFoundError results from a failed seach for a namsepace by Id 120type NamespaceNotFoundError struct { 121 NamespaceID string 122} 123 124func (e NamespaceNotFoundError) Error() string { 125 return fmt.Sprintf("Namespace ID %q not found", e.NamespaceID) 126} 127 128// LoadBalancerNotFoundError results from a failed seach for a loadbalancer by Id 129type LoadBalancerNotFoundError struct { 130 LoadBalancerId string 131} 132 133func (e LoadBalancerNotFoundError) Error() string { 134 return fmt.Sprintf("LoadBalancer %q not found", e.LoadBalancerId) 135} 136 137// RouteNotFoundError results from a failed seach for a route by Id 138type RouteNotFoundError struct { 139 RouteId string 140} 141 142func (e RouteNotFoundError) Error() string { 143 return fmt.Sprintf("SDN Route %q not found", e.RouteId) 144} 145 146// IsNotFoundError returns a boolean indicating whether the error was caused by 147// a resource not being found. 148func IsNotFoundError(err error) bool { 149 switch pe := err.(type) { 150 case NetworkNotFoundError: 151 return true 152 case EndpointNotFoundError: 153 return true 154 case NamespaceNotFoundError: 155 return true 156 case LoadBalancerNotFoundError: 157 return true 158 case RouteNotFoundError: 159 return true 160 case *hcserror.HcsError: 161 return pe.Err == hcs.ErrElementNotFound 162 } 163 return false 164} 165