aboutsummaryrefslogtreecommitdiffstats
path: root/lib/xdsserver/sdks.go
diff options
context:
space:
mode:
authorSebastien Douheret <sebastien.douheret@iot.bzh>2017-12-22 21:26:40 +0100
committerSebastien Douheret <sebastien.douheret@iot.bzh>2017-12-22 21:29:59 +0100
commitf1c182ede3c4aed0d6196d05b0a64ff93372e755 (patch)
tree2cf95732a06808aac8325bccb5199346b33165a2 /lib/xdsserver/sdks.go
parent285332c351777b74abca638b8b2a2cde3c68edc6 (diff)
Added SDKs management support.
Signed-off-by: Sebastien Douheret <sebastien.douheret@iot.bzh>
Diffstat (limited to 'lib/xdsserver/sdks.go')
-rw-r--r--lib/xdsserver/sdks.go222
1 files changed, 207 insertions, 15 deletions
diff --git a/lib/xdsserver/sdks.go b/lib/xdsserver/sdks.go
index 35aa0ba..38e380d 100644
--- a/lib/xdsserver/sdks.go
+++ b/lib/xdsserver/sdks.go
@@ -26,6 +26,7 @@ import (
common "github.com/iotbzh/xds-common/golib"
"github.com/iotbzh/xds-server/lib/xsapiv1"
+ uuid "github.com/satori/go.uuid"
)
// SDKs List of installed SDK
@@ -34,6 +35,7 @@ type SDKs struct {
Sdks map[string]*CrossSDK
mutex sync.Mutex
+ stop chan struct{} // signals intentional stop
}
// NewSDKs creates a new instance of SDKs
@@ -41,40 +43,140 @@ func NewSDKs(ctx *Context) (*SDKs, error) {
s := SDKs{
Context: ctx,
Sdks: make(map[string]*CrossSDK),
+ stop: make(chan struct{}),
}
- // Retrieve installed sdks
- sdkRD := ctx.Config.FileConf.SdkRootDir
+ scriptsDir := ctx.Config.FileConf.SdkScriptsDir
+ if !common.Exists(scriptsDir) {
+ // allow to use scripts/sdk in debug mode
+ 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)
+ }
+ }
+ s.Log.Infof("SDK scripts dir: %s", scriptsDir)
+
+ dirs, err := filepath.Glob(path.Join(scriptsDir, "*"))
+ if err != nil {
+ s.Log.Errorf("Error while retrieving SDK scripts: dir=%s, error=%s", scriptsDir, err.Error())
+ return &s, err
+ }
- if common.Exists(sdkRD) {
+ s.mutex.Lock()
+ defer s.mutex.Unlock()
- // Assume that SDK install tree is <rootdir>/<profile>/<version>/<arch>
- dirs, err := filepath.Glob(path.Join(sdkRD, "*", "*", "*"))
+ // 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)
if err != nil {
- ctx.Log.Debugf("Error while retrieving SDKs: dir=%s, error=%s", sdkRD, err.Error())
return &s, err
}
- s.mutex.Lock()
- defer s.mutex.Unlock()
+ s.LogSillyf("'%s' SDKs list: %v", d, sdksList)
- for _, d := range dirs {
- if !common.IsDir(d) {
- continue
- }
- cSdk, err := NewCrossSDK(d)
+ for _, sdk := range sdksList {
+ cSdk, err := NewCrossSDK(ctx, sdk, d)
if err != nil {
- ctx.Log.Debugf("Error while processing SDK dir=%s, err=%s", d, err.Error())
+ 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
}
}
- ctx.Log.Debugf("SDKs: %d cross sdks found", len(s.Sdks))
+ ctx.Log.Debugf("Cross SDKs: %d defined, %d installed", len(s.Sdks), nbInstalled)
+
+ // Start monitor thread to detect new SDKs
+ if len(monSdksPath) == 0 {
+ s.Log.Warningf("No cross SDKs definition found")
+ }
return &s, nil
}
+// Stop SDKs management
+func (s *SDKs) Stop() {
+ close(s.stop)
+}
+
+// monitorSDKInstallation
+/* TODO: cleanup
+func (s *SDKs) monitorSDKInstallation(monSDKs map[string]*xsapiv1.SDKFamilyConfig) {
+
+ // Set up a watchpoint listening for inotify-specific events
+ c := make(chan notify.EventInfo, 1)
+
+ addWatcher := func(rootDir string) error {
+ s.Log.Debugf("SDK Register watcher: rootDir=%s", rootDir)
+
+ if err := notify.Watch(rootDir+"/...", c, notify.Create, notify.Remove); err != nil {
+ return fmt.Errorf("SDK monitor: rootDir=%v err=%v", rootDir, err)
+ }
+ return nil
+ }
+
+ // Add directory watchers
+ for dir := range monSDKs {
+ if err := addWatcher(dir); err != nil {
+ s.Log.Errorln(err.Error())
+ }
+ }
+
+ // Wait inotify or stop events
+ for {
+ select {
+ case <-s.stop:
+ s.Log.Debugln("Stop monitorSDKInstallation")
+ notify.Stop(c)
+ return
+ case ei := <-c:
+ s.LogSillyf("monitorSDKInstallation SDKs event %v, path %v\n", ei.Event(), ei.Path())
+
+ // Filter out all event that doesn't match environment file
+ if !strings.Contains(ei.Path(), "environment-setup-") {
+ continue
+ }
+ dir := path.Dir(ei.Path())
+
+ sdk, err := s.GetByPath(dir)
+ if err != nil {
+ s.Log.Warningf("Cannot find SDK path to notify creation")
+ s.LogSillyf("event: %v", ei.Event())
+ continue
+ }
+
+ switch ei.Event() {
+ case notify.Create:
+ // Emit Folder state change event
+ if err := s.events.Emit(xsapiv1.EVTSDKInstall, sdk, ""); err != nil {
+ s.Log.Warningf("Cannot notify SDK install: %v", err)
+ }
+
+ case notify.Remove, notify.InMovedFrom:
+ // Emit Folder state change event
+ if err := s.events.Emit(xsapiv1.EVTSDKRemove, sdk, ""); err != nil {
+ s.Log.Warningf("Cannot notify SDK remove: %v", err)
+ }
+ }
+ }
+ }
+}
+*/
+
// ResolveID Complete an SDK ID (helper for user that can use partial ID value)
func (s *SDKs) ResolveID(id string) (string, error) {
if id == "" {
@@ -108,6 +210,19 @@ func (s *SDKs) Get(id string) *xsapiv1.SDK {
return (*sc).Get()
}
+// GetByPath Find a SDK from path
+func (s *SDKs) GetByPath(path string) (*xsapiv1.SDK, error) {
+ if path == "" {
+ return nil, fmt.Errorf("can't found sdk (empty path)")
+ }
+ for _, ss := range s.Sdks {
+ if ss.sdk.Path == path {
+ return ss.Get(), nil
+ }
+ }
+ return nil, fmt.Errorf("not found")
+}
+
// GetAll returns all existing SDKs
func (s *SDKs) GetAll() []xsapiv1.SDK {
s.mutex.Lock()
@@ -142,3 +257,80 @@ func (s *SDKs) GetEnvCmd(id string, defaultID string) []string {
// Return default env that may be empty
return []string{}
}
+
+// 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
+ if id != "" && filepath != "" {
+ return nil, fmt.Errorf("invalid parameter, both id and filepath are set")
+ }
+ if id != "" {
+ var exist bool
+ cSdk, exist = s.Sdks[id]
+ if !exist {
+ return nil, fmt.Errorf("unknown id")
+ }
+ } else if filepath != "" {
+ // TODO check that file is accessible
+
+ } else {
+ return nil, fmt.Errorf("invalid parameter, id or filepath must be set")
+ }
+
+ s.mutex.Lock()
+ defer s.mutex.Unlock()
+
+ // Launch script to install
+ // (note that add event will be generated by monitoring thread)
+ if err := cSdk.Install(filepath, force, timeout, sess); err != nil {
+ return &cSdk.sdk, err
+ }
+
+ return &cSdk.sdk, nil
+}
+
+// AbortInstall Used to abort SDK installation
+func (s *SDKs) AbortInstall(id string, timeout int) (*xsapiv1.SDK, error) {
+
+ if id == "" {
+ return nil, fmt.Errorf("invalid parameter")
+ }
+ cSdk, exist := s.Sdks[id]
+ if !exist {
+ return nil, fmt.Errorf("unknown id")
+ }
+
+ s.mutex.Lock()
+ defer s.mutex.Unlock()
+
+ err := cSdk.AbortInstallRemove(timeout)
+
+ 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()
+
+ cSdk, exist := s.Sdks[id]
+ if !exist {
+ return nil, fmt.Errorf("unknown id")
+ }
+
+ s.mutex.Lock()
+ defer s.mutex.Unlock()
+
+ // Launch script to remove/uninstall
+ // (note that remove event will be generated by monitoring thread)
+ if err := cSdk.Remove(); err != nil {
+ return &cSdk.sdk, err
+ }
+
+ sdk := cSdk.sdk
+
+ // Don't delete it from s.Sdks
+ // (always keep sdk reference to allow for example re-install)
+
+ return &sdk, nil
+}