summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorSebastien Douheret <sebastien.douheret@iot.bzh>2017-05-17 11:28:57 +0200
committerSebastien Douheret <sebastien.douheret@iot.bzh>2017-05-17 14:04:32 +0200
commit40a7183f3b4aa32379aa8b4949f5f9c5e32f79f6 (patch)
tree25a98c1b6c6c7b5e186ae3cf0dc11807b2fa088a /lib
parentc07adb807c41a1545a9a0f5bbf40080d86946538 (diff)
Add SDKs support.
Don't allow to install SDKs through XDS for now. Only probe existing SDKs that have been manually installed using scripts/agl/install-agl-sdks.sh. Signed-off-by: Sebastien Douheret <sebastien.douheret@iot.bzh>
Diffstat (limited to 'lib')
-rw-r--r--lib/apiv1/make.go4
-rw-r--r--lib/common/filepath.go15
-rw-r--r--lib/common/httpclient.go36
-rw-r--r--lib/crosssdk/sdk.go47
-rw-r--r--lib/crosssdk/sdks.go39
-rw-r--r--lib/syncthing/st.go46
-rw-r--r--lib/webserver/server.go29
-rw-r--r--lib/xdsconfig/config.go13
-rw-r--r--lib/xdsconfig/fileconfig.go46
9 files changed, 218 insertions, 57 deletions
diff --git a/lib/apiv1/make.go b/lib/apiv1/make.go
index 0f7561f..1e6d937 100644
--- a/lib/apiv1/make.go
+++ b/lib/apiv1/make.go
@@ -138,6 +138,10 @@ func (s *APIService) buildMake(c *gin.Context) {
cmdID := makeCommandID
makeCommandID++
+ /* SEB TODO . /opt/poky-agl/3.90.0+snapshot/environment-setup-aarch64-agl-linux
+ env := os.Environ()
+ */
+
s.log.Debugf("Execute [Cmd ID %d]: %v", cmdID, cmd)
err := common.ExecPipeWs(cmd, sop, sess.ID, cmdID, execTmo, s.log, oCB, eCB)
if err != nil {
diff --git a/lib/common/filepath.go b/lib/common/filepath.go
new file mode 100644
index 0000000..603c2a2
--- /dev/null
+++ b/lib/common/filepath.go
@@ -0,0 +1,15 @@
+package common
+
+import "os"
+
+// Exists returns whether the given file or directory exists or not
+func Exists(path string) bool {
+ _, err := os.Stat(path)
+ if err == nil {
+ return true
+ }
+ if os.IsNotExist(err) {
+ return false
+ }
+ return true
+}
diff --git a/lib/common/httpclient.go b/lib/common/httpclient.go
index 40d7bc2..72132bf 100644
--- a/lib/common/httpclient.go
+++ b/lib/common/httpclient.go
@@ -9,6 +9,8 @@ import (
"io/ioutil"
"net/http"
"strings"
+
+ "github.com/Sirupsen/logrus"
)
type HTTPClient struct {
@@ -20,6 +22,7 @@ type HTTPClient struct {
id string
csrf string
conf HTTPClientConfig
+ logger *logrus.Logger
}
type HTTPClientConfig struct {
@@ -30,6 +33,13 @@ type HTTPClientConfig struct {
CsrfDisable bool
}
+const (
+ logError = 1
+ logWarning = 2
+ logInfo = 3
+ logDebug = 4
+)
+
// Inspired by syncthing/cmd/cli
const insecure = false
@@ -64,6 +74,30 @@ func HTTPNewClient(baseURL string, cfg HTTPClientConfig) (*HTTPClient, error) {
return &client, nil
}
+// SetLogger Define the logger to use
+func (c *HTTPClient) SetLogger(log *logrus.Logger) {
+ c.logger = log
+}
+
+func (c *HTTPClient) log(level int, format string, args ...interface{}) {
+ if c.logger != nil {
+ switch level {
+ case logError:
+ c.logger.Errorf(format, args...)
+ break
+ case logWarning:
+ c.logger.Warningf(format, args...)
+ break
+ case logInfo:
+ c.logger.Infof(format, args...)
+ break
+ default:
+ c.logger.Debugf(format, args...)
+ break
+ }
+ }
+}
+
// Send request to retrieve Client id and/or CSRF token
func (c *HTTPClient) getCidAndCsrf() error {
request, err := http.NewRequest("GET", c.endpoint, nil)
@@ -171,6 +205,8 @@ func (c *HTTPClient) handleRequest(request *http.Request) (*http.Response, error
request.Header.Set("X-CSRF-Token-"+c.id[:5], c.csrf)
}
+ c.log(logDebug, "HTTP %s %v", request.Method, request.URL)
+
response, err := c.httpClient.Do(request)
if err != nil {
return nil, err
diff --git a/lib/crosssdk/sdk.go b/lib/crosssdk/sdk.go
new file mode 100644
index 0000000..2f22f22
--- /dev/null
+++ b/lib/crosssdk/sdk.go
@@ -0,0 +1,47 @@
+package crosssdk
+
+import (
+ "fmt"
+ "path"
+ "path/filepath"
+)
+
+// SDK Define a cross tool chain used to build application
+type SDK struct {
+ Profile string
+ Version string
+ Arch string
+ Path string
+ EnvFile string
+}
+
+// NewCrossSDK creates a new instance of Syncthing
+func NewCrossSDK(path string) (*SDK, error) {
+ // Assume that we have .../<profile>/<version>/<arch>
+ s := SDK{Path: path}
+
+ s.Arch = filepath.Base(path)
+
+ d := filepath.Dir(path)
+ s.Version = filepath.Base(d)
+
+ d = filepath.Dir(d)
+ s.Profile = filepath.Base(d)
+
+ envFile := filepath.Join(path, "environment-setup*")
+ ef, err := filepath.Glob(envFile)
+ if err != nil {
+ return nil, fmt.Errorf("Cannot retrieve environment setup file: %v", err)
+ }
+ if len(ef) != 1 {
+ return nil, fmt.Errorf("No environment setup file found match %s", envFile)
+ }
+ s.EnvFile = ef[0]
+
+ return &s, nil
+}
+
+// GetEnvCmd returns the command to initialized the environment to use a cross SDK
+func (s *SDK) GetEnvCmd() string {
+ return ". " + path.Join(s.Path, s.EnvFile)
+}
diff --git a/lib/crosssdk/sdks.go b/lib/crosssdk/sdks.go
new file mode 100644
index 0000000..435aae6
--- /dev/null
+++ b/lib/crosssdk/sdks.go
@@ -0,0 +1,39 @@
+package crosssdk
+
+import (
+ "path"
+ "path/filepath"
+
+ "github.com/Sirupsen/logrus"
+ "github.com/iotbzh/xds-server/lib/common"
+ "github.com/iotbzh/xds-server/lib/xdsconfig"
+)
+
+// SDKs List of installed SDK
+type SDKs []*SDK
+
+// Init creates a new instance of Syncthing
+func Init(cfg *xdsconfig.Config, log *logrus.Logger) (*SDKs, error) {
+ s := SDKs{}
+
+ // Retrieve installed sdks
+ sdkRD := cfg.FileConf.SdkRootDir
+
+ if common.Exists(sdkRD) {
+
+ // Assume that SDK install tree is <rootdir>/<profile>/<version>/<arch>
+ dirs, err := filepath.Glob(path.Join(sdkRD, "*", "*", "*"))
+ if err != nil {
+ log.Debugf("Error while retrieving SDKs: dir=%s, error=%s", sdkRD, err.Error())
+ return &s, err
+ }
+ for _, d := range dirs {
+ sdk, err := NewCrossSDK(d)
+ if err != nil {
+ log.Debugf("Error while processing SDK dir=%s, err=%s", d, err.Error())
+ }
+ s = append(s, sdk)
+ }
+ }
+ return &s, nil
+}
diff --git a/lib/syncthing/st.go b/lib/syncthing/st.go
index 15cab0d..9452fbd 100644
--- a/lib/syncthing/st.go
+++ b/lib/syncthing/st.go
@@ -27,13 +27,15 @@ type SyncThing struct {
APIKey string
Home string
STCmd *exec.Cmd
+ STICmd *exec.Cmd
// Private fields
- binDir string
- logsDir string
- exitSTChan chan ExitChan
- client *common.HTTPClient
- log *logrus.Logger
+ binDir string
+ logsDir string
+ exitSTChan chan ExitChan
+ exitSTIChan chan ExitChan
+ client *common.HTTPClient
+ log *logrus.Logger
}
// ExitChan Channel used for process exit
@@ -173,6 +175,28 @@ func (s *SyncThing) Start() (*exec.Cmd, error) {
return s.STCmd, err
}
+// StartInotify Starts syncthing-inotify process
+func (s *SyncThing) StartInotify() (*exec.Cmd, error) {
+ var err error
+
+ s.log.Infof(" STI home=%s", s.Home)
+ s.log.Infof(" STI url=%s", s.BaseURL)
+
+ args := []string{
+ "--home=" + s.Home,
+ "-target=" + s.BaseURL,
+ }
+ if s.log.Level == logrus.DebugLevel {
+ args = append(args, "-verbosity=4")
+ }
+
+ env := []string{}
+
+ s.STICmd, err = s.startProc("syncthing-inotify", args, env, &s.exitSTIChan)
+
+ return s.STICmd, err
+}
+
func (s *SyncThing) stopProc(pname string, proc *os.Process, exit chan ExitChan) {
if err := proc.Signal(os.Interrupt); err != nil {
s.log.Infof("Proc interrupt %s error: %s", pname, err.Error())
@@ -199,6 +223,15 @@ func (s *SyncThing) Stop() {
s.STCmd = nil
}
+// StopInotify Stops syncthing process
+func (s *SyncThing) StopInotify() {
+ if s.STICmd == nil {
+ return
+ }
+ s.stopProc("syncthing-inotify", s.STICmd.Process, s.exitSTIChan)
+ s.STICmd = nil
+}
+
// Connect Establish HTTP connection with Syncthing
func (s *SyncThing) Connect() error {
var err error
@@ -217,6 +250,9 @@ func (s *SyncThing) Connect() error {
if s.client == nil {
return fmt.Errorf("ERROR: cannot connect to Syncthing (null client)")
}
+
+ s.client.SetLogger(s.log)
+
return nil
}
diff --git a/lib/webserver/server.go b/lib/webserver/server.go
index 7be157a..40ce948 100644
--- a/lib/webserver/server.go
+++ b/lib/webserver/server.go
@@ -11,13 +11,14 @@ import (
"github.com/gin-gonic/gin"
"github.com/googollee/go-socket.io"
"github.com/iotbzh/xds-server/lib/apiv1"
+ "github.com/iotbzh/xds-server/lib/crosssdk"
"github.com/iotbzh/xds-server/lib/model"
"github.com/iotbzh/xds-server/lib/session"
"github.com/iotbzh/xds-server/lib/xdsconfig"
)
-// ServerService .
-type ServerService struct {
+// Server .
+type Server struct {
router *gin.Engine
api *apiv1.APIService
sIOServer *socketio.Server
@@ -25,6 +26,7 @@ type ServerService struct {
cfg *xdsconfig.Config
sessions *session.Sessions
mfolder *model.Folder
+ sdks *crosssdk.SDKs
log *logrus.Logger
stop chan struct{} // signals intentional stop
}
@@ -32,11 +34,11 @@ type ServerService struct {
const indexFilename = "index.html"
const cookieMaxAge = "3600"
-// NewServer creates an instance of ServerService
-func NewServer(cfg *xdsconfig.Config, mfolder *model.Folder, log *logrus.Logger) *ServerService {
+// New creates an instance of Server
+func New(cfg *xdsconfig.Config, mfolder *model.Folder, sdks *crosssdk.SDKs, log *logrus.Logger) *Server {
// Setup logging for gin router
- if cfg.Log.Level == logrus.DebugLevel {
+ if log.Level == logrus.DebugLevel {
gin.SetMode(gin.DebugMode)
} else {
gin.SetMode(gin.ReleaseMode)
@@ -51,15 +53,16 @@ func NewServer(cfg *xdsconfig.Config, mfolder *model.Folder, log *logrus.Logger)
// Creates gin router
r := gin.New()
- svr := &ServerService{
+ svr := &Server{
router: r,
api: nil,
sIOServer: nil,
webApp: nil,
cfg: cfg,
- log: log,
sessions: nil,
mfolder: mfolder,
+ sdks: sdks,
+ log: log,
stop: make(chan struct{}),
}
@@ -67,7 +70,7 @@ func NewServer(cfg *xdsconfig.Config, mfolder *model.Folder, log *logrus.Logger)
}
// Serve starts a new instance of the Web Server
-func (s *ServerService) Serve() error {
+func (s *Server) Serve() error {
var err error
// Setup middlewares
@@ -128,17 +131,17 @@ func (s *ServerService) Serve() error {
}
// Stop web server
-func (s *ServerService) Stop() {
+func (s *Server) Stop() {
close(s.stop)
}
// serveIndexFile provides initial file (eg. index.html) of webapp
-func (s *ServerService) serveIndexFile(c *gin.Context) {
+func (s *Server) serveIndexFile(c *gin.Context) {
c.HTML(200, indexFilename, gin.H{})
}
// Add details in Header
-func (s *ServerService) middlewareXDSDetails() gin.HandlerFunc {
+func (s *Server) middlewareXDSDetails() gin.HandlerFunc {
return func(c *gin.Context) {
c.Header("XDS-Version", s.cfg.Version)
c.Header("XDS-API-Version", s.cfg.APIVersion)
@@ -147,7 +150,7 @@ func (s *ServerService) middlewareXDSDetails() gin.HandlerFunc {
}
// CORS middleware
-func (s *ServerService) middlewareCORS() gin.HandlerFunc {
+func (s *Server) middlewareCORS() gin.HandlerFunc {
return func(c *gin.Context) {
if c.Request.Method == "OPTIONS" {
@@ -165,7 +168,7 @@ func (s *ServerService) middlewareCORS() gin.HandlerFunc {
}
// socketHandler is the handler for the "main" websocket connection
-func (s *ServerService) socketHandler(c *gin.Context) {
+func (s *Server) socketHandler(c *gin.Context) {
// Retrieve user session
sess := s.sessions.Get(c)
diff --git a/lib/xdsconfig/config.go b/lib/xdsconfig/config.go
index 3f8a91d..465620b 100644
--- a/lib/xdsconfig/config.go
+++ b/lib/xdsconfig/config.go
@@ -7,6 +7,7 @@ import (
"github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
+ "github.com/iotbzh/xds-server/lib/common"
)
// Config parameters (json format) of /config command
@@ -57,14 +58,14 @@ func Init(cliCtx *cli.Context, log *logrus.Logger) (*Config, error) {
}
// Update location of shared dir if needed
- if !dirExists(c.ShareRootDir) {
+ if !common.Exists(c.ShareRootDir) {
if err := os.MkdirAll(c.ShareRootDir, 0770); err != nil {
return nil, fmt.Errorf("No valid shared directory found: %v", err)
}
}
c.Log.Infoln("Share root directory: ", c.ShareRootDir)
- if c.FileConf.LogsDir != "" && !dirExists(c.FileConf.LogsDir) {
+ if c.FileConf.LogsDir != "" && !common.Exists(c.FileConf.LogsDir) {
if err := os.MkdirAll(c.FileConf.LogsDir, 0770); err != nil {
return nil, fmt.Errorf("Cannot create logs dir: %v", err)
}
@@ -73,11 +74,3 @@ func Init(cliCtx *cli.Context, log *logrus.Logger) (*Config, error) {
return &c, nil
}
-
-func dirExists(path string) bool {
- _, err := os.Stat(path)
- if os.IsNotExist(err) {
- return false
- }
- return true
-}
diff --git a/lib/xdsconfig/fileconfig.go b/lib/xdsconfig/fileconfig.go
index 3daf77c..776eb78 100644
--- a/lib/xdsconfig/fileconfig.go
+++ b/lib/xdsconfig/fileconfig.go
@@ -9,6 +9,8 @@ import (
"path/filepath"
"regexp"
"strings"
+
+ "github.com/iotbzh/xds-server/lib/common"
)
type SyncThingConf struct {
@@ -21,6 +23,7 @@ type SyncThingConf struct {
type FileConfig struct {
WebAppDir string `json:"webAppDir"`
ShareRootDir string `json:"shareRootDir"`
+ SdkRootDir string `json:"sdkRootDir"`
HTTPPort string `json:"httpPort"`
SThgConf *SyncThingConf `json:"syncthing"`
LogsDir string `json:"logsDir"`
@@ -78,23 +81,20 @@ func updateConfigFromFile(c *Config, confFile string) error {
c.FileConf = fCfg
// Support environment variables (IOW ${MY_ENV_VAR} syntax) in config.json
- // TODO: better to use reflect package to iterate on fields and be more generic
- var rep string
- if rep, err = resolveEnvVar(fCfg.WebAppDir); err != nil {
- return err
- }
- fCfg.WebAppDir = path.Clean(rep)
-
- if rep, err = resolveEnvVar(fCfg.ShareRootDir); err != nil {
- return err
- }
- fCfg.ShareRootDir = path.Clean(rep)
-
- if rep, err = resolveEnvVar(fCfg.SThgConf.Home); err != nil {
- return err
+ for _, field := range []*string{
+ &fCfg.WebAppDir,
+ &fCfg.ShareRootDir,
+ &fCfg.SdkRootDir,
+ &fCfg.LogsDir,
+ &fCfg.SThgConf.Home} {
+
+ rep, err := resolveEnvVar(*field)
+ if err != nil {
+ return err
+ }
+ *field = path.Clean(rep)
}
- fCfg.SThgConf.Home = path.Clean(rep)
-
+
// Config file settings overwrite default config
if fCfg.WebAppDir != "" {
@@ -105,7 +105,7 @@ func updateConfigFromFile(c *Config, confFile string) error {
// Check first from current directory
for _, rootD := range []string{cwd, exePath} {
ff := path.Join(rootD, c.WebAppDir, "index.html")
- if exists(ff) {
+ if common.Exists(ff) {
c.WebAppDir = path.Join(rootD, c.WebAppDir)
break
}
@@ -140,15 +140,3 @@ func resolveEnvVar(s string) (string, error) {
return res, nil
}
-
-// exists returns whether the given file or directory exists or not
-func exists(path string) bool {
- _, err := os.Stat(path)
- if err == nil {
- return true
- }
- if os.IsNotExist(err) {
- return false
- }
- return true
-}