func (s *daemon) doBackupDelete(version string, w http.ResponseWriter, r *http.Request, objs map[string]string) error { s.GlobalLock.Lock() defer s.GlobalLock.Unlock() request := &api.BackupDeleteRequest{} if err := decodeRequest(r, request); err != nil { return err } request.URL = util.UnescapeURL(request.URL) backupOps, err := s.getBackupOpsForBackup(request.URL) if err != nil { return err } log.WithFields(logrus.Fields{ LOG_FIELD_REASON: LOG_REASON_PREPARE, LOG_FIELD_EVENT: LOG_EVENT_REMOVE, LOG_FIELD_OBJECT: LOG_OBJECT_SNAPSHOT, LOG_FIELD_DEST_URL: request.URL, LOG_FIELD_DRIVER: backupOps.Name(), }).Debug() if err := backupOps.DeleteBackup(request.URL); err != nil { return err } log.WithFields(logrus.Fields{ LOG_FIELD_REASON: LOG_REASON_COMPLETE, LOG_FIELD_EVENT: LOG_EVENT_REMOVE, LOG_FIELD_OBJECT: LOG_OBJECT_SNAPSHOT, LOG_FIELD_DEST_URL: request.URL, LOG_FIELD_DRIVER: backupOps.Name(), }).Debug() return nil }
func (s *daemon) doBackupInspect(version string, w http.ResponseWriter, r *http.Request, objs map[string]string) error { s.GlobalLock.RLock() defer s.GlobalLock.RUnlock() request := &api.BackupListRequest{} if err := decodeRequest(r, request); err != nil { return err } request.URL = util.UnescapeURL(request.URL) backupOps, err := s.getBackupOpsForBackup(request.URL) if err != nil { return err } info, err := backupOps.GetBackupInfo(request.URL) if err != nil { return err } data, err := api.ResponseOutput(info) if err != nil { return err } _, err = w.Write(data) return err }
func (s *daemon) doBackupList(version string, w http.ResponseWriter, r *http.Request, objs map[string]string) error { request := &api.BackupListRequest{} if err := decodeRequest(r, request); err != nil { return err } request.URL = util.UnescapeURL(request.URL) opts := map[string]string{ OPT_VOLUME_NAME: request.VolumeName, } result := make(map[string]map[string]string) for _, driver := range s.ConvoyDrivers { backupOps, err := driver.BackupOps() if err != nil { // Not support backup ops continue } infos, err := backupOps.ListBackup(request.URL, opts) if err != nil { return err } for k, v := range infos { result[k] = v } } data, err := api.ResponseOutput(result) if err != nil { return err } _, err = w.Write(data) return err }
func doBackupDelete(c *cli.Context) error { var err error backupURL, err := util.GetFlag(c, "", true, err) if err != nil { return err } backupURL = util.UnescapeURL(backupURL) if err := objectstore.DeleteDeltaBlockBackup(backupURL); err != nil { return err } return nil }
func doBackupInspect(c *cli.Context) error { var err error backupURL, err := util.GetFlag(c, "", true, err) if err != nil { return err } backupURL = util.UnescapeURL(backupURL) info, err := objectstore.GetBackupInfo(backupURL) if err != nil { return err } data, err := api.ResponseOutput(info) if err != nil { return err } fmt.Println(string(data)) return nil }
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 (s *daemon) processVolumeCreate(request *api.VolumeCreateRequest) (*Volume, error) { volumeName := request.Name driverName := request.DriverName existedVolume := s.loadVolumeByName(volumeName) if existedVolume != nil { return nil, fmt.Errorf("Volume name %v already associate locally with volume %v ", volumeName, existedVolume.UUID) } volumeUUID := uuid.New() if volumeName == "" { volumeName = "volume-" + volumeUUID[:8] for s.NameUUIDIndex.Get(volumeName) != "" { volumeUUID = uuid.New() volumeName = "volume-" + volumeUUID[:8] } } if driverName == "" { driverName = s.DefaultDriver } driver, err := s.getDriver(driverName) if err != nil { return nil, err } volOps, err := driver.VolumeOps() if err != nil { return nil, err } opts := map[string]string{ convoydriver.OPT_SIZE: strconv.FormatInt(request.Size, 10), convoydriver.OPT_BACKUP_URL: util.UnescapeURL(request.BackupURL), convoydriver.OPT_VOLUME_NAME: request.Name, convoydriver.OPT_VOLUME_ID: request.DriverVolumeID, convoydriver.OPT_VOLUME_TYPE: request.Type, convoydriver.OPT_VOLUME_IOPS: strconv.FormatInt(request.IOPS, 10), } log.WithFields(logrus.Fields{ LOG_FIELD_REASON: LOG_REASON_PREPARE, LOG_FIELD_EVENT: LOG_EVENT_CREATE, LOG_FIELD_OBJECT: LOG_OBJECT_VOLUME, LOG_FIELD_VOLUME: volumeUUID, LOG_FIELD_VOLUME_NAME: volumeName, LOG_FIELD_OPTS: opts, }).Debug() if err := volOps.CreateVolume(volumeUUID, opts); err != nil { return nil, err } log.WithFields(logrus.Fields{ LOG_FIELD_REASON: LOG_REASON_COMPLETE, LOG_FIELD_EVENT: LOG_EVENT_CREATE, LOG_FIELD_OBJECT: LOG_OBJECT_VOLUME, LOG_FIELD_VOLUME: volumeUUID, }).Debug("Created volume") volume := &Volume{ UUID: volumeUUID, Name: volumeName, DriverName: driverName, FileSystem: "ext4", CreatedTime: util.Now(), Snapshots: make(map[string]Snapshot), } if err := s.saveVolume(volume); err != nil { return nil, err } if err := s.UUIDIndex.Add(volume.UUID); err != nil { return nil, err } if volume.Name != "" { if err := s.NameUUIDIndex.Add(volume.Name, volume.UUID); err != nil { return nil, err } } return volume, nil }
func (s *daemon) doBackupCreate(version string, w http.ResponseWriter, r *http.Request, objs map[string]string) error { request := &api.BackupCreateRequest{} if err := decodeRequest(r, request); err != nil { return err } request.URL = util.UnescapeURL(request.URL) snapshotUUID := request.SnapshotUUID volumeUUID := s.SnapshotVolumeIndex.Get(snapshotUUID) if volumeUUID == "" { return fmt.Errorf("Cannot find volume of snapshot %v", snapshotUUID) } if !s.snapshotExists(volumeUUID, snapshotUUID) { return fmt.Errorf("snapshot %v of volume %v doesn't exist", snapshotUUID, volumeUUID) } volume := s.loadVolume(volumeUUID) backupOps, err := s.getBackupOpsForVolume(volume) if err != nil { return err } opts := map[string]string{ convoydriver.OPT_VOLUME_NAME: volume.Name, convoydriver.OPT_FILESYSTEM: volume.FileSystem, convoydriver.OPT_VOLUME_CREATED_TIME: volume.CreatedTime, convoydriver.OPT_SNAPSHOT_NAME: volume.Snapshots[snapshotUUID].Name, convoydriver.OPT_SNAPSHOT_CREATED_TIME: volume.Snapshots[snapshotUUID].CreatedTime, } log.WithFields(logrus.Fields{ LOG_FIELD_REASON: LOG_REASON_PREPARE, LOG_FIELD_EVENT: LOG_EVENT_BACKUP, LOG_FIELD_OBJECT: LOG_OBJECT_SNAPSHOT, LOG_FIELD_SNAPSHOT: snapshotUUID, LOG_FIELD_VOLUME: volumeUUID, LOG_FIELD_DRIVER: backupOps.Name(), LOG_FIELD_DEST_URL: request.URL, }).Debug() backupURL, err := backupOps.CreateBackup(snapshotUUID, volumeUUID, request.URL, opts) if err != nil { return err } log.WithFields(logrus.Fields{ LOG_FIELD_REASON: LOG_REASON_COMPLETE, LOG_FIELD_EVENT: LOG_EVENT_BACKUP, LOG_FIELD_OBJECT: LOG_OBJECT_SNAPSHOT, LOG_FIELD_SNAPSHOT: snapshotUUID, LOG_FIELD_VOLUME: volumeUUID, LOG_FIELD_DRIVER: backupOps.Name(), LOG_FIELD_DEST_URL: request.URL, }).Debug() backup := &api.BackupURLResponse{ URL: backupURL, } if request.Verbose { return sendResponse(w, backup) } escapedURL := strings.Replace(backupURL, "&", "\\u0026", 1) return writeStringResponse(w, escapedURL) }
func (s *daemon) processVolumeCreate(request *api.VolumeCreateRequest) (*Volume, error) { volumeName := request.Name driverName := request.DriverName if volumeName == "" { volumeName = util.GenerateName("volume") for s.NameUUIDIndex.Get(volumeName) != "" { volumeName = util.GenerateName("volume") } } else { if s.NameUUIDIndex.Get(volumeName) != "" { return nil, fmt.Errorf("Volume %v already exists ", volumeName) } } if driverName == "" { driverName = s.DefaultDriver } driver, err := s.getDriver(driverName) if err != nil { return nil, err } volOps, err := driver.VolumeOps() if err != nil { return nil, err } req := Request{ Name: volumeName, Options: map[string]string{ OPT_SIZE: strconv.FormatInt(request.Size, 10), OPT_BACKUP_URL: util.UnescapeURL(request.BackupURL), OPT_VOLUME_NAME: volumeName, OPT_VOLUME_DRIVER_ID: request.DriverVolumeID, OPT_VOLUME_TYPE: request.Type, OPT_VOLUME_IOPS: strconv.FormatInt(request.IOPS, 10), OPT_PREPARE_FOR_VM: strconv.FormatBool(request.PrepareForVM), }, } log.WithFields(logrus.Fields{ LOG_FIELD_REASON: LOG_REASON_PREPARE, LOG_FIELD_EVENT: LOG_EVENT_CREATE, LOG_FIELD_OBJECT: LOG_OBJECT_VOLUME, LOG_FIELD_VOLUME: volumeName, LOG_FIELD_OPTS: req.Options, }).Debug() if err := volOps.CreateVolume(req); err != nil { return nil, err } log.WithFields(logrus.Fields{ LOG_FIELD_REASON: LOG_REASON_COMPLETE, LOG_FIELD_EVENT: LOG_EVENT_CREATE, LOG_FIELD_OBJECT: LOG_OBJECT_VOLUME, LOG_FIELD_VOLUME: volumeName, }).Debug("Created volume") volume := &Volume{ Name: volumeName, DriverName: driverName, } if err := s.NameUUIDIndex.Add(volumeName, "exists"); err != nil { return nil, err } return volume, nil }