Repository: kubernetes-sigs/aws-ebs-csi-driver
Pull request #2022 (2024-04-23 19:28:17)

Inject volumeWaitParameters dependency
**Is this a bug fix or adding new feature?**
Improvement

**What is this PR about? / Why do we need it?**
Today, we sleep in cloud package tests due to hardcoding volume polling parameters inside `waitFor` functions like `waitForVolume`

This PR:
- Injects the volumeWaitParameters dependency
- Decreases cloud package unit test duration by ~9 seconds (from 12s to 3.3s)
- (Optional) Consolidates backoff parameters and explanatory comments to their own `volumeWaitParameters.go` file 


Note:  Will rebase once #2021 is merged. 

**What testing is done?** 
`make test`

k8s-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by:
**Once this PR has been reviewed and has the lgtm label**, please ask for approval from [andrewsirenko](https://github.com/andrewsirenko). For more information see [the Kubernetes Code Review Process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process).

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Faws-ebs-csi-driver).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["andrewsirenko"]} -->
AndrewSirenko: /hold 

Will rebase once #2021 is merged. 
AndrewSirenko: /unhold

Merged #2021, rebased this PR with new backoff Cap. 

Patch:
diff --git a/Dockerfile b/Dockerfile
index f080a598..4ea5e1dd 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -36,10 +36,8 @@ ENTRYPOINT ["/bin/aws-ebs-csi-driver"]
 
 FROM public.ecr.aws/eks-distro-build-tooling/eks-distro-windows-base:1809 AS windows-ltsc2019
 COPY --from=builder /go/src/github.com/kubernetes-sigs/aws-ebs-csi-driver/bin/aws-ebs-csi-driver.exe /aws-ebs-csi-driver.exe
-ENV PATH="C:\\Windows\\System32\\WindowsPowerShell\\v1.0;${PATH}"
 ENTRYPOINT ["/aws-ebs-csi-driver.exe"]
 
 FROM public.ecr.aws/eks-distro-build-tooling/eks-distro-windows-base:ltsc2022 AS windows-ltsc2022
 COPY --from=builder /go/src/github.com/kubernetes-sigs/aws-ebs-csi-driver/bin/aws-ebs-csi-driver.exe /aws-ebs-csi-driver.exe
-ENV PATH="C:\\Windows\\System32\\WindowsPowerShell\\v1.0;${PATH}"
 ENTRYPOINT ["/aws-ebs-csi-driver.exe"]
diff --git a/Makefile b/Makefile
index 897f3c7c..bddd678b 100644
--- a/Makefile
+++ b/Makefile
@@ -54,7 +54,6 @@ ALL_OS_ARCH_OSVERSION=$(foreach os, $(ALL_OS), ${ALL_OS_ARCH_OSVERSION_${os}})
 CLUSTER_NAME?=ebs-csi-e2e.k8s.local
 CLUSTER_TYPE?=kops
 WINDOWS?=false
-WINDOWS_HOSTPROCESS?=false
 
 # split words on hyphen, access by 1-index
 word-hyphen = $(word $2,$(subst -, ,$1))
@@ -150,15 +149,6 @@ e2e/external-windows: bin/helm bin/kubetest2
 	EBS_INSTALL_SNAPSHOT="false" \
 	./hack/e2e/run.sh
 
-.PHONY: e2e/external-windows-hostprocess
-e2e/external-windows-hostprocess: bin/helm bin/kubetest2
-	WINDOWS_HOSTPROCESS=true \
-	WINDOWS=true \
-	GINKGO_SKIP="\[Disruptive\]|\[Serial\]|\[LinuxOnly\]|\[Feature:VolumeSnapshotDataSource\]|\(xfs\)|\(ext4\)|\(block volmode\)" \
-	GINKGO_PARALLEL=15 \
-	EBS_INSTALL_SNAPSHOT="false" \
-	./hack/e2e/run.sh
-
 .PHONY: e2e/external-kustomize
 e2e/external-kustomize: bin/kubetest2
 	DEPLOY_METHOD="kustomize" \
diff --git a/charts/aws-ebs-csi-driver/templates/_node-windows.tpl b/charts/aws-ebs-csi-driver/templates/_node-windows.tpl
index ab17f71e..56e8dcfa 100644
--- a/charts/aws-ebs-csi-driver/templates/_node-windows.tpl
+++ b/charts/aws-ebs-csi-driver/templates/_node-windows.tpl
@@ -49,21 +49,10 @@ spec:
         {{- toYaml . | nindent 8 }}
         {{- end }}
         {{- end }}
-      {{- if .Values.node.windowsHostProcess }}
-      securityContext:
-        windowsOptions:
-          hostProcess: true
-          runAsUserName: "NT AUTHORITY\\SYSTEM"
-      hostNetwork: true
-      {{- end }}
       containers:
         - name: ebs-plugin
           image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.image.repository (default (printf "v%s" .Chart.AppVersion) (toString .Values.image.tag)) }}
           imagePullPolicy: {{ .Values.image.pullPolicy }}
-          {{- if .Values.node.windowsHostProcess }}
-          command:
-            - "aws-ebs-csi-driver.exe"
-          {{- end }}
           args:
             - node
             - --endpoint=$(CSI_ENDPOINT)
@@ -77,16 +66,9 @@ spec:
             {{- if .Values.node.otelTracing }}
             - --enable-otel-tracing=true
             {{- end}}
-            {{- if .Values.node.windowsHostProcess }}
-            - --windows-host-process=true
-            {{- end }}
           env:
             - name: CSI_ENDPOINT
-            {{- if .Values.node.windowsHostProcess }}
-              value: unix://C:\\var\\lib\\kubelet\\plugins\\ebs.csi.aws.com\\csi.sock
-            {{- else }}
               value: unix:/csi/csi.sock
-            {{- end }}
             - name: CSI_NODE_NAME
               valueFrom:
                 fieldRef:
@@ -109,14 +91,12 @@ spec:
               mountPropagation: "None"
             - name: plugin-dir
               mountPath: C:\csi
-          {{- if not .Values.node.windowsHostProcess }}
             - name: csi-proxy-disk-pipe
               mountPath: \\.\pipe\csi-proxy-disk-v1
             - name: csi-proxy-volume-pipe
               mountPath: \\.\pipe\csi-proxy-volume-v1
             - name: csi-proxy-filesystem-pipe
               mountPath: \\.\pipe\csi-proxy-filesystem-v1
-          {{- end }}
           ports:
             - name: healthz
               containerPort: 9808
@@ -133,11 +113,9 @@ spec:
           resources:
             {{- toYaml . | nindent 12 }}
           {{- end }}
-          {{- if not .Values.node.windowsHostProcess }}
           securityContext:
             windowsOptions:
               runAsUserName: "ContainerAdministrator"
-          {{- end }}
           lifecycle:
             preStop:
               exec:
@@ -145,34 +123,15 @@ spec:
         - name: node-driver-registrar
           image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.nodeDriverRegistrar.image.repository .Values.sidecars.nodeDriverRegistrar.image.tag }}
           imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.nodeDriverRegistrar.image.pullPolicy }}
-          {{- if .Values.node.windowsHostProcess }}
-          command:
-            - "csi-node-driver-registrar.exe"
-          {{- end }}
           args:
             - --csi-address=$(ADDRESS)
             - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH)
-          {{- if .Values.node.windowsHostProcess }}
-            - --plugin-registration-path=$(PLUGIN_REG_DIR)
-          {{- end }}
             - --v={{ .Values.sidecars.nodeDriverRegistrar.logLevel }}
           env:
             - name: ADDRESS
-            {{- if .Values.node.windowsHostProcess }}
-              value: unix://C:\\var\\lib\\kubelet\\plugins\\ebs.csi.aws.com\\csi.sock
-            {{- else }}
               value: unix:/csi/csi.sock
-            {{- end }}
             - name: DRIVER_REG_SOCK_PATH
-            {{- if .Values.node.windowsHostProcess }}
-              value: C:\\var\\lib\\kubelet\\plugins\\ebs.csi.aws.com\\csi.sock
-            {{- else }}
               value: C:\var\lib\kubelet\plugins\ebs.csi.aws.com\csi.sock
-            {{- end }}
-          {{- if .Values.node.windowsHostProcess }}
-            - name: PLUGIN_REG_DIR
-              value: C:\\var\\lib\\kubelet\\plugins_registry\\
-          {{- end }}
             {{- if .Values.proxy.http_proxy }}
             {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }}
             {{- end }}
@@ -202,16 +161,8 @@ spec:
         - name: liveness-probe
           image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.livenessProbe.image.repository .Values.sidecars.livenessProbe.image.tag }}
           imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.livenessProbe.image.pullPolicy }}
-          {{- if .Values.node.windowsHostProcess }}
-          command:
-            - "livenessprobe.exe"
-          {{- end }}
           args:
-            {{- if .Values.node.windowsHostProcess }}
-            - --csi-address=unix://C:\\var\\lib\\kubelet\\plugins\\ebs.csi.aws.com\\csi.sock
-            {{- else }}
             - --csi-address=unix:/csi/csi.sock
-            {{- end }}
           volumeMounts:
             - name: plugin-dir
               mountPath: C:\csi
@@ -238,7 +189,6 @@ spec:
           hostPath:
             path: C:\var\lib\kubelet\plugins_registry
             type: Directory
-      {{- if not .Values.node.windowsHostProcess }}
         - name: csi-proxy-disk-pipe
           hostPath:
             path: \\.\pipe\csi-proxy-disk-v1
@@ -251,7 +201,6 @@ spec:
           hostPath:
             path: \\.\pipe\csi-proxy-filesystem-v1
             type: ""
-      {{- end }}
         - name: probe-dir
           {{- if .Values.node.probeDirVolume }}
           {{- toYaml .Values.node.probeDirVolume | nindent 10 }}
diff --git a/cmd/main.go b/cmd/main.go
index 47962f7a..417ec491 100644
--- a/cmd/main.go
+++ b/cmd/main.go
@@ -173,15 +173,14 @@ func main() {
 		klog.FlushAndExit(klog.ExitFlushTimeout, 1)
 	}
 
-	m, err := mounter.NewNodeMounter(options.WindowsHostProcess)
+	m, err := mounter.NewNodeMounter()
 	if err != nil {
-		klog.ErrorS(err, "failed to create node mounter")
-		klog.FlushAndExit(klog.ExitFlushTimeout, 1)
+		panic(err)
 	}
 
 	k8sClient, err := cfg.K8sAPIClient()
 	if err != nil {
-		klog.V(2).InfoS("Failed to setup k8s client", "err", err)
+		klog.V(2).InfoS("Failed to setup k8s client")
 	}
 
 	drv, err := driver.NewDriver(cloud, &options, m, md, k8sClient)
