mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-05-20 10:34:30 +00:00
backups: Rename network_storage module to store
Same module is being used to store/retrieve local disk repositories also. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
5df34d1927
commit
0df07f5cf2
@ -32,7 +32,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
from plinth.modules.storage import get_disks
|
from plinth.modules.storage import get_disks
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from . import ROOT_REPOSITORY_NAME, api, network_storage, split_path
|
from . import ROOT_REPOSITORY_NAME, api, split_path, store
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ def _get_app_choices(apps):
|
|||||||
def _get_repository_choices():
|
def _get_repository_choices():
|
||||||
"""Return the list of available repositories."""
|
"""Return the list of available repositories."""
|
||||||
choices = [('root', ROOT_REPOSITORY_NAME)]
|
choices = [('root', ROOT_REPOSITORY_NAME)]
|
||||||
storages = network_storage.get_storages()
|
storages = store.get_storages()
|
||||||
for storage in storages.values():
|
for storage in storages.values():
|
||||||
if storage.get('verified'):
|
if storage.get('verified'):
|
||||||
choices += [(storage['uuid'], storage['path'])]
|
choices += [(storage['uuid'], storage['path'])]
|
||||||
@ -204,7 +204,7 @@ class AddRemoteRepositoryForm(EncryptedBackupsMixin, forms.Form):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def _check_if_duplicate_remote(path):
|
def _check_if_duplicate_remote(path):
|
||||||
"""Raise validation error if given path is a stored remote."""
|
"""Raise validation error if given path is a stored remote."""
|
||||||
for storage in network_storage.get_storages().values():
|
for storage in store.get_storages().values():
|
||||||
if storage['path'] == path:
|
if storage['path'] == path:
|
||||||
raise forms.ValidationError(
|
raise forms.ValidationError(
|
||||||
_('Remote backup repository already exists.'))
|
_('Remote backup repository already exists.'))
|
||||||
|
|||||||
@ -31,8 +31,8 @@ from plinth import actions
|
|||||||
from plinth.errors import ActionError
|
from plinth.errors import ActionError
|
||||||
|
|
||||||
from . import (ROOT_REPOSITORY, ROOT_REPOSITORY_NAME, ROOT_REPOSITORY_UUID,
|
from . import (ROOT_REPOSITORY, ROOT_REPOSITORY_NAME, ROOT_REPOSITORY_UUID,
|
||||||
_backup_handler, api, get_known_hosts_path, network_storage,
|
_backup_handler, api, get_known_hosts_path,
|
||||||
restore_archive_handler)
|
restore_archive_handler, store)
|
||||||
from .errors import BorgError, BorgRepositoryDoesNotExistError, SshfsError
|
from .errors import BorgError, BorgRepositoryDoesNotExistError, SshfsError
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -127,7 +127,7 @@ class BaseBorgRepository(abc.ABC):
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
def _load_from_kvstore(self):
|
def _load_from_kvstore(self):
|
||||||
storage = network_storage.get(self.uuid)
|
storage = store.get(self.uuid)
|
||||||
try:
|
try:
|
||||||
self.credentials = storage['credentials']
|
self.credentials = storage['credentials']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@ -269,7 +269,7 @@ class BaseBorgRepository(abc.ABC):
|
|||||||
create_subvolume=False, backup_file=archive_path,
|
create_subvolume=False, backup_file=archive_path,
|
||||||
encryption_passphrase=passphrase)
|
encryption_passphrase=passphrase)
|
||||||
|
|
||||||
def _get_network_storage_format(self, store_credentials, verified):
|
def _get_storage_format(self, store_credentials, verified):
|
||||||
storage = {
|
storage = {
|
||||||
'path': self._path,
|
'path': self._path,
|
||||||
'storage_type': self.storage_type,
|
'storage_type': self.storage_type,
|
||||||
@ -287,8 +287,8 @@ class BaseBorgRepository(abc.ABC):
|
|||||||
Save the repository in network_storage (kvstore).
|
Save the repository in network_storage (kvstore).
|
||||||
- store_credentials: Boolean whether credentials should be stored.
|
- store_credentials: Boolean whether credentials should be stored.
|
||||||
"""
|
"""
|
||||||
storage = self._get_network_storage_format(store_credentials, verified)
|
storage = self._get_storage_format(store_credentials, verified)
|
||||||
self.uuid = network_storage.update_or_add(storage)
|
self.uuid = store.update_or_add(storage)
|
||||||
|
|
||||||
|
|
||||||
class RootBorgRepository(BaseBorgRepository):
|
class RootBorgRepository(BaseBorgRepository):
|
||||||
@ -327,7 +327,7 @@ class BorgRepository(BaseBorgRepository):
|
|||||||
|
|
||||||
def remove_repository(self):
|
def remove_repository(self):
|
||||||
"""Remove a repository from the kvstore and delete its mountpoint"""
|
"""Remove a repository from the kvstore and delete its mountpoint"""
|
||||||
network_storage.delete(self.uuid)
|
store.delete(self.uuid)
|
||||||
|
|
||||||
|
|
||||||
class SshBorgRepository(BaseBorgRepository):
|
class SshBorgRepository(BaseBorgRepository):
|
||||||
@ -382,7 +382,7 @@ class SshBorgRepository(BaseBorgRepository):
|
|||||||
def remove_repository(self):
|
def remove_repository(self):
|
||||||
"""Remove a repository from the kvstore and delete its mountpoint"""
|
"""Remove a repository from the kvstore and delete its mountpoint"""
|
||||||
self.umount()
|
self.umount()
|
||||||
network_storage.delete(self.uuid)
|
store.delete(self.uuid)
|
||||||
try:
|
try:
|
||||||
if os.path.exists(self.mountpoint):
|
if os.path.exists(self.mountpoint):
|
||||||
try:
|
try:
|
||||||
@ -411,7 +411,7 @@ class SshBorgRepository(BaseBorgRepository):
|
|||||||
def get_repositories():
|
def get_repositories():
|
||||||
"""Get all repositories of a given storage type."""
|
"""Get all repositories of a given storage type."""
|
||||||
repositories = [create_repository(ROOT_REPOSITORY_UUID)]
|
repositories = [create_repository(ROOT_REPOSITORY_UUID)]
|
||||||
for uuid in network_storage.get_storages():
|
for uuid in store.get_storages():
|
||||||
repositories.append(create_repository(uuid))
|
repositories.append(create_repository(uuid))
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -425,8 +425,8 @@ def create_repository(uuid):
|
|||||||
if uuid == ROOT_REPOSITORY_UUID:
|
if uuid == ROOT_REPOSITORY_UUID:
|
||||||
return RootBorgRepository(path=ROOT_REPOSITORY)
|
return RootBorgRepository(path=ROOT_REPOSITORY)
|
||||||
|
|
||||||
storage = network_storage.get(uuid)
|
storage = store.get(uuid)
|
||||||
if storage['storage_type'] == 'ssh':
|
if storage['storage_type'] == 'ssh':
|
||||||
return SshBorgRepository(uuid=uuid)
|
return SshBorgRepository(uuid=uuid)
|
||||||
else:
|
|
||||||
return BorgRepository(uuid=uuid)
|
return BorgRepository(uuid=uuid)
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
"""
|
"""
|
||||||
Manage remote (network) storage storages in plinths' KVStore.
|
Manage storage of repository information in KVStore table in database.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
@ -23,32 +23,39 @@ from uuid import uuid1
|
|||||||
|
|
||||||
from plinth import kvstore
|
from plinth import kvstore
|
||||||
|
|
||||||
# kvstore key for network storage
|
# kvstore key for repository store
|
||||||
NETWORK_STORAGE_KEY = 'network_storage'
|
STORAGE_KEY = 'network_storage'
|
||||||
REQUIRED_FIELDS = ['path', 'storage_type', 'added_by_module']
|
REQUIRED_FIELDS = ['path', 'storage_type', 'added_by_module']
|
||||||
|
|
||||||
|
|
||||||
def get_storages(storage_type=None):
|
def get_storages(storage_type=None):
|
||||||
"""Get network storages"""
|
"""Get all repositories from store."""
|
||||||
storages = kvstore.get_default(NETWORK_STORAGE_KEY, {})
|
storages = kvstore.get_default(STORAGE_KEY, {})
|
||||||
if storages:
|
if storages:
|
||||||
storages = json.loads(storages)
|
storages = json.loads(storages)
|
||||||
|
|
||||||
if storage_type:
|
if storage_type:
|
||||||
storages = {uuid: storage for uuid, storage in storages.items() if
|
storages = {
|
||||||
storage['storage_type'] == storage_type}
|
uuid: storage
|
||||||
|
for uuid, storage in storages.items()
|
||||||
|
if storage['storage_type'] == storage_type
|
||||||
|
}
|
||||||
|
|
||||||
return storages
|
return storages
|
||||||
|
|
||||||
|
|
||||||
def get(uuid):
|
def get(uuid):
|
||||||
|
"""Return a repository with given UUID from store."""
|
||||||
storages = get_storages()
|
storages = get_storages()
|
||||||
return storages[uuid]
|
return storages[uuid]
|
||||||
|
|
||||||
|
|
||||||
def update_or_add(storage):
|
def update_or_add(storage):
|
||||||
"""Update an existing or create a new network storage"""
|
"""Update an existing or create a new repository in store."""
|
||||||
for field in REQUIRED_FIELDS:
|
for field in REQUIRED_FIELDS:
|
||||||
if field not in storage:
|
if field not in storage:
|
||||||
raise ValueError('missing storage parameter: %s' % field)
|
raise ValueError('missing storage parameter: %s' % field)
|
||||||
|
|
||||||
existing_storages = get_storages()
|
existing_storages = get_storages()
|
||||||
if 'uuid' in storage:
|
if 'uuid' in storage:
|
||||||
# Replace the existing storage
|
# Replace the existing storage
|
||||||
@ -57,12 +64,13 @@ def update_or_add(storage):
|
|||||||
uuid = str(uuid1())
|
uuid = str(uuid1())
|
||||||
storage['uuid'] = uuid
|
storage['uuid'] = uuid
|
||||||
existing_storages[uuid] = storage
|
existing_storages[uuid] = storage
|
||||||
kvstore.set(NETWORK_STORAGE_KEY, json.dumps(existing_storages))
|
|
||||||
|
kvstore.set(STORAGE_KEY, json.dumps(existing_storages))
|
||||||
return storage['uuid']
|
return storage['uuid']
|
||||||
|
|
||||||
|
|
||||||
def delete(uuid):
|
def delete(uuid):
|
||||||
"""Remove a network storage from kvstore"""
|
"""Remove a repository from store."""
|
||||||
storages = get_storages()
|
storages = get_storages()
|
||||||
del storages[uuid]
|
del storages[uuid]
|
||||||
kvstore.set(NETWORK_STORAGE_KEY, json.dumps(storages))
|
kvstore.set(STORAGE_KEY, json.dumps(storages))
|
||||||
@ -20,26 +20,29 @@ Test network storage.
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from plinth.modules.backups import network_storage
|
from plinth.modules.backups import store
|
||||||
|
|
||||||
pytestmark = pytest.mark.django_db
|
pytestmark = pytest.mark.django_db
|
||||||
|
|
||||||
_storages = [{
|
_storages = [
|
||||||
'path': 'test@nonexistent.org:~/',
|
{
|
||||||
'storage_type': 'ssh',
|
'path': 'test@nonexistent.org:~/',
|
||||||
'added_by_module': 'test'
|
'storage_type': 'ssh',
|
||||||
}, {
|
'added_by_module': 'test'
|
||||||
'path': 'test@nonexistent.org:~/tmp/repo/',
|
},
|
||||||
'storage_type': 'ssh',
|
{
|
||||||
'added_by_module': 'test'
|
'path': 'test@nonexistent.org:~/tmp/repo/',
|
||||||
}]
|
'storage_type': 'ssh',
|
||||||
|
'added_by_module': 'test'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_add():
|
def test_add():
|
||||||
"""Add a storage item"""
|
"""Add a storage item"""
|
||||||
storage = _storages[0]
|
storage = _storages[0]
|
||||||
uuid = network_storage.update_or_add(storage)
|
uuid = store.update_or_add(storage)
|
||||||
_storage = network_storage.get(uuid)
|
_storage = store.get(uuid)
|
||||||
assert _storage['path'] == storage['path']
|
assert _storage['path'] == storage['path']
|
||||||
|
|
||||||
|
|
||||||
@ -50,7 +53,7 @@ def test_add_invalid():
|
|||||||
'added_by_module': 'test'
|
'added_by_module': 'test'
|
||||||
}
|
}
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
network_storage.update_or_add(storage_with_missing_type)
|
store.update_or_add(storage_with_missing_type)
|
||||||
|
|
||||||
|
|
||||||
def test_remove():
|
def test_remove():
|
||||||
@ -58,12 +61,12 @@ def test_remove():
|
|||||||
storage = _storages[0]
|
storage = _storages[0]
|
||||||
uuid = None
|
uuid = None
|
||||||
for storage in _storages:
|
for storage in _storages:
|
||||||
uuid = network_storage.update_or_add(storage)
|
uuid = store.update_or_add(storage)
|
||||||
|
|
||||||
storages = network_storage.get_storages()
|
storages = store.get_storages()
|
||||||
assert len(storages) == 2
|
assert len(storages) == 2
|
||||||
network_storage.delete(uuid)
|
store.delete(uuid)
|
||||||
storages = network_storage.get_storages()
|
storages = store.get_storages()
|
||||||
assert len(storages) == 1
|
assert len(storages) == 1
|
||||||
|
|
||||||
|
|
||||||
@ -71,11 +74,11 @@ def test_update():
|
|||||||
"""Update existing storage items"""
|
"""Update existing storage items"""
|
||||||
uuid = None
|
uuid = None
|
||||||
for storage in _storages:
|
for storage in _storages:
|
||||||
uuid = network_storage.update_or_add(storage)
|
uuid = store.update_or_add(storage)
|
||||||
|
|
||||||
storage = network_storage.get(uuid)
|
storage = store.get(uuid)
|
||||||
new_path = 'test@nonexistent.org:~/tmp/repo_new/'
|
new_path = 'test@nonexistent.org:~/tmp/repo_new/'
|
||||||
storage['path'] = new_path
|
storage['path'] = new_path
|
||||||
network_storage.update_or_add(storage)
|
store.update_or_add(storage)
|
||||||
_storage = network_storage.get(uuid)
|
_storage = store.get(uuid)
|
||||||
assert _storage['path'] == new_path
|
assert _storage['path'] == new_path
|
||||||
@ -39,7 +39,7 @@ from plinth.errors import PlinthError
|
|||||||
from plinth.modules import backups, storage
|
from plinth.modules import backups, storage
|
||||||
|
|
||||||
from . import (SESSION_PATH_VARIABLE, api, forms,
|
from . import (SESSION_PATH_VARIABLE, api, forms,
|
||||||
get_known_hosts_path, is_ssh_hostkey_verified, network_storage,
|
get_known_hosts_path, is_ssh_hostkey_verified, store,
|
||||||
split_path)
|
split_path)
|
||||||
from .decorators import delete_tmp_backup_file
|
from .decorators import delete_tmp_backup_file
|
||||||
from .errors import BorgRepositoryDoesNotExistError
|
from .errors import BorgRepositoryDoesNotExistError
|
||||||
@ -329,7 +329,7 @@ class VerifySshHostkeyView(SuccessMessageMixin, FormView):
|
|||||||
"""Fetch the repository data from DB only once."""
|
"""Fetch the repository data from DB only once."""
|
||||||
if not self.repo_data:
|
if not self.repo_data:
|
||||||
uuid = self.kwargs['uuid']
|
uuid = self.kwargs['uuid']
|
||||||
self.repo_data = network_storage.get(uuid)
|
self.repo_data = store.get(uuid)
|
||||||
|
|
||||||
return self.repo_data
|
return self.repo_data
|
||||||
|
|
||||||
@ -404,7 +404,7 @@ class VerifySshHostkeyView(SuccessMessageMixin, FormView):
|
|||||||
messages.error(self.request, _('Repository removed.'))
|
messages.error(self.request, _('Repository removed.'))
|
||||||
# Delete the repository so that the user can have another go at
|
# Delete the repository so that the user can have another go at
|
||||||
# creating it.
|
# creating it.
|
||||||
network_storage.delete(uuid)
|
store.delete(uuid)
|
||||||
return redirect(reverse_lazy('backups:add-remote-repository'))
|
return redirect(reverse_lazy('backups:add-remote-repository'))
|
||||||
|
|
||||||
|
|
||||||
@ -494,7 +494,7 @@ def umount_repository(request, uuid):
|
|||||||
def mount_repository(request, uuid):
|
def mount_repository(request, uuid):
|
||||||
"""View to mount a remote SSH repository."""
|
"""View to mount a remote SSH repository."""
|
||||||
# Do not mount unverified ssh repositories. Prompt for verification.
|
# Do not mount unverified ssh repositories. Prompt for verification.
|
||||||
if not network_storage.get(uuid).get('verified'):
|
if not store.get(uuid).get('verified'):
|
||||||
return redirect('backups:verify-ssh-hostkey', uuid=uuid)
|
return redirect('backups:verify-ssh-hostkey', uuid=uuid)
|
||||||
|
|
||||||
repository = SshBorgRepository(uuid=uuid)
|
repository = SshBorgRepository(uuid=uuid)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user