Skip to content

Commit

Permalink
Add support for multiples runtimes
Browse files Browse the repository at this point in the history
Signed-off-by: Kenfe-Mickael Laventure <[email protected]>
  • Loading branch information
mlaventure committed Jun 14, 2016
1 parent 2e9ea5c commit 7b2e521
Show file tree
Hide file tree
Showing 25 changed files with 568 additions and 23 deletions.
12 changes: 11 additions & 1 deletion api/client/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
ioutils.FprintfIfNotEmpty(cli.out, "Logging Driver: %s\n", info.LoggingDriver)
ioutils.FprintfIfNotEmpty(cli.out, "Cgroup Driver: %s\n", info.CgroupDriver)

fmt.Fprintf(cli.out, "Plugins: \n")
fmt.Fprintf(cli.out, "Plugins:\n")
fmt.Fprintf(cli.out, " Volume:")
fmt.Fprintf(cli.out, " %s", strings.Join(info.Plugins.Volume, " "))
fmt.Fprintf(cli.out, "\n")
Expand Down Expand Up @@ -84,6 +84,16 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
fmt.Fprintf(cli.out, " IsManager: No\n")
}
}

if len(info.Runtimes) > 0 {
fmt.Fprintf(cli.out, "Runtimes:")
for name := range info.Runtimes {
fmt.Fprintf(cli.out, " %s", name)
}
fmt.Fprint(cli.out, "\n")
fmt.Fprintf(cli.out, "Default Runtime: %s\n", info.DefaultRuntime)
}

ioutils.FprintfIfNotEmpty(cli.out, "Kernel Version: %s\n", info.KernelVersion)
ioutils.FprintfIfNotEmpty(cli.out, "Operating System: %s\n", info.OperatingSystem)
ioutils.FprintfIfNotEmpty(cli.out, "OSType: %s\n", info.OSType)
Expand Down
4 changes: 4 additions & 0 deletions cmd/dockerd/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,10 @@ func loadDaemonCliConfig(config *daemon.Config, flags *flag.FlagSet, commonConfi
}
}

if err := daemon.ValidateConfiguration(config); err != nil {
return nil, err
}

// Regardless of whether the user sets it to true or false, if they
// specify TLSVerify at all then we need to turn on TLS
if config.IsValueSet(cliflags.TLSVerifyKey) {
Expand Down
1 change: 1 addition & 0 deletions cmd/dockerd/daemon_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func (cli *DaemonCli) getPlatformRemoteOptions() []libcontainerd.RemoteOption {
if cli.Config.LiveRestore {
opts = append(opts, libcontainerd.WithLiveRestore(true))
}
opts = append(opts, libcontainerd.WithRuntimePath(daemon.DefaultRuntimeBinary))
return opts
}

Expand Down
31 changes: 27 additions & 4 deletions daemon/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/docker/docker/pkg/discovery"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/registry"
"github.com/docker/engine-api/types"
"github.com/imdario/mergo"
)

