Skip to content

Commit

Permalink
refactor: split boot_control._common module into boot_control._ota_st…
Browse files Browse the repository at this point in the history
…atus_control and otaclient_common.cmdhelper (#421)

This PR splits the large boot_control._common module into boot_control._ota_status_control and otaclient_common.cmdhelper, and integrate these new modules into otaclient.

No breaking changes are introduced.
  • Loading branch information
Bodong-Yang authored Nov 13, 2024
1 parent 558c099 commit 720af55
Show file tree
Hide file tree
Showing 14 changed files with 800 additions and 805 deletions.
706 changes: 0 additions & 706 deletions src/otaclient/boot_control/_common.py

This file was deleted.

23 changes: 9 additions & 14 deletions src/otaclient/boot_control/_grub.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,15 @@
from otaclient._types import OTAStatus
from otaclient.boot_control._slot_mnt_helper import SlotMountHelper
from otaclient.configs.cfg import cfg
from otaclient_common import cmdhelper
from otaclient_common._io import (
read_str_from_file,
symlink_atomic,
write_str_to_file_atomic,
)
from otaclient_common.common import subprocess_call, subprocess_check_output

from ._common import (
CMDHelperFuncs,
OTAStatusFilesControl,
cat_proc_cmdline,
)
from ._ota_status_control import OTAStatusFilesControl, cat_proc_cmdline
from .configs import grub_cfg as boot_cfg
from .protocol import BootControllerProtocol

Expand Down Expand Up @@ -320,8 +317,8 @@ def _get_sibling_dev(self, active_dev: str) -> str:
NOTE: revert to use previous detection mechanism.
TODO: refine this method.
"""
parent = CMDHelperFuncs.get_parent_dev(active_dev)
boot_dev = CMDHelperFuncs.get_dev_by_mount_point("/boot")
parent = cmdhelper.get_parent_dev(active_dev)
boot_dev = cmdhelper.get_dev_by_mount_point("/boot")
if not boot_dev:
_err_msg = "/boot is not mounted"
logger.error(_err_msg)
Expand Down Expand Up @@ -360,7 +357,7 @@ def _detect_active_slot(self) -> Tuple[str, str]:
of the active slot.
"""
try:
dev_path = CMDHelperFuncs.get_current_rootfs_dev()
dev_path = cmdhelper.get_current_rootfs_dev(cfg.ACTIVE_ROOT)
assert dev_path
except Exception as e:
_err_msg = f"failed to detect current rootfs dev: {e!r}"
Expand Down Expand Up @@ -622,9 +619,7 @@ def _grub_update_on_booted_slot(self, *, abort_on_standby_missed=True):

grub_cfg_content = GrubHelper.grub_mkconfig()
try:
standby_uuid = CMDHelperFuncs.get_attrs_by_dev(
"UUID", self.standby_root_dev
)
standby_uuid = cmdhelper.get_attrs_by_dev("UUID", self.standby_root_dev)
assert standby_uuid
except Exception as e:
_err_msg = f"failed to get UUID of {self.standby_root_dev}: {e!r}"
Expand Down Expand Up @@ -775,7 +770,7 @@ def _update_fstab(self, *, active_slot_fstab: Path, standby_slot_fstab: Path):
Override existed entries in standby fstab, merge new entries from active fstab.
"""
try:
standby_uuid = CMDHelperFuncs.get_attrs_by_dev(
standby_uuid = cmdhelper.get_attrs_by_dev(
"UUID", self._boot_control.standby_root_dev
)
assert standby_uuid
Expand Down Expand Up @@ -923,7 +918,7 @@ def post_update(self) -> Generator[None, None, None]:
self._boot_control.grub_reboot_to_standby()

yield # hand over control to otaclient
CMDHelperFuncs.reboot()
cmdhelper.reboot()
except Exception as e:
_err_msg = f"failed on post_update: {e!r}"
logger.error(_err_msg)
Expand All @@ -949,7 +944,7 @@ def post_rollback(self):
logger.info("grub_boot: post-rollback setup...")
self._boot_control.grub_reboot_to_standby()
self._mp_control.umount_all(ignore_error=True)
CMDHelperFuncs.reboot()
cmdhelper.reboot()
except Exception as e:
_err_msg = f"failed on pre_rollback: {e!r}"
logger.error(_err_msg)
Expand Down
16 changes: 8 additions & 8 deletions src/otaclient/boot_control/_jetson_cboot.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,11 @@
)
from otaclient.boot_control._slot_mnt_helper import SlotMountHelper
from otaclient.configs.cfg import cfg
from otaclient_common import replace_root
from otaclient_common import cmdhelper, replace_root
from otaclient_common._io import cal_file_digest
from otaclient_common.common import subprocess_run_wrapper
from otaclient_common.typing import StrOrPath

from ._common import CMDHelperFuncs, OTAStatusFilesControl
from ._jetson_common import (
SLOT_PAR_MAP,
BSPVersion,
Expand All @@ -56,6 +55,7 @@
preserve_ota_config_files_to_standby,
update_standby_slot_extlinux_cfg,
)
from ._ota_status_control import OTAStatusFilesControl
from .configs import cboot_cfg as boot_cfg
from .protocol import BootControllerProtocol

Expand Down Expand Up @@ -361,10 +361,10 @@ def __init__(self):
# ------ detect rootfs_dev and parent_dev ------ #
try:
self.curent_rootfs_devpath = current_rootfs_devpath = (
CMDHelperFuncs.get_current_rootfs_dev()
cmdhelper.get_current_rootfs_dev(cfg.ACTIVE_ROOT)
)
self.parent_devpath = parent_devpath = Path(
CMDHelperFuncs.get_parent_dev(current_rootfs_devpath)
cmdhelper.get_parent_dev(current_rootfs_devpath)
)
except Exception as e:
_err_msg = f"failed to detect rootfs: {e!r}"
Expand All @@ -379,10 +379,10 @@ def __init__(self):
parent_devpath=parent_devpath,
partition_id=SLOT_PAR_MAP[standby_rootfs_slot],
)
self.standby_rootfs_dev_partuuid = CMDHelperFuncs.get_attrs_by_dev(
self.standby_rootfs_dev_partuuid = cmdhelper.get_attrs_by_dev(
"PARTUUID", self.standby_rootfs_devpath
).strip()
current_rootfs_dev_partuuid = CMDHelperFuncs.get_attrs_by_dev(
current_rootfs_dev_partuuid = cmdhelper.get_attrs_by_dev(
"PARTUUID", current_rootfs_devpath
).strip()
except Exception as e:
Expand Down Expand Up @@ -678,7 +678,7 @@ def post_update(self) -> Generator[None, None, None]:
logger.info(f"[post-update]: \n{NVBootctrlJetsonCBOOT.dump_slots_info()}")
logger.info("post update finished, wait for reboot ...")
yield # hand over control back to otaclient
CMDHelperFuncs.reboot()
cmdhelper.reboot()
except Exception as e:
_err_msg = f"failed on post_update: {e!r}"
logger.error(_err_msg)
Expand All @@ -704,7 +704,7 @@ def post_rollback(self):
logger.info("jetson-cboot: post-rollback setup...")
self._mp_control.umount_all(ignore_error=True)
self._cboot_control.switch_boot_to_standby()
CMDHelperFuncs.reboot()
cmdhelper.reboot()
except Exception as e:
_err_msg = f"failed on post_rollback: {e!r}"
logger.error(_err_msg)
Expand Down
9 changes: 4 additions & 5 deletions src/otaclient/boot_control/_jetson_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,11 @@
from pydantic import BaseModel, BeforeValidator, PlainSerializer
from typing_extensions import Annotated, Literal, Self

from otaclient_common import replace_root
from otaclient_common import cmdhelper, replace_root
from otaclient_common._io import write_str_to_file_atomic
from otaclient_common.common import copytree_identical
from otaclient_common.typing import StrOrPath

from ._common import CMDHelperFuncs
from .configs import jetson_common_cfg

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -410,8 +409,8 @@ def copy_standby_slot_boot_to_internal_emmc(
internal_emmc_mp.mkdir(exist_ok=True, parents=True)

try:
CMDHelperFuncs.umount(internal_emmc_devpath, raise_exception=False)
CMDHelperFuncs.mount_rw(
cmdhelper.umount(internal_emmc_devpath, raise_exception=False)
cmdhelper.mount_rw(
target=str(internal_emmc_devpath),
mount_point=internal_emmc_mp,
)
Expand All @@ -429,7 +428,7 @@ def copy_standby_slot_boot_to_internal_emmc(
logger.error(_msg)
raise ValueError(_msg) from e
finally:
CMDHelperFuncs.umount(internal_emmc_mp, raise_exception=False)
cmdhelper.umount(internal_emmc_mp, raise_exception=False)


def preserve_ota_config_files_to_standby(
Expand Down
24 changes: 12 additions & 12 deletions src/otaclient/boot_control/_jetson_uefi.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,11 @@
)
from otaclient.boot_control._slot_mnt_helper import SlotMountHelper
from otaclient.configs.cfg import cfg
from otaclient_common import replace_root
from otaclient_common import cmdhelper, replace_root
from otaclient_common._io import cal_file_digest, file_sha256, write_str_to_file_atomic
from otaclient_common.common import subprocess_call
from otaclient_common.typing import StrOrPath

from ._common import CMDHelperFuncs, OTAStatusFilesControl
from ._jetson_common import (
SLOT_PAR_MAP,
BSPVersion,
Expand All @@ -63,6 +62,7 @@
preserve_ota_config_files_to_standby,
update_standby_slot_extlinux_cfg,
)
from ._ota_status_control import OTAStatusFilesControl
from .configs import jetson_uefi_cfg as boot_cfg
from .protocol import BootControllerProtocol

Expand Down Expand Up @@ -177,7 +177,7 @@ def verify(cls) -> str | None: # pragma: no cover
@contextlib.contextmanager
def _ensure_efivarfs_mounted() -> Generator[None, Any, None]: # pragma: no cover
"""Ensure the efivarfs is mounted as rw, and then umount it."""
if CMDHelperFuncs.is_target_mounted(EFIVARS_SYS_MOUNT_POINT, raise_exception=False):
if cmdhelper.is_target_mounted(EFIVARS_SYS_MOUNT_POINT, raise_exception=False):
options = "remount,rw,nosuid,nodev,noexec,relatime"
else:
logger.warning(
Expand Down Expand Up @@ -265,9 +265,9 @@ def _ensure_esp_mounted(
mount_point.mkdir(exist_ok=True, parents=True)

try:
CMDHelperFuncs.mount_rw(str(esp_dev), mount_point)
cmdhelper.mount_rw(str(esp_dev), mount_point)
yield
CMDHelperFuncs.umount(mount_point, raise_exception=False)
cmdhelper.umount(mount_point, raise_exception=False)
except Exception as e:
_err_msg = f"failed to mount {esp_dev} to {mount_point}: {e!r}"
logger.error(_err_msg)
Expand All @@ -277,7 +277,7 @@ def _ensure_esp_mounted(
def _detect_esp_dev(boot_parent_devpath: StrOrPath) -> str:
# NOTE: if boots from external, expects to have multiple esp parts,
# we need to get the one at our booted parent dev.
esp_parts = CMDHelperFuncs.get_dev_by_token(
esp_parts = cmdhelper.get_dev_by_token(
token="PARTLABEL", value=boot_cfg.ESP_PARTLABEL
)
if not esp_parts:
Expand Down Expand Up @@ -794,10 +794,10 @@ def __init__(self):
# ------ detect rootfs_dev and parent_dev ------ #
try:
self.curent_rootfs_devpath = current_rootfs_devpath = (
CMDHelperFuncs.get_current_rootfs_dev()
cmdhelper.get_current_rootfs_dev(cfg.ACTIVE_ROOT)
)
self.parent_devpath = parent_devpath = Path(
CMDHelperFuncs.get_parent_dev(current_rootfs_devpath)
cmdhelper.get_parent_dev(current_rootfs_devpath)
)
except Exception as e:
_err_msg = f"failed to detect rootfs dev: {e!r}"
Expand All @@ -813,10 +813,10 @@ def __init__(self):
)

try:
self.standby_rootfs_dev_partuuid = CMDHelperFuncs.get_attrs_by_dev(
self.standby_rootfs_dev_partuuid = cmdhelper.get_attrs_by_dev(
"PARTUUID", self.standby_rootfs_devpath
).strip()
current_rootfs_dev_partuuid = CMDHelperFuncs.get_attrs_by_dev(
current_rootfs_dev_partuuid = cmdhelper.get_attrs_by_dev(
"PARTUUID", current_rootfs_devpath
).strip()
except Exception as e:
Expand Down Expand Up @@ -1064,7 +1064,7 @@ def post_update(self) -> Generator[None, None, None]:
self._mp_control.umount_all(ignore_error=True)
logger.info("post update finished, wait for reboot ...")
yield # hand over control back to otaclient
CMDHelperFuncs.reboot()
cmdhelper.reboot()
except Exception as e:
_err_msg = f"jetson-uefi: failed on post_update: {e!r}"
logger.error(_err_msg)
Expand All @@ -1090,7 +1090,7 @@ def post_rollback(self):
logger.info("jetson-uefi: post-rollback setup...")
self._mp_control.umount_all(ignore_error=True)
self._uefi_control.switch_boot_to_standby()
CMDHelperFuncs.reboot()
cmdhelper.reboot()
except Exception as e:
_err_msg = f"jetson-uefi: failed on post_rollback: {e!r}"
logger.error(_err_msg)
Expand Down
Loading

1 comment on commit 720af55

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCoverMissing
src/ota_metadata/legacy
   __init__.py10100% 
   parser.py3264386%100, 156, 161, 197–198, 208–209, 212, 224, 277–279, 283–286, 320–323, 392, 395, 403–405, 418, 427–428, 431–432, 597–599, 649–650, 653, 681–683, 737, 740–742
   types.py841384%37, 40–42, 112–116, 122–125
src/ota_metadata/utils
   cert_store.py420100% 
src/ota_proxy
   __init__.py361072%59, 61, 63, 72, 81–82, 102, 104–106
   __main__.py770%16–18, 20, 22–23, 25
   _consts.py150100% 
   cache_control_header.py68494%71, 91, 113, 121
   cache_streaming.py1442284%154–156, 184–186, 211, 225, 229–230, 265–266, 268, 280, 349, 355–356, 359, 367–370
   config.py170100% 
   db.py731875%109, 115, 153, 159–160, 163, 169, 171, 192–199, 201–202
   errors.py50100% 
   lru_cache_helper.py47295%84–85
   ota_cache.py2155972%70–71, 140, 151–152, 184–185, 202, 239–243, 247–249, 251, 253–260, 262–264, 267–268, 272–273, 277, 324, 332–334, 413–416, 430, 433–434, 448–449, 451–453, 457–458, 464–465, 496, 502, 529, 581–583
   server_app.py1393971%76, 79, 85, 101, 103, 162, 171, 213–214, 216–218, 221, 226–228, 231–232, 235, 238, 241, 244, 257–258, 261–262, 264, 267, 293–296, 299, 313–315, 321–323
   utils.py140100% 
src/otaclient
   __init__.py5260%17, 19
   __main__.py110%16
   _types.py740100% 
   errors.py1210100% 
   log_setting.py51590%52, 54, 63–65
   ota_core.py38511370%84, 92, 113, 140, 142–143, 145, 149, 153–154, 159–160, 166, 168, 209–212, 218, 222, 228, 347, 359–360, 362, 371, 374, 379–380, 383, 389, 391–395, 414–417, 420–427, 455–458, 511–512, 516, 518–519, 549–550, 559–566, 573, 576–582, 630–632, 634, 636–639, 647, 662, 691–693, 698–700, 703–704, 706–707, 709, 767–768, 771, 779–780, 783, 794–795, 798, 806–807, 810, 821, 840, 867, 886, 904
   status_monitor.py1581391%46, 48–49, 134–135, 154, 157, 174, 177, 193–194, 201, 204
   utils.py170100% 
src/otaclient/app
   __main__.py110%16
   main.py44588%48–49, 71–73
   update_stats.py104991%57, 103, 105, 114, 116, 125, 127, 148, 179
src/otaclient/boot_control
   __init__.py40100% 
   _firmware_package.py932276%82, 86, 136, 180, 186, 209–210, 213–218, 220–221, 224–229, 231
   _grub.py41312469%214, 262–265, 271–275, 312–313, 320–325, 328–334, 337, 340–341, 346, 348–350, 359–365, 367–368, 370–372, 381–383, 385–387, 466–467, 471–472, 524, 530, 556, 578, 582–583, 598–600, 624–627, 639, 643–645, 647–649, 708–711, 736–739, 762–765, 777–778, 781–782, 817, 823, 843–844, 846, 871–873, 891–894, 922–925, 930–938, 943–951
   _jetson_cboot.py2562560%20, 22–25, 27–29, 35–40, 42, 58–60, 62, 64–65, 71, 75, 134, 137, 139–140, 143, 150–151, 159–160, 163, 169–170, 178, 187–191, 193, 199, 202–203, 209, 212–213, 218–219, 221, 227–228, 231–232, 235–237, 239, 245, 250–252, 254–256, 261, 263–266, 268–269, 278–279, 282–283, 288–289, 292–296, 299–300, 305–306, 309, 312–316, 321–324, 327, 330–331, 334, 337–338, 341, 345–350, 354–355, 359, 362–363, 366, 369–372, 374, 377–378, 382, 385, 388–391, 393, 400, 404–405, 408–409, 415–416, 422, 424–425, 429, 431, 433–435, 438, 442, 445, 448–449, 451, 454, 462–463, 470, 480, 483, 491–492, 497–500, 502, 509, 511–513, 519–520, 524–525, 528, 532, 535, 537, 544–548, 550, 562–565, 568, 571, 573, 580, 590–592, 594, 596, 599, 602, 605, 607–608, 611–615, 619–621, 623, 631–635, 637, 640, 644, 647, 658–659, 664, 674, 677–685, 689–698, 702–711, 715, 717–719
   _jetson_common.py1724573%132, 140, 288–291, 294, 311, 319, 354, 359–364, 382, 408–409, 411–413, 417–420, 422–423, 425–429, 431, 438–439, 442–443, 453, 456–457, 460, 462, 506–507
   _jetson_uefi.py39927132%124–126, 131–132, 151–153, 158–161, 328, 446, 448–451, 455, 459–460, 462–470, 472, 484–485, 488–489, 492–493, 496–498, 502–503, 508–510, 514, 518–519, 522–523, 526–527, 531, 534–535, 537, 542–543, 547, 550–551, 556, 560–561, 564, 568–570, 572, 576–579, 581–582, 604–605, 609–610, 612, 616, 620–621, 624–625, 632, 635–637, 640, 642–643, 648–649, 652–655, 657–658, 663, 665–666, 674, 677–680, 682–683, 685, 689–690, 694, 702–706, 709–710, 712, 715–719, 722, 725–729, 733–734, 737–742, 745–746, 749–752, 754–755, 762–763, 773–776, 779, 782–785, 788–792, 795–796, 799, 802–805, 808, 810, 815–816, 819, 822–825, 827, 833, 838–839, 858–859, 862, 870–871, 878, 888, 891, 898–899, 904–907, 915–918, 926–927, 939–942, 944, 947, 950, 958, 969–971, 973–975, 977–981, 986–987, 989, 1002, 1006, 1009, 1019, 1024, 1032–1033, 1036, 1040, 1042–1044, 1050–1051, 1056, 1064–1071, 1076–1084, 1089–1097, 1103–1105
   _ota_status_control.py1021189%117, 122, 127, 240, 244–245, 248, 255, 257–258, 273
   _rpi_boot.py28213053%53, 56, 120–121, 125, 133–136, 150–153, 158–159, 161–162, 167–168, 171–172, 181–182, 222, 228–232, 235, 253–255, 259–261, 266–268, 272–274, 284–285, 288, 291, 293–294, 296–297, 299–301, 307, 310–311, 321–324, 332–336, 338, 340–341, 346–347, 354, 357–362, 393, 395–398, 408–411, 415–416, 418–422, 450–453, 472–475, 501–504, 509–517, 522–530, 547–550, 556–558
   _slot_mnt_helper.py120100% 
   configs.py510100% 
   protocol.py60100% 
   selecter.py412929%44–46, 49–50, 54–55, 58–60, 63, 65, 69, 77–79, 81–82, 84–85, 89, 91, 93–94, 96, 98–99, 101, 103
src/otaclient/configs
   __init__.py170100% 
   _cfg_configurable.py490100% 
   _cfg_consts.py47197%97
   _common.py80100% 
   _ecu_info.py56394%59, 64–65
   _proxy_info.py51296%88, 90
   cfg.py190100% 
src/otaclient/create_standby
   __init__.py13561%30–32, 34, 36
   common.py2244480%62, 65–66, 70–72, 74, 78–79, 81, 129, 177–179, 181–183, 185, 188–191, 195, 206, 280–281, 283–288, 300, 337, 365, 368–370, 386–387, 401, 405, 427–428
   interface.py50100% 
   rebuild_mode.py98990%95–97, 109–114
src/otaclient/grpc
   _otaproxy_ctx.py1175156%68–70, 72–73, 81–84, 87–89, 93, 98–99, 101–102, 105, 107–108, 111–113, 116–117, 120–122, 127–132, 136, 139–143, 145–146, 154–156, 159, 196–198, 203, 239
src/otaclient/grpc/api_v2
   ecu_status.py1511292%73, 76, 79, 145, 169, 171, 195, 241, 298, 368–369, 408
   ecu_tracker.py321843%40–42, 48–51, 55–57, 64–66, 69, 73–76
   servicer.py1182876%88, 177–179, 186, 216–217, 220–224, 233–242, 249, 255, 258–259, 263, 266
   types.py44440%17, 19, 21–23, 26, 33–37, 39, 42, 45, 48, 51–52, 61, 67, 70–71, 73–76, 78–79, 82–88, 91–97, 100, 102–103
src/otaclient_api/v2
   api_caller.py39684%45–47, 83–85
   api_stub.py170100% 
   types.py2562391%86, 89–92, 131, 209–210, 212, 259, 262–263, 506–508, 512–513, 515, 518–519, 522–523, 586
src/otaclient_common
   __init__.py341555%42–44, 61, 63, 68–77
   _io.py64198%41
   cmdhelper.py90100% 
   common.py1061189%44, 148, 151–153, 168, 175–177, 271, 275
   downloader.py1991094%107–108, 126, 153, 369, 424, 428, 516–517, 526
   linux.py611575%51–53, 59, 69, 74, 76, 108–109, 133–134, 190, 195–196, 198
   logging.py29196%55
   persist_file_handling.py1181884%113, 118, 150–152, 163, 192–193, 228–232, 242–244, 246–247
   proto_streamer.py42880%33, 48, 66–67, 72, 81–82, 100
   proto_wrapper.py3984887%87, 165, 172, 184–186, 205, 210, 221, 257, 263, 268, 299, 303, 307, 402, 462, 469, 472, 492, 499, 501, 526, 532, 535, 537, 562, 568, 571, 573, 605, 609, 611, 625, 642, 669, 672, 676, 707, 713, 760–763, 765, 803–805
   retry_task_map.py105595%158–159, 161, 181–182
   typing.py31487%48, 97–98, 100
TOTAL6582163675% 

Tests Skipped Failures Errors Time
242 0 💤 0 ❌ 0 🔥 14m 9s ⏱️

Please sign in to comment.