|
@@ -6,6 +6,7 @@ import (
|
|
"fmt"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"io/ioutil"
|
|
"path"
|
|
"path"
|
|
|
|
+ "regexp"
|
|
"strconv"
|
|
"strconv"
|
|
"strings"
|
|
"strings"
|
|
"time"
|
|
"time"
|
|
@@ -21,6 +22,10 @@ import (
|
|
"github.com/spf13/pflag"
|
|
"github.com/spf13/pflag"
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+var (
|
|
|
|
+ deviceCgroupRuleRegexp = regexp.MustCompile("^[acb] ([0-9]+|\\*):([0-9]+|\\*) [rwm]{1,3}$")
|
|
|
|
+)
|
|
|
|
+
|
|
// containerOptions is a data object with all the options for creating a container
|
|
// containerOptions is a data object with all the options for creating a container
|
|
type containerOptions struct {
|
|
type containerOptions struct {
|
|
attach opts.ListOpts
|
|
attach opts.ListOpts
|
|
@@ -36,6 +41,7 @@ type containerOptions struct {
|
|
deviceWriteIOps opts.ThrottledeviceOpt
|
|
deviceWriteIOps opts.ThrottledeviceOpt
|
|
env opts.ListOpts
|
|
env opts.ListOpts
|
|
labels opts.ListOpts
|
|
labels opts.ListOpts
|
|
|
|
+ deviceCgroupRules opts.ListOpts
|
|
devices opts.ListOpts
|
|
devices opts.ListOpts
|
|
ulimits *opts.UlimitOpt
|
|
ulimits *opts.UlimitOpt
|
|
sysctls *opts.MapOpts
|
|
sysctls *opts.MapOpts
|
|
@@ -127,6 +133,7 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
|
dns: opts.NewListOpts(opts.ValidateIPAddress),
|
|
dns: opts.NewListOpts(opts.ValidateIPAddress),
|
|
dnsOptions: opts.NewListOpts(nil),
|
|
dnsOptions: opts.NewListOpts(nil),
|
|
dnsSearch: opts.NewListOpts(opts.ValidateDNSSearch),
|
|
dnsSearch: opts.NewListOpts(opts.ValidateDNSSearch),
|
|
|
|
+ deviceCgroupRules: opts.NewListOpts(validateDeviceCgroupRule),
|
|
deviceReadBps: opts.NewThrottledeviceOpt(opts.ValidateThrottleBpsDevice),
|
|
deviceReadBps: opts.NewThrottledeviceOpt(opts.ValidateThrottleBpsDevice),
|
|
deviceReadIOps: opts.NewThrottledeviceOpt(opts.ValidateThrottleIOpsDevice),
|
|
deviceReadIOps: opts.NewThrottledeviceOpt(opts.ValidateThrottleIOpsDevice),
|
|
deviceWriteBps: opts.NewThrottledeviceOpt(opts.ValidateThrottleBpsDevice),
|
|
deviceWriteBps: opts.NewThrottledeviceOpt(opts.ValidateThrottleBpsDevice),
|
|
@@ -154,6 +161,7 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
|
|
|
|
|
// General purpose flags
|
|
// General purpose flags
|
|
flags.VarP(&copts.attach, "attach", "a", "Attach to STDIN, STDOUT or STDERR")
|
|
flags.VarP(&copts.attach, "attach", "a", "Attach to STDIN, STDOUT or STDERR")
|
|
|
|
+ flags.Var(&copts.deviceCgroupRules, "device-cgroup-rule", "Add a rule to the cgroup allowed devices list")
|
|
flags.Var(&copts.devices, "device", "Add a host device to the container")
|
|
flags.Var(&copts.devices, "device", "Add a host device to the container")
|
|
flags.VarP(&copts.env, "env", "e", "Set environment variables")
|
|
flags.VarP(&copts.env, "env", "e", "Set environment variables")
|
|
flags.Var(&copts.envFile, "env-file", "Read in a file of environment variables")
|
|
flags.Var(&copts.envFile, "env-file", "Read in a file of environment variables")
|
|
@@ -548,6 +556,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions) (*container.Config, *c
|
|
IOMaximumIOps: copts.ioMaxIOps,
|
|
IOMaximumIOps: copts.ioMaxIOps,
|
|
IOMaximumBandwidth: uint64(maxIOBandwidth),
|
|
IOMaximumBandwidth: uint64(maxIOBandwidth),
|
|
Ulimits: copts.ulimits.GetList(),
|
|
Ulimits: copts.ulimits.GetList(),
|
|
|
|
+ DeviceCgroupRules: copts.deviceCgroupRules.GetAll(),
|
|
Devices: deviceMappings,
|
|
Devices: deviceMappings,
|
|
}
|
|
}
|
|
|
|
|
|
@@ -762,6 +771,17 @@ func parseDevice(device string) (container.DeviceMapping, error) {
|
|
return deviceMapping, nil
|
|
return deviceMapping, nil
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// validateDeviceCgroupRule validates a device cgroup rule string format
|
|
|
|
+// It will make sure 'val' is in the form:
|
|
|
|
+// 'type major:minor mode'
|
|
|
|
+func validateDeviceCgroupRule(val string) (string, error) {
|
|
|
|
+ if deviceCgroupRuleRegexp.MatchString(val) {
|
|
|
|
+ return val, nil
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return val, fmt.Errorf("invalid device cgroup format '%s'", val)
|
|
|
|
+}
|
|
|
|
+
|
|
// validDeviceMode checks if the mode for device is valid or not.
|
|
// validDeviceMode checks if the mode for device is valid or not.
|
|
// Valid mode is a composition of r (read), w (write), and m (mknod).
|
|
// Valid mode is a composition of r (read), w (write), and m (mknod).
|
|
func validDeviceMode(mode string) bool {
|
|
func validDeviceMode(mode string) bool {
|