diff options
author | Paul Eggleton <paul.eggleton@linux.intel.com> | 2016-01-23 00:59:51 +1300 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2016-01-24 09:40:32 +0000 |
commit | 44d1a2a45c4d92f331aef1a95adb6b12743d24cd (patch) | |
tree | bd4d1c53ca62bb40c14eee04c6a40141ac01169c /scripts/lib/devtool/sdk.py | |
parent | 3360baa96bb2ebd54efaba0fb9aa9a1c9093c233 (diff) | |
download | poky-44d1a2a45c4d92f331aef1a95adb6b12743d24cd.tar.gz |
devtool: sdk-update: improve SDK update process robustness
Make the following improvements to the SDK update process:
* Use a manifest file with sha256sums to track files other than sstate
and metadata that we need to update - e.g. conf files. This allows us
to handle where files such as auto.conf may or may not be present,
as well as the configuration changing without affecting task signatures
- we still want the config files copied in that case rather than it
saying nothing needs to be done.
* Write the SSTATE_MIRRORS_append to site.conf rather than local.conf
so that local.conf remains static (since we don't want to trigger an
update every time). Also, If there is an SSTATE_MIRRORS value already
set in the configuration we can skip this and assume it contains the
needed packages.
* Allow the update process to be run in any directory, don't assume
we're already at the base of the SDK
* Where practical, fetch remote files into a temporary location and
then move them to the desired location at the end, to avoid a
failed update leaving the SDK in a broken state.
* Update all installed do_populate_sysroot / do_packagedata tasks
instead of using the SDK targets. This ensures any item installed
through dependencies after installation (e.g. when running
"devtool build") won't go stale.
(From OE-Core rev: 3d35631121f0e030bc8151f5c23d84008d06f44b)
Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts/lib/devtool/sdk.py')
-rw-r--r-- | scripts/lib/devtool/sdk.py | 118 |
1 files changed, 84 insertions, 34 deletions
diff --git a/scripts/lib/devtool/sdk.py b/scripts/lib/devtool/sdk.py index 4fcd36a0df..80ea8711cc 100644 --- a/scripts/lib/devtool/sdk.py +++ b/scripts/lib/devtool/sdk.py | |||
@@ -75,6 +75,21 @@ def install_sstate_objects(sstate_objects, src_sdk, dest_sdk): | |||
75 | logger.debug("Copying %s to %s" % (sb, dst)) | 75 | logger.debug("Copying %s to %s" % (sb, dst)) |
76 | shutil.copy(sb, dst) | 76 | shutil.copy(sb, dst) |
77 | 77 | ||
78 | def check_manifest(fn, basepath): | ||
79 | import bb.utils | ||
80 | changedfiles = [] | ||
81 | with open(fn, 'r') as f: | ||
82 | for line in f: | ||
83 | splitline = line.split() | ||
84 | if len(splitline) > 1: | ||
85 | chksum = splitline[0] | ||
86 | fpath = splitline[1] | ||
87 | curr_chksum = bb.utils.sha256_file(os.path.join(basepath, fpath)) | ||
88 | if chksum != curr_chksum: | ||
89 | logger.debug('File %s changed: old csum = %s, new = %s' % (os.path.join(basepath, fpath), curr_chksum, chksum)) | ||
90 | changedfiles.append(fpath) | ||
91 | return changedfiles | ||
92 | |||
78 | def sdk_update(args, config, basepath, workspace): | 93 | def sdk_update(args, config, basepath, workspace): |
79 | # Fetch locked-sigs.inc file from remote/local destination | 94 | # Fetch locked-sigs.inc file from remote/local destination |
80 | updateserver = args.updateserver | 95 | updateserver = args.updateserver |
@@ -98,6 +113,18 @@ def sdk_update(args, config, basepath, workspace): | |||
98 | else: | 113 | else: |
99 | is_remote = False | 114 | is_remote = False |
100 | 115 | ||
116 | layers_dir = os.path.join(basepath, 'layers') | ||
117 | conf_dir = os.path.join(basepath, 'conf') | ||
118 | |||
119 | # Grab variable values | ||
120 | tinfoil = setup_tinfoil(config_only=True, basepath=basepath) | ||
121 | try: | ||
122 | stamps_dir = tinfoil.config_data.getVar('STAMPS_DIR', True) | ||
123 | sstate_mirrors = tinfoil.config_data.getVar('SSTATE_MIRRORS', True) | ||
124 | site_conf_version = tinfoil.config_data.getVar('SITE_CONF_VERSION', True) | ||
125 | finally: | ||
126 | tinfoil.shutdown() | ||
127 | |||
101 | if not is_remote: | 128 | if not is_remote: |
102 | # devtool sdk-update /local/path/to/latest/sdk | 129 | # devtool sdk-update /local/path/to/latest/sdk |
103 | new_locked_sig_file_path = os.path.join(updateserver, 'conf/locked-sigs.inc') | 130 | new_locked_sig_file_path = os.path.join(updateserver, 'conf/locked-sigs.inc') |
@@ -121,16 +148,14 @@ def sdk_update(args, config, basepath, workspace): | |||
121 | install_sstate_objects(sstate_objects, updateserver.rstrip('/'), basepath) | 148 | install_sstate_objects(sstate_objects, updateserver.rstrip('/'), basepath) |
122 | logger.info("Updating configuration files") | 149 | logger.info("Updating configuration files") |
123 | new_conf_dir = os.path.join(updateserver, 'conf') | 150 | new_conf_dir = os.path.join(updateserver, 'conf') |
124 | old_conf_dir = os.path.join(basepath, 'conf') | 151 | shutil.rmtree(conf_dir) |
125 | shutil.rmtree(old_conf_dir) | 152 | shutil.copytree(new_conf_dir, conf_dir) |
126 | shutil.copytree(new_conf_dir, old_conf_dir) | ||
127 | logger.info("Updating layers") | 153 | logger.info("Updating layers") |
128 | new_layers_dir = os.path.join(updateserver, 'layers') | 154 | new_layers_dir = os.path.join(updateserver, 'layers') |
129 | old_layers_dir = os.path.join(basepath, 'layers') | 155 | shutil.rmtree(layers_dir) |
130 | shutil.rmtree(old_layers_dir) | 156 | ret = subprocess.call("cp -a %s %s" % (new_layers_dir, layers_dir), shell=True) |
131 | ret = subprocess.call("cp -a %s %s" % (new_layers_dir, old_layers_dir), shell=True) | ||
132 | if ret != 0: | 157 | if ret != 0: |
133 | logger.error("Copying %s to %s failed" % (new_layers_dir, old_layers_dir)) | 158 | logger.error("Copying %s to %s failed" % (new_layers_dir, layers_dir)) |
134 | return ret | 159 | return ret |
135 | else: | 160 | else: |
136 | # devtool sdk-update http://myhost/sdk | 161 | # devtool sdk-update http://myhost/sdk |
@@ -138,50 +163,75 @@ def sdk_update(args, config, basepath, workspace): | |||
138 | try: | 163 | try: |
139 | os.makedirs(os.path.join(tmpsdk_dir, 'conf')) | 164 | os.makedirs(os.path.join(tmpsdk_dir, 'conf')) |
140 | new_locked_sig_file_path = os.path.join(tmpsdk_dir, 'conf', 'locked-sigs.inc') | 165 | new_locked_sig_file_path = os.path.join(tmpsdk_dir, 'conf', 'locked-sigs.inc') |
141 | # Fetch locked-sigs.inc from update server | 166 | # Fetch manifest from server |
142 | ret = subprocess.call("wget -q -O - %s/conf/locked-sigs.inc > %s" % (updateserver, new_locked_sig_file_path), shell=True) | 167 | tmpmanifest = os.path.join(tmpsdk_dir, 'conf', 'sdk-conf-manifest') |
143 | if ret != 0: | 168 | ret = subprocess.call("wget -q -O %s %s/conf/sdk-conf-manifest" % (tmpmanifest, updateserver), shell=True) |
144 | logger.error("Fetching conf/locked-sigs.inc from %s to %s failed" % (updateserver, new_locked_sig_file_path)) | 169 | changedfiles = check_manifest(tmpmanifest, basepath) |
145 | return ret | 170 | if not changedfiles: |
146 | else: | 171 | logger.info("Already up-to-date") |
147 | logger.info("Fetching conf/locked-sigs.inc from %s to %s succeeded" % (updateserver, new_locked_sig_file_path)) | ||
148 | update_dict = generate_update_dict(new_locked_sig_file_path, old_locked_sig_file_path) | ||
149 | logger.debug("update_dict = %s" % update_dict) | ||
150 | if len(update_dict) == 0: | ||
151 | logger.info("No need to update.") | ||
152 | return 0 | 172 | return 0 |
153 | # Update metadata | 173 | # Update metadata |
154 | logger.debug("Updating meta data via git ...") | 174 | logger.debug("Updating metadata via git ...") |
155 | # Try using 'git pull', if failed, use 'git clone' | 175 | # Try using 'git pull', if failed, use 'git clone' |
156 | if os.path.exists(os.path.join(basepath, 'layers/.git')): | 176 | if os.path.exists(os.path.join(basepath, 'layers/.git')): |
157 | ret = subprocess.call("cd layers && git pull %s/layers/.git" % updateserver, shell=True) | 177 | ret = subprocess.call("git pull %s/layers/.git" % updateserver, shell=True, cwd=layers_dir) |
158 | else: | 178 | else: |
159 | ret = -1 | 179 | ret = -1 |
160 | if ret != 0: | 180 | if ret != 0: |
161 | ret = subprocess.call("rm -rf layers && git clone %s/layers/.git" % updateserver, shell=True) | 181 | ret = subprocess.call("git clone %s/layers/.git" % updateserver, shell=True, cwd=tmpsdk_dir) |
162 | if ret != 0: | 182 | if ret != 0: |
163 | logger.error("Updating meta data via git failed") | 183 | logger.error("Updating metadata via git failed") |
164 | return ret | 184 | return ret |
165 | logger.debug("Updating conf files ...") | 185 | logger.debug("Updating conf files ...") |
166 | conf_files = ['local.conf', 'bblayers.conf', 'devtool.conf', 'locked-sigs.inc'] | 186 | for changedfile in changedfiles: |
167 | for conf in conf_files: | 187 | ret = subprocess.call("wget -q -O %s %s/%s" % (changedfile, updateserver, changedfile), shell=True, cwd=tmpsdk_dir) |
168 | ret = subprocess.call("wget -q -O - %s/conf/%s > conf/%s" % (updateserver, conf, conf), shell=True) | ||
169 | if ret != 0: | 188 | if ret != 0: |
170 | logger.error("Update %s failed" % conf) | 189 | logger.error("Updating %s failed" % changedfile) |
171 | return ret | 190 | return ret |
172 | with open(os.path.join(basepath, 'conf/local.conf'), 'a') as f: | 191 | |
173 | f.write('SSTATE_MIRRORS_append = " file://.* %s/sstate-cache/PATH \\n "\n' % updateserver) | 192 | # Ok, all is well at this point - move everything over |
193 | tmplayers_dir = os.path.join(tmpsdk_dir, 'layers') | ||
194 | if os.path.exists(tmplayers_dir): | ||
195 | shutil.rmtree(layers_dir) | ||
196 | shutil.move(tmplayers_dir, layers_dir) | ||
197 | for changedfile in changedfiles: | ||
198 | destfile = os.path.join(basepath, changedfile) | ||
199 | os.remove(destfile) | ||
200 | shutil.move(os.path.join(tmpsdk_dir, changedfile), destfile) | ||
201 | os.remove(os.path.join(conf_dir, 'sdk-conf-manifest')) | ||
202 | shutil.move(tmpmanifest, conf_dir) | ||
203 | |||
204 | if not sstate_mirrors: | ||
205 | with open(os.path.join(conf_dir, 'site.conf'), 'a') as f: | ||
206 | f.write('SCONF_VERSION = "%s"\n' % site_conf_version) | ||
207 | f.write('SSTATE_MIRRORS_append = " file://.* %s/sstate-cache/PATH \\n "\n' % updateserver) | ||
174 | finally: | 208 | finally: |
175 | shutil.rmtree(tmpsdk_dir) | 209 | shutil.rmtree(tmpsdk_dir) |
176 | 210 | ||
177 | if not args.skip_prepare: | 211 | if not args.skip_prepare: |
212 | # Find all potentially updateable tasks | ||
213 | sdk_update_targets = [] | ||
214 | tasks = ['do_populate_sysroot', 'do_packagedata'] | ||
215 | for root, _, files in os.walk(stamps_dir): | ||
216 | for fn in files: | ||
217 | if not '.sigdata.' in fn: | ||
218 | for task in tasks: | ||
219 | if '.%s.' % task in fn or '.%s_setscene.' % task in fn: | ||
220 | sdk_update_targets.append('%s:%s' % (os.path.basename(root), task)) | ||
178 | # Run bitbake command for the whole SDK | 221 | # Run bitbake command for the whole SDK |
179 | sdk_update_targets = config.get('SDK', 'sdk_update_targets', config.get('SDK', 'sdk_targets')) | ||
180 | logger.info("Preparing build system... (This may take some time.)") | 222 | logger.info("Preparing build system... (This may take some time.)") |
181 | try: | 223 | try: |
182 | exec_build_env_command(config.init_path, basepath, 'bitbake %s --setscene-only' % sdk_update_targets) | 224 | exec_build_env_command(config.init_path, basepath, 'bitbake --setscene-only %s' % ' '.join(sdk_update_targets), stderr=subprocess.STDOUT) |
183 | except: | 225 | output, _ = exec_build_env_command(config.init_path, basepath, 'bitbake -n %s' % ' '.join(sdk_update_targets), stderr=subprocess.STDOUT) |
184 | logger.error('bitbake %s failed' % sdk_update_targets) | 226 | runlines = [] |
227 | for line in output.splitlines(): | ||
228 | if 'Running task ' in line: | ||
229 | runlines.append(line) | ||
230 | if runlines: | ||
231 | logger.error('Unexecuted tasks found in preparation log:\n %s' % '\n '.join(runlines)) | ||
232 | return -1 | ||
233 | except bb.process.ExecutionError as e: | ||
234 | logger.error('Preparation failed:\n%s' % e.stdout) | ||
185 | return -1 | 235 | return -1 |
186 | return 0 | 236 | return 0 |
187 | 237 | ||