234 lines
4.7 KiB
Go
234 lines
4.7 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 main
|
|
|
|
import (
|
|
"atune/common/config"
|
|
"atune/common/log"
|
|
"atune/common/registry"
|
|
SVC "atune/common/service"
|
|
"atune/common/sqlstore"
|
|
"atune/common/utils"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net"
|
|
"os"
|
|
"os/exec"
|
|
"os/signal"
|
|
"syscall"
|
|
|
|
"github.com/coreos/go-systemd/daemon"
|
|
"github.com/urfave/cli"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/reflection"
|
|
)
|
|
|
|
const (
|
|
atunedUsage = `atuned daemon is the AI system daemon
|
|
To get more info of how to use atuned:
|
|
# atuned help
|
|
`
|
|
)
|
|
|
|
type swServer struct {
|
|
server *grpc.Server
|
|
svcs map[string]interface{}
|
|
}
|
|
|
|
func newServer(rpc *grpc.Server) (*swServer, error) {
|
|
server := new(swServer)
|
|
server.server = rpc
|
|
server.svcs = make(map[string]interface{})
|
|
|
|
return server, nil
|
|
}
|
|
|
|
func createSvcInsts(ctx *cli.Context, svr *swServer) error {
|
|
if err := SVC.WalkServices(func(nm string, svc *SVC.ProfileService) error {
|
|
inst, err := svc.NewInst(ctx)
|
|
if err != nil {
|
|
fmt.Printf("Create %s instance failed\n", nm)
|
|
return nil
|
|
}
|
|
|
|
log.Infof("Create %s service successfully\n", nm)
|
|
|
|
sinst, ok := inst.(SVC.SvrService)
|
|
if !ok {
|
|
return fmt.Errorf("not impletment SvrService")
|
|
}
|
|
|
|
if err := sinst.RegisterServer(svr.server); err != nil {
|
|
return err
|
|
}
|
|
|
|
svr.svcs[nm] = inst
|
|
|
|
return nil
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func loadModules(ctx *cli.Context, svr *swServer, path string) error {
|
|
exist, err := utils.PathExist(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !exist {
|
|
return nil
|
|
}
|
|
|
|
if err := utils.LoadPlugins(path); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := createSvcInsts(ctx, svr); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func checkValid(ctx *cli.Context) error {
|
|
return nil
|
|
}
|
|
|
|
func doBeforeJob(ctx *cli.Context) error {
|
|
if err := checkValid(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Load conf file
|
|
cfg := config.NewCfg()
|
|
if err := cfg.Load(); err != nil {
|
|
log.Errorf("Faild to load config file, error: %v", err)
|
|
return fmt.Errorf("Faild to load config file, error: %v", err)
|
|
}
|
|
|
|
store := &sqlstore.Sqlstore{
|
|
Cfg: cfg,
|
|
}
|
|
// init the sqlite3 database engine
|
|
if err := store.Init(); err != nil {
|
|
log.Error(err)
|
|
return err
|
|
}
|
|
|
|
services := registry.GetDaemonServices()
|
|
|
|
for _, service := range services {
|
|
log.Infof("initializing service: %s", service.Name)
|
|
service.Instance.Set(cfg)
|
|
if err := service.Instance.Init(); err != nil {
|
|
return fmt.Errorf("service init faild: %v", err)
|
|
}
|
|
}
|
|
|
|
// starting all service
|
|
for _, srv := range services {
|
|
service := srv
|
|
backgroundService, ok := service.Instance.(registry.BackgroundService)
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
go func() error {
|
|
err := backgroundService.Run()
|
|
if err != nil {
|
|
log.Errorf("service %s running faild, reason: %v", service.Name, err)
|
|
return err
|
|
}
|
|
return nil
|
|
}()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func listenToSystemSignals(cmd *exec.Cmd) {
|
|
signalChan := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(signalChan, os.Interrupt, os.Kill, syscall.SIGKILL)
|
|
select {
|
|
case <-signalChan:
|
|
syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
|
|
os.Exit(-1)
|
|
}
|
|
}
|
|
|
|
func showlogo() {
|
|
logo, err := ioutil.ReadFile("/usr/share/atuned/atune.logo")
|
|
if err != nil {
|
|
fmt.Print(err)
|
|
}
|
|
|
|
fmt.Print(string(logo))
|
|
}
|
|
|
|
func runatuned(ctx *cli.Context) error {
|
|
if err := checkValid(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
lis, err := net.Listen("tcp", config.Address+":"+config.Port)
|
|
if err != nil {
|
|
log.Fatalf("failed to listen: %v", err)
|
|
}
|
|
s := grpc.NewServer()
|
|
|
|
server, err := newServer(s)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := loadModules(ctx, server, config.DefaultModDaemonSvrPath); err != nil {
|
|
return err
|
|
}
|
|
|
|
/* Show atuned Log*/
|
|
showlogo()
|
|
if err := utils.WaitForPyservice(); err != nil {
|
|
log.Errorf("waiting for pyservice faild: %v", err)
|
|
return err
|
|
}
|
|
|
|
log.Info("pyservice has been started")
|
|
daemon.SdNotify(false, "READY=1")
|
|
|
|
reflection.Register(s)
|
|
if err := s.Serve(lis); err != nil {
|
|
log.Fatalf("failed to serve: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func main() {
|
|
app := cli.NewApp()
|
|
app.Name = "atuned"
|
|
app.Usage = atunedUsage
|
|
|
|
app.Version = config.Version
|
|
app.Before = doBeforeJob
|
|
app.Action = runatuned
|
|
|
|
if err := app.Run(os.Args); err != nil {
|
|
fmt.Printf("%s\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|