Akihiro Motoki 6bf20357fe Django 2.0 support
Replace django.core.urlresolves with django.urls

(In Django 2.0) The django.core.urlresolvers module is removed
in favor of its new location, django.urls.
It was deprecated in Django 1.10:

Note that this commit does not add py35dj20 like other horizon plugins
because there is no actual python unit tests in freezer-web-ui.

Older Django unit tests were dropped from tox.ini
as horizon dropped Django <=1.10 support in Rocky.

Change-Id: I38f3f05655324f2a5f38c6e8c6ab53ebaa42d4c8
2018-05-14 02:34:28 +09:00

223 lines
7.2 KiB

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import logging
import datetime
import re
from functools import wraps
from django.urls import reverse
from django.template.defaultfilters import date as django_date
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import get_user_home
from oslo_utils import uuidutils
LOG = logging.getLogger(__name__)
def create_dict(**kwargs):
"""Create a dict only with values that exists so we avoid send keys with
None values
return {k: v for k, v in kwargs.items() if v}
def timestamp_to_string(ts):
return django_date(
def create_dummy_id():
"""Generate a dummy id for documents generated by the scheduler.
This is needed when the scheduler creates jobs with actions attached
directly, those actions are not registered in the db.
return uuidutils.generate_uuid(dashed=False)
def get_action_ids(ids):
"""Return an ordered list of actions for a new job
ids = ids.split('===')
return [i for i in ids if i]
def assign_and_remove(source_dict, dest_dict, key):
"""Assign a value to a destination dict from a source dict
if the key exists
if key in source_dict:
dest_dict[key] = source_dict.pop(key)
class SessionObject(object):
def __init__(self, session_id, description, status, jobs,
start_datetime, interval, end_datetime):
self.session_id = session_id = session_id
self.description = description
self.status = status = jobs or []
self.schedule_start_date = start_datetime
self.schedule_end_date = end_datetime
self.schedule_interval = interval
class JobObject(object):
def __init__(self, job_id, description, result, event, client_id='_'):
self.job_id = job_id = job_id
self.description = description
self._result = result
self._event = event
# Checking if client_id composed like <tenant_id>_<hostname>
if"^[a-z0-9]{32}_.+", client_id):
self.client_id = client_id.split('_')[1]
self.client_id = client_id
def event(self):
return self._event or 'stop'
def result(self):
return self._result or 'pending'
class JobsInSessionObject(object):
def __init__(self, job_id, session_id, client_id, result):
self.job_id = job_id
self.session_id = session_id = session_id
self.client_id = client_id
self.result = result or 'pending'
class ActionObject(object):
def __init__(self, action_id=None, action=None, backup_name=None,
# action basic info = action_id
self.action_id = action_id or create_dummy_id()
self.action = action or 'backup'
self.backup_name = backup_name or 'no backup name available'
self.job_id = job_id
class ActionObjectDetail(object):
def __init__(self, action_id=None, action=None, backup_name=None,
path_to_backup=None, storage=None, mode=None, container=None,
mandatory=None, max_retries=None, max_retries_interval=None):
# action basic info = action_id
self.action_id = action_id or create_dummy_id()
self.action = action or 'backup'
self.backup_name = backup_name or 'no backup name available'
self.path_to_backup = path_to_backup = storage or 'swift'
self.mode = mode or 'fs'
self.container = container
# action rules
self.mandatory = mandatory
self.max_retries = max_retries
self.max_retries_interval = max_retries_interval
class BackupObject(object):
def __init__(self, backup_id=None, action=None, time_stamp=None,
backup_name=None, backup_media=None, path_to_backup=None,
hostname=None, level=None, container=None,
curr_backup_level=None, encrypted=None,
total_broken_links=None, excluded_files=None, storage=None,
ssh_host=None, ssh_key=None, ssh_username=None,
ssh_port=None, mode=None):
self.backup_id = backup_id = backup_id
self.backup_name = backup_name
self.action = action or 'backup'
self.time_stamp = time_stamp
self.backup_media = backup_media or 'fs'
self.path_to_backup = path_to_backup
self.hostname = hostname
self.container = container
self.level = level
self.curr_backup_level = curr_backup_level or 0
self.encrypted = encrypted
self.total_broken_links = total_broken_links or 0
self.excluded_files = excluded_files = storage
self.ssh_host = ssh_host
self.ssh_key = ssh_key
self.ssh_username = ssh_username
self.ssh_port = ssh_port or 22
self.mode = mode or 'fs'
class ClientObject(object):
def __init__(self, hostname, client_id, client_uuid):
self.hostname = hostname
self.client_id = client_id
self.uuid = client_uuid = client_id
def shield(message, redirect=''):
"""decorator to reduce boilerplate try except blocks for horizon functions
:param message: a str error message
:param redirect: a str with the redirect namespace without including
eg. @shield('error', redirect='jobs:index')
def wrap(function):
def wrapped_function(view, *args, **kwargs):
return function(view, *args, **kwargs)
except Exception as error:
namespace = "horizon:disaster_recovery:"
r = reverse("{0}{1}".format(namespace, redirect))
if view.request.path == r:
# To avoid an endless loop, we must not redirect to the
# same page on which the error happened
user_home = get_user_home(view.request.user)
exceptions.handle(view.request, _(error.message),
exceptions.handle(view.request, _(error.message),
return wrapped_function
return wrap
def timestamp_to_iso(ts):
"""Generate an iso date from time stamp
:param ts: time stamp
:return: iso date
return datetime.datetime.fromtimestamp(ts).isoformat()