def __init__(self, builder, callback, mode, destination_path):
        # Lowercase mode (eg "backup", "restore", "verify")
        mode_prefix = mode.name.lower()
        settings = {
            'server':
            builder.get_object(mode_prefix + "_network_server").get_text(),
            'username':
            builder.get_object(mode_prefix + "_network_username").get_text(),
            'password':
            builder.get_object(mode_prefix + "_network_password").get_text(),
            'domain':
            builder.get_object(mode_prefix + "_network_domain").get_text(),
            'version':
            builder.get_object(mode_prefix + "_network_version").get_text(),
            'destination_path':
            destination_path
        }

        # restore_network_version
        self.callback = callback
        self.please_wait_popup = PleaseWaitModalPopup(
            builder, title=_("Please wait..."), message=_("Mounting..."))
        self.please_wait_popup.show()
        thread = threading.Thread(target=self._do_mount_command,
                                  args=(settings, ))
        thread.daemon = True
        thread.start()
Exemple #2
0
 def overwrite_partition_table_toggle(self, is_overwriting_partition_table):
     print("Overwrite partition table toggle changed to " +
           str(is_overwriting_partition_table))
     if is_overwriting_partition_table:
         # Don't need to scan for existing LVM logical volumes when overwriting partition table.
         self.post_lvm_preparation(is_overwriting_partition_table, True, "")
     else:
         self.win.set_sensitive(False)
         self.please_wait_popup = PleaseWaitModalPopup(
             self.builder,
             title=_("Please wait..."),
             message=
             _("Scanning and unmounting any Logical Volume Manager (LVM) Logical Volumes..."
               ))
         self.please_wait_popup.show()
         if 'partitions' in self.dest_drive_dict.keys():
             partitions = self.dest_drive_dict['partitions']
         else:
             # TODO: Make this logic better.
             partitions = self.dest_drive_dict
         thread = threading.Thread(
             target=self._scan_and_unmount_existing_lvm,
             args=[
                 copy.deepcopy(partitions).keys(),
                 is_overwriting_partition_table
             ])
         thread.daemon = True
         thread.start()
Exemple #3
0
    def __init__(self, builder):
        self.builder = builder
        self.destination_partition_combobox_list = self.builder.get_object("destination_partition_combobox_list")

        self.NOT_RESTORING_PARTITION_KEY = "DISABLED"
        self.NOT_RESTORING_PARTITION_ENDUSER_FRIENDLY = _("Not restoring this partition")
        self.win = self.builder.get_object("main_window")

        self.overwriting_partition_table_message = "<b>" + _("You will be overwriting the partition table.") + "</b>"
        self.not_overwriting_partition_table_message = _("You will <b>not</b> be overwriting the partition table.")
        self.no_partition_table_message = _("The source does not contain a partition table.")

        self.lvm_lv_path_list = []
        self.lvm_lv_path_lock = threading.Lock()

        # FIXME: Refactor the code to remove the need for this ugly initialization.
        self.dest_drive_dict = {"partitions": {}}

        self.mode_list = [Mode.RESTORE, Mode.CLONE]
        self.partition_table_checkbutton_dict = {Mode.RESTORE: self.builder.get_object("restore_overwrite_partition_table_checkbutton"),
                                                 Mode.CLONE: self.builder.get_object("clone_overwrite_partition_table_checkbutton")}
        self.overwrite_partition_table_warning_label_dict = {Mode.RESTORE: self.builder.get_object("restore_step4_overwrite_partition_table_warning_label"),
                                                             Mode.CLONE: self.builder.get_object("clone_step4_overwrite_partition_table_warning_label")}
        self.selected_image_text_dict = {Mode.RESTORE: self.builder.get_object("restore_step4_selected_image_text"),
                                                             Mode.CLONE: self.builder.get_object("clone_step4_selected_drives_text")}
        self.partition_selection_list = self.builder.get_object("partition_selection_list")
        self.destination_partition_combobox_cell_renderer_dict = {Mode.RESTORE: self.builder.get_object("restore_destination_partition_combobox_cell_renderer"),
                                                             Mode.CLONE: self.builder.get_object("clone_destination_partition_combobox_cell_renderer")}

        self.selected_image = None
        self.please_wait_popup = None
        self.dest_drive_key = ""
        self.dest_drive_node = {}
