Skip to content

Commit bbc6725

Browse files
committed
Support UNSPECIFID zone and project in volume ID. Static driver name. Prep for Migration
1 parent 5291315 commit bbc6725

File tree

8 files changed

+132
-21
lines changed

8 files changed

+132
-21
lines changed

cmd/main.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,13 @@ func init() {
3434

3535
var (
3636
endpoint = flag.String("endpoint", "unix:/tmp/csi.sock", "CSI endpoint")
37-
driverName = flag.String("drivername", "com.google.csi.gcepd", "name of the driver")
3837
vendorVersion string
3938
)
4039

40+
const (
41+
driverName = "com.google.csi.gcepd"
42+
)
43+
4144
func main() {
4245
flag.Parse()
4346
rand.Seed(time.Now().UnixNano())
@@ -67,7 +70,7 @@ func handle() {
6770
glog.Fatalf("Failed to set up metadata service: %v", err)
6871
}
6972

70-
err = gceDriver.SetupGCEDriver(cloudProvider, mounter, deviceUtils, ms, *driverName, vendorVersion)
73+
err = gceDriver.SetupGCEDriver(cloudProvider, mounter, deviceUtils, ms, driverName, vendorVersion)
7174
if err != nil {
7275
glog.Fatalf("Failed to initialize GCE CSI Driver: %v", err)
7376
}

pkg/common/constants.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,6 @@ const (
2626

2727
// VolumeAttributes for Partition
2828
VolumeAttributePartition = "partition"
29+
30+
UnspecifiedValue = "UNSPECIFIED"
2931
)

pkg/common/utils.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ import (
2727
const (
2828
// Volume ID Expected Format
2929
// "projects/{projectName}/zones/{zoneName}/disks/{diskName}"
30+
volIDZonalFmt = "projects/%s/zones/%s/disks/%s"
3031
// "projects/{projectName}/regions/{regionName}/disks/{diskName}"
32+
volIDRegionalFmt = "projects/%s/regions/%s/disks/%s"
3133
volIDToplogyKey = 2
3234
volIDToplogyValue = 3
3335
volIDDiskNameValue = 5
@@ -71,6 +73,13 @@ func VolumeIDToKey(id string) (*meta.Key, error) {
7173
}
7274
}
7375

76+
func GenerateUnderspecifiedVolumeID(diskName string, isZonal bool) string {
77+
if isZonal {
78+
return fmt.Sprintf(volIDZonalFmt, UnspecifiedValue, UnspecifiedValue, diskName)
79+
}
80+
return fmt.Sprintf(volIDRegionalFmt, UnspecifiedValue, UnspecifiedValue, diskName)
81+
}
82+
7483
func SnapshotIDToKey(id string) (string, error) {
7584
splitId := strings.Split(id, "/")
7685
if len(splitId) != snapshotTotalElements {

pkg/gce-cloud-provider/compute/fake-gce.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ func FakeCreateCloudProvider(project, zone string) (*FakeCloudProvider, error) {
6060

6161
}
6262

63+
func (cloud *FakeCloudProvider) RepairUnderspecifiedVolumeKey(ctx context.Context, volumeKey *meta.Key) (*meta.Key, error) {
64+
return volumeKey, nil
65+
}
66+
6367
func (cloud *FakeCloudProvider) ListZones(ctx context.Context, region string) ([]string, error) {
6468
return []string{cloud.zone, "country-region-fakesecondzone"}, nil
6569
}
@@ -199,12 +203,12 @@ func (cloud *FakeCloudProvider) DeleteDisk(ctx context.Context, volKey *meta.Key
199203
return nil
200204
}
201205

202-
func (cloud *FakeCloudProvider) AttachDisk(ctx context.Context, disk *CloudDisk, volKey *meta.Key, readWrite, diskType, instanceZone, instanceName string) error {
206+
func (cloud *FakeCloudProvider) AttachDisk(ctx context.Context, volKey *meta.Key, readWrite, diskType, instanceZone, instanceName string) error {
203207
source := cloud.GetDiskSourceURI(volKey)
204208

205209
attachedDiskV1 := &compute.AttachedDisk{
206-
DeviceName: disk.GetName(),
207-
Kind: disk.GetKind(),
210+
DeviceName: volKey.Name,
211+
Kind: diskKind,
208212
Mode: readWrite,
209213
Source: source,
210214
Type: diskType,
@@ -217,14 +221,14 @@ func (cloud *FakeCloudProvider) AttachDisk(ctx context.Context, disk *CloudDisk,
217221
return nil
218222
}
219223

220-
func (cloud *FakeCloudProvider) DetachDisk(ctx context.Context, volKey *meta.Key, instanceZone, instanceName string) error {
224+
func (cloud *FakeCloudProvider) DetachDisk(ctx context.Context, deviceName, instanceZone, instanceName string) error {
221225
instance, ok := cloud.instances[instanceName]
222226
if !ok {
223227
return fmt.Errorf("Failed to get instance %v", instanceName)
224228
}
225229
found := -1
226230
for i, disk := range instance.Disks {
227-
if disk.DeviceName == volKey.Name {
231+
if disk.DeviceName == deviceName {
228232
found = i
229233
break
230234
}

pkg/gce-cloud-provider/compute/gce-compute.go

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,18 @@ import (
3434
const (
3535
operationStatusDone = "DONE"
3636
waitForSnapshotCreationTimeOut = 2 * time.Minute
37+
diskKind = "compute#disk"
3738
)
3839

3940
type GCECompute interface {
4041
// Disk Methods
4142
GetDisk(ctx context.Context, volumeKey *meta.Key) (*CloudDisk, error)
43+
RepairUnderspecifiedVolumeKey(ctx context.Context, volumeKey *meta.Key) (*meta.Key, error)
4244
ValidateExistingDisk(ctx context.Context, disk *CloudDisk, diskType string, reqBytes, limBytes int64) error
4345
InsertDisk(ctx context.Context, volKey *meta.Key, diskType string, capBytes int64, capacityRange *csi.CapacityRange, replicaZones []string) error
4446
DeleteDisk(ctx context.Context, volumeKey *meta.Key) error
45-
AttachDisk(ctx context.Context, disk *CloudDisk, volKey *meta.Key, readWrite, diskType, instanceZone, instanceName string) error
46-
DetachDisk(ctx context.Context, volKey *meta.Key, instanceZone, instanceName string) error
47+
AttachDisk(ctx context.Context, volKey *meta.Key, readWrite, diskType, instanceZone, instanceName string) error
48+
DetachDisk(ctx context.Context, deviceName string, instanceZone, instanceName string) error
4749
GetDiskSourceURI(volKey *meta.Key) string
4850
GetDiskTypeURI(volKey *meta.Key, diskType string) string
4951
WaitForAttach(ctx context.Context, volKey *meta.Key, instanceZone, instanceName string) error
@@ -59,7 +61,46 @@ type GCECompute interface {
5961
DeleteSnapshot(ctx context.Context, snapshotName string) error
6062
}
6163

64+
// RepairUnderspecifiedVolumeKey will query the cloud provider and check each zone for the disk specified
65+
// by the volume key and return a volume key with a correct zone
66+
func (cloud *CloudProvider) RepairUnderspecifiedVolumeKey(ctx context.Context, volumeKey *meta.Key) (*meta.Key, error) {
67+
region, err := common.GetRegionFromZones([]string{cloud.zone})
68+
if err != nil {
69+
return nil, fmt.Errorf("failed to get region from zones: %v", err)
70+
}
71+
switch volumeKey.Type() {
72+
case meta.Zonal:
73+
if volumeKey.Zone == common.UnspecifiedValue {
74+
// list all zones, try to get disk in each zone
75+
zones, err := cloud.ListZones(ctx, region)
76+
if err != nil {
77+
return nil, err
78+
}
79+
for _, zone := range zones {
80+
_, err := cloud.getZonalDiskOrError(ctx, zone, volumeKey.Name)
81+
if err == nil {
82+
// If there is no error we have found a disk
83+
volumeKey.Zone = zone
84+
return volumeKey, nil
85+
}
86+
}
87+
return nil, fmt.Errorf("volume zone unspecified and unable to find in any of these zones %v", zones)
88+
}
89+
return volumeKey, nil
90+
case meta.Regional:
91+
if volumeKey.Region == common.UnspecifiedValue {
92+
volumeKey.Region = region
93+
}
94+
return volumeKey, nil
95+
default:
96+
return nil, fmt.Errorf("key was neither zonal nor regional, got: %v", volumeKey.String())
97+
}
98+
}
99+
62100
func (cloud *CloudProvider) ListZones(ctx context.Context, region string) ([]string, error) {
101+
if len(cloud.zonesCache[region]) > 0 {
102+
return cloud.zonesCache[region], nil
103+
}
63104
zones := []string{}
64105
zoneList, err := cloud.service.Zones.List(cloud.project).Filter(fmt.Sprintf("region eq .*%s$", region)).Do()
65106
if err != nil {
@@ -68,6 +109,7 @@ func (cloud *CloudProvider) ListZones(ctx context.Context, region string) ([]str
68109
for _, zone := range zoneList.Items {
69110
zones = append(zones, zone.Name)
70111
}
112+
cloud.zonesCache[region] = zones
71113
return zones, nil
72114

73115
}
@@ -315,7 +357,7 @@ func (cloud *CloudProvider) deleteRegionalDisk(ctx context.Context, region, name
315357
return nil
316358
}
317359

318-
func (cloud *CloudProvider) AttachDisk(ctx context.Context, disk *CloudDisk, volKey *meta.Key, readWrite, diskType, instanceZone, instanceName string) error {
360+
func (cloud *CloudProvider) AttachDisk(ctx context.Context, volKey *meta.Key, readWrite, diskType, instanceZone, instanceName string) error {
319361
source := cloud.GetDiskSourceURI(volKey)
320362

321363
deviceName, err := common.GetDeviceName(volKey)
@@ -324,7 +366,7 @@ func (cloud *CloudProvider) AttachDisk(ctx context.Context, disk *CloudDisk, vol
324366
}
325367
attachedDiskV1 := &compute.AttachedDisk{
326368
DeviceName: deviceName,
327-
Kind: disk.GetKind(),
369+
Kind: diskKind,
328370
Mode: readWrite,
329371
Source: source,
330372
Type: diskType,
@@ -341,12 +383,7 @@ func (cloud *CloudProvider) AttachDisk(ctx context.Context, disk *CloudDisk, vol
341383
return nil
342384
}
343385

344-
func (cloud *CloudProvider) DetachDisk(ctx context.Context, volKey *meta.Key, instanceZone, instanceName string) error {
345-
deviceName, err := common.GetDeviceName(volKey)
346-
if err != nil {
347-
return err
348-
}
349-
386+
func (cloud *CloudProvider) DetachDisk(ctx context.Context, deviceName, instanceZone, instanceName string) error {
350387
op, err := cloud.service.Instances.DetachDisk(cloud.project, instanceZone, instanceName, deviceName).Context(ctx).Do()
351388
if err != nil {
352389
return err

pkg/gce-cloud-provider/compute/gce.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ type CloudProvider struct {
5151
betaService *beta.Service
5252
project string
5353
zone string
54+
55+
zonesCache map[string]([]string)
5456
}
5557

5658
var _ GCECompute = &CloudProvider{}
@@ -76,6 +78,7 @@ func CreateCloudProvider(vendorVersion string) (*CloudProvider, error) {
7678
betaService: betasvc,
7779
project: project,
7880
zone: zone,
81+
zonesCache: make(map[string]([]string)),
7982
}, nil
8083

8184
}

pkg/gce-pd-csi-driver/controller.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,11 @@ func (gceCS *GCEControllerServer) DeleteVolume(ctx context.Context, req *csi.Del
191191
return &csi.DeleteVolumeResponse{}, nil
192192
}
193193

194+
volKey, err = gceCS.CloudProvider.RepairUnderspecifiedVolumeKey(ctx, volKey)
195+
if err != nil {
196+
return nil, status.Error(codes.NotFound, fmt.Sprintf("Could not find volume with ID %v: %v", volumeID, err))
197+
}
198+
194199
err = gceCS.CloudProvider.DeleteDisk(ctx, volKey)
195200
if err != nil {
196201
return nil, status.Error(codes.Internal, fmt.Sprintf("unknown Delete disk error: %v", err))
@@ -222,13 +227,17 @@ func (gceCS *GCEControllerServer) ControllerPublishVolume(ctx context.Context, r
222227
return nil, status.Error(codes.NotFound, fmt.Sprintf("Could not find volume with ID %v: %v", volumeID, err))
223228
}
224229

230+
volKey, err = gceCS.CloudProvider.RepairUnderspecifiedVolumeKey(ctx, volKey)
231+
if err != nil {
232+
return nil, status.Error(codes.NotFound, fmt.Sprintf("Could not find volume with ID %v: %v", volumeID, err))
233+
}
225234
// TODO(#94): Check volume capability matches
226235

227236
pubVolResp := &csi.ControllerPublishVolumeResponse{
228237
PublishInfo: nil,
229238
}
230239

231-
disk, err := gceCS.CloudProvider.GetDisk(ctx, volKey)
240+
_, err = gceCS.CloudProvider.GetDisk(ctx, volKey)
232241
if err != nil {
233242
if gce.IsGCEError(err, "notFound") {
234243
return nil, status.Error(codes.NotFound, fmt.Sprintf("Could not find disk %v: %v", volKey.String(), err))
@@ -270,7 +279,7 @@ func (gceCS *GCEControllerServer) ControllerPublishVolume(ctx context.Context, r
270279
if err != nil {
271280
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("could not split nodeID: %v", err))
272281
}
273-
err = gceCS.CloudProvider.AttachDisk(ctx, disk, volKey, readWrite, attachableDiskTypePersistent, instanceZone, instanceName)
282+
err = gceCS.CloudProvider.AttachDisk(ctx, volKey, readWrite, attachableDiskTypePersistent, instanceZone, instanceName)
274283
if err != nil {
275284
return nil, status.Error(codes.Internal, fmt.Sprintf("unknown Attach error: %v", err))
276285
}
@@ -282,7 +291,7 @@ func (gceCS *GCEControllerServer) ControllerPublishVolume(ctx context.Context, r
282291
return nil, status.Error(codes.Internal, fmt.Sprintf("unknown WaitForAttach error: %v", err))
283292
}
284293

285-
glog.V(4).Infof("Disk %v attached to instance %v successfully", disk.GetName(), nodeID)
294+
glog.V(4).Infof("Disk %v attached to instance %v successfully", volKey.Name, nodeID)
286295
return pubVolResp, nil
287296
}
288297

@@ -326,7 +335,7 @@ func (gceCS *GCEControllerServer) ControllerUnpublishVolume(ctx context.Context,
326335
return &csi.ControllerUnpublishVolumeResponse{}, nil
327336
}
328337

329-
err = gceCS.CloudProvider.DetachDisk(ctx, volKey, instanceZone, instanceName)
338+
err = gceCS.CloudProvider.DetachDisk(ctx, deviceName, instanceZone, instanceName)
330339
if err != nil {
331340
return nil, status.Error(codes.Internal, fmt.Sprintf("unknown detach error: %v", err))
332341
}

test/e2e/tests/single_zone_e2e_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,50 @@ var _ = Describe("GCE PD CSI Driver", func() {
112112

113113
})
114114

115+
It("Should complete entire disk lifecycle with underspecified volume ID", func() {
116+
testContext := getRandomTestContext()
117+
118+
p, z, _ := testContext.Instance.GetIdentity()
119+
client := testContext.Client
120+
instance := testContext.Instance
121+
122+
// Create Disk
123+
volName := testNamePrefix + string(uuid.NewUUID())
124+
_, err := client.CreateVolume(volName, nil, defaultSizeGb,
125+
&csi.TopologyRequirement{
126+
Requisite: []*csi.Topology{
127+
{
128+
Segments: map[string]string{common.TopologyKeyZone: z},
129+
},
130+
},
131+
})
132+
Expect(err).To(BeNil(), "CreateVolume failed with error: %v", err)
133+
134+
// Validate Disk Created
135+
cloudDisk, err := computeService.Disks.Get(p, z, volName).Do()
136+
Expect(err).To(BeNil(), "Could not get disk from cloud directly")
137+
Expect(cloudDisk.Type).To(ContainSubstring(standardDiskType))
138+
Expect(cloudDisk.Status).To(Equal(readyState))
139+
Expect(cloudDisk.SizeGb).To(Equal(defaultSizeGb))
140+
Expect(cloudDisk.Name).To(Equal(volName))
141+
142+
underSpecifiedID := common.GenerateUnderspecifiedVolumeID(volName, true /* isZonal */)
143+
144+
defer func() {
145+
// Delete Disk
146+
client.DeleteVolume(underSpecifiedID)
147+
Expect(err).To(BeNil(), "DeleteVolume failed")
148+
149+
// Validate Disk Deleted
150+
_, err = computeService.Disks.Get(p, z, volName).Do()
151+
Expect(gce.IsGCEError(err, "notFound")).To(BeTrue(), "Expected disk to not be found")
152+
}()
153+
154+
// Attach Disk
155+
testAttachWriteReadDetach(underSpecifiedID, volName, instance, client, false /* readOnly */)
156+
157+
})
158+
115159
It("Should successfully create RePD in two zones in the drivers region when none are specified", func() {
116160
Expect(testContexts).ToNot(BeEmpty())
117161
testContext := getRandomTestContext()

0 commit comments

Comments
 (0)