From f50100605c739e70293516cb545e737e8bbc6eab Mon Sep 17 00:00:00 2001 From: Austin Gibbons Date: Fri, 26 Jul 2024 15:56:18 -0400 Subject: [PATCH] Raise exception and update status for duplicate volume group issues. --- src/thumbtack/exceptions.py | 4 ++++ src/thumbtack/resources.py | 3 +++ src/thumbtack/utils.py | 28 ++++++++++++++++++++++++++++ src/thumbtack/views.py | 8 +++++++- 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/thumbtack/exceptions.py b/src/thumbtack/exceptions.py index 65ccb27..8e33700 100644 --- a/src/thumbtack/exceptions.py +++ b/src/thumbtack/exceptions.py @@ -14,3 +14,7 @@ class DuplicateMountAttemptError(Exception): class EncryptedImageError(Exception): pass + +class DuplicateVolumeGroupError(Exception): + def __init__(self, msg): + super().__init__(msg) diff --git a/src/thumbtack/resources.py b/src/thumbtack/resources.py index 567a194..0c289dd 100644 --- a/src/thumbtack/resources.py +++ b/src/thumbtack/resources.py @@ -10,6 +10,7 @@ ImageNotInDatabaseError, DuplicateMountAttemptError, EncryptedImageError, + DuplicateVolumeGroupError, ) from .utils import get_mount_info, get_supported_libraries, mount_image, unmount_image, get_images, add_mountpoint @@ -85,6 +86,8 @@ def put(self, image_path): status = f"Unable to mount encrypted image." except DuplicateMountAttemptError: status = "Mount attempt is already in progress for this image. Please wait until the current mount attempt completes." + except DuplicateVolumeGroupError as e: + status = f"Unable to mount all volumes. Found duplicate volume group name: {str(e)}. Deactivate the volume group and remount the image." current_app.mnt_mutex.release() current_app.logger.error(status) diff --git a/src/thumbtack/utils.py b/src/thumbtack/utils.py index e811d95..55c3367 100644 --- a/src/thumbtack/utils.py +++ b/src/thumbtack/utils.py @@ -18,6 +18,7 @@ ImageNotInDatabaseError, DuplicateMountAttemptError, EncryptedImageError, + DuplicateVolumeGroupError, ) def get_supported_libraries(): @@ -130,11 +131,20 @@ def process_image_parser(image_parser, relative_image_path): Mountpoints for LVM volumes are not stored in the main mountpoint variable that we check and display in thumbtack. This loop identifies the LVM volumes and add them to the main volumes list. """ + duplicate_vg = False + vgname = "" + num_volumes = len(image_parser.disks[0].volumes.volumes) for v in image_parser.disks[0].volumes: + if v.duplicate_volume_group: + duplicate_vg = True + vgname = v.vgname if hasattr(v, 'volumes') and v.mountpoint is None: current_app.logger.info(f"Volume: {str(v)}") for vol in v.volumes: + if vol.duplicate_volume_group: + duplicate_vg = True + vgname = vol.vgname current_app.logger.info(f"Mountpoint: {str(vol.mountpoint)}") if vol.mountpoint is not None: vol.index = str(num_volumes) @@ -142,12 +152,22 @@ def process_image_parser(image_parser, relative_image_path): image_parser.disks[0].volumes.volumes.append(vol) if hasattr(vol, 'volumes'): for sub_vol in vol.volumes: + if sub_vol.duplicate_volume_group: + duplicate_vg = True + vgname = sub_vol.vgname current_app.logger.info(f"Mountpoint: {str(sub_vol.mountpoint)}") if sub_vol.mountpoint is not None: sub_vol.index = str(num_volumes) num_volumes += 1 image_parser.disks[0].volumes.volumes.append(sub_vol) + if duplicate_vg or [v for v in image_parser.disks[0].volumes if v.duplicate_volume_group]: + msg = "* Duplicate Volume groups detected." + if vgname: + msg += f" VG: {vgname}" + current_app.logger.error(msg) + raise DuplicateVolumeGroupError(vgname) + # Fail if we couldn't mount any of the volumes if not [v for v in image_parser.disks[0].volumes if v.mountpoint]: image_parser.clean(allow_lazy=True) @@ -197,11 +217,15 @@ def mount_image(relative_image_path, creds=None): update_or_insert_db(sql, [relative_image_path]) no_mountable_volumes = False + duplicate_vg = None try: image_parser = imagemounter_mitre.ImageParser( [full_image_path], pretty=True, mountdir=mount_dir, keys=creds ) image_parser = process_image_parser(image_parser, relative_image_path) + except DuplicateVolumeGroupError as e: + duplicate_vg = e + except NoMountableVolumesError as e: current_app.logger.error(f"fstypes: {image_parser.fstypes}.") no_mountable_volumes = True @@ -282,6 +306,10 @@ def mount_image(relative_image_path, creds=None): sql, [disk_image_id, mount_status_id, v_index, v_mountpoint] ) + if e := duplicate_vg: + current_app.logger.info(str(e)) + raise e + return image_parser.disks[0] def add_mountpoint(relative_image_path, mountpoint_path): diff --git a/src/thumbtack/views.py b/src/thumbtack/views.py index ce7d79d..869ec1a 100644 --- a/src/thumbtack/views.py +++ b/src/thumbtack/views.py @@ -5,7 +5,7 @@ import os -from .exceptions import UnexpectedDiskError, NoMountableVolumesError, DuplicateMountAttemptError, EncryptedImageError +from .exceptions import UnexpectedDiskError, NoMountableVolumesError, DuplicateMountAttemptError, EncryptedImageError, DuplicateVolumeGroupError from .resources import Mount, SupportedLibraries, Images, ImageDir, ManualMount from .utils import ( get_supported_libraries, @@ -78,6 +78,7 @@ def mount_form(): creds = None mounted_disk = None + duplicate_vg = False try: mounted_disk = mount_image(rel_path, creds) except imagemounter_mitre.exceptions.SubsystemError: @@ -98,7 +99,12 @@ def mount_form(): status = "Mount failed. Thumbtack server has no mount directory set." except DuplicateMountAttemptError: status = "Mount attempt is already in progress for this image. Please wait until the current mount attempt completes." + except DuplicateVolumeGroupError as e: + status = f"Unable to mount all volumes. Found duplicate volume group name: {str(e)}. Deactivate the volume group and remount the image." + duplicate_vg = True if mounted_disk and mounted_disk.mountpoint is not None: + if duplicate_vg: + status = ' '.join(["Mounted Successfully.", status]) status = "Mounted successfully" elif operation == "unmount":