feat(mount): moving to legacy mount

We can not mount the datasets to more than one path via zfs mount command,
shifting to the legacy way of handling ZFS volumes where we can mount/umount
the datasets via legacy mount and umount commands.

This will also add a building block for SINGLE-NODE-MULTI-WRITER Capability.

Signed-off-by: Pawan <pawan@mayadata.io>
This commit is contained in:
Pawan 2020-06-08 11:33:27 +05:30 committed by Kiran Mova
parent b08a1e2a1f
commit 639ead416e
3 changed files with 74 additions and 46 deletions

View file

@ -0,0 +1 @@
moving to legacy mount

View file

@ -3,6 +3,7 @@ package zfs
import ( import (
"fmt" "fmt"
"os" "os"
"os/exec"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
apis "github.com/openebs/zfs-localpv/pkg/apis/openebs.io/zfs/v1" apis "github.com/openebs/zfs-localpv/pkg/apis/openebs.io/zfs/v1"
@ -60,29 +61,28 @@ func UmountVolume(vol *apis.ZFSVolume, targetPath string,
return nil return nil
} }
if vol.Spec.VolumeType == VOLTYPE_DATASET { if err = mounter.Unmount(targetPath); err != nil {
if err = UmountZFSDataset(vol); err != nil { logrus.Errorf(
logrus.Errorf( "zfs: failed to unmount %s: path %s err: %v",
"zfspv failed to umount dataset: path %s Error: %v", vol.Name, targetPath, err,
targetPath, err, )
) return err
return err }
}
} else { if err = SetDatasetLegacyMount(vol); err != nil {
if err = mounter.Unmount(targetPath); err != nil { // ignoring the failure as the volume has already
logrus.Errorf( // been umounted, now the new pod can mount it
"zfspv failed to unmount zvol: path %s Error: %v", logrus.Warningf(
targetPath, err, "zfs: failed to set legacy mountpoint: %s err: %v",
) vol.Name, err,
return err )
}
} }
if err := os.Remove(targetPath); err != nil { if err := os.Remove(targetPath); err != nil {
logrus.Errorf("zfspv: failed to remove mount path Error: %v", err) logrus.Errorf("zfspv: failed to remove mount path vol %s err : %v", vol.Name, err)
} }
logrus.Infof("umount done path %v", targetPath) logrus.Infof("umount done %s path %v", vol.Name, targetPath)
return nil return nil
} }
@ -132,19 +132,19 @@ func IsMountPath(path string) bool {
func verifyMountRequest(vol *apis.ZFSVolume, mountpath string) error { func verifyMountRequest(vol *apis.ZFSVolume, mountpath string) error {
if len(mountpath) == 0 { if len(mountpath) == 0 {
return status.Error(codes.InvalidArgument, "mount path missing in request") return status.Error(codes.InvalidArgument, "verifyMount: mount path missing in request")
} }
if len(vol.Spec.OwnerNodeID) > 0 && if len(vol.Spec.OwnerNodeID) > 0 &&
vol.Spec.OwnerNodeID != NodeID { vol.Spec.OwnerNodeID != NodeID {
return status.Error(codes.Internal, "volume is owned by different node") return status.Error(codes.Internal, "verifyMount: volume is owned by different node")
} }
devicePath, err := GetVolumeDevPath(vol) devicePath, err := GetVolumeDevPath(vol)
if err != nil { if err != nil {
logrus.Errorf("can not get device for volume:%s dev %s err: %v", logrus.Errorf("can not get device for volume:%s dev %s err: %v",
vol.Name, devicePath, err.Error()) vol.Name, devicePath, err.Error())
return err return status.Errorf(codes.Internal, "verifyMount: GetVolumePath failed %s", err.Error())
} }
/* /*
@ -158,13 +158,13 @@ func verifyMountRequest(vol *apis.ZFSVolume, mountpath string) error {
if err != nil { if err != nil {
logrus.Errorf("can not get mounts for volume:%s dev %s err: %v", logrus.Errorf("can not get mounts for volume:%s dev %s err: %v",
vol.Name, devicePath, err.Error()) vol.Name, devicePath, err.Error())
return err return status.Errorf(codes.Internal, "verifyMount: Getmounts failed %s", err.Error())
} else if len(currentMounts) >= 1 { } else if len(currentMounts) >= 1 {
logrus.Errorf( logrus.Errorf(
"can not mount, volume:%s already mounted dev %s mounts: %v", "can not mount, volume:%s already mounted dev %s mounts: %v",
vol.Name, devicePath, currentMounts, vol.Name, devicePath, currentMounts,
) )
return status.Error(codes.Internal, "device already mounted") return status.Errorf(codes.Internal, "verifyMount: device already mounted at %s", currentMounts)
} }
return nil return nil
} }
@ -174,7 +174,7 @@ func MountZvol(vol *apis.ZFSVolume, mount *apis.MountInfo) error {
volume := vol.Spec.PoolName + "/" + vol.Name volume := vol.Spec.PoolName + "/" + vol.Name
err := verifyMountRequest(vol, mount.MountPath) err := verifyMountRequest(vol, mount.MountPath)
if err != nil { if err != nil {
return status.Error(codes.Internal, "zvol can not be mounted") return err
} }
devicePath := ZFS_DEVPATH + volume devicePath := ZFS_DEVPATH + volume
@ -194,15 +194,43 @@ func MountDataset(vol *apis.ZFSVolume, mount *apis.MountInfo) error {
volume := vol.Spec.PoolName + "/" + vol.Name volume := vol.Spec.PoolName + "/" + vol.Name
err := verifyMountRequest(vol, mount.MountPath) err := verifyMountRequest(vol, mount.MountPath)
if err != nil { if err != nil {
return status.Error(codes.Internal, "invalid mount request") return err
} }
err = MountZFSDataset(vol, mount.MountPath) val, err := GetVolumeProperty(vol, "mountpoint")
if err != nil { if err != nil {
return status.Errorf(codes.Internal, "zfs: mount failed err : %v", err.Error()) return err
} }
logrus.Infof("dataset %v mounted %v", volume, mount.MountPath) if val == "legacy" {
var MountVolArg []string
var mntopt string
for _, option := range mount.MountOptions {
mntopt += option + ","
}
MountVolArg = append(MountVolArg, "-o", mntopt, "-t", "zfs", volume, mount.MountPath)
cmd := exec.Command("mount", MountVolArg...)
out, err := cmd.CombinedOutput()
if err != nil {
logrus.Errorf("zfs: could not mount the dataset %v cmd %v error: %s",
volume, MountVolArg, string(out))
return status.Errorf(codes.Internal, "dataset: mount failed err : %s", string(out))
}
logrus.Infof("dataset : legacy mounted %s => %s", volume, mount.MountPath)
} else {
/*
* We might have created volumes and then upgraded the node agent before
* getting the mount request for that volume. In this case volume will
* not be created with mountpoint as legacy. Handling the mount in old way.
*/
err = MountZFSDataset(vol, mount.MountPath)
if err != nil {
return status.Errorf(codes.Internal, "zfs: mount failed err : %s", err.Error())
}
logrus.Infof("dataset : mounted %s => %s", volume, mount.MountPath)
}
return nil return nil
} }

