forked from Ivasoft/objectivefs-docker-volume
Volume with mounted snaphosts cannot unmount.
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
110
main.go
110
main.go
@@ -57,11 +57,6 @@ type ofsDriver struct {
|
||||
defMountSnapshots bool
|
||||
}
|
||||
|
||||
type snapshotRule struct {
|
||||
count int
|
||||
period time.Duration
|
||||
}
|
||||
|
||||
var version = "1.0"
|
||||
var objfsVersion = "7.2"
|
||||
|
||||
@@ -169,8 +164,27 @@ func (d *ofsDriver) Get(r *volume.GetRequest) (*volume.GetResponse, error) {
|
||||
func umount(v *ofsVolume, rt *ofsVolumeRt) error {
|
||||
log.WithFields(log.Fields{"name": v.Volume.Name}).Info("Unmount ObjectiveFS Volume")
|
||||
if !rt.mounted {
|
||||
return fmt.Errorf("Volume is not mounted")
|
||||
return fmt.Errorf("volume is not mounted")
|
||||
}
|
||||
|
||||
if v.MountSnapshots {
|
||||
// Snapshots must be unmounted first
|
||||
// Note: We do NOT remove the mount directory as other distributed mounts may be using them
|
||||
snapshotsPath := path.Join(v.Volume.Mountpoint, snapshotsDirectory)
|
||||
if existingMounts, err := getMountedSnaphots(snapshotsPath, true); err == nil {
|
||||
log.WithFields(log.Fields{"name": v.Volume.Name, "existingMounts": existingMounts}).Trace("Existing snapshot mounts")
|
||||
for i, path := range existingMounts {
|
||||
if err := exec.Command("umount", path).Run(); err != nil {
|
||||
log.WithFields(log.Fields{"name": v.Volume.Name, "snapshot": i}).Warn("Failed to unmount a snapshot on unmount.")
|
||||
} else {
|
||||
log.WithFields(log.Fields{"name": v.Volume.Name, "snapshot": i}).Trace("Snapshot unmounted on unmount.")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.WithFields(log.Fields{"name": v.Volume.Name, "Error": err}).Warn("Cannot determine existing snapshot mounts on unmount")
|
||||
}
|
||||
}
|
||||
|
||||
if err := exec.Command("umount", v.Volume.Mountpoint).Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -330,44 +344,56 @@ func (d *ofsDriver) Mount(r *volume.MountRequest) (*volume.MountResponse, error)
|
||||
if existingSnapshotsB, err := applyEnv(exec.Command("/sbin/mount.objectivefs", "list", "-sz", v.Fs), v.Env).Output(); err == nil {
|
||||
if existingSnapshots, err := parseExistingSnapshots(string(existingSnapshotsB), v.Fs); err == nil {
|
||||
log.WithFields(log.Fields{"name": r.Name, "existingSnapshots": existingSnapshots}).Trace("Existing snapshots")
|
||||
if existingMounts, err := getMountedSnaphots(snapshotsPath); err == nil {
|
||||
if existingMounts, err := getMountedSnaphots(snapshotsPath, true); err == nil {
|
||||
log.WithFields(log.Fields{"name": r.Name, "existingMounts": existingMounts}).Trace("Existing snapshot mounts")
|
||||
if existingMountDirs, err := getMountedSnaphots(snapshotsPath, false); err == nil {
|
||||
log.WithFields(log.Fields{"name": r.Name, "existingMountDirs": existingMounts}).Trace("Existing snapshot mount dirs")
|
||||
|
||||
// Remove mounts of expired snapshots
|
||||
for i, path := range setMinus(existingMounts, expectedSnapshots) {
|
||||
if err := exec.Command("umount", path).Run(); err != nil {
|
||||
log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Warn("Failed to unmount an expired snapshot.")
|
||||
} else {
|
||||
log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Debug("Snapshot unmounted.")
|
||||
}
|
||||
if err := os.Remove(path); err != nil {
|
||||
log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Warn("Failed to remove directory of an expired snapshot.")
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy old snapshots
|
||||
for i, name := range setMinus(existingSnapshots, expectedSnapshots) {
|
||||
expectedOutput := "Snapshot '" + name + "' destroyed."
|
||||
if output, err := applyEnv(exec.Command("/sbin/mount.objectivefs", "destroy", name, "-f"), v.Env).Output(); err != nil || strings.TrimSpace(string(output)) != expectedOutput {
|
||||
log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Warn("Failed to destroy an expired snapshot.")
|
||||
} else {
|
||||
log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Debug("Snapshot destroyed.")
|
||||
}
|
||||
}
|
||||
|
||||
// Add new mounts
|
||||
for i, name := range setMinus(setIntersect(existingSnapshots, expectedSnapshots), existingMounts) {
|
||||
dest := filepath.Join(snapshotsPath, i)
|
||||
if err := os.Mkdir(dest, os.ModePerm); err == nil || os.IsExist(err) {
|
||||
// Note: There is a missing "mount" argument so the mount continues running in a background process
|
||||
if err := applyEnv(exec.Command("/sbin/mount.objectivefs", name, dest), v.Env).Run(); err != nil {
|
||||
log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Warn("Failed to mount a new snapshot.")
|
||||
} else {
|
||||
log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Debug("Snapshot mounted.")
|
||||
// Remove left-over dirs of expired snapshots (ie. appears during downtime)
|
||||
for i, path := range setMinus(setMinus(existingMountDirs, expectedSnapshots), existingMounts) {
|
||||
if err := os.Remove(path); err != nil {
|
||||
log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Warn("Failed to remove directory of an off-line expired snapshot.")
|
||||
}
|
||||
} else {
|
||||
log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Warn("Failed to create directory for a snapshot.")
|
||||
}
|
||||
|
||||
// Remove mounts of expired snapshots
|
||||
for i, path := range setMinus(existingMounts, expectedSnapshots) {
|
||||
if err := exec.Command("umount", path).Run(); err != nil {
|
||||
log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Warn("Failed to unmount an expired snapshot.")
|
||||
} else {
|
||||
log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Debug("Snapshot unmounted.")
|
||||
}
|
||||
if err := os.Remove(path); err != nil {
|
||||
log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Warn("Failed to remove directory of an expired snapshot.")
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy old snapshots
|
||||
for i, name := range setMinus(existingSnapshots, expectedSnapshots) {
|
||||
expectedOutput := "Snapshot '" + name + "' destroyed."
|
||||
if output, err := applyEnv(exec.Command("/sbin/mount.objectivefs", "destroy", name, "-f"), v.Env).Output(); err != nil || strings.TrimSpace(string(output)) != expectedOutput {
|
||||
log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Warn("Failed to destroy an expired snapshot.")
|
||||
} else {
|
||||
log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Debug("Snapshot destroyed.")
|
||||
}
|
||||
}
|
||||
|
||||
// Add new mounts
|
||||
for i, name := range setMinus(setIntersect(existingSnapshots, expectedSnapshots), existingMounts) {
|
||||
dest := filepath.Join(snapshotsPath, i)
|
||||
if err := os.Mkdir(dest, os.ModePerm); err == nil || os.IsExist(err) {
|
||||
// Note: There is a missing "mount" argument so the mount continues running in a background process
|
||||
if err := applyEnv(exec.Command("/sbin/mount.objectivefs", name, dest), v.Env).Run(); err != nil {
|
||||
log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Warn("Failed to mount a new snapshot.")
|
||||
} else {
|
||||
log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Debug("Snapshot mounted.")
|
||||
}
|
||||
} else {
|
||||
log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Warn("Failed to create directory for a snapshot.")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.WithFields(log.Fields{"name": r.Name, "Error": err}).Warn("Cannot determine existing snapshot mount dirs")
|
||||
}
|
||||
} else {
|
||||
log.WithFields(log.Fields{"name": r.Name, "Error": err}).Warn("Cannot determine existing snapshot mounts")
|
||||
@@ -629,7 +655,7 @@ func parseExistingSnapshots(data string, expectedPrefix string) (map[string]stri
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func getMountedSnaphots(baseDir string) (map[string]string, error) {
|
||||
func getMountedSnaphots(baseDir string, checkMount bool) (map[string]string, error) {
|
||||
if entries, err := os.ReadDir(baseDir); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
@@ -637,7 +663,7 @@ func getMountedSnaphots(baseDir string) (map[string]string, error) {
|
||||
for _, i := range entries {
|
||||
if i.IsDir() {
|
||||
iPath := filepath.Join(baseDir, i.Name())
|
||||
if isObjFs, err := isObjectiveFsMount(iPath); err == nil && isObjFs {
|
||||
if isObjFs, err := isObjectiveFsMount(iPath); !checkMount || (err == nil && isObjFs) {
|
||||
result[i.Name()] = iPath
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user