mirror of
https://github.com/containers/podman.git
synced 2025-06-19 00:06:43 +08:00
Merge pull request #2033 from rhatdan/devices
Allow users to specify a directory for additonal devices
This commit is contained in:
@ -106,7 +106,7 @@ to be long lived. While Buildah containers are really just created to allow con
|
||||
to be added back to the container image. An easy way to think of it is the
|
||||
`buildah run` command emulates the RUN command in a Dockerfile while the `podman run`
|
||||
command emulates the `docker run` command in functionality. Because of this and their underlying
|
||||
storage differences, you can not see Podman containers from within Buildah or vice versa.
|
||||
storage differences, you cannot see Podman containers from within Buildah or vice versa.
|
||||
|
||||
In short Buildah is an efficient way to create OCI images while Podman allows
|
||||
you to manage and maintain those images and containers in a production environment using
|
||||
|
@ -462,7 +462,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
|
||||
tty := c.Bool("tty")
|
||||
|
||||
if c.Bool("detach") && c.Bool("rm") {
|
||||
return nil, errors.Errorf("--rm and --detach can not be specified together")
|
||||
return nil, errors.Errorf("--rm and --detach cannot be specified together")
|
||||
}
|
||||
if c.Int64("cpu-period") != 0 && c.Float64("cpus") > 0 {
|
||||
return nil, errors.Errorf("--cpu-period and --cpus cannot be set together")
|
||||
|
@ -144,7 +144,7 @@ func parseMounts(mounts []string) ([]spec.Mount, error) {
|
||||
mountInfo.Options = append(mountInfo.Options, kv[1])
|
||||
case "src", "source":
|
||||
if mountInfo.Type == "tmpfs" {
|
||||
return nil, errors.Errorf("can not use src= on a tmpfs file system")
|
||||
return nil, errors.Errorf("cannot use src= on a tmpfs file system")
|
||||
}
|
||||
if err := validateVolumeHostDir(kv[1]); err != nil {
|
||||
return nil, err
|
||||
@ -288,7 +288,7 @@ func verifyContainerResources(config *cc.CreateConfig, update bool) ([]string, e
|
||||
return warnings, fmt.Errorf("minimum memory reservation allowed is 4MB")
|
||||
}
|
||||
if config.Resources.Memory > 0 && config.Resources.MemoryReservation > 0 && config.Resources.Memory < config.Resources.MemoryReservation {
|
||||
return warnings, fmt.Errorf("minimum memory limit can not be less than memory reservation limit, see usage")
|
||||
return warnings, fmt.Errorf("minimum memory limit cannot be less than memory reservation limit, see usage")
|
||||
}
|
||||
if config.Resources.KernelMemory > 0 && !sysInfo.KernelMemory {
|
||||
warnings = addWarning(warnings, "Your kernel does not support kernel memory limit capabilities or the cgroup is not mounted. Limitation discarded.")
|
||||
@ -318,14 +318,14 @@ func verifyContainerResources(config *cc.CreateConfig, update bool) ([]string, e
|
||||
config.Resources.CPUPeriod = 0
|
||||
}
|
||||
if config.Resources.CPUPeriod != 0 && (config.Resources.CPUPeriod < 1000 || config.Resources.CPUPeriod > 1000000) {
|
||||
return warnings, fmt.Errorf("CPU cfs period can not be less than 1ms (i.e. 1000) or larger than 1s (i.e. 1000000)")
|
||||
return warnings, fmt.Errorf("CPU cfs period cannot be less than 1ms (i.e. 1000) or larger than 1s (i.e. 1000000)")
|
||||
}
|
||||
if config.Resources.CPUQuota > 0 && !sysInfo.CPUCfsQuota {
|
||||
warnings = addWarning(warnings, "Your kernel does not support CPU cfs quota or the cgroup is not mounted. Quota discarded.")
|
||||
config.Resources.CPUQuota = 0
|
||||
}
|
||||
if config.Resources.CPUQuota > 0 && config.Resources.CPUQuota < 1000 {
|
||||
return warnings, fmt.Errorf("CPU cfs quota can not be less than 1ms (i.e. 1000)")
|
||||
return warnings, fmt.Errorf("CPU cfs quota cannot be less than 1ms (i.e. 1000)")
|
||||
}
|
||||
// cpuset subsystem checks and adjustments
|
||||
if (config.Resources.CPUsetCPUs != "" || config.Resources.CPUsetMems != "") && !sysInfo.Cpuset {
|
||||
|
@ -84,7 +84,7 @@ func (n UTSMode) Valid() bool {
|
||||
// IpcMode represents the container ipc stack.
|
||||
type IpcMode string
|
||||
|
||||
// IsPrivate indicates whether the container uses its own private ipc namespace which can not be shared.
|
||||
// IsPrivate indicates whether the container uses its own private ipc namespace which cannot be shared.
|
||||
func (n IpcMode) IsPrivate() bool {
|
||||
return n == "private"
|
||||
}
|
||||
|
@ -3,7 +3,11 @@
|
||||
package createconfig
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/profiles/seccomp"
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
@ -27,6 +31,52 @@ func Device(d *configs.Device) spec.LinuxDevice {
|
||||
}
|
||||
}
|
||||
|
||||
// devicesFromPath computes a list of devices
|
||||
func devicesFromPath(g *generate.Generator, devicePath string) error {
|
||||
devs := strings.Split(devicePath, ":")
|
||||
resolvedDevicePath := devs[0]
|
||||
// check if it is a symbolic link
|
||||
if src, err := os.Lstat(resolvedDevicePath); err == nil && src.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
if linkedPathOnHost, err := filepath.EvalSymlinks(resolvedDevicePath); err == nil {
|
||||
resolvedDevicePath = linkedPathOnHost
|
||||
}
|
||||
}
|
||||
st, err := os.Stat(resolvedDevicePath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "cannot stat %s", devicePath)
|
||||
}
|
||||
if st.IsDir() {
|
||||
if len(devs) > 2 {
|
||||
return errors.Wrapf(unix.EINVAL, "not allowed to specify destination with a directory %s", devicePath)
|
||||
}
|
||||
found := false
|
||||
// mount the internal devices recursively
|
||||
if err := filepath.Walk(resolvedDevicePath, func(dpath string, f os.FileInfo, e error) error {
|
||||
|
||||
if f.Mode()&os.ModeDevice == os.ModeDevice {
|
||||
found = true
|
||||
device := dpath
|
||||
|
||||
if len(devs) > 1 {
|
||||
device = fmt.Sprintf("%s:%s", dpath, devs[1])
|
||||
}
|
||||
if err := addDevice(g, device); err != nil {
|
||||
return errors.Wrapf(err, "failed to add %s device", dpath)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if !found {
|
||||
return errors.Wrapf(unix.EINVAL, "no devices found in %s", devicePath)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return addDevice(g, devicePath)
|
||||
}
|
||||
|
||||
func addDevice(g *generate.Generator, device string) error {
|
||||
src, dst, permissions, err := ParseDevice(device)
|
||||
if err != nil {
|
||||
|
@ -166,7 +166,7 @@ func ParseDevice(device string) (string, string, string, error) { //nolint
|
||||
permissions = arr[1]
|
||||
} else {
|
||||
if arr[1][0] != '/' {
|
||||
return "", "", "", fmt.Errorf("invalid device mode: %s", arr[2])
|
||||
return "", "", "", fmt.Errorf("invalid device mode: %s", arr[1])
|
||||
}
|
||||
dst = arr[1]
|
||||
}
|
||||
|
@ -235,8 +235,8 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, device := range config.Devices {
|
||||
if err := addDevice(&g, device); err != nil {
|
||||
for _, devicePath := range config.Devices {
|
||||
if err := devicesFromPath(&g, devicePath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ var _ = Describe("Common functions test", func() {
|
||||
|
||||
It("Test SystemExec", func() {
|
||||
session := SystemExec(GoechoPath, []string{})
|
||||
Expect(session.Command.Process).ShouldNot(BeNil(), "SystemExec can not start a process")
|
||||
Expect(session.Command.Process).ShouldNot(BeNil(), "SystemExec cannot start a process")
|
||||
})
|
||||
|
||||
It("Test StringInSlice", func() {
|
||||
|
@ -18,7 +18,7 @@ and retry your command before reporting the issue.
|
||||
---
|
||||
### 2) No such image or Bare keys cannot contain ':'
|
||||
|
||||
When doing a `podman pull` or `podman build` command and a "common" image can not be pulled,
|
||||
When doing a `podman pull` or `podman build` command and a "common" image cannot be pulled,
|
||||
it is likely that the `/etc/containers/registries.conf` file is either not installed or possibly
|
||||
misconfigured.
|
||||
|
||||
|
Reference in New Issue
Block a user