Skip to content

Commit

Permalink
Merge pull request #1882 from QiWang19/ii1821
Browse files Browse the repository at this point in the history
Support additionaldevices and change vendor libpod
  • Loading branch information
k8s-ci-robot committed Nov 27, 2018
2 parents 81940d1 + 27ecc06 commit 41da373
Show file tree
Hide file tree
Showing 18 changed files with 756 additions and 39 deletions.
7 changes: 7 additions & 0 deletions cmd/crio/config.go
Expand Up @@ -172,6 +172,13 @@ default_capabilities = [
default_sysctls = [
{{ range $sysctl := .DefaultSysctls}}{{ printf "\t%q, \n" $sysctl}}{{ end }}]
# List of additional devices. specified as
# "<device-on-host>:<device-on-container>:<permissions>", for example: "--device=/dev/sdc:/dev/xvdc:rwm".
#If it is empty or commented out, only the devices
# defined in the container json file by the user/kube will be added.
additional_devices = [
{{ range $device := .AdditionalDevices}}{{ printf "\t%q, \n" $device}}{{ end }}]
# Path to the OCI hooks directory for automatically executed hooks.
hooks_dir_path = "{{ .HooksDirPath }}"
Expand Down
30 changes: 30 additions & 0 deletions cmd/crio/main.go
Expand Up @@ -17,6 +17,7 @@ import (

"github.com/containers/libpod/pkg/hooks"
_ "github.com/containers/libpod/pkg/hooks/0.1.0"
"github.com/containers/libpod/pkg/spec"
"github.com/containers/storage/pkg/reexec"
units "github.com/docker/go-units"
"github.com/kubernetes-sigs/cri-o/lib"
Expand Down Expand Up @@ -99,6 +100,28 @@ func validateConfig(config *server.Config) error {
}
}

for _, d := range config.RuntimeConfig.AdditionalDevices {
split := strings.Split(d, ":")
switch len(split) {
case 3:
if !createconfig.IsValidDeviceMode(split[2]) {
return fmt.Errorf("invalid device mode: %s", split[2])
}
fallthrough
case 2:
if (!createconfig.IsValidDeviceMode(split[1]) && !strings.HasPrefix(split[1], "/dev/")) || (len(split) == 3 && createconfig.IsValidDeviceMode(split[1])) {
return fmt.Errorf("invalid device mode: %s", split[1])
}
fallthrough
case 1:
if !strings.HasPrefix(split[0], "/dev/") {
return fmt.Errorf("invalid device mode: %s", split[0])
}
default:
return fmt.Errorf("invalid device specification: %s", d)
}
}

if config.UIDMappings != "" && config.ManageNetworkNSLifecycle {
return fmt.Errorf("Cannot use UIDMappings with ManageNetworkNSLifecycle")
}
Expand Down Expand Up @@ -251,6 +274,9 @@ func mergeConfig(config *server.Config, ctx *cli.Context) error {
if ctx.GlobalIsSet("log-level") {
config.LogLevel = ctx.GlobalString("log-level")
}
if ctx.GlobalIsSet("additional-devices") {
config.AdditionalDevices = ctx.GlobalStringSlice("additional-devices")
}
return nil
}

Expand Down Expand Up @@ -514,6 +540,10 @@ func main() {
Usage: "specify the GID mappings to use for the user namespace",
Value: "",
},
cli.StringSliceFlag{
Name: "additional-devices",
Usage: "devices to add to the containers",
},
}

sort.Sort(cli.FlagsByName(app.Flags))
Expand Down
3 changes: 3 additions & 0 deletions docs/crio.conf.5.md
Expand Up @@ -129,6 +129,9 @@ The `crio.runtime` table contains settings pertaining to the OCI runtime used an
**default_sysctls**=[]
List of default sysctls. If it is empty or commented out, only the sysctls defined in the container json file by the user/kube will be added.

**additional_devices**=[]
List of additional devices. If it is empty or commented out, only the devices defined in the container json file by the user/kube will be added.

**hooks_dir_path**="/usr/share/containers/oci/hooks.d"
Path to the OCI hooks directory for automatically executed hooks.

Expand Down
4 changes: 4 additions & 0 deletions lib/config.go
Expand Up @@ -248,6 +248,9 @@ type RuntimeConfig struct {

// DefeultUlimits specifies the default ulimits to apply to containers
DefaultUlimits []string `toml:"default_ulimits"`

// Devices to add to containers
AdditionalDevices []string `toml:"additional_devices"`
}

