Sunil Mohan Adapa 10b46f1968
storage: Use UDisks information as primary source
Rename get_disks() to get_mounts() and use it in for backups and samba shares.

Create a new get_disks() similar to get_mounts() but use df information only for
showing free space. This inverts the importance of 'df' and UDisks. Use UDisks
as primary source of information for showing list of disks and then use df to
fill in the free space information.

- Retrieve all the mount points of a device and return them as part of
get_disks() in an extra 'mount_points' property.

- For storage listing, this fixes showing up of /.snapshots as separate disk and
showing of vboxsf, network mounts etc. Only shows mounts that are related to
block devices.

- Update various uses of get_disks() within storage module to use
'mounts_points' instead of 'mount_point' to be accurate in cases where there are
multiple mounts for a given device. Use get_mounts() where appropriate instead.

- Display all the mount points against a devices in multiple lines.

- Also show devices that are not currently mounted.

Tests performed:

- Filling up a disk shows a disk space warning properly. Warning contains the
  free disk space correctly.

- Calling get_root_device(get_disks()) return the correct root device.

- In Deluge, the download directory contains a list of all samba current shares.
  If a disk with samba share is unmouted, it does not show up in the list.

- In the Samba app page, all disks are shown properly. Root disk is shown as
  'disk'. All other mount points such as .snapshots and /vagrant also show up.

- In the Samba app page, unavailable shares list shows up when a disk with a
  share is unmounted.

- Upload a backup, warning on the form shows available disk space properly.

- When adding a backup location. The list includes all mount points. Duplicated
  mount points are not shown. Root disk is not shown in the list. When all the
  disks are used up for backup location, a warning that no additional disks are
  available is shown.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2020-06-24 07:23:29 -04:00

172 lines
5.6 KiB
Python

# SPDX-License-Identifier: AGPL-3.0-or-later
"""
Tests for samba views.
"""
import json
import urllib
from unittest.mock import patch
import pytest
from django import urls
from django.contrib.messages.storage.fallback import FallbackStorage
from plinth import module_loader
from plinth.errors import ActionError
from plinth.modules.samba import views
# For all tests, use plinth.urls instead of urls configured for testing
pytestmark = pytest.mark.urls('plinth.urls')
USERS = {"access_ok": ["testuser"], 'password_re_enter_needed': []}
DISKS = [{
'device': '/dev/sda1',
'label': '',
'filesystem_type': 'ext4',
'mount_point': '/',
'percent_used': 63,
'size_str': '9.5 GiB',
'used_str': '5.7 GiB'
}]
SHARES = [
{
"name": "disk",
"mount_point": "/",
"path": "/var/lib/freedombox/shares/open_share",
"share_type": "open"
},
{
"name": "disk_home",
"mount_point": "/",
"path": "/var/lib/freedombox/shares/homes/%u",
"share_type": "home"
},
{
"name": "otherdisk",
"mount_point": "/media/root/otherdisk",
"path": "/media/root/otherdisk/FreedomBox/shares/homes/open_share",
"share_type": "open"
}
]
@pytest.fixture(autouse=True, scope='module')
def fixture_samba_urls():
"""Make sure samba app's URLs are part of plinth.urls."""
with patch('plinth.module_loader._modules_to_load', new=[]) as modules, \
patch('plinth.urls.urlpatterns', new=[]):
modules.append('plinth.modules.samba')
module_loader.include_urls()
yield
def action_run(action, options, **kwargs):
"""Action return values."""
if action == 'samba' and options == ['get-shares']:
return json.dumps(SHARES)
return None
@pytest.fixture(autouse=True)
def samba_patch_actions():
"""Patch actions scripts runner."""
with patch('plinth.actions.superuser_run', side_effect=action_run):
yield
def make_request(request, view, **kwargs):
"""Make request with a message storage."""
setattr(request, 'session', 'session')
messages = FallbackStorage(request)
setattr(request, '_messages', messages)
response = view(request, **kwargs)
return response, messages
def test_samba_shares_view(rf):
"""Test that a share list has correct view data."""
with patch('plinth.views.AppView.get_context_data', return_value={
'is_enabled': True
}), patch('plinth.modules.samba.get_users',
return_value=USERS), patch('plinth.modules.storage.get_mounts',
return_value=DISKS):
view = views.SambaAppView.as_view()
response, _ = make_request(rf.get(''), view)
assert response.context_data['disks'] == DISKS
assert response.context_data['shared_mounts'] == {
'/': ['open', 'home'],
'/media/root/otherdisk': ['open']
}
assert response.context_data['unavailable_shares'] == [{
'mount_point':
'/media/root/otherdisk',
'name':
'otherdisk',
'path':
'/media/root/otherdisk/FreedomBox/shares/homes/open_share',
'share_type':
'open'
}]
assert response.context_data['users'] == USERS
assert response.status_code == 200
def test_enable_samba_share_view(rf):
"""Test that enabling share sends correct success message."""
form_data = {'filesystem_type': 'ext4', 'open_share': 'enable'}
mount_point = urllib.parse.quote('/')
response, messages = make_request(
rf.post('', data=form_data), views.share, mount_point=mount_point)
assert list(messages)[0].message == 'Share enabled.'
assert response.status_code == 302
assert response.url == urls.reverse('samba:index')
def test_enable_samba_share_failed_view(rf):
"""Test that share enabling failure sends correct error message."""
form_data = {'filesystem_type': 'ext4', 'open_share': 'enable'}
mount_point = urllib.parse.quote('/')
error_message = 'Sharing failed'
with patch('plinth.modules.samba.add_share',
side_effect=ActionError(error_message)):
response, messages = make_request(
rf.post('', data=form_data), views.share, mount_point=mount_point)
assert list(messages)[0].message == 'Error enabling share: {0}'.format(
error_message)
assert response.status_code == 302
assert response.url == urls.reverse('samba:index')
def test_disable_samba_share(rf):
"""Test that enabling share sends correct success message."""
form_data = {'filesystem_type': 'ext4', 'open_share': 'disable'}
mount_point = urllib.parse.quote('/')
response, messages = make_request(
rf.post('', data=form_data), views.share, mount_point=mount_point)
assert list(messages)[0].message == 'Share disabled.'
assert response.status_code == 302
assert response.url == urls.reverse('samba:index')
def test_disable_samba_share_failed_view(rf):
"""Test that share disabling failure sends correct error message."""
form_data = {'filesystem_type': 'ext4', 'open_share': 'disable'}
mount_point = urllib.parse.quote('/')
error_message = 'Unsharing failed'
with patch('plinth.modules.samba.delete_share',
side_effect=ActionError(error_message)):
response, messages = make_request(
rf.post('', data=form_data), views.share, mount_point=mount_point)
assert list(messages)[
0].message == 'Error disabling share: {0}'.format(error_message)
assert response.status_code == 302
assert response.url == urls.reverse('samba:index')