diff --git a/pkg/compute/models/diskbackups.go b/pkg/compute/models/diskbackups.go index a277c36afd..fc5d9d8584 100644 --- a/pkg/compute/models/diskbackups.go +++ b/pkg/compute/models/diskbackups.go @@ -18,6 +18,7 @@ import ( "context" "database/sql" "reflect" + "strings" "time" "yunion.io/x/jsonutils" @@ -290,11 +291,26 @@ func (dm *SDiskBackupManager) ValidateCreateData( return input, httperrors.NewNotFoundError("fetch container by %s", input.BackupAsTar.ContainerId) } input.BackupAsTar.ContainerId = ctr.GetId() + if err := dm.validateBackupAsTarFiles(input.BackupAsTar.IncludeFiles); err != nil { + return input, httperrors.NewInputParameterError("validate include_files: %s", err) + } + if err := dm.validateBackupAsTarFiles(input.BackupAsTar.ExcludeFiles); err != nil { + return input, httperrors.NewInputParameterError("validate exclude_files: %s", err) + } } return input, nil } +func (dm *SDiskBackupManager) validateBackupAsTarFiles(paths []string) error { + for _, p := range paths { + if strings.HasPrefix(p, "/") { + return httperrors.NewInputParameterError("%s can't start with /", p) + } + } + return nil +} + func (db *SDiskBackup) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error { input := new(api.DiskBackupCreateInput) if err := data.Unmarshal(input); err != nil { diff --git a/pkg/hostman/guestman/pod.go b/pkg/hostman/guestman/pod.go index 6449c88e5e..9ea661080d 100644 --- a/pkg/hostman/guestman/pod.go +++ b/pkg/hostman/guestman/pod.go @@ -1851,28 +1851,38 @@ func (s *sPodGuestInstance) DoSnapshot(ctx context.Context, params *SDiskSnapsho return nil, errors.Wrapf(err, "bind mount %s to %s: %s", mntPath, targetBindMntPath, out) } } + deferUmount := func() error { + for _, vol := range vols { + // unbind mount + // umount + targetBindMntPath := filepath.Join(tmpBackRootDir, vol.Disk.SubDirectory) + if vol.Disk.StorageSizeFile != "" { + targetBindMntPath = filepath.Join(tmpBackRootDir, vol.Disk.StorageSizeFile) + } + out, err := procutils.NewRemoteCommandAsFarAsPossible("umount", targetBindMntPath).Output() + if err != nil { + return errors.Wrapf(err, "umount bind point %s: %s", targetBindMntPath, out) + } + } + for _, vol := range vols { + drv := volume_mount.GetDriver(vol.Type) + if err := drv.Unmount(s, input.ContainerId, vol); err != nil { + return errors.Wrapf(err, "unmount %s to %s", input.ContainerId, jsonutils.Marshal(vol)) + } + } + return nil + } + defer func() { + if err := deferUmount(); err != nil { + log.Errorf("deferUmount after snapshot error: %s", err) + } else { + log.Infof("defer umount success") + } + }() snapshotPath, err := s.createSnapshot(params, tmpBackRootDir) if err != nil { return nil, errors.Wrap(err, "create snapshot") } - for _, vol := range vols { - // unbind mount - // umount - targetBindMntPath := filepath.Join(tmpBackRootDir, vol.Disk.SubDirectory) - if vol.Disk.StorageSizeFile != "" { - targetBindMntPath = filepath.Join(tmpBackRootDir, vol.Disk.StorageSizeFile) - } - out, err := procutils.NewRemoteCommandAsFarAsPossible("umount", targetBindMntPath).Output() - if err != nil { - return nil, errors.Wrapf(err, "umount bind point %s: %s", targetBindMntPath, out) - } - } - for _, vol := range vols { - drv := volume_mount.GetDriver(vol.Type) - if err := drv.Unmount(s, input.ContainerId, vol); err != nil { - return nil, errors.Wrapf(err, "unmount %s to %s", input.ContainerId, jsonutils.Marshal(vol)) - } - } res := jsonutils.NewDict() res.Set("location", jsonutils.NewString(snapshotPath)) return res, nil