2 * Copyright (C) 2017-2018 "IoT.bzh"
3 * Author Sebastien Douheret <sebastien@iot.bzh>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
26 common "gerrit.automotivelinux.org/gerrit/src/xds/xds-common.git"
27 uuid "github.com/satori/go.uuid"
31 type XdsSupervisor struct {
40 client *common.HTTPClient
42 cbOnConnect OnConnectedXdsSupervCB
45 // XdsSuperVRequest Resquest field of a reply
46 type XdsSuperVRequest struct {
47 Status string `json:"status"`
48 Info string `json:"info"`
51 // XdsSuperVReply Reply structure of XDS Supervision Daemon
52 type XdsSuperVReply struct {
53 JType string `json:"jtype"`
54 Request XdsSuperVRequest `json:"request"`
55 Response interface{} `json:"response"`
58 // XdsSuperVTraceConfig
59 type XdsSuperVTraceConfig struct {
61 Pids []int `json:"pids"`
62 WsName string `json:"ws"`
65 // OnConnectedXdsSupervCB connect callback
66 type OnConnectedXdsSupervCB func(svr *XdsSupervisor) error
68 // NewXdsSupervisor creates an instance of XdsSupervisor
69 func NewXdsSupervisor(ctx *Context) *XdsSupervisor {
70 return &XdsSupervisor{
72 ID: "XdsSupervisor-" + uuid.NewV1().String(),
73 BaseURL: ctx.Config.FileConf.ProfileConf.XDSBinder.URL,
74 ConnRetry: ctx.Config.FileConf.ProfileConf.XDSBinder.ConnRetry,
82 // Connect Establish HTTP connection with XDS Supervisor Dameon
83 func (xs *XdsSupervisor) Connect() error {
91 for retry = xs.ConnRetry; retry > 0; retry-- {
92 if err = xs._CreateConnectHTTP(); err == nil {
95 if retry == xs.ConnRetry {
96 // Notify only on the first conn error
97 // doing that avoid 2 notifs (conn false; conn true) on startup
100 xs.Log.Infof("Establishing connection to XDS Supervisor daemon (retry %d/%d)", retry, xs.ConnRetry)
101 time.Sleep(time.Second)
104 // FIXME: re-use _Reconnect to wait longer in background
105 return fmt.Errorf("Connection to XDS Supervisor daemon failure")
111 // Check HTTP connection and establish WS connection
112 err = xs._Connect(false)
117 // ConnectOn Register a callback on events reception
118 func (xs *XdsSupervisor) ConnectOn(f OnConnectedXdsSupervCB) error {
123 // GetVersion Send Get request to retrieve XDS Supervision version
124 func (xs *XdsSupervisor) GetVersion(res interface{}) error {
125 // FIXME add suffix URLSuffix in common HTTP client lib instead of _BuildURL
126 return xs.client.Get(xs._BuildURL("/version"), &res)
129 // GetTopo Send Get request to retrieve Services/Daemons topology
130 func (xs *XdsSupervisor) GetTopo(res interface{}) error {
131 return xs.client.Get(xs._BuildURL("/list"), &res)
134 // StartTrace Send Supervisor config and start tracing
135 func (xs *XdsSupervisor) StartTrace(cfg XdsSuperVTraceConfig, res interface{}) error {
136 return xs.client.Post(xs._BuildURL("/trace/start"), cfg, &res)
139 // StopTrace Send Supervisor stop tracing
140 func (xs *XdsSupervisor) StopTrace(res interface{}) error {
142 return xs.client.Post(xs._BuildURL("/trace/stop"), cfg, res)
150 func (xs *XdsSupervisor) _BuildURL(url string) string {
151 return url + "?token=HELLO&uuid=magic"
154 // Create HTTP client
155 func (xs *XdsSupervisor) _CreateConnectHTTP() error {
157 // FIXME SEB - Client key not in header but in cookie
158 // temporary workaround: used _BuildURL to append uuid=magic in URL
159 // map[Set-Cookie:[x-afb-uuid-5678=2b185cc3-276b-4097-91fa-d607eaf937e6; Path=/api; Max-Age=32000000; ...
160 //port := strings.Split(xs.BaseURL, ":")[2]
161 //"x-afb-uuid-" + port
163 xs.client, err = common.HTTPNewClient(xs.BaseURL,
164 common.HTTPClientConfig{
165 //HeaderClientKeyName: "Xds-Sid",
166 HeaderAPIKeyName: "token",
168 URLPrefix: "/api/xds",
171 LogPrefix: "XDSSUPERV: ",
172 LogLevel: common.HTTPLogLevelWarning,
175 xs.client.SetLogLevel(xs.Log.Level.String())
178 msg := ": " + err.Error()
179 if strings.Contains(err.Error(), "connection refused") {
180 msg = fmt.Sprintf("(url: %s)", xs.BaseURL)
182 return fmt.Errorf("ERROR: cannot connect to XDS Supervisor %s", msg)
184 if xs.client == nil {
185 return fmt.Errorf("ERROR: cannot connect to XDS Supervisor (null client)")
191 // _Connect Established HTTP and WS connection
192 func (xs *XdsSupervisor) _Connect(reConn bool) error {
195 if err := xs.client.Get(xs._BuildURL("/ping"), &res); err != nil {
205 // Call OnConnect callback
206 if xs.cbOnConnect != nil {
214 // _NotifyState Send event to notify changes
215 func (xs *XdsSupervisor) _NotifyState() {
218 evSts := xaapiv1.ServerCfg{
222 PartialURL: xs.PartialURL,
223 ConnRetry: xs.ConnRetry,
224 Connected: xs.Connected,
226 if err := xs.events.Emit(xaapiv1.EVTServerConfig, evSts, ""); err != nil {
227 xs.Log.Warningf("Cannot notify XdsServer state change: %v", err)