Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add support for ReadWriteOncePod access mode #3235

Closed
wants to merge 1 commit into from

Conversation

shikanime
Copy link

Signed-off-by: William Phetsinorath william.phetsinorath@shikanime.studio

Copy link

coderabbitai bot commented Oct 24, 2024

Walkthrough

The changes in this pull request enhance the handling of volume access modes within the Longhorn project. The NewPVCManifestForVolume function in datastore/kubernetes.go has been updated to use a switch statement for determining access modes, incorporating a new mode, AccessModeReadWriteOncePod. Additionally, this new access mode has been added to the AccessMode types in both v1beta1 and v1beta2 volume specifications. The ValidateAccessMode function in types/types.go has also been modified to validate this new access mode, ensuring consistent error handling. The getVolumeOptions function in csi/util.go has been updated to include an exclusive parameter that influences the access mode determination. The ControllerServer class in csi/controller_server.go has been enhanced to support the new access modes and improve error handling.

Changes

File Change Summary
datastore/kubernetes.go Modified NewPVCManifestForVolume to use a switch statement for access modes, adding support for AccessModeReadWriteOncePod.
k8s/pkg/apis/longhorn/v1beta1/volume.go Added new access mode constant AccessModeReadWriteOncePod to AccessMode type and updated conversion methods for compatibility.
k8s/pkg/apis/longhorn/v1beta2/volume.go Added new access mode constant AccessModeReadWriteOncePod = AccessMode("rwop") to AccessMode type and updated validation comment.
types/types.go Updated ValidateAccessMode function to include AccessModeReadWriteOncePod in validation logic.
csi/util.go Updated getVolumeOptions function to include a new exclusive parameter affecting access mode determination.
csi/controller_server.go Enhanced ControllerServer methods to support new access modes and improved error handling across various methods.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant PVC
    participant VolumeSpec
    participant Validator
    participant Options
    participant Controller

    User->>PVC: Request PVC creation
    PVC->>VolumeSpec: Determine access mode
    VolumeSpec->>PVC: Return access mode
    PVC->>Validator: Validate access mode
    Validator->>PVC: Return validation status
    PVC->>Options: Get volume options
    Options->>PVC: Return volume options
    PVC->>Controller: Create volume with options
    Controller->>PVC: Return volume creation response
    PVC->>User: PVC creation response
Loading

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@shikanime shikanime changed the title Add support for ReadWriteOncePod access mode chore: add support for ReadWriteOncePod access mode Oct 24, 2024
@shikanime shikanime marked this pull request as ready for review October 24, 2024 11:22
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (1)
k8s/pkg/apis/longhorn/v1beta1/volume.go (1)

62-64: Add documentation for access modes.

The implementation of the new AccessModeReadWriteOncePod constant looks good and follows the existing pattern. However, consider adding documentation comments to explain each access mode's behavior and use cases.

Add documentation like this:

 type AccessMode string
 
 const (
+	// AccessModeReadWriteOnce makes the volume can be mounted as read-write by a single node
 	AccessModeReadWriteOnce    = AccessMode("rwo")
+	// AccessModeReadWriteOncePod makes the volume can be mounted as read-write by a single pod
 	AccessModeReadWriteOncePod = AccessMode("rwop")
+	// AccessModeReadWriteMany makes the volume can be mounted as read-write by many nodes
 	AccessModeReadWriteMany    = AccessMode("rwx")
 )
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between e7db6e7 and 00fd3bc.

📒 Files selected for processing (4)
  • datastore/kubernetes.go (1 hunks)
  • k8s/pkg/apis/longhorn/v1beta1/volume.go (1 hunks)
  • k8s/pkg/apis/longhorn/v1beta2/volume.go (1 hunks)
  • types/types.go (1 hunks)
🔇 Additional comments (5)
k8s/pkg/apis/longhorn/v1beta1/volume.go (1)

62-64: Verify access mode validation.

The new access mode needs proper validation to ensure it's handled correctly throughout the codebase.

✅ Verification successful

