From 31bbb64a0682e326b354ac54c6596402fc20a977 Mon Sep 17 00:00:00 2001 From: holyfei Date: Tue, 8 Sep 2020 20:03:41 +0800 Subject: [PATCH 1/5] kata-runtime: add interface for host cgroup reason: add interface for host cgroup, including CreateSandboxCgroup, DestroySandboxCgroup and AddPidToSandboxCgroup, GetSandboxCgroupPath Signed-off-by: yangfeiyu --- virtcontainers/cgroups.go | 111 +++++++++++++++++++++++++++++++++++++++ virtcontainers/implementation.go | 20 +++++++ virtcontainers/interfaces.go | 5 ++ 3 files changed, 136 insertions(+) diff --git a/virtcontainers/cgroups.go b/virtcontainers/cgroups.go index 4459df5..df0ec30 100644 --- a/virtcontainers/cgroups.go +++ b/virtcontainers/cgroups.go @@ -8,13 +8,20 @@ package virtcontainers import ( "bufio" + "context" + "encoding/json" "fmt" + "io/ioutil" "os" "path/filepath" "strings" "github.com/containerd/cgroups" specs "github.com/opencontainers/runtime-spec/specs-go" + "github.com/sirupsen/logrus" + + "github.com/kata-containers/runtime/virtcontainers/store" + "github.com/kata-containers/runtime/virtcontainers/types" ) type cgroupPather interface { @@ -30,6 +37,110 @@ const cgroupKataPath = "/kata/" var cgroupsLoadFunc = cgroups.Load var cgroupsNewFunc = cgroups.New +// CreateSandboxCgroup create cgroup based on the first container's cgroupPath of sandbox +func CreateSandboxCgroup(ctx context.Context, path string) error { + if path == "" { + return fmt.Errorf("sandbox cgroupPath shouldn't be empty!") + } + + var cgroupPath string + vcpuCgroupPath := filepath.Join(path, "vcpu") + if filepath.IsAbs(vcpuCgroupPath) { + cgroupPath = filepath.Clean(vcpuCgroupPath) + } else { + cgroupPath = filepath.Join(filepath.Clean("/" + vcpuCgroupPath)) + } + + resources := specs.LinuxResources{} + if _, err := cgroupsNewFunc(cgroups.V1, cgroups.StaticPath(cgroupPath), &resources); err != nil { + return fmt.Errorf("Could not create cgroup for %v: %v", cgroupPath, err) + } + + return nil +} + +// DestroySandboxCgroup destroy the cgroup dir created for sandbox +func DestroySandboxCgroup(ctx context.Context, cgroupPath string) error { + return deleteCgroup(cgroups.V1, cgroupPath) +} + +func deleteCgroup(hierarchy cgroups.Hierarchy, cgroupPath string) error { + if cgroupPath == "" { + logrus.Warn("delete cgroupPath shouldn't be empty!") + return nil + } + + cgroup, err := cgroupsLoadFunc(hierarchy, + cgroups.StaticPath(cgroupPath)) + + if err == cgroups.ErrCgroupDeleted { + // cgroup already deleted + return nil + } + + if err != nil { + return fmt.Errorf("Could not load cgroup %v: %v", cgroupPath, err) + } + + // move running process here, that way cgroup can be removed + parent, err := parentCgroup(hierarchy, cgroupPath) + if err != nil { + // parent cgroup doesn't exist, that means there are no process running + // and the container cgroup was removed. + logrus.Warn(err) + return nil + } + + if err := cgroup.MoveTo(parent); err != nil { + // Don't fail, cgroup can be deleted + logrus.Warnf("Could not move container process into parent cgroup: %v", err) + } + + if err := cgroup.Delete(); err != nil { + return fmt.Errorf("Could not delete cgroup %v: %v", cgroupPath, err) + } + + return nil +} + +// GetSandboxCgroupPath return the cgroup path of specified sandbox +func GetSandboxCgroupPath(ctx context.Context, sandboxID string) (string, error) { + stateFilePath := filepath.Join(store.RunStoragePath(), sandboxID, store.StateFile) + + fileData, err := ioutil.ReadFile(stateFilePath) + if err != nil { + return "", err + } + + state := types.SandboxState{} + + if err := json.Unmarshal(fileData, &state); err != nil { + return "", err + } + + if state.CgroupPath == "" { + return "", fmt.Errorf("get sandbox cgroup path error: cgroupPath is empty") + } + + return state.CgroupPath, nil +} + +// AddPidToSandboxCgroup add kata-runtime create process to cgroup +// the pid will be added to the cgroup of "/vcpu" +func AddPidToSandboxCgroup(ctx context.Context, pid int, cgroupPath string) error { + cgroup, err := cgroupsLoadFunc(cgroups.V1, cgroups.StaticPath(cgroupPath)) + if err != nil { + return err + } + + err = cgroup.Add(cgroups.Process{Pid: pid}) + if err != nil { + return err + } + + return nil +} + // V1Constraints returns the cgroups that are compatible with the VC architecture // and hypervisor, constraints can be applied to these cgroups. func V1Constraints() ([]cgroups.Subsystem, error) { diff --git a/virtcontainers/implementation.go b/virtcontainers/implementation.go index e4bc4ae..fedc51f 100644 --- a/virtcontainers/implementation.go +++ b/virtcontainers/implementation.go @@ -188,3 +188,23 @@ func (impl *VCImpl) CleanupContainer(ctx context.Context, sandboxID, containerID func (impl *VCImpl) UpdateIPVSRule(ctx context.Context, sandboxID string, IPVSRule *grpc.UpdateIPVSRequest) (*grpc.IPVSResponse, error) { return UpdateIPVSRule(ctx, sandboxID, IPVSRule) } + +// CreateSandboxCgroup implements the VC function of the same name. +func (impl *VCImpl) CreateSandboxCgroup(ctx context.Context, sandboxCgroupPath string) error { + return CreateSandboxCgroup(ctx, sandboxCgroupPath) +} + +// DestroySandboxCgroup implements the VC function of the same name. +func (impl *VCImpl) DestroySandboxCgroup(ctx context.Context, sandboxCgroupPath string) error { + return DestroySandboxCgroup(ctx, sandboxCgroupPath) +} + +// AddPidToSandboxCgroup implements the VC function of the same name. +func (impl *VCImpl) AddPidToSandboxCgroup(ctx context.Context, pid int, sandboxCgroupPath string) error { + return AddPidToSandboxCgroup(ctx, pid, sandboxCgroupPath) +} + +// GetSandboxCgroupPath implements the VC function of the same name. +func (impl *VCImpl) GetSandboxCgroupPath(ctx context.Context, sandboxID string) (string, error) { + return GetSandboxCgroupPath(ctx, sandboxID) +} diff --git a/virtcontainers/interfaces.go b/virtcontainers/interfaces.go index 0fd12d8..4d166e0 100644 --- a/virtcontainers/interfaces.go +++ b/virtcontainers/interfaces.go @@ -24,6 +24,11 @@ type VC interface { SetLogger(ctx context.Context, logger *logrus.Entry) SetFactory(ctx context.Context, factory Factory) + CreateSandboxCgroup(ctx context.Context, sandboxCgroupPath string) error + DestroySandboxCgroup(ctx context.Context, sandboxCgroupPath string) error + AddPidToSandboxCgroup(ctx context.Context, pid int, sandboxCgroupPath string) error + GetSandboxCgroupPath(ctx context.Context, sandboxID string) (string, error) + CreateSandbox(ctx context.Context, sandboxConfig SandboxConfig) (VCSandbox, error) DeleteSandbox(ctx context.Context, sandboxID string) (VCSandbox, error) FetchSandbox(ctx context.Context, sandboxID string) (VCSandbox, error) -- 1.8.3.1