Skip to content

Commit 8e7c69a

Browse files
committed
Set MaxVolumesPerNode in NodeGetInfo
Add unit test add e2e test case
1 parent 5d62c77 commit 8e7c69a

File tree

5 files changed

+144
-13
lines changed

5 files changed

+144
-13
lines changed

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

+10
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ const (
2626
FakeProject = "test-project"
2727
)
2828

29+
var FakeMachineType = "n1-standard-1"
30+
2931
func NewFakeService() MetadataService {
3032
return &fakeServiceManager{}
3133
}
@@ -41,3 +43,11 @@ func (manager *fakeServiceManager) GetProject() string {
4143
func (manager *fakeServiceManager) GetName() string {
4244
return "test-name"
4345
}
46+
47+
func (manager *fakeServiceManager) GetMachineType() string {
48+
return FakeMachineType
49+
}
50+
51+
func SetMachineType(s string) {
52+
FakeMachineType = s
53+
}

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

+21-6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package metadata
1818

1919
import (
2020
"fmt"
21+
"strings"
2122

2223
"cloud.google.com/go/compute/metadata"
2324
)
@@ -28,13 +29,15 @@ type MetadataService interface {
2829
GetZone() string
2930
GetProject() string
3031
GetName() string
32+
GetMachineType() string
3133
}
3234

3335
type metadataServiceManager struct {
3436
// Current zone the driver is running in
35-
zone string
36-
project string
37-
name string
37+
zone string
38+
project string
39+
name string
40+
machineType string
3841
}
3942

4043
var _ MetadataService = &metadataServiceManager{}
@@ -52,11 +55,19 @@ func NewMetadataService() (MetadataService, error) {
5255
if err != nil {
5356
return nil, fmt.Errorf("failed to get instance name: %v", err)
5457
}
58+
fullMachineType, err := metadata.Get("instance/machine-type")
59+
if err != nil {
60+
return nil, fmt.Errorf("failed to get machine-type: %v", err)
61+
}
62+
// Response format: "projects/[NUMERIC_PROJECT_ID]/machineTypes/[MACHINE_TYPE]"
63+
splits := strings.Split(fullMachineType, "/")
64+
machineType := splits[len(splits)-1]
5565

5666
return &metadataServiceManager{
57-
project: projectID,
58-
zone: zone,
59-
name: name,
67+
project: projectID,
68+
zone: zone,
69+
name: name,
70+
machineType: machineType,
6071
}, nil
6172
}
6273

@@ -71,3 +82,7 @@ func (manager *metadataServiceManager) GetProject() string {
7182
func (manager *metadataServiceManager) GetName() string {
7283
return manager.name
7384
}
85+
86+
func (manager *metadataServiceManager) GetMachineType() string {
87+
return manager.machineType
88+
}

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

+26-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package gceGCEDriver
1717
import (
1818
"fmt"
1919
"os"
20+
"strings"
2021
"sync"
2122

2223
csi "github.com/container-storage-interface/spec/lib/go/csi"
@@ -42,6 +43,14 @@ type GCENodeServer struct {
4243

4344
var _ csi.NodeServer = &GCENodeServer{}
4445

46+
// The constants are used to map from the machine type to the limit of
47+
// persistent disks that can be attached to an instance. Please refer to gcloud doc
48+
// https://cloud.google.com/compute/docs/disks/#pdnumberlimits
49+
const (
50+
volumeLimit16 int64 = 16
51+
volumeLimit128 int64 = 128
52+
)
53+
4554
func (ns *GCENodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) {
4655
ns.mux.Lock()
4756
defer ns.mux.Unlock()
@@ -284,15 +293,17 @@ func (ns *GCENodeServer) NodeGetInfo(ctx context.Context, req *csi.NodeGetInfoRe
284293

285294
nodeID := common.CreateNodeID(ns.MetadataService.GetProject(), ns.MetadataService.GetZone(), ns.MetadataService.GetName())
286295

296+
volumeLimits, err := ns.GetVolumeLimits()
297+
287298
resp := &csi.NodeGetInfoResponse{
288299
NodeId: nodeID,
289300
// TODO(#19): Set MaxVolumesPerNode based on Node Type
290301
// Default of 0 means that CO Decides how many nodes can be published
291302
// Can get from metadata server "machine-type"
292-
MaxVolumesPerNode: 0,
303+
MaxVolumesPerNode: volumeLimits,
293304
AccessibleTopology: top,
294305
}
295-
return resp, nil
306+
return resp, err
296307
}
297308

298309
func (ns *GCENodeServer) NodeGetVolumeStats(ctx context.Context, req *csi.NodeGetVolumeStatsRequest) (*csi.NodeGetVolumeStatsResponse, error) {
@@ -302,3 +313,16 @@ func (ns *GCENodeServer) NodeGetVolumeStats(ctx context.Context, req *csi.NodeGe
302313
func (ns *GCENodeServer) NodeExpandVolume(ctx context.Context, req *csi.NodeExpandVolumeRequest) (*csi.NodeExpandVolumeResponse, error) {
303314
return nil, status.Error(codes.Unimplemented, fmt.Sprintf("NodeExpandVolume is not yet implemented"))
304315
}
316+
317+
func (ns *GCENodeServer) GetVolumeLimits() (int64, error) {
318+
var volumeLimits int64
319+
320+
// Machine-type format: n1-type-CPUS or custom-CPUS-RAM or f1/g1-type
321+
machineType := ns.MetadataService.GetMachineType()
322+
if strings.HasPrefix(machineType, "n1-") || strings.HasPrefix(machineType, "custom-") {
323+
volumeLimits = volumeLimit128
324+
} else {
325+
volumeLimits = volumeLimit16
326+
}
327+
return volumeLimits, nil
328+
}

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

+73
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,76 @@ limitations under the License.
1313
*/
1414

1515
package gceGCEDriver
16+
17+
import (
18+
"testing"
19+
20+
csi "github.com/container-storage-interface/spec/lib/go/csi"
21+
"golang.org/x/net/context"
22+
metadataservice "sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/gce-cloud-provider/metadata"
23+
mountmanager "sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/mount-manager"
24+
)
25+
26+
func getTestGCEDriver(t *testing.T) *GCEDriver {
27+
gceDriver := GetGCEDriver()
28+
err := gceDriver.SetupGCEDriver(nil, mountmanager.NewFakeSafeMounter(), mountmanager.NewFakeDeviceUtils(), metadataservice.NewFakeService(), driver, "test-vendor")
29+
if err != nil {
30+
t.Fatalf("Failed to setup GCE Driver: %v", err)
31+
}
32+
return gceDriver
33+
}
34+
35+
func TestNodeGetVolumeLimits(t *testing.T) {
36+
37+
gceDriver := getTestGCEDriver(t)
38+
ns := gceDriver.ns
39+
req := &csi.NodeGetInfoRequest{}
40+
41+
testCases := []struct {
42+
name string
43+
machineType string
44+
expVolumeLimit int64
45+
}{
46+
{
47+
name: "Predifined standard machine",
48+
machineType: "n1-standard-1",
49+
expVolumeLimit: volumeLimit128,
50+
},
51+
{
52+
name: "Predifined micro machine",
53+
machineType: "f1-micro",
54+
expVolumeLimit: volumeLimit16,
55+
},
56+
{
57+
name: "Predifined small machine",
58+
machineType: "g1-small",
59+
expVolumeLimit: volumeLimit16,
60+
},
61+
{
62+
name: "Custom machine with 1GiB Mem",
63+
machineType: "custom-1-1024",
64+
expVolumeLimit: volumeLimit128,
65+
},
66+
{
67+
name: "Custom machine with 4GiB Mem",
68+
machineType: "custom-2-4096",
69+
expVolumeLimit: volumeLimit128,
70+
},
71+
}
72+
73+
for _, tc := range testCases {
74+
t.Logf("Test case: %s", tc.name)
75+
metadataservice.SetMachineType(tc.machineType)
76+
res, err := ns.NodeGetInfo(context.Background(), req)
77+
if err != nil {
78+
t.Fatalf("Failed to get node info: %v", err)
79+
} else {
80+
volumeLimit := res.GetMaxVolumesPerNode()
81+
if volumeLimit != tc.expVolumeLimit {
82+
t.Fatalf("Expected volume limit: %v, got %v, for machine-type: %v",
83+
tc.expVolumeLimit, volumeLimit, tc.machineType)
84+
}
85+
t.Logf("Get node info: %v", res)
86+
}
87+
}
88+
}

test/e2e/tests/single_zone_e2e_test.go

+14-5
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,24 @@ import (
3737
const (
3838
testNamePrefix = "gcepd-csi-e2e-"
3939

40-
defaultSizeGb int64 = 5
41-
defaultRepdSizeGb int64 = 200
42-
readyState = "READY"
43-
standardDiskType = "pd-standard"
44-
ssdDiskType = "pd-ssd"
40+
defaultSizeGb int64 = 5
41+
defaultRepdSizeGb int64 = 200
42+
readyState = "READY"
43+
standardDiskType = "pd-standard"
44+
ssdDiskType = "pd-ssd"
45+
defaultVolumeLimit int64 = 128
4546
)
4647

4748
var _ = Describe("GCE PD CSI Driver", func() {
4849

50+
It("Should get reasonable volume limits from nodes with NodeGetInfo", func() {
51+
testContext := getRandomTestContext()
52+
resp, err := testContext.Client.NodeGetInfo()
53+
Expect(err).To(BeNil())
54+
volumeLimit := resp.GetMaxVolumesPerNode()
55+
Expect(volumeLimit).To(Equal(defaultVolumeLimit))
56+
})
57+
4958
It("Should create->attach->stage->mount volume and check if it is writable, then unmount->unstage->detach->delete and check disk is deleted", func() {
5059
testContext := getRandomTestContext()
5160

0 commit comments

Comments
 (0)