Esempio n. 1
0
 def setUp(self):
     self.soon = 0
     self.later = 0
     self.clock = task.Clock()
     self.myBackup = BackupManager(self.clock,
                                   soonDuration=3,
                                   laterDuration=5,
                                   soonCommand=self.soonBackup,
                                   laterCommand=self.laterBackup)
Esempio n. 2
0
    def __init__(self, builder):
        # The GTKBuilder is used to retrieve any arbitrary GTK widgets using "id" attributes in the GTKBuilder
        # (.glade) XML file
        self.builder = builder
        self.save_partition_list_store = self.builder.get_object(
            "save_partition_list")
        self.drive_list_store = self.builder.get_object("drive_list")
        self.mount_partition_list_store = self.builder.get_object(
            "mount_partition_list")
        self.image_list_store = self.builder.get_object("image_list")

        self.has_prior_summary_page = False
        self.memory_bus_width = Utility.get_memory_bus_width().strip()
        self.version = Utility.read_file_into_string(
            "/usr/share/rescuezilla/VERSION").strip()
        self.commit_date = Utility.read_file_into_string(
            "/usr/share/rescuezilla/GIT_COMMIT_DATE").strip()
        self.main_statusbar = self.builder.get_object("main_statusbar")
        self.human_readable_version = self.version + " (" + self.memory_bus_width + ") " + self.commit_date
        self.display_welcome_page()
        self.mode = Mode.BACKUP
        self.current_page = Page.WELCOME
        self.drive_query = DriveQuery(self.builder, self.drive_list_store,
                                      self.save_partition_list_store,
                                      self.mount_partition_list_store)
        self.image_folder_query = ImageFolderQuery(self.builder,
                                                   self.image_list_store)

        self.restore_partition_selection_list = self.builder.get_object(
            "restore_partition_selection_list")
        self.backup_image = PartitionsToRestore(
            self.builder, self.restore_partition_selection_list)
        self.set_support_information_linkbutton_visible(False)
        self.set_patreon_call_to_action_visible(True)
        # TODO: Remove the need to set this variable to None
        self.selected_drive_key = None
        # Ensuring toggle button is ticked and consistency of the user-interface elements that are associated with this
        # checkbox.

        # Initialize network share options
        self.network_share_protocol_list = self.builder.get_object(
            "network_share_protocol_list")
        self.network_share_protocol_list.append(
            ["SMB", _("SMB/CIFS shared folder specified below")])
        self.builder.get_object("restore_source_network").set_active(0)
        self.builder.get_object("backup_dest_network").set_active(0)

        self.backup_manager = BackupManager(builder,
                                            self.human_readable_version)
        self.restore_manager = RestoreManager(builder)
Esempio n. 3
0
def main():
    """
    Fonction principale, lançant tout le programme selon la configuration donnée.

    La configuration du programme est disponible dans le fichier `settings.yaml`.
    """
    print("""Lancement du programme

    Assurez-vous que toutes les dépendances utilisées soient installées sur votre ordinateur ;
    si besoin entrez `pip install -r requirements.txt` dans votre console
    """)

    # Chargement de la configuration
    global SETTINGS
    try:
        SETTINGS = load_from_filename("settings.yaml")
    except AssertionError as e:
        print("Erreur lors du chargement de la configuration :\n" + e.args[0])
        return

    # Démarrage du debug
    if SETTINGS.debug_mode:
        pr = cProfile.Profile()
        pr.enable()

    draw.init()
    pygame.init()
    screen = pygame.display.set_mode(SETTINGS.screen_size)

    pygame.display.set_caption("TIPE")
    circuit = circuit_creation(SETTINGS)

    if SETTINGS.manual_control:
        manual_loop(screen, circuit)
    else:
        last_network = AI_loop(screen, circuit)
        if SETTINGS.autosave:
            BackupManager().create(network=last_network)

    pygame.quit()

    if SETTINGS.debug_mode:
        pr.disable()
        s = io.StringIO()
        sortby = SortKey.CUMULATIVE
        ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
        ps.print_stats()
        with open("stats_report.log", "w", encoding="utf-8") as f:
            f.write(s.getvalue())
from backup_manager import BackupManager
from argparser import ArgParser

if __name__ == '__main__':
    ap = ArgParser()
    backup_manager = BackupManager(**ap.get_parameters())
    backup_manager.check_free_space()
    if not backup_manager.is_actual_backup_exist():
        backup_manager.create_backup()
        backup_manager.check_actual_backup()
    else:
        backup_manager.check_actual_backup()
