2021-10-22 17:07:05 +02:00
import atexit
import json
2021-08-05 20:26:48 +02:00
import os
2021-10-22 17:07:05 +02:00
import re
2021-08-05 20:26:48 +02:00
import subprocess
import click
2021-10-27 02:52:46 +02:00
import logging
2022-01-28 14:21:11 +01:00
from signal import pause
2022-02-06 23:37:40 +01:00
from subprocess import run , CompletedProcess
2022-02-18 06:32:04 +01:00
from typing import Optional
2022-01-28 14:21:11 +01:00
2022-02-18 06:32:04 +01:00
from chroot . device import DeviceChroot , get_device_chroot
2022-03-03 16:54:43 +01:00
from constants import Arch , BASE_PACKAGES , DEVICES , FLAVOURS
2022-02-18 06:32:04 +01:00
from config import config , Profile
2022-03-03 16:54:43 +01:00
from distro . distro import get_base_distro , get_kupfer_https
2022-01-27 04:07:06 +01:00
from packages import build_enable_qemu_binfmt , discover_packages , build_packages
2021-10-15 22:52:13 +02:00
from ssh import copy_ssh_keys
2021-09-29 23:18:12 +02:00
from wrapper import enforce_wrap
2021-08-05 20:26:48 +02:00
2022-02-06 23:37:40 +01:00
# image files need to be slightly smaller than partitions to fit
IMG_FILE_ROOT_DEFAULT_SIZE = " 1800M "
IMG_FILE_BOOT_DEFAULT_SIZE = " 90M "
def dd_image ( input : str , output : str , blocksize = ' 1M ' ) - > CompletedProcess :
2022-05-08 17:27:58 +02:00
cmd = [
2022-02-06 23:37:40 +01:00
' dd ' ,
f ' if= { input } ' ,
f ' of= { output } ' ,
f ' bs= { blocksize } ' ,
' iflag=direct ' ,
' oflag=direct ' ,
' status=progress ' ,
' conv=sync,noerror ' ,
2022-05-08 17:27:58 +02:00
]
logging . debug ( f ' running dd cmd: { cmd } ' )
return subprocess . run ( cmd )
2022-02-06 23:37:40 +01:00
2021-08-05 20:26:48 +02:00
2022-02-06 23:40:00 +01:00
def partprobe ( device : str ) :
return subprocess . run ( [ ' partprobe ' , device ] )
2021-10-22 17:07:05 +02:00
def shrink_fs ( loop_device : str , file : str , sector_size : int ) :
# 8: 512 bytes sectors
# 1: 4096 bytes sectors
sectors_blocks_factor = 4096 / / sector_size
2022-03-02 15:59:51 +01:00
partprobe ( loop_device )
2021-10-22 17:07:05 +02:00
logging . debug ( f " Checking filesystem at { loop_device } p2 " )
result = subprocess . run ( [ ' e2fsck ' , ' -fy ' , f ' { loop_device } p2 ' ] )
2021-10-01 12:32:44 +02:00
if result . returncode > 2 :
2021-10-22 17:07:05 +02:00
# https://man7.org/linux/man-pages/man8/e2fsck.8.html#EXIT_CODE
raise Exception ( f ' Failed to e2fsck { loop_device } p2 with exit code { result . returncode } ' )
logging . debug ( f ' Shrinking filesystem at { loop_device } p2 ' )
result = subprocess . run ( [ ' resize2fs ' , ' -M ' , f ' { loop_device } p2 ' ] , capture_output = True )
if result . returncode != 0 :
print ( result . stdout )
print ( result . stderr )
raise Exception ( f ' Failed to resize2fs { loop_device } p2 ' )
logging . debug ( f ' Finding end block of shrunken filesystem on { loop_device } p2 ' )
2022-02-18 06:32:04 +01:00
blocks = int ( re . search ( ' is now [0-9]+ ' , result . stdout . decode ( ' utf-8 ' ) ) . group ( 0 ) . split ( ' ' ) [ 2 ] ) # type: ignore
2021-10-22 17:07:05 +02:00
sectors = blocks * sectors_blocks_factor #+ 157812 - 25600
logging . debug ( f ' Shrinking partition at { loop_device } p2 to { sectors } sectors ' )
child_proccess = subprocess . Popen (
[ ' fdisk ' , ' -b ' , str ( sector_size ) , loop_device ] ,
stdin = subprocess . PIPE ,
)
2022-02-18 06:32:04 +01:00
child_proccess . stdin . write ( ' \n ' . join ( [ # type: ignore
2021-10-22 17:07:05 +02:00
' d ' ,
' 2 ' ,
' n ' ,
' p ' ,
' 2 ' ,
' ' ,
f ' + { sectors } ' ,
' w ' ,
' q ' ,
] ) . encode ( ' utf-8 ' ) )
child_proccess . communicate ( )
returncode = child_proccess . wait ( )
if returncode == 1 :
# For some reason re-reading the partition table fails, but that is not a problem
subprocess . run ( [ ' partprobe ' ] )
if returncode > 1 :
raise Exception ( f ' Failed to shrink partition size of { loop_device } p2 with fdisk ' )
2022-02-06 23:40:00 +01:00
partprobe ( loop_device )
2021-10-22 17:07:05 +02:00
logging . debug ( f ' Finding end sector of partition at { loop_device } p2 ' )
result = subprocess . run ( [ ' fdisk ' , ' -b ' , str ( sector_size ) , ' -l ' , loop_device ] , capture_output = True )
if result . returncode != 0 :
print ( result . stdout )
print ( result . stderr )
raise Exception ( f ' Failed to fdisk -l { loop_device } ' )
end_sector = 0
for line in result . stdout . decode ( ' utf-8 ' ) . split ( ' \n ' ) :
if line . startswith ( f ' { loop_device } p2 ' ) :
parts = list ( filter ( lambda part : part != ' ' , line . split ( ' ' ) ) )
end_sector = int ( parts [ 2 ] )
if end_sector == 0 :
raise Exception ( f ' Failed to find end sector of { loop_device } p2 ' )
2022-03-02 15:59:51 +01:00
end_size = ( end_sector + 1 ) * sector_size
2021-10-22 17:07:05 +02:00
2022-03-02 15:59:51 +01:00
logging . debug ( f ' ( { end_sector } + 1) sectors * { sector_size } bytes/sector = { end_size } bytes ' )
logging . info ( f ' Truncating { file } to { end_size } bytes ' )
result = subprocess . run ( [ ' truncate ' , ' -s ' , str ( end_size ) , file ] )
2021-09-30 05:04:42 +02:00
if result . returncode != 0 :
2021-10-22 17:07:05 +02:00
raise Exception ( f ' Failed to truncate { file } ' )
2022-02-06 23:40:00 +01:00
partprobe ( loop_device )
2021-09-30 05:04:42 +02:00
2022-02-18 06:32:04 +01:00
def get_device_and_flavour ( profile_name : Optional [ str ] = None ) - > tuple [ str , str ] :
2021-10-25 21:00:18 +02:00
config . enforce_config_loaded ( )
2022-02-18 06:32:04 +01:00
profile = config . get_profile ( profile_name )
2021-09-29 02:00:59 +02:00
if not profile [ ' device ' ] :
raise Exception ( " Please set the device using ' kupferbootstrap config init ... ' " )
2021-08-05 20:26:48 +02:00
2021-09-29 02:00:59 +02:00
if not profile [ ' flavour ' ] :
raise Exception ( " Please set the flavour using ' kupferbootstrap config init ... ' " )
2021-08-05 20:26:48 +02:00
2021-09-29 02:00:59 +02:00
return ( profile [ ' device ' ] , profile [ ' flavour ' ] )
2021-08-05 20:26:48 +02:00
2022-02-06 23:37:40 +01:00
def get_image_name ( device , flavour , img_type = ' full ' ) - > str :
return f ' { device } - { flavour } - { img_type } .img '
2021-08-05 20:26:48 +02:00
2022-02-06 23:37:40 +01:00
def get_image_path ( device , flavour , img_type = ' full ' ) - > str :
return os . path . join ( config . get_path ( ' images ' ) , get_image_name ( device , flavour , img_type ) )
2021-08-05 20:26:48 +02:00
2021-08-08 18:32:42 +02:00
2021-10-22 17:07:05 +02:00
def losetup_rootfs_image ( image_path : str , sector_size : int ) - > str :
2022-01-28 14:21:11 +01:00
logging . debug ( f ' Creating loop device for { image_path } with sector size { sector_size } ' )
2021-10-22 17:07:05 +02:00
result = subprocess . run ( [
' losetup ' ,
' -f ' ,
' -b ' ,
str ( sector_size ) ,
2021-10-26 05:41:22 +02:00
' -P ' ,
2021-10-22 17:07:05 +02:00
image_path ,
] )
if result . returncode != 0 :
2022-01-28 14:21:11 +01:00
logging . fatal ( f ' Failed to create loop device for { image_path } ' )
2021-10-22 17:07:05 +02:00
exit ( 1 )
logging . debug ( f ' Finding loop device for { image_path } ' )
result = subprocess . run ( [ ' losetup ' , ' -J ' ] , capture_output = True )
if result . returncode != 0 :
print ( result . stdout )
print ( result . stderr )
logging . fatal ( ' Failed to list loop devices ' )
exit ( 1 )
data = json . loads ( result . stdout . decode ( ' utf-8 ' ) )
loop_device = ' '
for d in data [ ' loopdevices ' ] :
if d [ ' back-file ' ] == image_path :
loop_device = d [ ' name ' ]
break
if loop_device == ' ' :
raise Exception ( f ' Failed to find loop device for { image_path } ' )
2022-02-06 23:40:00 +01:00
partprobe ( loop_device )
2021-10-22 17:07:05 +02:00
def losetup_destroy ( ) :
logging . debug ( f ' Destroying loop device { loop_device } for { image_path } ' )
subprocess . run (
[
' losetup ' ,
' -d ' ,
loop_device ,
] ,
stderr = subprocess . DEVNULL ,
)
atexit . register ( losetup_destroy )
return loop_device
2022-02-18 06:32:04 +01:00
def mount_chroot ( rootfs_source : str , boot_src : str , chroot : DeviceChroot ) :
2022-02-06 19:48:34 +01:00
logging . debug ( f ' Mounting { rootfs_source } at { chroot . path } ' )
2021-10-22 17:07:05 +02:00
2022-02-06 19:48:34 +01:00
chroot . mount_rootfs ( rootfs_source )
2021-10-26 05:41:22 +02:00
assert ( os . path . ismount ( chroot . path ) )
2021-10-22 17:07:05 +02:00
2021-10-26 05:41:22 +02:00
os . makedirs ( chroot . get_path ( ' boot ' ) , exist_ok = True )
2021-10-22 17:07:05 +02:00
2022-02-06 19:48:34 +01:00
logging . debug ( f ' Mounting { boot_src } at { chroot . path } /boot ' )
chroot . mount ( boot_src , ' /boot ' , options = [ ' defaults ' ] )
2021-10-22 17:07:05 +02:00
2022-02-06 20:36:11 +01:00
def dump_aboot ( image_path : str ) - > str :
2022-02-06 19:41:31 +01:00
path = ' /tmp/aboot.img '
2021-08-17 20:57:31 +02:00
result = subprocess . run ( [
' debugfs ' ,
2021-10-25 21:00:18 +02:00
image_path ,
2021-08-17 20:57:31 +02:00
' -R ' ,
2022-02-06 19:41:31 +01:00
f ' dump /aboot.img { path } ' ,
2021-08-17 20:57:31 +02:00
] )
if result . returncode != 0 :
2022-02-06 19:41:31 +01:00
logging . fatal ( ' Failed to dump aboot.img ' )
2021-08-17 20:57:31 +02:00
exit ( 1 )
return path
2021-10-25 21:00:18 +02:00
def dump_lk2nd ( image_path : str ) - > str :
2021-08-17 20:57:31 +02:00
"""
This doesn ' t append the image with the appended DTB which is needed for some devices, so it should get added in the future.
"""
path = ' /tmp/lk2nd.img '
result = subprocess . run ( [
' debugfs ' ,
2021-10-25 21:00:18 +02:00
image_path ,
2021-08-17 20:57:31 +02:00
' -R ' ,
2021-10-22 17:07:05 +02:00
f ' dump /lk2nd.img { path } ' ,
2021-08-17 20:57:31 +02:00
] )
if result . returncode != 0 :
2021-09-30 03:50:11 +02:00
logging . fatal ( ' Failed to dump lk2nd.img ' )
2021-08-17 20:57:31 +02:00
exit ( 1 )
return path
2021-10-25 21:00:18 +02:00
def dump_qhypstub ( image_path : str ) - > str :
2021-08-17 20:57:31 +02:00
path = ' /tmp/qhypstub.bin '
result = subprocess . run ( [
' debugfs ' ,
2021-10-25 21:00:18 +02:00
image_path ,
2021-08-17 20:57:31 +02:00
' -R ' ,
2021-10-22 17:07:05 +02:00
f ' dump /qhypstub.bin { path } ' ,
2021-08-17 20:57:31 +02:00
] )
if result . returncode != 0 :
2021-09-30 03:50:11 +02:00
logging . fatal ( ' Failed to dump qhypstub.bin ' )
2021-08-17 20:57:31 +02:00
exit ( 1 )
return path
2022-02-06 23:37:40 +01:00
def create_img_file ( image_path : str , size_str : str ) :
result = subprocess . run ( [
' truncate ' ,
' -s ' ,
size_str ,
image_path ,
] )
if result . returncode != 0 :
raise Exception ( f ' Failed to allocate { image_path } ' )
return image_path
def partition_device ( device : str ) :
boot_partition_size = ' 100MiB '
create_partition_table = [ ' mklabel ' , ' msdos ' ]
create_boot_partition = [ ' mkpart ' , ' primary ' , ' ext2 ' , ' 0 % ' , boot_partition_size ]
create_root_partition = [ ' mkpart ' , ' primary ' , boot_partition_size , ' 100 % ' ]
enable_boot = [ ' set ' , ' 1 ' , ' boot ' , ' on ' ]
result = subprocess . run ( [
' parted ' ,
' --script ' ,
device ,
] + create_partition_table + create_boot_partition + create_root_partition + enable_boot )
if result . returncode != 0 :
raise Exception ( f ' Failed to create partitions on { device } ' )
2022-02-07 01:48:55 +01:00
def create_filesystem ( device : str , blocksize : int = 4096 , label = None , options = [ ] , fstype = ' ext4 ' ) :
# blocksize can be 4k max due to pagesize
blocksize = min ( blocksize , 4096 )
if fstype . startswith ( ' ext ' ) :
# blocksize for ext-fs must be >=1024
blocksize = max ( blocksize , 1024 )
labels = [ ' -L ' , label ] if label else [ ]
cmd = [
f ' mkfs. { fstype } ' ,
2022-02-06 23:37:40 +01:00
' -F ' ,
2022-02-07 01:20:38 +01:00
' -b ' ,
str ( blocksize ) ,
2022-02-07 01:48:55 +01:00
] + labels + [ device ]
result = subprocess . run ( cmd )
2022-02-06 23:37:40 +01:00
if result . returncode != 0 :
2022-02-07 01:48:55 +01:00
raise Exception ( f ' Failed to create { fstype } filesystem on { device } with CMD: { cmd } ' )
def create_root_fs ( device : str , blocksize : int ) :
create_filesystem ( device , blocksize = blocksize , label = ' kupfer_root ' , options = [ ' -O ' , ' ^metadata_csum ' , ' -N ' , ' 100000 ' ] )
2022-02-06 23:37:40 +01:00
2022-02-07 01:20:38 +01:00
def create_boot_fs ( device : str , blocksize : int ) :
2022-02-07 01:48:55 +01:00
create_filesystem ( device , blocksize = blocksize , label = ' kupfer_boot ' , fstype = ' ext2 ' )
2022-02-06 23:37:40 +01:00
2022-03-03 16:54:43 +01:00
def install_rootfs (
rootfs_device : str ,
bootfs_device : str ,
device : str ,
flavour : str ,
arch : Arch ,
packages : list [ str ] ,
use_local_repos : bool ,
profile : Profile ,
) :
2022-02-06 23:37:40 +01:00
user = profile [ ' username ' ] or ' kupfer '
post_cmds = FLAVOURS [ flavour ] . get ( ' post_cmds ' , [ ] )
2022-03-03 16:54:43 +01:00
chroot = get_device_chroot ( device = device , flavour = flavour , arch = arch , packages = packages , use_local_repos = use_local_repos )
2022-02-06 23:37:40 +01:00
mount_chroot ( rootfs_device , bootfs_device , chroot )
chroot . mount_pacman_cache ( )
chroot . initialize ( )
chroot . activate ( )
chroot . create_user (
user = user ,
password = profile [ ' password ' ] ,
)
copy_ssh_keys (
chroot . path ,
user = user ,
)
2022-03-02 15:29:58 +01:00
files = {
' etc/pacman.conf ' : get_base_distro ( arch ) . get_pacman_conf ( check_space = True , extra_repos = get_kupfer_https ( arch ) . repos ) ,
' etc/sudoers.d/wheel ' : " # allow members of group wheel to execute any command \n % wheel ALL=(ALL:ALL) ALL \n " ,
}
for target , content in files . items ( ) :
with open ( os . path . join ( chroot . path , target . lstrip ( ' / ' ) ) , ' w ' ) as file :
file . write ( content )
2022-02-06 23:37:40 +01:00
if post_cmds :
result = chroot . run_cmd ( ' && ' . join ( post_cmds ) )
2022-02-18 06:32:04 +01:00
assert isinstance ( result , subprocess . CompletedProcess )
2022-02-06 23:37:40 +01:00
if result . returncode != 0 :
raise Exception ( ' Error running post_cmds ' )
logging . info ( ' Preparing to unmount chroot ' )
res = chroot . run_cmd ( ' sync && umount /boot ' , attach_tty = True )
logging . debug ( f ' rc: { res } ' )
chroot . deactivate ( )
logging . debug ( f ' Unmounting rootfs at " { chroot . path } " ' )
res = run ( [ ' umount ' , chroot . path ] )
logging . debug ( f ' rc: { res . returncode } ' )
2021-08-05 20:26:48 +02:00
@click.group ( name = ' image ' )
def cmd_image ( ) :
2022-02-13 19:57:04 +01:00
""" Build and manage device images """
2021-08-05 20:26:48 +02:00
2021-09-29 23:18:12 +02:00
@cmd_image.command ( name = ' build ' )
2022-01-26 17:58:46 +01:00
@click.argument ( ' profile_name ' , required = False )
2022-08-09 00:09:50 +02:00
@click.option ( ' --local-repos/--no-local-repos ' , ' -l/-L ' , default = True , show_default = True , help = ' Whether to use local package repos at all or only use HTTPS repos. ' )
@click.option ( ' --build-pkgs/--no-build-pkgs ' , ' -p/-P ' , default = True , show_default = True , help = ' Whether to build missing/outdated local packages if local repos are enabled. ' )
@click.option ( ' --no-download-pkgs ' , is_flag = True , default = False , help = ' Disable trying to download packages instead of building if building is enabled. ' )
@click.option ( ' --block-target ' , default = None , help = ' Override the block device file to write the final image to ' )
@click.option ( ' --skip-part-images ' , is_flag = True , default = False , help = ' Skip creating image files for the partitions and directly work on the target block device. ' )
def cmd_build ( profile_name : str = None , local_repos : bool = True , build_pkgs : bool = True , no_download_pkgs = False , block_target : str = None , skip_part_images : bool = False ) :
2022-02-13 19:57:04 +01:00
""" Build a device image """
2021-09-29 23:18:12 +02:00
enforce_wrap ( )
2022-02-18 06:32:04 +01:00
profile : Profile = config . get_profile ( profile_name )
2022-01-26 17:58:46 +01:00
device , flavour = get_device_and_flavour ( profile_name )
2022-02-18 06:32:04 +01:00
size_extra_mb : int = int ( profile [ " size_extra_mb " ] )
2021-08-05 20:26:48 +02:00
2021-10-22 17:07:05 +02:00
# TODO: PARSE DEVICE ARCH AND SECTOR SIZE
arch = ' aarch64 '
sector_size = 4096
2022-02-14 19:32:04 +01:00
rootfs_size_mb = FLAVOURS [ flavour ] . get ( ' size ' , 2 ) * 1000
2021-09-29 16:54:26 +02:00
2021-10-25 21:00:18 +02:00
packages = BASE_PACKAGES + DEVICES [ device ] + FLAVOURS [ flavour ] [ ' packages ' ] + profile [ ' pkgs_include ' ]
2022-05-09 01:35:04 +02:00
if arch != config . runtime [ ' arch ' ] :
2022-05-08 18:02:36 +02:00
build_enable_qemu_binfmt ( arch )
if local_repos and build_pkgs :
logging . info ( " Making sure all packages are built " )
2022-01-27 04:07:06 +01:00
repo = discover_packages ( )
2022-08-09 00:09:50 +02:00
build_packages ( repo , [ p for name , p in repo . items ( ) if name in packages ] , arch , try_download = not no_download_pkgs )
2022-01-27 04:07:06 +01:00
2022-02-06 23:37:40 +01:00
image_path = block_target or get_image_path ( device , flavour )
2021-10-25 21:00:18 +02:00
2022-02-06 23:37:40 +01:00
os . makedirs ( os . path . dirname ( image_path ) , exist_ok = True )
2022-02-14 18:53:36 +01:00
logging . info ( f ' Creating new file at { image_path } ' )
2022-02-14 19:32:04 +01:00
create_img_file ( image_path , f " { rootfs_size_mb + size_extra_mb } M " )
2021-08-05 20:26:48 +02:00
2021-10-22 17:07:05 +02:00
loop_device = losetup_rootfs_image ( image_path , sector_size )
2022-02-06 23:37:40 +01:00
partition_device ( loop_device )
partprobe ( loop_device )
2021-10-16 10:46:27 +02:00
2022-02-18 06:32:04 +01:00
boot_dev : str
root_dev : str
2022-02-06 23:37:40 +01:00
loop_boot = loop_device + ' p1 '
loop_root = loop_device + ' p2 '
if skip_part_images :
boot_dev = loop_boot
root_dev = loop_root
else :
logging . info ( ' Creating per-partition image files ' )
boot_dev = create_img_file ( get_image_path ( device , flavour , ' boot ' ) , IMG_FILE_BOOT_DEFAULT_SIZE )
2022-02-14 19:32:04 +01:00
root_dev = create_img_file ( get_image_path ( device , flavour , ' root ' ) , f ' { rootfs_size_mb + size_extra_mb - 200 } M ' )
2022-02-06 23:37:40 +01:00
2022-02-07 01:20:38 +01:00
create_boot_fs ( boot_dev , sector_size )
create_root_fs ( root_dev , sector_size )
2022-02-06 23:37:40 +01:00
install_rootfs (
root_dev ,
boot_dev ,
device ,
flavour ,
arch ,
packages ,
2022-05-08 18:02:36 +02:00
local_repos ,
2022-02-06 23:37:40 +01:00
profile ,
2021-10-15 22:52:13 +02:00
)
2021-08-05 20:26:48 +02:00
2022-02-06 23:37:40 +01:00
if not skip_part_images :
logging . info ( ' Copying partition image files into full image: ' )
logging . info ( f ' Block-copying /boot to { image_path } ' )
dd_image ( input = boot_dev , output = loop_boot )
logging . info ( f ' Block-copying rootfs to { image_path } ' )
dd_image ( input = root_dev , output = loop_root )
2022-01-28 14:21:11 +01:00
logging . info ( f ' Done! Image saved to { image_path } ' )
2021-08-05 20:26:48 +02:00
2021-09-29 23:18:12 +02:00
@cmd_image.command ( name = ' inspect ' )
2021-10-25 20:45:23 +02:00
@click.option ( ' --shell ' , ' -s ' , is_flag = True )
2022-02-15 00:02:22 +01:00
@click.argument ( ' profile ' )
def cmd_inspect ( profile : str = None , shell : bool = False ) :
2022-02-13 19:57:04 +01:00
""" Open a shell in a device image """
2022-01-28 14:21:11 +01:00
enforce_wrap ( )
2022-02-15 00:02:22 +01:00
device , flavour = get_device_and_flavour ( profile )
2021-10-25 21:00:18 +02:00
# TODO: get arch from profile
arch = ' aarch64 '
2021-10-22 17:07:05 +02:00
# TODO: PARSE DEVICE SECTOR SIZE
sector_size = 4096
2021-10-25 21:00:18 +02:00
chroot = get_device_chroot ( device , flavour , arch )
2022-02-06 23:37:40 +01:00
image_path = get_image_path ( device , flavour )
2021-10-22 17:07:05 +02:00
loop_device = losetup_rootfs_image ( image_path , sector_size )
2022-02-06 23:40:00 +01:00
partprobe ( loop_device )
2022-02-06 19:48:34 +01:00
mount_chroot ( loop_device + ' p2 ' , loop_device + ' p1 ' , chroot )
2021-08-05 20:26:48 +02:00
2021-10-25 21:00:18 +02:00
logging . info ( f ' Inspect the rootfs image at { chroot . path } ' )
2021-08-05 20:26:48 +02:00
2021-10-25 20:45:23 +02:00
if shell :
chroot . initialized = True
chroot . activate ( )
2022-02-07 01:48:55 +01:00
if arch != config . runtime [ ' arch ' ] :
logging . info ( ' Installing requisites for foreign-arch shell ' )
build_enable_qemu_binfmt ( arch )
logging . info ( ' Starting inspection shell ' )
2021-10-25 20:45:23 +02:00
chroot . run_cmd ( ' /bin/bash ' )
else :
pause ( )