View file

@ -140,7 +140,7 @@ func buildCloneCreateArgs(vol *apis.ZFSVolume) []string {
reservationProperty := "reservation=" + vol.Spec.Capacity reservationProperty := "reservation=" + vol.Spec.Capacity
ZFSVolArg = append(ZFSVolArg, "-o", reservationProperty) ZFSVolArg = append(ZFSVolArg, "-o", reservationProperty)
} }
ZFSVolArg = append(ZFSVolArg, "-o", "mountpoint=none") ZFSVolArg = append(ZFSVolArg, "-o", "mountpoint=legacy")
} }
if len(vol.Spec.Dedup) != 0 { if len(vol.Spec.Dedup) != 0 {
@ -235,7 +235,7 @@ func buildDatasetCreateArgs(vol *apis.ZFSVolume) []string {
} }
// set the mount path to none, by default zfs mounts it to the default dataset path // set the mount path to none, by default zfs mounts it to the default dataset path
ZFSVolArg = append(ZFSVolArg, "-o", "mountpoint=none", volume) ZFSVolArg = append(ZFSVolArg, "-o", "mountpoint=legacy", volume)
return ZFSVolArg return ZFSVolArg
} }
@ -421,25 +421,24 @@ func MountZFSDataset(vol *apis.ZFSVolume, mountpath string) error {
return nil return nil
} }
// UmountZFSDataset umounts the dataset // SetDatasetLegacyMount sets the dataset mountpoint to legacy if not set
func UmountZFSDataset(vol *apis.ZFSVolume) error { func SetDatasetLegacyMount(vol *apis.ZFSVolume) error {
volume := vol.Spec.PoolName + "/" + vol.Name if vol.Spec.VolumeType != VOLTYPE_DATASET {
var MountVolArg []string return nil
MountVolArg = append(MountVolArg, "umount", volume) }
cmd := exec.Command(ZFSVolCmd, MountVolArg...)
out, err := cmd.CombinedOutput() prop, err := GetVolumeProperty(vol, "mountpoint")
if err != nil { if err != nil {
logrus.Errorf("zfs: could not umount the dataset %v cmd %v error: %s",
volume, MountVolArg, string(out))
return err return err
} }
// ignoring the failure of setting the mountpoint to none
// as the dataset has already been umounted, now the new pod
// can mount it and it will change that to desired mountpath
// and try to mount it if not mounted
SetDatasetMountProp(volume, "none")
return nil if prop != "legacy" {
// set the mountpoint to legacy
volume := vol.Spec.PoolName + "/" + vol.Name
err = SetDatasetMountProp(volume, "legacy")
}
return err
} }
// GetVolumeProperty gets zfs properties for the volume // GetVolumeProperty gets zfs properties for the volume
@ -454,7 +453,7 @@ func GetVolumeProperty(vol *apis.ZFSVolume, prop string) (string, error) {
if err != nil { if err != nil {
logrus.Errorf("zfs: could not get %s on dataset %v cmd %v error: %s", logrus.Errorf("zfs: could not get %s on dataset %v cmd %v error: %s",
prop, volume, ZFSVolArg, string(out)) prop, volume, ZFSVolArg, string(out))
return "", fmt.Errorf("get %s failed, %s", prop, string(out)) return "", fmt.Errorf("zfs get %s failed, %s", prop, string(out))
} }
val := out[:len(out)-1] val := out[:len(out)-1]
return string(val), nil return string(val), nil