Skip to content

Commit

Permalink
Add NFS support for PVC metrics in controller (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
rensyct committed Nov 16, 2021
1 parent 6dc318f commit 3dd023b
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 21 deletions.
2 changes: 2 additions & 0 deletions helm/csi-unity/templates/controller.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ spec:
- "--leader-election"
- "--http-endpoint=:8080"
- "--enable-node-watcher=true"
- "--monitor-interval={{ .Values.volumeHealthMonitorInterval | default "60s" }}"
- "--timeout=180s"
env:
- name: ADDRESS
value: /var/run/csi/csi.sock
Expand Down
6 changes: 6 additions & 0 deletions helm/csi-unity/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,9 @@ maxUnityVolumesPerNode: 0
# Default value: ""
# Examples : "tenant2" , "tenant3"
tenantName: ""

# healthMonitorInterval: Interval of monitoring volume health condition
# Allowed values: Number followed by unit (s,m,h)
# Examples: 60s, 5m, 1h
# Default value: 60s
volumeHealthMonitorInterval: 60s
107 changes: 90 additions & 17 deletions service/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -1788,33 +1788,106 @@ func (s *service) ControllerGetVolume(ctx context.Context,
volumeAPI := gounity.NewVolume(unity)
vol, err := volumeAPI.FindVolumeById(ctx, volID)
if err != nil {
if err == gounity.VolumeNotFoundError {
if err != gounity.VolumeNotFoundError {
return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Find volume failed with error: %v", err))
}
abnormal = true
message = "Volume not found"
}

if !abnormal {
content := vol.VolumeContent
if len(content.HostAccessResponse) > 0 {
for _, hostaccess := range content.HostAccessResponse {
hostcontent := hostaccess.HostContent
hosts = append(hosts, hostcontent.ID)
}
}

// check if volume is in ok state
if content.Health.Value != 5 {
abnormal = true
message = "volume not found"
message = "Volume is not in ok state"
}
return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Find volume failed with error: %v", err))
abnormal = false
message = "Volume is in ok state"
}
} else {
fileAPI := gounity.NewFilesystem(unity)
isSnapshot := false
filesystem, err := fileAPI.FindFilesystemById(ctx, volID)

content := vol.VolumeContent
if len(content.HostAccessResponse) > 0 {
for _, hostaccess := range content.HostAccessResponse {
hostcontent := hostaccess.HostContent
hosts = append(hosts, hostcontent.ID)
if err != nil {
var snapResp *types.Snapshot
snapshotAPI := gounity.NewSnapshot(unity)
snapResp, err = snapshotAPI.FindSnapshotById(ctx, volID)
if err != nil {
if err != gounity.SnapshotNotFoundError {
return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Find filesystem: %s failed with error: %v", volID, err))
}
abnormal = true
message = "Filesystem not found"
}

isSnapshot = true
if !abnormal {
filesystem, err = s.getFilesystemByResourceID(ctx, snapResp.SnapshotContent.StorageResource.Id, arrayID)
if err != nil {
return nil, err
}
}
}

// check if volume is in ready state
if content.Health.Value != 5 {
abnormal = true
message = "Volume is not in ok state"
if !abnormal {
nfsShareID := ""
for _, nfsShare := range filesystem.FileContent.NFSShare {
if isSnapshot {
if nfsShare.Path == NFSShareLocalPath && nfsShare.ParentSnap.Id == volID {
nfsShareID = nfsShare.Id
}
} else {
if nfsShare.Path == NFSShareLocalPath && nfsShare.ParentSnap.Id == "" {
nfsShareID = nfsShare.Id
}
}
}

if nfsShareID != "" {
nfsShareResp, err := fileAPI.FindNFSShareById(ctx, nfsShareID)
if err != nil {
return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Find NFS Share: %s failed. Error: %v", nfsShareID, err))
}
readOnlyHosts := nfsShareResp.NFSShareContent.ReadOnlyHosts
readWriteHosts := nfsShareResp.NFSShareContent.ReadWriteHosts
readOnlyRootHosts := nfsShareResp.NFSShareContent.ReadOnlyRootAccessHosts
readWriteRootHosts := nfsShareResp.NFSShareContent.RootAccessHosts

for _, host := range readOnlyHosts {
hosts = append(hosts, host.ID)
}
for _, host := range readWriteHosts {
hosts = append(hosts, host.ID)
}
for _, host := range readOnlyRootHosts {
hosts = append(hosts, host.ID)
}
for _, host := range readWriteRootHosts {
hosts = append(hosts, host.ID)
}
}
}

abnormal = false
message = "Volume is in ok state"
} else {
abnormal = false
message = "FileSystem is in ok state"
// check if filesystem is in ok state
if !abnormal {
if filesystem.FileContent.Health.Value != 5 {
abnormal = true
message = "Filesystem is not in ok state"
}
abnormal = false
message = "Filesystem is in ok state"
}
}

resp := &csi.ControllerGetVolumeResponse{
Volume: &csi.Volume{
VolumeId: req.GetVolumeId(),
Expand Down
8 changes: 4 additions & 4 deletions service/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -935,7 +935,7 @@ func (s *service) NodeGetVolumeStats(
resp := &csi.NodeGetVolumeStatsResponse{
VolumeCondition: &csi.VolumeCondition{
Abnormal: true,
Message: "filesystem not found",
Message: "Filesystem not found",
},
}
return resp, nil
Expand All @@ -950,7 +950,7 @@ func (s *service) NodeGetVolumeStats(
resp := &csi.NodeGetVolumeStatsResponse{
VolumeCondition: &csi.VolumeCondition{
Abnormal: true,
Message: "volume not found",
Message: "Volume not found",
},
}
return resp, nil
Expand All @@ -964,7 +964,7 @@ func (s *service) NodeGetVolumeStats(
resp := &csi.NodeGetVolumeStatsResponse{
VolumeCondition: &csi.VolumeCondition{
Abnormal: true,
Message: "volume path not mounted",
Message: "Volume path is not mounted",
},
}
return resp, nil
Expand All @@ -976,7 +976,7 @@ func (s *service) NodeGetVolumeStats(
resp := &csi.NodeGetVolumeStatsResponse{
VolumeCondition: &csi.VolumeCondition{
Abnormal: true,
Message: "volume path not accessible",
Message: "Volume path is not accessible",
},
}
return resp, nil
Expand Down
16 changes: 16 additions & 0 deletions test/unit-test/features/unit.feature
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,22 @@ Feature: CSI interface
When I call Controller Expand Volume "2" with volume ""
Then the error message should contain "required"

Scenario: Controller get volume for FC protocol
Given a CSI service
And a basic block volume request name "gdtest-vol26" arrayId "Array1-Id" protocol "FC"
When I call CreateVolume
Then there are no errors
When I call Controller Get Volume "gdtest-vol26"
Then there are no errors

Scenario: Controller get volume for NFS protocol
Given a CSI service
And a basic block volume request name "gdtest-vol26" arrayId "Array1-Id" protocol "NFS"
When I call CreateVolume
Then there are no errors
When I call Controller Get Volume "gdtest-vol26"
Then there are no errors

Scenario: Node stage, publish, unpublish and unstage volume
Given a CSI service
And a basic block volume request name "gdtest-vol30" arrayId "Array1-Id" protocol "FC" size "5"
Expand Down
20 changes: 20 additions & 0 deletions test/unit-test/unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type feature struct {
validateVolumeCapabilitiesRequest *csi.ValidateVolumeCapabilitiesRequest
controllerGetCapabilitiesRequest *csi.ControllerGetCapabilitiesRequest
controllerExpandVolumeRequest *csi.ControllerExpandVolumeRequest
controllerGetVolumeRequest *csi.ControllerGetVolumeRequest
nodePublishVolumeRequest *csi.NodePublishVolumeRequest
nodeUnpublishVolumeRequest *csi.NodeUnpublishVolumeRequest
nodeStageVolumeRequest *csi.NodeStageVolumeRequest
Expand Down Expand Up @@ -798,6 +799,25 @@ func (f *feature) iCallControllerExpandVolumeWithVolume(new_size int, volID stri
return nil
}

//iCallControllerGetVolume - Test case for controller get volume with volume id as parameter
func (f *feature) iCallControllerGetVolumeWithVolume(volID string) error {
f.controllerGetVolumeRequest = nil
req := new(csi.ControllerGetVolumeRequest)
req.VolumeId = volID
f.controllerGetVolumeRequest = req

ctx := context.Background()
client := csi.NewControllerClient(grpcClient)
_, err := client.ControllerGetVolume(ctx, req)
if err != nil {
fmt.Printf("Controller get volume failed: %s\n", err.Error())
f.addError(err)
} else {
fmt.Printf("Controller get volume completed successfully\n")
}
return nil
}

//whenICallNodePublishVolume - Test case for node publish volume
func (f *feature) whenICallNodePublishVolume(fsType, readonly string) error {
f.nodePublishVolumeRequest = nil
Expand Down

0 comments on commit 3dd023b

Please sign in to comment.