isu_pkgs_maker: Return exit code on error 57/293457/2 accepted/tizen/6.0/unified/20230717.162445 accepted/tizen/6.5/unified/20230717.164350 accepted/tizen/7.0/unified/20230717.162653
authorMateusz Moscicki <m.moscicki2@partner.samsung.com>
Mon, 29 May 2023 14:31:13 +0000 (16:31 +0200)
committerMateusz Moscicki <m.moscicki2@partner.samsung.com>
Tue, 30 May 2023 12:06:00 +0000 (14:06 +0200)
Change-Id: Iffe109fad430ec88da6833a1eb65b0124e3aaa09

src/pkg_maker/isu_pkgs_maker.py

index 6c9dcb5..a6c1b7e 100755 (executable)
@@ -6,6 +6,7 @@ import xml.etree.ElementTree as ET
 import contextlib
 import logging
 import os
+import sys
 import os.path
 import shutil
 import subprocess
@@ -65,6 +66,17 @@ class ISUNoServiceException(Exception):
     """No service file"""
     pass
 
+class MountErrorException(Exception):
+    pass
+
+class UncleanExitException(Exception):
+    pass
+
+class ISUPkgCreateErrorException(Exception):
+    pass
+
+class NoISUConfigDirException(Exception):
+    pass
 
 class Config:
     def __init__(self):
@@ -493,6 +505,7 @@ class ISUSinglePkgMaker:
                 logger.info(f"SUCCESS: ISU Package {pkg_result_name} created.")
             except FileExistsError as e:
                 logger.error(f"ISU package \"{self._ctx.cfg.name}\" prepare error: {e}")
+                raise ISUPkgCreateErrorException()
 
     def _clear(self):
         logger.info(f"Remove {self._ctx.work_dir}")
@@ -547,37 +560,49 @@ class ISUPkgsMaker:
 
         return cfg
 
-    def run(self):
-        try:
-            with Extractor(self._ctx) as extractor:
-                with contextlib.ExitStack() as stack:
-                    mounts = {img_name: stack.enter_context(Mounter(img_path, self._ctx.tmp_dir))
-                                             for (img_name, img_path) in extractor.images().items()}
-
-                    if any(m.failed() for m in mounts.values()):
-                        logger.error("Some error during mounts")
-                        return
-
-                    isu_on_rootfs = mounts['rootfs.img'].mnt_dir() / 'etc/isu'
-                    logger.info(f"Processing configs in {isu_on_rootfs}")
-                    for isudir in os.listdir(isu_on_rootfs):
-                        try:
-                            isudir_path = isu_on_rootfs / isudir
-                            isucfg_path = isudir_path / ISUSinglePkgMaker.ISU_CFG_FILE
-                            if isudir_path.is_dir() and isucfg_path.is_file():
-                                logger.info(f"\n=========\nProcess dir: {isudir}\n=========")
-                                cfg = self.load_config(isucfg_path)
-                                try:
-                                    with ISUSinglePkgMaker(isudir_path, cfg, mounts, self._ctx) as isu_maker:
-                                        isu_maker.make_pkg()
-                                except ISUNoServiceException as error:
-                                    logger.warning(f"No service file ({error}) found for {cfg.name} package. Perhaps the file was deleted by security-config tests.")
-                        except InvalidConfigException as error:
-                            logger.error(f"Load isu.cfg error: {error}")
-                    logger.info(f"End of processing")
-        except Exception as err:
-            logger.error(f"Run error: {err}")
-            traceback.print_exc()
+    def run(self, exit_on_any_error=False):
+        some_errors = False
+        with Extractor(self._ctx) as extractor:
+            with contextlib.ExitStack() as stack:
+                mounts = {img_name: stack.enter_context(Mounter(img_path, self._ctx.tmp_dir))
+                                         for (img_name, img_path) in extractor.images().items()}
+
+                if any(m.failed() for m in mounts.values()):
+                    logger.error("Some error during mounts")
+                    raise MountErrorException()
+
+                isu_on_rootfs = mounts['rootfs.img'].mnt_dir() / 'etc/isu'
+                logger.info(f"Processing configs in {isu_on_rootfs}")
+                if not isu_on_rootfs.is_dir():
+                    logger.warning("No ISU config dir on the image.")
+                    raise NoISUConfigDirException()
+                for isudir in os.listdir(isu_on_rootfs):
+                    try:
+                        isudir_path = isu_on_rootfs / isudir
+                        isucfg_path = isudir_path / ISUSinglePkgMaker.ISU_CFG_FILE
+                        if isudir_path.is_dir() and isucfg_path.is_file():
+                            logger.info(f"\n=========\nProcess dir: {isudir}\n=========")
+                            cfg = self.load_config(isucfg_path)
+                            try:
+                                with ISUSinglePkgMaker(isudir_path, cfg, mounts, self._ctx) as isu_maker:
+                                    isu_maker.make_pkg()
+                            except ISUPkgCreateErrorException:
+                                some_errors = True
+                                if exit_on_any_error:
+                                    break
+                            except ISUNoServiceException as error:
+                                logger.warning(f"No service file ({error}) found for {cfg.name} package. Perhaps the file was deleted by security-config tests.")
+                                some_errors = True
+                                if exit_on_any_error:
+                                    break
+                    except InvalidConfigException as error:
+                        logger.error(f"Load isu.cfg error: {error}")
+                        some_errors = True
+                        if exit_on_any_error:
+                            break
+                logger.info(f"End of processing")
+        if some_errors:
+            raise UncleanExitException()
 
 
 def load_map(map_path: Path) -> FileMapper:
@@ -587,14 +612,14 @@ def load_map(map_path: Path) -> FileMapper:
     return FileMapper(map)
 
 
-def main():
+def main() -> int:
     logger.info("Start")
 
     try:
         os.seteuid(getpwnam("nobody").pw_uid)
     except PermissionError as error:
         logger.error(f"seteuid() error: {error}")
-        return
+        return os.EX_NOPERM
     parser = argparse.ArgumentParser(description="ISU Pkgs maker")
     parser.add_argument('--src', '-s', type=str, required=True,
                         help="Directory with images archive")
@@ -604,14 +629,34 @@ def main():
                         help="File with image<->path mapping")
     parser.add_argument('--key', '-k', type=str, required=True,
                         help="Signing key")
+    parser.add_argument('--exit_on_any_error', '-e', action='store_true',
+                        required=False, help="Terminate after any error")
 
     args = parser.parse_args()
     map = load_map(args.map)
 
 
-    with TemporaryDirectory() as tmp_dir:
-        with ISUPkgsMaker(Path(args.src), Path(tmp_dir), Path(args.out), Path(args.key), map) as isu_pkgs_maker:
-            isu_pkgs_maker.run()
+    try:
+        with TemporaryDirectory() as tmp_dir:
+            with ISUPkgsMaker(Path(args.src),
+                              Path(tmp_dir),
+                              Path(args.out),
+                              Path(args.key),
+                              map) as isu_pkgs_maker:
+                isu_pkgs_maker.run(args.exit_on_any_error)
+    except NoISUConfigDirException:
+        return os.EX_OK
+    except MountErrorException:
+        return os.EX_IOERR
+    except UncleanExitException:
+        return os.EX_SOFTWARE
+    except Exception as err:
+        logger.error(f"Run error: {err}")
+        traceback.print_exc()
+        return os.EX_SOFTWARE
+
+    return os.EX_OK
 
 if __name__ == '__main__':
-    main()
+    code = main()
+    sys.exit(code)