// ImageConfig represents the "crio.image" TOML config table.
Expand Down Expand Up @@ -387,6 +390,7 @@ func DefaultConfig() *Config {
LogLevel: "error",
DefaultSysctls: []string{},
DefaultUlimits: []string{},
AdditionalDevices: []string{},
},
ImageConfig: ImageConfig{
DefaultTransport: defaultTransport,
Expand Down
35 changes: 35 additions & 0 deletions server/container_create_linux.go
Expand Up @@ -14,6 +14,7 @@ import (

"github.com/containers/libpod/pkg/apparmor"
"github.com/containers/libpod/pkg/secrets"
"github.com/containers/libpod/pkg/spec"
"github.com/containers/storage/pkg/idtools"
dockermounts "github.com/docker/docker/pkg/mount"
"github.com/docker/docker/pkg/symlink"
Expand Down Expand Up @@ -361,6 +362,14 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string,
// Add cgroup mount so container process can introspect its own limits
specgen.AddMount(mnt)

devices, err := getDevicesFromConfig(s.config)
if err != nil {
return nil, err
}
for _, d := range devices {
specgen.AddDevice(d)
}

if err := addDevices(sb, containerConfig, &specgen); err != nil {
return nil, err
}
Expand Down Expand Up @@ -1088,3 +1097,29 @@ func addOCIBindMounts(mountLabel string, containerConfig *pb.ContainerConfig, sp

return volumes, ociMounts, nil
}

func getDevicesFromConfig(config Config) ([]rspec.LinuxDevice, error) {
var linuxdevs []rspec.LinuxDevice
for _, d := range config.RuntimeConfig.AdditionalDevices {
src, dst, permissions, err := createconfig.ParseDevice(d)
if err != nil {
return nil, err
}
dev, err := devices.DeviceFromPath(src, permissions)
if err != nil {
return nil, errors.Wrapf(err, "%s is not a valid device", src)
}
dev.Path = dst
linuxdev := rspec.LinuxDevice{
Path: dev.Path,
Type: string(dev.Type),
Major: dev.Major,
Minor: dev.Minor,
FileMode: &dev.FileMode,
UID: &dev.Uid,
GID: &dev.Gid,
}
linuxdevs = append(linuxdevs, linuxdev)
}
return linuxdevs, nil
}
15 changes: 15 additions & 0 deletions test/command.bats
Expand Up @@ -23,3 +23,18 @@ load helpers
# can't cover everything here, ulimits parsing is tested in
# github.com/docker/go-units package
}

@test "invalid devices" {
run ${CRIO_BINARY} --additional-devices /dev/sda:/dev/foo:123
echo $output
[ "$status" -ne 0 ]
[[ "$output" =~ "invalid device mode:" ]]
run ${CRIO_BINARY} --additional-devices /dev/sda:/dee/foo:rm
echo $output
[ "$status" -ne 0 ]
[[ "$output" =~ "invalid device mode:" ]]
run ${CRIO_BINARY} --additional-devices /dee/sda:rmw
echo $output
[ "$status" -ne 0 ]
[[ "$output" =~ "invalid device mode:" ]]
}
34 changes: 34 additions & 0 deletions test/ctr.bats
Expand Up @@ -109,6 +109,40 @@ function teardown() {
stop_crio
}

@test "additional devices support" {
if test -n "$UID_MAPPINGS"; then
skip "userNS enabled"
fi
DEVICES="--additional-devices /dev/null:/dev/qifoo:rwm" start_crio
run crictl runp "$TESTDATA"/sandbox_config.json
echo "$output"
[ "$status" -eq 0 ]
pod_id="$output"

run crictl create "$pod_id" "$TESTDATA"/container_redis.json "$TESTDATA"/sandbox_config.json
echo "$output"
[ "$status" -eq 0 ]
ctr_id="$output"
run crictl start "$ctr_id"
echo "$output"
[ "$status" -eq 0 ]

run crictl exec --sync "$ctr_id" sh -c "ls /dev/qifoo"
echo $output
[ "$status" -eq 0 ]
[ "$output" == "/dev/qifoo" ]

run crictl stopp "$pod_id"
echo "$output"
[ "$status" -eq 0 ]
run crictl rmp "$pod_id"
echo "$output"
[ "$status" -eq 0 ]
cleanup_ctrs
cleanup_pods
stop_crio
}

@test "ctr remove" {
start_crio
run crictl runp "$TESTDATA"/sandbox_config.json
Expand Down
3 changes: 2 additions & 1 deletion test/helpers.bash
Expand Up @@ -29,6 +29,7 @@ RUNTIME=${RUNTIME:-runc}
UID_MAPPINGS=${UID_MAPPINGS:-}
GID_MAPPINGS=${GID_MAPPINGS:-}
ULIMITS=${ULIMITS:-}
DEVICES=${DEVICES:-}
OVERRIDE_OPTIONS=${OVERRIDE_OPTIONS:-}
RUNTIME_PATH=$(command -v $RUNTIME || true)
RUNTIME_BINARY=${RUNTIME_PATH:-/usr/local/sbin/runc}
Expand Down Expand Up @@ -243,7 +244,7 @@ function start_crio() {
"$COPYIMG_BINARY" --root "$TESTDIR/crio" $STORAGE_OPTIONS --runroot "$TESTDIR/crio-run" --image-name=quay.io/crio/image-volume-test:latest --import-from=dir:"$ARTIFACTS_PATH"/image-volume-test-image --signature-policy="$INTEGRATION_ROOT"/policy.json
"$COPYIMG_BINARY" --root "$TESTDIR/crio" $STORAGE_OPTIONS --runroot "$TESTDIR/crio-run" --image-name=quay.io/crio/busybox:latest --import-from=dir:"$ARTIFACTS_PATH"/busybox-image --signature-policy="$INTEGRATION_ROOT"/policy.json
"$COPYIMG_BINARY" --root "$TESTDIR/crio" $STORAGE_OPTIONS --runroot "$TESTDIR/crio-run" --image-name=quay.io/crio/stderr-test:latest --import-from=dir:"$ARTIFACTS_PATH"/stderr-test --signature-policy="$INTEGRATION_ROOT"/policy.json
"$CRIO_BINARY" ${DEFAULT_MOUNTS_OPTS} ${HOOKS_OPTS} --default-capabilities "$capabilities" --conmon "$CONMON_BINARY" --listen "$CRIO_SOCKET" --stream-port "$STREAM_PORT" --cgroup-manager "$CGROUP_MANAGER" --default-mounts-file "$TESTDIR/containers/mounts.conf" --registry "quay.io" --default-runtime $DEFAULT_RUNTIME --runtimes "$RUNTIME_NAME:$RUNTIME_BINARY" --root "$TESTDIR/crio" --runroot "$TESTDIR/crio-run" $STORAGE_OPTIONS --seccomp-profile "$seccomp" --apparmor-profile "$apparmor" --cni-config-dir "$CRIO_CNI_CONFIG" --cni-plugin-dir "$CRIO_CNI_PLUGIN" --signature-policy "$INTEGRATION_ROOT"/policy.json --image-volumes "$IMAGE_VOLUMES" --pids-limit "$PIDS_LIMIT" --log-size-max "$LOG_SIZE_MAX_LIMIT" $ULIMITS --uid-mappings "$UID_MAPPINGS" --gid-mappings "$GID_MAPPINGS" --default-sysctls "$TEST_SYSCTL" $OVERRIDE_OPTIONS --config /dev/null config >$CRIO_CONFIG
"$CRIO_BINARY" ${DEFAULT_MOUNTS_OPTS} ${HOOKS_OPTS} --default-capabilities "$capabilities" --conmon "$CONMON_BINARY" --listen "$CRIO_SOCKET" --stream-port "$STREAM_PORT" --cgroup-manager "$CGROUP_MANAGER" --default-mounts-file "$TESTDIR/containers/mounts.conf" --registry "quay.io" --default-runtime $DEFAULT_RUNTIME --runtimes "$RUNTIME_NAME:$RUNTIME_BINARY" --root "$TESTDIR/crio" --runroot "$TESTDIR/crio-run" $STORAGE_OPTIONS --seccomp-profile "$seccomp" --apparmor-profile "$apparmor" --cni-config-dir "$CRIO_CNI_CONFIG" --cni-plugin-dir "$CRIO_CNI_PLUGIN" --signature-policy "$INTEGRATION_ROOT"/policy.json --image-volumes "$IMAGE_VOLUMES" --pids-limit "$PIDS_LIMIT" --log-size-max "$LOG_SIZE_MAX_LIMIT" $DEVICES $ULIMITS --uid-mappings "$UID_MAPPINGS" --gid-mappings "$GID_MAPPINGS" --default-sysctls "$TEST_SYSCTL" $OVERRIDE_OPTIONS --config /dev/null config >$CRIO_CONFIG
sed -r -e 's/^(#)?root =/root =/g' -e 's/^(#)?runroot =/runroot =/g' -e 's/^(#)?storage_driver =/storage_driver =/g' -e '/^(#)?storage_option = (\[)?[ \t]*$/,/^#?$/s/^(#)?//g' -e '/^(#)?registries = (\[)?[ \t]*$/,/^#?$/s/^(#)?//g' -e '/^(#)?default_ulimits = (\[)?[ \t]*$/,/^#?$/s/^(#)?//g' -i $CRIO_CONFIG
# Prepare the CNI configuration files, we're running with non host networking by default
if [[ -n "$5" ]]; then
Expand Down
2 changes: 1 addition & 1 deletion vendor.conf
Expand Up @@ -124,7 +124,7 @@ github.com/cyphar/filepath-securejoin v0.2.1
gopkg.in/square/go-jose.v2 89060dee6a84df9a4dae49f676f0c755037834f1
golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631
github.com/cri-o/ocicni 84aa158d2bacf95147b2b0a89615dd665630f440
github.com/containers/libpod v0.8.3
github.com/containers/libpod e75469ab99c48e9fbe2b36ade229d384bdea9144
github.com/containerd/continuity d8fb8589b0e8e85b8c8bbaa8840226d0dfeb7371
github.com/modern-go/reflect2 05fbef0ca5da472bbf96c9322b84a53edc03c9fd
github.com/modern-go/concurrent bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94
Expand Down
60 changes: 49 additions & 11 deletions vendor/github.com/containers/libpod/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 41da373

Please sign in to comment.