Skip to content

Commit 6872057

Browse files
author
Mrunal Patel
authored
Merge pull request #307 from Kxuan/add-device
generate: add device option
2 parents 485e8cf + ebbc68e commit 6872057

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed

cmd/oci-runtime-tool/generate.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ var generateFlags = []cli.Flag{
2626
cli.StringSliceFlag{Name: "cap-drop", Usage: "drop Linux capabilities"},
2727
cli.StringFlag{Name: "cgroups-path", Usage: "specify the path to the cgroups"},
2828
cli.StringFlag{Name: "cwd", Value: "/", Usage: "current working directory for the process"},
29+
cli.StringSliceFlag{Name: "device", Usage: "specifies a device which must be made available in the container"},
2930
cli.BoolFlag{Name: "disable-oom-kill", Usage: "disable OOM Killer"},
3031
cli.StringSliceFlag{Name: "env", Usage: "add environment variable e.g. key=value"},
3132
cli.StringSliceFlag{Name: "env-file", Usage: "read in a file of environment variables"},
@@ -501,6 +502,15 @@ func setupSpec(g *generate.Generator, context *cli.Context) error {
501502
g.ClearProcessRlimits()
502503
}
503504

505+
if context.IsSet("device") {
506+
devices := context.StringSlice("device")
507+
for _, deviceArg := range devices {
508+
err := addDevice(deviceArg, g)
509+
if err != nil {
510+
return err
511+
}
512+
}
513+
}
504514
err := addSeccomp(context, g)
505515
return err
506516
}
@@ -625,6 +635,87 @@ func parseNamespace(ns string) (string, string, error) {
625635
return nsType, nsPath, nil
626636
}
627637

638+
var deviceType = map[string]bool{
639+
"b": true, // a block (buffered) special file
640+
"c": true, // a character special file
641+
"u": true, // a character (unbuffered) special file
642+
"p": true, // a FIFO
643+
}
644+
645+
// addDevice takes the raw string passed with the --device flag, parses it, and add it
646+
func addDevice(device string, g *generate.Generator) error {
647+
dev := rspec.Device{}
648+
649+
// The required part and optional part are seperated by ":"
650+
argsParts := strings.Split(device, ":")
651+
if len(argsParts) < 4 {
652+
return fmt.Errorf("Incomplete device arguments: %s", device)
653+
}
654+
requiredPart := argsParts[0:4]
655+
optionalPart := argsParts[4:]
656+
657+
// The required part must contain type, major, minor, and path
658+
dev.Type = requiredPart[0]
659+
if !deviceType[dev.Type] {
660+
return fmt.Errorf("Invalid device type: %s", dev.Type)
661+
}
662+
663+
i, err := strconv.ParseInt(requiredPart[1], 10, 64)
664+
if err != nil {
665+
return err
666+
}
667+
dev.Major = i
668+
669+
i, err = strconv.ParseInt(requiredPart[2], 10, 64)
670+
if err != nil {
671+
return err
672+
}
673+
dev.Minor = i
674+
dev.Path = requiredPart[3]
675+
676+
// The optional part include all optional property
677+
for _, s := range optionalPart {
678+
parts := strings.SplitN(s, "=", 2)
679+
680+
if len(parts) != 2 {
681+
return fmt.Errorf("Incomplete device arguments: %s", s)
682+
}
683+
684+
name, value := parts[0], parts[1]
685+
686+
switch name {
687+
case "fileMode":
688+
i, err := strconv.ParseInt(value, 10, 32)
689+
if err != nil {
690+
return err
691+
}
692+
mode := os.FileMode(i)
693+
dev.FileMode = &mode
694+
case "uid":
695+
i, err := strconv.ParseInt(value, 10, 32)
696+
if err != nil {
697+
return err
698+
}
699+
uid := uint32(i)
700+
dev.UID = &uid
701+
702+
case "gid":
703+
i, err := strconv.ParseInt(value, 10, 32)
704+
if err != nil {
705+
return err
706+
}
707+
gid := uint32(i)
708+
dev.GID = &gid
709+
default:
710+
return fmt.Errorf("'%s' is not supported by device section", name)
711+
}
712+
}
713+
714+
g.AddDevice(dev.Path, dev.Type, dev.Major, dev.Minor, dev.FileMode, dev.UID, dev.GID)
715+
716+
return nil
717+
}
718+
628719
func addSeccomp(context *cli.Context, g *generate.Generator) error {
629720

630721
// Set the DefaultAction of seccomp

completions/bash/oci-runtime-tool

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ _oci-runtime-tool_generate() {
305305
--cap-drop
306306
--cgroups-path
307307
--cwd
308+
--device
308309
--env
309310
--env-file
310311
--gid

generate/generate.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,22 @@ func (g *Generator) RemoveLinuxNamespace(ns string) error {
914914
return nil
915915
}
916916

917+
// AddDevice - add a device into g.spec.Linux.Devices
918+
func (g *Generator) AddDevice(path, devType string, major, minor int64, fileMode *os.FileMode, uid, gid *uint32) {
919+
g.initSpecLinux()
920+
921+
device := rspec.Device{
922+
Path: path,
923+
Type: devType,
924+
Major: major,
925+
Minor: minor,
926+
FileMode: fileMode,
927+
UID: uid,
928+
GID: gid,
929+
}
930+
g.spec.Linux.Devices = append(g.spec.Linux.Devices, device)
931+
}
932+
917933
// strPtr returns the pointer pointing to the string s.
918934
func strPtr(s string) *string { return &s }
919935

man/oci-runtime-tool-generate.1.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ read the configuration from `config.json`.
5151
**--cwd**=PATH
5252
Current working directory for the process. The deafult is */*.
5353

54+
**--device**=*TYPE:MAJOR:MINOR:PATH[:OPTIONS...]*
55+
Add a device file in container. e.g. --device=c:10:229:/dev/fuse:fileMode=438:uid=0:gid=0
56+
The *TYPE*, *MAJOR*, *MINOR*, *PATH* are required.
57+
*TYPE* is the device type. The acceptable values are b (block), c (character), u (unbuffered), p (FIFO).
58+
*MAJOR*/*MINOR* is the major/minor device id.
59+
*PATH* is the device path.
60+
The *fileMode*, *uid*, *gid* are optional.
61+
*fileMode* is the file mode of the device file.
62+
*uid*/*gid* is the user/group id of the device file.
63+
5464
**--disable-oom-kill**=true|false
5565
Whether to disable OOM Killer for the container or not.
5666

0 commit comments

Comments
 (0)