Repository: kubernetes-sigs/gcp-compute-persistent-disk-csi-driver
Pull request #661 (2020-11-07 18:54:47)

Add disk online/offline into Stage/Unstage volumes
Disk might be offline when attaching to VMs due to different reasons.
Add disk online logic into NodeStageVolume to make sure disk can be
accessed. Also add disk offline logic into NodeUnstageVolume to make
sure disk is in a clean state when detaching from VM.

Disk online/offline API is in csi proxy disk.v1beta2 api group, so
updating to use this group

<!--  Thanks for sending a pull request!  Here are some tips for you:

1. If this is your first time, please read our contributor guidelines: https://git.k8s.io/community/contributors/guide#your-first-contribution and developer guide https://git.k8s.io/community/contributors/devel/development.md#development-guide
2. Follow the instructions for writing a release note: https://git.k8s.io/community/contributors/guide/release-notes.md
3. If the PR is unfinished, see how to mark it: https://git.k8s.io/community/contributors/guide/pull-requests.md#marking-unfinished-pull-requests
-->

**What type of PR is this?**
> Uncomment only one ` /kind <>` line, hit enter to put that in a new line, and remove leading whitespaces from that line:
>
> /kind api-change
> /kind bug
> /kind cleanup
> /kind design
> /kind documentation
> /kind failing-test
> /kind feature
> /kind flake

**What this PR does / why we need it**:

**Which issue(s) this PR fixes**:
<!--
*Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
_If PR is about `failing-tests or flakes`, please post the related issues/tests in a comment and do not use `Fixes`_*
-->
Fixes #

**Special notes for your reviewer**:

**Does this PR introduce a user-facing change?**:
<!--
If no, just write "NONE" in the release-note block below.
If yes, a release note is required:
Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".
-->
```release-note
NONE
```


