| Brad Bishop | c342db3 | 2019-05-15 21:57:59 -0400 | [diff] [blame] | 1 | # | 
| Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 2 | # Copyright OpenEmbedded Contributors | 
|  | 3 | # | 
| Brad Bishop | c342db3 | 2019-05-15 21:57:59 -0400 | [diff] [blame] | 4 | # SPDX-License-Identifier: GPL-2.0-only | 
|  | 5 | # | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 6 | from abc import ABCMeta, abstractmethod | 
|  | 7 | from oe.utils import execute_pre_post_process | 
|  | 8 | from oe.package_manager import * | 
|  | 9 | from oe.manifest import * | 
|  | 10 | import oe.path | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 11 | import shutil | 
|  | 12 | import os | 
|  | 13 | import subprocess | 
|  | 14 | import re | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 15 |  | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 16 | class Rootfs(object, metaclass=ABCMeta): | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 17 | """ | 
|  | 18 | This is an abstract class. Do not instantiate this directly. | 
|  | 19 | """ | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 20 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 21 | def __init__(self, d, progress_reporter=None, logcatcher=None): | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 22 | self.d = d | 
|  | 23 | self.pm = None | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 24 | self.image_rootfs = self.d.getVar('IMAGE_ROOTFS') | 
|  | 25 | self.deploydir = self.d.getVar('IMGDEPLOYDIR') | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 26 | self.progress_reporter = progress_reporter | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 27 | self.logcatcher = logcatcher | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 28 |  | 
|  | 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 Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 47 | 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) | 
| Andrew Geissler | 4c19ea1 | 2020-10-27 13:52:24 -0500 | [diff] [blame] | 54 | # Insert custom log_check excludes | 
|  | 55 | excludes += [x for x in (self.d.getVar("IMAGE_LOG_CHECK_EXCLUDES") or "").split(" ") if x] | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 56 | excludes = [re.compile(x) for x in excludes] | 
|  | 57 | r = re.compile(match) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 58 | log_path = self.d.expand("${T}/log.do_rootfs") | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 59 | messages = [] | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 60 | with open(log_path, 'r') as log: | 
|  | 61 | for line in log: | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 62 | if self.logcatcher and self.logcatcher.contains(line.rstrip()): | 
|  | 63 | continue | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 64 | for ee in excludes: | 
|  | 65 | m = ee.search(line) | 
|  | 66 | if m: | 
|  | 67 | break | 
|  | 68 | if m: | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 69 | continue | 
|  | 70 |  | 
|  | 71 | m = r.search(line) | 
|  | 72 | if m: | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 73 | messages.append('[log_check] %s' % line) | 
|  | 74 | if messages: | 
|  | 75 | if len(messages) == 1: | 
|  | 76 | msg = '1 %s message' % type | 
|  | 77 | else: | 
|  | 78 | msg = '%d %s messages' % (len(messages), type) | 
|  | 79 | msg = '[log_check] %s: found %s in the logfile:\n%s' % \ | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 80 | (self.d.getVar('PN'), msg, ''.join(messages)) | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 81 | if type == 'error': | 
|  | 82 | bb.fatal(msg) | 
|  | 83 | else: | 
|  | 84 | bb.warn(msg) | 
|  | 85 |  | 
|  | 86 | def _log_check_warn(self): | 
|  | 87 | self._log_check_common('warning', '^(warn|Warn|WARNING:)') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 88 |  | 
|  | 89 | def _log_check_error(self): | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 90 | self._log_check_common('error', self.log_check_regex) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 91 |  | 
|  | 92 | def _insert_feed_uris(self): | 
|  | 93 | if bb.utils.contains("IMAGE_FEATURES", "package-management", | 
|  | 94 | True, False, self.d): | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 95 | self.pm.insert_feeds_uris(self.d.getVar('PACKAGE_FEED_URIS') or "", | 
|  | 96 | self.d.getVar('PACKAGE_FEED_BASE_PATHS') or "", | 
|  | 97 | self.d.getVar('PACKAGE_FEED_ARCHS')) | 
|  | 98 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 99 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 100 | """ | 
|  | 101 | The _cleanup() method should be used to clean-up stuff that we don't really | 
|  | 102 | want to end up on target. For example, in the case of RPM, the DB locks. | 
|  | 103 | The method is called, once, at the end of create() method. | 
|  | 104 | """ | 
|  | 105 | @abstractmethod | 
|  | 106 | def _cleanup(self): | 
|  | 107 | pass | 
|  | 108 |  | 
| Andrew Geissler | 8f84068 | 2023-07-21 09:09:43 -0500 | [diff] [blame] | 109 | def _setup_dbg_rootfs(self, package_paths): | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 110 | gen_debugfs = self.d.getVar('IMAGE_GEN_DEBUGFS') or '0' | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 111 | if gen_debugfs != '1': | 
|  | 112 | return | 
|  | 113 |  | 
|  | 114 | bb.note("  Renaming the original rootfs...") | 
|  | 115 | try: | 
|  | 116 | shutil.rmtree(self.image_rootfs + '-orig') | 
|  | 117 | except: | 
|  | 118 | pass | 
| Andrew Geissler | c926e17 | 2021-05-07 16:11:35 -0500 | [diff] [blame] | 119 | bb.utils.rename(self.image_rootfs, self.image_rootfs + '-orig') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 120 |  | 
|  | 121 | bb.note("  Creating debug rootfs...") | 
|  | 122 | bb.utils.mkdirhier(self.image_rootfs) | 
|  | 123 |  | 
|  | 124 | bb.note("  Copying back package database...") | 
| Andrew Geissler | 8f84068 | 2023-07-21 09:09:43 -0500 | [diff] [blame] | 125 | for path in package_paths: | 
|  | 126 | bb.utils.mkdirhier(self.image_rootfs + os.path.dirname(path)) | 
|  | 127 | if os.path.isdir(self.image_rootfs + '-orig' + path): | 
|  | 128 | shutil.copytree(self.image_rootfs + '-orig' + path, self.image_rootfs + path, symlinks=True) | 
|  | 129 | elif os.path.isfile(self.image_rootfs + '-orig' + path): | 
|  | 130 | shutil.copyfile(self.image_rootfs + '-orig' + path, self.image_rootfs + path) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 131 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 132 | # Copy files located in /usr/lib/debug or /usr/src/debug | 
|  | 133 | for dir in ["/usr/lib/debug", "/usr/src/debug"]: | 
|  | 134 | src = self.image_rootfs + '-orig' + dir | 
| Andrew Geissler | 82c905d | 2020-04-13 13:39:40 -0500 | [diff] [blame] | 135 | if os.path.exists(src): | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 136 | dst = self.image_rootfs + dir | 
|  | 137 | bb.utils.mkdirhier(os.path.dirname(dst)) | 
|  | 138 | shutil.copytree(src, dst) | 
|  | 139 |  | 
|  | 140 | # Copy files with suffix '.debug' or located in '.debug' dir. | 
| Andrew Geissler | 82c905d | 2020-04-13 13:39:40 -0500 | [diff] [blame] | 141 | for root, dirs, files in os.walk(self.image_rootfs + '-orig'): | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 142 | relative_dir = root[len(self.image_rootfs + '-orig'):] | 
|  | 143 | for f in files: | 
|  | 144 | if f.endswith('.debug') or '/.debug' in relative_dir: | 
|  | 145 | bb.utils.mkdirhier(self.image_rootfs + relative_dir) | 
|  | 146 | shutil.copy(os.path.join(root, f), | 
|  | 147 | self.image_rootfs + relative_dir) | 
|  | 148 |  | 
|  | 149 | bb.note("  Install complementary '*-dbg' packages...") | 
|  | 150 | self.pm.install_complementary('*-dbg') | 
|  | 151 |  | 
| Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame] | 152 | if self.d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg': | 
|  | 153 | bb.note("  Install complementary '*-src' packages...") | 
|  | 154 | self.pm.install_complementary('*-src') | 
|  | 155 |  | 
|  | 156 | """ | 
|  | 157 | Install additional debug packages. Possibility to install additional packages, | 
|  | 158 | which are not automatically installed as complementary package of | 
|  | 159 | standard one, e.g. debug package of static libraries. | 
|  | 160 | """ | 
|  | 161 | extra_debug_pkgs = self.d.getVar('IMAGE_INSTALL_DEBUGFS') | 
|  | 162 | if extra_debug_pkgs: | 
|  | 163 | bb.note("  Install extra debug packages...") | 
|  | 164 | self.pm.install(extra_debug_pkgs.split(), True) | 
|  | 165 |  | 
| Andrew Geissler | 8f84068 | 2023-07-21 09:09:43 -0500 | [diff] [blame] | 166 | bb.note("  Removing package database...") | 
|  | 167 | for path in package_paths: | 
|  | 168 | if os.path.isdir(self.image_rootfs + path): | 
|  | 169 | shutil.rmtree(self.image_rootfs + path) | 
|  | 170 | elif os.path.isfile(self.image_rootfs + path): | 
|  | 171 | os.remove(self.image_rootfs + path) | 
|  | 172 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 173 | bb.note("  Rename debug rootfs...") | 
|  | 174 | try: | 
|  | 175 | shutil.rmtree(self.image_rootfs + '-dbg') | 
|  | 176 | except: | 
|  | 177 | pass | 
| Andrew Geissler | c926e17 | 2021-05-07 16:11:35 -0500 | [diff] [blame] | 178 | bb.utils.rename(self.image_rootfs, self.image_rootfs + '-dbg') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 179 |  | 
| William A. Kennington III | ac69b48 | 2021-06-02 12:28:27 -0700 | [diff] [blame] | 180 | bb.note("  Restoring original rootfs...") | 
| Andrew Geissler | c926e17 | 2021-05-07 16:11:35 -0500 | [diff] [blame] | 181 | bb.utils.rename(self.image_rootfs + '-orig', self.image_rootfs) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 182 |  | 
|  | 183 | def _exec_shell_cmd(self, cmd): | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 184 | try: | 
| Andrew Geissler | 87f5cff | 2022-09-30 13:13:31 -0500 | [diff] [blame] | 185 | subprocess.check_output(cmd, stderr=subprocess.STDOUT) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 186 | except subprocess.CalledProcessError as e: | 
|  | 187 | return("Command '%s' returned %d:\n%s" % (e.cmd, e.returncode, e.output)) | 
|  | 188 |  | 
|  | 189 | return None | 
|  | 190 |  | 
|  | 191 | def create(self): | 
|  | 192 | bb.note("###### Generate rootfs #######") | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 193 | pre_process_cmds = self.d.getVar("ROOTFS_PREPROCESS_COMMAND") | 
|  | 194 | post_process_cmds = self.d.getVar("ROOTFS_POSTPROCESS_COMMAND") | 
|  | 195 | rootfs_post_install_cmds = self.d.getVar('ROOTFS_POSTINSTALL_COMMAND') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 196 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 197 | execute_pre_post_process(self.d, pre_process_cmds) | 
|  | 198 |  | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 199 | if self.progress_reporter: | 
|  | 200 | self.progress_reporter.next_stage() | 
|  | 201 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 202 | # call the package manager dependent create method | 
|  | 203 | self._create() | 
|  | 204 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 205 | sysconfdir = self.image_rootfs + self.d.getVar('sysconfdir') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 206 | bb.utils.mkdirhier(sysconfdir) | 
|  | 207 | with open(sysconfdir + "/version", "w+") as ver: | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 208 | ver.write(self.d.getVar('BUILDNAME') + "\n") | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 209 |  | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 210 | execute_pre_post_process(self.d, rootfs_post_install_cmds) | 
|  | 211 |  | 
| Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 212 | self.pm.run_intercepts() | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 213 |  | 
|  | 214 | execute_pre_post_process(self.d, post_process_cmds) | 
|  | 215 |  | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 216 | if self.progress_reporter: | 
|  | 217 | self.progress_reporter.next_stage() | 
|  | 218 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 219 | if bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs", | 
| Andrew Geissler | d1e8949 | 2021-02-12 15:35:20 -0600 | [diff] [blame] | 220 | True, False, self.d) and \ | 
|  | 221 | not bb.utils.contains("IMAGE_FEATURES", | 
|  | 222 | "read-only-rootfs-delayed-postinsts", | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 223 | True, False, self.d): | 
|  | 224 | delayed_postinsts = self._get_delayed_postinsts() | 
|  | 225 | if delayed_postinsts is not None: | 
|  | 226 | bb.fatal("The following packages could not be configured " | 
|  | 227 | "offline and rootfs is read-only: %s" % | 
|  | 228 | delayed_postinsts) | 
|  | 229 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 230 | if self.d.getVar('USE_DEVFS') != "1": | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 231 | self._create_devfs() | 
|  | 232 |  | 
|  | 233 | self._uninstall_unneeded() | 
|  | 234 |  | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 235 | if self.progress_reporter: | 
|  | 236 | self.progress_reporter.next_stage() | 
|  | 237 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 238 | self._insert_feed_uris() | 
|  | 239 |  | 
|  | 240 | self._run_ldconfig() | 
|  | 241 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 242 | if self.d.getVar('USE_DEPMOD') != "0": | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 243 | self._generate_kernel_module_deps() | 
|  | 244 |  | 
|  | 245 | self._cleanup() | 
|  | 246 | self._log_check() | 
|  | 247 |  | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 248 | if self.progress_reporter: | 
|  | 249 | self.progress_reporter.next_stage() | 
|  | 250 |  | 
|  | 251 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 252 | def _uninstall_unneeded(self): | 
| Andrew Geissler | 95ac1b8 | 2021-03-31 14:34:31 -0500 | [diff] [blame] | 253 | # Remove the run-postinsts package if no delayed postinsts are found | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 254 | delayed_postinsts = self._get_delayed_postinsts() | 
|  | 255 | if delayed_postinsts is None: | 
| Andrew Geissler | 5199d83 | 2021-09-24 16:47:35 -0500 | [diff] [blame] | 256 | if os.path.exists(self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/init.d/run-postinsts")) or os.path.exists(self.d.expand("${IMAGE_ROOTFS}${systemd_system_unitdir}/run-postinsts.service")): | 
| Andrew Geissler | 95ac1b8 | 2021-03-31 14:34:31 -0500 | [diff] [blame] | 257 | self.pm.remove(["run-postinsts"]) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 258 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 259 | image_rorfs = bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs", | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 260 | True, False, self.d) | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 261 | image_rorfs_force = self.d.getVar('FORCE_RO_REMOVE') | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 262 |  | 
|  | 263 | if image_rorfs or image_rorfs_force == "1": | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 264 | # Remove components that we don't need if it's a read-only rootfs | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 265 | unneeded_pkgs = self.d.getVar("ROOTFS_RO_UNNEEDED").split() | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 266 | pkgs_installed = image_list_installed_packages(self.d) | 
| Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 267 | # 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 Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 271 | 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 Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 273 |  | 
| Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 274 | # 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 Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 281 | if len(pkgs_to_remove) > 0: | 
| Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 282 | self.pm.remove([pkgs_to_remove[-1]], False) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 283 |  | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 284 | 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 Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 289 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 290 | post_uninstall_cmds = self.d.getVar("ROOTFS_POSTUNINSTALL_COMMAND") | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 291 | execute_pre_post_process(self.d, post_uninstall_cmds) | 
|  | 292 |  | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 293 | runtime_pkgmanage = bb.utils.contains("IMAGE_FEATURES", "package-management", | 
|  | 294 | True, False, self.d) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 295 | if not runtime_pkgmanage: | 
|  | 296 | # Remove the package manager data files | 
|  | 297 | self.pm.remove_packaging_data() | 
|  | 298 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 299 | def _run_ldconfig(self): | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 300 | if self.d.getVar('LDCONFIGDEPEND'): | 
| Andrew Geissler | 475cb72 | 2020-07-10 16:00:51 -0500 | [diff] [blame] | 301 | bb.note("Executing: ldconfig -r " + self.image_rootfs + " -c new -v -X") | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 302 | self._exec_shell_cmd(['ldconfig', '-r', self.image_rootfs, '-c', | 
| Andrew Geissler | 475cb72 | 2020-07-10 16:00:51 -0500 | [diff] [blame] | 303 | 'new', '-v', '-X']) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 304 |  | 
| Patrick Williams | 213cb26 | 2021-08-07 19:21:33 -0500 | [diff] [blame] | 305 | image_rorfs = bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs", | 
|  | 306 | True, False, self.d) | 
|  | 307 | ldconfig_in_features = bb.utils.contains("DISTRO_FEATURES", "ldconfig", | 
|  | 308 | True, False, self.d) | 
|  | 309 | if image_rorfs or not ldconfig_in_features: | 
|  | 310 | ldconfig_cache_dir = os.path.join(self.image_rootfs, "var/cache/ldconfig") | 
|  | 311 | if os.path.exists(ldconfig_cache_dir): | 
|  | 312 | bb.note("Removing ldconfig auxiliary cache...") | 
|  | 313 | shutil.rmtree(ldconfig_cache_dir) | 
|  | 314 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 315 | def _check_for_kernel_modules(self, modules_dir): | 
|  | 316 | for root, dirs, files in os.walk(modules_dir, topdown=True): | 
|  | 317 | for name in files: | 
| Andrew Geissler | 78b7279 | 2022-06-14 06:47:25 -0500 | [diff] [blame] | 318 | found_ko = name.endswith((".ko", ".ko.gz", ".ko.xz", ".ko.zst")) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 319 | if found_ko: | 
|  | 320 | return found_ko | 
|  | 321 | return False | 
|  | 322 |  | 
|  | 323 | def _generate_kernel_module_deps(self): | 
|  | 324 | modules_dir = os.path.join(self.image_rootfs, 'lib', 'modules') | 
|  | 325 | # if we don't have any modules don't bother to do the depmod | 
|  | 326 | if not self._check_for_kernel_modules(modules_dir): | 
|  | 327 | bb.note("No Kernel Modules found, not running depmod") | 
|  | 328 | return | 
|  | 329 |  | 
| Andrew Geissler | 87f5cff | 2022-09-30 13:13:31 -0500 | [diff] [blame] | 330 | pkgdatadir = self.d.getVar('PKGDATA_DIR') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 331 |  | 
| Andrew Geissler | 87f5cff | 2022-09-30 13:13:31 -0500 | [diff] [blame] | 332 | # PKGDATA_DIR can include multiple kernels so we run depmod for each | 
|  | 333 | # one of them. | 
|  | 334 | for direntry in os.listdir(pkgdatadir): | 
|  | 335 | match = re.match('(.*)-depmod', direntry) | 
|  | 336 | if not match: | 
|  | 337 | continue | 
|  | 338 | kernel_package_name = match.group(1) | 
| Andrew Geissler | 78b7279 | 2022-06-14 06:47:25 -0500 | [diff] [blame] | 339 |  | 
| Andrew Geissler | 87f5cff | 2022-09-30 13:13:31 -0500 | [diff] [blame] | 340 | kernel_abi_ver_file = oe.path.join(pkgdatadir, direntry, kernel_package_name + '-abiversion') | 
|  | 341 | if not os.path.exists(kernel_abi_ver_file): | 
|  | 342 | bb.fatal("No kernel-abiversion file found (%s), cannot run depmod, aborting" % kernel_abi_ver_file) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 343 |  | 
| Andrew Geissler | 87f5cff | 2022-09-30 13:13:31 -0500 | [diff] [blame] | 344 | with open(kernel_abi_ver_file) as f: | 
|  | 345 | kernel_ver = f.read().strip(' \n') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 346 |  | 
| Andrew Geissler | 87f5cff | 2022-09-30 13:13:31 -0500 | [diff] [blame] | 347 | versioned_modules_dir = os.path.join(self.image_rootfs, modules_dir, kernel_ver) | 
|  | 348 |  | 
|  | 349 | bb.utils.mkdirhier(versioned_modules_dir) | 
|  | 350 |  | 
|  | 351 | bb.note("Running depmodwrapper for %s ..." % versioned_modules_dir) | 
|  | 352 | self._exec_shell_cmd(['depmodwrapper', '-a', '-b', self.image_rootfs, kernel_ver, kernel_package_name]) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 353 |  | 
|  | 354 | """ | 
|  | 355 | Create devfs: | 
|  | 356 | * IMAGE_DEVICE_TABLE is the old name to an absolute path to a device table file | 
|  | 357 | * IMAGE_DEVICE_TABLES is a new name for a file, or list of files, seached | 
|  | 358 | for in the BBPATH | 
|  | 359 | If neither are specified then the default name of files/device_table-minimal.txt | 
|  | 360 | is searched for in the BBPATH (same as the old version.) | 
|  | 361 | """ | 
|  | 362 | def _create_devfs(self): | 
|  | 363 | devtable_list = [] | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 364 | devtable = self.d.getVar('IMAGE_DEVICE_TABLE') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 365 | if devtable is not None: | 
|  | 366 | devtable_list.append(devtable) | 
|  | 367 | else: | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 368 | devtables = self.d.getVar('IMAGE_DEVICE_TABLES') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 369 | if devtables is None: | 
|  | 370 | devtables = 'files/device_table-minimal.txt' | 
|  | 371 | for devtable in devtables.split(): | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 372 | devtable_list.append("%s" % bb.utils.which(self.d.getVar('BBPATH'), devtable)) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 373 |  | 
|  | 374 | for devtable in devtable_list: | 
|  | 375 | self._exec_shell_cmd(["makedevs", "-r", | 
|  | 376 | self.image_rootfs, "-D", devtable]) | 
|  | 377 |  | 
|  | 378 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 379 | def get_class_for_type(imgtype): | 
| Andrew Geissler | 6ce62a2 | 2020-11-30 19:58:47 -0600 | [diff] [blame] | 380 | import importlib | 
|  | 381 | mod = importlib.import_module('oe.package_manager.' + imgtype + '.rootfs') | 
|  | 382 | return mod.PkgRootfs | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 383 |  | 
|  | 384 | def variable_depends(d, manifest_dir=None): | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 385 | img_type = d.getVar('IMAGE_PKGTYPE') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 386 | cls = get_class_for_type(img_type) | 
|  | 387 | return cls._depends_list() | 
|  | 388 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 389 | def create_rootfs(d, manifest_dir=None, progress_reporter=None, logcatcher=None): | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 390 | env_bkp = os.environ.copy() | 
|  | 391 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 392 | img_type = d.getVar('IMAGE_PKGTYPE') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 393 |  | 
| Andrew Geissler | 6ce62a2 | 2020-11-30 19:58:47 -0600 | [diff] [blame] | 394 | cls = get_class_for_type(img_type) | 
|  | 395 | cls(d, manifest_dir, progress_reporter, logcatcher).create() | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 396 | os.environ.clear() | 
|  | 397 | os.environ.update(env_bkp) | 
|  | 398 |  | 
|  | 399 |  | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 400 | def image_list_installed_packages(d, rootfs_dir=None): | 
| Andrew Geissler | 87f5cff | 2022-09-30 13:13:31 -0500 | [diff] [blame] | 401 | # Theres no rootfs for baremetal images | 
|  | 402 | if bb.data.inherits_class('baremetal-image', d): | 
|  | 403 | return "" | 
|  | 404 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 405 | if not rootfs_dir: | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 406 | rootfs_dir = d.getVar('IMAGE_ROOTFS') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 407 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 408 | img_type = d.getVar('IMAGE_PKGTYPE') | 
| Andrew Geissler | 6ce62a2 | 2020-11-30 19:58:47 -0600 | [diff] [blame] | 409 |  | 
|  | 410 | import importlib | 
|  | 411 | cls = importlib.import_module('oe.package_manager.' + img_type) | 
|  | 412 | return cls.PMPkgsList(d, rootfs_dir).list_pkgs() | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 413 |  | 
|  | 414 | if __name__ == "__main__": | 
|  | 415 | """ | 
|  | 416 | We should be able to run this as a standalone script, from outside bitbake | 
|  | 417 | environment. | 
|  | 418 | """ | 
|  | 419 | """ | 
|  | 420 | TBD | 
|  | 421 | """ |