overflow_probes/service/ContainerService.go

166 lines
3.3 KiB
Go
Raw Normal View History

2017-12-08 08:31:45 +00:00
package service
import (
2017-12-15 08:18:32 +00:00
"fmt"
"io/ioutil"
2018-03-21 10:22:13 +00:00
"log"
2017-12-15 08:18:32 +00:00
"os"
2017-12-08 12:01:38 +00:00
"reflect"
2017-12-15 08:18:32 +00:00
"strconv"
"time"
2017-12-08 12:01:38 +00:00
cda "git.loafle.net/commons_go/di/annotation"
cdr "git.loafle.net/commons_go/di/registry"
2018-03-21 10:22:13 +00:00
"git.loafle.net/commons_go/logging"
2017-12-08 08:31:45 +00:00
crc "git.loafle.net/commons_go/rpc/client"
2018-03-15 13:52:23 +00:00
"git.loafle.net/overflow/overflow_probes/client/container"
2017-12-08 08:31:45 +00:00
)
2017-12-08 12:01:38 +00:00
func init() {
2018-03-15 13:52:23 +00:00
cdr.RegisterType(reflect.TypeOf((*ContainerService)(nil)))
2017-12-08 12:01:38 +00:00
}
2017-12-08 08:31:45 +00:00
type ContainerService struct {
2018-03-15 13:52:23 +00:00
cda.TypeAnnotation `annotation:"@overFlow:Service()"`
2017-12-08 08:31:45 +00:00
clients map[string]*containerState
}
type containerState struct {
2017-12-15 08:18:32 +00:00
pid int
port int
client crc.Client
2017-12-08 08:31:45 +00:00
}
func (cs *ContainerService) Call(name string, result interface{}, method string, params ...interface{}) error {
c, err := cs.GetClient(name)
if nil != err {
return err
}
return c.Call(result, method, params...)
}
func (cs *ContainerService) Send(name string, method string, params ...interface{}) error {
c, err := cs.GetClient(name)
if nil != err {
return err
}
return c.Send(method, params...)
}
func (cs *ContainerService) GetClient(name string) (crc.Client, error) {
2017-12-15 08:18:32 +00:00
cState, ok := cs.clients[name]
if !ok {
if err := cs.runProcess(name); nil != err {
return nil, err
}
cState, _ = cs.clients[name]
}
return cState.client, nil
2017-12-08 08:31:45 +00:00
}
func (cs *ContainerService) Connect(name string) error {
return nil
}
func (cs *ContainerService) runProcess(name string) error {
ok := cs.checkProcess(name)
if ok {
return nil
}
2018-03-21 10:22:13 +00:00
cmd, pidPath := container.GetContainerCommand(name)
if err := cmd.Start(); nil != err {
logging.Logger().Errorf("Probe: To run container(%s) failed err %v", name, err)
return err
}
2017-12-15 08:18:32 +00:00
2018-03-21 10:22:13 +00:00
port, err := watchPidFileCreate(pidPath, time.Duration(time.Second*2))
if nil != err {
return err
}
// port := 60000
2017-12-08 08:31:45 +00:00
2018-03-15 13:52:23 +00:00
client := container.New(port, nil)
2017-12-15 08:18:32 +00:00
if err := client.Connect(); nil != err {
2018-03-21 10:22:13 +00:00
cmd.Process.Kill()
2017-12-15 08:18:32 +00:00
return err
}
2017-12-08 08:31:45 +00:00
2018-03-21 10:22:13 +00:00
log.Printf("pid: %d", cmd.Process.Pid)
2017-12-15 08:18:32 +00:00
cState := &containerState{
2018-03-21 10:22:13 +00:00
pid: cmd.Process.Pid,
2017-12-15 08:18:32 +00:00
port: port,
client: client,
}
2017-12-08 08:31:45 +00:00
2018-03-15 13:52:23 +00:00
if nil == cs.clients {
cs.clients = make(map[string]*containerState, 0)
}
2017-12-15 08:18:32 +00:00
cs.clients[name] = cState
2017-12-08 08:31:45 +00:00
return nil
}
func (cs *ContainerService) checkProcess(name string) bool {
2017-12-15 08:18:32 +00:00
cState, ok := cs.clients[name]
if !ok || nil == cState || nil == cState.client {
return false
}
_, err := os.FindProcess(cState.pid)
if nil != err {
return false
}
return true
2017-12-08 08:31:45 +00:00
}
func (cs *ContainerService) killProcess(name string) error {
2017-12-15 08:18:32 +00:00
cState, ok := cs.clients[name]
if !ok || nil == cState || nil == cState.client {
return fmt.Errorf("Probe: Container[%s] is not exist", name)
}
p, err := os.FindProcess(cState.pid)
if nil != err {
return err
}
2018-03-15 13:52:23 +00:00
if err = p.Signal(os.Interrupt); nil != err {
2017-12-15 08:18:32 +00:00
return err
}
2018-03-15 13:52:23 +00:00
// if err = p.Kill(); nil != err {
// return err
// }
2017-12-08 08:31:45 +00:00
return nil
}
2017-12-15 08:18:32 +00:00
func watchPidFileCreate(pidFilePath string, waitTime time.Duration) (int, error) {
startTime := time.Now()
for {
if _, err := os.Stat(pidFilePath); err == nil {
buf, err := ioutil.ReadFile(pidFilePath)
if nil != err {
return 0, err
}
portNumber, err := strconv.ParseInt(string(buf), 10, 32)
if nil != err {
return 0, err
}
return int(portNumber), nil
}
if time.Since(startTime) > waitTime {
return 0, fmt.Errorf("Probe: pid file not exist")
}
time.Sleep(time.Duration(time.Millisecond * 100))
}
}