Exemple #4
0
    def __init__(self, builder, restore_image_partition_list):
        self.builder = builder
        self.restore_partition_selection_list = restore_image_partition_list
        self.destination_partition_combobox_list = self.builder.get_object(
            "destination_partition_combobox_list")
        self.restore_partition_treeview = self.builder.get_object(
            "restore_step4_image_partition_treeview")

        self.NOT_RESTORING_PARTITION_KEY = "DISABLED"
        self.NOT_RESTORING_PARTITION_ENDUSER_FRIENDLY = "Not restoring this partition"
        self.win = self.builder.get_object("main_window")

        self.overwriting_partition_table_message = "<b>" + _(
            "You will be overwriting the partition table.") + "</b>"
        self.not_overwriting_partition_table_message = _(
            "You will <b>not</b> be overwriting the partition table.")

        self.lvm_lv_path_list = []
        self.lvm_lv_path_lock = threading.Lock()

        # FIXME: Refactor the code to remove the need for this ugly initialization.
        self.dest_drive_dict = {"partitions": {}}

        self.selected_image = None
        self.dest_drive_key = ""
        self.dest_drive_node = {}
    def initialize_individual_partition_restore_list(self, selected_image, dest_drive_node, dest_drive_desc,
                                                     dest_drive_dict):
        self.selected_image = selected_image
        self.dest_drive_node = dest_drive_node
        self.dest_drive_desc = dest_drive_desc
        self.dest_drive_dict = dest_drive_dict

        if isinstance(self.selected_image, ClonezillaImage):
            print("Got selected Clonezilla image: " + str(selected_image.image_format_dict_dict))
        elif isinstance(self.selected_image, RedoBackupLegacyImage):
            print("Got selected RedoBackupLegacy image: " + str(selected_image.sfdisk_dict))
        self._use_image_partition_table()

        info_string = "<b>" + _("Selected image") + "</b> " + GObject.markup_escape_text(self.selected_image.absolute_path) + "\n" + "<b>" + _("Destination device") + "</b> " + GObject.markup_escape_text(self.dest_drive_desc)
        if isinstance(self.selected_image, ClonezillaImage) and len(
                self.selected_image.short_device_node_disk_list) > 1:
            # FIXME: Support Clonezilla multidisk images with subdisk selection combobox
            info_string += "\n" + "<b>" + _("IMPORTANT: Only selecting FIRST disk in Clonezilla image containing MULTIPLE DISKS.") + "</b>"
        self.builder.get_object("restore_step4_selected_image_text").set_markup(info_string)

        print("Have selected image " + str(self.selected_image))
        print("Have drive dict " + str(self.dest_drive_dict))

        # If the image has a partition table, the overwrite toggle is enabled and defaults to True. Otherwise
        # it's not possible to overwrite the partition table.
        overwrite_partition_table_checkbutton = self.builder.get_object("overwrite_partition_table_checkbutton")
        overwrite_partition_table_checkbutton.set_sensitive(self.selected_image.has_partition_table())
        overwrite_partition_table_checkbutton.set_active(self.selected_image.has_partition_table())
Exemple #6
0
    def confirm_backup_configuration(self):
        number = GObject.markup_escape_text(
            self.selected_drive_enduser_friendly_drive_number)
        device = GObject.markup_escape_text(self.selected_drive_key)
        size = GObject.markup_escape_text(self.selected_drive_capacity)
        if self.selected_drive_model is None:
            model = ""
        else:
            model = GObject.markup_escape_text(self.selected_drive_model)
        description = GObject.markup_escape_text(
            self.destination_partition_description)
        partition_list_string = ""
        for key in self.partitions_to_backup.keys():
            partition_list_string += "    " + GObject.markup_escape_text(
                key) + ":  " + GObject.markup_escape_text(
                    self.partitions_to_backup[key]['description']) + "\n"

        source_drive_heading = GObject.markup_escape_text(_("Source drive"))
        backup_partitions_heading = GObject.markup_escape_text(
            _("Backing up the following partition"))
        backup_image_destination_heading = GObject.markup_escape_text(
            _("The backup image will be written into folder {dest_dir} on {description}"
              ).format(dest_dir=self.dest_dir, description=description))

        text_to_display = f"""
<b>{source_drive_heading}</b> {number} [{size}] ({model})

<b>{backup_partitions_heading}</b>:
{partition_list_string}

<b>{backup_image_destination_heading}</b>
"""
        self.builder.get_object(
            "backup_step6_confirm_config_program_defined_text").set_markup(
                text_to_display)
Exemple #7
0
 def selected_folder(self, text, is_allow_selecting_folder_outside_mount):
     print("Received path " + text)
     if not is_allow_selecting_folder_outside_mount and not MOUNT_DIR in text:
         error = ErrorMessageModalPopup(
             self.builder,
             _("You must select a folder inside {location}").format(
                 location=MOUNT_DIR) + "\n" +
             _("Please select a different folder."))
     else:
         self.image_folder_query.query_folder(text)
