Skip to content

Commit 2a75a27

Browse files
authored
Merge pull request #1524 from amacaskill/alphaAPI
Use GCE Alpha API to create zonal disks when Storage Pools is enabled
2 parents d823eda + 3e947e0 commit 2a75a27

File tree

5 files changed

+138
-16
lines changed

5 files changed

+138
-16
lines changed

pkg/common/parameters.go

+11-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const (
3131
ParameterKeyProvisionedThroughputOnCreate = "provisioned-throughput-on-create"
3232
ParameterAvailabilityClass = "availability-class"
3333
ParameterKeyEnableConfidentialCompute = "enable-confidential-storage"
34+
ParameterKeyStoragePools = "storage-pools"
3435

3536
// Parameters for VolumeSnapshotClass
3637
ParameterKeyStorageLocations = "storage-locations"
@@ -94,6 +95,9 @@ type DiskParameters struct {
9495
EnableConfidentialCompute bool
9596
// Default: false
9697
ForceAttach bool
98+
// Values: {[]string}
99+
// Default: ""
100+
StoragePools []string
97101
}
98102

99103
// SnapshotParameters contains normalized and defaulted parameters for snapshots
@@ -183,12 +187,17 @@ func ExtractAndDefaultParameters(parameters map[string]string, driverName string
183187
if paramEnableConfidentialCompute {
184188
// DiskEncryptionKmsKey is needed to enable confidentialStorage
185189
if val, ok := parameters[ParameterKeyDiskEncryptionKmsKey]; !ok || !isValidDiskEncryptionKmsKey(val) {
186-
return p, fmt.Errorf("Valid %v is required to enbale ConfidentialStorage", ParameterKeyDiskEncryptionKmsKey)
190+
return p, fmt.Errorf("Valid %v is required to enable ConfidentialStorage", ParameterKeyDiskEncryptionKmsKey)
187191
}
188192
}
189193

190194
p.EnableConfidentialCompute = paramEnableConfidentialCompute
191-
195+
case ParameterKeyStoragePools:
196+
storagePools, err := ParseStoragePools(v)
197+
if err != nil {
198+
return p, fmt.Errorf("parameters contain invalid value for %s parameter: %w", ParameterKeyStoragePools, err)
199+
}
200+
p.StoragePools = storagePools
192201
default:
193202
return p, fmt.Errorf("parameters contains invalid option %q", k)
194203
}

pkg/common/utils.go

+13
Original file line numberDiff line numberDiff line change
@@ -392,3 +392,16 @@ func isValidDiskEncryptionKmsKey(DiskEncryptionKmsKey string) bool {
392392
kmsKeyPattern := regexp.MustCompile("projects/[^/]+/locations/([^/]+)/keyRings/[^/]+/cryptoKeys/[^/]+")
393393
return kmsKeyPattern.MatchString(DiskEncryptionKmsKey)
394394
}
395+
396+
// TODO(amacaskill): Implement this function.
397+
// ParseStoragePools returns an error if none of the given storagePools
398+
// (delimited by a comma) are in the format
399+
// projects/project/zones/zone/storagePools/storagePool.
400+
func ParseStoragePools(storagePools string) ([]string, error) {
401+
return nil, status.Errorf(codes.Unimplemented, "")
402+
}
403+
404+
// TODO(amacaskill): Implement this function.
405+
func StoragePoolInZone(storagePools []string, zone string) string {
406+
return ""
407+
}

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

+10-2
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ import (
1818
"strings"
1919

2020
"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta"
21+
computealpha "google.golang.org/api/compute/v0.alpha"
2122
computebeta "google.golang.org/api/compute/v0.beta"
2223
computev1 "google.golang.org/api/compute/v1"
2324
)
2425

2526
type CloudDisk struct {
26-
disk *computev1.Disk
27-
betaDisk *computebeta.Disk
27+
disk *computev1.Disk
28+
betaDisk *computebeta.Disk
29+
alphaDisk *computealpha.Disk
2830
}
2931

3032
type CloudDiskType string
@@ -41,6 +43,12 @@ func CloudDiskFromBeta(disk *computebeta.Disk) *CloudDisk {
4143
}
4244
}
4345

