Skip to content

Commit d630e83

Browse files
authored
Merge pull request #1241 from sunnylovestiramisu/automated-cherry-pick-of-#1079-#1101-upstream-release-1.8
Automated cherry pick of #1079: Add provisionedIops for pd-extreme #1101: Add provisionedThroughput for hyperdisk
2 parents cf106c9 + 0b0ae6b commit d630e83

File tree

22 files changed

+7916
-1462
lines changed

22 files changed

+7916
-1462
lines changed

README.md

+8-6
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,14 @@ See Github [Issues](https://github.com/kubernetes-sigs/gcp-compute-persistent-di
5858

5959
### CreateVolume Parameters
6060

61-
| Parameter | Values | Default | Description |
62-
|------------------|---------------------------|---------------|----------------------------------------------------------------------------------------------------|
63-
| type | Any PD type (see [GCP documentation](https://cloud.google.com/compute/docs/disks#disk-types)), eg `pd-ssd` `pd-balanced` | `pd-standard` | Type allows you to choose between standard Persistent Disks or Solid State Drive Persistent Disks |
64-
| replication-type | `none` OR `regional-pd` | `none` | Replication type allows you to choose between Zonal Persistent Disks or Regional Persistent Disks |
65-
| disk-encryption-kms-key | Fully qualified resource identifier for the key to use to encrypt new disks. | Empty string. | Encrypt disk using Customer Managed Encryption Key (CMEK). See [GKE Docs](https://cloud.google.com/kubernetes-engine/docs/how-to/using-cmek#create_a_cmek_protected_attached_disk) for details. |
66-
| labels | `key1=value1,key2=value2` | | Labels allow you to assign custom [GCE Disk labels](https://cloud.google.com/compute/docs/labeling-resources). |
61+
| Parameter | Values | Default | Description |
62+
|-----------------------------|---------------------------|---------------|----------------------------------------------------------------------------------------------------|
63+
| type | Any PD type (see [GCP documentation](https://cloud.google.com/compute/docs/disks#disk-types)), eg `pd-ssd` `pd-balanced` | `pd-standard` | Type allows you to choose between standard Persistent Disks or Solid State Drive Persistent Disks |
64+
| replication-type | `none` OR `regional-pd` | `none` | Replication type allows you to choose between Zonal Persistent Disks or Regional Persistent Disks |
65+
| disk-encryption-kms-key | Fully qualified resource identifier for the key to use to encrypt new disks. | Empty string. | Encrypt disk using Customer Managed Encryption Key (CMEK). See [GKE Docs](https://cloud.google.com/kubernetes-engine/docs/how-to/using-cmek#create_a_cmek_protected_attached_disk) for details. |
66+
| labels | `key1=value1,key2=value2` | | Labels allow you to assign custom [GCE Disk labels](https://cloud.google.com/compute/docs/labeling-resources). |
67+
| provisioned-iops-on-create | string (int64 format). Values typically between 10,000 and 120,000 | | Indicates how many IOPS to provision for the disk. See the [Extreme persistent disk documentation](https://cloud.google.com/compute/docs/disks/extreme-persistent-disk) for details, including valid ranges for IOPS. |
68+
| provisioned-throughput-on-create | string (int64 format). Values typically between 1 and 7,124 mb per second | | Indicates how much throughput to provision for the disk. See the [hyperdisk documentation](TBD) for details, including valid ranges for throughput. |
6769

6870
### Topology
6971

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ require (
2121
gopkg.in/gcfg.v1 v1.2.3
2222
k8s.io/apimachinery v0.24.1
2323
k8s.io/client-go v11.0.1-0.20190805182717-6502b5e7b1b5+incompatible
24+
k8s.io/cloud-provider v0.24.1
2425
k8s.io/component-base v0.24.1
2526
k8s.io/klog/v2 v2.60.1
2627
k8s.io/kubernetes v1.24.1

go.sum

+1
Original file line numberDiff line numberDiff line change
@@ -2432,6 +2432,7 @@ k8s.io/apiserver v0.24.1/go.mod h1:dQWNMx15S8NqJMp0gpYfssyvhYnkilc1LpExd/dkLh0=
24322432
k8s.io/cli-runtime v0.24.1/go.mod h1:14aVvCTqkA7dNXY51N/6hRY3GUjchyWDOwW84qmR3bs=
24332433
k8s.io/client-go v0.24.1 h1:w1hNdI9PFrzu3OlovVeTnf4oHDt+FJLd9Ndluvnb42E=
24342434
k8s.io/client-go v0.24.1/go.mod h1:f1kIDqcEYmwXS/vTbbhopMUbhKp2JhOeVTfxgaCIlF8=
2435+
k8s.io/cloud-provider v0.24.1 h1:SaQNq2Ax+epdY9wFngwN9GWpOVnM72hUqr2qy20cOvg=
24352436
k8s.io/cloud-provider v0.24.1/go.mod h1:h5m/KIiwiQ76hpUBsgrwm/rxteIfJG9kJQ/+/w1as2M=
24362437
k8s.io/cluster-bootstrap v0.24.1/go.mod h1:uq2PiYfKh8ZLb6DBU/3/2Z1DkMqXkTOHLemalC4tOgE=
24372438
k8s.io/code-generator v0.24.1/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w=

pkg/common/parameters.go

+24-4
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@ import (
2323

2424
const (
2525
// Parameters for StorageClass
26-
ParameterKeyType = "type"
27-
ParameterKeyReplicationType = "replication-type"
28-
ParameterKeyDiskEncryptionKmsKey = "disk-encryption-kms-key"
29-
ParameterKeyLabels = "labels"
26+
ParameterKeyType = "type"
27+
ParameterKeyReplicationType = "replication-type"
28+
ParameterKeyDiskEncryptionKmsKey = "disk-encryption-kms-key"
29+
ParameterKeyLabels = "labels"
30+
ParameterKeyProvisionedIOPSOnCreate = "provisioned-iops-on-create"
31+
ParameterKeyProvisionedThroughputOnCreate = "provisioned-throughput-on-create"
3032

3133
// Parameters for VolumeSnapshotClass
3234
ParameterKeyStorageLocations = "storage-locations"
@@ -75,6 +77,12 @@ type DiskParameters struct {
7577
// Values: {map[string]string}
7678
// Default: ""
7779
Labels map[string]string
80+
// Values: {int64}
81+
// Default: none
82+
ProvisionedIOPSOnCreate int64
83+
// Values: {int64}
84+
// Default: none
85+
ProvisionedThroughputOnCreate int64
7886
}
7987

8088
// SnapshotParameters contains normalized and defaulted parameters for snapshots
@@ -135,6 +143,18 @@ func ExtractAndDefaultParameters(parameters map[string]string, driverName string
135143
for labelKey, labelValue := range paramLabels {
136144
p.Labels[labelKey] = labelValue
137145
}
146+
case ParameterKeyProvisionedIOPSOnCreate:
147+
paramProvisionedIOPSOnCreate, err := ConvertStringToInt64(v)
148+
if err != nil {
149+
return p, fmt.Errorf("parameters contain invalid provisionedIOPSOnCreate parameter: %w", err)
150+
}
151+
p.ProvisionedIOPSOnCreate = paramProvisionedIOPSOnCreate
152+
case ParameterKeyProvisionedThroughputOnCreate:
153+
paramProvisionedThroughputOnCreate, err := ConvertMiStringToInt64(v)
154+
if err != nil {
155+
return p, fmt.Errorf("parameters contain invalid provisionedThroughputOnCreate parameter: %w", err)
156+
}
157+
p.ProvisionedThroughputOnCreate = paramProvisionedThroughputOnCreate
138158
default:
139159
return p, fmt.Errorf("parameters contains invalid option %q", k)
140160
}

pkg/common/parameters_test.go

+32
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,38 @@ func TestExtractAndDefaultParameters(t *testing.T) {
7474
},
7575
},
7676
},
77+
{
78+
name: "values from parameters, checking pd-extreme",
79+
parameters: map[string]string{ParameterKeyType: "pd-extreme", ParameterKeyReplicationType: "none", ParameterKeyDiskEncryptionKmsKey: "foo/key", ParameterKeyLabels: "key1=value1,key2=value2", ParameterKeyProvisionedIOPSOnCreate: "10k"},
80+
labels: map[string]string{},
81+
expectParams: DiskParameters{
82+
DiskType: "pd-extreme",
83+
ReplicationType: "none",
84+
DiskEncryptionKMSKey: "foo/key",
85+
Tags: map[string]string{},
86+
Labels: map[string]string{
87+
"key1": "value1",
88+
"key2": "value2",
89+
},
90+
ProvisionedIOPSOnCreate: 10000,
91+
},
92+
},
93+
{
94+
name: "values from parameters, checking hyperdisk-throughput",
95+
parameters: map[string]string{ParameterKeyType: "hyperdisk-throughput", ParameterKeyReplicationType: "none", ParameterKeyDiskEncryptionKmsKey: "foo/key", ParameterKeyLabels: "key1=value1,key2=value2", ParameterKeyProvisionedThroughputOnCreate: "1000Mi"},
96+
labels: map[string]string{},
97+
expectParams: DiskParameters{
98+
DiskType: "hyperdisk-throughput",
99+
ReplicationType: "none",
100+
DiskEncryptionKMSKey: "foo/key",
101+
Tags: map[string]string{},
102+
Labels: map[string]string{
103+
"key1": "value1",
104+
"key2": "value2",
105+
},
106+
ProvisionedThroughputOnCreate: 1000,
107+
},
108+
},
77109
{
78110
name: "values from parameters, checking balanced pd",
79111
parameters: map[string]string{ParameterKeyType: "pd-balanced", ParameterKeyReplicationType: "regional-pd", ParameterKeyDiskEncryptionKmsKey: "foo/key"},

pkg/common/utils.go

+20
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ import (
2222
"strings"
2323

2424
"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta"
25+
"k8s.io/apimachinery/pkg/api/resource"
2526
"k8s.io/apimachinery/pkg/util/sets"
27+
volumehelpers "k8s.io/cloud-provider/volume/helpers"
2628
)
2729

2830
const (
@@ -268,3 +270,21 @@ func ParseMachineType(machineTypeUrl string) (string, error) {
268270
}
269271
return machineType[1], nil
270272
}
273+
274+
// ConvertStringToInt64 converts a string to int64
275+
func ConvertStringToInt64(str string) (int64, error) {
276+
quantity, err := resource.ParseQuantity(str)
277+
if err != nil {
278+
return -1, err
279+
}
280+
return volumehelpers.RoundUpToB(quantity)
281+
}
282+
283+
// ConvertMiStringToInt64 converts a GiB string to int64
284+
func ConvertMiStringToInt64(str string) (int64, error) {
285+
quantity, err := resource.ParseQuantity(str)
286+
if err != nil {
287+
return -1, err
288+
}
289+
return volumehelpers.RoundUpToMiB(quantity)
290+
}

pkg/common/utils_test.go

+222
Original file line numberDiff line numberDiff line change
@@ -631,3 +631,225 @@ func TestParseMachineType(t *testing.T) {
631631
})
632632
}
633633
}
634+
635+
func TestConvertStringToInt64(t *testing.T) {
636+
tests := []struct {
637+
desc string
638+
inputStr string
639+
expInt64 int64
640+
expectError bool
641+
}{
642+
{
643+
desc: "valid number string",
644+
inputStr: "10000",
645+
expInt64: 10000,
646+
expectError: false,
647+
},
648+
{
649+
desc: "round M to number",
650+
inputStr: "1M",
651+
expInt64: 1000000,
652+
expectError: false,
653+
},
654+
{
655+
desc: "round m to number",
656+
inputStr: "1m",
657+
expInt64: 1,
658+
expectError: false,
659+
},
660+
{
661+
desc: "round k to number",
662+
inputStr: "1k",
663+
expInt64: 1000,
664+
expectError: false,
665+
},
666+
{
667+
desc: "invalid empty string",
668+
inputStr: "",
669+
expInt64: 0,
670+
expectError: true,
671+
},
672+
{
673+
desc: "invalid string",
674+
inputStr: "ew%65",
675+
expInt64: 0,
676+
expectError: true,
677+
},
678+
{
679+
desc: "invalid KiB string",
680+
inputStr: "10KiB",
681+
expInt64: 10000,
682+
expectError: true,
683+
},
684+
{
685+
desc: "invalid GB string",
686+
inputStr: "10GB",
687+
expInt64: 0,
688+
expectError: true,
689+
},
690+
{
691+
desc: "round Ki to number",
692+
inputStr: "1Ki",
693+
expInt64: 1024,
694+
expectError: false,
695+
},
696+
{
697+
desc: "round k to number",
698+
inputStr: "10k",
699+
expInt64: 10000,
700+
expectError: false,
701+
},
702+
{
703+
desc: "round Mi to number",
704+
inputStr: "10Mi",
705+
expInt64: 10485760,
706+
expectError: false,
707+
},
708+
{
709+
desc: "round M to number",
710+
inputStr: "10M",
711+
expInt64: 10000000,
712+
expectError: false,
713+
},
714+
{
715+
desc: "round G to number",
716+
inputStr: "10G",
717+
expInt64: 10000000000,
718+
expectError: false,
719+
},
720+
{
721+
desc: "round Gi to number",
722+
inputStr: "100Gi",
723+
expInt64: 107374182400,
724+
expectError: false,
725+
},
726+
{
727+
desc: "round decimal to number",
728+
inputStr: "1.2Gi",
729+
expInt64: 1288490189,
730+
expectError: false,
731+
},
732+
{
733+
desc: "round big value to number",
734+
inputStr: "8191Pi",
735+
expInt64: 9222246136947933184,
736+
expectError: false,
737+
},
738+
}
739+
for _, tc := range tests {
740+
t.Run(tc.desc, func(t *testing.T) {
741+
actualInt64, err := ConvertStringToInt64(tc.inputStr)
742+
if err != nil && !tc.expectError {
743+
t.Errorf("Got error %v converting string to int64 %s; expect no error", err, tc.inputStr)
744+
}
745+
if err == nil && tc.expectError {
746+
t.Errorf("Got no error converting string to int64 %s; expect an error", tc.inputStr)
747+
}
748+
if err == nil && actualInt64 != tc.expInt64 {
749+
t.Errorf("Got %d for converting string to int64; expect %d", actualInt64, tc.expInt64)
750+
}
751+
})
752+
}
753+
}
754+
755+
func TestConvertMiStringToInt64(t *testing.T) {
756+
tests := []struct {
757+
desc string
758+
inputStr string
759+
expInt64 int64
760+
expectError bool
761+
}{
762+
{
763+
desc: "valid number string",
764+
inputStr: "10000",
765+
expInt64: 1,
766+
expectError: false,
767+
},
768+
{
769+
desc: "round Ki to MiB",
770+
inputStr: "1000Ki",
771+
expInt64: 1,
772+
expectError: false,
773+
},
774+
{
775+
desc: "round k to MiB",
776+
inputStr: "1000k",
777+
expInt64: 1,
778+
expectError: false,
779+
},
780+
{
781+
desc: "round Mi to MiB",
782+
inputStr: "1000Mi",
783+
expInt64: 1000,
784+
expectError: false,
785+
},
786+
{
787+
desc: "round M to MiB",
788+
inputStr: "1000M",
789+
expInt64: 954,
790+
expectError: false,
791+
},
792+
{
793+
desc: "round G to MiB",
794+
inputStr: "1000G",
795+
expInt64: 953675,
796+
expectError: false,
797+
},
798+
{
799+
desc: "round Gi to MiB",
800+
inputStr: "10000Gi",
801+
expInt64: 10240000,
802+
expectError: false,
803+
},
804+
{
805+
desc: "round decimal to MiB",
806+
inputStr: "1.2Gi",
807+
expInt64: 1229,
808+
expectError: false,
809+
},
810+
{
811+
desc: "round big value to MiB",
812+
inputStr: "8191Pi",
813+
expInt64: 8795019280384,
814+
expectError: false,
815+
},
816+
{
817+
desc: "invalid empty string",
818+
inputStr: "",
819+
expInt64: 0,
820+
expectError: true,
821+
},
822+
{
823+
desc: "invalid KiB string",
824+
inputStr: "10KiB",
825+
expInt64: 10000,
826+
expectError: true,
827+
},
828+
{
829+
desc: "invalid GB string",
830+
inputStr: "10GB",
831+
expInt64: 0,
832+
expectError: true,
833+
},
834+
{
835+
desc: "invalid string",
836+
inputStr: "ew%65",
837+
expInt64: 0,
838+
expectError: true,
839+
},
840+
}
841+
for _, tc := range tests {
842+
t.Run(tc.desc, func(t *testing.T) {
843+
actualInt64, err := ConvertMiStringToInt64(tc.inputStr)
844+
if err != nil && !tc.expectError {
845+
t.Errorf("Got error %v converting string to int64 %s; expect no error", err, tc.inputStr)
846+
}
847+
if err == nil && tc.expectError {
848+
t.Errorf("Got no error converting string to int64 %s; expect an error", tc.inputStr)
849+
}
850+
if err == nil && actualInt64 != tc.expInt64 {
851+
t.Errorf("Got %d for converting string to int64; expect %d", actualInt64, tc.expInt64)
852+
}
853+
})
854+
}
855+
}

0 commit comments

Comments
 (0)