Fix qemu sdk detection
[src/xds/xds-server.git] / scripts / sdks / agl / db-dump
index aa8b30d..e5ee8c8 100755 (executable)
-#! /usr/bin/env nodejs
-
-/**************************************************************************
- * Copyright 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.
- **************************************************************************/
-
-const fs = require('fs');
-const process = require('process');
-const execSync = require('child_process').execSync;
-const path = require('path');
-
-
-// Only used for debug purpose
-const DEBUG = false || (process.argv.length > 2 && process.argv[2] == '-debug');
-dbgPrint = function () {
-    if (DEBUG) console.log.apply(console, arguments);
-}
-// Get env vars
-var envMap = {};
-envData = execSync(path.join(__dirname, '_env-init.sh -print'));
-envData.toString().split('\n').forEach(e => envMap[e.split('=')[0]] = e.split('=')[1]);
-const opts = {
-    cwd: __dirname,
-    env: envMap
-};
-
-// Get list of available SDKs
-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, 'db-update ' + sdksDBFile), opts);
-    }
-    // Read SDK Json database file
-    var data = fs.readFileSync(sdksDBFile);
-    var sdks = JSON.parse(data);
-
-    // Force some default fields value
-    sdks.forEach(sdk => {
-        sdk.status = 'Not Installed';
-    });
-} catch (err) {
-    dbgPrint('ERROR: ', err);
-    process.exit(-1)
-}
-
-// Get list of installed SDKs
-try {
-    const cmd = 'find "${SDK_ROOT_DIR}" -maxdepth 4 -name "${SDK_ENV_SETUP_FILENAME}"';
-    var data = execSync(cmd, opts);
-    data.toString().split('\n').forEach(envFile => {
-        if (envFile == '') return;
-
-        dbgPrint('Processing ', envFile);
-        const profile = envFile.split('/')[3];
-        const version = envFile.split('/')[4];
-        const arch = envFile.split('/')[5];
-        const dir = path.dirname(envFile);
-        if (profile == '' || version == '' || arch == '' || dir == '') {
-            return;
-        }
+#!/usr/bin/python3
+#
+# /**************************************************************************
+# * Copyright 2017-2018 IoT.bzh
+# *
+# * author: Romain Forlot <romain.forlot@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.
+# **************************************************************************/
 
-        sdkDate = ''
-        versionFile = path.join(path.dirname(envFile), 'version-*')
-        try {
-            cmdVer = "[ -f " + versionFile + " ] && grep Timestamp " + versionFile + " |cut -d' ' -f2"
-            var data = execSync(cmdVer);
-        } catch (err) {
-            dbgPrint('IGNORING SDK ', dir);
-            dbgPrint(err.toString());
-            if (DEBUG) {
-                process.exit(-1);
-            } else {
-                return;
-            }
-        }
-        d = data.toString()
-        if (d != "") {
-            sdkDate = d.substring(0, 4) + "-" + d.substring(4, 6) + "-" + d.substring(6, 8)
-            sdkDate += " " + d.substring(8, 10) + ":" + d.substring(10, 12)
-        }
+import os
+import sys
+import json
+import logging
+import inspect
+import fnmatch
+import argparse
+import subprocess
+import re
 
-        var found = false;
-        sdks.forEach(sdk => {
-            // Update sdk with local info when found
-            if (profile == sdk.profile && version == sdk.version && arch == sdk.arch) {
-                found = true;
-                dbgPrint(" OK found, updating...");
-                sdk.path = dir;
-                sdk.status = 'Installed';
-                sdk.data = sdkDate;
-                sdk.setupFile = envFile;
-                return
-            }
-        });
-        if (found == false) {
-            dbgPrint(" NOT found in database, adding it...");
-            sdks.push({
-                name: profile + '-' + arch + '-' + version,
-                description: 'AGL SDK ' + arch + ' (version ' + version + ')',
-                profile: profile,
-                version: version,
-                arch: arch,
-                path: dir,
-                url: "",
-                status: "Installed",
-                date: sdkDate,
-                size: "",
-                md5sum: "",
-                setupFile: envFile
-            });
-        }
-    });
+PARSER = argparse.ArgumentParser(
+    description='Lists available and installed SDKs')
+PARSER.add_argument('-debug', dest='debug', action='store_true',
+                    help='Output debug log messages')
+
+ARGS = PARSER.parse_args()
+
+if ARGS.debug:
+    logging.basicConfig(level=logging.DEBUG,
+                        format='%(asctime)s:%(levelname)s: %(message)s')
+else:
+    logging.basicConfig(level=logging.INFO,
+                        format='%(asctime)s:%(levelname)s: %(message)s')
+
+SCRIPT_PATH = os.path.dirname(os.path.abspath(
+    inspect.getfile(inspect.currentframe())))
+
+ENV = subprocess.check_output(
+    [os.path.join(SCRIPT_PATH, './_env-init.sh'), '-print']).splitlines()
+
+SDK_ROOT_DIR = None
+for elt in ENV:
+    # only match what defines a variable
+    z = re.match(r"^(\w+)=([^']*)$", elt.decode())
+    if z:
+        k = z.group(1)
+        v = z.group(2)
+        if k == 'SDK_ROOT_DIR':
+            SDK_ROOT_DIR = v.rstrip('/')
+        elif k == 'SDK_ENV_SETUP_FILENAME':
+            SDK_ENV_SETUP_FILENAME = v
+
+if SDK_ROOT_DIR is None:
+    logging.error('No SDK_ROOT_DIR environment variable found.')
+    exit(1)
+elif SDK_ENV_SETUP_FILENAME is None:
+    SDK_ENV_SETUP_FILENAME = 'environment-setup*'
+
+# Get list of available SDKs
+SDK_DB_FILEPATH = os.path.join(SDK_ROOT_DIR, 'sdks_latest.json')
+
+if not os.path.exists(SDK_DB_FILEPATH):
+    DB_UPDATE_FILEPATH = os.path.join(SCRIPT_PATH, 'db-update')
+    os.system(DB_UPDATE_FILEPATH + ' ' + SDK_DB_FILEPATH)
 
-} catch (err) {
-    dbgPrint('ERROR: ', err);
-    process.exit(-1)
-}
+SDK_DB_JSON = json.load(open(SDK_DB_FILEPATH, 'r'))
 