Esempio n. 5
0
class Handler:
    """As an event driven application, this handler is where most of the application logic is done.
   The widgets in the GTKBuilder (.glade) XML file are configured with the function names defined in this file (eg,
   when a button is clicked).

   Thread-safety note: All functions (other than the constructor) are expected to be called via the GTK event loop.
   Do long-running operations in a separate Python thread and update the UI by queueing a function to run on the GTK
   event loop up using GLib.idle_add(). Please note, these Python threads created by the threading module are subject
   to the CPython GIL (Global Interpreter Lock) which can be leveraged for some limited threadsafety guarantees.
   If/when the GIL is leveraged for the threadsafety guarantees, this will be clearly commented.

   Documentation/API reference:
   For developers with some knowledge of other UI frameworks but less experience with Python/PyGTK specifically, here is
   a gentle reference/tutorial with good examples: https://python-gtk-3-tutorial.readthedocs.io/en/latest/
   Generic GTK3 API documentation https://developer.gnome.org/gtk3/stable/
   PyGTK-specific API documentation https://developer.gnome.org/pygtk/stable/class-gtknotebook.html
   """
    def __init__(self, builder):
        # The GTKBuilder is used to retrieve any arbitrary GTK widgets using "id" attributes in the GTKBuilder
        # (.glade) XML file
        self.builder = builder
        self.save_partition_list_store = self.builder.get_object(
            "save_partition_list")
        self.drive_list_store = self.builder.get_object("drive_list")
        self.mount_partition_list_store = self.builder.get_object(
            "mount_partition_list")
        self.image_list_store = self.builder.get_object("image_list")

        self.has_prior_summary_page = False
        self.memory_bus_width = Utility.get_memory_bus_width().strip()
        self.version = Utility.read_file_into_string(
            "/usr/share/rescuezilla/VERSION").strip()
        self.commit_date = Utility.read_file_into_string(
            "/usr/share/rescuezilla/GIT_COMMIT_DATE").strip()
        self.main_statusbar = self.builder.get_object("main_statusbar")
        self.human_readable_version = self.version + " (" + self.memory_bus_width + ") " + self.commit_date
        self.display_welcome_page()
        self.mode = Mode.BACKUP
        self.current_page = Page.WELCOME
        self.drive_query = DriveQuery(self.builder, self.drive_list_store,
                                      self.save_partition_list_store,
                                      self.mount_partition_list_store)
        self.image_folder_query = ImageFolderQuery(self.builder,
                                                   self.image_list_store)

        self.restore_partition_selection_list = self.builder.get_object(
            "restore_partition_selection_list")
        self.backup_image = PartitionsToRestore(
            self.builder, self.restore_partition_selection_list)
        self.set_support_information_linkbutton_visible(False)
        self.set_patreon_call_to_action_visible(True)
        # TODO: Remove the need to set this variable to None
        self.selected_drive_key = None
        # Ensuring toggle button is ticked and consistency of the user-interface elements that are associated with this
        # checkbox.

        # Initialize network share options
        self.network_share_protocol_list = self.builder.get_object(
            "network_share_protocol_list")
        self.network_share_protocol_list.append(
            ["SMB", _("SMB/CIFS shared folder specified below")])
        self.builder.get_object("restore_source_network").set_active(0)
        self.builder.get_object("backup_dest_network").set_active(0)

        self.backup_manager = BackupManager(builder,
                                            self.human_readable_version)
        self.restore_manager = RestoreManager(builder)

    # Suggest the user read the frequently asked questions, then potentially proceed to the support forum.
    def set_support_information_linkbutton_visible(self, is_visible):
        self.builder.get_object("welcome_support_linkbutton").set_visible(
            is_visible)
        self.builder.get_object("backup_step8_support_linkbutton").set_visible(
            is_visible)
        self.builder.get_object(
            "restore_step7_support_linkbutton").set_visible(is_visible)

    # Ask users to contribute on the crowdfunding website Patreon.
    def set_patreon_call_to_action_visible(self, is_visible):
        self.builder.get_object("welcome_patreon_linkbutton").set_visible(
            is_visible)
        self.builder.get_object("backup_step8_patreon_linkbutton").set_visible(
            is_visible)
        self.builder.get_object(
            "restore_step7_patreon_linkbutton").set_visible(is_visible)

    def display_welcome_page(self):
        self.current_page = Page.WELCOME

        self.main_statusbar.push(self.main_statusbar.get_context_id("version"),
                                 self.human_readable_version)

        self.builder.get_object("mode_tabs").set_current_page(0)
        # Disable the forward/previous navigation buttons on the welcome page
        self.builder.get_object("button_next").set_sensitive(False)
        if self.has_prior_summary_page:
            self.builder.get_object("button_back").set_sensitive(True)
        else:
            self.builder.get_object("button_back").set_sensitive(False)

    def display_backup_wizard(self, button):
        self.mode = Mode.BACKUP
        self.drive_query.start_query()
        self.main_statusbar.pop(self.main_statusbar.get_context_id("version"))
        self.current_page = Page.BACKUP_SOURCE_DRIVE_SELECTION
        self.builder.get_object("mode_tabs").set_current_page(1)
        self.builder.get_object("backup_tabs").set_current_page(0)
        # Re-enable the forward/previous navigation buttons
        self.builder.get_object("button_back").set_sensitive(True)
        self.builder.get_object("button_next").set_sensitive(True)
        # Remove access to any summary pages from prior operations
        self.has_prior_summary_page = False

    def display_restore_wizard(self, button):
        self.mode = Mode.RESTORE
        self.drive_query.start_query()
        self.main_statusbar.pop(self.main_statusbar.get_context_id("version"))
        self.current_page = Page.RESTORE_SOURCE_LOCATION_SELECTION
        self.builder.get_object("mode_tabs").set_current_page(2)
        self.builder.get_object("restore_tabs").set_current_page(0)
        # Re-enable the forward/previous navigation buttons
        self.builder.get_object("button_back").set_sensitive(True)
        self.builder.get_object("button_next").set_sensitive(True)
        # Remove access to any summary pages from prior operations
        self.has_prior_summary_page = False

    def get_row(self, id):
        treeselection = self.builder.get_object(id)
        list_store, tree_path_list = treeselection.get_selected_rows()
        if len(list_store) == 0 or len(tree_path_list) == 0:
            return list_store, None
        iter = list_store.get_iter(tree_path_list[0])
        return list_store, iter

    def next_tab(self, button):
        try:
            print("Currently mode=" + str(self.mode) + " on page " +
                  str(self.current_page))
            if self.mode == Mode.BACKUP:
                if self.current_page == Page.WELCOME:
                    print("Unexpected")
                elif self.current_page == Page.BACKUP_SOURCE_DRIVE_SELECTION:
                    list_store, iter = self.get_row(
                        "backup_drive_selection_treeselection")
                    if iter is None:
                        error = ErrorMessageModalPopup(
                            self.builder,
                            "No source drive selected. Please select source "
                            "drive to backup")
                    else:
                        # Get first column (which is hidden/invisible) containing the drive shortdevname (eg, 'sda')
                        self.selected_drive_key = list_store.get(iter, 0)[0]
                        print("User selected drive: " +
                              self.selected_drive_key)
                        self.drive_query.populate_partition_selection_table(
                            self.selected_drive_key)

                        self.selected_drive_enduser_friendly_drive_number = list_store.get(
                            iter, 1)[0]
                        self.selected_drive_capacity = list_store.get(iter,
                                                                      2)[0]
                        # FIXME: May be None for devices like /dev/md127
                        self.selected_drive_model = list_store.get(iter, 3)[0]

                        self.current_page = Page.BACKUP_SOURCE_PARTITION_SELECTION
                        self.builder.get_object(
                            "backup_tabs").set_current_page(1)
                elif self.current_page == Page.BACKUP_SOURCE_PARTITION_SELECTION:
                    partition_list_store = self.builder.get_object(
                        "save_partition_list")
                    if 'partitions' not in self.drive_query.drive_state[
                            self.selected_drive_key].keys():
                        error = ErrorMessageModalPopup(
                            self.builder,
                            "Backup of drives without a partition table not yet supported by current version of Rescuezilla.\n\nSupport for this will be added in a future version.\n\nHowever, as a temporary workaround, it is possible to use Clonezilla's 'savedisk' option to backup the drive, and then use Rescuezilla to restore that image."
                        )
                        return
                    self.partitions_to_backup = collections.OrderedDict()
                    has_atleast_one = False
                    for row in partition_list_store:
                        print("row is " + str(row))
                        if row[1]:
                            self.partitions_to_backup[
                                row[0]] = self.drive_query.drive_state[
                                    self.selected_drive_key]['partitions'][
                                        row[0]]
                            self.partitions_to_backup[
                                row[0]]['description'] = row[2]
                            has_atleast_one = True
                    if not has_atleast_one:
                        error = ErrorMessageModalPopup(self.builder,
                                                       "Nothing selected!")
                    else:
                        self.drive_query.populate_mount_partition_table(
                            ignore_drive_key=self.selected_drive_key)
                        self.current_page = Page.BACKUP_DESTINATION_LOCATION_SELECTION
                        self.builder.get_object(
                            "backup_tabs").set_current_page(2)
                elif self.current_page == Page.BACKUP_DESTINATION_LOCATION_SELECTION:
                    backup_dest_use_local_radiobutton = self.builder.get_object(
                        "backup_dest_use_local_radiobutton")
                    if backup_dest_use_local_radiobutton.get_active():
                        list_store, iter = self.get_row(
                            "backup_destination_partition_selection_treeselection"
                        )
                        if iter is None:
                            error = ErrorMessageModalPopup(
                                self.builder,
                                "Please select destination drive to mount")
                        else:
                            # Get first column (which is hidden/invisible) containing the drive shortdevname (eg, 'sda')
                            selected_partition_key = list_store.get(iter, 0)[0]
                            self.destination_partition_description = list_store.get(
                                iter, 3)[0]
                            print("User selected partition: " +
                                  selected_partition_key)
                            # Callback determines whether wizard proceeds
                            MountLocalPath(self.builder,
                                           self._post_mount_callback,
                                           selected_partition_key, MOUNT_DIR)
                    else:
                        self.destination_partition_description = "network share"
                        MountNetworkPath(self.builder,
                                         self._post_mount_callback,
                                         "backup_dest", MOUNT_DIR)
                elif self.current_page == Page.BACKUP_DESTINATION_FOLDER:
                    enduser_date = datetime.today().strftime(
                        '%Y-%m-%d-%H%M') + "-img-rescuezilla"
                    self.builder.get_object("backup_name").set_text(
                        enduser_date)
                    self.current_page = Page.BACKUP_IMAGE_NAME_SELECTION
                    self.builder.get_object("backup_tabs").set_current_page(4)
                elif self.current_page == Page.BACKUP_IMAGE_NAME_SELECTION:
                    selected_directory = self.builder.get_object(
                        "backup_folder_label").get_text()
                    folder_name = self.builder.get_object(
                        "backup_name").get_text()
                    self.dest_dir = os.path.join(selected_directory,
                                                 folder_name)
                    print("going to write to" + str(self.dest_dir))
                    self.confirm_backup_configuration()
                    self.current_page = Page.BACKUP_CONFIRM_CONFIGURATION
                    self.builder.get_object("backup_tabs").set_current_page(5)
                elif self.current_page == Page.BACKUP_CONFIRM_CONFIGURATION:
                    self.current_page = Page.BACKUP_PROGRESS
                    self.builder.get_object("backup_tabs").set_current_page(6)
                    self.backup_manager.start_backup(
                        self.selected_drive_key, self.partitions_to_backup,
                        self.drive_query.drive_state, self.dest_dir,
                        self._on_backup_restore_operation_completed_callback)
                    # Disable back/next button until the restore completes
                    self.builder.get_object("button_next").set_sensitive(False)
                    self.builder.get_object("button_back").set_sensitive(False)
                    # On success, display the Patreon call-to-action.
                    self.set_patreon_call_to_action_visible(True)
                    # Disable back/next button until the backup completes
                    self.builder.get_object("button_back").set_sensitive(False)
                    # self.builder.get_object("button_next").set_sensitive(False)
                elif self.current_page == Page.BACKUP_PROGRESS:
                    self.current_page = Page.BACKUP_SUMMARY_SCREEN
                    self.builder.get_object("backup_tabs").set_current_page(7)
                    self.builder.get_object("button_next").set_sensitive(True)
                    self.builder.get_object("button_back").set_sensitive(False)
                elif self.current_page == Page.BACKUP_SUMMARY_SCREEN:
                    self.has_prior_summary_page = True
                    self.display_welcome_page()
                else:
                    print("Unexpected")
            elif self.mode == Mode.RESTORE:
                if self.current_page == Page.WELCOME:
                    print("Unexpected")
                elif self.current_page == Page.RESTORE_SOURCE_LOCATION_SELECTION:
                    restore_source_use_local_radiobutton = self.builder.get_object(
                        "restore_source_use_local_radiobutton")
                    if restore_source_use_local_radiobutton.get_active():
                        list_store, iter = self.get_row(
                            "source_partition_selection_treeselection")
                        if iter is None:
                            error = ErrorMessageModalPopup(
                                self.builder, "Please select drive to mount")
                        else:
                            # Get first column (which is hidden/invisible) containing the drive shortdevname (eg, 'sda')
                            self.image_source_partition_key = list_store.get(
                                iter, 0)[0]
                            print("User selected partition: " +
                                  self.image_source_partition_key)
                            # Callback determines whether wizard proceeds
                            MountLocalPath(self.builder,
                                           self._post_mount_callback,
                                           self.image_source_partition_key,
                                           MOUNT_DIR)
                    else:
                        # In network mode, there is no partition key for the source drive
                        self.image_source_partition_key = None
                        MountNetworkPath(self.builder,
                                         self._post_mount_callback,
                                         "restore_source", MOUNT_DIR)
                elif self.current_page == Page.RESTORE_SOURCE_IMAGE_SELECTION:
                    list_store, iter = self.get_row(
                        "restore_partition_selection_treeselection")
                    if iter is None:
                        error = ErrorMessageModalPopup(self.builder,
                                                       "No image selected")
                    else:
                        self.selected_image_absolute_path = list_store.get(
                            iter, 0)[0]
                        print("User image: " +
                              self.selected_image_absolute_path)
                        image = self.image_folder_query.image_dict[
                            self.selected_image_absolute_path]
                        if image.is_needs_decryption:
                            error = ErrorMessageModalPopup(
                                self.builder,
                                "Ecryptfs encrypted images are not supported by current version of Rescuezilla.\n\nSupport for ecryptfs will be improved in a future version.\n\nHowever, as a temporary workaround, it is possible to carefully use the ecryptfs command line utility to mount and decrypt the image, and then point Rescuezilla to this ecryptfs mount point and then use Rescuezilla to restore the image as normal."
                            )
                        else:
                            if len(image.short_device_node_disk_list) > 1:
                                # Unlike Rescuezilla, Clonezilla is able to backup multiple devices at the same time into
                                # a single image. The Rescuezilla user-interface doesn't yet support this, so the first
                                # disk is always selected.
                                error = ErrorMessageModalPopup(
                                    self.builder,
                                    _("IMPORTANT: Only selecting FIRST disk in Clonezilla image containing MULTIPLE DISKS."
                                      ) + "\n\n" +
                                    "Multidisk Clonezilla images are not fully supported by the current version of Rescuezilla.\n\nOnly the FIRST disk in the multidisk image has been selected.\n\nBefore proceeding, please double-check if this is suitable."
                                )
                            self.current_page = Page.RESTORE_DESTINATION_DRIVE_SELECTION
                            self.builder.get_object(
                                "restore_tabs").set_current_page(2)
                elif self.current_page == Page.RESTORE_DESTINATION_DRIVE_SELECTION:
                    list_store, iter = self.get_row(
                        "restore_step3_drive_selection_treeselection")
                    if iter is None:
                        error = ErrorMessageModalPopup(
                            self.builder,
                            "Please select destination drive to mount")
                    else:
                        self.restore_destination_drive = list_store.get(
                            iter, 0)[0]
                        if self.image_source_partition_key is not None and self.image_source_partition_key.startswith(
                                self.restore_destination_drive):
                            # TODO: Handle this situation more effectively than "startswith" on the device nodes.
                            error = ErrorMessageModalPopup(
                                self.builder,
                                "Destination device cannot be the same as source image device."
                            )
                            return
                        # Set a nice description like "sdc: 8.00 GB (TOSHIBA USB DRV)
                        self.restore_destination_drive_desc = list_store.get(
                            iter, 1)[0] + ": " + list_store.get(iter, 2)[0]
                        drive_model = list_store.get(iter, 3)[0]
                        if drive_model is not None:
                            # Some devices, such as RAID devices /dev/md127 don't set the drive model field.
                            self.restore_destination_drive_desc += " (" + drive_model + ")"
                        print("User selected destination drive: " +
                              self.restore_destination_drive)
                        self.selected_image = self.image_folder_query.image_dict[
                            self.selected_image_absolute_path]
                        drive_dict = self.drive_query.drive_state[
                            self.restore_destination_drive]
                        # TODO: Compare self.selected_image.size_bytes to drive_dict["capacity"] in bytes
                        try:
                            self.backup_image.initialize_individual_partition_restore_list(
                                self.selected_image,
                                self.restore_destination_drive,
                                self.restore_destination_drive_desc,
                                drive_dict)
                        except Exception as e:
                            tb = traceback.format_exc()
                            traceback.print_exc()
                            error = ErrorMessageModalPopup(
                                self.builder, "Unable to process image " + tb)
                        self.current_page = Page.RESTORE_DESTINATION_PARTITION_SELECTION
                        self.builder.get_object(
                            "restore_tabs").set_current_page(3)
                elif self.current_page == Page.RESTORE_DESTINATION_PARTITION_SELECTION:
                    self.is_overwriting_partition_table = self.builder.get_object(
                        "overwrite_partition_table_checkbutton").get_active()
                    restore_partition_selection_list = self.builder.get_object(
                        "restore_partition_selection_list")
                    self.partitions_to_restore = collections.OrderedDict()
                    has_atleast_one = False
                    for row in restore_partition_selection_list:
                        print("row is " + str(row))
                        if row[1]:
                            image_key = row[0]
                            self.partitions_to_restore[image_key] = {
                                "description": row[2],
                                "dest_key": row[3],
                                "dest_description": row[4]
                            }
                            print("Added " + image_key + " " +
                                  str(self.partitions_to_restore[image_key]))
                            has_atleast_one = True
                    if not has_atleast_one:
                        error = ErrorMessageModalPopup(
                            self.builder,
                            "Please select partitions to restore!")
                    else:
                        self.confirm_restore_configuration()
                        self.current_page = Page.RESTORE_CONFIRM_CONFIGURATION
                        self.builder.get_object(
                            "restore_tabs").set_current_page(4)
                elif self.current_page == Page.RESTORE_CONFIRM_CONFIGURATION:
                    # Disable back/next button until the restore completes
                    self.builder.get_object("button_next").set_sensitive(False)
                    self.builder.get_object("button_back").set_sensitive(False)
                    AreYouSureModalPopup(
                        self.builder,
                        _("Are you sure you want to restore the backup to {destination_drive}? Doing so will permanently overwrite the data on this drive!"
                          ).format(destination_drive=self.
                                   restore_destination_drive),
                        self._restore_confirmation_callback)
                elif self.current_page == Page.RESTORE_PROGRESS:
                    self.current_page = Page.RESTORE_SUMMARY_SCREEN
                    self.builder.get_object("restore_tabs").set_current_page(6)
                    self.builder.get_object("button_back").set_sensitive(False)
                    self.builder.get_object("button_next").set_sensitive(True)
                elif self.current_page == Page.RESTORE_SUMMARY_SCREEN:
                    self.has_prior_summary_page = True
                    self.display_welcome_page()
                else:
                    print("Unexpected")
            else:
                print("Unexpected")
            print(" Moving to mode=" + str(self.mode) + " on page " +
                  str(self.current_page))
        except Exception as e:
            tb = traceback.format_exc()
            traceback.print_exc()
            error = ErrorMessageModalPopup(self.builder, tb)

    def prev_tab(self, button):
        try:
            print("Currently mode=" + str(self.mode) + " on page " +
                  str(self.current_page))
            if self.mode == Mode.BACKUP:
                if self.current_page == Page.WELCOME:
                    print("Previous backup summary page")
                    self.builder.get_object("mode_tabs").set_current_page(1)
                    self.builder.get_object("backup_tabs").set_current_page(7)
                    self.current_page = Page.BACKUP_SUMMARY_SCREEN
                    self.builder.get_object("button_back").set_sensitive(False)
                    self.builder.get_object("button_next").set_sensitive(True)
                elif self.current_page == Page.BACKUP_SOURCE_DRIVE_SELECTION:
                    self.current_page = Page.WELCOME
                    self.display_welcome_page()
                elif self.current_page == Page.BACKUP_SOURCE_PARTITION_SELECTION:
                    self.current_page = Page.BACKUP_SOURCE_DRIVE_SELECTION
                    self.builder.get_object("backup_tabs").set_current_page(0)
                elif self.current_page == Page.BACKUP_DESTINATION_LOCATION_SELECTION:
                    self.current_page = Page.BACKUP_SOURCE_PARTITION_SELECTION
                    self.builder.get_object("backup_tabs").set_current_page(1)
                elif self.current_page == Page.BACKUP_DESTINATION_FOLDER:
                    self.current_page = Page.BACKUP_DESTINATION_LOCATION_SELECTION
                    self.builder.get_object("backup_tabs").set_current_page(2)
                elif self.current_page == Page.BACKUP_IMAGE_NAME_SELECTION:
                    self.current_page = Page.BACKUP_DESTINATION_FOLDER
                    self.builder.get_object("backup_tabs").set_current_page(3)
                elif self.current_page == Page.BACKUP_CONFIRM_CONFIGURATION:
                    self.current_page = Page.BACKUP_IMAGE_NAME_SELECTION
                    self.builder.get_object("backup_tabs").set_current_page(4)
                elif self.current_page == Page.BACKUP_PROGRESS:
                    self.current_page = Page.BACKUP_CONFIRM_CONFIGURATION
                    self.builder.get_object("backup_tabs").set_current_page(5)
                elif self.current_page == Page.BACKUP_SUMMARY_SCREEN:
                    self.current_page = Page.BACKUP_PROGRESS
                    self.builder.get_object("backup_tabs").set_current_page(6)
                else:
                    print("Unexpected")
            elif self.mode == Mode.RESTORE:
                if self.current_page == Page.WELCOME:
                    print("Previous restore summary page")
                    self.builder.get_object("mode_tabs").set_current_page(2)
                    self.builder.get_object("restore_tabs").set_current_page(6)
                    self.current_page = Page.RESTORE_SUMMARY_SCREEN
                    self.builder.get_object("button_back").set_sensitive(False)
                    self.builder.get_object("button_next").set_sensitive(True)
                elif self.current_page == Page.RESTORE_SOURCE_LOCATION_SELECTION:
                    self.current_page = Page.WELCOME
                    self.display_welcome_page()
                elif self.current_page == Page.BACKUP_SOURCE_PARTITION_SELECTION:
                    self.builder.get_object("mode_tabs").set_current_page(0)
                elif self.current_page == Page.RESTORE_SOURCE_IMAGE_SELECTION:
                    self.current_page = Page.RESTORE_SOURCE_LOCATION_SELECTION
                    self.builder.get_object("restore_tabs").set_current_page(0)
                elif self.current_page == Page.RESTORE_DESTINATION_DRIVE_SELECTION:
                    self.current_page = Page.RESTORE_SOURCE_IMAGE_SELECTION
                    self.builder.get_object("restore_tabs").set_current_page(1)
                elif self.current_page == Page.RESTORE_DESTINATION_PARTITION_SELECTION:
                    self.current_page = Page.RESTORE_DESTINATION_DRIVE_SELECTION
                    self.builder.get_object("restore_tabs").set_current_page(2)
                elif self.current_page == Page.RESTORE_CONFIRM_CONFIGURATION:
                    self.current_page = Page.RESTORE_DESTINATION_PARTITION_SELECTION
                    self.builder.get_object("restore_tabs").set_current_page(3)
                elif self.current_page == Page.RESTORE_PROGRESS:
                    self.current_page = Page.RESTORE_CONFIRM_CONFIGURATION
                    self.builder.get_object("restore_tabs").set_current_page(4)
                elif self.current_page == Page.RESTORE_SUMMARY_SCREEN:
                    self.current_page = Page.RESTORE_PROGRESS
                    self.builder.get_object("restore_tabs").set_current_page(5)
                else:
                    print("Unexpected")
            else:
                print("Unexpected")
            print("Moving to mode=" + str(self.mode) + " on page " +
                  str(self.current_page))
        except Exception as e:
            tb = traceback.format_exc()
            traceback.print_exc()
            error = ErrorMessageModalPopup(self.builder, tb)

    def _post_mount_callback(self,
                             is_success,
                             error_message,
                             mounted_path=None):
        if not is_success or mounted_path is None:
            error = ErrorMessageModalPopup(self.builder, error_message)
        else:
            if self.mode == Mode.BACKUP:
                self.current_page = Page.BACKUP_DESTINATION_FOLDER
                self.builder.get_object("backup_tabs").set_current_page(3)
                self.selected_folder(mounted_path, False)
            else:
                self.current_page = Page.RESTORE_SOURCE_IMAGE_SELECTION
                self.builder.get_object("restore_tabs").set_current_page(1)
                self.selected_folder(mounted_path, True)

    # Called via AreYouSure prompt
    def _restore_confirmation_callback(self, is_affirmative):
        if is_affirmative:
            self.current_page = Page.RESTORE_PROGRESS
            self.builder.get_object("restore_tabs").set_current_page(5)
            self.restore_manager.start_restore(
                self.selected_image, self.restore_destination_drive,
                self.partitions_to_restore,
                self.is_overwriting_partition_table,
                self._on_backup_restore_operation_completed_callback)
            # Display the Patreon call-to-action.
            self.set_patreon_call_to_action_visible(True)
        else:
            self.builder.get_object("button_back").set_sensitive(True)
            self.builder.get_object("button_next").set_sensitive(True)

    def _on_backup_restore_operation_completed_callback(self, is_success):
        if is_success:
            self.set_support_information_linkbutton_visible(False)
            self.set_patreon_call_to_action_visible(True)
        else:
            self.set_support_information_linkbutton_visible(True)
            self.set_patreon_call_to_action_visible(False)
        self.next_tab(None)

    def row_activated_next_tab(self, treeview, path, view_column):
        # Callback for double click (row-activate).
        self.next_tab(None)
        # Not using index = path.get_indices()[0], as the next button could also be used not double-click.

    def save_partition_toggled(self, cellrendertoggle, path):
        print("Backup partition toggled: " + str(path))
        iter = self.save_partition_list_store.get_iter(path)
        # Get the first column
        state = self.save_partition_list_store.get(iter, 1)[0]
        # invert toggle
        self.save_partition_list_store.set_value(iter, 1, not state)

    def exit_app(self):
        print("Exiting Rescuezilla.")
        try:
            # Launch subprocess to unmount target directory. Subprocess is detached so it doesn't block Rescuezilla's
            # shutdown.
            subprocess.Popen(["umount", MOUNT_DIR])
        except Exception as e:
            tb = traceback.format_exc()
            traceback.print_exc()
        Gtk.main_quit()

    def _cancel_current_operations(self, is_affirmative):
        if is_affirmative:
            print("Cancelling current operations.")
            if self.restore_manager.is_restore_in_progress():
                self.restore_manager.cancel_restore()
            if self.backup_manager.is_backup_in_progress():
                self.backup_manager.cancel_backup()

    # Main window receives close signal
    def main_window_delete_event(self, widget, event):
        print("Received Rescuezilla shutdown request")
        if self.backup_manager.is_backup_in_progress(
        ) or self.restore_manager.is_restore_in_progress():
            print("An operation is in progress. Do you wish to cancel?")
            AreYouSureModalPopup(
                self.builder,
                "An operation is in progress. Do you wish to cancel?",
                self._cancel_current_operations)
        else:
            self.exit_app()
        # Return True to prevent the window closing from this signal, and instead rely on the dialog box callback.
        # ("True to stop other handlers from being invoked for the event. False to propagate the event further.")
        return True

    def restore_file_changed(self):
        print("test")

    def restore_scan_network(self):
        return

    def restore_source_network_changed(self):
        return

    def backup_destination_location_toggle(self, toggle_button):
        backup_frame_local = self.builder.get_object("backup_frame_local")
        backup_frame_network = self.builder.get_object("backup_frame_network")

        use_local_radiobutton = self.builder.get_object(
            "backup_dest_use_local_radiobutton")
        use_network_radiobutton = self.builder.get_object(
            "backup_dest_use_network_radiobutton")

        if toggle_button.get_active():
            if toggle_button == use_local_radiobutton:
                backup_frame_network.set_visible(False)
                backup_frame_local.set_visible(True)
                print("toggle 1")
            elif toggle_button == use_network_radiobutton:
                backup_frame_network.set_visible(True)
                backup_frame_local.set_visible(False)
                print("toggle 2")
        return

    def restore_source_location_toggle(self, toggle_button):
        restore_frame_local = self.builder.get_object("restore_frame_local")
        restore_frame_network = self.builder.get_object(
            "restore_frame_network")

        use_local_radiobutton = self.builder.get_object(
            "restore_source_use_local_radiobutton")
        use_network_radiobutton = self.builder.get_object(
            "restore_source_use_network_radiobutton")

        print("restore changed")
        if toggle_button.get_active():
            if toggle_button == use_local_radiobutton:
                restore_frame_network.set_visible(False)
                restore_frame_local.set_visible(True)
                print("toggle 1")
            elif toggle_button == use_network_radiobutton:
                restore_frame_network.set_visible(True)
                restore_frame_local.set_visible(False)
                print("toggle 2")
        return

    def restore_partition_toggled(self, cell_render_toggle, path):
        iter = self.restore_partition_selection_list.get_iter(path)
        new_state = not self.restore_partition_selection_list.get(iter, 1)[0]
        self.backup_image.toggle_restore_of_row(iter, new_state)

    def destination_partition_node_changed(self, cell_renderer_combo, path,
                                           cell_render_combo_iter):
        # Retrieve the selected string from the CellRendererCombo combo widget.
        cell_render_model = cell_renderer_combo.get_property("model")
        key = cell_render_model.get_value(cell_render_combo_iter, 0)
        enduser_friendly_string = cell_render_model.get_value(
            cell_render_combo_iter, 1)
        self.backup_image.change_combo_box(path, key, enduser_friendly_string)

    def overwrite_partition_table_toggle(self, toggle_button):
        self.backup_image.overwrite_partition_table_toggle(
            toggle_button.get_active())

    def show_hidden_devices_toggle(self, toggle_button):
        new_state = toggle_button.get_active()
        # Ensure all the similar toggle buttons in the application are consistent.
        # FIXME: Not ideal from an abstraction perspective
        self.builder.get_object("backup_step1_show_hidden_devices").set_active(
            new_state)
        self.builder.get_object("backup_step3_show_hidden_devices").set_active(
            new_state)
        self.builder.get_object(
            "restore_step1_show_hidden_devices").set_active(new_state)
        self.builder.get_object(
            "restore_step3_show_hidden_devices").set_active(new_state)
        self.drive_query.set_show_hidden_information(new_state)
        # Refresh the tables.
        # FIXME: Not ideal from an abstraction perspective
        if self.selected_drive_key is not None:
            self.drive_query.populate_partition_selection_table(
                self.selected_drive_key)
            self.drive_query.populate_mount_partition_table(
                ignore_drive_key=self.selected_drive_key)
        else:
            self.drive_query.populate_drive_selection_table()

    def open_url_as_non_root(self, button):
        Utility.open_url_as_non_root("ubuntu", button.get_uri())
        return

    def backup_name_changed(self):
        return

    def select_backup_folder(self, button):
        backup_folder_label = self.builder.get_object("backup_folder_label")
        folder_selection_popup = FolderSelectionPopup(self.builder,
                                                      self.selected_folder,
                                                      MOUNT_DIR, False)
        return

    def select_restore_folder(self, button):
        restore_folder_label = self.builder.get_object("restore_folder_label")
        folder_selection_popup = FolderSelectionPopup(self.builder,
                                                      self.selected_folder,
                                                      MOUNT_DIR, True)
        return

    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)

    def backup_scan_network(self):
        return

    def backup_dest_network_changed(self, toggle_button):
        return

    def backup_dest_changed(self, toggle_button):
        return

    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)

    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)

    def find_network_share(self, button):
        # FIXME: Overhaul network share handling.
        error = ErrorMessageModalPopup(
            self.builder,
            "Search network function is disabled and will be re-introduced in the next version.\n\nPlease enter the network details manually."
        )
