1
2
3 package hcs
4
5 import (
6 "context"
7 "encoding/json"
8 "errors"
9 "fmt"
10 "net"
11 "syscall"
12
13 "github.com/Microsoft/hcsshim/internal/log"
14 )
15
16 var (
17
18 ErrComputeSystemDoesNotExist = syscall.Errno(0xc037010e)
19
20
21 ErrElementNotFound = syscall.Errno(0x490)
22
23
24 ErrNotSupported = syscall.Errno(0x32)
25
26
27
28 ErrInvalidData = syscall.Errno(0xd)
29
30
31 ErrHandleClose = errors.New("hcsshim: the handle generating this notification has been closed")
32
33
34 ErrAlreadyClosed = errors.New("hcsshim: the handle has already been closed")
35
36
37 ErrInvalidNotificationType = errors.New("hcsshim: invalid notification type")
38
39
40 ErrInvalidProcessState = errors.New("the process is in an invalid state for the attempted operation")
41
42
43 ErrTimeout = errors.New("hcsshim: timeout waiting for notification")
44
45
46
47 ErrUnexpectedContainerExit = errors.New("unexpected container exit")
48
49
50
51 ErrUnexpectedProcessAbort = errors.New("lost communication with compute service")
52
53
54 ErrUnexpectedValue = errors.New("unexpected value returned from hcs")
55
56
57 ErrOperationDenied = errors.New("operation denied")
58
59
60 ErrVmcomputeAlreadyStopped = syscall.Errno(0xc0370110)
61
62
63 ErrVmcomputeOperationPending = syscall.Errno(0xC0370103)
64
65
66 ErrVmcomputeOperationInvalidState = syscall.Errno(0xc0370105)
67
68
69 ErrProcNotFound = syscall.Errno(0x7f)
70
71
72
73 ErrVmcomputeOperationAccessIsDenied = syscall.Errno(0x5)
74
75
76 ErrVmcomputeInvalidJSON = syscall.Errno(0xc037010d)
77
78
79 ErrVmcomputeUnknownMessage = syscall.Errno(0xc037010b)
80
81
82 ErrVmcomputeUnexpectedExit = syscall.Errno(0xC0370106)
83
84
85 ErrPlatformNotSupported = errors.New("unsupported platform request")
86
87
88 ErrProcessAlreadyStopped = syscall.Errno(0x8037011f)
89
90
91
92 ErrInvalidHandle = syscall.Errno(0x6)
93 )
94
95 type ErrorEvent struct {
96 Message string `json:"Message,omitempty"`
97 StackTrace string `json:"StackTrace,omitempty"`
98 Provider string `json:"Provider,omitempty"`
99 EventID uint16 `json:"EventId,omitempty"`
100 Flags uint32 `json:"Flags,omitempty"`
101 Source string `json:"Source,omitempty"`
102
103 }
104
105 type hcsResult struct {
106 Error int32
107 ErrorMessage string
108 ErrorEvents []ErrorEvent `json:"ErrorEvents,omitempty"`
109 }
110
111 func (ev *ErrorEvent) String() string {
112 evs := "[Event Detail: " + ev.Message
113 if ev.StackTrace != "" {
114 evs += " Stack Trace: " + ev.StackTrace
115 }
116 if ev.Provider != "" {
117 evs += " Provider: " + ev.Provider
118 }
119 if ev.EventID != 0 {
120 evs = fmt.Sprintf("%s EventID: %d", evs, ev.EventID)
121 }
122 if ev.Flags != 0 {
123 evs = fmt.Sprintf("%s flags: %d", evs, ev.Flags)
124 }
125 if ev.Source != "" {
126 evs += " Source: " + ev.Source
127 }
128 evs += "]"
129 return evs
130 }
131
132 func processHcsResult(ctx context.Context, resultJSON string) []ErrorEvent {
133 if resultJSON != "" {
134 result := &hcsResult{}
135 if err := json.Unmarshal([]byte(resultJSON), result); err != nil {
136 log.G(ctx).WithError(err).Warning("Could not unmarshal HCS result")
137 return nil
138 }
139 return result.ErrorEvents
140 }
141 return nil
142 }
143
144 type HcsError struct {
145 Op string
146 Err error
147 Events []ErrorEvent
148 }
149
150 var _ net.Error = &HcsError{}
151
152 func (e *HcsError) Error() string {
153 s := e.Op + ": " + e.Err.Error()
154 for _, ev := range e.Events {
155 s += "\n" + ev.String()
156 }
157 return s
158 }
159
160 func (e *HcsError) Is(target error) bool {
161 return errors.Is(e.Err, target)
162 }
163
164
165
166 func (e *HcsError) Unwrap() error {
167 return e.Err
168 }
169
170
171 func (e *HcsError) Temporary() bool {
172 err := e.netError()
173 return (err != nil) && err.Temporary()
174 }
175
176 func (e *HcsError) Timeout() bool {
177 err := e.netError()
178 return (err != nil) && err.Timeout()
179 }
180
181 func (e *HcsError) netError() (err net.Error) {
182 if errors.As(e.Unwrap(), &err) {
183 return err
184 }
185 return nil
186 }
187
188
189 type SystemError struct {
190 HcsError
191 ID string
192 }
193
194 var _ net.Error = &SystemError{}
195
196 func (e *SystemError) Error() string {
197 s := e.Op + " " + e.ID + ": " + e.Err.Error()
198 for _, ev := range e.Events {
199 s += "\n" + ev.String()
200 }
201 return s
202 }
203
204 func makeSystemError(system *System, op string, err error, events []ErrorEvent) error {
205
206 var e *SystemError
207 if errors.As(err, &e) {
208 return err
209 }
210
211 return &SystemError{
212 ID: system.ID(),
213 HcsError: HcsError{
214 Op: op,
215 Err: err,
216 Events: events,
217 },
218 }
219 }
220
221
222 type ProcessError struct {
223 HcsError
224 SystemID string
225 Pid int
226 }
227
228 var _ net.Error = &ProcessError{}
229
230 func (e *ProcessError) Error() string {
231 s := fmt.Sprintf("%s %s:%d: %s", e.Op, e.SystemID, e.Pid, e.Err.Error())
232 for _, ev := range e.Events {
233 s += "\n" + ev.String()
234 }
235 return s
236 }
237
238 func makeProcessError(process *Process, op string, err error, events []ErrorEvent) error {
239
240 var e *ProcessError
241 if errors.As(err, &e) {
242 return err
243 }
244 return &ProcessError{
245 Pid: process.Pid(),
246 SystemID: process.SystemID(),
247 HcsError: HcsError{
248 Op: op,
249 Err: err,
250 Events: events,
251 },
252 }
253 }
254
255
256
257
258
259 func IsNotExist(err error) bool {
260 return IsAny(err, ErrComputeSystemDoesNotExist, ErrElementNotFound)
261 }
262
263
264
265
266 func IsErrorInvalidHandle(err error) bool {
267 return errors.Is(err, ErrInvalidHandle)
268 }
269
270
271
272 func IsAlreadyClosed(err error) bool {
273 return errors.Is(err, ErrAlreadyClosed)
274 }
275
276
277
278 func IsPending(err error) bool {
279 return errors.Is(err, ErrVmcomputeOperationPending)
280 }
281
282
283
284 func IsTimeout(err error) bool {
285
286
287
288
289 if errors.Is(err, ErrTimeout) {
290 return true
291 }
292
293 var nerr net.Error
294 return errors.As(err, &nerr) && nerr.Timeout()
295 }
296
297
298
299
300
301
302 func IsAlreadyStopped(err error) bool {
303 return IsAny(err, ErrVmcomputeAlreadyStopped, ErrProcessAlreadyStopped, ErrElementNotFound)
304 }
305
306
307
308
309
310
311 func IsNotSupported(err error) bool {
312
313 return IsAny(err, ErrVmcomputeInvalidJSON, ErrInvalidData, ErrNotSupported, ErrVmcomputeUnknownMessage)
314 }
315
316
317
318 func IsOperationInvalidState(err error) bool {
319 return errors.Is(err, ErrVmcomputeOperationInvalidState)
320 }
321
322
323
324 func IsAccessIsDenied(err error) bool {
325 return errors.Is(err, ErrVmcomputeOperationAccessIsDenied)
326 }
327
328
329 func IsAny(err error, targets ...error) bool {
330 for _, e := range targets {
331 if errors.Is(err, e) {
332 return true
333 }
334 }
335 return false
336 }
337
View as plain text