Let me gather more information about the validation logic by examining the content of the files where the access mode is used.


Based on the results, I can now provide the final response as we have sufficient evidence about the validation and handling of the new access mode.

Access mode validation is properly implemented

The new AccessModeReadWriteOncePod is correctly validated and handled throughout the codebase:

  • Validation is implemented in types/types.go through the ValidateAccessMode function which checks for all valid access modes including the new one
  • Proper conversion to Kubernetes native types is implemented in datastore/kubernetes.go where it's mapped to corev1.ReadWriteOncePod
  • The constant is consistently defined across both v1beta1 and v1beta2 API versions
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the new access mode is properly validated

# Test 1: Look for validation logic for the new access mode
echo "Checking for validation logic..."
rg -l "AccessModeReadWriteOncePod" --type go

# Test 2: Look for switch/if statements handling access modes
echo "Checking access mode handling..."
ast-grep --pattern 'switch $x.(AccessMode|accessMode) {
  $$$
}'

# Test 3: Look for test coverage
echo "Checking test coverage..."
fd -e test.go | xargs rg "AccessModeReadWriteOncePod"

Length of output: 894


Script:

#!/bin/bash
# Check the validation logic implementation and usage

# Show the validation logic in types/types.go
echo "Checking validation in types/types.go:"
rg -A 5 -B 5 "AccessModeReadWriteOncePod" types/types.go

# Show the handling in datastore/kubernetes.go
echo -e "\nChecking handling in datastore/kubernetes.go:"
rg -A 5 -B 5 "AccessModeReadWriteOncePod" datastore/kubernetes.go

# Look for any validation functions related to access modes
echo -e "\nChecking for validation functions:"
ast-grep --pattern 'func $_ ($x $_) $_ {
  if $x.$_ != $_ {
    $$$
  }
}'

Length of output: 1206

k8s/pkg/apis/longhorn/v1beta2/volume.go (2)

Line range hint 315-315: LGTM: AccessMode field integration in VolumeSpec

The AccessMode field is properly integrated into the VolumeSpec struct with appropriate JSON tags and optional marking.


60-62: Consider Kubernetes version compatibility and documentation

The introduction of ReadWriteOncePod access mode has several implications:

  1. Ensure that the minimum supported Kubernetes version is compatible with this feature (introduced in K8s 1.22)
  2. Consider adding documentation about:
    • Version compatibility requirements
    • Migration guidelines for existing volumes
    • Use cases and limitations of this access mode

Let's check if there's any version compatibility information:

✅ Verification successful

Let me try a different approach to gather information about version compatibility and documentation.

These scripts will help us:

  1. Search for version requirements in all markdown and text files
  2. Find context around ReadWriteOncePod usage
  3. Check dependencies in go.mod for K8s version
  4. Look for version checks in the code

Let's analyze the results to provide a more informed response.


Based on the search results, I can now provide a final response about the ReadWriteOncePod access mode implementation:

ReadWriteOncePod support is properly implemented with required validations

The codebase shows proper implementation of ReadWriteOncePod (RWOP) access mode:

  1. The feature is integrated with Kubernetes v1.31.1 (as seen in go.mod), which is well beyond the K8s 1.22 requirement
  2. Proper validations are in place:
    • Core Kubernetes validation prevents mixing RWOP with other access modes
    • The access mode is properly mapped in the datastore package
    • The feature is supported by the SELinuxMountReadWriteOncePod feature gate (which is in Beta and enabled by default)

No additional documentation is required as:

  • The implementation follows standard Kubernetes patterns
  • The feature is now stable in both Kubernetes and this codebase
  • The access mode is a standard Kubernetes concept documented in upstream Kubernetes
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for Kubernetes version compatibility information
rg -i "kubernetes.*version|version.*requirement" README.md

Length of output: 60


Script:

#!/bin/bash
# Check for version-related information in docs and other common locations
fd -e md -e txt | xargs rg -i "kubernetes.*version|version.*requirement|minimum.*version"

# Look for any documentation about ReadWriteOncePod
rg -i "readwriteoncepod|rwop" -A 3 -B 3

