diff options
author | Fredrik Gustafsson <fredrik.gustafsson@axis.com> | 2020-07-24 16:42:39 +0200 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2020-07-27 19:58:10 +0100 |
commit | c5bea36b7275f1692f5847af84d320b674a4c62e (patch) | |
tree | ad4222a7564b5710472b0673e0503cb03884f6d4 /meta/lib | |
parent | 635305fe27b12fca554d694da00ba31d4b552d39 (diff) | |
download | poky-c5bea36b7275f1692f5847af84d320b674a4c62e.tar.gz |
rpm: Move package manager to its own dir
This is part of a refactor that will split the package manager
code so that it's possible to use other package managers in other
layers.
RP: Fixes to parse/build
(From OE-Core rev: 8b776ed9ed291dd8e112621561762449c7eb5ee2)
Signed-off-by: Fredrik Gustafsson <fredrigu@axis.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib')
-rw-r--r-- | meta/lib/oe/package_manager/__init__.py | 400 | ||||
-rw-r--r-- | meta/lib/oe/package_manager/rpm/__init__.py | 399 | ||||
-rw-r--r-- | meta/lib/oe/package_manager/rpm/rootfs.py | 2 | ||||
-rw-r--r-- | meta/lib/oe/package_manager/rpm/sdk.py | 2 | ||||
-rw-r--r-- | meta/lib/oe/rootfs.py | 1 | ||||
-rw-r--r-- | meta/lib/oe/sdk.py | 1 | ||||
-rw-r--r-- | meta/lib/oeqa/utils/package_manager.py | 4 |
7 files changed, 408 insertions, 401 deletions
diff --git a/meta/lib/oe/package_manager/__init__.py b/meta/lib/oe/package_manager/__init__.py index 35e5cff073..36606d8cb3 100644 --- a/meta/lib/oe/package_manager/__init__.py +++ b/meta/lib/oe/package_manager/__init__.py | |||
@@ -149,43 +149,6 @@ class Indexer(object, metaclass=ABCMeta): | |||
149 | def write_index(self): | 149 | def write_index(self): |
150 | pass | 150 | pass |
151 | 151 | ||
152 | |||
153 | class RpmIndexer(Indexer): | ||
154 | def write_index(self): | ||
155 | self.do_write_index(self.deploy_dir) | ||
156 | |||
157 | def do_write_index(self, deploy_dir): | ||
158 | if self.d.getVar('PACKAGE_FEED_SIGN') == '1': | ||
159 | signer = get_signer(self.d, self.d.getVar('PACKAGE_FEED_GPG_BACKEND')) | ||
160 | else: | ||
161 | signer = None | ||
162 | |||
163 | createrepo_c = bb.utils.which(os.environ['PATH'], "createrepo_c") | ||
164 | result = create_index("%s --update -q %s" % (createrepo_c, deploy_dir)) | ||
165 | if result: | ||
166 | bb.fatal(result) | ||
167 | |||
168 | # Sign repomd | ||
169 | if signer: | ||
170 | sig_type = self.d.getVar('PACKAGE_FEED_GPG_SIGNATURE_TYPE') | ||
171 | is_ascii_sig = (sig_type.upper() != "BIN") | ||
172 | signer.detach_sign(os.path.join(deploy_dir, 'repodata', 'repomd.xml'), | ||
173 | self.d.getVar('PACKAGE_FEED_GPG_NAME'), | ||
174 | self.d.getVar('PACKAGE_FEED_GPG_PASSPHRASE_FILE'), | ||
175 | armor=is_ascii_sig) | ||
176 | |||
177 | class RpmSubdirIndexer(RpmIndexer): | ||
178 | def write_index(self): | ||
179 | bb.note("Generating package index for %s" %(self.deploy_dir)) | ||
180 | self.do_write_index(self.deploy_dir) | ||
181 | for entry in os.walk(self.deploy_dir): | ||
182 | if os.path.samefile(self.deploy_dir, entry[0]): | ||
183 | for dir in entry[1]: | ||
184 | if dir != 'repodata': | ||
185 | dir_path = oe.path.join(self.deploy_dir, dir) | ||
186 | bb.note("Generating package index for %s" %(dir_path)) | ||
187 | self.do_write_index(dir_path) | ||
188 | |||
189 | class OpkgIndexer(Indexer): | 152 | class OpkgIndexer(Indexer): |
190 | def write_index(self): | 153 | def write_index(self): |
191 | arch_vars = ["ALL_MULTILIB_PACKAGE_ARCHS", | 154 | arch_vars = ["ALL_MULTILIB_PACKAGE_ARCHS", |
@@ -323,10 +286,6 @@ class PkgsList(object, metaclass=ABCMeta): | |||
323 | def list_pkgs(self): | 286 | def list_pkgs(self): |
324 | pass | 287 | pass |
325 | 288 | ||
326 | class RpmPkgsList(PkgsList): | ||
327 | def list_pkgs(self): | ||
328 | return RpmPM(self.d, self.rootfs_dir, self.d.getVar('TARGET_VENDOR'), needfeed=False).list_installed() | ||
329 | |||
330 | class OpkgPkgsList(PkgsList): | 289 | class OpkgPkgsList(PkgsList): |
331 | def __init__(self, d, rootfs_dir, config_file): | 290 | def __init__(self, d, rootfs_dir, config_file): |
332 | super(OpkgPkgsList, self).__init__(d, rootfs_dir) | 291 | super(OpkgPkgsList, self).__init__(d, rootfs_dir) |
@@ -737,363 +696,6 @@ def create_packages_dir(d, subrepo_dir, deploydir, taskname, filterbydependencie | |||
737 | else: | 696 | else: |
738 | raise | 697 | raise |
739 | 698 | ||
740 | class RpmPM(PackageManager): | ||
741 | def __init__(self, | ||
742 | d, | ||
743 | target_rootfs, | ||
744 | target_vendor, | ||
745 | task_name='target', | ||
746 | arch_var=None, | ||
747 | os_var=None, | ||
748 | rpm_repo_workdir="oe-rootfs-repo", | ||
749 | filterbydependencies=True, | ||
750 | needfeed=True): | ||
751 | super(RpmPM, self).__init__(d, target_rootfs) | ||
752 | self.target_vendor = target_vendor | ||
753 | self.task_name = task_name | ||
754 | if arch_var == None: | ||
755 | self.archs = self.d.getVar('ALL_MULTILIB_PACKAGE_ARCHS').replace("-","_") | ||
756 | else: | ||
757 | self.archs = self.d.getVar(arch_var).replace("-","_") | ||
758 | if task_name == "host": | ||
759 | self.primary_arch = self.d.getVar('SDK_ARCH') | ||
760 | else: | ||
761 | self.primary_arch = self.d.getVar('MACHINE_ARCH') | ||
762 | |||
763 | if needfeed: | ||
764 | self.rpm_repo_dir = oe.path.join(self.d.getVar('WORKDIR'), rpm_repo_workdir) | ||
765 | create_packages_dir(self.d, oe.path.join(self.rpm_repo_dir, "rpm"), d.getVar("DEPLOY_DIR_RPM"), "package_write_rpm", filterbydependencies) | ||
766 | |||
767 | self.saved_packaging_data = self.d.expand('${T}/saved_packaging_data/%s' % self.task_name) | ||
768 | if not os.path.exists(self.d.expand('${T}/saved_packaging_data')): | ||
769 | bb.utils.mkdirhier(self.d.expand('${T}/saved_packaging_data')) | ||
770 | self.packaging_data_dirs = ['etc/rpm', 'etc/rpmrc', 'etc/dnf', 'var/lib/rpm', 'var/lib/dnf', 'var/cache/dnf'] | ||
771 | self.solution_manifest = self.d.expand('${T}/saved/%s_solution' % | ||
772 | self.task_name) | ||
773 | if not os.path.exists(self.d.expand('${T}/saved')): | ||
774 | bb.utils.mkdirhier(self.d.expand('${T}/saved')) | ||
775 | |||
776 | def _configure_dnf(self): | ||
777 | # libsolv handles 'noarch' internally, we don't need to specify it explicitly | ||
778 | archs = [i for i in reversed(self.archs.split()) if i not in ["any", "all", "noarch"]] | ||
779 | # This prevents accidental matching against libsolv's built-in policies | ||
780 | if len(archs) <= 1: | ||
781 | archs = archs + ["bogusarch"] | ||
782 | # This architecture needs to be upfront so that packages using it are properly prioritized | ||
783 | archs = ["sdk_provides_dummy_target"] + archs | ||
784 | confdir = "%s/%s" %(self.target_rootfs, "etc/dnf/vars/") | ||
785 | bb.utils.mkdirhier(confdir) | ||
786 | open(confdir + "arch", 'w').write(":".join(archs)) | ||
787 | distro_codename = self.d.getVar('DISTRO_CODENAME') | ||
788 | open(confdir + "releasever", 'w').write(distro_codename if distro_codename is not None else '') | ||
789 | |||
790 | open(oe.path.join(self.target_rootfs, "etc/dnf/dnf.conf"), 'w').write("") | ||
791 | |||
792 | |||
793 | def _configure_rpm(self): | ||
794 | # We need to configure rpm to use our primary package architecture as the installation architecture, | ||
795 | # and to make it compatible with other package architectures that we use. | ||
796 | # Otherwise it will refuse to proceed with packages installation. | ||
797 | platformconfdir = "%s/%s" %(self.target_rootfs, "etc/rpm/") | ||
798 | rpmrcconfdir = "%s/%s" %(self.target_rootfs, "etc/") | ||
799 | bb.utils.mkdirhier(platformconfdir) | ||
800 | open(platformconfdir + "platform", 'w').write("%s-pc-linux" % self.primary_arch) | ||
801 | with open(rpmrcconfdir + "rpmrc", 'w') as f: | ||
802 | f.write("arch_compat: %s: %s\n" % (self.primary_arch, self.archs if len(self.archs) > 0 else self.primary_arch)) | ||
803 | f.write("buildarch_compat: %s: noarch\n" % self.primary_arch) | ||
804 | |||
805 | open(platformconfdir + "macros", 'w').write("%_transaction_color 7\n") | ||
806 | if self.d.getVar('RPM_PREFER_ELF_ARCH'): | ||
807 | open(platformconfdir + "macros", 'a').write("%%_prefer_color %s" % (self.d.getVar('RPM_PREFER_ELF_ARCH'))) | ||
808 | |||
809 | if self.d.getVar('RPM_SIGN_PACKAGES') == '1': | ||
810 | signer = get_signer(self.d, self.d.getVar('RPM_GPG_BACKEND')) | ||
811 | pubkey_path = oe.path.join(self.d.getVar('B'), 'rpm-key') | ||
812 | signer.export_pubkey(pubkey_path, self.d.getVar('RPM_GPG_NAME')) | ||
813 | rpm_bin = bb.utils.which(os.getenv('PATH'), "rpmkeys") | ||
814 | cmd = [rpm_bin, '--root=%s' % self.target_rootfs, '--import', pubkey_path] | ||
815 | try: | ||
816 | subprocess.check_output(cmd, stderr=subprocess.STDOUT) | ||
817 | except subprocess.CalledProcessError as e: | ||
818 | bb.fatal("Importing GPG key failed. Command '%s' " | ||
819 | "returned %d:\n%s" % (' '.join(cmd), e.returncode, e.output.decode("utf-8"))) | ||
820 | |||
821 | def create_configs(self): | ||
822 | self._configure_dnf() | ||
823 | self._configure_rpm() | ||
824 | |||
825 | def write_index(self): | ||
826 | lockfilename = self.d.getVar('DEPLOY_DIR_RPM') + "/rpm.lock" | ||
827 | lf = bb.utils.lockfile(lockfilename, False) | ||
828 | RpmIndexer(self.d, self.rpm_repo_dir).write_index() | ||
829 | bb.utils.unlockfile(lf) | ||
830 | |||
831 | def insert_feeds_uris(self, feed_uris, feed_base_paths, feed_archs): | ||
832 | from urllib.parse import urlparse | ||
833 | |||
834 | if feed_uris == "": | ||
835 | return | ||
836 | |||
837 | gpg_opts = '' | ||
838 | if self.d.getVar('PACKAGE_FEED_SIGN') == '1': | ||
839 | gpg_opts += 'repo_gpgcheck=1\n' | ||
840 | gpg_opts += 'gpgkey=file://%s/pki/packagefeed-gpg/PACKAGEFEED-GPG-KEY-%s-%s\n' % (self.d.getVar('sysconfdir'), self.d.getVar('DISTRO'), self.d.getVar('DISTRO_CODENAME')) | ||
841 | |||
842 | if self.d.getVar('RPM_SIGN_PACKAGES') != '1': | ||
843 | gpg_opts += 'gpgcheck=0\n' | ||
844 | |||
845 | bb.utils.mkdirhier(oe.path.join(self.target_rootfs, "etc", "yum.repos.d")) | ||
846 | remote_uris = self.construct_uris(feed_uris.split(), feed_base_paths.split()) | ||
847 | for uri in remote_uris: | ||
848 | repo_base = "oe-remote-repo" + "-".join(urlparse(uri).path.split("/")) | ||
849 | if feed_archs is not None: | ||
850 | for arch in feed_archs.split(): | ||
851 | repo_uri = uri + "/" + arch | ||
852 | repo_id = "oe-remote-repo" + "-".join(urlparse(repo_uri).path.split("/")) | ||
853 | repo_name = "OE Remote Repo:" + " ".join(urlparse(repo_uri).path.split("/")) | ||
854 | open(oe.path.join(self.target_rootfs, "etc", "yum.repos.d", repo_base + ".repo"), 'a').write( | ||
855 | "[%s]\nname=%s\nbaseurl=%s\n%s\n" % (repo_id, repo_name, repo_uri, gpg_opts)) | ||
856 | else: | ||
857 | repo_name = "OE Remote Repo:" + " ".join(urlparse(uri).path.split("/")) | ||
858 | repo_uri = uri | ||
859 | open(oe.path.join(self.target_rootfs, "etc", "yum.repos.d", repo_base + ".repo"), 'w').write( | ||
860 | "[%s]\nname=%s\nbaseurl=%s\n%s" % (repo_base, repo_name, repo_uri, gpg_opts)) | ||
861 | |||
862 | def _prepare_pkg_transaction(self): | ||
863 | os.environ['D'] = self.target_rootfs | ||
864 | os.environ['OFFLINE_ROOT'] = self.target_rootfs | ||
865 | os.environ['IPKG_OFFLINE_ROOT'] = self.target_rootfs | ||
866 | os.environ['OPKG_OFFLINE_ROOT'] = self.target_rootfs | ||
867 | os.environ['INTERCEPT_DIR'] = self.intercepts_dir | ||
868 | os.environ['NATIVE_ROOT'] = self.d.getVar('STAGING_DIR_NATIVE') | ||
869 | |||
870 | |||
871 | def install(self, pkgs, attempt_only = False): | ||
872 | if len(pkgs) == 0: | ||
873 | return | ||
874 | self._prepare_pkg_transaction() | ||
875 | |||
876 | bad_recommendations = self.d.getVar('BAD_RECOMMENDATIONS') | ||
877 | package_exclude = self.d.getVar('PACKAGE_EXCLUDE') | ||
878 | exclude_pkgs = (bad_recommendations.split() if bad_recommendations else []) + (package_exclude.split() if package_exclude else []) | ||
879 | |||
880 | output = self._invoke_dnf((["--skip-broken"] if attempt_only else []) + | ||
881 | (["-x", ",".join(exclude_pkgs)] if len(exclude_pkgs) > 0 else []) + | ||
882 | (["--setopt=install_weak_deps=False"] if self.d.getVar('NO_RECOMMENDATIONS') == "1" else []) + | ||
883 | (["--nogpgcheck"] if self.d.getVar('RPM_SIGN_PACKAGES') != '1' else ["--setopt=gpgcheck=True"]) + | ||
884 | ["install"] + | ||
885 | pkgs) | ||
886 | |||
887 | failed_scriptlets_pkgnames = collections.OrderedDict() | ||
888 | for line in output.splitlines(): | ||
889 | if line.startswith("Error in POSTIN scriptlet in rpm package"): | ||
890 | failed_scriptlets_pkgnames[line.split()[-1]] = True | ||
891 | |||
892 | if len(failed_scriptlets_pkgnames) > 0: | ||
893 | failed_postinsts_abort(list(failed_scriptlets_pkgnames.keys()), self.d.expand("${T}/log.do_${BB_CURRENTTASK}")) | ||
894 | |||
895 | def remove(self, pkgs, with_dependencies = True): | ||
896 | if not pkgs: | ||
897 | return | ||
898 | |||
899 | self._prepare_pkg_transaction() | ||
900 | |||
901 | if with_dependencies: | ||
902 | self._invoke_dnf(["remove"] + pkgs) | ||
903 | else: | ||
904 | cmd = bb.utils.which(os.getenv('PATH'), "rpm") | ||
905 | args = ["-e", "-v", "--nodeps", "--root=%s" %self.target_rootfs] | ||
906 | |||
907 | try: | ||
908 | bb.note("Running %s" % ' '.join([cmd] + args + pkgs)) | ||
909 | output = subprocess.check_output([cmd] + args + pkgs, stderr=subprocess.STDOUT).decode("utf-8") | ||
910 | bb.note(output) | ||
911 | except subprocess.CalledProcessError as e: | ||
912 | bb.fatal("Could not invoke rpm. Command " | ||
913 | "'%s' returned %d:\n%s" % (' '.join([cmd] + args + pkgs), e.returncode, e.output.decode("utf-8"))) | ||
914 | |||
915 | def upgrade(self): | ||
916 | self._prepare_pkg_transaction() | ||
917 | self._invoke_dnf(["upgrade"]) | ||
918 | |||
919 | def autoremove(self): | ||
920 | self._prepare_pkg_transaction() | ||
921 | self._invoke_dnf(["autoremove"]) | ||
922 | |||
923 | def remove_packaging_data(self): | ||
924 | self._invoke_dnf(["clean", "all"]) | ||
925 | for dir in self.packaging_data_dirs: | ||
926 | bb.utils.remove(oe.path.join(self.target_rootfs, dir), True) | ||
927 | |||
928 | def backup_packaging_data(self): | ||
929 | # Save the packaging dirs for increment rpm image generation | ||
930 | if os.path.exists(self.saved_packaging_data): | ||
931 | bb.utils.remove(self.saved_packaging_data, True) | ||
932 | for i in self.packaging_data_dirs: | ||
933 | source_dir = oe.path.join(self.target_rootfs, i) | ||
934 | target_dir = oe.path.join(self.saved_packaging_data, i) | ||
935 | if os.path.isdir(source_dir): | ||
936 | shutil.copytree(source_dir, target_dir, symlinks=True) | ||
937 | elif os.path.isfile(source_dir): | ||
938 | shutil.copy2(source_dir, target_dir) | ||
939 | |||
940 | def recovery_packaging_data(self): | ||
941 | # Move the rpmlib back | ||
942 | if os.path.exists(self.saved_packaging_data): | ||
943 | for i in self.packaging_data_dirs: | ||
944 | target_dir = oe.path.join(self.target_rootfs, i) | ||
945 | if os.path.exists(target_dir): | ||
946 | bb.utils.remove(target_dir, True) | ||
947 | source_dir = oe.path.join(self.saved_packaging_data, i) | ||
948 | if os.path.isdir(source_dir): | ||
949 | shutil.copytree(source_dir, target_dir, symlinks=True) | ||
950 | elif os.path.isfile(source_dir): | ||
951 | shutil.copy2(source_dir, target_dir) | ||
952 | |||
953 | def list_installed(self): | ||
954 | output = self._invoke_dnf(["repoquery", "--installed", "--queryformat", "Package: %{name} %{arch} %{version} %{name}-%{version}-%{release}.%{arch}.rpm\nDependencies:\n%{requires}\nRecommendations:\n%{recommends}\nDependenciesEndHere:\n"], | ||
955 | print_output = False) | ||
956 | packages = {} | ||
957 | current_package = None | ||
958 | current_deps = None | ||
959 | current_state = "initial" | ||
960 | for line in output.splitlines(): | ||
961 | if line.startswith("Package:"): | ||
962 | package_info = line.split(" ")[1:] | ||
963 | current_package = package_info[0] | ||
964 | package_arch = package_info[1] | ||
965 | package_version = package_info[2] | ||
966 | package_rpm = package_info[3] | ||
967 | packages[current_package] = {"arch":package_arch, "ver":package_version, "filename":package_rpm} | ||
968 | current_deps = [] | ||
969 | elif line.startswith("Dependencies:"): | ||
970 | current_state = "dependencies" | ||
971 | elif line.startswith("Recommendations"): | ||
972 | current_state = "recommendations" | ||
973 | elif line.startswith("DependenciesEndHere:"): | ||
974 | current_state = "initial" | ||
975 | packages[current_package]["deps"] = current_deps | ||
976 | elif len(line) > 0: | ||
977 | if current_state == "dependencies": | ||
978 | current_deps.append(line) | ||
979 | elif current_state == "recommendations": | ||
980 | current_deps.append("%s [REC]" % line) | ||
981 | |||
982 | return packages | ||
983 | |||
984 | def update(self): | ||
985 | self._invoke_dnf(["makecache", "--refresh"]) | ||
986 | |||
987 | def _invoke_dnf(self, dnf_args, fatal = True, print_output = True ): | ||
988 | os.environ['RPM_ETCCONFIGDIR'] = self.target_rootfs | ||
989 | |||
990 | dnf_cmd = bb.utils.which(os.getenv('PATH'), "dnf") | ||
991 | standard_dnf_args = ["-v", "--rpmverbosity=info", "-y", | ||
992 | "-c", oe.path.join(self.target_rootfs, "etc/dnf/dnf.conf"), | ||
993 | "--setopt=reposdir=%s" %(oe.path.join(self.target_rootfs, "etc/yum.repos.d")), | ||
994 | "--installroot=%s" % (self.target_rootfs), | ||
995 | "--setopt=logdir=%s" % (self.d.getVar('T')) | ||
996 | ] | ||
997 | if hasattr(self, "rpm_repo_dir"): | ||
998 | standard_dnf_args.append("--repofrompath=oe-repo,%s" % (self.rpm_repo_dir)) | ||
999 | cmd = [dnf_cmd] + standard_dnf_args + dnf_args | ||
1000 | bb.note('Running %s' % ' '.join(cmd)) | ||
1001 | try: | ||
1002 | output = subprocess.check_output(cmd,stderr=subprocess.STDOUT).decode("utf-8") | ||
1003 | if print_output: | ||
1004 | bb.debug(1, output) | ||
1005 | return output | ||
1006 | except subprocess.CalledProcessError as e: | ||
1007 | if print_output: | ||
1008 | (bb.note, bb.fatal)[fatal]("Could not invoke dnf. Command " | ||
1009 | "'%s' returned %d:\n%s" % (' '.join(cmd), e.returncode, e.output.decode("utf-8"))) | ||
1010 | else: | ||
1011 | (bb.note, bb.fatal)[fatal]("Could not invoke dnf. Command " | ||
1012 | "'%s' returned %d:" % (' '.join(cmd), e.returncode)) | ||
1013 | return e.output.decode("utf-8") | ||
1014 | |||
1015 | def dump_install_solution(self, pkgs): | ||
1016 | open(self.solution_manifest, 'w').write(" ".join(pkgs)) | ||
1017 | return pkgs | ||
1018 | |||
1019 | def load_old_install_solution(self): | ||
1020 | if not os.path.exists(self.solution_manifest): | ||
1021 | return [] | ||
1022 | with open(self.solution_manifest, 'r') as fd: | ||
1023 | return fd.read().split() | ||
1024 | |||
1025 | def _script_num_prefix(self, path): | ||
1026 | files = os.listdir(path) | ||
1027 | numbers = set() | ||
1028 | numbers.add(99) | ||
1029 | for f in files: | ||
1030 | numbers.add(int(f.split("-")[0])) | ||
1031 | return max(numbers) + 1 | ||
1032 | |||
1033 | def save_rpmpostinst(self, pkg): | ||
1034 | bb.note("Saving postinstall script of %s" % (pkg)) | ||
1035 | cmd = bb.utils.which(os.getenv('PATH'), "rpm") | ||
1036 | args = ["-q", "--root=%s" % self.target_rootfs, "--queryformat", "%{postin}", pkg] | ||
1037 | |||
1038 | try: | ||
1039 | output = subprocess.check_output([cmd] + args,stderr=subprocess.STDOUT).decode("utf-8") | ||
1040 | except subprocess.CalledProcessError as e: | ||
1041 | bb.fatal("Could not invoke rpm. Command " | ||
1042 | "'%s' returned %d:\n%s" % (' '.join([cmd] + args), e.returncode, e.output.decode("utf-8"))) | ||
1043 | |||
1044 | # may need to prepend #!/bin/sh to output | ||
1045 | |||
1046 | target_path = oe.path.join(self.target_rootfs, self.d.expand('${sysconfdir}/rpm-postinsts/')) | ||
1047 | bb.utils.mkdirhier(target_path) | ||
1048 | num = self._script_num_prefix(target_path) | ||
1049 | saved_script_name = oe.path.join(target_path, "%d-%s" % (num, pkg)) | ||
1050 | open(saved_script_name, 'w').write(output) | ||
1051 | os.chmod(saved_script_name, 0o755) | ||
1052 | |||
1053 | def _handle_intercept_failure(self, registered_pkgs): | ||
1054 | rpm_postinsts_dir = self.target_rootfs + self.d.expand('${sysconfdir}/rpm-postinsts/') | ||
1055 | bb.utils.mkdirhier(rpm_postinsts_dir) | ||
1056 | |||
1057 | # Save the package postinstalls in /etc/rpm-postinsts | ||
1058 | for pkg in registered_pkgs.split(): | ||
1059 | self.save_rpmpostinst(pkg) | ||
1060 | |||
1061 | def extract(self, pkg): | ||
1062 | output = self._invoke_dnf(["repoquery", "--queryformat", "%{location}", pkg]) | ||
1063 | pkg_name = output.splitlines()[-1] | ||
1064 | if not pkg_name.endswith(".rpm"): | ||
1065 | bb.fatal("dnf could not find package %s in repository: %s" %(pkg, output)) | ||
1066 | pkg_path = oe.path.join(self.rpm_repo_dir, pkg_name) | ||
1067 | |||
1068 | cpio_cmd = bb.utils.which(os.getenv("PATH"), "cpio") | ||
1069 | rpm2cpio_cmd = bb.utils.which(os.getenv("PATH"), "rpm2cpio") | ||
1070 | |||
1071 | if not os.path.isfile(pkg_path): | ||
1072 | bb.fatal("Unable to extract package for '%s'." | ||
1073 | "File %s doesn't exists" % (pkg, pkg_path)) | ||
1074 | |||
1075 | tmp_dir = tempfile.mkdtemp() | ||
1076 | current_dir = os.getcwd() | ||
1077 | os.chdir(tmp_dir) | ||
1078 | |||
1079 | try: | ||
1080 | cmd = "%s %s | %s -idmv" % (rpm2cpio_cmd, pkg_path, cpio_cmd) | ||
1081 | output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) | ||
1082 | except subprocess.CalledProcessError as e: | ||
1083 | bb.utils.remove(tmp_dir, recurse=True) | ||
1084 | bb.fatal("Unable to extract %s package. Command '%s' " | ||
1085 | "returned %d:\n%s" % (pkg_path, cmd, e.returncode, e.output.decode("utf-8"))) | ||
1086 | except OSError as e: | ||
1087 | bb.utils.remove(tmp_dir, recurse=True) | ||
1088 | bb.fatal("Unable to extract %s package. Command '%s' " | ||
1089 | "returned %d:\n%s at %s" % (pkg_path, cmd, e.errno, e.strerror, e.filename)) | ||
1090 | |||
1091 | bb.note("Extracted %s to %s" % (pkg_path, tmp_dir)) | ||
1092 | os.chdir(current_dir) | ||
1093 | |||
1094 | return tmp_dir | ||
1095 | |||
1096 | |||
1097 | class OpkgDpkgPM(PackageManager): | 699 | class OpkgDpkgPM(PackageManager): |
1098 | def __init__(self, d, target_rootfs): | 700 | def __init__(self, d, target_rootfs): |
1099 | """ | 701 | """ |
@@ -1842,6 +1444,8 @@ class DpkgPM(OpkgDpkgPM): | |||
1842 | return tmp_dir | 1444 | return tmp_dir |
1843 | 1445 | ||
1844 | def generate_index_files(d): | 1446 | def generate_index_files(d): |
1447 | from oe.package_manager.rpm import RpmSubdirIndexer | ||
1448 | |||
1845 | classes = d.getVar('PACKAGE_CLASSES').replace("package_", "").split() | 1449 | classes = d.getVar('PACKAGE_CLASSES').replace("package_", "").split() |
1846 | 1450 | ||
1847 | indexer_map = { | 1451 | indexer_map = { |
diff --git a/meta/lib/oe/package_manager/rpm/__init__.py b/meta/lib/oe/package_manager/rpm/__init__.py index a2094304c9..6183f81d58 100644 --- a/meta/lib/oe/package_manager/rpm/__init__.py +++ b/meta/lib/oe/package_manager/rpm/__init__.py | |||
@@ -1,3 +1,402 @@ | |||
1 | # | 1 | # |
2 | # SPDX-License-Identifier: GPL-2.0-only | 2 | # SPDX-License-Identifier: GPL-2.0-only |
3 | # | 3 | # |
4 | |||
5 | from oe.package_manager import * | ||
6 | |||
7 | class RpmIndexer(Indexer): | ||
8 | def write_index(self): | ||
9 | self.do_write_index(self.deploy_dir) | ||
10 | |||
11 | def do_write_index(self, deploy_dir): | ||
12 | if self.d.getVar('PACKAGE_FEED_SIGN') == '1': | ||
13 | signer = get_signer(self.d, self.d.getVar('PACKAGE_FEED_GPG_BACKEND')) | ||
14 | else: | ||
15 | signer = None | ||
16 | |||
17 | createrepo_c = bb.utils.which(os.environ['PATH'], "createrepo_c") | ||
18 | result = create_index("%s --update -q %s" % (createrepo_c, deploy_dir)) | ||
19 | if result: | ||
20 | bb.fatal(result) | ||
21 | |||
22 | # Sign repomd | ||
23 | if signer: | ||
24 | sig_type = self.d.getVar('PACKAGE_FEED_GPG_SIGNATURE_TYPE') | ||
25 | is_ascii_sig = (sig_type.upper() != "BIN") | ||
26 | signer.detach_sign(os.path.join(deploy_dir, 'repodata', 'repomd.xml'), | ||
27 | self.d.getVar('PACKAGE_FEED_GPG_NAME'), | ||
28 | self.d.getVar('PACKAGE_FEED_GPG_PASSPHRASE_FILE'), | ||
29 | armor=is_ascii_sig) | ||
30 | |||
31 | class RpmSubdirIndexer(RpmIndexer): | ||
32 | def write_index(self): | ||
33 | bb.note("Generating package index for %s" %(self.deploy_dir)) | ||
34 | self.do_write_index(self.deploy_dir) | ||
35 | for entry in os.walk(self.deploy_dir): | ||
36 | if os.path.samefile(self.deploy_dir, entry[0]): | ||
37 | for dir in entry[1]: | ||
38 | if dir != 'repodata': | ||
39 | dir_path = oe.path.join(self.deploy_dir, dir) | ||
40 | bb.note("Generating package index for %s" %(dir_path)) | ||
41 | self.do_write_index(dir_path) | ||
42 | |||
43 | |||
44 | class RpmPkgsList(PkgsList): | ||
45 | def list_pkgs(self): | ||
46 | return RpmPM(self.d, self.rootfs_dir, self.d.getVar('TARGET_VENDOR'), needfeed=False).list_installed() | ||
47 | |||
48 | class RpmPM(PackageManager): | ||
49 | def __init__(self, | ||
50 | d, | ||
51 | target_rootfs, | ||
52 | target_vendor, | ||
53 | task_name='target', | ||
54 | arch_var=None, | ||
55 | os_var=None, | ||
56 | rpm_repo_workdir="oe-rootfs-repo", | ||
57 | filterbydependencies=True, | ||
58 | needfeed=True): | ||
59 | super(RpmPM, self).__init__(d, target_rootfs) | ||
60 | self.target_vendor = target_vendor | ||
61 | self.task_name = task_name | ||
62 | if arch_var == None: | ||
63 | self.archs = self.d.getVar('ALL_MULTILIB_PACKAGE_ARCHS').replace("-","_") | ||
64 | else: | ||
65 | self.archs = self.d.getVar(arch_var).replace("-","_") | ||
66 | if task_name == "host": | ||
67 | self.primary_arch = self.d.getVar('SDK_ARCH') | ||
68 | else: | ||
69 | self.primary_arch = self.d.getVar('MACHINE_ARCH') | ||
70 | |||
71 | if needfeed: | ||
72 | self.rpm_repo_dir = oe.path.join(self.d.getVar('WORKDIR'), rpm_repo_workdir) | ||
73 | create_packages_dir(self.d, oe.path.join(self.rpm_repo_dir, "rpm"), d.getVar("DEPLOY_DIR_RPM"), "package_write_rpm", filterbydependencies) | ||
74 | |||
75 | self.saved_packaging_data = self.d.expand('${T}/saved_packaging_data/%s' % self.task_name) | ||
76 | if not os.path.exists(self.d.expand('${T}/saved_packaging_data')): | ||
77 | bb.utils.mkdirhier(self.d.expand('${T}/saved_packaging_data')) | ||
78 | self.packaging_data_dirs = ['etc/rpm', 'etc/rpmrc', 'etc/dnf', 'var/lib/rpm', 'var/lib/dnf', 'var/cache/dnf'] | ||
79 | self.solution_manifest = self.d.expand('${T}/saved/%s_solution' % | ||
80 | self.task_name) | ||
81 | if not os.path.exists(self.d.expand('${T}/saved')): | ||
82 | bb.utils.mkdirhier(self.d.expand('${T}/saved')) | ||
83 | |||
84 | def _configure_dnf(self): | ||
85 | # libsolv handles 'noarch' internally, we don't need to specify it explicitly | ||
86 | archs = [i for i in reversed(self.archs.split()) if i not in ["any", "all", "noarch"]] | ||
87 | # This prevents accidental matching against libsolv's built-in policies | ||
88 | if len(archs) <= 1: | ||
89 | archs = archs + ["bogusarch"] | ||
90 | # This architecture needs to be upfront so that packages using it are properly prioritized | ||
91 | archs = ["sdk_provides_dummy_target"] + archs | ||
92 | confdir = "%s/%s" %(self.target_rootfs, "etc/dnf/vars/") | ||
93 | bb.utils.mkdirhier(confdir) | ||
94 | open(confdir + "arch", 'w').write(":".join(archs)) | ||
95 | distro_codename = self.d.getVar('DISTRO_CODENAME') | ||
96 | open(confdir + "releasever", 'w').write(distro_codename if distro_codename is not None else '') | ||
97 | |||
98 | open(oe.path.join(self.target_rootfs, "etc/dnf/dnf.conf"), 'w').write("") | ||
99 | |||
100 | |||
101 | def _configure_rpm(self): | ||
102 | # We need to configure rpm to use our primary package architecture as the installation architecture, | ||
103 | # and to make it compatible with other package architectures that we use. | ||
104 | # Otherwise it will refuse to proceed with packages installation. | ||
105 | platformconfdir = "%s/%s" %(self.target_rootfs, "etc/rpm/") | ||
106 | rpmrcconfdir = "%s/%s" %(self.target_rootfs, "etc/") | ||
107 | bb.utils.mkdirhier(platformconfdir) | ||
108 | open(platformconfdir + "platform", 'w').write("%s-pc-linux" % self.primary_arch) | ||
109 | with open(rpmrcconfdir + "rpmrc", 'w') as f: | ||
110 | f.write("arch_compat: %s: %s\n" % (self.primary_arch, self.archs if len(self.archs) > 0 else self.primary_arch)) | ||
111 | f.write("buildarch_compat: %s: noarch\n" % self.primary_arch) | ||
112 | |||
113 | open(platformconfdir + "macros", 'w').write("%_transaction_color 7\n") | ||
114 | if self.d.getVar('RPM_PREFER_ELF_ARCH'): | ||
115 | open(platformconfdir + "macros", 'a').write("%%_prefer_color %s" % (self.d.getVar('RPM_PREFER_ELF_ARCH'))) | ||
116 | |||
117 | if self.d.getVar('RPM_SIGN_PACKAGES') == '1': | ||
118 | signer = get_signer(self.d, self.d.getVar('RPM_GPG_BACKEND')) | ||
119 | pubkey_path = oe.path.join(self.d.getVar('B'), 'rpm-key') | ||
120 | signer.export_pubkey(pubkey_path, self.d.getVar('RPM_GPG_NAME')) | ||
121 | rpm_bin = bb.utils.which(os.getenv('PATH'), "rpmkeys") | ||
122 | cmd = [rpm_bin, '--root=%s' % self.target_rootfs, '--import', pubkey_path] | ||
123 | try: | ||
124 | subprocess.check_output(cmd, stderr=subprocess.STDOUT) | ||
125 | except subprocess.CalledProcessError as e: | ||
126 | bb.fatal("Importing GPG key failed. Command '%s' " | ||
127 | "returned %d:\n%s" % (' '.join(cmd), e.returncode, e.output.decode("utf-8"))) | ||
128 | |||
129 | def create_configs(self): | ||
130 | self._configure_dnf() | ||
131 | self._configure_rpm() | ||
132 | |||
133 | def write_index(self): | ||
134 | lockfilename = self.d.getVar('DEPLOY_DIR_RPM') + "/rpm.lock" | ||
135 | lf = bb.utils.lockfile(lockfilename, False) | ||
136 | RpmIndexer(self.d, self.rpm_repo_dir).write_index() | ||
137 | bb.utils.unlockfile(lf) | ||
138 | |||
139 | def insert_feeds_uris(self, feed_uris, feed_base_paths, feed_archs): | ||
140 | from urllib.parse import urlparse | ||
141 | |||
142 | if feed_uris == "": | ||
143 | return | ||
144 | |||
145 | gpg_opts = '' | ||
146 | if self.d.getVar('PACKAGE_FEED_SIGN') == '1': | ||
147 | gpg_opts += 'repo_gpgcheck=1\n' | ||
148 | gpg_opts += 'gpgkey=file://%s/pki/packagefeed-gpg/PACKAGEFEED-GPG-KEY-%s-%s\n' % (self.d.getVar('sysconfdir'), self.d.getVar('DISTRO'), self.d.getVar('DISTRO_CODENAME')) | ||
149 | |||
150 | if self.d.getVar('RPM_SIGN_PACKAGES') != '1': | ||
151 | gpg_opts += 'gpgcheck=0\n' | ||
152 | |||
153 | bb.utils.mkdirhier(oe.path.join(self.target_rootfs, "etc", "yum.repos.d")) | ||
154 | remote_uris = self.construct_uris(feed_uris.split(), feed_base_paths.split()) | ||
155 | for uri in remote_uris: | ||
156 | repo_base = "oe-remote-repo" + "-".join(urlparse(uri).path.split("/")) | ||
157 | if feed_archs is not None: | ||
158 | for arch in feed_archs.split(): | ||
159 | repo_uri = uri + "/" + arch | ||
160 | repo_id = "oe-remote-repo" + "-".join(urlparse(repo_uri).path.split("/")) | ||
161 | repo_name = "OE Remote Repo:" + " ".join(urlparse(repo_uri).path.split("/")) | ||
162 | open(oe.path.join(self.target_rootfs, "etc", "yum.repos.d", repo_base + ".repo"), 'a').write( | ||
163 | "[%s]\nname=%s\nbaseurl=%s\n%s\n" % (repo_id, repo_name, repo_uri, gpg_opts)) | ||
164 | else: | ||
165 | repo_name = "OE Remote Repo:" + " ".join(urlparse(uri).path.split("/")) | ||
166 | repo_uri = uri | ||
167 | open(oe.path.join(self.target_rootfs, "etc", "yum.repos.d", repo_base + ".repo"), 'w').write( | ||
168 | "[%s]\nname=%s\nbaseurl=%s\n%s" % (repo_base, repo_name, repo_uri, gpg_opts)) | ||
169 | |||
170 | def _prepare_pkg_transaction(self): | ||
171 | os.environ['D'] = self.target_rootfs | ||
172 | os.environ['OFFLINE_ROOT'] = self.target_rootfs | ||
173 | os.environ['IPKG_OFFLINE_ROOT'] = self.target_rootfs | ||
174 | os.environ['OPKG_OFFLINE_ROOT'] = self.target_rootfs | ||
175 | os.environ['INTERCEPT_DIR'] = self.intercepts_dir | ||
176 | os.environ['NATIVE_ROOT'] = self.d.getVar('STAGING_DIR_NATIVE') | ||
177 | |||
178 | |||
179 | def install(self, pkgs, attempt_only = False): | ||
180 | if len(pkgs) == 0: | ||
181 | return | ||
182 | self._prepare_pkg_transaction() | ||
183 | |||
184 | bad_recommendations = self.d.getVar('BAD_RECOMMENDATIONS') | ||
185 | package_exclude = self.d.getVar('PACKAGE_EXCLUDE') | ||
186 | exclude_pkgs = (bad_recommendations.split() if bad_recommendations else []) + (package_exclude.split() if package_exclude else []) | ||
187 | |||
188 | output = self._invoke_dnf((["--skip-broken"] if attempt_only else []) + | ||
189 | (["-x", ",".join(exclude_pkgs)] if len(exclude_pkgs) > 0 else []) + | ||
190 | (["--setopt=install_weak_deps=False"] if self.d.getVar('NO_RECOMMENDATIONS') == "1" else []) + | ||
191 | (["--nogpgcheck"] if self.d.getVar('RPM_SIGN_PACKAGES') != '1' else ["--setopt=gpgcheck=True"]) + | ||
192 | ["install"] + | ||
193 | pkgs) | ||
194 | |||
195 | failed_scriptlets_pkgnames = collections.OrderedDict() | ||
196 | for line in output.splitlines(): | ||
197 | if line.startswith("Error in POSTIN scriptlet in rpm package"): | ||
198 | failed_scriptlets_pkgnames[line.split()[-1]] = True | ||
199 | |||
200 | if len(failed_scriptlets_pkgnames) > 0: | ||
201 | failed_postinsts_abort(list(failed_scriptlets_pkgnames.keys()), self.d.expand("${T}/log.do_${BB_CURRENTTASK}")) | ||
202 | |||
203 | def remove(self, pkgs, with_dependencies = True): | ||
204 | if not pkgs: | ||
205 | return | ||
206 | |||
207 | self._prepare_pkg_transaction() | ||
208 | |||
209 | if with_dependencies: | ||
210 | self._invoke_dnf(["remove"] + pkgs) | ||
211 | else: | ||
212 | cmd = bb.utils.which(os.getenv('PATH'), "rpm") | ||
213 | args = ["-e", "-v", "--nodeps", "--root=%s" %self.target_rootfs] | ||
214 | |||
215 | try: | ||
216 | bb.note("Running %s" % ' '.join([cmd] + args + pkgs)) | ||
217 | output = subprocess.check_output([cmd] + args + pkgs, stderr=subprocess.STDOUT).decode("utf-8") | ||
218 | bb.note(output) | ||
219 | except subprocess.CalledProcessError as e: | ||
220 | bb.fatal("Could not invoke rpm. Command " | ||
221 | "'%s' returned %d:\n%s" % (' '.join([cmd] + args + pkgs), e.returncode, e.output.decode("utf-8"))) | ||
222 | |||
223 | def upgrade(self): | ||
224 | self._prepare_pkg_transaction() | ||
225 | self._invoke_dnf(["upgrade"]) | ||
226 | |||
227 | def autoremove(self): | ||
228 | self._prepare_pkg_transaction() | ||
229 | self._invoke_dnf(["autoremove"]) | ||
230 | |||
231 | def remove_packaging_data(self): | ||
232 | self._invoke_dnf(["clean", "all"]) | ||
233 | for dir in self.packaging_data_dirs: | ||
234 | bb.utils.remove(oe.path.join(self.target_rootfs, dir), True) | ||
235 | |||
236 | def backup_packaging_data(self): | ||
237 | # Save the packaging dirs for increment rpm image generation | ||
238 | if os.path.exists(self.saved_packaging_data): | ||
239 | bb.utils.remove(self.saved_packaging_data, True) | ||
240 | for i in self.packaging_data_dirs: | ||
241 | source_dir = oe.path.join(self.target_rootfs, i) | ||
242 | target_dir = oe.path.join(self.saved_packaging_data, i) | ||
243 | if os.path.isdir(source_dir): | ||
244 | shutil.copytree(source_dir, target_dir, symlinks=True) | ||
245 | elif os.path.isfile(source_dir): | ||
246 | shutil.copy2(source_dir, target_dir) | ||
247 | |||
248 | def recovery_packaging_data(self): | ||
249 | # Move the rpmlib back | ||
250 | if os.path.exists(self.saved_packaging_data): | ||
251 | for i in self.packaging_data_dirs: | ||
252 | target_dir = oe.path.join(self.target_rootfs, i) | ||
253 | if os.path.exists(target_dir): | ||
254 | bb.utils.remove(target_dir, True) | ||
255 | source_dir = oe.path.join(self.saved_packaging_data, i) | ||
256 | if os.path.isdir(source_dir): | ||
257 | shutil.copytree(source_dir, target_dir, symlinks=True) | ||
258 | elif os.path.isfile(source_dir): | ||
259 | shutil.copy2(source_dir, target_dir) | ||
260 | |||
261 | def list_installed(self): | ||
262 | output = self._invoke_dnf(["repoquery", "--installed", "--queryformat", "Package: %{name} %{arch} %{version} %{name}-%{version}-%{release}.%{arch}.rpm\nDependencies:\n%{requires}\nRecommendations:\n%{recommends}\nDependenciesEndHere:\n"], | ||
263 | print_output = False) | ||
264 | packages = {} | ||
265 | current_package = None | ||
266 | current_deps = None | ||
267 | current_state = "initial" | ||
268 | for line in output.splitlines(): | ||
269 | if line.startswith("Package:"): | ||
270 | package_info = line.split(" ")[1:] | ||
271 | current_package = package_info[0] | ||
272 | package_arch = package_info[1] | ||
273 | package_version = package_info[2] | ||
274 | package_rpm = package_info[3] | ||
275 | packages[current_package] = {"arch":package_arch, "ver":package_version, "filename":package_rpm} | ||
276 | current_deps = [] | ||
277 | elif line.startswith("Dependencies:"): | ||
278 | current_state = "dependencies" | ||
279 | elif line.startswith("Recommendations"): | ||
280 | current_state = "recommendations" | ||
281 | elif line.startswith("DependenciesEndHere:"): | ||
282 | current_state = "initial" | ||
283 | packages[current_package]["deps"] = current_deps | ||
284 | elif len(line) > 0: | ||
285 | if current_state == "dependencies": | ||
286 | current_deps.append(line) | ||
287 | elif current_state == "recommendations": | ||
288 | current_deps.append("%s [REC]" % line) | ||
289 | |||
290 | return packages | ||
291 | |||
292 | def update(self): | ||
293 | self._invoke_dnf(["makecache", "--refresh"]) | ||
294 | |||
295 | def _invoke_dnf(self, dnf_args, fatal = True, print_output = True ): | ||
296 | os.environ['RPM_ETCCONFIGDIR'] = self.target_rootfs | ||
297 | |||
298 | dnf_cmd = bb.utils.which(os.getenv('PATH'), "dnf") | ||
299 | standard_dnf_args = ["-v", "--rpmverbosity=info", "-y", | ||
300 | "-c", oe.path.join(self.target_rootfs, "etc/dnf/dnf.conf"), | ||
301 | "--setopt=reposdir=%s" %(oe.path.join(self.target_rootfs, "etc/yum.repos.d")), | ||
302 | "--installroot=%s" % (self.target_rootfs), | ||
303 | "--setopt=logdir=%s" % (self.d.getVar('T')) | ||
304 | ] | ||
305 | if hasattr(self, "rpm_repo_dir"): | ||
306 | standard_dnf_args.append("--repofrompath=oe-repo,%s" % (self.rpm_repo_dir)) | ||
307 | cmd = [dnf_cmd] + standard_dnf_args + dnf_args | ||
308 | bb.note('Running %s' % ' '.join(cmd)) | ||
309 | try: | ||
310 | output = subprocess.check_output(cmd,stderr=subprocess.STDOUT).decode("utf-8") | ||
311 | if print_output: | ||
312 | bb.debug(1, output) | ||
313 | return output | ||
314 | except subprocess.CalledProcessError as e: | ||
315 | if print_output: | ||
316 | (bb.note, bb.fatal)[fatal]("Could not invoke dnf. Command " | ||
317 | "'%s' returned %d:\n%s" % (' '.join(cmd), e.returncode, e.output.decode("utf-8"))) | ||
318 | else: | ||
319 | (bb.note, bb.fatal)[fatal]("Could not invoke dnf. Command " | ||
320 | "'%s' returned %d:" % (' '.join(cmd), e.returncode)) | ||
321 | return e.output.decode("utf-8") | ||
322 | |||
323 | def dump_install_solution(self, pkgs): | ||
324 | open(self.solution_manifest, 'w').write(" ".join(pkgs)) | ||
325 | return pkgs | ||
326 | |||
327 | def load_old_install_solution(self): | ||
328 | if not os.path.exists(self.solution_manifest): | ||
329 | return [] | ||
330 | with open(self.solution_manifest, 'r') as fd: | ||
331 | return fd.read().split() | ||
332 | |||
333 | def _script_num_prefix(self, path): | ||
334 | files = os.listdir(path) | ||
335 | numbers = set() | ||
336 | numbers.add(99) | ||
337 | for f in files: | ||
338 | numbers.add(int(f.split("-")[0])) | ||
339 | return max(numbers) + 1 | ||
340 | |||
341 | def save_rpmpostinst(self, pkg): | ||
342 | bb.note("Saving postinstall script of %s" % (pkg)) | ||
343 | cmd = bb.utils.which(os.getenv('PATH'), "rpm") | ||
344 | args = ["-q", "--root=%s" % self.target_rootfs, "--queryformat", "%{postin}", pkg] | ||
345 | |||
346 | try: | ||
347 | output = subprocess.check_output([cmd] + args,stderr=subprocess.STDOUT).decode("utf-8") | ||
348 | except subprocess.CalledProcessError as e: | ||
349 | bb.fatal("Could not invoke rpm. Command " | ||
350 | "'%s' returned %d:\n%s" % (' '.join([cmd] + args), e.returncode, e.output.decode("utf-8"))) | ||
351 | |||
352 | # may need to prepend #!/bin/sh to output | ||
353 | |||
354 | target_path = oe.path.join(self.target_rootfs, self.d.expand('${sysconfdir}/rpm-postinsts/')) | ||
355 | bb.utils.mkdirhier(target_path) | ||
356 | num = self._script_num_prefix(target_path) | ||
357 | saved_script_name = oe.path.join(target_path, "%d-%s" % (num, pkg)) | ||
358 | open(saved_script_name, 'w').write(output) | ||
359 | os.chmod(saved_script_name, 0o755) | ||
360 | |||
361 | def _handle_intercept_failure(self, registered_pkgs): | ||
362 | rpm_postinsts_dir = self.target_rootfs + self.d.expand('${sysconfdir}/rpm-postinsts/') | ||
363 | bb.utils.mkdirhier(rpm_postinsts_dir) | ||
364 | |||
365 | # Save the package postinstalls in /etc/rpm-postinsts | ||
366 | for pkg in registered_pkgs.split(): | ||
367 | self.save_rpmpostinst(pkg) | ||
368 | |||
369 | def extract(self, pkg): | ||
370 | output = self._invoke_dnf(["repoquery", "--queryformat", "%{location}", pkg]) | ||
371 | pkg_name = output.splitlines()[-1] | ||
372 | if not pkg_name.endswith(".rpm"): | ||
373 | bb.fatal("dnf could not find package %s in repository: %s" %(pkg, output)) | ||
374 | pkg_path = oe.path.join(self.rpm_repo_dir, pkg_name) | ||
375 | |||
376 | cpio_cmd = bb.utils.which(os.getenv("PATH"), "cpio") | ||
377 | rpm2cpio_cmd = bb.utils.which(os.getenv("PATH"), "rpm2cpio") | ||
378 | |||
379 | if not os.path.isfile(pkg_path): | ||
380 | bb.fatal("Unable to extract package for '%s'." | ||
381 | "File %s doesn't exists" % (pkg, pkg_path)) | ||
382 | |||
383 | tmp_dir = tempfile.mkdtemp() | ||
384 | current_dir = os.getcwd() | ||
385 | os.chdir(tmp_dir) | ||
386 | |||
387 | try: | ||
388 | cmd = "%s %s | %s -idmv" % (rpm2cpio_cmd, pkg_path, cpio_cmd) | ||
389 | output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) | ||
390 | except subprocess.CalledProcessError as e: | ||
391 | bb.utils.remove(tmp_dir, recurse=True) | ||
392 | bb.fatal("Unable to extract %s package. Command '%s' " | ||
393 | "returned %d:\n%s" % (pkg_path, cmd, e.returncode, e.output.decode("utf-8"))) | ||
394 | except OSError as e: | ||
395 | bb.utils.remove(tmp_dir, recurse=True) | ||
396 | bb.fatal("Unable to extract %s package. Command '%s' " | ||
397 | "returned %d:\n%s at %s" % (pkg_path, cmd, e.errno, e.strerror, e.filename)) | ||
398 | |||
399 | bb.note("Extracted %s to %s" % (pkg_path, tmp_dir)) | ||
400 | os.chdir(current_dir) | ||
401 | |||
402 | return tmp_dir | ||
diff --git a/meta/lib/oe/package_manager/rpm/rootfs.py b/meta/lib/oe/package_manager/rpm/rootfs.py index 3d9eb95528..2de5752b91 100644 --- a/meta/lib/oe/package_manager/rpm/rootfs.py +++ b/meta/lib/oe/package_manager/rpm/rootfs.py | |||
@@ -3,10 +3,10 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | from oe.rootfs import Rootfs | 5 | from oe.rootfs import Rootfs |
6 | from oe.package_manager import RpmPM | ||
7 | from oe.manifest import Manifest | 6 | from oe.manifest import Manifest |
8 | from oe.utils import execute_pre_post_process | 7 | from oe.utils import execute_pre_post_process |
9 | from oe.package_manager.rpm.manifest import RpmManifest | 8 | from oe.package_manager.rpm.manifest import RpmManifest |
9 | from oe.package_manager.rpm import RpmPM | ||
10 | 10 | ||
11 | class RpmRootfs(Rootfs): | 11 | class RpmRootfs(Rootfs): |
12 | def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None): | 12 | def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None): |
diff --git a/meta/lib/oe/package_manager/rpm/sdk.py b/meta/lib/oe/package_manager/rpm/sdk.py index ab816f43df..4d3f9461ef 100644 --- a/meta/lib/oe/package_manager/rpm/sdk.py +++ b/meta/lib/oe/package_manager/rpm/sdk.py | |||
@@ -5,7 +5,7 @@ | |||
5 | from oe.utils import execute_pre_post_process | 5 | from oe.utils import execute_pre_post_process |
6 | from oe.sdk import Sdk | 6 | from oe.sdk import Sdk |
7 | from oe.manifest import Manifest | 7 | from oe.manifest import Manifest |
8 | from oe.package_manager import RpmPM | 8 | from oe.package_manager.rpm import RpmPM |
9 | import glob | 9 | import glob |
10 | 10 | ||
11 | class RpmSdk(Sdk): | 11 | class RpmSdk(Sdk): |
diff --git a/meta/lib/oe/rootfs.py b/meta/lib/oe/rootfs.py index 17ca323588..a37f1e8147 100644 --- a/meta/lib/oe/rootfs.py +++ b/meta/lib/oe/rootfs.py | |||
@@ -13,6 +13,7 @@ import re | |||
13 | from oe.package_manager.rpm.manifest import RpmManifest | 13 | from oe.package_manager.rpm.manifest import RpmManifest |
14 | from oe.package_manager.ipk.manifest import OpkgManifest | 14 | from oe.package_manager.ipk.manifest import OpkgManifest |
15 | from oe.package_manager.deb.manifest import DpkgManifest | 15 | from oe.package_manager.deb.manifest import DpkgManifest |
16 | from oe.package_manager.rpm import RpmPkgsList | ||
16 | 17 | ||
17 | class Rootfs(object, metaclass=ABCMeta): | 18 | class Rootfs(object, metaclass=ABCMeta): |
18 | """ | 19 | """ |
diff --git a/meta/lib/oe/sdk.py b/meta/lib/oe/sdk.py index 2f8cbd03d7..3a4c9bb7ca 100644 --- a/meta/lib/oe/sdk.py +++ b/meta/lib/oe/sdk.py | |||
@@ -117,6 +117,7 @@ def sdk_list_installed_packages(d, target, rootfs_dir=None): | |||
117 | 117 | ||
118 | rootfs_dir = [sdk_output, os.path.join(sdk_output, target_path)][target is True] | 118 | rootfs_dir = [sdk_output, os.path.join(sdk_output, target_path)][target is True] |
119 | 119 | ||
120 | from oe.package_manager.rpm import RpmPkgsList | ||
120 | img_type = d.getVar('IMAGE_PKGTYPE') | 121 | img_type = d.getVar('IMAGE_PKGTYPE') |
121 | if img_type == "rpm": | 122 | if img_type == "rpm": |
122 | arch_var = ["SDK_PACKAGE_ARCHS", None][target is True] | 123 | arch_var = ["SDK_PACKAGE_ARCHS", None][target is True] |
diff --git a/meta/lib/oeqa/utils/package_manager.py b/meta/lib/oeqa/utils/package_manager.py index 2d358f7172..15ffd59231 100644 --- a/meta/lib/oeqa/utils/package_manager.py +++ b/meta/lib/oeqa/utils/package_manager.py | |||
@@ -12,7 +12,9 @@ def get_package_manager(d, root_path): | |||
12 | """ | 12 | """ |
13 | Returns an OE package manager that can install packages in root_path. | 13 | Returns an OE package manager that can install packages in root_path. |
14 | """ | 14 | """ |
15 | from oe.package_manager import RpmPM, OpkgPM, DpkgPM | 15 | from oe.package_manager import OpkgPM, DpkgPM |
16 | from oe.package_manager.rpm import RpmPM | ||
17 | |||
16 | 18 | ||
17 | pkg_class = d.getVar("IMAGE_PKGTYPE") | 19 | pkg_class = d.getVar("IMAGE_PKGTYPE") |
18 | if pkg_class == "rpm": | 20 | if pkg_class == "rpm": |