Exemple #8
0
    def populate_summary_page(self):
        with self.summary_message_lock:
            self.logger.write("Populating summary page with:\n\n" +
                              self.summary_message)
            text_to_display = _("""<b>{heading}</b>

{message}""").format(heading=_("Verification Summary"),
                     message=GObject.markup_escape_text(self.summary_message))
        self.builder.get_object("verify_step4_summary_program_defined_text"
                                ).set_markup(text_to_display)
    def adjust_ntfs_filesystem_chs_geometry_information(
            ntfs_partition_long_device_node, ntfs_partition_start_sector,
            destination_disk_geometry_dict, is_edd_geometry, logger):
        cylinders = str(destination_disk_geometry_dict['cylinders'])
        ntfsfixboot_geometry_options = []
        if destination_disk_geometry_dict is not None:
            ntfsfixboot_geometry_options = [
                # "-h, Specify number of heads per track. If omitted, determined via ioctl."
                "-h",
                str(destination_disk_geometry_dict['heads']),
                # "-t, Specify number of sectors per track. If omitted, determined via ioctl."
                "-t",
                str(destination_disk_geometry_dict['sectors'])
            ]
        if ntfs_partition_start_sector is not None:
            # "-s, New start sector to write. If omitted, determined via ioctl."
            ntfsfixboot_geometry_options += [
                '-s', str(ntfs_partition_start_sector)
            ]

        ntfsfixboot_dry_run_cmd_list = [
            "partclone.ntfsfixboot"
        ] + ntfsfixboot_geometry_options + [ntfs_partition_long_device_node]
        process, flat_command_string, failed_message = Utility.run(
            "Dry-run adjust filesystem geometry for the NTFS partition",
            ntfsfixboot_dry_run_cmd_list,
            use_c_locale=True,
            logger=logger)
        if process.returncode == 1:
            return True, _(
                "No changes needed for NTFS filesystem geometry of {ntfs_device}"
            ).format(ntfs_device=ntfs_partition_long_device_node)

        # Regardless of if a change is needed, try to write
        # "-w, Write new start sector to the partition."
        ntfsfixboot_cmd_list = ["partclone.ntfsfixboot"] + [
            '-w'
        ] + ntfsfixboot_geometry_options + [ntfs_partition_long_device_node]
        process, flat_command_string, failed_message = Utility.run(
            "Adjust filesystem geometry for the NTFS partition",
            ntfsfixboot_cmd_list,
            use_c_locale=False,
            logger=logger)
        if process.returncode != 0:
            return False, failed_message

        # It's unclear why there are difference between EDD and sfdisk geometry, so let the user know the source.
        if is_edd_geometry:
            geometry_source = "EDD"
        else:
            geometry_source = "sfdisk"
        return True, _(
            "Successfully adjusted NTFS filesystem geometry of {ntfs_device} using values from {geometry_source}"
        ).format(ntfs_device=ntfs_partition_long_device_node,
                 geometry_source=geometry_source)
Exemple #10
0
    def __init__(self, builder, callback, mode, network_widget_dict,
                 destination_path):
        # Lowercase mode (eg "backup", "restore", "verify")
        mode_prefix = mode.name.lower()
        settings = {
            'server':
            network_widget_dict["network_server"][mode].get_text().strip(),
            'username':
            network_widget_dict["network_username"][mode].get_text().strip(),
            # For protocols that specify the remote path separately from the server
            'remote_path':
            network_widget_dict["network_remote_path"]
            [mode].get_text().strip(),
            # NOT stripping whitespace from the password
            'password':
            network_widget_dict["network_password"][mode].get_text(),
            'domain':
            network_widget_dict["network_domain"][mode].get_text().strip(),
            'version':
            network_widget_dict["network_version"][mode].get_text().strip(),
            'ssh_idfile':
            network_widget_dict["network_ssh_idfile"][mode].get_text().strip(),
            'destination_path':
            destination_path
        }

        network_protocol_key = Utility.get_combobox_key(
            network_widget_dict['network_protocol_combobox'][mode])
        # restore_network_version
        self.callback = callback

        self.requested_stop_lock = threading.Lock()
        self.requested_stop = False

        self.please_wait_popup = PleaseWaitModalPopup(
            builder,
            title=_("Please wait..."),
            message=_("Mounting...") + "\n\n" +
            _("Close this popup to cancel the mount operation."),
            on_close_callback=self.cancel_mount)
        self.please_wait_popup.show()
        if network_protocol_key == "SMB":
            thread = threading.Thread(target=self._do_smb_mount_command,
                                      args=(settings, ))
        elif network_protocol_key == "SSH":
            thread = threading.Thread(target=self._do_ssh_mount_command,
                                      args=(settings, ))
        elif network_protocol_key == "NFS":
            thread = threading.Thread(target=self._do_nfs_mount_command,
                                      args=(settings, ))
        else:
            raise ValueError("Unknown network protocol: " +
                             network_protocol_key)
        thread.daemon = True
        thread.start()
