Beispiel #1
0
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
}
Beispiel #2
0
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
}
Beispiel #3
0
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
}
Beispiel #4
0
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
}
Beispiel #5
0
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
}
Beispiel #6
0
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
}
Beispiel #7
0
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
}
Beispiel #8
0
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)
}
Beispiel #9
0
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
}