summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/agent/agent.go11
-rw-r--r--lib/agent/apiv1-supervisor.go114
-rw-r--r--lib/agent/apiv1.go3
-rw-r--r--lib/agent/xdsserver.go2
-rw-r--r--lib/agent/xdssupervior.go230
-rw-r--r--lib/xdsconfig/config.go6
-rw-r--r--lib/xdsconfig/configfile.go10
7 files changed, 370 insertions, 6 deletions
diff --git a/lib/agent/agent.go b/lib/agent/agent.go
index 3aa89a8..58f336c 100644
--- a/lib/agent/agent.go
+++ b/lib/agent/agent.go
@@ -47,11 +47,12 @@ type Context struct {
SThgCmd *exec.Cmd
SThgInotCmd *exec.Cmd
- webServer *WebServer
- xdsServers map[string]*XdsServer
- sessions *Sessions
- events *Events
- projects *Projects
+ webServer *WebServer
+ xdsServers map[string]*XdsServer
+ XdsSupervisor *XdsSupervisor
+ sessions *Sessions
+ events *Events
+ projects *Projects
Exit chan os.Signal
}
diff --git a/lib/agent/apiv1-supervisor.go b/lib/agent/apiv1-supervisor.go
new file mode 100644
index 0000000..a34a913
--- /dev/null
+++ b/lib/agent/apiv1-supervisor.go
@@ -0,0 +1,114 @@
+/*
+ * 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 (
+ "net/http"
+
+ common "gerrit.automotivelinux.org/gerrit/src/xds/xds-common.git/golib"
+ "github.com/gin-gonic/gin"
+)
+
+// getSupervisorTopo : return current AGL daemons topology using supervisor
+func (s *APIService) getSupervisorTopo(c *gin.Context) {
+
+ xdspvr, err := s._initXdsSupervisor()
+ if err != nil {
+ common.APIError(c, err.Error())
+ return
+ }
+
+ var res XdsSuperVReply
+ if err = xdspvr.GetTopo(&res); err != nil {
+ common.APIError(c, err.Error())
+ return
+ }
+
+ if res.Request.Status != "success" {
+ common.APIError(c, res.Request.Info)
+ return
+ }
+
+ c.JSON(http.StatusOK, res.Response)
+}
+
+// startSupervisor : resquest to supervisor to start tracing
+func (s *APIService) startSupervisor(c *gin.Context) {
+
+ xdspvr, err := s._initXdsSupervisor()
+ if err != nil {
+ common.APIError(c, err.Error())
+ return
+ }
+
+ var cfg XdsSuperVTraceConfig
+ if c.BindJSON(&cfg) != nil {
+ common.APIError(c, "Invalid config argument")
+ return
+ }
+ s.Log.Debugf("Start Supervisor cfgArg %v\n", cfg)
+
+ var res XdsSuperVReply
+ if err = xdspvr.StartTrace(cfg, &res); err != nil {
+ common.APIError(c, err.Error())
+ return
+ }
+
+ if res.Request.Status != "success" {
+ common.APIError(c, res.Request.Info)
+ return
+ }
+
+ c.JSON(http.StatusOK, res.Response)
+}
+
+// stopSupervisor : resquest to supervisor to stop tracing
+func (s *APIService) stopSupervisor(c *gin.Context) {
+
+ xdspvr, err := s._initXdsSupervisor()
+ if err != nil {
+ common.APIError(c, err.Error())
+ return
+ }
+
+ var res XdsSuperVReply
+ if err = xdspvr.StopTrace(&res); err != nil {
+ common.APIError(c, err.Error())
+ return
+ }
+
+ if res.Request.Status != "success" {
+ common.APIError(c, res.Request.Info)
+ return
+ }
+
+ c.JSON(http.StatusOK, res.Response)
+}
+
+// _initXdsSupervisor .
+func (s *APIService) _initXdsSupervisor() (*XdsSupervisor, error) {
+
+ if s.XdsSupervisor == nil {
+ xs := NewXdsSupervisor(s.Context)
+ if err := xs.Connect(); err != nil {
+ return nil, err
+ }
+ s.XdsSupervisor = xs
+ }
+ return s.XdsSupervisor, nil
+}
diff --git a/lib/agent/apiv1.go b/lib/agent/apiv1.go
index 97165b3..504558e 100644
--- a/lib/agent/apiv1.go
+++ b/lib/agent/apiv1.go
@@ -67,6 +67,9 @@ func NewAPIV1(ctx *Context) *APIService {
s.apiRouter.POST("/events/register", s.eventsRegister)
s.apiRouter.POST("/events/unregister", s.eventsUnRegister)
+ s.apiRouter.GET("/supervisor/topo", s.getSupervisorTopo)
+ s.apiRouter.POST("/supervisor/trace/start", s.startSupervisor)
+ s.apiRouter.POST("/supervisor/trace/stop", s.stopSupervisor)
return s
}
diff --git a/lib/agent/xdsserver.go b/lib/agent/xdsserver.go
index f74e3ba..24e51d7 100644
--- a/lib/agent/xdsserver.go
+++ b/lib/agent/xdsserver.go
@@ -157,7 +157,7 @@ func (xs *XdsServer) SetLoggerOutput(out io.Writer) {
xs.logOut = out
}
-// GetConfig
+// GetConfig return the current server config
func (xs *XdsServer) GetConfig() xaapiv1.ServerCfg {
return xaapiv1.ServerCfg{
ID: xs.ID,
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)
+ }
+ */
+}
diff --git a/lib/xdsconfig/config.go b/lib/xdsconfig/config.go
index b7bf57b..352ba84 100644
--- a/lib/xdsconfig/config.go
+++ b/lib/xdsconfig/config.go
@@ -91,6 +91,12 @@ func Init(ctx *cli.Context, log *logrus.Logger) (*Config, error) {
SThgConf: &SyncThingConf{
Home: defaultSTHomeDir,
},
+ ProfileConf: ProfileConfT{
+ XDSBinder: XDSBinderConf{
+ URL: "http://localhost:5678",
+ ConnRetry: 10,
+ },
+ },
},
Log: log,
}
diff --git a/lib/xdsconfig/configfile.go b/lib/xdsconfig/configfile.go
index 009517f..1390456 100644
--- a/lib/xdsconfig/configfile.go
+++ b/lib/xdsconfig/configfile.go
@@ -43,6 +43,15 @@ type XDSServerConf struct {
APIPartialURL string `json:"-"`
}
+type XDSBinderConf struct {
+ URL string `json:"url"`
+ ConnRetry int `json:"connRetry"`
+}
+
+type ProfileConfT struct {
+ XDSBinder XDSBinderConf `json:"xdsBinder"`
+}
+
type FileConfig struct {
HTTPPort string `json:"httpPort"`
WebAppDir string `json:"webAppDir"`
@@ -50,6 +59,7 @@ type FileConfig struct {
XDSAPIKey string `json:"xds-apikey"`
ServersConf []XDSServerConf `json:"xdsServers"`
SThgConf *SyncThingConf `json:"syncthing"`
+ ProfileConf ProfileConfT `json:"profileConf"`
}
// readGlobalConfig reads configuration from a config file.