2017-12-08 08:31:45 +00:00
|
|
|
package service
|
|
|
|
|
|
|
|
import (
|
2017-12-15 08:18:32 +00:00
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"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-22 16:10:38 +00:00
|
|
|
crr "git.loafle.net/commons_go/rpc/registry"
|
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()"`
|
|
|
|
|
2018-03-22 16:10:38 +00:00
|
|
|
ProbeRPCInvoker crr.RPCInvoker `annotation:"@Resource()"`
|
|
|
|
|
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)
|
2018-03-22 16:10:38 +00:00
|
|
|
removePidFile(pidPath)
|
|
|
|
|
2018-03-21 10:22:13 +00:00
|
|
|
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-22 16:10:38 +00:00
|
|
|
client := container.New(port, cs.ProbeRPCInvoker)
|
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-22 16:10:38 +00:00
|
|
|
logging.Logger().Debugf("Container[%s] pid: %d", name, cmd.Process.Pid)
|
2018-03-21 10:22:13 +00:00
|
|
|
|
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
|
|
|
|
2018-03-22 16:10:38 +00:00
|
|
|
func removePidFile(pidFilePath string) {
|
|
|
|
if _, err := os.Stat(pidFilePath); err == nil {
|
|
|
|
if err := os.Remove(pidFilePath); nil != err {
|
|
|
|
logging.Logger().Errorf("Probe: Removing pid file has been failed [%v]", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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))
|
|
|
|
}
|
|
|
|
}
|