Improved and fixed local SDK tarball installation.
authorSebastien Douheret <sebastien.douheret@iot.bzh>
Thu, 4 Jan 2018 22:40:25 +0000 (23:40 +0100)
committerSebastien Douheret <sebastien.douheret@iot.bzh>
Thu, 4 Jan 2018 22:40:25 +0000 (23:40 +0100)
Signed-off-by: Sebastien Douheret <sebastien.douheret@iot.bzh>
13 files changed:
.vscode/settings.json
lib/xdsserver/apiv1-sdks.go
lib/xdsserver/folders.go
lib/xdsserver/sdk.go
lib/xdsserver/sdks.go
lib/xsapiv1/sdks.go
scripts/sdks/README.md
scripts/sdks/agl/add
scripts/sdks/agl/db-dump [moved from scripts/sdks/agl/list with 98% similarity]
scripts/sdks/agl/db-update [moved from scripts/sdks/agl/update with 100% similarity]
scripts/sdks/agl/get-family-config [moved from scripts/sdks/agl/get-config with 100% similarity]
scripts/sdks/agl/get-sdk-info [new file with mode: 0755]
scripts/sdks/agl/remove

index 6415d9e..b34fa85 100644 (file)
@@ -30,6 +30,6 @@
         "gdbserver", "golib", "eows", "mfolders", "IFOLDER", "flds", "dflt",
         "stconfig", "reflectme", "franciscocpg", "crosssdk", "urfave", "EXEPATH",
         "conv", "Sillyf", "xsapiv",
-        "EVTSDK"
+        "EVTSDK", "zillode"
     ]
 }
index ba32dc9..e69b82d 100644 (file)
@@ -74,7 +74,7 @@ func (s *APIService) installSdk(c *gin.Context) {
                return
        }
 
-       sdk, err := s.sdks.Install(id, args.Filename, args.Force, args.Timeout, sess)
+       sdk, err := s.sdks.Install(id, args.Filename, args.Force, args.Timeout, args.InstallArgs, sess)
        if err != nil {
                common.APIError(c, err.Error())
                return
index b0c198a..93d2898 100644 (file)
@@ -177,7 +177,7 @@ func (f *Folders) ResolveID(id string) (string, error) {
        } else if len(match) == 0 {
                return id, fmt.Errorf("Unknown id")
        }
-       return id, fmt.Errorf("Multiple IDs found with provided prefix: " + id)
+       return id, fmt.Errorf("Multiple IDs found %v", match)
 }
 
 // Get returns the folder config or nil if not existing
