Exemple #1
0
    def get_schedule_command(self, profile, type):
        # Configures the backup and log target paths
        log_path = profile.backup_directory
        filename = "\$BACKUP_NAME"
        
        if type == "incremental":
            filename = "inc/\$BACKUP_NAME"
            log_path = joinpath(log_path, 'inc')
            
        log_path = joinpath(log_path, "\$BACKUP_NAME.log 2>&1")
            
        # Creates the mysqlbackup command call
        command = self.create_backup_command_call(profile, type, to_schedule=True, filename=filename)
        
        # Chooses the proper scheduling data and creates the schedule command
        schedule_data = profile.full_backups if type == 'full' else profile.inc_backups

        schedule = []
        schedule.append(str(schedule_data.minute))
        schedule.append('*' if schedule_data.frequency == Frequency.hourly else str(schedule_data.hour))
        schedule.append('*' if schedule_data.frequency in [Frequency.hourly,Frequency.daily,Frequency.weekly] else str(schedule_data.month_day))
        schedule.append('*')
        schedule.append('*' if schedule_data.frequency != Frequency.weekly else str(schedule_data.week_day))
        schedule.append("BACKUP_NAME=\$(date +\%Y-\%m-\%d_\%H-\%M-\%S); " + command)

        schedule.append("> " + log_path)

        # A temporary file to store the crontab
        cron_file = "%s/wb_cron_file" % profile.backup_directory

        cron_entry = " ".join(schedule)
        schedule_command = 'crontab -l > %s; echo "%s" >> %s; crontab %s; rm %s' % (cron_file, cron_entry, cron_file, cron_file, cron_file)
        
        return schedule_command
Exemple #2
0
    def create_backup_command_call(self, profile, type, to_schedule, filename=None):
        cmd_data = []
        if ' ' in self._context.config.backup_command:
            cmd_data.append('"%s"' % self._context.config.backup_command)
        else:
            cmd_data.append('%s' % self._context.config.backup_command)

        # Uses the configuration file for the backup (MUST be the 1st option)
        cmd_data.append('--defaults-file=%s' % profile.defaults_file)

        # If a filename is explicitly requested, then use it
        if filename:
            if type == 'incremental':
                #cmd_data.append('--backup-dir=%s' % joinpath(profile.backup_directory, filename))
                cmd_data.append('--incremental-backup-dir=%s' % joinpath(profile.backup_directory, filename))
            else:
                cmd_data.append('--backup-dir=%s' % joinpath(profile.backup_directory, filename))

        # Passes the mutually excluyent parameters
        if type == 'full':
            # The compress option is set only for full backups when apply-log is not
            # enabled, this is because --compress will be ignored anyway
            if profile.compress and not profile.apply_log:
                cmd_data.append('--compress')

        elif type == 'incremental':
            cmd_data.append('--incremental')

        # apply-log is only used on full backups when enabled
        if profile.apply_log and type == 'full':
            cmd_data.append('backup-and-apply-log')
        else:
            cmd_data.append('backup')

        return " ".join(cmd_data)
    def save_changes(self):
        if self.validate():
            path = self._dest_directory.get_string_value()
            if not self._context.ctrl_be.server_helper.file_exists(path):
                r = mforms.Utilities.show_warning("Save Backup Profile", "Target backup directory '%s' does not exist, would you like to create it?" % path, "Create", "Cancel", "")
                if r == mforms.ResultOk:
                    self._context.server_interface.create_directory(path)
                else:
                    return

            self.flush_data()
            
            # The next operations ONLY apply if anything changed on the profile
            if self._profile.has_changed:
                self._profile.save()
            
                path = joinpath(path, "inc")
                if not self._context.ctrl_be.server_helper.file_exists(path):
                    self._context.server_interface.create_directory(path)
            
                # Reschedules the backup with the new information
                self._context.server_interface.unschedule_backup(self._profile)
                self._context.server_interface.schedule_backup(self._profile)
                
                if self.profile_saved_callback is not None:
                    self.profile_saved_callback(self._profile)
                
            self._owner.hide_editor()
Exemple #4
0
    def restore_backup(self, backup_entry, output_handler=None):
        # create a defaults file containing the cnf data saved by mysqlbackup in backup-my.cnf and
        # the last known correct datadir
        import uuid
        restore_defaults_file = joinpath(self._context.config.backup_home, str(uuid.uuid1())+"-restore.cnf")
        data = self.get_file_content(joinpath(backup_entry.data_path, "backup-my.cnf"))
        data += "datadir = %s\n" % self._context.config.datadir
        self.perform_as_user(self._context.mysql_user, lambda as_user, user_password: self._context.ctrl_be.server_helper.set_file_content(restore_defaults_file, data, as_user, user_password))

        try:
            command = self.create_restore_command_call(backup_entry.data_path, restore_defaults_file, backup_entry.profile.defaults_file)
            result = self._context.ctrl_be.server_helper.execute_command(command, as_user=self._context.mysql_user, user_password=self._context.ctrl_be.password_handler.get_password_for("file"), output_handler=output_handler)
        finally:
            try:
                self.perform_as_user(self._context.mysql_user, lambda as_user, user_password: self._context.ctrl_be.server_helper.delete_file(restore_defaults_file, as_user, user_password))
            except Exception, e:
                if output_handler:
                    output_handler("Could not delete temporary defaults file %s: %s\n" % (restore_defaults_file, e))
