From e8553a124d8f18f6ab7f31e45234d937cae49f70 Mon Sep 17 00:00:00 2001 From: Antonio Murdaca Date: Wed, 6 Sep 2017 17:04:18 +0200 Subject: [PATCH] container_create: better handling of devices Signed-off-by: Antonio Murdaca --- server/container_create.go | 118 +++++++++++++++++++++++++++++++------ server/sandbox_run.go | 4 ++ server/server.go | 1 + 3 files changed, 105 insertions(+), 18 deletions(-) diff --git a/server/container_create.go b/server/container_create.go index f1393935..7b073284 100644 --- a/server/container_create.go +++ b/server/container_create.go @@ -124,29 +124,111 @@ func addImageVolumes(rootfs string, s *Server, containerInfo *storage.ContainerI return nil } +// resolveSymbolicLink resolves a possbile symlink path. If the path is a symlink, returns resolved +// path; if not, returns the original path. +func resolveSymbolicLink(path string) (string, error) { + info, err := os.Lstat(path) + if err != nil { + return "", err + } + if info.Mode()&os.ModeSymlink != os.ModeSymlink { + return path, nil + } + return filepath.EvalSymlinks(path) +} + func addDevices(sb *sandbox.Sandbox, containerConfig *pb.ContainerConfig, specgen *generate.Generator) error { sp := specgen.Spec() - for _, device := range containerConfig.GetDevices() { - dev, err := devices.DeviceFromPath(device.HostPath, device.Permissions) + if containerConfig.GetLinux().GetSecurityContext().Privileged { + hostDevices, err := devices.HostDevices() if err != nil { - return fmt.Errorf("failed to add device: %v", err) + return err } - rd := rspec.LinuxDevice{ - Path: device.ContainerPath, - Type: string(dev.Type), - Major: dev.Major, - Minor: dev.Minor, - UID: &dev.Uid, - GID: &dev.Gid, + for _, hostDevice := range hostDevices { + rd := rspec.LinuxDevice{ + Path: hostDevice.Path, + Type: string(hostDevice.Type), + Major: hostDevice.Major, + Minor: hostDevice.Minor, + UID: &hostDevice.Uid, + GID: &hostDevice.Gid, + } + if hostDevice.Major == 0 && hostDevice.Minor == 0 { + // Invalid device, most likely a symbolic link, skip it. + continue + } + specgen.AddDevice(rd) + } + sp.Linux.Resources.Devices = []rspec.LinuxDeviceCgroup{ + { + Allow: true, + Access: "rwm", + }, + } + return nil + } + for _, device := range containerConfig.GetDevices() { + path, err := resolveSymbolicLink(device.HostPath) + if err != nil { + return err + } + dev, err := devices.DeviceFromPath(path, device.Permissions) + // if there was no error, return the device + if err == nil { + rd := rspec.LinuxDevice{ + Path: device.ContainerPath, + Type: string(dev.Type), + Major: dev.Major, + Minor: dev.Minor, + UID: &dev.Uid, + GID: &dev.Gid, + } + specgen.AddDevice(rd) + sp.Linux.Resources.Devices = append(sp.Linux.Resources.Devices, rspec.LinuxDeviceCgroup{ + Allow: true, + Type: string(dev.Type), + Major: &dev.Major, + Minor: &dev.Minor, + Access: dev.Permissions, + }) + continue + } + // if the device is not a device node + // try to see if it's a directory holding many devices + if err == devices.ErrNotADevice { + + // check if it is a directory + if src, e := os.Stat(path); e == nil && src.IsDir() { + + // mount the internal devices recursively + filepath.Walk(path, func(dpath string, f os.FileInfo, e error) error { + childDevice, e := devices.DeviceFromPath(dpath, device.Permissions) + if e != nil { + // ignore the device + return nil + } + cPath := strings.Replace(dpath, path, device.ContainerPath, 1) + rd := rspec.LinuxDevice{ + Path: cPath, + Type: string(childDevice.Type), + Major: childDevice.Major, + Minor: childDevice.Minor, + UID: &childDevice.Uid, + GID: &childDevice.Gid, + } + specgen.AddDevice(rd) + sp.Linux.Resources.Devices = append(sp.Linux.Resources.Devices, rspec.LinuxDeviceCgroup{ + Allow: true, + Type: string(childDevice.Type), + Major: &childDevice.Major, + Minor: &childDevice.Minor, + Access: childDevice.Permissions, + }) + + return nil + }) + } } - specgen.AddDevice(rd) - sp.Linux.Resources.Devices = append(sp.Linux.Resources.Devices, rspec.LinuxDeviceCgroup{ - Allow: true, - Type: string(dev.Type), - Major: &dev.Major, - Minor: &dev.Minor, - Access: dev.Permissions, - }) } return nil } diff --git a/server/sandbox_run.go b/server/sandbox_run.go index ac9823c8..376eeaf9 100644 --- a/server/sandbox_run.go +++ b/server/sandbox_run.go @@ -35,6 +35,8 @@ const ( // TODO: Remove this const once this value is provided over CRI // See https://github.com/kubernetes/kubernetes/issues/47938 PodInfraOOMAdj int = -998 + // PodInfraCPUshares is default cpu shares for sandbox container. + PodInfraCPUshares = 2 ) // privilegedSandbox returns true if the sandbox configuration @@ -389,6 +391,8 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest // so it doesn't get killed. g.SetProcessOOMScoreAdj(PodInfraOOMAdj) + g.SetLinuxResourcesCPUShares(PodInfraCPUshares) + hostNetwork := req.GetConfig().GetLinux().GetSecurityContext().GetNamespaceOptions().HostNetwork // set up namespaces diff --git a/server/server.go b/server/server.go index b32220ab..15b55254 100644 --- a/server/server.go +++ b/server/server.go @@ -360,6 +360,7 @@ func (s *Server) StopExitMonitor() { close(s.exitMonitorChan) } +// ExitMonitorCloseChan returns the close chan for the exit monitor func (s *Server) ExitMonitorCloseChan() chan struct{} { return s.exitMonitorChan }