...
1 package server
2
3 import (
4 "flag"
5 "fmt"
6 "golang.conradwood.net/apis/common"
7 "golang.conradwood.net/apis/goeasyops"
8 "golang.conradwood.net/go-easyops/cmdline"
9 "golang.conradwood.net/go-easyops/utils"
10 ad "golang.yacloud.eu/apis/autodeployer2"
11 "golang.yacloud.eu/unixipc"
12 "strconv"
13 "sync"
14 )
15
16 var (
17 enable_ipc = flag.Bool("ge_enable_ipc", true, "enable the internal ipc between code and autodeployer")
18 ipc_fd_env = cmdline.ENV("GE_AUTODEPLOYER_IPC_FD", "if set it is assumed to be a filedescriptor over which an IPC can be initiated with the autodeployer")
19 ipc_lock sync.Mutex
20 ipc_started = false
21 ipc_fd_found = false
22 ipc_ready = false
23 unixipc_srv *unixipc.IPCServer
24 )
25
26 func ipc_enabled() bool {
27 if *enable_ipc {
28 return true
29 }
30 return false
31 }
32
33 func start_ipc() {
34 if !ipc_enabled() {
35 return
36 }
37 ipc_lock.Lock()
38 defer ipc_lock.Unlock()
39 if ipc_started {
40 return
41 }
42 ipc_started = true
43 if ipc_fd_env.Value() == "" {
44 ipc_fd_found = false
45 fmt.Printf("[go-easyops] no ipc fd\n")
46 return
47 }
48 ipc_fd_found = true
49 fd, err := strconv.Atoi(ipc_fd_env.Value())
50 if err != nil {
51 panic(fmt.Sprintf("GE_AUTODEPLOYER_IPC_FD invalid value: %s", err))
52 }
53 unixipc_srv, err = unixipc.NewConnectedServer(fd)
54 if err != nil {
55 panic(fmt.Sprintf("failed to start autodeployer IPC: %s", err))
56 }
57 unixipc_srv.Name = "goeasyops"
58 unixipc_srv.RegisterRequestHandler(ipc_new_packet)
59 ipc_ready = true
60 }
61
62
63 func ipc_new_packet(req unixipc.Request) ([]byte, error) {
64 if req.RPCName() == "STOPREQUEST" {
65 stop_requested()
66 response := &goeasyops.StopUpdate{Stopping: true, ActiveRPCs: uint32(ActiveRPCs())}
67 b, err := utils.MarshalBytes(response)
68 if err != nil {
69 return nil, err
70 }
71 return b, nil
72 }
73 return nil, fmt.Errorf("[go-easyops] unipc client does not implement rpc call \"%s\"", req.RPCName())
74 }
75 func ipc_send_startup(sd *serverDef) error {
76 start_ipc()
77
78 if !ipc_ready {
79 fmt.Printf("[go-easyops] attempted to send ipc whilst it was not ready yet\n")
80 return nil
81 }
82 proto_payload := &ad.INTRPCStartup{
83 ServiceName: sd.name,
84 Port: uint32(sd.port),
85 Healthz: health,
86 }
87 payload, err := utils.MarshalBytes(proto_payload)
88 if err != nil {
89 return err
90 }
91 _, err = unixipc_srv.Send("startup", payload)
92 if err != nil {
93 return err
94 }
95 return nil
96 }
97 func ipc_send_new_para(sd *serverDef, name, value string) error {
98 start_ipc()
99 if !ipc_ready {
100 fmt.Printf("[go-easyops] no unixipc to report new flag %s=%s to\n", name, value)
101 return nil
102 }
103 if sd == nil {
104 sd = &serverDef{name: "", port: 0}
105 }
106 proto_payload := &ad.INTRPCFlagChange{
107 ServiceName: sd.name,
108 FlagName: name,
109 NewValue: value,
110 }
111 payload, err := utils.MarshalBytes(proto_payload)
112 if err != nil {
113 return err
114 }
115 _, err = unixipc_srv.Send("flagchange", payload)
116 if err != nil {
117 return err
118 }
119 return nil
120 }
121 func ipc_send_health(sd *serverDef, h common.Health) error {
122 start_ipc()
123 if !ipc_ready {
124 fmt.Printf("[go-easyops] no unixipc to report new health %v to\n", h)
125 return nil
126 }
127 if sd == nil {
128 sd = &serverDef{name: "", port: 0}
129 }
130 proto_payload := &ad.INTRPCHealthz{
131 ServiceName: sd.name,
132 Port: uint32(sd.port),
133 Healthz: h,
134 }
135 payload, err := utils.MarshalBytes(proto_payload)
136 if err != nil {
137 return err
138 }
139 _, err = unixipc_srv.Send("healthz", payload)
140 if err != nil {
141 return err
142 }
143 return nil
144 }
145
View as plain text