Add --device flag to ctr
Closes #3066 Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
		| @@ -126,6 +126,10 @@ var ( | ||||
| 			Name:  "memory-limit", | ||||
| 			Usage: "memory limit (in bytes) for the container", | ||||
| 		}, | ||||
| 		cli.StringSliceFlag{ | ||||
| 			Name:  "device", | ||||
| 			Usage: "add a device to a container", | ||||
| 		}, | ||||
| 	} | ||||
| 	// ImageDecryptionFlags are cli flags needed when decrypting an image | ||||
| 	ImageDecryptionFlags = []cli.Flag{ | ||||
|   | ||||
| @@ -155,6 +155,9 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli | ||||
| 		if limit != 0 { | ||||
| 			opts = append(opts, oci.WithMemoryLimit(limit)) | ||||
| 		} | ||||
| 		for _, dev := range context.StringSlice("device") { | ||||
| 			opts = append(opts, oci.WithLinuxDevice(dev, "rwm")) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	cOpts = append(cOpts, containerd.WithRuntime(context.String("runtime"), nil)) | ||||
|   | ||||
| @@ -76,6 +76,20 @@ func setLinux(s *Spec) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // nolint | ||||
| func setResources(s *Spec) { | ||||
| 	if s.Linux != nil { | ||||
| 		if s.Linux.Resources == nil { | ||||
| 			s.Linux.Resources = &specs.LinuxResources{} | ||||
| 		} | ||||
| 	} | ||||
| 	if s.Windows != nil { | ||||
| 		if s.Windows.Resources == nil { | ||||
| 			s.Windows.Resources = &specs.WindowsResources{} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // setCapabilities sets Linux Capabilities to empty if unset | ||||
| func setCapabilities(s *Spec) { | ||||
| 	setProcess(s) | ||||
| @@ -1148,3 +1162,30 @@ func WithLinuxDevices(devices []specs.LinuxDevice) SpecOpts { | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| var ErrNotADevice = errors.New("not a device node") | ||||
|  | ||||
| // WithLinuxDevice adds the device specified by path to the spec | ||||
| func WithLinuxDevice(path, permissions string) SpecOpts { | ||||
| 	return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { | ||||
| 		setLinux(s) | ||||
| 		setResources(s) | ||||
|  | ||||
| 		dev, err := deviceFromPath(path, permissions) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		s.Linux.Devices = append(s.Linux.Devices, *dev) | ||||
|  | ||||
| 		s.Linux.Resources.Devices = append(s.Linux.Resources.Devices, specs.LinuxDeviceCgroup{ | ||||
| 			Type:   dev.Type, | ||||
| 			Allow:  true, | ||||
| 			Major:  &dev.Major, | ||||
| 			Minor:  &dev.Minor, | ||||
| 			Access: permissions, | ||||
| 		}) | ||||
|  | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										63
									
								
								oci/spec_opts_linux.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								oci/spec_opts_linux.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| // +build linux | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package oci | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
|  | ||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| func deviceFromPath(path, permissions string) (*specs.LinuxDevice, error) { | ||||
| 	var stat unix.Stat_t | ||||
| 	if err := unix.Lstat(path, &stat); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		devNumber = stat.Rdev | ||||
| 		major     = unix.Major(devNumber) | ||||
| 		minor     = unix.Minor(devNumber) | ||||
| 	) | ||||
| 	if major == 0 { | ||||
| 		return nil, ErrNotADevice | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		devType string | ||||
| 		mode    = stat.Mode | ||||
| 	) | ||||
| 	switch { | ||||
| 	case mode&unix.S_IFBLK == unix.S_IFBLK: | ||||
| 		devType = "b" | ||||
| 	case mode&unix.S_IFCHR == unix.S_IFCHR: | ||||
| 		devType = "c" | ||||
| 	} | ||||
| 	fm := os.FileMode(mode) | ||||
| 	return &specs.LinuxDevice{ | ||||
| 		Type:     devType, | ||||
| 		Path:     path, | ||||
| 		Major:    int64(major), | ||||
| 		Minor:    int64(minor), | ||||
| 		FileMode: &fm, | ||||
| 		UID:      &stat.Uid, | ||||
| 		GID:      &stat.Gid, | ||||
| 	}, nil | ||||
| } | ||||
							
								
								
									
										63
									
								
								oci/spec_opts_unix.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								oci/spec_opts_unix.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| // +build !linux,!windows | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package oci | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
|  | ||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| func deviceFromPath(path, permissions string) (*specs.LinuxDevice, error) { | ||||
| 	var stat unix.Stat_t | ||||
| 	if err := unix.Lstat(path, &stat); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		devNumber = uint64(stat.Rdev) | ||||
| 		major     = unix.Major(devNumber) | ||||
| 		minor     = unix.Minor(devNumber) | ||||
| 	) | ||||
| 	if major == 0 { | ||||
| 		return nil, ErrNotADevice | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		devType string | ||||
| 		mode    = stat.Mode | ||||
| 	) | ||||
| 	switch { | ||||
| 	case mode&unix.S_IFBLK == unix.S_IFBLK: | ||||
| 		devType = "b" | ||||
| 	case mode&unix.S_IFCHR == unix.S_IFCHR: | ||||
| 		devType = "c" | ||||
| 	} | ||||
| 	fm := os.FileMode(mode) | ||||
| 	return &specs.LinuxDevice{ | ||||
| 		Type:     devType, | ||||
| 		Path:     path, | ||||
| 		Major:    int64(major), | ||||
| 		Minor:    int64(minor), | ||||
| 		FileMode: &fm, | ||||
| 		UID:      &stat.Uid, | ||||
| 		GID:      &stat.Gid, | ||||
| 	}, nil | ||||
| } | ||||
| @@ -23,6 +23,7 @@ import ( | ||||
|  | ||||
| 	"github.com/containerd/containerd/containers" | ||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
|  | ||||
| // WithWindowsCPUCount sets the `Windows.Resources.CPU.Count` section to the | ||||
| @@ -65,3 +66,7 @@ func WithWindowNetworksAllowUnqualifiedDNSQuery() SpecOpts { | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func deviceFromPath(path, permissions string) (*specs.LinuxDevice, error) { | ||||
| 	return nil, errors.New("device from path not supported on Windows") | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Michael Crosby
					Michael Crosby