func doBackupRestore(c *cli.Context) error { var err error backupURL, err := util.GetFlag(c, "", true, err) if err != nil { return err } backupURL = util.UnescapeURL(backupURL) toFile, err := util.GetFlag(c, "to", true, err) if err != nil { return err } if err := objectstore.RestoreDeltaBlockBackup(backupURL, toFile); err != nil { return err } if err := createNewSnapshotMetafile(toFile + ".meta"); err != nil { return err } return nil }
func (d *Driver) CreateVolume(id string, opts map[string]string) error { var ( size int64 err error ) backupURL := opts[convoydriver.OPT_BACKUP_URL] if backupURL != "" { objVolume, err := objectstore.LoadVolume(backupURL) if err != nil { return err } if objVolume.Driver != d.Name() { return fmt.Errorf("Cannot restore backup of %v to %v", objVolume.Driver, d.Name()) } size, err = d.getSize(opts, objVolume.Size) if err != nil { return err } if size != objVolume.Size { return fmt.Errorf("Volume size must match with backup's size") } } else { size, err = d.getSize(opts, d.DefaultVolumeSize) if err != nil { return err } } if size%(d.ThinpoolBlockSize*SECTOR_SIZE) != 0 { return fmt.Errorf("Size must be multiple of block size") } volume := d.blankVolume(id) exists, err := util.ObjectExists(volume) if err != nil { return err } if exists { return generateError(logrus.Fields{ LOG_FIELD_VOLUME: id, }, "Already has volume with specific uuid") } devID, err := d.allocateDevID() if err != nil { return err } log.WithFields(logrus.Fields{ LOG_FIELD_REASON: LOG_REASON_START, LOG_FIELD_EVENT: LOG_EVENT_CREATE, LOG_FIELD_OBJECT: LOG_OBJECT_VOLUME, LOG_FIELD_VOLUME: id, DM_LOG_FIELD_VOLUME_DEVID: devID, }).Debugf("Creating volume") err = devicemapper.CreateDevice(d.ThinpoolDevice, devID) if err != nil { return err } log.WithFields(logrus.Fields{ LOG_FIELD_REASON: LOG_REASON_START, LOG_FIELD_EVENT: LOG_EVENT_ACTIVATE, LOG_FIELD_OBJECT: LOG_OBJECT_VOLUME, LOG_FIELD_VOLUME: id, DM_LOG_FIELD_VOLUME_DEVID: devID, }).Debugf("Activating device for volume") err = devicemapper.ActivateDevice(d.ThinpoolDevice, id, devID, uint64(size)) if err != nil { log.WithFields(logrus.Fields{ LOG_FIELD_REASON: LOG_REASON_ROLLBACK, LOG_FIELD_EVENT: LOG_EVENT_REMOVE, LOG_FIELD_OBJECT: LOG_OBJECT_VOLUME, LOG_FIELD_VOLUME: id, DM_LOG_FIELD_VOLUME_DEVID: devID, }).Debugf("Removing device for volume due to fail to activate") if err := devicemapper.DeleteDevice(d.ThinpoolDevice, devID); err != nil { log.WithFields(logrus.Fields{ LOG_FIELD_REASON: LOG_REASON_FAILURE, LOG_FIELD_EVENT: LOG_EVENT_REMOVE, LOG_FIELD_OBJECT: LOG_OBJECT_VOLUME, LOG_FIELD_VOLUME: id, DM_LOG_FIELD_VOLUME_DEVID: devID, }).Debugf("Failed to remove device") } return err } volume.DevID = devID volume.Size = size volume.Snapshots = make(map[string]Snapshot) if err := util.ObjectSave(volume); err != nil { return err } dev, err := d.GetVolumeDevice(id) if err != nil { return err } if backupURL == "" { // format the device if _, err := util.Execute("mkfs", []string{"-t", "ext4", dev}); err != nil { return err } } else { if err := objectstore.RestoreDeltaBlockBackup(backupURL, dev); err != nil { return err } } return nil }