/*
- * Copyright (C) 2017 "IoT.bzh"
+ * Copyright (C) 2017-2018 "IoT.bzh"
* Author Sebastien Douheret <sebastien@iot.bzh>
*
* Licensed under the Apache License, Version 2.0 (the "License");
"strings"
"sync"
- common "github.com/iotbzh/xds-common/golib"
- "github.com/iotbzh/xds-server/lib/xsapiv1"
- uuid "github.com/satori/go.uuid"
+ common "gerrit.automotivelinux.org/gerrit/src/xds/xds-common.git"
+ "gerrit.automotivelinux.org/gerrit/src/xds/xds-server.git/lib/xdsconfig"
+ "gerrit.automotivelinux.org/gerrit/src/xds/xds-server.git/lib/xsapiv1"
)
// SDKs List of installed SDK
type SDKs struct {
*Context
- Sdks map[string]*CrossSDK
+ Sdks map[string]*CrossSDK
+ SdksFamilies map[string]*xsapiv1.SDKFamilyConfig
mutex sync.Mutex
stop chan struct{} // signals intentional stop
}
-// NewSDKs creates a new instance of SDKs
-func NewSDKs(ctx *Context) (*SDKs, error) {
+// SDKsConstructor creates a new instance of SDKs
+func SDKsConstructor(ctx *Context) (*SDKs, error) {
s := SDKs{
- Context: ctx,
- Sdks: make(map[string]*CrossSDK),
- stop: make(chan struct{}),
+ Context: ctx,
+ Sdks: make(map[string]*CrossSDK),
+ SdksFamilies: make(map[string]*xsapiv1.SDKFamilyConfig),
+ stop: make(chan struct{}),
}
scriptsDir := ctx.Config.FileConf.SdkScriptsDir
if !common.Exists(scriptsDir) {
- // allow to use scripts/sdk in debug mode
+ // allow to use scripts/sdk when debugging with vscode(EXEPATH=WORKSPACE)
scriptsDir = filepath.Join(filepath.Dir(ctx.Config.FileConf.SdkScriptsDir), "scripts", "sdks")
if !common.Exists(scriptsDir) {
return &s, fmt.Errorf("scripts directory doesn't exist (%v)", scriptsDir)
return &s, err
}
+ // Update SDK DB on startup by default (can be disable using config file)
+ update := true
+ if s.Config.FileConf.SdkDbUpdate != "startup" {
+ update = false
+ }
+
s.mutex.Lock()
defer s.mutex.Unlock()
// Foreach directories in scripts/sdk
nbInstalled := 0
- monSdksPath := make(map[string]*xsapiv1.SDKFamilyConfig)
for _, d := range dirs {
if !common.IsDir(d) {
continue
}
- sdksList, err := ListCrossSDK(d, s.Log)
+ sdksList, err := ListCrossSDK(d, update, s.Log)
if err != nil {
- return &s, err
+ // allow to use XDS even if error on list
+ s.Log.Errorf("Cannot retrieve SDK list: %v", err)
+ sdksList, _ = ListCrossSDK(d, false, s.Log)
}
s.LogSillyf("'%s' SDKs list: %v", d, sdksList)
for _, sdk := range sdksList {
- cSdk, err := NewCrossSDK(ctx, sdk, d)
+ cSdk, err := s._createNewCrossSDK(sdk, d, false, false)
if err != nil {
s.Log.Debugf("Error while processing SDK sdk=%v\n err=%s", sdk, err.Error())
continue
}
- if _, exist := s.Sdks[cSdk.sdk.ID]; exist {
- s.Log.Warningf("Duplicate SDK ID : %v", cSdk.sdk.ID)
- cSdk.sdk.ID += "_DUPLICATE_" + uuid.NewV1().String()
- }
- s.Sdks[cSdk.sdk.ID] = cSdk
+
if cSdk.sdk.Status == xsapiv1.SdkStatusInstalled {
nbInstalled++
}
- monSdksPath[cSdk.sdk.FamilyConf.RootDir] = &cSdk.sdk.FamilyConf
+ s.SdksFamilies[cSdk.sdk.FamilyConf.FamilyName] = &cSdk.sdk.FamilyConf
}
}
- ctx.Log.Debugf("Cross SDKs: %d defined, %d installed", len(s.Sdks), nbInstalled)
+ ctx.Log.Infof("Cross SDKs: %d defined, %d installed", len(s.Sdks), nbInstalled)
// Start monitor thread to detect new SDKs
- if len(monSdksPath) == 0 {
+ sdksDirs := []string{}
+ for _, sf := range s.SdksFamilies {
+ sdksDirs = append(sdksDirs, sf.RootDir)
+ }
+
+ if len(s.SdksFamilies) == 0 {
s.Log.Warningf("No cross SDKs definition found")
+ /* TODO: used it or cleanup
+ } else {
+ go s.monitorSDKInstallation(sdksDirs)
+ */
}
return &s, nil
}
+// _createNewCrossSDK Private function to create a new Cross SDK
+func (s *SDKs) _createNewCrossSDK(sdk xsapiv1.SDK, scriptDir string, installing bool, force bool) (*CrossSDK, error) {
+
+ cSdk, err := NewCrossSDK(s.Context, sdk, scriptDir)
+ if err != nil {
+ return cSdk, err
+ }
+
+ // Allow to overwrite not installed SDK or when force is set
+ if _, exist := s.Sdks[cSdk.sdk.ID]; exist {
+ if !force && cSdk.sdk.Path != "" && common.Exists(cSdk.sdk.Path) {
+ return cSdk, fmt.Errorf("SDK ID %s already installed in %s", cSdk.sdk.ID, cSdk.sdk.Path)
+ }
+ if !force && cSdk.sdk.Status != xsapiv1.SdkStatusNotInstalled {
+ return cSdk, fmt.Errorf("Duplicate SDK ID %s (use force to overwrite)", cSdk.sdk.ID)
+ }
+ }
+
+ // Sanity check
+ errMsg := "Invalid SDK definition "
+ if installing && cSdk.sdk.Path == "" {
+ return cSdk, fmt.Errorf(errMsg + "(path not set)")
+ }
+ if installing && cSdk.sdk.URL == "" {
+ return cSdk, fmt.Errorf(errMsg + "(url not set)")
+ }
+
+ // Add to list
+ s.Sdks[cSdk.sdk.ID] = cSdk
+
+ return cSdk, err
+}
+
// Stop SDKs management
func (s *SDKs) Stop() {
close(s.stop)
}
// monitorSDKInstallation
-/* TODO: cleanup
-func (s *SDKs) monitorSDKInstallation(monSDKs map[string]*xsapiv1.SDKFamilyConfig) {
+/* TODO: used it or cleanup
+import "github.com/zillode/notify"
+
+func (s *SDKs) monitorSDKInstallation(watchingDirs []string) {
// Set up a watchpoint listening for inotify-specific events
c := make(chan notify.EventInfo, 1)
}
// Add directory watchers
- for dir := range monSDKs {
+ for _, dir := range watchingDirs {
if err := addWatcher(dir); err != nil {
s.Log.Errorln(err.Error())
}
switch ei.Event() {
case notify.Create:
+ sdkDef, err := GetSDKInfo(scriptDir, sdk.URL, "", "", s.Log)
+ if err != nil {
+ s.Log.Warningf("Cannot get sdk info: %v", err)
+ continue
+ }
+ sdk.Path = sdkDef.Path
+ sdk.Path = sdkDef.SetupFile
+
// Emit Folder state change event
- if err := s.events.Emit(xsapiv1.EVTSDKInstall, sdk, ""); err != nil {
+ if err := s.events.Emit(xsapiv1.EVTSDKAdd, sdk, ""); err != nil {
s.Log.Warningf("Cannot notify SDK install: %v", err)
}
} else if len(match) == 0 {
return id, fmt.Errorf("Unknown sdk id")
}
- return id, fmt.Errorf("Multiple sdk IDs found with provided prefix: " + id)
+ return id, fmt.Errorf("Multiple sdk IDs found: %v", match)
}
// Get returns an SDK from id
}
// Install Used to install a new SDK
-func (s *SDKs) Install(id, filepath string, force bool, timeout int, sess *ClientSession) (*xsapiv1.SDK, error) {
- var cSdk *CrossSDK
+func (s *SDKs) Install(id, filepath string, force bool, timeout int, args []string, sess *ClientSession) (*xsapiv1.SDK, error) {
+
+ var sdk *xsapiv1.SDK
+ var err error
+ scriptDir := ""
+ sdkFilename := ""
+
if id != "" && filepath != "" {
return nil, fmt.Errorf("invalid parameter, both id and filepath are set")
}
+
+ s.mutex.Lock()
+ defer s.mutex.Unlock()
+
if id != "" {
- var exist bool
- cSdk, exist = s.Sdks[id]
+ curSdk, exist := s.Sdks[id]
if !exist {
return nil, fmt.Errorf("unknown id")
}
+
+ sdk = &curSdk.sdk
+ scriptDir = sdk.FamilyConf.ScriptsDir
+
+ // Update path when not set
+ if sdk.Path == "" {
+ sdkDef, err := GetSDKInfo(scriptDir, sdk.URL, "", "", sdk.UUID, s.Log)
+ if err != nil || sdkDef.Path == "" {
+ return nil, fmt.Errorf("cannot retrieve sdk path %v", err)
+ }
+ sdk.Path = sdkDef.Path
+ }
+
} else if filepath != "" {
- // TODO check that file is accessible
+ // FIXME support any location and also sharing either by pathmap or Syncthing
+
+ baseDir := path.Join(xdsconfig.WorkspaceRootDir(), "sdks")
+ sdkFilename, _ = common.ResolveEnvVar(path.Join(baseDir, path.Base(filepath)))
+ if !common.Exists(sdkFilename) {
+ return nil, fmt.Errorf("SDK file not accessible, must be in %s", baseDir)
+ }
+
+ for _, sf := range s.SdksFamilies {
+ sdkDef, err := GetSDKInfo(sf.ScriptsDir, "", sdkFilename, "", "", s.Log)
+ if err == nil {
+ // OK, sdk found
+ sdk = &sdkDef
+ scriptDir = sf.ScriptsDir
+ break
+ }
+
+ s.Log.Debugf("GetSDKInfo error: family=%s, sdkFilename=%s, err=%v", sf.FamilyName, path.Base(sdkFilename), err)
+ }
+ if sdk == nil {
+ return nil, fmt.Errorf("Cannot identify SDK family for %s", path.Base(filepath))
+ }
} else {
return nil, fmt.Errorf("invalid parameter, id or filepath must be set")
}
- s.mutex.Lock()
- defer s.mutex.Unlock()
+ cSdk, err := s._createNewCrossSDK(*sdk, scriptDir, true, force)
+ if err != nil {
+ return nil, err
+ }
// Launch script to install
// (note that add event will be generated by monitoring thread)
- if err := cSdk.Install(filepath, force, timeout, sess); err != nil {
+ if err := cSdk.Install(sdkFilename, force, timeout, args, sess); err != nil {
return &cSdk.sdk, err
}
}
// Remove Used to uninstall a SDK
-func (s *SDKs) Remove(id string) (*xsapiv1.SDK, error) {
- s.mutex.Lock()
- defer s.mutex.Unlock()
+func (s *SDKs) Remove(id string, timeout int, sess *ClientSession) (*xsapiv1.SDK, error) {
cSdk, exist := s.Sdks[id]
if !exist {
// Launch script to remove/uninstall
// (note that remove event will be generated by monitoring thread)
- if err := cSdk.Remove(); err != nil {
+ if err := cSdk.Remove(timeout, sess); err != nil {
return &cSdk.sdk, err
}