2 * Copyright (C) 2019 "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 "gerrit.automotivelinux.org/gerrit/src/xds/xds-agent.git/lib/aglafb"
27 common "gerrit.automotivelinux.org/gerrit/src/xds/xds-common.git"
28 uuid "github.com/satori/go.uuid"
32 type XdsLowCollector struct {
39 DefaultPlugins []string
40 DefaultCollectTime int
42 client *common.HTTPClient
44 cbOnConnect OnConnectedXdsAlcCB
47 // OnConnectedXdsAlcCB connect callback
48 type OnConnectedXdsAlcCB func(svr *XdsLowCollector) error
50 // NewXdsLowCollector creates an instance of XdsLowCollector
51 func NewXdsLowCollector(ctx *Context) *XdsLowCollector {
52 return &XdsLowCollector{
54 ID: "XdsAlc-" + uuid.NewV1().String(),
55 BaseURL: ctx.Config.FileConf.ProfileConf.XDSLowCollector.URL,
56 ConnRetry: ctx.Config.FileConf.ProfileConf.XDSLowCollector.ConnRetry,
60 DefaultPlugins: []string{
67 // SEB "systemd_file",
69 DefaultCollectTime: 5,
73 // Connect Establish HTTP connection with XDS Low Collector Dameon
74 func (xs *XdsLowCollector) Connect() error {
82 for retry = xs.ConnRetry; retry > 0; retry-- {
83 if err = xs._CreateConnectHTTP(); err == nil {
86 if retry == xs.ConnRetry {
87 // Notify only on the first conn error
88 // doing that avoid 2 notifs (conn false; conn true) on startup
91 xs.Log.Infof("Establishing connection to XDS Low Collector daemon (retry %d/%d)", retry, xs.ConnRetry)
92 time.Sleep(time.Second)
95 // FIXME: re-use _Reconnect to wait longer in background
96 return fmt.Errorf("Connection to XDS Low Collector daemon failure")
102 // Check HTTP connection and establish WS connection
103 err = xs._Connect(false)
108 // ConnectOn Register a callback on events reception
109 func (xs *XdsLowCollector) ConnectOn(f OnConnectedXdsAlcCB) error {
114 // GetVersion Send Get request to retrieve XDS Low Collector version
115 func (xs *XdsLowCollector) GetVersion(res interface{}) error {
116 // FIXME add suffix URLSuffix in common HTTP client lib instead of _BuildURL
117 return xs.client.Get(xs._BuildURL("/version"), &res)
120 // Init Initialize collector plugins
121 func (xs *XdsLowCollector) Init() error {
124 // Directly send config in order to init and config plugins
126 type alcCfgPluginT struct {
127 Plugin string `json:"plugin"`
128 Config string `json:"config"`
131 cfg := []alcCfgPluginT{}
133 for _, p := range xs.DefaultPlugins {
134 cfg = append(cfg, alcCfgPluginT{
140 res := aglafb.NewAfbReply()
141 xs.Log.Debugf("Low Collector /config %v", cfg)
142 err = xs.client.Post(xs._BuildURL("/config"), cfg, res)
144 if err == nil && !res.Success() {
151 // Start data collection
152 func (xs *XdsLowCollector) Start(time int) error {
155 // TODO - SEB : support start one or multiple plugins
158 time = xs.DefaultCollectTime
161 type alcStartT struct {
162 Plugin string `json:"plugin"`
163 Time int `json:"time"`
166 // TODO SEB : allow to start only 1 plugin
171 for _, p := range xs.DefaultPlugins {
172 cfg = append(cfg, alcStartT{Plugin: p, Time: time})
175 res := aglafb.NewAfbReply()
176 xs.Log.Debugf("Low Collector /start %v", cfg)
177 err = xs.client.Post(xs._BuildURL("/start"), cfg, res)
179 if err == nil && !res.Success() {
183 for _, p := range xs.DefaultPlugins {
184 cfg := alcStartT{Plugin: p, Time: time}
186 res := aglafb.NewAfbReply()
187 xs.Log.Debugf("Low Collector /start %v", cfg)
188 err = xs.client.Post(xs._BuildURL("/start"), cfg, res)
193 return res.GetError()
201 // Stop data collection
202 func (xs *XdsLowCollector) Stop() error {
204 // TODO - SEB : support start one or multiple plugins
206 type alcStopT struct {
207 Plugin []string `json:"plugin"`
211 for _, p := range xs.DefaultPlugins {
212 cfg.Plugin = append(cfg.Plugin, p)
215 res := aglafb.NewAfbReply()
216 xs.Log.Debugf("Low Collector /stop %v", cfg)
217 err := xs.client.Post(xs._BuildURL("/stop"), cfg, res)
219 if err == nil && !res.Success() {
226 // Read a single data of a specific plugin
227 func (xs *XdsLowCollector) Read(data interface{}) error {
228 return fmt.Errorf("No implemented")
236 func (xs *XdsLowCollector) _BuildURL(url string) string {
237 return url + "?token=HELLO&uuid=magic"
240 // Create HTTP client
241 func (xs *XdsLowCollector) _CreateConnectHTTP() error {
243 // FIXME SEB - Client key not in header but in cookie
244 // temporary workaround: used _BuildURL to append uuid=magic in URL
245 // map[Set-Cookie:[x-afb-uuid-5678=2b185cc3-276b-4097-91fa-d607eaf937e6; Path=/api; Max-Age=32000000; ...
246 //port := strings.Split(xs.BaseURL, ":")[2]
247 //"x-afb-uuid-" + port
249 xs.client, err = common.HTTPNewClient(xs.BaseURL,
250 common.HTTPClientConfig{
251 //HeaderClientKeyName: "Xds-Sid",
252 HeaderAPIKeyName: "token",
254 URLPrefix: "/api/alc",
257 LogPrefix: "XDSALC: ",
258 LogLevel: common.HTTPLogLevelWarning,
261 xs.client.SetLogLevel(xs.Log.Level.String())
264 msg := ": " + err.Error()
265 if strings.Contains(err.Error(), "connection refused") {
266 msg = fmt.Sprintf("(url: %s)", xs.BaseURL)
268 return fmt.Errorf("ERROR: cannot connect to XDS Low Collector %s", msg)
270 if xs.client == nil {
271 return fmt.Errorf("ERROR: cannot connect to XDS Low Collector (null client)")
277 // _Connect Established HTTP and WS connection
278 func (xs *XdsLowCollector) _Connect(reConn bool) error {
280 if err := xs.client.Get(xs._BuildURL("/ping"), &res); err != nil {
282 // SEB FIXME tempo Hack
283 time.Sleep(time.Microsecond * 300)
284 if err := xs.client.Get(xs._BuildURL("/ping"), &res); err != nil {
286 // xs.Connected = false
296 // Call OnConnect callback
297 if xs.cbOnConnect != nil {
305 // _NotifyState Send event to notify changes
306 func (xs *XdsLowCollector) _NotifyState() {
309 evSts := xaapiv1.ServerCfg{
313 PartialURL: xs.PartialURL,
314 ConnRetry: xs.ConnRetry,
315 Connected: xs.Connected,
317 if err := xs.events.Emit(xaapiv1.EVTServerConfig, evSts, ""); err != nil {
318 xs.Log.Warningf("Cannot notify XdsServer state change: %v", err)