-// Print result
-console.log(JSON.stringify(sdks));
+for one_sdk in SDK_DB_JSON:
+    one_sdk['status'] = 'Not Installed'
+    one_sdk['uuid'] = ''
+
+INSTALLED_SDK = []
+for root, dirs, files in os.walk(SDK_ROOT_DIR):
+    depth = root[len(SDK_ROOT_DIR) + len(os.path.sep):].count(os.path.sep)
+    # Limit the walking depth of processed directories
+    if depth >= 4:
+        dirs[:] = []
+    # Only process SDK dir matching profile/version/arch or
+    # profile/version/arch/tag
+    elif depth != 2 and depth != 3:
+        continue
+
+    # Only consider SDK as valid if environment-setup and version files and
+    # sysroots directory can be found
+    EF, VF, SR = '', '', ''
+    for one_dir in dirs:
+        if fnmatch.fnmatch(one_dir, 'sysroots'):
+            SR = os.path.join(root, one_dir)
+
+    for one_file in files:
+        if fnmatch.fnmatch(one_file, SDK_ENV_SETUP_FILENAME):
+            EF = os.path.join(root, one_file)
+        elif fnmatch.fnmatch(one_file, 'version-*'):
+            VF = os.path.join(root, one_file)
+    if EF != '' and VF != '' and SR != '':
+        logging.debug('Adding installed SDK ' + root)
+        INSTALLED_SDK.append(
+            {'ENV_FILE': EF, 'VERSION_FILE': VF, 'SYSROOTS': SR})
+    elif (EF == '' and VF != '') or (EF != '' and VF == ''):
+        logging.debug(
+            'WARNING SDK ignored : root=%s, EnvFile=%s, VersionFile=%s, sysroots=%s', root, EF, VF, SR)
+
+for one_sdk in INSTALLED_SDK:
+    logging.debug('Processing %s', one_sdk['ENV_FILE'])
+    envFile = one_sdk['ENV_FILE'].split(SDK_ROOT_DIR+'/')[1]
+    PROFILE = envFile.split('/')[0]
+    VERSION = envFile.split('/')[1]
+    ARCH = envFile.split('/')[2]
+    # and specific case for qemu where arch is not the same (qemux86-64 vs corei7-64)
+    if ARCH == 'corei7-64':
+        # Use /etc/rpm/platform to distinguish qemux86-64 from corei7-64 architecture
+        grepQemu = subprocess.call(['grep', '-q', 'qemux86', os.path.join(
+            one_sdk['SYSROOTS'], 'corei7-64-agl-linux', 'etc', 'rpm', 'platform')])
+        if grepQemu == 0:
+            ARCH = 'qemux86-64'
+
+    DIR = os.path.dirname(one_sdk['ENV_FILE'])
+    if PROFILE == '' or VERSION == '' or ARCH == '' or DIR == '':
+        logging.debug('Path not compliant, skipping')
+        continue
+
+    UUID = os.path.basename(os.path.normpath(DIR))
+
+    SDK_DATE = ''
+    for line in open(one_sdk['VERSION_FILE']).readlines():
+        if line.startswith('Timestamp'):
+            D = line.split(':')[1]
+            if D:
+                D = D.strip()
+                SDK_DATE = '{}-{}-{} {}:{}'.format(
+                    D[0:4], D[4:6], D[6:8], D[8:10], D[10:12])
+                logging.debug('Found date: %s', SDK_DATE)
+
+    # Check if installed SDKs match the ones listed in json file
+    found = False
+    for sdk in SDK_DB_JSON:
+        # Matching based on profile + version + arch fields
+        if sdk['profile'] == PROFILE and sdk['version'] == VERSION and sdk['arch'] == ARCH:
+            if sdk['status'] == 'Installed':
+                continue
+            # Additional verification based on url used to generate UUID (see also same logic in add script)
+            if sdk['url'] != '':
+                try:
+                    ps = subprocess.Popen(
+                        ('echo', sdk['url']), stdout=subprocess.PIPE)
+                    uuid_md5 = subprocess.check_output(
+                        ('md5sum'), stdin=ps.stdout)
+                    ps.wait()
+                    if str(uuid_md5).split(' ')[0][2:] != UUID:
+                        continue
+                except:
+                    e = sys.exc_info()[0]
+                    logging.error('Error while checking UUID: ' % e)
+
+            found = True
+            sdk['status'] = 'Installed'
+            sdk['date'] = SDK_DATE
+            sdk['setupFile'] = one_sdk['ENV_FILE']
+            sdk['path'] = DIR
+            sdk['uuid'] = UUID
+            break
+
+    if not found:
+        logging.debug('Not found in database, add: ' +
+                      PROFILE + '-' + ARCH + '-' + VERSION)
+        NEW_SDK = {
+            'name': PROFILE + '-' + ARCH + '-' + VERSION,
+            'uuid': UUID,
+            'description': 'AGL SDK ' + ARCH + ' (version ' + VERSION + ')',
+            'profile': PROFILE,
+            'version': VERSION,
+            'arch': ARCH,
+            'path': DIR,
+            'url': '',
+            'status': 'Installed',
+            'date': SDK_DATE,
+            'size': '',
+            'md5sum': '',
+            'setupFile': one_sdk['ENV_FILE']
+        }
+        SDK_DB_JSON.append(NEW_SDK)
 
-process.exit(0)
+print(json.dumps(SDK_DB_JSON))