Chroot into image root and use rpm command to unintsall packages.
authorwanchao-xu <wanchao.xu@samsung.com>
Tue, 27 Aug 2024 03:18:59 +0000 (11:18 +0800)
committerwanchao-xu <wanchao.xu@samsung.com>
Fri, 30 Aug 2024 09:40:44 +0000 (17:40 +0800)
  * python-rpm has a crash bug while use 'addErase' and 'run' to remove packages
  * rpm packages has been installed while recreate image, so chroot into instroot and use rpm command to unintsall packages.

Change-Id: I53ee977ed14690981d100b2661cd0db5dffedde4
Signed-off-by: wanchao-xu <wanchao.xu@samsung.com>
plugins/backend/zypppkgmgr.py

index 524ae8d63ebde3be12768e80c68088df24080a34..4558673fe2bc389c6e22c8b0534276ba10ee336b 100644 (file)
@@ -21,6 +21,7 @@ import urllib.parse
 import rpm
 import glob
 import functools
+import subprocess
 
 import zypp #pylint: disable=import-error
 if not hasattr(zypp, 'PoolQuery') or \
@@ -293,9 +294,42 @@ class Zypp(BackendPlugin):
         """
 
         packages = self._findPackage(pkg)
+        update_pkgs = []
         if len(packages) > 0:
             for pkg in packages:
-                self.update_pkgs.append(pkg)
+                update_pkgs.append(pkg)
+            try:
+                deleted_pkgs = self.uninstallPkgs(update_pkgs)
+                for item in deleted_pkgs:
+                    po = self._zyppQueryPackage(item)
+                    if po:
+                        self.update_pkgs.append(po)
+                    else:
+                        msger.warning("No updated rpm found for: %s" % item)
+            except (CreatorError, RpmError):
+                raise
+            except Exception as e:
+                raise CreatorError("Package uninstallation failed: %s" % str(e))
+            return None
+        else:
+            raise CreatorError("Unable to find package: %s" % (pkg))
+
+    def erasePackage(self, pkg):
+        """Erase a given package or package pattern, can be specified
+        with name.arch or name* or *name
+        """
+
+        packages = self._findPackage(pkg)
+        erase_pkgs = []
+        if len(packages) > 0:
+            for pkg in packages:
+                erase_pkgs.append(pkg)
+            try:
+                self.uninstallPkgs(erase_pkgs)
+            except (CreatorError, RpmError):
+                raise
+            except Exception as e:
+                raise CreatorError("Package uninstallation failed: %s" % str(e))
             return None
         else:
             raise CreatorError("Unable to find package: %s" % (pkg))
@@ -525,7 +559,6 @@ class Zypp(BackendPlugin):
 
         # re-create image with updating some packages
         if len(installed_pkgs) == 0:
-            self.deleteUpdatedPkgs()
             installed_pkgs = self.update_pkgs
             update_only = True
 
@@ -970,9 +1003,10 @@ class Zypp(BackendPlugin):
             self.show_unresolved_dependencies_msg(unresolved_dependencies)
             raise RepoError("Unresolved dependencies, transaction failed.")
 
-    def deleteUpdatedPkgs(self):
-        if not self.update_pkgs:
-            return
+    def uninstallPkgs(self, package_objects):
+        def mychroot():
+            os.chroot(self.instroot)
+            os.chdir("/")
 
         if not self.ts:
             self.__initialize_transaction()
@@ -987,7 +1021,7 @@ class Zypp(BackendPlugin):
         self.ts.setProbFilter(probfilter)
 
         to_delete = []
-        for po in self.update_pkgs:
+        for po in package_objects:
             self.ts.addErase(po.name())
             to_delete.append(po.name())
         self.ts.order()
@@ -1008,8 +1042,10 @@ class Zypp(BackendPlugin):
                 unresolved_dependencies = self.ts.check()
             else:
                 self.show_unresolved_dependencies_msg(unresolved_dependencies)
-                raise RepoError("Unresolved dependencies, transaction failed.")
+                raise RpmError("Unresolved dependencies, transaction failed.")
 
+        # python rpm has a crash bug while use 'addErase' and 'run' to remove packages
+        """
         cb = rpmmisc.RPMInstallCallback(self.ts)
         logfile = "%s/__catched_stderr.buf" % (self.instroot)
 
@@ -1026,20 +1062,27 @@ class Zypp(BackendPlugin):
             if len(errors) == 0:
                 msger.warning('scriptlet or other non-fatal errors occurred '
                               'during transaction.')
-                if self.strict_mode:
-                    raise CreatorError("mic failes to uninstall some packages")
+                raise CreatorError("mic failes to uninstall some packages")
             else:
                 for e in errors:
                     msger.warning(e[0])
-                raise RepoError('Could not run transaction.')
+                raise RpmError('Could not run transaction.')
+        """
 
-        self.update_pkgs.clear()
-        for item in to_delete:
-            pkg = self._zyppQueryPackage(item)
-            if pkg:
-                self.update_pkgs.append(pkg)
-            else:
-                msger.warning("No updated rpm found for: %s" % item)
+        self.ts.closeDB()
+        self.ts = None
+
+        # chroot into install root and remove packages with rpm cmd
+        # note: the rpm package should has been installed in install root
+        retcode = 0
+        try:
+            cmd = 'rpm -e --allmatches %s' % ' '.join(to_delete)
+            msger.debug("do chroot and run command [%s] to erase packages" % cmd)
+            retcode = subprocess.call(cmd, preexec_fn=mychroot, shell=True)
+        except (IOError, OSError) as err:
+            raise CreatorError("chroot err: %s" % str(err))
+
+        return to_delete
 
     def __initialize_transaction(self):
         if not self.ts: