scheduling policies pluggable from commandline
This commit is contained in:
parent
051aca4d10
commit
04f24beac5
10 changed files with 216 additions and 121 deletions
|
@ -1,8 +1,8 @@
|
||||||
package pcp
|
package pcp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bitbucket.org/sunybingcloud/elektron/rapl"
|
|
||||||
"bitbucket.org/sunybingcloud/elektron/pcp"
|
"bitbucket.org/sunybingcloud/elektron/pcp"
|
||||||
|
"bitbucket.org/sunybingcloud/elektron/rapl"
|
||||||
"bufio"
|
"bufio"
|
||||||
"container/ring"
|
"container/ring"
|
||||||
"log"
|
"log"
|
||||||
|
|
|
@ -2,8 +2,8 @@ package pcp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bitbucket.org/sunybingcloud/elektron/constants"
|
"bitbucket.org/sunybingcloud/elektron/constants"
|
||||||
"bitbucket.org/sunybingcloud/elektron/rapl"
|
|
||||||
"bitbucket.org/sunybingcloud/elektron/pcp"
|
"bitbucket.org/sunybingcloud/elektron/pcp"
|
||||||
|
"bitbucket.org/sunybingcloud/elektron/rapl"
|
||||||
"bitbucket.org/sunybingcloud/elektron/utilities"
|
"bitbucket.org/sunybingcloud/elektron/utilities"
|
||||||
"bufio"
|
"bufio"
|
||||||
"container/ring"
|
"container/ring"
|
||||||
|
|
76
scheduler.go
76
scheduler.go
|
@ -17,29 +17,63 @@ import (
|
||||||
|
|
||||||
var master = flag.String("master", "<mesos-master>:5050", "Location of leading Mesos master")
|
var master = flag.String("master", "<mesos-master>:5050", "Location of leading Mesos master")
|
||||||
var tasksFile = flag.String("workload", "", "JSON file containing task definitions")
|
var tasksFile = flag.String("workload", "", "JSON file containing task definitions")
|
||||||
var wattsAsAResource = flag.Bool("wattsAsAResource", false, "Enable Watts as a Resource. This allows the usage of the Watts attribute (if present) in the workload definition during offer matching.")
|
var wattsAsAResource = flag.Bool("wattsAsAResource", false, "Enable Watts as a Resource. "+
|
||||||
|
"This allows the usage of the Watts attribute (if present) in the workload definition during offer matching.")
|
||||||
var pcplogPrefix = flag.String("logPrefix", "", "Prefix for PCP log file")
|
var pcplogPrefix = flag.String("logPrefix", "", "Prefix for PCP log file")
|
||||||
var hiThreshold = flag.Float64("hiThreshold", 0.0, "Upperbound for Cluster average historical power consumption, beyond which extrema/progressive-extrema would start power-capping")
|
var hiThreshold = flag.Float64("hiThreshold", 0.0, "Upperbound for Cluster average historical power consumption, "+
|
||||||
var loThreshold = flag.Float64("loThreshold", 0.0, "Lowerbound for Cluster average historical power consumption, below which extrema/progressive-extrema would stop power-capping")
|
"beyond which extrema/progressive-extrema would start power-capping")
|
||||||
|
var loThreshold = flag.Float64("loThreshold", 0.0, "Lowerbound for Cluster average historical power consumption, "+
|
||||||
|
"below which extrema/progressive-extrema would stop power-capping")
|
||||||
var classMapWatts = flag.Bool("classMapWatts", false, "Enable mapping of watts to powerClass of node")
|
var classMapWatts = flag.Bool("classMapWatts", false, "Enable mapping of watts to powerClass of node")
|
||||||
|
var schedPolicyName = flag.String("schedPolicy", "first-fit", "Name of the scheduling policy to be used (default = first-fit).\n "+
|
||||||
|
"Use option -listSchedPolicies to get the names of available scheduling policies")
|
||||||
|
var listSchedPolicies = flag.Bool("listSchedPolicies", false, "Names of the pluaggable scheduling policies.")
|
||||||
|
|
||||||
// Short hand args
|
// Short hand args
|
||||||
func init() {
|
func init() {
|
||||||
flag.StringVar(master, "m", "<mesos-master>:5050", "Location of leading Mesos master (shorthand)")
|
flag.StringVar(master, "m", "<mesos-master>:5050", "Location of leading Mesos master (shorthand)")
|
||||||
flag.StringVar(tasksFile, "w", "", "JSON file containing task definitions (shorthand)")
|
flag.StringVar(tasksFile, "w", "", "JSON file containing task definitions (shorthand)")
|
||||||
flag.BoolVar(wattsAsAResource, "waar", false, "Enable Watts as a Resource. " +
|
flag.BoolVar(wattsAsAResource, "waar", false, "Enable Watts as a Resource. "+
|
||||||
"This allows the usage of the Watts attribute (if present) in the workload definition during offer matching. (shorthand)")
|
"This allows the usage of the Watts attribute (if present) in the workload definition during offer matching. (shorthand)")
|
||||||
flag.StringVar(pcplogPrefix, "p", "", "Prefix for PCP log file (shorthand)")
|
flag.StringVar(pcplogPrefix, "p", "", "Prefix for PCP log file (shorthand)")
|
||||||
flag.Float64Var(hiThreshold, "ht", 700.0, "Upperbound for Cluster average historical power consumption, " +
|
flag.Float64Var(hiThreshold, "ht", 700.0, "Upperbound for Cluster average historical power consumption, "+
|
||||||
"beyond which extrema/progressive-extrema would start power-capping (shorthand)")
|
"beyond which extrema/progressive-extrema would start power-capping (shorthand)")
|
||||||
flag.Float64Var(loThreshold, "lt", 400.0, "Lowerbound for Cluster average historical power consumption, " +
|
flag.Float64Var(loThreshold, "lt", 400.0, "Lowerbound for Cluster average historical power consumption, "+
|
||||||
"below which extrema/progressive-extrema would stop power-capping (shorthand)")
|
"below which extrema/progressive-extrema would stop power-capping (shorthand)")
|
||||||
flag.BoolVar(classMapWatts, "cmw", false, "Enable mapping of watts to powerClass of node (shorthand)")
|
flag.BoolVar(classMapWatts, "cmw", false, "Enable mapping of watts to powerClass of node (shorthand)")
|
||||||
|
flag.StringVar(schedPolicyName, "sp", "first-fit", "Name of the scheduling policy to be used (default = first-fit).\n "+
|
||||||
|
"Use option -listSchedPolicies to get the names of available scheduling policies (shorthand)")
|
||||||
|
flag.BoolVar(listSchedPolicies, "lsp", false, "Names of the pluaggable scheduling policies. (shorthand)")
|
||||||
|
}
|
||||||
|
|
||||||
|
func listAllSchedulingPolicies() {
|
||||||
|
fmt.Println("Scheduling Policies")
|
||||||
|
fmt.Println("-------------------")
|
||||||
|
for policyName, _ := range schedulers.Schedulers {
|
||||||
|
fmt.Println(policyName)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
// checking to see if we need to just list the pluggable scheduling policies
|
||||||
|
if *listSchedPolicies {
|
||||||
|
listAllSchedulingPolicies()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If non-default scheduling policy given,
|
||||||
|
// checking if scheduling policyName exists
|
||||||
|
if *schedPolicyName != "first-fit" {
|
||||||
|
if _, ok := schedulers.Schedulers[*schedPolicyName]; !ok {
|
||||||
|
// invalid scheduling policy
|
||||||
|
log.Println("Invalid scheduling policy given. The possible scheduling policies are:")
|
||||||
|
listAllSchedulingPolicies()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if *tasksFile == "" {
|
if *tasksFile == "" {
|
||||||
fmt.Println("No file containing tasks specifiction provided.")
|
fmt.Println("No file containing tasks specifiction provided.")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
@ -63,7 +97,19 @@ func main() {
|
||||||
startTime := time.Now().Format("20060102150405")
|
startTime := time.Now().Format("20060102150405")
|
||||||
logPrefix := *pcplogPrefix + "_" + startTime
|
logPrefix := *pcplogPrefix + "_" + startTime
|
||||||
|
|
||||||
scheduler := schedulers.NewFirstFit(tasks, *wattsAsAResource, logPrefix, *classMapWatts)
|
shutdown := make(chan struct{})
|
||||||
|
done := make(chan struct{})
|
||||||
|
pcpLog := make(chan struct{})
|
||||||
|
recordPCP := false
|
||||||
|
scheduler := schedulers.SchedFactory(*schedPolicyName,
|
||||||
|
schedulers.WithTasks(tasks),
|
||||||
|
schedulers.WithWattsAsAResource(*wattsAsAResource),
|
||||||
|
schedulers.WithClassMapWatts(*classMapWatts),
|
||||||
|
schedulers.WithSchedTracePrefix(logPrefix),
|
||||||
|
schedulers.WithRecordPCP(&recordPCP),
|
||||||
|
schedulers.WithShutdown(shutdown),
|
||||||
|
schedulers.WithDone(done),
|
||||||
|
schedulers.WithPCPLog(pcpLog))
|
||||||
driver, err := sched.NewMesosSchedulerDriver(sched.DriverConfig{
|
driver, err := sched.NewMesosSchedulerDriver(sched.DriverConfig{
|
||||||
Master: *master,
|
Master: *master,
|
||||||
Framework: &mesos.FrameworkInfo{
|
Framework: &mesos.FrameworkInfo{
|
||||||
|
@ -77,9 +123,9 @@ func main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
go pcp.Start(scheduler.PCPLog, &scheduler.RecordPCP, logPrefix)
|
go pcp.Start(pcpLog, &recordPCP, logPrefix)
|
||||||
//go pcp.StartPCPLogAndExtremaDynamicCap(scheduler.PCPLog, &scheduler.RecordPCP, logPrefix, *hiThreshold, *loThreshold)
|
//go pcp.StartPCPLogAndExtremaDynamicCap(pcpLog, &recordPCP, logPrefix, *hiThreshold, *loThreshold)
|
||||||
//go pcp.StartPCPLogAndProgressiveExtremaCap(scheduler.PCPLog, &scheduler.RecordPCP, logPrefix, *hiThreshold, *loThreshold)
|
//go pcp.StartPCPLogAndProgressiveExtremaCap(pcpLog, &recordPCP, logPrefix, *hiThreshold, *loThreshold)
|
||||||
time.Sleep(1 * time.Second) // Take a second between starting PCP log and continuing
|
time.Sleep(1 * time.Second) // Take a second between starting PCP log and continuing
|
||||||
|
|
||||||
// Attempt to handle SIGINT to not leave pmdumptext running
|
// Attempt to handle SIGINT to not leave pmdumptext running
|
||||||
|
@ -89,26 +135,26 @@ func main() {
|
||||||
signal.Notify(c, os.Interrupt, os.Kill)
|
signal.Notify(c, os.Interrupt, os.Kill)
|
||||||
s := <-c
|
s := <-c
|
||||||
if s != os.Interrupt {
|
if s != os.Interrupt {
|
||||||
close(scheduler.PCPLog)
|
close(pcpLog)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Received SIGINT...stopping")
|
log.Printf("Received SIGINT...stopping")
|
||||||
close(scheduler.Done)
|
close(done)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
|
||||||
// Signals we have scheduled every task we have
|
// Signals we have scheduled every task we have
|
||||||
select {
|
select {
|
||||||
case <-scheduler.Shutdown:
|
case <-shutdown:
|
||||||
//case <-time.After(shutdownTimeout):
|
//case <-time.After(shutdownTimeout):
|
||||||
}
|
}
|
||||||
|
|
||||||
// All tasks have finished
|
// All tasks have finished
|
||||||
select {
|
select {
|
||||||
case <-scheduler.Done:
|
case <-done:
|
||||||
close(scheduler.PCPLog)
|
close(pcpLog)
|
||||||
time.Sleep(5 * time.Second) //Wait for PCP to log a few more seconds
|
time.Sleep(5 * time.Second) //Wait for PCP to log a few more seconds
|
||||||
//case <-time.After(shutdownTimeout):
|
//case <-time.After(shutdownTimeout):
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,14 @@ import (
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Implements mesos scheduler.
|
||||||
|
type ElectronScheduler interface {
|
||||||
|
sched.Scheduler
|
||||||
|
init(opts ...schedPolicyOption)
|
||||||
|
}
|
||||||
|
|
||||||
type base struct {
|
type base struct {
|
||||||
|
ElectronScheduler
|
||||||
tasksCreated int
|
tasksCreated int
|
||||||
tasksRunning int
|
tasksRunning int
|
||||||
tasks []def.Task
|
tasks []def.Task
|
||||||
|
@ -18,7 +25,7 @@ type base struct {
|
||||||
|
|
||||||
// First set of PCP values are garbage values, signal to logger to start recording when we're
|
// First set of PCP values are garbage values, signal to logger to start recording when we're
|
||||||
// about to schedule a new task
|
// about to schedule a new task
|
||||||
RecordPCP bool
|
RecordPCP *bool
|
||||||
|
|
||||||
// This channel is closed when the program receives an interrupt,
|
// This channel is closed when the program receives an interrupt,
|
||||||
// signalling that the program should shut down.
|
// signalling that the program should shut down.
|
||||||
|
@ -33,6 +40,16 @@ type base struct {
|
||||||
schedTrace *log.Logger
|
schedTrace *log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *base) init(opts ...schedPolicyOption) {
|
||||||
|
for _, opt := range opts {
|
||||||
|
// applying options
|
||||||
|
if err := opt(s); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.running = make(map[string]map[string]bool)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *base) OfferRescinded(_ sched.SchedulerDriver, offerID *mesos.OfferID) {
|
func (s *base) OfferRescinded(_ sched.SchedulerDriver, offerID *mesos.OfferID) {
|
||||||
log.Printf("Offer %s rescinded", offerID)
|
log.Printf("Offer %s rescinded", offerID)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"github.com/mesos/mesos-go/mesosutil"
|
"github.com/mesos/mesos-go/mesosutil"
|
||||||
sched "github.com/mesos/mesos-go/scheduler"
|
sched "github.com/mesos/mesos-go/scheduler"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,38 +36,20 @@ type BinPacking struct {
|
||||||
base // Type embedded to inherit common functions
|
base // Type embedded to inherit common functions
|
||||||
}
|
}
|
||||||
|
|
||||||
// New elektron scheduler
|
// Initialization
|
||||||
func NewBinPacking(tasks []def.Task, wattsAsAResource bool, schedTracePrefix string, classMapWatts bool) *BinPacking {
|
func (s *BinPacking) init(opts ...schedPolicyOption) {
|
||||||
def.SortTasks(tasks, def.SortByWatts)
|
s.base.init(opts...)
|
||||||
|
// sorting the tasks based on watts
|
||||||
logFile, err := os.Create("./" + schedTracePrefix + "_schedTrace.log")
|
def.SortTasks(s.tasks, def.SortByWatts)
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s := &BinPacking{
|
|
||||||
base: base{
|
|
||||||
tasks: tasks,
|
|
||||||
wattsAsAResource: wattsAsAResource,
|
|
||||||
classMapWatts: classMapWatts,
|
|
||||||
Shutdown: make(chan struct{}),
|
|
||||||
Done: make(chan struct{}),
|
|
||||||
PCPLog: make(chan struct{}),
|
|
||||||
running: make(map[string]map[string]bool),
|
|
||||||
RecordPCP: false,
|
|
||||||
schedTrace: log.New(logFile, "", log.LstdFlags),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *BinPacking) newTask(offer *mesos.Offer, task def.Task) *mesos.TaskInfo {
|
func (s *BinPacking) newTask(offer *mesos.Offer, task def.Task) *mesos.TaskInfo {
|
||||||
taskName := fmt.Sprintf("%s-%d", task.Name, *task.Instances)
|
taskName := fmt.Sprintf("%s-%d", task.Name, *task.Instances)
|
||||||
s.tasksCreated++
|
s.tasksCreated++
|
||||||
|
|
||||||
if !s.RecordPCP {
|
if !*s.RecordPCP {
|
||||||
// Turn on logging
|
// Turn on logging
|
||||||
s.RecordPCP = true
|
*s.RecordPCP = true
|
||||||
time.Sleep(1 * time.Second) // Make sure we're recording by the time the first task starts
|
time.Sleep(1 * time.Second) // Make sure we're recording by the time the first task starts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"github.com/mesos/mesos-go/mesosutil"
|
"github.com/mesos/mesos-go/mesosutil"
|
||||||
sched "github.com/mesos/mesos-go/scheduler"
|
sched "github.com/mesos/mesos-go/scheduler"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,37 +37,18 @@ type FirstFit struct {
|
||||||
base // Type embedded to inherit common functions
|
base // Type embedded to inherit common functions
|
||||||
}
|
}
|
||||||
|
|
||||||
// New elektron scheduler
|
// Initialization
|
||||||
func NewFirstFit(tasks []def.Task, wattsAsAResource bool, schedTracePrefix string, classMapWatts bool) *FirstFit {
|
func (s *FirstFit) init(opts ...schedPolicyOption) {
|
||||||
|
s.base.init(opts...)
|
||||||
logFile, err := os.Create("./" + schedTracePrefix + "_schedTrace.log")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s := &FirstFit{
|
|
||||||
base: base{
|
|
||||||
tasks: tasks,
|
|
||||||
wattsAsAResource: wattsAsAResource,
|
|
||||||
classMapWatts: classMapWatts,
|
|
||||||
Shutdown: make(chan struct{}),
|
|
||||||
Done: make(chan struct{}),
|
|
||||||
PCPLog: make(chan struct{}),
|
|
||||||
running: make(map[string]map[string]bool),
|
|
||||||
RecordPCP: false,
|
|
||||||
schedTrace: log.New(logFile, "", log.LstdFlags),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *FirstFit) newTask(offer *mesos.Offer, task def.Task) *mesos.TaskInfo {
|
func (s *FirstFit) newTask(offer *mesos.Offer, task def.Task) *mesos.TaskInfo {
|
||||||
taskName := fmt.Sprintf("%s-%d", task.Name, *task.Instances)
|
taskName := fmt.Sprintf("%s-%d", task.Name, *task.Instances)
|
||||||
s.tasksCreated++
|
s.tasksCreated++
|
||||||
|
|
||||||
if !s.RecordPCP {
|
if !*s.RecordPCP {
|
||||||
// Turn on logging
|
// Turn on logging
|
||||||
s.RecordPCP = true
|
*s.RecordPCP = true
|
||||||
time.Sleep(1 * time.Second) // Make sure we're recording by the time the first task starts
|
time.Sleep(1 * time.Second) // Make sure we're recording by the time the first task starts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,11 @@ package schedulers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bitbucket.org/sunybingcloud/elektron/constants"
|
"bitbucket.org/sunybingcloud/elektron/constants"
|
||||||
|
"bitbucket.org/sunybingcloud/elektron/def"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
func coLocated(tasks map[string]bool) {
|
func coLocated(tasks map[string]bool) {
|
||||||
|
@ -24,3 +27,83 @@ func hostToPowerClass(hostName string) string {
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// scheduler policy options to help initialize schedulers
|
||||||
|
type schedPolicyOption func(e ElectronScheduler) error
|
||||||
|
|
||||||
|
func WithTasks(ts []def.Task) schedPolicyOption {
|
||||||
|
return func(s ElectronScheduler) error {
|
||||||
|
if ts == nil {
|
||||||
|
return errors.New("Task[] is empty.")
|
||||||
|
} else {
|
||||||
|
s.(*base).tasks = ts
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithWattsAsAResource(waar bool) schedPolicyOption {
|
||||||
|
return func(s ElectronScheduler) error {
|
||||||
|
s.(*base).wattsAsAResource = waar
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithClassMapWatts(cmw bool) schedPolicyOption {
|
||||||
|
return func(s ElectronScheduler) error {
|
||||||
|
s.(*base).classMapWatts = cmw
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithRecordPCP(recordPCP *bool) schedPolicyOption {
|
||||||
|
return func(s ElectronScheduler) error {
|
||||||
|
s.(*base).RecordPCP = recordPCP
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithSchedTracePrefix(schedTracePrefix string) schedPolicyOption {
|
||||||
|
return func(s ElectronScheduler) error {
|
||||||
|
logFile, err := os.Create("./" + schedTracePrefix + "_schedTrace.log")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
s.(*base).schedTrace = log.New(logFile, "", log.LstdFlags)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithShutdown(shutdown chan struct{}) schedPolicyOption {
|
||||||
|
return func(s ElectronScheduler) error {
|
||||||
|
if shutdown == nil {
|
||||||
|
return errors.New("Shutdown channel is nil.")
|
||||||
|
} else {
|
||||||
|
s.(*base).Shutdown = shutdown
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithDone(done chan struct{}) schedPolicyOption {
|
||||||
|
return func(s ElectronScheduler) error {
|
||||||
|
if done == nil {
|
||||||
|
return errors.New("Done channel is nil.")
|
||||||
|
} else {
|
||||||
|
s.(*base).Done = done
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithPCPLog(pcpLog chan struct{}) schedPolicyOption {
|
||||||
|
return func(s ElectronScheduler) error {
|
||||||
|
if pcpLog == nil {
|
||||||
|
return errors.New("PCPLog channel is nil.")
|
||||||
|
} else {
|
||||||
|
s.(*base).PCPLog = pcpLog
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"github.com/mesos/mesos-go/mesosutil"
|
"github.com/mesos/mesos-go/mesosutil"
|
||||||
sched "github.com/mesos/mesos-go/scheduler"
|
sched "github.com/mesos/mesos-go/scheduler"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,29 +37,9 @@ type MaxGreedyMins struct {
|
||||||
base //Type embedding to inherit common functions
|
base //Type embedding to inherit common functions
|
||||||
}
|
}
|
||||||
|
|
||||||
// New elektron scheduler
|
// Initialization
|
||||||
func NewMaxGreedyMins(tasks []def.Task, wattsAsAResource bool, schedTracePrefix string, classMapWatts bool) *MaxGreedyMins {
|
func (s *MaxGreedyMins) init(opts ...schedPolicyOption) {
|
||||||
def.SortTasks(tasks, def.SortByWatts)
|
s.base.init(opts...)
|
||||||
|
|
||||||
logFile, err := os.Create("./" + schedTracePrefix + "_schedTrace.log")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s := &MaxGreedyMins{
|
|
||||||
base: base{
|
|
||||||
tasks: tasks,
|
|
||||||
wattsAsAResource: wattsAsAResource,
|
|
||||||
classMapWatts: classMapWatts,
|
|
||||||
Shutdown: make(chan struct{}),
|
|
||||||
Done: make(chan struct{}),
|
|
||||||
PCPLog: make(chan struct{}),
|
|
||||||
running: make(map[string]map[string]bool),
|
|
||||||
RecordPCP: false,
|
|
||||||
schedTrace: log.New(logFile, "", log.LstdFlags),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MaxGreedyMins) newTask(offer *mesos.Offer, task def.Task) *mesos.TaskInfo {
|
func (s *MaxGreedyMins) newTask(offer *mesos.Offer, task def.Task) *mesos.TaskInfo {
|
||||||
|
@ -68,9 +47,9 @@ func (s *MaxGreedyMins) newTask(offer *mesos.Offer, task def.Task) *mesos.TaskIn
|
||||||
s.tasksCreated++
|
s.tasksCreated++
|
||||||
|
|
||||||
// Start recording only when we're creating the first task
|
// Start recording only when we're creating the first task
|
||||||
if !s.RecordPCP {
|
if !*s.RecordPCP {
|
||||||
// Turn on logging
|
// Turn on logging
|
||||||
s.RecordPCP = true
|
*s.RecordPCP = true
|
||||||
time.Sleep(1 * time.Second) // Make sure we're recording by the time the first task starts
|
time.Sleep(1 * time.Second) // Make sure we're recording by the time the first task starts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"github.com/mesos/mesos-go/mesosutil"
|
"github.com/mesos/mesos-go/mesosutil"
|
||||||
sched "github.com/mesos/mesos-go/scheduler"
|
sched "github.com/mesos/mesos-go/scheduler"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,29 +37,9 @@ type MaxMin struct {
|
||||||
base //Type embedding to inherit common functions
|
base //Type embedding to inherit common functions
|
||||||
}
|
}
|
||||||
|
|
||||||
// New elektron scheduler
|
// Initialization
|
||||||
func NewMaxMin(tasks []def.Task, wattsAsAResource bool, schedTracePrefix string, classMapWatts bool) *MaxMin {
|
func (s *MaxMin) init(opts ...schedPolicyOption) {
|
||||||
def.SortTasks(tasks, def.SortByWatts)
|
s.base.init(opts...)
|
||||||
|
|
||||||
logFile, err := os.Create("./" + schedTracePrefix + "_schedTrace.log")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s := &MaxMin{
|
|
||||||
base: base{
|
|
||||||
tasks: tasks,
|
|
||||||
wattsAsAResource: wattsAsAResource,
|
|
||||||
classMapWatts: classMapWatts,
|
|
||||||
Shutdown: make(chan struct{}),
|
|
||||||
Done: make(chan struct{}),
|
|
||||||
PCPLog: make(chan struct{}),
|
|
||||||
running: make(map[string]map[string]bool),
|
|
||||||
RecordPCP: false,
|
|
||||||
schedTrace: log.New(logFile, "", log.LstdFlags),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MaxMin) newTask(offer *mesos.Offer, task def.Task) *mesos.TaskInfo {
|
func (s *MaxMin) newTask(offer *mesos.Offer, task def.Task) *mesos.TaskInfo {
|
||||||
|
@ -68,9 +47,9 @@ func (s *MaxMin) newTask(offer *mesos.Offer, task def.Task) *mesos.TaskInfo {
|
||||||
s.tasksCreated++
|
s.tasksCreated++
|
||||||
|
|
||||||
// Start recording only when we're creating the first task
|
// Start recording only when we're creating the first task
|
||||||
if !s.RecordPCP {
|
if !*s.RecordPCP {
|
||||||
// Turn on logging
|
// Turn on logging
|
||||||
s.RecordPCP = true
|
*s.RecordPCP = true
|
||||||
time.Sleep(1 * time.Second) // Make sure we're recording by the time the first task starts
|
time.Sleep(1 * time.Second) // Make sure we're recording by the time the first task starts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
30
schedulers/store.go
Normal file
30
schedulers/store.go
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package schedulers
|
||||||
|
|
||||||
|
import "github.com/mesos/mesos-go/scheduler"
|
||||||
|
|
||||||
|
// Names of different scheduling policies.
|
||||||
|
const (
|
||||||
|
ff = "first-fit"
|
||||||
|
bp = "bin-packing"
|
||||||
|
mgm = "max-greedymins"
|
||||||
|
mm = "max-min"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Scheduler class factory
|
||||||
|
var Schedulers map[string]scheduler.Scheduler = map[string]scheduler.Scheduler{
|
||||||
|
ff: &FirstFit{base: base{}},
|
||||||
|
bp: &BinPacking{base: base{}},
|
||||||
|
mgm: &MaxGreedyMins{base: base{}},
|
||||||
|
mm: &MaxMin{base: base{}},
|
||||||
|
}
|
||||||
|
|
||||||
|
// build the scheduling policy with the options being applied
|
||||||
|
func BuildSchedPolicy(s scheduler.Scheduler, opts ...schedPolicyOption) {
|
||||||
|
s.(ElectronScheduler).init(opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SchedFactory(schedPolicyName string, opts ...schedPolicyOption) scheduler.Scheduler {
|
||||||
|
s := Schedulers[schedPolicyName]
|
||||||
|
BuildSchedPolicy(s, opts...)
|
||||||
|
return s
|
||||||
|
}
|
Reference in a new issue