diff --git a/go.mod b/go.mod
index 8cd561ef..954cedd5 100644
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,6 @@ require (
 	github.com/google/go-cmp v0.6.0
 	github.com/google/uuid v1.6.0
 	github.com/kubernetes-csi/csi-proxy/client v1.1.3
-	github.com/kubernetes-csi/csi-proxy/v2 v2.0.0-alpha.1
 	github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0
 	github.com/onsi/ginkgo/v2 v2.17.1
 	github.com/onsi/gomega v1.33.0
diff --git a/go.sum b/go.sum
index d783105e..3a1fb734 100644
--- a/go.sum
+++ b/go.sum
@@ -752,7 +752,6 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
 github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U=
 github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk=
 github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
-github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
 github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
@@ -967,8 +966,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/kubernetes-csi/csi-proxy/client v1.1.3 h1:FdGU7NtxGhQX2wTfnuscmThG920hq0OaVVpuJW9t2k0=
 github.com/kubernetes-csi/csi-proxy/client v1.1.3/go.mod h1:SfK4HVKQdMH5KrffivddAWgX5hl3P5KmnuOTBbDNboU=
-github.com/kubernetes-csi/csi-proxy/v2 v2.0.0-alpha.1 h1:tVPvlL5N5X598hrO3g9rhyoi6h0LP4RpSJlGHItsbEE=
-github.com/kubernetes-csi/csi-proxy/v2 v2.0.0-alpha.1/go.mod h1:pacx+PW7lLlu6kAvpr8Lgq/5fdiAsKxOtXXFHMaLMb8=
 github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0 h1:nHHjmvjitIiyPlUHk/ofpgvBcNcawJLtf4PYHORLjAA=
 github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0/go.mod h1:YBCo4DoEeDndqvAn6eeu0vWM7QdXmHEeI9cFWplmBys=
 github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
@@ -1983,7 +1980,6 @@ k8s.io/csi-translation-lib v0.30.0 h1:pEe6jshNVE4od2AdgYlsAtiKP/MH+NcsBbUPA/dWA6
 k8s.io/csi-translation-lib v0.30.0/go.mod h1:5TT/awOiKEX+8CcbReVYJyddT7xqlFrp3ChE9e45MyU=
 k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8=
 k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
-k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
 k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
 k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
 k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
diff --git a/hack/update-mockgen.sh b/hack/update-mockgen.sh
index ec78cfd3..10cd3ed6 100755
--- a/hack/update-mockgen.sh
+++ b/hack/update-mockgen.sh
@@ -22,6 +22,7 @@ BIN="$(dirname "$(realpath "${BASH_SOURCE[0]}")")/../bin"
 "${BIN}/mockgen" -package cloud -destination=./pkg/cloud/mock_cloud.go -source pkg/cloud/interface.go
 "${BIN}/mockgen" -package metadata -destination=./pkg/cloud/metadata/mock_metadata.go -source pkg/cloud/metadata/interface.go
 "${BIN}/mockgen" -package mounter -destination=./pkg/mounter/mock_mount.go -source pkg/mounter/mount.go
+"${BIN}/mockgen" -package mounter -destination=./pkg/mounter/mock_mount_windows.go -source pkg/mounter/safe_mounter_windows.go
 "${BIN}/mockgen" -package cloud -destination=./pkg/cloud/mock_ec2.go -source pkg/cloud/ec2_interface.go EC2API
 
 # Reflection-based mocking for external dependencies
diff --git a/pkg/cloud/cloud.go b/pkg/cloud/cloud.go
index fa8aea89..9889c6c1 100644
--- a/pkg/cloud/cloud.go
+++ b/pkg/cloud/cloud.go
@@ -86,20 +86,6 @@ var (
 		VolumeTypeST1,
 		VolumeTypeStandard,
 	}
-
-	volumeCreationPollInitialDelay    = 1250 * time.Millisecond
-	volumeCreationPollBackoffDuration = 500 * time.Millisecond
-	volumeCreationPollBackoffFactor   = 1.5
-	volumeCreationPollBackoffSteps    = 25
-	volumeCreationPollBackoffCap      = 3 * time.Second
-
-	volumeModificationDuration   = 1 * time.Second
-	volumeModificationWaitFactor = 1.7
-	volumeModificationWaitSteps  = 10
-
-	volumeAttachmentStatePollSteps  = 13
-	volumeAttachmentStatePollDelay  = 1 * time.Second
-	volumeAttachmentStatePollFactor = 1.8
 )
 
 const (
@@ -265,6 +251,47 @@ type ec2ListSnapshotsResponse struct {
 	NextToken *string
 }
 
+// volumeWaitParameters dictates how to poll for volume events.
+// E.g. how often to check if volume is created after an EC2 CreateVolume call.
+type volumeWaitParameters struct {
+	creationInitialDelay time.Duration
+	creationBackoff      wait.Backoff
+	modificationBackoff  wait.Backoff
+	attachmentBackoff    wait.Backoff
+}
+
+var (
+	vwp = volumeWaitParameters{
+		// Based on our testing in us-west-2 and ap-south-1, the median/p99 time until volume creation is ~1.5/~4 seconds.
+		// We have found that the following parameters are optimal for minimizing provisioning time and DescribeVolumes calls
+		// we queue DescribeVolume calls after [1.25, 0.5, 0.75, 1.125, 1.7, 2.5, 3] seconds.
+		// In total, we wait for ~60 seconds.
+		creationInitialDelay: 1250 * time.Millisecond,
+		creationBackoff: wait.Backoff{
+			Duration: 500 * time.Millisecond,
+			Factor:   1.5,
+			Steps:    25,
+			Cap:      3 * time.Second,
+		},
+
+		// Most attach/detach operations on AWS finish within 1-4 seconds.
+		// By using 1 second starting interval with a backoff of 1.8,
+		// we get [1, 1.8, 3.24, 5.832000000000001, 10.4976].
+		// In total, we wait for 2601 seconds.
+		attachmentBackoff: wait.Backoff{
+			Duration: 1 * time.Second,
+			Factor:   1.8,
+			Steps:    13,
+		},
+
+		modificationBackoff: wait.Backoff{
+			Duration: 1 * time.Second,
+			Factor:   1.7,
+			Steps:    10,
+		},
+	}
+)
+
 // volumeBatcherType is an enum representing the types of volume batchers available.
 type volumeBatcherType int
 
@@ -287,6 +314,7 @@ type cloud struct {
 	dm     dm.DeviceManager
 	bm     *batcherManager
 	rm     *retryManager
+	vwp    volumeWaitParameters
 }
 
 var _ Cloud = &cloud{}
@@ -343,14 +371,13 @@ func newEC2Cloud(region string, awsSdkDebugLog bool, userAgentExtra string, batc
 		bm = newBatcherManager(svc)
 	}
 
-	rm := newRetryManager()
-
 	return &cloud{
 		region: region,
 		dm:     dm.NewDeviceManager(),
 		ec2:    svc,
 		bm:     bm,
-		rm:     rm,
+		rm:     newRetryManager(),
+		vwp:    vwp,
 	}
 }
 
