Skip to content

Commit

Permalink
NFS exports restored as read-only rockstor#2912
Browse files Browse the repository at this point in the history
# Includes
- Instructions on fixture creation.
- Instructions on running nfs export tests.
- Modernise test_nfs_export.py by re-instating test_nfs.json fixture
and removing prior hard-coded object mock stand-ins for DB models
during these test runs.
  • Loading branch information
phillxnet committed Nov 6, 2024
1 parent e88854b commit 6c89004
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 49 deletions.
112 changes: 112 additions & 0 deletions src/rockstor/storageadmin/fixtures/test_nfs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
[
{
"model": "storageadmin.pool",
"pk": 11,
"fields": {
"name": "rock-pool",
"uuid": "26e1fb5e-65fc-43e1-8054-60ccec189243",
"size": 10485760,
"raid": "single-dup",
"toc": "2024-11-06T16:05:29.817Z",
"compression": "no",
"mnt_options": null,
"role": null
}
},
{
"model": "storageadmin.share",
"pk": 21,
"fields": {
"pool": 11,
"qgroup": "0/463",
"pqgroup": "2015/3",
"name": "share-nfs",
"uuid": null,
"size": 1048576,
"owner": "root",
"group": "root",
"perms": "755",
"toc": "2024-11-06T16:05:29.894Z",
"subvol_name": "share-nfs",
"replica": false,
"compression_algo": "no",
"rusage": 16,
"eusage": 16,
"pqgroup_rusage": 16,
"pqgroup_eusage": 16
}
},
{
"model": "storageadmin.share",
"pk": 22,
"fields": {
"pool": 11,
"qgroup": "0/464",
"pqgroup": "2015/4",
"name": "share2",
"uuid": null,
"size": 1048576,
"owner": "root",
"group": "root",
"perms": "755",
"toc": "2024-11-06T16:05:29.918Z",
"subvol_name": "share2",
"replica": false,
"compression_algo": "no",
"rusage": 16,
"eusage": 16,
"pqgroup_rusage": 16,
"pqgroup_eusage": 16
}
},
{
"model": "storageadmin.nfsexport",
"pk": 3,
"fields": {
"export_group": 3,
"share": 21,
"mount": "/export/share-nfs"
}
},
{
"model": "storageadmin.nfsexportgroup",
"pk": 3,
"fields": {
"host_str": "*",
"editable": "rw",
"syncable": "async",
"mount_security": "insecure",
"nohide": false,
"enabled": true,
"admin_host": null
}
},
{
"model": "storageadmin.user",
"pk": 1,
"fields": {
"user": [
"admin"
],
"username": "admin",
"uid": 1000,
"gid": 100,
"public_key": null,
"shell": "/bin/bash",
"homedir": "/home/admin",
"email": null,
"admin": true,
"group": 1,
"smb_shares": []
}
},
{
"model": "storageadmin.group",
"pk": 1,
"fields": {
"gid": 100,
"groupname": "users",
"admin": true
}
}
]
96 changes: 47 additions & 49 deletions src/rockstor/storageadmin/tests/test_nfs_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,52 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
from unittest import mock
from unittest.mock import patch

from rest_framework import status
from storageadmin.models import Pool, Share, NFSExportGroup, NFSExport
from storageadmin.tests.test_api import APITestMixin

"""
fixture with:
Pool:
- pk=11
- name="rock-pool"
Share:
- pk=21
- name: "share-nfs"
- pool: "rock-pool" above
- exported with defaults:
- (NFS Clients) host_str: "*"
- (Admin Host) admin_host: None
- (Access type) mod_choice: "rw"
- (Response type) sync_choice: "async"
Share:
- pk=22
- name: "share2"
User:
- pk: 1
- name: admin
- group: 1
Group:
- pk: 1
proposed fixture = 'test_nfs.json'
cd /opt/rockstor
poetry run django-admin dumpdata storageadmin.pool storageadmin.share \
storageadmin.nfsexport storageadmin.nfsexportgroup \
storageadmin.user storageadmin.group \
--natural-foreign --indent 4 > \
src/rockstor/storageadmin/fixtures/test_nfs.json
To run the tests:
cd /opt/rockstor/src/rockstor
poetry run django-admin test -v 2 -p test_nfs_export.py
"""


class NFSExportTests(APITestMixin):
# fixture with:
# share-nfs - NFS exported - with defaults: client=*, Writable, async
# {'host_str': '*', 'mod_choice': 'rw', 'sync_choice': 'async', }
# share2 - no NFS export
# proposed fixture = 'test_nfs.json'
fixtures = ["test_api.json"]
fixtures = ["test_api.json", "test_nfs.json"]
BASE_URL = "/api/nfs-exports"

@classmethod
Expand All @@ -51,21 +82,6 @@ def setUpClass(cls):
# validate_nfs_modify_str
# validate_nfs_sync_choice

