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

     1  // +build !linux,!windows
     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  		devNumber = uint64(stat.Rdev)
    93  		major     = unix.Major(devNumber)
    94  		minor     = unix.Minor(devNumber)
    95  	)
    96  	if major == 0 {
    97  		return nil, ErrNotADevice
    98  	}
    99  
   100  	var (
   101  		devType string
   102  		mode    = stat.Mode
   103  	)
   104  	switch {
   105  	case mode&unix.S_IFBLK == unix.S_IFBLK:
   106  		devType = "b"
   107  	case mode&unix.S_IFCHR == unix.S_IFCHR:
   108  		devType = "c"
   109  	}
   110  	fm := os.FileMode(mode)
   111  	return &specs.LinuxDevice{
   112  		Type:     devType,
   113  		Path:     path,
   114  		Major:    int64(major),
   115  		Minor:    int64(minor),
   116  		FileMode: &fm,
   117  		UID:      &stat.Uid,
   118  		GID:      &stat.Gid,
   119  	}, nil
   120  }
   121  
   122  // WithCPUCFS sets the container's Completely fair scheduling (CFS) quota and period
   123  func WithCPUCFS(quota int64, period uint64) SpecOpts {
   124  	return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
   125  		return nil
   126  	}
   127  }