@@ -531,72 +531,69 @@ def run_guestfs_mount(image_path, mount_target):
531531# the paths to be used for analysis and then clean up once given back
532532# control.
533533def diff_metal_helper (diff_from , diff_to ):
534- metal_from = get_metal_path (diff_from )
535- metal_to = get_metal_path (diff_to )
536-
537- mount_dir_from = os .path .join (cache_dir ("metal" ), diff_from .id )
538- mount_dir_to = os .path .join (cache_dir ("metal" ), diff_to .id )
539-
540- for d in [mount_dir_from , mount_dir_to ]:
541- if os .path .exists (d ):
542- shutil .rmtree (d )
543- os .makedirs (d )
544-
545- # As the libreguest mount call is blocking until unmounted, let's
546- # do that in a separate thread
547- p_from = Process (target = run_guestfs_mount , args = (metal_from , mount_dir_from ))
548- p_to = Process (target = run_guestfs_mount , args = (metal_to , mount_dir_to ))
549-
550- try :
551- p_from .start ()
552- p_to .start ()
553- # Wait for the FUSE mounts to be ready. We'll check for a known file.
554- for i , d in enumerate ([mount_dir_from , mount_dir_to ]):
555- p = p_from if i == 0 else p_to
556- timeout = 60 # seconds
557- start_time = time .time ()
558- check_file = os .path .join (d , 'ostree' )
559- while not os .path .exists (check_file ):
560- time .sleep (1 )
561- if time .time () - start_time > timeout :
562- raise Exception (f"Timeout waiting for mount in { d } " )
563- if not p .is_alive ():
564- raise Exception (f"A guestfs process for { os .path .basename (d )} died unexpectedly." )
565-
566- # Allow the caller to operate on these values
567- yield mount_dir_from , mount_dir_to
568-
569- finally :
570- # Unmount the FUSE binds, this will make the guestfs mount calls return
571- runcmd (['fusermount' , '-u' , mount_dir_from ], check = False )
572- runcmd (['fusermount' , '-u' , mount_dir_to ], check = False )
573-
574- # Ensure the background processes are terminated
575- def shutdown_process (process ):
576- process .join (timeout = 5 )
577- if process .is_alive ():
578- process .terminate ()
579- process .join ()
580-
581- shutdown_process (p_from )
582- shutdown_process (p_to )
534+ metal_image_from = get_metal_path (diff_from )
535+ metal_image_to = get_metal_path (diff_to )
536+
537+ diff_dir_from = os .path .join (cache_dir ("metal" ), diff_from .id )
538+ diff_dir_to = os .path .join (cache_dir ("metal" ), diff_to .id )
539+
540+ for image_path , diff_dir in [(metal_image_from , diff_dir_from ),
541+ (metal_image_to , diff_dir_to )]:
542+ if os .path .exists (diff_dir ):
543+ # If it exists assume it's cached already and we don't
544+ # need to do anything. If it's stale for whatever reason
545+ # the user can `cosa diff --gc`.
546+ continue
547+
548+ os .makedirs (diff_dir )
549+
550+ g = None
551+ try :
552+ g = guestfs .GuestFS (python_return_dict = True )
553+ g .set_backend ("direct" )
554+ g .add_drive_opts (image_path , readonly = 1 )
555+ g .launch ()
556+
557+ # Mount the disks in the guestfs VM
558+ root = g .findfs_label ("root" )
559+ g .mount_ro (root , "/" )
560+ boot = g .findfs_label ("boot" )
561+ g .mount_ro (boot , "/boot" )
562+ efi = g .findfs_label ("EFI-SYSTEM" )
563+ g .mount_ro (efi , "/boot/efi" )
564+
565+
566+ with tempfile .NamedTemporaryFile (suffix = ".tar" , delete = True ) as tmp_tar :
567+ g .tar_out ("/" , tmp_tar .name , xattrs = True , selinux = True , excludes = excludes )
568+ # Extract the tarball.
569+ runcmd (['tar' , '-xf' , tmp_tar .name , '-C' , diff_dir ])
570+
571+ except Exception as e :
572+ print (f"Error in guestfs process for { image_path } : { e } " , file = sys .stderr )
573+ raise
574+ finally :
575+ if g :
576+ g .close ()
577+
578+ # Allow the caller to operate on these values
579+ return diff_dir_from , diff_dir_to
583580
584581
585582def diff_metal (diff_from , diff_to ):
586- for mount_dir_from , mount_dir_to in diff_metal_helper (diff_from , diff_to ):
587- git_diff (mount_dir_from , mount_dir_to )
583+ mount_dir_from , mount_dir_to = diff_metal_helper (diff_from , diff_to )
584+ git_diff (mount_dir_from , mount_dir_to )
588585
589586
590587def diff_metal_du (diff_from , diff_to ):
591- for mount_dir_from , mount_dir_to in diff_metal_helper (diff_from , diff_to ):
592- cmd = ['find' , '.' , '-type' , 'd' , '-exec' , 'du' , '-sh' , '{}' , ';' ]
593- diff_cmd_outputs (cmd , mount_dir_from , mount_dir_to , strategy = DiffCmdOutputStrategy .CD )
588+ mount_dir_from , mount_dir_to = diff_metal_helper (diff_from , diff_to )
589+ cmd = ['find' , '.' , '-type' , 'd' , '-exec' , 'du' , '-sh' , '{}' , ';' ]
590+ diff_cmd_outputs (cmd , mount_dir_from , mount_dir_to , strategy = DiffCmdOutputStrategy .CD )
594591
595592
596593def diff_metal_ls (diff_from , diff_to ):
597- for mount_dir_from , mount_dir_to in diff_metal_helper (diff_from , diff_to ):
598- cmd = ['find' , '.' ]
599- diff_cmd_outputs (cmd , mount_dir_from , mount_dir_to , strategy = DiffCmdOutputStrategy .CD )
594+ mount_dir_from , mount_dir_to = diff_metal_helper (diff_from , diff_to )
595+ cmd = ['find' , '.' ]
596+ diff_cmd_outputs (cmd , mount_dir_from , mount_dir_to , strategy = DiffCmdOutputStrategy .CD )
600597
601598
602599def diff_cmd_outputs (cmd , path_from , path_to , strategy : DiffCmdOutputStrategy = DiffCmdOutputStrategy .TEMPLATE ):
0 commit comments