Skip to content

Commit fd64b83

Browse files
authored
Merge pull request kubernetes#77837 from davidz627/fix/pdFSType
Translate StorageClass object instead of parameters. Add GCE PD Storage class translation logic.
2 parents 0a3884e + 6aea7fc commit fd64b83

File tree

8 files changed

+385
-15
lines changed

8 files changed

+385
-15
lines changed

staging/src/k8s.io/csi-translation-lib/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ go_library(
88
visibility = ["//visibility:public"],
99
deps = [
1010
"//staging/src/k8s.io/api/core/v1:go_default_library",
11+
"//staging/src/k8s.io/api/storage/v1:go_default_library",
1112
"//staging/src/k8s.io/csi-translation-lib/plugins:go_default_library",
1213
],
1314
)

staging/src/k8s.io/csi-translation-lib/plugins/BUILD

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ go_library(
1313
visibility = ["//visibility:public"],
1414
deps = [
1515
"//staging/src/k8s.io/api/core/v1:go_default_library",
16+
"//staging/src/k8s.io/api/storage/v1:go_default_library",
1617
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
1718
"//staging/src/k8s.io/cloud-provider/volume:go_default_library",
1819
],
@@ -34,6 +35,13 @@ filegroup(
3435

3536
go_test(
3637
name = "go_default_test",
37-
srcs = ["aws_ebs_test.go"],
38+
srcs = [
39+
"aws_ebs_test.go",
40+
"gce_pd_test.go",
41+
],
3842
embed = [":go_default_library"],
43+
deps = [
44+
"//staging/src/k8s.io/api/core/v1:go_default_library",
45+
"//staging/src/k8s.io/api/storage/v1:go_default_library",
46+
],
3947
)

staging/src/k8s.io/csi-translation-lib/plugins/aws_ebs.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"strings"
2525

2626
"k8s.io/api/core/v1"
27+
storage "k8s.io/api/storage/v1"
2728
)
2829

2930
const (
@@ -44,8 +45,8 @@ func NewAWSElasticBlockStoreCSITranslator() InTreePlugin {
4445
}
4546

4647
// TranslateInTreeStorageClassParametersToCSI translates InTree EBS storage class parameters to CSI storage class
47-
func (t *awsElasticBlockStoreCSITranslator) TranslateInTreeStorageClassParametersToCSI(scParameters map[string]string) (map[string]string, error) {
48-
return scParameters, nil
48+
func (t *awsElasticBlockStoreCSITranslator) TranslateInTreeStorageClassToCSI(sc *storage.StorageClass) (*storage.StorageClass, error) {
49+
return sc, nil
4950
}
5051

5152
// TranslateInTreePVToCSI takes a PV with AWSElasticBlockStore set from in-tree

staging/src/k8s.io/csi-translation-lib/plugins/gce_pd.go

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"strings"
2323

2424
"k8s.io/api/core/v1"
25+
storage "k8s.io/api/storage/v1"
2526
"k8s.io/apimachinery/pkg/util/sets"
2627
cloudvolume "k8s.io/cloud-provider/volume"
2728
)
@@ -32,6 +33,9 @@ const (
3233
// GCEPDInTreePluginName is the name of the intree plugin for GCE PD
3334
GCEPDInTreePluginName = "kubernetes.io/gce-pd"
3435

36+
// GCEPDTopologyKey is the zonal topology key for GCE PD CSI Driver
37+
GCEPDTopologyKey = "topology.gke.io/zone"
38+
3539
// Volume ID Expected Format
3640
// "projects/{projectName}/zones/{zoneName}/disks/{diskName}"
3741
volIDZonalFmt = "projects/%s/zones/%s/disks/%s"
@@ -55,9 +59,102 @@ func NewGCEPersistentDiskCSITranslator() InTreePlugin {
5559
return &gcePersistentDiskCSITranslator{}
5660
}
5761

62+
func translateAllowedTopologies(terms []v1.TopologySelectorTerm) ([]v1.TopologySelectorTerm, error) {
63+
if terms == nil {
64+
return nil, nil
65+
}
66+
67+
newTopologies := []v1.TopologySelectorTerm{}
68+
for _, term := range terms {
69+
newTerm := v1.TopologySelectorTerm{}
70+
for _, exp := range term.MatchLabelExpressions {
71+
var newExp v1.TopologySelectorLabelRequirement
72+
if exp.Key == v1.LabelZoneFailureDomain {
73+
newExp = v1.TopologySelectorLabelRequirement{
74+
Key: GCEPDTopologyKey,
75+
Values: exp.Values,
76+
}
77+
} else if exp.Key == GCEPDTopologyKey {
78+
newExp = exp
79+
} else {
80+
return nil, fmt.Errorf("unknown topology key: %v", exp.Key)
81+
}
82+
newTerm.MatchLabelExpressions = append(newTerm.MatchLabelExpressions, newExp)
83+
}
84+
newTopologies = append(newTopologies, newTerm)
85+
}
86+
return newTopologies, nil
87+
}
88+
89+
func generateToplogySelectors(key string, values []string) []v1.TopologySelectorTerm {
90+
return []v1.TopologySelectorTerm{
91+
{
92+
MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{
93+
{
94+
Key: key,
95+
Values: values,
96+
},
97+
},
98+
},
99+
}
100+
}
101+
58102
// TranslateInTreeStorageClassParametersToCSI translates InTree GCE storage class parameters to CSI storage class
59-
func (g *gcePersistentDiskCSITranslator) TranslateInTreeStorageClassParametersToCSI(scParameters map[string]string) (map[string]string, error) {
60-
return scParameters, nil
103+
func (g *gcePersistentDiskCSITranslator) TranslateInTreeStorageClassToCSI(sc *storage.StorageClass) (*storage.StorageClass, error) {
104+
var generatedTopologies []v1.TopologySelectorTerm
105+
106+
np := map[string]string{}
107+
for k, v := range sc.Parameters {
108+
switch strings.ToLower(k) {
109+
case "fstype":
110+
// prefixed fstype parameter is stripped out by external provisioner
111+
np["csi.storage.k8s.io/fstype"] = v
112+
// Strip out zone and zones parameters and translate them into topologies instead
113+
case "zone":
114+
generatedTopologies = generateToplogySelectors(GCEPDTopologyKey, []string{v})
115+
case "zones":
116+
generatedTopologies = generateToplogySelectors(GCEPDTopologyKey, strings.Split(v, ","))
117+
default:
118+
np[k] = v
119+
}
120+
}
121+
122+
if len(generatedTopologies) > 0 && len(sc.AllowedTopologies) > 0 {
123+
return nil, fmt.Errorf("cannot simultaneously set allowed topologies and zone/zones parameters")
124+
} else if len(generatedTopologies) > 0 {
125+
sc.AllowedTopologies = generatedTopologies
126+
} else if len(sc.AllowedTopologies) > 0 {
127+
newTopologies, err := translateAllowedTopologies(sc.AllowedTopologies)
128+
if err != nil {
129+
return nil, fmt.Errorf("failed translating allowed topologies: %v", err)
130+
}
131+
sc.AllowedTopologies = newTopologies
132+
}
133+
134+
sc.Parameters = np
135+
136+
return sc, nil
137+
}
138+
139+
// backwardCompatibleAccessModes translates all instances of ReadWriteMany
140+
// access mode from the in-tree plugin to ReadWriteOnce. This is because in-tree
141+
// plugin never supported ReadWriteMany but also did not validate or enforce
142+
// this access mode for pre-provisioned volumes. The GCE PD CSI Driver validates
143+
// and enforces (fails) ReadWriteMany. Therefore we treat all in-tree
144+
// ReadWriteMany as ReadWriteOnce volumes to not break legacy volumes.
145+
func backwardCompatibleAccessModes(ams []v1.PersistentVolumeAccessMode) []v1.PersistentVolumeAccessMode {
146+
if ams == nil {
147+
return nil
148+
}
149+
newAM := []v1.PersistentVolumeAccessMode{}
150+
for _, am := range ams {
151+
if am == v1.ReadWriteMany {
152+
newAM = append(newAM, v1.ReadWriteOnce)
153+
} else {
154+
newAM = append(newAM, am)
155+
}
156+
}
157+
return newAM
61158
}
62159

63160
// TranslateInTreePVToCSI takes a PV with GCEPersistentDisk set from in-tree
@@ -105,6 +202,7 @@ func (g *gcePersistentDiskCSITranslator) TranslateInTreePVToCSI(pv *v1.Persisten
105202

106203
pv.Spec.PersistentVolumeSource.GCEPersistentDisk = nil
107204
pv.Spec.PersistentVolumeSource.CSI = csiSource
205+
pv.Spec.AccessModes = backwardCompatibleAccessModes(pv.Spec.AccessModes)
108206

109207
return pv, nil
110208
}

0 commit comments

Comments
 (0)