diff options
Diffstat (limited to 'lib/agent/xdssupervior.go')
-rw-r--r-- | lib/agent/xdssupervior.go | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/lib/agent/xdssupervior.go b/lib/agent/xdssupervior.go new file mode 100644 index 0000000..bbe2500 --- /dev/null +++ b/lib/agent/xdssupervior.go @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2017-2018 "IoT.bzh" + * Author Sebastien Douheret <sebastien@iot.bzh> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package agent + +import ( + "fmt" + "io" + "strings" + "time" + + common "gerrit.automotivelinux.org/gerrit/src/xds/xds-common.git/golib" + uuid "github.com/satori/go.uuid" +) + +// XdsSupervisor . +type XdsSupervisor struct { + *Context + ID string + BaseURL string + ConnRetry int + Connected bool + Disabled bool + + // Private fields + client *common.HTTPClient + logOut io.Writer + cbOnConnect OnConnectedXdsSupervCB +} + +// XdsSuperVRequest Resquest field of a reply +type XdsSuperVRequest struct { + Status string `json:"status"` + Info string `json:"info"` +} + +// XdsSuperVReply Reply structure of XDS Supervision Daemon +type XdsSuperVReply struct { + JType string `json:"jtype"` + Request XdsSuperVRequest `json:"request"` + Response interface{} `json:"response"` +} + +// XdsSuperVTraceConfig +type XdsSuperVTraceConfig struct { + Pid int `json:"pid"` + Pids []int `json:"pids"` + WsName string `json:"ws"` +} + +// OnConnectedXdsSupervCB connect callback +type OnConnectedXdsSupervCB func(svr *XdsSupervisor) error + +// NewXdsSupervisor creates an instance of XdsSupervisor +func NewXdsSupervisor(ctx *Context) *XdsSupervisor { + return &XdsSupervisor{ + Context: ctx, + ID: "XdsSupervisor-" + uuid.NewV1().String(), + BaseURL: ctx.Config.FileConf.ProfileConf.XDSBinder.URL, + ConnRetry: ctx.Config.FileConf.ProfileConf.XDSBinder.ConnRetry, + Connected: false, + Disabled: false, + + logOut: ctx.Log.Out, + } +} + +// Connect Establish HTTP connection with XDS Supervisor Dameon +func (xs *XdsSupervisor) Connect() error { + var err error + var retry int + + xs.Disabled = false + xs.Connected = false + + err = nil + for retry = xs.ConnRetry; retry > 0; retry-- { + if err = xs._CreateConnectHTTP(); err == nil { + break + } + if retry == xs.ConnRetry { + // Notify only on the first conn error + // doing that avoid 2 notifs (conn false; conn true) on startup + xs._NotifyState() + } + xs.Log.Infof("Establishing connection to XDS Supervisor daemon (retry %d/%d)", retry, xs.ConnRetry) + time.Sleep(time.Second) + } + if retry == 0 { + // FIXME: re-use _Reconnect to wait longer in background + return fmt.Errorf("Connection to XDS Supervisor daemon failure") + } + if err != nil { + return err + } + + // Check HTTP connection and establish WS connection + err = xs._Connect(false) + + return err +} + +// ConnectOn Register a callback on events reception +func (xs *XdsSupervisor) ConnectOn(f OnConnectedXdsSupervCB) error { + xs.cbOnConnect = f + return nil +} + +// GetVersion Send Get request to retrieve XDS Supervision version +func (xs *XdsSupervisor) GetVersion(res interface{}) error { + // FIXME add suffix URLSuffix in common HTTP client lib instead of _BuildURL + return xs.client.Get(xs._BuildURL("/version"), &res) +} + +// GetTopo Send Get request to retrieve Services/Daemons topology +func (xs *XdsSupervisor) GetTopo(res interface{}) error { + return xs.client.Get(xs._BuildURL("/list"), &res) +} + +// StartTrace Send Supervisor config and start tracing +func (xs *XdsSupervisor) StartTrace(cfg XdsSuperVTraceConfig, res interface{}) error { + return xs.client.Post(xs._BuildURL("/trace/start"), cfg, &res) +} + +// StopTrace Send Supervisor stop tracing +func (xs *XdsSupervisor) StopTrace(res interface{}) error { + var cfg interface{} + return xs.client.Post(xs._BuildURL("/trace/stop"), cfg, res) +} + +/*** +** Private functions +***/ + +// _BuildURL . +func (xs *XdsSupervisor) _BuildURL(url string) string { + return url + "?token=HELLO&uuid=magic" +} + +// Create HTTP client +func (xs *XdsSupervisor) _CreateConnectHTTP() error { + var err error + // FIXME SEB - Client key not in header but in cookie + // temporary workaround: used _BuildURL to append uuid=magic in URL + // map[Set-Cookie:[x-afb-uuid-5678=2b185cc3-276b-4097-91fa-d607eaf937e6; Path=/api; Max-Age=32000000; ... + //port := strings.Split(xs.BaseURL, ":")[2] + //"x-afb-uuid-" + port + + xs.client, err = common.HTTPNewClient(xs.BaseURL, + common.HTTPClientConfig{ + //HeaderClientKeyName: "Xds-Sid", + HeaderAPIKeyName: "token", + Apikey: "HELLO", + URLPrefix: "/api/xds", + CsrfDisable: true, + LogOut: xs.logOut, + LogPrefix: "XDSSUPERV: ", + LogLevel: common.HTTPLogLevelWarning, + }) + + xs.client.SetLogLevel(xs.Log.Level.String()) + + if err != nil { + msg := ": " + err.Error() + if strings.Contains(err.Error(), "connection refused") { + msg = fmt.Sprintf("(url: %s)", xs.BaseURL) + } + return fmt.Errorf("ERROR: cannot connect to XDS Supervisor %s", msg) + } + if xs.client == nil { + return fmt.Errorf("ERROR: cannot connect to XDS Supervisor (null client)") + } + + return nil +} + +// _Connect Established HTTP and WS connection +func (xs *XdsSupervisor) _Connect(reConn bool) error { + + var res interface{} + if err := xs.client.Get(xs._BuildURL("/ping"), &res); err != nil { + xs.Connected = false + if !reConn { + xs._NotifyState() + } + return err + } + + xs.Connected = true + + // Call OnConnect callback + if xs.cbOnConnect != nil { + xs.cbOnConnect(xs) + } + + xs._NotifyState() + return nil +} + +// _NotifyState Send event to notify changes +func (xs *XdsSupervisor) _NotifyState() { + + /* TODO + evSts := xaapiv1.ServerCfg{ + ID: xs.ID, + URL: xs.BaseURL, + APIURL: xs.APIURL, + PartialURL: xs.PartialURL, + ConnRetry: xs.ConnRetry, + Connected: xs.Connected, + } + if err := xs.events.Emit(xaapiv1.EVTServerConfig, evSts, ""); err != nil { + xs.Log.Warningf("Cannot notify XdsServer state change: %v", err) + } + */ +} |