Merge pull request #168 from vieux/strategy_flag

add --strategy to choose the strategy to use
This commit is contained in:
Andrea Luzzardi 2014-12-12 17:03:37 -08:00
commit 264dce3cc6
7 changed files with 113 additions and 55 deletions

52
flags.go Normal file
View File

@ -0,0 +1,52 @@
package main
import "github.com/codegangsta/cli"
var (
flDiscovery = cli.StringFlag{
Name: "discovery",
Value: "",
Usage: "DiscoveryService to use [token://<token>, etcd://<ip1>,<ip2>/<path>, 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",
}
)

44
main.go
View File

@ -36,49 +36,6 @@ func main() {
return nil
}
// flags
flDiscovery := cli.StringFlag{
Name: "discovery",
Value: "",
Usage: "token://<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},

View File

@ -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))
}

View File

@ -3,6 +3,7 @@ package strategy
import (
"errors"
"sort"
"strconv"
"github.com/docker/swarm/cluster"
"github.com/samalba/dockerclient"
@ -13,16 +14,21 @@ var (
)
type BinPackingPlacementStrategy struct {
OvercommitRatio float64
ratio int64
}
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 {

View File

@ -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

View File

@ -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))

View File

@ -1,12 +1,48 @@
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 = map[string]PlacementStrategy{
"binpacking": &BinPackingPlacementStrategy{},
"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
}