Esempio n. 6
0
import sys
from backup_manager import BackupManager

if __name__ == "__main__":

    if len(sys.argv) > 1:
        bm = BackupManager(sys.argv[1])
    else:
        argv1 = input("Введите название проекта: ")
        bm = BackupManager(argv1)
    bm.backup()
Esempio n. 7
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--action",
        choices=['sync_local', 'sync_remote', 'map_fs', 'cleanup'],
        dest='action',
        required=True,
        help=
        'choose action, sync_local: sync from local to remote, sync_remote: sync from remote to'
        ' local, map_fs: map objects to database, cleanup: reduce databases and clean up'
        ' unreferenced objects')
    parser.add_argument("--thread",
                        help='threads for parallel adb pull/push/stat',
                        type=int,
                        default=8,
                        dest='thread_count')
    parser.add_argument('base_path',
                        help='path where the backup files stores in the fs',
                        type=str)
    parser.add_argument('db_path',
                        help='path in the database system',
                        type=str,
                        nargs='?')
    parser.add_argument(
        'fs_or_remote_path',
        help='remote path when syncing or fs path when mapping',
        type=str,
        nargs='?')
    args = parser.parse_args()
    # print(args)
    manager = BackupManager(args.base_path, args.thread_count)
    if args.action == 'sync_local':
        assert args.fs_or_remote_path is not None, 'Missing required field: fs_or_remote_path'
        assert args.db_path is not None, 'Missing required field: db_path'
        manager.sync_local(args.fs_or_remote_path, args.db_path)
    elif args.action == 'sync_remote':
        assert args.fs_or_remote_path is not None, 'Missing required field: fs_or_remote_path'
        assert args.db_path is not None, 'Missing required field: db_path'
        manager.sync_remote(args.fs_or_remote_path, args.db_path)
    elif args.action == 'map_fs':
        assert args.fs_or_remote_path is not None, 'Missing required field: fs_or_remote_path'
        assert args.db_path is not None, 'Missing required field: db_path'
        manager.map_database_to_fs(args.db_path, args.fs_or_remote_path)
    elif args.action == 'cleanup':
        manager.compress_database()
        manager.cleanup_objects()
    else:
        print("Don't know what to do for action", args.action)
        exit(1)
