blob: 754ef563abe54b316f22f501c065c5143ca6887f [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001from abc import ABCMeta, abstractmethod
2from oe.utils import execute_pre_post_process
3from oe.package_manager import *
4from oe.manifest import *
5import oe.path
6import filecmp
7import shutil
8import os
9import subprocess
10import re
11
12
Patrick Williamsc0f7c042017-02-23 20:41:17 -060013class Rootfs(object, metaclass=ABCMeta):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050014 """
15 This is an abstract class. Do not instantiate this directly.
16 """
Patrick Williamsc124f4f2015-09-15 14:41:29 -050017
Brad Bishop6e60e8b2018-02-01 10:27:11 -050018 def __init__(self, d, progress_reporter=None, logcatcher=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050019 self.d = d
20 self.pm = None
Brad Bishop6e60e8b2018-02-01 10:27:11 -050021 self.image_rootfs = self.d.getVar('IMAGE_ROOTFS')
22 self.deploydir = self.d.getVar('IMGDEPLOYDIR')
Patrick Williamsc0f7c042017-02-23 20:41:17 -060023 self.progress_reporter = progress_reporter
Brad Bishop6e60e8b2018-02-01 10:27:11 -050024 self.logcatcher = logcatcher
Patrick Williamsc124f4f2015-09-15 14:41:29 -050025
26 self.install_order = Manifest.INSTALL_ORDER
27
28 @abstractmethod
29 def _create(self):
30 pass
31
32 @abstractmethod
33 def _get_delayed_postinsts(self):
34 pass
35
36 @abstractmethod
37 def _save_postinsts(self):
38 pass
39
40 @abstractmethod
41 def _log_check(self):
42 pass
43
Patrick Williamsc0f7c042017-02-23 20:41:17 -060044 def _log_check_common(self, type, match):
45 # Ignore any lines containing log_check to avoid recursion, and ignore
46 # lines beginning with a + since sh -x may emit code which isn't
47 # actually executed, but may contain error messages
48 excludes = [ 'log_check', r'^\+' ]
49 if hasattr(self, 'log_check_expected_regexes'):
50 excludes.extend(self.log_check_expected_regexes)
51 excludes = [re.compile(x) for x in excludes]
52 r = re.compile(match)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050053 log_path = self.d.expand("${T}/log.do_rootfs")
Patrick Williamsc0f7c042017-02-23 20:41:17 -060054 messages = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -050055 with open(log_path, 'r') as log:
56 for line in log:
Brad Bishop6e60e8b2018-02-01 10:27:11 -050057 if self.logcatcher and self.logcatcher.contains(line.rstrip()):
58 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -060059 for ee in excludes:
60 m = ee.search(line)
61 if m:
62 break
63 if m:
Patrick Williamsc124f4f2015-09-15 14:41:29 -050064 continue
65
66 m = r.search(line)
67 if m:
Patrick Williamsc0f7c042017-02-23 20:41:17 -060068 messages.append('[log_check] %s' % line)
69 if messages:
70 if len(messages) == 1:
71 msg = '1 %s message' % type
72 else:
73 msg = '%d %s messages' % (len(messages), type)
74 msg = '[log_check] %s: found %s in the logfile:\n%s' % \
Brad Bishop6e60e8b2018-02-01 10:27:11 -050075 (self.d.getVar('PN'), msg, ''.join(messages))
Patrick Williamsc0f7c042017-02-23 20:41:17 -060076 if type == 'error':
77 bb.fatal(msg)
78 else:
79 bb.warn(msg)
80
81 def _log_check_warn(self):
82 self._log_check_common('warning', '^(warn|Warn|WARNING:)')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050083
84 def _log_check_error(self):
Patrick Williamsc0f7c042017-02-23 20:41:17 -060085 self._log_check_common('error', self.log_check_regex)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050086
87 def _insert_feed_uris(self):
88 if bb.utils.contains("IMAGE_FEATURES", "package-management",
89 True, False, self.d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -050090 self.pm.insert_feeds_uris(self.d.getVar('PACKAGE_FEED_URIS') or "",
91 self.d.getVar('PACKAGE_FEED_BASE_PATHS') or "",
92 self.d.getVar('PACKAGE_FEED_ARCHS'))
93
Patrick Williamsc124f4f2015-09-15 14:41:29 -050094
95 @abstractmethod
96 def _handle_intercept_failure(self, failed_script):
97 pass
98
99 """
100 The _cleanup() method should be used to clean-up stuff that we don't really
101 want to end up on target. For example, in the case of RPM, the DB locks.
102 The method is called, once, at the end of create() method.
103 """
104 @abstractmethod
105 def _cleanup(self):
106 pass
107
108 def _setup_dbg_rootfs(self, dirs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500109 gen_debugfs = self.d.getVar('IMAGE_GEN_DEBUGFS') or '0'
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500110 if gen_debugfs != '1':
111 return
112
113 bb.note(" Renaming the original rootfs...")
114 try:
115 shutil.rmtree(self.image_rootfs + '-orig')
116 except:
117 pass
118 os.rename(self.image_rootfs, self.image_rootfs + '-orig')
119
120 bb.note(" Creating debug rootfs...")
121 bb.utils.mkdirhier(self.image_rootfs)
122
123 bb.note(" Copying back package database...")
124 for dir in dirs:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600125 if not os.path.isdir(self.image_rootfs + '-orig' + dir):
126 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500127 bb.utils.mkdirhier(self.image_rootfs + os.path.dirname(dir))
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600128 shutil.copytree(self.image_rootfs + '-orig' + dir, self.image_rootfs + dir, symlinks=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500129
130 cpath = oe.cachedpath.CachedPath()
131 # Copy files located in /usr/lib/debug or /usr/src/debug
132 for dir in ["/usr/lib/debug", "/usr/src/debug"]:
133 src = self.image_rootfs + '-orig' + dir
134 if cpath.exists(src):
135 dst = self.image_rootfs + dir
136 bb.utils.mkdirhier(os.path.dirname(dst))
137 shutil.copytree(src, dst)
138
139 # Copy files with suffix '.debug' or located in '.debug' dir.
140 for root, dirs, files in cpath.walk(self.image_rootfs + '-orig'):
141 relative_dir = root[len(self.image_rootfs + '-orig'):]
142 for f in files:
143 if f.endswith('.debug') or '/.debug' in relative_dir:
144 bb.utils.mkdirhier(self.image_rootfs + relative_dir)
145 shutil.copy(os.path.join(root, f),
146 self.image_rootfs + relative_dir)
147
148 bb.note(" Install complementary '*-dbg' packages...")
149 self.pm.install_complementary('*-dbg')
150
151 bb.note(" Rename debug rootfs...")
152 try:
153 shutil.rmtree(self.image_rootfs + '-dbg')
154 except:
155 pass
156 os.rename(self.image_rootfs, self.image_rootfs + '-dbg')
157
158 bb.note(" Restoreing original rootfs...")
159 os.rename(self.image_rootfs + '-orig', self.image_rootfs)
160
161 def _exec_shell_cmd(self, cmd):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500162 fakerootcmd = self.d.getVar('FAKEROOT')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500163 if fakerootcmd is not None:
164 exec_cmd = [fakerootcmd, cmd]
165 else:
166 exec_cmd = cmd
167
168 try:
169 subprocess.check_output(exec_cmd, stderr=subprocess.STDOUT)
170 except subprocess.CalledProcessError as e:
171 return("Command '%s' returned %d:\n%s" % (e.cmd, e.returncode, e.output))
172
173 return None
174
175 def create(self):
176 bb.note("###### Generate rootfs #######")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500177 pre_process_cmds = self.d.getVar("ROOTFS_PREPROCESS_COMMAND")
178 post_process_cmds = self.d.getVar("ROOTFS_POSTPROCESS_COMMAND")
179 rootfs_post_install_cmds = self.d.getVar('ROOTFS_POSTINSTALL_COMMAND')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500180
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500181 postinst_intercepts_dir = self.d.getVar("POSTINST_INTERCEPTS_DIR")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500182 if not postinst_intercepts_dir:
183 postinst_intercepts_dir = self.d.expand("${COREBASE}/scripts/postinst-intercepts")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500184 intercepts_dir = os.path.join(self.d.getVar('WORKDIR'),
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500185 "intercept_scripts")
186
187 bb.utils.remove(intercepts_dir, True)
188
189 bb.utils.mkdirhier(self.image_rootfs)
190
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600191 bb.utils.mkdirhier(self.deploydir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500192
193 shutil.copytree(postinst_intercepts_dir, intercepts_dir)
194
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500195 execute_pre_post_process(self.d, pre_process_cmds)
196
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600197 if self.progress_reporter:
198 self.progress_reporter.next_stage()
199
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500200 # call the package manager dependent create method
201 self._create()
202
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500203 sysconfdir = self.image_rootfs + self.d.getVar('sysconfdir')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500204 bb.utils.mkdirhier(sysconfdir)
205 with open(sysconfdir + "/version", "w+") as ver:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500206 ver.write(self.d.getVar('BUILDNAME') + "\n")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500207
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500208 execute_pre_post_process(self.d, rootfs_post_install_cmds)
209
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500210 self._run_intercepts()
211
212 execute_pre_post_process(self.d, post_process_cmds)
213
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600214 if self.progress_reporter:
215 self.progress_reporter.next_stage()
216
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500217 if bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs",
218 True, False, self.d):
219 delayed_postinsts = self._get_delayed_postinsts()
220 if delayed_postinsts is not None:
221 bb.fatal("The following packages could not be configured "
222 "offline and rootfs is read-only: %s" %
223 delayed_postinsts)
224
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500225 if self.d.getVar('USE_DEVFS') != "1":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500226 self._create_devfs()
227
228 self._uninstall_unneeded()
229
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600230 if self.progress_reporter:
231 self.progress_reporter.next_stage()
232
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500233 self._insert_feed_uris()
234
235 self._run_ldconfig()
236
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500237 if self.d.getVar('USE_DEPMOD') != "0":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500238 self._generate_kernel_module_deps()
239
240 self._cleanup()
241 self._log_check()
242
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600243 if self.progress_reporter:
244 self.progress_reporter.next_stage()
245
246
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500247 def _uninstall_unneeded(self):
248 # Remove unneeded init script symlinks
249 delayed_postinsts = self._get_delayed_postinsts()
250 if delayed_postinsts is None:
251 if os.path.exists(self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/init.d/run-postinsts")):
252 self._exec_shell_cmd(["update-rc.d", "-f", "-r",
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500253 self.d.getVar('IMAGE_ROOTFS'),
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500254 "run-postinsts", "remove"])
255
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500256 image_rorfs = bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs",
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500257 True, False, self.d)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500258 image_rorfs_force = self.d.getVar('FORCE_RO_REMOVE')
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600259
260 if image_rorfs or image_rorfs_force == "1":
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500261 # Remove components that we don't need if it's a read-only rootfs
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500262 unneeded_pkgs = self.d.getVar("ROOTFS_RO_UNNEEDED").split()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500263 pkgs_installed = image_list_installed_packages(self.d)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500264 # Make sure update-alternatives is removed last. This is
265 # because its database has to available while uninstalling
266 # other packages, allowing alternative symlinks of packages
267 # to be uninstalled or to be managed correctly otherwise.
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500268 provider = self.d.getVar("VIRTUAL-RUNTIME_update-alternatives")
269 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 -0500270
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500271 # update-alternatives provider is removed in its own remove()
272 # call because all package managers do not guarantee the packages
273 # are removed in the order they given in the list (which is
274 # passed to the command line). The sorting done earlier is
275 # utilized to implement the 2-stage removal.
276 if len(pkgs_to_remove) > 1:
277 self.pm.remove(pkgs_to_remove[:-1], False)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500278 if len(pkgs_to_remove) > 0:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500279 self.pm.remove([pkgs_to_remove[-1]], False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500280
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500281 if delayed_postinsts:
282 self._save_postinsts()
283 if image_rorfs:
284 bb.warn("There are post install scripts "
285 "in a read-only rootfs")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500286
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500287 post_uninstall_cmds = self.d.getVar("ROOTFS_POSTUNINSTALL_COMMAND")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500288 execute_pre_post_process(self.d, post_uninstall_cmds)
289
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500290 runtime_pkgmanage = bb.utils.contains("IMAGE_FEATURES", "package-management",
291 True, False, self.d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500292 if not runtime_pkgmanage:
293 # Remove the package manager data files
294 self.pm.remove_packaging_data()
295
296 def _run_intercepts(self):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500297 intercepts_dir = os.path.join(self.d.getVar('WORKDIR'),
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500298 "intercept_scripts")
299
300 bb.note("Running intercept scripts:")
301 os.environ['D'] = self.image_rootfs
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500302 os.environ['STAGING_DIR_NATIVE'] = self.d.getVar('STAGING_DIR_NATIVE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500303 for script in os.listdir(intercepts_dir):
304 script_full = os.path.join(intercepts_dir, script)
305
306 if script == "postinst_intercept" or not os.access(script_full, os.X_OK):
307 continue
308
309 bb.note("> Executing %s intercept ..." % script)
310
311 try:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500312 output = subprocess.check_output(script_full, stderr=subprocess.STDOUT)
313 if output: bb.note(output.decode("utf-8"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500314 except subprocess.CalledProcessError as e:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500315 bb.warn("The postinstall intercept hook '%s' failed, details in log.do_rootfs" % script)
316 bb.note("Exit code %d. Output:\n%s" % (e.returncode, e.output.decode("utf-8")))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500317
318 with open(script_full) as intercept:
319 registered_pkgs = None
320 for line in intercept.read().split("\n"):
321 m = re.match("^##PKGS:(.*)", line)
322 if m is not None:
323 registered_pkgs = m.group(1).strip()
324 break
325
326 if registered_pkgs is not None:
327 bb.warn("The postinstalls for the following packages "
328 "will be postponed for first boot: %s" %
329 registered_pkgs)
330
331 # call the backend dependent handler
332 self._handle_intercept_failure(registered_pkgs)
333
334 def _run_ldconfig(self):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500335 if self.d.getVar('LDCONFIGDEPEND'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500336 bb.note("Executing: ldconfig -r" + self.image_rootfs + "-c new -v")
337 self._exec_shell_cmd(['ldconfig', '-r', self.image_rootfs, '-c',
338 'new', '-v'])
339
340 def _check_for_kernel_modules(self, modules_dir):
341 for root, dirs, files in os.walk(modules_dir, topdown=True):
342 for name in files:
343 found_ko = name.endswith(".ko")
344 if found_ko:
345 return found_ko
346 return False
347
348 def _generate_kernel_module_deps(self):
349 modules_dir = os.path.join(self.image_rootfs, 'lib', 'modules')
350 # if we don't have any modules don't bother to do the depmod
351 if not self._check_for_kernel_modules(modules_dir):
352 bb.note("No Kernel Modules found, not running depmod")
353 return
354
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500355 kernel_abi_ver_file = oe.path.join(self.d.getVar('PKGDATA_DIR'), "kernel-depmod",
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500356 'kernel-abiversion')
357 if not os.path.exists(kernel_abi_ver_file):
358 bb.fatal("No kernel-abiversion file found (%s), cannot run depmod, aborting" % kernel_abi_ver_file)
359
360 kernel_ver = open(kernel_abi_ver_file).read().strip(' \n')
361 versioned_modules_dir = os.path.join(self.image_rootfs, modules_dir, kernel_ver)
362
363 bb.utils.mkdirhier(versioned_modules_dir)
364
365 self._exec_shell_cmd(['depmodwrapper', '-a', '-b', self.image_rootfs, kernel_ver])
366
367 """
368 Create devfs:
369 * IMAGE_DEVICE_TABLE is the old name to an absolute path to a device table file
370 * IMAGE_DEVICE_TABLES is a new name for a file, or list of files, seached
371 for in the BBPATH
372 If neither are specified then the default name of files/device_table-minimal.txt
373 is searched for in the BBPATH (same as the old version.)
374 """
375 def _create_devfs(self):
376 devtable_list = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500377 devtable = self.d.getVar('IMAGE_DEVICE_TABLE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500378 if devtable is not None:
379 devtable_list.append(devtable)
380 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500381 devtables = self.d.getVar('IMAGE_DEVICE_TABLES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500382 if devtables is None:
383 devtables = 'files/device_table-minimal.txt'
384 for devtable in devtables.split():
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500385 devtable_list.append("%s" % bb.utils.which(self.d.getVar('BBPATH'), devtable))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500386
387 for devtable in devtable_list:
388 self._exec_shell_cmd(["makedevs", "-r",
389 self.image_rootfs, "-D", devtable])
390
391
392class RpmRootfs(Rootfs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500393 def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None):
394 super(RpmRootfs, self).__init__(d, progress_reporter, logcatcher)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500395 self.log_check_regex = '(unpacking of archive failed|Cannot find package'\
396 '|exit 1|ERROR: |Error: |Error |ERROR '\
397 '|Failed |Failed: |Failed$|Failed\(\d+\):)'
398 self.manifest = RpmManifest(d, manifest_dir)
399
400 self.pm = RpmPM(d,
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500401 d.getVar('IMAGE_ROOTFS'),
402 self.d.getVar('TARGET_VENDOR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500403 )
404
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500405 self.inc_rpm_image_gen = self.d.getVar('INC_RPM_IMAGE_GEN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500406 if self.inc_rpm_image_gen != "1":
407 bb.utils.remove(self.image_rootfs, True)
408 else:
409 self.pm.recovery_packaging_data()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500410 bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500411
412 self.pm.create_configs()
413
414 '''
415 While rpm incremental image generation is enabled, it will remove the
416 unneeded pkgs by comparing the new install solution manifest and the
417 old installed manifest.
418 '''
419 def _create_incremental(self, pkgs_initial_install):
420 if self.inc_rpm_image_gen == "1":
421
422 pkgs_to_install = list()
423 for pkg_type in pkgs_initial_install:
424 pkgs_to_install += pkgs_initial_install[pkg_type]
425
426 installed_manifest = self.pm.load_old_install_solution()
427 solution_manifest = self.pm.dump_install_solution(pkgs_to_install)
428
429 pkg_to_remove = list()
430 for pkg in installed_manifest:
431 if pkg not in solution_manifest:
432 pkg_to_remove.append(pkg)
433
434 self.pm.update()
435
436 bb.note('incremental update -- upgrade packages in place ')
437 self.pm.upgrade()
438 if pkg_to_remove != []:
439 bb.note('incremental removed: %s' % ' '.join(pkg_to_remove))
440 self.pm.remove(pkg_to_remove)
441
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500442 self.pm.autoremove()
443
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500444 def _create(self):
445 pkgs_to_install = self.manifest.parse_initial_manifest()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500446 rpm_pre_process_cmds = self.d.getVar('RPM_PREPROCESS_COMMANDS')
447 rpm_post_process_cmds = self.d.getVar('RPM_POSTPROCESS_COMMANDS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500448
449 # update PM index files
450 self.pm.write_index()
451
452 execute_pre_post_process(self.d, rpm_pre_process_cmds)
453
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600454 if self.progress_reporter:
455 self.progress_reporter.next_stage()
456
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500457 if self.inc_rpm_image_gen == "1":
458 self._create_incremental(pkgs_to_install)
459
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600460 if self.progress_reporter:
461 self.progress_reporter.next_stage()
462
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500463 self.pm.update()
464
465 pkgs = []
466 pkgs_attempt = []
467 for pkg_type in pkgs_to_install:
468 if pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY:
469 pkgs_attempt += pkgs_to_install[pkg_type]
470 else:
471 pkgs += pkgs_to_install[pkg_type]
472
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600473 if self.progress_reporter:
474 self.progress_reporter.next_stage()
475
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500476 self.pm.install(pkgs)
477
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600478 if self.progress_reporter:
479 self.progress_reporter.next_stage()
480
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500481 self.pm.install(pkgs_attempt, True)
482
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600483 if self.progress_reporter:
484 self.progress_reporter.next_stage()
485
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500486 self.pm.install_complementary()
487
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600488 if self.progress_reporter:
489 self.progress_reporter.next_stage()
490
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500491 self._setup_dbg_rootfs(['/etc', '/var/lib/rpm', '/var/cache/dnf', '/var/lib/dnf'])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500492
493 execute_pre_post_process(self.d, rpm_post_process_cmds)
494
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500495 if self.inc_rpm_image_gen == "1":
496 self.pm.backup_packaging_data()
497
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600498 if self.progress_reporter:
499 self.progress_reporter.next_stage()
500
501
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500502 @staticmethod
503 def _depends_list():
504 return ['DEPLOY_DIR_RPM', 'INC_RPM_IMAGE_GEN', 'RPM_PREPROCESS_COMMANDS',
505 'RPM_POSTPROCESS_COMMANDS', 'RPM_PREFER_ELF_ARCH']
506
507 def _get_delayed_postinsts(self):
508 postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/rpm-postinsts")
509 if os.path.isdir(postinst_dir):
510 files = os.listdir(postinst_dir)
511 for f in files:
512 bb.note('Delayed package scriptlet: %s' % f)
513 return files
514
515 return None
516
517 def _save_postinsts(self):
518 # this is just a stub. For RPM, the failed postinstalls are
519 # already saved in /etc/rpm-postinsts
520 pass
521
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500522 def _log_check(self):
523 self._log_check_warn()
524 self._log_check_error()
525
526 def _handle_intercept_failure(self, registered_pkgs):
527 rpm_postinsts_dir = self.image_rootfs + self.d.expand('${sysconfdir}/rpm-postinsts/')
528 bb.utils.mkdirhier(rpm_postinsts_dir)
529
530 # Save the package postinstalls in /etc/rpm-postinsts
531 for pkg in registered_pkgs.split():
532 self.pm.save_rpmpostinst(pkg)
533
534 def _cleanup(self):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500535 self.pm._invoke_dnf(["clean", "all"])
536
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500537
538class DpkgOpkgRootfs(Rootfs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500539 def __init__(self, d, progress_reporter=None, logcatcher=None):
540 super(DpkgOpkgRootfs, self).__init__(d, progress_reporter, logcatcher)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500541
542 def _get_pkgs_postinsts(self, status_file):
543 def _get_pkg_depends_list(pkg_depends):
544 pkg_depends_list = []
545 # filter version requirements like libc (>= 1.1)
546 for dep in pkg_depends.split(', '):
547 m_dep = re.match("^(.*) \(.*\)$", dep)
548 if m_dep:
549 dep = m_dep.group(1)
550 pkg_depends_list.append(dep)
551
552 return pkg_depends_list
553
554 pkgs = {}
555 pkg_name = ""
556 pkg_status_match = False
557 pkg_depends = ""
558
559 with open(status_file) as status:
560 data = status.read()
561 status.close()
562 for line in data.split('\n'):
563 m_pkg = re.match("^Package: (.*)", line)
564 m_status = re.match("^Status:.*unpacked", line)
565 m_depends = re.match("^Depends: (.*)", line)
566
567 if m_pkg is not None:
568 if pkg_name and pkg_status_match:
569 pkgs[pkg_name] = _get_pkg_depends_list(pkg_depends)
570
571 pkg_name = m_pkg.group(1)
572 pkg_status_match = False
573 pkg_depends = ""
574 elif m_status is not None:
575 pkg_status_match = True
576 elif m_depends is not None:
577 pkg_depends = m_depends.group(1)
578
579 # remove package dependencies not in postinsts
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600580 pkg_names = list(pkgs.keys())
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500581 for pkg_name in pkg_names:
582 deps = pkgs[pkg_name][:]
583
584 for d in deps:
585 if d not in pkg_names:
586 pkgs[pkg_name].remove(d)
587
588 return pkgs
589
590 def _get_delayed_postinsts_common(self, status_file):
591 def _dep_resolve(graph, node, resolved, seen):
592 seen.append(node)
593
594 for edge in graph[node]:
595 if edge not in resolved:
596 if edge in seen:
597 raise RuntimeError("Packages %s and %s have " \
598 "a circular dependency in postinsts scripts." \
599 % (node, edge))
600 _dep_resolve(graph, edge, resolved, seen)
601
602 resolved.append(node)
603
604 pkg_list = []
605
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500606 pkgs = None
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500607 if not self.d.getVar('PACKAGE_INSTALL').strip():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500608 bb.note("Building empty image")
609 else:
610 pkgs = self._get_pkgs_postinsts(status_file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500611 if pkgs:
612 root = "__packagegroup_postinst__"
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600613 pkgs[root] = list(pkgs.keys())
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500614 _dep_resolve(pkgs, root, pkg_list, [])
615 pkg_list.remove(root)
616
617 if len(pkg_list) == 0:
618 return None
619
620 return pkg_list
621
622 def _save_postinsts_common(self, dst_postinst_dir, src_postinst_dir):
623 num = 0
624 for p in self._get_delayed_postinsts():
625 bb.utils.mkdirhier(dst_postinst_dir)
626
627 if os.path.exists(os.path.join(src_postinst_dir, p + ".postinst")):
628 shutil.copy(os.path.join(src_postinst_dir, p + ".postinst"),
629 os.path.join(dst_postinst_dir, "%03d-%s" % (num, p)))
630
631 num += 1
632
633class DpkgRootfs(DpkgOpkgRootfs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500634 def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None):
635 super(DpkgRootfs, self).__init__(d, progress_reporter, logcatcher)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500636 self.log_check_regex = '^E:'
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600637 self.log_check_expected_regexes = \
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500638 [
639 "^E: Unmet dependencies."
640 ]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500641
642 bb.utils.remove(self.image_rootfs, True)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500643 bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500644 self.manifest = DpkgManifest(d, manifest_dir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500645 self.pm = DpkgPM(d, d.getVar('IMAGE_ROOTFS'),
646 d.getVar('PACKAGE_ARCHS'),
647 d.getVar('DPKG_ARCH'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500648
649
650 def _create(self):
651 pkgs_to_install = self.manifest.parse_initial_manifest()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500652 deb_pre_process_cmds = self.d.getVar('DEB_PREPROCESS_COMMANDS')
653 deb_post_process_cmds = self.d.getVar('DEB_POSTPROCESS_COMMANDS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500654
655 alt_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/alternatives")
656 bb.utils.mkdirhier(alt_dir)
657
658 # update PM index files
659 self.pm.write_index()
660
661 execute_pre_post_process(self.d, deb_pre_process_cmds)
662
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600663 if self.progress_reporter:
664 self.progress_reporter.next_stage()
665 # Don't support incremental, so skip that
666 self.progress_reporter.next_stage()
667
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500668 self.pm.update()
669
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600670 if self.progress_reporter:
671 self.progress_reporter.next_stage()
672
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500673 for pkg_type in self.install_order:
674 if pkg_type in pkgs_to_install:
675 self.pm.install(pkgs_to_install[pkg_type],
676 [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
677
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600678 if self.progress_reporter:
679 # Don't support attemptonly, so skip that
680 self.progress_reporter.next_stage()
681 self.progress_reporter.next_stage()
682
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500683 self.pm.install_complementary()
684
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600685 if self.progress_reporter:
686 self.progress_reporter.next_stage()
687
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500688 self._setup_dbg_rootfs(['/var/lib/dpkg'])
689
690 self.pm.fix_broken_dependencies()
691
692 self.pm.mark_packages("installed")
693
694 self.pm.run_pre_post_installs()
695
696 execute_pre_post_process(self.d, deb_post_process_cmds)
697
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600698 if self.progress_reporter:
699 self.progress_reporter.next_stage()
700
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500701 @staticmethod
702 def _depends_list():
703 return ['DEPLOY_DIR_DEB', 'DEB_SDK_ARCH', 'APTCONF_TARGET', 'APT_ARGS', 'DPKG_ARCH', 'DEB_PREPROCESS_COMMANDS', 'DEB_POSTPROCESS_COMMANDS']
704
705 def _get_delayed_postinsts(self):
706 status_file = self.image_rootfs + "/var/lib/dpkg/status"
707 return self._get_delayed_postinsts_common(status_file)
708
709 def _save_postinsts(self):
710 dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/deb-postinsts")
711 src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/info")
712 return self._save_postinsts_common(dst_postinst_dir, src_postinst_dir)
713
714 def _handle_intercept_failure(self, registered_pkgs):
715 self.pm.mark_packages("unpacked", registered_pkgs.split())
716
717 def _log_check(self):
718 self._log_check_warn()
719 self._log_check_error()
720
721 def _cleanup(self):
722 pass
723
724
725class OpkgRootfs(DpkgOpkgRootfs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500726 def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None):
727 super(OpkgRootfs, self).__init__(d, progress_reporter, logcatcher)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500728 self.log_check_regex = '(exit 1|Collected errors)'
729
730 self.manifest = OpkgManifest(d, manifest_dir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500731 self.opkg_conf = self.d.getVar("IPKGCONF_TARGET")
732 self.pkg_archs = self.d.getVar("ALL_MULTILIB_PACKAGE_ARCHS")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500733
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500734 self.inc_opkg_image_gen = self.d.getVar('INC_IPK_IMAGE_GEN') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500735 if self._remove_old_rootfs():
736 bb.utils.remove(self.image_rootfs, True)
737 self.pm = OpkgPM(d,
738 self.image_rootfs,
739 self.opkg_conf,
740 self.pkg_archs)
741 else:
742 self.pm = OpkgPM(d,
743 self.image_rootfs,
744 self.opkg_conf,
745 self.pkg_archs)
746 self.pm.recover_packaging_data()
747
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500748 bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500749
750 def _prelink_file(self, root_dir, filename):
751 bb.note('prelink %s in %s' % (filename, root_dir))
752 prelink_cfg = oe.path.join(root_dir,
753 self.d.expand('${sysconfdir}/prelink.conf'))
754 if not os.path.exists(prelink_cfg):
755 shutil.copy(self.d.expand('${STAGING_DIR_NATIVE}${sysconfdir_native}/prelink.conf'),
756 prelink_cfg)
757
758 cmd_prelink = self.d.expand('${STAGING_DIR_NATIVE}${sbindir_native}/prelink')
759 self._exec_shell_cmd([cmd_prelink,
760 '--root',
761 root_dir,
762 '-amR',
763 '-N',
764 '-c',
765 self.d.expand('${sysconfdir}/prelink.conf')])
766
767 '''
768 Compare two files with the same key twice to see if they are equal.
769 If they are not equal, it means they are duplicated and come from
770 different packages.
771 1st: Comapre them directly;
772 2nd: While incremental image creation is enabled, one of the
773 files could be probaly prelinked in the previous image
774 creation and the file has been changed, so we need to
775 prelink the other one and compare them.
776 '''
777 def _file_equal(self, key, f1, f2):
778
779 # Both of them are not prelinked
780 if filecmp.cmp(f1, f2):
781 return True
782
783 if self.image_rootfs not in f1:
784 self._prelink_file(f1.replace(key, ''), f1)
785
786 if self.image_rootfs not in f2:
787 self._prelink_file(f2.replace(key, ''), f2)
788
789 # Both of them are prelinked
790 if filecmp.cmp(f1, f2):
791 return True
792
793 # Not equal
794 return False
795
796 """
797 This function was reused from the old implementation.
798 See commit: "image.bbclass: Added variables for multilib support." by
799 Lianhao Lu.
800 """
801 def _multilib_sanity_test(self, dirs):
802
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500803 allow_replace = self.d.getVar("MULTILIBRE_ALLOW_REP")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500804 if allow_replace is None:
805 allow_replace = ""
806
807 allow_rep = re.compile(re.sub("\|$", "", allow_replace))
808 error_prompt = "Multilib check error:"
809
810 files = {}
811 for dir in dirs:
812 for root, subfolders, subfiles in os.walk(dir):
813 for file in subfiles:
814 item = os.path.join(root, file)
815 key = str(os.path.join("/", os.path.relpath(item, dir)))
816
817 valid = True
818 if key in files:
819 #check whether the file is allow to replace
820 if allow_rep.match(key):
821 valid = True
822 else:
823 if os.path.exists(files[key]) and \
824 os.path.exists(item) and \
825 not self._file_equal(key, files[key], item):
826 valid = False
827 bb.fatal("%s duplicate files %s %s is not the same\n" %
828 (error_prompt, item, files[key]))
829
830 #pass the check, add to list
831 if valid:
832 files[key] = item
833
834 def _multilib_test_install(self, pkgs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500835 ml_temp = self.d.getVar("MULTILIB_TEMP_ROOTFS")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500836 bb.utils.mkdirhier(ml_temp)
837
838 dirs = [self.image_rootfs]
839
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500840 for variant in self.d.getVar("MULTILIB_VARIANTS").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500841 ml_target_rootfs = os.path.join(ml_temp, variant)
842
843 bb.utils.remove(ml_target_rootfs, True)
844
845 ml_opkg_conf = os.path.join(ml_temp,
846 variant + "-" + os.path.basename(self.opkg_conf))
847
848 ml_pm = OpkgPM(self.d, ml_target_rootfs, ml_opkg_conf, self.pkg_archs)
849
850 ml_pm.update()
851 ml_pm.install(pkgs)
852
853 dirs.append(ml_target_rootfs)
854
855 self._multilib_sanity_test(dirs)
856
857 '''
858 While ipk incremental image generation is enabled, it will remove the
859 unneeded pkgs by comparing the old full manifest in previous existing
860 image and the new full manifest in the current image.
861 '''
862 def _remove_extra_packages(self, pkgs_initial_install):
863 if self.inc_opkg_image_gen == "1":
864 # Parse full manifest in previous existing image creation session
865 old_full_manifest = self.manifest.parse_full_manifest()
866
867 # Create full manifest for the current image session, the old one
868 # will be replaced by the new one.
869 self.manifest.create_full(self.pm)
870
871 # Parse full manifest in current image creation session
872 new_full_manifest = self.manifest.parse_full_manifest()
873
874 pkg_to_remove = list()
875 for pkg in old_full_manifest:
876 if pkg not in new_full_manifest:
877 pkg_to_remove.append(pkg)
878
879 if pkg_to_remove != []:
880 bb.note('decremental removed: %s' % ' '.join(pkg_to_remove))
881 self.pm.remove(pkg_to_remove)
882
883 '''
884 Compare with previous existing image creation, if some conditions
885 triggered, the previous old image should be removed.
886 The conditions include any of 'PACKAGE_EXCLUDE, NO_RECOMMENDATIONS
887 and BAD_RECOMMENDATIONS' has been changed.
888 '''
889 def _remove_old_rootfs(self):
890 if self.inc_opkg_image_gen != "1":
891 return True
892
893 vars_list_file = self.d.expand('${T}/vars_list')
894
895 old_vars_list = ""
896 if os.path.exists(vars_list_file):
897 old_vars_list = open(vars_list_file, 'r+').read()
898
899 new_vars_list = '%s:%s:%s\n' % \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500900 ((self.d.getVar('BAD_RECOMMENDATIONS') or '').strip(),
901 (self.d.getVar('NO_RECOMMENDATIONS') or '').strip(),
902 (self.d.getVar('PACKAGE_EXCLUDE') or '').strip())
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500903 open(vars_list_file, 'w+').write(new_vars_list)
904
905 if old_vars_list != new_vars_list:
906 return True
907
908 return False
909
910 def _create(self):
911 pkgs_to_install = self.manifest.parse_initial_manifest()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500912 opkg_pre_process_cmds = self.d.getVar('OPKG_PREPROCESS_COMMANDS')
913 opkg_post_process_cmds = self.d.getVar('OPKG_POSTPROCESS_COMMANDS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500914
915 # update PM index files, unless users provide their own feeds
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500916 if (self.d.getVar('BUILD_IMAGES_FROM_FEEDS') or "") != "1":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500917 self.pm.write_index()
918
919 execute_pre_post_process(self.d, opkg_pre_process_cmds)
920
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600921 if self.progress_reporter:
922 self.progress_reporter.next_stage()
923 # Steps are a bit different in order, skip next
924 self.progress_reporter.next_stage()
925
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500926 self.pm.update()
927
928 self.pm.handle_bad_recommendations()
929
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600930 if self.progress_reporter:
931 self.progress_reporter.next_stage()
932
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500933 if self.inc_opkg_image_gen == "1":
934 self._remove_extra_packages(pkgs_to_install)
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 for pkg_type in self.install_order:
940 if pkg_type in pkgs_to_install:
941 # For multilib, we perform a sanity test before final install
942 # If sanity test fails, it will automatically do a bb.fatal()
943 # and the installation will stop
944 if pkg_type == Manifest.PKG_TYPE_MULTILIB:
945 self._multilib_test_install(pkgs_to_install[pkg_type])
946
947 self.pm.install(pkgs_to_install[pkg_type],
948 [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
949
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600950 if self.progress_reporter:
951 self.progress_reporter.next_stage()
952
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500953 self.pm.install_complementary()
954
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600955 if self.progress_reporter:
956 self.progress_reporter.next_stage()
957
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500958 opkg_lib_dir = self.d.getVar('OPKGLIBDIR')
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500959 opkg_dir = os.path.join(opkg_lib_dir, 'opkg')
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500960 self._setup_dbg_rootfs([opkg_dir])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500961
962 execute_pre_post_process(self.d, opkg_post_process_cmds)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500963
964 if self.inc_opkg_image_gen == "1":
965 self.pm.backup_packaging_data()
966
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600967 if self.progress_reporter:
968 self.progress_reporter.next_stage()
969
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500970 @staticmethod
971 def _depends_list():
972 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']
973
974 def _get_delayed_postinsts(self):
975 status_file = os.path.join(self.image_rootfs,
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500976 self.d.getVar('OPKGLIBDIR').strip('/'),
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500977 "opkg", "status")
978 return self._get_delayed_postinsts_common(status_file)
979
980 def _save_postinsts(self):
981 dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/ipk-postinsts")
982 src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${OPKGLIBDIR}/opkg/info")
983 return self._save_postinsts_common(dst_postinst_dir, src_postinst_dir)
984
985 def _handle_intercept_failure(self, registered_pkgs):
986 self.pm.mark_packages("unpacked", registered_pkgs.split())
987
988 def _log_check(self):
989 self._log_check_warn()
990 self._log_check_error()
991
992 def _cleanup(self):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500993 self.pm.remove_lists()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500994
995def get_class_for_type(imgtype):
996 return {"rpm": RpmRootfs,
997 "ipk": OpkgRootfs,
998 "deb": DpkgRootfs}[imgtype]
999
1000def variable_depends(d, manifest_dir=None):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001001 img_type = d.getVar('IMAGE_PKGTYPE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001002 cls = get_class_for_type(img_type)
1003 return cls._depends_list()
1004
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001005def create_rootfs(d, manifest_dir=None, progress_reporter=None, logcatcher=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001006 env_bkp = os.environ.copy()
1007
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001008 img_type = d.getVar('IMAGE_PKGTYPE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001009 if img_type == "rpm":
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001010 RpmRootfs(d, manifest_dir, progress_reporter, logcatcher).create()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001011 elif img_type == "ipk":
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001012 OpkgRootfs(d, manifest_dir, progress_reporter, logcatcher).create()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001013 elif img_type == "deb":
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001014 DpkgRootfs(d, manifest_dir, progress_reporter, logcatcher).create()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001015
1016 os.environ.clear()
1017 os.environ.update(env_bkp)
1018
1019
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001020def image_list_installed_packages(d, rootfs_dir=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001021 if not rootfs_dir:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001022 rootfs_dir = d.getVar('IMAGE_ROOTFS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001023
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001024 img_type = d.getVar('IMAGE_PKGTYPE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001025 if img_type == "rpm":
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001026 return RpmPkgsList(d, rootfs_dir).list_pkgs()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001027 elif img_type == "ipk":
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001028 return OpkgPkgsList(d, rootfs_dir, d.getVar("IPKGCONF_TARGET")).list_pkgs()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001029 elif img_type == "deb":
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001030 return DpkgPkgsList(d, rootfs_dir).list_pkgs()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001031
1032if __name__ == "__main__":
1033 """
1034 We should be able to run this as a standalone script, from outside bitbake
1035 environment.
1036 """
1037 """
1038 TBD
1039 """