Expand All @@ -40,6 +41,7 @@ const (
var flatOptions = map[string]bool{
"cluster-store-opts": true,
"log-opts": true,
"runtimes": true,
}

// LogConfig represents the default log configuration.
Expand Down Expand Up @@ -200,7 +202,7 @@ func ReloadConfiguration(configFile string, flags *flag.FlagSet, reload func(*Co
return err
}

if err := validateConfiguration(newConfig); err != nil {
if err := ValidateConfiguration(newConfig); err != nil {
return fmt.Errorf("file configuration validation failed (%v)", err)
}

Expand All @@ -224,7 +226,7 @@ func MergeDaemonConfigurations(flagsConfig *Config, flags *flag.FlagSet, configF
return nil, err
}

if err := validateConfiguration(fileConfig); err != nil {
if err := ValidateConfiguration(fileConfig); err != nil {
return nil, fmt.Errorf("file configuration validation failed (%v)", err)
}

Expand All @@ -233,6 +235,12 @@ func MergeDaemonConfigurations(flagsConfig *Config, flags *flag.FlagSet, configF
return nil, err
}

// We need to validate again once both fileConfig and flagsConfig
// have been merged
if err := ValidateConfiguration(fileConfig); err != nil {
return nil, fmt.Errorf("file configuration validation failed (%v)", err)
}

return fileConfig, nil
}

Expand Down Expand Up @@ -381,10 +389,10 @@ func findConfigurationConflicts(config map[string]interface{}, flags *flag.FlagS
return nil
}

// validateConfiguration validates some specific configs.
// ValidateConfiguration validates some specific configs.
// such as config.DNS, config.Labels, config.DNSSearch,
// as well as config.MaxConcurrentDownloads, config.MaxConcurrentUploads.
func validateConfiguration(config *Config) error {
func ValidateConfiguration(config *Config) error {
// validate DNS
for _, dns := range config.DNS {
if _, err := opts.ValidateIPAddress(dns); err != nil {
Expand Down Expand Up @@ -415,5 +423,20 @@ func validateConfiguration(config *Config) error {
if config.IsValueSet("max-concurrent-uploads") && config.MaxConcurrentUploads != nil && *config.MaxConcurrentUploads < 0 {
return fmt.Errorf("invalid max concurrent uploads: %d", *config.MaxConcurrentUploads)
}

// validate that "default" runtime is not reset
if runtimes := config.GetAllRuntimes(); len(runtimes) > 0 {
if _, ok := runtimes[types.DefaultRuntimeName]; ok {
return fmt.Errorf("runtime name '%s' is reserved", types.DefaultRuntimeName)
}
}

if defaultRuntime := config.GetDefaultRuntimeName(); defaultRuntime != "" && defaultRuntime != types.DefaultRuntimeName {
runtimes := config.GetAllRuntimes()
if _, ok := runtimes[defaultRuntime]; !ok {
return fmt.Errorf("specified default runtime '%s' does not exist", defaultRuntime)
}
}

return nil
}
12 changes: 6 additions & 6 deletions daemon/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ func TestValidateConfiguration(t *testing.T) {
},
}

err := validateConfiguration(c1)
err := ValidateConfiguration(c1)
if err == nil {
t.Fatal("expected error, got nil")
}
Expand All @@ -227,7 +227,7 @@ func TestValidateConfiguration(t *testing.T) {
},
}

err = validateConfiguration(c2)
err = ValidateConfiguration(c2)
if err != nil {
t.Fatalf("expected no error, got error %v", err)
}
Expand All @@ -238,7 +238,7 @@ func TestValidateConfiguration(t *testing.T) {
},
}

err = validateConfiguration(c3)
err = ValidateConfiguration(c3)
if err != nil {
t.Fatalf("expected no error, got error %v", err)
}
Expand All @@ -249,7 +249,7 @@ func TestValidateConfiguration(t *testing.T) {
},
}

err = validateConfiguration(c4)
err = ValidateConfiguration(c4)
if err == nil {
t.Fatal("expected error, got nil")
}
Expand All @@ -260,7 +260,7 @@ func TestValidateConfiguration(t *testing.T) {
},
}

err = validateConfiguration(c5)
err = ValidateConfiguration(c5)
if err != nil {
t.Fatalf("expected no error, got error %v", err)
}
Expand All @@ -271,7 +271,7 @@ func TestValidateConfiguration(t *testing.T) {
},
}

err = validateConfiguration(c6)
err = ValidateConfiguration(c6)
if err == nil {
t.Fatal("expected error, got nil")
}
Expand Down
34 changes: 34 additions & 0 deletions daemon/config_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/docker/docker/opts"
flag "github.com/docker/docker/pkg/mflag"
runconfigopts "github.com/docker/docker/runconfig/opts"
"github.com/docker/engine-api/types"
"github.com/docker/go-units"
)