Esempio n. 8
0
class BackupManagerTestScheduler(unittest.TestCase):
    def setUp(self):
        self.soon = 0
        self.later = 0
        self.clock = task.Clock()
        self.myBackup = BackupManager(self.clock,
                                      soonDuration=3,
                                      laterDuration=5,
                                      soonCommand=self.soonBackup,
                                      laterCommand=self.laterBackup)

    def soonBackup(self):
        self.soon += 1

    def laterBackup(self):
        self.later += 1

    def _testSoon(self):
        self.myBackup.scheduleBackup()
        self.clock.advance(3)

    def _testLater(self):
        self.myBackup.scheduleBackup()
        self.clock.advance(1)
        self.myBackup.scheduleBackup()
        self.clock.advance(1)
        self.myBackup.scheduleBackup()
        self.clock.advance(3)

    def testOnlySoon(self):
        self._testSoon()
        self.assertEqual(self.soon, 1)
        self.assertEqual(self.later, 0)

    def testOnlyLater(self):
        self._testLater()
        self.assertEqual(self.soon, 0)
        self.assertEqual(self.later, 1)

    def testSoonAndLater(self):
        self._testSoon()
        self._testLater()
        self.assertEqual(self.soon, 1)
        self.assertEqual(self.later, 1)

    def test2Soon(self):
        self._testSoon()
        self._testSoon()
        self.assertEqual(self.soon, 2)
        self.assertEqual(self.later, 0)

    def test2Later(self):
        self._testLater()
        self._testLater()
        self.assertEqual(self.soon, 0)
        self.assertEqual(self.later, 2)

    def test2Later1Soon(self):
        self._testLater()
        self._testLater()
        self._testSoon()
        self.assertEqual(self.soon, 1)
        self.assertEqual(self.later, 2)

    def test2Later2Soon(self):
        self._testLater()
        self._testLater()
        self._testSoon()
        self._testSoon()
        self.assertEqual(self.soon, 2)
        self.assertEqual(self.later, 2)