Exemple #11
0
 def start_query(self):
     print("Starting drive query...")
     self.win.set_sensitive(False)
     self.please_wait_popup = PleaseWaitModalPopup(
         self.builder,
         title=_("Please wait..."),
         message=_("Identifying disk drives..."))
     self.please_wait_popup.show()
     thread = threading.Thread(target=self._do_drive_query)
     thread.daemon = True
     thread.start()
    def completed_clone(self, succeeded, message):
        clone_timeend = datetime.now()
        duration_minutes = Utility.get_human_readable_minutes_seconds(
            (clone_timeend - self.clone_timestart).total_seconds())

        if isinstance(self.image, QemuImage):
            is_success, failed_message = self.image.deassociate_nbd(
                QEMU_NBD_NBD_DEVICE)
            if not is_success:
                with self.summary_message_lock:
                    self.summary_message += message + "\n"
                error = ErrorMessageModalPopup(self.builder, failed_message)
                print(failed_message)

        if succeeded:
            if os.path.exists(self.temp_dir):
                shutil.rmtree(self.temp_dir)
        else:
            # Keep temp_dir for debugging
            print("Not deleting " + self.temp_dir)
        self.main_statusbar.remove_all(
            self.main_statusbar.get_context_id("restore"))
        self.main_statusbar.remove_all(
            self.main_statusbar.get_context_id("clone"))
        with self.clone_in_progress_lock:
            self.clone_in_progress = False
        if succeeded:
            print("Success")
        else:
            with self.summary_message_lock:
                self.summary_message += message + "\n"
            error = ErrorMessageModalPopup(self.builder, message)
            print("Failure")
        with self.summary_message_lock:
            self.summary_message += "\n" + _(
                "Operation took {num_minutes} minutes.").format(
                    num_minutes=duration_minutes) + "\n"
            if self.post_task_action != "DO_NOTHING":
                if succeeded:
                    has_scheduled, msg = Utility.schedule_shutdown_reboot(
                        self.post_task_action)
                    self.summary_message += "\n" + msg
                else:
                    self.summary_message += "\n" + _(
                        "Shutdown/Reboot cancelled due to errors.")
        is_unmounted, umount_message = Utility.umount_warn_on_busy(
            "/mnt/backup", is_lazy_umount=True)
        if not is_unmounted:
            print(umount_message)
            with self.summary_message_lock:
                self.summary_message += umount_message + "\n"
        self.populate_summary_page()
        self.completed_callback(succeeded)
    def _do_mount_command(self, source_path, destination_path):
        try:
            if not os.path.exists(destination_path) and not os.path.isdir(
                    destination_path):
                os.mkdir(destination_path, 0o755)

            if self.is_stop_requested():
                GLib.idle_add(self.callback, False,
                              _("Operation cancelled by user."))
                return

            is_unmounted, message = Utility.umount_warn_on_busy(
                destination_path)
            if not is_unmounted:
                GLib.idle_add(self.please_wait_popup.destroy)
                GLib.idle_add(self.callback, False, message)
                return

            if self.is_stop_requested():
                GLib.idle_add(self.callback, False,
                              _("Operation cancelled by user."))
                return

            is_unmounted, message = Utility.umount_warn_on_busy(source_path)
            if not is_unmounted:
                GLib.idle_add(self.please_wait_popup.destroy)
                GLib.idle_add(self.callback, False, message)
                return

            if self.is_stop_requested():
                GLib.idle_add(self.callback, False,
                              _("Operation cancelled by user."))
                return

            mount_cmd_list = ['mount', source_path, destination_path]
            process, flat_command_string, failed_message = Utility.interruptable_run(
                "Mounting selected partition: ",
                mount_cmd_list,
                use_c_locale=False,
                is_shutdown_fn=self.is_stop_requested)
            if process.returncode != 0:
                GLib.idle_add(self.please_wait_popup.destroy)
                GLib.idle_add(self.callback, False, failed_message)
                return
            else:
                GLib.idle_add(self.please_wait_popup.destroy)
                GLib.idle_add(self.callback, True, "", destination_path)
        except Exception as e:
            tb = traceback.format_exc()
            print(tb)
            GLib.idle_add(self.please_wait_popup.destroy)
            GLib.idle_add(self.callback, False, "Error mounting folder: " + tb)
Exemple #14
0
 def set_mounted_state(self, is_mounted):
     if is_mounted:
         self.is_partition_mounted = True
         self.builder.get_object("button_mount").set_label(_("Unmount"))
         self.set_parts_of_image_explorer_page_sensitive(False)
         self.builder.get_object("button_open_file_manager").set_sensitive(
             True)
     else:
         self.is_partition_mounted = False
         self.builder.get_object("button_mount").set_label(_("Mount"))
         self.set_parts_of_image_explorer_page_sensitive(True)
         self.builder.get_object("button_open_file_manager").set_sensitive(
             False)
