func (d *Driver) CreateVolume(id string, opts map[string]string) error { d.mutex.Lock() defer d.mutex.Unlock() 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()) } } volumeName := opts[convoydriver.OPT_VOLUME_NAME] if volumeName == "" { volumeName = "volume-" + id[:8] } volume := d.blankVolume(id) exists, err := util.ObjectExists(volume) if err != nil { return err } if exists { return fmt.Errorf("volume %v already exists", id) } volume.PrepareForVM, err = strconv.ParseBool(opts[convoydriver.OPT_PREPARE_FOR_VM]) if err != nil { return err } if volume.PrepareForVM { volume.Size, err = d.getSize(opts, d.DefaultVolumeSize) if err != nil { return err } } volumePath := filepath.Join(d.Path, volumeName) if err := util.MkdirIfNotExists(volumePath); err != nil { return err } volume.Path = volumePath volume.Snapshots = make(map[string]Snapshot) if backupURL != "" { file, err := objectstore.RestoreSingleFileBackup(backupURL, volumePath) if err != nil { return err } // file would be removed after this because it's under volumePath if err := util.DecompressDir(file, volumePath); err != nil { return err } } return util.ObjectSave(volume) }
func (d *Driver) GetBackupInfo(backupURL string) (map[string]string, error) { objVolume, err := objectstore.LoadVolume(backupURL) if err != nil { return nil, err } if objVolume.Driver != d.Name() { return nil, fmt.Errorf("BUG: Wrong driver handling DeleteBackup(), driver should be %v but is %v", objVolume.Driver, d.Name()) } return objectstore.GetBackupInfo(backupURL) }
func (d *Driver) DeleteBackup(backupURL string) error { objVolume, err := objectstore.LoadVolume(backupURL) if err != nil { return err } if objVolume.Driver != d.Name() { return fmt.Errorf("BUG: Wrong driver handling DeleteBackup(), driver should be %v but is %v", objVolume.Driver, d.Name()) } return objectstore.DeleteSingleFileBackup(backupURL) }
func (s *daemon) getBackupOpsForBackup(requestURL string) (convoydriver.BackupOperations, error) { objVolume, err := objectstore.LoadVolume(requestURL) if err != nil { return nil, err } driver := s.ConvoyDrivers[objVolume.Driver] if driver == nil { return nil, fmt.Errorf("Cannot find driver %v for restoring", objVolume.Driver) } return driver.BackupOps() }
func (d *Driver) DeleteBackup(backupURL string) error { d.mutex.Lock() defer d.mutex.Unlock() objVolume, err := objectstore.LoadVolume(backupURL) if err != nil { return err } if objVolume.Driver != d.Name() { return fmt.Errorf("BUG: Wrong driver handling DeleteBackup(), driver should be %v but is %v", objVolume.Driver, d.Name()) } return objectstore.DeleteDeltaBlockBackup(backupURL) }
func (s *daemon) getBackupOpsForBackup(requestURL string) (convoydriver.BackupOperations, error) { driverName := "" if _, err := objectstore.GetObjectStoreDriver(requestURL); err == nil { // Known objectstore driver objVolume, err := objectstore.LoadVolume(requestURL) if err != nil { return nil, err } driverName = objVolume.Driver } else { // Try Convoy driver u, err := url.Parse(requestURL) if err != nil { return nil, err } driverName = u.Scheme } driver := s.ConvoyDrivers[driverName] if driver == nil { return nil, fmt.Errorf("Cannot find driver %v for restoring", driverName) } return driver.BackupOps() }
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 }