func mkdir(path string) (bool, error) {
	st, err := os.Stat(path)
	if os.IsNotExist(err) {
		if err := os.Mkdir(path, 0750); err != nil {
			log.WithField("dir", path).WithError(
				err).Error("Unable to create dir")
			return false, err
		}
		log.WithField("path", path).Debug("created directory")
		return true, nil
	}
	if !st.IsDir() {
		return false, fmt.Errorf("existing path is not a directory")
	}
	return false, nil
}
mkdir creates the directory specified by path if needed.
return pair is a bool flag of whether dir was created, and an error
package service
import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"
	csi "github.com/container-storage-interface/spec/lib/go/csi"
	"github.com/dell/gofsutil"
	log "github.com/sirupsen/logrus"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)
var unitTestEmulateBlockDevice bool
var removeWithRetrySleepTime = 2 * time.Second
type Device struct {
	FullPath string
	Name     string
	RealDev  string
}
func GetDevice(path string) (*Device, error) {
	fi, err := os.Lstat(path)
	if err != nil {
		log.Error("Could not lstat path: " + path)
		return nil, err
	}
	d, err := filepath.EvalSymlinks(path)
	if err != nil {
		log.Error("Could not evaluate symlinks path: " + path)
		return nil, err
	}
	ds, _ := os.Stat(d)
	dm := ds.Mode()
	if unitTestEmulateBlockDevice {
		dm = dm | os.ModeDevice
	}
	if dm&os.ModeDevice == 0 {
		return nil, fmt.Errorf(
			"%s is not a block device", path)
	}
	dev := &Device{
		Name:     fi.Name(),
		FullPath: path,
		RealDev:  strings.Replace(d, "\\", "/", -1),
	}
	log.Debug(fmt.Sprintf("Device: %#v", dev))
	return dev, nil
}
func publishVolume(
	req *csi.NodePublishVolumeRequest,
	privDir, device string, reqID string) error {
	id := req.GetVolumeId()
	target := req.GetTargetPath()
	if target == "" {
		return status.Error(codes.InvalidArgument,
			"Target Path is required")
	}
	ro := req.GetReadonly()
	volCap := req.GetVolumeCapability()
	if volCap == nil {
		return status.Error(codes.InvalidArgument,
			"Volume Capability is required")
	}
	sysDevice, err := GetDevice(device)
	if err != nil {
		return status.Errorf(codes.Internal,
			"error getting block device for volume: %s, err: %s",
			id, err.Error())
	}
	isBlock, mntVol, accMode, multiAccessFlag, err := validateVolumeCapability(volCap, ro)
	if err != nil {
		return err
	}
	privTgt := getPrivateMountPoint(privDir, id)
	err = createTarget(target, isBlock)
	if err != nil {
		cleanupPrivateTarget(reqID, privTgt)
		return status.Error(codes.FailedPrecondition, fmt.Sprintf("Could not create %s: %s", target, err.Error()))
	}
	if _, err := mkdir(privDir); err != nil {
		return err
	}
	if isBlock {
		mntFlags := mntVol.GetMountFlags()
		err = mountBlock(sysDevice, target, mntFlags, singleAccessMode(accMode))
		return err
	}
	f := log.Fields{
		"id":           id,
		"volumePath":   sysDevice.FullPath,
		"device":       sysDevice.RealDev,
		"CSIRequestID": reqID,
		"target":       target,
		"privateMount": privTgt,
	}
	ctx := context.WithValue(context.Background(), gofsutil.ContextKey("RequestID"), reqID)
	devMnts, err := getDevMounts(sysDevice)
	if err != nil {
		return status.Errorf(codes.Internal,
			"could not reliably determine existing mount status: %s",
			err.Error())
	}
	if len(devMnts) == 0 {
		log.WithFields(f).Debug("attempting mount to private area")
		var created bool
		created, err = mkdir(privTgt)
		if err != nil {
			return status.Errorf(codes.Internal,
				"Unable to create private mount point: %s",
				err.Error())
		}
		alreadyMounted := false
		if !created {
			log.WithFields(f).Debug("private mount target already exists")
			mnts, err := gofsutil.GetMounts(ctx)
			if err != nil {
				return status.Errorf(codes.Internal,
					"could not reliably determine existing mount status: %s",
					err.Error())
			}
			if len(mnts) == 0 {
				return status.Errorf(codes.Unavailable, "volume %s not published to node", id)
			}
			for _, m := range mnts {
				if m.Path == privTgt {
					log.Debug(fmt.Sprintf("MOUNT: %#v", m))
					resolvedMountDevice := evalSymlinks(m.Device)
					if resolvedMountDevice != sysDevice.RealDev {
						return status.Errorf(codes.FailedPrecondition, "Private mount point: %s mounted by different device: %s", privTgt, resolvedMountDevice)
					}
					alreadyMounted = true
				}
			}
		}
		if !alreadyMounted {
			fs := mntVol.GetFsType()
			mntFlags := mntVol.GetMountFlags()
			if fs == "xfs" {
				mntFlags = append(mntFlags, "nouuid")
			}
			if err := handlePrivFSMount(
				ctx, accMode, sysDevice, mntFlags, fs, privTgt); err != nil {
				cleanupPrivateTarget(reqID, privTgt)
				return err
			}
		}
	} else {
		mounted := false
		log.Infof("A devMnts: %#v", devMnts)
		for _, m := range devMnts {
			if m.Path == target {
				log.Infof("mount %#v already mounted to requested target %s", m, target)
				mounted = true
			}
			if m.Path == privTgt {
				mounted = true
				rwo := multiAccessFlag
				if ro {
					rwo = "ro"
				}
				if rwo == "" || contains(m.Opts, rwo) {
					log.WithFields(f).Debug(
						"private mount already in place")
					break
				} else {
					log.WithFields(f).Infof("mount %#v rwo %s", m, rwo)
					return status.Error(codes.InvalidArgument,
						"access mode conflicts with existing mounts")
				}
			}
		}
		if !mounted {
			return status.Error(codes.Internal,
				"device already in use and mounted elsewhere")
		}
	}
	targetMnts, err := getPathMounts(target)
	if err != nil {
		return status.Errorf(codes.Internal,
			"could not reliably determine existing mount status: %s",
			err.Error())
	}
	if len(targetMnts) > 0 {
		for _, m := range targetMnts {
			log.Infof("pathMnt: %#v", m)
			if m.Device == sysDevice.RealDev || m.Device == sysDevice.FullPath || m.Source == privTgt {
				rwo := multiAccessFlag
				if ro {
					rwo = "ro"
				}
				if rwo != "" && !contains(m.Opts, rwo) {
					log.WithFields(f).Printf("mount %#v rwo %s\n", m, rwo)
					return status.Error(codes.Internal, "volume previously published with different mount options")
				}
				log.WithFields(f).Info("volume already published to target")
				return nil
			}
			return status.Error(codes.AlreadyExists, "target already has a conflicting mount")
		}
	}
	err = createTarget(target, isBlock)
	if err != nil {
		cleanupPrivateTarget(reqID, privTgt)
		return status.Error(codes.FailedPrecondition, fmt.Sprintf("Could not create %s: %s", target, err.Error()))
	}
	var mntFlags []string
	mntFlags = make([]string, 0)
	mntFlags = mntVol.GetMountFlags()
	if mntVol.FsType == "xfs" {
		mntFlags = append(mntFlags, "nouuid")
	}
	if ro || accMode.GetMode() == csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY {
		mntFlags = append(mntFlags, "ro")
	}
	if err := gofsutil.BindMount(ctx, privTgt, target, mntFlags...); err != nil {
		cleanupPrivateTarget(reqID, privTgt)
		return status.Errorf(codes.Internal,
			"error publish volume to target path: %s",
			err.Error())
	}
	return nil
}
func cleanupPrivateTarget(reqID, privTgt string) {
	log.WithField("CSIRequestID", reqID).WithField("privTgt", privTgt).Info("Cleaning up private target")
	if privErr := gofsutil.Unmount(context.Background(), privTgt); privErr != nil {
		log.WithField("CSIRequestID", reqID).Printf("Error unmounting privTgt %s: %s", privTgt, privErr)
	}
	if privErr := removeWithRetry(privTgt); privErr != nil {
		log.WithField("CSIRequestID", reqID).Printf("Error removing privTgt %s: %s", privTgt, privErr)
	}
}
func mountBlock(device *Device, target string, mntFlags []string, singleAccess bool) error {
	log.Infof("mountBlock called device %#v target %s mntFlags %#v", device, target, mntFlags)
	mnts, err := getDevMounts(device)
	if err != nil {
		return status.Errorf(codes.Internal, "Could not getDevMounts for: %s", device.RealDev)
	}
	for _, mnt := range mnts {
		if mnt.Path == target {
			log.Info("Block volume target is already mounted")
			return nil
		} else if singleAccess {
			return status.Error(codes.InvalidArgument, "Access mode conflicts with existing mounts")
		}
	}
	err = createTarget(target, true)
	if err != nil {
		return status.Error(codes.FailedPrecondition, fmt.Sprintf("Could not create %s: %s", target, err.Error()))
	}
	err = gofsutil.BindMount(context.Background(), device.RealDev, target, mntFlags...)
	if err != nil {
		return status.Errorf(codes.Internal, "error bind mounting to target path: %s", target)
	}
	return nil
}
func handlePrivFSMount(
	ctx context.Context,
	accMode *csi.VolumeCapability_AccessMode,
	sysDevice *Device,
	mntFlags []string,
	fs, privTgt string) error {
	formatCtx := context.WithValue(ctx, gofsutil.ContextKey(gofsutil.NoDiscard), gofsutil.NoDiscard)
	if accMode.GetMode() == csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY {
		mntFlags = append(mntFlags, "ro")
		if err := gofsutil.Mount(ctx, sysDevice.FullPath, privTgt, fs, mntFlags...); err != nil {
			return status.Errorf(codes.Internal, "error performing private mount: %s", err.Error())
		}
		return nil
	} else if accMode.GetMode() == csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER {
		if err := gofsutil.FormatAndMount(formatCtx, sysDevice.FullPath, privTgt, fs, mntFlags...); err != nil {
			return status.Errorf(codes.Internal, "error performing private mount: %s", err.Error())
		}
		return nil
	}
	return status.Error(codes.Internal, "Invalid access mode")
}
func getPrivateMountPoint(privDir string, name string) string {
	return fmt.Sprintf("%s/%s", privDir, name)
}
func contains(list []string, item string) bool {
	for _, x := range list {
		if x == item {
			return true
		}
	}
	return false
}
func mkfile(path string) (bool, error) {
	st, err := os.Stat(path)
	if os.IsNotExist(err) {
		file, err := os.OpenFile(path, os.O_CREATE, 0600)  
		if err != nil {
			log.WithField("path", path).WithError(
				err).Error("Unable to create file")
			return false, err
		}
		file.Close()  
		log.WithField("path", path).Debug("created file")
		return true, nil
	}
	if st.IsDir() {
		return false, fmt.Errorf("existing path is a directory")
	}
	return false, nil
}