Expand All @@ -30,6 +31,8 @@ type Config struct {
ExecRoot string `json:"exec-root,omitempty"`
RemappedRoot string `json:"userns-remap,omitempty"`
Ulimits map[string]*units.Ulimit `json:"default-ulimits,omitempty"`
Runtimes map[string]types.Runtime `json:"runtimes,omitempty"`
DefaultRuntime string `json:"default-runtime,omitempty"`
}

// bridgeConfig stores all the bridge driver specific
Expand Down Expand Up @@ -83,6 +86,37 @@ func (config *Config) InstallFlags(cmd *flag.FlagSet, usageFn func(string) strin
cmd.StringVar(&config.RemappedRoot, []string{"-userns-remap"}, "", usageFn("User/Group setting for user namespaces"))
cmd.StringVar(&config.ContainerdAddr, []string{"-containerd"}, "", usageFn("Path to containerd socket"))
cmd.BoolVar(&config.LiveRestore, []string{"-live-restore"}, false, usageFn("Enable live restore of docker when containers are still running"))
config.Runtimes = make(map[string]types.Runtime)
cmd.Var(runconfigopts.NewNamedRuntimeOpt("runtimes", &config.Runtimes), []string{"-add-runtime"}, usageFn("Register an additional OCI compatible runtime"))
cmd.StringVar(&config.DefaultRuntime, []string{"-default-runtime"}, types.DefaultRuntimeName, usageFn("Default OCI runtime to be used"))

config.attachExperimentalFlags(cmd, usageFn)
}

// GetRuntime returns the runtime path and arguments for a given
// runtime name
func (config *Config) GetRuntime(name string) *types.Runtime {
config.reloadLock.Lock()
defer config.reloadLock.Unlock()
if rt, ok := config.Runtimes[name]; ok {
return &rt
}
return nil
}

// GetDefaultRuntimeName returns the current default runtime
func (config *Config) GetDefaultRuntimeName() string {
config.reloadLock.Lock()
rt := config.DefaultRuntime
config.reloadLock.Unlock()

return rt
}

// GetAllRuntimes returns a copy of the runtimes map
func (config *Config) GetAllRuntimes() map[string]types.Runtime {
config.reloadLock.Lock()
rts := config.Runtimes
config.reloadLock.Unlock()
return rts
}
17 changes: 17 additions & 0 deletions daemon/config_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"os"

flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/engine-api/types"
)

