github.com/containerd/containerd@v22.0.0-20200918172823-438c87b8e050+incompatible/oci/spec_opts_linux.go (about)

     1  // +build linux
     2  
     3  /*
     4     Copyright The containerd Authors.
     5  
     6     Licensed under the Apache License, Version 2.0 (the "License");
     7     you may not use this file except in compliance with the License.
     8     You may obtain a copy of the License at
     9  
    10         http://www.apache.org/licenses/LICENSE-2.0
    11  
    12     Unless required by applicable law or agreed to in writing, software
    13     distributed under the License is distributed on an "AS IS" BASIS,
    14     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15     See the License for the specific language governing permissions and
    16     limitations under the License.
    17  */
    18  
    19  package oci
    20  
    21  import (
    22  	"context"
    23  	"io/ioutil"
    24  	"os"
    25  	"path/filepath"
    26  
    27  	"github.com/containerd/containerd/containers"
    28  	specs "github.com/opencontainers/runtime-spec/specs-go"
    29  	"golang.org/x/sys/unix"
    30  )
    31  
    32  // WithHostDevices adds all the hosts device nodes to the container's spec
    33  func WithHostDevices(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
    34  	setLinux(s)
    35  
    36  	devs, err := getDevices("/dev")
    37  	if err != nil {
    38  		return err
    39  	}
    40  	s.Linux.Devices = append(s.Linux.Devices, devs...)
    41  	return nil
    42  }
    43  
    44  func getDevices(path string) ([]specs.LinuxDevice, error) {
    45  	files, err := ioutil.ReadDir(path)
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  	var out []specs.LinuxDevice
    50  	for _, f := range files {
    51  		switch {
    52  		case f.IsDir():
    53  			switch f.Name() {
    54  			// ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825
    55  			// ".udev" added to address https://github.com/opencontainers/runc/issues/2093
    56  			case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts", ".udev":
    57  				continue
    58  			default:
    59  				sub, err := getDevices(filepath.Join(path, f.Name()))
    60  				if err != nil {
    61  					return nil, err
    62  				}
    63  
    64  				out = append(out, sub...)
    65  				continue
    66  			}
    67  		case f.Name() == "console":
    68  			continue
    69  		}
    70  		device, err := deviceFromPath(filepath.Join(path, f.Name()), "rwm")
    71  		if err != nil {
    72  			if err == ErrNotADevice {
    73  				continue
    74  			}
    75  			if os.IsNotExist(err) {
    76  				continue
    77  			}
    78  			return nil, err
    79  		}
    80  		out = append(out, *device)
    81  	}
    82  	return out, nil
    83  }
    84  
    85  func deviceFromPath(path, permissions string) (*specs.LinuxDevice, error) {
    86  	var stat unix.Stat_t
    87  	if err := unix.Lstat(path, &stat); err != nil {
    88  		return nil, err
    89  	}
    90  
    91  	var (
    92  		// The type is 32bit on mips.
    93  		devNumber = uint64(stat.Rdev) // nolint: unconvert
    94  		major     = unix.Major(devNumber)
    95  		minor     = unix.Minor(devNumber)
    96  	)
    97  	if major == 0 {
    98  		return nil, ErrNotADevice
    99  	}
   100  
   101  	var (
   102  		devType string
   103  		mode    = stat.Mode
   104  	)
   105  	switch {
   106  	case mode&unix.S_IFBLK == unix.S_IFBLK:
   107  		devType = "b"
   108  	case mode&unix.S_IFCHR == unix.S_IFCHR:
   109  		devType = "c"
   110  	}
   111  	fm := os.FileMode(mode)
   112  	return &specs.LinuxDevice{
   113  		Type:     devType,
   114  		Path:     path,
   115  		Major:    int64(major),
   116  		Minor:    int64(minor),
   117  		FileMode: &fm,
   118  		UID:      &stat.Uid,
   119  		GID:      &stat.Gid,
   120  	}, nil
   121  }
   122  
   123  // WithMemorySwap sets the container's swap in bytes
   124  func WithMemorySwap(swap int64) SpecOpts {
   125  	return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
   126  		setResources(s)
   127  		if s.Linux.Resources.Memory == nil {
   128  			s.Linux.Resources.Memory = &specs.LinuxMemory{}
   129  		}
   130  		s.Linux.Resources.Memory.Swap = &swap
   131  		return nil
   132  	}
   133  }
   134  
   135  // WithPidsLimit sets the container's pid limit or maximum
   136  func WithPidsLimit(limit int64) SpecOpts {
   137  	return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
   138  		setResources(s)
   139  		if s.Linux.Resources.Pids == nil {
   140  			s.Linux.Resources.Pids = &specs.LinuxPids{}
   141  		}
   142  		s.Linux.Resources.Pids.Limit = limit
   143  		return nil
   144  	}
   145  }
   146  
   147  // WithCPUShares sets the container's cpu shares
   148  func WithCPUShares(shares uint64) SpecOpts {
   149  	return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
   150  		setCPU(s)
   151  		s.Linux.Resources.CPU.Shares = &shares
   152  		return nil
   153  	}
   154  }
   155  
   156  // WithCPUs sets the container's cpus/cores for use by the container
   157  func WithCPUs(cpus string) SpecOpts {
   158  	return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
   159  		setCPU(s)
   160  		s.Linux.Resources.CPU.Cpus = cpus
   161  		return nil
   162  	}
   163  }
   164  
   165  // WithCPUsMems sets the container's cpu mems for use by the container
   166  func WithCPUsMems(mems string) SpecOpts {
   167  	return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
   168  		setCPU(s)
   169  		s.Linux.Resources.CPU.Mems = mems
   170  		return nil
   171  	}
   172  }
   173  
   174  // WithCPUCFS sets the container's Completely fair scheduling (CFS) quota and period
   175  func WithCPUCFS(quota int64, period uint64) SpecOpts {
   176  	return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
   177  		setCPU(s)
   178  		s.Linux.Resources.CPU.Quota = &quota
   179  		s.Linux.Resources.CPU.Period = &period
   180  		return nil
   181  	}
   182  }