Skip to content

Commit 69de5c7

Browse files
authored
Merge pull request #129 from davidz627/feature/migrationSupport
Support UNSPECIFIED zone and project in volume ID. Static driver name. To prep for migration
2 parents 5291315 + b7916a4 commit 69de5c7

File tree

12 files changed

+221
-70
lines changed

12 files changed

+221
-70
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/cloud-disk.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,14 @@ func (d *CloudDisk) GetSizeGb() int64 {
123123
return -1
124124
}
125125
}
126+
127+
func (d *CloudDisk) GetZone() string {
128+
switch d.Type() {
129+
case Zonal:
130+
return d.ZonalDisk.Zone
131+
case Regional:
132+
return d.RegionalDisk.Zone
133+
default:
134+
return ""
135+
}
136+
}

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

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,49 @@ type FakeCloudProvider struct {
4949

5050
var _ GCECompute = &FakeCloudProvider{}
5151

52-
func FakeCreateCloudProvider(project, zone string) (*FakeCloudProvider, error) {
53-
return &FakeCloudProvider{
52+
func FakeCreateCloudProvider(project, zone string, cloudDisks []*CloudDisk) (*FakeCloudProvider, error) {
53+
fcp := &FakeCloudProvider{
5454
project: project,
5555
zone: zone,
5656
disks: map[string]*CloudDisk{},
5757
instances: map[string]*compute.Instance{},
5858
snapshots: map[string]*compute.Snapshot{},
59-
}, nil
59+
}
60+
for _, d := range cloudDisks {
61+
fcp.disks[d.GetName()] = d
62+
}
63+
return fcp, nil
6064

6165
}
6266

67+
func (cloud *FakeCloudProvider) RepairUnderspecifiedVolumeKey(ctx context.Context, volumeKey *meta.Key) (*meta.Key, error) {
68+
switch volumeKey.Type() {
69+
case meta.Zonal:
70+
if volumeKey.Zone != common.UnspecifiedValue {
71+
return volumeKey, nil
72+
}
73+
for name, d := range cloud.disks {
74+
if name == volumeKey.Name {
75+
volumeKey.Zone = d.GetZone()
76+
return volumeKey, nil
77+
}
78+
}
79+
return nil, fmt.Errorf("Couldn't repair unspecified volume information")
80+
case meta.Regional:
81+
if volumeKey.Region != common.UnspecifiedValue {
82+
return volumeKey, nil
83+
}
84+
r, err := common.GetRegionFromZones([]string{cloud.zone})
85+
if err != nil {
86+
return nil, fmt.Errorf("failed to get region from zones: %v", err)
87+
}
88+
volumeKey.Region = r
89+
return volumeKey, nil
90+
default:
91+
return nil, fmt.Errorf("Volume key %v not zonal nor regional", volumeKey.Name)
92+
}
93+
}
94+
6395
func (cloud *FakeCloudProvider) ListZones(ctx context.Context, region string) ([]string, error) {
6496
return []string{cloud.zone, "country-region-fakesecondzone"}, nil
6597
}
@@ -195,16 +227,19 @@ func (cloud *FakeCloudProvider) InsertDisk(ctx context.Context, volKey *meta.Key
195227
}
196228

197229
func (cloud *FakeCloudProvider) DeleteDisk(ctx context.Context, volKey *meta.Key) error {
230+
if _, ok := cloud.disks[volKey.Name]; !ok {
231+
return notFoundError()
232+
}
198233
delete(cloud.disks, volKey.Name)
199234
return nil
200235
}
201236

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

205240
attachedDiskV1 := &compute.AttachedDisk{
206-
DeviceName: disk.GetName(),
207-
Kind: disk.GetKind(),
241+
DeviceName: volKey.Name,
242+
Kind: diskKind,
208243
Mode: readWrite,
209244
Source: source,
210245
Type: diskType,
@@ -217,14 +252,14 @@ func (cloud *FakeCloudProvider) AttachDisk(ctx context.Context, disk *CloudDisk,
217252
return nil
218253
}
219254

220-
func (cloud *FakeCloudProvider) DetachDisk(ctx context.Context, volKey *meta.Key, instanceZone, instanceName string) error {
255+
func (cloud *FakeCloudProvider) DetachDisk(ctx context.Context, deviceName, instanceZone, instanceName string) error {
221256
instance, ok := cloud.instances[instanceName]
222257
if !ok {
223258
return fmt.Errorf("Failed to get instance %v", instanceName)
224259
}
225260
found := -1
226261
for i, disk := range instance.Disks {
227-
if disk.DeviceName == volKey.Name {
262+
if disk.DeviceName == deviceName {
228263
found = i
229264
break
230265
}

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
}

0 commit comments

Comments
 (0)