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 }