package strategy import ( "errors" log "github.com/Sirupsen/logrus" "github.com/docker/swarm/cluster" "github.com/docker/swarm/scheduler/node" ) // PlacementStrategy is the interface for a container placement strategy. type PlacementStrategy interface { // Name of the strategy Name() string // Initialize performs any initial configuration required by the strategy and returns // an error if one is encountered. // If no initial configuration is needed, this may be a no-op and return a nil error. Initialize() error // RankAndSort applies the strategy to a list of nodes and ranks them based // on the best fit given the container configuration. It returns a sorted // list of nodes (based on their ranks) or an error if there is no // available node on which to schedule the container. RankAndSort(config *cluster.ContainerConfig, nodes []*node.Node) ([]*node.Node, error) } var ( strategies []PlacementStrategy // ErrNotSupported is the error returned when a strategy name does not match // any supported placement strategy. ErrNotSupported = errors.New("strategy not supported") // ErrNoResourcesAvailable is the error returned when there are no resources // available to schedule a container. This can occur if there are no nodes in // the cluster or if no node contains sufficient resources for the container. ErrNoResourcesAvailable = errors.New("no resources available to schedule container") ) func init() { strategies = []PlacementStrategy{ &SpreadPlacementStrategy{}, &BinpackPlacementStrategy{}, &RandomPlacementStrategy{}, } } // New creates a new PlacementStrategy for the given strategy name. func New(name string) (PlacementStrategy, error) { if name == "binpacking" { //TODO: remove this compat name = "binpack" } for _, strategy := range strategies { if strategy.Name() == name { log.WithField("name", name).Debugf("Initializing strategy") err := strategy.Initialize() return strategy, err } } return nil, ErrNotSupported } // List returns the names of all the available strategies. func List() []string { names := []string{} for _, strategy := range strategies { names = append(names, strategy.Name()) } return names }