Skip to content

Support NFS RDMA enabled key for nfs_global_settings module #191

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

Merged
merged 2 commits into from
Jun 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions docs/modules/nfs_global_settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ Parameters
Enable/Disable the rquota protocol.


nfs_rdma_enabled (optional, bool, None)
Enables or disables RDMA for NFS.

Supported on PowerScale 9.8 and later.


nfsv3 (optional, dict, None)
Enable/disable NFSv3 protocol.

Expand All @@ -56,6 +62,8 @@ Parameters
nfsv3_rdma_enabled (optional, bool, None)
To enable/disable RDMA for NFSv3 protocol.

For PowerScale 9.8 :emphasis:`nfsv3\_rdma\_enabled` is not supported and :emphasis:`nfs\_rdma\_enabled` is used for both nfsv3 and nfsv4.



nfsv4 (optional, dict, None)
Expand Down Expand Up @@ -90,9 +98,9 @@ Parameters
verify_ssl (True, bool, None)
boolean variable to specify whether to validate SSL certificate or not.

\ :literal:`true`\ - indicates that the SSL certificate should be verified.
:literal:`true` - indicates that the SSL certificate should be verified.

\ :literal:`false`\ - indicates that the SSL certificate should not be verified.
:literal:`false` - indicates that the SSL certificate should not be verified.


api_user (True, str, None)
Expand All @@ -110,7 +118,7 @@ Notes
-----

.. note::
- The \ :emphasis:`check\_mode`\ is supported.
- The :emphasis:`check\_mode` is supported.
- The modules present in this collection named as 'dellemc.powerscale' are built to support the Dell PowerScale storage platform.


Expand Down Expand Up @@ -144,6 +152,7 @@ Examples
nfsv40_enabled: true
nfsv41_enabled: true
nfsv42_enabled: false
nfs_rdma_enabled: true
rpc_minthreads: 17
rpc_maxthreads: 20
rquota_enabled: true
Expand Down
36 changes: 32 additions & 4 deletions plugins/modules/nfs_global_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@
description:
- Enable/Disable the rquota protocol.
type: bool
nfs_rdma_enabled:
description:
- Enables or disables RDMA for NFS.
- Supported on PowerScale 9.8 and later.
type: bool
nfsv3:
description:
- Enable/disable NFSv3 protocol.
Expand All @@ -53,6 +58,8 @@
nfsv3_rdma_enabled:
description:
- To enable/disable RDMA for NFSv3 protocol.
- For PowerScale 9.8 I(nfsv3_rdma_enabled) is not supported
and I(nfs_rdma_enabled) is used for both nfsv3 and nfsv4.
type: bool
nfsv4:
description:
Expand Down Expand Up @@ -102,6 +109,7 @@
nfsv40_enabled: true
nfsv41_enabled: true
nfsv42_enabled: false
nfs_rdma_enabled: true
rpc_minthreads: 17
rpc_maxthreads: 20
rquota_enabled: true
Expand Down Expand Up @@ -197,12 +205,30 @@ def __init__(self):

self.api_client = utils.get_powerscale_connection(self.module.params)
self.isi_sdk = utils.get_powerscale_sdk()
self.array_version = f"{self.isi_sdk.major}.{self.isi_sdk.minor}"

LOG.info('Got python SDK instance for provisioning on PowerScale ')
check_mode_msg = f'Check mode flag is {self.module.check_mode}'
LOG.info(check_mode_msg)

self.protocol_api = self.isi_sdk.ProtocolsApi(self.api_client)

def validate_input(self):
"""
Validate the input parameters based on the array version.
This method checks whether certain parameters are allowed based on the array version.
If the array version is 9.8 or later, the nfsv3.nfsv3_rdma_enabled parameter is not allowed.
If the array version is earlier than 9.8, the nfs_rdma_enabled parameter is not allowed.
"""
params = self.module.params

if utils.parse_version(self.array_version) < utils.parse_version("9.8"):
if params.get("nfs_rdma_enabled") is not None:
self.module.fail_json(msg="nfs_rdma_enabled is not allowed when array version is earlier than 9.8.")
else:
if params.get("nfsv3") and params.get("nfsv3").get("nfsv3_rdma_enabled") is not None:
self.module.fail_json(msg="nfsv3.nfsv3_rdma_enabled is not allowed when array version is 9.8 or later.")

