Prevent db-dump failure when sdk is not valid
[src/xds/xds-server.git] / scripts / sdks / agl / db-dump
1 #!/usr/bin/python3
2 #
3 # /**************************************************************************
4 # * Copyright 2017-2018 IoT.bzh
5 # *
6 # * author: Romain Forlot <romain.forlot@iot.bzh>
7 # *
8 # * Licensed under the Apache License, Version 2.0 (the "License");
9 # * you may not use this file except in compliance with the License.
10 # * You may obtain a copy of the License at
11 # *
12 # *     http://www.apache.org/licenses/LICENSE-2.0
13 # *
14 # * Unless required by applicable law or agreed to in writing, software
15 # * distributed under the License is distributed on an "AS IS" BASIS,
16 # * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 # * See the License for the specific language governing permissions and
18 # * limitations under the License.
19 # **************************************************************************/
20
21 import os
22 import sys
23 import json
24 import logging
25 import inspect
26 import fnmatch
27 import argparse
28 import subprocess
29 from subprocess import DEVNULL
30 import re
31
32 PARSER = argparse.ArgumentParser(
33     description='Lists available and installed SDKs')
34 PARSER.add_argument('-debug', dest='debug', action='store_true',
35                     help='Output debug log messages')
36
37 ARGS = PARSER.parse_args()
38
39 if ARGS.debug:
40     logging.basicConfig(level=logging.DEBUG,
41                         format='%(asctime)s:%(levelname)s: %(message)s')
42 else:
43     logging.basicConfig(level=logging.INFO,
44                         format='%(asctime)s:%(levelname)s: %(message)s')
45
46 SCRIPT_PATH = os.path.dirname(os.path.abspath(
47     inspect.getfile(inspect.currentframe())))
48
49 ENV = subprocess.check_output(
50     [os.path.join(SCRIPT_PATH, './_env-init.sh'), '-print']).splitlines()
51
52 SDK_ROOT_DIR = None
53 for elt in ENV:
54     # only match what defines a variable
55     z = re.match(r"^(\w+)=([^']*)$", elt.decode())
56     if z:
57         k = z.group(1)
58         v = z.group(2)
59         if k == 'SDK_ROOT_DIR':
60             SDK_ROOT_DIR = v.rstrip('/')
61         elif k == 'SDK_ENV_SETUP_FILENAME':
62             SDK_ENV_SETUP_FILENAME = v
63
64 if SDK_ROOT_DIR is None:
65     logging.error('No SDK_ROOT_DIR environment variable found.')
66     exit(1)
67 elif SDK_ENV_SETUP_FILENAME is None:
68     SDK_ENV_SETUP_FILENAME = 'environment-setup*'
69
70 # Get list of available SDKs
71 SDK_DB_FILEPATH = os.path.join(SDK_ROOT_DIR, 'sdks_latest.json')
72
73 if not os.path.exists(SDK_DB_FILEPATH):
74     DB_UPDATE_FILEPATH = os.path.join(SCRIPT_PATH, 'db-update')
75     os.system(DB_UPDATE_FILEPATH + ' ' + SDK_DB_FILEPATH)
76
77 SDK_DB_JSON = json.load(open(SDK_DB_FILEPATH, 'r'))
78
79 for one_sdk in SDK_DB_JSON:
80     one_sdk['status'] = 'Not Installed'
81     one_sdk['uuid'] = ''
82
83 INSTALLED_SDK = []
84 for root, dirs, files in os.walk(SDK_ROOT_DIR):
85     depth = root[len(SDK_ROOT_DIR) + len(os.path.sep):].count(os.path.sep)
86     # Limit the walking depth of processed directories
87     if depth >= 4:
88         dirs[:] = []
89     # Only process SDK dir matching profile/version/arch or
90     # profile/version/arch/tag
91     elif depth != 2 and depth != 3:
92         continue
93
94     # Only consider SDK as valid if environment-setup and version files and
95     # sysroots directory can be found
96     EF, VF, SR = '', '', ''
97     for one_dir in dirs:
98         if fnmatch.fnmatch(one_dir, 'sysroots'):
99             SR = os.path.join(root, one_dir)
100
101     for one_file in files:
102         if fnmatch.fnmatch(one_file, SDK_ENV_SETUP_FILENAME):
103             EF = os.path.join(root, one_file)
104         elif fnmatch.fnmatch(one_file, 'version-*'):
105             VF = os.path.join(root, one_file)
106     if EF != '' and VF != '' and SR != '':
107         logging.debug('Adding installed SDK ' + root)
108         INSTALLED_SDK.append(
109             {'ENV_FILE': EF, 'VERSION_FILE': VF, 'SYSROOTS': SR})
110     elif (EF == '' and VF != '') or (EF != '' and VF == ''):
111         logging.debug(
112             'WARNING SDK ignored : root=%s, EnvFile=%s, VersionFile=%s, sysroots=%s', root, EF, VF, SR)
113
114 for one_sdk in INSTALLED_SDK:
115     logging.debug('Processing %s', one_sdk['ENV_FILE'])
116     envFile = one_sdk['ENV_FILE'].split(SDK_ROOT_DIR+'/')[1]
117     PROFILE = envFile.split('/')[0]
118     VERSION = envFile.split('/')[1]
119     ARCH = envFile.split('/')[2]
120     # and specific case for qemu where arch is not the same (qemux86-64 vs corei7-64)
121     if ARCH == 'corei7-64':
122         # Use /etc/rpm/platform to distinguish qemux86-64 from corei7-64 architecture
123         grepQemu = subprocess.call(['grep', '-q', 'qemux86', os.path.join(
124             one_sdk['SYSROOTS'], 'corei7-64-agl-linux', 'etc', 'rpm', 'platform')],
125             stdout=DEVNULL, stderr=subprocess.STDOUT)
126         if grepQemu == 0:
127             ARCH = 'qemux86-64'
128
129     DIR = os.path.dirname(one_sdk['ENV_FILE'])
130     if PROFILE == '' or VERSION == '' or ARCH == '' or DIR == '':
131         logging.debug('Path not compliant, skipping')
132         continue
133
134     UUID = os.path.basename(os.path.normpath(DIR))
135
136     SDK_DATE = ''
137     for line in open(one_sdk['VERSION_FILE']).readlines():
138         if line.startswith('Timestamp'):
139             D = line.split(':')[1]
140             if D:
141                 D = D.strip()
142                 SDK_DATE = '{}-{}-{} {}:{}'.format(
143                     D[0:4], D[4:6], D[6:8], D[8:10], D[10:12])
144                 logging.debug('Found date: %s', SDK_DATE)
145
146     # Check if installed SDKs match the ones listed in json file
147     found = False
148     for sdk in SDK_DB_JSON:
149         # Matching based on profile + version + arch fields
150         if sdk['profile'] == PROFILE and sdk['version'] == VERSION and sdk['arch'] == ARCH:
151             if sdk['status'] == 'Installed':
152                 continue
153             # Additional verification based on url used to generate UUID (see also same logic in add script)
154             if sdk['url'] != '':
155                 try:
156                     ps = subprocess.Popen(
157                         ('echo', sdk['url']), stdout=subprocess.PIPE)
158                     uuid_md5 = subprocess.check_output(
159                         ('md5sum'), stdin=ps.stdout)
160                     ps.wait()
161                     if str(uuid_md5).split(' ')[0][2:] != UUID:
162                         continue
163                 except:
164                     e = sys.exc_info()[0]
165                     logging.error('Error while checking UUID: ' % e)
166
167             found = True
168             sdk['status'] = 'Installed'
169             sdk['date'] = SDK_DATE
170             sdk['setupFile'] = one_sdk['ENV_FILE']
171             sdk['path'] = DIR
172             sdk['uuid'] = UUID
173             break
174
175     if not found:
176         logging.debug('Not found in database, add: ' +
177                       PROFILE + '-' + ARCH + '-' + VERSION)
178         NEW_SDK = {
179             'name': PROFILE + '-' + ARCH + '-' + VERSION,
180             'uuid': UUID,
181             'description': 'AGL SDK ' + ARCH + ' (version ' + VERSION + ')',
182             'profile': PROFILE,
183             'version': VERSION,
184             'arch': ARCH,
185             'path': DIR,
186             'url': '',
187             'status': 'Installed',
188             'date': SDK_DATE,
189             'size': '',
190             'md5sum': '',
191             'setupFile': one_sdk['ENV_FILE']
192         }
193         SDK_DB_JSON.append(NEW_SDK)
194
195 print(json.dumps(SDK_DB_JSON))