Reorganized code.

Building the scheduler in phases. To be able to do this, increased
visibility of schedulers/helpers.go#schedulerOptions.
Refactored dependent code.
This commit is contained in:
Pradyumna Kaushik 2018-10-04 19:24:16 -04:00
parent c9d4e66236
commit 4637355721
5 changed files with 110 additions and 91 deletions

View file

@ -15,8 +15,8 @@ import (
"gitlab.com/spdf/elektron/def"
elekLogDef "gitlab.com/spdf/elektron/logging/def"
"gitlab.com/spdf/elektron/pcp"
"gitlab.com/spdf/elektron/schedulers"
"gitlab.com/spdf/elektron/powerCap"
"gitlab.com/spdf/elektron/schedulers"
)
var master = flag.String("master", "", "Location of leading Mesos master -- <mesos-master>:<port>")
@ -71,12 +71,13 @@ func listAllSchedulingPolicies() {
func main() {
flag.Parse()
// checking to see if we need to just list the pluggable scheduling policies
// Checking to see if we need to just list the pluggable scheduling policies
if *listSchedPolicies {
listAllSchedulingPolicies()
os.Exit(1)
}
// Creating logger and attaching different logging platforms.
startTime := time.Now()
formattedStartTime := startTime.Format("20060102150405")
// Checking if prefix contains any special characters
@ -84,16 +85,18 @@ func main() {
log.Fatal("log file prefix should not contain '/'.")
}
logPrefix := *pcplogPrefix + "_" + formattedStartTime
// creating logger and attaching different logging platforms
logger := elekLogDef.BuildLogger(startTime, logPrefix)
// logging channels
// Logging channels.
logMType := make(chan elekLogDef.LogMessageType)
logMsg := make(chan string)
go logger.Listen(logMType, logMsg)
// If non-default scheduling policy given,
// checking if scheduling policyName exists
// First we need to build the scheduler using scheduler options.
var schedOptions []schedulers.SchedulerOptions = make([]schedulers.SchedulerOptions, 0, 10)
// OPTIONAL PARAMETERS
// Scheduling Policy Name
// If non-default scheduling policy given, checking if name exists.
if *schedPolicyName != "first-fit" {
if _, ok := schedulers.SchedPolicies[*schedPolicyName]; !ok {
// invalid scheduling policy
@ -103,68 +106,54 @@ func main() {
}
}
if *tasksFile == "" {
//fmt.Println("No file containing tasks specifiction provided.")
logger.WriteLog(elekLogDef.ERROR, "No file containing tasks specification provided")
os.Exit(1)
}
if *hiThreshold < *loThreshold {
//fmt.Println("High threshold is of a lower value than low threshold.")
logger.WriteLog(elekLogDef.ERROR, "High threshold is of a lower value than low threshold")
os.Exit(1)
}
tasks, err := def.TasksFromJSON(*tasksFile)
if err != nil || len(tasks) == 0 {
//fmt.Println("Invalid tasks specification file provided")
logger.WriteLog(elekLogDef.ERROR, "Invalid tasks specification file provided")
os.Exit(1)
}
//log.Println("Scheduling the following tasks:")
logger.WriteLog(elekLogDef.GENERAL, "Scheduling the following tasks:")
for _, task := range tasks {
fmt.Println(task)
}
if *enableSchedPolicySwitch {
if spcf := *schedPolConfigFile; spcf == "" {
logger.WriteLog(elekLogDef.ERROR, "No file containing characteristics for scheduling policies")
} else {
// Initializing the characteristics of the scheduling policies.
schedulers.InitSchedPolicyCharacteristics(spcf)
}
}
// CHANNELS AND FLAGS.
shutdown := make(chan struct{})
done := make(chan struct{})
pcpLog := make(chan struct{})
recordPCP := false
scheduler := schedulers.SchedFactory(
schedulers.WithSchedPolicy(*schedPolicyName),
schedulers.WithTasks(tasks),
schedulers.WithWattsAsAResource(*wattsAsAResource),
schedulers.WithClassMapWatts(*classMapWatts),
schedulers.WithRecordPCP(&recordPCP),
schedulers.WithShutdown(shutdown),
schedulers.WithDone(done),
schedulers.WithPCPLog(pcpLog),
schedulers.WithLoggingChannels(logMType, logMsg),
schedulers.WithSchedPolSwitchEnabled(*enableSchedPolicySwitch, *schedPolSwitchCriteria),
schedulers.WithNameOfFirstSchedPolToFix(*fixFirstSchedPol),
schedulers.WithFixedSchedulingWindow(*fixSchedWindow, *schedWindowSize))
driver, err := sched.NewMesosSchedulerDriver(sched.DriverConfig{
Master: *master,
Framework: &mesos.FrameworkInfo{
Name: proto.String("Elektron"),
User: proto.String(""),
},
Scheduler: scheduler,
})
if err != nil {
log.Printf("Unable to create scheduler driver: %s", err)
return
// Logging channels.
// These channels are used by the framework to log messages.
// The channels are used to send the type of log message and the message string.
schedOptions = append(schedOptions, schedulers.WithLoggingChannels(logMType, logMsg))
// Shutdown indicator channels.
// These channels are used to notify,
// 1. scheduling is complete.
// 2. all scheduled tasks have completed execution and framework can shutdown.
schedOptions = append(schedOptions, schedulers.WithShutdown(shutdown))
schedOptions = append(schedOptions, schedulers.WithDone(done))
// If here, then valid scheduling policy name provided.
schedOptions = append(schedOptions, schedulers.WithSchedPolicy(*schedPolicyName))
// Scheduling Policy Switching.
if *enableSchedPolicySwitch {
// Scheduling policy config file required.
if spcf := *schedPolConfigFile; spcf == "" {
logger.WriteLog(elekLogDef.ERROR, "No file containing characteristics for"+
" scheduling policies")
os.Exit(1)
} else {
// Initializing the characteristics of the scheduling policies.
schedulers.InitSchedPolicyCharacteristics(spcf)
schedOptions = append(schedOptions, schedulers.WithSchedPolSwitchEnabled(*enableSchedPolicySwitch, *schedPolSwitchCriteria))
// Fix First Scheduling Policy.
schedOptions = append(schedOptions, schedulers.WithNameOfFirstSchedPolToFix(*fixFirstSchedPol))
// Fix Scheduling Window.
schedOptions = append(schedOptions, schedulers.WithFixedSchedulingWindow(*fixSchedWindow, *schedWindowSize))
}
}
// Watts as a Resource (WaaR) and ClassMapWatts (CMW).
// If WaaR and CMW is enabled then for each task the class_to_watts mapping is used to
// fit tasks into offers.
// If CMW is disabled, then the Median of Medians Max Peak Power Usage value is used
// as the watts value for each task.
if *wattsAsAResource {
logger.WriteLog(elekLogDef.GENERAL, "WaaR enabled...")
schedOptions = append(schedOptions, schedulers.WithWattsAsAResource(*wattsAsAResource))
schedOptions = append(schedOptions, schedulers.WithClassMapWatts(*classMapWatts))
}
// REQUIRED PARAMETERS.
// PCP logging, Power capping and High and Low thresholds.
@ -204,12 +193,40 @@ func main() {
}
}
// Checking if pcp config file exists.
if _, err := os.Stat(*pcpConfigFile); os.IsNotExist(err) {
logger.WriteLog(elekLogDef.ERROR, "PCP config file does not exist!")
// Tasks
// If httpServer is disabled, then path of file containing workload needs to be provided.
if *tasksFile == "" {
logger.WriteLog(elekLogDef.ERROR, "No file containing tasks specification"+
" provided.")
os.Exit(1)
}
tasks, err := def.TasksFromJSON(*tasksFile)
if err != nil || len(tasks) == 0 {
logger.WriteLog(elekLogDef.ERROR, "Invalid tasks specification file "+
"provided.")
os.Exit(1)
}
schedOptions = append(schedOptions, schedulers.WithTasks(tasks))
// Scheduler.
scheduler := schedulers.SchedFactory(schedOptions...)
// Scheduler driver.
driver, err := sched.NewMesosSchedulerDriver(sched.DriverConfig{
Master: *master,
Framework: &mesos.FrameworkInfo{
Name: proto.String("Elektron"),
User: proto.String(""),
},
Scheduler: scheduler,
})
if err != nil {
logger.WriteLog(elekLogDef.ERROR, fmt.Sprintf("Unable to create scheduler driver:"+
" %s", err))
os.Exit(1)
}
// Starting PCP logging.
if noPowercap {
go pcp.Start(pcpLog, &recordPCP, logMType, logMsg, *pcpConfigFile, scheduler)
} else if extrema {
@ -220,7 +237,8 @@ func main() {
*loThreshold, logMType, logMsg, *pcpConfigFile)
}
time.Sleep(1 * time.Second) // Take a second between starting PCP log and continuing
// Take a second between starting PCP log and continuing.
time.Sleep(1 * time.Second)
// Attempt to handle SIGINT to not leave pmdumptext running.
// Catch interrupt.
@ -233,34 +251,35 @@ func main() {
return
}
log.Println("Received SIGINT...stopping")
log.Println("Received SIGINT... stopping")
close(done)
}()
go func() {
// Signals we have scheduled every task we have.
// Signals we have scheduled every task we have
select {
case <-shutdown:
//case <-time.After(shutdownTimeout):
}
// All tasks have finished.
// All tasks have finished
select {
case <-done:
close(pcpLog)
time.Sleep(5 * time.Second) //Wait for PCP to log a few more seconds
// Closing logging channels.
close(logMType)
close(logMsg)
//case <-time.After(shutdownTimeout):
}
// Done shutting down.
// Done shutting down
driver.Stop(false)
}()
log.Println("Starting...")
// Starting the scheduler driver.
if status, err := driver.Run(); err != nil {
log.Printf("Framework stopped with status %s and error: %s\n", status.String(), err.Error())
}