# all values as per fixture
cls.temp_pool = Pool(id=11, name="rock-pool", size=5242880)
cls.temp_share_nfs = Share(id=21, name="share-nfs", pool=cls.temp_pool)
# the following is not picking up from db !!
# cls.temp_nfsexportgroup = NFSExportGroup.objects.get(id=1)
cls.temp_nfsexportgroup = NFSExportGroup(id=1)
cls.temp_nfsexport = NFSExport(
export_group=cls.temp_nfsexportgroup,
share=cls.temp_share_nfs,
mount="/export/share-nfs",
id=1,
)

cls.temp_share2 = Share(id=22, name="share2", pool=cls.temp_pool)

@classmethod
def tearDownClass(cls):
super(NFSExportTests, cls).tearDownClass()
Expand All @@ -91,8 +107,7 @@ def test_invalid_get(self):
response = self.client.get("{}/99999".format(self.BASE_URL))
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND, msg=response)

@mock.patch("storageadmin.views.share_helpers.Share")
def test_post_requests(self, mock_share):
def test_post_requests(self):
"""
invalid nfs-export api operations
1. Add nfs-export without providing share names
Expand All @@ -115,8 +130,6 @@ def test_post_requests(self, mock_share):
e_msg = "Cannot export without specifying shares."
self.assertEqual(response.data[0], e_msg)

mock_share.objects.get.return_value = self.temp_share2

# AssertionError: ["{'share': [u'share instance with id 22 does not exist.']}",
# # happy path
# data1 = {'shares': ('share2',), 'host_str': '*.edu',
Expand Down Expand Up @@ -203,10 +216,7 @@ def test_post_requests(self, mock_share):
# self.assertEqual(response.data[0], e_msg)
# self.mock_refresh_nfs_exports.side_effect = None

@mock.patch("storageadmin.views.share_helpers.Share")
def test_invalid_admin_host1(self, mock_share):

mock_share.objects.get.return_value = self.temp_share2
def test_invalid_admin_host1(self):

# invalid post request
# Add nfs-export providing invalid admin host
Expand Down Expand Up @@ -255,9 +265,7 @@ def test_invalid_admin_host2(self):
# self.assertEqual(response.data[0], e_msg)
self.mock_refresh_nfs_exports.side_effect = None

@mock.patch("storageadmin.views.nfs_exports.NFSExportGroup")
@mock.patch("storageadmin.views.share_helpers.Share")
def test_put_requests(self, mock_share, mock_nfsexportgroup):
def test_put_requests(self):
"""
. Edit nfs-export with no shares
. Edit nfs-export
Expand All @@ -268,7 +276,8 @@ def test_put_requests(self, mock_share, mock_nfsexportgroup):
self.mock_refresh_nfs_exports.side_effect = None
self.mock_refresh_nfs_exports.return_value = "out", "err", 0

nfs_id = self.temp_nfsexport.id
# from fixture, TODO remove hard-coding.
nfs_id = 3
data = {"host_str": "*.edu", "mod_choice": "rw", "sync_choice": "async"}
response = self.client.put("{}/{}".format(self.BASE_URL, nfs_id), data=data)
self.assertEqual(
Expand All @@ -279,9 +288,6 @@ def test_put_requests(self, mock_share, mock_nfsexportgroup):
e_msg = "Cannot export without specifying shares."
self.assertEqual(response.data[0], e_msg)

mock_share.objects.get.return_value = self.temp_share_nfs
mock_nfsexportgroup.objects.get.return_value = self.temp_nfsexportgroup

# TODO: FAIL AssertionError: ["{'export_group': [u'This field cannot be null.'],
# 'share': [u'share instance with id 21 does not exist.']}",
# # happy path of editing existing nfs export
Expand Down Expand Up @@ -319,20 +325,15 @@ def test_put_requests(self, mock_share, mock_nfsexportgroup):
# e_msg = 'NFS export with id ({}) does not exist.'.format(nfs_id)
# self.assertEqual(response.data[0], e_msg)

@mock.patch("storageadmin.views.nfs_exports.NFSExport")
@mock.patch("storageadmin.views.nfs_exports.NFSExportGroup")
def test_delete_requests(self, mock_nfsexportgroup, mock_nfsexport):
def test_delete_requests(self):

"""
. Delete nfs-export that does not exist
. Delete nfs-export
"""

mock_nfsexportgroup.objects.get.return_value = self.temp_nfsexportgroup
mock_nfsexport.objects.get.return_value = self.temp_nfsexport

# happy path
nfs_id = self.temp_nfsexport.id
nfs_id = 3
response = self.client.delete("{}/{}".format(self.BASE_URL, nfs_id))
self.assertEqual(response.status_code, status.HTTP_200_OK, msg=response.data)

Expand All @@ -357,10 +358,7 @@ def test_adv_nfs_get(self):
# get base URL
self.get_base("/api/adv-nfs-exports")

@mock.patch("storageadmin.views.share_helpers.Share")
def test_adv_nfs_post_requests(self, mock_share):

mock_share.objects.get.return_value = self.temp_share_nfs
def test_adv_nfs_post_requests(self):

# without specifying entries
data = {}
Expand Down

0 comments on commit 6c89004

Please sign in to comment.