2017-09-11 00:22:51 +09:00
|
|
|
package consumer
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os/exec"
|
|
|
|
"time"
|
2018-07-06 01:42:09 +09:00
|
|
|
zlog "amuz.es/src/infra/goutils/logger/zap"
|
2017-09-11 00:37:01 +09:00
|
|
|
"bytes"
|
2018-07-06 01:42:09 +09:00
|
|
|
"amuz.es/src/infra/goutils/handler"
|
|
|
|
"amuz.es/src/infra/cpu_ctrl/producer"
|
|
|
|
"go.uber.org/zap"
|
2018-07-06 01:57:59 +09:00
|
|
|
"github.com/alecthomas/chroma/lexers/m"
|
2017-09-11 00:37:01 +09:00
|
|
|
)
|
|
|
|
|
2018-07-06 01:42:09 +09:00
|
|
|
var ()
|
2017-09-11 00:22:51 +09:00
|
|
|
|
|
|
|
type fanControl struct {
|
|
|
|
processorCount int
|
2018-07-06 01:42:09 +09:00
|
|
|
handler *handler.Handler
|
|
|
|
fanSpeedConsumer chan producer.FanspeedInfo
|
2017-09-11 00:22:51 +09:00
|
|
|
sampleDuration time.Duration
|
2018-07-06 01:42:09 +09:00
|
|
|
logger *zap.SugaredLogger
|
2017-09-11 00:22:51 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
type FanControl interface {
|
2018-07-06 01:42:09 +09:00
|
|
|
Consumer() chan<- producer.FanspeedInfo
|
2017-09-11 00:22:51 +09:00
|
|
|
StartControl()
|
|
|
|
}
|
|
|
|
|
2018-07-06 01:42:09 +09:00
|
|
|
func NewFanControl(processorCount int, sampleDuration time.Duration, handler *handler.Handler) FanControl {
|
2017-09-11 00:22:51 +09:00
|
|
|
return &fanControl{
|
|
|
|
processorCount: processorCount,
|
|
|
|
handler: handler,
|
2018-07-06 01:42:09 +09:00
|
|
|
fanSpeedConsumer: make(chan producer.FanspeedInfo, processorCount),
|
2017-09-11 00:22:51 +09:00
|
|
|
sampleDuration: sampleDuration,
|
2018-07-06 01:42:09 +09:00
|
|
|
logger: zlog.New(nil, "fanspeed"),
|
2017-09-11 00:22:51 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-06 01:42:09 +09:00
|
|
|
func (c *fanControl) Consumer() chan<- producer.FanspeedInfo { return c.fanSpeedConsumer }
|
2017-09-11 00:22:51 +09:00
|
|
|
|
|
|
|
func (c *fanControl) StartControl() {
|
|
|
|
defer c.handler.DecreaseWait()
|
|
|
|
defer func() {
|
|
|
|
if err := recover(); err != nil {
|
|
|
|
c.handler.NotifyError(err.(error))
|
|
|
|
}
|
|
|
|
}()
|
2018-07-06 01:42:09 +09:00
|
|
|
defer c.logger.Info("Fan control stopped")
|
|
|
|
c.logger.Info("Fan control started")
|
2017-09-11 00:22:51 +09:00
|
|
|
|
|
|
|
ticker := time.Tick(c.sampleDuration)
|
2017-09-13 00:33:34 +09:00
|
|
|
pastFanSpeedList, newFanSpeedList := make([]int, c.processorCount), make([]int, c.processorCount)
|
2018-07-06 01:57:59 +09:00
|
|
|
|
|
|
|
go func() {
|
|
|
|
for changedFanspeed := range c.fanSpeedConsumer {
|
|
|
|
newFanSpeedList[changedFanspeed.Id] = changedFanspeed.FanSpeed
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2017-09-11 00:22:51 +09:00
|
|
|
for {
|
2017-09-13 00:33:34 +09:00
|
|
|
select {
|
|
|
|
case <-ticker:
|
2017-09-13 00:53:45 +09:00
|
|
|
if !compareFanSpeed(pastFanSpeedList, newFanSpeedList) {
|
|
|
|
copy(pastFanSpeedList, newFanSpeedList)
|
|
|
|
go c.applyFanspeed(pastFanSpeedList)
|
|
|
|
}
|
2017-09-13 00:33:34 +09:00
|
|
|
case <-c.handler.Done():
|
|
|
|
return
|
2017-09-11 00:22:51 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-09-13 00:53:45 +09:00
|
|
|
func (c *fanControl) applyFanspeed(newFanSpeedList []int) {
|
2017-09-13 00:33:34 +09:00
|
|
|
args := make([]string, 0)
|
|
|
|
args = append(args, "raw", "0x3a", "0x01", )
|
|
|
|
for _, item := range newFanSpeedList {
|
|
|
|
args = append(args, fmt.Sprintf("0x%x", item))
|
|
|
|
}
|
|
|
|
args = append(args,
|
|
|
|
"0x0", "0x0", "0x0", "0x0", "0x0", "0x0",
|
|
|
|
)
|
|
|
|
cmd := exec.Command("ipmitool", args...)
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
|
|
c.handler.NotifyError(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
buf := bytes.NewBufferString("")
|
|
|
|
for _, item := range newFanSpeedList {
|
|
|
|
buf.WriteString(fmt.Sprintf("0x%x", item))
|
|
|
|
buf.WriteRune(' ')
|
|
|
|
}
|
2018-07-06 01:42:09 +09:00
|
|
|
c.logger.Infof("Commit fan speed with %s", buf.String())
|
2017-09-13 00:33:34 +09:00
|
|
|
}
|
2017-09-11 00:22:51 +09:00
|
|
|
|
|
|
|
func compareFanSpeed(old, new []int) bool {
|
2017-09-11 01:18:37 +09:00
|
|
|
new = new[:len(old)] // this line is the key
|
2017-09-11 00:22:51 +09:00
|
|
|
for i, v := range old {
|
|
|
|
if v != new[i] { // here is no bounds checking for b[i]
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|