Exemple #5
0
 def on_change(self):
     if self.dlg_type == OpenDirectory:
         self.selection = self.curdir.get_string_value()
     else:
         selid = self.flist.get_selected_node()
         if selid:
             fname = selid.get_string(0)
             self.selection = joinpath(self.curdir.get_string_value(),
                                       fname)
Exemple #6
0
    def create_backup_command_call(self, profile, type, to_schedule, filename=None):
        # If the command is not to be scheduled it will return the direct call to
        # the mysqlbackup command
        if not to_schedule:
            return super(WBBackupWindowsInterface, self).create_backup_command_call(profile, type, to_schedule, filename)

        cmd_data = []

        script_name = joinpath(parentdir(self._context.server_profile.config_file_path), "mysqlwbbackup.vbs")

        cmd_data.append('\\"%s\\"' % script_name)

        # Uses the configuration file for the backup (MUST be the 1st option)
        cmd_data.append('%s.cnf' % profile._uuid)

        # Creates the values for compress and incremental
        compress_incremental = "0 0"
        if type == 'full':
            # The compress option is set only for full backups when apply-log is not
            # enabled, this is because --compress will be ignored anyway
            if profile.compress and not profile.apply_log:
                # 1 to indicate compress, 0 to indicate NOT incremental
                compress_incremental = '1 0'

        elif type == 'incremental':
            compress_incremental = "0 1"

        cmd_data.append(compress_incremental)

        # apply-log is only used on full backups when enabled
        if profile.apply_log and type == 'full':
            cmd_data.append('backup-and-apply-log')
        else:
            cmd_data.append('backup')

        # If a filename is explicitly requested, then use it
        if filename:
            cmd_data.append(filename)

        return " ".join(cmd_data)
Exemple #7
0
 def _mark_incremental_applied(self, incremental_path):
     # if mysqlbackup some day adds this internally, this should be changed to only do it for older versions
     self.perform_as_user(self._context.mysql_user, lambda as_user, user_password: self._context.ctrl_be.server_helper.set_file_content(joinpath(incremental_path, "applied.txt"), "", as_user, user_password))
Exemple #8
0
    def chdir(self, fname, is_full_path):
        #         import traceback
        #         traceback.print_stack()

        success = False
        if fname is not None and fname != "":
            log_debug("Directory changed: " + fname + " was full path: " +
                      str(is_full_path) + "\n")
            path = fname if is_full_path else joinpath(
                self.curdir.get_string_value(), fname)

            (success, target_is_file) = self.try_cd(path)

            # The change failed... but still could be a valid
            if not success:
                done = target_is_file

                # If the failure is because an attempt to cd to a file was done
                if target_is_file:
                    # If saving a file, we need to confirm the user wants to override the existing file
                    if self.dlg_type == SaveFile:
                        if mforms.Utilities.show_warning(
                                'File Already Exist',
                                "The file %s already exists.\n Do you want to replace it?"
                                % path, "Yes", "No", "") != mforms.ResultOk:
                            done = False

                # When saving a file, an invalid path could mean a new file, we need to
                # check if the parent folder exists and if so... then we are done!
                elif self.dlg_type == SaveFile:
                    (done, target_is_file) = self.try_cd(parentdir(path))

                    if not done:
                        mforms.Utilities.show_warning(
                            'Invalid Path',
                            "The path to %s is invalid." % path, "Ok", "", "")

                # Done will be true when:
                # - OpenFile on a file path
                # - SaveFile on an existing path and user indicated to override
                # - SaveFile on an unexisting path with a valid directory
                if done:
                    self.selection = path
                    self.form.close()
                    return
        else:
            log_debug("Directory not changed\n")

        # Updates the file list only in case a cd has been done
        if success or fname is None:
            curdir = self.cwd()
            log_debug("chdir: Current dir is: " + curdir + "\n")
            #if curdir:
            #    if curdir[-1] != "/":
            #        curdir += "/"
            self.update_text(curdir)
            self._invalid_text = False

            self.flist.clear()

            (disr, files) = ((), ())
            entries = self.ls(curdir)
            dirs = [
                d['name'] for d in entries
                if d['isDir'] == 1 and d['name'] != ".." and d['name'] != "."
            ]
            files = [
                f['name'] for f in entries
                if f['isDir'] == 0 and f['name'] != ".." and f['name'] != "."
            ]
            dirs.sort()
            files.sort()

            row_id = self.flist.add_node()
            row_id.set_icon_path(0, 'folder')
            row_id.set_string(0, '..')

            for d in dirs:
                row_id = self.flist.add_node()
                row_id.set_icon_path(0, 'folder')
                row_id.set_string(0, d)

            for f in files:
                row_id = self.flist.add_node()
                row_id.set_string(0, f)