add -experimental to enable rescheduling

Signed-off-by: Victor Vieux <vieux@docker.com>
This commit is contained in:
Victor Vieux 2016-01-12 00:03:00 -08:00
parent 254e095f77
commit 14bf4e08b3
6 changed files with 55 additions and 23 deletions

View File

@ -7,6 +7,7 @@ import (
log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/docker/swarm/experimental"
"github.com/docker/swarm/version"
)
@ -32,6 +33,11 @@ func Run() {
Value: "info",
Usage: fmt.Sprintf("Log level (options: debug, info, warn, error, fatal, panic)"),
},
cli.BoolFlag{
Name: "experimental",
Usage: "enable experimental features",
},
}
// logs
@ -49,6 +55,8 @@ func Run() {
log.SetLevel(log.DebugLevel)
}
experimental.ENABLED = c.Bool("experimental")
return nil
}

View File

@ -17,6 +17,7 @@ import (
"github.com/docker/swarm/cluster"
"github.com/docker/swarm/cluster/mesos"
"github.com/docker/swarm/cluster/swarm"
"github.com/docker/swarm/experimental"
"github.com/docker/swarm/leadership"
"github.com/docker/swarm/scheduler"
"github.com/docker/swarm/scheduler/filter"
@ -324,6 +325,9 @@ func manage(c *cli.Context) {
server.SetHandler(api.NewPrimary(cl, tlsConfig, &statusHandler{cl, nil, nil}, c.GlobalBool("debug"), c.Bool("cors")))
}
cluster.NewWatchdog(cl)
if experimental.ENABLED {
log.Warn("WARNING: rescheduling is currently experimental, use at your own risks")
cluster.NewWatchdog(cl)
}
log.Fatal(server.ListenAndServe())
}

View File

@ -6,6 +6,7 @@ import (
"fmt"
"strings"
"github.com/docker/swarm/experimental"
"github.com/samalba/dockerclient"
)
@ -86,25 +87,26 @@ func BuildContainerConfig(c dockerclient.ContainerConfig) *ContainerConfig {
json.Unmarshal([]byte(labels), &constraints)
}
// parse reschedule policy from labels (ex. docker run --label 'com.docker.swarm.reschedule-policies=on-node-failure')
if labels, ok := c.Labels[SwarmLabelNamespace+".reschedule-policies"]; ok {
json.Unmarshal([]byte(labels), &reschedulePolicies)
if experimental.ENABLED {
// parse reschedule policy from labels (ex. docker run --label 'com.docker.swarm.reschedule-policies=on-node-failure')
if labels, ok := c.Labels[SwarmLabelNamespace+".reschedule-policies"]; ok {
json.Unmarshal([]byte(labels), &reschedulePolicies)
}
}
// parse affinities/constraints/reschedule policies from env (ex. docker run -e affinity:container==redis -e affinity:image==nginx -e constraint:region==us-east -e constraint:storage==ssd -e reschedule:off)
for _, e := range c.Env {
if ok, key, value := parseEnv(e); ok && key == "affinity" {
affinities = append(affinities, value)
} else if ok && key == "constraint" {
constraints = append(constraints, value)
} else if ok && key == "reschedule" {
} else if experimental.ENABLED && ok && key == "reschedule" {
reschedulePolicies = append(reschedulePolicies, value)
} else {
env = append(env, e)
}
}
// remove affinities/constraints from env
// remove affinities/constraints/reschedule policies from env
c.Env = env
// store affinities in labels
@ -121,10 +123,12 @@ func BuildContainerConfig(c dockerclient.ContainerConfig) *ContainerConfig {
}
}
// store reschedule policies in labels
if len(reschedulePolicies) > 0 {
if labels, err := json.Marshal(reschedulePolicies); err == nil {
c.Labels[SwarmLabelNamespace+".reschedule-policies"] = string(labels)
if experimental.ENABLED {
// store reschedule policies in labels
if len(reschedulePolicies) > 0 {
if labels, err := json.Marshal(reschedulePolicies); err == nil {
c.Labels[SwarmLabelNamespace+".reschedule-policies"] = string(labels)
}
}
}
@ -217,19 +221,23 @@ func (c *ContainerConfig) HasReschedulePolicy(p string) bool {
// Validate returns an error if the config isn't valid
func (c *ContainerConfig) Validate() error {
//TODO: add validation for affinities and constraints
reschedulePolicies := c.extractExprs("reschedule-policies")
if len(reschedulePolicies) > 1 {
return errors.New("too many reschedule policies")
} else if len(reschedulePolicies) == 1 {
valid := false
for _, validReschedulePolicy := range []string{"off", "on-node-failure"} {
if reschedulePolicies[0] == validReschedulePolicy {
valid = true
if experimental.ENABLED {
reschedulePolicies := c.extractExprs("reschedule-policies")
if len(reschedulePolicies) > 1 {
return errors.New("too many reschedule policies")
} else if len(reschedulePolicies) == 1 {
valid := false
for _, validReschedulePolicy := range []string{"off", "on-node-failure"} {
if reschedulePolicies[0] == validReschedulePolicy {
valid = true
}
}
if !valid {
return fmt.Errorf("invalid reschedule policy: %s", reschedulePolicies[0])
}
}
if !valid {
return fmt.Errorf("invalid reschedule policy: %s", reschedulePolicies[0])
}
}
return nil
}

View File

@ -8,7 +8,15 @@ The information below describes each feature and the GitHub pull requests and
issues associated with it. If necessary, links are provided to additional
documentation on an issue. As an active Docker user and community member,
please feel free to provide any feedback on these features you wish.
## Enable experimental features
To enable experimental feature, use the flag `-experimental` on swarm, for example:
```
$ swarm -experimental manage ...
# or
$ swarm -experimental join ...
```
## Current experimental features

View File

@ -0,0 +1,4 @@
package experimental
// ENABLED is set to true when the -experimental flag is set.
var ENABLED = false

View File

@ -117,7 +117,7 @@ function swarm_manage_no_wait() {
local port=$(($SWARM_BASE_PORT + $i))
local host=127.0.0.1:$port
"$SWARM_BINARY" -l debug manage -H "$host" --heartbeat=1s $discovery &
"$SWARM_BINARY" -l debug -experimental manage -H "$host" --heartbeat=1s $discovery &
SWARM_MANAGE_PID[$i]=$!
SWARM_HOSTS[$i]=$host