Upgrade docker (#2440)

* somehow now the only thing that doesnt work is devices.Device

Signed-off-by: Joe Kimmel <jkimmel@vmware.com>

* this gets rid of all the compiler errors in the vendored code

Signed-off-by: Joe Kimmel <jkimmel@vmware.com>

* fixed some things but a bunch of tests and maybe some compiler steps are still failing

Signed-off-by: Joe Kimmel <jkimmel@vmware.com>

* all the things i figured out how to fix so far

Signed-off-by: Joe Kimmel <jkimmel@vmware.com>

* guess i had to redo go mods after rebasing again

Signed-off-by: Joe Kimmel <jkimmel@vmware.com>

* update docker constants to be SHOUTY CASE now

Signed-off-by: Joe Kimmel <jkimmel@vmware.com>

* include DestPath in resolveEnv

Signed-off-by: Joe Kimmel <jkimmel@vmware.com>

* fix one mistake in Docker lib upgrade and some typos/deprecations in the file

Signed-off-by: Joe Kimmel <jkimmel@vmware.com>

* last changes (hopefully) to update to new docker libs

Signed-off-by: Joe Kimmel <jkimmel@vmware.com>

---------

Signed-off-by: Joe Kimmel <jkimmel@vmware.com>
This commit is contained in:
Joe Kimmel
2023-03-23 20:34:25 -04:00
committed by GitHub
parent 86a73c5439
commit 906cc96b59
1356 changed files with 96735 additions and 72375 deletions
+58 -3
View File
@@ -9,7 +9,7 @@ Go package for creating, managing, inspecting, and destroying cgroups.
The resources format for settings on the cgroup uses the OCI runtime-spec found
[here](https://github.com/opencontainers/runtime-spec).
## Examples
## Examples (v1)
### Create a new cgroup
@@ -26,7 +26,7 @@ uses the v1 implementation of cgroups.
```go
shares := uint64(100)
control, err := cgroups.New(cgroups.V1, cgroups.StaticPath("/test"), &specs.LinuxResources{
CPU: &specs.CPU{
CPU: &specs.LinuxCPU{
Shares: &shares,
},
})
@@ -58,7 +58,7 @@ if err := control.Add(cgroups.Process{Pid:1234}); err != nil {
}
```
### Update the cgroup
### Update the cgroup
To update the resources applied in the cgroup
@@ -133,6 +133,61 @@ event := cgroups.OOMEvent()
efd, err := control.RegisterMemoryEvent(event)
```
## Examples (v2/unified)
### Check that the current system is running cgroups v2
```go
var cgroupV2 bool
if cgroups.Mode() == cgroups.Unified {
cgroupV2 = true
}
```
### Create a new cgroup
This creates a new systemd v2 cgroup slice. Systemd slices consider ["-" a special character](https://www.freedesktop.org/software/systemd/man/systemd.slice.html),
so the resulting slice would be located here on disk:
* /sys/fs/cgroup/my.slice/my-cgroup.slice/my-cgroup-abc.slice
```go
import (
cgroupsv2 "github.com/containerd/cgroups/v2"
specs "github.com/opencontainers/runtime-spec/specs-go"
)
res := cgroupsv2.Resources{}
// dummy PID of -1 is used for creating a "general slice" to be used as a parent cgroup.
// see https://github.com/containerd/cgroups/blob/1df78138f1e1e6ee593db155c6b369466f577651/v2/manager.go#L732-L735
m, err := cgroupsv2.NewSystemd("/", "my-cgroup-abc.slice", -1, &res)
if err != nil {
return err
}
```
### Load an existing cgroup
```go
m, err := cgroupsv2.LoadSystemd("/", "my-cgroup-abc.slice")
if err != nil {
return err
}
```
### Delete a cgroup
```go
m, err := cgroupsv2.LoadSystemd("/", "my-cgroup-abc.slice")
if err != nil {
return err
}
err = m.DeleteSystemd()
if err != nil {
return err
}
```
### Attention
All static path should not include `/sys/fs/cgroup/` prefix, it should start with your own cgroups name
-46
View File
@@ -1,46 +0,0 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
# Fedora box is used for testing cgroup v2 support
config.vm.box = "fedora/32-cloud-base"
config.vm.provider :virtualbox do |v|
v.memory = 2048
v.cpus = 2
end
config.vm.provider :libvirt do |v|
v.memory = 2048
v.cpus = 2
end
config.vm.provision "shell", inline: <<-SHELL
set -eux -o pipefail
# configuration
GO_VERSION="1.15"
# install gcc and Golang
dnf -y install gcc
curl -fsSL "https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz" | tar Cxz /usr/local
# setup env vars
cat >> /etc/profile.d/sh.local <<EOF
PATH=/usr/local/go/bin:$PATH
GO111MODULE=on
export PATH GO111MODULE
EOF
source /etc/profile.d/sh.local
# enter /root/go/src/github.com/containerd/cgroups
mkdir -p /root/go/src/github.com/containerd
ln -s /vagrant /root/go/src/github.com/containerd/cgroups
cd /root/go/src/github.com/containerd/cgroups
# create /test.sh
cat > /test.sh <<EOF
#!/bin/bash
set -eux -o pipefail
cd /root/go/src/github.com/containerd/cgroups
go test -v ./...
EOF
chmod +x /test.sh
SHELL
end
+11 -1
View File
@@ -84,7 +84,7 @@ func Load(hierarchy Hierarchy, path Path, opts ...InitOpts) (Cgroup, error) {
for _, s := range pathers(subsystems) {
p, err := path(s.Name())
if err != nil {
if errors.Is(err, os.ErrNotExist) {
if errors.Is(err, os.ErrNotExist) {
return nil, ErrCgroupDeleted
}
if err == ErrControllerNotActive {
@@ -228,6 +228,15 @@ func (c *cgroup) Delete() error {
}
var errs []string
for _, s := range c.subsystems {
// kernel prevents cgroups with running process from being removed, check the tree is empty
procs, err := c.processes(s.Name(), true, cgroupProcs)
if err != nil {
return err
}
if len(procs) > 0 {
errs = append(errs, fmt.Sprintf("%s (contains running processes)", string(s.Name())))
continue
}
if d, ok := s.(deleter); ok {
sp, err := c.path(s.Name())
if err != nil {
@@ -247,6 +256,7 @@ func (c *cgroup) Delete() error {
if err := remove(path); err != nil {
errs = append(errs, path)
}
continue
}
}
if len(errs) > 0 {
+21 -15
View File
@@ -17,8 +17,9 @@
package cgroups
import (
"bufio"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
@@ -70,7 +71,7 @@ func (c *cpuacctController) Stat(path string, stats *v1.Metrics) error {
func (c *cpuacctController) percpuUsage(path string) ([]uint64, error) {
var usage []uint64
data, err := ioutil.ReadFile(filepath.Join(c.Path(path), "cpuacct.usage_percpu"))
data, err := os.ReadFile(filepath.Join(c.Path(path), "cpuacct.usage_percpu"))
if err != nil {
return nil, err
}
@@ -86,36 +87,41 @@ func (c *cpuacctController) percpuUsage(path string) ([]uint64, error) {
func (c *cpuacctController) getUsage(path string) (user uint64, kernel uint64, err error) {
statPath := filepath.Join(c.Path(path), "cpuacct.stat")
data, err := ioutil.ReadFile(statPath)
f, err := os.Open(statPath)
if err != nil {
return 0, 0, err
}
fields := strings.Fields(string(data))
if len(fields) != 4 {
return 0, 0, fmt.Errorf("%q is expected to have 4 fields", statPath)
defer f.Close()
var (
raw = make(map[string]uint64)
sc = bufio.NewScanner(f)
)
for sc.Scan() {
key, v, err := parseKV(sc.Text())
if err != nil {
return 0, 0, err
}
raw[key] = v
}
if err := sc.Err(); err != nil {
return 0, 0, err
}
for _, t := range []struct {
index int
name string
value *uint64
}{
{
index: 0,
name: "user",
value: &user,
},
{
index: 2,
name: "system",
value: &kernel,
},
} {
if fields[t.index] != t.name {
return 0, 0, fmt.Errorf("expected field %q but found %q in %q", t.name, fields[t.index], statPath)
}
v, err := strconv.ParseUint(fields[t.index+1], 10, 64)
if err != nil {
return 0, 0, err
v, ok := raw[t.name]
if !ok {
return 0, 0, fmt.Errorf("expected field %q but not found in %q", t.name, statPath)
}
*t.value = v
}
+2 -3
View File
@@ -19,7 +19,6 @@ package cgroups
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
@@ -87,10 +86,10 @@ func (c *cpusetController) Update(path string, resources *specs.LinuxResources)
}
func (c *cpusetController) getValues(path string) (cpus []byte, mems []byte, err error) {
if cpus, err = ioutil.ReadFile(filepath.Join(path, "cpuset.cpus")); err != nil && !os.IsNotExist(err) {
if cpus, err = os.ReadFile(filepath.Join(path, "cpuset.cpus")); err != nil && !os.IsNotExist(err) {
return
}
if mems, err = ioutil.ReadFile(filepath.Join(path, "cpuset.mems")); err != nil && !os.IsNotExist(err) {
if mems, err = os.ReadFile(filepath.Join(path, "cpuset.mems")); err != nil && !os.IsNotExist(err) {
return
}
return cpus, mems, nil
+2 -2
View File
@@ -17,7 +17,7 @@
package cgroups
import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"time"
@@ -58,7 +58,7 @@ func (f *freezerController) changeState(path string, state State) error {
}
func (f *freezerController) state(path string) (State, error) {
current, err := ioutil.ReadFile(filepath.Join(f.root, path, "freezer.state"))
current, err := os.ReadFile(filepath.Join(f.root, path, "freezer.state"))
if err != nil {
return "", err
}
+1 -2
View File
@@ -17,7 +17,6 @@
package cgroups
import (
"io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -69,7 +68,7 @@ func (p *pidsController) Stat(path string, stats *v1.Metrics) error {
return err
}
var max uint64
maxData, err := ioutil.ReadFile(filepath.Join(p.Path(path), "pids.max"))
maxData, err := os.ReadFile(filepath.Join(p.Path(path), "pids.max"))
if err != nil {
return err
}
+2 -3
View File
@@ -17,7 +17,6 @@
package cgroups
import (
"io/ioutil"
"math"
"os"
"path/filepath"
@@ -126,13 +125,13 @@ func toRdmaEntry(strEntries []string) []*v1.RdmaEntry {
func (p *rdmaController) Stat(path string, stats *v1.Metrics) error {
currentData, err := ioutil.ReadFile(filepath.Join(p.Path(path), "rdma.current"))
currentData, err := os.ReadFile(filepath.Join(p.Path(path), "rdma.current"))
if err != nil {
return err
}
currentPerDevices := strings.Split(string(currentData), "\n")
maxData, err := ioutil.ReadFile(filepath.Join(p.Path(path), "rdma.max"))
maxData, err := os.ReadFile(filepath.Join(p.Path(path), "rdma.max"))
if err != nil {
return err
}
+26 -18
View File
@@ -21,7 +21,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -200,7 +199,7 @@ func hugePageSizes() ([]string, error) {
pageSizes []string
sizeList = []string{"B", "KB", "MB", "GB", "TB", "PB"}
)
files, err := ioutil.ReadDir("/sys/kernel/mm/hugepages")
files, err := os.ReadDir("/sys/kernel/mm/hugepages")
if err != nil {
return nil, err
}
@@ -216,7 +215,7 @@ func hugePageSizes() ([]string, error) {
}
func readUint(path string) (uint64, error) {
v, err := ioutil.ReadFile(path)
v, err := os.ReadFile(path)
if err != nil {
return 0, err
}
@@ -261,21 +260,28 @@ func parseKV(raw string) (string, uint64, error) {
// "pids": "/user.slice/user-1000.slice"
// etc.
//
// Note that for cgroup v2 unified hierarchy, there are no per-controller
// cgroup paths, so the resulting map will have a single element where the key
// is empty string ("") and the value is the cgroup path the <pid> is in.
// The resulting map does not have an element for cgroup v2 unified hierarchy.
// Use ParseCgroupFileUnified to get the unified path.
func ParseCgroupFile(path string) (map[string]string, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
return parseCgroupFromReader(f)
x, _, err := ParseCgroupFileUnified(path)
return x, err
}
func parseCgroupFromReader(r io.Reader) (map[string]string, error) {
// ParseCgroupFileUnified returns legacy subsystem paths as the first value,
// and returns the unified path as the second value.
func ParseCgroupFileUnified(path string) (map[string]string, string, error) {
f, err := os.Open(path)
if err != nil {
return nil, "", err
}
defer f.Close()
return parseCgroupFromReaderUnified(f)
}
func parseCgroupFromReaderUnified(r io.Reader) (map[string]string, string, error) {
var (
cgroups = make(map[string]string)
unified = ""
s = bufio.NewScanner(r)
)
for s.Scan() {
@@ -284,18 +290,20 @@ func parseCgroupFromReader(r io.Reader) (map[string]string, error) {
parts = strings.SplitN(text, ":", 3)
)
if len(parts) < 3 {
return nil, fmt.Errorf("invalid cgroup entry: %q", text)
return nil, unified, fmt.Errorf("invalid cgroup entry: %q", text)
}
for _, subs := range strings.Split(parts[1], ",") {
if subs != "" {
if subs == "" {
unified = parts[2]
} else {
cgroups[subs] = parts[2]
}
}
}
if err := s.Err(); err != nil {
return nil, err
return nil, unified, err
}
return cgroups, nil
return cgroups, unified, nil
}
func getCgroupDestination(subsystem string) (string, error) {
@@ -373,7 +381,7 @@ func retryingWriteFile(path string, data []byte, mode os.FileMode) error {
// Retry writes on EINTR; see:
// https://github.com/golang/go/issues/38033
for {
err := ioutil.WriteFile(path, data, mode)
err := os.WriteFile(path, data, mode)
if err == nil {
return nil
} else if !errors.Is(err, syscall.EINTR) {
+78 -10
View File
@@ -21,7 +21,7 @@ import (
"context"
"errors"
"fmt"
"io/ioutil"
"io"
"math"
"os"
"path/filepath"
@@ -147,7 +147,7 @@ func (c *Value) write(path string, perm os.FileMode) error {
// Retry writes on EINTR; see:
// https://github.com/golang/go/issues/38033
for {
err := ioutil.WriteFile(
err := os.WriteFile(
filepath.Join(path, c.filename),
data,
perm,
@@ -225,7 +225,7 @@ func setResources(path string, resources *Resources) error {
}
func (c *Manager) RootControllers() ([]string, error) {
b, err := ioutil.ReadFile(filepath.Join(c.unifiedMountpoint, controllersFile))
b, err := os.ReadFile(filepath.Join(c.unifiedMountpoint, controllersFile))
if err != nil {
return nil, err
}
@@ -233,13 +233,17 @@ func (c *Manager) RootControllers() ([]string, error) {
}
func (c *Manager) Controllers() ([]string, error) {
b, err := ioutil.ReadFile(filepath.Join(c.path, controllersFile))
b, err := os.ReadFile(filepath.Join(c.path, controllersFile))
if err != nil {
return nil, err
}
return strings.Fields(string(b)), nil
}
func (c *Manager) Update(resources *Resources) error {
return setResources(c.path, resources)
}
type ControllerToggle int
const (
@@ -332,7 +336,23 @@ func (c *Manager) AddProc(pid uint64) error {
return writeValues(c.path, []Value{v})
}
func (c *Manager) AddThread(tid uint64) error {
v := Value{
filename: cgroupThreads,
value: tid,
}
return writeValues(c.path, []Value{v})
}
func (c *Manager) Delete() error {
// kernel prevents cgroups with running process from being removed, check the tree is empty
processes, err := c.Procs(true)
if err != nil {
return err
}
if len(processes) > 0 {
return fmt.Errorf("cgroups: unable to remove path %q: still contains running processes", c.path)
}
return remove(c.path)
}
@@ -362,6 +382,22 @@ func (c *Manager) Procs(recursive bool) ([]uint64, error) {
return processes, err
}
func (c *Manager) MoveTo(destination *Manager) error {
processes, err := c.Procs(true)
if err != nil {
return err
}
for _, p := range processes {
if err := destination.AddProc(p); err != nil {
if strings.Contains(err.Error(), "no such process") {
continue
}
return err
}
}
return nil
}
var singleValueFiles = []string{
"pids.current",
"pids.max",
@@ -502,7 +538,7 @@ func readSingleFile(path string, file string, out map[string]interface{}) error
return err
}
defer f.Close()
data, err := ioutil.ReadAll(f)
data, err := io.ReadAll(f)
if err != nil {
return err
}
@@ -701,12 +737,39 @@ func setDevices(path string, devices []specs.LinuxDeviceCgroup) error {
return nil
}
// getSystemdFullPath returns the full systemd path when creating a systemd slice group.
// the reason this is necessary is because the "-" character has a special meaning in
// systemd slice. For example, when creating a slice called "my-group-112233.slice",
// systemd will create a hierarchy like this:
// /sys/fs/cgroup/my.slice/my-group.slice/my-group-112233.slice
func getSystemdFullPath(slice, group string) string {
return filepath.Join(defaultCgroup2Path, dashesToPath(slice), dashesToPath(group))
}
// dashesToPath converts a slice name with dashes to it's corresponding systemd filesystem path.
func dashesToPath(in string) string {
path := ""
if strings.HasSuffix(in, ".slice") && strings.Contains(in, "-") {
parts := strings.Split(in, "-")
for i := range parts {
s := strings.Join(parts[0:i+1], "-")
if !strings.HasSuffix(s, ".slice") {
s += ".slice"
}
path = filepath.Join(path, s)
}
} else {
path = filepath.Join(path, in)
}
return path
}
func NewSystemd(slice, group string, pid int, resources *Resources) (*Manager, error) {
if slice == "" {
slice = defaultSlice
}
ctx := context.TODO()
path := filepath.Join(defaultCgroup2Path, slice, group)
path := getSystemdFullPath(slice, group)
conn, err := systemdDbus.NewWithContext(ctx)
if err != nil {
return &Manager{}, err
@@ -734,12 +797,17 @@ func NewSystemd(slice, group string, pid int, resources *Resources) (*Manager, e
properties = append(properties, newSystemdProperty("PIDs", []uint32{uint32(pid)}))
}
if resources.Memory != nil && *resources.Memory.Max != 0 {
if resources.Memory != nil && resources.Memory.Min != nil && *resources.Memory.Min != 0 {
properties = append(properties,
newSystemdProperty("MemoryMin", uint64(*resources.Memory.Min)))
}
if resources.Memory != nil && resources.Memory.Max != nil && *resources.Memory.Max != 0 {
properties = append(properties,
newSystemdProperty("MemoryMax", uint64(*resources.Memory.Max)))
}
if resources.CPU != nil && *resources.CPU.Weight != 0 {
if resources.CPU != nil && resources.CPU.Weight != nil && *resources.CPU.Weight != 0 {
properties = append(properties,
newSystemdProperty("CPUWeight", *resources.CPU.Weight))
}
@@ -796,9 +864,9 @@ func LoadSystemd(slice, group string) (*Manager, error) {
if slice == "" {
slice = defaultSlice
}
group = filepath.Join(defaultCgroup2Path, slice, group)
path := getSystemdFullPath(slice, group)
return &Manager{
path: group,
path: path,
}, nil
}
+7
View File
@@ -18,6 +18,7 @@ package v2
type Memory struct {
Swap *int64
Min *int64
Max *int64
Low *int64
High *int64
@@ -30,6 +31,12 @@ func (r *Memory) Values() (o []Value) {
value: *r.Swap,
})
}
if r.Min != nil {
o = append(o, Value{
filename: "memory.min",
value: *r.Min,
})
}
if r.Max != nil {
o = append(o, Value{
filename: "memory.max",
+2 -2
View File
@@ -17,7 +17,7 @@
package v2
import (
"io/ioutil"
"os"
"path/filepath"
"strings"
)
@@ -50,7 +50,7 @@ func (s State) Values() []Value {
}
func fetchState(path string) (State, error) {
current, err := ioutil.ReadFile(filepath.Join(path, cgroupFreeze))
current, err := os.ReadFile(filepath.Join(path, cgroupFreeze))
if err != nil {
return Unknown, err
}
+6 -6
View File
@@ -20,7 +20,6 @@ import (
"bufio"
"fmt"
"io"
"io/ioutil"
"math"
"os"
"path/filepath"
@@ -37,6 +36,7 @@ import (
const (
cgroupProcs = "cgroup.procs"
cgroupThreads = "cgroup.threads"
defaultDirPerm = 0755
)
@@ -227,7 +227,7 @@ func ToResources(spec *specs.LinuxResources) *Resources {
if i := spec.Rdma; i != nil {
resources.RDMA = &RDMA{}
for device, value := range spec.Rdma {
if device != "" && (value.HcaHandles != nil || value.HcaObjects != nil) {
if device != "" && (value.HcaHandles != nil && value.HcaObjects != nil) {
resources.RDMA.Limit = append(resources.RDMA.Limit, RDMAEntry{
Device: device,
HcaHandles: *value.HcaHandles,
@@ -242,7 +242,7 @@ func ToResources(spec *specs.LinuxResources) *Resources {
// Gets uint64 parsed content of single value cgroup stat file
func getStatFileContentUint64(filePath string) uint64 {
contents, err := ioutil.ReadFile(filePath)
contents, err := os.ReadFile(filePath)
if err != nil {
return 0
}
@@ -264,7 +264,7 @@ func readIoStats(path string) []*stats.IOEntry {
// more details on the io.stat file format: https://www.kernel.org/doc/Documentation/cgroup-v2.txt
var usage []*stats.IOEntry
fpath := filepath.Join(path, "io.stat")
currentData, err := ioutil.ReadFile(fpath)
currentData, err := os.ReadFile(fpath)
if err != nil {
return usage
}
@@ -318,7 +318,7 @@ func readIoStats(path string) []*stats.IOEntry {
}
func rdmaStats(filepath string) []*stats.RdmaEntry {
currentData, err := ioutil.ReadFile(filepath)
currentData, err := os.ReadFile(filepath)
if err != nil {
return []*stats.RdmaEntry{}
}
@@ -406,7 +406,7 @@ func readHugeTlbStats(path string) []*stats.HugeTlbStat {
hugeTlb = &stats.HugeTlbStat{}
}
hugeTlb.Pagesize = pageSize
out, err := ioutil.ReadFile(filepath.Join(path, file.Name()))
out, err := os.ReadFile(filepath.Join(path, file.Name()))
if err != nil {
continue
}