Fix minor bugs in freezer dashboard

freezer dashboard now handles slashes in the dynamic urls
improve resilience of backup table
updated backup_id encoding when it contains slash or back slash

Change-Id: I66e6973e5b55cd8845ec90413867fe5694f1433a
This commit is contained in:
memo 2015-10-15 17:00:39 +01:00
parent 7b12891d57
commit d4c7b4d2f0
6 changed files with 51 additions and 43 deletions

View File

@ -401,6 +401,14 @@ def backups_list(request, offset=0, time_after=None, time_before=None,
def backup_get(request, backup_id): def backup_get(request, backup_id):
"""Get a single backup""" """Get a single backup"""
# for a local or ssh backup, the backup_id contains the
# path of the directory to backup, so that includes "/"
# or "\" for windows.
# so we send "--" instead "/" from the client to avoid
# conflicts in the api endpoint
backup_id = backup_id.replace("/", '--')
backup_id = backup_id.replace("\\", '--')
backup = _freezerclient(request).backups.get(backup_id) backup = _freezerclient(request).backups.get(backup_id)
backup = Backup(backup) backup = Backup(backup)
return backup return backup

View File

@ -47,12 +47,11 @@ def icons(backup):
level_txt = "Level: {} ({} backup) out of {}".format( level_txt = "Level: {} ({} backup) out of {}".format(
backup.level, "Full" if backup.level == 0 else "Incremental", backup.level, "Full" if backup.level == 0 else "Incremental",
backup.max_level) backup.max_level)
result.append(
'<i class="fa fa-fw fa-custom-number" title="{}">{}</i>'.format(
level_txt, backup.level))
except Exception: except Exception:
level_txt = 'N/A' result.append("Level: {}".format("Full"))
result.append(
'<i class="fa fa-fw fa-custom-number" title="{}">{}</i>'.format(
level_txt, backup.level))
try: try:
if backup.encrypted: if backup.encrypted:
@ -84,13 +83,12 @@ def icons(backup):
def backup_detail_view(backup): def backup_detail_view(backup):
return reverse("horizon:freezer_ui:backups:detail", return reverse("horizon:freezer_ui:backups:detail",
args=[backup.id]) args=[backup.backup_id])
class BackupsTable(tables.DataTable): class BackupsTable(tables.DataTable):
name = tables.Column('backup_name', backup_name = tables.Column('backup_name',
verbose_name=_("Backup Name"), verbose_name=_("Backup Name"))
link=backup_detail_view)
hostname = tables.Column('hostname', verbose_name=_("Hostname")) hostname = tables.Column('hostname', verbose_name=_("Hostname"))
created = tables.Column("time_stamp", created = tables.Column("time_stamp",
verbose_name=_("Created At"), verbose_name=_("Created At"),

View File

@ -51,9 +51,9 @@ class RestoreView(workflows.WorkflowView):
workflow_class = restore_workflow.Restore workflow_class = restore_workflow.Restore
def get_object(self, *args, **kwargs): def get_object(self, *args, **kwargs):
id = self.kwargs['backup_id'] backup_id = self.kwargs['backup_id']
try: try:
return freezer_api.backup_get(self.request, id) return freezer_api.backup_get(self.request, backup_id)
except Exception: except Exception:
redirect = reverse("horizon:freezer_ui:backups:index") redirect = reverse("horizon:freezer_ui:backups:index")
msg = _('Unable to retrieve details.') msg = _('Unable to retrieve details.')
@ -63,12 +63,13 @@ class RestoreView(workflows.WorkflowView):
return 'name' in self.kwargs and bool(self.kwargs['name']) return 'name' in self.kwargs and bool(self.kwargs['name'])
def get_workflow_name(self): def get_workflow_name(self):
backup = freezer_api.backup_get(self.request, self.kwargs['backup_id']) backup_id = self.kwargs['backup_id']
backup = freezer_api.backup_get(self.request, backup_id)
backup_date = datetime.datetime.fromtimestamp( backup_date = datetime.datetime.fromtimestamp(
int(backup.data_dict[0]['backup_metadata']['time_stamp'])) int(backup.data_dict['backup_metadata']['time_stamp']))
backup_date_str = django_date(backup_date, 'SHORT_DATETIME_FORMAT') backup_date_str = django_date(backup_date, 'SHORT_DATETIME_FORMAT')
return "Restore '{}' from {}".format( return "Restore '{}' from {}".format(
backup.data_dict[0]['backup_metadata']['backup_name'], backup.data_dict['backup_metadata']['backup_name'],
backup_date_str) backup_date_str)
def get_initial(self): def get_initial(self):
@ -77,5 +78,4 @@ class RestoreView(workflows.WorkflowView):
def get_workflow(self, *args, **kwargs): def get_workflow(self, *args, **kwargs):
workflow = super(RestoreView, self).get_workflow(*args, **kwargs) workflow = super(RestoreView, self).get_workflow(*args, **kwargs)
workflow.name = self.get_workflow_name() workflow.name = self.get_workflow_name()
return workflow return workflow

View File

@ -83,10 +83,10 @@ class Restore(workflows.Workflow):
"original_name": job, # this is the job_id "original_name": job, # this is the job_id
"action": "restore", "action": "restore",
"backup_name": "backup_name":
backup.data_dict[0]['backup_metadata']['backup_name'], backup.data_dict['backup_metadata']['backup_name'],
"restore_abs_path": data['path'], "restore_abs_path": data['path'],
"container": "container":
backup.data_dict[0]['backup_metadata']['container'], backup.data_dict['backup_metadata']['container'],
"restore_from_host": client.hostname, "restore_from_host": client.hostname,
"max_retries": 3, "max_retries": 3,
"max_retries_interval": 60, "max_retries_interval": 60,

View File

@ -324,12 +324,13 @@ class SnapshotConfiguration(workflows.Step):
contributes = ('use_snapshot', contributes = ('use_snapshot',
'is_windows', 'is_windows',
'vssadmin', 'vssadmin',
'lvm_auto_snap', # 'lvm_auto_snap',
'lvm_srcvol', # 'lvm_srcvol',
'lvm_snapname', # 'lvm_snapname',
'lvm_snapsize', # 'lvm_snapsize',
'lvm_dirmount', # 'lvm_dirmount',
'lvm_volgroup',) # 'lvm_volgroup',
)
class AdvancedConfigurationAction(workflows.Action): class AdvancedConfigurationAction(workflows.Action):
@ -527,25 +528,26 @@ class AdvancedConfigurationAction(workflows.Action):
class AdvancedConfiguration(workflows.Step): class AdvancedConfiguration(workflows.Step):
action_class = AdvancedConfigurationAction action_class = AdvancedConfigurationAction
contributes = ('log_file', contributes = ('log_file',
'exclude', # 'exclude',
'proxy', # 'proxy',
'os_auth_ver', # 'os_auth_ver',
'upload_limit', # 'upload_limit',
'download_limit', # 'download_limit',
'optimize', # 'optimize',
'compression', # 'compression',
'max_segment_size', # 'max_segment_size',
'hostname', # 'hostname',
'encryption_password', # 'encryption_password',
'no_incremental', # 'no_incremental',
'max_level', # 'max_level',
'always_level', # 'always_level',
'restart_always_level', # 'restart_always_level',
'insecure', # 'insecure',
'dereference_symlink', # 'dereference_symlink',
'dry_run', # 'dry_run',
'max_priority', # 'max_priority',
'quiet',) # 'quiet',
)
class RulesConfigurationAction(workflows.Action): class RulesConfigurationAction(workflows.Action):