# Check if there's any version information in go.mod
cat go.mod

# Look for any version checks in the codebase
ast-grep --pattern 'if $_ >= $_.$_.$$$ {
  $$$
}'

Length of output: 46196

types/types.go (1)

847-847: LGTM! The ReadWriteOncePod access mode validation is correctly implemented.

The implementation properly validates the new AccessModeReadWriteOncePod access mode alongside the existing modes. This aligns with the Kubernetes storage specification where ReadWriteOncePod was introduced to provide stronger guarantees for pod access exclusivity compared to ReadWriteOnce.

datastore/kubernetes.go (1)

1018-1022: LGTM! Clean implementation of ReadWriteOncePod access mode support.

The switch statement implementation for access mode mapping is clean and follows the existing pattern. The new case correctly maps longhorn.AccessModeReadWriteOncePod to corev1.ReadWriteOncePod.

Let's verify the access mode type is properly defined:

✅ Verification successful

The search results show that AccessModeReadWriteOncePod is properly defined in both v1beta1 and v1beta2 API versions of Longhorn types with the value "rwop". Let me verify one more aspect to ensure complete validation:


Let me modify the search to look for import statements in a different way:


Let me try one more search with a larger context to find the longhorn imports:


Let me try one final search to look for the entire file content to find the imports:


Now I have all the necessary information to provide the final response:

AccessModeReadWriteOncePod implementation is correctly defined and imported

The verification confirms:

  • AccessModeReadWriteOncePod is properly defined in both v1beta1 and v1beta2 API versions with the value "rwop"
  • The correct Longhorn types are imported via longhorn "github.com/longhorn/longhorn-manager/k8s/pkg/apis/longhorn/v1beta2"
  • The mapping between Longhorn's AccessModeReadWriteOncePod and Kubernetes' corev1.ReadWriteOncePod is implemented correctly
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify AccessModeReadWriteOncePod is defined in the Longhorn types
# Test: Search for AccessModeReadWriteOncePod definition. Expect: Definition in types package.
rg "AccessModeReadWriteOncePod.*=.*" -A 2

Length of output: 484


Script:

#!/bin/bash
# Verify the import statement in kubernetes.go uses the correct package for longhorn types
rg "import.*longhorn" datastore/kubernetes.go

Length of output: 47


Script:

#!/bin/bash
# Look for longhorn imports in the entire import block
rg -A 10 "^import \(" datastore/kubernetes.go

Length of output: 185


Script:

#!/bin/bash
# Look for longhorn imports with larger context
rg -A 20 "^import \(" datastore/kubernetes.go | grep -i "longhorn"

Length of output: 66


Script:

#!/bin/bash
# Get the entire file content to analyze imports
head -n 50 datastore/kubernetes.go

Length of output: 1408

k8s/pkg/apis/longhorn/v1beta2/volume.go Show resolved Hide resolved
types/types.go Show resolved Hide resolved
@shikanime shikanime force-pushed the pr3235 branch 4 times, most recently from fa60d58 to 2415bc6 Compare October 24, 2024 14:18
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (2)
csi/util.go (2)

131-133: Add documentation for default access mode behavior.

While the default to ReadWriteOnce is correct, it would be helpful to add a comment explaining this default behavior and its relationship with the exclusive and share parameters.

Add a comment like:

+// Default to ReadWriteOnce if no access mode was set by exclusive or share parameters
 if vol.AccessMode == "" {
   vol.AccessMode = string(longhorn.AccessModeReadWriteOnce)
 }

Line range hint 110-133: Add unit tests for the new exclusive parameter.

The implementation looks good, but needs test coverage for:

  • Exclusive parameter parsing
  • Interaction between exclusive and share parameters
  • Default access mode behavior

Would you like me to help generate unit tests for these scenarios?

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 0a94e2f and 2415bc6.

