From b1e80ce157a68e31a4382f79859de66df946094e Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Fri, 12 Dec 2014 23:57:27 +0000 Subject: [PATCH 1/3] 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 +} From cd243cfa3487a32c4af66834aba4c6c8a4adf942 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Sat, 13 Dec 2014 00:07:27 +0000 Subject: [PATCH 2/3] simplify Signed-off-by: Victor Vieux --- scheduler/strategy/binpacking.go | 12 ++++++------ scheduler/strategy/binpacking_test.go | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/scheduler/strategy/binpacking.go b/scheduler/strategy/binpacking.go index cf3520a77d..ccd38ceb2c 100644 --- a/scheduler/strategy/binpacking.go +++ b/scheduler/strategy/binpacking.go @@ -14,21 +14,21 @@ var ( ) type BinPackingPlacementStrategy struct { - OvercommitRatio float64 + ratio int64 } -func (p *BinPackingPlacementStrategy) Initialize(opts string) (err error) { - p.OvercommitRatio, err = strconv.ParseFloat(opts, 64) +func (p *BinPackingPlacementStrategy) Initialize(opts string) error { + overcommitRatio, err := strconv.ParseFloat(opts, 64) + p.ratio = int64(overcommitRatio * 100) return err } func (p *BinPackingPlacementStrategy) PlaceContainer(config *dockerclient.ContainerConfig, nodes []*cluster.Node) (*cluster.Node, error) { scores := scores{} - ratio := int64(p.OvercommitRatio * 100) for _, node := range nodes { - nodeMemory := node.Memory + (node.Memory * ratio / 100) - nodeCpus := node.Cpus + (node.Cpus * ratio / 100) + nodeMemory := node.Memory + (node.Memory * p.ratio / 100) + nodeCpus := node.Cpus + (node.Cpus * p.ratio / 100) // Skip nodes that are smaller than the requested resources. if nodeMemory < int64(config.Memory) || nodeCpus < config.CpuShares { diff --git a/scheduler/strategy/binpacking_test.go b/scheduler/strategy/binpacking_test.go index 79579654a8..d4e2aba8a2 100644 --- a/scheduler/strategy/binpacking_test.go +++ b/scheduler/strategy/binpacking_test.go @@ -114,7 +114,8 @@ func TestPlaceContainerHuge(t *testing.T) { } func TestPlaceContainerOvercommit(t *testing.T) { - s := &BinPackingPlacementStrategy{OvercommitRatio: 0.05} + s, err := New("binpacking:0.05") + assert.NoError(t, err) nodes := []*cluster.Node{createNode("node-1", 0, 1)} nodes[0].Memory = 100 From 9196927ce2ec75c7fcd3048315a1ddbf5a05dddc Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Sat, 13 Dec 2014 00:56:37 +0000 Subject: [PATCH 3/3] nitpick Signed-off-by: Victor Vieux --- scheduler/strategy/strategy.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scheduler/strategy/strategy.go b/scheduler/strategy/strategy.go index ccb36f8218..c85ed2d03f 100644 --- a/scheduler/strategy/strategy.go +++ b/scheduler/strategy/strategy.go @@ -22,9 +22,10 @@ var ( ) func init() { - strategies = make(map[string]PlacementStrategy) - strategies["binpacking"] = &BinPackingPlacementStrategy{} - strategies["random"] = &RandomPlacementStrategy{} + strategies = map[string]PlacementStrategy{ + "binpacking": &BinPackingPlacementStrategy{}, + "random": &RandomPlacementStrategy{}, + } } func New(nameAndOpts string) (PlacementStrategy, error) {