blob: c62fa5f54adb7698f7e81fb3cc9f776cbebed51b [file] [log] [blame]
Brad Bishopc342db32019-05-15 21:57:59 -04001#
2# SPDX-License-Identifier: GPL-2.0-only
3#
Patrick Williamsc124f4f2015-09-15 14:41:29 -05004from abc import ABCMeta, abstractmethod
5from oe.utils import execute_pre_post_process
6from oe.package_manager import *
7from oe.manifest import *
8import oe.path
9import filecmp
10import shutil
11import os
12import subprocess
13import re
14
15
Patrick Williamsc0f7c042017-02-23 20:41:17 -060016class Rootfs(object, metaclass=ABCMeta):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050017 """
18 This is an abstract class. Do not instantiate this directly.
19 """
Patrick Williamsc124f4f2015-09-15 14:41:29 -050020
Brad Bishop6e60e8b2018-02-01 10:27:11 -050021 def __init__(self, d, progress_reporter=None, logcatcher=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050022 self.d = d
23 self.pm = None
Brad Bishop6e60e8b2018-02-01 10:27:11 -050024 self.image_rootfs = self.d.getVar('IMAGE_ROOTFS')
25 self.deploydir = self.d.getVar('IMGDEPLOYDIR')
Patrick Williamsc0f7c042017-02-23 20:41:17 -060026 self.progress_reporter = progress_reporter
Brad Bishop6e60e8b2018-02-01 10:27:11 -050027 self.logcatcher = logcatcher
Patrick Williamsc124f4f2015-09-15 14:41:29 -050028
29 self.install_order = Manifest.INSTALL_ORDER
30
31 @abstractmethod
32 def _create(self):
33 pass
34
35 @abstractmethod
36 def _get_delayed_postinsts(self):
37 pass
38
39 @abstractmethod
40 def _save_postinsts(self):
41 pass
42
43 @abstractmethod
44 def _log_check(self):
45 pass
46
Patrick Williamsc0f7c042017-02-23 20:41:17 -060047 def _log_check_common(self, type, match):
48 # Ignore any lines containing log_check to avoid recursion, and ignore
49 # lines beginning with a + since sh -x may emit code which isn't
50 # actually executed, but may contain error messages
51 excludes = [ 'log_check', r'^\+' ]
52 if hasattr(self, 'log_check_expected_regexes'):
53 excludes.extend(self.log_check_expected_regexes)
54 excludes = [re.compile(x) for x in excludes]
55 r = re.compile(match)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050056 log_path = self.d.expand("${T}/log.do_rootfs")
Patrick Williamsc0f7c042017-02-23 20:41:17 -060057 messages = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -050058 with open(log_path, 'r') as log:
59 for line in log:
Brad Bishop6e60e8b2018-02-01 10:27:11 -050060 if self.logcatcher and self.logcatcher.contains(line.rstrip()):
61 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -060062 for ee in excludes:
63 m = ee.search(line)
64 if m:
65 break
66 if m:
Patrick Williamsc124f4f2015-09-15 14:41:29 -050067 continue
68
69 m = r.search(line)
70 if m:
Patrick Williamsc0f7c042017-02-23 20:41:17 -060071 messages.append('[log_check] %s' % line)
72 if messages:
73 if len(messages) == 1:
74 msg = '1 %s message' % type
75 else:
76 msg = '%d %s messages' % (len(messages), type)
77 msg = '[log_check] %s: found %s in the logfile:\n%s' % \
Brad Bishop6e60e8b2018-02-01 10:27:11 -050078 (self.d.getVar('PN'), msg, ''.join(messages))
Patrick Williamsc0f7c042017-02-23 20:41:17 -060079 if type == 'error':
80 bb.fatal(msg)
81 else:
82 bb.warn(msg)
83
84 def _log_check_warn(self):
85 self._log_check_common('warning', '^(warn|Warn|WARNING:)')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050086
87 def _log_check_error(self):
Patrick Williamsc0f7c042017-02-23 20:41:17 -060088 self._log_check_common('error', self.log_check_regex)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050089
90 def _insert_feed_uris(self):
91 if bb.utils.contains("IMAGE_FEATURES", "package-management",
92 True, False, self.d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -050093 self.pm.insert_feeds_uris(self.d.getVar('PACKAGE_FEED_URIS') or "",
94 self.d.getVar('PACKAGE_FEED_BASE_PATHS') or "",
95 self.d.getVar('PACKAGE_FEED_ARCHS'))
96
Patrick Williamsc124f4f2015-09-15 14:41:29 -050097
Patrick Williamsc124f4f2015-09-15 14:41:29 -050098 """
99 The _cleanup() method should be used to clean-up stuff that we don't really
100 want to end up on target. For example, in the case of RPM, the DB locks.
101 The method is called, once, at the end of create() method.
102 """
103 @abstractmethod
104 def _cleanup(self):
105 pass
106
107 def _setup_dbg_rootfs(self, dirs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500108 gen_debugfs = self.d.getVar('IMAGE_GEN_DEBUGFS') or '0'
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500109 if gen_debugfs != '1':
110 return
111
112 bb.note(" Renaming the original rootfs...")
113 try:
114 shutil.rmtree(self.image_rootfs + '-orig')
115 except:
116 pass
117 os.rename(self.image_rootfs, self.image_rootfs + '-orig')
118
119 bb.note(" Creating debug rootfs...")
120 bb.utils.mkdirhier(self.image_rootfs)
121
122 bb.note(" Copying back package database...")
123 for dir in dirs:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600124 if not os.path.isdir(self.image_rootfs + '-orig' + dir):
125 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500126 bb.utils.mkdirhier(self.image_rootfs + os.path.dirname(dir))
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600127 shutil.copytree(self.image_rootfs + '-orig' + dir, self.image_rootfs + dir, symlinks=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500128
129 cpath = oe.cachedpath.CachedPath()
130 # Copy files located in /usr/lib/debug or /usr/src/debug
131 for dir in ["/usr/lib/debug", "/usr/src/debug"]:
132 src = self.image_rootfs + '-orig' + dir
133 if cpath.exists(src):
134 dst = self.image_rootfs + dir
135 bb.utils.mkdirhier(os.path.dirname(dst))
136 shutil.copytree(src, dst)
137
138 # Copy files with suffix '.debug' or located in '.debug' dir.
139 for root, dirs, files in cpath.walk(self.image_rootfs + '-orig'):
140 relative_dir = root[len(self.image_rootfs + '-orig'):]
141 for f in files:
142 if f.endswith('.debug') or '/.debug' in relative_dir:
143 bb.utils.mkdirhier(self.image_rootfs + relative_dir)
144 shutil.copy(os.path.join(root, f),
145 self.image_rootfs + relative_dir)
146
147 bb.note(" Install complementary '*-dbg' packages...")
148 self.pm.install_complementary('*-dbg')
149
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800150 if self.d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg':
151 bb.note(" Install complementary '*-src' packages...")
152 self.pm.install_complementary('*-src')
153
154 """
155 Install additional debug packages. Possibility to install additional packages,
156 which are not automatically installed as complementary package of
157 standard one, e.g. debug package of static libraries.
158 """
159 extra_debug_pkgs = self.d.getVar('IMAGE_INSTALL_DEBUGFS')
160 if extra_debug_pkgs:
161 bb.note(" Install extra debug packages...")
162 self.pm.install(extra_debug_pkgs.split(), True)
163
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500164 bb.note(" Rename debug rootfs...")
165 try:
166 shutil.rmtree(self.image_rootfs + '-dbg')
167 except:
168 pass
169 os.rename(self.image_rootfs, self.image_rootfs + '-dbg')
170
171 bb.note(" Restoreing original rootfs...")
172 os.rename(self.image_rootfs + '-orig', self.image_rootfs)
173
174 def _exec_shell_cmd(self, cmd):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500175 fakerootcmd = self.d.getVar('FAKEROOT')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500176 if fakerootcmd is not None:
177 exec_cmd = [fakerootcmd, cmd]
178 else:
179 exec_cmd = cmd
180
181 try:
182 subprocess.check_output(exec_cmd, stderr=subprocess.STDOUT)
183 except subprocess.CalledProcessError as e:
184 return("Command '%s' returned %d:\n%s" % (e.cmd, e.returncode, e.output))
185
186 return None
187
188 def create(self):
189 bb.note("###### Generate rootfs #######")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500190 pre_process_cmds = self.d.getVar("ROOTFS_PREPROCESS_COMMAND")
191 post_process_cmds = self.d.getVar("ROOTFS_POSTPROCESS_COMMAND")
192 rootfs_post_install_cmds = self.d.getVar('ROOTFS_POSTINSTALL_COMMAND')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500193
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500194 bb.utils.mkdirhier(self.image_rootfs)
195
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600196 bb.utils.mkdirhier(self.deploydir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500197
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500198 execute_pre_post_process(self.d, pre_process_cmds)
199
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600200 if self.progress_reporter:
201 self.progress_reporter.next_stage()
202
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500203 # call the package manager dependent create method
204 self._create()
205
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500206 sysconfdir = self.image_rootfs + self.d.getVar('sysconfdir')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500207 bb.utils.mkdirhier(sysconfdir)
208 with open(sysconfdir + "/version", "w+") as ver:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500209 ver.write(self.d.getVar('BUILDNAME') + "\n")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500210
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500211 execute_pre_post_process(self.d, rootfs_post_install_cmds)
212
Brad Bishop316dfdd2018-06-25 12:45:53 -0400213 self.pm.run_intercepts()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500214
215 execute_pre_post_process(self.d, post_process_cmds)
216
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600217 if self.progress_reporter:
218 self.progress_reporter.next_stage()
219
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500220 if bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs",
221 True, False, self.d):
222 delayed_postinsts = self._get_delayed_postinsts()
223 if delayed_postinsts is not None:
224 bb.fatal("The following packages could not be configured "
225 "offline and rootfs is read-only: %s" %
226 delayed_postinsts)
227
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500228 if self.d.getVar('USE_DEVFS') != "1":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500229 self._create_devfs()
230
231 self._uninstall_unneeded()
232
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600233 if self.progress_reporter:
234 self.progress_reporter.next_stage()
235
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500236 self._insert_feed_uris()
237
238 self._run_ldconfig()
239
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500240 if self.d.getVar('USE_DEPMOD') != "0":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500241 self._generate_kernel_module_deps()
242
243 self._cleanup()
244 self._log_check()
245
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600246 if self.progress_reporter:
247 self.progress_reporter.next_stage()
248
249
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500250 def _uninstall_unneeded(self):
251 # Remove unneeded init script symlinks
252 delayed_postinsts = self._get_delayed_postinsts()
253 if delayed_postinsts is None:
254 if os.path.exists(self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/init.d/run-postinsts")):
255 self._exec_shell_cmd(["update-rc.d", "-f", "-r",
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500256 self.d.getVar('IMAGE_ROOTFS'),
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500257 "run-postinsts", "remove"])
258
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500259 image_rorfs = bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs",
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500260 True, False, self.d)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500261 image_rorfs_force = self.d.getVar('FORCE_RO_REMOVE')
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600262
263 if image_rorfs or image_rorfs_force == "1":
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500264 # Remove components that we don't need if it's a read-only rootfs
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500265 unneeded_pkgs = self.d.getVar("ROOTFS_RO_UNNEEDED").split()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500266 pkgs_installed = image_list_installed_packages(self.d)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500267 # Make sure update-alternatives is removed last. This is
268 # because its database has to available while uninstalling
269 # other packages, allowing alternative symlinks of packages
270 # to be uninstalled or to be managed correctly otherwise.
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500271 provider = self.d.getVar("VIRTUAL-RUNTIME_update-alternatives")
272 pkgs_to_remove = sorted([pkg for pkg in pkgs_installed if pkg in unneeded_pkgs], key=lambda x: x == provider)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500273
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500274 # update-alternatives provider is removed in its own remove()
275 # call because all package managers do not guarantee the packages
276 # are removed in the order they given in the list (which is
277 # passed to the command line). The sorting done earlier is
278 # utilized to implement the 2-stage removal.
279 if len(pkgs_to_remove) > 1:
280 self.pm.remove(pkgs_to_remove[:-1], False)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500281 if len(pkgs_to_remove) > 0:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500282 self.pm.remove([pkgs_to_remove[-1]], False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500283
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500284 if delayed_postinsts:
285 self._save_postinsts()
286 if image_rorfs:
287 bb.warn("There are post install scripts "
288 "in a read-only rootfs")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500289
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500290 post_uninstall_cmds = self.d.getVar("ROOTFS_POSTUNINSTALL_COMMAND")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500291 execute_pre_post_process(self.d, post_uninstall_cmds)
292
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500293 runtime_pkgmanage = bb.utils.contains("IMAGE_FEATURES", "package-management",
294 True, False, self.d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500295 if not runtime_pkgmanage:
296 # Remove the package manager data files
297 self.pm.remove_packaging_data()
298
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500299 def _run_ldconfig(self):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500300 if self.d.getVar('LDCONFIGDEPEND'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500301 bb.note("Executing: ldconfig -r" + self.image_rootfs + "-c new -v")
302 self._exec_shell_cmd(['ldconfig', '-r', self.image_rootfs, '-c',
303 'new', '-v'])
304
305 def _check_for_kernel_modules(self, modules_dir):
306 for root, dirs, files in os.walk(modules_dir, topdown=True):
307 for name in files:
308 found_ko = name.endswith(".ko")
309 if found_ko:
310 return found_ko
311 return False
312
313 def _generate_kernel_module_deps(self):
314 modules_dir = os.path.join(self.image_rootfs, 'lib', 'modules')
315 # if we don't have any modules don't bother to do the depmod
316 if not self._check_for_kernel_modules(modules_dir):
317 bb.note("No Kernel Modules found, not running depmod")
318 return
319
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500320 kernel_abi_ver_file = oe.path.join(self.d.getVar('PKGDATA_DIR'), "kernel-depmod",
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500321 'kernel-abiversion')
322 if not os.path.exists(kernel_abi_ver_file):
323 bb.fatal("No kernel-abiversion file found (%s), cannot run depmod, aborting" % kernel_abi_ver_file)
324
325 kernel_ver = open(kernel_abi_ver_file).read().strip(' \n')
326 versioned_modules_dir = os.path.join(self.image_rootfs, modules_dir, kernel_ver)
327
328 bb.utils.mkdirhier(versioned_modules_dir)
329
330 self._exec_shell_cmd(['depmodwrapper', '-a', '-b', self.image_rootfs, kernel_ver])
331
332 """
333 Create devfs:
334 * IMAGE_DEVICE_TABLE is the old name to an absolute path to a device table file
335 * IMAGE_DEVICE_TABLES is a new name for a file, or list of files, seached
336 for in the BBPATH
337 If neither are specified then the default name of files/device_table-minimal.txt
338 is searched for in the BBPATH (same as the old version.)
339 """
340 def _create_devfs(self):
341 devtable_list = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500342 devtable = self.d.getVar('IMAGE_DEVICE_TABLE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500343 if devtable is not None:
344 devtable_list.append(devtable)
345 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500346 devtables = self.d.getVar('IMAGE_DEVICE_TABLES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500347 if devtables is None:
348 devtables = 'files/device_table-minimal.txt'
349 for devtable in devtables.split():
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500350 devtable_list.append("%s" % bb.utils.which(self.d.getVar('BBPATH'), devtable))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500351
352 for devtable in devtable_list:
353 self._exec_shell_cmd(["makedevs", "-r",
354 self.image_rootfs, "-D", devtable])
355
356
357class RpmRootfs(Rootfs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500358 def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None):
359 super(RpmRootfs, self).__init__(d, progress_reporter, logcatcher)
Brad Bishop19323692019-04-05 15:28:33 -0400360 self.log_check_regex = r'(unpacking of archive failed|Cannot find package'\
361 r'|exit 1|ERROR: |Error: |Error |ERROR '\
362 r'|Failed |Failed: |Failed$|Failed\(\d+\):)'
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500363 self.manifest = RpmManifest(d, manifest_dir)
364
365 self.pm = RpmPM(d,
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500366 d.getVar('IMAGE_ROOTFS'),
367 self.d.getVar('TARGET_VENDOR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500368 )
369
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500370 self.inc_rpm_image_gen = self.d.getVar('INC_RPM_IMAGE_GEN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500371 if self.inc_rpm_image_gen != "1":
372 bb.utils.remove(self.image_rootfs, True)
373 else:
374 self.pm.recovery_packaging_data()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500375 bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500376
377 self.pm.create_configs()
378
379 '''
380 While rpm incremental image generation is enabled, it will remove the
381 unneeded pkgs by comparing the new install solution manifest and the
382 old installed manifest.
383 '''
384 def _create_incremental(self, pkgs_initial_install):
385 if self.inc_rpm_image_gen == "1":
386
387 pkgs_to_install = list()
388 for pkg_type in pkgs_initial_install:
389 pkgs_to_install += pkgs_initial_install[pkg_type]
390
391 installed_manifest = self.pm.load_old_install_solution()
392 solution_manifest = self.pm.dump_install_solution(pkgs_to_install)
393
394 pkg_to_remove = list()
395 for pkg in installed_manifest:
396 if pkg not in solution_manifest:
397 pkg_to_remove.append(pkg)
398
399 self.pm.update()
400
401 bb.note('incremental update -- upgrade packages in place ')
402 self.pm.upgrade()
403 if pkg_to_remove != []:
404 bb.note('incremental removed: %s' % ' '.join(pkg_to_remove))
405 self.pm.remove(pkg_to_remove)
406
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500407 self.pm.autoremove()
408
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500409 def _create(self):
410 pkgs_to_install = self.manifest.parse_initial_manifest()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500411 rpm_pre_process_cmds = self.d.getVar('RPM_PREPROCESS_COMMANDS')
412 rpm_post_process_cmds = self.d.getVar('RPM_POSTPROCESS_COMMANDS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500413
414 # update PM index files
415 self.pm.write_index()
416
417 execute_pre_post_process(self.d, rpm_pre_process_cmds)
418
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600419 if self.progress_reporter:
420 self.progress_reporter.next_stage()
421
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500422 if self.inc_rpm_image_gen == "1":
423 self._create_incremental(pkgs_to_install)
424
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600425 if self.progress_reporter:
426 self.progress_reporter.next_stage()
427
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500428 self.pm.update()
429
430 pkgs = []
431 pkgs_attempt = []
432 for pkg_type in pkgs_to_install:
433 if pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY:
434 pkgs_attempt += pkgs_to_install[pkg_type]
435 else:
436 pkgs += pkgs_to_install[pkg_type]
437
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600438 if self.progress_reporter:
439 self.progress_reporter.next_stage()
440
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500441 self.pm.install(pkgs)
442
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600443 if self.progress_reporter:
444 self.progress_reporter.next_stage()
445
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500446 self.pm.install(pkgs_attempt, True)
447
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600448 if self.progress_reporter:
449 self.progress_reporter.next_stage()
450
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500451 self.pm.install_complementary()
452
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600453 if self.progress_reporter:
454 self.progress_reporter.next_stage()
455
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500456 self._setup_dbg_rootfs(['/etc', '/var/lib/rpm', '/var/cache/dnf', '/var/lib/dnf'])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500457
458 execute_pre_post_process(self.d, rpm_post_process_cmds)
459
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500460 if self.inc_rpm_image_gen == "1":
461 self.pm.backup_packaging_data()
462
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600463 if self.progress_reporter:
464 self.progress_reporter.next_stage()
465
466
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500467 @staticmethod
468 def _depends_list():
469 return ['DEPLOY_DIR_RPM', 'INC_RPM_IMAGE_GEN', 'RPM_PREPROCESS_COMMANDS',
470 'RPM_POSTPROCESS_COMMANDS', 'RPM_PREFER_ELF_ARCH']
471
472 def _get_delayed_postinsts(self):
473 postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/rpm-postinsts")
474 if os.path.isdir(postinst_dir):
475 files = os.listdir(postinst_dir)
476 for f in files:
477 bb.note('Delayed package scriptlet: %s' % f)
478 return files
479
480 return None
481
482 def _save_postinsts(self):
483 # this is just a stub. For RPM, the failed postinstalls are
484 # already saved in /etc/rpm-postinsts
485 pass
486
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500487 def _log_check(self):
488 self._log_check_warn()
489 self._log_check_error()
490
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500491 def _cleanup(self):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800492 if bb.utils.contains("IMAGE_FEATURES", "package-management", True, False, self.d):
493 self.pm._invoke_dnf(["clean", "all"])
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500494
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500495
496class DpkgOpkgRootfs(Rootfs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500497 def __init__(self, d, progress_reporter=None, logcatcher=None):
498 super(DpkgOpkgRootfs, self).__init__(d, progress_reporter, logcatcher)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500499
500 def _get_pkgs_postinsts(self, status_file):
501 def _get_pkg_depends_list(pkg_depends):
502 pkg_depends_list = []
503 # filter version requirements like libc (>= 1.1)
504 for dep in pkg_depends.split(', '):
Brad Bishop19323692019-04-05 15:28:33 -0400505 m_dep = re.match(r"^(.*) \(.*\)$", dep)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500506 if m_dep:
507 dep = m_dep.group(1)
508 pkg_depends_list.append(dep)
509
510 return pkg_depends_list
511
512 pkgs = {}
513 pkg_name = ""
514 pkg_status_match = False
515 pkg_depends = ""
516
517 with open(status_file) as status:
518 data = status.read()
519 status.close()
520 for line in data.split('\n'):
Brad Bishop19323692019-04-05 15:28:33 -0400521 m_pkg = re.match(r"^Package: (.*)", line)
522 m_status = re.match(r"^Status:.*unpacked", line)
523 m_depends = re.match(r"^Depends: (.*)", line)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500524
Brad Bishop19323692019-04-05 15:28:33 -0400525 #Only one of m_pkg, m_status or m_depends is not None at time
526 #If m_pkg is not None, we started a new package
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500527 if m_pkg is not None:
Brad Bishop19323692019-04-05 15:28:33 -0400528 #Get Package name
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500529 pkg_name = m_pkg.group(1)
Brad Bishop19323692019-04-05 15:28:33 -0400530 #Make sure we reset other variables
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500531 pkg_status_match = False
532 pkg_depends = ""
533 elif m_status is not None:
Brad Bishop19323692019-04-05 15:28:33 -0400534 #New status matched
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500535 pkg_status_match = True
536 elif m_depends is not None:
Brad Bishop19323692019-04-05 15:28:33 -0400537 #New depends macthed
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500538 pkg_depends = m_depends.group(1)
Brad Bishop19323692019-04-05 15:28:33 -0400539 else:
540 pass
541
542 #Now check if we can process package depends and postinst
543 if "" != pkg_name and pkg_status_match:
544 pkgs[pkg_name] = _get_pkg_depends_list(pkg_depends)
545 else:
546 #Not enough information
547 pass
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500548
549 # remove package dependencies not in postinsts
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600550 pkg_names = list(pkgs.keys())
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500551 for pkg_name in pkg_names:
552 deps = pkgs[pkg_name][:]
553
554 for d in deps:
555 if d not in pkg_names:
556 pkgs[pkg_name].remove(d)
557
558 return pkgs
559
560 def _get_delayed_postinsts_common(self, status_file):
561 def _dep_resolve(graph, node, resolved, seen):
562 seen.append(node)
563
564 for edge in graph[node]:
565 if edge not in resolved:
566 if edge in seen:
567 raise RuntimeError("Packages %s and %s have " \
568 "a circular dependency in postinsts scripts." \
569 % (node, edge))
570 _dep_resolve(graph, edge, resolved, seen)
571
572 resolved.append(node)
573
574 pkg_list = []
575
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500576 pkgs = None
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500577 if not self.d.getVar('PACKAGE_INSTALL').strip():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500578 bb.note("Building empty image")
579 else:
580 pkgs = self._get_pkgs_postinsts(status_file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500581 if pkgs:
582 root = "__packagegroup_postinst__"
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600583 pkgs[root] = list(pkgs.keys())
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500584 _dep_resolve(pkgs, root, pkg_list, [])
585 pkg_list.remove(root)
586
587 if len(pkg_list) == 0:
588 return None
589
590 return pkg_list
591
592 def _save_postinsts_common(self, dst_postinst_dir, src_postinst_dir):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800593 if bb.utils.contains("IMAGE_FEATURES", "package-management",
594 True, False, self.d):
595 return
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500596 num = 0
597 for p in self._get_delayed_postinsts():
598 bb.utils.mkdirhier(dst_postinst_dir)
599
600 if os.path.exists(os.path.join(src_postinst_dir, p + ".postinst")):
601 shutil.copy(os.path.join(src_postinst_dir, p + ".postinst"),
602 os.path.join(dst_postinst_dir, "%03d-%s" % (num, p)))
603
604 num += 1
605
606class DpkgRootfs(DpkgOpkgRootfs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500607 def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None):
608 super(DpkgRootfs, self).__init__(d, progress_reporter, logcatcher)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500609 self.log_check_regex = '^E:'
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600610 self.log_check_expected_regexes = \
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500611 [
612 "^E: Unmet dependencies."
613 ]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500614
615 bb.utils.remove(self.image_rootfs, True)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500616 bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500617 self.manifest = DpkgManifest(d, manifest_dir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500618 self.pm = DpkgPM(d, d.getVar('IMAGE_ROOTFS'),
619 d.getVar('PACKAGE_ARCHS'),
620 d.getVar('DPKG_ARCH'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500621
622
623 def _create(self):
624 pkgs_to_install = self.manifest.parse_initial_manifest()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500625 deb_pre_process_cmds = self.d.getVar('DEB_PREPROCESS_COMMANDS')
626 deb_post_process_cmds = self.d.getVar('DEB_POSTPROCESS_COMMANDS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500627
628 alt_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/alternatives")
629 bb.utils.mkdirhier(alt_dir)
630
631 # update PM index files
632 self.pm.write_index()
633
634 execute_pre_post_process(self.d, deb_pre_process_cmds)
635
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600636 if self.progress_reporter:
637 self.progress_reporter.next_stage()
638 # Don't support incremental, so skip that
639 self.progress_reporter.next_stage()
640
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500641 self.pm.update()
642
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600643 if self.progress_reporter:
644 self.progress_reporter.next_stage()
645
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500646 for pkg_type in self.install_order:
647 if pkg_type in pkgs_to_install:
648 self.pm.install(pkgs_to_install[pkg_type],
649 [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
Brad Bishopf3fd2882019-06-21 08:06:37 -0400650 self.pm.fix_broken_dependencies()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500651
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600652 if self.progress_reporter:
653 # Don't support attemptonly, so skip that
654 self.progress_reporter.next_stage()
655 self.progress_reporter.next_stage()
656
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500657 self.pm.install_complementary()
658
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600659 if self.progress_reporter:
660 self.progress_reporter.next_stage()
661
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500662 self._setup_dbg_rootfs(['/var/lib/dpkg'])
663
664 self.pm.fix_broken_dependencies()
665
666 self.pm.mark_packages("installed")
667
668 self.pm.run_pre_post_installs()
669
670 execute_pre_post_process(self.d, deb_post_process_cmds)
671
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600672 if self.progress_reporter:
673 self.progress_reporter.next_stage()
674
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500675 @staticmethod
676 def _depends_list():
677 return ['DEPLOY_DIR_DEB', 'DEB_SDK_ARCH', 'APTCONF_TARGET', 'APT_ARGS', 'DPKG_ARCH', 'DEB_PREPROCESS_COMMANDS', 'DEB_POSTPROCESS_COMMANDS']
678
679 def _get_delayed_postinsts(self):
680 status_file = self.image_rootfs + "/var/lib/dpkg/status"
681 return self._get_delayed_postinsts_common(status_file)
682
683 def _save_postinsts(self):
684 dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/deb-postinsts")
685 src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/info")
686 return self._save_postinsts_common(dst_postinst_dir, src_postinst_dir)
687
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500688 def _log_check(self):
689 self._log_check_warn()
690 self._log_check_error()
691
692 def _cleanup(self):
693 pass
694
695
696class OpkgRootfs(DpkgOpkgRootfs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500697 def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None):
698 super(OpkgRootfs, self).__init__(d, progress_reporter, logcatcher)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500699 self.log_check_regex = '(exit 1|Collected errors)'
700
701 self.manifest = OpkgManifest(d, manifest_dir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500702 self.opkg_conf = self.d.getVar("IPKGCONF_TARGET")
703 self.pkg_archs = self.d.getVar("ALL_MULTILIB_PACKAGE_ARCHS")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500704
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500705 self.inc_opkg_image_gen = self.d.getVar('INC_IPK_IMAGE_GEN') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500706 if self._remove_old_rootfs():
707 bb.utils.remove(self.image_rootfs, True)
708 self.pm = OpkgPM(d,
709 self.image_rootfs,
710 self.opkg_conf,
711 self.pkg_archs)
712 else:
713 self.pm = OpkgPM(d,
714 self.image_rootfs,
715 self.opkg_conf,
716 self.pkg_archs)
717 self.pm.recover_packaging_data()
718
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500719 bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500720
721 def _prelink_file(self, root_dir, filename):
722 bb.note('prelink %s in %s' % (filename, root_dir))
723 prelink_cfg = oe.path.join(root_dir,
724 self.d.expand('${sysconfdir}/prelink.conf'))
725 if not os.path.exists(prelink_cfg):
726 shutil.copy(self.d.expand('${STAGING_DIR_NATIVE}${sysconfdir_native}/prelink.conf'),
727 prelink_cfg)
728
729 cmd_prelink = self.d.expand('${STAGING_DIR_NATIVE}${sbindir_native}/prelink')
730 self._exec_shell_cmd([cmd_prelink,
731 '--root',
732 root_dir,
733 '-amR',
734 '-N',
735 '-c',
736 self.d.expand('${sysconfdir}/prelink.conf')])
737
738 '''
739 Compare two files with the same key twice to see if they are equal.
740 If they are not equal, it means they are duplicated and come from
741 different packages.
742 1st: Comapre them directly;
743 2nd: While incremental image creation is enabled, one of the
744 files could be probaly prelinked in the previous image
745 creation and the file has been changed, so we need to
746 prelink the other one and compare them.
747 '''
748 def _file_equal(self, key, f1, f2):
749
750 # Both of them are not prelinked
751 if filecmp.cmp(f1, f2):
752 return True
753
Brad Bishop19323692019-04-05 15:28:33 -0400754 if bb.data.inherits_class('image-prelink', self.d):
755 if self.image_rootfs not in f1:
756 self._prelink_file(f1.replace(key, ''), f1)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500757
Brad Bishop19323692019-04-05 15:28:33 -0400758 if self.image_rootfs not in f2:
759 self._prelink_file(f2.replace(key, ''), f2)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500760
Brad Bishop19323692019-04-05 15:28:33 -0400761 # Both of them are prelinked
762 if filecmp.cmp(f1, f2):
763 return True
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500764
765 # Not equal
766 return False
767
768 """
769 This function was reused from the old implementation.
770 See commit: "image.bbclass: Added variables for multilib support." by
771 Lianhao Lu.
772 """
773 def _multilib_sanity_test(self, dirs):
774
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500775 allow_replace = self.d.getVar("MULTILIBRE_ALLOW_REP")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500776 if allow_replace is None:
777 allow_replace = ""
778
Brad Bishop19323692019-04-05 15:28:33 -0400779 allow_rep = re.compile(re.sub(r"\|$", r"", allow_replace))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500780 error_prompt = "Multilib check error:"
781
782 files = {}
783 for dir in dirs:
784 for root, subfolders, subfiles in os.walk(dir):
785 for file in subfiles:
786 item = os.path.join(root, file)
787 key = str(os.path.join("/", os.path.relpath(item, dir)))
788
789 valid = True
790 if key in files:
791 #check whether the file is allow to replace
792 if allow_rep.match(key):
793 valid = True
794 else:
795 if os.path.exists(files[key]) and \
796 os.path.exists(item) and \
797 not self._file_equal(key, files[key], item):
798 valid = False
799 bb.fatal("%s duplicate files %s %s is not the same\n" %
800 (error_prompt, item, files[key]))
801
802 #pass the check, add to list
803 if valid:
804 files[key] = item
805
806 def _multilib_test_install(self, pkgs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500807 ml_temp = self.d.getVar("MULTILIB_TEMP_ROOTFS")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500808 bb.utils.mkdirhier(ml_temp)
809
810 dirs = [self.image_rootfs]
811
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500812 for variant in self.d.getVar("MULTILIB_VARIANTS").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500813 ml_target_rootfs = os.path.join(ml_temp, variant)
814
815 bb.utils.remove(ml_target_rootfs, True)
816
817 ml_opkg_conf = os.path.join(ml_temp,
818 variant + "-" + os.path.basename(self.opkg_conf))
819
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800820 ml_pm = OpkgPM(self.d, ml_target_rootfs, ml_opkg_conf, self.pkg_archs, prepare_index=False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500821
822 ml_pm.update()
823 ml_pm.install(pkgs)
824
825 dirs.append(ml_target_rootfs)
826
827 self._multilib_sanity_test(dirs)
828
829 '''
830 While ipk incremental image generation is enabled, it will remove the
831 unneeded pkgs by comparing the old full manifest in previous existing
832 image and the new full manifest in the current image.
833 '''
834 def _remove_extra_packages(self, pkgs_initial_install):
835 if self.inc_opkg_image_gen == "1":
836 # Parse full manifest in previous existing image creation session
837 old_full_manifest = self.manifest.parse_full_manifest()
838
839 # Create full manifest for the current image session, the old one
840 # will be replaced by the new one.
841 self.manifest.create_full(self.pm)
842
843 # Parse full manifest in current image creation session
844 new_full_manifest = self.manifest.parse_full_manifest()
845
846 pkg_to_remove = list()
847 for pkg in old_full_manifest:
848 if pkg not in new_full_manifest:
849 pkg_to_remove.append(pkg)
850
851 if pkg_to_remove != []:
852 bb.note('decremental removed: %s' % ' '.join(pkg_to_remove))
853 self.pm.remove(pkg_to_remove)
854
855 '''
856 Compare with previous existing image creation, if some conditions
857 triggered, the previous old image should be removed.
858 The conditions include any of 'PACKAGE_EXCLUDE, NO_RECOMMENDATIONS
859 and BAD_RECOMMENDATIONS' has been changed.
860 '''
861 def _remove_old_rootfs(self):
862 if self.inc_opkg_image_gen != "1":
863 return True
864
865 vars_list_file = self.d.expand('${T}/vars_list')
866
867 old_vars_list = ""
868 if os.path.exists(vars_list_file):
869 old_vars_list = open(vars_list_file, 'r+').read()
870
871 new_vars_list = '%s:%s:%s\n' % \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500872 ((self.d.getVar('BAD_RECOMMENDATIONS') or '').strip(),
873 (self.d.getVar('NO_RECOMMENDATIONS') or '').strip(),
874 (self.d.getVar('PACKAGE_EXCLUDE') or '').strip())
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500875 open(vars_list_file, 'w+').write(new_vars_list)
876
877 if old_vars_list != new_vars_list:
878 return True
879
880 return False
881
882 def _create(self):
883 pkgs_to_install = self.manifest.parse_initial_manifest()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500884 opkg_pre_process_cmds = self.d.getVar('OPKG_PREPROCESS_COMMANDS')
885 opkg_post_process_cmds = self.d.getVar('OPKG_POSTPROCESS_COMMANDS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500886
Brad Bishop004d4992018-10-02 23:54:45 +0200887 # update PM index files
888 self.pm.write_index()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500889
890 execute_pre_post_process(self.d, opkg_pre_process_cmds)
891
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600892 if self.progress_reporter:
893 self.progress_reporter.next_stage()
894 # Steps are a bit different in order, skip next
895 self.progress_reporter.next_stage()
896
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500897 self.pm.update()
898
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600899 if self.progress_reporter:
900 self.progress_reporter.next_stage()
901
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500902 if self.inc_opkg_image_gen == "1":
903 self._remove_extra_packages(pkgs_to_install)
904
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600905 if self.progress_reporter:
906 self.progress_reporter.next_stage()
907
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500908 for pkg_type in self.install_order:
909 if pkg_type in pkgs_to_install:
910 # For multilib, we perform a sanity test before final install
911 # If sanity test fails, it will automatically do a bb.fatal()
912 # and the installation will stop
913 if pkg_type == Manifest.PKG_TYPE_MULTILIB:
914 self._multilib_test_install(pkgs_to_install[pkg_type])
915
916 self.pm.install(pkgs_to_install[pkg_type],
917 [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
918
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600919 if self.progress_reporter:
920 self.progress_reporter.next_stage()
921
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500922 self.pm.install_complementary()
923
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600924 if self.progress_reporter:
925 self.progress_reporter.next_stage()
926
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500927 opkg_lib_dir = self.d.getVar('OPKGLIBDIR')
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500928 opkg_dir = os.path.join(opkg_lib_dir, 'opkg')
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500929 self._setup_dbg_rootfs([opkg_dir])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500930
931 execute_pre_post_process(self.d, opkg_post_process_cmds)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500932
933 if self.inc_opkg_image_gen == "1":
934 self.pm.backup_packaging_data()
935
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600936 if self.progress_reporter:
937 self.progress_reporter.next_stage()
938
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500939 @staticmethod
940 def _depends_list():
941 return ['IPKGCONF_SDK', 'IPK_FEED_URIS', 'DEPLOY_DIR_IPK', 'IPKGCONF_TARGET', 'INC_IPK_IMAGE_GEN', 'OPKG_ARGS', 'OPKGLIBDIR', 'OPKG_PREPROCESS_COMMANDS', 'OPKG_POSTPROCESS_COMMANDS', 'OPKGLIBDIR']
942
943 def _get_delayed_postinsts(self):
944 status_file = os.path.join(self.image_rootfs,
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500945 self.d.getVar('OPKGLIBDIR').strip('/'),
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500946 "opkg", "status")
947 return self._get_delayed_postinsts_common(status_file)
948
949 def _save_postinsts(self):
950 dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/ipk-postinsts")
951 src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${OPKGLIBDIR}/opkg/info")
952 return self._save_postinsts_common(dst_postinst_dir, src_postinst_dir)
953
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500954 def _log_check(self):
955 self._log_check_warn()
956 self._log_check_error()
957
958 def _cleanup(self):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500959 self.pm.remove_lists()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500960
961def get_class_for_type(imgtype):
962 return {"rpm": RpmRootfs,
963 "ipk": OpkgRootfs,
964 "deb": DpkgRootfs}[imgtype]
965
966def variable_depends(d, manifest_dir=None):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500967 img_type = d.getVar('IMAGE_PKGTYPE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500968 cls = get_class_for_type(img_type)
969 return cls._depends_list()
970
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500971def create_rootfs(d, manifest_dir=None, progress_reporter=None, logcatcher=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500972 env_bkp = os.environ.copy()
973
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500974 img_type = d.getVar('IMAGE_PKGTYPE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500975 if img_type == "rpm":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500976 RpmRootfs(d, manifest_dir, progress_reporter, logcatcher).create()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500977 elif img_type == "ipk":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500978 OpkgRootfs(d, manifest_dir, progress_reporter, logcatcher).create()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500979 elif img_type == "deb":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500980 DpkgRootfs(d, manifest_dir, progress_reporter, logcatcher).create()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500981
982 os.environ.clear()
983 os.environ.update(env_bkp)
984
985
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500986def image_list_installed_packages(d, rootfs_dir=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500987 if not rootfs_dir:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500988 rootfs_dir = d.getVar('IMAGE_ROOTFS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500989
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500990 img_type = d.getVar('IMAGE_PKGTYPE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500991 if img_type == "rpm":
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500992 return RpmPkgsList(d, rootfs_dir).list_pkgs()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500993 elif img_type == "ipk":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500994 return OpkgPkgsList(d, rootfs_dir, d.getVar("IPKGCONF_TARGET")).list_pkgs()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500995 elif img_type == "deb":
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500996 return DpkgPkgsList(d, rootfs_dir).list_pkgs()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500997
998if __name__ == "__main__":
999 """
1000 We should be able to run this as a standalone script, from outside bitbake
1001 environment.
1002 """
1003 """
1004 TBD
1005 """