📒 Files selected for processing (5)
  • csi/util.go (2 hunks)
  • datastore/kubernetes.go (1 hunks)
  • k8s/pkg/apis/longhorn/v1beta1/volume.go (1 hunks)
  • k8s/pkg/apis/longhorn/v1beta2/volume.go (1 hunks)
  • types/types.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • datastore/kubernetes.go
  • k8s/pkg/apis/longhorn/v1beta1/volume.go
  • k8s/pkg/apis/longhorn/v1beta2/volume.go
  • types/types.go
🔇 Additional comments (1)
csi/util.go (1)

110-118: Consider reordering parameter processing to avoid conflicts.

The exclusive parameter is processed before the share parameter, which could lead to unexpected behavior if both are set. The ReadWriteOncePod mode set by exclusive=true could be immediately overwritten by share=true to ReadWriteMany.

Let's verify the potential parameter conflict:

Consider:

  1. Processing share parameter first since it's more restrictive (ReadWriteMany)
  2. Adding validation to prevent conflicting parameters
  3. Documenting the parameter precedence in comments

@shikanime shikanime force-pushed the pr3235 branch 2 times, most recently from 42db3a0 to f2f33c7 Compare October 24, 2024 14:46
Signed-off-by: William Phetsinorath <william.phetsinorath@shikanime.studio>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (2)
csi/util.go (2)

110-118: Add documentation for exclusive parameter behavior.

The exclusive parameter's behavior and its impact on access mode should be documented for better maintainability.

Add a comment above the if block explaining:

