backups: Minor styling changes

- Add docstrings.

- Add blank lines for extra readability.

- Use <span> instead of <i> tag for icon in template.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Joseph Nuthalapati <njoseph@thoughtworks.com>
This commit is contained in:
Sunil Mohan Adapa 2019-06-24 16:46:23 -07:00 committed by Joseph Nuthalapati
parent 984b7dca88
commit 661a00198e
No known key found for this signature in database
GPG Key ID: 5398F00A2FA43C35
6 changed files with 30 additions and 9 deletions

View File

@ -148,7 +148,9 @@ def restore_from_upload(path, apps=None):
def is_ssh_hostkey_verified(hostname):
"""Check whether SSH Hostkey has already been verified.
hostname: Domain name or IP address of the host
"""
known_hosts_path = cfg.known_hosts
if not os.path.exists(known_hosts_path):
@ -164,5 +166,6 @@ def split_path(path):
Network interface information is kept in the hostname if provided.
e.g. fe80::2078:6c26:498a:1fa5%wlp1s0
"""
return re.findall(r'^(.*)@([^/]*):(.*)$', path)[0]

View File

@ -59,6 +59,7 @@ def _get_repository_choices():
for storage in storages.values():
if storage['verified']:
choices += [(storage['uuid'], storage['path'])]
return choices
@ -99,6 +100,7 @@ class UploadForm(forms.Form):
def repository_validator(path):
"""Validate an SSH repository path."""
if not ('@' in path and ':' in path):
raise ValidationError(_('Repository path format incorrect.'))
@ -125,6 +127,7 @@ def repository_validator(path):
class AddRepositoryForm(forms.Form):
"""Form to add new SSH remote repository."""
repository = forms.CharField(
label=_('SSH Repository Path'), strip=True,
help_text=_('Path of a new or existing repository. Example: '
@ -161,19 +164,23 @@ class AddRepositoryForm(forms.Form):
return self.cleaned_data
def clean_repository(self):
"""Validate repository form field."""
path = self.cleaned_data.get('repository')
# Avoid creation of duplicate ssh remotes
self._check_if_duplicate_remote(path)
return path
def _check_if_duplicate_remote(self, path):
for ns in network_storage.get_storages().values():
if ns['path'] == path:
@staticmethod
def _check_if_duplicate_remote(path):
"""Raise validation error if given path is a stored remote."""
for storage in network_storage.get_storages().values():
if storage['path'] == path:
raise forms.ValidationError(
_('Remote backup repository already exists.'))
class VerifySshHostkeyForm(forms.Form):
"""Form to verify the SSH public key for a host."""
ssh_public_key = forms.ChoiceField(
label=_('Select verified SSH public key'), widget=forms.RadioSelect)
@ -184,9 +191,9 @@ class VerifySshHostkeyForm(forms.Form):
self.fields['ssh_public_key'].choices = self._get_all_public_keys(
hostname)
def _get_all_public_keys(self, hostname):
"""Use ssh-keyscan to get all the SSH public keys of the
given hostname."""
@staticmethod
def _get_all_public_keys(hostname):
"""Use ssh-keyscan to get all the SSH public keys of a host."""
# Fetch public keys of ssh remote
res1 = subprocess.run(['ssh-keyscan', hostname],
stdout=subprocess.PIPE,

View File

@ -311,6 +311,7 @@ class SshBorgRepository(BorgRepository):
"""Initialize / create a borg repository."""
if encryption not in SUPPORTED_BORG_ENCRYPTION:
raise ValueError('Unsupported encryption: %s' % encryption)
self.run(
['init', '--path', self.repo_path, '--encryption', encryption])

View File

@ -264,7 +264,7 @@ class DownloadArchiveView(View):
class AddRepositoryView(SuccessMessageMixin, FormView):
"""View to verify the SSH Hostkey of the server and save repository."""
"""View to create a new remote backup repository."""
form_class = forms.AddRepositoryForm
template_name = 'backups_repository_add.html'
success_url = reverse_lazy('backups:index')
@ -319,6 +319,7 @@ class VerifySshHostkeyView(SuccessMessageMixin, FormView):
if not self.repo_data:
uuid = self.kwargs['uuid']
self.repo_data = network_storage.get(uuid)
return self.repo_data
def _get_hostname(self):
@ -346,6 +347,7 @@ class VerifySshHostkeyView(SuccessMessageMixin, FormView):
known_hosts_file.write('\n')
def get(self, *args, **kwargs):
"""Skip this view if host is already verified."""
if is_ssh_hostkey_verified(self._get_hostname()):
self._add_remote_repository()
messages.success(self.request,
@ -363,6 +365,7 @@ class VerifySshHostkeyView(SuccessMessageMixin, FormView):
return super().form_valid(form)
def _add_remote_repository(self):
"""On successful verification of host, add repository."""
repo_data = self._get_repo_data()
path = repo_data['path']
credentials = repo_data['credentials']
@ -476,21 +479,26 @@ class RemoveRepositoryView(SuccessMessageMixin, TemplateView):
messages.success(
request,
_('Repository removed. The remote backup itself was not deleted.'))
return redirect('backups:index')
def umount_repository(request, uuid):
"""View to unmount a remote SSH repository."""
repository = SshBorgRepository(uuid=uuid)
repository.umount()
if repository.is_mounted:
messages.error(request, _('Unmounting failed!'))
return redirect('backups:index')
def mount_repository(request, uuid):
"""View to mount a remote SSH repository."""
# Do not mount unverified ssh repositories. Prompt for verification.
if not network_storage.get(uuid).get('verified'):
return redirect('backups:verify-ssh-hostkey', uuid=uuid)
repository = SshBorgRepository(uuid=uuid)
try:
repository.mount()
@ -500,4 +508,5 @@ def mount_repository(request, uuid):
else:
if not repository.is_mounted:
messages.error(request, _('Mounting failed'))
return redirect('backups:index')

View File

@ -25,7 +25,8 @@
<p>
<button type="button" class="btn btn-default collapsed collapsible-button"
data-toggle="collapse" data-target="#clients">
<i class="fa fa-chevron-right fa-fw" aria-hidden="true"></i> {% trans "Client Apps" %}
<span class="fa fa-chevron-right fa-fw" aria-hidden="true"></span>
{% trans "Client Apps" %}
</button>
</p>

View File

@ -244,7 +244,7 @@ footer {
content: "\f054";
}
/* No-JS fallbacks for collapsible content in clients.html */
/* No-JS fallbacks for collapsible content */
.no-js .collapse {
display: block;
}