Exemple #15
0
    def _use_image_partition_table(self):
        # Populate image partition list
        self.destination_partition_combobox_list.clear()
        self.partition_selection_list.clear()
        if isinstance(self.selected_image, ClonezillaImage) or isinstance(self.selected_image, RedoBackupLegacyImage) or \
                isinstance(self.selected_image, FogProjectImage) or isinstance(self.selected_image, RedoRescueImage) or \
                isinstance(self.selected_image, FoxcloneImage) or isinstance(self.selected_image, MetadataOnlyImage):
            for image_format_dict_key in self.selected_image.image_format_dict_dict.keys():
                print("ClonezillaImage contains partition " + image_format_dict_key)
                if self.selected_image.does_image_key_belong_to_device(image_format_dict_key):
                    if self.selected_image.image_format_dict_dict[image_format_dict_key]['is_lvm_logical_volume']:
                        # The destination of an LVM logical volume within a partition (eg /dev/cl/root) is unchanged
                        dest_partition = self.selected_image.image_format_dict_dict[image_format_dict_key][
                            'logical_volume_long_device_node']
                        flat_description = "Logical Volume " + image_format_dict_key + ": " + self.selected_image.flatten_partition_string(image_format_dict_key)
                    else:
                        # The destination partition of a regular partition in the image (eg, /dev/sda4) is dependent on
                        # the destination drive node (eg /dev/sdb) so we need to split and join the device so the
                        # mapping correctly reads "/dev/sdb4".
                        image_base_device_node, image_partition_number = Utility.split_device_string(image_format_dict_key)
                        # Combine image partition number with destination device node base
                        dest_partition = Utility.join_device_string(self.dest_drive_node, image_partition_number)
                        flat_description = _("Partition {partition_number}").format(partition_number=str(
                            image_partition_number)) + ": " + self.selected_image.flatten_partition_string(image_format_dict_key)
                    self.destination_partition_combobox_list.append([dest_partition, flat_description])
                    self.partition_selection_list.append(
                        [image_format_dict_key, True, flat_description, dest_partition, flat_description,
                         dest_partition, flat_description])
        elif isinstance(self.selected_image, FsArchiverImage):
            # Doesn't appear that FsArchiver images ever have an partition table backup associated with it. But
            # keeping this section for reference, especially if a frontend like qt-fsarchiver adds partition table
            # backups.
            for fs_key in self.selected_image.fsa_dict['filesystems'].keys():
                long_device_node = self.selected_image.fsa_dict['filesystems'][fs_key]['original_long_device_node']
                image_base_device_node, image_partition_number = Utility.split_device_string(long_device_node)
                # Combine image partition number with destination device node base
                dest_partition = Utility.join_device_string(self.dest_drive_node, image_partition_number)
                flat_description = _("Partition {partition_number}").format(partition_number=str(
                    image_partition_number)) + " (" + dest_partition + "): " + self.selected_image.flatten_partition_string(
                    fs_key)
                self.destination_partition_combobox_list.append([dest_partition, flat_description])
                self.partition_selection_list.append(
                    [fs_key, True, flat_description, dest_partition, flat_description, dest_partition,
                     flat_description])
        elif isinstance(self.selected_image, ApartGtkImage):
            # Shouldn't be called because ApartGTK images don't have a partition table
            print("Error: Images created with apart-gtk don't have partition tables")

        for mode in self.mode_list:
            self.destination_partition_combobox_cell_renderer_dict[mode].set_sensitive(False)
Exemple #16
0
 def get_enduser_friendly_partition_description(self):
     flat_string = ""
     drive_index = 0
     for short_disk_key in self.short_device_node_disk_list:
         if self.ecryptfs_info_dict is not None and 'size' in self.ecryptfs_info_dict.keys(
         ):
             flat_string += "ECRYPTFS: "
         if len(self.short_device_node_disk_list) > 1:
             if drive_index == 0:
                 # Capitalized text that (in conjunction with a error box) will help assist Rescuezilla users in
                 # understanding Clonezilla multidisk images are not yet fully supported.
                 flat_string += "MULTIDISK "
             flat_string += _("Drive {drive_number}".format(
                 drive_number=str(drive_index + 1))) + ": "
         for image_format_dict_key in self.image_format_dict_dict.keys():
             if self.does_image_key_belong_to_device(
                     image_format_dict_key, short_disk_key):
                 if self.image_format_dict_dict[image_format_dict_key][
                         'is_lvm_logical_volume']:
                     flat_string += "(" + image_format_dict_key + ": " + self.flatten_partition_string(
                         short_disk_key, image_format_dict_key) + ") "
                 else:
                     base_device_node, partition_number = Utility.split_device_string(
                         image_format_dict_key)
                     flat_string += "(" + str(
                         partition_number
                     ) + ": " + self.flatten_partition_string(
                         short_disk_key, image_format_dict_key) + ") "
         drive_index += 1
     return flat_string
