backups: Improve UX of adding ssh remote

- Create empty directory if not exists
- Check if the directory is empty
  - if not empty, check if it's an existing backup repository
  - else throw an error

Signed-off-by: Joseph Nuthalapati <njoseph@thoughtworks.com>
This commit is contained in:
Joseph Nuthalapati 2019-05-16 16:40:02 +05:30
parent 10cf3ee536
commit e618e08fe7
No known key found for this signature in database
GPG Key ID: 5398F00A2FA43C35
2 changed files with 44 additions and 7 deletions

View File

@ -31,9 +31,9 @@ from plinth.utils import format_lazy
from . import api
version = 2
version = 3
managed_packages = ['borgbackup', 'sshfs']
managed_packages = ['borgbackup', 'sshfs', 'python3-paramiko']
name = _('Backups')

View File

@ -18,6 +18,8 @@
Forms for backups module.
"""
import logging
import paramiko
from django import forms
from django.core.validators import FileExtensionValidator
from django.utils.translation import ugettext, ugettext_lazy as _
@ -28,6 +30,8 @@ from . import api, network_storage, ROOT_REPOSITORY_NAME
from .errors import BorgRepositoryDoesNotExistError
from .repository import SshBorgRepository
logger = logging.getLogger(__name__)
def _get_app_choices(apps):
"""Return a list of check box multiple choices from list of apps."""
@ -130,6 +134,14 @@ class AddRepositoryForm(forms.Form):
return credentials
def clean(self):
"""
Validation of SSH remote
* Create empty directory if not exists
* Check if the directory is empty
- if not empty, check if it's an existing backup repository
- else throw an error
"""
cleaned_data = super(AddRepositoryForm, self).clean()
passphrase = cleaned_data.get("encryption_passphrase")
confirm_passphrase = cleaned_data.get("confirm_encryption_passphrase")
@ -141,12 +153,37 @@ class AddRepositoryForm(forms.Form):
path = cleaned_data.get("repository")
credentials = self.get_credentials()
# Validate remote
user_at_host, dir_path = path.split(':')
username, hostname = user_at_host.split('@')
dir_path = dir_path.replace('~', f'/home/{username}')
password = credentials['ssh_password']
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
self.repository = SshBorgRepository(path=path,
credentials=credentials)
self.repository.get_info()
except BorgRepositoryDoesNotExistError:
pass
ssh_client.connect(hostname, username=username, password=password)
except Exception as err:
msg = _('Accessing the remote repository failed. Details: %(err)s')
raise forms.ValidationError(msg, params={'err': str(err)})
else:
with ssh_client.open_sftp() as sftp_client:
try:
dir_contents = sftp_client.listdir(dir_path)
except FileNotFoundError:
logger.info(
_(f"Directory {dir_path} doesn't exist. Creating ..."))
sftp_client.mkdir(dir_path)
else:
if dir_contents:
try:
self.repository = SshBorgRepository(
path=path, credentials=credentials)
self.repository.get_info()
except BorgRepositoryDoesNotExistError:
msg = _(f'Directory {path.split(":")[-1]} is '
'neither empty nor is an existing '
'backups repository.')
raise forms.ValidationError(msg)
finally:
ssh_client.close()