|
@@ -4,8 +4,10 @@ import (
|
|
"fmt"
|
|
"fmt"
|
|
"github.com/dotcloud/docker/nat"
|
|
"github.com/dotcloud/docker/nat"
|
|
"github.com/dotcloud/docker/opts"
|
|
"github.com/dotcloud/docker/opts"
|
|
|
|
+ "github.com/dotcloud/docker/pkg/label"
|
|
flag "github.com/dotcloud/docker/pkg/mflag"
|
|
flag "github.com/dotcloud/docker/pkg/mflag"
|
|
"github.com/dotcloud/docker/pkg/sysinfo"
|
|
"github.com/dotcloud/docker/pkg/sysinfo"
|
|
|
|
+ "github.com/dotcloud/docker/runtime/execdriver"
|
|
"github.com/dotcloud/docker/utils"
|
|
"github.com/dotcloud/docker/utils"
|
|
"io/ioutil"
|
|
"io/ioutil"
|
|
"path"
|
|
"path"
|
|
@@ -32,6 +34,10 @@ func ParseSubcommand(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo)
|
|
}
|
|
}
|
|
|
|
|
|
func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Config, *HostConfig, *flag.FlagSet, error) {
|
|
func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Config, *HostConfig, *flag.FlagSet, error) {
|
|
|
|
+ var (
|
|
|
|
+ processLabel string
|
|
|
|
+ mountLabel string
|
|
|
|
+ )
|
|
var (
|
|
var (
|
|
// FIXME: use utils.ListOpts for attach and volumes?
|
|
// FIXME: use utils.ListOpts for attach and volumes?
|
|
flAttach = opts.NewListOpts(opts.ValidateAttach)
|
|
flAttach = opts.NewListOpts(opts.ValidateAttach)
|
|
@@ -61,6 +67,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
|
|
flUser = cmd.String([]string{"u", "-user"}, "", "Username or UID")
|
|
flUser = cmd.String([]string{"u", "-user"}, "", "Username or UID")
|
|
flWorkingDir = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container")
|
|
flWorkingDir = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container")
|
|
flCpuShares = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
|
|
flCpuShares = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
|
|
|
|
+ flLabelOptions = cmd.String([]string{"Z", "-label"}, "", "Options to pass to underlying labeling system")
|
|
|
|
|
|
// For documentation purpose
|
|
// For documentation purpose
|
|
_ = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxify all received signal to the process (even in non-tty mode)")
|
|
_ = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxify all received signal to the process (even in non-tty mode)")
|
|
@@ -77,7 +84,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
|
|
cmd.Var(&flDns, []string{"#dns", "-dns"}, "Set custom dns servers")
|
|
cmd.Var(&flDns, []string{"#dns", "-dns"}, "Set custom dns servers")
|
|
cmd.Var(&flDnsSearch, []string{"-dns-search"}, "Set custom dns search domains")
|
|
cmd.Var(&flDnsSearch, []string{"-dns-search"}, "Set custom dns search domains")
|
|
cmd.Var(&flVolumesFrom, []string{"#volumes-from", "-volumes-from"}, "Mount volumes from the specified container(s)")
|
|
cmd.Var(&flVolumesFrom, []string{"#volumes-from", "-volumes-from"}, "Mount volumes from the specified container(s)")
|
|
- cmd.Var(&flLxcOpts, []string{"#lxc-conf", "#-lxc-conf"}, "Add custom lxc options --lxc-conf=\"lxc.cgroup.cpuset.cpus = 0,1\"")
|
|
|
|
|
|
+ cmd.Var(&flLxcOpts, []string{"#lxc-conf", "#-lxc-conf"}, "(lxc exec-driver only) Add custom lxc options --lxc-conf=\"lxc.cgroup.cpuset.cpus = 0,1\"")
|
|
cmd.Var(&flDriverOpts, []string{"o", "-opt"}, "Add custom driver options")
|
|
cmd.Var(&flDriverOpts, []string{"o", "-opt"}, "Add custom driver options")
|
|
|
|
|
|
if err := cmd.Parse(args); err != nil {
|
|
if err := cmd.Parse(args); err != nil {
|
|
@@ -152,7 +159,16 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
|
|
entrypoint = []string{*flEntrypoint}
|
|
entrypoint = []string{*flEntrypoint}
|
|
}
|
|
}
|
|
|
|
|
|
- lxcConf, err := parseLxcConfOpts(flLxcOpts)
|
|
|
|
|
|
+ if !*flPrivileged {
|
|
|
|
+ pLabel, mLabel, e := label.GenLabels(*flLabelOptions)
|
|
|
|
+ if e != nil {
|
|
|
|
+ return nil, nil, cmd, fmt.Errorf("Invalid security labels : %s", e)
|
|
|
|
+ }
|
|
|
|
+ processLabel = pLabel
|
|
|
|
+ mountLabel = mLabel
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ lxcConf, err := parseKeyValueOpts(flLxcOpts)
|
|
if err != nil {
|
|
if err != nil {
|
|
return nil, nil, cmd, err
|
|
return nil, nil, cmd, err
|
|
}
|
|
}
|
|
@@ -206,6 +222,15 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
|
|
VolumesFrom: strings.Join(flVolumesFrom.GetAll(), ","),
|
|
VolumesFrom: strings.Join(flVolumesFrom.GetAll(), ","),
|
|
Entrypoint: entrypoint,
|
|
Entrypoint: entrypoint,
|
|
WorkingDir: *flWorkingDir,
|
|
WorkingDir: *flWorkingDir,
|
|
|
|
+ Context: execdriver.Context{
|
|
|
|
+ "mount_label": mountLabel,
|
|
|
|
+ "process_label": processLabel,
|
|
|
|
+ },
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ driverOptions, err := parseDriverOpts(flDriverOpts)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, nil, cmd, err
|
|
}
|
|
}
|
|
|
|
|
|
pluginOptions, err := parseDriverOpts(flDriverOpts)
|
|
pluginOptions, err := parseDriverOpts(flDriverOpts)
|
|
@@ -221,7 +246,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
|
|
PortBindings: portBindings,
|
|
PortBindings: portBindings,
|
|
Links: flLinks.GetAll(),
|
|
Links: flLinks.GetAll(),
|
|
PublishAllPorts: *flPublishAll,
|
|
PublishAllPorts: *flPublishAll,
|
|
- DriverOptions: pluginOptions,
|
|
|
|
|
|
+ DriverOptions: driverOptions,
|
|
}
|
|
}
|
|
|
|
|
|
if sysInfo != nil && flMemory > 0 && !sysInfo.SwapLimit {
|
|
if sysInfo != nil && flMemory > 0 && !sysInfo.SwapLimit {
|
|
@@ -236,24 +261,33 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
|
|
return config, hostConfig, cmd, nil
|
|
return config, hostConfig, cmd, nil
|
|
}
|
|
}
|
|
|
|
|
|
-func parseLxcConfOpts(opts opts.ListOpts) ([]KeyValuePair, error) {
|
|
|
|
- out := make([]KeyValuePair, opts.Len())
|
|
|
|
- for i, o := range opts.GetAll() {
|
|
|
|
- k, v, err := parseLxcOpt(o)
|
|
|
|
- if err != nil {
|
|
|
|
- return nil, err
|
|
|
|
|
|
+// options will come in the format of name.key=value or name.option
|
|
|
|
+func parseDriverOpts(opts opts.ListOpts) (map[string][]string, error) {
|
|
|
|
+ out := make(map[string][]string, len(opts.GetAll()))
|
|
|
|
+ for _, o := range opts.GetAll() {
|
|
|
|
+ parts := strings.SplitN(o, ".", 2)
|
|
|
|
+ if len(parts) < 2 {
|
|
|
|
+ return nil, fmt.Errorf("invalid opt format %s", o)
|
|
|
|
+ }
|
|
|
|
+ values, exists := out[parts[0]]
|
|
|
|
+ if !exists {
|
|
|
|
+ values = []string{}
|
|
}
|
|
}
|
|
- out[i] = KeyValuePair{Key: k, Value: v}
|
|
|
|
|
|
+ out[parts[0]] = append(values, parts[1])
|
|
}
|
|
}
|
|
return out, nil
|
|
return out, nil
|
|
}
|
|
}
|
|
|
|
|
|
-func parseLxcOpt(opt string) (string, string, error) {
|
|
|
|
- parts := strings.SplitN(opt, "=", 2)
|
|
|
|
- if len(parts) != 2 {
|
|
|
|
- return "", "", fmt.Errorf("Unable to parse lxc conf option: %s", opt)
|
|
|
|
|
|
+func parseKeyValueOpts(opts opts.ListOpts) ([]utils.KeyValuePair, error) {
|
|
|
|
+ out := make([]utils.KeyValuePair, opts.Len())
|
|
|
|
+ for i, o := range opts.GetAll() {
|
|
|
|
+ k, v, err := utils.ParseKeyValueOpt(o)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+ out[i] = utils.KeyValuePair{Key: k, Value: v}
|
|
}
|
|
}
|
|
- return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
|
|
|
|
|
|
+ return out, nil
|
|
}
|
|
}
|
|
|
|
|
|
// options will come in the format of name.type=value
|
|
// options will come in the format of name.type=value
|