From b1e80ce157a68e31a4382f79859de66df946094e Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Fri, 12 Dec 2014 23:57:27 +0000 Subject: [PATCH] add --strategy to choose the strategy to use Signed-off-by: Victor Vieux --- flags.go | 52 ++++++++++++++++++++++++++++++++ main.go | 44 +-------------------------- manage.go | 10 ++++-- scheduler/strategy/binpacking.go | 6 ++++ scheduler/strategy/random.go | 9 +++--- scheduler/strategy/strategy.go | 35 +++++++++++++++++++++ 6 files changed, 106 insertions(+), 50 deletions(-) create mode 100644 flags.go diff --git a/flags.go b/flags.go new file mode 100644 index 0000000000..e2910a7347 --- /dev/null +++ b/flags.go @@ -0,0 +1,52 @@ +package main + +import "github.com/codegangsta/cli" + +var ( + flDiscovery = cli.StringFlag{ + Name: "discovery", + Value: "", + Usage: "DiscoveryService to use [token://, etcd://,/, file://path/to/file]", + EnvVar: "SWARM_DISCOVERY", + } + flAddr = cli.StringFlag{ + Name: "addr", + Value: "127.0.0.1:4243", + Usage: "ip to advertise", + EnvVar: "SWARM_ADDR", + } + flHeartBeat = cli.IntFlag{ + Name: "heartbeat, hb", + Value: 25, + Usage: "time in second between each heartbeat", + } + flEnableCors = cli.BoolFlag{ + Name: "api-enable-cors, cors", + Usage: "enable CORS headers in the remote API", + } + flTls = cli.BoolFlag{ + Name: "tls", + Usage: "Use TLS; implied by --tlsverify=true", + } + flTlsCaCert = cli.StringFlag{ + Name: "tlscacert", + Usage: "Trust only remotes providing a certificate signed by the CA given here", + } + flTlsCert = cli.StringFlag{ + Name: "tlscert", + Usage: "Path to TLS certificate file", + } + flTlsKey = cli.StringFlag{ + Name: "tlskey", + Usage: "Path to TLS key file", + } + flTlsVerify = cli.BoolFlag{ + Name: "tlsverify", + Usage: "Use TLS and verify the remote", + } + flStrategy = cli.StringFlag{ + Name: "strategy", + Usage: "PlacementStrategy to use [binpacking, random]", + Value: "binpacking:0.05", + } +) diff --git a/main.go b/main.go index 332dbada1d..ea733d5226 100644 --- a/main.go +++ b/main.go @@ -36,49 +36,6 @@ func main() { return nil } - // flags - flDiscovery := cli.StringFlag{ - Name: "discovery", - Value: "", - Usage: "token://, file://path/to/file", - EnvVar: "SWARM_DISCOVERY", - } - flAddr := cli.StringFlag{ - Name: "addr", - Value: "127.0.0.1:4243", - Usage: "ip to advertise", - EnvVar: "SWARM_ADDR", - } - flHeartBeat := cli.IntFlag{ - Name: "heartbeat, hb", - Value: 25, - Usage: "time in second between each heartbeat", - } - flEnableCors := cli.BoolFlag{ - Name: "api-enable-cors, cors", - Usage: "enable CORS headers in the remote API", - } - flTls := cli.BoolFlag{ - Name: "tls", - Usage: "Use TLS; implied by --tlsverify=true", - } - flTlsCaCert := cli.StringFlag{ - Name: "tlscacert", - Usage: "Trust only remotes providing a certificate signed by the CA given here", - } - flTlsCert := cli.StringFlag{ - Name: "tlscert", - Usage: "Path to TLS certificate file", - } - flTlsKey := cli.StringFlag{ - Name: "tlskey", - Usage: "Path to TLS key file", - } - flTlsVerify := cli.BoolFlag{ - Name: "tlsverify", - Usage: "Use TLS and verify the remote", - } - app.Commands = []cli.Command{ { Name: "create", @@ -121,6 +78,7 @@ func main() { ShortName: "m", Usage: "manage a docker cluster", Flags: []cli.Flag{ + flStrategy, flDiscovery, flAddr, flHeartBeat, flTls, flTlsCaCert, flTlsCert, flTlsKey, flTlsVerify, flEnableCors}, diff --git a/manage.go b/manage.go index ce131e4ff7..cdf4397c31 100644 --- a/manage.go +++ b/manage.go @@ -123,9 +123,13 @@ func manage(c *cli.Context) { } }() - s := scheduler.NewScheduler( + s, err := strategy.New(c.String("strategy")) + if err != nil { + log.Fatal(err) + } + sched := scheduler.NewScheduler( cluster, - &strategy.BinPackingPlacementStrategy{OvercommitRatio: 0.05}, + s, []filter.Filter{ &filter.HealthFilter{}, &filter.LabelFilter{}, @@ -133,5 +137,5 @@ func manage(c *cli.Context) { }, ) - log.Fatal(api.ListenAndServe(cluster, s, c.String("addr"), c.App.Version, c.Bool("cors"), tlsConfig)) + log.Fatal(api.ListenAndServe(cluster, sched, c.String("addr"), c.App.Version, c.Bool("cors"), tlsConfig)) } diff --git a/scheduler/strategy/binpacking.go b/scheduler/strategy/binpacking.go index 6634341c44..cf3520a77d 100644 --- a/scheduler/strategy/binpacking.go +++ b/scheduler/strategy/binpacking.go @@ -3,6 +3,7 @@ package strategy import ( "errors" "sort" + "strconv" "github.com/docker/swarm/cluster" "github.com/samalba/dockerclient" @@ -16,6 +17,11 @@ type BinPackingPlacementStrategy struct { OvercommitRatio float64 } +func (p *BinPackingPlacementStrategy) Initialize(opts string) (err error) { + p.OvercommitRatio, err = strconv.ParseFloat(opts, 64) + return err +} + func (p *BinPackingPlacementStrategy) PlaceContainer(config *dockerclient.ContainerConfig, nodes []*cluster.Node) (*cluster.Node, error) { scores := scores{} diff --git a/scheduler/strategy/random.go b/scheduler/strategy/random.go index a6c6af3896..8cdcc1f872 100644 --- a/scheduler/strategy/random.go +++ b/scheduler/strategy/random.go @@ -9,14 +9,15 @@ import ( "github.com/samalba/dockerclient" ) -func init() { - rand.Seed(time.Now().UTC().UnixNano()) -} - // Randomly place the container into the cluster. type RandomPlacementStrategy struct { } +func (p *RandomPlacementStrategy) Initialize(_ string) error { + rand.Seed(time.Now().UTC().UnixNano()) + return nil +} + func (p *RandomPlacementStrategy) PlaceContainer(config *dockerclient.ContainerConfig, nodes []*cluster.Node) (*cluster.Node, error) { if size := len(nodes); size > 0 { n := rand.Intn(len(nodes)) diff --git a/scheduler/strategy/strategy.go b/scheduler/strategy/strategy.go index fc1459be47..ccb36f8218 100644 --- a/scheduler/strategy/strategy.go +++ b/scheduler/strategy/strategy.go @@ -1,12 +1,47 @@ package strategy import ( + "errors" + "strings" + + log "github.com/Sirupsen/logrus" "github.com/docker/swarm/cluster" "github.com/samalba/dockerclient" ) type PlacementStrategy interface { + Initialize(string) error // Given a container configuration and a set of nodes, select the target // node where the container should be scheduled. PlaceContainer(config *dockerclient.ContainerConfig, nodes []*cluster.Node) (*cluster.Node, error) } + +var ( + strategies map[string]PlacementStrategy + ErrNotSupported = errors.New("strategy not supported") +) + +func init() { + strategies = make(map[string]PlacementStrategy) + strategies["binpacking"] = &BinPackingPlacementStrategy{} + strategies["random"] = &RandomPlacementStrategy{} +} + +func New(nameAndOpts string) (PlacementStrategy, error) { + var ( + parts = strings.SplitN(nameAndOpts, ":", 2) + name = parts[0] + opts string + ) + if len(parts) == 2 { + opts = parts[1] + } + + if strategy, exists := strategies[name]; exists { + log.Debugf("Initialising %q strategy with %q", name, opts) + err := strategy.Initialize(opts) + return strategy, err + } + + return nil, ErrNotSupported +}