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