def get_nfs_global_settings_details(self):
"""
Get details of NFS global settings
Expand Down Expand Up @@ -249,14 +275,14 @@ def is_nfsv3v4_modify_required(self, settings_params, settings_details, modify_d
nfsv4_keys = ["nfsv4_enabled", "nfsv40_enabled", "nfsv41_enabled", "nfsv42_enabled"]
if settings_params["nfsv4"] is not None:
for key in nfsv4_keys:
if settings_params["nfsv4"][key] is not None and \
if key in settings_params["nfsv4"] and settings_params["nfsv4"][key] is not None and \
settings_details[key] != settings_params["nfsv4"][key]:
modify_dict[key] = settings_params["nfsv4"][key]

nfsv3_keys = ["nfsv3_enabled", "nfsv3_rdma_enabled"]
if settings_params["nfsv3"] is not None:
for key in nfsv3_keys:
if settings_params["nfsv3"][key] is not None and \
if key in settings_params["nfsv3"] and settings_params["nfsv3"][key] is not None and \
settings_details[key] != settings_params["nfsv3"][key]:
modify_dict[key] = settings_params["nfsv3"][key]

Expand All @@ -267,9 +293,9 @@ def is_nfs_global_modify_required(self, settings_params, settings_details):
Check whether modification is required in NFS global settings
"""
modify_dict = {}
keys = ["service", "rpc_maxthreads", "rpc_minthreads", "rquota_enabled"]
keys = ["service", "rpc_maxthreads", "rpc_minthreads", "rquota_enabled", "nfs_rdma_enabled"]
for key in keys:
if settings_params[key] is not None and \
if key in settings_params and settings_params[key] is not None and \
settings_details[key] != settings_params[key]:
modify_dict[key] = settings_params[key]