var (
Expand Down Expand Up @@ -40,3 +41,19 @@ func (config *Config) InstallFlags(cmd *flag.FlagSet, usageFn func(string) strin
cmd.StringVar(&config.bridgeConfig.Iface, []string{"b", "-bridge"}, "", "Attach containers to a virtual switch")
cmd.StringVar(&config.SocketGroup, []string{"G", "-group"}, "", usageFn("Users or groups that can access the named pipe"))
}

// GetRuntime returns the runtime path and arguments for a given
// runtime name
func (config *Config) GetRuntime(name string) *types.Runtime {
return nil
}

// GetDefaultRuntimeName returns the current default runtime
func (config *Config) GetDefaultRuntimeName() string {
return types.DefaultRuntimeName
}

// GetAllRuntimes returns a copy of the runtimes map
func (config *Config) GetAllRuntimes() map[string]types.Runtime {
return map[string]types.Runtime{}
}
22 changes: 19 additions & 3 deletions daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ import (
)

var (
// DefaultRuntimeBinary is the default runtime to be used by
// containerd if none is specified
DefaultRuntimeBinary = "docker-runc"

errSystemNotSupported = fmt.Errorf("The Docker daemon is not supported on this platform.")
)

Expand Down Expand Up @@ -811,10 +815,24 @@ func (daemon *Daemon) initDiscovery(config *Config) error {
// - Cluster discovery (reconfigure and restart).
// - Daemon live restore
func (daemon *Daemon) Reload(config *Config) error {
var err error
// used to hold reloaded changes
attributes := map[string]string{}

// We need defer here to ensure the lock is released as
// daemon.SystemInfo() will try to get it too
defer func() {
if err == nil {
daemon.LogDaemonEventWithAttributes("reload", attributes)
}
}()

daemon.configStore.reloadLock.Lock()
defer daemon.configStore.reloadLock.Unlock()

if err := daemon.reloadClusterDiscovery(config); err != nil {
daemon.platformReload(config, &attributes)

if err = daemon.reloadClusterDiscovery(config); err != nil {
return err
}

Expand Down Expand Up @@ -859,7 +877,6 @@ func (daemon *Daemon) Reload(config *Config) error {
}

// We emit daemon reload event here with updatable configurations
attributes := map[string]string{}
attributes["debug"] = fmt.Sprintf("%t", daemon.configStore.Debug)
attributes["cluster-store"] = daemon.configStore.ClusterStore
if daemon.configStore.ClusterOpts != nil {
Expand All @@ -877,7 +894,6 @@ func (daemon *Daemon) Reload(config *Config) error {
}
attributes["max-concurrent-downloads"] = fmt.Sprintf("%d", *daemon.configStore.MaxConcurrentDownloads)
attributes["max-concurrent-uploads"] = fmt.Sprintf("%d", *daemon.configStore.MaxConcurrentUploads)
daemon.LogDaemonEventWithAttributes("reload", attributes)

return nil
}
Expand Down
4 changes: 4 additions & 0 deletions daemon/daemon_solaris.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.
return warnings, nil
}

// platformReload update configuration with platform specific options
func (daemon *Daemon) platformReload(config *Config, attributes *map[string]string) {
}

// verifyDaemonSettings performs validation of daemon config struct
func verifyDaemonSettings(config *Config) error {
// checkSystem validates platform-specific requirements
Expand Down
43 changes: 43 additions & 0 deletions daemon/daemon_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package daemon

import (
"bytes"
"fmt"
"io/ioutil"
"net"
Expand Down Expand Up @@ -515,9 +516,42 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.
return warnings, fmt.Errorf("cgroup-parent for systemd cgroup should be a valid slice named as \"xxx.slice\"")
}
}
if hostConfig.Runtime == "" {
hostConfig.Runtime = daemon.configStore.GetDefaultRuntimeName()
}

if rt := daemon.configStore.GetRuntime(hostConfig.Runtime); rt == nil {
return warnings, fmt.Errorf("Unknown runtime specified %s", hostConfig.Runtime)
}

return warnings, nil
}

// platformReload update configuration with platform specific options
func (daemon *Daemon) platformReload(config *Config, attributes *map[string]string) {
if config.IsValueSet("runtimes") {
daemon.configStore.Runtimes = config.Runtimes
// Always set the default one
daemon.configStore.Runtimes[types.DefaultRuntimeName] = types.Runtime{Path: DefaultRuntimeBinary}
}

if config.DefaultRuntime != "" {
daemon.configStore.DefaultRuntime = config.DefaultRuntime
}

// Update attributes
var runtimeList bytes.Buffer
for name, rt := range daemon.configStore.Runtimes {
if runtimeList.Len() > 0 {
runtimeList.WriteRune(' ')
}
runtimeList.WriteString(fmt.Sprintf("%s:%s", name, rt))
}

(*attributes)["runtimes"] = runtimeList.String()
(*attributes)["default-runtime"] = daemon.configStore.DefaultRuntime
}

// verifyDaemonSettings performs validation of daemon config struct
func verifyDaemonSettings(config *Config) error {
// Check for mutually incompatible config options
Expand All @@ -538,6 +572,15 @@ func verifyDaemonSettings(config *Config) error {
return fmt.Errorf("cgroup-parent for systemd cgroup should be a valid slice named as \"xxx.slice\"")
}
}

if config.DefaultRuntime == "" {
config.DefaultRuntime = types.DefaultRuntimeName
}
if config.Runtimes == nil {
config.Runtimes = make(map[string]types.Runtime)
}
config.Runtimes[types.DefaultRuntimeName] = types.Runtime{Path: DefaultRuntimeBinary}

return nil
}

Expand Down
Loading

0 comments on commit 7b2e521

Please sign in to comment.