2016-09-08 02:06:24 -04:00
package main
import (
2017-09-26 00:18:35 -04:00
"bitbucket.org/sunybingcloud/elektron/def"
"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"
mesos "github.com/mesos/mesos-go/mesosproto"
sched "github.com/mesos/mesos-go/scheduler"
"log"
"os"
2016-10-07 20:47:59 -04:00
"os/signal"
2016-10-13 17:15:09 -04:00
"time"
2016-09-08 02:06:24 -04:00
)
2017-09-26 01:05:18 -04:00
var master = flag . String ( "master" , "<mesos-master>:5050" , "Location of leading Mesos master" )
2016-09-27 18:12:50 -04:00
var tasksFile = flag . String ( "workload" , "" , "JSON file containing task definitions" )
2017-09-26 13:17:47 -04:00
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." )
2017-09-26 01:05:18 -04:00
var pcplogPrefix = flag . String ( "logPrefix" , "" , "Prefix for PCP log file" )
2017-09-26 13:17:47 -04:00
var hiThreshold = flag . Float64 ( "hiThreshold" , 0.0 , "Upperbound for Cluster average historical power consumption, " +
"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" )
2017-09-26 01:05:18 -04:00
var classMapWatts = flag . Bool ( "classMapWatts" , false , "Enable mapping of watts to powerClass of node" )
2017-09-26 13:17:47 -04:00
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." )
2016-09-27 18:12:50 -04:00
// Short hand args
2016-10-13 17:15:09 -04:00
func init ( ) {
2017-09-26 01:05:18 -04:00
flag . StringVar ( master , "m" , "<mesos-master>:5050" , "Location of leading Mesos master (shorthand)" )
2016-09-27 19:15:32 -04:00
flag . StringVar ( tasksFile , "w" , "" , "JSON file containing task definitions (shorthand)" )
2017-09-26 13:17:47 -04:00
flag . BoolVar ( wattsAsAResource , "waar" , false , "Enable Watts as a Resource. " +
2017-09-26 01:05:18 -04:00
"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)" )
2017-09-26 13:17:47 -04:00
flag . Float64Var ( hiThreshold , "ht" , 700.0 , "Upperbound for Cluster average historical power consumption, " +
2017-09-26 01:05:18 -04:00
"beyond which extrema/progressive-extrema would start power-capping (shorthand)" )
2017-09-26 13:17:47 -04:00
flag . Float64Var ( loThreshold , "lt" , 400.0 , "Lowerbound for Cluster average historical power consumption, " +
2017-09-26 01:05:18 -04:00
"below which extrema/progressive-extrema would stop power-capping (shorthand)" )
flag . BoolVar ( classMapWatts , "cmw" , false , "Enable mapping of watts to powerClass of node (shorthand)" )
2017-09-26 13:17:47 -04:00
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 )
}
2016-09-27 18:12:50 -04:00
}
2016-09-08 02:06:24 -04:00
func main ( ) {
flag . Parse ( )
2017-09-26 13:17:47 -04:00
// 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 )
}
}
2016-09-16 19:06:53 -04:00
if * tasksFile == "" {
fmt . Println ( "No file containing tasks specifiction provided." )
os . Exit ( 1 )
}
2016-10-18 17:38:49 -04:00
if * hiThreshold < * loThreshold {
2017-03-24 17:13:21 -04:00
fmt . Println ( "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 {
2016-09-16 19:06:53 -04:00
fmt . Println ( "Invalid tasks specification file provided" )
os . Exit ( 1 )
}
2016-09-17 18:55:35 -04:00
log . Println ( "Scheduling the following tasks:" )
for _ , task := range tasks {
fmt . Println ( task )
}
2017-01-03 20:30:21 -05:00
startTime := time . Now ( ) . Format ( "20060102150405" )
logPrefix := * pcplogPrefix + "_" + startTime
2016-09-17 18:55:35 -04:00
2017-09-26 13:17:47 -04:00
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 ) )
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
}
2017-09-26 13:17:47 -04:00
go pcp . Start ( pcpLog , & recordPCP , logPrefix )
//go pcp.StartPCPLogAndExtremaDynamicCap(pcpLog, &recordPCP, logPrefix, *hiThreshold, *loThreshold)
//go pcp.StartPCPLogAndProgressiveExtremaCap(pcpLog, &recordPCP, logPrefix, *hiThreshold, *loThreshold)
2017-01-04 20:25:54 -05:00
time . Sleep ( 1 * time . Second ) // Take a second between starting PCP log and continuing
2016-09-26 19:14:51 -04:00
2017-03-24 17:13:21 -04:00
// Attempt to handle SIGINT to not leave pmdumptext running
2016-09-08 02:06:24 -04:00
// 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 ( ) {
2016-09-26 19:14:51 -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
2016-10-07 20:47:59 -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
2017-01-28 17:48:15 -05:00
//case <-time.After(shutdownTimeout):
2016-09-08 02:06:24 -04:00
}
// Done shutting down
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
}