Esempio n. 9
0
import sys
from backup_manager import BackupManager

if __name__ == "__main__":
    try:
        if (len(sys.argv) == 2):
            project_name = sys.argv[1]

            backup_manager = BackupManager()
            backup_manager.copy(project_name)
        else:
            project_name = input("Введите название проекта: ")

            backup_manager = BackupManager()
            backup_manager.copy(project_name)
    except Exception as err:
        print("Во время работы программы произошла ошибка! - {}".format(err))
Esempio n. 10
0
def AI_loop(screen: pygame.Surface, circuit: dict) -> Network:
    """
    Boucle principale pour le mode automatique du programme

    Le but ici est d'entraîner des IA pour qu'elles soient le plus performant possible sur le
    circuit, donc en trouver au moins une qui arrive à la fin du circuit sans toucher aucune
    bordure.

    Parameters
    ----------
    screen:
        La fenêtre du programme
    circuit:
        Un dictionnaire contenant la liste des bordures représentant le circuit, ainsi que les deux
        points définissant la ligne de départ

    Returns
    -------
    Network:
        Le meilleur réseau de la dernière génération complétée
    """
    print("Astuce : Appuyez sur la touche R si une voiture tourne en rond\n")
    clock = pygame.time.Clock()
    small_font = pygame.font.SysFont('Arial', ceil(18 * SETTINGS.scale_avg))
    title_font = pygame.font.SysFont('Arial', ceil(30 * SETTINGS.scale_avg))
    dt = 1
    init_pos, init_angle = calc_starting_pos(circuit["point1"],
                                             circuit["point2"])
    cars = [
        Car(circuit["bordures"],
            color=SETTINGS.colors["cars"],
            starting_pos=init_pos,
            abs_rotation=init_angle) for _ in range(SETTINGS.cars_number)
    ]
    networks = [Network(c) for c in cars]
    networks[0].from_json(BackupManager().load()["network"])
    networks[0].car.color = "#00FF00"
    running = True

    increment = 0
    last_sorted_networks = None
    on_pause = False

    while running:
        increment += 1
        endgen = False
        cleanup_done = False
        start_time = time.time()
        while not endgen:

            temp = check_events()
            if temp == 1:
                endgen = True
            if temp == 2:
                return last_sorted_networks[
                    0] if last_sorted_networks is not None else None
            if temp == 3:
                on_pause = not on_pause

            screen.fill(SETTINGS.colors["background"])
            draw.circuit(screen, circuit["bordures"])
            draw.car(screen, (net.car for net in networks))

            delta = dt * FPS / 1000
            if not on_pause:
                # Gestion du mouvement de la voiture
                for net in networks:
                    if not net.dead:
                        net.update()
                        net.car.abs_rotation += SETTINGS.car_maniability * delta * net.direction

                        net.car.apply_vector(net.car.direction_vector() *
                                             net.engine * 2 *
                                             SETTINGS.scale_avg)
                        if not net.car.detection(screen,
                                                 SETTINGS.display_rays):
                            net.dead = True
                            net.car.death_time = time.time()

                survived = sum(1 for n in networks if not n.dead)
                if survived == 0:
                    endgen = True
                elif time.time() - start_time > 10 and not cleanup_done:
                    for net in networks:
                        if (not net.dead) and net.car.position[0] < 150:
                            net.dead = True
                            net.car.death_time = time.time()

            draw.general_stats(screen, small_font, clock, increment, survived,
                               start_time)
            draw.car_specs(screen, small_font, networks[0])
            draw.car_network(screen, small_font, networks[0])
            if on_pause:
                draw.pause_screen(screen, title_font)
                elapsed = dt / 1000
                start_time += elapsed
                for net in networks:
                    if not net.dead:
                        net.car.start_time += elapsed
            pygame.display.flip()
            dt = clock.tick(FPS)

        arrival = circuit["bordures"][-1]  # ligne d'arrivée
        # calcul des scores
        for net in networks:
            net.score = net.car.get_score()
            if net.car.distance_to_segment(arrival) <= 8:
                net.score += 300  # points bonus si la voiture a atteint la ligne d'arrivée
        average = round(sum([net.score for net in networks]) / len(networks))
        print(f"Génération N°{increment} terminée - score moyen : {average}")
        last_sorted_networks = copy.deepcopy(networks)

        # Darwin
        networks = darwin(networks)

        # Reset des réseaux/voitures
        for net in networks:
            net.dead = 0
            # net.car.position = [80, 130]
            net.car.color = SETTINGS.colors["cars"]
            net.car.reset()
        networks[0].car.color = SETTINGS.colors["main_car"]