index cafd182..e5d4d7c 100644 (file)
@@ -36,19 +36,21 @@ import (
 
 // Definition of scripts used to managed SDKs
 const (
-       scriptAdd       = "add"
-       scriptGetConfig = "get-config"
-       scriptList      = "list"
-       scriptRemove    = "remove"
-       scriptUpdate    = "update"
+       scriptAdd          = "add"
+       scriptDbDump       = "db-dump"
+       scriptDbUpdate     = "db-update"
+       scriptGetFamConfig = "get-family-config"
+       scriptGetSdkInfo   = "get-sdk-info"
+       scriptRemove       = "remove"
 )
 
 var scriptsAll = []string{
        scriptAdd,
-       scriptGetConfig,
-       scriptList,
+       scriptDbDump,
+       scriptDbUpdate,
+       scriptGetFamConfig,
+       scriptGetSdkInfo,
        scriptRemove,
-       scriptUpdate,
 }
 
 var sdkCmdID = 0
@@ -65,26 +67,55 @@ type CrossSDK struct {
        bufStderr string
 }
 
-// ListCrossSDK List all available and installed SDK  (call "list" script)
+// ListCrossSDK List all available and installed SDK  (call "db-dump" script)
 func ListCrossSDK(scriptDir string, log *logrus.Logger) ([]xsapiv1.SDK, error) {
        sdksList := []xsapiv1.SDK{}
 
        // Retrieve SDKs list and info
-       cmd := exec.Command(path.Join(scriptDir, scriptList))
+       cmd := exec.Command(path.Join(scriptDir, scriptDbDump))
        stdout, err := cmd.CombinedOutput()
        if err != nil {
                return sdksList, fmt.Errorf("Cannot get sdks list: %v", err)
        }
 
        if err = json.Unmarshal(stdout, &sdksList); err != nil {
-               log.Errorf("SDK list script output:\n%v\n", string(stdout))
+               log.Errorf("SDK %s script output:\n%v\n", scriptDbDump, string(stdout))
                return sdksList, fmt.Errorf("Cannot decode sdk list %v", err)
        }
 
        return sdksList, nil
 }
 
-// NewCrossSDK creates a new instance of Syncthing
+// GetSDKInfo Used get-sdk-info script to extract SDK get info from a SDK file/tarball
+func GetSDKInfo(scriptDir, url, filename, md5sum string, log *logrus.Logger) (xsapiv1.SDK, error) {
+       sdk := xsapiv1.SDK{}
+
+       args := []string{}
+       if url != "" {
+               args = append(args, "--url", url)
+       } else if filename != "" {
+               args = append(args, "--file", filename)
+               if md5sum != "" {
+                       args = append(args, "--md5", md5sum)
+               }
+       } else {
+               return sdk, fmt.Errorf("url of filename must be set")
+       }
+
+       cmd := exec.Command(path.Join(scriptDir, scriptGetSdkInfo), args...)
+       stdout, err := cmd.CombinedOutput()
+       if err != nil {
+               return sdk, fmt.Errorf("%v %v", string(stdout), err)
+       }
+
+       if err = json.Unmarshal(stdout, &sdk); err != nil {
+               log.Errorf("SDK %s script output:\n%v\n", scriptGetSdkInfo, string(stdout))
+               return sdk, fmt.Errorf("Cannot decode sdk info %v", err)
+       }
+       return sdk, nil
+}
+
+// NewCrossSDK creates a new instance of CrossSDK
 func NewCrossSDK(ctx *Context, sdk xsapiv1.SDK, scriptDir string) (*CrossSDK, error) {
        s := CrossSDK{
                Context: ctx,
@@ -93,9 +124,9 @@ func NewCrossSDK(ctx *Context, sdk xsapiv1.SDK, scriptDir string) (*CrossSDK, er
        }
 
        // Execute get-config script to retrieve SDK configuration
-       getConfFile := path.Join(scriptDir, scriptGetConfig)
+       getConfFile := path.Join(scriptDir, scriptGetFamConfig)
        if !common.Exists(getConfFile) {
-               return &s, fmt.Errorf("'%s' script file not found in %s", scriptGetConfig, scriptDir)
+               return &s, fmt.Errorf("'%s' script file not found in %s", scriptGetFamConfig, scriptDir)
        }
 
        cmd := exec.Command(getConfFile)
@@ -170,7 +201,7 @@ func NewCrossSDK(ctx *Context, sdk xsapiv1.SDK, scriptDir string) (*CrossSDK, er
 }
 
 // Install a SDK (non blocking command, IOW run in background)
-func (s *CrossSDK) Install(file string, force bool, timeout int, sess *ClientSession) error {
+func (s *CrossSDK) Install(file string, force bool, timeout int, args []string, sess *ClientSession) error {
 
        if s.sdk.Status == xsapiv1.SdkStatusInstalled {
                return fmt.Errorf("already installed")
@@ -190,6 +221,11 @@ func (s *CrossSDK) Install(file string, force bool, timeout int, sess *ClientSes
                cmdArgs = append(cmdArgs, "--force")
        }
 
+       // Append additional args (passthrough arguments)
+       if len(args) > 0 {
+               cmdArgs = append(cmdArgs, args...)
+       }
+
        // Unique command id
        sdkCmdID++
        cmdID := "sdk-install-" + strconv.Itoa(sdkCmdID)
@@ -308,6 +344,21 @@ func (s *CrossSDK) Install(file string, force bool, timeout int, sess *ClientSes
                if code == 0 && exitError == nil {
                        s.sdk.LastError = ""
                        s.sdk.Status = xsapiv1.SdkStatusInstalled
+
+                       // FIXME: better update it using monitoring install dir (inotify)
+                       // (see sdks.go / monitorSDKInstallation )
+                       // Update SetupFile when n
+                       if s.sdk.SetupFile == "" {
+                               sdkDef, err := GetSDKInfo(s.sdk.FamilyConf.ScriptsDir, s.sdk.URL, "", "", s.Log)
+                               if err != nil || sdkDef.SetupFile == "" {
+                                       code = 1
+                                       s.sdk.LastError = "Installation failed (cannot init SetupFile path)"
+                                       s.sdk.Status = xsapiv1.SdkStatusNotInstalled
+                               } else {
+                                       s.sdk.SetupFile = sdkDef.SetupFile
+                               }
+                       }
+
                } else {
                        s.sdk.LastError = "Installation failed (code " + strconv.Itoa(code) +
                                ")"
index 9c10747..b7f7e2e 100644 (file)
@@ -26,13 +26,13 @@ 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
 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
@@ -41,9 +41,10 @@ type SDKs struct {
 // NewSDKs creates a new instance of SDKs
 func NewSDKs(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
@@ -67,7 +68,6 @@ func NewSDKs(ctx *Context) (*SDKs, error) {
 
        // Foreach directories in scripts/sdk
        nbInstalled := 0
-       monSdksPath := make(map[string]*xsapiv1.SDKFamilyConfig)
        for _, d := range dirs {
                if !common.IsDir(d) {
                        continue
@@ -81,42 +81,82 @@ func NewSDKs(ctx *Context) (*SDKs, error) {
                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)
 
        // 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)
@@ -131,7 +171,7 @@ func (s *SDKs) monitorSDKInstallation(monSDKs map[string]*xsapiv1.SDKFamilyConfi
        }
 
        // Add directory watchers
-       for dir := range monSDKs {
+       for _, dir := range watchingDirs {
                if err := addWatcher(dir); err != nil {
                        s.Log.Errorln(err.Error())
                }
@@ -162,6 +202,14 @@ func (s *SDKs) monitorSDKInstallation(monSDKs map[string]*xsapiv1.SDKFamilyConfi
 
                        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 {
                                        s.Log.Warningf("Cannot notify SDK install: %v", err)
@@ -196,7 +244,7 @@ func (s *SDKs) ResolveID(id string) (string, error) {
        } 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
@@ -260,30 +308,73 @@ func (s *SDKs) GetEnvCmd(id string, defaultID string) []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
+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, "", "", 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 := "${HOME}/xds-workspace/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
        }
 
index 3a79c99..44b0940 100644 (file)
@@ -58,10 +58,11 @@ type SDKFamilyConfig struct {
 
 // SDKInstallArgs JSON parameters of POST /sdks or /sdks/abortinstall commands
 type SDKInstallArgs struct {
-       ID       string `json:"id" binding:"required"` // install by ID (must be part of GET /sdks result)
-       Filename string `json:"filename"`              // install by using a file
-       Force    bool   `json:"force"`                 // force SDK install when already existing
-       Timeout  int    `json:"timeout"`               // 1800 == default 30 minutes
+       ID          string   `json:"id"`          // install by ID (must be part of GET /sdks result)
+       Filename    string   `json:"filename"`    // install by using a file
+       Force       bool     `json:"force"`       // force SDK install when already existing
+       Timeout     int      `json:"timeout"`     // 1800 == default 30 minutes
+       InstallArgs []string `json:"installArgs"` // args directly passed to add/install script
 }
 
 // SDKManagementMsg Message send during SDK installation or when installation is complete
index 8b741ec..97bae21 100644 (file)
@@ -5,35 +5,31 @@ To support a new SDK family, you must create a new directory under
 
 Then you must create the following scripts (or executable) :
 
-- `get-config`: returned SDK configuration structure
-- `list`: returned the list of installed SDKs
 - `add`: add a new SDK
+- `db-dump`: returned the list of available SDKs (JSON format)
+- `db-update`: update SDKs database
+- `get-family-config`: returned SDK family configuration structure (JSON format)
+- `get-sdk-info`: extract SDK info (JSON format) from a SDK file/tarball
 - `remove`: remove an existing SDK
 
-## `get-config`
+## `add`
 
-Returned SDK configuration as json format:
+add a new SDK
 
-```json
-{
-    "familyName": "xxx",
-    "description": "bla bla",
-    "rootDir": "/yyy/zzz",
-    "envSetupFilename": "my-envfilename*",
-    "scriptsDir": "scripts_path"
-}
-```
+This script returns code 0 when sdk is successfully installed, else returns an
+error code.
 
-where:
+List of parameters to implement:
 
-- `familyName` : sdk familyName (usually same name used as xxx directory)
-- `rootDir` : root directory where SDK are/will be  installed
-- `envSetupFilename` : sdk files (present in each sdk) that will be sourced to
-  setup sdk environment
+- `-f|--file <filepath>` :  install a SDK using a file
+- `--force`:                force SDK install when a SDK already in the same destination directory
+- `-u|--url <url>` :        download SDK using this URL and then install it
+- `-no-clean` :             don't cleanup temporary files
+- `-h|--help` :             display help
 
-## `list`
+## `db-dump`
 
-Returned the list all SDKs (available and installed)
+Returned the list all SDKs (available and installed) using JSON format.
 
 ```json
 [
@@ -59,18 +55,67 @@ Returned the list all SDKs (available and installed)
 ]
 ```
 
-## `add`
+## `db-update`
 
-add a new SDK
+Update sdk database that may be used by `list` command.
+
+## `get-family-config`
+
+Returned SDK configuration as JSON format:
+
+```json
+{
+    "familyName": "xxx",
+    "description": "bla bla",
+    "rootDir": "/yyy/zzz",
+    "envSetupFilename": "my-envfilename*",
+    "scriptsDir": "scripts_path"
+}
+```
+
+where:
+
+- `familyName` : sdk familyName (usually same name used as xxx directory)
+- `rootDir` : root directory where SDK are/will be  installed
+- `envSetupFilename` : sdk files (present in each sdk) that will be sourced to
+  setup sdk environment
+
+## `get-sdk-info`
+
+Extract SDK info, such as name, version, ... from a SDK tarball file (when
+--file option is set) or from a url (when --url option is set).
+
+This script may also be used to check that a SDK tarball file is correct in
+order to determine for example that the SDK family.
 
 List of parameters to implement:
 
-- `-f|--file <filepath>` :  install a SDK using a file
-- `--force`:                force SDK install when a SDK already in the same destination directory
-- `-u|--url <url>` :        download SDK using this URL and then install it
-- `-no-clean` :             don't cleanup temporary files
+- `-f|--file <filepath>` :  SDK tarball file used to get SDK info
+- `-u|--url <url>` :        url link used to get SDK info
+- `--md5` :                 md5sum value used to validate SDK tarball file
 - `-h|--help` :             display help
 
+This script returns an error (value different from 0) and potential print an
+error message. Else when info are successfully extracted, this script must
+returned the following JSON structure:
+
+```json
+{
+    "name":         "My SDK name",
+    "description":  "A description",
+    "profile":      "profile",
+    "version":      "version",
+    "arch":         "architecture",
+    "path":         "",
+    "url":          "https://website.url.to.download.sdk",
+    "status":       "Not Installed",
+    "date":         "2017-12-25 00:00",
+    "size":         "123 MB",
+    "md5sum":       "123456789",
+    "setupFile":    "path to file to setup SDK environment"
+}
+```
+
 ## `remove`
 
 Remove an existing SDK
index e9a9fd1..7c8321c 100755 (executable)
@@ -17,7 +17,8 @@
 # limitations under the License.
 ###########################################################################
 
-. $(dirname "$0")/_env-init.sh
+SCRIPTS_DIR=$(cd $(dirname "$0") && pwd)
+. ${SCRIPTS_DIR}/_env-init.sh
 
 usage() {
     echo "Usage: $(basename $0) [-h|--help] [-f|--file <sdk-filename>] [-u|--url <https_url>] [--force] [--no-clean]"
@@ -27,10 +28,15 @@ usage() {
 TMPDIR=""
 SDK_FILE=""
 URL=""
+DEBUG_OPT=""
 do_cleanup=true
 do_force=false
 while [ $# -ne 0 ]; do
     case $1 in
+        --debug)
+            set -x
+            DEBUG_OPT="-D"
+            ;;
         -f|--file)
             shift
             SDK_FILE=$1
@@ -79,13 +85,16 @@ if [ "$URL" != "" ]; then
     wget --no-check-certificate "$URL" -O "${SDK_FILE}" || exit 1
 fi
 
-# Retreive default install dir to extract version
-offset=$(grep -na -m1 "^MARKER:$" "${SDK_FILE}" | cut -d':' -f1)
-eval $(head -n $offset "${SDK_FILE}" | grep ^DEFAULT_INSTALL_DIR= )
+# Retreive SDK info
+sdkNfo=$(${SCRIPTS_DIR}/get-sdk-info --file "${SDK_FILE}")
+if [ "$?" != "0" ]; then
+    echo $sdkNfo
+    exit 1
+fi
 
-PROFILE=$(basename $(dirname $DEFAULT_INSTALL_DIR))
-VERSION=$(basename $DEFAULT_INSTALL_DIR)
-ARCH=$(echo "$SDK_FILE" | sed -r 's/.*crosssdk-(.*)-toolchain.*/\1/')
+PROFILE=$(echo "$sdkNfo" |egrep -o '"profile"[^,]*' |cut -d'"' -f4)
+VERSION=$(echo "$sdkNfo" |egrep -o '"version"[^,]*' |cut -d'"' -f4)
+ARCH=$(echo "$sdkNfo" |egrep -o '"arch"[^,]*' |cut -d'"' -f4)
 
 [ "$PROFILE" = "" ] && { echo "PROFILE is not set"; exit 1; }
 [ "$VERSION" = "" ] && { echo "VERSION is not set"; exit 1; }
@@ -100,4 +109,4 @@ rm -rf ${DESTDIR} && mkdir -p ${DESTDIR} || exit 1
 
 # Install sdk
 chmod +x ${SDK_FILE}
-${SDK_FILE} -y -d ${DESTDIR}
+${SDK_FILE} ${DEBUG_OPT} -y -d ${DESTDIR} 2>&1
similarity index 98%
rename from scripts/sdks/agl/list
rename to scripts/sdks/agl/db-dump
index af1d19f..e13a8d8 100755 (executable)
@@ -43,8 +43,7 @@ sdksDBFile = path.join(envMap["SDK_ROOT_DIR"], "sdks_latest.json")
 try {
     // Fetch SDK Json database file when not existing
     if (!fs.existsSync(sdksDBFile)) {
-
-        var data = execSync(path.join(__dirname, 'update ' + sdksDBFile), opts);
+        var data = execSync(path.join(__dirname, 'update-db ' + sdksDBFile), opts);
     }
     // Read SDK Json database file
     var data = fs.readFileSync(sdksDBFile);
diff --git a/scripts/sdks/agl/get-sdk-info b/scripts/sdks/agl/get-sdk-info
new file mode 100755 (executable)
index 0000000..19bf685
--- /dev/null
@@ -0,0 +1,146 @@
+#!/bin/bash
+ ###########################################################################
+# Copyright 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.
+###########################################################################
+
+. $(dirname "$0")/_env-init.sh
+
+usage() {
+    echo "Usage: $(basename $0) [-h|--help] [-f|--file <sdk-filename>] [-u|--url <https_url>] [--md5 <string>]"
+       exit 1
+}
+
+SDK_FILE=""
+MD5VAL=""
+URL=""
+
+while [ $# -ne 0 ]; do
+    case $1 in
+        -f|--file)
+            shift
+            SDK_FILE=$1
+            ;;
+        -h|--help)
+            usage
+            ;;
+        --md5)
+            shift
+            MD5VAL=$1
+            ;;
+        -u|--url)
+            shift
+            URL=$1
+            ;;
+        *)
+            echo "Invalid argument: $1"
+            usage
+            ;;
+    esac
+    shift
+done
+
+if [ "${SDK_FILE}" != "" ]; then
+
+    if [ ! -f "${SDK_FILE}" ]; then
+        echo "sdk file doesn't exist"
+        exit 1
+    fi
+
+    # Criteria to consider that SDK is a valid AGL sdk:
+    #  - shell and binary file type
+    #  - "$MARKER:$" string found
+    #  - md5sum match MD5VAL if MD5VAL is set
+
+    if ! file "${SDK_FILE}" |grep shell |grep -q binary ; then
+        echo "Not expected file type"
+        exit 2
+    fi
+
+    if ! grep -aq -m1 "^MARKER:$" "${SDK_FILE}"; then
+        echo "marker not found"
+        exit 4
+    fi
+
+    if [ "${MD5VAL}" != "" ]; then
+        if ! echo "${MD5VAL} ${SDK_FILE}" | md5sum --status -c -; then
+            echo "md5sum dit not match"
+            exit 5
+        fi
+    fi
+
+    filename=$(basename "${SDK_FILE}")
+    sdkUrl=file://${SDK_FILE}
+    sdkDate=$(stat -c %y "${SDK_FILE}")
+    sdkSize=$(/bin/ls -sh "${SDK_FILE}" |cut -d' ' -f1)
+
+elif [ "${URL}" != "" ]; then
+
+    filename=$(basename "${URL}")
+    sdkUrl=${URL}
+    sdkDate=""
+    sdkSize=""
+
+else
+    echo "--file or --url option must be set"
+    exit 1
+fi
+
+# assume that sdk name follow this format :
+#  _PROFILE_-_COMPILER_ARCH_-_TARGET_-crosssdk-_ARCH_-toolchain-_VERSION_.sh
+# for example:
+#  poky-agl-glibc-x86_64-agl-demo-platform-crosssdk-corei7-64-toolchain-4.0.1.sh
+
+
+if [[ "${filename}" != *"crosssdk"* ]]; then
+    echo "malformed sdk file name"
+    exit 6
+fi
+
+profile=$(echo "${filename}" | sed -r 's/(.*)-glibc.*/\1/')
+version=$(echo "${filename}" | sed -r 's/.*toolchain-(.*).sh/\1/')
+arch=$(echo "${filename}" | sed -r 's/.*crosssdk-(.*)-toolchain.*/\1/')
+installPath=${SDK_ROOT_DIR}/${profile}/${version}/${arch}
+
+[ "${profile}" = "" ] && { echo "profile not set"; exit 7; }
+[ "${version}" = "" ] && { echo "version not set"; exit 8; }
+[ "${arch}" = "" ] && { echo " arch not set"; exit 9; }
+
+status="Not Installed"
+if [ -d ${installPath} ]; then
+    envFile=$(find "${installPath}" -maxdepth 1 -name "${SDK_ENV_SETUP_FILENAME}")
+    [ "${envFile}" != "" ] && status="Installed"
+fi
+
+read -r -d '' res <<- EndOfMessage
+{
+    "name":         "${profile}_${arch}_${version}",
+    "description":  "AGL SDK ${arch} (version ${version})",
+    "profile":      "${profile}",
+    "version":      "${version}",
+    "arch":         "${arch}",
+    "path":         "${installPath}",
+    "url":          "${sdkUrl}",
+    "status":       "${status}",
+    "date":         "${sdkDate}",
+    "size":         "${sdkSize}",
+    "md5sum":       "${MD5VAL}",
+    "setupFile":    "${envFile}"
+}
+EndOfMessage
+
+echo "$res"
+exit 0
index d0f30b1..ec98f72 100755 (executable)
@@ -30,3 +30,8 @@ if [ ! -d "${1}" ]; then
 fi
 
 rm -rf "${1}" && echo "SDK successfully removed."
+
+# Potentially remove parent directory when it is the latest SDK for this version
+rmdir "$(dirname ${1})"
+
+exit 0