func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) {
	volID := req.GetVolumeId()
	targetPath := req.GetTargetPath()
	fsType := req.GetVolumeCapability().GetMount().GetFsType()
	targetID, mappingIndex, err := parseVolumeID(volID)
	if err != nil {
		return nil, status.Error(codes.InvalidArgument, err.Error())
	}
	target, err := ns.targetAPI.Get(targetID)
	if err != nil {
		msg := fmt.Sprintf(
			"Unable to find target of ID: %d", targetID)
		glog.V(3).Info(msg)
		return nil, status.Error(codes.NotFound, msg)
	}
	if err = ns.iscsiDrv.discovery(); err != nil {
		msg := fmt.Sprintf("Failed to run ISCSI discovery: %v", err)
		glog.V(3).Info(msg)
		return nil, status.Error(codes.Internal, msg)
	}
	hasSession, err := ns.hasSession(target.IQN)
	if err != nil {
		return nil, err
	}
	if hasSession {
		glog.V(5).Infof("Found an existing session for %s", target.IQN)
	} else {
		if err = ns.iscsiDrv.login(target); err != nil {
			msg := fmt.Sprintf("Failed to run ISCSI login: %v", err)
			glog.V(3).Info(msg)
			return nil, status.Error(codes.Internal, msg)
		}
		defer func() {
			if err != nil {
				_ = ns.iscsiDrv.logout(target)
			}
		}()
	}
	targetDevPath := fmt.Sprintf("%s-lun-%d", target.IQN, mappingIndex)
	devicePath, err := probeDevice(targetDevPath)
	if err != nil {
		msg := fmt.Sprintf("Failed to find device for %s", targetDevPath)
		glog.V(3).Info(msg)
		return nil, errors.New(msg)
	}
	glog.V(5).Infof("Target path: %s", targetPath)
	notMnt := true
	if notMnt {
		exists, err := mount.PathExists(devicePath)
		if !exists || err != nil {
			msg := fmt.Sprintf("Could not find ISCSI device: %s", devicePath)
			glog.V(3).Info(msg)
			return nil, status.Error(codes.Internal, msg)
		}
		mounter := &mount.SafeFormatAndMount{
			Interface: mount.New(""),
			Exec:      utilexec.New(),
		}
		options := []string{"rw"}
		mountFlags := req.GetVolumeCapability().GetMount().GetMountFlags()
		options = append(options, mountFlags...)
		glog.V(5).Infof(
			"Mounting %s to %s(fstype: %s, options: %v)",
			devicePath, targetPath, fsType, options)
		err = mounter.FormatAndMount(devicePath, targetPath, fsType, options)
		if err != nil {
			msg := fmt.Sprintf(
				"Failed to mount %s to %s(fstype: %s, options: %v): %v",
				devicePath, targetPath, fsType, options, err)
			glog.V(5).Info(msg)
			return nil, status.Error(codes.Internal, msg)
		}
		glog.V(5).Infof(
			"Mounted %s to %s(fstype: %s, options: %v)",
			devicePath, targetPath, fsType, options)
	} else {
		glog.V(5).Infof("%s is already mounted", targetPath)
	}
	return &csi.NodePublishVolumeResponse{}, nil
}
NodePublishVolume mounts the volume to target path
package driver
import (
	"errors"
	"fmt"
	"path/filepath"
	"strings"
	"time"
	"io/ioutil"
	"github.com/golang/glog"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"golang.org/x/net/context"
	"k8s.io/kubernetes/pkg/util/resizefs"
	"k8s.io/utils/exec"
	utilexec "k8s.io/utils/exec"
	"k8s.io/utils/mount"
	"github.com/container-storage-interface/spec/lib/go/csi"
	csicommon "github.com/kubernetes-csi/drivers/pkg/csi-common"
	"github.com/jparklab/synology-csi/pkg/synology/api/iscsi"
)
const (
	probeDeviceInterval = 1 * time.Second
	probeDeviceTimeout  = 60 * time.Second
)
type nodeServer struct {
	*csicommon.DefaultNodeServer
	targetAPI iscsi.TargetAPI
	lunAPI    iscsi.LunAPI
	iscsiDrv iscsiDriver
}
func getDevicePath(targetDevPath string) string {
	diskDevPath := "/dev/disk/by-path"
	if entries, err := ioutil.ReadDir(diskDevPath); err == nil {
		for _, f := range entries {
			glog.V(5).Info(f.Name())
			if strings.Index(f.Name(), targetDevPath) != -1 {
				return strings.Join([]string{diskDevPath, f.Name()}, "/")
			}
		}
	}
	return ""
}
func probeDevice(targetDevPath string) (string, error) {
	ticker := time.NewTicker(probeDeviceInterval)
	defer ticker.Stop()
	timer := time.NewTimer(probeDeviceTimeout)
	defer timer.Stop()
	for {
		select {
		case <-ticker.C:
			if devicePath := getDevicePath(targetDevPath); devicePath != "" {
				return devicePath, nil
			}
		case <-timer.C:
			return "", fmt.Errorf("Timed out while waiting for device for %s", targetDevPath)
		}
	}
}