Exemple #17
0
    def initialize_individual_partition_restore_list(self, selected_image, dest_drive_node, dest_drive_desc,
                                                     dest_drive_dict):
        self.selected_image = selected_image
        self.dest_drive_node = dest_drive_node
        self.dest_drive_desc = dest_drive_desc
        self.dest_drive_dict = dest_drive_dict

        if isinstance(self.selected_image, ClonezillaImage):
            print("Got selected Clonezilla image: " + str(selected_image.image_format_dict_dict))
        elif isinstance(self.selected_image, RedoBackupLegacyImage):
            print("Got selected RedoBackupLegacy image: " + str(selected_image.normalized_sfdisk_dict))
        self._use_image_partition_table()

        info_string = "<b>" + _("Selected image") + "</b> " + GObject.markup_escape_text(self.selected_image.absolute_path) + "\n" + "<b>" + _("Destination device") + "</b> " + GObject.markup_escape_text(self.dest_drive_desc)
        for mode in self.mode_list:
            self.selected_image_text_dict[mode].set_markup(info_string)

        print("Have selected image " + str(self.selected_image))
        print("Have drive dict " + str(self.dest_drive_dict))

        # If the image has a partition table, the overwrite toggle is enabled and defaults to True. Otherwise
        # it's not possible to overwrite the partition table.
        for overwrite_partition_table_checkbutton in self.partition_table_checkbutton_dict.values():
            overwrite_partition_table_checkbutton.set_sensitive(self.selected_image.has_partition_table())
            overwrite_partition_table_checkbutton.set_active(self.selected_image.has_partition_table())
        self.set_overwriting_partition_warning_label(self.selected_image.has_partition_table())
Exemple #18
0
    def toggle_restore_of_row(self, iter, new_toggle_state):
        # Need to be able to disable restore of individual partitions.

        is_empty_dest_partition = False
        if self.restore_partition_selection_list.get_value(
                iter, 5) == self.NOT_RESTORING_PARTITION_KEY:
            is_empty_dest_partition = True
        if new_toggle_state and is_empty_dest_partition:
            print(
                "Blocking enabling the toggle when the destination partition is not set"
            )
            error = ErrorMessageModalPopup(
                self.builder,
                _("No destination partition selected. Use the destination partition drop-down menu to select the destination"
                  ))
            return

        # Update the underlying model to ensure the checkbox will reflect the new state
        self.restore_partition_selection_list.set_value(
            iter, 1, new_toggle_state)
        self._swap_destination_partition_node_with_backup(iter)
        # If the row has been disabled, update the combobox
        if not new_toggle_state:
            self.restore_partition_selection_list.set_value(
                iter, 3, self.NOT_RESTORING_PARTITION_KEY)
            self.restore_partition_selection_list.set_value(
                iter, 4, self.NOT_RESTORING_PARTITION_ENDUSER_FRIENDLY)
    def __init__(self, builder, callback, source_path, destination_path):
        self.destination_path = destination_path

        self.source_path = source_path
        self.destination_path = destination_path

        self.callback = callback
        self.please_wait_popup = PleaseWaitModalPopup(
            builder, title=_("Please wait..."), message=_("Mounting..."))
        self.please_wait_popup.show()
        thread = threading.Thread(target=self._do_mount_command,
                                  args=(
                                      source_path,
                                      destination_path,
                                  ))
        thread.daemon = True
        thread.start()
Exemple #20
0
 def query_folder(self, path):
     self.query_path = path
     self.image_list_store.clear()
     print("Starting scan of provided path " + self.query_path)
     self.backup_label.set_text(self.query_path)
     self.restore_label.set_text(self.query_path)
     self.image_list_store.clear()
     self.failed_to_read_image_dict.clear()
     self.win.set_sensitive(False)
     self.please_wait_popup = PleaseWaitModalPopup(
         self.builder,
         title=_("Please wait..."),
         message=_("Scanning folder for backup images..."))
     self.please_wait_popup.show()
     thread = threading.Thread(target=self.scan_image_directory)
     thread.daemon = True
     thread.start()
