2019-10-31 14:32:46 -04:00
// Copyright (C) 2018 spdfg
2019-12-09 20:15:33 -05:00
//
2018-10-06 20:03:14 -07:00
// This file is part of Elektron.
2019-12-09 20:15:33 -05:00
//
2018-10-06 20:03:14 -07:00
// Elektron is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
2019-12-09 20:15:33 -05:00
//
2018-10-06 20:03:14 -07:00
// Elektron is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
2019-12-09 20:15:33 -05:00
//
2018-10-06 20:03:14 -07:00
// You should have received a copy of the GNU General Public License
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
2019-12-09 20:15:33 -05:00
//
2018-10-06 20:03:14 -07:00
2017-03-23 22:09:51 -04:00
package offerUtils
import (
2017-03-24 16:34:17 -04:00
"strings"
2018-09-30 18:23:38 -07:00
mesos "github.com/mesos/mesos-go/api/v0/mesosproto"
2019-12-09 20:15:33 -05:00
log "github.com/sirupsen/logrus"
2019-10-31 14:32:46 -04:00
"github.com/spdfg/elektron/constants"
2019-12-09 20:15:33 -05:00
elekLog "github.com/spdfg/elektron/logging"
. "github.com/spdfg/elektron/logging/types"
2017-03-23 22:09:51 -04:00
)
func OfferAgg ( offer * mesos . Offer ) ( float64 , float64 , float64 ) {
var cpus , mem , watts float64
for _ , resource := range offer . Resources {
switch resource . GetName ( ) {
case "cpus" :
cpus += * resource . GetScalar ( ) . Value
case "mem" :
mem += * resource . GetScalar ( ) . Value
case "watts" :
watts += * resource . GetScalar ( ) . Value
}
}
return cpus , mem , watts
}
2017-09-28 15:36:47 -04:00
// Determine the power class of the host in the offer.
2017-03-23 22:09:51 -04:00
func PowerClass ( offer * mesos . Offer ) string {
var powerClass string
for _ , attr := range offer . GetAttributes ( ) {
if attr . GetName ( ) == "class" {
powerClass = attr . GetText ( ) . GetValue ( )
}
}
return powerClass
}
// Implements the sort.Sort interface to sort Offers based on CPU.
2017-09-28 15:36:47 -04:00
// TODO: Have a generic sorter that sorts based on a defined requirement (CPU, RAM, DISK or Watts).
2017-03-23 22:09:51 -04:00
type OffersSorter [ ] * mesos . Offer
func ( offersSorter OffersSorter ) Len ( ) int {
return len ( offersSorter )
}
func ( offersSorter OffersSorter ) Swap ( i , j int ) {
offersSorter [ i ] , offersSorter [ j ] = offersSorter [ j ] , offersSorter [ i ]
}
func ( offersSorter OffersSorter ) Less ( i , j int ) bool {
2017-09-28 15:36:47 -04:00
// Getting CPU resource availability of offersSorter[i].
2017-03-23 22:09:51 -04:00
cpu1 , _ , _ := OfferAgg ( offersSorter [ i ] )
2017-09-28 15:36:47 -04:00
// Getting CPU resource availability of offersSorter[j].
2017-03-23 22:09:51 -04:00
cpu2 , _ , _ := OfferAgg ( offersSorter [ j ] )
return cpu1 <= cpu2
}
// Is there a mismatch between the task's host requirement and the host corresponding to the offer.
func HostMismatch ( offerHost string , taskHost string ) bool {
if taskHost != "" && ! strings . HasPrefix ( offerHost , taskHost ) {
return true
}
return false
}
2017-03-24 16:27:14 -04:00
// If the host in the offer is a new host, add the host to the set of Hosts and
// register the powerclass of this host.
2017-03-25 18:05:36 -04:00
func UpdateEnvironment ( offer * mesos . Offer ) {
2017-03-24 16:27:14 -04:00
var host = offer . GetHostname ( )
// If this host is not present in the set of hosts.
if _ , ok := constants . Hosts [ host ] ; ! ok {
2019-12-09 20:15:33 -05:00
elekLog . WithField ( "host" , host ) . Log ( CONSOLE , log . InfoLevel , "New host detected" )
2017-03-24 16:27:14 -04:00
// Add this host.
constants . Hosts [ host ] = struct { } { }
// Get the power class of this host.
2017-03-25 21:11:24 -04:00
class := PowerClass ( offer )
2019-12-09 20:15:33 -05:00
elekLog . WithFields ( log . Fields {
"host" : host ,
"PowerClass" : class ,
} ) . Log ( CONSOLE , log . InfoLevel , "Registering the power class..." )
2017-03-25 18:05:36 -04:00
// If new power class, register the power class.
2017-03-24 16:27:14 -04:00
if _ , ok := constants . PowerClasses [ class ] ; ! ok {
constants . PowerClasses [ class ] = make ( map [ string ] struct { } )
}
// If the host of this class is not yet present in PowerClasses[class], add it.
2017-03-24 16:34:17 -04:00
if _ , ok := constants . PowerClasses [ class ] [ host ] ; ! ok {
2017-03-24 16:27:14 -04:00
constants . PowerClasses [ class ] [ host ] = struct { } { }
}
}
2017-03-24 16:34:17 -04:00
}