2016-09-08 02:06:24 -04:00
package main
import (
2017-09-26 00:18:35 -04:00
"bitbucket.org/sunybingcloud/elektron/def"
2018-01-31 19:00:31 -05:00
elecLogDef "bitbucket.org/sunybingcloud/elektron/logging/def"
2017-09-26 00:18:35 -04:00
"bitbucket.org/sunybingcloud/elektron/pcp"
"bitbucket.org/sunybingcloud/elektron/schedulers"
2016-09-08 02:06:24 -04:00
"flag"
"fmt"
"github.com/golang/protobuf/proto"
2018-01-19 17:46:35 -05:00
mesos "github.com/mesos/mesos-go/api/v0/mesosproto"
sched "github.com/mesos/mesos-go/api/v0/scheduler"
2016-09-08 02:06:24 -04:00
"log"
"os"
2016-10-07 20:47:59 -04:00
"os/signal"
2018-01-19 21:20:43 +00:00
"strings"
2016-10-13 17:15:09 -04:00
"time"
2016-09-08 02:06:24 -04:00
)
2017-10-03 20:10:44 -04:00
var master = flag . String ( "master" , "" , "Location of leading Mesos master -- <mesos-master>:<port>" )
2016-09-27 18:12:50 -04:00
var tasksFile = flag . String ( "workload" , "" , "JSON file containing task definitions" )
2018-01-19 21:20:43 +00:00
var wattsAsAResource = flag . Bool ( "wattsAsAResource" , false , "Enable Watts as a Resource" )
var pcplogPrefix = flag . String ( "logPrefix" , "" , "Prefix for pcplog" )
var hiThreshold = flag . Float64 ( "hiThreshold" , 0.0 , "Upperbound for when we should start capping" )
var loThreshold = flag . Float64 ( "loThreshold" , 0.0 , "Lowerbound for when we should start uncapping" )
var classMapWatts = flag . Bool ( "classMapWatts" , false , "Enable mapping of watts to power class of node" )
var schedPolicyName = flag . String ( "schedPolicy" , "first-fit" , "Name of the scheduling policy to be used.\n\tUse option -listSchedPolicies to get the names of available scheduling policies" )
var listSchedPolicies = flag . Bool ( "listSchedPolicies" , false , "List the names of the pluaggable scheduling policies." )
var enableSchedPolicySwitch = flag . Bool ( "switchSchedPolicy" , false , "Enable switching of scheduling policies at runtime." )
2018-02-26 01:59:09 +00:00
var schedPolConfigFile = flag . String ( "schedPolConfig" , "" , "Config file that contains information for each scheduling policy." )
2018-01-19 21:20:43 +00:00
// Short hand args
2016-10-13 17:15:09 -04:00
func init ( ) {
2017-10-03 20:10:44 -04:00
flag . StringVar ( master , "m" , "" , "Location of leading Mesos master (shorthand)" )
2016-09-27 19:15:32 -04:00
flag . StringVar ( tasksFile , "w" , "" , "JSON file containing task definitions (shorthand)" )
2018-01-19 21:20:43 +00:00
flag . BoolVar ( wattsAsAResource , "waar" , false , "Enable Watts as a Resource (shorthand)" )
flag . StringVar ( pcplogPrefix , "p" , "" , "Prefix for pcplog (shorthand)" )
flag . Float64Var ( hiThreshold , "ht" , 700.0 , "Upperbound for when we should start capping (shorthand)" )
flag . Float64Var ( loThreshold , "lt" , 400.0 , "Lowerbound for when we should start uncapping (shorthand)" )
flag . BoolVar ( classMapWatts , "cmw" , false , "Enable mapping of watts to power class of node (shorthand)" )
flag . StringVar ( schedPolicyName , "sp" , "first-fit" , "Name of the scheduling policy to be used.\n Use option -listSchedPolicies to get the names of available scheduling policies (shorthand)" )
2017-09-26 13:17:47 -04:00
flag . BoolVar ( listSchedPolicies , "lsp" , false , "Names of the pluaggable scheduling policies. (shorthand)" )
2018-01-19 21:20:43 +00:00
flag . BoolVar ( enableSchedPolicySwitch , "ssp" , false , "Enable switching of scheduling policies at runtime." )
2018-02-26 01:59:09 +00:00
flag . StringVar ( schedPolConfigFile , "spConfig" , "" , "Config file that contains information for each scheduling policy (shorthand)." )
2017-09-26 13:17:47 -04:00
}
func listAllSchedulingPolicies ( ) {
fmt . Println ( "Scheduling Policies" )
fmt . Println ( "-------------------" )
2018-01-19 21:20:43 +00:00
for policyName , _ := range schedulers . SchedPolicies {
2017-09-26 13:17:47 -04:00
fmt . Println ( policyName )
}
2016-09-27 18:12:50 -04:00
}
2016-09-08 02:06:24 -04:00
func main ( ) {
flag . Parse ( )
2018-01-19 21:20:43 +00:00
// checking to see if we need to just list the pluggable scheduling policies
2017-09-26 13:17:47 -04:00
if * listSchedPolicies {
listAllSchedulingPolicies ( )
os . Exit ( 1 )
}
2018-01-19 21:20:43 +00:00
startTime := time . Now ( )
formattedStartTime := startTime . Format ( "20060102150405" )
// Checking if prefix contains any special characters
if strings . Contains ( * pcplogPrefix , "/" ) {
log . Fatal ( "log file prefix should not contain '/'." )
}
logPrefix := * pcplogPrefix + "_" + formattedStartTime
// creating logger and attaching different logging platforms
logger := elecLogDef . BuildLogger ( startTime , logPrefix )
// logging channels
logMType := make ( chan elecLogDef . LogMessageType )
logMsg := make ( chan string )
go logger . Listen ( logMType , logMsg )
2017-09-26 13:17:47 -04:00
// If non-default scheduling policy given,
2018-01-19 21:20:43 +00:00
// checking if scheduling policyName exists
2017-09-26 13:17:47 -04:00
if * schedPolicyName != "first-fit" {
2018-01-19 21:20:43 +00:00
if _ , ok := schedulers . SchedPolicies [ * schedPolicyName ] ; ! ok {
// invalid scheduling policy
2017-09-26 13:17:47 -04:00
log . Println ( "Invalid scheduling policy given. The possible scheduling policies are:" )
listAllSchedulingPolicies ( )
os . Exit ( 1 )
}
}
2016-09-16 19:06:53 -04:00
if * tasksFile == "" {
2018-01-19 21:20:43 +00:00
//fmt.Println("No file containing tasks specifiction provided.")
logger . WriteLog ( elecLogDef . ERROR , "No file containing tasks specification provided" )
2016-09-16 19:06:53 -04:00
os . Exit ( 1 )
}
2016-10-18 17:38:49 -04:00
if * hiThreshold < * loThreshold {
2018-01-19 21:20:43 +00:00
//fmt.Println("High threshold is of a lower value than low threshold.")
logger . WriteLog ( elecLogDef . ERROR , "High threshold is of a lower value than low threshold" )
2016-10-18 17:38:49 -04:00
os . Exit ( 1 )
}
2016-10-13 17:15:09 -04:00
tasks , err := def . TasksFromJSON ( * tasksFile )
if err != nil || len ( tasks ) == 0 {
2018-01-19 21:20:43 +00:00
//fmt.Println("Invalid tasks specification file provided")
logger . WriteLog ( elecLogDef . ERROR , "Invalid tasks specification file provided" )
2016-09-16 19:06:53 -04:00
os . Exit ( 1 )
}
2018-01-19 21:20:43 +00:00
//log.Println("Scheduling the following tasks:")
logger . WriteLog ( elecLogDef . GENERAL , "Scheduling the following tasks:" )
2016-09-17 18:55:35 -04:00
for _ , task := range tasks {
fmt . Println ( task )
}
2018-02-26 01:59:09 +00:00
if * enableSchedPolicySwitch {
if spcf := * schedPolConfigFile ; spcf == "" {
logger . WriteLog ( elecLogDef . ERROR , "No file containing characteristics for scheduling policies" )
} else {
// Initializing the characteristics of the scheduling policies.
schedulers . InitSchedPolicyCharacteristics ( spcf )
}
}
2017-09-26 13:17:47 -04:00
shutdown := make ( chan struct { } )
done := make ( chan struct { } )
pcpLog := make ( chan struct { } )
recordPCP := false
2018-01-19 21:20:43 +00:00
scheduler := schedulers . SchedFactory (
schedulers . WithSchedPolicy ( * schedPolicyName ) ,
2017-09-26 13:17:47 -04:00
schedulers . WithTasks ( tasks ) ,
schedulers . WithWattsAsAResource ( * wattsAsAResource ) ,
schedulers . WithClassMapWatts ( * classMapWatts ) ,
schedulers . WithRecordPCP ( & recordPCP ) ,
schedulers . WithShutdown ( shutdown ) ,
schedulers . WithDone ( done ) ,
2018-01-19 21:20:43 +00:00
schedulers . WithPCPLog ( pcpLog ) ,
schedulers . WithLoggingChannels ( logMType , logMsg ) ,
schedulers . WithSchedPolSwitchEnabled ( * enableSchedPolicySwitch ) )
2016-09-08 02:06:24 -04:00
driver , err := sched . NewMesosSchedulerDriver ( sched . DriverConfig {
Master : * master ,
Framework : & mesos . FrameworkInfo {
2017-09-26 01:05:18 -04:00
Name : proto . String ( "Elektron" ) ,
2016-09-08 02:06:24 -04:00
User : proto . String ( "" ) ,
} ,
Scheduler : scheduler ,
} )
if err != nil {
log . Printf ( "Unable to create scheduler driver: %s" , err )
return
}
2018-02-02 19:24:51 -05:00
go pcp . Start ( pcpLog , & recordPCP , logMType , logMsg , scheduler )
2018-01-19 21:20:43 +00:00
//go pcp.StartPCPLogAndExtremaDynamicCap(pcpLog, &recordPCP, *hiThreshold, *loThreshold, logMType, logMsg)
//go pcp.StartPCPLogAndProgressiveExtremaCap(pcpLog, &recordPCP, *hiThreshold, *loThreshold, logMType, logMsg)
time . Sleep ( 1 * time . Second ) // Take a second between starting PCP log and continuing
2016-09-26 19:14:51 -04:00
2017-09-28 15:36:47 -04:00
// Attempt to handle SIGINT to not leave pmdumptext running.
// Catch interrupt.
2016-10-07 20:47:59 -04:00
go func ( ) {
c := make ( chan os . Signal , 1 )
signal . Notify ( c , os . Interrupt , os . Kill )
s := <- c
if s != os . Interrupt {
2017-09-26 13:17:47 -04:00
close ( pcpLog )
2016-10-07 20:47:59 -04:00
return
}
log . Printf ( "Received SIGINT...stopping" )
2017-09-26 13:17:47 -04:00
close ( done )
2016-10-07 20:47:59 -04:00
} ( )
2016-09-08 02:06:24 -04:00
go func ( ) {
2017-09-28 15:36:47 -04:00
// Signals we have scheduled every task we have.
2016-09-19 20:25:10 -04:00
select {
2017-09-26 13:17:47 -04:00
case <- shutdown :
2017-01-28 17:48:15 -05:00
//case <-time.After(shutdownTimeout):
2016-09-17 18:55:35 -04:00
}
2016-09-08 02:06:24 -04:00
2017-09-28 15:36:47 -04:00
// All tasks have finished.
2016-09-08 02:06:24 -04:00
select {
2017-09-26 13:17:47 -04:00
case <- done :
close ( pcpLog )
2016-09-26 19:14:51 -04:00
time . Sleep ( 5 * time . Second ) //Wait for PCP to log a few more seconds
2018-01-19 21:20:43 +00:00
close ( logMType )
close ( logMsg )
2017-01-28 17:48:15 -05:00
//case <-time.After(shutdownTimeout):
2016-09-08 02:06:24 -04:00
}
2017-09-28 15:36:47 -04:00
// Done shutting down.
2016-09-08 02:06:24 -04:00
driver . Stop ( false )
2016-09-17 18:55:35 -04:00
2016-09-08 02:06:24 -04:00
} ( )
2016-09-15 15:53:56 -04:00
log . Printf ( "Starting..." )
2016-09-08 02:06:24 -04:00
if status , err := driver . Run ( ) ; err != nil {
log . Printf ( "Framework stopped with status %s and error: %s\n" , status . String ( ) , err . Error ( ) )
}
log . Println ( "Exiting..." )
2017-08-22 12:56:36 -04:00
}