mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-10-21 14:29:33 +08:00
167 lines
3.8 KiB
Go
167 lines
3.8 KiB
Go
package daemon
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials/insecure"
|
|
"google.golang.org/grpc/health/grpc_health_v1"
|
|
_ "google.golang.org/grpc/resolver/dns"
|
|
_ "google.golang.org/grpc/resolver/passthrough"
|
|
|
|
"github.com/wencaiwulue/kubevpn/pkg/config"
|
|
"github.com/wencaiwulue/kubevpn/pkg/daemon/rpc"
|
|
)
|
|
|
|
var daemonClient, sudoDaemonClient rpc.DaemonClient
|
|
|
|
func GetClient(isSudo bool) rpc.DaemonClient {
|
|
if _, err := os.Stat(GetSockPath(isSudo)); errors.Is(err, os.ErrNotExist) {
|
|
return nil
|
|
}
|
|
if isSudo && sudoDaemonClient != nil {
|
|
return sudoDaemonClient
|
|
}
|
|
if !isSudo && daemonClient != nil {
|
|
return daemonClient
|
|
}
|
|
|
|
sudo := ""
|
|
if isSudo {
|
|
sudo = "sudo"
|
|
}
|
|
ctx := context.Background()
|
|
conn, err := grpc.DialContext(ctx, "passthrough:///unix://"+GetSockPath(isSudo), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
|
if err != nil {
|
|
log.Errorf("cannot connect to %s server: %v", sudo, err)
|
|
fmt.Println(fmt.Errorf("cannot connect to %s server: %v", sudo, err))
|
|
return nil
|
|
}
|
|
c := rpc.NewDaemonClient(conn)
|
|
now := time.Now()
|
|
healthClient := grpc_health_v1.NewHealthClient(conn)
|
|
response, err := healthClient.Check(ctx, &grpc_health_v1.HealthCheckRequest{})
|
|
if err != nil {
|
|
log.Printf("%v", err)
|
|
return nil
|
|
}
|
|
fmt.Println(response.Status, sudo, time.Now().Sub(now).String())
|
|
now = time.Now()
|
|
_, err = c.Status(ctx, &rpc.StatusRequest{})
|
|
fmt.Printf("call %s api status use %s\n", sudo, time.Now().Sub(now))
|
|
if err != nil {
|
|
fmt.Println(fmt.Errorf("cannot call %s api status: %v", sudo, err))
|
|
log.Error(err)
|
|
return nil
|
|
}
|
|
if isSudo {
|
|
sudoDaemonClient = c
|
|
} else {
|
|
daemonClient = c
|
|
}
|
|
return c
|
|
}
|
|
|
|
func GetSockPath(isSudo bool) string {
|
|
name := config.SockPath
|
|
if isSudo {
|
|
name = config.SudoSockPath
|
|
}
|
|
return filepath.Join(config.DaemonPath, name)
|
|
}
|
|
|
|
func GetPidPath(isSudo bool) string {
|
|
name := config.PidPath
|
|
if isSudo {
|
|
name = config.SudoPidPath
|
|
}
|
|
return filepath.Join(config.DaemonPath, name)
|
|
}
|
|
|
|
func GetDaemonCommand(isSudo bool) *exec.Cmd {
|
|
if isSudo {
|
|
return exec.Command("sudo", "--preserve-env", os.Args[0], "daemon", "--sudo")
|
|
}
|
|
return exec.Command(os.Args[0], "daemon")
|
|
}
|
|
|
|
func StartupDaemon(ctx context.Context) error {
|
|
// normal daemon
|
|
if daemonClient = GetClient(false); daemonClient == nil {
|
|
if err := runDaemon(ctx, false); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// sudo daemon
|
|
if sudoDaemonClient = GetClient(true); sudoDaemonClient == nil {
|
|
if err := runDaemon(ctx, true); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func runDaemon(ctx context.Context, isSudo bool) error {
|
|
portPath := GetSockPath(isSudo)
|
|
err := os.Remove(portPath)
|
|
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
|
return err
|
|
}
|
|
pidPath := GetPidPath(isSudo)
|
|
var file []byte
|
|
if file, err = os.ReadFile(pidPath); err == nil {
|
|
var pid int
|
|
if pid, err = strconv.Atoi(strings.TrimSpace(string(file))); err == nil {
|
|
var p *os.Process
|
|
if p, err = os.FindProcess(pid); err == nil {
|
|
if err = p.Kill(); err != nil && err != os.ErrProcessDone {
|
|
log.Error(err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
cmd := GetDaemonCommand(isSudo)
|
|
cmd.Stdin = os.Stdin
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
if err = cmd.Start(); err != nil {
|
|
return err
|
|
}
|
|
err = os.WriteFile(pidPath, []byte(strconv.Itoa(cmd.Process.Pid)), os.ModePerm)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = os.Chmod(GetPidPath(false), os.ModePerm)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
go func() {
|
|
cmd.Wait()
|
|
}()
|
|
|
|
for ctx.Err() == nil {
|
|
time.Sleep(time.Millisecond * 50)
|
|
if _, err = os.Stat(portPath); err == nil {
|
|
break
|
|
}
|
|
}
|
|
|
|
client := GetClient(isSudo)
|
|
if client == nil {
|
|
return fmt.Errorf("can not get daemon server client")
|
|
}
|
|
_, err = client.Status(ctx, &rpc.StatusRequest{})
|
|
|
|
return err
|
|
}
|