Esempio n. 1
0
// RemoveBackup removes the given backup.
func (a *App) RemoveBackup(timestamp string) error {
	// Create the backup directory path.
	path := a.BackupDirectoryPath() + "/" + timestamp

	// Check if the backup exists.
	if !btrfs.IsSubvolume(path) {
		return fmt.Errorf("no backup '%s' found!", timestamp)
	}

	log.Infof("Removing backup '%s' of app '%s'.", timestamp, a.name)

	// Remove the backup subvolume.
	err := btrfs.DeleteSubvolume(path)
	if err != nil {
		return fmt.Errorf("failed to delete backup subvolume '%s': %v", timestamp, err)
	}

	return nil
}
Esempio n. 2
0
// loadApp loads the app with the given name from the apps directory.
func loadApp(name string) (*App, error) {
	// Create a new app value.
	a, err := newApp(name)
	if err != nil {
		return nil, err
	}

	// The app directory has to be a btrfs subvolume.
	if !btrfs.IsSubvolume(a.path) {
		return nil, fmt.Errorf("the app's directory '%s' is not a btrfs subvolume!", a.path)
	}

	// Load the app settings.
	err = a.loadSettings()
	if err != nil {
		return nil, err
	}

	return a, nil
}
Esempio n. 3
0
// RestoreBackup restores the given app backup.
func (a *App) RestoreBackup(timestamp string) (err error) {
	// Lock the task mutex.
	// The app should not be started during a backup process.
	a.taskMutex.Lock()
	defer a.taskMutex.Unlock()

	// Abort if any app ask is running.
	if a.IsTaskRunning() {
		return fmt.Errorf("the app is running!")
	}

	// Create the backup directory path.
	backupPath := a.BackupDirectoryPath() + "/" + timestamp

	// Check if the backup exists.
	if !btrfs.IsSubvolume(backupPath) {
		return fmt.Errorf("no backup '%s' found!", timestamp)
	}

	// Create the apps backup path for the current data.
	newAppBackupPath := a.BackupDirectoryPath() + "/" + strconv.FormatInt(time.Now().Unix(), 10)

	// Log
	log.Infof("restoring backup of app '%s': %s", a.name, timestamp)

	// Reload the turtlefile and settings on defer.
	defer func() {
		err = a.reload()
	}()

	// Move the current subvolume to the backup location with the current timestamp.
	err = os.Rename(a.path, newAppBackupPath)
	if err != nil {
		return fmt.Errorf("failed to move apps current subvolume: %v", err)
	}

	// Restore the current backup subvolume on failure.
	defer func() {
		if err != nil {
			errR := os.Rename(newAppBackupPath, a.path)
			if errR != nil {
				log.Errorf("failed to restore apps current subvolume backup: %v", errR)
			} else {
				// Remove the readonly flag again.
				errR = btrfs.SetSubvolumeReadonly(a.path, false)
				if errR != nil {
					log.Errorf("failed to restore apps subvolume flag: %v", errR)
				}
			}
		}
	}()

	// Set the readonly flag on the moved subvolume.
	err = btrfs.SetSubvolumeReadonly(newAppBackupPath, true)
	if err != nil {
		return err
	}

	// Create a snapshot of the backup and restore it to the app path.
	err = btrfs.Snapshot(backupPath, a.path, false)
	if err != nil {
		return fmt.Errorf("failed to restore app '%s': %v", a.name, err)
	}

	return nil
}