podman

Форк
0
/
util_linux.go 
166 строк · 4.9 Кб
1
//go:build !remote
2

3
package libpod
4

5
import (
6
	"errors"
7
	"fmt"
8
	"path/filepath"
9
	"strings"
10
	"syscall"
11

12
	"github.com/containers/common/pkg/cgroups"
13
	"github.com/containers/podman/v5/libpod/define"
14
	"github.com/containers/podman/v5/pkg/rootless"
15
	"github.com/containers/storage/pkg/fileutils"
16
	spec "github.com/opencontainers/runtime-spec/specs-go"
17
	"github.com/opencontainers/selinux/go-selinux/label"
18
	"github.com/sirupsen/logrus"
19
	"golang.org/x/sys/unix"
20
)
21

22
func cgroupExist(path string) bool {
23
	cgroupv2, _ := cgroups.IsCgroup2UnifiedMode()
24
	var fullPath string
25
	if cgroupv2 {
26
		fullPath = filepath.Join("/sys/fs/cgroup", path)
27
	} else {
28
		fullPath = filepath.Join("/sys/fs/cgroup/memory", path)
29
	}
30
	return fileutils.Exists(fullPath) == nil
31
}
32

33
// systemdSliceFromPath makes a new systemd slice under the given parent with
34
// the given name.
35
// The parent must be a slice. The name must NOT include ".slice"
36
func systemdSliceFromPath(parent, name string, resources *spec.LinuxResources) (string, error) {
37
	cgroupPath, systemdPath, err := assembleSystemdCgroupName(parent, name)
38
	if err != nil {
39
		return "", err
40
	}
41

42
	logrus.Debugf("Created cgroup path %s for parent %s and name %s", systemdPath, parent, name)
43

44
	if !cgroupExist(cgroupPath) {
45
		if err := makeSystemdCgroup(systemdPath, resources); err != nil {
46
			return "", fmt.Errorf("creating cgroup %s: %w", cgroupPath, err)
47
		}
48
	}
49

50
	logrus.Debugf("Created cgroup %s", systemdPath)
51

52
	return cgroupPath, nil
53
}
54

55
func getDefaultSystemdCgroup() string {
56
	if rootless.IsRootless() {
57
		return SystemdDefaultRootlessCgroupParent
58
	}
59
	return SystemdDefaultCgroupParent
60
}
61

62
// makeSystemdCgroup creates a systemd Cgroup at the given location.
63
func makeSystemdCgroup(path string, resources *spec.LinuxResources) error {
64
	res, err := GetLimits(resources)
65
	if err != nil {
66
		return err
67
	}
68
	controller, err := cgroups.NewSystemd(getDefaultSystemdCgroup(), &res)
69
	if err != nil {
70
		return err
71
	}
72

73
	if rootless.IsRootless() {
74
		return controller.CreateSystemdUserUnit(path, rootless.GetRootlessUID())
75
	}
76
	err = controller.CreateSystemdUnit(path)
77
	if err != nil {
78
		return err
79
	}
80
	return nil
81
}
82

83
// deleteSystemdCgroup deletes the systemd cgroup at the given location
84
func deleteSystemdCgroup(path string, resources *spec.LinuxResources) error {
85
	res, err := GetLimits(resources)
86
	if err != nil {
87
		return err
88
	}
89
	controller, err := cgroups.NewSystemd(getDefaultSystemdCgroup(), &res)
90
	if err != nil {
91
		return err
92
	}
93
	if rootless.IsRootless() {
94
		conn, err := cgroups.UserConnection(rootless.GetRootlessUID())
95
		if err != nil {
96
			return err
97
		}
98
		defer conn.Close()
99
		return controller.DeleteByPathConn(path, conn)
100
	}
101

102
	return controller.DeleteByPath(path)
103
}
104

105
// assembleSystemdCgroupName creates a systemd cgroup path given a base and
106
// a new component to add.  It also returns the path to the cgroup as it accessible
107
// below the cgroup mounts.
108
// The base MUST be systemd slice (end in .slice)
109
func assembleSystemdCgroupName(baseSlice, newSlice string) (string, string, error) {
110
	const sliceSuffix = ".slice"
111

112
	if !strings.HasSuffix(baseSlice, sliceSuffix) {
113
		return "", "", fmt.Errorf("cannot assemble cgroup path with base %q - must end in .slice: %w", baseSlice, define.ErrInvalidArg)
114
	}
115

116
	noSlice := strings.TrimSuffix(baseSlice, sliceSuffix)
117
	systemdPath := fmt.Sprintf("%s/%s-%s%s", baseSlice, noSlice, newSlice, sliceSuffix)
118

119
	if rootless.IsRootless() {
120
		// When we run as rootless, the cgroup has a path like the following:
121
		///sys/fs/cgroup/user.slice/user-@$UID.slice/user@$UID.service/user.slice/user-libpod_pod_$POD_ID.slice
122
		uid := rootless.GetRootlessUID()
123
		raw := fmt.Sprintf("user.slice/%s-%d.slice/user@%d.service/%s/%s-%s%s", noSlice, uid, uid, baseSlice, noSlice, newSlice, sliceSuffix)
124
		return raw, systemdPath, nil
125
	}
126
	return systemdPath, systemdPath, nil
127
}
128

129
var lvpRelabel = label.Relabel
130
var lvpInitLabels = label.InitLabels
131
var lvpReleaseLabel = label.ReleaseLabel
132

133
// LabelVolumePath takes a mount path for a volume and gives it an
134
// selinux label of either shared or not
135
func LabelVolumePath(path, mountLabel string) error {
136
	if mountLabel == "" {
137
		var err error
138
		_, mountLabel, err = lvpInitLabels([]string{})
139
		if err != nil {
140
			return fmt.Errorf("getting default mountlabels: %w", err)
141
		}
142
		if err := lvpReleaseLabel(mountLabel); err != nil {
143
			return fmt.Errorf("releasing label %q: %w", mountLabel, err)
144
		}
145
	}
146

147
	if err := lvpRelabel(path, mountLabel, true); err != nil {
148
		if errors.Is(err, unix.ENOTSUP) {
149
			logrus.Debugf("Labeling not supported on %q", path)
150
		} else {
151
			return fmt.Errorf("setting selinux label for %s to %q as shared: %w", path, mountLabel, err)
152
		}
153
	}
154
	return nil
155
}
156

157
// Unmount umounts a target directory
158
func Unmount(mount string) {
159
	if err := unix.Unmount(mount, unix.MNT_DETACH); err != nil {
160
		if err != syscall.EINVAL {
161
			logrus.Warnf("Failed to unmount %s : %v", mount, err)
162
		} else {
163
			logrus.Debugf("failed to unmount %s : %v", mount, err)
164
		}
165
	}
166
}
167

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.