@@ -967,16 +994,6 @@ func (c *cloud) DetachDisk(ctx context.Context, volumeID, nodeID string) error {
 
 // WaitForAttachmentState polls until the attachment status is the expected value.
 func (c *cloud) WaitForAttachmentState(ctx context.Context, volumeID, expectedState string, expectedInstance string, expectedDevice string, alreadyAssigned bool) (*types.VolumeAttachment, error) {
-	// Most attach/detach operations on AWS finish within 1-4 seconds.
-	// By using 1 second starting interval with a backoff of 1.8,
-	// we get [1, 1.8, 3.24, 5.832000000000001, 10.4976].
-	// In total we wait for 2601 seconds.
-	backoff := wait.Backoff{
-		Duration: volumeAttachmentStatePollDelay,
-		Factor:   volumeAttachmentStatePollFactor,
-		Steps:    volumeAttachmentStatePollSteps,
-	}
-
 	var attachment *types.VolumeAttachment
 
 	verifyVolumeFunc := func(ctx context.Context) (bool, error) {
@@ -1063,7 +1080,7 @@ func (c *cloud) WaitForAttachmentState(ctx context.Context, volumeID, expectedSt
 		return false, nil
 	}
 
-	return attachment, wait.ExponentialBackoffWithContext(ctx, backoff, verifyVolumeFunc)
+	return attachment, wait.ExponentialBackoffWithContext(ctx, c.vwp.attachmentBackoff, verifyVolumeFunc)
 }
 
 func (c *cloud) GetDiskByName(ctx context.Context, name string, capacityBytes int64) (*Disk, error) {
@@ -1533,26 +1550,13 @@ func (c *cloud) listSnapshots(ctx context.Context, request *ec2.DescribeSnapshot
 
 // waitForVolume waits for volume to be in the "available" state.
 func (c *cloud) waitForVolume(ctx context.Context, volumeID string) error {
-	// Based on our testing in us-west-2 and ap-south-1, the median/p99 time until volume creation is ~1.5/~4 seconds.
-	// We have found that the following parameters are optimal for minimizing provisioning time and DescribeVolumes calls
-	// we queue DescribeVolume calls after [1.25, 0.5, 0.75, 1.125, 1.7, 2.5, 3] seconds.
-	// In total, we wait for ~60 seconds.
-	var (
-		backoff = wait.Backoff{
-			Duration: volumeCreationPollBackoffDuration,
-			Factor:   volumeCreationPollBackoffFactor,
-			Steps:    volumeCreationPollBackoffSteps,
-			Cap:      volumeCreationPollBackoffCap,
-		}
-	)
-
-	time.Sleep(volumeCreationPollInitialDelay)
+	time.Sleep(c.vwp.creationInitialDelay)
 
 	request := &ec2.DescribeVolumesInput{
 		VolumeIds: []string{volumeID},
 	}
 
-	err := wait.ExponentialBackoffWithContext(ctx, backoff, func(ctx context.Context) (done bool, err error) {
+	err := wait.ExponentialBackoffWithContext(ctx, c.vwp.creationBackoff, func(ctx context.Context) (done bool, err error) {
 		vol, err := c.getVolume(ctx, request)
 		if err != nil {
 			return true, err
@@ -1682,13 +1686,7 @@ func (c *cloud) checkDesiredState(ctx context.Context, volumeID string, desiredS
 
 // waitForVolumeModification waits for a volume modification to finish.
 func (c *cloud) waitForVolumeModification(ctx context.Context, volumeID string) error {
-	backoff := wait.Backoff{
-		Duration: volumeModificationDuration,
-		Factor:   volumeModificationWaitFactor,
-		Steps:    volumeModificationWaitSteps,
-	}
-
-	waitErr := wait.ExponentialBackoff(backoff, func() (bool, error) {
+	waitErr := wait.ExponentialBackoff(c.vwp.modificationBackoff, func() (bool, error) {
 		m, err := c.getLatestVolumeModification(ctx, volumeID, true)
 		// Consider volumes that have never been modified as done
 		if err != nil && errors.Is(err, VolumeNotBeingModified) {
diff --git a/pkg/cloud/metadata/k8s.go b/pkg/cloud/metadata/k8s.go
index 4ff8dd63..c288f634 100644
--- a/pkg/cloud/metadata/k8s.go
+++ b/pkg/cloud/metadata/k8s.go
@@ -2,19 +2,14 @@ package metadata
 
 import (
 	"context"
-	"errors"
 	"fmt"
-	"net"
 	"os"
-	"path/filepath"
 	"regexp"
 
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/client-go/kubernetes"
 	"k8s.io/client-go/rest"
-	"k8s.io/client-go/util/cert"
-	"k8s.io/klog/v2"
 )
 
 type KubernetesAPIClient func() (kubernetes.Interface, error)
@@ -23,39 +18,7 @@ var DefaultKubernetesAPIClient = func() (kubernetes.Interface, error) {
 	// creates the in-cluster config
 	config, err := rest.InClusterConfig()
 	if err != nil {
-		if errors.Is(err, os.ErrNotExist) {
-			klog.InfoS("InClusterConfig failed to read token file, retrieving file from sandbox mount point")
-			// CONTAINER_SANDBOX_MOUNT_POINT env is set upon container creation in containerd v1.6+
-			// it provides the absolute host path to the container volume.
-			sandboxMountPoint := os.Getenv("CONTAINER_SANDBOX_MOUNT_POINT")
-			if sandboxMountPoint == "" {
-				return nil, fmt.Errorf("CONTAINER_SANDBOX_MOUNT_POINT environment variable is not set")
-			}
-
-			tokenFile := filepath.Join(sandboxMountPoint, "var", "run", "secrets", "kubernetes.io", "serviceaccount", "token")
-			rootCAFile := filepath.Join(sandboxMountPoint, "var", "run", "secrets", "kubernetes.io", "serviceaccount", "ca.crt")
-
-			token, tokenErr := os.ReadFile(tokenFile)
-			if err != nil {
-				return nil, tokenErr
-			}
-
-			tlsClientConfig := rest.TLSClientConfig{}
-			if _, certErr := cert.NewPool(rootCAFile); err != nil {
-				return nil, fmt.Errorf("expected to load root CA config from %s, but got err: %w", rootCAFile, certErr)
-			} else {
-				tlsClientConfig.CAFile = rootCAFile
-			}
-
-			config = &rest.Config{
-				Host:            "https://" + net.JoinHostPort(os.Getenv("KUBERNETES_SERVICE_HOST"), os.Getenv("KUBERNETES_SERVICE_PORT")),
-				TLSClientConfig: tlsClientConfig,
-				BearerToken:     string(token),
-				BearerTokenFile: tokenFile,
-			}
-		} else {
-			return nil, err
-		}
+		return nil, err
 	}
 	// creates the clientset
 	clientset, err := kubernetes.NewForConfig(config)
diff --git a/pkg/cloud/retry_manager.go b/pkg/cloud/retry_manager.go
index 5258d38d..077991d7 100644
--- a/pkg/cloud/retry_manager.go
+++ b/pkg/cloud/retry_manager.go
@@ -1,3 +1,19 @@
+/*
+Copyright 2024 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package cloud
 
 import (
diff --git a/pkg/coalescer/coalescer.go b/pkg/coalescer/coalescer.go
deleted file mode 100644
index 3eb0a82e..00000000
--- a/pkg/coalescer/coalescer.go
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
-Copyright 2024 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Package coalescer combines multiple requests made over a period of time into a single request
-package coalescer
-
-import (
-	"time"
-
-	"k8s.io/klog/v2"
-)
-
-// Coalescer is an interface to combine multiple requests made over a period of time into a single request
-//
-// When a request is received that matches an existing in-flight request, the coalescer will attempt to
-// merge that request into the existing request pool using the provided mergeFunction
-//
-// When the delay on the request expires (determined by the time the first request comes in), the merged
-// input is passed to the execution function, and the result to all waiting callers (those that were
-// not rejected during the merge step)
-type Coalescer[InputType comparable, ResultType any] interface {
-	// Coalesce is a function to coalesce a given input
-	// key = only requests with this same key will be coalesced (such as volume ID)
-	// input = input to merge with other inputs
-	// It is NOT guaranteed all callers receive the same result (for example, if
-	// an input fails to merge, only that caller will receive an error)
-	Coalesce(key string, input InputType) (ResultType, error)
-}
-
-// New is a function to creates a new coalescer and immediately begin processing requests
-// delay = the time to wait for other requests to coalesce before executing
-// mergeFunction = a function to merge a new input with the existing inputs
-// (should return an error if the new input cannot be combined with the existing inputs,
-// otherwise return the new merged input)
-// executeFunction = the function to call when the delay expires
-func New[InputType comparable, ResultType any](delay time.Duration,
-	mergeFunction func(input InputType, existing InputType) (InputType, error),
-	executeFunction func(key string, input InputType) (ResultType, error),
-) Coalescer[InputType, ResultType] {
-	c := coalescer[InputType, ResultType]{
-		delay:           delay,
-		mergeFunction:   mergeFunction,
-		executeFunction: executeFunction,
-		inputChannel:    make(chan newInput[InputType, ResultType]),
-		timerChannel:    make(chan string),
-		pendingInputs:   make(map[string]pendingInput[InputType, ResultType]),
-	}
-
-	go c.coalescerThread()
-	return &c
-}
-
-// Type to store a result or error in channels
-type result[ResultType any] struct {
-	result ResultType
-	err    error
-}
-
-// Type to send inputs from Coalesce() to coalescerThread() via channel
-// Includes a return channel for the result
-type newInput[InputType comparable, ResultType any] struct {
-	key           string
-	input         InputType
-	resultChannel chan result[ResultType]
-}
-
-// Type to store pending inputs in the input map
-type pendingInput[InputType comparable, ResultType any] struct {
-	input          InputType
-	resultChannels []chan result[ResultType]
-}
-
-type coalescer[InputType comparable, ResultType any] struct {
-	delay           time.Duration
-	mergeFunction   func(input InputType, existing InputType) (InputType, error)
-	executeFunction func(key string, input InputType) (ResultType, error)
-
-	inputChannel chan newInput[InputType, ResultType]
-	timerChannel chan string
-
-	pendingInputs map[string]pendingInput[InputType, ResultType]
-}
-
-func (c *coalescer[InputType, ResultType]) Coalesce(key string, input InputType) (ResultType, error) {
-	resultChannel := make(chan result[ResultType])
-
-	c.inputChannel <- newInput[InputType, ResultType]{
-		key:           key,
-		input:         input,
-		resultChannel: resultChannel,
-	}
-	result := <-resultChannel
-
-	if result.err != nil {
-		return *new(ResultType), result.err
-	} else {
-		return result.result, nil
-	}
-}
-
-func (c *coalescer[InputType, ResultType]) coalescerThread() {
-	for {
-		select {
-		case i := <-c.inputChannel:
-			klog.V(7).InfoS("coalescerThread: Input received", "key", i.key, "input", i.input)
-			if pending, ok := c.pendingInputs[i.key]; ok {
-				klog.V(7).InfoS("coalescerThread: Input matched existing input, attempting to merge", "key", i.key)
-				newInput, err := c.mergeFunction(i.input, pending.input)
-
-				if err == nil {
-					klog.V(7).InfoS("coalescerThread: Merged input into existing inputs", "key", i.key)
-					pending.input = newInput
-					pending.resultChannels = append(pending.resultChannels, i.resultChannel)
-					c.pendingInputs[i.key] = pending
-				} else {
-					klog.V(7).InfoS("coalescerThread: Failed to merge inputs into existing inputs", "key", i.key)
-					i.resultChannel <- result[ResultType]{
-						err: err,
-					}
-				}
-			} else {
-				klog.V(7).InfoS("coalescerThread: New input, setting up fresh coalesce operation", "key", i.key)
-				c.pendingInputs[i.key] = pendingInput[InputType, ResultType]{
-					input: i.input,
-					resultChannels: []chan result[ResultType]{
-						i.resultChannel,
-					},
-				}
-				time.AfterFunc(c.delay, func() {
-					c.timerChannel <- i.key
-				})
-			}
-
-		case k := <-c.timerChannel:
-			klog.V(7).InfoS("coalescerThread: Coalescing delay reached, spawning execution thread", "key", k)
-			pending := c.pendingInputs[k]
-			delete(c.pendingInputs, k)
-
-			go func() {
-				r, err := c.executeFunction(k, pending.input)
-				klog.V(7).InfoS("coalescerThread: Finished executing", "key", k, "result", r, "error", err)
-				result := result[ResultType]{
-					result: r,
-					err:    err,
-				}
-				for _, c := range pending.resultChannels {
-					c <- result
-				}
-			}()
-		}
-	}
-}
diff --git a/pkg/driver/driver.go b/pkg/driver/driver.go
index 2e73a2c9..63471429 100644
--- a/pkg/driver/driver.go
+++ b/pkg/driver/driver.go
@@ -91,7 +91,7 @@ func NewDriver(c cloud.Cloud, o *Options, m mounter.Mounter, md metadata.Metadat
 }
 
 func (d *Driver) Run() error {
-	scheme, addr, err := util.ParseEndpoint(d.options.Endpoint, d.options.WindowsHostProcess)
+	scheme, addr, err := util.ParseEndpoint(d.options.Endpoint)
 	if err != nil {
 		return err
 	}
diff --git a/pkg/driver/options.go b/pkg/driver/options.go
index d06f9878..2a4a8165 100644
--- a/pkg/driver/options.go
+++ b/pkg/driver/options.go
@@ -81,8 +81,6 @@ type Options struct {
 	// When -1, the amount of reserved attachments is loaded from instance metadata that captured state at node boot
 	// and may include not only system disks but also CSI volumes (and therefore it may be wrong).
 	ReservedVolumeAttachments int
-	// ALPHA: WindowsHostProcess indicates whether the driver is running in a Windows privileged container
-	WindowsHostProcess bool
 }
 
 func (o *Options) AddFlags(f *flag.FlagSet) {
@@ -108,7 +106,6 @@ func (o *Options) AddFlags(f *flag.FlagSet) {
 	if o.Mode == AllMode || o.Mode == NodeMode {
 		f.Int64Var(&o.VolumeAttachLimit, "volume-attach-limit", -1, "Value for the maximum number of volumes attachable per node. If specified, the limit applies to all nodes and overrides --reserved-volume-attachments. If not specified, the value is approximated from the instance type.")
 		f.IntVar(&o.ReservedVolumeAttachments, "reserved-volume-attachments", -1, "Number of volume attachments reserved for system use. Not used when --volume-attach-limit is specified. The total amount of volume attachments for a node is computed as: <nr. of attachments for corresponding instance type> - <number of NICs, if relevant to the instance type> - <reserved-volume-attachments value>. When -1, the amount of reserved attachments is loaded from instance metadata that captured state at node boot and may include not only system disks but also CSI volumes.")
-		f.BoolVar(&o.WindowsHostProcess, "windows-host-process", false, "ALPHA: Indicates whether the driver is running in a Windows privileged container")
 	}
 }
 
diff --git a/pkg/mounter/mock_mount_windows.go b/pkg/mounter/mock_mount_windows.go
new file mode 100644
index 00000000..0c5ffe98
--- /dev/null
+++ b/pkg/mounter/mock_mount_windows.go
@@ -0,0 +1,351 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: pkg/mounter/safe_mounter_windows.go
+
+// Package mounter is a generated GoMock package.
+package mounter
+
+import (
+	reflect "reflect"
+
+	gomock "github.com/golang/mock/gomock"
+	mount "k8s.io/mount-utils"
+)
+
+// MockProxyMounter is a mock of ProxyMounter interface.
+type MockProxyMounter struct {
+	ctrl     *gomock.Controller
+	recorder *MockProxyMounterMockRecorder
+}
+
+// MockProxyMounterMockRecorder is the mock recorder for MockProxyMounter.
+type MockProxyMounterMockRecorder struct {
+	mock *MockProxyMounter
+}
+
+// NewMockProxyMounter creates a new mock instance.
+func NewMockProxyMounter(ctrl *gomock.Controller) *MockProxyMounter {
+	mock := &MockProxyMounter{ctrl: ctrl}
+	mock.recorder = &MockProxyMounterMockRecorder{mock}
+	return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockProxyMounter) EXPECT() *MockProxyMounterMockRecorder {
+	return m.recorder
+}
+
+// CanSafelySkipMountPointCheck mocks base method.
+func (m *MockProxyMounter) CanSafelySkipMountPointCheck() bool {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CanSafelySkipMountPointCheck")
+	ret0, _ := ret[0].(bool)
+	return ret0
+}
+
+// CanSafelySkipMountPointCheck indicates an expected call of CanSafelySkipMountPointCheck.
+func (mr *MockProxyMounterMockRecorder) CanSafelySkipMountPointCheck() *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CanSafelySkipMountPointCheck", reflect.TypeOf((*MockProxyMounter)(nil).CanSafelySkipMountPointCheck))
+}
+
+// ExistsPath mocks base method.
+func (m *MockProxyMounter) ExistsPath(path string) (bool, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ExistsPath", path)
+	ret0, _ := ret[0].(bool)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// ExistsPath indicates an expected call of ExistsPath.
+func (mr *MockProxyMounterMockRecorder) ExistsPath(path interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExistsPath", reflect.TypeOf((*MockProxyMounter)(nil).ExistsPath), path)
+}
+
+// FindDiskByLun mocks base method.
+func (m *MockProxyMounter) FindDiskByLun(lun string) (string, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FindDiskByLun", lun)
+	ret0, _ := ret[0].(string)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// FindDiskByLun indicates an expected call of FindDiskByLun.
+func (mr *MockProxyMounterMockRecorder) FindDiskByLun(lun interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindDiskByLun", reflect.TypeOf((*MockProxyMounter)(nil).FindDiskByLun), lun)
+}
+
+// FormatAndMountSensitiveWithFormatOptions mocks base method.
+func (m *MockProxyMounter) FormatAndMountSensitiveWithFormatOptions(source, target, fstype string, options, sensitiveOptions, formatOptions []string) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FormatAndMountSensitiveWithFormatOptions", source, target, fstype, options, sensitiveOptions, formatOptions)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// FormatAndMountSensitiveWithFormatOptions indicates an expected call of FormatAndMountSensitiveWithFormatOptions.
+func (mr *MockProxyMounterMockRecorder) FormatAndMountSensitiveWithFormatOptions(source, target, fstype, options, sensitiveOptions, formatOptions interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FormatAndMountSensitiveWithFormatOptions", reflect.TypeOf((*MockProxyMounter)(nil).FormatAndMountSensitiveWithFormatOptions), source, target, fstype, options, sensitiveOptions, formatOptions)
+}
+
+// GetDeviceNameFromMount mocks base method.
+func (m *MockProxyMounter) GetDeviceNameFromMount(mountPath, pluginMountDir string) (string, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetDeviceNameFromMount", mountPath, pluginMountDir)
+	ret0, _ := ret[0].(string)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetDeviceNameFromMount indicates an expected call of GetDeviceNameFromMount.
+func (mr *MockProxyMounterMockRecorder) GetDeviceNameFromMount(mountPath, pluginMountDir interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDeviceNameFromMount", reflect.TypeOf((*MockProxyMounter)(nil).GetDeviceNameFromMount), mountPath, pluginMountDir)
+}
+
+// GetDeviceSize mocks base method.
+func (m *MockProxyMounter) GetDeviceSize(devicePath string) (int64, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetDeviceSize", devicePath)
+	ret0, _ := ret[0].(int64)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetDeviceSize indicates an expected call of GetDeviceSize.
+func (mr *MockProxyMounterMockRecorder) GetDeviceSize(devicePath interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDeviceSize", reflect.TypeOf((*MockProxyMounter)(nil).GetDeviceSize), devicePath)
+}
+
+// GetMountRefs mocks base method.
+func (m *MockProxyMounter) GetMountRefs(pathname string) ([]string, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetMountRefs", pathname)
+	ret0, _ := ret[0].([]string)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetMountRefs indicates an expected call of GetMountRefs.
+func (mr *MockProxyMounterMockRecorder) GetMountRefs(pathname interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMountRefs", reflect.TypeOf((*MockProxyMounter)(nil).GetMountRefs), pathname)
+}
+
+// GetVolumeSizeInBytes mocks base method.
+func (m *MockProxyMounter) GetVolumeSizeInBytes(deviceMountPath string) (int64, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetVolumeSizeInBytes", deviceMountPath)
+	ret0, _ := ret[0].(int64)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetVolumeSizeInBytes indicates an expected call of GetVolumeSizeInBytes.
+func (mr *MockProxyMounterMockRecorder) GetVolumeSizeInBytes(deviceMountPath interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVolumeSizeInBytes", reflect.TypeOf((*MockProxyMounter)(nil).GetVolumeSizeInBytes), deviceMountPath)
+}
+
+// IsLikelyNotMountPoint mocks base method.
+func (m *MockProxyMounter) IsLikelyNotMountPoint(file string) (bool, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "IsLikelyNotMountPoint", file)
+	ret0, _ := ret[0].(bool)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// IsLikelyNotMountPoint indicates an expected call of IsLikelyNotMountPoint.
+func (mr *MockProxyMounterMockRecorder) IsLikelyNotMountPoint(file interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsLikelyNotMountPoint", reflect.TypeOf((*MockProxyMounter)(nil).IsLikelyNotMountPoint), file)
+}
+
+// IsMountPoint mocks base method.
+func (m *MockProxyMounter) IsMountPoint(file string) (bool, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "IsMountPoint", file)
+	ret0, _ := ret[0].(bool)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// IsMountPoint indicates an expected call of IsMountPoint.
+func (mr *MockProxyMounterMockRecorder) IsMountPoint(file interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsMountPoint", reflect.TypeOf((*MockProxyMounter)(nil).IsMountPoint), file)
+}
+
+// IsMountPointMatch mocks base method.
+func (m *MockProxyMounter) IsMountPointMatch(mp mount.MountPoint, dir string) bool {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "IsMountPointMatch", mp, dir)
+	ret0, _ := ret[0].(bool)
+	return ret0
+}
+
+// IsMountPointMatch indicates an expected call of IsMountPointMatch.
+func (mr *MockProxyMounterMockRecorder) IsMountPointMatch(mp, dir interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsMountPointMatch", reflect.TypeOf((*MockProxyMounter)(nil).IsMountPointMatch), mp, dir)
+}
+
+// List mocks base method.
+func (m *MockProxyMounter) List() ([]mount.MountPoint, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "List")
+	ret0, _ := ret[0].([]mount.MountPoint)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// List indicates an expected call of List.
+func (mr *MockProxyMounterMockRecorder) List() *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockProxyMounter)(nil).List))
+}
+
+// MakeFile mocks base method.
+func (m *MockProxyMounter) MakeFile(pathname string) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "MakeFile", pathname)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// MakeFile indicates an expected call of MakeFile.
+func (mr *MockProxyMounterMockRecorder) MakeFile(pathname interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MakeFile", reflect.TypeOf((*MockProxyMounter)(nil).MakeFile), pathname)
+}
+
+// Mount mocks base method.
+func (m *MockProxyMounter) Mount(source, target, fstype string, options []string) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "Mount", source, target, fstype, options)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// Mount indicates an expected call of Mount.
+func (mr *MockProxyMounterMockRecorder) Mount(source, target, fstype, options interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Mount", reflect.TypeOf((*MockProxyMounter)(nil).Mount), source, target, fstype, options)
+}
+
+// MountSensitive mocks base method.
+func (m *MockProxyMounter) MountSensitive(source, target, fstype string, options, sensitiveOptions []string) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "MountSensitive", source, target, fstype, options, sensitiveOptions)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// MountSensitive indicates an expected call of MountSensitive.
+func (mr *MockProxyMounterMockRecorder) MountSensitive(source, target, fstype, options, sensitiveOptions interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MountSensitive", reflect.TypeOf((*MockProxyMounter)(nil).MountSensitive), source, target, fstype, options, sensitiveOptions)
+}
+
+// MountSensitiveWithoutSystemd mocks base method.
+func (m *MockProxyMounter) MountSensitiveWithoutSystemd(source, target, fstype string, options, sensitiveOptions []string) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "MountSensitiveWithoutSystemd", source, target, fstype, options, sensitiveOptions)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// MountSensitiveWithoutSystemd indicates an expected call of MountSensitiveWithoutSystemd.
+func (mr *MockProxyMounterMockRecorder) MountSensitiveWithoutSystemd(source, target, fstype, options, sensitiveOptions interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MountSensitiveWithoutSystemd", reflect.TypeOf((*MockProxyMounter)(nil).MountSensitiveWithoutSystemd), source, target, fstype, options, sensitiveOptions)
+}
+
+// MountSensitiveWithoutSystemdWithMountFlags mocks base method.
+func (m *MockProxyMounter) MountSensitiveWithoutSystemdWithMountFlags(source, target, fstype string, options, sensitiveOptions, mountFlags []string) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "MountSensitiveWithoutSystemdWithMountFlags", source, target, fstype, options, sensitiveOptions, mountFlags)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// MountSensitiveWithoutSystemdWithMountFlags indicates an expected call of MountSensitiveWithoutSystemdWithMountFlags.
+func (mr *MockProxyMounterMockRecorder) MountSensitiveWithoutSystemdWithMountFlags(source, target, fstype, options, sensitiveOptions, mountFlags interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MountSensitiveWithoutSystemdWithMountFlags", reflect.TypeOf((*MockProxyMounter)(nil).MountSensitiveWithoutSystemdWithMountFlags), source, target, fstype, options, sensitiveOptions, mountFlags)
+}
+
+// Rescan mocks base method.
+func (m *MockProxyMounter) Rescan() error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "Rescan")
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// Rescan indicates an expected call of Rescan.
+func (mr *MockProxyMounterMockRecorder) Rescan() *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Rescan", reflect.TypeOf((*MockProxyMounter)(nil).Rescan))
+}
+
+// ResizeVolume mocks base method.
+func (m *MockProxyMounter) ResizeVolume(deviceMountPath string) (bool, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ResizeVolume", deviceMountPath)
+	ret0, _ := ret[0].(bool)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// ResizeVolume indicates an expected call of ResizeVolume.
+func (mr *MockProxyMounterMockRecorder) ResizeVolume(deviceMountPath interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResizeVolume", reflect.TypeOf((*MockProxyMounter)(nil).ResizeVolume), deviceMountPath)
+}
+
+// Rmdir mocks base method.
+func (m *MockProxyMounter) Rmdir(path string) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "Rmdir", path)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// Rmdir indicates an expected call of Rmdir.
+func (mr *MockProxyMounterMockRecorder) Rmdir(path interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Rmdir", reflect.TypeOf((*MockProxyMounter)(nil).Rmdir), path)
+}
+
+// Unmount mocks base method.
+func (m *MockProxyMounter) Unmount(target string) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "Unmount", target)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// Unmount indicates an expected call of Unmount.
+func (mr *MockProxyMounterMockRecorder) Unmount(target interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unmount", reflect.TypeOf((*MockProxyMounter)(nil).Unmount), target)
+}
+
+// WriteVolumeCache mocks base method.
+func (m *MockProxyMounter) WriteVolumeCache(target string) {
+	m.ctrl.T.Helper()
+	m.ctrl.Call(m, "WriteVolumeCache", target)
+}
+
+// WriteVolumeCache indicates an expected call of WriteVolumeCache.
+func (mr *MockProxyMounterMockRecorder) WriteVolumeCache(target interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteVolumeCache", reflect.TypeOf((*MockProxyMounter)(nil).WriteVolumeCache), target)
+}
diff --git a/pkg/mounter/mount.go b/pkg/mounter/mount.go
index c75bfb4c..e4a69fd7 100644
--- a/pkg/mounter/mount.go
+++ b/pkg/mounter/mount.go
@@ -54,16 +54,9 @@ type NodeMounter struct {
 }
 
 // NewNodeMounter returns a new intsance of NodeMounter.
-func NewNodeMounter(hostprocess bool) (Mounter, error) {
-	var safeMounter *mountutils.SafeFormatAndMount
-	var err error
-
-	if hostprocess {
-		safeMounter, err = NewSafeMounterV2()
-	} else {
-		safeMounter, err = NewSafeMounter()
-	}
-
+func NewNodeMounter() (Mounter, error) {
+	// mounter.NewSafeMounter returns a SafeFormatAndMount
+	safeMounter, err := NewSafeMounter()
 	if err != nil {
 		return nil, err
 	}
diff --git a/pkg/mounter/mount_linux.go b/pkg/mounter/mount_linux.go
index 7df2219b..e2b6c6b0 100644
--- a/pkg/mounter/mount_linux.go
+++ b/pkg/mounter/mount_linux.go
@@ -32,7 +32,6 @@ import (
 	"golang.org/x/sys/unix"
 	"k8s.io/klog/v2"
 	mountutils "k8s.io/mount-utils"
-	utilexec "k8s.io/utils/exec"
 )
 
 const (
@@ -40,17 +39,6 @@ const (
 	diskPartitionSuffix     = ""
 )
 
-func NewSafeMounter() (*mountutils.SafeFormatAndMount, error) {
-	return &mountutils.SafeFormatAndMount{
-		Interface: mountutils.New(""),
-		Exec:      utilexec.New(),
-	}, nil
-}
-
-func NewSafeMounterV2() (*mountutils.SafeFormatAndMount, error) {
-	return nil, fmt.Errorf("NewSafeMounterV2 is not supported on this platform")
-}
-
 // FindDevicePath finds path of device and verifies its existence
 // if the device is not nvme, return the path directly
 // if the device is nvme, finds and returns the nvme device path eg. /dev/nvme1n1
diff --git a/pkg/mounter/mount_windows.go b/pkg/mounter/mount_windows.go
index afb4f411..15ceb1f6 100644
--- a/pkg/mounter/mount_windows.go
+++ b/pkg/mounter/mount_windows.go
@@ -20,29 +20,51 @@ limitations under the License.
 package mounter
 
 import (
+	"context"
 	"fmt"
-
 	"regexp"
+	"strconv"
+	"strings"
 
-	"github.com/kubernetes-sigs/aws-ebs-csi-driver/pkg/util"
-
+	diskapi "github.com/kubernetes-csi/csi-proxy/client/api/disk/v1"
+	diskclient "github.com/kubernetes-csi/csi-proxy/client/groups/disk/v1"
 	"k8s.io/klog/v2"
 	mountutils "k8s.io/mount-utils"
 )
 
-var (
-	ErrUnsupportedMounter = fmt.Errorf("unsupported mounter type")
+const (
+	DefaultBlockSize = 4096
 )
 
 func (m NodeMounter) FindDevicePath(devicePath, volumeID, _, _ string) (string, error) {
-	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
-	case *CSIProxyMounterV2:
-		return proxyMounter.FindDevicePath(devicePath, volumeID, "", "")
-	case *CSIProxyMounter:
-		return proxyMounter.FindDevicePath(devicePath, volumeID, "", "")
-	default:
-		return "", ErrUnsupportedMounter
+	diskClient, err := diskclient.NewClient()
+	if err != nil {
+		return "", fmt.Errorf("error creating csi-proxy disk client: %q", err)
+	}
+	defer diskClient.Close()
+
+	response, err := diskClient.ListDiskIDs(context.TODO(), &diskapi.ListDiskIDsRequest{})
+	if err != nil {
+		return "", fmt.Errorf("error listing disk ids: %q", err)
 	}
+
+	diskIDs := response.GetDiskIDs()
+
+	foundDiskNumber := ""
+	for diskNumber, diskID := range diskIDs {
+		serialNumber := diskID.GetSerialNumber()
+		cleanVolumeID := strings.ReplaceAll(volumeID, "-", "")
+		if strings.Contains(serialNumber, cleanVolumeID) {
+			foundDiskNumber = strconv.Itoa(int(diskNumber))
+			break
+		}
+	}
+
+	if foundDiskNumber == "" {
+		return "", fmt.Errorf("disk number for device path %q volume id %q not found", devicePath, volumeID)
+	}
+
+	return foundDiskNumber, nil
 }
 
 func (m NodeMounter) PreparePublishTarget(target string) error {
@@ -56,24 +78,16 @@ func (m NodeMounter) PreparePublishTarget(target string) error {
 		return fmt.Errorf("error checking path %q exists: %v", target, err)
 	}
 
-	if !exists {
-		return nil // If the target does not exist, no action is necessary
+	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
+	if !ok {
+		return fmt.Errorf("failed to cast mounter to csi proxy mounter")
 	}
 
-	// Handle different mounter implementations
-	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
-	case *CSIProxyMounterV2:
-		if err := proxyMounter.Rmdir(target); err != nil {
-			return fmt.Errorf("error Rmdir target %q: %v", target, err)
-		}
-	case *CSIProxyMounter:
+	if exists {
 		if err := proxyMounter.Rmdir(target); err != nil {
 			return fmt.Errorf("error Rmdir target %q: %v", target, err)
 		}
-	default:
-		return ErrUnsupportedMounter
 	}
-
 	return nil
 }
 
@@ -84,33 +98,25 @@ func (m NodeMounter) IsBlockDevice(fullPath string) (bool, error) {
 
 // getBlockSizeBytes gets the size of the disk in bytes
 func (m NodeMounter) GetBlockSizeBytes(devicePath string) (int64, error) {
-	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
-	case *CSIProxyMounterV2:
-		sizeInBytes, err := proxyMounter.GetDeviceSize(devicePath)
-		if err != nil {
-			return -1, err
-		}
-		return sizeInBytes, nil
-	case *CSIProxyMounter:
-		sizeInBytes, err := proxyMounter.GetDeviceSize(devicePath)
-		if err != nil {
-			return -1, err
-		}
-		return sizeInBytes, nil
-	default:
-		return -1, ErrUnsupportedMounter
+	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
+	if !ok {
+		return -1, fmt.Errorf("failed to cast mounter to csi proxy mounter")
+	}
+
+	sizeInBytes, err := proxyMounter.GetDeviceSize(devicePath)
+	if err != nil {
+		return -1, err
 	}
+
+	return sizeInBytes, nil
 }
 
 func (m NodeMounter) FormatAndMountSensitiveWithFormatOptions(source string, target string, fstype string, options []string, sensitiveOptions []string, formatOptions []string) error {
-	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
-	case *CSIProxyMounterV2:
-		return proxyMounter.FormatAndMountSensitiveWithFormatOptions(source, target, fstype, options, sensitiveOptions, formatOptions)
-	case *CSIProxyMounter:
-		return proxyMounter.FormatAndMountSensitiveWithFormatOptions(source, target, fstype, options, sensitiveOptions, formatOptions)
-	default:
-		return ErrUnsupportedMounter
+	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
+	if !ok {
+		return fmt.Errorf("failed to cast mounter to csi proxy mounter")
 	}
+	return proxyMounter.FormatAndMountSensitiveWithFormatOptions(source, target, fstype, options, sensitiveOptions, formatOptions)
 }
 
 // GetDeviceNameFromMount returns the volume ID for a mount path.
@@ -122,42 +128,30 @@ func (m NodeMounter) FormatAndMountSensitiveWithFormatOptions(source string, tar
 // Command to determine ref count would be something like:
 // Get-Volume -UniqueId "\\?\Volume{7c3da0c1-0000-0000-0000-010000000000}\" | Get-Partition | Select AccessPaths
 func (m NodeMounter) GetDeviceNameFromMount(mountPath string) (string, int, error) {
-	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
-	// HACK change csi-proxy behavior instead of relying on fragile internal
-	// implementation details!
-	// if err contains '"(Get-Item...).Target, output: , error: <nil>' then the
-	// internal Get-Item cmdlet didn't fail but no item/device was found at the
-	// path so we should return empty string and nil error just like the Linux
-	// implementation would.
-	case *CSIProxyMounterV2:
-		deviceName, err := proxyMounter.GetDeviceNameFromMount(mountPath, "")
-		if err != nil {
-			return handleGetDeviceNameFromMountError(err)
+	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
+	if !ok {
+		return "", 0, fmt.Errorf("failed to cast mounter to csi proxy mounter")
+	}
+	deviceName, err := proxyMounter.GetDeviceNameFromMount(mountPath, "")
+	if err != nil {
+		// HACK change csi-proxy behavior instead of relying on fragile internal
+		// implementation details!
+		// if err contains '"(Get-Item...).Target, output: , error: <nil>' then the
+		// internal Get-Item cmdlet didn't fail but no item/device was found at the
+		// path so we should return empty string and nil error just like the Linux
+		// implementation would.
+		pattern := `(Get-Item -Path \S+).Target, output: , error: <nil>|because it does not exist`
+		matched, matchErr := regexp.MatchString(pattern, err.Error())
+		if matched {
+			return "", 0, nil
 		}
-		return deviceName, 1, nil
-	case *CSIProxyMounter:
-		deviceName, err := proxyMounter.GetDeviceNameFromMount(mountPath, "")
-		if err != nil {
-			return handleGetDeviceNameFromMountError(err)
+		err = fmt.Errorf("error getting device name from mount: %v", err)
+		if matchErr != nil {
+			err = fmt.Errorf("%v, and error matching pattern %q: %v", err, pattern, matchErr)
 		}
-		return deviceName, 1, nil
-	default:
-		return "", 0, ErrUnsupportedMounter
+		return "", 0, err
 	}
-}
-
-// handleGetDeviceNameFromMountError processes common error patterns for GetDeviceNameFromMount
-func handleGetDeviceNameFromMountError(err error) (string, int, error) {
-	// Handling common error pattern as seen in previous implementations
-	pattern := `(Get-Item -Path \S+).Target, output: , error: <nil>|because it does not exist`
-	matched, matchErr := regexp.MatchString(pattern, err.Error())
-	if matched {
-		return "", 0, nil // No device found, but not an error condition
-	}
-	if matchErr != nil {
-		return "", 0, fmt.Errorf("error processing error message: %v, matching pattern %q: %v", err, pattern, matchErr)
-	}
-	return "", 0, fmt.Errorf("error getting device name from mount: %v", err)
+	return deviceName, 1, nil
 }
 
 // IsCorruptedMnt return true if err is about corrupted mount point
@@ -166,79 +160,55 @@ func (m NodeMounter) IsCorruptedMnt(err error) bool {
 }
 
 func (m *NodeMounter) MakeFile(path string) error {
-	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
-	case *CSIProxyMounterV2:
-		return proxyMounter.MakeFile(path)
-	case *CSIProxyMounter:
-		return proxyMounter.MakeFile(path)
-	default:
-		return ErrUnsupportedMounter
+	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
+	if !ok {
+		return fmt.Errorf("failed to cast mounter to csi proxy mounter")
 	}
+	return proxyMounter.MakeFile(path)
 }
 
 func (m *NodeMounter) MakeDir(path string) error {
-	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
-	case *CSIProxyMounterV2:
-		return proxyMounter.MakeDir(path)
-	case *CSIProxyMounter:
-		return proxyMounter.MakeDir(path)
-	default:
-		return ErrUnsupportedMounter
+	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
+	if !ok {
+		return fmt.Errorf("failed to cast mounter to csi proxy mounter")
 	}
+	return proxyMounter.MakeDir(path)
 }
 
 func (m *NodeMounter) PathExists(path string) (bool, error) {
-	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
-	case *CSIProxyMounterV2:
-		return proxyMounter.ExistsPath(path)
-	case *CSIProxyMounter:
-		return proxyMounter.ExistsPath(path)
-	default:
-		return false, ErrUnsupportedMounter
+	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
+	if !ok {
+		return false, fmt.Errorf("failed to cast mounter to csi proxy mounter")
 	}
+	return proxyMounter.ExistsPath(path)
 }
 
 func (m *NodeMounter) Resize(devicePath, deviceMountPath string) (bool, error) {
-	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
-	case *CSIProxyMounterV2:
-		return proxyMounter.ResizeVolume(deviceMountPath)
-	case *CSIProxyMounter:
-		return proxyMounter.ResizeVolume(deviceMountPath)
-	default:
-		return false, ErrUnsupportedMounter
+	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
+	if !ok {
+		return false, fmt.Errorf("failed to cast mounter to csi proxy mounter")
 	}
+	return proxyMounter.ResizeVolume(deviceMountPath)
 }
 
 // NeedResize called at NodeStage to ensure file system is the correct size
 func (m *NodeMounter) NeedResize(devicePath, deviceMountPath string) (bool, error) {
-	var err error
-	var deviceSize, fsSize int64
-
-	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
-	case *CSIProxyMounterV2:
-		deviceSize, err = proxyMounter.GetDeviceSize(devicePath)
-		if err != nil {
-			return false, fmt.Errorf("failed to get device size: %w", err)
-		}
-		fsSize, err = proxyMounter.GetVolumeSizeInBytes(deviceMountPath)
-		if err != nil {
-			return false, fmt.Errorf("failed to get filesystem size: %w", err)
-		}
-	case *CSIProxyMounter:
-		deviceSize, err = proxyMounter.GetDeviceSize(devicePath)
-		if err != nil {
-			return false, fmt.Errorf("failed to get device size: %w", err)
-		}
-		fsSize, err = proxyMounter.GetVolumeSizeInBytes(deviceMountPath)
-		if err != nil {
-			return false, fmt.Errorf("failed to get filesystem size: %w", err)
-		}
-	default:
-		return false, ErrUnsupportedMounter
+	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
+	if !ok {
+		return false, fmt.Errorf("failed to cast mounter to csi proxy mounter")
 	}
 
+	deviceSize, err := proxyMounter.GetDeviceSize(devicePath)
+	if err != nil {
+		return false, err
+	}
+
+	fsSize, err := proxyMounter.GetVolumeSizeInBytes(deviceMountPath)
+	if err != nil {
+		return false, err
+	}
 	// Tolerate one block difference (4096 bytes)
-	if deviceSize <= util.DefaultBlockSize+fsSize {
+	if deviceSize <= DefaultBlockSize+fsSize {
 		return true, nil
 	}
 	return false, nil
@@ -246,39 +216,29 @@ func (m *NodeMounter) NeedResize(devicePath, deviceMountPath string) (bool, erro
 
 // Unmount volume from target path
 func (m *NodeMounter) Unpublish(target string) error {
-	var err error
-	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
-	case *CSIProxyMounterV2:
-		err = proxyMounter.Rmdir(target)
-	case *CSIProxyMounter:
-		err = proxyMounter.Rmdir(target)
-	default:
-		return ErrUnsupportedMounter
+	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
+	if !ok {
+		return fmt.Errorf("failed to cast mounter to csi proxy mounter")
 	}
-
+	// Remove symlink
+	err := proxyMounter.Rmdir(target)
 	if err != nil {
-		return fmt.Errorf("failed to remove directory: %w", err)
+		return err
 	}
-
 	return nil
 }
 
 // Unmount volume from staging path
 // usually this staging path is a global directory on the node
 func (m *NodeMounter) Unstage(target string) error {
-	var err error
-	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
-	case *CSIProxyMounterV2:
-		err = proxyMounter.Unmount(target)
-	case *CSIProxyMounter:
-		err = proxyMounter.Unmount(target)
-	default:
-		return ErrUnsupportedMounter
+	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
+	if !ok {
+		return fmt.Errorf("failed to cast mounter to csi proxy mounter")
 	}
-
+	// Unmounts and offlines the disk via the CSI Proxy API
+	err := proxyMounter.Unmount(target)
 	if err != nil {
-		return fmt.Errorf("unmount failed: %w", err)
+		return err
 	}
-
 	return nil
 }
diff --git a/pkg/mounter/mount_windows_proxyV2.go b/pkg/mounter/mount_windows_proxyV2.go
deleted file mode 100644
index 468ee219..00000000
--- a/pkg/mounter/mount_windows_proxyV2.go
+++ /dev/null
@@ -1,501 +0,0 @@
-//go:build windows
-// +build windows
-
-/*
-Copyright 2024 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package mounter
-
-import (
-	"context"
-	"errors"
-	"fmt"
-	"os"
-	"strconv"
-	"strings"
-
-	diskv2 "github.com/kubernetes-csi/csi-proxy/v2/pkg/disk"
-	diskapiv2 "github.com/kubernetes-csi/csi-proxy/v2/pkg/disk/hostapi"
-	fsv2 "github.com/kubernetes-csi/csi-proxy/v2/pkg/filesystem"
-	fsapiv2 "github.com/kubernetes-csi/csi-proxy/v2/pkg/filesystem/hostapi"
-	volumev2 "github.com/kubernetes-csi/csi-proxy/v2/pkg/volume"
-	volumeapiv2 "github.com/kubernetes-csi/csi-proxy/v2/pkg/volume/hostapi"
-	"github.com/kubernetes-sigs/aws-ebs-csi-driver/pkg/util"
-	"k8s.io/klog/v2"
-	mountutils "k8s.io/mount-utils"
-	utilexec "k8s.io/utils/exec"
-)
-
-type CSIProxyMounterV2 struct {
-	FsClient     fsv2.Interface
-	DiskClient   diskv2.Interface
-	VolumeClient volumev2.Interface
-}
-
-// NewSafeMounterV2 returns a new instance of SafeFormatAndMount.
-func NewSafeMounterV2() (*mountutils.SafeFormatAndMount, error) {
-	fs, err := fsv2.New(fsapiv2.New())
-	if err != nil {
-		return nil, err
-	}
-	disk, err := diskv2.New(diskapiv2.New())
-	if err != nil {
-		return nil, err
-	}
-	volume, err := volumev2.New(volumeapiv2.New())
-	if err != nil {
-		return nil, err
-	}
-	return &mountutils.SafeFormatAndMount{
-		Interface: &CSIProxyMounterV2{
-			FsClient:     fs,
-			DiskClient:   disk,
-			VolumeClient: volume,
-		},
-		Exec: utilexec.New(),
-	}, nil
-}
-
-// Mount just creates a soft link at target pointing to source.
-func (mounter *CSIProxyMounterV2) Mount(source string, target string, fstype string, options []string) error {
-	// Mount is called after the format is done.
-	// TODO: Confirm that fstype is empty.
-	linkRequest := &fsv2.CreateSymlinkRequest{
-		SourcePath: util.NormalizeWindowsPath(source),
-		TargetPath: util.NormalizeWindowsPath(target),
-	}
-	_, err := mounter.FsClient.CreateSymlink(context.Background(), linkRequest)
-	if err != nil {
-		return err
-	}
-	return nil
-}
-
-func (mounter *CSIProxyMounterV2) Unmount(target string) error {
-	// Find the volume id
-	getVolumeIdRequest := &volumev2.GetVolumeIDFromTargetPathRequest{
-		TargetPath: util.NormalizeWindowsPath(target),
-	}
-	volumeIdResponse, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), getVolumeIdRequest)
-	if err != nil {
-		return err
-	}
-
-	// Call UnmountVolume CSI proxy function which flushes data cache to disk and removes the global staging path
-	unmountVolumeRequest := &volumev2.UnmountVolumeRequest{
-		VolumeID:   volumeIdResponse.VolumeID,
-		TargetPath: util.NormalizeWindowsPath(target),
-	}
-	_, err = mounter.VolumeClient.UnmountVolume(context.Background(), unmountVolumeRequest)
-	if err != nil {
-		return err
-	}
-
-	// Cleanup stage path
-	err = mounter.Rmdir(target)
-	if err != nil {
-		return err
-	}
-
-	// Get disk number
-	getDiskNumberRequest := &volumev2.GetDiskNumberFromVolumeIDRequest{
-		VolumeID: volumeIdResponse.VolumeID,
-	}
-	getDiskNumberResponse, err := mounter.VolumeClient.GetDiskNumberFromVolumeID(context.Background(), getDiskNumberRequest)
-	if err != nil {
-		return err
-	}
-
-	// Offline the disk
-	setDiskStateRequest := &diskv2.SetDiskStateRequest{
-		DiskNumber: getDiskNumberResponse.DiskNumber,
-		IsOnline:   false,
-	}
-	_, err = mounter.DiskClient.SetDiskState(context.Background(), setDiskStateRequest)
-	if err != nil {
-		return err
-	}
-	klog.V(4).InfoS("Successfully unmounted volume", "diskNumber", getDiskNumberResponse.DiskNumber, "volumeId", volumeIdResponse.VolumeID, "target", target)
-	return nil
-}
-
-// Rmdir - delete the given directory
-func (mounter *CSIProxyMounterV2) Rmdir(path string) error {
-	rmdirRequest := &fsv2.RmdirRequest{
-		Path:  util.NormalizeWindowsPath(path),
-		Force: true,
-	}
-	_, err := mounter.FsClient.Rmdir(context.Background(), rmdirRequest)
-	if err != nil {
-		return err
-	}
-	return nil
-}
-
-func (mounter *CSIProxyMounterV2) WriteVolumeCache(target string) {
-	request := &volumev2.GetVolumeIDFromTargetPathRequest{TargetPath: util.NormalizeWindowsPath(target)}
-	response, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), request)
-	if err != nil || response == nil {
-		klog.InfoS("GetVolumeIDFromTargetPath failed", "target", target, "err", err, "response", response)
-	} else {
-		request := &volumev2.WriteVolumeCacheRequest{
-			VolumeID: response.VolumeID,
-		}
-		if res, err := mounter.VolumeClient.WriteVolumeCache(context.Background(), request); err != nil {
-			klog.InfoS("WriteVolumeCache failed", "volumeID", response.VolumeID, "err", err, "res", res)
-		}
-	}
-}
-
-func (mounter *CSIProxyMounterV2) List() ([]mountutils.MountPoint, error) {
-	return []mountutils.MountPoint{}, fmt.Errorf("List not implemented for CSIProxyMounter")
-}
-
-func (mounter *CSIProxyMounterV2) IsMountPointMatch(mp mountutils.MountPoint, dir string) bool {
-	return mp.Path == dir
-}
-
-// IsMountPoint: determines if a directory is a mountpoint.
-func (mounter *CSIProxyMounterV2) IsMountPoint(file string) (bool, error) {
-	isNotMnt, err := mounter.IsLikelyNotMountPoint(file)
-	if err != nil {
-		return false, err
-	}
-	return !isNotMnt, nil
-}
-
-// IsLikelyMountPoint - If the directory does not exists, the function will return os.ErrNotExist error.
-//
-//	If the path exists, call to CSI proxy will check if its a link, if its a link then existence of target
-//	path is checked.
-func (mounter *CSIProxyMounterV2) IsLikelyNotMountPoint(path string) (bool, error) {
-	isExists, err := mounter.ExistsPath(path)
-	if err != nil {
-		return false, err
-	}
-
-	if !isExists {
-		return true, os.ErrNotExist
-	}
-
-	response, err := mounter.FsClient.IsSymlink(context.Background(),
-		&fsv2.IsSymlinkRequest{
-			Path: util.NormalizeWindowsPath(path),
-		})
-	if err != nil {
-		return false, err
-	}
-	return !response.IsSymlink, nil
-}
-
-func (mounter *CSIProxyMounterV2) PathIsDevice(pathname string) (bool, error) {
-	return false, fmt.Errorf("PathIsDevice not implemented for CSIProxyMounter")
-}
-
-func (mounter *CSIProxyMounterV2) DeviceOpened(pathname string) (bool, error) {
-	return false, fmt.Errorf("DeviceOpened not implemented for CSIProxyMounter")
-}
-
-// GetDeviceNameFromMount returns the disk number for a mount path.
-func (mounter *CSIProxyMounterV2) GetDeviceNameFromMount(mountPath, _ string) (string, error) {
-	req := &volumev2.GetVolumeIDFromTargetPathRequest{TargetPath: util.NormalizeWindowsPath(mountPath)}
-	resp, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), req)
-	if err != nil {
-		return "", err
-	}
-	// Get disk number
-	getDiskNumberRequest := &volumev2.GetDiskNumberFromVolumeIDRequest{
-		VolumeID: resp.VolumeID,
-	}
-	getDiskNumberResponse, err := mounter.VolumeClient.GetDiskNumberFromVolumeID(context.Background(), getDiskNumberRequest)
-	if err != nil {
-		return "", err
-	}
-	klog.V(4).InfoS("GetDeviceNameFromMount called", "diskNumber", getDiskNumberResponse.DiskNumber, "volumeID", resp.VolumeID, "mountPath", mountPath)
-	return fmt.Sprint(getDiskNumberResponse.DiskNumber), nil
-}
-
-func (mounter *CSIProxyMounterV2) MakeRShared(path string) error {
-	return fmt.Errorf("MakeRShared not implemented for CSIProxyMounter")
-}
-
-func (mounter *CSIProxyMounterV2) MakeFile(pathname string) error {
-	return fmt.Errorf("MakeFile not implemented for CSIProxyMounter")
-}
-
-// MakeDir - Creates a directory. The CSI proxy takes in context information.
-// Currently the make dir is only used from the staging code path, hence we call it
-// with Plugin context..
-func (mounter *CSIProxyMounterV2) MakeDir(pathname string) error {
-	mkdirReq := &fsv2.MkdirRequest{
-		Path: util.NormalizeWindowsPath(pathname),
-	}
-	_, err := mounter.FsClient.Mkdir(context.Background(), mkdirReq)
-	if err != nil {
-		klog.V(4).InfoS("Error", err)
-		return err
-	}
-
-	return nil
-}
-
-// ExistsPath - Checks if a path exists. Unlike util ExistsPath, this call does not perform follow link.
-func (mounter *CSIProxyMounterV2) ExistsPath(path string) (bool, error) {
-	isExistsResponse, err := mounter.FsClient.PathExists(context.Background(),
-		&fsv2.PathExistsRequest{
-			Path: util.NormalizeWindowsPath(path),
-		})
-	if err != nil {
-		return false, err
-	}
-	return isExistsResponse.Exists, err
-}
-
-func (mounter *CSIProxyMounterV2) EvalHostSymlinks(pathname string) (string, error) {
-	return "", fmt.Errorf("EvalHostSymlinks is not implemented for CSIProxyMounter")
-}
-
-func (mounter *CSIProxyMounterV2) GetMountRefs(pathname string) ([]string, error) {
-	return []string{}, fmt.Errorf("GetMountRefs is not implemented for CSIProxyMounter")
-}
-
-func (mounter *CSIProxyMounterV2) GetFSGroup(pathname string) (int64, error) {
-	return -1, fmt.Errorf("GetFSGroup is not implemented for CSIProxyMounter")
-}
-
-func (mounter *CSIProxyMounterV2) GetSELinuxSupport(pathname string) (bool, error) {
-	return false, fmt.Errorf("GetSELinuxSupport is not implemented for CSIProxyMounter")
-}
-
-func (mounter *CSIProxyMounterV2) GetMode(pathname string) (os.FileMode, error) {
-	return 0, fmt.Errorf("GetMode is not implemented for CSIProxyMounter")
-}
-
-func (mounter *CSIProxyMounterV2) MountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
-	return fmt.Errorf("MountSensitive is not implemented for CSIProxyMounter")
-}
-
-func (mounter *CSIProxyMounterV2) MountSensitiveWithoutSystemd(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
-	return fmt.Errorf("MountSensitiveWithoutSystemd is not implemented for CSIProxyMounter")
-}
-
-func (mounter *CSIProxyMounterV2) MountSensitiveWithoutSystemdWithMountFlags(source string, target string, fstype string, options []string, sensitiveOptions []string, mountFlags []string) error {
-	return fmt.Errorf("MountSensitiveWithoutSystemdWithMountFlags is not implemented for CSIProxyMounter")
-}
-
-// Rescan would trigger an update storage cache via the CSI proxy.
-func (mounter *CSIProxyMounterV2) Rescan() error {
-	// Call Rescan from disk APIs of CSI Proxy.
-	if _, err := mounter.DiskClient.Rescan(context.Background(), &diskv2.RescanRequest{}); err != nil {
-		return err
-	}
-	return nil
-}
-
-// FindDiskByLun - given a lun number, find out the corresponding disk
-func (mounter *CSIProxyMounterV2) FindDiskByLun(lun string) (diskNum string, err error) {
-	findDiskByLunResponse, err := mounter.DiskClient.ListDiskLocations(context.Background(), &diskv2.ListDiskLocationsRequest{})
-	if err != nil {
-		return "", err
-	}
-
-	// List all disk locations and match the lun id being requested for.
-	// If match is found then return back the disk number.
-	for diskID, location := range findDiskByLunResponse.DiskLocations {
-		if strings.EqualFold(location.LUNID, lun) {
-			return strconv.Itoa(int(diskID)), nil
-		}
-	}
-	return "", fmt.Errorf("could not find disk id for lun: %s", lun)
-}
-
-// FormatAndMount - accepts the source disk number, target path to mount, the fstype to format with and options to be used.
-func (mounter *CSIProxyMounterV2) FormatAndMountSensitiveWithFormatOptions(source string, target string, fstype string, options []string, sensitiveOptions []string, formatOptions []string) error {
-	// sensitiveOptions is not supported on Windows because we have no reasonable way to control what the csi-proxy does
-	if len(sensitiveOptions) > 0 {
-		return errors.New("sensitiveOptions not supported on Windows!")
-	}
-	// formatOptions is not supported on Windows because the csi-proxy does not allow supplying format arguments
-	// This limitation will be addressed in the future with privileged Windows containers
-	if len(formatOptions) > 0 {
-		return errors.New("formatOptions not supported on Windows!")
-	}
-
-	diskNumber, err := strconv.Atoi(source)
-	if err != nil {
-		return err
-	}
-
-	// Call PartitionDisk CSI proxy call to partition the disk and return the volume id
-	partionDiskRequest := &diskv2.PartitionDiskRequest{
-		DiskNumber: uint32(diskNumber),
-	}
-	_, err = mounter.DiskClient.PartitionDisk(context.Background(), partionDiskRequest)
-	if err != nil {
-		return err
-	}
-
-	// Ensure the disk is online before mounting.
-	setDiskStateRequest := &diskv2.SetDiskStateRequest{
-		DiskNumber: uint32(diskNumber),
-		IsOnline:   true,
-	}
-	_, err = mounter.DiskClient.SetDiskState(context.Background(), setDiskStateRequest)
-	if err != nil {
-		return err
-	}
-
-	// List the volumes on the given disk.
-	volumeIDsRequest := &volumev2.ListVolumesOnDiskRequest{
-		DiskNumber: uint32(diskNumber),
-	}
-	volumeIdResponse, err := mounter.VolumeClient.ListVolumesOnDisk(context.Background(), volumeIDsRequest)
-	if err != nil {
-		return err
-	}
-
-	// TODO: consider partitions and choose the right partition.
-	// For now just choose the first volume.
-	volumeID := volumeIdResponse.VolumeIDs[0]
-
-	// Check if the volume is formatted.
-	isVolumeFormattedRequest := &volumev2.IsVolumeFormattedRequest{
-		VolumeID: volumeID,
-	}
-	isVolumeFormattedResponse, err := mounter.VolumeClient.IsVolumeFormatted(context.Background(), isVolumeFormattedRequest)
-	if err != nil {
-		return err
-	}
-
-	// If the volume is not formatted, then format it, else proceed to mount.
-	if !isVolumeFormattedResponse.Formatted {
-		formatVolumeRequest := &volumev2.FormatVolumeRequest{
-			VolumeID: volumeID,
-			// TODO: Accept the filesystem and other options
-		}
-		_, err = mounter.VolumeClient.FormatVolume(context.Background(), formatVolumeRequest)
-		if err != nil {
-			return err
-		}
-	}
-
-	// Mount the volume by calling the CSI proxy call.
-	mountVolumeRequest := &volumev2.MountVolumeRequest{
-		VolumeID:   volumeID,
-		TargetPath: util.NormalizeWindowsPath(target),
-	}
-	_, err = mounter.VolumeClient.MountVolume(context.Background(), mountVolumeRequest)
-	if err != nil {
-		return err
-	}
-	return nil
-}
-
-// ResizeVolume resizes the volume at given mount path
-func (mounter *CSIProxyMounterV2) ResizeVolume(deviceMountPath string) (bool, error) {
-	// Find the volume id
-	getVolumeIdRequest := &volumev2.GetVolumeIDFromTargetPathRequest{
-		TargetPath: util.NormalizeWindowsPath(deviceMountPath),
-	}
-	volumeIdResponse, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), getVolumeIdRequest)
-	if err != nil {
-		return false, err
-	}
-	volumeId := volumeIdResponse.VolumeID
-
-	// Resize volume
-	resizeVolumeRequest := &volumev2.ResizeVolumeRequest{
-		VolumeID: volumeId,
-	}
-	_, err = mounter.VolumeClient.ResizeVolume(context.Background(), resizeVolumeRequest)
-	if err != nil {
-		return false, err
-	}
-
-	return true, nil
-}
-
-// GetVolumeSizeInBytes returns the size of the volume in bytes
-func (mounter *CSIProxyMounterV2) GetVolumeSizeInBytes(deviceMountPath string) (int64, error) {
-	// Find the volume id
-	getVolumeIdRequest := &volumev2.GetVolumeIDFromTargetPathRequest{
-		TargetPath: util.NormalizeWindowsPath(deviceMountPath),
-	}
-	volumeIdResponse, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), getVolumeIdRequest)
-	if err != nil {
-		return -1, err
-	}
-	volumeId := volumeIdResponse.VolumeID
-
-	// Get size of the volume
-	getVolumeStatsRequest := &volumev2.GetVolumeStatsRequest{
-		VolumeID: volumeId,
-	}
-	resp, err := mounter.VolumeClient.GetVolumeStats(context.Background(), getVolumeStatsRequest)
-	if err != nil {
-		return -1, err
-	}
-
-	return resp.TotalBytes, nil
-}
-
-// GetDeviceSize returns the size of the disk in bytes
-func (mounter *CSIProxyMounterV2) GetDeviceSize(devicePath string) (int64, error) {
-	diskNumber, err := strconv.Atoi(devicePath)
-	if err != nil {
-		return -1, err
-	}
-
-	//Get size of the disk
-	getDiskStatsRequest := &diskv2.GetDiskStatsRequest{
-		DiskNumber: uint32(diskNumber),
-	}
-	resp, err := mounter.DiskClient.GetDiskStats(context.Background(), getDiskStatsRequest)
-	if err != nil {
-		return -1, err
-	}
-
-	return resp.TotalBytes, nil
-}
-
-func (mounter *CSIProxyMounterV2) CanSafelySkipMountPointCheck() bool {
-	return false
-}
-
-func (mounter *CSIProxyMounterV2) FindDevicePath(devicePath, volumeID, _, _ string) (string, error) {
-	response, err := mounter.DiskClient.ListDiskIDs(context.TODO(), &diskv2.ListDiskIDsRequest{})
-	if err != nil {
-		return "", fmt.Errorf("error listing disk ids: %q", err)
-	}
-
-	diskIDs := response.DiskIDs
-
-	foundDiskNumber := ""
-	for diskNumber, diskID := range diskIDs {
-		serialNumber := diskID.SerialNumber
-		cleanVolumeID := strings.ReplaceAll(volumeID, "-", "")
-		if strings.Contains(serialNumber, cleanVolumeID) {
-			foundDiskNumber = strconv.Itoa(int(diskNumber))
-			break
-		}
-	}
-
-	if foundDiskNumber == "" {
-		return "", fmt.Errorf("disk number for device path %q volume id %q not found", devicePath, volumeID)
-	}
-
-	return foundDiskNumber, nil
-}
diff --git a/pkg/mounter/safe_mounter.go b/pkg/mounter/safe_mounter.go
new file mode 100644
index 00000000..215047b0
--- /dev/null
+++ b/pkg/mounter/safe_mounter.go
@@ -0,0 +1,32 @@
+//go:build linux || darwin
+// +build linux darwin
+
+/*
+Copyright 2020 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package mounter
+
+import (
+	"k8s.io/mount-utils"
+	utilexec "k8s.io/utils/exec"
+)
+
+func NewSafeMounter() (*mount.SafeFormatAndMount, error) {
+	return &mount.SafeFormatAndMount{
+		Interface: mount.New(""),
+		Exec:      utilexec.New(),
+	}, nil
+}
diff --git a/pkg/mounter/mount_windows_proxyV1.go b/pkg/mounter/safe_mounter_windows.go
similarity index 85%
rename from pkg/mounter/mount_windows_proxyV1.go
rename to pkg/mounter/safe_mounter_windows.go
index 71cdf93c..81ef3aa6 100644
--- a/pkg/mounter/mount_windows_proxyV1.go
+++ b/pkg/mounter/safe_mounter_windows.go
@@ -2,7 +2,7 @@
 // +build windows
 
 /*
-Copyright 2024 The Kubernetes Authors.
+Copyright 2020 The Kubernetes Authors.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -28,46 +28,52 @@ import (
 	"strings"
 
 	disk "github.com/kubernetes-csi/csi-proxy/client/api/disk/v1"
-	fs "github.com/kubernetes-csi/csi-proxy/client/api/filesystem/v1"
-	volume "github.com/kubernetes-csi/csi-proxy/client/api/volume/v1"
 	diskclient "github.com/kubernetes-csi/csi-proxy/client/groups/disk/v1"
+
+	fs "github.com/kubernetes-csi/csi-proxy/client/api/filesystem/v1"
 	fsclient "github.com/kubernetes-csi/csi-proxy/client/groups/filesystem/v1"
+
+	volume "github.com/kubernetes-csi/csi-proxy/client/api/volume/v1"
 	volumeclient "github.com/kubernetes-csi/csi-proxy/client/groups/volume/v1"
-	"github.com/kubernetes-sigs/aws-ebs-csi-driver/pkg/util"
 
 	"k8s.io/klog/v2"
-	mountutils "k8s.io/mount-utils"
+	mount_utils "k8s.io/mount-utils"
 	utilexec "k8s.io/utils/exec"
 )
 
+var _ ProxyMounter = &CSIProxyMounter{}
+
+type ProxyMounter interface {
+	mount_utils.Interface
+
+	Rmdir(path string) error
+	WriteVolumeCache(target string)
+	IsMountPointMatch(mp mount_utils.MountPoint, dir string) bool
+	GetDeviceNameFromMount(mountPath, pluginMountDir string) (string, error)
+	MakeFile(pathname string) error
+	ExistsPath(path string) (bool, error)
+	Rescan() error
+	FindDiskByLun(lun string) (diskNum string, err error)
+	FormatAndMountSensitiveWithFormatOptions(source string, target string, fstype string, options []string, sensitiveOptions []string, formatOptions []string) error
+	ResizeVolume(deviceMountPath string) (bool, error)
+	GetVolumeSizeInBytes(deviceMountPath string) (int64, error)
+	GetDeviceSize(devicePath string) (int64, error)
+	IsMountPoint(pathname string) (bool, error)
+}
+
 type CSIProxyMounter struct {
+	mount_utils.Interface
 	FsClient     *fsclient.Client
 	DiskClient   *diskclient.Client
 	VolumeClient *volumeclient.Client
 }
 
-// NewSafeMounter returns a new instance of SafeFormatAndMount.
-func NewSafeMounter() (*mountutils.SafeFormatAndMount, error) {
-	fsClient, err := fsclient.NewClient()
-	if err != nil {
-		return nil, err
-	}
-	diskClient, err := diskclient.NewClient()
-	if err != nil {
-		return nil, err
-	}
-	volumeClient, err := volumeclient.NewClient()
-	if err != nil {
-		return nil, err
+func normalizeWindowsPath(path string) string {
+	normalizedPath := strings.Replace(path, "/", "\\", -1)
+	if strings.HasPrefix(normalizedPath, "\\") {
+		normalizedPath = "c:" + normalizedPath
 	}
-	return &mountutils.SafeFormatAndMount{
-		Interface: &CSIProxyMounter{
-			FsClient:     fsClient,
-			DiskClient:   diskClient,
-			VolumeClient: volumeClient,
-		},
-		Exec: utilexec.New(),
-	}, nil
+	return normalizedPath
 }
 
 // Mount just creates a soft link at target pointing to source.
@@ -75,8 +81,8 @@ func (mounter *CSIProxyMounter) Mount(source string, target string, fstype strin
 	// Mount is called after the format is done.
 	// TODO: Confirm that fstype is empty.
 	linkRequest := &fs.CreateSymlinkRequest{
-		SourcePath: util.NormalizeWindowsPath(source),
-		TargetPath: util.NormalizeWindowsPath(target),
+		SourcePath: normalizeWindowsPath(source),
+		TargetPath: normalizeWindowsPath(target),
 	}
 	_, err := mounter.FsClient.CreateSymlink(context.Background(), linkRequest)
 	if err != nil {
@@ -88,7 +94,7 @@ func (mounter *CSIProxyMounter) Mount(source string, target string, fstype strin
 func (mounter *CSIProxyMounter) Unmount(target string) error {
 	// Find the volume id
 	getVolumeIdRequest := &volume.GetVolumeIDFromTargetPathRequest{
-		TargetPath: util.NormalizeWindowsPath(target),
+		TargetPath: normalizeWindowsPath(target),
 	}
 	volumeIdResponse, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), getVolumeIdRequest)
 	if err != nil {
@@ -98,7 +104,7 @@ func (mounter *CSIProxyMounter) Unmount(target string) error {
 	// Call UnmountVolume CSI proxy function which flushes data cache to disk and removes the global staging path
 	unmountVolumeRequest := &volume.UnmountVolumeRequest{
 		VolumeId:   volumeIdResponse.VolumeId,
-		TargetPath: util.NormalizeWindowsPath(target),
+		TargetPath: normalizeWindowsPath(target),
 	}
 	_, err = mounter.VolumeClient.UnmountVolume(context.Background(), unmountVolumeRequest)
 	if err != nil {
@@ -136,7 +142,7 @@ func (mounter *CSIProxyMounter) Unmount(target string) error {
 // Rmdir - delete the given directory
 func (mounter *CSIProxyMounter) Rmdir(path string) error {
 	rmdirRequest := &fs.RmdirRequest{
-		Path:  util.NormalizeWindowsPath(path),
+		Path:  normalizeWindowsPath(path),
 		Force: true,
 	}
 	_, err := mounter.FsClient.Rmdir(context.Background(), rmdirRequest)
@@ -147,7 +153,7 @@ func (mounter *CSIProxyMounter) Rmdir(path string) error {
 }
 
 func (mounter *CSIProxyMounter) WriteVolumeCache(target string) {
-	request := &volume.GetVolumeIDFromTargetPathRequest{TargetPath: util.NormalizeWindowsPath(target)}
+	request := &volume.GetVolumeIDFromTargetPathRequest{TargetPath: normalizeWindowsPath(target)}
 	response, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), request)
 	if err != nil || response == nil {
 		klog.InfoS("GetVolumeIDFromTargetPath failed", "target", target, "err", err, "response", response)
@@ -161,11 +167,11 @@ func (mounter *CSIProxyMounter) WriteVolumeCache(target string) {
 	}
 }
 
-func (mounter *CSIProxyMounter) List() ([]mountutils.MountPoint, error) {
-	return []mountutils.MountPoint{}, fmt.Errorf("List not implemented for CSIProxyMounter")
+func (mounter *CSIProxyMounter) List() ([]mount_utils.MountPoint, error) {
+	return []mount_utils.MountPoint{}, fmt.Errorf("List not implemented for CSIProxyMounter")
 }
 
-func (mounter *CSIProxyMounter) IsMountPointMatch(mp mountutils.MountPoint, dir string) bool {
+func (mounter *CSIProxyMounter) IsMountPointMatch(mp mount_utils.MountPoint, dir string) bool {
 	return mp.Path == dir
 }
 
@@ -194,7 +200,7 @@ func (mounter *CSIProxyMounter) IsLikelyNotMountPoint(path string) (bool, error)
 
 	response, err := mounter.FsClient.IsSymlink(context.Background(),
 		&fs.IsSymlinkRequest{
-			Path: util.NormalizeWindowsPath(path),
+			Path: normalizeWindowsPath(path),
 		})
 	if err != nil {
 		return false, err
@@ -212,7 +218,7 @@ func (mounter *CSIProxyMounter) DeviceOpened(pathname string) (bool, error) {
 
 // GetDeviceNameFromMount returns the disk number for a mount path.
 func (mounter *CSIProxyMounter) GetDeviceNameFromMount(mountPath, _ string) (string, error) {
-	req := &volume.GetVolumeIDFromTargetPathRequest{TargetPath: util.NormalizeWindowsPath(mountPath)}
+	req := &volume.GetVolumeIDFromTargetPathRequest{TargetPath: normalizeWindowsPath(mountPath)}
 	resp, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), req)
 	if err != nil {
 		return "", err
@@ -242,7 +248,7 @@ func (mounter *CSIProxyMounter) MakeFile(pathname string) error {
 // with Plugin context..
 func (mounter *CSIProxyMounter) MakeDir(pathname string) error {
 	mkdirReq := &fs.MkdirRequest{
-		Path: util.NormalizeWindowsPath(pathname),
+		Path: normalizeWindowsPath(pathname),
 	}
 	_, err := mounter.FsClient.Mkdir(context.Background(), mkdirReq)
 	if err != nil {
@@ -257,7 +263,7 @@ func (mounter *CSIProxyMounter) MakeDir(pathname string) error {
 func (mounter *CSIProxyMounter) ExistsPath(path string) (bool, error) {
 	isExistsResponse, err := mounter.FsClient.PathExists(context.Background(),
 		&fs.PathExistsRequest{
-			Path: util.NormalizeWindowsPath(path),
+			Path: normalizeWindowsPath(path),
 		})
 	if err != nil {
 		return false, err
@@ -396,7 +402,7 @@ func (mounter *CSIProxyMounter) FormatAndMountSensitiveWithFormatOptions(source
 	// Mount the volume by calling the CSI proxy call.
 	mountVolumeRequest := &volume.MountVolumeRequest{
 		VolumeId:   volumeID,
-		TargetPath: util.NormalizeWindowsPath(target),
+		TargetPath: normalizeWindowsPath(target),
 	}
 	_, err = mounter.VolumeClient.MountVolume(context.Background(), mountVolumeRequest)
 	if err != nil {
@@ -409,7 +415,7 @@ func (mounter *CSIProxyMounter) FormatAndMountSensitiveWithFormatOptions(source
 func (mounter *CSIProxyMounter) ResizeVolume(deviceMountPath string) (bool, error) {
 	// Find the volume id
 	getVolumeIdRequest := &volume.GetVolumeIDFromTargetPathRequest{
-		TargetPath: util.NormalizeWindowsPath(deviceMountPath),
+		TargetPath: normalizeWindowsPath(deviceMountPath),
 	}
 	volumeIdResponse, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), getVolumeIdRequest)
 	if err != nil {
@@ -433,7 +439,7 @@ func (mounter *CSIProxyMounter) ResizeVolume(deviceMountPath string) (bool, erro
 func (mounter *CSIProxyMounter) GetVolumeSizeInBytes(deviceMountPath string) (int64, error) {
 	// Find the volume id
 	getVolumeIdRequest := &volume.GetVolumeIDFromTargetPathRequest{
-		TargetPath: util.NormalizeWindowsPath(deviceMountPath),
+		TargetPath: normalizeWindowsPath(deviceMountPath),
 	}
 	volumeIdResponse, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), getVolumeIdRequest)
 	if err != nil {
@@ -472,37 +478,35 @@ func (mounter *CSIProxyMounter) GetDeviceSize(devicePath string) (int64, error)
 	return resp.TotalBytes, nil
 }
 
-func (mounter *CSIProxyMounter) CanSafelySkipMountPointCheck() bool {
-	return false
-}
-
-func (mounter *CSIProxyMounter) FindDevicePath(devicePath, volumeID, _, _ string) (string, error) {
-	diskClient, err := diskclient.NewClient()
+// NewCSIProxyMounter - creates a new CSI Proxy mounter struct which encompassed all the
+// clients to the CSI proxy - filesystem, disk and volume clients.
+func NewCSIProxyMounter() (*CSIProxyMounter, error) {
+	fsClient, err := fsclient.NewClient()
 	if err != nil {
-		return "", fmt.Errorf("error creating csi-proxy disk client: %q", err)
+		return nil, err
 	}
-	defer diskClient.Close()
-
-	response, err := diskClient.ListDiskIDs(context.TODO(), &disk.ListDiskIDsRequest{})
+	diskClient, err := diskclient.NewClient()
 	if err != nil {
-		return "", fmt.Errorf("error listing disk ids: %q", err)
+		return nil, err
 	}
-
-	diskIDs := response.GetDiskIDs()
-
-	foundDiskNumber := ""
-	for diskNumber, diskID := range diskIDs {
-		serialNumber := diskID.GetSerialNumber()
-		cleanVolumeID := strings.ReplaceAll(volumeID, "-", "")
-		if strings.Contains(serialNumber, cleanVolumeID) {
-			foundDiskNumber = strconv.Itoa(int(diskNumber))
-			break
-		}
+	volumeClient, err := volumeclient.NewClient()
+	if err != nil {
+		return nil, err
 	}
+	return &CSIProxyMounter{
+		FsClient:     fsClient,
+		DiskClient:   diskClient,
+		VolumeClient: volumeClient,
+	}, nil
+}
 
-	if foundDiskNumber == "" {
-		return "", fmt.Errorf("disk number for device path %q volume id %q not found", devicePath, volumeID)
+func NewSafeMounter() (*mount_utils.SafeFormatAndMount, error) {
+	csiProxyMounter, err := NewCSIProxyMounter()
+	if err != nil {
+		return nil, err
 	}
-
-	return foundDiskNumber, nil
+	return &mount_utils.SafeFormatAndMount{
+		Interface: csiProxyMounter,
+		Exec:      utilexec.New(),
+	}, nil
 }
diff --git a/pkg/util/util.go b/pkg/util/util.go
index 488b8396..fcaae443 100644
--- a/pkg/util/util.go
+++ b/pkg/util/util.go
@@ -23,15 +23,13 @@ import (
 	"os"
 	"path/filepath"
 	"regexp"
-	"runtime"
 	"strings"
 
 	csi "github.com/container-storage-interface/spec/lib/go/csi"
 )
 
 const (
-	GiB              = int64(1024 * 1024 * 1024)
-	DefaultBlockSize = 4096
+	GiB = int64(1024 * 1024 * 1024)
 )
 
 var (
@@ -68,26 +66,7 @@ func GiBToBytes(volumeSizeGiB int32) int64 {
 	return int64(volumeSizeGiB) * GiB
 }
 
-func ParseEndpoint(endpoint string, hostprocess bool) (string, string, error) {
-	if runtime.GOOS == "windows" && hostprocess {
-		parts := strings.SplitN(endpoint, "://", 2)
-		if len(parts) != 2 {
-			return "", "", fmt.Errorf("invalid endpoint format: %s", endpoint)
-		}
-		scheme := strings.ToLower(parts[0])
-		addr := parts[1]
-
-		// Remove the socket file if it already exists
-		if scheme == "unix" {
-			if _, err := os.Stat(addr); err == nil {
-				if err := os.Remove(addr); err != nil {
-					return "", "", fmt.Errorf("failed to remove existing socket file: %w", err)
-				}
-			}
-		}
-		return scheme, addr, nil
-	}
-
+func ParseEndpoint(endpoint string) (string, string, error) {
 	u, err := url.Parse(endpoint)
 	if err != nil {
 		return "", "", fmt.Errorf("could not parse endpoint: %w", err)
@@ -135,12 +114,3 @@ func IsSBE(region string) bool {
 func StringIsAlphanumeric(s string) bool {
 	return isAlphanumericRegex(s)
 }
-
-// NormalizeWindowsPath normalizes a Windows path
-func NormalizeWindowsPath(path string) string {
-	normalizedPath := strings.Replace(path, "/", "\\", -1)
-	if strings.HasPrefix(normalizedPath, "\\") {
-		normalizedPath = "c:" + normalizedPath
-	}
-	return normalizedPath
-}


Test patch:
diff --git a/hack/e2e/run.sh b/hack/e2e/run.sh
index c889c52d..8aa987d3 100755
--- a/hack/e2e/run.sh
+++ b/hack/e2e/run.sh
@@ -83,7 +83,6 @@ if [[ "${HELM_CT_TEST}" != true ]]; then
       --set image.repository="${IMAGE_NAME}"
       --set image.tag="${IMAGE_TAG}"
       --set node.enableWindows="${WINDOWS}"
-      --set node.windowsHostProcess="${WINDOWS_HOSTPROCESS}"
       --set=controller.k8sTagClusterId="${CLUSTER_NAME}"
       --timeout 10m0s
       --wait
diff --git a/hack/prow-e2e.sh b/hack/prow-e2e.sh
index 4487ab23..5923f2b7 100755
--- a/hack/prow-e2e.sh
+++ b/hack/prow-e2e.sh
@@ -42,12 +42,6 @@ test-e2e-external-eks-windows)
   export CLUSTER_TYPE="eksctl"
   export WINDOWS="true"
   ;;
-test-e2e-external-windows-hostprocess)
-  TEST="external-windows-hostprocess"
-  export CLUSTER_TYPE="eksctl"
-  export WINDOWS="true"
-  export WINDOWS_HOSTPROCESS="true"
-  ;;
 test-e2e-external-kustomize)
   TEST="external-kustomize"
   ;;
diff --git a/pkg/cloud/cloud_test.go b/pkg/cloud/cloud_test.go
index 65fd1cee..99b21ed8 100644
--- a/pkg/cloud/cloud_test.go
+++ b/pkg/cloud/cloud_test.go
@@ -20,6 +20,7 @@ import (
 	"context"
 	"errors"
 	"fmt"
+	"k8s.io/apimachinery/pkg/util/wait"
 	"reflect"
 	"strings"
 	"sync"
@@ -931,7 +932,7 @@ func TestCreateDisk(t *testing.T) {
 				AvailabilityZone: "",
 			},
 			expCreateVolumeInput: &ec2.CreateVolumeInput{},
-			expErr:               fmt.Errorf("timed out waiting for volume to create: context deadline exceeded"),
+			expErr:               fmt.Errorf("timed out waiting for volume to create: timed out waiting for the condition"),
 		},
 		{
 			name:       "success: normal from snapshot",
@@ -2387,8 +2388,6 @@ func TestResizeOrModifyDisk(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockCtrl := gomock.NewController(t)
 			mockEC2 := NewMockEC2API(mockCtrl)
-			// reduce number of steps to reduce test time
-			volumeModificationWaitSteps = 3
 			c := newCloud(mockEC2)
 
 			ctx := context.Background()
@@ -2990,8 +2989,6 @@ func TestWaitForAttachmentState(t *testing.T) {
 		},
 	}
 
-	volumeAttachmentStatePollSteps = 1
-
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
 			mockCtrl := gomock.NewController(t)
@@ -3072,12 +3069,28 @@ func TestWaitForAttachmentState(t *testing.T) {
 	}
 }
 
+func testVolumeWaitParameters() volumeWaitParameters {
+	testBackoff := wait.Backoff{
+		Duration: 100 * time.Millisecond,
+		Factor:   1,
+		Steps:    3,
+	}
+
+	return volumeWaitParameters{
+		creationInitialDelay: 0,
+		creationBackoff:      testBackoff,
+		attachmentBackoff:    testBackoff,
+		modificationBackoff:  testBackoff,
+	}
+}
+
 func newCloud(mockEC2 EC2API) Cloud {
 	c := &cloud{
 		region: "test-region",
 		dm:     dm.NewDeviceManager(),
 		ec2:    mockEC2,
 		rm:     newRetryManager(),
+		vwp:    testVolumeWaitParameters(),
 	}
 	return c
 }
diff --git a/pkg/coalescer/coalescer_test.go b/pkg/coalescer/coalescer_test.go
deleted file mode 100644
index be401670..00000000
--- a/pkg/coalescer/coalescer_test.go
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
-Copyright 2024 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package coalescer
-
-import (
-	"errors"
-	"fmt"
-	"testing"
-	"time"
-)
-
-var (
-	errFailedToMerge   = fmt.Errorf("Failed to merge")
-	errFailedToExecute = fmt.Errorf("Failed to execute")
-)
-
-// Merge function used to test the coalescer
-// For testing purposes, positive numbers are added to the existing input,
-// and negative numbers return an error ("fail to merge")
-func mockMerge(input int, existing int) (int, error) {
-	if input < 0 {
-		return 0, errFailedToMerge
-	} else {
-		return input + existing, nil
-	}
-}
-
-// Execute function used to test the coalescer
-// For testing purposes, small numbers (numbers less than 100) successfully execute,
-// and large numbers (numbers 100 or greater) fail to execute
-func mockExecute(_ string, input int) (string, error) {
-	if input < 100 {
-		return "success", nil
-	} else {
-		return "failure", errFailedToExecute
-	}
-}
-
-func TestCoalescer(t *testing.T) {
-	testCases := []struct {
-		name                 string
-		inputs               []int
-		expectMergeFailure   bool
-		expectExecuteFailure bool
-	}{
-		{
-			name:   "one input",
-			inputs: []int{42},
-		},
-		{
-			name:   "many inputs",
-			inputs: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
-		},
-		{
-			name:               "failed merge",
-			inputs:             []int{1, -2, 3, -4, 5, -6, 7, -8, 9, -10},
-			expectMergeFailure: true,
-		},
-		{
-			name:                 "failed execute",
-			inputs:               []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100},
-			expectExecuteFailure: true,
-		},
-	}
-
-	for _, tc := range testCases {
-		t.Run(tc.name, func(t *testing.T) {
-			t.Parallel()
-			c := New[int, string](50*time.Millisecond, mockMerge, mockExecute)
-			testChannel := make(chan error)
-
-			for _, i := range tc.inputs {
-				go func() {
-					_, err := c.Coalesce("testKey", i)
-					testChannel <- err
-				}()
-			}
-
-			mergeFailure := false
-			executeFailure := false
-			for range tc.inputs {
-				err := <-testChannel
-				if err != nil {
-					if errors.Is(err, errFailedToMerge) {
-						mergeFailure = true
-					} else if errors.Is(err, errFailedToExecute) {
-						executeFailure = true
-					} else {
-						t.Fatalf("Unexpected error %v", err)
-					}
-				}
-			}
-
-			if mergeFailure != tc.expectMergeFailure {
-				if tc.expectMergeFailure {
-					t.Fatalf("Expected to observe merge failure, did not")
-				} else {
-					t.Fatalf("Observed unexpected merge failure")
-				}
-			}
-			if executeFailure != tc.expectExecuteFailure {
-				if tc.expectExecuteFailure {
-					t.Fatalf("Expected to observe execute failure, did not")
-				} else {
-					t.Fatalf("Observed unexpected execute failure")
-				}
-			}
-		})
-	}
-}
diff --git a/pkg/mounter/mount_linux_test.go b/pkg/mounter/mount_test.go
similarity index 98%
rename from pkg/mounter/mount_linux_test.go
rename to pkg/mounter/mount_test.go
index c3682664..0e9c3b34 100644
--- a/pkg/mounter/mount_linux_test.go
+++ b/pkg/mounter/mount_test.go
@@ -94,7 +94,7 @@ func TestMakeDir(t *testing.T) {
 
 	targetPath := filepath.Join(dir, "targetdir")
 
-	mountObj, err := NewNodeMounter(false)
+	mountObj, err := NewNodeMounter()
 	if err != nil {
 		t.Fatalf("error creating mounter %v", err)
 	}
@@ -122,7 +122,7 @@ func TestMakeFile(t *testing.T) {
 
 	targetPath := filepath.Join(dir, "targetfile")
 
-	mountObj, err := NewNodeMounter(false)
+	mountObj, err := NewNodeMounter()
 	if err != nil {
 		t.Fatalf("error creating mounter %v", err)
 	}
@@ -151,7 +151,7 @@ func TestPathExists(t *testing.T) {
 
 	targetPath := filepath.Join(dir, "notafile")
 
-	mountObj, err := NewNodeMounter(false)
+	mountObj, err := NewNodeMounter()
 	if err != nil {
 		t.Fatalf("error creating mounter %v", err)
 	}
@@ -178,7 +178,7 @@ func TestGetDeviceName(t *testing.T) {
 
 	targetPath := filepath.Join(dir, "notafile")
 
-	mountObj, err := NewNodeMounter(false)
+	mountObj, err := NewNodeMounter()
 	if err != nil {
 		t.Fatalf("error creating mounter %v", err)
 	}
diff --git a/pkg/mounter/safe_mounter_test.go b/pkg/mounter/safe_mounter_test.go
new file mode 100644
index 00000000..3b7dfc7e
--- /dev/null
+++ b/pkg/mounter/safe_mounter_test.go
@@ -0,0 +1,33 @@
+//go:build linux
+// +build linux
+
+/*
+Copyright 2020 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package mounter
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func TestNewSafeMounter(t *testing.T) {
+	resp, err := NewSafeMounter()
+	assert.NotNil(t, resp)
+	require.NoError(t, err)
+}
diff --git a/pkg/util/util_test.go b/pkg/util/util_test.go
index d2f5d1f0..096446bf 100644
--- a/pkg/util/util_test.go
+++ b/pkg/util/util_test.go
@@ -113,7 +113,7 @@ func TestParseEndpoint(t *testing.T) {
 
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
-			scheme, addr, err := ParseEndpoint(tc.endpoint, false)
+			scheme, addr, err := ParseEndpoint(tc.endpoint)
 
 			if tc.expErr != nil {
 				if err.Error() != tc.expErr.Error() {