k8s-ci-robot: @jingxu97: Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our [release note process](https://git.k8s.io/community/contributors/guide/release-notes.md) to remove it.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
k8s-ci-robot: @jingxu97: Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our [release note process](https://git.k8s.io/community/contributors/guide/release-notes.md) to remove it.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
k8s-ci-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver/pull/661#" title="Author self-approved">jingxu97</a>*

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

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

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

- ~~[OWNERS](https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver/blob/master/OWNERS)~~ [jingxu97]

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":[]} -->

Patch:
diff --git a/deploy/kubernetes/base/node_windows/node.yaml b/deploy/kubernetes/base/node_windows/node.yaml
index 0e9ecf29..e7c24a01 100644
--- a/deploy/kubernetes/base/node_windows/node.yaml
+++ b/deploy/kubernetes/base/node_windows/node.yaml
@@ -83,3 +83,5 @@ spec:
         hostPath:
           path: \var\lib\kubelet\plugins\pd.csi.storage.gke.io
           type: DirectoryOrCreate
+      tolerations:
+      - operator: Exists
diff --git a/deploy/kubernetes/overlays/dev/kustomization.yaml b/deploy/kubernetes/overlays/dev/kustomization.yaml
index 2db58d45..68fff136 100644
--- a/deploy/kubernetes/overlays/dev/kustomization.yaml
+++ b/deploy/kubernetes/overlays/dev/kustomization.yaml
@@ -1,14 +1,11 @@
 apiVersion: kustomize.config.k8s.io/v1beta1
 kind: Kustomization
+resources:
+- ../alpha
 patchesStrategicMerge:
 - controller_always_pull.yaml
 - node_always_pull.yaml
 namespace: gce-pd-csi-driver
-resources:
-- ../../base/
-# Here dev overlay is using the same image as alpha
-transformers:
-- ../../images/alpha
 # To change the dev image, add something like the following.
 #images:
 #- name: gke.gcr.io/gcp-compute-persistent-disk-csi-driver
diff --git a/deploy/kubernetes/overlays/noauth/kustomization.yaml b/deploy/kubernetes/overlays/noauth/kustomization.yaml
index f4c1b0d5..146ec04d 100644
--- a/deploy/kubernetes/overlays/noauth/kustomization.yaml
+++ b/deploy/kubernetes/overlays/noauth/kustomization.yaml
@@ -1,15 +1,7 @@
 apiVersion: kustomize.config.k8s.io/v1beta1
 kind: Kustomization
 resources:
-- ../../base/
-# Here noauth overlay is using the same image as alpha
-transformers:
-- ../../images/alpha
+- ../dev
 patchesStrategicMerge:
 - noauth.yaml
 namespace: gce-pd-csi-driver
-# To change the dev image, add something like the following.
-#images:
-#- name: gke.gcr.io/gcp-compute-persistent-disk-csi-driver
-#  newName: gcr.io/mattcary-gke-dev-owned/csi/gce-pd-driver
-#  newTag: latest.
diff --git a/go.mod b/go.mod
index 5afc6cae..38802d84 100644
--- a/go.mod
+++ b/go.mod
@@ -9,7 +9,7 @@ require (
 	github.com/golang/protobuf v1.4.2
 	github.com/google/uuid v1.1.1
 	github.com/hashicorp/go-multierror v1.0.0 // indirect
-	github.com/kubernetes-csi/csi-proxy/client v0.2.1
+	github.com/kubernetes-csi/csi-proxy/client v0.2.2
 	github.com/kubernetes-csi/csi-test/v3 v3.0.0
 	github.com/onsi/ginkgo v1.11.0
 	github.com/onsi/gomega v1.7.1
diff --git a/go.sum b/go.sum
index 4e77a8e3..3370814e 100644
--- a/go.sum
+++ b/go.sum
@@ -476,8 +476,11 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
 github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kubernetes-csi/csi-proxy v0.2.2 h1:LqablYFEGw7FYBjwoh5TeXFzlcx8C+YQjKfGy6fFWJs=
 github.com/kubernetes-csi/csi-proxy/client v0.2.1 h1:n21d2U9HvgQ6jfJayafRv8kXXtLvnRNEqoD0mQNucKc=
 github.com/kubernetes-csi/csi-proxy/client v0.2.1/go.mod h1:6ptQQmti5QHwBxSsh8Cy00oGdogj0JXewFnu8FFjgOs=
+github.com/kubernetes-csi/csi-proxy/client v0.2.2 h1:VpMddHnbYA1oBeU5nrisdyrpOAAT0HqME7fsTi6BG2w=
+github.com/kubernetes-csi/csi-proxy/client v0.2.2/go.mod h1:6ptQQmti5QHwBxSsh8Cy00oGdogj0JXewFnu8FFjgOs=
 github.com/kubernetes-csi/csi-test/v3 v3.0.0 h1:mVsfA4J67uNm8fdF/Pr84oMqL92qjIhjWbEUH8zv1fU=
 github.com/kubernetes-csi/csi-test/v3 v3.0.0/go.mod h1:VdIKGnDZHOjg4M5yd0OZICtsoEzdn64d0K33N6dm35Q=
 github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
diff --git a/pkg/gce-cloud-provider/compute/cloud-disk.go b/pkg/gce-cloud-provider/compute/cloud-disk.go
index 86243d98..be04fe03 100644
--- a/pkg/gce-cloud-provider/compute/cloud-disk.go
+++ b/pkg/gce-cloud-provider/compute/cloud-disk.go
@@ -17,89 +17,126 @@ package gcecloudprovider
 import (
 	"strings"
 
-	"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta"
-	computebeta "google.golang.org/api/compute/v0.beta"
+	computealpha "google.golang.org/api/compute/v0.alpha"
 	computev1 "google.golang.org/api/compute/v1"
 )
 
 type CloudDisk struct {
-	disk     *computev1.Disk
-	betaDisk *computebeta.Disk
+	ZonalDisk         *computev1.Disk
+	RegionalDisk      *computev1.Disk
+	ZonalAlphaDisk    *computealpha.Disk
+	RegionalAlphaDisk *computealpha.Disk
 }
 
 type CloudDiskType string
 
-func CloudDiskFromV1(disk *computev1.Disk) *CloudDisk {
+const (
+	// Zonal key type.
+	Zonal = "zonal"
+	// Regional key type.
+	Regional = "regional"
+	// ZonalAlpha key type.
+	ZonalAlpha = "zonalAlpha"
+	// RegionalAlpha key type.
+	RegionalAlpha = "regionalAlpha"
+	// Global key type.
+	Global = "global"
+)
+
+func ZonalCloudDisk(disk *computev1.Disk) *CloudDisk {
 	return &CloudDisk{
-		disk: disk,
+		ZonalDisk: disk,
 	}
 }
 
-func CloudDiskFromBeta(disk *computebeta.Disk) *CloudDisk {
+func RegionalCloudDisk(disk *computev1.Disk) *CloudDisk {
 	return &CloudDisk{
-		betaDisk: disk,
+		RegionalDisk: disk,
 	}
 }
 
-func (d *CloudDisk) LocationType() meta.KeyType {
-	var zone, region string
-	switch {
-	case d.disk != nil:
-		zone = d.disk.Zone
-		region = d.disk.Region
-	case d.betaDisk != nil:
-		zone = d.betaDisk.Zone
-		region = d.betaDisk.Region
+func ZonalAlphaCloudDisk(disk *computealpha.Disk) *CloudDisk {
+	return &CloudDisk{
+		ZonalAlphaDisk: disk,
+	}
+}
+
+func RegionalAlphaCloudDisk(disk *computealpha.Disk) *CloudDisk {
+	return &CloudDisk{
+		RegionalAlphaDisk: disk,
 	}
+}
+
+func (d *CloudDisk) Type() CloudDiskType {
 	switch {
-	case zone != "":
-		return meta.Zonal
-	case region != "":
-		return meta.Regional
+	case d.ZonalDisk != nil:
+		return Zonal
+	case d.RegionalDisk != nil:
+		return Regional
+	case d.ZonalAlphaDisk != nil:
+		return ZonalAlpha
+	case d.RegionalAlphaDisk != nil:
+		return RegionalAlpha
 	default:
-		return meta.Global
+		return Global
 	}
 }
 
 func (d *CloudDisk) GetUsers() []string {
-	switch {
-	case d.disk != nil:
-		return d.disk.Users
-	case d.betaDisk != nil:
-		return d.betaDisk.Users
+	switch d.Type() {
+	case Zonal:
+		return d.ZonalDisk.Users
+	case Regional:
+		return d.RegionalDisk.Users
+	case ZonalAlpha:
+		return d.ZonalAlphaDisk.Users
+	case RegionalAlpha:
+		return d.RegionalAlphaDisk.Users
 	default:
 		return nil
 	}
 }
 
 func (d *CloudDisk) GetName() string {
-	switch {
-	case d.disk != nil:
-		return d.disk.Name
-	case d.betaDisk != nil:
-		return d.betaDisk.Name
+	switch d.Type() {
+	case Zonal:
+		return d.ZonalDisk.Name
+	case Regional:
+		return d.RegionalDisk.Name
+	case ZonalAlpha:
+		return d.ZonalAlphaDisk.Name
+	case RegionalAlpha:
+		return d.RegionalAlphaDisk.Name
 	default:
 		return ""
 	}
 }
 
 func (d *CloudDisk) GetKind() string {
-	switch {
-	case d.disk != nil:
-		return d.disk.Kind
-	case d.betaDisk != nil:
-		return d.betaDisk.Kind
+	switch d.Type() {
+	case Zonal:
+		return d.ZonalDisk.Kind
+	case Regional:
+		return d.RegionalDisk.Kind
+	case ZonalAlpha:
+		return d.ZonalAlphaDisk.Kind
+	case RegionalAlpha:
+		return d.RegionalAlphaDisk.Kind
 	default:
 		return ""
 	}
 }
 
 func (d *CloudDisk) GetStatus() string {
-	switch {
-	case d.disk != nil:
-		return d.disk.Status
-	case d.betaDisk != nil:
-		return d.betaDisk.Status
+	switch d.Type() {
+	case Zonal:
+		return d.ZonalDisk.Status
+	case Regional:
+		return d.RegionalDisk.Status
+	case ZonalAlpha:
+		return d.ZonalAlphaDisk.Status
+	case RegionalAlpha:
+		return d.RegionalAlphaDisk.Status
 	default:
 		return "Unknown"
 	}
@@ -110,11 +147,15 @@ func (d *CloudDisk) GetStatus() string {
 // validated, it is just passed verbatium from GCP.
 func (d *CloudDisk) GetPDType() string {
 	var pdType string
-	switch {
-	case d.disk != nil:
-		pdType = d.disk.Type
-	case d.betaDisk != nil:
-		pdType = d.betaDisk.Type
+	switch d.Type() {
+	case Zonal:
+		pdType = d.ZonalDisk.Type
+	case Regional:
+		pdType = d.RegionalDisk.Type
+	case ZonalAlpha:
+		pdType = d.ZonalAlphaDisk.Type
+	case RegionalAlpha:
+		pdType = d.RegionalAlphaDisk.Type
 	default:
 		return ""
 	}
@@ -123,22 +164,30 @@ func (d *CloudDisk) GetPDType() string {
 }
 
 func (d *CloudDisk) GetSelfLink() string {
-	switch {
-	case d.disk != nil:
-		return d.disk.SelfLink
-	case d.betaDisk != nil:
-		return d.betaDisk.SelfLink
+	switch d.Type() {
+	case Zonal:
+		return d.ZonalDisk.SelfLink
+	case Regional:
+		return d.RegionalDisk.SelfLink
+	case ZonalAlpha:
+		return d.ZonalAlphaDisk.SelfLink
+	case RegionalAlpha:
+		return d.RegionalAlphaDisk.SelfLink
 	default:
 		return ""
 	}
 }
 
 func (d *CloudDisk) GetSizeGb() int64 {
-	switch {
-	case d.disk != nil:
-		return d.disk.SizeGb
-	case d.betaDisk != nil:
-		return d.betaDisk.SizeGb
+	switch d.Type() {
+	case Zonal:
+		return d.ZonalDisk.SizeGb
+	case Regional:
+		return d.RegionalDisk.SizeGb
+	case ZonalAlpha:
+		return d.ZonalAlphaDisk.SizeGb
+	case RegionalAlpha:
+		return d.RegionalAlphaDisk.SizeGb
 	default:
 		return -1
 	}
@@ -147,56 +196,82 @@ func (d *CloudDisk) GetSizeGb() int64 {
 // setSizeGb sets the size of the disk used ONLY
 // for testing purposes.
 func (d *CloudDisk) setSizeGb(size int64) {
-	switch {
-	case d.disk != nil:
-		d.disk.SizeGb = size
-	case d.betaDisk != nil:
-		d.betaDisk.SizeGb = size
+	switch d.Type() {
+	case Zonal:
+		d.ZonalDisk.SizeGb = size
+	case Regional:
+		d.RegionalDisk.SizeGb = size
+	case ZonalAlpha:
+		d.ZonalAlphaDisk.SizeGb = size
+	case RegionalAlpha:
+		d.RegionalAlphaDisk.SizeGb = size
 	}
 }
 
 func (d *CloudDisk) GetZone() string {
-	switch {
-	case d.disk != nil:
-		return d.disk.Zone
-	case d.betaDisk != nil:
-		return d.betaDisk.Zone
+	switch d.Type() {
+	case Zonal:
+		return d.ZonalDisk.Zone
+	case Regional:
+		return d.RegionalDisk.Zone
+	case ZonalAlpha:
+		return d.ZonalAlphaDisk.Zone
+	case RegionalAlpha:
+		return d.RegionalAlphaDisk.Zone
 	default:
 		return ""
 	}
 }
 
 func (d *CloudDisk) GetSnapshotId() string {
-	switch {
-	case d.disk != nil:
-		return d.disk.SourceSnapshotId
-	case d.betaDisk != nil:
-		return d.betaDisk.SourceSnapshotId
+	switch d.Type() {
+	case Zonal:
+		return d.ZonalDisk.SourceSnapshotId
+	case Regional:
+		return d.RegionalDisk.SourceSnapshotId
+	case ZonalAlpha:
+		return d.ZonalAlphaDisk.SourceSnapshotId
+	case RegionalAlpha:
+		return d.RegionalAlphaDisk.SourceSnapshotId
 	default:
 		return ""
 	}
 }
 
 func (d *CloudDisk) GetKMSKeyName() string {
-	switch {
-	case d.disk != nil:
-		if dek := d.disk.DiskEncryptionKey; dek != nil {
-			return dek.KmsKeyName
-		}
-	case d.betaDisk != nil:
-		if dek := d.betaDisk.DiskEncryptionKey; dek != nil {
-			return dek.KmsKeyName
-		}
+	var dek *computev1.CustomerEncryptionKey
+	var dekAlpha *computealpha.CustomerEncryptionKey
+	switch d.Type() {
+	case Zonal:
+		dek = d.ZonalDisk.DiskEncryptionKey
+	case Regional:
+		dek = d.RegionalDisk.DiskEncryptionKey
+	case ZonalAlpha:
+		dekAlpha = d.ZonalAlphaDisk.DiskEncryptionKey
+	case RegionalAlpha:
+		dekAlpha = d.RegionalAlphaDisk.DiskEncryptionKey
+	default:
+		return ""
+	}
+
+	if dek != nil {
+		return dek.KmsKeyName
+	} else if dekAlpha != nil {
+		return dekAlpha.KmsKeyName
 	}
 	return ""
 }
 
 func (d *CloudDisk) GetMultiWriter() bool {
-	switch {
-	case d.disk != nil:
+	switch d.Type() {
+	case Zonal:
+		return false
+	case Regional:
 		return false
-	case d.betaDisk != nil:
-		return d.betaDisk.MultiWriter
+	case ZonalAlpha:
+		return d.ZonalAlphaDisk.MultiWriter
+	case RegionalAlpha:
+		return d.RegionalAlphaDisk.MultiWriter
 	default:
 		return false
 	}
diff --git a/pkg/gce-cloud-provider/compute/fake-gce.go b/pkg/gce-cloud-provider/compute/fake-gce.go
index 93da6fb5..e61e0686 100644
--- a/pkg/gce-cloud-provider/compute/fake-gce.go
+++ b/pkg/gce-cloud-provider/compute/fake-gce.go
@@ -134,9 +134,9 @@ func (cloud *FakeCloudProvider) ListDisks(ctx context.Context, maxEntries int64,
 	}
 
 	for name, cd := range cloud.disks {
-		// Only return v1 disks for simplicity
+		// Only return zonal disks for simplicity
 		if !seen.Has(name) {
-			d = append(d, cd.disk)
+			d = append(d, cd.ZonalDisk)
 			seen.Insert(name)
 			count++
 		}
@@ -260,31 +260,45 @@ func (cloud *FakeCloudProvider) InsertDisk(ctx context.Context, volKey *meta.Key
 		}
 	}
 
-	computeDisk := &computev1.Disk{
-		Name:             volKey.Name,
-		SizeGb:           common.BytesToGb(capBytes),
-		Description:      "Disk created by GCE-PD CSI Driver",
-		Type:             cloud.GetDiskTypeURI(volKey, params.DiskType),
-		SourceSnapshotId: snapshotID,
-		Status:           cloud.mockDiskStatus,
-	}
-	if params.DiskEncryptionKMSKey != "" {
-		computeDisk.DiskEncryptionKey = &computev1.CustomerEncryptionKey{
-			KmsKeyName: params.DiskEncryptionKMSKey,
-		}
-	}
+	var diskToCreate *CloudDisk
 	switch volKey.Type() {
 	case meta.Zonal:
-		computeDisk.Zone = volKey.Zone
-		computeDisk.SelfLink = fmt.Sprintf("projects/%s/zones/%s/disks/%s", cloud.project, volKey.Zone, volKey.Name)
+		diskToCreateGA := &computev1.Disk{
+			Name:             volKey.Name,
+			SizeGb:           common.BytesToGb(capBytes),
+			Description:      "Disk created by GCE-PD CSI Driver",
+			Type:             cloud.GetDiskTypeURI(volKey, params.DiskType),
+			SelfLink:         fmt.Sprintf("projects/%s/zones/%s/disks/%s", cloud.project, volKey.Zone, volKey.Name),
+			SourceSnapshotId: snapshotID,
+			Status:           cloud.mockDiskStatus,
+		}
+		if params.DiskEncryptionKMSKey != "" {
+			diskToCreateGA.DiskEncryptionKey = &computev1.CustomerEncryptionKey{
+				KmsKeyName: params.DiskEncryptionKMSKey,
+			}
+		}
+		diskToCreate = ZonalCloudDisk(diskToCreateGA)
 	case meta.Regional:
-		computeDisk.Region = volKey.Region
-		computeDisk.SelfLink = fmt.Sprintf("projects/%s/regions/%s/disks/%s", cloud.project, volKey.Region, volKey.Name)
+		diskToCreateV1 := &computev1.Disk{
+			Name:             volKey.Name,
+			SizeGb:           common.BytesToGb(capBytes),
+			Description:      "Regional disk created by GCE-PD CSI Driver",
+			Type:             cloud.GetDiskTypeURI(volKey, params.DiskType),
+			SelfLink:         fmt.Sprintf("projects/%s/regions/%s/disks/%s", cloud.project, volKey.Region, volKey.Name),
+			SourceSnapshotId: snapshotID,
+			Status:           cloud.mockDiskStatus,
+		}
+		if params.DiskEncryptionKMSKey != "" {
+			diskToCreateV1.DiskEncryptionKey = &computev1.CustomerEncryptionKey{
+				KmsKeyName: params.DiskEncryptionKMSKey,
+			}
+		}
+		diskToCreate = RegionalCloudDisk(diskToCreateV1)
 	default:
 		return fmt.Errorf("could not create disk, key was neither zonal nor regional, instead got: %v", volKey.String())
 	}
 
-	cloud.disks[volKey.Name] = CloudDiskFromV1(computeDisk)
+	cloud.disks[volKey.Name] = diskToCreate
 	return nil
 }
 
@@ -442,9 +456,9 @@ func (cloud *FakeCloudProvider) ValidateExistingSnapshot(resp *computev1.Snapsho
 
 func (cloud *FakeCloudProvider) GetDiskSourceURI(volKey *meta.Key) string {
 	switch volKey.Type() {
-	case meta.Zonal:
+	case Zonal:
 		return cloud.getZonalDiskSourceURI(volKey.Name, volKey.Zone)
-	case meta.Regional:
+	case Regional:
 		return cloud.getRegionalDiskSourceURI(volKey.Name, volKey.Region)
 	default:
 		return ""
diff --git a/pkg/gce-cloud-provider/compute/gce-compute.go b/pkg/gce-cloud-provider/compute/gce-compute.go
index afca4bba..37b173b0 100644
--- a/pkg/gce-cloud-provider/compute/gce-compute.go
+++ b/pkg/gce-cloud-provider/compute/gce-compute.go
@@ -15,15 +15,16 @@ limitations under the License.
 package gcecloudprovider
 
 import (
-	"context"
 	"encoding/json"
 	"fmt"
 	"strings"
 	"time"
 
+	"context"
+
 	"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta"
 	csi "github.com/container-storage-interface/spec/lib/go/csi"
-	computebeta "google.golang.org/api/compute/v0.beta"
+	computealpha "google.golang.org/api/compute/v0.alpha"
 	computev1 "google.golang.org/api/compute/v1"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
@@ -45,7 +46,7 @@ const (
 	// V1 key type
 	GCEAPIVersionV1 GCEAPIVersion = "v1"
 	// Alpha key type
-	GCEAPIVersionBeta GCEAPIVersion = "beta"
+	GCEAPIVersionAlpha GCEAPIVersion = "alpha"
 )
 
 type GCECompute interface {
@@ -192,20 +193,20 @@ func (cloud *CloudProvider) GetDisk(ctx context.Context, key *meta.Key, gceAPIVe
 	klog.V(5).Infof("Getting disk %v", key)
 	switch key.Type() {
 	case meta.Zonal:
-		if gceAPIVersion == GCEAPIVersionBeta {
-			disk, err := cloud.getZonalBetaDiskOrError(ctx, key.Zone, key.Name)
-			return CloudDiskFromBeta(disk), err
+		if gceAPIVersion == GCEAPIVersionAlpha {
+			disk, err := cloud.getZonalAlphaDiskOrError(ctx, key.Zone, key.Name)
+			return ZonalAlphaCloudDisk(disk), err
 		} else {
 			disk, err := cloud.getZonalDiskOrError(ctx, key.Zone, key.Name)
-			return CloudDiskFromV1(disk), err
+			return ZonalCloudDisk(disk), err
 		}
 	case meta.Regional:
-		if gceAPIVersion == GCEAPIVersionBeta {
+		if gceAPIVersion == GCEAPIVersionAlpha {
 			disk, err := cloud.getRegionalAlphaDiskOrError(ctx, key.Region, key.Name)
-			return CloudDiskFromBeta(disk), err
+			return RegionalAlphaCloudDisk(disk), err
 		} else {
 			disk, err := cloud.getRegionalDiskOrError(ctx, key.Region, key.Name)
-			return CloudDiskFromV1(disk), err
+			return RegionalCloudDisk(disk), err
 		}
 	default:
 		return nil, fmt.Errorf("key was neither zonal nor regional, got: %v", key.String())
@@ -232,18 +233,18 @@ func (cloud *CloudProvider) getRegionalDiskOrError(ctx context.Context, volumeRe
 	return disk, nil
 }
 
-func (cloud *CloudProvider) getZonalBetaDiskOrError(ctx context.Context, volumeZone, volumeName string) (*computebeta.Disk, error) {
+func (cloud *CloudProvider) getZonalAlphaDiskOrError(ctx context.Context, volumeZone, volumeName string) (*computealpha.Disk, error) {
 	project := cloud.project
-	disk, err := cloud.betaService.Disks.Get(project, volumeZone, volumeName).Context(ctx).Do()
+	disk, err := cloud.alphaService.Disks.Get(project, volumeZone, volumeName).Context(ctx).Do()
 	if err != nil {
 		return nil, err
 	}
 	return disk, nil
 }
 
-func (cloud *CloudProvider) getRegionalAlphaDiskOrError(ctx context.Context, volumeRegion, volumeName string) (*computebeta.Disk, error) {
+func (cloud *CloudProvider) getRegionalAlphaDiskOrError(ctx context.Context, volumeRegion, volumeName string) (*computealpha.Disk, error) {
 	project := cloud.project
-	disk, err := cloud.betaService.RegionDisks.Get(project, volumeRegion, volumeName).Context(ctx).Do()
+	disk, err := cloud.alphaService.RegionDisks.Get(project, volumeRegion, volumeName).Context(ctx).Do()
 	if err != nil {
 		return nil, err
 	}
@@ -292,9 +293,12 @@ func ValidateDiskParameters(disk *CloudDisk, params common.DiskParameters) error
 		return fmt.Errorf("actual pd type %s did not match the expected param %s", disk.GetPDType(), params.DiskType)
 	}
 
-	locationType := disk.LocationType()
-	if (params.ReplicationType == "none" && locationType != meta.Zonal) || (params.ReplicationType == "regional-pd" && locationType != meta.Regional) {
-		return fmt.Errorf("actual disk replication type %v did not match expected param %s", locationType, params.ReplicationType)
+	if params.ReplicationType == "none" && disk.Type() != Zonal && disk.Type() != ZonalAlpha {
+		return fmt.Errorf("actual disk replication type %v did not match expected param %s", disk.Type(), params.ReplicationType)
+	}
+
+	if params.ReplicationType == "regional-pd" && disk.Type() != Regional && disk.Type() != RegionalAlpha {
+		return fmt.Errorf("actual disk replication type %v did not match expected param %s", disk.Type(), "regional-pd")
 	}
 
 	if !kmsKeyEqual(
@@ -330,8 +334,8 @@ func (cloud *CloudProvider) InsertDisk(ctx context.Context, volKey *meta.Key, pa
 	}
 }
 
-func convertV1CustomerEncryptionKeyToBeta(v1Key *computev1.CustomerEncryptionKey) *computebeta.CustomerEncryptionKey {
-	return &computebeta.CustomerEncryptionKey{
+func convertV1CustomerEncryptionKeyToAlpha(v1Key *computev1.CustomerEncryptionKey) *computealpha.CustomerEncryptionKey {
+	return &computealpha.CustomerEncryptionKey{
 		KmsKeyName:      v1Key.KmsKeyName,
 		RawKey:          v1Key.RawKey,
 		Sha256:          v1Key.Sha256,
@@ -340,15 +344,15 @@ func convertV1CustomerEncryptionKeyToBeta(v1Key *computev1.CustomerEncryptionKey
 	}
 }
 
-func convertV1DiskToBetaDisk(v1Disk *computev1.Disk) *computebeta.Disk {
-	var dek *computebeta.CustomerEncryptionKey = nil
+func convertV1DiskToAlphaDisk(v1Disk *computev1.Disk) *computealpha.Disk {
+	var dek *computealpha.CustomerEncryptionKey = nil
 
 	if v1Disk.DiskEncryptionKey != nil {
-		dek = convertV1CustomerEncryptionKeyToBeta(v1Disk.DiskEncryptionKey)
+		dek = convertV1CustomerEncryptionKeyToAlpha(v1Disk.DiskEncryptionKey)
 	}
 
 	// Note: this is an incomplete list. It only includes the fields we use for disk creation.
-	return &computebeta.Disk{
+	return &computealpha.Disk{
 		Name:              v1Disk.Name,
 		SizeGb:            v1Disk.SizeGb,
 		Description:       v1Disk.Description,
@@ -376,7 +380,7 @@ func (cloud *CloudProvider) insertRegionalDisk(
 	)
 
 	if multiWriter {
-		gceAPIVersion = GCEAPIVersionBeta
+		gceAPIVersion = GCEAPIVersionAlpha
 	}
 
 	diskToCreate := &computev1.Disk{
@@ -397,11 +401,11 @@ func (cloud *CloudProvider) insertRegionalDisk(
 		}
 	}
 
-	if gceAPIVersion == GCEAPIVersionBeta {
-		var insertOp *computebeta.Operation
-		betaDiskToCreate := convertV1DiskToBetaDisk(diskToCreate)
-		betaDiskToCreate.MultiWriter = multiWriter
-		insertOp, err = cloud.betaService.RegionDisks.Insert(cloud.project, volKey.Region, betaDiskToCreate).Context(ctx).Do()
+	if gceAPIVersion == GCEAPIVersionAlpha {
+		var insertOp *computealpha.Operation
+		alphaDiskToCreate := convertV1DiskToAlphaDisk(diskToCreate)
+		alphaDiskToCreate.MultiWriter = multiWriter
+		insertOp, err = cloud.alphaService.RegionDisks.Insert(cloud.project, volKey.Region, alphaDiskToCreate).Context(ctx).Do()
 		if insertOp != nil {
 			opName = insertOp.Name
 		}
@@ -469,7 +473,7 @@ func (cloud *CloudProvider) insertZonalDisk(
 	)
 
 	if multiWriter {
-		gceAPIVersion = GCEAPIVersionBeta
+		gceAPIVersion = GCEAPIVersionAlpha
 	}
 
 	diskToCreate := &computev1.Disk{
@@ -489,11 +493,11 @@ func (cloud *CloudProvider) insertZonalDisk(
 		}
 	}
 
-	if gceAPIVersion == GCEAPIVersionBeta {
-		var insertOp *computebeta.Operation
-		betaDiskToCreate := convertV1DiskToBetaDisk(diskToCreate)
-		betaDiskToCreate.MultiWriter = multiWriter
-		insertOp, err = cloud.betaService.Disks.Insert(cloud.project, volKey.Zone, betaDiskToCreate).Context(ctx).Do()
+	if gceAPIVersion == GCEAPIVersionAlpha {
+		var insertOp *computealpha.Operation
+		alphaDiskToCreate := convertV1DiskToAlphaDisk(diskToCreate)
+		alphaDiskToCreate.MultiWriter = multiWriter
+		insertOp, err = cloud.alphaService.Disks.Insert(cloud.project, volKey.Zone, alphaDiskToCreate).Context(ctx).Do()
 		if insertOp != nil {
 			opName = insertOp.Name
 		}
@@ -633,9 +637,9 @@ func (cloud *CloudProvider) DetachDisk(ctx context.Context, deviceName, instance
 
 func (cloud *CloudProvider) GetDiskSourceURI(volKey *meta.Key) string {
 	switch volKey.Type() {
-	case meta.Zonal:
+	case Zonal:
 		return cloud.getZonalDiskSourceURI(volKey.Name, volKey.Zone)
-	case meta.Regional:
+	case Regional:
 		return cloud.getRegionalDiskSourceURI(volKey.Name, volKey.Region)
 	default:
 		return ""
diff --git a/pkg/gce-cloud-provider/compute/gce.go b/pkg/gce-cloud-provider/compute/gce.go
index 2385889b..0686a68e 100644
--- a/pkg/gce-cloud-provider/compute/gce.go
+++ b/pkg/gce-cloud-provider/compute/gce.go
@@ -23,12 +23,11 @@ import (
 	"time"
 
 	"golang.org/x/oauth2/google"
-	"google.golang.org/api/option"
 	"gopkg.in/gcfg.v1"
 
 	"cloud.google.com/go/compute/metadata"
 	"golang.org/x/oauth2"
-	computebeta "google.golang.org/api/compute/v0.beta"
+	alpha "google.golang.org/api/compute/v0.alpha"
 	"google.golang.org/api/compute/v1"
 	"google.golang.org/api/googleapi"
 	"k8s.io/apimachinery/pkg/util/wait"
@@ -52,12 +51,12 @@ const (
 )
 
 type CloudProvider struct {
-	service     *compute.Service
-	betaService *computebeta.Service
-	project     string
-	zone        string
+	service      *compute.Service
+	alphaService *alpha.Service
+	project      string
+	zone         string
 
-	zonesCache map[string][]string
+	zonesCache map[string]([]string)
 }
 
 var _ GCECompute = &CloudProvider{}
@@ -93,7 +92,7 @@ func CreateCloudProvider(ctx context.Context, vendorVersion string, configPath s
 		return nil, err
 	}
 
-	betasvc, err := createBetaCloudService(ctx, vendorVersion, tokenSource)
+	alphasvc, err := createAlphaCloudService(ctx, vendorVersion, tokenSource)
 	if err != nil {
 		return nil, err
 	}
@@ -104,11 +103,11 @@ func CreateCloudProvider(ctx context.Context, vendorVersion string, configPath s
 	}
 
 	return &CloudProvider{
-		service:     svc,
-		betaService: betasvc,
-		project:     project,
-		zone:        zone,
-		zonesCache:  make(map[string]([]string)),
+		service:      svc,
+		alphaService: alphasvc,
+		project:      project,
+		zone:         zone,
+		zonesCache:   make(map[string]([]string)),
 	}, nil
 
 }
@@ -159,12 +158,12 @@ func readConfig(configPath string) (*ConfigFile, error) {
 	return cfg, nil
 }
 
-func createBetaCloudService(ctx context.Context, vendorVersion string, tokenSource oauth2.TokenSource) (*computebeta.Service, error) {
+func createAlphaCloudService(ctx context.Context, vendorVersion string, tokenSource oauth2.TokenSource) (*alpha.Service, error) {
 	client, err := newOauthClient(ctx, tokenSource)
 	if err != nil {
 		return nil, err
 	}
-	service, err := computebeta.NewService(ctx, option.WithHTTPClient(client))
+	service, err := alpha.New(client)
 	if err != nil {
 		return nil, err
 	}
diff --git a/pkg/gce-pd-csi-driver/controller.go b/pkg/gce-pd-csi-driver/controller.go
index 6974b18a..bde1d4b2 100644
--- a/pkg/gce-pd-csi-driver/controller.go
+++ b/pkg/gce-pd-csi-driver/controller.go
@@ -115,7 +115,7 @@ func (gceCS *GCEControllerServer) CreateVolume(ctx context.Context, req *csi.Cre
 	gceAPIVersion := gce.GCEAPIVersionV1
 	multiWriter, _ := getMultiWriterFromCapabilities(volumeCapabilities)
 	if multiWriter {
-		gceAPIVersion = gce.GCEAPIVersionBeta
+		gceAPIVersion = gce.GCEAPIVersionAlpha
 	}
 	// Determine the zone or zones+region of the disk
 	var zones []string
@@ -1033,7 +1033,7 @@ func createRegionalDisk(ctx context.Context, cloudProvider gce.GCECompute, name
 
 	gceAPIVersion := gce.GCEAPIVersionV1
 	if multiWriter {
-		gceAPIVersion = gce.GCEAPIVersionBeta
+		gceAPIVersion = gce.GCEAPIVersionAlpha
 	}
 
 	disk, err := cloudProvider.GetDisk(ctx, meta.RegionalKey(name, region), gceAPIVersion)
@@ -1055,7 +1055,7 @@ func createSingleZoneDisk(ctx context.Context, cloudProvider gce.GCECompute, nam
 
 	gceAPIVersion := gce.GCEAPIVersionV1
 	if multiWriter {
-		gceAPIVersion = gce.GCEAPIVersionBeta
+		gceAPIVersion = gce.GCEAPIVersionAlpha
 	}
 	disk, err := cloudProvider.GetDisk(ctx, meta.ZonalKey(name, diskZone), gceAPIVersion)
 	if err != nil {
diff --git a/pkg/mount-manager/safe-mounter_windows.go b/pkg/mount-manager/safe-mounter_windows.go
index 11645c01..1eb1708c 100644
--- a/pkg/mount-manager/safe-mounter_windows.go
+++ b/pkg/mount-manager/safe-mounter_windows.go
@@ -22,10 +22,11 @@ import (
 	"fmt"
 	"os"
 	"path/filepath"
+	"strconv"
 	"strings"
 
-	diskapi "github.com/kubernetes-csi/csi-proxy/client/api/disk/v1beta1"
-	diskclient "github.com/kubernetes-csi/csi-proxy/client/groups/disk/v1beta1"
+	diskapi "github.com/kubernetes-csi/csi-proxy/client/api/disk/v1beta2"
+	diskclient "github.com/kubernetes-csi/csi-proxy/client/groups/disk/v1beta2"
 
 	fsapi "github.com/kubernetes-csi/csi-proxy/client/api/filesystem/v1beta1"
 	fsclient "github.com/kubernetes-csi/csi-proxy/client/groups/filesystem/v1beta1"
@@ -159,6 +160,25 @@ func (mounter *CSIProxyMounter) UnmountDevice(target string) error {
 	if err != nil {
 		return err
 	}
+
+	// Set disk to offline mode to have a clean state
+	getDiskNumberRequest := &volumeapi.VolumeDiskNumberRequest{
+		VolumeId: volumeId,
+	}
+	id, err := mounter.VolumeClient.GetVolumeDiskNumber(context.Background(), getDiskNumberRequest)
+	if err != nil {
+		return err
+	}
+	diskId := id.GetDiskNumber()
+	klog.V(4).Infof("get disk number %d from volume %s", diskId, volumeId)
+	setDiskRequest := &diskapi.SetAttachStateRequest{
+		DiskID:   strconv.FormatInt(diskId, 10),
+		IsOnline: false,
+	}
+	if _, err = mounter.DiskClient.SetAttachState(context.Background(), setDiskRequest); err != nil {
+		return err
+	}
+
 	return nil
 }
 
@@ -203,6 +223,17 @@ func (mounter *CSIProxyMounter) FormatAndMount(source string, target string, fst
 	if err != nil {
 		return err
 	}
+
+	// make sure disk is online. if disk is already online, this call should also succeed.
+	setDiskRequest := &diskapi.SetAttachStateRequest{
+		DiskID:   source,
+		IsOnline: true,
+	}
+	_, err = mounter.DiskClient.SetAttachState(context.Background(), setDiskRequest)
+	if err != nil {
+		return err
+	}
+
 	volumeIDsRequest := &volumeapi.ListVolumesOnDiskRequest{
 		DiskId: source,
 	}
diff --git a/vendor/github.com/kubernetes-csi/csi-proxy/client/api/disk/v1beta2/api.pb.go b/vendor/github.com/kubernetes-csi/csi-proxy/client/api/disk/v1beta2/api.pb.go
new file mode 100644
index 00000000..27324f1e
--- /dev/null
+++ b/vendor/github.com/kubernetes-csi/csi-proxy/client/api/disk/v1beta2/api.pb.go
@@ -0,0 +1,1028 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: github.com/kubernetes-csi/csi-proxy/client/api/disk/v1beta2/api.proto
+
+package v1beta2
+
+import (
+	context "context"
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type ListDiskLocationsRequest struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ListDiskLocationsRequest) Reset()         { *m = ListDiskLocationsRequest{} }
+func (m *ListDiskLocationsRequest) String() string { return proto.CompactTextString(m) }
+func (*ListDiskLocationsRequest) ProtoMessage()    {}
+func (*ListDiskLocationsRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b8298108b4474af1, []int{0}
+}
+
+func (m *ListDiskLocationsRequest) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ListDiskLocationsRequest.Unmarshal(m, b)
+}
+func (m *ListDiskLocationsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ListDiskLocationsRequest.Marshal(b, m, deterministic)
+}
+func (m *ListDiskLocationsRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ListDiskLocationsRequest.Merge(m, src)
+}
+func (m *ListDiskLocationsRequest) XXX_Size() int {
+	return xxx_messageInfo_ListDiskLocationsRequest.Size(m)
+}
+func (m *ListDiskLocationsRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_ListDiskLocationsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ListDiskLocationsRequest proto.InternalMessageInfo
+
+type DiskLocation struct {
+	Adapter              string   `protobuf:"bytes,1,opt,name=Adapter,proto3" json:"Adapter,omitempty"`
+	Bus                  string   `protobuf:"bytes,2,opt,name=Bus,proto3" json:"Bus,omitempty"`
+	Target               string   `protobuf:"bytes,3,opt,name=Target,proto3" json:"Target,omitempty"`
+	LUNID                string   `protobuf:"bytes,4,opt,name=LUNID,proto3" json:"LUNID,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *DiskLocation) Reset()         { *m = DiskLocation{} }
+func (m *DiskLocation) String() string { return proto.CompactTextString(m) }
+func (*DiskLocation) ProtoMessage()    {}
+func (*DiskLocation) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b8298108b4474af1, []int{1}
+}
+
+func (m *DiskLocation) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_DiskLocation.Unmarshal(m, b)
+}
+func (m *DiskLocation) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_DiskLocation.Marshal(b, m, deterministic)
+}
+func (m *DiskLocation) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DiskLocation.Merge(m, src)
+}
+func (m *DiskLocation) XXX_Size() int {
+	return xxx_messageInfo_DiskLocation.Size(m)
+}
+func (m *DiskLocation) XXX_DiscardUnknown() {
+	xxx_messageInfo_DiskLocation.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DiskLocation proto.InternalMessageInfo
+
+func (m *DiskLocation) GetAdapter() string {
+	if m != nil {
+		return m.Adapter
+	}
+	return ""
+}
+
+func (m *DiskLocation) GetBus() string {
+	if m != nil {
+		return m.Bus
+	}
+	return ""
+}
+
+func (m *DiskLocation) GetTarget() string {
+	if m != nil {
+		return m.Target
+	}
+	return ""
+}
+
+func (m *DiskLocation) GetLUNID() string {
+	if m != nil {
+		return m.LUNID
+	}
+	return ""
+}
+
+type ListDiskLocationsResponse struct {
+	// Map of disk device IDs and <adapter, bus, target, lun ID> associated with each disk device
+	DiskLocations        map[string]*DiskLocation `protobuf:"bytes,1,rep,name=disk_locations,json=diskLocations,proto3" json:"disk_locations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	XXX_NoUnkeyedLiteral struct{}                 `json:"-"`
+	XXX_unrecognized     []byte                   `json:"-"`
+	XXX_sizecache        int32                    `json:"-"`
+}
+
+func (m *ListDiskLocationsResponse) Reset()         { *m = ListDiskLocationsResponse{} }
+func (m *ListDiskLocationsResponse) String() string { return proto.CompactTextString(m) }
+func (*ListDiskLocationsResponse) ProtoMessage()    {}
+func (*ListDiskLocationsResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b8298108b4474af1, []int{2}
+}
+
+func (m *ListDiskLocationsResponse) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ListDiskLocationsResponse.Unmarshal(m, b)
+}
+func (m *ListDiskLocationsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ListDiskLocationsResponse.Marshal(b, m, deterministic)
+}
+func (m *ListDiskLocationsResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ListDiskLocationsResponse.Merge(m, src)
+}
+func (m *ListDiskLocationsResponse) XXX_Size() int {
+	return xxx_messageInfo_ListDiskLocationsResponse.Size(m)
+}
+func (m *ListDiskLocationsResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_ListDiskLocationsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ListDiskLocationsResponse proto.InternalMessageInfo
+
+func (m *ListDiskLocationsResponse) GetDiskLocations() map[string]*DiskLocation {
+	if m != nil {
+		return m.DiskLocations
+	}
+	return nil
+}
+
+type PartitionDiskRequest struct {
+	// Disk device ID of the disk to partition
+	DiskID               string   `protobuf:"bytes,1,opt,name=diskID,proto3" json:"diskID,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *PartitionDiskRequest) Reset()         { *m = PartitionDiskRequest{} }
+func (m *PartitionDiskRequest) String() string { return proto.CompactTextString(m) }
+func (*PartitionDiskRequest) ProtoMessage()    {}
+func (*PartitionDiskRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b8298108b4474af1, []int{3}
+}
+
+func (m *PartitionDiskRequest) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_PartitionDiskRequest.Unmarshal(m, b)
+}
+func (m *PartitionDiskRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_PartitionDiskRequest.Marshal(b, m, deterministic)
+}
+func (m *PartitionDiskRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PartitionDiskRequest.Merge(m, src)
+}
+func (m *PartitionDiskRequest) XXX_Size() int {
+	return xxx_messageInfo_PartitionDiskRequest.Size(m)
+}
+func (m *PartitionDiskRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_PartitionDiskRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PartitionDiskRequest proto.InternalMessageInfo
+
+func (m *PartitionDiskRequest) GetDiskID() string {
+	if m != nil {
+		return m.DiskID
+	}
+	return ""
+}
+
+type PartitionDiskResponse struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *PartitionDiskResponse) Reset()         { *m = PartitionDiskResponse{} }
+func (m *PartitionDiskResponse) String() string { return proto.CompactTextString(m) }
+func (*PartitionDiskResponse) ProtoMessage()    {}
+func (*PartitionDiskResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b8298108b4474af1, []int{4}
+}
+
+func (m *PartitionDiskResponse) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_PartitionDiskResponse.Unmarshal(m, b)
+}
+func (m *PartitionDiskResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_PartitionDiskResponse.Marshal(b, m, deterministic)
+}
+func (m *PartitionDiskResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PartitionDiskResponse.Merge(m, src)
+}
+func (m *PartitionDiskResponse) XXX_Size() int {
+	return xxx_messageInfo_PartitionDiskResponse.Size(m)
+}
+func (m *PartitionDiskResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_PartitionDiskResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PartitionDiskResponse proto.InternalMessageInfo
+
+type RescanRequest struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *RescanRequest) Reset()         { *m = RescanRequest{} }
+func (m *RescanRequest) String() string { return proto.CompactTextString(m) }
+func (*RescanRequest) ProtoMessage()    {}
+func (*RescanRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b8298108b4474af1, []int{5}
+}
+
+func (m *RescanRequest) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_RescanRequest.Unmarshal(m, b)
+}
+func (m *RescanRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_RescanRequest.Marshal(b, m, deterministic)
+}
+func (m *RescanRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RescanRequest.Merge(m, src)
+}
+func (m *RescanRequest) XXX_Size() int {
+	return xxx_messageInfo_RescanRequest.Size(m)
+}
+func (m *RescanRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_RescanRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_RescanRequest proto.InternalMessageInfo
+
+type RescanResponse struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *RescanResponse) Reset()         { *m = RescanResponse{} }
+func (m *RescanResponse) String() string { return proto.CompactTextString(m) }
+func (*RescanResponse) ProtoMessage()    {}
+func (*RescanResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b8298108b4474af1, []int{6}
+}
+
+func (m *RescanResponse) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_RescanResponse.Unmarshal(m, b)
+}
+func (m *RescanResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_RescanResponse.Marshal(b, m, deterministic)
+}
+func (m *RescanResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RescanResponse.Merge(m, src)
+}
+func (m *RescanResponse) XXX_Size() int {
+	return xxx_messageInfo_RescanResponse.Size(m)
+}
+func (m *RescanResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_RescanResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_RescanResponse proto.InternalMessageInfo
+
+type ListDiskIDsRequest struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ListDiskIDsRequest) Reset()         { *m = ListDiskIDsRequest{} }
+func (m *ListDiskIDsRequest) String() string { return proto.CompactTextString(m) }
+func (*ListDiskIDsRequest) ProtoMessage()    {}
+func (*ListDiskIDsRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b8298108b4474af1, []int{7}
+}
+
+func (m *ListDiskIDsRequest) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ListDiskIDsRequest.Unmarshal(m, b)
+}
+func (m *ListDiskIDsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ListDiskIDsRequest.Marshal(b, m, deterministic)
+}
+func (m *ListDiskIDsRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ListDiskIDsRequest.Merge(m, src)
+}
+func (m *ListDiskIDsRequest) XXX_Size() int {
+	return xxx_messageInfo_ListDiskIDsRequest.Size(m)
+}
+func (m *ListDiskIDsRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_ListDiskIDsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ListDiskIDsRequest proto.InternalMessageInfo
+
+type DiskIDs struct {
+	// Map of Disk ID types and Disk ID values
+	Identifiers          map[string]string `protobuf:"bytes,1,rep,name=identifiers,proto3" json:"identifiers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
+	XXX_unrecognized     []byte            `json:"-"`
+	XXX_sizecache        int32             `json:"-"`
+}
+
+func (m *DiskIDs) Reset()         { *m = DiskIDs{} }
+func (m *DiskIDs) String() string { return proto.CompactTextString(m) }
+func (*DiskIDs) ProtoMessage()    {}
+func (*DiskIDs) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b8298108b4474af1, []int{8}
+}
+
+func (m *DiskIDs) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_DiskIDs.Unmarshal(m, b)
+}
+func (m *DiskIDs) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_DiskIDs.Marshal(b, m, deterministic)
+}
+func (m *DiskIDs) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DiskIDs.Merge(m, src)
+}
+func (m *DiskIDs) XXX_Size() int {
+	return xxx_messageInfo_DiskIDs.Size(m)
+}
+func (m *DiskIDs) XXX_DiscardUnknown() {
+	xxx_messageInfo_DiskIDs.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DiskIDs proto.InternalMessageInfo
+
+func (m *DiskIDs) GetIdentifiers() map[string]string {
+	if m != nil {
+		return m.Identifiers
+	}
+	return nil
+}
+
+type ListDiskIDsResponse struct {
+	// Map of disk device numbers and IDs <page83> associated with each disk device
+	DiskIDs              map[string]*DiskIDs `protobuf:"bytes,1,rep,name=diskIDs,proto3" json:"diskIDs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	XXX_NoUnkeyedLiteral struct{}            `json:"-"`
+	XXX_unrecognized     []byte              `json:"-"`
+	XXX_sizecache        int32               `json:"-"`
+}
+
+func (m *ListDiskIDsResponse) Reset()         { *m = ListDiskIDsResponse{} }
+func (m *ListDiskIDsResponse) String() string { return proto.CompactTextString(m) }
+func (*ListDiskIDsResponse) ProtoMessage()    {}
+func (*ListDiskIDsResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b8298108b4474af1, []int{9}
+}
+
+func (m *ListDiskIDsResponse) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ListDiskIDsResponse.Unmarshal(m, b)
+}
+func (m *ListDiskIDsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ListDiskIDsResponse.Marshal(b, m, deterministic)
+}
+func (m *ListDiskIDsResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ListDiskIDsResponse.Merge(m, src)
+}
+func (m *ListDiskIDsResponse) XXX_Size() int {
+	return xxx_messageInfo_ListDiskIDsResponse.Size(m)
+}
+func (m *ListDiskIDsResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_ListDiskIDsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ListDiskIDsResponse proto.InternalMessageInfo
+
+func (m *ListDiskIDsResponse) GetDiskIDs() map[string]*DiskIDs {
+	if m != nil {
+		return m.DiskIDs
+	}
+	return nil
+}
+
+type DiskStatsRequest struct {
+	// Disk device ID of the disk to get the size from
+	DiskID               string   `protobuf:"bytes,1,opt,name=diskID,proto3" json:"diskID,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *DiskStatsRequest) Reset()         { *m = DiskStatsRequest{} }
+func (m *DiskStatsRequest) String() string { return proto.CompactTextString(m) }
+func (*DiskStatsRequest) ProtoMessage()    {}
+func (*DiskStatsRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b8298108b4474af1, []int{10}
+}
+
+func (m *DiskStatsRequest) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_DiskStatsRequest.Unmarshal(m, b)
+}
+func (m *DiskStatsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_DiskStatsRequest.Marshal(b, m, deterministic)
+}
+func (m *DiskStatsRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DiskStatsRequest.Merge(m, src)
+}
+func (m *DiskStatsRequest) XXX_Size() int {
+	return xxx_messageInfo_DiskStatsRequest.Size(m)
+}
+func (m *DiskStatsRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_DiskStatsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DiskStatsRequest proto.InternalMessageInfo
+
+func (m *DiskStatsRequest) GetDiskID() string {
+	if m != nil {
+		return m.DiskID
+	}
+	return ""
+}
+
+type DiskStatsResponse struct {
+	//Total size of the volume
+	DiskSize             int64    `protobuf:"varint,1,opt,name=diskSize,proto3" json:"diskSize,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *DiskStatsResponse) Reset()         { *m = DiskStatsResponse{} }
+func (m *DiskStatsResponse) String() string { return proto.CompactTextString(m) }
+func (*DiskStatsResponse) ProtoMessage()    {}
+func (*DiskStatsResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b8298108b4474af1, []int{11}
+}
+
+func (m *DiskStatsResponse) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_DiskStatsResponse.Unmarshal(m, b)
+}
+func (m *DiskStatsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_DiskStatsResponse.Marshal(b, m, deterministic)
+}
+func (m *DiskStatsResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DiskStatsResponse.Merge(m, src)
+}
+func (m *DiskStatsResponse) XXX_Size() int {
+	return xxx_messageInfo_DiskStatsResponse.Size(m)
+}
+func (m *DiskStatsResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_DiskStatsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DiskStatsResponse proto.InternalMessageInfo
+
+func (m *DiskStatsResponse) GetDiskSize() int64 {
+	if m != nil {
+		return m.DiskSize
+	}
+	return 0
+}
+
+type SetAttachStateRequest struct {
+	// Disk device ID (number) of the disk which state will change
+	DiskID string `protobuf:"bytes,1,opt,name=diskID,proto3" json:"diskID,omitempty"`
+	// Online state to set for the disk. true for online, false for offline
+	IsOnline             bool     `protobuf:"varint,2,opt,name=isOnline,proto3" json:"isOnline,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *SetAttachStateRequest) Reset()         { *m = SetAttachStateRequest{} }
+func (m *SetAttachStateRequest) String() string { return proto.CompactTextString(m) }
+func (*SetAttachStateRequest) ProtoMessage()    {}
+func (*SetAttachStateRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b8298108b4474af1, []int{12}
+}
+
+func (m *SetAttachStateRequest) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_SetAttachStateRequest.Unmarshal(m, b)
+}
+func (m *SetAttachStateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_SetAttachStateRequest.Marshal(b, m, deterministic)
+}
+func (m *SetAttachStateRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_SetAttachStateRequest.Merge(m, src)
+}
+func (m *SetAttachStateRequest) XXX_Size() int {
+	return xxx_messageInfo_SetAttachStateRequest.Size(m)
+}
+func (m *SetAttachStateRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_SetAttachStateRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SetAttachStateRequest proto.InternalMessageInfo
+
+func (m *SetAttachStateRequest) GetDiskID() string {
+	if m != nil {
+		return m.DiskID
+	}
+	return ""
+}
+
+func (m *SetAttachStateRequest) GetIsOnline() bool {
+	if m != nil {
+		return m.IsOnline
+	}
+	return false
+}
+
+type SetAttachStateResponse struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *SetAttachStateResponse) Reset()         { *m = SetAttachStateResponse{} }
+func (m *SetAttachStateResponse) String() string { return proto.CompactTextString(m) }
+func (*SetAttachStateResponse) ProtoMessage()    {}
+func (*SetAttachStateResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b8298108b4474af1, []int{13}
+}
+
+func (m *SetAttachStateResponse) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_SetAttachStateResponse.Unmarshal(m, b)
+}
+func (m *SetAttachStateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_SetAttachStateResponse.Marshal(b, m, deterministic)
+}
+func (m *SetAttachStateResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_SetAttachStateResponse.Merge(m, src)
+}
+func (m *SetAttachStateResponse) XXX_Size() int {
+	return xxx_messageInfo_SetAttachStateResponse.Size(m)
+}
+func (m *SetAttachStateResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_SetAttachStateResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SetAttachStateResponse proto.InternalMessageInfo
+
+type GetAttachStateRequest struct {
+	// Disk device ID (number) of the disk
+	DiskID               string   `protobuf:"bytes,1,opt,name=diskID,proto3" json:"diskID,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *GetAttachStateRequest) Reset()         { *m = GetAttachStateRequest{} }
+func (m *GetAttachStateRequest) String() string { return proto.CompactTextString(m) }
+func (*GetAttachStateRequest) ProtoMessage()    {}
+func (*GetAttachStateRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b8298108b4474af1, []int{14}
+}
+
+func (m *GetAttachStateRequest) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_GetAttachStateRequest.Unmarshal(m, b)
+}
+func (m *GetAttachStateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_GetAttachStateRequest.Marshal(b, m, deterministic)
+}
+func (m *GetAttachStateRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_GetAttachStateRequest.Merge(m, src)
+}
+func (m *GetAttachStateRequest) XXX_Size() int {
+	return xxx_messageInfo_GetAttachStateRequest.Size(m)
+}
+func (m *GetAttachStateRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_GetAttachStateRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetAttachStateRequest proto.InternalMessageInfo
+
+func (m *GetAttachStateRequest) GetDiskID() string {
+	if m != nil {
+		return m.DiskID
+	}
+	return ""
+}
+
+type GetAttachStateResponse struct {
+	// Online state of the disk. true for online, false for offline
+	IsOnline             bool     `protobuf:"varint,1,opt,name=isOnline,proto3" json:"isOnline,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *GetAttachStateResponse) Reset()         { *m = GetAttachStateResponse{} }
+func (m *GetAttachStateResponse) String() string { return proto.CompactTextString(m) }
+func (*GetAttachStateResponse) ProtoMessage()    {}
+func (*GetAttachStateResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b8298108b4474af1, []int{15}
+}
+
+func (m *GetAttachStateResponse) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_GetAttachStateResponse.Unmarshal(m, b)
+}
+func (m *GetAttachStateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_GetAttachStateResponse.Marshal(b, m, deterministic)
+}
+func (m *GetAttachStateResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_GetAttachStateResponse.Merge(m, src)
+}
+func (m *GetAttachStateResponse) XXX_Size() int {
+	return xxx_messageInfo_GetAttachStateResponse.Size(m)
+}
+func (m *GetAttachStateResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_GetAttachStateResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetAttachStateResponse proto.InternalMessageInfo
+
+func (m *GetAttachStateResponse) GetIsOnline() bool {
+	if m != nil {
+		return m.IsOnline
+	}
+	return false
+}
+
+func init() {
+	proto.RegisterType((*ListDiskLocationsRequest)(nil), "v1beta2.ListDiskLocationsRequest")
+	proto.RegisterType((*DiskLocation)(nil), "v1beta2.DiskLocation")
+	proto.RegisterType((*ListDiskLocationsResponse)(nil), "v1beta2.ListDiskLocationsResponse")
+	proto.RegisterMapType((map[string]*DiskLocation)(nil), "v1beta2.ListDiskLocationsResponse.DiskLocationsEntry")
+	proto.RegisterType((*PartitionDiskRequest)(nil), "v1beta2.PartitionDiskRequest")
+	proto.RegisterType((*PartitionDiskResponse)(nil), "v1beta2.PartitionDiskResponse")
+	proto.RegisterType((*RescanRequest)(nil), "v1beta2.RescanRequest")
+	proto.RegisterType((*RescanResponse)(nil), "v1beta2.RescanResponse")
+	proto.RegisterType((*ListDiskIDsRequest)(nil), "v1beta2.ListDiskIDsRequest")
+	proto.RegisterType((*DiskIDs)(nil), "v1beta2.DiskIDs")
+	proto.RegisterMapType((map[string]string)(nil), "v1beta2.DiskIDs.IdentifiersEntry")
+	proto.RegisterType((*ListDiskIDsResponse)(nil), "v1beta2.ListDiskIDsResponse")
+	proto.RegisterMapType((map[string]*DiskIDs)(nil), "v1beta2.ListDiskIDsResponse.DiskIDsEntry")
+	proto.RegisterType((*DiskStatsRequest)(nil), "v1beta2.DiskStatsRequest")
+	proto.RegisterType((*DiskStatsResponse)(nil), "v1beta2.DiskStatsResponse")
+	proto.RegisterType((*SetAttachStateRequest)(nil), "v1beta2.SetAttachStateRequest")
+	proto.RegisterType((*SetAttachStateResponse)(nil), "v1beta2.SetAttachStateResponse")
+	proto.RegisterType((*GetAttachStateRequest)(nil), "v1beta2.GetAttachStateRequest")
+	proto.RegisterType((*GetAttachStateResponse)(nil), "v1beta2.GetAttachStateResponse")
+}
+
+func init() {
+	proto.RegisterFile("github.com/kubernetes-csi/csi-proxy/client/api/disk/v1beta2/api.proto", fileDescriptor_b8298108b4474af1)
+}
+
+var fileDescriptor_b8298108b4474af1 = []byte{
+	// 647 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0xdd, 0x6e, 0xd3, 0x4c,
+	0x10, 0xad, 0x9b, 0xb6, 0x69, 0x27, 0x5f, 0xf3, 0xa5, 0x4b, 0x92, 0xba, 0xe6, 0xaf, 0xdd, 0x0b,
+	0x54, 0x40, 0xb5, 0x45, 0x00, 0x09, 0x51, 0x81, 0xd4, 0xd6, 0x55, 0x14, 0x88, 0xa0, 0x72, 0x40,
+	0x48, 0xa8, 0x12, 0x72, 0x9c, 0xa5, 0x59, 0x25, 0xd8, 0xc1, 0xbb, 0xa9, 0x08, 0x0f, 0xc1, 0x73,
+	0x70, 0xc7, 0xbb, 0xf0, 0x44, 0x68, 0xed, 0xb5, 0xbb, 0x4e, 0x9c, 0x46, 0x88, 0x3b, 0xcf, 0x99,
+	0x99, 0xb3, 0x67, 0xfe, 0x64, 0x38, 0xbd, 0xa0, 0xbc, 0x3f, 0xee, 0x9a, 0x5e, 0xf0, 0xc5, 0x1a,
+	0x8c, 0xbb, 0x24, 0xf4, 0x09, 0x27, 0xec, 0xc0, 0x63, 0xd4, 0xf2, 0x18, 0x3d, 0x18, 0x85, 0xc1,
+	0xb7, 0x89, 0xe5, 0x0d, 0x29, 0xf1, 0xb9, 0xe5, 0x8e, 0xa8, 0xd5, 0xa3, 0x6c, 0x60, 0x5d, 0x3e,
+	0xea, 0x12, 0xee, 0x36, 0x04, 0x60, 0x8e, 0xc2, 0x80, 0x07, 0xa8, 0x28, 0x21, 0x6c, 0x80, 0xde,
+	0xa6, 0x8c, 0xdb, 0x94, 0x0d, 0xda, 0x81, 0xe7, 0x72, 0x1a, 0xf8, 0xcc, 0x21, 0x5f, 0xc7, 0x84,
+	0x71, 0xdc, 0x87, 0xff, 0x54, 0x1c, 0xe9, 0x50, 0x3c, 0xea, 0xb9, 0x23, 0x4e, 0x42, 0x5d, 0xdb,
+	0xd5, 0xf6, 0x37, 0x9c, 0xc4, 0x44, 0x15, 0x28, 0x1c, 0x8f, 0x99, 0xbe, 0x1c, 0xa1, 0xe2, 0x13,
+	0xd5, 0x61, 0xed, 0x9d, 0x1b, 0x5e, 0x10, 0xae, 0x17, 0x22, 0x50, 0x5a, 0xa8, 0x0a, 0xab, 0xed,
+	0xf7, 0x6f, 0x5a, 0xb6, 0xbe, 0x12, 0xc1, 0xb1, 0x81, 0x7f, 0x6b, 0xb0, 0x93, 0x23, 0x83, 0x8d,
+	0x02, 0x9f, 0x11, 0x74, 0x0e, 0x65, 0x51, 0xc6, 0xa7, 0x61, 0xe2, 0xd1, 0xb5, 0xdd, 0xc2, 0x7e,
+	0xa9, 0xf1, 0xd4, 0x94, 0x55, 0x98, 0x73, 0x73, 0xcd, 0x0c, 0x7a, 0xea, 0xf3, 0x70, 0xe2, 0x6c,
+	0xf6, 0x54, 0xcc, 0xf8, 0x00, 0x68, 0x36, 0x48, 0x54, 0x34, 0x20, 0x13, 0x59, 0xa7, 0xf8, 0x44,
+	0x0f, 0x61, 0xf5, 0xd2, 0x1d, 0x8e, 0x49, 0x54, 0x65, 0xa9, 0x51, 0x4b, 0x1f, 0x57, 0xb3, 0x9d,
+	0x38, 0xe6, 0xf9, 0xf2, 0x33, 0x0d, 0x9b, 0x50, 0x3d, 0x73, 0x43, 0x4e, 0x05, 0x2e, 0x62, 0x64,
+	0x5b, 0x45, 0x6b, 0x84, 0x82, 0x96, 0x2d, 0xd9, 0xa5, 0x85, 0xb7, 0xa1, 0x36, 0x15, 0x1f, 0xd7,
+	0x80, 0xff, 0x87, 0x4d, 0x87, 0x30, 0xcf, 0xf5, 0x93, 0xc1, 0x54, 0xa0, 0x9c, 0x00, 0x32, 0xa4,
+	0x0a, 0x28, 0xe9, 0x41, 0xcb, 0x4e, 0x07, 0xf8, 0x43, 0x83, 0xa2, 0x84, 0xd0, 0x09, 0x94, 0x68,
+	0x8f, 0xf8, 0x9c, 0x7e, 0xa6, 0x24, 0x4c, 0x3a, 0xb8, 0x97, 0x29, 0xa2, 0x65, 0x33, 0xb3, 0x75,
+	0x15, 0x13, 0x77, 0x4b, 0xcd, 0x32, 0x5e, 0x42, 0x65, 0x3a, 0x20, 0xa7, 0x53, 0x55, 0xb5, 0x53,
+	0x1b, 0x6a, 0x4b, 0x7e, 0x6a, 0x70, 0x23, 0xa3, 0x53, 0x4e, 0xf8, 0x04, 0x8a, 0x71, 0x13, 0x12,
+	0x61, 0xf7, 0x67, 0x46, 0xab, 0x84, 0x27, 0x62, 0x63, 0x81, 0x49, 0xa6, 0xd1, 0x8e, 0xd7, 0x35,
+	0x71, 0xe4, 0x08, 0xbb, 0x97, 0x1d, 0x61, 0x65, 0xba, 0x7a, 0x55, 0xea, 0x03, 0xa8, 0x08, 0xb4,
+	0xc3, 0x5d, 0xce, 0x16, 0x4d, 0xce, 0x82, 0x2d, 0x25, 0x56, 0xd6, 0x64, 0xc0, 0xba, 0x70, 0x77,
+	0xe8, 0x77, 0x12, 0x85, 0x17, 0x9c, 0xd4, 0xc6, 0xaf, 0xa1, 0xd6, 0x21, 0xfc, 0x88, 0x73, 0xd7,
+	0xeb, 0x8b, 0x2c, 0xb2, 0xe0, 0x05, 0x41, 0x46, 0xd9, 0x5b, 0x7f, 0x48, 0xfd, 0x58, 0xfc, 0xba,
+	0x93, 0xda, 0x58, 0x87, 0xfa, 0x34, 0x99, 0xdc, 0x0a, 0x0b, 0x6a, 0xcd, 0xbf, 0x79, 0x06, 0x3f,
+	0x81, 0x7a, 0x33, 0x97, 0x2a, 0x23, 0x40, 0xcb, 0x0a, 0x68, 0xfc, 0x5a, 0x81, 0x15, 0x51, 0x3f,
+	0x3a, 0x87, 0xad, 0x99, 0x4b, 0x44, 0x7b, 0xd7, 0x5d, 0x69, 0x24, 0xc7, 0xc0, 0x8b, 0x0f, 0x19,
+	0x2f, 0xa1, 0x33, 0xd8, 0xcc, 0xdc, 0x07, 0xba, 0x9d, 0xa6, 0xe5, 0xdd, 0x99, 0x71, 0x67, 0x9e,
+	0x3b, 0x65, 0x3c, 0x84, 0xb5, 0xf8, 0x8e, 0x50, 0x3d, 0x8d, 0xcd, 0x5c, 0x9a, 0xb1, 0x3d, 0x83,
+	0xa7, 0xc9, 0xaf, 0xa0, 0xa4, 0xec, 0x26, 0xba, 0x99, 0xbf, 0xb1, 0x31, 0xcd, 0xad, 0xeb, 0xd6,
+	0x19, 0x2f, 0x21, 0x1b, 0x36, 0xd2, 0x05, 0x42, 0x3b, 0x99, 0xb5, 0x54, 0x17, 0xd0, 0x30, 0xf2,
+	0x5c, 0x29, 0x4b, 0x07, 0xca, 0xd9, 0x45, 0x40, 0x57, 0x2d, 0xc8, 0x5d, 0x37, 0xe3, 0xee, 0x5c,
+	0xbf, 0x4a, 0xda, 0x9c, 0x47, 0xda, 0x5c, 0x40, 0xda, 0x9c, 0x43, 0x7a, 0xfc, 0xe2, 0xe3, 0xe1,
+	0x3f, 0xfc, 0xc7, 0xba, 0x6b, 0xd1, 0x4f, 0xec, 0xf1, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x68,
+	0x06, 0xb4, 0xd5, 0x0d, 0x07, 0x00, 0x00,
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConnInterface
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion6
+
+// DiskClient is the client API for Disk service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type DiskClient interface {
+	// ListDiskLocations returns locations <Adapter, Bus, Target, LUN ID> of all
+	// disk devices enumerated by the host
+	ListDiskLocations(ctx context.Context, in *ListDiskLocationsRequest, opts ...grpc.CallOption) (*ListDiskLocationsResponse, error)
+	// PartitionDisk initializes and partitions a disk device (if the disk has not
+	// been partitioned already) and returns the resulting volume device ID
+	PartitionDisk(ctx context.Context, in *PartitionDiskRequest, opts ...grpc.CallOption) (*PartitionDiskResponse, error)
+	// Rescan refreshes the host's storage cache
+	Rescan(ctx context.Context, in *RescanRequest, opts ...grpc.CallOption) (*RescanResponse, error)
+	// ListDiskIDs returns a map of DiskID objects where the key is the disk number
+	ListDiskIDs(ctx context.Context, in *ListDiskIDsRequest, opts ...grpc.CallOption) (*ListDiskIDsResponse, error)
+	// DiskStats returns the stats for the disk
+	DiskStats(ctx context.Context, in *DiskStatsRequest, opts ...grpc.CallOption) (*DiskStatsResponse, error)
+	// SetAttachState sets the offline/online state of a disk
+	SetAttachState(ctx context.Context, in *SetAttachStateRequest, opts ...grpc.CallOption) (*SetAttachStateResponse, error)
+	// GetAttachState gets the offline/online state of a disk
+	GetAttachState(ctx context.Context, in *GetAttachStateRequest, opts ...grpc.CallOption) (*GetAttachStateResponse, error)
+}
+
+type diskClient struct {
+	cc grpc.ClientConnInterface
+}
+
+func NewDiskClient(cc grpc.ClientConnInterface) DiskClient {
+	return &diskClient{cc}
+}
+
+func (c *diskClient) ListDiskLocations(ctx context.Context, in *ListDiskLocationsRequest, opts ...grpc.CallOption) (*ListDiskLocationsResponse, error) {
+	out := new(ListDiskLocationsResponse)
+	err := c.cc.Invoke(ctx, "/v1beta2.Disk/ListDiskLocations", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *diskClient) PartitionDisk(ctx context.Context, in *PartitionDiskRequest, opts ...grpc.CallOption) (*PartitionDiskResponse, error) {
+	out := new(PartitionDiskResponse)
+	err := c.cc.Invoke(ctx, "/v1beta2.Disk/PartitionDisk", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *diskClient) Rescan(ctx context.Context, in *RescanRequest, opts ...grpc.CallOption) (*RescanResponse, error) {
+	out := new(RescanResponse)
+	err := c.cc.Invoke(ctx, "/v1beta2.Disk/Rescan", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *diskClient) ListDiskIDs(ctx context.Context, in *ListDiskIDsRequest, opts ...grpc.CallOption) (*ListDiskIDsResponse, error) {
+	out := new(ListDiskIDsResponse)
+	err := c.cc.Invoke(ctx, "/v1beta2.Disk/ListDiskIDs", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *diskClient) DiskStats(ctx context.Context, in *DiskStatsRequest, opts ...grpc.CallOption) (*DiskStatsResponse, error) {
+	out := new(DiskStatsResponse)
+	err := c.cc.Invoke(ctx, "/v1beta2.Disk/DiskStats", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *diskClient) SetAttachState(ctx context.Context, in *SetAttachStateRequest, opts ...grpc.CallOption) (*SetAttachStateResponse, error) {
+	out := new(SetAttachStateResponse)
+	err := c.cc.Invoke(ctx, "/v1beta2.Disk/SetAttachState", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *diskClient) GetAttachState(ctx context.Context, in *GetAttachStateRequest, opts ...grpc.CallOption) (*GetAttachStateResponse, error) {
+	out := new(GetAttachStateResponse)
+	err := c.cc.Invoke(ctx, "/v1beta2.Disk/GetAttachState", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// DiskServer is the server API for Disk service.
+type DiskServer interface {
+	// ListDiskLocations returns locations <Adapter, Bus, Target, LUN ID> of all
+	// disk devices enumerated by the host
+	ListDiskLocations(context.Context, *ListDiskLocationsRequest) (*ListDiskLocationsResponse, error)
+	// PartitionDisk initializes and partitions a disk device (if the disk has not
+	// been partitioned already) and returns the resulting volume device ID
+	PartitionDisk(context.Context, *PartitionDiskRequest) (*PartitionDiskResponse, error)
+	// Rescan refreshes the host's storage cache
+	Rescan(context.Context, *RescanRequest) (*RescanResponse, error)
+	// ListDiskIDs returns a map of DiskID objects where the key is the disk number
+	ListDiskIDs(context.Context, *ListDiskIDsRequest) (*ListDiskIDsResponse, error)
+	// DiskStats returns the stats for the disk
+	DiskStats(context.Context, *DiskStatsRequest) (*DiskStatsResponse, error)
+	// SetAttachState sets the offline/online state of a disk
+	SetAttachState(context.Context, *SetAttachStateRequest) (*SetAttachStateResponse, error)
+	// GetAttachState gets the offline/online state of a disk
+	GetAttachState(context.Context, *GetAttachStateRequest) (*GetAttachStateResponse, error)
+}
+
+// UnimplementedDiskServer can be embedded to have forward compatible implementations.
+type UnimplementedDiskServer struct {
+}
+
+func (*UnimplementedDiskServer) ListDiskLocations(ctx context.Context, req *ListDiskLocationsRequest) (*ListDiskLocationsResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method ListDiskLocations not implemented")
+}
+func (*UnimplementedDiskServer) PartitionDisk(ctx context.Context, req *PartitionDiskRequest) (*PartitionDiskResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method PartitionDisk not implemented")
+}
+func (*UnimplementedDiskServer) Rescan(ctx context.Context, req *RescanRequest) (*RescanResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Rescan not implemented")
+}
+func (*UnimplementedDiskServer) ListDiskIDs(ctx context.Context, req *ListDiskIDsRequest) (*ListDiskIDsResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method ListDiskIDs not implemented")
+}
+func (*UnimplementedDiskServer) DiskStats(ctx context.Context, req *DiskStatsRequest) (*DiskStatsResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method DiskStats not implemented")
+}
+func (*UnimplementedDiskServer) SetAttachState(ctx context.Context, req *SetAttachStateRequest) (*SetAttachStateResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method SetAttachState not implemented")
+}
+func (*UnimplementedDiskServer) GetAttachState(ctx context.Context, req *GetAttachStateRequest) (*GetAttachStateResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetAttachState not implemented")
+}
+
+func RegisterDiskServer(s *grpc.Server, srv DiskServer) {
+	s.RegisterService(&_Disk_serviceDesc, srv)
+}
+
+func _Disk_ListDiskLocations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ListDiskLocationsRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(DiskServer).ListDiskLocations(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/v1beta2.Disk/ListDiskLocations",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(DiskServer).ListDiskLocations(ctx, req.(*ListDiskLocationsRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Disk_PartitionDisk_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(PartitionDiskRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(DiskServer).PartitionDisk(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/v1beta2.Disk/PartitionDisk",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(DiskServer).PartitionDisk(ctx, req.(*PartitionDiskRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Disk_Rescan_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(RescanRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(DiskServer).Rescan(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/v1beta2.Disk/Rescan",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(DiskServer).Rescan(ctx, req.(*RescanRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Disk_ListDiskIDs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ListDiskIDsRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(DiskServer).ListDiskIDs(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/v1beta2.Disk/ListDiskIDs",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(DiskServer).ListDiskIDs(ctx, req.(*ListDiskIDsRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Disk_DiskStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(DiskStatsRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(DiskServer).DiskStats(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/v1beta2.Disk/DiskStats",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(DiskServer).DiskStats(ctx, req.(*DiskStatsRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Disk_SetAttachState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(SetAttachStateRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(DiskServer).SetAttachState(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/v1beta2.Disk/SetAttachState",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(DiskServer).SetAttachState(ctx, req.(*SetAttachStateRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Disk_GetAttachState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(GetAttachStateRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(DiskServer).GetAttachState(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/v1beta2.Disk/GetAttachState",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(DiskServer).GetAttachState(ctx, req.(*GetAttachStateRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+var _Disk_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "v1beta2.Disk",
+	HandlerType: (*DiskServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "ListDiskLocations",
+			Handler:    _Disk_ListDiskLocations_Handler,
+		},
+		{
+			MethodName: "PartitionDisk",
+			Handler:    _Disk_PartitionDisk_Handler,
+		},
+		{
+			MethodName: "Rescan",
+			Handler:    _Disk_Rescan_Handler,
+		},
+		{
+			MethodName: "ListDiskIDs",
+			Handler:    _Disk_ListDiskIDs_Handler,
+		},
+		{
+			MethodName: "DiskStats",
+			Handler:    _Disk_DiskStats_Handler,
+		},
+		{
+			MethodName: "SetAttachState",
+			Handler:    _Disk_SetAttachState_Handler,
+		},
+		{
+			MethodName: "GetAttachState",
+			Handler:    _Disk_GetAttachState_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "github.com/kubernetes-csi/csi-proxy/client/api/disk/v1beta2/api.proto",
+}
diff --git a/vendor/github.com/kubernetes-csi/csi-proxy/client/api/disk/v1beta2/api.proto b/vendor/github.com/kubernetes-csi/csi-proxy/client/api/disk/v1beta2/api.proto
new file mode 100644
index 00000000..c9f6c8f8
--- /dev/null
+++ b/vendor/github.com/kubernetes-csi/csi-proxy/client/api/disk/v1beta2/api.proto
@@ -0,0 +1,109 @@
+syntax = "proto3";
+
+package v1beta2;
+
+option go_package = "github.com/kubernetes-csi/csi-proxy/client/api/disk/v1beta2";
+
+service Disk {
+    // ListDiskLocations returns locations <Adapter, Bus, Target, LUN ID> of all
+    // disk devices enumerated by the host
+    rpc ListDiskLocations(ListDiskLocationsRequest) returns (ListDiskLocationsResponse) {}
+
+    // PartitionDisk initializes and partitions a disk device (if the disk has not
+    // been partitioned already) and returns the resulting volume device ID
+    rpc PartitionDisk(PartitionDiskRequest) returns (PartitionDiskResponse) {}
+
+    // Rescan refreshes the host's storage cache
+    rpc Rescan(RescanRequest) returns (RescanResponse) {}
+
+    // ListDiskIDs returns a map of DiskID objects where the key is the disk number
+    rpc ListDiskIDs(ListDiskIDsRequest) returns (ListDiskIDsResponse) {}
+
+    // DiskStats returns the stats for the disk
+    rpc DiskStats(DiskStatsRequest) returns (DiskStatsResponse) {}
+
+    // SetAttachState sets the offline/online state of a disk
+    rpc SetAttachState(SetAttachStateRequest) returns (SetAttachStateResponse) {}
+
+    // GetAttachState gets the offline/online state of a disk
+    rpc GetAttachState(GetAttachStateRequest) returns (GetAttachStateResponse) {}
+}
+
+message ListDiskLocationsRequest {
+    // Intentionally empty
+}
+
+message DiskLocation {
+    string Adapter = 1;
+    string Bus = 2;
+    string Target = 3;
+    string LUNID = 4;
+}
+
+message ListDiskLocationsResponse {
+    // Map of disk device IDs and <adapter, bus, target, lun ID> associated with each disk device
+    map <string, DiskLocation> disk_locations = 1;
+}
+
+message PartitionDiskRequest {
+    // Disk device ID of the disk to partition
+    string diskID = 1;
+}
+
+message PartitionDiskResponse {
+    // Intentionally empty
+}
+
+message RescanRequest {
+    // Intentionally empty
+}
+
+message RescanResponse {
+    // Intentionally empty
+}
+
+message ListDiskIDsRequest {
+    // Intentionally empty
+}
+
+message DiskIDs {
+    // Map of Disk ID types and Disk ID values
+    map <string, string> identifiers = 1;
+}
+
+message ListDiskIDsResponse {
+    // Map of disk device numbers and IDs <page83> associated with each disk device
+    map <string, DiskIDs> diskIDs = 1;
+}
+
+message DiskStatsRequest {
+    // Disk device ID of the disk to get the size from
+    string diskID = 1;
+}
+
+message DiskStatsResponse {
+    //Total size of the volume
+    int64 diskSize = 1;
+}
+
+message SetAttachStateRequest {
+    // Disk device ID (number) of the disk which state will change
+    string diskID = 1;
+
+    // Online state to set for the disk. true for online, false for offline
+    bool isOnline = 2;
+}
+
+message SetAttachStateResponse {
+}
+
+message GetAttachStateRequest {
+    // Disk device ID (number) of the disk
+    string diskID = 1;
+}
+
+message GetAttachStateResponse {
+    // Online state of the disk. true for online, false for offline
+    bool isOnline = 1;
+}
+
diff --git a/vendor/github.com/kubernetes-csi/csi-proxy/client/groups/disk/v1beta2/client_generated.go b/vendor/github.com/kubernetes-csi/csi-proxy/client/groups/disk/v1beta2/client_generated.go
new file mode 100644
index 00000000..a5e85d81
--- /dev/null
+++ b/vendor/github.com/kubernetes-csi/csi-proxy/client/groups/disk/v1beta2/client_generated.go
@@ -0,0 +1,80 @@
+// Code generated by csi-proxy-api-gen. DO NOT EDIT.
+
+package v1beta2
+
+import (
+	"context"
+	"net"
+
+	"github.com/Microsoft/go-winio"
+	"github.com/kubernetes-csi/csi-proxy/client"
+	"github.com/kubernetes-csi/csi-proxy/client/api/disk/v1beta2"
+	"github.com/kubernetes-csi/csi-proxy/client/apiversion"
+	"google.golang.org/grpc"
+)
+
+const groupName = "disk"
+
+var version = apiversion.NewVersionOrPanic("v1beta2")
+
+type Client struct {
+	client     v1beta2.DiskClient
+	connection *grpc.ClientConn
+}
+
+// NewClient returns a client to make calls to the disk API group version v1beta2.
+// It's the caller's responsibility to Close the client when done.
+func NewClient() (*Client, error) {
+	pipePath := client.PipePath(groupName, version)
+
+	connection, err := grpc.Dial(pipePath,
+		grpc.WithContextDialer(func(context context.Context, s string) (net.Conn, error) {
+			return winio.DialPipeContext(context, s)
+		}),
+		grpc.WithInsecure())
+	if err != nil {
+		return nil, err
+	}
+
+	client := v1beta2.NewDiskClient(connection)
+	return &Client{
+		client:     client,
+		connection: connection,
+	}, nil
+}
+
+// Close closes the client. It must be called before the client gets GC-ed.
+func (w *Client) Close() error {
+	return w.connection.Close()
+}
+
+// ensures we implement all the required methods
+var _ v1beta2.DiskClient = &Client{}
+
+func (w *Client) DiskStats(context context.Context, request *v1beta2.DiskStatsRequest, opts ...grpc.CallOption) (*v1beta2.DiskStatsResponse, error) {
+	return w.client.DiskStats(context, request, opts...)
+}
+
+func (w *Client) GetAttachState(context context.Context, request *v1beta2.GetAttachStateRequest, opts ...grpc.CallOption) (*v1beta2.GetAttachStateResponse, error) {
+	return w.client.GetAttachState(context, request, opts...)
+}
+
+func (w *Client) ListDiskIDs(context context.Context, request *v1beta2.ListDiskIDsRequest, opts ...grpc.CallOption) (*v1beta2.ListDiskIDsResponse, error) {
+	return w.client.ListDiskIDs(context, request, opts...)
+}
+
+func (w *Client) ListDiskLocations(context context.Context, request *v1beta2.ListDiskLocationsRequest, opts ...grpc.CallOption) (*v1beta2.ListDiskLocationsResponse, error) {
+	return w.client.ListDiskLocations(context, request, opts...)
+}
+
+func (w *Client) PartitionDisk(context context.Context, request *v1beta2.PartitionDiskRequest, opts ...grpc.CallOption) (*v1beta2.PartitionDiskResponse, error) {
+	return w.client.PartitionDisk(context, request, opts...)
+}
+
+func (w *Client) Rescan(context context.Context, request *v1beta2.RescanRequest, opts ...grpc.CallOption) (*v1beta2.RescanResponse, error) {
+	return w.client.Rescan(context, request, opts...)
+}
+
+func (w *Client) SetAttachState(context context.Context, request *v1beta2.SetAttachStateRequest, opts ...grpc.CallOption) (*v1beta2.SetAttachStateResponse, error) {
+	return w.client.SetAttachState(context, request, opts...)
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 587dc05b..844cb236 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -56,15 +56,19 @@ github.com/imdario/mergo
 github.com/json-iterator/go
 # github.com/konsorten/go-windows-terminal-sequences v1.0.2
 github.com/konsorten/go-windows-terminal-sequences
-# github.com/kubernetes-csi/csi-proxy/client v0.2.1
+# github.com/kubernetes-csi/csi-proxy/client v0.2.2
 github.com/kubernetes-csi/csi-proxy/client
 github.com/kubernetes-csi/csi-proxy/client/api/disk/v1beta1
+github.com/kubernetes-csi/csi-proxy/client/api/disk/v1beta2
 github.com/kubernetes-csi/csi-proxy/client/api/filesystem/v1beta1
 github.com/kubernetes-csi/csi-proxy/client/api/volume/v1beta1
+github.com/kubernetes-csi/csi-proxy/client/api/volume/v1beta2
 github.com/kubernetes-csi/csi-proxy/client/apiversion
 github.com/kubernetes-csi/csi-proxy/client/groups/disk/v1beta1
+github.com/kubernetes-csi/csi-proxy/client/groups/disk/v1beta2
 github.com/kubernetes-csi/csi-proxy/client/groups/filesystem/v1beta1
 github.com/kubernetes-csi/csi-proxy/client/groups/volume/v1beta1
+github.com/kubernetes-csi/csi-proxy/client/groups/volume/v1beta2
 # github.com/kubernetes-csi/csi-test/v3 v3.0.0
 github.com/kubernetes-csi/csi-test/v3/pkg/sanity
 github.com/kubernetes-csi/csi-test/v3/utils


Test patch:
diff --git a/pkg/gce-cloud-provider/compute/gce-compute_test.go b/pkg/gce-cloud-provider/compute/gce-compute_test.go
index 1a9c9f6e..9a0b7864 100644
--- a/pkg/gce-cloud-provider/compute/gce-compute_test.go
+++ b/pkg/gce-cloud-provider/compute/gce-compute_test.go
@@ -66,22 +66,24 @@ func TestValidateDiskParameters(t *testing.T) {
 
 	for i, tc := range testCases {
 		// Arrange
-		existingDisk := CloudDiskFromV1(&computev1.Disk{
-			Id:                546559531467326555,
-			CreationTimestamp: "2020-07-24T17:20:06.292-07:00",
-			Name:              "test-disk",
-			SizeGb:            500,
-			Zone:              "https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1-c",
-			Status:            "READY",
-			SelfLink:          "https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1-c/disks/test-disk",
-			Type:              "https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1-c/diskTypes/pd-standard",
-			DiskEncryptionKey: &computev1.CustomerEncryptionKey{
-				KmsKeyName: tc.fetchedKMSKey,
+		existingDisk := &CloudDisk{
+			ZonalDisk: &computev1.Disk{
+				Id:                546559531467326555,
+				CreationTimestamp: "2020-07-24T17:20:06.292-07:00",
+				Name:              "test-disk",
+				SizeGb:            500,
+				Zone:              "https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1-c",
+				Status:            "READY",
+				SelfLink:          "https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1-c/disks/test-disk",
+				Type:              "https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1-c/diskTypes/pd-standard",
+				DiskEncryptionKey: &computev1.CustomerEncryptionKey{
+					KmsKeyName: tc.fetchedKMSKey,
+				},
+				LabelFingerprint:       "42WmSpB8rSM=",
+				PhysicalBlockSizeBytes: 4096,
+				Kind:                   "compute#disk",
 			},
-			LabelFingerprint:       "42WmSpB8rSM=",
-			PhysicalBlockSizeBytes: 4096,
-			Kind:                   "compute#disk",
-		})
+		}
 
 		storageClassParams := common.DiskParameters{
 			DiskType:             "pd-standard",
diff --git a/pkg/gce-pd-csi-driver/controller_test.go b/pkg/gce-pd-csi-driver/controller_test.go
index e712f9a1..1e7bf863 100644
--- a/pkg/gce-pd-csi-driver/controller_test.go
+++ b/pkg/gce-pd-csi-driver/controller_test.go
@@ -751,10 +751,10 @@ func TestListVolumeArgs(t *testing.T) {
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
 			// Setup new driver each time so no interference
-			var d []*gce.CloudDisk
+			d := []*gce.CloudDisk{}
 			for i := 0; i < 600; i++ {
 				// Create 600 dummy disks
-				d = append(d, gce.CloudDiskFromV1(&compute.Disk{Name: fmt.Sprintf("%v", i)}))
+				d = append(d, &gce.CloudDisk{ZonalDisk: &compute.Disk{Name: fmt.Sprintf("%v", i)}})
 			}
 			gceDriver := initGCEDriver(t, d)
 			lvr := &csi.ListVolumesRequest{
@@ -890,7 +890,7 @@ func TestCreateVolumeRandomRequisiteTopology(t *testing.T) {
 }
 
 func createZonalCloudDisk(name string) *gce.CloudDisk {
-	return gce.CloudDiskFromV1(&compute.Disk{
+	return gce.ZonalCloudDisk(&compute.Disk{
 		Name: name,
 	})
 }
diff --git a/test/k8s-integration/driver-config.go b/test/k8s-integration/driver-config.go
index c612ea91..eaba8b66 100644
--- a/test/k8s-integration/driver-config.go
+++ b/test/k8s-integration/driver-config.go
@@ -27,15 +27,15 @@ const (
 
 // generateDriverConfigFile loads a testdriver config template and creates a file
 // with the test-specific configuration
-func generateDriverConfigFile(testParams *testParameters, storageClassFile string) (string, error) {
+func generateDriverConfigFile(platform, pkgDir, storageClassFile, snapshotClassFile, deploymentStrat string) (string, error) {
 	// Load template
-	t, err := template.ParseFiles(filepath.Join(testParams.pkgDir, testConfigDir, configTemplateFile))
+	t, err := template.ParseFiles(filepath.Join(pkgDir, testConfigDir, configTemplateFile))
 	if err != nil {
 		return "", err
 	}
 
 	// Create destination
-	configFilePath := filepath.Join(testParams.pkgDir, testConfigDir, configFile)
+	configFilePath := filepath.Join(pkgDir, testConfigDir, configFile)
 	f, err := os.Create(configFilePath)
 	if err != nil {
 		return "", err
@@ -55,11 +55,9 @@ func generateDriverConfigFile(testParams *testParameters, storageClassFile strin
 		"exec",
 		"multipods",
 		"topology",
-		"controllerExpansion",
-		"nodeExpansion",
 	}
 	var fsTypes []string
-	if testParams.platform == "windows" {
+	if platform == "windows" {
 		fsTypes = []string{"ntfs"}
 		caps = []string{
 			"persistence",
@@ -72,6 +70,7 @@ func generateDriverConfigFile(testParams *testParameters, storageClassFile strin
 			"ext2",
 			"ext3",
 			"ext4",
+			"xfs",
 		}
 	}
 
@@ -83,38 +82,22 @@ func generateDriverConfigFile(testParams *testParameters, storageClassFile strin
 	   dataSource
 	*/
 
-	switch testParams.deploymentStrategy {
+	// TODO: Support adding/removing capabilities based on Kubernetes version.
+	switch deploymentStrat {
 	case "gke":
-		if testParams.imageType == "cos" {
-			var gkeVer *version
-			// The node version is what matters for XFS support. If the node version is not given, we assume
-			// it's the same as the cluster master version.
-			if testParams.nodeVersion != "" {
-				gkeVer = mustParseVersion(testParams.nodeVersion)
-			} else {
-				gkeVer = mustParseVersion(testParams.clusterVersion)
-			}
-			if gkeVer.lessThan(mustParseVersion("1.18.0")) {
-				// XFS is not supported on COS before 1.18.0
-			} else {
-				fsTypes = append(fsTypes, "xfs")
-			}
-		} else {
-			// XFS is supported on all non-COS images.
-			fsTypes = append(fsTypes, "xfs")
-		}
+		fallthrough
 	case "gce":
-		fsTypes = append(fsTypes, "xfs")
+		caps = append(caps, "controllerExpansion", "nodeExpansion")
 	default:
-		return "", fmt.Errorf("got unknown deployment strat %s, expected gce or gke", testParams.deploymentStrategy)
+		return "", fmt.Errorf("got unknown deployment strat %s, expected gce or gke", deploymentStrat)
 	}
 
 	var absSnapshotClassFilePath string
 	// If snapshot class is passed in as argument, include snapshot specific driver capabiltiites.
-	if testParams.snapshotClassFile != "" {
+	if snapshotClassFile != "" {
 		caps = append(caps, "snapshotDataSource")
 		// Update the absolute file path pointing to the snapshot class file, if it is provided as an argument.
-		absSnapshotClassFilePath = filepath.Join(testParams.pkgDir, testConfigDir, testParams.snapshotClassFile)
+		absSnapshotClassFilePath = filepath.Join(pkgDir, testConfigDir, snapshotClassFile)
 	}
 
 	minimumVolumeSize := "5Gi"
@@ -124,7 +107,7 @@ func generateDriverConfigFile(testParams *testParameters, storageClassFile strin
 		numAllowedTopologies = 2
 	}
 	params := driverConfig{
-		StorageClassFile:     filepath.Join(testParams.pkgDir, testConfigDir, storageClassFile),
+		StorageClassFile:     filepath.Join(pkgDir, testConfigDir, storageClassFile),
 		StorageClass:         storageClassFile[:strings.LastIndex(storageClassFile, ".")],
 		SnapshotClassFile:    absSnapshotClassFilePath,
 		SupportedFsType:      fsTypes,
diff --git a/test/k8s-integration/driver.go b/test/k8s-integration/driver.go
index edf1987a..bb9ce5ca 100644
--- a/test/k8s-integration/driver.go
+++ b/test/k8s-integration/driver.go
@@ -15,17 +15,17 @@ func getOverlayDir(pkgDir, deployOverlayName string) string {
 	return filepath.Join(pkgDir, "deploy", "kubernetes", "overlays", deployOverlayName)
 }
 
-func installDriver(testParams *testParameters, stagingImage, deployOverlayName string, doDriverBuild bool) error {
+func installDriver(platform, goPath, pkgDir, stagingImage, stagingVersion, deployOverlayName string, doDriverBuild bool) error {
 	if doDriverBuild {
 		// Install kustomize
 		klog.Infof("Installing kustomize")
-		out, err := exec.Command(filepath.Join(testParams.pkgDir, "deploy", "kubernetes", "install-kustomize.sh")).CombinedOutput()
+		out, err := exec.Command(filepath.Join(pkgDir, "deploy", "kubernetes", "install-kustomize.sh")).CombinedOutput()
 		if err != nil {
 			return fmt.Errorf("failed to install kustomize: %s, err: %v", out, err)
 		}
 
 		// Edit ci kustomization to use given image tag
-		overlayDir := getOverlayDir(testParams.pkgDir, deployOverlayName)
+		overlayDir := getOverlayDir(pkgDir, deployOverlayName)
 		err = os.Chdir(overlayDir)
 		if err != nil {
 			return fmt.Errorf("failed to change to overlay directory: %s, err: %v", out, err)
@@ -34,11 +34,11 @@ func installDriver(testParams *testParameters, stagingImage, deployOverlayName s
 		// TODO (#138): in a local environment this is going to modify the actual kustomize files.
 		// maybe a copy should be made instead
 		out, err = exec.Command(
-			filepath.Join(testParams.pkgDir, "bin", "kustomize"),
+			filepath.Join(pkgDir, "bin", "kustomize"),
 			"edit",
 			"set",
 			"image",
-			fmt.Sprintf("%s=%s:%s", pdImagePlaceholder, stagingImage, testParams.stagingVersion)).CombinedOutput()
+			fmt.Sprintf("%s=%s:%s", pdImagePlaceholder, stagingImage, stagingVersion)).CombinedOutput()
 		if err != nil {
 			return fmt.Errorf("failed to edit kustomize: %s, err: %v", out, err)
 		}
@@ -61,9 +61,9 @@ func installDriver(testParams *testParameters, stagingImage, deployOverlayName s
 	}
 
 	// deploy driver
-	deployCmd := exec.Command(filepath.Join(testParams.pkgDir, "deploy", "kubernetes", "deploy-driver.sh"), "--skip-sa-check")
+	deployCmd := exec.Command(filepath.Join(pkgDir, "deploy", "kubernetes", "deploy-driver.sh"), "--skip-sa-check")
 	deployEnv = append(deployEnv,
-		fmt.Sprintf("GOPATH=%s", testParams.goPath),
+		fmt.Sprintf("GOPATH=%s", goPath),
 		fmt.Sprintf("GCE_PD_DRIVER_VERSION=%s", deployOverlayName))
 	deployEnv = append(os.Environ(), deployEnv...)
 	deployCmd.Env = deployEnv
@@ -72,14 +72,14 @@ func installDriver(testParams *testParameters, stagingImage, deployOverlayName s
 		return fmt.Errorf("failed to deploy driver: %w", err)
 	}
 
-	waitScript := filepath.Join(testParams.pkgDir, "deploy", "kubernetes", "wait-for-driver.sh")
+	waitScript := filepath.Join(pkgDir, "deploy", "kubernetes", "wait-for-driver.sh")
 	waitCmd := exec.Command(waitScript)
 	waitCmd.Env = deployEnv
 	err = runCommand("Waiting for driver to start", waitCmd)
 	if err != nil {
 		return fmt.Errorf("driver failed to come up: %w", err)
 	}
-	if testParams.platform == "windows" {
+	if platform == "windows" {
 		waitCmd = exec.Command(waitScript, "--windows")
 		waitCmd.Env = deployEnv
 		err = runCommand("Waiting for windows deployment to start", waitCmd)
@@ -91,15 +91,15 @@ func installDriver(testParams *testParameters, stagingImage, deployOverlayName s
 	klog.Infof("describe pods \n %s", string(out))
 
 	if err != nil {
-		return fmt.Errorf("failed to describe pods: %w", err)
+		return fmt.Errorf("failed to describe pods: %v", err)
 	}
 	return nil
 }
 
-func deleteDriver(testParams *testParameters, deployOverlayName string) error {
-	deleteCmd := exec.Command(filepath.Join(testParams.pkgDir, "deploy", "kubernetes", "delete-driver.sh"))
+func deleteDriver(goPath, pkgDir, deployOverlayName string) error {
+	deleteCmd := exec.Command(filepath.Join(pkgDir, "deploy", "kubernetes", "delete-driver.sh"))
 	deleteCmd.Env = append(os.Environ(),
-		fmt.Sprintf("GOPATH=%s", testParams.goPath),
+		fmt.Sprintf("GOPATH=%s", goPath),
 		fmt.Sprintf("GCE_PD_DRIVER_VERSION=%s", deployOverlayName),
 	)
 	err := runCommand("Deleting driver", deleteCmd)
diff --git a/test/k8s-integration/main.go b/test/k8s-integration/main.go
index 134489ac..7c11e646 100644
--- a/test/k8s-integration/main.go
+++ b/test/k8s-integration/main.go
@@ -78,26 +78,6 @@ const (
 	regionalPDStorageClass    = "sc-regional.yaml"
 )
 
-type testParameters struct {
-	platform             string
-	stagingVersion       string
-	goPath               string
-	pkgDir               string
-	testParentDir        string
-	testDir              string
-	testFocus            string
-	testSkip             string
-	snapshotClassFile    string
-	cloudProviderArgs    []string
-	deploymentStrategy   string
-	outputDir            string
-	allowedNotReadyNodes int
-	useGKEManagedDriver  bool
-	clusterVersion       string
-	nodeVersion          string
-	imageType            string
-}
-
 func init() {
 	flag.Set("logtostderr", "true")
 }
@@ -186,22 +166,14 @@ func handle() error {
 	oldmask := syscall.Umask(0000)
 	defer syscall.Umask(oldmask)
 
-	testParams := &testParameters{
-		platform:            *platform,
-		testFocus:           *testFocus,
-		snapshotClassFile:   *snapshotClassFile,
-		stagingVersion:      string(uuid.NewUUID()),
-		deploymentStrategy:  *deploymentStrat,
-		useGKEManagedDriver: *useGKEManagedDriver,
-		imageType:           *imageType,
-	}
+	stagingVersion := string(uuid.NewUUID())
 
 	goPath, ok := os.LookupEnv("GOPATH")
 	if !ok {
 		return fmt.Errorf("Could not find env variable GOPATH")
 	}
-	testParams.goPath = goPath
-	testParams.pkgDir = filepath.Join(goPath, "src", "sigs.k8s.io", "gcp-compute-persistent-disk-csi-driver")
+
+	pkgDir := filepath.Join(goPath, "src", "sigs.k8s.io", "gcp-compute-persistent-disk-csi-driver")
 
 	// If running in Prow, then acquire and set up a project through Boskos
 	if *inProw {
@@ -241,13 +213,13 @@ func handle() error {
 
 	// Build and push the driver, if required. Defer the driver image deletion.
 	if *doDriverBuild {
-		err := pushImage(testParams.pkgDir, *stagingImage, testParams.stagingVersion, testParams.platform)
+		err := pushImage(pkgDir, *stagingImage, stagingVersion, *platform)
 		if err != nil {
 			return fmt.Errorf("failed pushing image: %v", err)
 		}
 		defer func() {
 			if *teardownCluster {
-				err := deleteImage(*stagingImage, testParams.stagingVersion)
+				err := deleteImage(*stagingImage, stagingVersion)
 				if err != nil {
 					klog.Errorf("failed to delete image: %v", err)
 				}
@@ -258,15 +230,15 @@ func handle() error {
 	// Create temporary directories for kubernetes builds
 	k8sParentDir := generateUniqueTmpDir()
 	k8sDir := filepath.Join(k8sParentDir, "kubernetes")
-	testParams.testParentDir = generateUniqueTmpDir()
-	testParams.testDir = filepath.Join(testParams.testParentDir, "kubernetes")
+	testParentDir := generateUniqueTmpDir()
+	testDir := filepath.Join(testParentDir, "kubernetes")
 	defer removeDir(k8sParentDir)
-	defer removeDir(testParams.testParentDir)
+	defer removeDir(testParentDir)
 
 	// If kube version is set, then download and build Kubernetes for cluster creation
 	// Otherwise, either GKE or a prebuild local K8s dir is being used
 	if len(*kubeVersion) != 0 {
-		err := downloadKubernetesSource(testParams.pkgDir, k8sParentDir, *kubeVersion)
+		err := downloadKubernetesSource(pkgDir, k8sParentDir, *kubeVersion)
 		if err != nil {
 			return fmt.Errorf("failed to download Kubernetes source: %v", err)
 		}
@@ -281,25 +253,25 @@ func handle() error {
 	// If test version is set, then download and build Kubernetes to run K8s tests
 	// Otherwise, either kube version is set (which implies GCE) or a local K8s dir is being used
 	if len(*testVersion) != 0 && *testVersion != *kubeVersion {
-		err := downloadKubernetesSource(testParams.pkgDir, testParams.testParentDir, *testVersion)
+		err := downloadKubernetesSource(pkgDir, testParentDir, *testVersion)
 		if err != nil {
 			return fmt.Errorf("failed to download Kubernetes source: %v", err)
 		}
-		err = buildKubernetes(testParams.testDir, "WHAT=test/e2e/e2e.test")
+		err = buildKubernetes(testDir, "WHAT=test/e2e/e2e.test")
 		if err != nil {
 			return fmt.Errorf("failed to build Kubernetes e2e: %v", err)
 		}
 		// kubetest relies on ginkgo and kubectl already built in the test k8s directory
-		err = buildKubernetes(testParams.testDir, "ginkgo")
+		err = buildKubernetes(testDir, "ginkgo")
 		if err != nil {
 			return fmt.Errorf("failed to build gingko: %v", err)
 		}
-		err = buildKubernetes(testParams.testDir, "kubectl")
+		err = buildKubernetes(testDir, "kubectl")
 		if err != nil {
 			return fmt.Errorf("failed to build kubectl: %v", err)
 		}
 	} else {
-		testParams.testDir = k8sDir
+		testDir = k8sDir
 	}
 
 	if *deploymentStrat == "gke" {
@@ -315,11 +287,11 @@ func handle() error {
 		var err error = nil
 		switch *deploymentStrat {
 		case "gce":
-			err = clusterUpGCE(k8sDir, *gceZone, *numNodes, testParams.imageType)
+			err = clusterUpGCE(k8sDir, *gceZone, *numNodes, *imageType)
 		case "gke":
-			err = clusterUpGKE(*gceZone, *gceRegion, *numNodes, testParams.imageType, testParams.useGKEManagedDriver)
+			err = clusterUpGKE(*gceZone, *gceRegion, *numNodes, *imageType, *useGKEManagedDriver)
 		default:
-			err = fmt.Errorf("deployment-strategy must be set to 'gce' or 'gke', but is: %s", testParams.deploymentStrategy)
+			err = fmt.Errorf("deployment-strategy must be set to 'gce' or 'gke', but is: %s", *deploymentStrat)
 		}
 		if err != nil {
 			return fmt.Errorf("failed to cluster up: %v", err)
@@ -329,7 +301,7 @@ func handle() error {
 	// Defer the tear down of the cluster through GKE or GCE
 	if *teardownCluster {
 		defer func() {
-			switch testParams.deploymentStrategy {
+			switch *deploymentStrat {
 			case "gce":
 				err := clusterDownGCE(k8sDir)
 				if err != nil {
@@ -341,14 +313,14 @@ func handle() error {
 					klog.Errorf("failed to cluster down: %v", err)
 				}
 			default:
-				klog.Errorf("deployment-strategy must be set to 'gce' or 'gke', but is: %s", testParams.deploymentStrategy)
+				klog.Errorf("deployment-strategy must be set to 'gce' or 'gke', but is: %s", *deploymentStrat)
 			}
 		}()
 	}
 
 	// For windows cluster, when cluster is up, all Windows nodes are tainted with NoSchedule to avoid linux pods
 	// being scheduled to Windows nodes. When running windows tests, we need to remove the taint.
-	if testParams.platform == "windows" {
+	if *platform == "windows" {
 		nodesCmd := exec.Command("kubectl", "get", "nodes", "-l", "kubernetes.io/os=windows", "-o", "name")
 		out, err := nodesCmd.CombinedOutput()
 		if err != nil {
@@ -367,11 +339,11 @@ func handle() error {
 		// It typically takes 5+ minutes to download Windows container image. To avoid tests being timed out,
 		// pre-pulling the test images as best effort.
 		klog.Infof("Prepulling test images.")
-		err = os.Setenv("PREPULL_YAML", filepath.Join(testParams.pkgDir, "test", "k8s-integration", "prepull.yaml"))
+		err = os.Setenv("PREPULL_YAML", filepath.Join(pkgDir, "test", "k8s-integration", "prepull.yaml"))
 		if err != nil {
 			return err
 		}
-		out, err = exec.Command(filepath.Join(testParams.pkgDir, "test", "k8s-integration", "prepull-image.sh")).CombinedOutput()
+		out, err = exec.Command(filepath.Join(pkgDir, "test", "k8s-integration", "prepull-image.sh")).CombinedOutput()
 		if err != nil {
 			return fmt.Errorf("failed to prepull images: %s, err: %v", out, err)
 		}
@@ -384,12 +356,12 @@ func handle() error {
 
 	}
 
-	if !testParams.useGKEManagedDriver {
+	if !*useGKEManagedDriver {
 		// Install the driver and defer its teardown
-		err := installDriver(testParams, *stagingImage, *deployOverlayName, *doDriverBuild)
+		err := installDriver(*platform, goPath, pkgDir, *stagingImage, stagingVersion, *deployOverlayName, *doDriverBuild)
 		if *teardownDriver {
 			defer func() {
-				if teardownErr := deleteDriver(testParams, *deployOverlayName); teardownErr != nil {
+				if teardownErr := deleteDriver(goPath, pkgDir, *deployOverlayName); teardownErr != nil {
 					klog.Errorf("failed to delete driver: %v", teardownErr)
 				}
 			}()
@@ -415,7 +387,7 @@ func handle() error {
 	// Also the test framework will not proceed to run tests unless all nodes are ready
 	// AND schedulable. Allow not-ready nodes since we make Linux nodes
 	// unschedulable.
-	testParams.allowedNotReadyNodes = 0
+	allowedNotReadyNodes := 0
 	if *platform == "windows" {
 		nodesCmd := exec.Command("kubectl", "get", "nodes", "-l", "kubernetes.io/os=linux", "-o", "name")
 		out, err := nodesCmd.CombinedOutput()
@@ -423,7 +395,7 @@ func handle() error {
 			return fmt.Errorf("failed to get linux nodes: %v", err)
 		}
 		nodes := strings.Fields(string(out))
-		testParams.allowedNotReadyNodes = len(nodes)
+		allowedNotReadyNodes = len(nodes)
 		for _, node := range nodes {
 			taintCmd := exec.Command("kubectl", "taint", "node", node, "node.kubernetes.io/os:NoSchedule")
 			out, err := taintCmd.CombinedOutput()
@@ -434,9 +406,10 @@ func handle() error {
 		}
 	}
 
-	switch testParams.deploymentStrategy {
+	var cloudProviderArgs []string
+	switch *deploymentStrat {
 	case "gke":
-		testParams.cloudProviderArgs, err = getGKEKubeTestArgs(*gceZone, *gceRegion, testParams.imageType)
+		cloudProviderArgs, err = getGKEKubeTestArgs(*gceZone, *gceRegion, *imageType)
 		if err != nil {
 			return fmt.Errorf("failed to build GKE kubetest args: %v", err)
 		}
@@ -445,15 +418,15 @@ func handle() error {
 	// Kubernetes version of GKE deployments are expected to be of the pattern x.y.z-gke.k,
 	// hence we use the main.Version utils to parse and compare GKE managed cluster versions.
 	// For clusters deployed on GCE, use the apimachinery version utils (which supports non-gke based semantic versioning).
-	testParams.clusterVersion = mustGetKubeClusterVersion()
-	switch testParams.deploymentStrategy {
+	clusterVersion := mustGetKubeClusterVersion()
+	var testSkip string
+	switch *deploymentStrat {
 	case "gce":
-		testParams.testSkip = generateGCETestSkip(testParams)
+		testSkip = generateGCETestSkip(clusterVersion, *platform)
 	case "gke":
-		testParams.testSkip = generateGKETestSkip(testParams)
-		testParams.nodeVersion = *gkeNodeVersion
+		testSkip = generateGKETestSkip(clusterVersion, *useGKEManagedDriver)
 	default:
-		return fmt.Errorf("Unknown deployment strategy %s", testParams.deploymentStrategy)
+		return fmt.Errorf("Unknown deployment strategy %s", *deploymentStrat)
 	}
 
 	// Run the tests using the testDir kubernetes
@@ -478,7 +451,8 @@ func handle() error {
 		for _, scFile := range applicableStorageClassFiles {
 			outputDir := strings.TrimSuffix(scFile, ".yaml")
 			testOutputDirs = append(testOutputDirs, outputDir)
-			if err = runCSITests(testParams, scFile, outputDir); err != nil {
+			if err = runCSITests(*platform, pkgDir, testDir, *testFocus, testSkip, scFile,
+				*snapshotClassFile, cloudProviderArgs, *deploymentStrat, outputDir, allowedNotReadyNodes); err != nil {
 				ginkgoErrors = append(ginkgoErrors, err.Error())
 			}
 		}
@@ -489,7 +463,7 @@ func handle() error {
 			return fmt.Errorf("runCSITests failed: %v", strings.Join(ginkgoErrors, " "))
 		}
 	} else if *migrationTest {
-		err = runMigrationTests(testParams)
+		err = runMigrationTests(pkgDir, testDir, *testFocus, testSkip, cloudProviderArgs)
 	} else {
 		return fmt.Errorf("did not run either CSI or Migration test")
 	}
@@ -501,9 +475,9 @@ func handle() error {
 	return nil
 }
 
-func generateGCETestSkip(testParams *testParameters) string {
+func generateGCETestSkip(clusterVersion, platform string) string {
 	skipString := "\\[Disruptive\\]|\\[Serial\\]"
-	v := apimachineryversion.MustParseSemantic(testParams.clusterVersion)
+	v := apimachineryversion.MustParseSemantic(clusterVersion)
 
 	// "volumeMode should not mount / map unused volumes in a pod" tests a
 	// (https://github.com/kubernetes/kubernetes/pull/81163)
@@ -514,15 +488,15 @@ func generateGCETestSkip(testParams *testParameters) string {
 	if v.LessThan(apimachineryversion.MustParseSemantic("1.17.0")) {
 		skipString = skipString + "|VolumeSnapshotDataSource"
 	}
-	if testParams.platform == "windows" {
+	if platform == "windows" {
 		skipString = skipString + "|\\[LinuxOnly\\]"
 	}
 	return skipString
 }
 
-func generateGKETestSkip(testParams *testParameters) string {
+func generateGKETestSkip(clusterVersion string, use_gke_managed_driver bool) string {
 	skipString := "\\[Disruptive\\]|\\[Serial\\]"
-	curVer := mustParseVersion(testParams.clusterVersion)
+	curVer := mustParseVersion(clusterVersion)
 
 	// "volumeMode should not mount / map unused volumes in a pod" tests a
 	// (https://github.com/kubernetes/kubernetes/pull/81163)
@@ -532,14 +506,14 @@ func generateGKETestSkip(testParams *testParameters) string {
 	}
 
 	// For GKE deployed PD CSI driver, resizer sidecar is enabled in 1.16.8-gke.3
-	if (testParams.useGKEManagedDriver && curVer.lessThan(mustParseVersion("1.16.8-gke.3"))) ||
-		(!testParams.useGKEManagedDriver && curVer.lessThan(mustParseVersion("1.16.0"))) {
+	if (use_gke_managed_driver && curVer.lessThan(mustParseVersion("1.16.8-gke.3"))) ||
+		(!use_gke_managed_driver && curVer.lessThan(mustParseVersion("1.16.0"))) {
 		skipString = skipString + "|allowExpansion"
 	}
 
 	// For GKE deployed PD CSI snapshot is enabled in 1.17.6-gke.4(and higher), 1.18.3-gke.0(and higher).
-	if (testParams.useGKEManagedDriver && curVer.lessThan(mustParseVersion("1.17.6-gke.4"))) ||
-		(!testParams.useGKEManagedDriver && (*curVer).lessThan(mustParseVersion("1.17.0"))) {
+	if (use_gke_managed_driver && curVer.lessThan(mustParseVersion("1.17.6-gke.4"))) ||
+		(!use_gke_managed_driver && (*curVer).lessThan(mustParseVersion("1.17.0"))) {
 		skipString = skipString + "|VolumeSnapshotDataSource"
 	}
 	return skipString
@@ -558,21 +532,22 @@ func setEnvProject(project string) error {
 	return nil
 }
 
-func runMigrationTests(testParams *testParameters) error {
-	return runTestsWithConfig(testParams, "--storage.migratedPlugins=kubernetes.io/gce-pd", "")
+func runMigrationTests(pkgDir, testDir, testFocus, testSkip string, cloudProviderArgs []string) error {
+	return runTestsWithConfig(testDir, testFocus, testSkip, "--storage.migratedPlugins=kubernetes.io/gce-pd", cloudProviderArgs, "", 0)
 }
 
-func runCSITests(testParams *testParameters, storageClassFile string, reportPrefix string) error {
-	testDriverConfigFile, err := generateDriverConfigFile(testParams, storageClassFile)
+func runCSITests(platform, pkgDir, testDir, testFocus, testSkip, storageClassFile, snapshotClassFile string,
+	cloudProviderArgs []string, deploymentStrat, reportPrefix string, allowedNotReadyNodes int) error {
+	testDriverConfigFile, err := generateDriverConfigFile(platform, pkgDir, storageClassFile, snapshotClassFile, deploymentStrat)
 	if err != nil {
 		return err
 	}
 	testConfigArg := fmt.Sprintf("--storage.testdriver=%s", testDriverConfigFile)
-	return runTestsWithConfig(testParams, testConfigArg, reportPrefix)
+	return runTestsWithConfig(testDir, testFocus, testSkip, testConfigArg, cloudProviderArgs, reportPrefix, allowedNotReadyNodes)
 }
 
-func runTestsWithConfig(testParams *testParameters, testConfigArg, reportPrefix string) error {
-	err := os.Chdir(testParams.testDir)
+func runTestsWithConfig(testDir, testFocus, testSkip, testConfigArg string, cloudProviderArgs []string, reportPrefix string, allowedNotReadyNodes int) error {
+	err := os.Chdir(testDir)
 	if err != nil {
 		return err
 	}
@@ -596,9 +571,9 @@ func runTestsWithConfig(testParams *testParameters, testConfigArg, reportPrefix
 			kubetestDumpDir = artifactsDir
 		}
 	}
-	ginkgoArgs := fmt.Sprintf("--ginkgo.focus=%s --ginkgo.skip=%s", testParams.testFocus, testParams.testSkip)
-	if testParams.platform == "windows" {
-		ginkgoArgs = ginkgoArgs + fmt.Sprintf(" --node-os-distro=%s --allowed-not-ready-nodes=%d", testParams.platform, testParams.allowedNotReadyNodes)
+	ginkgoArgs := fmt.Sprintf("--ginkgo.focus=%s --ginkgo.skip=%s", testFocus, testSkip)
+	if *platform == "windows" {
+		ginkgoArgs = ginkgoArgs + fmt.Sprintf(" --node-os-distro=%s --allowed-not-ready-nodes=%d", *platform, allowedNotReadyNodes)
 	}
 	testArgs := fmt.Sprintf("%s %s %s",
 		ginkgoArgs,
@@ -614,7 +589,7 @@ func runTestsWithConfig(testParams *testParameters, testConfigArg, reportPrefix
 	if kubetestDumpDir != "" {
 		kubeTestArgs = append(kubeTestArgs, fmt.Sprintf("--dump=%s", kubetestDumpDir))
 	}
-	kubeTestArgs = append(kubeTestArgs, testParams.cloudProviderArgs...)
+	kubeTestArgs = append(kubeTestArgs, cloudProviderArgs...)
 
 	err = runCommand("Running Tests", exec.Command("kubetest", kubeTestArgs...))
 	if err != nil {