github.com/yasker/longhorn-engine@v0.0.0-20160621014712-6ed6cfca0729/sync/backup.go (about)

     1  package sync
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/Sirupsen/logrus"
     7  	"github.com/rancher/longhorn/controller/rest"
     8  	"github.com/rancher/longhorn/replica"
     9  	replicaClient "github.com/rancher/longhorn/replica/client"
    10  	"github.com/rancher/longhorn/util"
    11  )
    12  
    13  func (t *Task) CreateBackup(snapshot, dest string) (string, error) {
    14  	var replica *rest.Replica
    15  
    16  	volume, err := t.client.GetVolume()
    17  	if err != nil {
    18  		return "", err
    19  	}
    20  
    21  	replicas, err := t.client.ListReplicas()
    22  	if err != nil {
    23  		return "", err
    24  	}
    25  
    26  	for _, r := range replicas {
    27  		if r.Mode == "RW" {
    28  			replica = &r
    29  			break
    30  		}
    31  	}
    32  
    33  	if replica == nil {
    34  		return "", fmt.Errorf("Cannot find a suitable replica for backup")
    35  	}
    36  
    37  	backup, err := t.createBackup(replica, snapshot, dest, volume.Name)
    38  	if err != nil {
    39  		return "", err
    40  	}
    41  	return backup, nil
    42  }
    43  
    44  func (t *Task) createBackup(replicaInController *rest.Replica, snapshot, dest, volumeName string) (string, error) {
    45  	if replicaInController.Mode != "RW" {
    46  		return "", fmt.Errorf("Can only create backup from replica in mode RW, got %s", replicaInController.Mode)
    47  	}
    48  
    49  	repClient, err := replicaClient.NewReplicaClient(replicaInController.Address)
    50  	if err != nil {
    51  		return "", err
    52  	}
    53  
    54  	replica, err := repClient.GetReplica()
    55  	if err != nil {
    56  		return "", err
    57  	}
    58  
    59  	snapshotName, index := getNameAndIndex(replica.Chain, snapshot)
    60  	switch {
    61  	case index < 0:
    62  		return "", fmt.Errorf("Snapshot %s not found on replica %s", snapshot, replicaInController.Address)
    63  	case index == 0:
    64  		return "", fmt.Errorf("Can not backup the head disk in the chain")
    65  	}
    66  
    67  	logrus.Infof("Backing up %s on %s, to %s", snapshotName, replicaInController.Address, dest)
    68  
    69  	backup, err := repClient.CreateBackup(snapshotName, dest, volumeName)
    70  	if err != nil {
    71  		logrus.Errorf("Failed backing up %s on %s to %s", snapshotName, replicaInController.Address, dest)
    72  		return "", err
    73  	}
    74  	return backup, nil
    75  }
    76  
    77  func (t *Task) RmBackup(backup string) error {
    78  	var replica *rest.Replica
    79  
    80  	replicas, err := t.client.ListReplicas()
    81  	if err != nil {
    82  		return err
    83  	}
    84  
    85  	for _, r := range replicas {
    86  		if r.Mode == "RW" {
    87  			replica = &r
    88  			break
    89  		}
    90  	}
    91  
    92  	if replica == nil {
    93  		return fmt.Errorf("Cannot find a suitable replica for remove backup")
    94  	}
    95  
    96  	if err := t.rmBackup(replica, backup); err != nil {
    97  		return err
    98  	}
    99  	return nil
   100  }
   101  
   102  func (t *Task) rmBackup(replicaInController *rest.Replica, backup string) error {
   103  	if replicaInController.Mode != "RW" {
   104  		return fmt.Errorf("Can only remove backup from replica in mode RW, got %s", replicaInController.Mode)
   105  	}
   106  
   107  	repClient, err := replicaClient.NewReplicaClient(replicaInController.Address)
   108  	if err != nil {
   109  		return err
   110  	}
   111  
   112  	logrus.Infof("Removing backup %s on %s", backup, replicaInController.Address)
   113  
   114  	if err := repClient.RmBackup(backup); err != nil {
   115  		logrus.Errorf("Failed removing backup %s on %s", backup, replicaInController.Address)
   116  		return err
   117  	}
   118  	return nil
   119  }
   120  
   121  func (t *Task) RestoreBackup(backup string) error {
   122  	replicas, err := t.client.ListReplicas()
   123  	if err != nil {
   124  		return err
   125  	}
   126  
   127  	for _, r := range replicas {
   128  		if ok, err := t.isRebuilding(&r); err != nil {
   129  			return err
   130  		} else if ok {
   131  			return fmt.Errorf("Can not restore from backup because %s is rebuilding", r.Address)
   132  		}
   133  	}
   134  
   135  	// generate new snapshot and metafile as base for new volume
   136  	snapshotID := util.UUID()
   137  	snapshotFile := replica.GenerateSnapshotDiskName(snapshotID)
   138  	for _, replica := range replicas {
   139  		if err := t.restoreBackup(&replica, backup, snapshotFile); err != nil {
   140  			return err
   141  		}
   142  	}
   143  
   144  	// call to controller to revert to sfile
   145  	if err := t.client.RevertSnapshot(snapshotID); err != nil {
   146  		return fmt.Errorf("Fail to revert to snapshot %v", snapshotID)
   147  	}
   148  	return nil
   149  }
   150  
   151  func (t *Task) restoreBackup(replicaInController *rest.Replica, backup string, snapshotFile string) error {
   152  	if replicaInController.Mode != "RW" {
   153  		return fmt.Errorf("Can only restore backup from replica in mode RW, got %s", replicaInController.Mode)
   154  	}
   155  
   156  	repClient, err := replicaClient.NewReplicaClient(replicaInController.Address)
   157  	if err != nil {
   158  		return err
   159  	}
   160  
   161  	logrus.Infof("Restoring backup %s on %s", backup, replicaInController.Address)
   162  
   163  	if err := repClient.RestoreBackup(backup, snapshotFile); err != nil {
   164  		logrus.Errorf("Failed restoring backup %s on %s", backup, replicaInController.Address)
   165  		return err
   166  	}
   167  	return nil
   168  }
   169  
   170  func (t *Task) InspectBackup(backup string) (string, error) {
   171  	var replica *rest.Replica
   172  
   173  	replicas, err := t.client.ListReplicas()
   174  	if err != nil {
   175  		return "", err
   176  	}
   177  
   178  	for _, r := range replicas {
   179  		if r.Mode == "RW" {
   180  			replica = &r
   181  			break
   182  		}
   183  	}
   184  
   185  	if replica == nil {
   186  		return "", fmt.Errorf("Cannot find a suitable replica for inspect backup")
   187  	}
   188  
   189  	result, err := t.inspectBackup(replica, backup)
   190  	if err != nil {
   191  		return "", err
   192  	}
   193  	return result, nil
   194  }
   195  
   196  func (t *Task) inspectBackup(replicaInController *rest.Replica, backup string) (string, error) {
   197  	if replicaInController.Mode != "RW" {
   198  		return "", fmt.Errorf("Can only inspect backup from replica in mode RW, got %s", replicaInController.Mode)
   199  	}
   200  
   201  	repClient, err := replicaClient.NewReplicaClient(replicaInController.Address)
   202  	if err != nil {
   203  		return "", err
   204  	}
   205  
   206  	result, err := repClient.InspectBackup(backup)
   207  	if err != nil {
   208  		logrus.Errorf("Failed inspect backup %s on %s", backup, replicaInController.Address)
   209  		return "", err
   210  	}
   211  	return result, nil
   212  }