Exemple #21
0
 def scan_image_directory(self):
     self.image_dict.clear()
     self.failed_to_read_image_dict.clear()
     try:
         # list files and directories
         for filename in os.listdir(self.query_path):
             if self.is_stop_requested():
                 break
             abs_base_scan_path = os.path.abspath(
                 join(self.query_path, filename))
             print("Scanning " + abs_base_scan_path)
             if isfile(abs_base_scan_path):
                 print("Scanning file " + abs_base_scan_path)
                 is_image = self.scan_file(abs_base_scan_path, filename,
                                           filename)
                 if is_image:
                     GLib.idle_add(
                         self.please_wait_popup.set_secondary_label_text,
                         _("Scanned: {filename}").format(filename=filename))
             elif isdir(abs_base_scan_path):
                 # List the subdirectory (1 level deep)
                 for subdir_filename in os.listdir(abs_base_scan_path):
                     if self.is_stop_requested():
                         break
                     absolute_path = join(abs_base_scan_path,
                                          subdir_filename)
                     enduser_filename = os.path.join(
                         filename, subdir_filename)
                     if isfile(absolute_path):
                         print("Scanning subdir file " + absolute_path)
                         is_image = self.scan_file(absolute_path,
                                                   subdir_filename,
                                                   enduser_filename)
                         if is_image:
                             GLib.idle_add(
                                 self.please_wait_popup.
                                 set_secondary_label_text,
                                 _("Scanned: {filename}").format(
                                     filename=enduser_filename))
     except Exception as e:
         tb = traceback.format_exc()
         GLib.idle_add(
             ErrorMessageModalPopup.display_nonfatal_warning_message,
             self.builder, "Failed to scan for images: " + tb)
     # Relying on CPython GIL to access the self.image_list
     GLib.idle_add(self._populate_image_list_table)
Exemple #22
0
 def _do_drive_query_wrapper(self):
     try:
         self._do_drive_query()
     except Exception as exception:
         tb = traceback.format_exc()
         traceback.print_exc()
         GLib.idle_add(self.error_message_callback, False, _("Error querying drives: ") + tb)
         return
Exemple #23
0
    def start_query(self, error_message_callback):
        print("Starting drive query...")
        self.win.set_sensitive(False)
        self.requested_stop_lock = threading.Lock()
        self.requested_stop = False

        self.please_wait_popup = PleaseWaitModalPopup(
            self.builder,
            title=_("Please wait..."),
            message=_("Identifying disk drives..."),
            on_close_callback=self.cancel_query)
        self.please_wait_popup.show()
        self.error_message_callback = error_message_callback

        thread = threading.Thread(target=self._do_drive_query_wrapper)
        thread.daemon = True
        thread.start()
Exemple #24
0
 def scan_file(self, absolute_path, filename, enduser_filename):
     print("Scan file " + absolute_path)
     is_image = False
     try:
         image = None
         if isfile(absolute_path):
             # Identify Clonezilla images by presence of a file named "parts". Cannot use "clonezilla-img" or
             # "dev-fs.list" because these files were not created by in earlier Clonezilla versions. Cannot use
             # "disk" as Clonezilla's 'saveparts' function does not create it. But both 'savedisk' and 'saveparts'
             # always creates a file named 'parts' across every version of Clonezilla tested.
             error_suffix = ""
             if absolute_path.endswith("parts"):
                 print("Found Clonezilla image " + filename)
                 image = ClonezillaImage(absolute_path, enduser_filename)
                 error_suffix = _(
                     "This can happen when loading images which Clonezilla was unable to completely backup. Any other filesystems within the image should be restorable as normal."
                 )
                 is_image = True
             elif absolute_path.endswith(".backup"):
                 print(
                     "Found a legacy Redo Backup / Rescuezilla v1.0.5 image "
                     + filename)
                 image = RedoBackupLegacyImage(absolute_path,
                                               enduser_filename, filename)
                 error_suffix = _(
                     "Any other filesystems within the image should be restorable as normal."
                 )
                 is_image = True
             if is_image:
                 image_warning_message = ""
                 for short_partition_key in image.warning_dict.keys():
                     image_warning_message += "    " + short_partition_key + ": " + image.warning_dict[
                         short_partition_key] + "\n"
                 if len(image_warning_message) > 0:
                     self.failed_to_read_image_dict[absolute_path] = _(
                         "Unable to fully process the image associated with the following partitions:"
                     ) + "\n" + image_warning_message + error_suffix
         if image is not None:
             self.image_dict[image.absolute_path] = image
     except Exception as e:
         print("Failed to read: " + absolute_path)
         tb = traceback.format_exc()
         self.failed_to_read_image_dict[enduser_filename] = tb
         traceback.print_exc()
     return is_image
Exemple #25
0
 def do_backup_wrapper(self):
     try:
         self.do_backup()
     except Exception as exception:
         tb = traceback.format_exc()
         traceback.print_exc()
         GLib.idle_add(self.completed_backup, False,
                       _("Error creating backup: ") + tb)
         return
 def do_clone_wrapper(self):
     try:
         self.do_clone()
     except Exception as exception:
         tb = traceback.format_exc()
         traceback.print_exc()
         GLib.idle_add(self.completed_clone, False,
                       _("Error restoring image: ") + tb)
         return
Exemple #27
0
 def do_verify_wrapper(self):
     try:
         self.do_verify()
     except Exception as exception:
         tb = traceback.format_exc()
         traceback.print_exc()
         GLib.idle_add(self.completed_verify, False,
                       _("Error verifying image: ") + tb)
         return
