From 0dd7972bd8856457855f781369e8ff98a2d7fb26 Mon Sep 17 00:00:00 2001 From: DeepikaDixit Date: Wed, 13 Mar 2019 19:41:15 -0700 Subject: [PATCH] [K10-1939] Add GCP multi-zone support (#5186) * Add GCP multi-zone support * Fix imports --- pkg/blockstorage/gcepd/gcepd.go | 132 +++++++++++++++++++++++++++- pkg/blockstorage/gcepd/zone_test.go | 64 ++++++++++++++ 2 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 pkg/blockstorage/gcepd/zone_test.go diff --git a/pkg/blockstorage/gcepd/gcepd.go b/pkg/blockstorage/gcepd/gcepd.go index f838c3c46e..e3986a3d8b 100644 --- a/pkg/blockstorage/gcepd/gcepd.go +++ b/pkg/blockstorage/gcepd/gcepd.go @@ -17,10 +17,12 @@ import ( "github.com/kanisterio/kanister/pkg/blockstorage" ktags "github.com/kanisterio/kanister/pkg/blockstorage/tags" + "github.com/kanisterio/kanister/pkg/blockstorage/zone" "github.com/kanisterio/kanister/pkg/poll" ) var _ blockstorage.Provider = (*gpdStorage)(nil) +var _ zone.Mapper = (*gpdStorage)(nil) type gpdStorage struct { service *compute.Service @@ -255,7 +257,10 @@ func (s *gpdStorage) VolumeCreateFromSnapshot(ctx context.Context, snapshot bloc tags[tag.Key] = tag.Value } } - + zone, err := zone.FromSourceRegionZone(ctx, s, snapshot.Region, snapshot.Volume.Az) + if err != nil { + return nil, err + } createDisk := &compute.Disk{ Name: fmt.Sprintf(volumeNameFmt, uuid.NewV1().String()), SizeGb: snapshot.Volume.Size, @@ -264,15 +269,15 @@ func (s *gpdStorage) VolumeCreateFromSnapshot(ctx context.Context, snapshot bloc SourceSnapshot: snap.SelfLink, } - resp, err := s.service.Disks.Insert(s.project, snapshot.Volume.Az, createDisk).Context(ctx).Do() + resp, err := s.service.Disks.Insert(s.project, zone, createDisk).Context(ctx).Do() if err != nil { return nil, err } - if err := s.waitOnOperation(ctx, resp, snapshot.Volume.Az); err != nil { + if err := s.waitOnOperation(ctx, resp, zone); err != nil { return nil, err } - return s.VolumeGet(ctx, createDisk.Name, snapshot.Volume.Az) + return s.VolumeGet(ctx, createDisk.Name, zone) } func (s *gpdStorage) SetTags(ctx context.Context, resource interface{}, tags map[string]string) error { @@ -386,3 +391,122 @@ func isNotFoundError(err error) bool { ae, ok := err.(*googleapi.Error) return ok && ae.Code == http.StatusNotFound } + +func (s *gpdStorage) FromRegion(ctx context.Context, region string) ([]string, error) { + return staticRegionToZones(region) +} + +func staticRegionToZones(region string) ([]string, error) { + switch region { + case "asia-east1": + return []string{ + "asia-east1a", + "asia-east1b", + "asia-east1c", + }, nil + case "asia-east2": + return []string{ + "asia-east2a", + "asia-east2b", + "asia-east2c", + }, nil + case "asia-northeast1": + return []string{ + "asia-northeast1a", + "asia-northeast1b", + "asia-northeast1c", + }, nil + case "asia-south1": + return []string{ + "asia-south1a", + "asia-south1b", + "asia-south1c", + }, nil + case "asia-southeast1": + return []string{ + "asia-southeast1a", + "asia-southeast1b", + "asia-southeast1c", + }, nil + case "australia-southeast1": + return []string{ + "australia-southeast1a", + "australia-southeast1b", + "australia-southeast1c", + }, nil + case "europe-north1": + return []string{ + "europe-north1a", + "europe-north1b", + "europe-north1c", + }, nil + case "europe-west1": + return []string{ + "europe-west1b", + "europe-west1c", + "europe-west1d", + }, nil + case "europe-west2": + return []string{ + "europe-west2a", + "europe-west2b", + "europe-west2c", + }, nil + case "europe-west3": + return []string{ + "europe-west3a", + "europe-west3b", + "europe-west3c", + }, nil + case "europe-west4": + return []string{ + "europe-west4a", + "europe-west4b", + "europe-west4c", + }, nil + case "northamerica-northeast1": + return []string{ + "northamerica-northeast1a", + "northamerica-northeast1b", + "northamerica-northeast1c", + }, nil + case "southamerica-east1": + return []string{ + "southamerica-east1", + "southamerica-east1b", + "southamerica-east1c", + }, nil + case "us-central1": + return []string{ + "us-central1a", + "us-central1b", + "us-central1c", + "us-central1f", + }, nil + case "us-east1": + return []string{ + "us-east1b", + "us-east1c", + "us-east1d", + }, nil + case "us-east4": + return []string{ + "us-east4a", + "us-east4b", + "us-east4c", + }, nil + case "us-west1": + return []string{ + "us-west1a", + "us-west1b", + "us-west1c", + }, nil + case "us-west2": + return []string{ + "us-west2a", + "us-west2b", + "us-west2c", + }, nil + } + return nil, errors.New("cannot get availability zones for region") +} diff --git a/pkg/blockstorage/gcepd/zone_test.go b/pkg/blockstorage/gcepd/zone_test.go new file mode 100644 index 0000000000..1357acf8cf --- /dev/null +++ b/pkg/blockstorage/gcepd/zone_test.go @@ -0,0 +1,64 @@ +package gcepd + +import ( + "context" + "os" + + . "gopkg.in/check.v1" + + "github.com/kanisterio/kanister/pkg/blockstorage" + "github.com/kanisterio/kanister/pkg/blockstorage/zone" +) + +type ZoneSuite struct{} + +var _ = Suite(&ZoneSuite{}) + +func (s ZoneSuite) TestZoneWithUnknownNodeZones(c *C) { + ctx := context.Background() + for _, tc := range []struct { + region string + in string + out string + }{ + { + region: "us-west2", + in: "us-west2a", + out: "us-west2a", + }, + { + region: "us-west2", + in: "us-east1f", + out: "us-west2a", + }, + { + region: "us-west2", + in: "us-east2b", + out: "us-west2b", + }, + { + region: "us-west2", + in: "us-east1f", + out: "us-west2a", + }, + } { + config := getConfigForTest(c) + provider, err := NewProvider(config) + z, err := zone.WithUnknownNodeZones(ctx, provider.(zone.Mapper), tc.region, tc.in) + c.Assert(err, IsNil) + c.Assert(z, Not(Equals), "") + if tc.out != "" { + c.Assert(z, Equals, tc.out) + } + } +} + +func getConfigForTest(c *C) map[string]string { + config := make(map[string]string) + creds, ok := os.LookupEnv(blockstorage.GoogleCloudCreds) + if !ok { + c.Skip("The necessary env variable GOOGLE_APPLICATION_CREDENTIALS is not set.") + } + config[blockstorage.GoogleCloudCreds] = creds + return config +}