Update containerd to 06b9cb35161009dcb7123345749fef02f7cea8e0
John Howard authored on 2017/08/25 06:25:44... | ... |
@@ -38,7 +38,9 @@ const ( |
38 | 38 |
) |
39 | 39 |
|
40 | 40 |
func getMemoryResources(config containertypes.Resources) specs.CappedMemory { |
41 |
- memory := specs.CappedMemory{} |
|
41 |
+ memory := specs.CappedMemory{ |
|
42 |
+ DisableOOMKiller: config.OomKillDisable, |
|
43 |
+ } |
|
42 | 44 |
|
43 | 45 |
if config.Memory > 0 { |
44 | 46 |
memory.Physical = strconv.FormatInt(config.Memory, 10) |
... | ... |
@@ -68,18 +68,15 @@ func getMemoryResources(config containertypes.Resources) *specs.LinuxMemory { |
68 | 68 |
memory := specs.LinuxMemory{} |
69 | 69 |
|
70 | 70 |
if config.Memory > 0 { |
71 |
- limit := uint64(config.Memory) |
|
72 |
- memory.Limit = &limit |
|
71 |
+ memory.Limit = &config.Memory |
|
73 | 72 |
} |
74 | 73 |
|
75 | 74 |
if config.MemoryReservation > 0 { |
76 |
- reservation := uint64(config.MemoryReservation) |
|
77 |
- memory.Reservation = &reservation |
|
75 |
+ memory.Reservation = &config.MemoryReservation |
|
78 | 76 |
} |
79 | 77 |
|
80 | 78 |
if config.MemorySwap > 0 { |
81 |
- swap := uint64(config.MemorySwap) |
|
82 |
- memory.Swap = &swap |
|
79 |
+ memory.Swap = &config.MemorySwap |
|
83 | 80 |
} |
84 | 81 |
|
85 | 82 |
if config.MemorySwappiness != nil { |
... | ... |
@@ -88,8 +85,7 @@ func getMemoryResources(config containertypes.Resources) *specs.LinuxMemory { |
88 | 88 |
} |
89 | 89 |
|
90 | 90 |
if config.KernelMemory != 0 { |
91 |
- kernelMemory := uint64(config.KernelMemory) |
|
92 |
- memory.Kernel = &kernelMemory |
|
91 |
+ memory.Kernel = &config.KernelMemory |
|
93 | 92 |
} |
94 | 93 |
|
95 | 94 |
return &memory |
... | ... |
@@ -22,22 +22,17 @@ func (daemon *Daemon) postRunProcessing(container *container.Container, e libcon |
22 | 22 |
return err |
23 | 23 |
} |
24 | 24 |
|
25 |
- newOpts := []libcontainerd.CreateOption{&libcontainerd.ServicingOption{ |
|
26 |
- IsServicing: true, |
|
27 |
- }} |
|
25 |
+ // Turn on servicing |
|
26 |
+ spec.Windows.Servicing = true |
|
28 | 27 |
|
29 | 28 |
copts, err := daemon.getLibcontainerdCreateOptions(container) |
30 | 29 |
if err != nil { |
31 | 30 |
return err |
32 | 31 |
} |
33 | 32 |
|
34 |
- if copts != nil { |
|
35 |
- newOpts = append(newOpts, copts...) |
|
36 |
- } |
|
37 |
- |
|
38 | 33 |
// Create a new servicing container, which will start, complete the update, and merge back the |
39 | 34 |
// results if it succeeded, all as part of the below function call. |
40 |
- if err := daemon.containerd.Create((container.ID + "_servicing"), "", "", *spec, container.InitializeStdio, newOpts...); err != nil { |
|
35 |
+ if err := daemon.containerd.Create((container.ID + "_servicing"), "", "", *spec, container.InitializeStdio, copts...); err != nil { |
|
41 | 36 |
container.SetExitCode(-1) |
42 | 37 |
return fmt.Errorf("Post-run update servicing failed: %s", err) |
43 | 38 |
} |
... | ... |
@@ -73,7 +73,6 @@ func setResources(s *specs.Spec, r containertypes.Resources) error { |
73 | 73 |
ThrottleReadIOPSDevice: readIOpsDevice, |
74 | 74 |
ThrottleWriteIOPSDevice: writeIOpsDevice, |
75 | 75 |
}, |
76 |
- DisableOOMKiller: r.OomKillDisable, |
|
77 | 76 |
Pids: &specs.LinuxPids{ |
78 | 77 |
Limit: r.PidsLimit, |
79 | 78 |
}, |
... | ... |
@@ -157,14 +156,14 @@ func setDevices(s *specs.Spec, c *container.Container) error { |
157 | 157 |
} |
158 | 158 |
|
159 | 159 |
func setRlimits(daemon *Daemon, s *specs.Spec, c *container.Container) error { |
160 |
- var rlimits []specs.LinuxRlimit |
|
160 |
+ var rlimits []specs.POSIXRlimit |
|
161 | 161 |
|
162 | 162 |
// We want to leave the original HostConfig alone so make a copy here |
163 | 163 |
hostConfig := *c.HostConfig |
164 | 164 |
// Merge with the daemon defaults |
165 | 165 |
daemon.mergeUlimits(&hostConfig) |
166 | 166 |
for _, ul := range hostConfig.Ulimits { |
167 |
- rlimits = append(rlimits, specs.LinuxRlimit{ |
|
167 |
+ rlimits = append(rlimits, specs.POSIXRlimit{ |
|
168 | 168 |
Type: "RLIMIT_" + strings.ToUpper(ul.Name), |
169 | 169 |
Soft: uint64(ul.Soft), |
170 | 170 |
Hard: uint64(ul.Hard), |
... | ... |
@@ -631,7 +630,7 @@ func (daemon *Daemon) populateCommonSpec(s *specs.Spec, c *container.Container) |
631 | 631 |
if err != nil { |
632 | 632 |
return err |
633 | 633 |
} |
634 |
- s.Root = specs.Root{ |
|
634 |
+ s.Root = &specs.Root{ |
|
635 | 635 |
Path: c.BaseFS, |
636 | 636 |
Readonly: c.HostConfig.ReadonlyRootfs, |
637 | 637 |
} |
... | ... |
@@ -708,7 +707,6 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) { |
708 | 708 |
if err := setResources(&s, c.HostConfig.Resources); err != nil { |
709 | 709 |
return nil, fmt.Errorf("linux runtime spec resources: %v", err) |
710 | 710 |
} |
711 |
- s.Linux.Resources.OOMScoreAdj = &c.HostConfig.OomScoreAdj |
|
712 | 711 |
s.Linux.Sysctl = c.HostConfig.Sysctls |
713 | 712 |
|
714 | 713 |
p := s.Linux.CgroupsPath |
... | ... |
@@ -832,6 +830,7 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) { |
832 | 832 |
} |
833 | 833 |
s.Process.SelinuxLabel = c.GetProcessLabel() |
834 | 834 |
s.Process.NoNewPrivileges = c.NoNewPrivileges |
835 |
+ s.Process.OOMScoreAdj = &c.HostConfig.OomScoreAdj |
|
835 | 836 |
s.Linux.MountLabel = c.MountLabel |
836 | 837 |
|
837 | 838 |
return (*specs.Spec)(&s), nil |
... | ... |
@@ -1,13 +1,25 @@ |
1 | 1 |
package daemon |
2 | 2 |
|
3 | 3 |
import ( |
4 |
+ "fmt" |
|
5 |
+ "io/ioutil" |
|
6 |
+ "path/filepath" |
|
7 |
+ "strings" |
|
8 |
+ |
|
4 | 9 |
containertypes "github.com/docker/docker/api/types/container" |
5 | 10 |
"github.com/docker/docker/container" |
11 |
+ "github.com/docker/docker/layer" |
|
6 | 12 |
"github.com/docker/docker/oci" |
7 | 13 |
"github.com/docker/docker/pkg/sysinfo" |
8 | 14 |
"github.com/docker/docker/pkg/system" |
9 | 15 |
"github.com/opencontainers/runtime-spec/specs-go" |
10 | 16 |
"golang.org/x/sys/windows" |
17 |
+ "golang.org/x/sys/windows/registry" |
|
18 |
+) |
|
19 |
+ |
|
20 |
+const ( |
|
21 |
+ credentialSpecRegistryLocation = `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\Containers\CredentialSpecs` |
|
22 |
+ credentialSpecFileLocation = "CredentialSpecs" |
|
11 | 23 |
) |
12 | 24 |
|
13 | 25 |
func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) { |
... | ... |
@@ -53,6 +65,10 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) { |
53 | 53 |
isHyperV = c.HostConfig.Isolation.IsHyperV() |
54 | 54 |
} |
55 | 55 |
|
56 |
+ if isHyperV { |
|
57 |
+ s.Windows.HyperV = &specs.WindowsHyperV{} |
|
58 |
+ } |
|
59 |
+ |
|
56 | 60 |
// If the container has not been started, and has configs or secrets |
57 | 61 |
// secrets, create symlinks to each config and secret. If it has been |
58 | 62 |
// started before, the symlinks should have already been created. Also, it |
... | ... |
@@ -105,13 +121,93 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) { |
105 | 105 |
s.Process.Env = c.CreateDaemonEnvironment(c.Config.Tty, linkedEnv) |
106 | 106 |
if c.Config.Tty { |
107 | 107 |
s.Process.Terminal = c.Config.Tty |
108 |
- s.Process.ConsoleSize.Height = c.HostConfig.ConsoleSize[0] |
|
109 |
- s.Process.ConsoleSize.Width = c.HostConfig.ConsoleSize[1] |
|
108 |
+ s.Process.ConsoleSize = &specs.Box{ |
|
109 |
+ Height: c.HostConfig.ConsoleSize[0], |
|
110 |
+ Width: c.HostConfig.ConsoleSize[1], |
|
111 |
+ } |
|
110 | 112 |
} |
111 | 113 |
s.Process.User.Username = c.Config.User |
112 | 114 |
|
115 |
+ // Get the layer path for each layer. |
|
116 |
+ max := len(img.RootFS.DiffIDs) |
|
117 |
+ for i := 1; i <= max; i++ { |
|
118 |
+ img.RootFS.DiffIDs = img.RootFS.DiffIDs[:i] |
|
119 |
+ layerPath, err := layer.GetLayerPath(daemon.stores[c.Platform].layerStore, img.RootFS.ChainID()) |
|
120 |
+ if err != nil { |
|
121 |
+ return nil, fmt.Errorf("failed to get layer path from graphdriver %s for ImageID %s - %s", daemon.stores[c.Platform].layerStore, img.RootFS.ChainID(), err) |
|
122 |
+ } |
|
123 |
+ // Reverse order, expecting parent most first |
|
124 |
+ s.Windows.LayerFolders = append([]string{layerPath}, s.Windows.LayerFolders...) |
|
125 |
+ } |
|
126 |
+ m, err := c.RWLayer.Metadata() |
|
127 |
+ if err != nil { |
|
128 |
+ return nil, fmt.Errorf("failed to get layer metadata - %s", err) |
|
129 |
+ } |
|
130 |
+ s.Windows.LayerFolders = append(s.Windows.LayerFolders, m["dir"]) |
|
131 |
+ |
|
132 |
+ dnsSearch := daemon.getDNSSearchSettings(c) |
|
133 |
+ |
|
134 |
+ // Get endpoints for the libnetwork allocated networks to the container |
|
135 |
+ var epList []string |
|
136 |
+ AllowUnqualifiedDNSQuery := false |
|
137 |
+ gwHNSID := "" |
|
138 |
+ if c.NetworkSettings != nil { |
|
139 |
+ for n := range c.NetworkSettings.Networks { |
|
140 |
+ sn, err := daemon.FindNetwork(n) |
|
141 |
+ if err != nil { |
|
142 |
+ continue |
|
143 |
+ } |
|
144 |
+ |
|
145 |
+ ep, err := c.GetEndpointInNetwork(sn) |
|
146 |
+ if err != nil { |
|
147 |
+ continue |
|
148 |
+ } |
|
149 |
+ |
|
150 |
+ data, err := ep.DriverInfo() |
|
151 |
+ if err != nil { |
|
152 |
+ continue |
|
153 |
+ } |
|
154 |
+ |
|
155 |
+ if data["GW_INFO"] != nil { |
|
156 |
+ gwInfo := data["GW_INFO"].(map[string]interface{}) |
|
157 |
+ if gwInfo["hnsid"] != nil { |
|
158 |
+ gwHNSID = gwInfo["hnsid"].(string) |
|
159 |
+ } |
|
160 |
+ } |
|
161 |
+ |
|
162 |
+ if data["hnsid"] != nil { |
|
163 |
+ epList = append(epList, data["hnsid"].(string)) |
|
164 |
+ } |
|
165 |
+ |
|
166 |
+ if data["AllowUnqualifiedDNSQuery"] != nil { |
|
167 |
+ AllowUnqualifiedDNSQuery = true |
|
168 |
+ } |
|
169 |
+ } |
|
170 |
+ } |
|
171 |
+ |
|
172 |
+ var networkSharedContainerID string |
|
173 |
+ if c.HostConfig.NetworkMode.IsContainer() { |
|
174 |
+ networkSharedContainerID = c.NetworkSharedContainerID |
|
175 |
+ for _, ep := range c.SharedEndpointList { |
|
176 |
+ epList = append(epList, ep) |
|
177 |
+ } |
|
178 |
+ } |
|
179 |
+ |
|
180 |
+ if gwHNSID != "" { |
|
181 |
+ epList = append(epList, gwHNSID) |
|
182 |
+ } |
|
183 |
+ |
|
184 |
+ s.Windows.Network = &specs.WindowsNetwork{ |
|
185 |
+ AllowUnqualifiedDNSQuery: AllowUnqualifiedDNSQuery, |
|
186 |
+ DNSSearchList: dnsSearch, |
|
187 |
+ EndpointList: epList, |
|
188 |
+ NetworkSharedContainerName: networkSharedContainerID, |
|
189 |
+ } |
|
190 |
+ |
|
113 | 191 |
if img.OS == "windows" { |
114 |
- daemon.createSpecWindowsFields(c, &s, isHyperV) |
|
192 |
+ if err := daemon.createSpecWindowsFields(c, &s, isHyperV); err != nil { |
|
193 |
+ return nil, err |
|
194 |
+ } |
|
115 | 195 |
} else { |
116 | 196 |
// TODO @jhowardmsft LCOW Support. Modify this check when running in dual-mode |
117 | 197 |
if system.LCOWSupported() && img.OS == "linux" { |
... | ... |
@@ -123,7 +219,7 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) { |
123 | 123 |
} |
124 | 124 |
|
125 | 125 |
// Sets the Windows-specific fields of the OCI spec |
126 |
-func (daemon *Daemon) createSpecWindowsFields(c *container.Container, s *specs.Spec, isHyperV bool) { |
|
126 |
+func (daemon *Daemon) createSpecWindowsFields(c *container.Container, s *specs.Spec, isHyperV bool) error { |
|
127 | 127 |
if len(s.Process.Cwd) == 0 { |
128 | 128 |
// We default to C:\ to workaround the oddity of the case that the |
129 | 129 |
// default directory for cmd running as LocalSystem (or |
... | ... |
@@ -138,8 +234,14 @@ func (daemon *Daemon) createSpecWindowsFields(c *container.Container, s *specs.S |
138 | 138 |
s.Root.Readonly = false // Windows does not support a read-only root filesystem |
139 | 139 |
if !isHyperV { |
140 | 140 |
s.Root.Path = c.BaseFS // This is not set for Hyper-V containers |
141 |
+ if !strings.HasSuffix(s.Root.Path, `\`) { |
|
142 |
+ s.Root.Path = s.Root.Path + `\` // Ensure a correctly formatted volume GUID path \\?\Volume{GUID}\ |
|
143 |
+ } |
|
141 | 144 |
} |
142 | 145 |
|
146 |
+ // First boot optimization |
|
147 |
+ s.Windows.IgnoreFlushesDuringBoot = !c.HasBeenStartedBefore |
|
148 |
+ |
|
143 | 149 |
// In s.Windows.Resources |
144 | 150 |
cpuShares := uint16(c.HostConfig.CPUShares) |
145 | 151 |
cpuMaximum := uint16(c.HostConfig.CPUPercent) * 100 |
... | ... |
@@ -179,6 +281,54 @@ func (daemon *Daemon) createSpecWindowsFields(c *container.Container, s *specs.S |
179 | 179 |
Iops: &c.HostConfig.IOMaximumIOps, |
180 | 180 |
}, |
181 | 181 |
} |
182 |
+ |
|
183 |
+ // Read and add credentials from the security options if a credential spec has been provided. |
|
184 |
+ if c.HostConfig.SecurityOpt != nil { |
|
185 |
+ cs := "" |
|
186 |
+ for _, sOpt := range c.HostConfig.SecurityOpt { |
|
187 |
+ sOpt = strings.ToLower(sOpt) |
|
188 |
+ if !strings.Contains(sOpt, "=") { |
|
189 |
+ return fmt.Errorf("invalid security option: no equals sign in supplied value %s", sOpt) |
|
190 |
+ } |
|
191 |
+ var splitsOpt []string |
|
192 |
+ splitsOpt = strings.SplitN(sOpt, "=", 2) |
|
193 |
+ if len(splitsOpt) != 2 { |
|
194 |
+ return fmt.Errorf("invalid security option: %s", sOpt) |
|
195 |
+ } |
|
196 |
+ if splitsOpt[0] != "credentialspec" { |
|
197 |
+ return fmt.Errorf("security option not supported: %s", splitsOpt[0]) |
|
198 |
+ } |
|
199 |
+ |
|
200 |
+ var ( |
|
201 |
+ match bool |
|
202 |
+ csValue string |
|
203 |
+ err error |
|
204 |
+ ) |
|
205 |
+ if match, csValue = getCredentialSpec("file://", splitsOpt[1]); match { |
|
206 |
+ if csValue == "" { |
|
207 |
+ return fmt.Errorf("no value supplied for file:// credential spec security option") |
|
208 |
+ } |
|
209 |
+ if cs, err = readCredentialSpecFile(c.ID, daemon.root, filepath.Clean(csValue)); err != nil { |
|
210 |
+ return err |
|
211 |
+ } |
|
212 |
+ } else if match, csValue = getCredentialSpec("registry://", splitsOpt[1]); match { |
|
213 |
+ if csValue == "" { |
|
214 |
+ return fmt.Errorf("no value supplied for registry:// credential spec security option") |
|
215 |
+ } |
|
216 |
+ if cs, err = readCredentialSpecRegistry(c.ID, csValue); err != nil { |
|
217 |
+ return err |
|
218 |
+ } |
|
219 |
+ } else { |
|
220 |
+ return fmt.Errorf("invalid credential spec security option - value must be prefixed file:// or registry:// followed by a value") |
|
221 |
+ } |
|
222 |
+ } |
|
223 |
+ s.Windows.CredentialSpec = cs |
|
224 |
+ } |
|
225 |
+ |
|
226 |
+ // Assume we are not starting a container for a servicing operation |
|
227 |
+ s.Windows.Servicing = false |
|
228 |
+ |
|
229 |
+ return nil |
|
182 | 230 |
} |
183 | 231 |
|
184 | 232 |
// Sets the Linux-specific fields of the OCI spec |
... | ... |
@@ -205,3 +355,52 @@ func escapeArgs(args []string) []string { |
205 | 205 |
func (daemon *Daemon) mergeUlimits(c *containertypes.HostConfig) { |
206 | 206 |
return |
207 | 207 |
} |
208 |
+ |
|
209 |
+// getCredentialSpec is a helper function to get the value of a credential spec supplied |
|
210 |
+// on the CLI, stripping the prefix |
|
211 |
+func getCredentialSpec(prefix, value string) (bool, string) { |
|
212 |
+ if strings.HasPrefix(value, prefix) { |
|
213 |
+ return true, strings.TrimPrefix(value, prefix) |
|
214 |
+ } |
|
215 |
+ return false, "" |
|
216 |
+} |
|
217 |
+ |
|
218 |
+// readCredentialSpecRegistry is a helper function to read a credential spec from |
|
219 |
+// the registry. If not found, we return an empty string and warn in the log. |
|
220 |
+// This allows for staging on machines which do not have the necessary components. |
|
221 |
+func readCredentialSpecRegistry(id, name string) (string, error) { |
|
222 |
+ var ( |
|
223 |
+ k registry.Key |
|
224 |
+ err error |
|
225 |
+ val string |
|
226 |
+ ) |
|
227 |
+ if k, err = registry.OpenKey(registry.LOCAL_MACHINE, credentialSpecRegistryLocation, registry.QUERY_VALUE); err != nil { |
|
228 |
+ return "", fmt.Errorf("failed handling spec %q for container %s - %s could not be opened", name, id, credentialSpecRegistryLocation) |
|
229 |
+ } |
|
230 |
+ if val, _, err = k.GetStringValue(name); err != nil { |
|
231 |
+ if err == registry.ErrNotExist { |
|
232 |
+ return "", fmt.Errorf("credential spec %q for container %s as it was not found", name, id) |
|
233 |
+ } |
|
234 |
+ return "", fmt.Errorf("error %v reading credential spec %q from registry for container %s", err, name, id) |
|
235 |
+ } |
|
236 |
+ return val, nil |
|
237 |
+} |
|
238 |
+ |
|
239 |
+// readCredentialSpecFile is a helper function to read a credential spec from |
|
240 |
+// a file. If not found, we return an empty string and warn in the log. |
|
241 |
+// This allows for staging on machines which do not have the necessary components. |
|
242 |
+func readCredentialSpecFile(id, root, location string) (string, error) { |
|
243 |
+ if filepath.IsAbs(location) { |
|
244 |
+ return "", fmt.Errorf("invalid credential spec - file:// path cannot be absolute") |
|
245 |
+ } |
|
246 |
+ base := filepath.Join(root, credentialSpecFileLocation) |
|
247 |
+ full := filepath.Join(base, location) |
|
248 |
+ if !strings.HasPrefix(full, base) { |
|
249 |
+ return "", fmt.Errorf("invalid credential spec - file:// path must be under %s", base) |
|
250 |
+ } |
|
251 |
+ bcontents, err := ioutil.ReadFile(full) |
|
252 |
+ if err != nil { |
|
253 |
+ return "", fmt.Errorf("credential spec '%s' for container %s as the file could not be read: %q", full, id, err) |
|
254 |
+ } |
|
255 |
+ return string(bcontents[:]), nil |
|
256 |
+} |
... | ... |
@@ -1,148 +1,14 @@ |
1 | 1 |
package daemon |
2 | 2 |
|
3 | 3 |
import ( |
4 |
- "fmt" |
|
5 |
- "io/ioutil" |
|
6 |
- "path/filepath" |
|
7 |
- "strings" |
|
8 |
- |
|
9 | 4 |
"github.com/Microsoft/opengcs/client" |
10 | 5 |
"github.com/docker/docker/container" |
11 |
- "github.com/docker/docker/layer" |
|
12 | 6 |
"github.com/docker/docker/libcontainerd" |
13 |
- "golang.org/x/sys/windows/registry" |
|
14 |
-) |
|
15 |
- |
|
16 |
-const ( |
|
17 |
- credentialSpecRegistryLocation = `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\Containers\CredentialSpecs` |
|
18 |
- credentialSpecFileLocation = "CredentialSpecs" |
|
19 | 7 |
) |
20 | 8 |
|
21 | 9 |
func (daemon *Daemon) getLibcontainerdCreateOptions(container *container.Container) ([]libcontainerd.CreateOption, error) { |
22 | 10 |
createOptions := []libcontainerd.CreateOption{} |
23 | 11 |
|
24 |
- // Are we going to run as a Hyper-V container? |
|
25 |
- hvOpts := &libcontainerd.HyperVIsolationOption{} |
|
26 |
- if container.HostConfig.Isolation.IsDefault() { |
|
27 |
- // Container is set to use the default, so take the default from the daemon configuration |
|
28 |
- hvOpts.IsHyperV = daemon.defaultIsolation.IsHyperV() |
|
29 |
- } else { |
|
30 |
- // Container is requesting an isolation mode. Honour it. |
|
31 |
- hvOpts.IsHyperV = container.HostConfig.Isolation.IsHyperV() |
|
32 |
- } |
|
33 |
- |
|
34 |
- dnsSearch := daemon.getDNSSearchSettings(container) |
|
35 |
- |
|
36 |
- // Generate the layer folder of the layer options |
|
37 |
- layerOpts := &libcontainerd.LayerOption{} |
|
38 |
- m, err := container.RWLayer.Metadata() |
|
39 |
- if err != nil { |
|
40 |
- return nil, fmt.Errorf("failed to get layer metadata - %s", err) |
|
41 |
- } |
|
42 |
- layerOpts.LayerFolderPath = m["dir"] |
|
43 |
- |
|
44 |
- // Generate the layer paths of the layer options |
|
45 |
- img, err := daemon.stores[container.Platform].imageStore.Get(container.ImageID) |
|
46 |
- if err != nil { |
|
47 |
- return nil, fmt.Errorf("failed to graph.Get on ImageID %s - %s", container.ImageID, err) |
|
48 |
- } |
|
49 |
- // Get the layer path for each layer. |
|
50 |
- max := len(img.RootFS.DiffIDs) |
|
51 |
- for i := 1; i <= max; i++ { |
|
52 |
- img.RootFS.DiffIDs = img.RootFS.DiffIDs[:i] |
|
53 |
- layerPath, err := layer.GetLayerPath(daemon.stores[container.Platform].layerStore, img.RootFS.ChainID()) |
|
54 |
- if err != nil { |
|
55 |
- return nil, fmt.Errorf("failed to get layer path from graphdriver %s for ImageID %s - %s", daemon.stores[container.Platform].layerStore, img.RootFS.ChainID(), err) |
|
56 |
- } |
|
57 |
- // Reverse order, expecting parent most first |
|
58 |
- layerOpts.LayerPaths = append([]string{layerPath}, layerOpts.LayerPaths...) |
|
59 |
- } |
|
60 |
- |
|
61 |
- // Get endpoints for the libnetwork allocated networks to the container |
|
62 |
- var epList []string |
|
63 |
- AllowUnqualifiedDNSQuery := false |
|
64 |
- gwHNSID := "" |
|
65 |
- if container.NetworkSettings != nil { |
|
66 |
- for n := range container.NetworkSettings.Networks { |
|
67 |
- sn, err := daemon.FindNetwork(n) |
|
68 |
- if err != nil { |
|
69 |
- continue |
|
70 |
- } |
|
71 |
- |
|
72 |
- ep, err := container.GetEndpointInNetwork(sn) |
|
73 |
- if err != nil { |
|
74 |
- continue |
|
75 |
- } |
|
76 |
- |
|
77 |
- data, err := ep.DriverInfo() |
|
78 |
- if err != nil { |
|
79 |
- continue |
|
80 |
- } |
|
81 |
- |
|
82 |
- if data["GW_INFO"] != nil { |
|
83 |
- gwInfo := data["GW_INFO"].(map[string]interface{}) |
|
84 |
- if gwInfo["hnsid"] != nil { |
|
85 |
- gwHNSID = gwInfo["hnsid"].(string) |
|
86 |
- } |
|
87 |
- } |
|
88 |
- |
|
89 |
- if data["hnsid"] != nil { |
|
90 |
- epList = append(epList, data["hnsid"].(string)) |
|
91 |
- } |
|
92 |
- |
|
93 |
- if data["AllowUnqualifiedDNSQuery"] != nil { |
|
94 |
- AllowUnqualifiedDNSQuery = true |
|
95 |
- } |
|
96 |
- } |
|
97 |
- } |
|
98 |
- |
|
99 |
- if gwHNSID != "" { |
|
100 |
- epList = append(epList, gwHNSID) |
|
101 |
- } |
|
102 |
- |
|
103 |
- // Read and add credentials from the security options if a credential spec has been provided. |
|
104 |
- if container.HostConfig.SecurityOpt != nil { |
|
105 |
- for _, sOpt := range container.HostConfig.SecurityOpt { |
|
106 |
- sOpt = strings.ToLower(sOpt) |
|
107 |
- if !strings.Contains(sOpt, "=") { |
|
108 |
- return nil, fmt.Errorf("invalid security option: no equals sign in supplied value %s", sOpt) |
|
109 |
- } |
|
110 |
- var splitsOpt []string |
|
111 |
- splitsOpt = strings.SplitN(sOpt, "=", 2) |
|
112 |
- if len(splitsOpt) != 2 { |
|
113 |
- return nil, fmt.Errorf("invalid security option: %s", sOpt) |
|
114 |
- } |
|
115 |
- if splitsOpt[0] != "credentialspec" { |
|
116 |
- return nil, fmt.Errorf("security option not supported: %s", splitsOpt[0]) |
|
117 |
- } |
|
118 |
- |
|
119 |
- credentialsOpts := &libcontainerd.CredentialsOption{} |
|
120 |
- var ( |
|
121 |
- match bool |
|
122 |
- csValue string |
|
123 |
- err error |
|
124 |
- ) |
|
125 |
- if match, csValue = getCredentialSpec("file://", splitsOpt[1]); match { |
|
126 |
- if csValue == "" { |
|
127 |
- return nil, fmt.Errorf("no value supplied for file:// credential spec security option") |
|
128 |
- } |
|
129 |
- if credentialsOpts.Credentials, err = readCredentialSpecFile(container.ID, daemon.root, filepath.Clean(csValue)); err != nil { |
|
130 |
- return nil, err |
|
131 |
- } |
|
132 |
- } else if match, csValue = getCredentialSpec("registry://", splitsOpt[1]); match { |
|
133 |
- if csValue == "" { |
|
134 |
- return nil, fmt.Errorf("no value supplied for registry:// credential spec security option") |
|
135 |
- } |
|
136 |
- if credentialsOpts.Credentials, err = readCredentialSpecRegistry(container.ID, csValue); err != nil { |
|
137 |
- return nil, err |
|
138 |
- } |
|
139 |
- } else { |
|
140 |
- return nil, fmt.Errorf("invalid credential spec security option - value must be prefixed file:// or registry:// followed by a value") |
|
141 |
- } |
|
142 |
- createOptions = append(createOptions, credentialsOpts) |
|
143 |
- } |
|
144 |
- } |
|
145 |
- |
|
146 | 12 |
// LCOW options. |
147 | 13 |
if container.Platform == "linux" { |
148 | 14 |
config := &client.Config{} |
... | ... |
@@ -173,73 +39,5 @@ func (daemon *Daemon) getLibcontainerdCreateOptions(container *container.Contain |
173 | 173 |
createOptions = append(createOptions, lcowOpts) |
174 | 174 |
} |
175 | 175 |
|
176 |
- // Now add the remaining options. |
|
177 |
- createOptions = append(createOptions, &libcontainerd.FlushOption{IgnoreFlushesDuringBoot: !container.HasBeenStartedBefore}) |
|
178 |
- createOptions = append(createOptions, hvOpts) |
|
179 |
- createOptions = append(createOptions, layerOpts) |
|
180 |
- |
|
181 |
- var networkSharedContainerID string |
|
182 |
- if container.HostConfig.NetworkMode.IsContainer() { |
|
183 |
- networkSharedContainerID = container.NetworkSharedContainerID |
|
184 |
- for _, ep := range container.SharedEndpointList { |
|
185 |
- epList = append(epList, ep) |
|
186 |
- } |
|
187 |
- } |
|
188 |
- |
|
189 |
- createOptions = append(createOptions, &libcontainerd.NetworkEndpointsOption{ |
|
190 |
- Endpoints: epList, |
|
191 |
- AllowUnqualifiedDNSQuery: AllowUnqualifiedDNSQuery, |
|
192 |
- DNSSearchList: dnsSearch, |
|
193 |
- NetworkSharedContainerID: networkSharedContainerID, |
|
194 |
- }) |
|
195 | 176 |
return createOptions, nil |
196 | 177 |
} |
197 |
- |
|
198 |
-// getCredentialSpec is a helper function to get the value of a credential spec supplied |
|
199 |
-// on the CLI, stripping the prefix |
|
200 |
-func getCredentialSpec(prefix, value string) (bool, string) { |
|
201 |
- if strings.HasPrefix(value, prefix) { |
|
202 |
- return true, strings.TrimPrefix(value, prefix) |
|
203 |
- } |
|
204 |
- return false, "" |
|
205 |
-} |
|
206 |
- |
|
207 |
-// readCredentialSpecRegistry is a helper function to read a credential spec from |
|
208 |
-// the registry. If not found, we return an empty string and warn in the log. |
|
209 |
-// This allows for staging on machines which do not have the necessary components. |
|
210 |
-func readCredentialSpecRegistry(id, name string) (string, error) { |
|
211 |
- var ( |
|
212 |
- k registry.Key |
|
213 |
- err error |
|
214 |
- val string |
|
215 |
- ) |
|
216 |
- if k, err = registry.OpenKey(registry.LOCAL_MACHINE, credentialSpecRegistryLocation, registry.QUERY_VALUE); err != nil { |
|
217 |
- return "", fmt.Errorf("failed handling spec %q for container %s - %s could not be opened", name, id, credentialSpecRegistryLocation) |
|
218 |
- } |
|
219 |
- if val, _, err = k.GetStringValue(name); err != nil { |
|
220 |
- if err == registry.ErrNotExist { |
|
221 |
- return "", fmt.Errorf("credential spec %q for container %s as it was not found", name, id) |
|
222 |
- } |
|
223 |
- return "", fmt.Errorf("error %v reading credential spec %q from registry for container %s", err, name, id) |
|
224 |
- } |
|
225 |
- return val, nil |
|
226 |
-} |
|
227 |
- |
|
228 |
-// readCredentialSpecFile is a helper function to read a credential spec from |
|
229 |
-// a file. If not found, we return an empty string and warn in the log. |
|
230 |
-// This allows for staging on machines which do not have the necessary components. |
|
231 |
-func readCredentialSpecFile(id, root, location string) (string, error) { |
|
232 |
- if filepath.IsAbs(location) { |
|
233 |
- return "", fmt.Errorf("invalid credential spec - file:// path cannot be absolute") |
|
234 |
- } |
|
235 |
- base := filepath.Join(root, credentialSpecFileLocation) |
|
236 |
- full := filepath.Join(base, location) |
|
237 |
- if !strings.HasPrefix(full, base) { |
|
238 |
- return "", fmt.Errorf("invalid credential spec - file:// path must be under %s", base) |
|
239 |
- } |
|
240 |
- bcontents, err := ioutil.ReadFile(full) |
|
241 |
- if err != nil { |
|
242 |
- return "", fmt.Errorf("credential spec '%s' for container %s as the file could not be read: %q", full, id, err) |
|
243 |
- } |
|
244 |
- return string(bcontents[:]), nil |
|
245 |
-} |
... | ... |
@@ -3,8 +3,8 @@ |
3 | 3 |
TOMLV_COMMIT=9baf8a8a9f2ed20a8e54160840c492f937eeaf9a |
4 | 4 |
|
5 | 5 |
# When updating RUNC_COMMIT, also update runc in vendor.conf accordingly |
6 |
-RUNC_COMMIT=2d41c047c83e09a6d61d464906feb2a2f3c52aa4 |
|
7 |
-CONTAINERD_COMMIT=3addd840653146c90a254301d6c3a663c7fd6429 |
|
6 |
+RUNC_COMMIT=3f2f8b84a77f73d38244dd690525642a72156c64 |
|
7 |
+CONTAINERD_COMMIT=06b9cb35161009dcb7123345749fef02f7cea8e0 |
|
8 | 8 |
TINI_COMMIT=949e6facb77383876aeff8a6944dde66b3089574 |
9 | 9 |
LIBNETWORK_COMMIT=7b2b1feb1de4817d522cc372af149ff48d25028e |
10 | 10 |
VNDR_COMMIT=9909bb2b8a0b7ea464527b376dc50389c90df587 |
... | ... |
@@ -20,7 +20,7 @@ RUNC_BUILDTAGS="${RUNC_BUILDTAGS:-"seccomp apparmor selinux"}" |
20 | 20 |
|
21 | 21 |
install_runc() { |
22 | 22 |
echo "Install runc version $RUNC_COMMIT" |
23 |
- git clone https://github.com/docker/runc.git "$GOPATH/src/github.com/opencontainers/runc" |
|
23 |
+ git clone https://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" |
|
24 | 24 |
cd "$GOPATH/src/github.com/opencontainers/runc" |
25 | 25 |
git checkout -q "$RUNC_COMMIT" |
26 | 26 |
make BUILDTAGS="$RUNC_BUILDTAGS" $1 |
... | ... |
@@ -71,7 +71,7 @@ VERSION=$(< ./VERSION) |
71 | 71 |
! BUILDTIME=$(date -u -d "@${SOURCE_DATE_EPOCH:-$(date +%s)}" --rfc-3339 ns 2> /dev/null | sed -e 's/ /T/') |
72 | 72 |
if [ "$DOCKER_GITCOMMIT" ]; then |
73 | 73 |
GITCOMMIT="$DOCKER_GITCOMMIT" |
74 |
-elif command -v git &> /dev/null && [ -d .git ] && git rev-parse &> /dev/null; then |
|
74 |
+elif command -v git &> /dev/null && [ -e .git ] && git rev-parse &> /dev/null; then |
|
75 | 75 |
GITCOMMIT=$(git rev-parse --short HEAD) |
76 | 76 |
if [ -n "$(git status --porcelain --untracked-files=no)" ]; then |
77 | 77 |
GITCOMMIT="$GITCOMMIT-unsupported" |
... | ... |
@@ -8,6 +8,7 @@ import ( |
8 | 8 |
"io/ioutil" |
9 | 9 |
"os" |
10 | 10 |
"path/filepath" |
11 |
+ "regexp" |
|
11 | 12 |
"strings" |
12 | 13 |
"syscall" |
13 | 14 |
"time" |
... | ... |
@@ -102,8 +103,11 @@ func (clnt *client) Create(containerID string, checkpoint string, checkpointDir |
102 | 102 |
if b, err := json.Marshal(spec); err == nil { |
103 | 103 |
logrus.Debugln("libcontainerd: client.Create() with spec", string(b)) |
104 | 104 |
} |
105 |
- osName := spec.Platform.OS |
|
106 |
- if osName == "windows" { |
|
105 |
+ |
|
106 |
+ // spec.Linux must be nil for Windows containers, but spec.Windows will be filled in regardless of container platform. |
|
107 |
+ // This is a temporary workaround due to LCOW requiring layer folder paths, which are stored under spec.Windows. |
|
108 |
+ // TODO: @darrenstahlmsft fix this once the OCI spec is updated to support layer folder paths for LCOW |
|
109 |
+ if spec.Linux == nil { |
|
107 | 110 |
return clnt.createWindows(containerID, checkpoint, checkpointDir, spec, attachStdio, options...) |
108 | 111 |
} |
109 | 112 |
return clnt.createLinux(containerID, checkpoint, checkpointDir, spec, attachStdio, options...) |
... | ... |
@@ -114,9 +118,10 @@ func (clnt *client) createWindows(containerID string, checkpoint string, checkpo |
114 | 114 |
SystemType: "Container", |
115 | 115 |
Name: containerID, |
116 | 116 |
Owner: defaultOwner, |
117 |
- IgnoreFlushesDuringBoot: false, |
|
117 |
+ IgnoreFlushesDuringBoot: spec.Windows.IgnoreFlushesDuringBoot, |
|
118 | 118 |
HostName: spec.Hostname, |
119 | 119 |
HvPartition: false, |
120 |
+ Servicing: spec.Windows.Servicing, |
|
120 | 121 |
} |
121 | 122 |
|
122 | 123 |
if spec.Windows.Resources != nil { |
... | ... |
@@ -155,49 +160,43 @@ func (clnt *client) createWindows(containerID string, checkpoint string, checkpo |
155 | 155 |
} |
156 | 156 |
} |
157 | 157 |
|
158 |
- var layerOpt *LayerOption |
|
159 |
- for _, option := range options { |
|
160 |
- if s, ok := option.(*ServicingOption); ok { |
|
161 |
- configuration.Servicing = s.IsServicing |
|
162 |
- continue |
|
163 |
- } |
|
164 |
- if f, ok := option.(*FlushOption); ok { |
|
165 |
- configuration.IgnoreFlushesDuringBoot = f.IgnoreFlushesDuringBoot |
|
166 |
- continue |
|
167 |
- } |
|
168 |
- if h, ok := option.(*HyperVIsolationOption); ok { |
|
169 |
- configuration.HvPartition = h.IsHyperV |
|
170 |
- continue |
|
171 |
- } |
|
172 |
- if l, ok := option.(*LayerOption); ok { |
|
173 |
- layerOpt = l |
|
174 |
- } |
|
175 |
- if n, ok := option.(*NetworkEndpointsOption); ok { |
|
176 |
- configuration.EndpointList = n.Endpoints |
|
177 |
- configuration.AllowUnqualifiedDNSQuery = n.AllowUnqualifiedDNSQuery |
|
178 |
- if n.DNSSearchList != nil { |
|
179 |
- configuration.DNSSearchList = strings.Join(n.DNSSearchList, ",") |
|
180 |
- } |
|
181 |
- configuration.NetworkSharedContainerName = n.NetworkSharedContainerID |
|
182 |
- continue |
|
183 |
- } |
|
184 |
- if c, ok := option.(*CredentialsOption); ok { |
|
185 |
- configuration.Credentials = c.Credentials |
|
186 |
- continue |
|
158 |
+ if spec.Windows.HyperV != nil { |
|
159 |
+ configuration.HvPartition = true |
|
160 |
+ } |
|
161 |
+ |
|
162 |
+ if spec.Windows.Network != nil { |
|
163 |
+ configuration.EndpointList = spec.Windows.Network.EndpointList |
|
164 |
+ configuration.AllowUnqualifiedDNSQuery = spec.Windows.Network.AllowUnqualifiedDNSQuery |
|
165 |
+ if spec.Windows.Network.DNSSearchList != nil { |
|
166 |
+ configuration.DNSSearchList = strings.Join(spec.Windows.Network.DNSSearchList, ",") |
|
187 | 167 |
} |
168 |
+ configuration.NetworkSharedContainerName = spec.Windows.Network.NetworkSharedContainerName |
|
169 |
+ } |
|
170 |
+ |
|
171 |
+ if cs, ok := spec.Windows.CredentialSpec.(string); ok { |
|
172 |
+ configuration.Credentials = cs |
|
188 | 173 |
} |
189 | 174 |
|
190 |
- // We must have a layer option with at least one path |
|
191 |
- if layerOpt == nil || layerOpt.LayerPaths == nil { |
|
192 |
- return fmt.Errorf("no layer option or paths were supplied to the runtime") |
|
175 |
+ // We must have least two layers in the spec, the bottom one being a base image, |
|
176 |
+ // the top one being the RW layer. |
|
177 |
+ if spec.Windows.LayerFolders == nil || len(spec.Windows.LayerFolders) < 2 { |
|
178 |
+ return fmt.Errorf("OCI spec is invalid - at least two LayerFolders must be supplied to the runtime") |
|
193 | 179 |
} |
194 | 180 |
|
181 |
+ // Strip off the top-most layer as that's passed in separately to HCS |
|
182 |
+ configuration.LayerFolderPath = spec.Windows.LayerFolders[len(spec.Windows.LayerFolders)-1] |
|
183 |
+ layerFolders := spec.Windows.LayerFolders[:len(spec.Windows.LayerFolders)-1] |
|
184 |
+ |
|
195 | 185 |
if configuration.HvPartition { |
196 |
- // Find the upper-most utility VM image, since the utility VM does not |
|
197 |
- // use layering in RS1. |
|
198 |
- // TODO @swernli/jhowardmsft at some point post RS1 this may be re-locatable. |
|
186 |
+ // We don't currently support setting the utility VM image explicitly. |
|
187 |
+ // TODO @swernli/jhowardmsft circa RS3/4, this may be re-locatable. |
|
188 |
+ if spec.Windows.HyperV.UtilityVMPath != "" { |
|
189 |
+ return errors.New("runtime does not support an explicit utility VM path for Hyper-V containers") |
|
190 |
+ } |
|
191 |
+ |
|
192 |
+ // Find the upper-most utility VM image. |
|
199 | 193 |
var uvmImagePath string |
200 |
- for _, path := range layerOpt.LayerPaths { |
|
194 |
+ for _, path := range layerFolders { |
|
201 | 195 |
fullPath := filepath.Join(path, "UtilityVM") |
202 | 196 |
_, err := os.Stat(fullPath) |
203 | 197 |
if err == nil { |
... | ... |
@@ -212,13 +211,24 @@ func (clnt *client) createWindows(containerID string, checkpoint string, checkpo |
212 | 212 |
return errors.New("utility VM image could not be found") |
213 | 213 |
} |
214 | 214 |
configuration.HvRuntime = &hcsshim.HvRuntime{ImagePath: uvmImagePath} |
215 |
+ |
|
216 |
+ if spec.Root.Path != "" { |
|
217 |
+ return errors.New("OCI spec is invalid - Root.Path must be omitted for a Hyper-V container") |
|
218 |
+ } |
|
215 | 219 |
} else { |
216 |
- configuration.VolumePath = spec.Root.Path |
|
220 |
+ const volumeGUIDRegex = `^\\\\\?\\(Volume)\{{0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}\}\\$` |
|
221 |
+ if _, err := regexp.MatchString(volumeGUIDRegex, spec.Root.Path); err != nil { |
|
222 |
+ return fmt.Errorf(`OCI spec is invalid - Root.Path '%s' must be a volume GUID path in the format '\\?\Volume{GUID}\'`, spec.Root.Path) |
|
223 |
+ } |
|
224 |
+ // HCS API requires the trailing backslash to be removed |
|
225 |
+ configuration.VolumePath = spec.Root.Path[:len(spec.Root.Path)-1] |
|
217 | 226 |
} |
218 | 227 |
|
219 |
- configuration.LayerFolderPath = layerOpt.LayerFolderPath |
|
228 |
+ if spec.Root.Readonly { |
|
229 |
+ return errors.New(`OCI spec is invalid - Root.Readonly must not be set on Windows`) |
|
230 |
+ } |
|
220 | 231 |
|
221 |
- for _, layerPath := range layerOpt.LayerPaths { |
|
232 |
+ for _, layerPath := range layerFolders { |
|
222 | 233 |
_, filename := filepath.Split(layerPath) |
223 | 234 |
g, err := hcsshim.NameToGuid(filename) |
224 | 235 |
if err != nil { |
... | ... |
@@ -235,6 +245,9 @@ func (clnt *client) createWindows(containerID string, checkpoint string, checkpo |
235 | 235 |
var mps []hcsshim.MappedPipe |
236 | 236 |
for _, mount := range spec.Mounts { |
237 | 237 |
const pipePrefix = `\\.\pipe\` |
238 |
+ if mount.Type != "" { |
|
239 |
+ return fmt.Errorf("OCI spec is invalid - Mount.Type '%s' must not be set", mount.Type) |
|
240 |
+ } |
|
238 | 241 |
if strings.HasPrefix(mount.Destination, pipePrefix) { |
239 | 242 |
mp := hcsshim.MappedPipe{ |
240 | 243 |
HostPath: mount.Source, |
... | ... |
@@ -278,6 +291,7 @@ func (clnt *client) createWindows(containerID string, checkpoint string, checkpo |
278 | 278 |
}, |
279 | 279 |
processes: make(map[string]*process), |
280 | 280 |
}, |
281 |
+ isWindows: true, |
|
281 | 282 |
ociSpec: spec, |
282 | 283 |
hcsContainer: hcsContainer, |
283 | 284 |
} |
... | ... |
@@ -306,12 +320,8 @@ func (clnt *client) createWindows(containerID string, checkpoint string, checkpo |
306 | 306 |
func (clnt *client) createLinux(containerID string, checkpoint string, checkpointDir string, spec specs.Spec, attachStdio StdioCallback, options ...CreateOption) error { |
307 | 307 |
logrus.Debugf("libcontainerd: createLinux(): containerId %s ", containerID) |
308 | 308 |
|
309 |
- var layerOpt *LayerOption |
|
310 | 309 |
var lcowOpt *LCOWOption |
311 | 310 |
for _, option := range options { |
312 |
- if layer, ok := option.(*LayerOption); ok { |
|
313 |
- layerOpt = layer |
|
314 |
- } |
|
315 | 311 |
if lcow, ok := option.(*LCOWOption); ok { |
316 | 312 |
lcowOpt = lcow |
317 | 313 |
} |
... | ... |
@@ -344,14 +354,20 @@ func (clnt *client) createLinux(containerID string, checkpoint string, checkpoin |
344 | 344 |
} |
345 | 345 |
} |
346 | 346 |
|
347 |
- // We must have a layer option with at least one path |
|
348 |
- if layerOpt == nil || layerOpt.LayerPaths == nil { |
|
349 |
- return fmt.Errorf("no layer option or paths were supplied to the runtime") |
|
347 |
+ if spec.Windows == nil { |
|
348 |
+ return fmt.Errorf("spec.Windows must not be nil for LCOW containers") |
|
349 |
+ } |
|
350 |
+ |
|
351 |
+ // We must have least one layer in the spec |
|
352 |
+ if spec.Windows.LayerFolders == nil || len(spec.Windows.LayerFolders) == 0 { |
|
353 |
+ return fmt.Errorf("OCI spec is invalid - at least one LayerFolders must be supplied to the runtime") |
|
350 | 354 |
} |
351 | 355 |
|
352 |
- // LayerFolderPath (writeable layer) + Layers (Guid + path) |
|
353 |
- configuration.LayerFolderPath = layerOpt.LayerFolderPath |
|
354 |
- for _, layerPath := range layerOpt.LayerPaths { |
|
356 |
+ // Strip off the top-most layer as that's passed in separately to HCS |
|
357 |
+ configuration.LayerFolderPath = spec.Windows.LayerFolders[len(spec.Windows.LayerFolders)-1] |
|
358 |
+ layerFolders := spec.Windows.LayerFolders[:len(spec.Windows.LayerFolders)-1] |
|
359 |
+ |
|
360 |
+ for _, layerPath := range layerFolders { |
|
355 | 361 |
_, filename := filepath.Split(layerPath) |
356 | 362 |
g, err := hcsshim.NameToGuid(filename) |
357 | 363 |
if err != nil { |
... | ... |
@@ -363,16 +379,13 @@ func (clnt *client) createLinux(containerID string, checkpoint string, checkpoin |
363 | 363 |
}) |
364 | 364 |
} |
365 | 365 |
|
366 |
- for _, option := range options { |
|
367 |
- if n, ok := option.(*NetworkEndpointsOption); ok { |
|
368 |
- configuration.EndpointList = n.Endpoints |
|
369 |
- configuration.AllowUnqualifiedDNSQuery = n.AllowUnqualifiedDNSQuery |
|
370 |
- if n.DNSSearchList != nil { |
|
371 |
- configuration.DNSSearchList = strings.Join(n.DNSSearchList, ",") |
|
372 |
- } |
|
373 |
- configuration.NetworkSharedContainerName = n.NetworkSharedContainerID |
|
374 |
- break |
|
366 |
+ if spec.Windows.Network != nil { |
|
367 |
+ configuration.EndpointList = spec.Windows.Network.EndpointList |
|
368 |
+ configuration.AllowUnqualifiedDNSQuery = spec.Windows.Network.AllowUnqualifiedDNSQuery |
|
369 |
+ if spec.Windows.Network.DNSSearchList != nil { |
|
370 |
+ configuration.DNSSearchList = strings.Join(spec.Windows.Network.DNSSearchList, ",") |
|
375 | 371 |
} |
372 |
+ configuration.NetworkSharedContainerName = spec.Windows.Network.NetworkSharedContainerName |
|
376 | 373 |
} |
377 | 374 |
|
378 | 375 |
hcsContainer, err := hcsshim.CreateContainer(containerID, configuration) |
... | ... |
@@ -438,8 +451,10 @@ func (clnt *client) AddProcess(ctx context.Context, containerID, processFriendly |
438 | 438 |
} |
439 | 439 |
if procToAdd.Terminal { |
440 | 440 |
createProcessParms.EmulateConsole = true |
441 |
- createProcessParms.ConsoleSize[0] = uint(procToAdd.ConsoleSize.Height) |
|
442 |
- createProcessParms.ConsoleSize[1] = uint(procToAdd.ConsoleSize.Width) |
|
441 |
+ if procToAdd.ConsoleSize != nil { |
|
442 |
+ createProcessParms.ConsoleSize[0] = uint(procToAdd.ConsoleSize.Height) |
|
443 |
+ createProcessParms.ConsoleSize[1] = uint(procToAdd.ConsoleSize.Width) |
|
444 |
+ } |
|
443 | 445 |
} |
444 | 446 |
|
445 | 447 |
// Take working directory from the process to add if it is defined, |
... | ... |
@@ -452,7 +467,7 @@ func (clnt *client) AddProcess(ctx context.Context, containerID, processFriendly |
452 | 452 |
|
453 | 453 |
// Configure the environment for the process |
454 | 454 |
createProcessParms.Environment = setupEnvironmentVariables(procToAdd.Env) |
455 |
- if container.ociSpec.Platform.OS == "windows" { |
|
455 |
+ if container.isWindows { |
|
456 | 456 |
createProcessParms.CommandLine = strings.Join(procToAdd.Args, " ") |
457 | 457 |
} else { |
458 | 458 |
createProcessParms.CommandArgs = procToAdd.Args |
... | ... |
@@ -616,13 +631,8 @@ func (clnt *client) Pause(containerID string) error { |
616 | 616 |
return err |
617 | 617 |
} |
618 | 618 |
|
619 |
- for _, option := range container.options { |
|
620 |
- if h, ok := option.(*HyperVIsolationOption); ok { |
|
621 |
- if !h.IsHyperV { |
|
622 |
- return errors.New("cannot pause Windows Server Containers") |
|
623 |
- } |
|
624 |
- break |
|
625 |
- } |
|
619 |
+ if container.ociSpec.Windows.HyperV == nil { |
|
620 |
+ return errors.New("cannot pause Windows Server Containers") |
|
626 | 621 |
} |
627 | 622 |
|
628 | 623 |
err = container.hcsContainer.Pause() |
... | ... |
@@ -656,13 +666,9 @@ func (clnt *client) Resume(containerID string) error { |
656 | 656 |
} |
657 | 657 |
|
658 | 658 |
// This should never happen, since Windows Server Containers cannot be paused |
659 |
- for _, option := range container.options { |
|
660 |
- if h, ok := option.(*HyperVIsolationOption); ok { |
|
661 |
- if !h.IsHyperV { |
|
662 |
- return errors.New("cannot resume Windows Server Containers") |
|
663 |
- } |
|
664 |
- break |
|
665 |
- } |
|
659 |
+ |
|
660 |
+ if container.ociSpec.Windows.HyperV == nil { |
|
661 |
+ return errors.New("cannot resume Windows Server Containers") |
|
666 | 662 |
} |
667 | 663 |
|
668 | 664 |
err = container.hcsContainer.Resume() |
... | ... |
@@ -25,6 +25,7 @@ type container struct { |
25 | 25 |
// otherwise have access to the Spec |
26 | 26 |
ociSpec specs.Spec |
27 | 27 |
|
28 |
+ isWindows bool |
|
28 | 29 |
manualStopRequested bool |
29 | 30 |
hcsContainer hcsshim.Container |
30 | 31 |
} |
... | ... |
@@ -43,13 +44,6 @@ func (ctr *container) newProcess(friendlyName string) *process { |
43 | 43 |
// Caller needs to lock container ID before calling this method. |
44 | 44 |
func (ctr *container) start(attachStdio StdioCallback) error { |
45 | 45 |
var err error |
46 |
- isServicing := false |
|
47 |
- |
|
48 |
- for _, option := range ctr.options { |
|
49 |
- if s, ok := option.(*ServicingOption); ok && s.IsServicing { |
|
50 |
- isServicing = true |
|
51 |
- } |
|
52 |
- } |
|
53 | 46 |
|
54 | 47 |
// Start the container. If this is a servicing container, this call will block |
55 | 48 |
// until the container is done with the servicing execution. |
... | ... |
@@ -69,27 +63,39 @@ func (ctr *container) start(attachStdio StdioCallback) error { |
69 | 69 |
// docker can always grab the output through logs. We also tell HCS to always |
70 | 70 |
// create stdin, even if it's not used - it will be closed shortly. Stderr |
71 | 71 |
// is only created if it we're not -t. |
72 |
+ var ( |
|
73 |
+ emulateConsole bool |
|
74 |
+ createStdErrPipe bool |
|
75 |
+ ) |
|
76 |
+ if ctr.ociSpec.Process != nil { |
|
77 |
+ emulateConsole = ctr.ociSpec.Process.Terminal |
|
78 |
+ createStdErrPipe = !ctr.ociSpec.Process.Terminal && !ctr.ociSpec.Windows.Servicing |
|
79 |
+ } |
|
80 |
+ |
|
72 | 81 |
createProcessParms := &hcsshim.ProcessConfig{ |
73 |
- EmulateConsole: ctr.ociSpec.Process.Terminal, |
|
82 |
+ EmulateConsole: emulateConsole, |
|
74 | 83 |
WorkingDirectory: ctr.ociSpec.Process.Cwd, |
75 |
- CreateStdInPipe: !isServicing, |
|
76 |
- CreateStdOutPipe: !isServicing, |
|
77 |
- CreateStdErrPipe: !ctr.ociSpec.Process.Terminal && !isServicing, |
|
84 |
+ CreateStdInPipe: !ctr.ociSpec.Windows.Servicing, |
|
85 |
+ CreateStdOutPipe: !ctr.ociSpec.Windows.Servicing, |
|
86 |
+ CreateStdErrPipe: createStdErrPipe, |
|
87 |
+ } |
|
88 |
+ |
|
89 |
+ if ctr.ociSpec.Process != nil && ctr.ociSpec.Process.ConsoleSize != nil { |
|
90 |
+ createProcessParms.ConsoleSize[0] = uint(ctr.ociSpec.Process.ConsoleSize.Height) |
|
91 |
+ createProcessParms.ConsoleSize[1] = uint(ctr.ociSpec.Process.ConsoleSize.Width) |
|
78 | 92 |
} |
79 |
- createProcessParms.ConsoleSize[0] = uint(ctr.ociSpec.Process.ConsoleSize.Height) |
|
80 |
- createProcessParms.ConsoleSize[1] = uint(ctr.ociSpec.Process.ConsoleSize.Width) |
|
81 | 93 |
|
82 | 94 |
// Configure the environment for the process |
83 | 95 |
createProcessParms.Environment = setupEnvironmentVariables(ctr.ociSpec.Process.Env) |
84 |
- if ctr.ociSpec.Platform.OS == "windows" { |
|
96 |
+ if ctr.isWindows { |
|
85 | 97 |
createProcessParms.CommandLine = strings.Join(ctr.ociSpec.Process.Args, " ") |
86 | 98 |
} else { |
87 | 99 |
createProcessParms.CommandArgs = ctr.ociSpec.Process.Args |
88 | 100 |
} |
89 | 101 |
createProcessParms.User = ctr.ociSpec.Process.User.Username |
90 | 102 |
|
91 |
- // Linux containers requires the raw OCI spec passed through HCS and onwards to GCS for the utility VM. |
|
92 |
- if ctr.ociSpec.Platform.OS == "linux" { |
|
103 |
+ // LCOW requires the raw OCI spec passed through HCS and onwards to GCS for the utility VM. |
|
104 |
+ if !ctr.isWindows { |
|
93 | 105 |
ociBuf, err := json.Marshal(ctr.ociSpec) |
94 | 106 |
if err != nil { |
95 | 107 |
return err |
... | ... |
@@ -118,7 +124,7 @@ func (ctr *container) start(attachStdio StdioCallback) error { |
118 | 118 |
|
119 | 119 |
// If this is a servicing container, wait on the process synchronously here and |
120 | 120 |
// if it succeeds, wait for it cleanly shutdown and merge into the parent container. |
121 |
- if isServicing { |
|
121 |
+ if ctr.ociSpec.Windows.Servicing { |
|
122 | 122 |
exitCode := ctr.waitProcessExitCode(&ctr.process) |
123 | 123 |
|
124 | 124 |
if exitCode != 0 { |
... | ... |
@@ -244,7 +250,7 @@ func (ctr *container) waitExit(process *process, isFirstProcessToStart bool) err |
244 | 244 |
si.State = StateExitProcess |
245 | 245 |
} else { |
246 | 246 |
// Pending updates is only applicable for WCOW |
247 |
- if ctr.ociSpec.Platform.OS == "windows" { |
|
247 |
+ if ctr.isWindows { |
|
248 | 248 |
updatePending, err := ctr.hcsContainer.HasPendingUpdates() |
249 | 249 |
if err != nil { |
250 | 250 |
logrus.Warnf("libcontainerd: HasPendingUpdates() failed (container may have been killed): %s", err) |
... | ... |
@@ -21,7 +21,7 @@ type Process struct { |
21 | 21 |
// Capabilities are linux capabilities that are kept for the container. |
22 | 22 |
Capabilities []string `json:"capabilities,omitempty"` |
23 | 23 |
// Rlimits specifies rlimit options to apply to the process. |
24 |
- Rlimits []specs.LinuxRlimit `json:"rlimits,omitempty"` |
|
24 |
+ Rlimits []specs.POSIXRlimit `json:"rlimits,omitempty"` |
|
25 | 25 |
// ApparmorProfile specifies the apparmor profile for the container. |
26 | 26 |
ApparmorProfile *string `json:"apparmorProfile,omitempty"` |
27 | 27 |
// SelinuxLabel specifies the selinux context that the container process is run as. |
... | ... |
@@ -31,49 +31,6 @@ type LCOWOption struct { |
31 | 31 |
Config *opengcs.Config |
32 | 32 |
} |
33 | 33 |
|
34 |
-// ServicingOption is a CreateOption with a no-op application that signifies |
|
35 |
-// the container needs to be used for a Windows servicing operation. |
|
36 |
-type ServicingOption struct { |
|
37 |
- IsServicing bool |
|
38 |
-} |
|
39 |
- |
|
40 |
-// FlushOption is a CreateOption that signifies if the container should be |
|
41 |
-// started with flushes ignored until boot has completed. This is an optimisation |
|
42 |
-// for first boot of a container. |
|
43 |
-type FlushOption struct { |
|
44 |
- IgnoreFlushesDuringBoot bool |
|
45 |
-} |
|
46 |
- |
|
47 |
-// HyperVIsolationOption is a CreateOption that indicates whether the runtime |
|
48 |
-// should start the container as a Hyper-V container. |
|
49 |
-type HyperVIsolationOption struct { |
|
50 |
- IsHyperV bool |
|
51 |
-} |
|
52 |
- |
|
53 |
-// LayerOption is a CreateOption that indicates to the runtime the layer folder |
|
54 |
-// and layer paths for a container. |
|
55 |
-type LayerOption struct { |
|
56 |
- // LayerFolderPath is the path to the current layer folder. Empty for Hyper-V containers. |
|
57 |
- LayerFolderPath string `json:",omitempty"` |
|
58 |
- // Layer paths of the parent layers |
|
59 |
- LayerPaths []string |
|
60 |
-} |
|
61 |
- |
|
62 |
-// NetworkEndpointsOption is a CreateOption that provides the runtime list |
|
63 |
-// of network endpoints to which a container should be attached during its creation. |
|
64 |
-type NetworkEndpointsOption struct { |
|
65 |
- Endpoints []string |
|
66 |
- AllowUnqualifiedDNSQuery bool |
|
67 |
- DNSSearchList []string |
|
68 |
- NetworkSharedContainerID string |
|
69 |
-} |
|
70 |
- |
|
71 |
-// CredentialsOption is a CreateOption that indicates the credentials from |
|
72 |
-// a credential spec to be used to the runtime |
|
73 |
-type CredentialsOption struct { |
|
74 |
- Credentials string |
|
75 |
-} |
|
76 |
- |
|
77 | 34 |
// Checkpoint holds the details of a checkpoint (not supported in windows) |
78 | 35 |
type Checkpoint struct { |
79 | 36 |
Name string |
... | ... |
@@ -43,7 +43,7 @@ func systemPid(ctr *containerd.Container) uint32 { |
43 | 43 |
return pid |
44 | 44 |
} |
45 | 45 |
|
46 |
-func convertRlimits(sr []specs.LinuxRlimit) (cr []*containerd.Rlimit) { |
|
46 |
+func convertRlimits(sr []specs.POSIXRlimit) (cr []*containerd.Rlimit) { |
|
47 | 47 |
for _, r := range sr { |
48 | 48 |
cr = append(cr, &containerd.Rlimit{ |
49 | 49 |
Type: r.Type, |
... | ... |
@@ -15,36 +15,6 @@ func setupEnvironmentVariables(a []string) map[string]string { |
15 | 15 |
return r |
16 | 16 |
} |
17 | 17 |
|
18 |
-// Apply for a servicing option is a no-op. |
|
19 |
-func (s *ServicingOption) Apply(interface{}) error { |
|
20 |
- return nil |
|
21 |
-} |
|
22 |
- |
|
23 |
-// Apply for the flush option is a no-op. |
|
24 |
-func (f *FlushOption) Apply(interface{}) error { |
|
25 |
- return nil |
|
26 |
-} |
|
27 |
- |
|
28 |
-// Apply for the hypervisolation option is a no-op. |
|
29 |
-func (h *HyperVIsolationOption) Apply(interface{}) error { |
|
30 |
- return nil |
|
31 |
-} |
|
32 |
- |
|
33 |
-// Apply for the layer option is a no-op. |
|
34 |
-func (h *LayerOption) Apply(interface{}) error { |
|
35 |
- return nil |
|
36 |
-} |
|
37 |
- |
|
38 |
-// Apply for the network endpoints option is a no-op. |
|
39 |
-func (s *NetworkEndpointsOption) Apply(interface{}) error { |
|
40 |
- return nil |
|
41 |
-} |
|
42 |
- |
|
43 |
-// Apply for the credentials option is a no-op. |
|
44 |
-func (s *CredentialsOption) Apply(interface{}) error { |
|
45 |
- return nil |
|
46 |
-} |
|
47 |
- |
|
48 | 18 |
// Apply for the LCOW option is a no-op. |
49 | 19 |
func (s *LCOWOption) Apply(interface{}) error { |
50 | 20 |
return nil |
... | ... |
@@ -50,11 +50,9 @@ func DefaultOSSpec(osName string) specs.Spec { |
50 | 50 |
func DefaultWindowsSpec() specs.Spec { |
51 | 51 |
return specs.Spec{ |
52 | 52 |
Version: specs.Version, |
53 |
- Platform: specs.Platform{ |
|
54 |
- OS: runtime.GOOS, |
|
55 |
- Arch: runtime.GOARCH, |
|
56 |
- }, |
|
57 | 53 |
Windows: &specs.Windows{}, |
54 |
+ Process: &specs.Process{}, |
|
55 |
+ Root: &specs.Root{}, |
|
58 | 56 |
} |
59 | 57 |
} |
60 | 58 |
|
... | ... |
@@ -62,10 +60,6 @@ func DefaultWindowsSpec() specs.Spec { |
62 | 62 |
func DefaultSolarisSpec() specs.Spec { |
63 | 63 |
s := specs.Spec{ |
64 | 64 |
Version: "0.6.0", |
65 |
- Platform: specs.Platform{ |
|
66 |
- OS: "SunOS", |
|
67 |
- Arch: runtime.GOARCH, |
|
68 |
- }, |
|
69 | 65 |
} |
70 | 66 |
s.Solaris = &specs.Solaris{} |
71 | 67 |
return s |
... | ... |
@@ -75,10 +69,8 @@ func DefaultSolarisSpec() specs.Spec { |
75 | 75 |
func DefaultLinuxSpec() specs.Spec { |
76 | 76 |
s := specs.Spec{ |
77 | 77 |
Version: specs.Version, |
78 |
- Platform: specs.Platform{ |
|
79 |
- OS: "linux", |
|
80 |
- Arch: runtime.GOARCH, |
|
81 |
- }, |
|
78 |
+ Process: &specs.Process{}, |
|
79 |
+ Root: &specs.Root{}, |
|
82 | 80 |
} |
83 | 81 |
s.Mounts = []specs.Mount{ |
84 | 82 |
{ |
... | ... |
@@ -124,11 +116,13 @@ func DefaultLinuxSpec() specs.Spec { |
124 | 124 |
Options: []string{"nosuid", "noexec", "nodev", "mode=1777"}, |
125 | 125 |
}, |
126 | 126 |
} |
127 |
- s.Process.Capabilities = &specs.LinuxCapabilities{ |
|
128 |
- Bounding: defaultCapabilities(), |
|
129 |
- Permitted: defaultCapabilities(), |
|
130 |
- Inheritable: defaultCapabilities(), |
|
131 |
- Effective: defaultCapabilities(), |
|
127 |
+ s.Process = &specs.Process{ |
|
128 |
+ Capabilities: &specs.LinuxCapabilities{ |
|
129 |
+ Bounding: defaultCapabilities(), |
|
130 |
+ Permitted: defaultCapabilities(), |
|
131 |
+ Inheritable: defaultCapabilities(), |
|
132 |
+ Effective: defaultCapabilities(), |
|
133 |
+ }, |
|
132 | 134 |
} |
133 | 135 |
|
134 | 136 |
s.Linux = &specs.Linux{ |
... | ... |
@@ -218,6 +212,11 @@ func DefaultLinuxSpec() specs.Spec { |
218 | 218 |
}, |
219 | 219 |
} |
220 | 220 |
|
221 |
+ // For LCOW support, populate a blank Windows spec |
|
222 |
+ if runtime.GOOS == "windows" { |
|
223 |
+ s.Windows = &specs.Windows{} |
|
224 |
+ } |
|
225 |
+ |
|
221 | 226 |
// For LCOW support, don't mask /sys/firmware |
222 | 227 |
if runtime.GOOS != "windows" { |
223 | 228 |
s.Linux.MaskedPaths = append(s.Linux.MaskedPaths, "/sys/firmware") |
... | ... |
@@ -18,7 +18,7 @@ import ( |
18 | 18 |
// InitSpec creates an OCI spec from the plugin's config. |
19 | 19 |
func (p *Plugin) InitSpec(execRoot string) (*specs.Spec, error) { |
20 | 20 |
s := oci.DefaultSpec() |
21 |
- s.Root = specs.Root{ |
|
21 |
+ s.Root = &specs.Root{ |
|
22 | 22 |
Path: p.Rootfs, |
23 | 23 |
Readonly: false, // TODO: all plugins should be readonly? settable in config? |
24 | 24 |
} |
... | ... |
@@ -62,9 +62,9 @@ github.com/pborman/uuid v1.0 |
62 | 62 |
google.golang.org/grpc v1.3.0 |
63 | 63 |
|
64 | 64 |
# When updating, also update RUNC_COMMIT in hack/dockerfile/binaries-commits accordingly |
65 |
-github.com/opencontainers/runc e9325d442f5979c4f79bfa9e09bdf7abb74ba03b https://github.com/dmcgowan/runc.git |
|
65 |
+github.com/opencontainers/runc 3f2f8b84a77f73d38244dd690525642a72156c64 |
|
66 | 66 |
github.com/opencontainers/image-spec 372ad780f63454fbbbbcc7cf80e5b90245c13e13 |
67 |
-github.com/opencontainers/runtime-spec d42f1eb741e6361e858d83fc75aa6893b66292c4 # specs |
|
67 |
+github.com/opencontainers/runtime-spec v1.0.0 |
|
68 | 68 |
|
69 | 69 |
github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0 |
70 | 70 |
|
... | ... |
@@ -101,7 +101,7 @@ github.com/googleapis/gax-go da06d194a00e19ce00d9011a13931c3f6f6887c7 |
101 | 101 |
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 |
102 | 102 |
|
103 | 103 |
# containerd |
104 |
-github.com/containerd/containerd fc10004571bb9b26695ccbf2dd4a83213f60b93e https://github.com/dmcgowan/containerd.git |
|
104 |
+github.com/containerd/containerd 06b9cb35161009dcb7123345749fef02f7cea8e0 |
|
105 | 105 |
github.com/tonistiigi/fifo 1405643975692217d6720f8b54aeee1bf2cd5cf4 |
106 | 106 |
github.com/stevvooe/continuity cd7a8e21e2b6f84799f5dd4b65faf49c8d3ee02d |
107 | 107 |
github.com/tonistiigi/fsutil 0ac4c11b053b9c5c7c47558f81f96c7100ce50fb |
... | ... |
@@ -1,6 +1,5 @@ |
1 |
-// Code generated by protoc-gen-go. |
|
1 |
+// Code generated by protoc-gen-go. DO NOT EDIT. |
|
2 | 2 |
// source: api.proto |
3 |
-// DO NOT EDIT! |
|
4 | 3 |
|
5 | 4 |
/* |
6 | 5 |
Package types is a generated protocol buffer package. |
... | ... |
@@ -1052,6 +1051,8 @@ type UpdateResource struct { |
1052 | 1052 |
BlkioThrottleReadIopsDevice []*ThrottleDevice `protobuf:"bytes,16,rep,name=blkioThrottleReadIopsDevice" json:"blkioThrottleReadIopsDevice,omitempty"` |
1053 | 1053 |
BlkioThrottleWriteIopsDevice []*ThrottleDevice `protobuf:"bytes,17,rep,name=blkioThrottleWriteIopsDevice" json:"blkioThrottleWriteIopsDevice,omitempty"` |
1054 | 1054 |
PidsLimit uint64 `protobuf:"varint,18,opt,name=pidsLimit" json:"pidsLimit,omitempty"` |
1055 |
+ CpuRealtimePeriod uint64 `protobuf:"varint,19,opt,name=cpuRealtimePeriod" json:"cpuRealtimePeriod,omitempty"` |
|
1056 |
+ CpuRealtimeRuntime int64 `protobuf:"varint,20,opt,name=cpuRealtimeRuntime" json:"cpuRealtimeRuntime,omitempty"` |
|
1055 | 1057 |
} |
1056 | 1058 |
|
1057 | 1059 |
func (m *UpdateResource) Reset() { *m = UpdateResource{} } |
... | ... |
@@ -1185,6 +1186,20 @@ func (m *UpdateResource) GetPidsLimit() uint64 { |
1185 | 1185 |
return 0 |
1186 | 1186 |
} |
1187 | 1187 |
|
1188 |
+func (m *UpdateResource) GetCpuRealtimePeriod() uint64 { |
|
1189 |
+ if m != nil { |
|
1190 |
+ return m.CpuRealtimePeriod |
|
1191 |
+ } |
|
1192 |
+ return 0 |
|
1193 |
+} |
|
1194 |
+ |
|
1195 |
+func (m *UpdateResource) GetCpuRealtimeRuntime() int64 { |
|
1196 |
+ if m != nil { |
|
1197 |
+ return m.CpuRealtimeRuntime |
|
1198 |
+ } |
|
1199 |
+ return 0 |
|
1200 |
+} |
|
1201 |
+ |
|
1188 | 1202 |
type BlockIODevice struct { |
1189 | 1203 |
Major int64 `protobuf:"varint,1,opt,name=major" json:"major,omitempty"` |
1190 | 1204 |
Minor int64 `protobuf:"varint,2,opt,name=minor" json:"minor,omitempty"` |
... | ... |
@@ -2415,170 +2430,172 @@ var _API_serviceDesc = grpc.ServiceDesc{ |
2415 | 2415 |
func init() { proto.RegisterFile("api.proto", fileDescriptor0) } |
2416 | 2416 |
|
2417 | 2417 |
var fileDescriptor0 = []byte{ |
2418 |
- // 2632 bytes of a gzipped FileDescriptorProto |
|
2418 |
+ // 2666 bytes of a gzipped FileDescriptorProto |
|
2419 | 2419 |
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x19, 0x4d, 0x6f, 0x24, 0x47, |
2420 | 2420 |
0x75, 0x67, 0xa6, 0xed, 0xf1, 0xbc, 0xf9, 0xb0, 0xa7, 0xd6, 0xeb, 0xed, 0x9d, 0x24, 0xbb, 0x4e, |
2421 | 2421 |
0x2b, 0x10, 0x03, 0x91, 0xb3, 0x78, 0x13, 0x58, 0x11, 0x09, 0x69, 0xd7, 0x1b, 0x82, 0xc9, 0x3a, |
2422 |
- 0x99, 0xb4, 0x6d, 0x56, 0x48, 0x48, 0xa3, 0x76, 0x77, 0xed, 0x4c, 0xe1, 0x9e, 0xae, 0x4e, 0x75, |
|
2423 |
- 0xb5, 0x3d, 0xbe, 0xe4, 0xc0, 0x01, 0x0e, 0x48, 0x70, 0x45, 0xe2, 0xc8, 0x8d, 0x3b, 0x07, 0xf8, |
|
2424 |
- 0x03, 0x48, 0xfc, 0x10, 0x6e, 0xdc, 0x39, 0xa2, 0xfa, 0xe8, 0xea, 0xea, 0xf9, 0xf0, 0x6e, 0x90, |
|
2425 |
- 0x10, 0x17, 0x2e, 0xad, 0x7a, 0xaf, 0xde, 0x57, 0xbd, 0x7a, 0xef, 0xd5, 0xab, 0x6a, 0x68, 0x05, |
|
2426 |
- 0x29, 0xd9, 0x4f, 0x19, 0xe5, 0x14, 0xad, 0xf1, 0xeb, 0x14, 0x67, 0x83, 0x07, 0x63, 0x4a, 0xc7, |
|
2427 |
- 0x31, 0x7e, 0x5f, 0x22, 0xcf, 0xf3, 0x97, 0xef, 0x73, 0x32, 0xc5, 0x19, 0x0f, 0xa6, 0xa9, 0xa2, |
|
2428 |
- 0xf3, 0xee, 0xc1, 0xdd, 0x4f, 0x30, 0x3f, 0xc1, 0xec, 0x12, 0xb3, 0x9f, 0x62, 0x96, 0x11, 0x9a, |
|
2429 |
- 0xf8, 0xf8, 0xcb, 0x1c, 0x67, 0xdc, 0x9b, 0x81, 0xbb, 0x38, 0x95, 0xa5, 0x34, 0xc9, 0x30, 0xda, |
|
2430 |
- 0x86, 0xb5, 0x69, 0xf0, 0x0b, 0xca, 0xdc, 0xda, 0x6e, 0x6d, 0xaf, 0xeb, 0x2b, 0x40, 0x62, 0x49, |
|
2431 |
- 0x42, 0x99, 0x5b, 0xd7, 0x58, 0x01, 0x08, 0x6c, 0x1a, 0xf0, 0x70, 0xe2, 0x36, 0x14, 0x56, 0x02, |
|
2432 |
- 0x68, 0x00, 0x1b, 0x0c, 0x5f, 0x12, 0x21, 0xd5, 0x75, 0x76, 0x6b, 0x7b, 0x2d, 0xdf, 0xc0, 0xde, |
|
2433 |
- 0xaf, 0x6a, 0xb0, 0x7d, 0x96, 0x46, 0x01, 0xc7, 0x43, 0x46, 0x43, 0x9c, 0x65, 0xda, 0x24, 0xd4, |
|
2434 |
- 0x83, 0x3a, 0x89, 0xa4, 0xce, 0x96, 0x5f, 0x27, 0x11, 0xda, 0x82, 0x46, 0x4a, 0x22, 0xa9, 0xae, |
|
2435 |
- 0xe5, 0x8b, 0x21, 0xba, 0x0f, 0x10, 0xc6, 0x34, 0xc3, 0x27, 0x3c, 0x22, 0x89, 0xd4, 0xb8, 0xe1, |
|
2436 |
- 0x5b, 0x18, 0x61, 0xcc, 0x15, 0x89, 0xf8, 0x44, 0xea, 0xec, 0xfa, 0x0a, 0x40, 0x3b, 0xb0, 0x3e, |
|
2437 |
- 0xc1, 0x64, 0x3c, 0xe1, 0xee, 0x9a, 0x44, 0x6b, 0xc8, 0xbb, 0x0b, 0x77, 0xe6, 0xec, 0x50, 0xeb, |
|
2438 |
- 0xf7, 0xfe, 0x5e, 0x87, 0x9d, 0x43, 0x86, 0x03, 0x8e, 0x0f, 0x69, 0xc2, 0x03, 0x92, 0x60, 0xb6, |
|
2439 |
- 0xca, 0xc6, 0xfb, 0x00, 0xe7, 0x79, 0x12, 0xc5, 0x78, 0x18, 0xf0, 0x89, 0x36, 0xd5, 0xc2, 0x48, |
|
2440 |
- 0x8b, 0x27, 0x38, 0xbc, 0x48, 0x29, 0x49, 0xb8, 0xb4, 0xb8, 0xe5, 0x5b, 0x18, 0x61, 0x71, 0x26, |
|
2441 |
- 0x17, 0xa3, 0xbc, 0xa4, 0x00, 0x61, 0x71, 0xc6, 0x23, 0x9a, 0x2b, 0x8b, 0x5b, 0xbe, 0x86, 0x34, |
|
2442 |
- 0x1e, 0x33, 0xe6, 0xae, 0x1b, 0x3c, 0x66, 0x4c, 0xe0, 0xe3, 0xe0, 0x1c, 0xc7, 0x99, 0xdb, 0xdc, |
|
2443 |
- 0x6d, 0x08, 0xbc, 0x82, 0xd0, 0x2e, 0xb4, 0x13, 0x3a, 0x24, 0x97, 0x94, 0xfb, 0x94, 0x72, 0x77, |
|
2444 |
- 0x43, 0x3a, 0xcc, 0x46, 0x21, 0x17, 0x9a, 0x2c, 0x4f, 0x44, 0xdc, 0xb8, 0x2d, 0x29, 0xb2, 0x00, |
|
2445 |
- 0x05, 0xaf, 0x1e, 0x3e, 0x61, 0xe3, 0xcc, 0x05, 0x29, 0xd8, 0x46, 0xa1, 0x77, 0xa0, 0x5b, 0xae, |
|
2446 |
- 0xe4, 0x19, 0x61, 0x6e, 0x5b, 0x4a, 0xa8, 0x22, 0xbd, 0x23, 0xb8, 0xbb, 0xe0, 0x4b, 0x1d, 0x67, |
|
2447 |
- 0xfb, 0xd0, 0x0a, 0x0b, 0xa4, 0xf4, 0x69, 0xfb, 0x60, 0x6b, 0x5f, 0x86, 0xf6, 0x7e, 0x49, 0x5c, |
|
2448 |
- 0x92, 0x78, 0x47, 0xd0, 0x3d, 0x21, 0xe3, 0x24, 0x88, 0x5f, 0x3f, 0x62, 0x84, 0xc7, 0x24, 0x8b, |
|
2449 |
- 0x8e, 0x4f, 0x0d, 0x79, 0x5b, 0xd0, 0x2b, 0x44, 0xe9, 0x4d, 0xff, 0x73, 0x03, 0xfa, 0x4f, 0xa2, |
|
2450 |
- 0xe8, 0x15, 0x31, 0x39, 0x80, 0x0d, 0x8e, 0xd9, 0x94, 0x08, 0x89, 0x75, 0xe9, 0x4e, 0x03, 0xa3, |
|
2451 |
- 0x07, 0xe0, 0xe4, 0x19, 0x66, 0x52, 0x53, 0xfb, 0xa0, 0xad, 0x57, 0x72, 0x96, 0x61, 0xe6, 0xcb, |
|
2452 |
- 0x09, 0x84, 0xc0, 0x09, 0x84, 0x2f, 0x1d, 0xe9, 0x4b, 0x39, 0x16, 0x26, 0xe3, 0xe4, 0xd2, 0x5d, |
|
2453 |
- 0x93, 0x28, 0x31, 0x14, 0x98, 0xf0, 0x2a, 0xd2, 0x3b, 0x2c, 0x86, 0xc5, 0xb2, 0x9a, 0xe5, 0xb2, |
|
2454 |
- 0x4c, 0xd8, 0x6c, 0x2c, 0x0f, 0x9b, 0xd6, 0x8a, 0xb0, 0x81, 0x4a, 0xd8, 0x78, 0xd0, 0x09, 0x83, |
|
2455 |
- 0x34, 0x38, 0x27, 0x31, 0xe1, 0x04, 0x67, 0x6e, 0x5b, 0x1a, 0x51, 0xc1, 0xa1, 0x3d, 0xd8, 0x0c, |
|
2456 |
- 0xd2, 0x34, 0x60, 0x53, 0xca, 0x86, 0x8c, 0xbe, 0x24, 0x31, 0x76, 0x3b, 0x52, 0xc8, 0x3c, 0x5a, |
|
2457 |
- 0x48, 0xcb, 0x70, 0x4c, 0x92, 0x7c, 0xf6, 0x5c, 0x44, 0x9f, 0xdb, 0x95, 0x64, 0x15, 0x9c, 0x90, |
|
2458 |
- 0x96, 0xd0, 0xcf, 0xf0, 0xd5, 0x90, 0x91, 0x4b, 0x12, 0xe3, 0x31, 0xce, 0xdc, 0x9e, 0xf4, 0xe2, |
|
2459 |
- 0x3c, 0x1a, 0xbd, 0x0b, 0x4d, 0x16, 0x93, 0x29, 0xe1, 0x99, 0xbb, 0xb9, 0xdb, 0xd8, 0x6b, 0x1f, |
|
2460 |
- 0x74, 0xb5, 0x3f, 0x7d, 0x89, 0xf5, 0x8b, 0x59, 0xef, 0x19, 0xac, 0x2b, 0x94, 0x70, 0xaf, 0x20, |
|
2461 |
- 0xd1, 0xbb, 0x25, 0xc7, 0x02, 0x97, 0xd1, 0x97, 0x5c, 0xee, 0x95, 0xe3, 0xcb, 0xb1, 0xc0, 0x4d, |
|
2462 |
- 0x02, 0x16, 0xc9, 0x7d, 0x72, 0x7c, 0x39, 0xf6, 0x7c, 0x70, 0xc4, 0x46, 0x09, 0x57, 0xe7, 0x7a, |
|
2463 |
- 0xc3, 0xbb, 0xbe, 0x18, 0x0a, 0xcc, 0x58, 0xc7, 0x54, 0xd7, 0x17, 0x43, 0xf4, 0x4d, 0xe8, 0x05, |
|
2464 |
- 0x51, 0x44, 0x38, 0xa1, 0x49, 0x10, 0x7f, 0x42, 0xa2, 0xcc, 0x6d, 0xec, 0x36, 0xf6, 0xba, 0xfe, |
|
2465 |
- 0x1c, 0xd6, 0x3b, 0x00, 0x64, 0x07, 0x94, 0x0e, 0xfa, 0x37, 0xa1, 0x95, 0x5d, 0x67, 0x1c, 0x4f, |
|
2466 |
- 0x87, 0x46, 0x4f, 0x89, 0xf0, 0x7e, 0x59, 0x33, 0xe9, 0x62, 0xb2, 0x68, 0x55, 0x2c, 0x7e, 0xb7, |
|
2467 |
- 0x52, 0x5b, 0xea, 0x32, 0xea, 0xfa, 0x45, 0xfe, 0x94, 0xdc, 0x76, 0xb9, 0x59, 0x48, 0xd9, 0xc6, |
|
2468 |
- 0xb2, 0x94, 0x1d, 0x80, 0xbb, 0x68, 0x83, 0x4e, 0x93, 0x10, 0xee, 0x3e, 0xc3, 0x31, 0x7e, 0x1d, |
|
2469 |
- 0xfb, 0x10, 0x38, 0x49, 0x30, 0xc5, 0x3a, 0x1d, 0xe5, 0xf8, 0xf5, 0x0d, 0x58, 0x54, 0xa2, 0x0d, |
|
2470 |
- 0x38, 0x86, 0x3b, 0xcf, 0x49, 0xc6, 0x5f, 0xad, 0x7e, 0x41, 0x55, 0x7d, 0x99, 0xaa, 0xdf, 0xd7, |
|
2471 |
- 0x00, 0x4a, 0x59, 0xc6, 0xe6, 0x9a, 0x65, 0x33, 0x02, 0x07, 0xcf, 0x08, 0xd7, 0xf9, 0x2e, 0xc7, |
|
2472 |
- 0x22, 0x2a, 0x78, 0x98, 0xea, 0x23, 0x48, 0x0c, 0x45, 0xbd, 0xcc, 0x13, 0x32, 0x3b, 0xa1, 0xe1, |
|
2473 |
- 0x05, 0xe6, 0x99, 0xac, 0xe7, 0x1b, 0xbe, 0x8d, 0x92, 0x49, 0x3b, 0xc1, 0x71, 0x2c, 0x8b, 0xfa, |
|
2474 |
- 0x86, 0xaf, 0x00, 0x51, 0x81, 0xf1, 0x34, 0xe5, 0xd7, 0x9f, 0x9d, 0xb8, 0xeb, 0x32, 0xff, 0x0a, |
|
2475 |
- 0xd0, 0x3b, 0x86, 0x9d, 0xf9, 0x95, 0xea, 0x18, 0x7a, 0x04, 0xed, 0x72, 0x15, 0x99, 0x5b, 0x93, |
|
2476 |
- 0x09, 0xb2, 0x64, 0xeb, 0x6d, 0x2a, 0xef, 0x3e, 0x74, 0x4e, 0x78, 0xc0, 0xf1, 0x0a, 0x7f, 0x79, |
|
2477 |
- 0x7b, 0xd0, 0x33, 0x55, 0x57, 0x12, 0xaa, 0xba, 0x11, 0xf0, 0x3c, 0xd3, 0x54, 0x1a, 0xf2, 0xfe, |
|
2478 |
- 0xd2, 0x80, 0xa6, 0x0e, 0xeb, 0xa2, 0x36, 0xd5, 0xca, 0xda, 0xf4, 0x3f, 0x29, 0x91, 0x95, 0xac, |
|
2479 |
- 0x6a, 0xce, 0x65, 0xd5, 0xff, 0xcb, 0x65, 0x59, 0x2e, 0xff, 0x56, 0x83, 0x96, 0xd9, 0xe6, 0xaf, |
|
2480 |
- 0xdd, 0xce, 0xbc, 0x07, 0xad, 0x54, 0x6d, 0x3c, 0x56, 0x55, 0xaf, 0x7d, 0xd0, 0xd3, 0x8a, 0x8a, |
|
2481 |
- 0x3a, 0x57, 0x12, 0x58, 0xf1, 0xe3, 0xd8, 0xf1, 0x63, 0xb5, 0x2b, 0x6b, 0x95, 0x76, 0x05, 0x81, |
|
2482 |
- 0x93, 0x8a, 0x72, 0xba, 0x2e, 0xcb, 0xa9, 0x1c, 0xdb, 0x0d, 0x4a, 0xb3, 0xd2, 0xa0, 0x78, 0x1f, |
|
2483 |
- 0x42, 0xf3, 0x38, 0x08, 0x27, 0x24, 0x91, 0x19, 0x1a, 0xa6, 0x3a, 0x4c, 0xbb, 0xbe, 0x1c, 0x0b, |
|
2484 |
- 0x25, 0x53, 0x3c, 0xa5, 0xec, 0x5a, 0xd7, 0x7e, 0x0d, 0x79, 0x17, 0xd0, 0xd5, 0x69, 0xa0, 0x93, |
|
2485 |
- 0xe9, 0x21, 0x80, 0x69, 0x31, 0x8a, 0x5c, 0x5a, 0x6c, 0x43, 0x2c, 0x1a, 0xb4, 0x07, 0xcd, 0xa9, |
|
2486 |
- 0xd2, 0xac, 0xab, 0x6e, 0xe1, 0x03, 0x6d, 0x8f, 0x5f, 0x4c, 0x7b, 0xbf, 0xae, 0xc1, 0x8e, 0xea, |
|
2487 |
- 0x31, 0x5f, 0xd9, 0x49, 0x2e, 0xef, 0x5d, 0x94, 0xfb, 0x1a, 0x15, 0xf7, 0x3d, 0x82, 0x16, 0xc3, |
|
2488 |
- 0x19, 0xcd, 0x59, 0x88, 0x95, 0x67, 0xdb, 0x07, 0x77, 0x8a, 0x4c, 0x92, 0xba, 0x7c, 0x3d, 0xeb, |
|
2489 |
- 0x97, 0x74, 0xde, 0x6f, 0x9a, 0xd0, 0xab, 0xce, 0x8a, 0x8a, 0x75, 0x1e, 0x5f, 0x10, 0xfa, 0x42, |
|
2490 |
- 0x35, 0xc7, 0x35, 0xe9, 0x26, 0x1b, 0x25, 0xb2, 0x2a, 0x4c, 0xf3, 0x93, 0x49, 0xc0, 0x70, 0xa6, |
|
2491 |
- 0xdd, 0x58, 0x22, 0xf4, 0xec, 0x10, 0x33, 0x42, 0x8b, 0xc3, 0xb4, 0x44, 0x88, 0x32, 0x10, 0xa6, |
|
2492 |
- 0xf9, 0x17, 0x39, 0xe5, 0x81, 0x34, 0xd2, 0xf1, 0x0d, 0x2c, 0xbb, 0xe2, 0x34, 0xcf, 0x30, 0x3f, |
|
2493 |
- 0x14, 0xbb, 0xb6, 0xa6, 0xbb, 0x62, 0x83, 0x29, 0xe7, 0x8f, 0xf1, 0x34, 0xd3, 0x69, 0x6e, 0x61, |
|
2494 |
- 0x84, 0xe5, 0x6a, 0x37, 0x9f, 0x8b, 0xa0, 0x96, 0x81, 0xe1, 0xf8, 0x36, 0x4a, 0x48, 0x50, 0xe0, |
|
2495 |
- 0xc9, 0x55, 0x90, 0xca, 0xb4, 0x77, 0x7c, 0x0b, 0x83, 0xde, 0x83, 0xbe, 0x82, 0x7c, 0x9c, 0x61, |
|
2496 |
- 0x76, 0x19, 0x88, 0x63, 0x5b, 0x96, 0x01, 0xc7, 0x5f, 0x9c, 0x10, 0xd4, 0x17, 0x98, 0x25, 0x38, |
|
2497 |
- 0x3e, 0xb6, 0xb4, 0x82, 0xa2, 0x5e, 0x98, 0x40, 0x07, 0xb0, 0xad, 0x90, 0xa7, 0x87, 0x43, 0x9b, |
|
2498 |
- 0xa1, 0x2d, 0x19, 0x96, 0xce, 0x89, 0x4c, 0x97, 0x8e, 0x7f, 0x8e, 0x83, 0x97, 0x7a, 0x3f, 0x3a, |
|
2499 |
- 0x92, 0x7c, 0x1e, 0x8d, 0x9e, 0x40, 0xdf, 0xda, 0xa2, 0x67, 0xf8, 0x92, 0x84, 0xd8, 0xed, 0xca, |
|
2500 |
- 0xa8, 0xbd, 0xad, 0xa3, 0xc0, 0x9e, 0xf2, 0x17, 0xa9, 0xd1, 0x19, 0x0c, 0x24, 0xf2, 0x74, 0xc2, |
|
2501 |
- 0x28, 0xe7, 0x31, 0xf6, 0x71, 0x10, 0x3d, 0x4d, 0x33, 0x2d, 0xab, 0x27, 0x65, 0x15, 0x11, 0x55, |
|
2502 |
- 0xd0, 0x68, 0x69, 0x37, 0x30, 0xa2, 0x17, 0xf0, 0x46, 0x65, 0xf6, 0x05, 0x23, 0x1c, 0x97, 0x72, |
|
2503 |
- 0x37, 0x6f, 0x92, 0x7b, 0x13, 0xe7, 0x82, 0x60, 0xa1, 0xf6, 0x88, 0x1a, 0xc1, 0x5b, 0xaf, 0x2f, |
|
2504 |
- 0xb8, 0xca, 0x89, 0x7e, 0x06, 0x6f, 0x2e, 0xea, 0xb5, 0x24, 0xf7, 0x6f, 0x92, 0x7c, 0x23, 0xab, |
|
2505 |
- 0x48, 0x0e, 0x51, 0xbf, 0xd4, 0xce, 0x23, 0x95, 0x1c, 0x06, 0xe1, 0x7d, 0x04, 0xdd, 0xa7, 0x31, |
|
2506 |
- 0x0d, 0x2f, 0x8e, 0x3e, 0xd7, 0xe4, 0x95, 0x2b, 0x77, 0x63, 0xe9, 0x95, 0xbb, 0xa1, 0xaf, 0xdc, |
|
2507 |
- 0xde, 0x57, 0xd0, 0xa9, 0x6c, 0xe7, 0xf7, 0x64, 0x1e, 0x17, 0xa2, 0xf4, 0x45, 0x6a, 0x5b, 0x1b, |
|
2508 |
- 0x5d, 0x51, 0xe3, 0xdb, 0x84, 0xa2, 0xbe, 0x5c, 0xa9, 0x50, 0x53, 0xcd, 0xad, 0x86, 0x44, 0xee, |
|
2509 |
- 0xc4, 0x65, 0x18, 0xaa, 0x7b, 0x93, 0x85, 0xf1, 0x7e, 0x0e, 0xbd, 0xaa, 0x2b, 0xfe, 0x63, 0x0b, |
|
2510 |
- 0x10, 0x38, 0x2c, 0xe0, 0xb8, 0xe8, 0xce, 0xc5, 0xd8, 0xbb, 0x07, 0x77, 0x17, 0x2a, 0xa6, 0x6e, |
|
2511 |
- 0xfd, 0xae, 0xa1, 0xfb, 0xf1, 0x25, 0x4e, 0xb8, 0xb9, 0x9d, 0x3d, 0x86, 0x96, 0x79, 0xf2, 0xd0, |
|
2512 |
- 0xa5, 0x78, 0xb0, 0xaf, 0x1e, 0x45, 0xf6, 0x8b, 0x47, 0x91, 0xfd, 0xd3, 0x82, 0xc2, 0x2f, 0x89, |
|
2513 |
- 0xc5, 0x1a, 0x33, 0x4e, 0x19, 0x8e, 0x3e, 0x4f, 0xe2, 0xeb, 0xe2, 0x25, 0xa1, 0xc4, 0xe8, 0xea, |
|
2514 |
- 0xec, 0x98, 0xe6, 0xe8, 0x77, 0x35, 0x58, 0x93, 0xba, 0x97, 0xde, 0x32, 0x14, 0x75, 0xdd, 0xd4, |
|
2515 |
- 0xf2, 0x6a, 0xe5, 0xee, 0x9a, 0xca, 0xad, 0x6b, 0xbc, 0x53, 0xd6, 0xf8, 0xca, 0x0a, 0xd6, 0xbf, |
|
2516 |
- 0xc6, 0x0a, 0xbc, 0xdf, 0xd6, 0xa1, 0xf3, 0x19, 0xe6, 0x57, 0x94, 0x5d, 0x88, 0xf3, 0x2c, 0x5b, |
|
2517 |
- 0xda, 0xba, 0xde, 0x83, 0x0d, 0x36, 0x1b, 0x9d, 0x5f, 0x73, 0x53, 0xbf, 0x9b, 0x6c, 0xf6, 0x54, |
|
2518 |
- 0x80, 0xe8, 0x2d, 0x00, 0x36, 0x1b, 0x0d, 0x03, 0xd5, 0xae, 0xea, 0xf2, 0xcd, 0x66, 0x1a, 0x81, |
|
2519 |
- 0xde, 0x80, 0x96, 0x3f, 0x1b, 0x61, 0xc6, 0x28, 0xcb, 0x8a, 0xfa, 0xed, 0xcf, 0x3e, 0x96, 0xb0, |
|
2520 |
- 0xe0, 0xf5, 0x67, 0xa3, 0x88, 0xd1, 0x34, 0xc5, 0x91, 0xac, 0xdf, 0x8e, 0xdf, 0xf2, 0x67, 0xcf, |
|
2521 |
- 0x14, 0x42, 0x68, 0x3d, 0x2d, 0xb4, 0xae, 0x2b, 0xad, 0xa7, 0xa5, 0xd6, 0xd3, 0xd9, 0x28, 0xd5, |
|
2522 |
- 0x5a, 0x55, 0xe1, 0x6e, 0x9d, 0xda, 0x5a, 0x4f, 0x8d, 0x56, 0x55, 0xb5, 0x37, 0x4e, 0x2d, 0xad, |
|
2523 |
- 0xa7, 0xa5, 0xd6, 0x56, 0xc1, 0xab, 0xb5, 0x7a, 0x7f, 0xaa, 0xc1, 0xc6, 0x61, 0x9a, 0x9f, 0x65, |
|
2524 |
- 0xc1, 0x18, 0xa3, 0x07, 0xd0, 0xe6, 0x94, 0x07, 0xf1, 0x28, 0x17, 0xa0, 0x3e, 0xdb, 0x40, 0xa2, |
|
2525 |
- 0x14, 0xc1, 0xdb, 0xd0, 0x49, 0x31, 0x0b, 0xd3, 0x5c, 0x53, 0xd4, 0x77, 0x1b, 0xe2, 0x0c, 0x51, |
|
2526 |
- 0x38, 0x45, 0xb2, 0x0f, 0xb7, 0xe5, 0xdc, 0x88, 0x24, 0x23, 0x55, 0xb4, 0xa7, 0x34, 0xc2, 0xda, |
|
2527 |
- 0x55, 0x7d, 0x39, 0x75, 0x94, 0x7c, 0x6a, 0x26, 0xd0, 0xb7, 0xa1, 0x6f, 0xe8, 0x45, 0x33, 0x2b, |
|
2528 |
- 0xa9, 0x95, 0xeb, 0x36, 0x35, 0xf5, 0x99, 0x46, 0x7b, 0x5f, 0x99, 0x1c, 0x22, 0xc9, 0xf8, 0x59, |
|
2529 |
- 0xc0, 0x03, 0xd1, 0xe8, 0xa4, 0xf2, 0xe4, 0xcc, 0xb4, 0xb5, 0x05, 0x88, 0xbe, 0x03, 0x7d, 0xae, |
|
2530 |
- 0xf3, 0x2d, 0x1a, 0x15, 0x34, 0x6a, 0x37, 0xb7, 0xcc, 0xc4, 0x50, 0x13, 0x7f, 0x03, 0x7a, 0x25, |
|
2531 |
- 0xb1, 0x6c, 0x9b, 0x94, 0xbd, 0x5d, 0x83, 0x15, 0xd1, 0xe4, 0xfd, 0x41, 0x39, 0x4b, 0x45, 0xce, |
|
2532 |
- 0x7b, 0xf2, 0x20, 0xb7, 0x5c, 0xd5, 0x3e, 0xd8, 0x2c, 0x1a, 0x20, 0xed, 0x0c, 0x79, 0x78, 0x2b, |
|
2533 |
- 0xb7, 0xfc, 0x10, 0x36, 0xb9, 0x31, 0x7d, 0x14, 0x05, 0x3c, 0xd0, 0xa9, 0x37, 0x57, 0x27, 0xf5, |
|
2534 |
- 0xc2, 0xfc, 0x1e, 0xaf, 0x2e, 0xf4, 0x6d, 0xe8, 0xa8, 0xce, 0x5c, 0x2b, 0x54, 0xf6, 0xb5, 0x15, |
|
2535 |
- 0x4e, 0xaa, 0xf0, 0x3e, 0x82, 0xd6, 0x90, 0x44, 0x99, 0xb2, 0xce, 0x85, 0x66, 0x98, 0x33, 0x86, |
|
2536 |
- 0x93, 0xa2, 0x45, 0x29, 0x40, 0x51, 0x1e, 0x65, 0x57, 0xab, 0x9d, 0xa1, 0x00, 0x8f, 0x02, 0xa8, |
|
2537 |
- 0x93, 0x55, 0x6a, 0xdb, 0x86, 0x35, 0x3b, 0x04, 0x14, 0x20, 0xe2, 0x6c, 0x1a, 0xcc, 0xcc, 0xd6, |
|
2538 |
- 0xcb, 0x38, 0x9b, 0x06, 0x33, 0xb5, 0x40, 0x17, 0x9a, 0x2f, 0x03, 0x12, 0x87, 0xfa, 0xc1, 0xce, |
|
2539 |
- 0xf1, 0x0b, 0xb0, 0x54, 0xe8, 0xd8, 0x0a, 0xff, 0x58, 0x87, 0xb6, 0xd2, 0xa8, 0x0c, 0xde, 0x86, |
|
2540 |
- 0xb5, 0x30, 0x08, 0x27, 0x46, 0xa5, 0x04, 0xd0, 0xbb, 0x85, 0x21, 0xd5, 0x8b, 0x7a, 0x69, 0x6a, |
|
2541 |
- 0x61, 0xdb, 0x43, 0x80, 0xec, 0x2a, 0x48, 0x2d, 0xef, 0x2c, 0xa5, 0x6e, 0x09, 0x22, 0x65, 0xf0, |
|
2542 |
- 0x07, 0xd0, 0x51, 0xf1, 0xa9, 0x79, 0x9c, 0x55, 0x3c, 0x6d, 0x45, 0xa6, 0xb8, 0x1e, 0x89, 0x4b, |
|
2543 |
- 0x51, 0xc0, 0x55, 0x13, 0xde, 0x3e, 0x78, 0xab, 0x42, 0x2e, 0x57, 0xb2, 0x2f, 0xbf, 0x1f, 0x27, |
|
2544 |
- 0x9c, 0x5d, 0xfb, 0x8a, 0x76, 0xf0, 0x18, 0xa0, 0x44, 0x8a, 0x7a, 0x76, 0x81, 0xaf, 0x8b, 0xcb, |
|
2545 |
- 0xdf, 0x05, 0xbe, 0x16, 0x6b, 0xbf, 0x0c, 0xe2, 0xbc, 0x70, 0xaa, 0x02, 0x7e, 0x50, 0x7f, 0x5c, |
|
2546 |
- 0xf3, 0x42, 0xd8, 0x7c, 0x2a, 0x0e, 0x4c, 0x8b, 0xbd, 0x72, 0xe8, 0x39, 0x4b, 0x0f, 0x3d, 0xa7, |
|
2547 |
- 0x78, 0x67, 0xee, 0x41, 0x9d, 0xa6, 0xba, 0x11, 0xae, 0xd3, 0xb4, 0x54, 0xe4, 0x58, 0x8a, 0xbc, |
|
2548 |
- 0x7f, 0x38, 0x00, 0xa5, 0x16, 0x74, 0x02, 0x03, 0x42, 0x47, 0xa2, 0x8f, 0x23, 0x21, 0x56, 0x05, |
|
2549 |
- 0x69, 0xc4, 0x70, 0x98, 0xb3, 0x8c, 0x5c, 0x62, 0xdd, 0xea, 0xef, 0x98, 0x63, 0xaa, 0x62, 0x9c, |
|
2550 |
- 0x7f, 0x97, 0xd0, 0x13, 0xc5, 0x28, 0x2b, 0x97, 0x5f, 0xb0, 0xa1, 0x9f, 0xc0, 0x9d, 0x52, 0x68, |
|
2551 |
- 0x64, 0xc9, 0xab, 0xdf, 0x28, 0xef, 0xb6, 0x91, 0x17, 0x95, 0xb2, 0x7e, 0x04, 0xb7, 0x09, 0x1d, |
|
2552 |
- 0x7d, 0x99, 0xe3, 0xbc, 0x22, 0xa9, 0x71, 0xa3, 0xa4, 0x3e, 0xa1, 0x5f, 0x48, 0x8e, 0x52, 0xce, |
|
2553 |
- 0x17, 0x70, 0xcf, 0x5a, 0xa8, 0x48, 0x7b, 0x4b, 0x9a, 0x73, 0xa3, 0xb4, 0x1d, 0x63, 0x97, 0x28, |
|
2554 |
- 0x0c, 0xa5, 0xc8, 0x4f, 0x61, 0x87, 0xd0, 0xd1, 0x55, 0x40, 0xf8, 0xbc, 0xbc, 0xb5, 0x57, 0xad, |
|
2555 |
- 0xf3, 0x45, 0x40, 0x78, 0x55, 0x98, 0x5a, 0xe7, 0x14, 0xb3, 0x71, 0x65, 0x9d, 0xeb, 0xaf, 0x5a, |
|
2556 |
- 0xe7, 0xb1, 0xe4, 0x28, 0xe5, 0x3c, 0x85, 0x3e, 0xa1, 0xf3, 0xf6, 0x34, 0x6f, 0x94, 0xb2, 0x49, |
|
2557 |
- 0x68, 0xd5, 0x96, 0x43, 0xe8, 0x67, 0x38, 0xe4, 0x94, 0xd9, 0xb1, 0xb0, 0x71, 0xa3, 0x8c, 0x2d, |
|
2558 |
- 0xcd, 0x60, 0x84, 0x78, 0x5f, 0x42, 0xe7, 0xc7, 0xf9, 0x18, 0xf3, 0xf8, 0xdc, 0xe4, 0xfc, 0x7f, |
|
2559 |
- 0xbb, 0xcc, 0xfc, 0xab, 0x0e, 0xed, 0xc3, 0x31, 0xa3, 0x79, 0x5a, 0xa9, 0xda, 0x2a, 0x87, 0x17, |
|
2560 |
- 0xaa, 0xb6, 0xa4, 0x91, 0x55, 0x5b, 0x51, 0x7f, 0x08, 0x1d, 0x75, 0xaf, 0xd1, 0x0c, 0xaa, 0x0a, |
|
2561 |
- 0xa1, 0xc5, 0xa4, 0x2f, 0xee, 0x51, 0x8a, 0xed, 0x40, 0xdf, 0x11, 0x35, 0x57, 0xb5, 0x1a, 0x95, |
|
2562 |
- 0x6e, 0xf2, 0xe1, 0xbc, 0xcc, 0xba, 0x23, 0xe8, 0x4e, 0x94, 0x6f, 0x34, 0x97, 0x0a, 0xc0, 0x77, |
|
2563 |
- 0x0a, 0xe3, 0xca, 0x35, 0xec, 0xdb, 0x3e, 0x54, 0xae, 0xee, 0x4c, 0x6c, 0xb7, 0xbe, 0x0f, 0x20, |
|
2564 |
- 0x9a, 0xe6, 0x51, 0x51, 0xa8, 0xec, 0x5f, 0x04, 0xe6, 0x84, 0x50, 0x8d, 0xb5, 0x1c, 0x0e, 0x4e, |
|
2565 |
- 0xa1, 0xbf, 0x20, 0x73, 0x49, 0x99, 0xfa, 0x96, 0x5d, 0xa6, 0xca, 0x8b, 0x93, 0xcd, 0x6a, 0xd7, |
|
2566 |
- 0xae, 0xbf, 0xd6, 0xd4, 0xa3, 0x41, 0xf9, 0x8a, 0xfb, 0x18, 0xba, 0x89, 0x6a, 0xbe, 0xcc, 0x06, |
|
2567 |
- 0xd8, 0x37, 0x30, 0xbb, 0x31, 0xf3, 0x3b, 0x89, 0xdd, 0xa6, 0x7d, 0x08, 0x9d, 0x50, 0x7a, 0x60, |
|
2568 |
- 0xe9, 0x46, 0x58, 0xce, 0xf1, 0xdb, 0xa1, 0xb5, 0xdb, 0x95, 0x46, 0xd1, 0xf9, 0x3a, 0x8d, 0xa2, |
|
2569 |
- 0x7e, 0xf7, 0x5b, 0xf5, 0x4b, 0xe3, 0xe0, 0x9f, 0xeb, 0xd0, 0x78, 0x32, 0x3c, 0x42, 0x67, 0xb0, |
|
2570 |
- 0x35, 0xff, 0x47, 0x10, 0xdd, 0xd7, 0x66, 0xad, 0xf8, 0x8b, 0x38, 0x78, 0xb0, 0x72, 0x5e, 0xb7, |
|
2571 |
- 0xec, 0xb7, 0x90, 0x0f, 0x9b, 0x73, 0xff, 0x7f, 0x50, 0x71, 0xd4, 0x2c, 0xff, 0xc7, 0x36, 0xb8, |
|
2572 |
- 0xbf, 0x6a, 0xda, 0x96, 0x39, 0x77, 0x47, 0x30, 0x32, 0x97, 0xbf, 0xb6, 0x18, 0x99, 0xab, 0xae, |
|
2573 |
- 0x16, 0xb7, 0xd0, 0xf7, 0x61, 0x5d, 0xfd, 0x11, 0x42, 0xc5, 0xc5, 0xa5, 0xf2, 0xaf, 0x69, 0x70, |
|
2574 |
- 0x67, 0x0e, 0x6b, 0x18, 0x9f, 0x43, 0xb7, 0xf2, 0x1b, 0x11, 0xbd, 0x51, 0xd1, 0x55, 0xfd, 0xa1, |
|
2575 |
- 0x34, 0x78, 0x73, 0xf9, 0xa4, 0x91, 0x76, 0x08, 0x50, 0xfe, 0x34, 0x40, 0xae, 0xa6, 0x5e, 0xf8, |
|
2576 |
- 0x31, 0x35, 0xb8, 0xb7, 0x64, 0xc6, 0x08, 0x39, 0x83, 0xad, 0xf9, 0x07, 0x7c, 0x34, 0xe7, 0xd5, |
|
2577 |
- 0xf9, 0xe7, 0x73, 0xb3, 0x95, 0x2b, 0x5f, 0xfe, 0xa5, 0xd8, 0xf9, 0x67, 0x79, 0x23, 0x76, 0xc5, |
|
2578 |
- 0x4f, 0x01, 0x23, 0x76, 0xe5, 0x7b, 0xfe, 0x2d, 0xf4, 0x39, 0xf4, 0xaa, 0xef, 0xdc, 0xa8, 0x70, |
|
2579 |
- 0xd2, 0xd2, 0x87, 0xfe, 0xc1, 0x5b, 0x2b, 0x66, 0x8d, 0xc0, 0x0f, 0x60, 0x4d, 0x3d, 0x60, 0x17, |
|
2580 |
- 0xe9, 0x68, 0xbf, 0x7b, 0x0f, 0xb6, 0xab, 0x48, 0xc3, 0xf5, 0x10, 0xd6, 0xd5, 0xed, 0xd2, 0x04, |
|
2581 |
- 0x40, 0xe5, 0xb2, 0x39, 0xe8, 0xd8, 0x58, 0xef, 0xd6, 0xc3, 0x5a, 0xa1, 0x27, 0xab, 0xe8, 0xc9, |
|
2582 |
- 0x96, 0xe9, 0xb1, 0x36, 0xe7, 0x7c, 0x5d, 0xa6, 0xeb, 0xa3, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, |
|
2583 |
- 0x4c, 0xa9, 0xa8, 0x4d, 0xd0, 0x1f, 0x00, 0x00, |
|
2422 |
+ 0x99, 0x94, 0x6d, 0x56, 0x48, 0x48, 0xa3, 0x76, 0x77, 0xed, 0x4c, 0xe1, 0x9e, 0xae, 0x4e, 0x75, |
|
2423 |
+ 0xb5, 0x3d, 0xbe, 0xe4, 0xc0, 0x01, 0x6e, 0x70, 0x45, 0xe2, 0xc8, 0x8d, 0x3b, 0x07, 0xf8, 0x03, |
|
2424 |
+ 0x48, 0xfc, 0x10, 0x24, 0x0e, 0xdc, 0x39, 0xa2, 0xfa, 0xe8, 0xee, 0xea, 0xf9, 0xf0, 0x6e, 0x90, |
|
2425 |
+ 0x10, 0x17, 0x2e, 0xad, 0x7a, 0xaf, 0xde, 0x57, 0xbd, 0x7a, 0xef, 0xd5, 0xab, 0x2e, 0x68, 0xf9, |
|
2426 |
+ 0x09, 0xdd, 0x4f, 0x38, 0x13, 0x0c, 0xad, 0x89, 0xeb, 0x84, 0xa4, 0x83, 0x07, 0x63, 0xc6, 0xc6, |
|
2427 |
+ 0x11, 0x79, 0x5f, 0x21, 0xcf, 0xb3, 0x97, 0xef, 0x0b, 0x3a, 0x25, 0xa9, 0xf0, 0xa7, 0x89, 0xa6, |
|
2428 |
+ 0xf3, 0xee, 0xc1, 0xdd, 0x4f, 0x88, 0x38, 0x21, 0xfc, 0x92, 0xf0, 0x9f, 0x12, 0x9e, 0x52, 0x16, |
|
2429 |
+ 0x63, 0xf2, 0x65, 0x46, 0x52, 0xe1, 0xcd, 0xc0, 0x5d, 0x9c, 0x4a, 0x13, 0x16, 0xa7, 0x04, 0x6d, |
|
2430 |
+ 0xc3, 0xda, 0xd4, 0xff, 0x05, 0xe3, 0x6e, 0x6d, 0xb7, 0xb6, 0xd7, 0xc5, 0x1a, 0x50, 0x58, 0x1a, |
|
2431 |
+ 0x33, 0xee, 0xd6, 0x0d, 0x56, 0x02, 0x12, 0x9b, 0xf8, 0x22, 0x98, 0xb8, 0x0d, 0x8d, 0x55, 0x00, |
|
2432 |
+ 0x1a, 0xc0, 0x06, 0x27, 0x97, 0x54, 0x4a, 0x75, 0x9d, 0xdd, 0xda, 0x5e, 0x0b, 0x17, 0xb0, 0xf7, |
|
2433 |
+ 0xab, 0x1a, 0x6c, 0x9f, 0x25, 0xa1, 0x2f, 0xc8, 0x90, 0xb3, 0x80, 0xa4, 0xa9, 0x31, 0x09, 0xf5, |
|
2434 |
+ 0xa0, 0x4e, 0x43, 0xa5, 0xb3, 0x85, 0xeb, 0x34, 0x44, 0x5b, 0xd0, 0x48, 0x68, 0xa8, 0xd4, 0xb5, |
|
2435 |
+ 0xb0, 0x1c, 0xa2, 0xfb, 0x00, 0x41, 0xc4, 0x52, 0x72, 0x22, 0x42, 0x1a, 0x2b, 0x8d, 0x1b, 0xd8, |
|
2436 |
+ 0xc2, 0x48, 0x63, 0xae, 0x68, 0x28, 0x26, 0x4a, 0x67, 0x17, 0x6b, 0x00, 0xed, 0xc0, 0xfa, 0x84, |
|
2437 |
+ 0xd0, 0xf1, 0x44, 0xb8, 0x6b, 0x0a, 0x6d, 0x20, 0xef, 0x2e, 0xdc, 0x99, 0xb3, 0x43, 0xaf, 0xdf, |
|
2438 |
+ 0xfb, 0x5b, 0x1d, 0x76, 0x0e, 0x39, 0xf1, 0x05, 0x39, 0x64, 0xb1, 0xf0, 0x69, 0x4c, 0xf8, 0x2a, |
|
2439 |
+ 0x1b, 0xef, 0x03, 0x9c, 0x67, 0x71, 0x18, 0x91, 0xa1, 0x2f, 0x26, 0xc6, 0x54, 0x0b, 0xa3, 0x2c, |
|
2440 |
+ 0x9e, 0x90, 0xe0, 0x22, 0x61, 0x34, 0x16, 0xca, 0xe2, 0x16, 0xb6, 0x30, 0xd2, 0xe2, 0x54, 0x2d, |
|
2441 |
+ 0x46, 0x7b, 0x49, 0x03, 0xd2, 0xe2, 0x54, 0x84, 0x2c, 0xd3, 0x16, 0xb7, 0xb0, 0x81, 0x0c, 0x9e, |
|
2442 |
+ 0x70, 0xee, 0xae, 0x17, 0x78, 0xc2, 0xb9, 0xc4, 0x47, 0xfe, 0x39, 0x89, 0x52, 0xb7, 0xb9, 0xdb, |
|
2443 |
+ 0x90, 0x78, 0x0d, 0xa1, 0x5d, 0x68, 0xc7, 0x6c, 0x48, 0x2f, 0x99, 0xc0, 0x8c, 0x09, 0x77, 0x43, |
|
2444 |
+ 0x39, 0xcc, 0x46, 0x21, 0x17, 0x9a, 0x3c, 0x8b, 0x65, 0xdc, 0xb8, 0x2d, 0x25, 0x32, 0x07, 0x25, |
|
2445 |
+ 0xaf, 0x19, 0x3e, 0xe1, 0xe3, 0xd4, 0x05, 0x25, 0xd8, 0x46, 0xa1, 0x77, 0xa0, 0x5b, 0xae, 0xe4, |
|
2446 |
+ 0x19, 0xe5, 0x6e, 0x5b, 0x49, 0xa8, 0x22, 0xbd, 0x23, 0xb8, 0xbb, 0xe0, 0x4b, 0x13, 0x67, 0xfb, |
|
2447 |
+ 0xd0, 0x0a, 0x72, 0xa4, 0xf2, 0x69, 0xfb, 0x60, 0x6b, 0x5f, 0x85, 0xf6, 0x7e, 0x49, 0x5c, 0x92, |
|
2448 |
+ 0x78, 0x47, 0xd0, 0x3d, 0xa1, 0xe3, 0xd8, 0x8f, 0x5e, 0x3f, 0x62, 0xa4, 0xc7, 0x14, 0x8b, 0x89, |
|
2449 |
+ 0x4f, 0x03, 0x79, 0x5b, 0xd0, 0xcb, 0x45, 0x99, 0x4d, 0xff, 0x53, 0x03, 0xfa, 0x4f, 0xc2, 0xf0, |
|
2450 |
+ 0x15, 0x31, 0x39, 0x80, 0x0d, 0x41, 0xf8, 0x94, 0x4a, 0x89, 0x75, 0xe5, 0xce, 0x02, 0x46, 0x0f, |
|
2451 |
+ 0xc0, 0xc9, 0x52, 0xc2, 0x95, 0xa6, 0xf6, 0x41, 0xdb, 0xac, 0xe4, 0x2c, 0x25, 0x1c, 0xab, 0x09, |
|
2452 |
+ 0x84, 0xc0, 0xf1, 0xa5, 0x2f, 0x1d, 0xe5, 0x4b, 0x35, 0x96, 0x26, 0x93, 0xf8, 0xd2, 0x5d, 0x53, |
|
2453 |
+ 0x28, 0x39, 0x94, 0x98, 0xe0, 0x2a, 0x34, 0x3b, 0x2c, 0x87, 0xf9, 0xb2, 0x9a, 0xe5, 0xb2, 0x8a, |
|
2454 |
+ 0xb0, 0xd9, 0x58, 0x1e, 0x36, 0xad, 0x15, 0x61, 0x03, 0x95, 0xb0, 0xf1, 0xa0, 0x13, 0xf8, 0x89, |
|
2455 |
+ 0x7f, 0x4e, 0x23, 0x2a, 0x28, 0x49, 0xdd, 0xb6, 0x32, 0xa2, 0x82, 0x43, 0x7b, 0xb0, 0xe9, 0x27, |
|
2456 |
+ 0x89, 0xcf, 0xa7, 0x8c, 0x0f, 0x39, 0x7b, 0x49, 0x23, 0xe2, 0x76, 0x94, 0x90, 0x79, 0xb4, 0x94, |
|
2457 |
+ 0x96, 0x92, 0x88, 0xc6, 0xd9, 0xec, 0xb9, 0x8c, 0x3e, 0xb7, 0xab, 0xc8, 0x2a, 0x38, 0x29, 0x2d, |
|
2458 |
+ 0x66, 0x9f, 0x91, 0xab, 0x21, 0xa7, 0x97, 0x34, 0x22, 0x63, 0x92, 0xba, 0x3d, 0xe5, 0xc5, 0x79, |
|
2459 |
+ 0x34, 0x7a, 0x17, 0x9a, 0x3c, 0xa2, 0x53, 0x2a, 0x52, 0x77, 0x73, 0xb7, 0xb1, 0xd7, 0x3e, 0xe8, |
|
2460 |
+ 0x1a, 0x7f, 0x62, 0x85, 0xc5, 0xf9, 0xac, 0xf7, 0x0c, 0xd6, 0x35, 0x4a, 0xba, 0x57, 0x92, 0x98, |
|
2461 |
+ 0xdd, 0x52, 0x63, 0x89, 0x4b, 0xd9, 0x4b, 0xa1, 0xf6, 0xca, 0xc1, 0x6a, 0x2c, 0x71, 0x13, 0x9f, |
|
2462 |
+ 0x87, 0x6a, 0x9f, 0x1c, 0xac, 0xc6, 0x1e, 0x06, 0x47, 0x6e, 0x94, 0x74, 0x75, 0x66, 0x36, 0xbc, |
|
2463 |
+ 0x8b, 0xe5, 0x50, 0x62, 0xc6, 0x26, 0xa6, 0xba, 0x58, 0x0e, 0xd1, 0x37, 0xa1, 0xe7, 0x87, 0x21, |
|
2464 |
+ 0x15, 0x94, 0xc5, 0x7e, 0xf4, 0x09, 0x0d, 0x53, 0xb7, 0xb1, 0xdb, 0xd8, 0xeb, 0xe2, 0x39, 0xac, |
|
2465 |
+ 0x77, 0x00, 0xc8, 0x0e, 0x28, 0x13, 0xf4, 0x6f, 0x42, 0x2b, 0xbd, 0x4e, 0x05, 0x99, 0x0e, 0x0b, |
|
2466 |
+ 0x3d, 0x25, 0xc2, 0xfb, 0x65, 0xad, 0x48, 0x97, 0x22, 0x8b, 0x56, 0xc5, 0xe2, 0x77, 0x2b, 0xb5, |
|
2467 |
+ 0xa5, 0xae, 0xa2, 0xae, 0x9f, 0xe7, 0x4f, 0xc9, 0x6d, 0x97, 0x9b, 0x85, 0x94, 0x6d, 0x2c, 0x4b, |
|
2468 |
+ 0xd9, 0x01, 0xb8, 0x8b, 0x36, 0x98, 0x34, 0x09, 0xe0, 0xee, 0x33, 0x12, 0x91, 0xd7, 0xb1, 0x0f, |
|
2469 |
+ 0x81, 0x13, 0xfb, 0x53, 0x62, 0xd2, 0x51, 0x8d, 0x5f, 0xdf, 0x80, 0x45, 0x25, 0xc6, 0x80, 0x63, |
|
2470 |
+ 0xb8, 0xf3, 0x9c, 0xa6, 0xe2, 0xd5, 0xea, 0x17, 0x54, 0xd5, 0x97, 0xa9, 0xfa, 0x5d, 0x0d, 0xa0, |
|
2471 |
+ 0x94, 0x55, 0xd8, 0x5c, 0xb3, 0x6c, 0x46, 0xe0, 0x90, 0x19, 0x15, 0x26, 0xdf, 0xd5, 0x58, 0x46, |
|
2472 |
+ 0x85, 0x08, 0x12, 0x73, 0x04, 0xc9, 0xa1, 0xac, 0x97, 0x59, 0x4c, 0x67, 0x27, 0x2c, 0xb8, 0x20, |
|
2473 |
+ 0x22, 0x55, 0xf5, 0x7c, 0x03, 0xdb, 0x28, 0x95, 0xb4, 0x13, 0x12, 0x45, 0xaa, 0xa8, 0x6f, 0x60, |
|
2474 |
+ 0x0d, 0xc8, 0x0a, 0x4c, 0xa6, 0x89, 0xb8, 0xfe, 0xec, 0xc4, 0x5d, 0x57, 0xf9, 0x97, 0x83, 0xde, |
|
2475 |
+ 0x31, 0xec, 0xcc, 0xaf, 0xd4, 0xc4, 0xd0, 0x23, 0x68, 0x97, 0xab, 0x48, 0xdd, 0x9a, 0x4a, 0x90, |
|
2476 |
+ 0x25, 0x5b, 0x6f, 0x53, 0x79, 0xf7, 0xa1, 0x73, 0x22, 0x7c, 0x41, 0x56, 0xf8, 0xcb, 0xdb, 0x83, |
|
2477 |
+ 0x5e, 0x51, 0x75, 0x15, 0xa1, 0xae, 0x1b, 0xbe, 0xc8, 0x52, 0x43, 0x65, 0x20, 0xef, 0xcf, 0x0d, |
|
2478 |
+ 0x68, 0x9a, 0xb0, 0xce, 0x6b, 0x53, 0xad, 0xac, 0x4d, 0xff, 0x93, 0x12, 0x59, 0xc9, 0xaa, 0xe6, |
|
2479 |
+ 0x5c, 0x56, 0xfd, 0xbf, 0x5c, 0x96, 0xe5, 0xf2, 0xaf, 0x35, 0x68, 0x15, 0xdb, 0xfc, 0xb5, 0xdb, |
|
2480 |
+ 0x99, 0xf7, 0xa0, 0x95, 0xe8, 0x8d, 0x27, 0xba, 0xea, 0xb5, 0x0f, 0x7a, 0x46, 0x51, 0x5e, 0xe7, |
|
2481 |
+ 0x4a, 0x02, 0x2b, 0x7e, 0x1c, 0x3b, 0x7e, 0xac, 0x76, 0x65, 0xad, 0xd2, 0xae, 0x20, 0x70, 0x12, |
|
2482 |
+ 0x59, 0x4e, 0xd7, 0x55, 0x39, 0x55, 0x63, 0xbb, 0x41, 0x69, 0x56, 0x1a, 0x14, 0xef, 0x43, 0x68, |
|
2483 |
+ 0x1e, 0xfb, 0xc1, 0x84, 0xc6, 0x2a, 0x43, 0x83, 0xc4, 0x84, 0x69, 0x17, 0xab, 0xb1, 0x54, 0x32, |
|
2484 |
+ 0x25, 0x53, 0xc6, 0xaf, 0x4d, 0xed, 0x37, 0x90, 0x77, 0x01, 0x5d, 0x93, 0x06, 0x26, 0x99, 0x1e, |
|
2485 |
+ 0x02, 0x14, 0x2d, 0x46, 0x9e, 0x4b, 0x8b, 0x6d, 0x88, 0x45, 0x83, 0xf6, 0xa0, 0x39, 0xd5, 0x9a, |
|
2486 |
+ 0x4d, 0xd5, 0xcd, 0x7d, 0x60, 0xec, 0xc1, 0xf9, 0xb4, 0xf7, 0xeb, 0x1a, 0xec, 0xe8, 0x1e, 0xf3, |
|
2487 |
+ 0x95, 0x9d, 0xe4, 0xf2, 0xde, 0x45, 0xbb, 0xaf, 0x51, 0x71, 0xdf, 0x23, 0x68, 0x71, 0x92, 0xb2, |
|
2488 |
+ 0x8c, 0x07, 0x44, 0x7b, 0xb6, 0x7d, 0x70, 0x27, 0xcf, 0x24, 0xa5, 0x0b, 0x9b, 0x59, 0x5c, 0xd2, |
|
2489 |
+ 0x79, 0xff, 0x68, 0x42, 0xaf, 0x3a, 0x2b, 0x2b, 0xd6, 0x79, 0x74, 0x41, 0xd9, 0x0b, 0xdd, 0x1c, |
|
2490 |
+ 0xd7, 0x94, 0x9b, 0x6c, 0x94, 0xcc, 0xaa, 0x20, 0xc9, 0x4e, 0x26, 0x3e, 0x27, 0xa9, 0x71, 0x63, |
|
2491 |
+ 0x89, 0x30, 0xb3, 0x43, 0xc2, 0x29, 0xcb, 0x0f, 0xd3, 0x12, 0x21, 0xcb, 0x40, 0x90, 0x64, 0x5f, |
|
2492 |
+ 0x64, 0x4c, 0xf8, 0xca, 0x48, 0x07, 0x17, 0xb0, 0xea, 0x8a, 0x93, 0x2c, 0x25, 0xe2, 0x50, 0xee, |
|
2493 |
+ 0xda, 0x9a, 0xe9, 0x8a, 0x0b, 0x4c, 0x39, 0x7f, 0x4c, 0xa6, 0xa9, 0x49, 0x73, 0x0b, 0x23, 0x2d, |
|
2494 |
+ 0xd7, 0xbb, 0xf9, 0x5c, 0x06, 0xb5, 0x0a, 0x0c, 0x07, 0xdb, 0x28, 0x29, 0x41, 0x83, 0x27, 0x57, |
|
2495 |
+ 0x7e, 0xa2, 0xd2, 0xde, 0xc1, 0x16, 0x06, 0xbd, 0x07, 0x7d, 0x0d, 0x61, 0x92, 0x12, 0x7e, 0xe9, |
|
2496 |
+ 0xcb, 0x63, 0x5b, 0x95, 0x01, 0x07, 0x2f, 0x4e, 0x48, 0xea, 0x0b, 0xc2, 0x63, 0x12, 0x1d, 0x5b, |
|
2497 |
+ 0x5a, 0x41, 0x53, 0x2f, 0x4c, 0xa0, 0x03, 0xd8, 0xd6, 0xc8, 0xd3, 0xc3, 0xa1, 0xcd, 0xd0, 0x56, |
|
2498 |
+ 0x0c, 0x4b, 0xe7, 0x64, 0xa6, 0x2b, 0xc7, 0x3f, 0x27, 0xfe, 0x4b, 0xb3, 0x1f, 0x1d, 0x45, 0x3e, |
|
2499 |
+ 0x8f, 0x46, 0x4f, 0xa0, 0x6f, 0x6d, 0xd1, 0x33, 0x72, 0x49, 0x03, 0xe2, 0x76, 0x55, 0xd4, 0xde, |
|
2500 |
+ 0x36, 0x51, 0x60, 0x4f, 0xe1, 0x45, 0x6a, 0x74, 0x06, 0x03, 0x85, 0x3c, 0x9d, 0x70, 0x26, 0x44, |
|
2501 |
+ 0x44, 0x30, 0xf1, 0xc3, 0xa7, 0x49, 0x6a, 0x64, 0xf5, 0x94, 0xac, 0x3c, 0xa2, 0x72, 0x1a, 0x23, |
|
2502 |
+ 0xed, 0x06, 0x46, 0xf4, 0x02, 0xde, 0xa8, 0xcc, 0xbe, 0xe0, 0x54, 0x90, 0x52, 0xee, 0xe6, 0x4d, |
|
2503 |
+ 0x72, 0x6f, 0xe2, 0x5c, 0x10, 0x2c, 0xd5, 0x1e, 0xb1, 0x42, 0xf0, 0xd6, 0xeb, 0x0b, 0xae, 0x72, |
|
2504 |
+ 0xa2, 0x9f, 0xc1, 0x9b, 0x8b, 0x7a, 0x2d, 0xc9, 0xfd, 0x9b, 0x24, 0xdf, 0xc8, 0x2a, 0x93, 0x43, |
|
2505 |
+ 0xd6, 0x2f, 0xbd, 0xf3, 0x48, 0x27, 0x47, 0x81, 0x90, 0x01, 0x15, 0x24, 0x19, 0x26, 0x7e, 0x24, |
|
2506 |
+ 0x4b, 0x99, 0x49, 0xa1, 0xdb, 0x3a, 0xa0, 0x16, 0x26, 0xd0, 0x3e, 0x20, 0x0b, 0x89, 0x4d, 0x39, |
|
2507 |
+ 0xdc, 0xde, 0xad, 0xed, 0x35, 0xf0, 0x92, 0x19, 0xef, 0x23, 0xe8, 0x3e, 0x8d, 0x58, 0x70, 0x71, |
|
2508 |
+ 0xf4, 0xb9, 0x31, 0xa6, 0x72, 0xa1, 0x6f, 0x2c, 0xbd, 0xd0, 0x37, 0xcc, 0x85, 0xde, 0xfb, 0x0a, |
|
2509 |
+ 0x3a, 0x95, 0x60, 0xf9, 0x9e, 0xaa, 0x12, 0xb9, 0x28, 0x73, 0x4d, 0xdb, 0x36, 0x2e, 0xa9, 0xa8, |
|
2510 |
+ 0xc1, 0x36, 0xa1, 0xac, 0x5e, 0x57, 0x3a, 0x90, 0x75, 0xeb, 0x6c, 0x20, 0x99, 0x99, 0x51, 0x19, |
|
2511 |
+ 0xe4, 0xfa, 0x56, 0x66, 0x61, 0xbc, 0x9f, 0x43, 0xaf, 0xea, 0xe8, 0xff, 0xd8, 0x02, 0x04, 0x0e, |
|
2512 |
+ 0xf7, 0x05, 0xc9, 0x7b, 0x7f, 0x39, 0xf6, 0xee, 0xc1, 0xdd, 0x85, 0x7a, 0x6c, 0x1a, 0xcb, 0x6b, |
|
2513 |
+ 0xe8, 0x7e, 0x7c, 0x49, 0x62, 0x51, 0xdc, 0xfd, 0x1e, 0x43, 0xab, 0xf8, 0xa1, 0x62, 0x0a, 0xfd, |
|
2514 |
+ 0x60, 0x5f, 0xff, 0x72, 0xd9, 0xcf, 0x7f, 0xb9, 0xec, 0x9f, 0xe6, 0x14, 0xb8, 0x24, 0x96, 0x6b, |
|
2515 |
+ 0x4c, 0x05, 0xe3, 0x24, 0xfc, 0x3c, 0x8e, 0xae, 0xf3, 0xff, 0x14, 0x25, 0xc6, 0xd4, 0x7e, 0xa7, |
|
2516 |
+ 0x68, 0xbd, 0x7e, 0x5b, 0x83, 0x35, 0xa5, 0x7b, 0xe9, 0x1d, 0x46, 0x53, 0xd7, 0x8b, 0x93, 0xa2, |
|
2517 |
+ 0x7a, 0x2e, 0x74, 0x8b, 0x73, 0xc1, 0x9c, 0x20, 0x4e, 0x79, 0x82, 0x54, 0x56, 0xb0, 0xfe, 0x35, |
|
2518 |
+ 0x56, 0xe0, 0xfd, 0xa6, 0x0e, 0x9d, 0xcf, 0x88, 0xb8, 0x62, 0xfc, 0x42, 0x9e, 0x96, 0xe9, 0xd2, |
|
2519 |
+ 0xc6, 0xf8, 0x1e, 0x6c, 0xf0, 0xd9, 0xe8, 0xfc, 0x5a, 0x14, 0xa7, 0x43, 0x93, 0xcf, 0x9e, 0x4a, |
|
2520 |
+ 0x10, 0xbd, 0x05, 0xc0, 0x67, 0xa3, 0xa1, 0xaf, 0x9b, 0x61, 0x73, 0x38, 0xf0, 0x99, 0x41, 0xa0, |
|
2521 |
+ 0x37, 0xa0, 0x85, 0x67, 0x23, 0xc2, 0x39, 0xe3, 0x69, 0x7e, 0x3a, 0xe0, 0xd9, 0xc7, 0x0a, 0x96, |
|
2522 |
+ 0xbc, 0x78, 0x36, 0x0a, 0x39, 0x4b, 0x12, 0x12, 0xaa, 0xd3, 0xc1, 0xc1, 0x2d, 0x3c, 0x7b, 0xa6, |
|
2523 |
+ 0x11, 0x52, 0xeb, 0x69, 0xae, 0x75, 0x5d, 0x6b, 0x3d, 0x2d, 0xb5, 0x9e, 0xce, 0x46, 0x89, 0xd1, |
|
2524 |
+ 0xaa, 0x8f, 0x85, 0xd6, 0xa9, 0xad, 0xf5, 0xb4, 0xd0, 0xaa, 0xcf, 0x84, 0x8d, 0x53, 0x4b, 0xeb, |
|
2525 |
+ 0x69, 0xa9, 0xb5, 0x95, 0xf3, 0x1a, 0xad, 0xde, 0x1f, 0x6b, 0xb0, 0x71, 0x98, 0x64, 0x67, 0xa9, |
|
2526 |
+ 0x3f, 0x26, 0xe8, 0x01, 0xb4, 0x05, 0x13, 0x7e, 0x34, 0xca, 0x24, 0x68, 0x4e, 0x4e, 0x50, 0x28, |
|
2527 |
+ 0x4d, 0xf0, 0x36, 0x74, 0x12, 0xc2, 0x83, 0x24, 0x33, 0x14, 0xf5, 0xdd, 0x86, 0x3c, 0xa1, 0x34, |
|
2528 |
+ 0x4e, 0x93, 0xec, 0xc3, 0x6d, 0x35, 0x37, 0xa2, 0xf1, 0x48, 0x1f, 0x09, 0x53, 0x16, 0x12, 0xe3, |
|
2529 |
+ 0xaa, 0xbe, 0x9a, 0x3a, 0x8a, 0x3f, 0x2d, 0x26, 0xd0, 0xb7, 0xa1, 0x5f, 0xd0, 0xcb, 0x56, 0x59, |
|
2530 |
+ 0x51, 0x6b, 0xd7, 0x6d, 0x1a, 0xea, 0x33, 0x83, 0xf6, 0xbe, 0x2a, 0x72, 0x88, 0xc6, 0xe3, 0x67, |
|
2531 |
+ 0xbe, 0xf0, 0x65, 0x1b, 0x95, 0xa8, 0x62, 0x92, 0x1a, 0x6b, 0x73, 0x10, 0x7d, 0x07, 0xfa, 0xc2, |
|
2532 |
+ 0xe4, 0x5b, 0x38, 0xca, 0x69, 0xf4, 0x6e, 0x6e, 0x15, 0x13, 0x43, 0x43, 0xfc, 0x0d, 0xe8, 0x95, |
|
2533 |
+ 0xc4, 0xaa, 0x0a, 0x69, 0x7b, 0xbb, 0x05, 0x56, 0x46, 0x93, 0xf7, 0x7b, 0xed, 0x2c, 0x1d, 0x39, |
|
2534 |
+ 0xef, 0xa9, 0x36, 0xc1, 0x72, 0x55, 0xfb, 0x60, 0x33, 0x6f, 0xaf, 0x8c, 0x33, 0x54, 0x6b, 0xa0, |
|
2535 |
+ 0xdd, 0xf2, 0x43, 0xd8, 0x14, 0x85, 0xe9, 0xa3, 0xd0, 0x17, 0xbe, 0x49, 0xbd, 0xb9, 0x2a, 0x6c, |
|
2536 |
+ 0x16, 0x86, 0x7b, 0xa2, 0xba, 0xd0, 0xb7, 0xa1, 0xa3, 0xfb, 0x7e, 0xa3, 0x50, 0xdb, 0xd7, 0xd6, |
|
2537 |
+ 0x38, 0xa5, 0xc2, 0xfb, 0x08, 0x5a, 0x43, 0x1a, 0xa6, 0xda, 0x3a, 0x17, 0x9a, 0x41, 0xc6, 0x39, |
|
2538 |
+ 0x89, 0xf3, 0x06, 0x28, 0x07, 0x65, 0x79, 0x54, 0x3d, 0xb3, 0x71, 0x86, 0x06, 0x3c, 0x06, 0xa0, |
|
2539 |
+ 0xcf, 0x6d, 0xa5, 0x6d, 0x1b, 0xd6, 0xec, 0x10, 0xd0, 0x80, 0x8c, 0xb3, 0xa9, 0x3f, 0x2b, 0xb6, |
|
2540 |
+ 0x5e, 0xc5, 0xd9, 0xd4, 0x9f, 0xe9, 0x05, 0xba, 0xd0, 0x7c, 0xe9, 0xd3, 0x28, 0x30, 0xbf, 0x03, |
|
2541 |
+ 0x1d, 0x9c, 0x83, 0xa5, 0x42, 0xc7, 0x56, 0xf8, 0x87, 0x3a, 0xb4, 0xb5, 0x46, 0x6d, 0xf0, 0x36, |
|
2542 |
+ 0xac, 0x05, 0x7e, 0x30, 0x29, 0x54, 0x2a, 0x00, 0xbd, 0x9b, 0x1b, 0x52, 0xfd, 0x0d, 0x50, 0x9a, |
|
2543 |
+ 0x9a, 0xdb, 0xf6, 0x10, 0x20, 0xbd, 0xf2, 0x13, 0xcb, 0x3b, 0x4b, 0xa9, 0x5b, 0x92, 0x48, 0x1b, |
|
2544 |
+ 0xfc, 0x01, 0x74, 0x74, 0x7c, 0x1a, 0x1e, 0x67, 0x15, 0x4f, 0x5b, 0x93, 0x69, 0xae, 0x47, 0xf2, |
|
2545 |
+ 0xca, 0xe5, 0x0b, 0xdd, 0xe2, 0xb7, 0x0f, 0xde, 0xaa, 0x90, 0xab, 0x95, 0xec, 0xab, 0xef, 0xc7, |
|
2546 |
+ 0xb1, 0xe0, 0xd7, 0x58, 0xd3, 0x0e, 0x1e, 0x03, 0x94, 0x48, 0x59, 0xcf, 0x2e, 0xc8, 0x75, 0x7e, |
|
2547 |
+ 0xb5, 0xbc, 0x20, 0xd7, 0x72, 0xed, 0x97, 0x7e, 0x94, 0xe5, 0x4e, 0xd5, 0xc0, 0x0f, 0xea, 0x8f, |
|
2548 |
+ 0x6b, 0x5e, 0x00, 0x9b, 0x4f, 0xe5, 0x71, 0x6c, 0xb1, 0x57, 0x0e, 0x3d, 0x67, 0xe9, 0xa1, 0xe7, |
|
2549 |
+ 0xe4, 0x7f, 0xb1, 0x7b, 0x50, 0x67, 0x89, 0x69, 0xb3, 0xeb, 0x2c, 0x29, 0x15, 0x39, 0x96, 0x22, |
|
2550 |
+ 0xef, 0xef, 0x0e, 0x40, 0xa9, 0x05, 0x9d, 0xc0, 0x80, 0xb2, 0x91, 0xec, 0x12, 0x69, 0x40, 0x74, |
|
2551 |
+ 0x41, 0x1a, 0x71, 0x12, 0x64, 0x3c, 0xa5, 0x97, 0xc4, 0x5c, 0x24, 0x76, 0x8a, 0x63, 0xaa, 0x62, |
|
2552 |
+ 0x1c, 0xbe, 0x4b, 0xd9, 0x89, 0x66, 0x54, 0x95, 0x0b, 0xe7, 0x6c, 0xe8, 0x27, 0x70, 0xa7, 0x14, |
|
2553 |
+ 0x1a, 0x5a, 0xf2, 0xea, 0x37, 0xca, 0xbb, 0x5d, 0xc8, 0x0b, 0x4b, 0x59, 0x3f, 0x82, 0xdb, 0x94, |
|
2554 |
+ 0x8d, 0xbe, 0xcc, 0x48, 0x56, 0x91, 0xd4, 0xb8, 0x51, 0x52, 0x9f, 0xb2, 0x2f, 0x14, 0x47, 0x29, |
|
2555 |
+ 0xe7, 0x0b, 0xb8, 0x67, 0x2d, 0x54, 0xa6, 0xbd, 0x25, 0xcd, 0xb9, 0x51, 0xda, 0x4e, 0x61, 0x97, |
|
2556 |
+ 0x2c, 0x0c, 0xa5, 0xc8, 0x4f, 0x61, 0x87, 0xb2, 0xd1, 0x95, 0x4f, 0xc5, 0xbc, 0xbc, 0xb5, 0x57, |
|
2557 |
+ 0xad, 0xf3, 0x85, 0x4f, 0x45, 0x55, 0x98, 0x5e, 0xe7, 0x94, 0xf0, 0x71, 0x65, 0x9d, 0xeb, 0xaf, |
|
2558 |
+ 0x5a, 0xe7, 0xb1, 0xe2, 0x28, 0xe5, 0x3c, 0x85, 0x3e, 0x65, 0xf3, 0xf6, 0x34, 0x6f, 0x94, 0xb2, |
|
2559 |
+ 0x49, 0x59, 0xd5, 0x96, 0x43, 0xe8, 0xa7, 0x24, 0x10, 0x8c, 0xdb, 0xb1, 0xb0, 0x71, 0xa3, 0x8c, |
|
2560 |
+ 0x2d, 0xc3, 0x50, 0x08, 0xf1, 0xbe, 0x84, 0xce, 0x8f, 0xb3, 0x31, 0x11, 0xd1, 0x79, 0x91, 0xf3, |
|
2561 |
+ 0xff, 0xed, 0x32, 0xf3, 0xaf, 0x3a, 0xb4, 0x0f, 0xc7, 0x9c, 0x65, 0x49, 0xa5, 0x6a, 0xeb, 0x1c, |
|
2562 |
+ 0x5e, 0xa8, 0xda, 0x8a, 0x46, 0x55, 0x6d, 0x4d, 0xfd, 0x21, 0x74, 0xf4, 0xad, 0xc9, 0x30, 0xe8, |
|
2563 |
+ 0x2a, 0x84, 0x16, 0x93, 0x3e, 0xbf, 0xa5, 0x69, 0xb6, 0x03, 0x73, 0x03, 0x35, 0x5c, 0xd5, 0x6a, |
|
2564 |
+ 0x54, 0xba, 0x09, 0xc3, 0x79, 0x99, 0x75, 0x47, 0xd0, 0x9d, 0x68, 0xdf, 0x18, 0x2e, 0x1d, 0x80, |
|
2565 |
+ 0xef, 0xe4, 0xc6, 0x95, 0x6b, 0xd8, 0xb7, 0x7d, 0xa8, 0x5d, 0xdd, 0x99, 0xd8, 0x6e, 0x7d, 0x1f, |
|
2566 |
+ 0x40, 0xb6, 0xe4, 0xa3, 0xbc, 0x50, 0xd9, 0x0f, 0x10, 0xc5, 0x09, 0xa1, 0xdb, 0x76, 0x35, 0x1c, |
|
2567 |
+ 0x9c, 0x42, 0x7f, 0x41, 0xe6, 0x92, 0x32, 0xf5, 0x2d, 0xbb, 0x4c, 0x95, 0xd7, 0x32, 0x9b, 0xd5, |
|
2568 |
+ 0xae, 0x5d, 0x7f, 0xa9, 0xe9, 0x5f, 0x12, 0xe5, 0x3f, 0xe2, 0xc7, 0xd0, 0x8d, 0x75, 0xf3, 0x55, |
|
2569 |
+ 0x6c, 0x80, 0x7d, 0xbf, 0xb3, 0x1b, 0x33, 0xdc, 0x89, 0xed, 0x36, 0xed, 0x43, 0xe8, 0x04, 0xca, |
|
2570 |
+ 0x03, 0x4b, 0x37, 0xc2, 0x72, 0x0e, 0x6e, 0x07, 0xd6, 0x6e, 0x57, 0x1a, 0x45, 0xe7, 0xeb, 0x34, |
|
2571 |
+ 0x8a, 0xe6, 0xaf, 0xe2, 0xaa, 0x07, 0x93, 0x83, 0x7f, 0xae, 0x43, 0xe3, 0xc9, 0xf0, 0x08, 0x9d, |
|
2572 |
+ 0xc1, 0xd6, 0xfc, 0x7b, 0x23, 0xba, 0x6f, 0xcc, 0x5a, 0xf1, 0x46, 0x39, 0x78, 0xb0, 0x72, 0xde, |
|
2573 |
+ 0xb4, 0xec, 0xb7, 0x10, 0x86, 0xcd, 0xb9, 0xd7, 0x25, 0x94, 0x1f, 0x35, 0xcb, 0x5f, 0xf0, 0x06, |
|
2574 |
+ 0xf7, 0x57, 0x4d, 0xdb, 0x32, 0xe7, 0xee, 0x08, 0x85, 0xcc, 0xe5, 0xff, 0x72, 0x0a, 0x99, 0xab, |
|
2575 |
+ 0xae, 0x16, 0xb7, 0xd0, 0xf7, 0x61, 0x5d, 0xbf, 0x37, 0xa1, 0xfc, 0xe2, 0x52, 0x79, 0xc9, 0x1a, |
|
2576 |
+ 0xdc, 0x99, 0xc3, 0x16, 0x8c, 0xcf, 0xa1, 0x5b, 0x79, 0xa4, 0x44, 0x6f, 0x54, 0x74, 0x55, 0x9f, |
|
2577 |
+ 0xab, 0x06, 0x6f, 0x2e, 0x9f, 0x2c, 0xa4, 0x1d, 0x02, 0x94, 0x4f, 0x12, 0xc8, 0x35, 0xd4, 0x0b, |
|
2578 |
+ 0xcf, 0x5e, 0x83, 0x7b, 0x4b, 0x66, 0x0a, 0x21, 0x67, 0xb0, 0x35, 0xff, 0x3c, 0x80, 0xe6, 0xbc, |
|
2579 |
+ 0x3a, 0xff, 0x73, 0xbe, 0xd8, 0xca, 0x95, 0xef, 0x0a, 0x4a, 0xec, 0xfc, 0x4f, 0xff, 0x42, 0xec, |
|
2580 |
+ 0x8a, 0x27, 0x87, 0x42, 0xec, 0xca, 0xd7, 0x82, 0x5b, 0xe8, 0x73, 0xe8, 0x55, 0xff, 0xa2, 0xa3, |
|
2581 |
+ 0xdc, 0x49, 0x4b, 0x9f, 0x11, 0x06, 0x6f, 0xad, 0x98, 0x2d, 0x04, 0x7e, 0x00, 0x6b, 0xfa, 0xf7, |
|
2582 |
+ 0x78, 0x9e, 0x8e, 0xf6, 0x5f, 0xf5, 0xc1, 0x76, 0x15, 0x59, 0x70, 0x3d, 0x84, 0x75, 0x7d, 0xbb, |
|
2583 |
+ 0x2c, 0x02, 0xa0, 0x72, 0xd9, 0x1c, 0x74, 0x6c, 0xac, 0x77, 0xeb, 0x61, 0x2d, 0xd7, 0x93, 0x56, |
|
2584 |
+ 0xf4, 0xa4, 0xcb, 0xf4, 0x58, 0x9b, 0x73, 0xbe, 0xae, 0xd2, 0xf5, 0xd1, 0xbf, 0x03, 0x00, 0x00, |
|
2585 |
+ 0xff, 0xff, 0x8c, 0xbd, 0xc2, 0x0b, 0x2e, 0x20, 0x00, 0x00, |
|
2584 | 2586 |
} |
... | ... |
@@ -211,6 +211,8 @@ message UpdateResource { |
211 | 211 |
repeated ThrottleDevice blkioThrottleReadIopsDevice = 16; |
212 | 212 |
repeated ThrottleDevice blkioThrottleWriteIopsDevice = 17; |
213 | 213 |
uint64 pidsLimit = 18; |
214 |
+ uint64 cpuRealtimePeriod = 19; |
|
215 |
+ int64 cpuRealtimeRuntime = 20; |
|
214 | 216 |
} |
215 | 217 |
|
216 | 218 |
message BlockIODevice { |
... | ... |
@@ -434,7 +434,7 @@ func (c *container) Start(ctx context.Context, checkpointPath string, s Stdio) ( |
434 | 434 |
c: c, |
435 | 435 |
stdio: s, |
436 | 436 |
spec: spec, |
437 |
- processSpec: specs.ProcessSpec(spec.Process), |
|
437 |
+ processSpec: specs.ProcessSpec(*spec.Process), |
|
438 | 438 |
} |
439 | 439 |
p, err := newProcess(config) |
440 | 440 |
if err != nil { |
... | ... |
@@ -544,7 +544,6 @@ func (c *container) createCmd(ctx context.Context, pid string, cmd *exec.Cmd, p |
544 | 544 |
case err := <-ch: |
545 | 545 |
return err |
546 | 546 |
} |
547 |
- return nil |
|
548 | 547 |
} |
549 | 548 |
|
550 | 549 |
func hostIDFromMap(id uint32, mp []ocs.LinuxIDMapping) int { |
... | ... |
@@ -112,18 +112,20 @@ func i64Ptr(i int64) *int64 { return &i } |
112 | 112 |
func (c *container) UpdateResources(r *Resource) error { |
113 | 113 |
sr := ocs.LinuxResources{ |
114 | 114 |
Memory: &ocs.LinuxMemory{ |
115 |
- Limit: u64Ptr(uint64(r.Memory)), |
|
116 |
- Reservation: u64Ptr(uint64(r.MemoryReservation)), |
|
117 |
- Swap: u64Ptr(uint64(r.MemorySwap)), |
|
118 |
- Kernel: u64Ptr(uint64(r.KernelMemory)), |
|
119 |
- KernelTCP: u64Ptr(uint64(r.KernelTCPMemory)), |
|
115 |
+ Limit: i64Ptr(r.Memory), |
|
116 |
+ Reservation: i64Ptr(r.MemoryReservation), |
|
117 |
+ Swap: i64Ptr(r.MemorySwap), |
|
118 |
+ Kernel: i64Ptr(r.KernelMemory), |
|
119 |
+ KernelTCP: i64Ptr(r.KernelTCPMemory), |
|
120 | 120 |
}, |
121 | 121 |
CPU: &ocs.LinuxCPU{ |
122 |
- Shares: u64Ptr(uint64(r.CPUShares)), |
|
123 |
- Quota: i64Ptr(int64(r.CPUQuota)), |
|
124 |
- Period: u64Ptr(uint64(r.CPUPeriod)), |
|
125 |
- Cpus: r.CpusetCpus, |
|
126 |
- Mems: r.CpusetMems, |
|
122 |
+ Shares: u64Ptr(uint64(r.CPUShares)), |
|
123 |
+ Quota: i64Ptr(int64(r.CPUQuota)), |
|
124 |
+ Period: u64Ptr(uint64(r.CPUPeriod)), |
|
125 |
+ Cpus: r.CpusetCpus, |
|
126 |
+ Mems: r.CpusetMems, |
|
127 |
+ RealtimePeriod: u64Ptr(uint64(r.CPURealtimePeriod)), |
|
128 |
+ RealtimeRuntime: i64Ptr(int64(r.CPURealtimdRuntime)), |
|
127 | 129 |
}, |
128 | 130 |
BlockIO: &ocs.LinuxBlockIO{ |
129 | 131 |
Weight: &r.BlkioWeight, |
... | ... |
@@ -233,7 +233,7 @@ func (p *process) updateExitStatusFile(status uint32) (uint32, error) { |
233 | 233 |
p.stateLock.Lock() |
234 | 234 |
p.state = Stopped |
235 | 235 |
p.stateLock.Unlock() |
236 |
- err := ioutil.WriteFile(filepath.Join(p.root, ExitStatusFile), []byte(fmt.Sprintf("%u", status)), 0644) |
|
236 |
+ err := ioutil.WriteFile(filepath.Join(p.root, ExitStatusFile), []byte(fmt.Sprintf("%d", status)), 0644) |
|
237 | 237 |
return status, err |
238 | 238 |
} |
239 | 239 |
|
... | ... |
@@ -262,10 +262,27 @@ func (p *process) handleSigkilledShim(rst uint32, rerr error) (uint32, error) { |
262 | 262 |
} |
263 | 263 |
if ppid == "1" { |
264 | 264 |
logrus.Warnf("containerd: %s:%s shim died, killing associated process", p.container.id, p.id) |
265 |
+ // Before sending SIGKILL to container, we need to make sure |
|
266 |
+ // the container is not in Paused state. If the container is |
|
267 |
+ // Paused, the container will not response to any signal |
|
268 |
+ // we should Resume it after sending SIGKILL |
|
269 |
+ var ( |
|
270 |
+ s State |
|
271 |
+ err1 error |
|
272 |
+ ) |
|
273 |
+ if p.container != nil { |
|
274 |
+ s, err1 = p.container.Status() |
|
275 |
+ } |
|
276 |
+ |
|
265 | 277 |
unix.Kill(p.pid, syscall.SIGKILL) |
266 | 278 |
if err != nil && err != syscall.ESRCH { |
267 | 279 |
return UnknownStatus, fmt.Errorf("containerd: unable to SIGKILL %s:%s (pid %v): %v", p.container.id, p.id, p.pid, err) |
268 | 280 |
} |
281 |
+ if p.container != nil { |
|
282 |
+ if err1 == nil && s == Paused { |
|
283 |
+ p.container.Resume() |
|
284 |
+ } |
|
285 |
+ } |
|
269 | 286 |
|
270 | 287 |
// wait for the process to die |
271 | 288 |
for { |
... | ... |
@@ -283,14 +300,23 @@ func (p *process) handleSigkilledShim(rst uint32, rerr error) (uint32, error) { |
283 | 283 |
return rst, rerr |
284 | 284 |
} |
285 | 285 |
|
286 |
- // Possible that the shim was SIGKILLED |
|
287 |
- e := unix.Kill(p.cmd.Process.Pid, 0) |
|
288 |
- if e != syscall.ESRCH { |
|
289 |
- return rst, rerr |
|
286 |
+ // The shim was SIGKILLED |
|
287 |
+ // We should get the container state first |
|
288 |
+ // to make sure the container is not in |
|
289 |
+ // Pause state, if it's Paused, we should resume it |
|
290 |
+ // and it will exit immediately because shim will send sigkill to |
|
291 |
+ // container when died. |
|
292 |
+ s, err1 := p.container.Status() |
|
293 |
+ if err1 == nil && s == Paused { |
|
294 |
+ p.container.Resume() |
|
290 | 295 |
} |
291 | 296 |
|
292 | 297 |
// Ensure we got the shim ProcessState |
293 |
- <-p.cmdDoneCh |
|
298 |
+ select { |
|
299 |
+ case <-p.cmdDoneCh: |
|
300 |
+ case <-time.After(2 * time.Minute): |
|
301 |
+ return rst, fmt.Errorf("could not get the shim ProcessState within two minutes") |
|
302 |
+ } |
|
294 | 303 |
|
295 | 304 |
shimStatus := p.cmd.ProcessState.Sys().(syscall.WaitStatus) |
296 | 305 |
if shimStatus.Signaled() && shimStatus.Signal() == syscall.SIGKILL { |
... | ... |
@@ -84,18 +84,20 @@ type State string |
84 | 84 |
|
85 | 85 |
// Resource regroups the various container limits that can be updated |
86 | 86 |
type Resource struct { |
87 |
- CPUShares int64 |
|
88 |
- BlkioWeight uint16 |
|
89 |
- CPUPeriod int64 |
|
90 |
- CPUQuota int64 |
|
91 |
- CpusetCpus string |
|
92 |
- CpusetMems string |
|
93 |
- KernelMemory int64 |
|
94 |
- KernelTCPMemory int64 |
|
95 |
- Memory int64 |
|
96 |
- MemoryReservation int64 |
|
97 |
- MemorySwap int64 |
|
98 |
- PidsLimit int64 |
|
87 |
+ CPUShares int64 |
|
88 |
+ BlkioWeight uint16 |
|
89 |
+ CPUPeriod int64 |
|
90 |
+ CPUQuota int64 |
|
91 |
+ CpusetCpus string |
|
92 |
+ CpusetMems string |
|
93 |
+ KernelMemory int64 |
|
94 |
+ KernelTCPMemory int64 |
|
95 |
+ Memory int64 |
|
96 |
+ MemoryReservation int64 |
|
97 |
+ MemorySwap int64 |
|
98 |
+ PidsLimit int64 |
|
99 |
+ CPURealtimePeriod uint64 |
|
100 |
+ CPURealtimdRuntime int64 |
|
99 | 101 |
} |
100 | 102 |
|
101 | 103 |
// Possible container states |
13 | 13 |
new file mode 100755 |
... | ... |
@@ -0,0 +1,33 @@ |
0 |
+github.com/sirupsen/logrus v1.0.1 |
|
1 |
+github.com/cloudfoundry/gosigar 3ed7c74352dae6dc00bdc8c74045375352e3ec05 |
|
2 |
+github.com/urfave/cli 8ba6f23b6e36d03666a14bd9421f5e3efcb59aca |
|
3 |
+github.com/coreos/go-systemd 7b2428fec40033549c68f54e26e89e7ca9a9ce31 |
|
4 |
+github.com/cyberdelia/go-metrics-graphite 7e54b5c2aa6eaff4286c44129c3def899dff528c |
|
5 |
+github.com/docker/docker f577caff19d486d8d01443507d891cb1b0891cdc |
|
6 |
+github.com/docker/go-units 5d2041e26a699eaca682e2ea41c8f891e1060444 |
|
7 |
+github.com/godbus/dbus e2cf28118e66a6a63db46cf6088a35d2054d3bb0 |
|
8 |
+github.com/golang/glog 23def4e6c14b4da8ac2ed8007337bc5eb5007998 |
|
9 |
+github.com/golang/protobuf 8ee79997227bf9b34611aee7946ae64735e6fd93 |
|
10 |
+github.com/opencontainers/runc d40db12e72a40109dfcf28539f5ee0930d2f0277 |
|
11 |
+github.com/opencontainers/runtime-spec v1.0.0 |
|
12 |
+github.com/rcrowley/go-metrics eeba7bd0dd01ace6e690fa833b3f22aaec29af43 |
|
13 |
+github.com/satori/go.uuid f9ab0dce87d815821e221626b772e3475a0d2749 |
|
14 |
+github.com/syndtr/gocapability 2c00daeb6c3b45114c80ac44119e7b8801fdd852 |
|
15 |
+github.com/vishvananda/netlink adb0f53af689dd38f1443eba79489feaacf0b22e |
|
16 |
+github.com/Azure/go-ansiterm 70b2c90b260171e829f1ebd7c17f600c11858dbe |
|
17 |
+golang.org/x/net 991d3e32f76f19ee6d9caadb3a22eae8d23315f7 https://github.com/golang/net.git |
|
18 |
+golang.org/x/sys 0e0164865330d5cf1c00247be08330bf96e2f87c https://github.com/golang/sys |
|
19 |
+google.golang.org/grpc v1.0.4 https://github.com/grpc/grpc-go.git |
|
20 |
+github.com/seccomp/libseccomp-golang 1b506fc7c24eec5a3693cdcbed40d9c226cfc6a1 |
|
21 |
+github.com/tonistiigi/fifo b45391ebcd3d282404092c04a2b015b37df12383 |
|
22 |
+github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9 |
|
23 |
+ |
|
24 |
+github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3 |
|
25 |
+github.com/go-check/check a625211d932a2a643d0d17352095f03fb7774663 https://github.com/cpuguy83/check.git |
|
26 |
+ |
|
27 |
+github.com/containerd/console a3863895279f5104533fd999c1babf80faffd98c |
|
28 |
+github.com/containerd/go-runc 5fe4d8cb7fdc0fae5f5a7f4f1d65a565032401b2 |
|
29 |
+ |
|
30 |
+# dependencies of docker/pkg/listeners |
|
31 |
+github.com/docker/go-connections 3ede32e2033de7505e6500d6c868c2b9ed9f169d |
|
32 |
+github.com/Microsoft/go-winio v0.3.2 |
... | ... |
@@ -145,11 +145,33 @@ Your process field in the `config.json` should look like this below with `"termi |
145 | 145 |
"TERM=xterm" |
146 | 146 |
], |
147 | 147 |
"cwd": "/", |
148 |
- "capabilities": [ |
|
149 |
- "CAP_AUDIT_WRITE", |
|
150 |
- "CAP_KILL", |
|
151 |
- "CAP_NET_BIND_SERVICE" |
|
152 |
- ], |
|
148 |
+ "capabilities": { |
|
149 |
+ "bounding": [ |
|
150 |
+ "CAP_AUDIT_WRITE", |
|
151 |
+ "CAP_KILL", |
|
152 |
+ "CAP_NET_BIND_SERVICE" |
|
153 |
+ ], |
|
154 |
+ "effective": [ |
|
155 |
+ "CAP_AUDIT_WRITE", |
|
156 |
+ "CAP_KILL", |
|
157 |
+ "CAP_NET_BIND_SERVICE" |
|
158 |
+ ], |
|
159 |
+ "inheritable": [ |
|
160 |
+ "CAP_AUDIT_WRITE", |
|
161 |
+ "CAP_KILL", |
|
162 |
+ "CAP_NET_BIND_SERVICE" |
|
163 |
+ ], |
|
164 |
+ "permitted": [ |
|
165 |
+ "CAP_AUDIT_WRITE", |
|
166 |
+ "CAP_KILL", |
|
167 |
+ "CAP_NET_BIND_SERVICE" |
|
168 |
+ ], |
|
169 |
+ "ambient": [ |
|
170 |
+ "CAP_AUDIT_WRITE", |
|
171 |
+ "CAP_KILL", |
|
172 |
+ "CAP_NET_BIND_SERVICE" |
|
173 |
+ ] |
|
174 |
+ }, |
|
153 | 175 |
"rlimits": [ |
154 | 176 |
{ |
155 | 177 |
"type": "RLIMIT_NOFILE", |
... | ... |
@@ -161,7 +183,7 @@ Your process field in the `config.json` should look like this below with `"termi |
161 | 161 |
}, |
162 | 162 |
``` |
163 | 163 |
|
164 |
-Now we can go though the lifecycle operations in your shell. |
|
164 |
+Now we can go through the lifecycle operations in your shell. |
|
165 | 165 |
|
166 | 166 |
|
167 | 167 |
```bash |
... | ... |
@@ -56,25 +56,91 @@ Once you have an instance of the factory created we can create a configuration |
56 | 56 |
struct describing how the container is to be created. A sample would look similar to this: |
57 | 57 |
|
58 | 58 |
```go |
59 |
-defaultMountFlags := syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV |
|
59 |
+defaultMountFlags := unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV |
|
60 | 60 |
config := &configs.Config{ |
61 | 61 |
Rootfs: "/your/path/to/rootfs", |
62 |
- Capabilities: []string{ |
|
63 |
- "CAP_CHOWN", |
|
64 |
- "CAP_DAC_OVERRIDE", |
|
65 |
- "CAP_FSETID", |
|
66 |
- "CAP_FOWNER", |
|
67 |
- "CAP_MKNOD", |
|
68 |
- "CAP_NET_RAW", |
|
69 |
- "CAP_SETGID", |
|
70 |
- "CAP_SETUID", |
|
71 |
- "CAP_SETFCAP", |
|
72 |
- "CAP_SETPCAP", |
|
73 |
- "CAP_NET_BIND_SERVICE", |
|
74 |
- "CAP_SYS_CHROOT", |
|
75 |
- "CAP_KILL", |
|
76 |
- "CAP_AUDIT_WRITE", |
|
77 |
- }, |
|
62 |
+ Capabilities: &configs.Capabilities{ |
|
63 |
+ Bounding: []string{ |
|
64 |
+ "CAP_CHOWN", |
|
65 |
+ "CAP_DAC_OVERRIDE", |
|
66 |
+ "CAP_FSETID", |
|
67 |
+ "CAP_FOWNER", |
|
68 |
+ "CAP_MKNOD", |
|
69 |
+ "CAP_NET_RAW", |
|
70 |
+ "CAP_SETGID", |
|
71 |
+ "CAP_SETUID", |
|
72 |
+ "CAP_SETFCAP", |
|
73 |
+ "CAP_SETPCAP", |
|
74 |
+ "CAP_NET_BIND_SERVICE", |
|
75 |
+ "CAP_SYS_CHROOT", |
|
76 |
+ "CAP_KILL", |
|
77 |
+ "CAP_AUDIT_WRITE", |
|
78 |
+ }, |
|
79 |
+ Effective: []string{ |
|
80 |
+ "CAP_CHOWN", |
|
81 |
+ "CAP_DAC_OVERRIDE", |
|
82 |
+ "CAP_FSETID", |
|
83 |
+ "CAP_FOWNER", |
|
84 |
+ "CAP_MKNOD", |
|
85 |
+ "CAP_NET_RAW", |
|
86 |
+ "CAP_SETGID", |
|
87 |
+ "CAP_SETUID", |
|
88 |
+ "CAP_SETFCAP", |
|
89 |
+ "CAP_SETPCAP", |
|
90 |
+ "CAP_NET_BIND_SERVICE", |
|
91 |
+ "CAP_SYS_CHROOT", |
|
92 |
+ "CAP_KILL", |
|
93 |
+ "CAP_AUDIT_WRITE", |
|
94 |
+ }, |
|
95 |
+ Inheritable: []string{ |
|
96 |
+ "CAP_CHOWN", |
|
97 |
+ "CAP_DAC_OVERRIDE", |
|
98 |
+ "CAP_FSETID", |
|
99 |
+ "CAP_FOWNER", |
|
100 |
+ "CAP_MKNOD", |
|
101 |
+ "CAP_NET_RAW", |
|
102 |
+ "CAP_SETGID", |
|
103 |
+ "CAP_SETUID", |
|
104 |
+ "CAP_SETFCAP", |
|
105 |
+ "CAP_SETPCAP", |
|
106 |
+ "CAP_NET_BIND_SERVICE", |
|
107 |
+ "CAP_SYS_CHROOT", |
|
108 |
+ "CAP_KILL", |
|
109 |
+ "CAP_AUDIT_WRITE", |
|
110 |
+ }, |
|
111 |
+ Permitted: []string{ |
|
112 |
+ "CAP_CHOWN", |
|
113 |
+ "CAP_DAC_OVERRIDE", |
|
114 |
+ "CAP_FSETID", |
|
115 |
+ "CAP_FOWNER", |
|
116 |
+ "CAP_MKNOD", |
|
117 |
+ "CAP_NET_RAW", |
|
118 |
+ "CAP_SETGID", |
|
119 |
+ "CAP_SETUID", |
|
120 |
+ "CAP_SETFCAP", |
|
121 |
+ "CAP_SETPCAP", |
|
122 |
+ "CAP_NET_BIND_SERVICE", |
|
123 |
+ "CAP_SYS_CHROOT", |
|
124 |
+ "CAP_KILL", |
|
125 |
+ "CAP_AUDIT_WRITE", |
|
126 |
+ }, |
|
127 |
+ Ambient: []string{ |
|
128 |
+ "CAP_CHOWN", |
|
129 |
+ "CAP_DAC_OVERRIDE", |
|
130 |
+ "CAP_FSETID", |
|
131 |
+ "CAP_FOWNER", |
|
132 |
+ "CAP_MKNOD", |
|
133 |
+ "CAP_NET_RAW", |
|
134 |
+ "CAP_SETGID", |
|
135 |
+ "CAP_SETUID", |
|
136 |
+ "CAP_SETFCAP", |
|
137 |
+ "CAP_SETPCAP", |
|
138 |
+ "CAP_NET_BIND_SERVICE", |
|
139 |
+ "CAP_SYS_CHROOT", |
|
140 |
+ "CAP_KILL", |
|
141 |
+ "CAP_AUDIT_WRITE", |
|
142 |
+ }, |
|
143 |
+ }, |
|
78 | 144 |
Namespaces: configs.Namespaces([]configs.Namespace{ |
79 | 145 |
{Type: configs.NEWNS}, |
80 | 146 |
{Type: configs.NEWUTS}, |
... | ... |
@@ -112,14 +178,14 @@ config := &configs.Config{ |
112 | 112 |
Source: "tmpfs", |
113 | 113 |
Destination: "/dev", |
114 | 114 |
Device: "tmpfs", |
115 |
- Flags: syscall.MS_NOSUID | syscall.MS_STRICTATIME, |
|
115 |
+ Flags: unix.MS_NOSUID | unix.MS_STRICTATIME, |
|
116 | 116 |
Data: "mode=755", |
117 | 117 |
}, |
118 | 118 |
{ |
119 | 119 |
Source: "devpts", |
120 | 120 |
Destination: "/dev/pts", |
121 | 121 |
Device: "devpts", |
122 |
- Flags: syscall.MS_NOSUID | syscall.MS_NOEXEC, |
|
122 |
+ Flags: unix.MS_NOSUID | unix.MS_NOEXEC, |
|
123 | 123 |
Data: "newinstance,ptmxmode=0666,mode=0620,gid=5", |
124 | 124 |
}, |
125 | 125 |
{ |
... | ... |
@@ -139,7 +205,7 @@ config := &configs.Config{ |
139 | 139 |
Source: "sysfs", |
140 | 140 |
Destination: "/sys", |
141 | 141 |
Device: "sysfs", |
142 |
- Flags: defaultMountFlags | syscall.MS_RDONLY, |
|
142 |
+ Flags: defaultMountFlags | unix.MS_RDONLY, |
|
143 | 143 |
}, |
144 | 144 |
}, |
145 | 145 |
UidMappings: []configs.IDMap{ |
... | ... |
@@ -165,7 +231,7 @@ config := &configs.Config{ |
165 | 165 |
}, |
166 | 166 |
Rlimits: []configs.Rlimit{ |
167 | 167 |
{ |
168 |
- Type: syscall.RLIMIT_NOFILE, |
|
168 |
+ Type: unix.RLIMIT_NOFILE, |
|
169 | 169 |
Hard: uint64(1025), |
170 | 170 |
Soft: uint64(1025), |
171 | 171 |
}, |
... | ... |
@@ -51,6 +51,8 @@ type MemoryStats struct { |
51 | 51 |
KernelUsage MemoryData `json:"kernel_usage,omitempty"` |
52 | 52 |
// usage of kernel TCP memory |
53 | 53 |
KernelTCPUsage MemoryData `json:"kernel_tcp_usage,omitempty"` |
54 |
+ // if true, memory usage is accounted for throughout a hierarchy of cgroups. |
|
55 |
+ UseHierarchy bool `json:"use_hierarchy"` |
|
54 | 56 |
|
55 | 57 |
Stats map[string]uint64 `json:"stats,omitempty"` |
56 | 58 |
} |
... | ... |
@@ -66,6 +66,21 @@ func isSubsystemAvailable(subsystem string) bool { |
66 | 66 |
return avail |
67 | 67 |
} |
68 | 68 |
|
69 |
+func GetClosestMountpointAncestor(dir, mountinfo string) string { |
|
70 |
+ deepestMountPoint := "" |
|
71 |
+ for _, mountInfoEntry := range strings.Split(mountinfo, "\n") { |
|
72 |
+ mountInfoParts := strings.Fields(mountInfoEntry) |
|
73 |
+ if len(mountInfoParts) < 5 { |
|
74 |
+ continue |
|
75 |
+ } |
|
76 |
+ mountPoint := mountInfoParts[4] |
|
77 |
+ if strings.HasPrefix(mountPoint, deepestMountPoint) && strings.HasPrefix(dir, mountPoint) { |
|
78 |
+ deepestMountPoint = mountPoint |
|
79 |
+ } |
|
80 |
+ } |
|
81 |
+ return deepestMountPoint |
|
82 |
+} |
|
83 |
+ |
|
69 | 84 |
func FindCgroupMountpointDir() (string, error) { |
70 | 85 |
f, err := os.Open("/proc/self/mountinfo") |
71 | 86 |
if err != nil { |
72 | 87 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,122 @@ |
0 |
+package configs |
|
1 |
+ |
|
2 |
+type FreezerState string |
|
3 |
+ |
|
4 |
+const ( |
|
5 |
+ Undefined FreezerState = "" |
|
6 |
+ Frozen FreezerState = "FROZEN" |
|
7 |
+ Thawed FreezerState = "THAWED" |
|
8 |
+) |
|
9 |
+ |
|
10 |
+type Cgroup struct { |
|
11 |
+ // Deprecated, use Path instead |
|
12 |
+ Name string `json:"name,omitempty"` |
|
13 |
+ |
|
14 |
+ // name of parent of cgroup or slice |
|
15 |
+ // Deprecated, use Path instead |
|
16 |
+ Parent string `json:"parent,omitempty"` |
|
17 |
+ |
|
18 |
+ // Path specifies the path to cgroups that are created and/or joined by the container. |
|
19 |
+ // The path is assumed to be relative to the host system cgroup mountpoint. |
|
20 |
+ Path string `json:"path"` |
|
21 |
+ |
|
22 |
+ // ScopePrefix describes prefix for the scope name |
|
23 |
+ ScopePrefix string `json:"scope_prefix"` |
|
24 |
+ |
|
25 |
+ // Paths represent the absolute cgroups paths to join. |
|
26 |
+ // This takes precedence over Path. |
|
27 |
+ Paths map[string]string |
|
28 |
+ |
|
29 |
+ // Resources contains various cgroups settings to apply |
|
30 |
+ *Resources |
|
31 |
+} |
|
32 |
+ |
|
33 |
+type Resources struct { |
|
34 |
+ // If this is true allow access to any kind of device within the container. If false, allow access only to devices explicitly listed in the allowed_devices list. |
|
35 |
+ // Deprecated |
|
36 |
+ AllowAllDevices *bool `json:"allow_all_devices,omitempty"` |
|
37 |
+ // Deprecated |
|
38 |
+ AllowedDevices []*Device `json:"allowed_devices,omitempty"` |
|
39 |
+ // Deprecated |
|
40 |
+ DeniedDevices []*Device `json:"denied_devices,omitempty"` |
|
41 |
+ |
|
42 |
+ Devices []*Device `json:"devices"` |
|
43 |
+ |
|
44 |
+ // Memory limit (in bytes) |
|
45 |
+ Memory int64 `json:"memory"` |
|
46 |
+ |
|
47 |
+ // Memory reservation or soft_limit (in bytes) |
|
48 |
+ MemoryReservation int64 `json:"memory_reservation"` |
|
49 |
+ |
|
50 |
+ // Total memory usage (memory + swap); set `-1` to enable unlimited swap |
|
51 |
+ MemorySwap int64 `json:"memory_swap"` |
|
52 |
+ |
|
53 |
+ // Kernel memory limit (in bytes) |
|
54 |
+ KernelMemory int64 `json:"kernel_memory"` |
|
55 |
+ |
|
56 |
+ // Kernel memory limit for TCP use (in bytes) |
|
57 |
+ KernelMemoryTCP int64 `json:"kernel_memory_tcp"` |
|
58 |
+ |
|
59 |
+ // CPU shares (relative weight vs. other containers) |
|
60 |
+ CpuShares uint64 `json:"cpu_shares"` |
|
61 |
+ |
|
62 |
+ // CPU hardcap limit (in usecs). Allowed cpu time in a given period. |
|
63 |
+ CpuQuota int64 `json:"cpu_quota"` |
|
64 |
+ |
|
65 |
+ // CPU period to be used for hardcapping (in usecs). 0 to use system default. |
|
66 |
+ CpuPeriod uint64 `json:"cpu_period"` |
|
67 |
+ |
|
68 |
+ // How many time CPU will use in realtime scheduling (in usecs). |
|
69 |
+ CpuRtRuntime int64 `json:"cpu_rt_quota"` |
|
70 |
+ |
|
71 |
+ // CPU period to be used for realtime scheduling (in usecs). |
|
72 |
+ CpuRtPeriod uint64 `json:"cpu_rt_period"` |
|
73 |
+ |
|
74 |
+ // CPU to use |
|
75 |
+ CpusetCpus string `json:"cpuset_cpus"` |
|
76 |
+ |
|
77 |
+ // MEM to use |
|
78 |
+ CpusetMems string `json:"cpuset_mems"` |
|
79 |
+ |
|
80 |
+ // Process limit; set <= `0' to disable limit. |
|
81 |
+ PidsLimit int64 `json:"pids_limit"` |
|
82 |
+ |
|
83 |
+ // Specifies per cgroup weight, range is from 10 to 1000. |
|
84 |
+ BlkioWeight uint16 `json:"blkio_weight"` |
|
85 |
+ |
|
86 |
+ // Specifies tasks' weight in the given cgroup while competing with the cgroup's child cgroups, range is from 10 to 1000, cfq scheduler only |
|
87 |
+ BlkioLeafWeight uint16 `json:"blkio_leaf_weight"` |
|
88 |
+ |
|
89 |
+ // Weight per cgroup per device, can override BlkioWeight. |
|
90 |
+ BlkioWeightDevice []*WeightDevice `json:"blkio_weight_device"` |
|
91 |
+ |
|
92 |
+ // IO read rate limit per cgroup per device, bytes per second. |
|
93 |
+ BlkioThrottleReadBpsDevice []*ThrottleDevice `json:"blkio_throttle_read_bps_device"` |
|
94 |
+ |
|
95 |
+ // IO write rate limit per cgroup per device, bytes per second. |
|
96 |
+ BlkioThrottleWriteBpsDevice []*ThrottleDevice `json:"blkio_throttle_write_bps_device"` |
|
97 |
+ |
|
98 |
+ // IO read rate limit per cgroup per device, IO per second. |
|
99 |
+ BlkioThrottleReadIOPSDevice []*ThrottleDevice `json:"blkio_throttle_read_iops_device"` |
|
100 |
+ |
|
101 |
+ // IO write rate limit per cgroup per device, IO per second. |
|
102 |
+ BlkioThrottleWriteIOPSDevice []*ThrottleDevice `json:"blkio_throttle_write_iops_device"` |
|
103 |
+ |
|
104 |
+ // set the freeze value for the process |
|
105 |
+ Freezer FreezerState `json:"freezer"` |
|
106 |
+ |
|
107 |
+ // Hugetlb limit (in bytes) |
|
108 |
+ HugetlbLimit []*HugepageLimit `json:"hugetlb_limit"` |
|
109 |
+ |
|
110 |
+ // Whether to disable OOM Killer |
|
111 |
+ OomKillDisable bool `json:"oom_kill_disable"` |
|
112 |
+ |
|
113 |
+ // Tuning swappiness behaviour per cgroup |
|
114 |
+ MemorySwappiness *uint64 `json:"memory_swappiness"` |
|
115 |
+ |
|
116 |
+ // Set priority of network traffic for container |
|
117 |
+ NetPrioIfpriomap []*IfPrioMap `json:"net_prio_ifpriomap"` |
|
118 |
+ |
|
119 |
+ // Set class identifier for container's network packets |
|
120 |
+ NetClsClassid uint32 `json:"net_cls_classid_u"` |
|
121 |
+} |
0 | 122 |
deleted file mode 100644 |
... | ... |
@@ -1,124 +0,0 @@ |
1 |
-// +build linux freebsd |
|
2 |
- |
|
3 |
-package configs |
|
4 |
- |
|
5 |
-type FreezerState string |
|
6 |
- |
|
7 |
-const ( |
|
8 |
- Undefined FreezerState = "" |
|
9 |
- Frozen FreezerState = "FROZEN" |
|
10 |
- Thawed FreezerState = "THAWED" |
|
11 |
-) |
|
12 |
- |
|
13 |
-type Cgroup struct { |
|
14 |
- // Deprecated, use Path instead |
|
15 |
- Name string `json:"name,omitempty"` |
|
16 |
- |
|
17 |
- // name of parent of cgroup or slice |
|
18 |
- // Deprecated, use Path instead |
|
19 |
- Parent string `json:"parent,omitempty"` |
|
20 |
- |
|
21 |
- // Path specifies the path to cgroups that are created and/or joined by the container. |
|
22 |
- // The path is assumed to be relative to the host system cgroup mountpoint. |
|
23 |
- Path string `json:"path"` |
|
24 |
- |
|
25 |
- // ScopePrefix describes prefix for the scope name |
|
26 |
- ScopePrefix string `json:"scope_prefix"` |
|
27 |
- |
|
28 |
- // Paths represent the absolute cgroups paths to join. |
|
29 |
- // This takes precedence over Path. |
|
30 |
- Paths map[string]string |
|
31 |
- |
|
32 |
- // Resources contains various cgroups settings to apply |
|
33 |
- *Resources |
|
34 |
-} |
|
35 |
- |
|
36 |
-type Resources struct { |
|
37 |
- // If this is true allow access to any kind of device within the container. If false, allow access only to devices explicitly listed in the allowed_devices list. |
|
38 |
- // Deprecated |
|
39 |
- AllowAllDevices *bool `json:"allow_all_devices,omitempty"` |
|
40 |
- // Deprecated |
|
41 |
- AllowedDevices []*Device `json:"allowed_devices,omitempty"` |
|
42 |
- // Deprecated |
|
43 |
- DeniedDevices []*Device `json:"denied_devices,omitempty"` |
|
44 |
- |
|
45 |
- Devices []*Device `json:"devices"` |
|
46 |
- |
|
47 |
- // Memory limit (in bytes) |
|
48 |
- Memory uint64 `json:"memory"` |
|
49 |
- |
|
50 |
- // Memory reservation or soft_limit (in bytes) |
|
51 |
- MemoryReservation uint64 `json:"memory_reservation"` |
|
52 |
- |
|
53 |
- // Total memory usage (memory + swap); set `-1` to enable unlimited swap |
|
54 |
- MemorySwap uint64 `json:"memory_swap"` |
|
55 |
- |
|
56 |
- // Kernel memory limit (in bytes) |
|
57 |
- KernelMemory uint64 `json:"kernel_memory"` |
|
58 |
- |
|
59 |
- // Kernel memory limit for TCP use (in bytes) |
|
60 |
- KernelMemoryTCP uint64 `json:"kernel_memory_tcp"` |
|
61 |
- |
|
62 |
- // CPU shares (relative weight vs. other containers) |
|
63 |
- CpuShares uint64 `json:"cpu_shares"` |
|
64 |
- |
|
65 |
- // CPU hardcap limit (in usecs). Allowed cpu time in a given period. |
|
66 |
- CpuQuota int64 `json:"cpu_quota"` |
|
67 |
- |
|
68 |
- // CPU period to be used for hardcapping (in usecs). 0 to use system default. |
|
69 |
- CpuPeriod uint64 `json:"cpu_period"` |
|
70 |
- |
|
71 |
- // How many time CPU will use in realtime scheduling (in usecs). |
|
72 |
- CpuRtRuntime int64 `json:"cpu_rt_quota"` |
|
73 |
- |
|
74 |
- // CPU period to be used for realtime scheduling (in usecs). |
|
75 |
- CpuRtPeriod uint64 `json:"cpu_rt_period"` |
|
76 |
- |
|
77 |
- // CPU to use |
|
78 |
- CpusetCpus string `json:"cpuset_cpus"` |
|
79 |
- |
|
80 |
- // MEM to use |
|
81 |
- CpusetMems string `json:"cpuset_mems"` |
|
82 |
- |
|
83 |
- // Process limit; set <= `0' to disable limit. |
|
84 |
- PidsLimit int64 `json:"pids_limit"` |
|
85 |
- |
|
86 |
- // Specifies per cgroup weight, range is from 10 to 1000. |
|
87 |
- BlkioWeight uint16 `json:"blkio_weight"` |
|
88 |
- |
|
89 |
- // Specifies tasks' weight in the given cgroup while competing with the cgroup's child cgroups, range is from 10 to 1000, cfq scheduler only |
|
90 |
- BlkioLeafWeight uint16 `json:"blkio_leaf_weight"` |
|
91 |
- |
|
92 |
- // Weight per cgroup per device, can override BlkioWeight. |
|
93 |
- BlkioWeightDevice []*WeightDevice `json:"blkio_weight_device"` |
|
94 |
- |
|
95 |
- // IO read rate limit per cgroup per device, bytes per second. |
|
96 |
- BlkioThrottleReadBpsDevice []*ThrottleDevice `json:"blkio_throttle_read_bps_device"` |
|
97 |
- |
|
98 |
- // IO write rate limit per cgroup per device, bytes per second. |
|
99 |
- BlkioThrottleWriteBpsDevice []*ThrottleDevice `json:"blkio_throttle_write_bps_device"` |
|
100 |
- |
|
101 |
- // IO read rate limit per cgroup per device, IO per second. |
|
102 |
- BlkioThrottleReadIOPSDevice []*ThrottleDevice `json:"blkio_throttle_read_iops_device"` |
|
103 |
- |
|
104 |
- // IO write rate limit per cgroup per device, IO per second. |
|
105 |
- BlkioThrottleWriteIOPSDevice []*ThrottleDevice `json:"blkio_throttle_write_iops_device"` |
|
106 |
- |
|
107 |
- // set the freeze value for the process |
|
108 |
- Freezer FreezerState `json:"freezer"` |
|
109 |
- |
|
110 |
- // Hugetlb limit (in bytes) |
|
111 |
- HugetlbLimit []*HugepageLimit `json:"hugetlb_limit"` |
|
112 |
- |
|
113 |
- // Whether to disable OOM Killer |
|
114 |
- OomKillDisable bool `json:"oom_kill_disable"` |
|
115 |
- |
|
116 |
- // Tuning swappiness behaviour per cgroup |
|
117 |
- MemorySwappiness *uint64 `json:"memory_swappiness"` |
|
118 |
- |
|
119 |
- // Set priority of network traffic for container |
|
120 |
- NetPrioIfpriomap []*IfPrioMap `json:"net_prio_ifpriomap"` |
|
121 |
- |
|
122 |
- // Set class identifier for container's network packets |
|
123 |
- NetClsClassid uint32 `json:"net_cls_classid_u"` |
|
124 |
-} |
14 | 15 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,61 @@ |
0 |
+package configs |
|
1 |
+ |
|
2 |
+import "fmt" |
|
3 |
+ |
|
4 |
+// HostUID gets the translated uid for the process on host which could be |
|
5 |
+// different when user namespaces are enabled. |
|
6 |
+func (c Config) HostUID(containerId int) (int, error) { |
|
7 |
+ if c.Namespaces.Contains(NEWUSER) { |
|
8 |
+ if c.UidMappings == nil { |
|
9 |
+ return -1, fmt.Errorf("User namespaces enabled, but no uid mappings found.") |
|
10 |
+ } |
|
11 |
+ id, found := c.hostIDFromMapping(containerId, c.UidMappings) |
|
12 |
+ if !found { |
|
13 |
+ return -1, fmt.Errorf("User namespaces enabled, but no user mapping found.") |
|
14 |
+ } |
|
15 |
+ return id, nil |
|
16 |
+ } |
|
17 |
+ // Return unchanged id. |
|
18 |
+ return containerId, nil |
|
19 |
+} |
|
20 |
+ |
|
21 |
+// HostRootUID gets the root uid for the process on host which could be non-zero |
|
22 |
+// when user namespaces are enabled. |
|
23 |
+func (c Config) HostRootUID() (int, error) { |
|
24 |
+ return c.HostUID(0) |
|
25 |
+} |
|
26 |
+ |
|
27 |
+// HostGID gets the translated gid for the process on host which could be |
|
28 |
+// different when user namespaces are enabled. |
|
29 |
+func (c Config) HostGID(containerId int) (int, error) { |
|
30 |
+ if c.Namespaces.Contains(NEWUSER) { |
|
31 |
+ if c.GidMappings == nil { |
|
32 |
+ return -1, fmt.Errorf("User namespaces enabled, but no gid mappings found.") |
|
33 |
+ } |
|
34 |
+ id, found := c.hostIDFromMapping(containerId, c.GidMappings) |
|
35 |
+ if !found { |
|
36 |
+ return -1, fmt.Errorf("User namespaces enabled, but no group mapping found.") |
|
37 |
+ } |
|
38 |
+ return id, nil |
|
39 |
+ } |
|
40 |
+ // Return unchanged id. |
|
41 |
+ return containerId, nil |
|
42 |
+} |
|
43 |
+ |
|
44 |
+// HostRootGID gets the root gid for the process on host which could be non-zero |
|
45 |
+// when user namespaces are enabled. |
|
46 |
+func (c Config) HostRootGID() (int, error) { |
|
47 |
+ return c.HostGID(0) |
|
48 |
+} |
|
49 |
+ |
|
50 |
+// Utility function that gets a host ID for a container ID from user namespace map |
|
51 |
+// if that ID is present in the map. |
|
52 |
+func (c Config) hostIDFromMapping(containerID int, uMap []IDMap) (int, bool) { |
|
53 |
+ for _, m := range uMap { |
|
54 |
+ if (containerID >= m.ContainerID) && (containerID <= (m.ContainerID + m.Size - 1)) { |
|
55 |
+ hostID := m.HostID + (containerID - m.ContainerID) |
|
56 |
+ return hostID, true |
|
57 |
+ } |
|
58 |
+ } |
|
59 |
+ return -1, false |
|
60 |
+} |
0 | 61 |
deleted file mode 100644 |
... | ... |
@@ -1,63 +0,0 @@ |
1 |
-// +build freebsd linux |
|
2 |
- |
|
3 |
-package configs |
|
4 |
- |
|
5 |
-import "fmt" |
|
6 |
- |
|
7 |
-// HostUID gets the translated uid for the process on host which could be |
|
8 |
-// different when user namespaces are enabled. |
|
9 |
-func (c Config) HostUID(containerId int) (int, error) { |
|
10 |
- if c.Namespaces.Contains(NEWUSER) { |
|
11 |
- if c.UidMappings == nil { |
|
12 |
- return -1, fmt.Errorf("User namespaces enabled, but no uid mappings found.") |
|
13 |
- } |
|
14 |
- id, found := c.hostIDFromMapping(containerId, c.UidMappings) |
|
15 |
- if !found { |
|
16 |
- return -1, fmt.Errorf("User namespaces enabled, but no user mapping found.") |
|
17 |
- } |
|
18 |
- return id, nil |
|
19 |
- } |
|
20 |
- // Return unchanged id. |
|
21 |
- return containerId, nil |
|
22 |
-} |
|
23 |
- |
|
24 |
-// HostRootUID gets the root uid for the process on host which could be non-zero |
|
25 |
-// when user namespaces are enabled. |
|
26 |
-func (c Config) HostRootUID() (int, error) { |
|
27 |
- return c.HostUID(0) |
|
28 |
-} |
|
29 |
- |
|
30 |
-// HostGID gets the translated gid for the process on host which could be |
|
31 |
-// different when user namespaces are enabled. |
|
32 |
-func (c Config) HostGID(containerId int) (int, error) { |
|
33 |
- if c.Namespaces.Contains(NEWUSER) { |
|
34 |
- if c.GidMappings == nil { |
|
35 |
- return -1, fmt.Errorf("User namespaces enabled, but no gid mappings found.") |
|
36 |
- } |
|
37 |
- id, found := c.hostIDFromMapping(containerId, c.GidMappings) |
|
38 |
- if !found { |
|
39 |
- return -1, fmt.Errorf("User namespaces enabled, but no group mapping found.") |
|
40 |
- } |
|
41 |
- return id, nil |
|
42 |
- } |
|
43 |
- // Return unchanged id. |
|
44 |
- return containerId, nil |
|
45 |
-} |
|
46 |
- |
|
47 |
-// HostRootGID gets the root gid for the process on host which could be non-zero |
|
48 |
-// when user namespaces are enabled. |
|
49 |
-func (c Config) HostRootGID() (int, error) { |
|
50 |
- return c.HostGID(0) |
|
51 |
-} |
|
52 |
- |
|
53 |
-// Utility function that gets a host ID for a container ID from user namespace map |
|
54 |
-// if that ID is present in the map. |
|
55 |
-func (c Config) hostIDFromMapping(containerID int, uMap []IDMap) (int, bool) { |
|
56 |
- for _, m := range uMap { |
|
57 |
- if (containerID >= m.ContainerID) && (containerID <= (m.ContainerID + m.Size - 1)) { |
|
58 |
- hostID := m.HostID + (containerID - m.ContainerID) |
|
59 |
- return hostID, true |
|
60 |
- } |
|
61 |
- } |
|
62 |
- return -1, false |
|
63 |
-} |
64 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,122 @@ |
0 |
+package configs |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "fmt" |
|
4 |
+ "os" |
|
5 |
+ "sync" |
|
6 |
+) |
|
7 |
+ |
|
8 |
+const ( |
|
9 |
+ NEWNET NamespaceType = "NEWNET" |
|
10 |
+ NEWPID NamespaceType = "NEWPID" |
|
11 |
+ NEWNS NamespaceType = "NEWNS" |
|
12 |
+ NEWUTS NamespaceType = "NEWUTS" |
|
13 |
+ NEWIPC NamespaceType = "NEWIPC" |
|
14 |
+ NEWUSER NamespaceType = "NEWUSER" |
|
15 |
+) |
|
16 |
+ |
|
17 |
+var ( |
|
18 |
+ nsLock sync.Mutex |
|
19 |
+ supportedNamespaces = make(map[NamespaceType]bool) |
|
20 |
+) |
|
21 |
+ |
|
22 |
+// NsName converts the namespace type to its filename |
|
23 |
+func NsName(ns NamespaceType) string { |
|
24 |
+ switch ns { |
|
25 |
+ case NEWNET: |
|
26 |
+ return "net" |
|
27 |
+ case NEWNS: |
|
28 |
+ return "mnt" |
|
29 |
+ case NEWPID: |
|
30 |
+ return "pid" |
|
31 |
+ case NEWIPC: |
|
32 |
+ return "ipc" |
|
33 |
+ case NEWUSER: |
|
34 |
+ return "user" |
|
35 |
+ case NEWUTS: |
|
36 |
+ return "uts" |
|
37 |
+ } |
|
38 |
+ return "" |
|
39 |
+} |
|
40 |
+ |
|
41 |
+// IsNamespaceSupported returns whether a namespace is available or |
|
42 |
+// not |
|
43 |
+func IsNamespaceSupported(ns NamespaceType) bool { |
|
44 |
+ nsLock.Lock() |
|
45 |
+ defer nsLock.Unlock() |
|
46 |
+ supported, ok := supportedNamespaces[ns] |
|
47 |
+ if ok { |
|
48 |
+ return supported |
|
49 |
+ } |
|
50 |
+ nsFile := NsName(ns) |
|
51 |
+ // if the namespace type is unknown, just return false |
|
52 |
+ if nsFile == "" { |
|
53 |
+ return false |
|
54 |
+ } |
|
55 |
+ _, err := os.Stat(fmt.Sprintf("/proc/self/ns/%s", nsFile)) |
|
56 |
+ // a namespace is supported if it exists and we have permissions to read it |
|
57 |
+ supported = err == nil |
|
58 |
+ supportedNamespaces[ns] = supported |
|
59 |
+ return supported |
|
60 |
+} |
|
61 |
+ |
|
62 |
+func NamespaceTypes() []NamespaceType { |
|
63 |
+ return []NamespaceType{ |
|
64 |
+ NEWUSER, // Keep user NS always first, don't move it. |
|
65 |
+ NEWIPC, |
|
66 |
+ NEWUTS, |
|
67 |
+ NEWNET, |
|
68 |
+ NEWPID, |
|
69 |
+ NEWNS, |
|
70 |
+ } |
|
71 |
+} |
|
72 |
+ |
|
73 |
+// Namespace defines configuration for each namespace. It specifies an |
|
74 |
+// alternate path that is able to be joined via setns. |
|
75 |
+type Namespace struct { |
|
76 |
+ Type NamespaceType `json:"type"` |
|
77 |
+ Path string `json:"path"` |
|
78 |
+} |
|
79 |
+ |
|
80 |
+func (n *Namespace) GetPath(pid int) string { |
|
81 |
+ return fmt.Sprintf("/proc/%d/ns/%s", pid, NsName(n.Type)) |
|
82 |
+} |
|
83 |
+ |
|
84 |
+func (n *Namespaces) Remove(t NamespaceType) bool { |
|
85 |
+ i := n.index(t) |
|
86 |
+ if i == -1 { |
|
87 |
+ return false |
|
88 |
+ } |
|
89 |
+ *n = append((*n)[:i], (*n)[i+1:]...) |
|
90 |
+ return true |
|
91 |
+} |
|
92 |
+ |
|
93 |
+func (n *Namespaces) Add(t NamespaceType, path string) { |
|
94 |
+ i := n.index(t) |
|
95 |
+ if i == -1 { |
|
96 |
+ *n = append(*n, Namespace{Type: t, Path: path}) |
|
97 |
+ return |
|
98 |
+ } |
|
99 |
+ (*n)[i].Path = path |
|
100 |
+} |
|
101 |
+ |
|
102 |
+func (n *Namespaces) index(t NamespaceType) int { |
|
103 |
+ for i, ns := range *n { |
|
104 |
+ if ns.Type == t { |
|
105 |
+ return i |
|
106 |
+ } |
|
107 |
+ } |
|
108 |
+ return -1 |
|
109 |
+} |
|
110 |
+ |
|
111 |
+func (n *Namespaces) Contains(t NamespaceType) bool { |
|
112 |
+ return n.index(t) != -1 |
|
113 |
+} |
|
114 |
+ |
|
115 |
+func (n *Namespaces) PathOf(t NamespaceType) string { |
|
116 |
+ i := n.index(t) |
|
117 |
+ if i == -1 { |
|
118 |
+ return "" |
|
119 |
+ } |
|
120 |
+ return (*n)[i].Path |
|
121 |
+} |
... | ... |
@@ -2,19 +2,19 @@ |
2 | 2 |
|
3 | 3 |
package configs |
4 | 4 |
|
5 |
-import "syscall" |
|
5 |
+import "golang.org/x/sys/unix" |
|
6 | 6 |
|
7 | 7 |
func (n *Namespace) Syscall() int { |
8 | 8 |
return namespaceInfo[n.Type] |
9 | 9 |
} |
10 | 10 |
|
11 | 11 |
var namespaceInfo = map[NamespaceType]int{ |
12 |
- NEWNET: syscall.CLONE_NEWNET, |
|
13 |
- NEWNS: syscall.CLONE_NEWNS, |
|
14 |
- NEWUSER: syscall.CLONE_NEWUSER, |
|
15 |
- NEWIPC: syscall.CLONE_NEWIPC, |
|
16 |
- NEWUTS: syscall.CLONE_NEWUTS, |
|
17 |
- NEWPID: syscall.CLONE_NEWPID, |
|
12 |
+ NEWNET: unix.CLONE_NEWNET, |
|
13 |
+ NEWNS: unix.CLONE_NEWNS, |
|
14 |
+ NEWUSER: unix.CLONE_NEWUSER, |
|
15 |
+ NEWIPC: unix.CLONE_NEWIPC, |
|
16 |
+ NEWUTS: unix.CLONE_NEWUTS, |
|
17 |
+ NEWPID: unix.CLONE_NEWPID, |
|
18 | 18 |
} |
19 | 19 |
|
20 | 20 |
// CloneFlags parses the container's Namespaces options to set the correct |
21 | 21 |
deleted file mode 100644 |
... | ... |
@@ -1,127 +0,0 @@ |
1 |
-// +build linux freebsd |
|
2 |
- |
|
3 |
-package configs |
|
4 |
- |
|
5 |
-import ( |
|
6 |
- "fmt" |
|
7 |
- "os" |
|
8 |
- "sync" |
|
9 |
-) |
|
10 |
- |
|
11 |
-const ( |
|
12 |
- NEWNET NamespaceType = "NEWNET" |
|
13 |
- NEWPID NamespaceType = "NEWPID" |
|
14 |
- NEWNS NamespaceType = "NEWNS" |
|
15 |
- NEWUTS NamespaceType = "NEWUTS" |
|
16 |
- NEWIPC NamespaceType = "NEWIPC" |
|
17 |
- NEWUSER NamespaceType = "NEWUSER" |
|
18 |
-) |
|
19 |
- |
|
20 |
-var ( |
|
21 |
- nsLock sync.Mutex |
|
22 |
- supportedNamespaces = make(map[NamespaceType]bool) |
|
23 |
-) |
|
24 |
- |
|
25 |
-// NsName converts the namespace type to its filename |
|
26 |
-func NsName(ns NamespaceType) string { |
|
27 |
- switch ns { |
|
28 |
- case NEWNET: |
|
29 |
- return "net" |
|
30 |
- case NEWNS: |
|
31 |
- return "mnt" |
|
32 |
- case NEWPID: |
|
33 |
- return "pid" |
|
34 |
- case NEWIPC: |
|
35 |
- return "ipc" |
|
36 |
- case NEWUSER: |
|
37 |
- return "user" |
|
38 |
- case NEWUTS: |
|
39 |
- return "uts" |
|
40 |
- } |
|
41 |
- return "" |
|
42 |
-} |
|
43 |
- |
|
44 |
-// IsNamespaceSupported returns whether a namespace is available or |
|
45 |
-// not |
|
46 |
-func IsNamespaceSupported(ns NamespaceType) bool { |
|
47 |
- nsLock.Lock() |
|
48 |
- defer nsLock.Unlock() |
|
49 |
- supported, ok := supportedNamespaces[ns] |
|
50 |
- if ok { |
|
51 |
- return supported |
|
52 |
- } |
|
53 |
- nsFile := NsName(ns) |
|
54 |
- // if the namespace type is unknown, just return false |
|
55 |
- if nsFile == "" { |
|
56 |
- return false |
|
57 |
- } |
|
58 |
- _, err := os.Stat(fmt.Sprintf("/proc/self/ns/%s", nsFile)) |
|
59 |
- // a namespace is supported if it exists and we have permissions to read it |
|
60 |
- supported = err == nil |
|
61 |
- supportedNamespaces[ns] = supported |
|
62 |
- return supported |
|
63 |
-} |
|
64 |
- |
|
65 |
-func NamespaceTypes() []NamespaceType { |
|
66 |
- return []NamespaceType{ |
|
67 |
- NEWUSER, // Keep user NS always first, don't move it. |
|
68 |
- NEWIPC, |
|
69 |
- NEWUTS, |
|
70 |
- NEWNET, |
|
71 |
- NEWPID, |
|
72 |
- NEWNS, |
|
73 |
- } |
|
74 |
-} |
|
75 |
- |
|
76 |
-// Namespace defines configuration for each namespace. It specifies an |
|
77 |
-// alternate path that is able to be joined via setns. |
|
78 |
-type Namespace struct { |
|
79 |
- Type NamespaceType `json:"type"` |
|
80 |
- Path string `json:"path"` |
|
81 |
-} |
|
82 |
- |
|
83 |
-func (n *Namespace) GetPath(pid int) string { |
|
84 |
- if n.Path != "" { |
|
85 |
- return n.Path |
|
86 |
- } |
|
87 |
- return fmt.Sprintf("/proc/%d/ns/%s", pid, NsName(n.Type)) |
|
88 |
-} |
|
89 |
- |
|
90 |
-func (n *Namespaces) Remove(t NamespaceType) bool { |
|
91 |
- i := n.index(t) |
|
92 |
- if i == -1 { |
|
93 |
- return false |
|
94 |
- } |
|
95 |
- *n = append((*n)[:i], (*n)[i+1:]...) |
|
96 |
- return true |
|
97 |
-} |
|
98 |
- |
|
99 |
-func (n *Namespaces) Add(t NamespaceType, path string) { |
|
100 |
- i := n.index(t) |
|
101 |
- if i == -1 { |
|
102 |
- *n = append(*n, Namespace{Type: t, Path: path}) |
|
103 |
- return |
|
104 |
- } |
|
105 |
- (*n)[i].Path = path |
|
106 |
-} |
|
107 |
- |
|
108 |
-func (n *Namespaces) index(t NamespaceType) int { |
|
109 |
- for i, ns := range *n { |
|
110 |
- if ns.Type == t { |
|
111 |
- return i |
|
112 |
- } |
|
113 |
- } |
|
114 |
- return -1 |
|
115 |
-} |
|
116 |
- |
|
117 |
-func (n *Namespaces) Contains(t NamespaceType) bool { |
|
118 |
- return n.index(t) != -1 |
|
119 |
-} |
|
120 |
- |
|
121 |
-func (n *Namespaces) PathOf(t NamespaceType) string { |
|
122 |
- i := n.index(t) |
|
123 |
- if i == -1 { |
|
124 |
- return "" |
|
125 |
- } |
|
126 |
- return (*n)[i].Path |
|
127 |
-} |
5 | 5 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,104 @@ |
0 |
+package devices |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "errors" |
|
4 |
+ "io/ioutil" |
|
5 |
+ "os" |
|
6 |
+ "path/filepath" |
|
7 |
+ |
|
8 |
+ "github.com/opencontainers/runc/libcontainer/configs" |
|
9 |
+ |
|
10 |
+ "golang.org/x/sys/unix" |
|
11 |
+) |
|
12 |
+ |
|
13 |
+var ( |
|
14 |
+ ErrNotADevice = errors.New("not a device node") |
|
15 |
+) |
|
16 |
+ |
|
17 |
+// Testing dependencies |
|
18 |
+var ( |
|
19 |
+ unixLstat = unix.Lstat |
|
20 |
+ ioutilReadDir = ioutil.ReadDir |
|
21 |
+) |
|
22 |
+ |
|
23 |
+// Given the path to a device and its cgroup_permissions(which cannot be easily queried) look up the information about a linux device and return that information as a Device struct. |
|
24 |
+func DeviceFromPath(path, permissions string) (*configs.Device, error) { |
|
25 |
+ var stat unix.Stat_t |
|
26 |
+ err := unixLstat(path, &stat) |
|
27 |
+ if err != nil { |
|
28 |
+ return nil, err |
|
29 |
+ } |
|
30 |
+ |
|
31 |
+ var ( |
|
32 |
+ devNumber = int(stat.Rdev) |
|
33 |
+ major = Major(devNumber) |
|
34 |
+ ) |
|
35 |
+ if major == 0 { |
|
36 |
+ return nil, ErrNotADevice |
|
37 |
+ } |
|
38 |
+ |
|
39 |
+ var ( |
|
40 |
+ devType rune |
|
41 |
+ mode = stat.Mode |
|
42 |
+ ) |
|
43 |
+ switch { |
|
44 |
+ case mode&unix.S_IFBLK == unix.S_IFBLK: |
|
45 |
+ devType = 'b' |
|
46 |
+ case mode&unix.S_IFCHR == unix.S_IFCHR: |
|
47 |
+ devType = 'c' |
|
48 |
+ } |
|
49 |
+ return &configs.Device{ |
|
50 |
+ Type: devType, |
|
51 |
+ Path: path, |
|
52 |
+ Major: major, |
|
53 |
+ Minor: Minor(devNumber), |
|
54 |
+ Permissions: permissions, |
|
55 |
+ FileMode: os.FileMode(mode), |
|
56 |
+ Uid: stat.Uid, |
|
57 |
+ Gid: stat.Gid, |
|
58 |
+ }, nil |
|
59 |
+} |
|
60 |
+ |
|
61 |
+func HostDevices() ([]*configs.Device, error) { |
|
62 |
+ return getDevices("/dev") |
|
63 |
+} |
|
64 |
+ |
|
65 |
+func getDevices(path string) ([]*configs.Device, error) { |
|
66 |
+ files, err := ioutilReadDir(path) |
|
67 |
+ if err != nil { |
|
68 |
+ return nil, err |
|
69 |
+ } |
|
70 |
+ out := []*configs.Device{} |
|
71 |
+ for _, f := range files { |
|
72 |
+ switch { |
|
73 |
+ case f.IsDir(): |
|
74 |
+ switch f.Name() { |
|
75 |
+ // ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825 |
|
76 |
+ case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts": |
|
77 |
+ continue |
|
78 |
+ default: |
|
79 |
+ sub, err := getDevices(filepath.Join(path, f.Name())) |
|
80 |
+ if err != nil { |
|
81 |
+ return nil, err |
|
82 |
+ } |
|
83 |
+ |
|
84 |
+ out = append(out, sub...) |
|
85 |
+ continue |
|
86 |
+ } |
|
87 |
+ case f.Name() == "console": |
|
88 |
+ continue |
|
89 |
+ } |
|
90 |
+ device, err := DeviceFromPath(filepath.Join(path, f.Name()), "rwm") |
|
91 |
+ if err != nil { |
|
92 |
+ if err == ErrNotADevice { |
|
93 |
+ continue |
|
94 |
+ } |
|
95 |
+ if os.IsNotExist(err) { |
|
96 |
+ continue |
|
97 |
+ } |
|
98 |
+ return nil, err |
|
99 |
+ } |
|
100 |
+ out = append(out, device) |
|
101 |
+ } |
|
102 |
+ return out, nil |
|
103 |
+} |
0 | 104 |
deleted file mode 100644 |
... | ... |
@@ -1,106 +0,0 @@ |
1 |
-// +build linux freebsd |
|
2 |
- |
|
3 |
-package devices |
|
4 |
- |
|
5 |
-import ( |
|
6 |
- "errors" |
|
7 |
- "fmt" |
|
8 |
- "io/ioutil" |
|
9 |
- "os" |
|
10 |
- "path/filepath" |
|
11 |
- "syscall" |
|
12 |
- |
|
13 |
- "github.com/opencontainers/runc/libcontainer/configs" |
|
14 |
-) |
|
15 |
- |
|
16 |
-var ( |
|
17 |
- ErrNotADevice = errors.New("not a device node") |
|
18 |
-) |
|
19 |
- |
|
20 |
-// Testing dependencies |
|
21 |
-var ( |
|
22 |
- osLstat = os.Lstat |
|
23 |
- ioutilReadDir = ioutil.ReadDir |
|
24 |
-) |
|
25 |
- |
|
26 |
-// Given the path to a device and its cgroup_permissions(which cannot be easily queried) look up the information about a linux device and return that information as a Device struct. |
|
27 |
-func DeviceFromPath(path, permissions string) (*configs.Device, error) { |
|
28 |
- fileInfo, err := osLstat(path) |
|
29 |
- if err != nil { |
|
30 |
- return nil, err |
|
31 |
- } |
|
32 |
- var ( |
|
33 |
- devType rune |
|
34 |
- mode = fileInfo.Mode() |
|
35 |
- fileModePermissionBits = os.FileMode.Perm(mode) |
|
36 |
- ) |
|
37 |
- switch { |
|
38 |
- case mode&os.ModeDevice == 0: |
|
39 |
- return nil, ErrNotADevice |
|
40 |
- case mode&os.ModeCharDevice != 0: |
|
41 |
- fileModePermissionBits |= syscall.S_IFCHR |
|
42 |
- devType = 'c' |
|
43 |
- default: |
|
44 |
- fileModePermissionBits |= syscall.S_IFBLK |
|
45 |
- devType = 'b' |
|
46 |
- } |
|
47 |
- stat_t, ok := fileInfo.Sys().(*syscall.Stat_t) |
|
48 |
- if !ok { |
|
49 |
- return nil, fmt.Errorf("cannot determine the device number for device %s", path) |
|
50 |
- } |
|
51 |
- devNumber := int(stat_t.Rdev) |
|
52 |
- return &configs.Device{ |
|
53 |
- Type: devType, |
|
54 |
- Path: path, |
|
55 |
- Major: Major(devNumber), |
|
56 |
- Minor: Minor(devNumber), |
|
57 |
- Permissions: permissions, |
|
58 |
- FileMode: fileModePermissionBits, |
|
59 |
- Uid: stat_t.Uid, |
|
60 |
- Gid: stat_t.Gid, |
|
61 |
- }, nil |
|
62 |
-} |
|
63 |
- |
|
64 |
-func HostDevices() ([]*configs.Device, error) { |
|
65 |
- return getDevices("/dev") |
|
66 |
-} |
|
67 |
- |
|
68 |
-func getDevices(path string) ([]*configs.Device, error) { |
|
69 |
- files, err := ioutilReadDir(path) |
|
70 |
- if err != nil { |
|
71 |
- return nil, err |
|
72 |
- } |
|
73 |
- out := []*configs.Device{} |
|
74 |
- for _, f := range files { |
|
75 |
- switch { |
|
76 |
- case f.IsDir(): |
|
77 |
- switch f.Name() { |
|
78 |
- // ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825 |
|
79 |
- case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts": |
|
80 |
- continue |
|
81 |
- default: |
|
82 |
- sub, err := getDevices(filepath.Join(path, f.Name())) |
|
83 |
- if err != nil { |
|
84 |
- return nil, err |
|
85 |
- } |
|
86 |
- |
|
87 |
- out = append(out, sub...) |
|
88 |
- continue |
|
89 |
- } |
|
90 |
- case f.Name() == "console": |
|
91 |
- continue |
|
92 |
- } |
|
93 |
- device, err := DeviceFromPath(filepath.Join(path, f.Name()), "rwm") |
|
94 |
- if err != nil { |
|
95 |
- if err == ErrNotADevice { |
|
96 |
- continue |
|
97 |
- } |
|
98 |
- if os.IsNotExist(err) { |
|
99 |
- continue |
|
100 |
- } |
|
101 |
- return nil, err |
|
102 |
- } |
|
103 |
- out = append(out, device) |
|
104 |
- } |
|
105 |
- return out, nil |
|
106 |
-} |
... | ... |
@@ -143,8 +143,7 @@ static int write_file(char *data, size_t data_len, char *pathfmt, ...) |
143 | 143 |
|
144 | 144 |
fd = open(path, O_RDWR); |
145 | 145 |
if (fd < 0) { |
146 |
- ret = -1; |
|
147 |
- goto out; |
|
146 |
+ return -1; |
|
148 | 147 |
} |
149 | 148 |
|
150 | 149 |
len = write(fd, data, data_len); |
... | ... |
@@ -543,7 +542,7 @@ void nsexec(void) |
543 | 543 |
*/ |
544 | 544 |
case JUMP_PARENT: { |
545 | 545 |
int len; |
546 |
- pid_t child; |
|
546 |
+ pid_t child, first_child = -1; |
|
547 | 547 |
char buf[JSON_MAX]; |
548 | 548 |
bool ready = false; |
549 | 549 |
|
... | ... |
@@ -607,18 +606,18 @@ void nsexec(void) |
607 | 607 |
} |
608 | 608 |
break; |
609 | 609 |
case SYNC_RECVPID_PLS: { |
610 |
- pid_t old = child; |
|
610 |
+ first_child = child; |
|
611 | 611 |
|
612 | 612 |
/* Get the init_func pid. */ |
613 | 613 |
if (read(syncfd, &child, sizeof(child)) != sizeof(child)) { |
614 |
- kill(old, SIGKILL); |
|
614 |
+ kill(first_child, SIGKILL); |
|
615 | 615 |
bail("failed to sync with child: read(childpid)"); |
616 | 616 |
} |
617 | 617 |
|
618 | 618 |
/* Send ACK. */ |
619 | 619 |
s = SYNC_RECVPID_ACK; |
620 | 620 |
if (write(syncfd, &s, sizeof(s)) != sizeof(s)) { |
621 |
- kill(old, SIGKILL); |
|
621 |
+ kill(first_child, SIGKILL); |
|
622 | 622 |
kill(child, SIGKILL); |
623 | 623 |
bail("failed to sync with child: write(SYNC_RECVPID_ACK)"); |
624 | 624 |
} |
... | ... |
@@ -666,8 +665,13 @@ void nsexec(void) |
666 | 666 |
} |
667 | 667 |
} |
668 | 668 |
|
669 |
- /* Send the init_func pid back to our parent. */ |
|
670 |
- len = snprintf(buf, JSON_MAX, "{\"pid\": %d}\n", child); |
|
669 |
+ /* |
|
670 |
+ * Send the init_func pid and the pid of the first child back to our parent. |
|
671 |
+ * |
|
672 |
+ * We need to send both back because we can't reap the first child we created (CLONE_PARENT). |
|
673 |
+ * It becomes the responsibility of our parent to reap the first child. |
|
674 |
+ */ |
|
675 |
+ len = snprintf(buf, JSON_MAX, "{\"pid\": %d, \"pid_first\": %d}\n", child, first_child); |
|
671 | 676 |
if (len < 0) { |
672 | 677 |
kill(child, SIGKILL); |
673 | 678 |
bail("unable to generate JSON for child pid"); |
... | ... |
@@ -7,8 +7,10 @@ import ( |
7 | 7 |
"fmt" |
8 | 8 |
"os" |
9 | 9 |
"os/exec" |
10 |
- "syscall" |
|
10 |
+ "syscall" // only for exec |
|
11 | 11 |
"unsafe" |
12 |
+ |
|
13 |
+ "golang.org/x/sys/unix" |
|
12 | 14 |
) |
13 | 15 |
|
14 | 16 |
// If arg2 is nonzero, set the "child subreaper" attribute of the |
... | ... |
@@ -53,8 +55,8 @@ func Execv(cmd string, args []string, env []string) error { |
53 | 53 |
return syscall.Exec(name, args, env) |
54 | 54 |
} |
55 | 55 |
|
56 |
-func Prlimit(pid, resource int, limit syscall.Rlimit) error { |
|
57 |
- _, _, err := syscall.RawSyscall6(syscall.SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(&limit)), uintptr(unsafe.Pointer(&limit)), 0, 0) |
|
56 |
+func Prlimit(pid, resource int, limit unix.Rlimit) error { |
|
57 |
+ _, _, err := unix.RawSyscall6(unix.SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(&limit)), uintptr(unsafe.Pointer(&limit)), 0, 0) |
|
58 | 58 |
if err != 0 { |
59 | 59 |
return err |
60 | 60 |
} |
... | ... |
@@ -62,7 +64,7 @@ func Prlimit(pid, resource int, limit syscall.Rlimit) error { |
62 | 62 |
} |
63 | 63 |
|
64 | 64 |
func SetParentDeathSignal(sig uintptr) error { |
65 |
- if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_PDEATHSIG, sig, 0); err != 0 { |
|
65 |
+ if err := unix.Prctl(unix.PR_SET_PDEATHSIG, sig, 0, 0, 0); err != nil { |
|
66 | 66 |
return err |
67 | 67 |
} |
68 | 68 |
return nil |
... | ... |
@@ -70,15 +72,14 @@ func SetParentDeathSignal(sig uintptr) error { |
70 | 70 |
|
71 | 71 |
func GetParentDeathSignal() (ParentDeathSignal, error) { |
72 | 72 |
var sig int |
73 |
- _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_GET_PDEATHSIG, uintptr(unsafe.Pointer(&sig)), 0) |
|
74 |
- if err != 0 { |
|
73 |
+ if err := unix.Prctl(unix.PR_GET_PDEATHSIG, uintptr(unsafe.Pointer(&sig)), 0, 0, 0); err != nil { |
|
75 | 74 |
return -1, err |
76 | 75 |
} |
77 | 76 |
return ParentDeathSignal(sig), nil |
78 | 77 |
} |
79 | 78 |
|
80 | 79 |
func SetKeepCaps() error { |
81 |
- if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_KEEPCAPS, 1, 0); err != 0 { |
|
80 |
+ if err := unix.Prctl(unix.PR_SET_KEEPCAPS, 1, 0, 0, 0); err != nil { |
|
82 | 81 |
return err |
83 | 82 |
} |
84 | 83 |
|
... | ... |
@@ -86,7 +87,7 @@ func SetKeepCaps() error { |
86 | 86 |
} |
87 | 87 |
|
88 | 88 |
func ClearKeepCaps() error { |
89 |
- if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_KEEPCAPS, 0, 0); err != 0 { |
|
89 |
+ if err := unix.Prctl(unix.PR_SET_KEEPCAPS, 0, 0, 0, 0); err != nil { |
|
90 | 90 |
return err |
91 | 91 |
} |
92 | 92 |
|
... | ... |
@@ -94,7 +95,7 @@ func ClearKeepCaps() error { |
94 | 94 |
} |
95 | 95 |
|
96 | 96 |
func Setctty() error { |
97 |
- if _, _, err := syscall.RawSyscall(syscall.SYS_IOCTL, 0, uintptr(syscall.TIOCSCTTY), 0); err != 0 { |
|
97 |
+ if err := unix.IoctlSetInt(0, unix.TIOCSCTTY, 0); err != nil { |
|
98 | 98 |
return err |
99 | 99 |
} |
100 | 100 |
return nil |
... | ... |
@@ -131,13 +132,5 @@ func RunningInUserNS() bool { |
131 | 131 |
|
132 | 132 |
// SetSubreaper sets the value i as the subreaper setting for the calling process |
133 | 133 |
func SetSubreaper(i int) error { |
134 |
- return Prctl(PR_SET_CHILD_SUBREAPER, uintptr(i), 0, 0, 0) |
|
135 |
-} |
|
136 |
- |
|
137 |
-func Prctl(option int, arg2, arg3, arg4, arg5 uintptr) (err error) { |
|
138 |
- _, _, e1 := syscall.Syscall6(syscall.SYS_PRCTL, uintptr(option), arg2, arg3, arg4, arg5, 0) |
|
139 |
- if e1 != 0 { |
|
140 |
- err = e1 |
|
141 |
- } |
|
142 |
- return |
|
134 |
+ return unix.Prctl(PR_SET_CHILD_SUBREAPER, uintptr(i), 0, 0, 0) |
|
143 | 135 |
} |
... | ... |
@@ -1,43 +1,113 @@ |
1 | 1 |
package system |
2 | 2 |
|
3 | 3 |
import ( |
4 |
+ "fmt" |
|
4 | 5 |
"io/ioutil" |
5 | 6 |
"path/filepath" |
6 | 7 |
"strconv" |
7 | 8 |
"strings" |
8 | 9 |
) |
9 | 10 |
|
10 |
-// look in /proc to find the process start time so that we can verify |
|
11 |
-// that this pid has started after ourself |
|
11 |
+// State is the status of a process. |
|
12 |
+type State rune |
|
13 |
+ |
|
14 |
+const ( // Only values for Linux 3.14 and later are listed here |
|
15 |
+ Dead State = 'X' |
|
16 |
+ DiskSleep State = 'D' |
|
17 |
+ Running State = 'R' |
|
18 |
+ Sleeping State = 'S' |
|
19 |
+ Stopped State = 'T' |
|
20 |
+ TracingStop State = 't' |
|
21 |
+ Zombie State = 'Z' |
|
22 |
+) |
|
23 |
+ |
|
24 |
+// String forms of the state from proc(5)'s documentation for |
|
25 |
+// /proc/[pid]/status' "State" field. |
|
26 |
+func (s State) String() string { |
|
27 |
+ switch s { |
|
28 |
+ case Dead: |
|
29 |
+ return "dead" |
|
30 |
+ case DiskSleep: |
|
31 |
+ return "disk sleep" |
|
32 |
+ case Running: |
|
33 |
+ return "running" |
|
34 |
+ case Sleeping: |
|
35 |
+ return "sleeping" |
|
36 |
+ case Stopped: |
|
37 |
+ return "stopped" |
|
38 |
+ case TracingStop: |
|
39 |
+ return "tracing stop" |
|
40 |
+ case Zombie: |
|
41 |
+ return "zombie" |
|
42 |
+ default: |
|
43 |
+ return fmt.Sprintf("unknown (%c)", s) |
|
44 |
+ } |
|
45 |
+} |
|
46 |
+ |
|
47 |
+// Stat_t represents the information from /proc/[pid]/stat, as |
|
48 |
+// described in proc(5) with names based on the /proc/[pid]/status |
|
49 |
+// fields. |
|
50 |
+type Stat_t struct { |
|
51 |
+ // PID is the process ID. |
|
52 |
+ PID uint |
|
53 |
+ |
|
54 |
+ // Name is the command run by the process. |
|
55 |
+ Name string |
|
56 |
+ |
|
57 |
+ // State is the state of the process. |
|
58 |
+ State State |
|
59 |
+ |
|
60 |
+ // StartTime is the number of clock ticks after system boot (since |
|
61 |
+ // Linux 2.6). |
|
62 |
+ StartTime uint64 |
|
63 |
+} |
|
64 |
+ |
|
65 |
+// Stat returns a Stat_t instance for the specified process. |
|
66 |
+func Stat(pid int) (stat Stat_t, err error) { |
|
67 |
+ bytes, err := ioutil.ReadFile(filepath.Join("/proc", strconv.Itoa(pid), "stat")) |
|
68 |
+ if err != nil { |
|
69 |
+ return stat, err |
|
70 |
+ } |
|
71 |
+ return parseStat(string(bytes)) |
|
72 |
+} |
|
73 |
+ |
|
74 |
+// GetProcessStartTime is deprecated. Use Stat(pid) and |
|
75 |
+// Stat_t.StartTime instead. |
|
12 | 76 |
func GetProcessStartTime(pid int) (string, error) { |
13 |
- data, err := ioutil.ReadFile(filepath.Join("/proc", strconv.Itoa(pid), "stat")) |
|
77 |
+ stat, err := Stat(pid) |
|
14 | 78 |
if err != nil { |
15 | 79 |
return "", err |
16 | 80 |
} |
17 |
- return parseStartTime(string(data)) |
|
81 |
+ return fmt.Sprintf("%d", stat.StartTime), nil |
|
18 | 82 |
} |
19 | 83 |
|
20 |
-func parseStartTime(stat string) (string, error) { |
|
21 |
- // the starttime is located at pos 22 |
|
22 |
- // from the man page |
|
23 |
- // |
|
24 |
- // starttime %llu (was %lu before Linux 2.6) |
|
25 |
- // (22) The time the process started after system boot. In kernels before Linux 2.6, this |
|
26 |
- // value was expressed in jiffies. Since Linux 2.6, the value is expressed in clock ticks |
|
27 |
- // (divide by sysconf(_SC_CLK_TCK)). |
|
28 |
- // |
|
29 |
- // NOTE: |
|
30 |
- // pos 2 could contain space and is inside `(` and `)`: |
|
31 |
- // (2) comm %s |
|
32 |
- // The filename of the executable, in parentheses. |
|
33 |
- // This is visible whether or not the executable is |
|
34 |
- // swapped out. |
|
35 |
- // |
|
36 |
- // the following is an example: |
|
84 |
+func parseStat(data string) (stat Stat_t, err error) { |
|
85 |
+ // From proc(5), field 2 could contain space and is inside `(` and `)`. |
|
86 |
+ // The following is an example: |
|
37 | 87 |
// 89653 (gunicorn: maste) S 89630 89653 89653 0 -1 4194560 29689 28896 0 3 146 32 76 19 20 0 1 0 2971844 52965376 3920 18446744073709551615 1 1 0 0 0 0 0 16781312 137447943 0 0 0 17 1 0 0 0 0 0 0 0 0 0 0 0 0 0 |
88 |
+ i := strings.LastIndex(data, ")") |
|
89 |
+ if i <= 2 || i >= len(data)-1 { |
|
90 |
+ return stat, fmt.Errorf("invalid stat data: %q", data) |
|
91 |
+ } |
|
92 |
+ |
|
93 |
+ parts := strings.SplitN(data[:i], "(", 2) |
|
94 |
+ if len(parts) != 2 { |
|
95 |
+ return stat, fmt.Errorf("invalid stat data: %q", data) |
|
96 |
+ } |
|
97 |
+ |
|
98 |
+ stat.Name = parts[1] |
|
99 |
+ _, err = fmt.Sscanf(parts[0], "%d", &stat.PID) |
|
100 |
+ if err != nil { |
|
101 |
+ return stat, err |
|
102 |
+ } |
|
38 | 103 |
|
39 |
- // get parts after last `)`: |
|
40 |
- s := strings.Split(stat, ")") |
|
41 |
- parts := strings.Split(strings.TrimSpace(s[len(s)-1]), " ") |
|
42 |
- return parts[22-3], nil // starts at 3 (after the filename pos `2`) |
|
104 |
+ // parts indexes should be offset by 3 from the field number given |
|
105 |
+ // proc(5), because parts is zero-indexed and we've removed fields |
|
106 |
+ // one (PID) and two (Name) in the paren-split. |
|
107 |
+ parts = strings.Split(data[i+2:], " ") |
|
108 |
+ var state int |
|
109 |
+ fmt.Sscanf(parts[3-3], "%c", &state) |
|
110 |
+ stat.State = State(state) |
|
111 |
+ fmt.Sscanf(parts[22-3], "%d", &stat.StartTime) |
|
112 |
+ return stat, nil |
|
43 | 113 |
} |
44 | 114 |
deleted file mode 100644 |
... | ... |
@@ -1,40 +0,0 @@ |
1 |
-package system |
|
2 |
- |
|
3 |
-import ( |
|
4 |
- "fmt" |
|
5 |
- "runtime" |
|
6 |
- "syscall" |
|
7 |
-) |
|
8 |
- |
|
9 |
-// Via http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=7b21fddd087678a70ad64afc0f632e0f1071b092 |
|
10 |
-// |
|
11 |
-// We need different setns values for the different platforms and arch |
|
12 |
-// We are declaring the macro here because the SETNS syscall does not exist in th stdlib |
|
13 |
-var setNsMap = map[string]uintptr{ |
|
14 |
- "linux/386": 346, |
|
15 |
- "linux/arm64": 268, |
|
16 |
- "linux/amd64": 308, |
|
17 |
- "linux/arm": 375, |
|
18 |
- "linux/ppc": 350, |
|
19 |
- "linux/ppc64": 350, |
|
20 |
- "linux/ppc64le": 350, |
|
21 |
- "linux/s390x": 339, |
|
22 |
-} |
|
23 |
- |
|
24 |
-var sysSetns = setNsMap[fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)] |
|
25 |
- |
|
26 |
-func SysSetns() uint32 { |
|
27 |
- return uint32(sysSetns) |
|
28 |
-} |
|
29 |
- |
|
30 |
-func Setns(fd uintptr, flags uintptr) error { |
|
31 |
- ns, exists := setNsMap[fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)] |
|
32 |
- if !exists { |
|
33 |
- return fmt.Errorf("unsupported platform %s/%s", runtime.GOOS, runtime.GOARCH) |
|
34 |
- } |
|
35 |
- _, _, err := syscall.RawSyscall(ns, fd, flags, 0) |
|
36 |
- if err != 0 { |
|
37 |
- return err |
|
38 |
- } |
|
39 |
- return nil |
|
40 |
-} |
... | ... |
@@ -3,12 +3,12 @@ |
3 | 3 |
package system |
4 | 4 |
|
5 | 5 |
import ( |
6 |
- "syscall" |
|
6 |
+ "golang.org/x/sys/unix" |
|
7 | 7 |
) |
8 | 8 |
|
9 | 9 |
// Setuid sets the uid of the calling thread to the specified uid. |
10 | 10 |
func Setuid(uid int) (err error) { |
11 |
- _, _, e1 := syscall.RawSyscall(syscall.SYS_SETUID32, uintptr(uid), 0, 0) |
|
11 |
+ _, _, e1 := unix.RawSyscall(unix.SYS_SETUID32, uintptr(uid), 0, 0) |
|
12 | 12 |
if e1 != 0 { |
13 | 13 |
err = e1 |
14 | 14 |
} |
... | ... |
@@ -17,7 +17,7 @@ func Setuid(uid int) (err error) { |
17 | 17 |
|
18 | 18 |
// Setgid sets the gid of the calling thread to the specified gid. |
19 | 19 |
func Setgid(gid int) (err error) { |
20 |
- _, _, e1 := syscall.RawSyscall(syscall.SYS_SETGID32, uintptr(gid), 0, 0) |
|
20 |
+ _, _, e1 := unix.RawSyscall(unix.SYS_SETGID32, uintptr(gid), 0, 0) |
|
21 | 21 |
if e1 != 0 { |
22 | 22 |
err = e1 |
23 | 23 |
} |
... | ... |
@@ -3,12 +3,12 @@ |
3 | 3 |
package system |
4 | 4 |
|
5 | 5 |
import ( |
6 |
- "syscall" |
|
6 |
+ "golang.org/x/sys/unix" |
|
7 | 7 |
) |
8 | 8 |
|
9 | 9 |
// Setuid sets the uid of the calling thread to the specified uid. |
10 | 10 |
func Setuid(uid int) (err error) { |
11 |
- _, _, e1 := syscall.RawSyscall(syscall.SYS_SETUID, uintptr(uid), 0, 0) |
|
11 |
+ _, _, e1 := unix.RawSyscall(unix.SYS_SETUID, uintptr(uid), 0, 0) |
|
12 | 12 |
if e1 != 0 { |
13 | 13 |
err = e1 |
14 | 14 |
} |
... | ... |
@@ -17,7 +17,7 @@ func Setuid(uid int) (err error) { |
17 | 17 |
|
18 | 18 |
// Setgid sets the gid of the calling thread to the specified gid. |
19 | 19 |
func Setgid(gid int) (err error) { |
20 |
- _, _, e1 := syscall.RawSyscall(syscall.SYS_SETGID, uintptr(gid), 0, 0) |
|
20 |
+ _, _, e1 := unix.RawSyscall(unix.SYS_SETGID, uintptr(gid), 0, 0) |
|
21 | 21 |
if e1 != 0 { |
22 | 22 |
err = e1 |
23 | 23 |
} |
... | ... |
@@ -3,12 +3,12 @@ |
3 | 3 |
package system |
4 | 4 |
|
5 | 5 |
import ( |
6 |
- "syscall" |
|
6 |
+ "golang.org/x/sys/unix" |
|
7 | 7 |
) |
8 | 8 |
|
9 | 9 |
// Setuid sets the uid of the calling thread to the specified uid. |
10 | 10 |
func Setuid(uid int) (err error) { |
11 |
- _, _, e1 := syscall.RawSyscall(syscall.SYS_SETUID32, uintptr(uid), 0, 0) |
|
11 |
+ _, _, e1 := unix.RawSyscall(unix.SYS_SETUID32, uintptr(uid), 0, 0) |
|
12 | 12 |
if e1 != 0 { |
13 | 13 |
err = e1 |
14 | 14 |
} |
... | ... |
@@ -17,7 +17,7 @@ func Setuid(uid int) (err error) { |
17 | 17 |
|
18 | 18 |
// Setgid sets the gid of the calling thread to the specified gid. |
19 | 19 |
func Setgid(gid int) (err error) { |
20 |
- _, _, e1 := syscall.RawSyscall(syscall.SYS_SETGID32, uintptr(gid), 0, 0) |
|
20 |
+ _, _, e1 := unix.RawSyscall(unix.SYS_SETGID32, uintptr(gid), 0, 0) |
|
21 | 21 |
if e1 != 0 { |
22 | 22 |
err = e1 |
23 | 23 |
} |
... | ... |
@@ -1,99 +1,35 @@ |
1 | 1 |
package system |
2 | 2 |
|
3 |
-import ( |
|
4 |
- "syscall" |
|
5 |
- "unsafe" |
|
6 |
-) |
|
7 |
- |
|
8 |
-var _zero uintptr |
|
9 |
- |
|
10 |
-// Returns the size of xattrs and nil error |
|
11 |
-// Requires path, takes allocated []byte or nil as last argument |
|
12 |
-func Llistxattr(path string, dest []byte) (size int, err error) { |
|
13 |
- pathBytes, err := syscall.BytePtrFromString(path) |
|
14 |
- if err != nil { |
|
15 |
- return -1, err |
|
16 |
- } |
|
17 |
- var newpathBytes unsafe.Pointer |
|
18 |
- if len(dest) > 0 { |
|
19 |
- newpathBytes = unsafe.Pointer(&dest[0]) |
|
20 |
- } else { |
|
21 |
- newpathBytes = unsafe.Pointer(&_zero) |
|
22 |
- } |
|
23 |
- |
|
24 |
- _size, _, errno := syscall.Syscall6(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(newpathBytes), uintptr(len(dest)), 0, 0, 0) |
|
25 |
- size = int(_size) |
|
26 |
- if errno != 0 { |
|
27 |
- return -1, errno |
|
28 |
- } |
|
29 |
- |
|
30 |
- return size, nil |
|
31 |
-} |
|
3 |
+import "golang.org/x/sys/unix" |
|
32 | 4 |
|
33 | 5 |
// Returns a []byte slice if the xattr is set and nil otherwise |
34 | 6 |
// Requires path and its attribute as arguments |
35 | 7 |
func Lgetxattr(path string, attr string) ([]byte, error) { |
36 | 8 |
var sz int |
37 |
- pathBytes, err := syscall.BytePtrFromString(path) |
|
38 |
- if err != nil { |
|
39 |
- return nil, err |
|
40 |
- } |
|
41 |
- attrBytes, err := syscall.BytePtrFromString(attr) |
|
42 |
- if err != nil { |
|
43 |
- return nil, err |
|
44 |
- } |
|
45 |
- |
|
46 | 9 |
// Start with a 128 length byte array |
47 |
- sz = 128 |
|
48 |
- dest := make([]byte, sz) |
|
49 |
- destBytes := unsafe.Pointer(&dest[0]) |
|
50 |
- _sz, _, errno := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0) |
|
10 |
+ dest := make([]byte, 128) |
|
11 |
+ sz, errno := unix.Lgetxattr(path, attr, dest) |
|
51 | 12 |
|
52 | 13 |
switch { |
53 |
- case errno == syscall.ENODATA: |
|
14 |
+ case errno == unix.ENODATA: |
|
54 | 15 |
return nil, errno |
55 |
- case errno == syscall.ENOTSUP: |
|
16 |
+ case errno == unix.ENOTSUP: |
|
56 | 17 |
return nil, errno |
57 |
- case errno == syscall.ERANGE: |
|
18 |
+ case errno == unix.ERANGE: |
|
58 | 19 |
// 128 byte array might just not be good enough, |
59 |
- // A dummy buffer is used ``uintptr(0)`` to get real size |
|
20 |
+ // A dummy buffer is used to get the real size |
|
60 | 21 |
// of the xattrs on disk |
61 |
- _sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(unsafe.Pointer(nil)), uintptr(0), 0, 0) |
|
62 |
- sz = int(_sz) |
|
63 |
- if sz < 0 { |
|
22 |
+ sz, errno = unix.Lgetxattr(path, attr, []byte{}) |
|
23 |
+ if errno != nil { |
|
64 | 24 |
return nil, errno |
65 | 25 |
} |
66 | 26 |
dest = make([]byte, sz) |
67 |
- destBytes := unsafe.Pointer(&dest[0]) |
|
68 |
- _sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0) |
|
69 |
- if errno != 0 { |
|
27 |
+ sz, errno = unix.Lgetxattr(path, attr, dest) |
|
28 |
+ if errno != nil { |
|
70 | 29 |
return nil, errno |
71 | 30 |
} |
72 |
- case errno != 0: |
|
31 |
+ case errno != nil: |
|
73 | 32 |
return nil, errno |
74 | 33 |
} |
75 |
- sz = int(_sz) |
|
76 | 34 |
return dest[:sz], nil |
77 | 35 |
} |
78 |
- |
|
79 |
-func Lsetxattr(path string, attr string, data []byte, flags int) error { |
|
80 |
- pathBytes, err := syscall.BytePtrFromString(path) |
|
81 |
- if err != nil { |
|
82 |
- return err |
|
83 |
- } |
|
84 |
- attrBytes, err := syscall.BytePtrFromString(attr) |
|
85 |
- if err != nil { |
|
86 |
- return err |
|
87 |
- } |
|
88 |
- var dataBytes unsafe.Pointer |
|
89 |
- if len(data) > 0 { |
|
90 |
- dataBytes = unsafe.Pointer(&data[0]) |
|
91 |
- } else { |
|
92 |
- dataBytes = unsafe.Pointer(&_zero) |
|
93 |
- } |
|
94 |
- _, _, errno := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(dataBytes), uintptr(len(data)), uintptr(flags), 0) |
|
95 |
- if errno != 0 { |
|
96 |
- return errno |
|
97 |
- } |
|
98 |
- return nil |
|
99 |
-} |
... | ... |
@@ -2,7 +2,6 @@ package user |
2 | 2 |
|
3 | 3 |
import ( |
4 | 4 |
"errors" |
5 |
- "syscall" |
|
6 | 5 |
) |
7 | 6 |
|
8 | 7 |
var ( |
... | ... |
@@ -36,13 +35,6 @@ func lookupUser(filter func(u User) bool) (User, error) { |
36 | 36 |
return users[0], nil |
37 | 37 |
} |
38 | 38 |
|
39 |
-// CurrentUser looks up the current user by their user id in /etc/passwd. If the |
|
40 |
-// user cannot be found (or there is no /etc/passwd file on the filesystem), |
|
41 |
-// then CurrentUser returns an error. |
|
42 |
-func CurrentUser() (User, error) { |
|
43 |
- return LookupUid(syscall.Getuid()) |
|
44 |
-} |
|
45 |
- |
|
46 | 39 |
// LookupUser looks up a user by their username in /etc/passwd. If the user |
47 | 40 |
// cannot be found (or there is no /etc/passwd file on the filesystem), then |
48 | 41 |
// LookupUser returns an error. |
... | ... |
@@ -84,13 +76,6 @@ func lookupGroup(filter func(g Group) bool) (Group, error) { |
84 | 84 |
return groups[0], nil |
85 | 85 |
} |
86 | 86 |
|
87 |
-// CurrentGroup looks up the current user's group by their primary group id's |
|
88 |
-// entry in /etc/passwd. If the group cannot be found (or there is no |
|
89 |
-// /etc/group file on the filesystem), then CurrentGroup returns an error. |
|
90 |
-func CurrentGroup() (Group, error) { |
|
91 |
- return LookupGid(syscall.Getgid()) |
|
92 |
-} |
|
93 |
- |
|
94 | 87 |
// LookupGroup looks up a group by its name in /etc/group. If the group cannot |
95 | 88 |
// be found (or there is no /etc/group file on the filesystem), then LookupGroup |
96 | 89 |
// returns an error. |
... | ... |
@@ -5,6 +5,8 @@ package user |
5 | 5 |
import ( |
6 | 6 |
"io" |
7 | 7 |
"os" |
8 |
+ |
|
9 |
+ "golang.org/x/sys/unix" |
|
8 | 10 |
) |
9 | 11 |
|
10 | 12 |
// Unix-specific path to the passwd and group formatted files. |
... | ... |
@@ -28,3 +30,17 @@ func GetGroupPath() (string, error) { |
28 | 28 |
func GetGroup() (io.ReadCloser, error) { |
29 | 29 |
return os.Open(unixGroupPath) |
30 | 30 |
} |
31 |
+ |
|
32 |
+// CurrentUser looks up the current user by their user id in /etc/passwd. If the |
|
33 |
+// user cannot be found (or there is no /etc/passwd file on the filesystem), |
|
34 |
+// then CurrentUser returns an error. |
|
35 |
+func CurrentUser() (User, error) { |
|
36 |
+ return LookupUid(unix.Getuid()) |
|
37 |
+} |
|
38 |
+ |
|
39 |
+// CurrentGroup looks up the current user's group by their primary group id's |
|
40 |
+// entry in /etc/passwd. If the group cannot be found (or there is no |
|
41 |
+// /etc/group file on the filesystem), then CurrentGroup returns an error. |
|
42 |
+func CurrentGroup() (Group, error) { |
|
43 |
+ return LookupGid(unix.Getgid()) |
|
44 |
+} |
... | ... |
@@ -2,7 +2,10 @@ |
2 | 2 |
|
3 | 3 |
package user |
4 | 4 |
|
5 |
-import "io" |
|
5 |
+import ( |
|
6 |
+ "io" |
|
7 |
+ "syscall" |
|
8 |
+) |
|
6 | 9 |
|
7 | 10 |
func GetPasswdPath() (string, error) { |
8 | 11 |
return "", ErrUnsupported |
... | ... |
@@ -19,3 +22,17 @@ func GetGroupPath() (string, error) { |
19 | 19 |
func GetGroup() (io.ReadCloser, error) { |
20 | 20 |
return nil, ErrUnsupported |
21 | 21 |
} |
22 |
+ |
|
23 |
+// CurrentUser looks up the current user by their user id in /etc/passwd. If the |
|
24 |
+// user cannot be found (or there is no /etc/passwd file on the filesystem), |
|
25 |
+// then CurrentUser returns an error. |
|
26 |
+func CurrentUser() (User, error) { |
|
27 |
+ return LookupUid(syscall.Getuid()) |
|
28 |
+} |
|
29 |
+ |
|
30 |
+// CurrentGroup looks up the current user's group by their primary group id's |
|
31 |
+// entry in /etc/passwd. If the group cannot be found (or there is no |
|
32 |
+// /etc/group file on the filesystem), then CurrentGroup returns an error. |
|
33 |
+func CurrentGroup() (Group, error) { |
|
34 |
+ return LookupGid(syscall.Getgid()) |
|
35 |
+} |
... | ... |
@@ -1,21 +1,21 @@ |
1 | 1 |
# OCI runtime-spec. When updating this, make sure you use a version tag rather |
2 | 2 |
# than a commit ID so it's much more obvious what version of the spec we are |
3 | 3 |
# using. |
4 |
-github.com/opencontainers/runtime-spec v1.0.0-rc5 |
|
4 |
+github.com/opencontainers/runtime-spec v1.0.0 |
|
5 | 5 |
# Core libcontainer functionality. |
6 | 6 |
github.com/mrunalp/fileutils ed869b029674c0e9ce4c0dfa781405c2d9946d08 |
7 | 7 |
github.com/opencontainers/selinux v1.0.0-rc1 |
8 | 8 |
github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0 |
9 |
-github.com/Sirupsen/logrus 26709e2714106fb8ad40b773b711ebce25b78914 |
|
10 |
-github.com/syndtr/gocapability e7cb7fa329f456b3855136a2642b197bad7366ba |
|
9 |
+github.com/sirupsen/logrus a3f95b5c423586578a4e099b11a46c2479628cac |
|
10 |
+github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16 |
|
11 | 11 |
github.com/vishvananda/netlink 1e2e08e8a2dcdacaae3f14ac44c5cfa31361f270 |
12 | 12 |
# systemd integration. |
13 | 13 |
github.com/coreos/go-systemd v14 |
14 | 14 |
github.com/coreos/pkg v3 |
15 | 15 |
github.com/godbus/dbus v3 |
16 |
-github.com/golang/protobuf f7137ae6b19afbfd61a94b746fda3b3fe0491874 |
|
16 |
+github.com/golang/protobuf 18c9bb3261723cd5401db4d0c9fbc5c3b6c70fe8 |
|
17 | 17 |
# Command-line interface. |
18 | 18 |
github.com/docker/docker 0f5c9d301b9b1cca66b3ea0f9dec3b5317d3686d |
19 | 19 |
github.com/docker/go-units v0.2.0 |
20 | 20 |
github.com/urfave/cli d53eb991652b1d438abdd34ce4bfa3ef1539108e |
21 |
-golang.org/x/sys 9a7256cb28ed514b4e1e5f68959914c4c28a92e0 https://github.com/golang/sys |
|
21 |
+golang.org/x/sys 0e0164865330d5cf1c00247be08330bf96e2f87c https://github.com/golang/sys |
... | ... |
@@ -10,7 +10,6 @@ Additional documentation about how this group operates: |
10 | 10 |
|
11 | 11 |
- [Code of Conduct][code-of-conduct] |
12 | 12 |
- [Style and Conventions](style.md) |
13 |
-- [Roadmap](ROADMAP.md) |
|
14 | 13 |
- [Implementations](implementations.md) |
15 | 14 |
- [Releases](RELEASES.md) |
16 | 15 |
- [project](project.md) |
... | ... |
@@ -33,12 +32,7 @@ Example use cases include sophisticated network configuration, volume garbage co |
33 | 33 |
|
34 | 34 |
### Runtime Developers |
35 | 35 |
|
36 |
-Runtime developers can build runtime implementations that run OCI-compliant bundles and container configuration, containing low-level OS and host specific details, on a particular platform. |
|
37 |
- |
|
38 |
-## Releases |
|
39 |
- |
|
40 |
-There is a loose [Road Map](./ROADMAP.md). |
|
41 |
-During the `0.x` series of OCI releases we make no backwards compatibility guarantees and intend to break the schema during this series. |
|
36 |
+Runtime developers can build runtime implementations that run OCI-compliant bundles and container configuration, containing low-level OS and host-specific details, on a particular platform. |
|
42 | 37 |
|
43 | 38 |
## Contributing |
44 | 39 |
|
... | ... |
@@ -63,7 +57,7 @@ When in doubt, start on the [mailing-list](#mailing-list). |
63 | 63 |
The contributors and maintainers of all OCI projects have a weekly meeting on Wednesdays at: |
64 | 64 |
|
65 | 65 |
* 8:00 AM (USA Pacific), during [odd weeks][iso-week]. |
66 |
-* 5:00 PM (USA Pacific), during [even weeks][iso-week]. |
|
66 |
+* 2:00 PM (USA Pacific), during [even weeks][iso-week]. |
|
67 | 67 |
|
68 | 68 |
There is an [iCalendar][rfc5545] format for the meetings [here](meeting.ics). |
69 | 69 |
|
... | ... |
@@ -145,7 +139,7 @@ Read more on [How to Write a Git Commit Message][how-to-git-commit] or the Discu |
145 | 145 |
5. Use the imperative mood in the subject line |
146 | 146 |
6. Wrap the body at 72 characters |
147 | 147 |
7. Use the body to explain what and why vs. how |
148 |
- * If there was important/useful/essential conversation or information, copy or include a reference |
|
148 |
+ * If there was important/useful/essential conversation or information, copy or include a reference |
|
149 | 149 |
8. When possible, one keyword to scope the change in the subject (i.e. "README: ...", "runtime: ...") |
150 | 150 |
|
151 | 151 |
|
... | ... |
@@ -6,26 +6,24 @@ import "os" |
6 | 6 |
type Spec struct { |
7 | 7 |
// Version of the Open Container Runtime Specification with which the bundle complies. |
8 | 8 |
Version string `json:"ociVersion"` |
9 |
- // Platform specifies the configuration's target platform. |
|
10 |
- Platform Platform `json:"platform"` |
|
11 | 9 |
// Process configures the container process. |
12 |
- Process Process `json:"process"` |
|
10 |
+ Process *Process `json:"process,omitempty"` |
|
13 | 11 |
// Root configures the container's root filesystem. |
14 |
- Root Root `json:"root"` |
|
12 |
+ Root *Root `json:"root,omitempty"` |
|
15 | 13 |
// Hostname configures the container's hostname. |
16 | 14 |
Hostname string `json:"hostname,omitempty"` |
17 | 15 |
// Mounts configures additional mounts (on top of Root). |
18 | 16 |
Mounts []Mount `json:"mounts,omitempty"` |
19 | 17 |
// Hooks configures callbacks for container lifecycle events. |
20 |
- Hooks *Hooks `json:"hooks,omitempty"` |
|
18 |
+ Hooks *Hooks `json:"hooks,omitempty" platform:"linux,solaris"` |
|
21 | 19 |
// Annotations contains arbitrary metadata for the container. |
22 | 20 |
Annotations map[string]string `json:"annotations,omitempty"` |
23 | 21 |
|
24 |
- // Linux is platform specific configuration for Linux based containers. |
|
22 |
+ // Linux is platform-specific configuration for Linux based containers. |
|
25 | 23 |
Linux *Linux `json:"linux,omitempty" platform:"linux"` |
26 |
- // Solaris is platform specific configuration for Solaris containers. |
|
24 |
+ // Solaris is platform-specific configuration for Solaris based containers. |
|
27 | 25 |
Solaris *Solaris `json:"solaris,omitempty" platform:"solaris"` |
28 |
- // Windows is platform specific configuration for Windows based containers, including Hyper-V containers. |
|
26 |
+ // Windows is platform-specific configuration for Windows based containers. |
|
29 | 27 |
Windows *Windows `json:"windows,omitempty" platform:"windows"` |
30 | 28 |
} |
31 | 29 |
|
... | ... |
@@ -34,7 +32,7 @@ type Process struct { |
34 | 34 |
// Terminal creates an interactive terminal for the container. |
35 | 35 |
Terminal bool `json:"terminal,omitempty"` |
36 | 36 |
// ConsoleSize specifies the size of the console. |
37 |
- ConsoleSize Box `json:"consoleSize,omitempty"` |
|
37 |
+ ConsoleSize *Box `json:"consoleSize,omitempty"` |
|
38 | 38 |
// User specifies user information for the process. |
39 | 39 |
User User `json:"user"` |
40 | 40 |
// Args specifies the binary and arguments for the application to execute. |
... | ... |
@@ -47,11 +45,13 @@ type Process struct { |
47 | 47 |
// Capabilities are Linux capabilities that are kept for the process. |
48 | 48 |
Capabilities *LinuxCapabilities `json:"capabilities,omitempty" platform:"linux"` |
49 | 49 |
// Rlimits specifies rlimit options to apply to the process. |
50 |
- Rlimits []LinuxRlimit `json:"rlimits,omitempty" platform:"linux"` |
|
50 |
+ Rlimits []POSIXRlimit `json:"rlimits,omitempty" platform:"linux,solaris"` |
|
51 | 51 |
// NoNewPrivileges controls whether additional privileges could be gained by processes in the container. |
52 | 52 |
NoNewPrivileges bool `json:"noNewPrivileges,omitempty" platform:"linux"` |
53 | 53 |
// ApparmorProfile specifies the apparmor profile for the container. |
54 | 54 |
ApparmorProfile string `json:"apparmorProfile,omitempty" platform:"linux"` |
55 |
+ // Specify an oom_score_adj for the container. |
|
56 |
+ OOMScoreAdj *int `json:"oomScoreAdj,omitempty" platform:"linux"` |
|
55 | 57 |
// SelinuxLabel specifies the selinux context that the container process is run as. |
56 | 58 |
SelinuxLabel string `json:"selinuxLabel,omitempty" platform:"linux"` |
57 | 59 |
} |
... | ... |
@@ -99,23 +99,13 @@ type Root struct { |
99 | 99 |
Readonly bool `json:"readonly,omitempty"` |
100 | 100 |
} |
101 | 101 |
|
102 |
-// Platform specifies OS and arch information for the host system that the container |
|
103 |
-// is created for. |
|
104 |
-type Platform struct { |
|
105 |
- // OS is the operating system. |
|
106 |
- OS string `json:"os"` |
|
107 |
- // Arch is the architecture |
|
108 |
- Arch string `json:"arch"` |
|
109 |
-} |
|
110 |
- |
|
111 | 102 |
// Mount specifies a mount for a container. |
112 | 103 |
type Mount struct { |
113 |
- // Destination is the path where the mount will be placed relative to the container's root. The path and child directories MUST exist, a runtime MUST NOT create directories automatically to a mount point. |
|
104 |
+ // Destination is the absolute path where the mount will be placed in the container. |
|
114 | 105 |
Destination string `json:"destination"` |
115 | 106 |
// Type specifies the mount kind. |
116 |
- Type string `json:"type,omitempty"` |
|
117 |
- // Source specifies the source path of the mount. In the case of bind mounts on |
|
118 |
- // Linux based systems this would be the file on the host. |
|
107 |
+ Type string `json:"type,omitempty" platform:"linux,solaris"` |
|
108 |
+ // Source specifies the source path of the mount. |
|
119 | 109 |
Source string `json:"source,omitempty"` |
120 | 110 |
// Options are fstab style mount options. |
121 | 111 |
Options []string `json:"options,omitempty"` |
... | ... |
@@ -132,7 +122,6 @@ type Hook struct { |
132 | 132 |
// Hooks for container setup and teardown |
133 | 133 |
type Hooks struct { |
134 | 134 |
// Prestart is a list of hooks to be run before the container process is executed. |
135 |
- // On Linux, they are run after the container namespaces are created. |
|
136 | 135 |
Prestart []Hook `json:"prestart,omitempty"` |
137 | 136 |
// Poststart is a list of hooks to be run after the container process is started. |
138 | 137 |
Poststart []Hook `json:"poststart,omitempty"` |
... | ... |
@@ -140,11 +129,11 @@ type Hooks struct { |
140 | 140 |
Poststop []Hook `json:"poststop,omitempty"` |
141 | 141 |
} |
142 | 142 |
|
143 |
-// Linux contains platform specific configuration for Linux based containers. |
|
143 |
+// Linux contains platform-specific configuration for Linux based containers. |
|
144 | 144 |
type Linux struct { |
145 |
- // UIDMapping specifies user mappings for supporting user namespaces on Linux. |
|
145 |
+ // UIDMapping specifies user mappings for supporting user namespaces. |
|
146 | 146 |
UIDMappings []LinuxIDMapping `json:"uidMappings,omitempty"` |
147 |
- // GIDMapping specifies group mappings for supporting user namespaces on Linux. |
|
147 |
+ // GIDMapping specifies group mappings for supporting user namespaces. |
|
148 | 148 |
GIDMappings []LinuxIDMapping `json:"gidMappings,omitempty"` |
149 | 149 |
// Sysctl are a set of key value pairs that are set for the container on start |
150 | 150 |
Sysctl map[string]string `json:"sysctl,omitempty"` |
... | ... |
@@ -176,7 +165,7 @@ type Linux struct { |
176 | 176 |
|
177 | 177 |
// LinuxNamespace is the configuration for a Linux namespace |
178 | 178 |
type LinuxNamespace struct { |
179 |
- // Type is the type of Linux namespace |
|
179 |
+ // Type is the type of namespace |
|
180 | 180 |
Type LinuxNamespaceType `json:"type"` |
181 | 181 |
// Path is a path to an existing namespace persisted on disk that can be joined |
182 | 182 |
// and is of the same type |
... | ... |
@@ -213,8 +202,8 @@ type LinuxIDMapping struct { |
213 | 213 |
Size uint32 `json:"size"` |
214 | 214 |
} |
215 | 215 |
|
216 |
-// LinuxRlimit type and restrictions |
|
217 |
-type LinuxRlimit struct { |
|
216 |
+// POSIXRlimit type and restrictions |
|
217 |
+type POSIXRlimit struct { |
|
218 | 218 |
// Type of the rlimit to set |
219 | 219 |
Type string `json:"type"` |
220 | 220 |
// Hard is the hard limit for the specified type |
... | ... |
@@ -247,7 +236,7 @@ type linuxBlockIODevice struct { |
247 | 247 |
Minor int64 `json:"minor"` |
248 | 248 |
} |
249 | 249 |
|
250 |
-// LinuxWeightDevice struct holds a `major:minor weight` pair for blkioWeightDevice |
|
250 |
+// LinuxWeightDevice struct holds a `major:minor weight` pair for weightDevice |
|
251 | 251 |
type LinuxWeightDevice struct { |
252 | 252 |
linuxBlockIODevice |
253 | 253 |
// Weight is the bandwidth rate for the device. |
... | ... |
@@ -266,35 +255,37 @@ type LinuxThrottleDevice struct { |
266 | 266 |
// LinuxBlockIO for Linux cgroup 'blkio' resource management |
267 | 267 |
type LinuxBlockIO struct { |
268 | 268 |
// Specifies per cgroup weight |
269 |
- Weight *uint16 `json:"blkioWeight,omitempty"` |
|
269 |
+ Weight *uint16 `json:"weight,omitempty"` |
|
270 | 270 |
// Specifies tasks' weight in the given cgroup while competing with the cgroup's child cgroups, CFQ scheduler only |
271 |
- LeafWeight *uint16 `json:"blkioLeafWeight,omitempty"` |
|
271 |
+ LeafWeight *uint16 `json:"leafWeight,omitempty"` |
|
272 | 272 |
// Weight per cgroup per device, can override BlkioWeight |
273 |
- WeightDevice []LinuxWeightDevice `json:"blkioWeightDevice,omitempty"` |
|
273 |
+ WeightDevice []LinuxWeightDevice `json:"weightDevice,omitempty"` |
|
274 | 274 |
// IO read rate limit per cgroup per device, bytes per second |
275 |
- ThrottleReadBpsDevice []LinuxThrottleDevice `json:"blkioThrottleReadBpsDevice,omitempty"` |
|
275 |
+ ThrottleReadBpsDevice []LinuxThrottleDevice `json:"throttleReadBpsDevice,omitempty"` |
|
276 | 276 |
// IO write rate limit per cgroup per device, bytes per second |
277 |
- ThrottleWriteBpsDevice []LinuxThrottleDevice `json:"blkioThrottleWriteBpsDevice,omitempty"` |
|
277 |
+ ThrottleWriteBpsDevice []LinuxThrottleDevice `json:"throttleWriteBpsDevice,omitempty"` |
|
278 | 278 |
// IO read rate limit per cgroup per device, IO per second |
279 |
- ThrottleReadIOPSDevice []LinuxThrottleDevice `json:"blkioThrottleReadIOPSDevice,omitempty"` |
|
279 |
+ ThrottleReadIOPSDevice []LinuxThrottleDevice `json:"throttleReadIOPSDevice,omitempty"` |
|
280 | 280 |
// IO write rate limit per cgroup per device, IO per second |
281 |
- ThrottleWriteIOPSDevice []LinuxThrottleDevice `json:"blkioThrottleWriteIOPSDevice,omitempty"` |
|
281 |
+ ThrottleWriteIOPSDevice []LinuxThrottleDevice `json:"throttleWriteIOPSDevice,omitempty"` |
|
282 | 282 |
} |
283 | 283 |
|
284 | 284 |
// LinuxMemory for Linux cgroup 'memory' resource management |
285 | 285 |
type LinuxMemory struct { |
286 | 286 |
// Memory limit (in bytes). |
287 |
- Limit *uint64 `json:"limit,omitempty"` |
|
287 |
+ Limit *int64 `json:"limit,omitempty"` |
|
288 | 288 |
// Memory reservation or soft_limit (in bytes). |
289 |
- Reservation *uint64 `json:"reservation,omitempty"` |
|
289 |
+ Reservation *int64 `json:"reservation,omitempty"` |
|
290 | 290 |
// Total memory limit (memory + swap). |
291 |
- Swap *uint64 `json:"swap,omitempty"` |
|
291 |
+ Swap *int64 `json:"swap,omitempty"` |
|
292 | 292 |
// Kernel memory limit (in bytes). |
293 |
- Kernel *uint64 `json:"kernel,omitempty"` |
|
293 |
+ Kernel *int64 `json:"kernel,omitempty"` |
|
294 | 294 |
// Kernel memory limit for tcp (in bytes) |
295 |
- KernelTCP *uint64 `json:"kernelTCP,omitempty"` |
|
296 |
- // How aggressive the kernel will swap memory pages. Range from 0 to 100. |
|
295 |
+ KernelTCP *int64 `json:"kernelTCP,omitempty"` |
|
296 |
+ // How aggressive the kernel will swap memory pages. |
|
297 | 297 |
Swappiness *uint64 `json:"swappiness,omitempty"` |
298 |
+ // DisableOOMKiller disables the OOM killer for out of memory conditions |
|
299 |
+ DisableOOMKiller *bool `json:"disableOOMKiller,omitempty"` |
|
298 | 300 |
} |
299 | 301 |
|
300 | 302 |
// LinuxCPU for Linux cgroup 'cpu' resource management |
... | ... |
@@ -333,10 +324,6 @@ type LinuxNetwork struct { |
333 | 333 |
type LinuxResources struct { |
334 | 334 |
// Devices configures the device whitelist. |
335 | 335 |
Devices []LinuxDeviceCgroup `json:"devices,omitempty"` |
336 |
- // DisableOOMKiller disables the OOM killer for out of memory conditions |
|
337 |
- DisableOOMKiller *bool `json:"disableOOMKiller,omitempty"` |
|
338 |
- // Specify an oom_score_adj for the container. |
|
339 |
- OOMScoreAdj *int `json:"oomScoreAdj,omitempty"` |
|
340 | 336 |
// Memory restriction configuration |
341 | 337 |
Memory *LinuxMemory `json:"memory,omitempty"` |
342 | 338 |
// CPU resource restriction configuration |
... | ... |
@@ -383,7 +370,7 @@ type LinuxDeviceCgroup struct { |
383 | 383 |
Access string `json:"access,omitempty"` |
384 | 384 |
} |
385 | 385 |
|
386 |
-// Solaris contains platform specific configuration for Solaris application containers. |
|
386 |
+// Solaris contains platform-specific configuration for Solaris application containers. |
|
387 | 387 |
type Solaris struct { |
388 | 388 |
// SMF FMRI which should go "online" before we start the container process. |
389 | 389 |
Milestone string `json:"milestone,omitempty"` |
... | ... |
@@ -430,8 +417,20 @@ type SolarisAnet struct { |
430 | 430 |
|
431 | 431 |
// Windows defines the runtime configuration for Windows based containers, including Hyper-V containers. |
432 | 432 |
type Windows struct { |
433 |
+ // LayerFolders contains a list of absolute paths to directories containing image layers. |
|
434 |
+ LayerFolders []string `json:"layerFolders"` |
|
433 | 435 |
// Resources contains information for handling resource constraints for the container. |
434 | 436 |
Resources *WindowsResources `json:"resources,omitempty"` |
437 |
+ // CredentialSpec contains a JSON object describing a group Managed Service Account (gMSA) specification. |
|
438 |
+ CredentialSpec interface{} `json:"credentialSpec,omitempty"` |
|
439 |
+ // Servicing indicates if the container is being started in a mode to apply a Windows Update servicing operation. |
|
440 |
+ Servicing bool `json:"servicing,omitempty"` |
|
441 |
+ // IgnoreFlushesDuringBoot indicates if the container is being started in a mode where disk writes are not flushed during its boot process. |
|
442 |
+ IgnoreFlushesDuringBoot bool `json:"ignoreFlushesDuringBoot,omitempty"` |
|
443 |
+ // HyperV contains information for running a container with Hyper-V isolation. |
|
444 |
+ HyperV *WindowsHyperV `json:"hyperv,omitempty"` |
|
445 |
+ // Network restriction configuration. |
|
446 |
+ Network *WindowsNetwork `json:"network,omitempty"` |
|
435 | 447 |
} |
436 | 448 |
|
437 | 449 |
// WindowsResources has container runtime resource constraints for containers running on Windows. |
... | ... |
@@ -442,23 +441,19 @@ type WindowsResources struct { |
442 | 442 |
CPU *WindowsCPUResources `json:"cpu,omitempty"` |
443 | 443 |
// Storage restriction configuration. |
444 | 444 |
Storage *WindowsStorageResources `json:"storage,omitempty"` |
445 |
- // Network restriction configuration. |
|
446 |
- Network *WindowsNetworkResources `json:"network,omitempty"` |
|
447 | 445 |
} |
448 | 446 |
|
449 | 447 |
// WindowsMemoryResources contains memory resource management settings. |
450 | 448 |
type WindowsMemoryResources struct { |
451 | 449 |
// Memory limit in bytes. |
452 | 450 |
Limit *uint64 `json:"limit,omitempty"` |
453 |
- // Memory reservation in bytes. |
|
454 |
- Reservation *uint64 `json:"reservation,omitempty"` |
|
455 | 451 |
} |
456 | 452 |
|
457 | 453 |
// WindowsCPUResources contains CPU resource management settings. |
458 | 454 |
type WindowsCPUResources struct { |
459 | 455 |
// Number of CPUs available to the container. |
460 | 456 |
Count *uint64 `json:"count,omitempty"` |
461 |
- // CPU shares (relative weight to other containers with cpu shares). Range is from 1 to 10000. |
|
457 |
+ // CPU shares (relative weight to other containers with cpu shares). |
|
462 | 458 |
Shares *uint16 `json:"shares,omitempty"` |
463 | 459 |
// Specifies the portion of processor cycles that this container can use as a percentage times 100. |
464 | 460 |
Maximum *uint16 `json:"maximum,omitempty"` |
... | ... |
@@ -474,10 +469,22 @@ type WindowsStorageResources struct { |
474 | 474 |
SandboxSize *uint64 `json:"sandboxSize,omitempty"` |
475 | 475 |
} |
476 | 476 |
|
477 |
-// WindowsNetworkResources contains network resource management settings. |
|
478 |
-type WindowsNetworkResources struct { |
|
479 |
- // EgressBandwidth is the maximum egress bandwidth in bytes per second. |
|
480 |
- EgressBandwidth *uint64 `json:"egressBandwidth,omitempty"` |
|
477 |
+// WindowsNetwork contains network settings for Windows containers. |
|
478 |
+type WindowsNetwork struct { |
|
479 |
+ // List of HNS endpoints that the container should connect to. |
|
480 |
+ EndpointList []string `json:"endpointList,omitempty"` |
|
481 |
+ // Specifies if unqualified DNS name resolution is allowed. |
|
482 |
+ AllowUnqualifiedDNSQuery bool `json:"allowUnqualifiedDNSQuery,omitempty"` |
|
483 |
+ // Comma separated list of DNS suffixes to use for name resolution. |
|
484 |
+ DNSSearchList []string `json:"DNSSearchList,omitempty"` |
|
485 |
+ // Name (ID) of the container that we will share with the network stack. |
|
486 |
+ NetworkSharedContainerName string `json:"networkSharedContainerName,omitempty"` |
|
487 |
+} |
|
488 |
+ |
|
489 |
+// WindowsHyperV contains information for configuring a container to run with Hyper-V isolation. |
|
490 |
+type WindowsHyperV struct { |
|
491 |
+ // UtilityVMPath is an optional path to the image used for the Utility VM. |
|
492 |
+ UtilityVMPath string `json:"utilityVMPath,omitempty"` |
|
481 | 493 |
} |
482 | 494 |
|
483 | 495 |
// LinuxSeccomp represents syscall restrictions |
... | ... |
@@ -543,7 +550,7 @@ const ( |
543 | 543 |
type LinuxSeccompArg struct { |
544 | 544 |
Index uint `json:"index"` |
545 | 545 |
Value uint64 `json:"value"` |
546 |
- ValueTwo uint64 `json:"valueTwo"` |
|
546 |
+ ValueTwo uint64 `json:"valueTwo,omitempty"` |
|
547 | 547 |
Op LinuxSeccompOperator `json:"op"` |
548 | 548 |
} |
549 | 549 |
|
... | ... |
@@ -9,7 +9,7 @@ type State struct { |
9 | 9 |
// Status is the runtime status of the container. |
10 | 10 |
Status string `json:"status"` |
11 | 11 |
// Pid is the process ID for the container process. |
12 |
- Pid int `json:"pid"` |
|
12 |
+ Pid int `json:"pid,omitempty"` |
|
13 | 13 |
// Bundle is the path to the container's bundle directory. |
14 | 14 |
Bundle string `json:"bundle"` |
15 | 15 |
// Annotations are key values associated with the container. |