46+
func CloudDiskFromAlpha(disk *computealpha.Disk) *CloudDisk {
47+
return &CloudDisk{
48+
alphaDisk: disk,
49+
}
50+
}
51+
4452
func (d *CloudDisk) LocationType() meta.KeyType {
4553
var zone, region string
4654
switch {

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

+68-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta"
2626
csi "github.com/container-storage-interface/spec/lib/go/csi"
27+
computealpha "google.golang.org/api/compute/v0.alpha"
2728
computebeta "google.golang.org/api/compute/v0.beta"
2829
computev1 "google.golang.org/api/compute/v1"
2930
"google.golang.org/grpc/codes"
@@ -51,8 +52,10 @@ type GCEAPIVersion string
5152
const (
5253
// V1 key type
5354
GCEAPIVersionV1 GCEAPIVersion = "v1"
54-
// Alpha key type
55+
// Beta key type
5556
GCEAPIVersionBeta GCEAPIVersion = "beta"
57+
// Alpha key type
58+
GCEAPIVersionAlpha GCEAPIVersion = "alpha"
5659
)
5760

5861
// AttachDiskBackoff is backoff used to wait for AttachDisk to complete.
@@ -266,13 +269,16 @@ func (cloud *CloudProvider) GetDisk(ctx context.Context, project string, key *me
266269
if gceAPIVersion == GCEAPIVersionBeta {
267270
disk, err := cloud.getZonalBetaDiskOrError(ctx, project, key.Zone, key.Name)
268271
return CloudDiskFromBeta(disk), err
272+
} else if gceAPIVersion == GCEAPIVersionAlpha {
273+
disk, err := cloud.getZonalAlphaDiskOrError(ctx, project, key.Zone, key.Name)
274+
return CloudDiskFromAlpha(disk), err
269275
} else {
270276
disk, err := cloud.getZonalDiskOrError(ctx, project, key.Zone, key.Name)
271277
return CloudDiskFromV1(disk), err
272278
}
273279
case meta.Regional:
274280
if gceAPIVersion == GCEAPIVersionBeta {
275-
disk, err := cloud.getRegionalAlphaDiskOrError(ctx, project, key.Region, key.Name)
281+
disk, err := cloud.getRegionalBetaDiskOrError(ctx, project, key.Region, key.Name)
276282
return CloudDiskFromBeta(disk), err
277283
} else {
278284
disk, err := cloud.getRegionalDiskOrError(ctx, project, key.Region, key.Name)
@@ -299,6 +305,14 @@ func (cloud *CloudProvider) getRegionalDiskOrError(ctx context.Context, project,
299305
return disk, nil
300306
}
301307

308+
func (cloud *CloudProvider) getZonalAlphaDiskOrError(ctx context.Context, project, volumeZone, volumeName string) (*computealpha.Disk, error) {
309+
disk, err := cloud.alphaService.Disks.Get(project, volumeZone, volumeName).Context(ctx).Do()
310+
if err != nil {
311+
return nil, err
312+
}
313+
return disk, nil
314+
}
315+
302316
func (cloud *CloudProvider) getZonalBetaDiskOrError(ctx context.Context, project, volumeZone, volumeName string) (*computebeta.Disk, error) {
303317
disk, err := cloud.betaService.Disks.Get(project, volumeZone, volumeName).Context(ctx).Do()
304318
if err != nil {
@@ -307,7 +321,7 @@ func (cloud *CloudProvider) getZonalBetaDiskOrError(ctx context.Context, project
307321
return disk, nil
308322
}
309323

310-
func (cloud *CloudProvider) getRegionalAlphaDiskOrError(ctx context.Context, project, volumeRegion, volumeName string) (*computebeta.Disk, error) {
324+
func (cloud *CloudProvider) getRegionalBetaDiskOrError(ctx context.Context, project, volumeRegion, volumeName string) (*computebeta.Disk, error) {
311325
disk, err := cloud.betaService.RegionDisks.Get(project, volumeRegion, volumeName).Context(ctx).Do()
312326
if err != nil {
313327
return nil, err
@@ -440,6 +454,37 @@ func convertV1DiskToBetaDisk(v1Disk *computev1.Disk, provisionedThroughputOnCrea
440454
return betaDisk
441455
}
442456

457+
func convertV1DiskToAlphaDisk(v1Disk *computev1.Disk, provisionedThroughputOnCreate int64, storagePool string) *computealpha.Disk {
458+
// Note: this is an incomplete list. It only includes the fields we use for disk creation.
459+
alphaDisk := &computealpha.Disk{
460+
Name: v1Disk.Name,
461+
SizeGb: v1Disk.SizeGb,
462+
Description: v1Disk.Description,
463+
Type: v1Disk.Type,
464+
SourceSnapshot: v1Disk.SourceSnapshot,
465+
SourceImage: v1Disk.SourceImage,
466+
SourceImageId: v1Disk.SourceImageId,
467+
SourceSnapshotId: v1Disk.SourceSnapshotId,
468+
SourceDisk: v1Disk.SourceDisk,
469+
ReplicaZones: v1Disk.ReplicaZones,
470+
Zone: v1Disk.Zone,
471+
Region: v1Disk.Region,
472+
Status: v1Disk.Status,
473+
SelfLink: v1Disk.SelfLink,
474+
}
475+
if v1Disk.ProvisionedIops > 0 {
476+
alphaDisk.ProvisionedIops = v1Disk.ProvisionedIops
477+
}
478+
if provisionedThroughputOnCreate > 0 {
479+
alphaDisk.ProvisionedThroughput = provisionedThroughputOnCreate
480+
}
481+
if storagePool != "" {
482+
alphaDisk.StoragePool = storagePool
483+
}
484+
485+
return alphaDisk
486+
}
487+
443488
func (cloud *CloudProvider) insertRegionalDisk(
444489
ctx context.Context,
445490
project string,
@@ -572,6 +617,10 @@ func (cloud *CloudProvider) insertZonalDisk(
572617
if multiWriter || containsBetaDiskType(hyperdiskTypes, params.DiskType) {
573618
gceAPIVersion = GCEAPIVersionBeta
574619
}
620+
storagePoolsEnabled := params.StoragePools != nil
621+
if storagePoolsEnabled {
622+
gceAPIVersion = GCEAPIVersionAlpha
623+
}
575624

576625
diskToCreate := &computev1.Disk{
577626
Name: volKey.Name,
@@ -618,6 +667,22 @@ func (cloud *CloudProvider) insertZonalDisk(
618667
if insertOp != nil {
619668
opName = insertOp.Name
620669
}
670+
} else if gceAPIVersion == GCEAPIVersionAlpha {
671+
var insertOp *computealpha.Operation
672+
var storagePool string
673+
if storagePoolsEnabled {
674+
storagePool = common.StoragePoolInZone(params.StoragePools, diskToCreate.Zone)
675+
if storagePool == "" {
676+
return status.Errorf(codes.InvalidArgument, "cannot create disk in zone %q: no Storage Pools exist in zone", diskToCreate.Zone)
677+
}
678+
}
679+
alphaDiskToCreate := convertV1DiskToAlphaDisk(diskToCreate, params.ProvisionedThroughputOnCreate, storagePool)
680+
alphaDiskToCreate.MultiWriter = multiWriter
681+
alphaDiskToCreate.EnableConfidentialCompute = params.EnableConfidentialCompute
682+
insertOp, err = cloud.alphaService.Disks.Insert(project, volKey.Zone, alphaDiskToCreate).Context(ctx).Do()
683+
if insertOp != nil {
684+
opName = insertOp.Name
685+
}
621686
} else {
622687
var insertOp *computev1.Operation
623688
insertOp, err = cloud.service.Disks.Insert(project, volKey.Zone, diskToCreate).Context(ctx).Do()

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

+36-9
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929

3030
"cloud.google.com/go/compute/metadata"
3131
"golang.org/x/oauth2"
32+
computealpha "google.golang.org/api/compute/v0.alpha"
3233
computebeta "google.golang.org/api/compute/v0.beta"
3334
"google.golang.org/api/compute/v1"
3435
"google.golang.org/api/googleapi"
@@ -49,10 +50,11 @@ const (
4950
)
5051

5152
type CloudProvider struct {
52-
service *compute.Service
53-
betaService *computebeta.Service
54-
project string
55-
zone string
53+
service *compute.Service
54+
betaService *computebeta.Service
55+
alphaService *computealpha.Service
56+
project string
57+
zone string
5658

5759
zonesCache map[string][]string
5860
}
@@ -95,17 +97,23 @@ func CreateCloudProvider(ctx context.Context, vendorVersion string, configPath s
9597
return nil, err
9698
}
9799

100+
alphasvc, err := createAlphaCloudService(ctx, vendorVersion, tokenSource, computeEndpoint)
101+
if err != nil {
102+
return nil, err
103+
}
104+
98105
project, zone, err := getProjectAndZone(configFile)
99106
if err != nil {
100107
return nil, fmt.Errorf("Failed getting Project and Zone: %w", err)
101108
}
102109

103110
return &CloudProvider{
104-
service: svc,
105-
betaService: betasvc,
106-
project: project,
107-
zone: zone,
108-
zonesCache: make(map[string]([]string)),
111+
service: svc,
112+
betaService: betasvc,
113+
alphaService: alphasvc,
114+
project: project,
115+
zone: zone,
116+
zonesCache: make(map[string]([]string)),
109117
}, nil
110118

111119
}
@@ -175,6 +183,25 @@ func createBetaCloudService(ctx context.Context, vendorVersion string, tokenSour
175183
return service, nil
176184
}
177185

186+
func createAlphaCloudService(ctx context.Context, vendorVersion string, tokenSource oauth2.TokenSource, computeEndpoint string) (*computealpha.Service, error) {
187+
client, err := newOauthClient(ctx, tokenSource)
188+
if err != nil {
189+
return nil, err
190+
}
191+
192+
computeOpts := []option.ClientOption{option.WithHTTPClient(client)}
193+
if computeEndpoint != "" {
194+
alphaEndpoint := fmt.Sprintf("%s/compute/alpha/", computeEndpoint)
195+
computeOpts = append(computeOpts, option.WithEndpoint(alphaEndpoint))
196+
}
197+
service, err := computealpha.NewService(ctx, computeOpts...)
198+
if err != nil {
199+
return nil, err
200+
}
201+
service.UserAgent = fmt.Sprintf("GCE CSI Driver/%s (%s %s)", vendorVersion, runtime.GOOS, runtime.GOARCH)
202+
return service, nil
203+
}
204+
178205
func createCloudService(ctx context.Context, vendorVersion string, tokenSource oauth2.TokenSource, computeEndpoint string) (*compute.Service, error) {
179206
svc, err := createCloudServiceWithDefaultServiceAccount(ctx, vendorVersion, tokenSource, computeEndpoint)
180207
return svc, err

0 commit comments

Comments
 (0)