Browse code

Merge pull request #34356 from mlaventure/update-containerd

Update containerd to 06b9cb35161009dcb7123345749fef02f7cea8e0

John Howard authored on 2017/08/25 06:25:44
Showing 58 changed files
... ...
@@ -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
... ...
@@ -8,5 +8,5 @@ type (
8 8
 	// Spec aliases the platform oci spec
9 9
 	Spec oci.Spec
10 10
 	// Rlimit aliases the platform resource limit
11
-	Rlimit oci.LinuxRlimit
11
+	Rlimit oci.POSIXRlimit
12 12
 )
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
-}
... ...
@@ -8,6 +8,7 @@ import (
8 8
 	"time"
9 9
 
10 10
 	"github.com/opencontainers/runtime-spec/specs-go"
11
+
11 12
 	"github.com/sirupsen/logrus"
12 13
 )
13 14
 
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
-}
... ...
@@ -1,4 +1,4 @@
1
-// +build !linux,!freebsd
1
+// +build !linux
2 2
 
3 3
 package configs
4 4
 
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
-}
... ...
@@ -1,3 +1,3 @@
1
-// +build windows
1
+// +build !linux
2 2
 
3 3
 package devices
... ...
@@ -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.
... ...
@@ -11,7 +11,7 @@ const (
11 11
 	VersionPatch = 0
12 12
 
13 13
 	// VersionDev indicates development branch. Releases will be empty string.
14
-	VersionDev = "-rc5-dev"
14
+	VersionDev = ""
15 15
 )
16 16
 
17 17
 // Version is the specification version that the package types support.