A-Tune/common/project/projet.go
Zhipeng Xie 4335408875 atune: init code
upload code to gitee

Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
2019-11-13 17:14:15 +08:00

200 lines
5.0 KiB
Go

/*
* Copyright (c) 2019 Huawei Technologies Co., Ltd.
* A-Tune is licensed under the Mulan PSL v1.
* You can use this software according to the terms and conditions of the Mulan PSL v1.
* You may obtain a copy of Mulan PSL v1 at:
* http://license.coscl.org.cn/MulanPSL
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v1 for more details.
* Create: 2019-10-29
*/
package project
import (
"atune/common/log"
"atune/common/utils"
"fmt"
"io/ioutil"
"os/exec"
"strconv"
"strings"
yaml "gopkg.in/yaml.v2"
)
// Evaluate :store the evaluate object
type Evaluate struct {
Name string `yaml : "name"`
Info EvalInfo `yaml : "info"`
}
// EvalInfo :store the evaluation object
type EvalInfo struct {
Get string `yaml : "get"`
Type string `yaml : "type"`
Weight int64 `yaml : "weight"`
Threshold int64 `yaml : "threshold"`
}
// YamlPrj :store the yaml project
type YamlPrj struct {
Object []YamlPrjObj `yaml : "object"`
Startworkload string `yaml : "startworkload"`
Stopworkload string `yaml : "stopworkload"`
Iterations int `yaml : "iterations"`
Benchmark string `yaml : "benchmark"`
Evaluations []Evaluate `yaml : "evaluations"`
}
// YamlObj :yaml Object
type YamlObj struct {
Name string `yaml:"name"`
Desc string `yaml:"desc"`
GetScript string `yaml:"get"`
SetScript string `yaml:"set"`
Needrestart string `yaml:"needrestart"`
Type string `yaml:"type"`
Step int64 `yaml:"step"`
Items []int64 `yaml:"items"`
Options []string `yaml:"options"`
Scope []int64 `yaml:"scope,flow"`
Dtype string `yaml:"dtype"`
Ref string `yaml:"ref"`
}
// YamlPrjObj :store the yaml object
type YamlPrjObj struct {
Name string `yaml : "name"`
Info YamlObj `yaml : "info"`
}
// LoadProject method load the tuning yaml
func LoadProject(path string) (*YamlPrj, error) {
exist, err := utils.PathExist(path)
if err != nil {
return nil, err
}
if !exist {
return nil, fmt.Errorf("The path %s doesn't exist", path)
}
return newProject(path)
}
func newProject(path string) (*YamlPrj, error) {
info, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
prj := new(YamlPrj)
if err := yaml.Unmarshal(info, prj); err != nil {
return nil, fmt.Errorf("Parse %s failed : %s", path, err)
}
return prj, nil
}
// BenchMark method call the benchmark script
func (y *YamlPrj) BenchMark() ([]byte, error) {
log.Info("start to benchmark the performance")
cmd := exec.Command("sudo", "sh", "-c", y.Benchmark)
benchOutByte, err := cmd.CombinedOutput()
if err != nil {
return nil, err
}
return benchOutByte, nil
}
// Evaluation method get the evaluation value from the benchmark result
func (y *YamlPrj) Evaluation(benchmarkByte []byte) (string, error) {
benchmarkOut := string(benchmarkByte)
benchStr := ""
for _, evaluation := range y.Evaluations {
newScript := strings.Replace(evaluation.Info.Get, "$out", benchmarkOut, -1)
cmd := exec.Command("sudo", "sh", "-c", newScript)
bout, err := cmd.Output()
if err != nil {
log.Error(err)
return benchStr, err
}
floatout, err := strconv.ParseFloat(strings.Replace(string(bout), "\n", "", -1), 64)
if err != nil {
log.Error(err)
return benchStr, err
}
out := strconv.FormatFloat((floatout * float64(evaluation.Info.Weight) / 100), 'E', -1, 64)
if evaluation.Info.Type == "negative" {
out = "-" + out
}
benchStr = benchStr + out + ","
}
benchStr = benchStr[:len(benchStr)-1]
return benchStr, nil
}
// RunSet method call the set script to set set the value
func (y *YamlPrj) RunSet(optStr string) error {
paraMap := make(map[string]string)
paraSlice := strings.Split(optStr, ",")
for _, para := range paraSlice {
kvs := strings.Split(para, "=")
paraMap[kvs[0]] = kvs[1]
}
for _, obj := range y.Object {
obj.Info.Ref = paraMap[obj.Name]
}
for _, obj := range y.Object {
script := obj.Info.SetScript
newScript := strings.Replace(script, "$value", obj.Info.Ref, -1)
log.Info("set script:", newScript)
cmd := exec.Command("sudo", "sh", "-c", newScript)
err := cmd.Run()
if err != nil {
return err
}
}
return nil
}
// RestartProject method call the StartWorkload and StopWorkload script to restart the service
func (y *YamlPrj) RestartProject() error {
startWorkload := y.Startworkload
stopWorkload := y.Stopworkload
needRestart := false
for _, obj := range y.Object {
if obj.Info.Needrestart == "true" {
needRestart = true
break
}
}
if needRestart == true {
cmd := exec.Command("sudo", "sh", "-c", stopWorkload)
out, err := cmd.CombinedOutput()
log.Debug(string(out))
if err != nil {
return err
}
cmd = exec.Command("sudo", "sh", "-c", startWorkload)
out, err = cmd.CombinedOutput()
log.Debug(string(out))
if err != nil {
return err
}
}
return nil
}