1
2
3 package hcsshim
4
5 import (
6 "context"
7 "fmt"
8 "os"
9 "sync"
10 "time"
11
12 "github.com/Microsoft/hcsshim/internal/hcs"
13 "github.com/Microsoft/hcsshim/internal/hcs/schema1"
14 "github.com/Microsoft/hcsshim/internal/mergemaps"
15 )
16
17
18 type ContainerProperties = schema1.ContainerProperties
19
20
21 type MemoryStats = schema1.MemoryStats
22
23
24 type ProcessorStats = schema1.ProcessorStats
25
26
27 type StorageStats = schema1.StorageStats
28
29
30 type NetworkStats = schema1.NetworkStats
31
32
33 type Statistics = schema1.Statistics
34
35
36 type ProcessListItem = schema1.ProcessListItem
37
38
39 type MappedVirtualDiskController = schema1.MappedVirtualDiskController
40
41
42 type RequestType = schema1.RequestType
43
44
45 type ResourceType = schema1.ResourceType
46
47
48 const (
49 Add = schema1.Add
50 Remove = schema1.Remove
51 Network = schema1.Network
52 )
53
54
55
56 type ResourceModificationRequestResponse = schema1.ResourceModificationRequestResponse
57
58 type container struct {
59 system *hcs.System
60 waitOnce sync.Once
61 waitErr error
62 waitCh chan struct{}
63 }
64
65
66
67
68 var createContainerAdditionalJSON []byte
69
70 func init() {
71 createContainerAdditionalJSON = ([]byte)(os.Getenv("HCSSHIM_CREATECONTAINER_ADDITIONALJSON"))
72 }
73
74
75 func CreateContainer(id string, c *ContainerConfig) (Container, error) {
76 fullConfig, err := mergemaps.MergeJSON(c, createContainerAdditionalJSON)
77 if err != nil {
78 return nil, fmt.Errorf("failed to merge additional JSON '%s': %s", createContainerAdditionalJSON, err)
79 }
80
81 system, err := hcs.CreateComputeSystem(context.Background(), id, fullConfig)
82 if err != nil {
83 return nil, err
84 }
85 return &container{system: system}, err
86 }
87
88
89 func OpenContainer(id string) (Container, error) {
90 system, err := hcs.OpenComputeSystem(context.Background(), id)
91 if err != nil {
92 return nil, err
93 }
94 return &container{system: system}, err
95 }
96
97
98 func GetContainers(q ComputeSystemQuery) ([]ContainerProperties, error) {
99 return hcs.GetComputeSystems(context.Background(), q)
100 }
101
102
103 func (container *container) Start() error {
104 return convertSystemError(container.system.Start(context.Background()), container)
105 }
106
107
108 func (container *container) Shutdown() error {
109 err := container.system.Shutdown(context.Background())
110 if err != nil {
111 return convertSystemError(err, container)
112 }
113 return &ContainerError{Container: container, Err: ErrVmcomputeOperationPending, Operation: "hcsshim::ComputeSystem::Shutdown"}
114 }
115
116
117 func (container *container) Terminate() error {
118 err := container.system.Terminate(context.Background())
119 if err != nil {
120 return convertSystemError(err, container)
121 }
122 return &ContainerError{Container: container, Err: ErrVmcomputeOperationPending, Operation: "hcsshim::ComputeSystem::Terminate"}
123 }
124
125
126 func (container *container) Wait() error {
127 err := container.system.Wait()
128 if err == nil {
129 err = container.system.ExitError()
130 }
131 return convertSystemError(err, container)
132 }
133
134
135
136 func (container *container) WaitTimeout(timeout time.Duration) error {
137 container.waitOnce.Do(func() {
138 container.waitCh = make(chan struct{})
139 go func() {
140 container.waitErr = container.Wait()
141 close(container.waitCh)
142 }()
143 })
144 t := time.NewTimer(timeout)
145 defer t.Stop()
146 select {
147 case <-t.C:
148 return &ContainerError{Container: container, Err: ErrTimeout, Operation: "hcsshim::ComputeSystem::Wait"}
149 case <-container.waitCh:
150 return container.waitErr
151 }
152 }
153
154
155 func (container *container) Pause() error {
156 return convertSystemError(container.system.Pause(context.Background()), container)
157 }
158
159
160 func (container *container) Resume() error {
161 return convertSystemError(container.system.Resume(context.Background()), container)
162 }
163
164
165 func (container *container) HasPendingUpdates() (bool, error) {
166 return false, nil
167 }
168
169
170 func (container *container) Statistics() (Statistics, error) {
171 properties, err := container.system.Properties(context.Background(), schema1.PropertyTypeStatistics)
172 if err != nil {
173 return Statistics{}, convertSystemError(err, container)
174 }
175
176 return properties.Statistics, nil
177 }
178
179
180 func (container *container) ProcessList() ([]ProcessListItem, error) {
181 properties, err := container.system.Properties(context.Background(), schema1.PropertyTypeProcessList)
182 if err != nil {
183 return nil, convertSystemError(err, container)
184 }
185
186 return properties.ProcessList, nil
187 }
188
189
190 func (container *container) MappedVirtualDisks() (map[int]MappedVirtualDiskController, error) {
191 properties, err := container.system.Properties(context.Background(), schema1.PropertyTypeMappedVirtualDisk)
192 if err != nil {
193 return nil, convertSystemError(err, container)
194 }
195
196 return properties.MappedVirtualDiskControllers, nil
197 }
198
199
200 func (container *container) CreateProcess(c *ProcessConfig) (Process, error) {
201 p, err := container.system.CreateProcess(context.Background(), c)
202 if err != nil {
203 return nil, convertSystemError(err, container)
204 }
205 return &process{p: p.(*hcs.Process)}, nil
206 }
207
208
209 func (container *container) OpenProcess(pid int) (Process, error) {
210 p, err := container.system.OpenProcess(context.Background(), pid)
211 if err != nil {
212 return nil, convertSystemError(err, container)
213 }
214 return &process{p: p}, nil
215 }
216
217
218 func (container *container) Close() error {
219 return convertSystemError(container.system.Close(), container)
220 }
221
222
223 func (container *container) Modify(config *ResourceModificationRequestResponse) error {
224 return convertSystemError(container.system.Modify(context.Background(), config), container)
225 }
226
View as plain text