Exemple #28
0
    def _do_nfs_mount_command(self, settings):
        destination_path = settings['destination_path']
        try:
            if not os.path.exists(destination_path) and not os.path.isdir(
                    destination_path):
                os.mkdir(destination_path, 0o755)

            is_unmounted, message = Utility.umount_warn_on_busy(
                destination_path)
            if not is_unmounted:
                GLib.idle_add(self.please_wait_popup.destroy)
                GLib.idle_add(self.callback, False, message)
                return

            if settings['server'] != "":
                server = settings['server']
            else:
                GLib.idle_add(self.please_wait_popup.destroy)
                GLib.idle_add(self.callback, False, "Must specify server.")
                return

            if settings['remote_path'] != "":
                exported_dir = settings['remote_path']
            else:
                GLib.idle_add(self.please_wait_popup.destroy)
                GLib.idle_add(self.callback, False,
                              "Must specify exported directory.")
                return

            mount_cmd_list = [
                "mount.nfs", server + ":" + exported_dir,
                settings['destination_path']
            ]
            mount_process, mount_flat_command_string, mount_failed_message = Utility.interruptable_run(
                "Mounting network shared folder with NFS: ",
                mount_cmd_list,
                use_c_locale=False,
                is_shutdown_fn=self.is_stop_requested)
            if mount_process.returncode != 0:
                check_password_msg = _(
                    "Please ensure the server and exported path are correct, and try again."
                )
                GLib.idle_add(self.please_wait_popup.destroy)
                GLib.idle_add(
                    self.callback, False,
                    mount_failed_message + "\n\n" + check_password_msg)
                return
            else:
                GLib.idle_add(self.please_wait_popup.destroy)
                GLib.idle_add(self.callback, True, "", destination_path)
        except Exception as e:
            tb = traceback.format_exc()
            print(tb)
            GLib.idle_add(self.please_wait_popup.destroy)
            GLib.idle_add(self.callback, False,
                          "Error mounting NFS folder: " + tb)
    def __init__(self, builder, callback, prefix, destination_path):
        settings = {
            'server': builder.get_object(prefix + "_server").get_text(),
            'username': builder.get_object(prefix + "_username").get_text(),
            'password': builder.get_object(prefix + "_password").get_text(),
            'domain': builder.get_object(prefix + "_domain").get_text(),
            'version': builder.get_object(prefix + "_version").get_text(),
            'destination_path': destination_path
        }

        # restore_source_version
        self.callback = callback
        self.please_wait_popup = PleaseWaitModalPopup(
            builder, title=_("Please wait..."), message=_("Mounting..."))
        self.please_wait_popup.show()
        thread = threading.Thread(target=self._do_mount_command,
                                  args=(settings, ))
        thread.daemon = True
        thread.start()
Exemple #30
0
    def update(drawing=drawing, usage_label=usage_label, node=node):

        usage_label.set_text(_('Network usage so far: ')
                             + utility.human_size(node.network_usage))
        
        if not drawing.flags() & gtk.VISIBLE:
            return 0

        drawing.queue_draw()
        return 1
Exemple #31
0
    def confirm_restore_configuration(self):
        # number = GObject.markup_escape_text(self.selected_drive_enduser_friendly_drive_number)

        print("Partitions to restore is " + str(self.partitions_to_restore))
        source_image_absolute_path = self.selected_image_absolute_path
        destination_drive_description = self.restore_destination_drive_desc
        restore_partition_list_string = ""
        for key in self.partitions_to_restore.keys():
            image_part_description = GObject.markup_escape_text(
                self.partitions_to_restore[key]["description"])
            dest_key = GObject.markup_escape_text(
                self.partitions_to_restore[key]["dest_key"])
            dest_description = GObject.markup_escape_text(
                self.partitions_to_restore[key]["dest_description"])
            restore_partition_list_string += "    " + GObject.markup_escape_text(
                key
            ) + " (" + image_part_description + ")  ---->  " + dest_key + " (" + dest_description + ")\n"
        restore_partition_list_string += "\n"

        if self.is_overwriting_partition_table:
            overwriting_partition_table_string = "<b>" + _(
                "WILL BE OVERWRITING PARTITION TABLE") + "</b>"
        else:
            overwriting_partition_table_string = _(
                "Will <b>NOT</b> be overwriting partition table")

        source_image_heading = _("Source image")
        destination_drive_msg = _("Destination drive")
        restoring_following_partition_msg = _(
            "Restoring the following partitions")

        text_to_display = f"""
<b>{source_image_heading}</b> {source_image_absolute_path}
<b>{destination_drive_msg}</b> {destination_drive_description}

<b>{restoring_following_partition_msg}</b>:
{restore_partition_list_string}

{overwriting_partition_table_string}
"""
        self.builder.get_object(
            "restore_step5_confirm_config_program_defined_text").set_markup(
                text_to_display)