Expand All @@ -284,6 +310,7 @@ def get_nfs_global_settings_parameters(self):
service=dict(type='bool'), rpc_maxthreads=dict(type='int'),
rpc_minthreads=dict(type='int'),
rquota_enabled=dict(type='bool'),
nfs_rdma_enabled=dict(type='bool'),
nfsv3=dict(
type='dict', options=dict(
nfsv3_enabled=dict(type='bool'),
Expand Down Expand Up @@ -319,6 +346,7 @@ def handle(self, nfs_global_obj, nfs_global_params, nfs_global_details):

class NFSGlobalSettingsHandler:
def handle(self, nfs_global_obj, nfs_global_params):
nfs_global_obj.validate_input()
nfs_global_details = nfs_global_obj.get_nfs_global_settings_details()
NFSGlobalSettingsModifyHandler().handle(
nfs_global_obj=nfs_global_obj, nfs_global_params=nfs_global_params,
Expand Down
Empty file removed tests/unit/plugins/__init__
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,35 @@ class MockNFSGlobalSettingsApi:

NFS_GLOBAL_COMMON_ARGS = {
"onefs_host": "**.***.**.***",
"nfsv3_enabled": None,
"nfsv3": None,
"nfsv4": None,
"rpc_maxthreads": 20,
"rpc_minthreads": 17,
"rquota_enabled": None,
"service": None
}

NFS_GLOBAL_97_RDMA_ARGS = {
"onefs_host": "**.***.**.**",
"nfsv3": {"nfsv3_rdma_enabled": True},
"nfsv4": None,
"rpc_maxthreads": 20,
"rpc_minthreads": 17,
"rquota_enabled": None,
"service": None
}

NFS_GLOBAL_98_RDMA_ARGS = {
"onefs_host": "**.***.**.**",
"nfs_rdma_enabled": True,
"nfsv3": None,
"nfsv4": None,
"rpc_maxthreads": 20,
"rpc_minthreads": 17,
"rquota_enabled": None,
"service": None
}

GET_NFS_GLOBAL_RESPONSE = {
"nfsv3_enabled": False,
"nfsv3_rdma_enabled": True,
Expand All @@ -35,9 +56,26 @@ class MockNFSGlobalSettingsApi:
"service": True
}

GET_NFS_GLOBAL_RESPONSE_RDMA_98 = {
"nfsv3_enabled": False,
"nfs_rdma_enabled": True,
"nfsv40_enabled": True,
"nfsv41_enabled": True,
"nfsv42_enabled": False,
"nfsv4_enabled": True,
"rpc_maxthreads": 20,
"rpc_minthreads": 17,
"rquota_enabled": True,
"service": True
}

@staticmethod
def get_nfs_global_settings_exception_response(response_type):
if response_type == 'get_details_exception':
return "Got error SDK Error message while getting NFS global setings details "
elif response_type == 'update_exception':
return "Modify NFS global settings failed with error: SDK Error message"
elif response_type == 'rdma_exception':
return "nfs_rdma_enabled is not allowed when array version is earlier than 9.8."
elif response_type == 'rdma_v3_exception':
return "nfsv3.nfsv3_rdma_enabled is not allowed when array version is 9.8 or later."
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def capture_fail_json_call(self, error_msg, module_handler=None, invoke_perform_
self.powerscale_module_mock.perform_module_operation()
self.powerscale_module_mock.module.fail_json.assert_called()
call_args = self.powerscale_module_mock.module.fail_json.call_args.kwargs
assert error_msg in call_args['msg']
assert call_args['msg'] is not None and error_msg in call_args['msg']

def capture_fail_json_method(self, error_msg, module_mock, function_name, *args, **kwargs):
with pytest.raises(SystemExit):
Expand Down
Empty file.
31 changes: 31 additions & 0 deletions tests/unit/plugins/modules/test_nfs_global_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
import MockApiException
from ansible_collections.dellemc.powerscale.tests.unit.plugins.module_utils.shared_library.powerscale_unit_base import \
PowerScaleUnitBase
from ansible_collections.dellemc.powerscale.tests.unit.plugins.module_utils.mock_sdk_response import (
MockSDKResponse,
)


class TestNFSGlobalSettings(PowerScaleUnitBase):
Expand All @@ -35,18 +38,44 @@ def test_get_nfs_global_details(self, powerscale_module_mock):
self.nfs_global_args.update({
})
powerscale_module_mock.module.params = self.nfs_global_args
powerscale_module_mock.array_version = "9.7"
NFSGlobalSettingsHandler().handle(powerscale_module_mock, powerscale_module_mock.module.params)
powerscale_module_mock.protocol_api.get_nfs_settings_global.assert_called()

def test_get_nfs_global_details_exception(self, powerscale_module_mock):
self.nfs_global_args.update({})
powerscale_module_mock.module.params = self.nfs_global_args
powerscale_module_mock.array_version = "9.7"
powerscale_module_mock.protocol_api.get_nfs_settings_global = MagicMock(
side_effect=MockApiException)
self.capture_fail_json_call(
MockNFSGlobalSettingsApi.get_nfs_global_settings_exception_response('get_details_exception'),
NFSGlobalSettingsHandler)

def test_modify_nfs_rdma_97_exception(self, powerscale_module_mock):
self.nfs_global_args.update(MockNFSGlobalSettingsApi.GET_NFS_GLOBAL_RESPONSE_RDMA_98)
powerscale_module_mock.module.params = self.nfs_global_args
powerscale_module_mock.array_version = "9.7"
powerscale_module_mock.protocol_api.get_nfs_settings_global = MagicMock(
return_value=MockSDKResponse(
MockNFSGlobalSettingsApi.GET_NFS_GLOBAL_RESPONSE_RDMA_98
))
self.capture_fail_json_call(
MockNFSGlobalSettingsApi.get_nfs_global_settings_exception_response('rdma_exception'),
NFSGlobalSettingsHandler)

def test_modify_nfs_rdma_98_exception(self, powerscale_module_mock):
self.nfs_global_args.update(MockNFSGlobalSettingsApi.NFS_GLOBAL_97_RDMA_ARGS)
powerscale_module_mock.module.params = self.nfs_global_args
powerscale_module_mock.array_version = "9.8"
powerscale_module_mock.protocol_api.get_nfs_settings_global = MagicMock(
return_value=MockSDKResponse(
MockNFSGlobalSettingsApi.GET_NFS_GLOBAL_RESPONSE_RDMA_98
))
self.capture_fail_json_call(
MockNFSGlobalSettingsApi.get_nfs_global_settings_exception_response('rdma_v3_exception'),
NFSGlobalSettingsHandler)

def test_modify_nfs_global_response(self, powerscale_module_mock):
self.nfs_global_args.update({
"service": True,
Expand All @@ -59,6 +88,7 @@ def test_modify_nfs_global_response(self, powerscale_module_mock):
}
})
powerscale_module_mock.module.params = self.nfs_global_args
powerscale_module_mock.array_version = "9.7"
powerscale_module_mock.get_nfs_global_settings_details = MagicMock(
return_value=MockNFSGlobalSettingsApi.GET_NFS_GLOBAL_RESPONSE)
NFSGlobalSettingsHandler().handle(powerscale_module_mock,
Expand All @@ -78,6 +108,7 @@ def test_modify_nfs_global_exception(self, powerscale_module_mock):
}
})
powerscale_module_mock.module.params = self.nfs_global_args
powerscale_module_mock.array_version = "9.7"
powerscale_module_mock.get_nfs_global_settings_details = MagicMock(
return_value=MockNFSGlobalSettingsApi.GET_NFS_GLOBAL_RESPONSE)
powerscale_module_mock.protocol_api.update_nfs_settings_global = MagicMock(
Expand Down