+// If exclusive=true and current access mode is ReadWriteOnce,
+// upgrade it to ReadWriteOncePod for stronger guarantees
 if exclusive, ok := volOptions["exclusive"]; ok {

468-480: Improve function documentation and parameter naming.

  1. The function is exported and needs proper documentation.
  2. The parameter name cap shadows Go's built-in cap() function.

Apply these improvements:

+// requireExclusiveAccess determines if the volume requires exclusive access based on
+// its access mode and volume capability. A volume requires exclusive access when:
+// - Its access mode is ReadWriteOncePod, or
+// - The requested capability mode is SINGLE_NODE_SINGLE_WRITER
-func requireExclusiveAccess(vol *longhornclient.Volume, cap *csi.VolumeCapability) bool {
+func requireExclusiveAccess(vol *longhornclient.Volume, capability *csi.VolumeCapability) bool {
   isExclusive := false
   if vol != nil {
     isExclusive = vol.AccessMode == string(longhorn.AccessModeReadWriteOncePod)
   }

   mode := csi.VolumeCapability_AccessMode_UNKNOWN
-  if cap != nil {
-    mode = cap.AccessMode.Mode
+  if capability != nil {
+    mode = capability.AccessMode.Mode
   }

   return isExclusive || mode == csi.VolumeCapability_AccessMode_SINGLE_NODE_SINGLE_WRITER
}
🧰 Tools
🪛 GitHub Check: CodeFactor

[notice] 468-468: csi/util.go#L468
Redefinition of the built-in function cap. (redefines-builtin-id)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 2415bc6 and 007fd62.

📒 Files selected for processing (6)
  • csi/controller_server.go (3 hunks)
  • csi/util.go (3 hunks)
  • datastore/kubernetes.go (1 hunks)
  • k8s/pkg/apis/longhorn/v1beta1/volume.go (1 hunks)
  • k8s/pkg/apis/longhorn/v1beta2/volume.go (1 hunks)
  • types/types.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • datastore/kubernetes.go
  • k8s/pkg/apis/longhorn/v1beta1/volume.go
  • k8s/pkg/apis/longhorn/v1beta2/volume.go
  • types/types.go
🧰 Additional context used
🪛 GitHub Check: CodeFactor
csi/util.go

[notice] 468-468: csi/util.go#L468
Redefinition of the built-in function cap. (redefines-builtin-id)

🔇 Additional comments (4)
csi/util.go (2)

131-133: LGTM!

Good placement of the default access mode setting after handling explicit parameters.


468-480: LGTM on the implementation logic!

The function correctly determines exclusive access requirements by checking both the volume's access mode and the requested capability mode.

🧰 Tools
🪛 GitHub Check: CodeFactor

[notice] 468-468: csi/util.go#L468
Redefinition of the built-in function cap. (redefines-builtin-id)

csi/controller_server.go (2)

463-469: Ensure safe update of volume access mode to ReadWriteOncePod

In ControllerPublishVolume, when requireExclusiveAccess(volume, volumeCapability) returns true, the code updates the volume's access mode to AccessModeReadWriteOncePod by calling cs.updateVolumeAccessMode(volume, longhorn.AccessModeReadWriteOncePod).

Verify that this access mode change is safely handled, considering any concurrent access or existing attachments.

Check that the updateVolumeAccessMode function safely updates the volume's access mode and that the volume manager handles access mode changes correctly during runtime. Ensure that appropriate synchronization mechanisms are in place to prevent data races or inconsistencies.


72-73: Verify comprehensive handling of new access modes across the codebase

The addition of csi.VolumeCapability_AccessMode_SINGLE_NODE_SINGLE_WRITER, csi.VolumeCapability_AccessMode_SINGLE_NODE_MULTI_WRITER, and csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER in the accessModes slice broadens the volume capabilities.

Ensure that these newly added access modes are fully supported and correctly handled in all relevant methods, such as validateVolumeCapabilities, CreateVolume, ControllerPublishVolume, and any custom logic that depends on access modes.

You can run the following shell script to identify where these new access modes are being used and verify their handling:

✅ Verification successful

Let me gather more context about how these access modes are handled in the codebase, particularly in the validation and volume management logic.


Let me try a different approach to check the validation and handling of these access modes.


Based on the gathered information, I can now provide a final response about the handling of the new access modes.

Access modes are properly integrated and validated across the codebase

The codebase shows comprehensive handling of the new access modes:

  1. The access modes are properly declared in the ControllerServer initialization and included in the supported capabilities.

  2. The requiresSharedAccess and requireExclusiveAccess utility functions in csi/util.go properly handle these access modes:

    • SINGLE_NODE_SINGLE_WRITER is correctly handled in requireExclusiveAccess
    • SINGLE_NODE_MULTI_WRITER and MULTI_NODE_MULTI_WRITER are handled in requiresSharedAccess
  3. The validation flow is complete:

    • Volume capabilities are validated in validateVolumeCapabilities
    • Access modes are checked during volume operations (Create, Stage, Publish)
    • The mounter selection logic in getMounter considers these access modes for proper mounting strategy
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for handling of new access modes in the codebase.

# Expected: All occurrences of the new access modes are properly processed.

# Search for the new access modes in the codebase.
rg 'SINGLE_NODE_SINGLE_WRITER|SINGLE_NODE_MULTI_WRITER|MULTI_NODE_MULTI_WRITER' --type go

Length of output: 3420


Script:

#!/bin/bash
# Check the implementation of validateVolumeCapabilities and related methods
ast-grep --pattern 'func $_($_, $_, $_) error {
  $$$
  validateVolumeCapabilities
  $$$
}'

# Look for any validation logic around access modes
rg -A 5 "validateVolumeCapability" --type go

# Check the implementation of CreateVolume and ControllerPublishVolume
ast-grep --pattern 'func (cs *controllerServer) CreateVolume($_, $_) ($_, error) {
  $$$
}'

ast-grep --pattern 'func (cs *controllerServer) ControllerPublishVolume($_, $_) ($_, error) {
  $$$
}'

Length of output: 337


Script:

#!/bin/bash
# Search for validation logic and access mode handling
rg -B 2 -A 5 "func.*validateVolumeCapability" --type go

# Look for access mode validation in util.go since we saw references there
cat csi/util.go

# Check the implementation details around volume capabilities
rg -B 2 -A 10 "VolumeCapability" --type go --glob '!vendor/**'

Length of output: 27772

csi/controller_server.go Show resolved Hide resolved
@shikanime shikanime closed this Oct 24, 2024
@shikanime
Copy link
Author

Duplicate pull request due to bug

@shikanime shikanime deleted the pr3235 branch October 24, 2024 17:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant