415 lines
13 KiB
Python
415 lines
13 KiB
Python
# 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
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# 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.
|
|
|
|
# Some helper functions to use the freezer_ui client functionality
|
|
# from horizon.
|
|
|
|
|
|
import warnings
|
|
|
|
from django.conf import settings
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
from horizon.utils import functions as utils
|
|
from horizon.utils.memoized import memoized # noqa
|
|
|
|
import freezer.apiclient.client
|
|
from freezer_ui.utils import Action
|
|
from freezer_ui.utils import ActionJob
|
|
from freezer_ui.utils import Backup
|
|
from freezer_ui.utils import Client
|
|
from freezer_ui.utils import Job
|
|
from freezer_ui.utils import JobList
|
|
from freezer_ui.utils import Session
|
|
from freezer_ui.utils import create_dict_action
|
|
from freezer_ui.utils import create_dummy_id
|
|
from freezer_ui.utils import assign_value_from_source
|
|
|
|
|
|
@memoized
|
|
def get_hardcoded_url():
|
|
"""Get FREEZER_API_URL from local_settings.py"""
|
|
try:
|
|
warnings.warn(_('Using hardcoded FREEZER_API_URL at {0}')
|
|
.format(settings.FREEZER_API_URL))
|
|
return getattr(settings, 'FREEZER_API_URL', None)
|
|
except (AttributeError, TypeError):
|
|
warnings.warn(_('No FREEZER_API_URL was found in local_settings.py'))
|
|
raise
|
|
|
|
|
|
@memoized
|
|
def get_service_url(request):
|
|
"""Get Freezer API url from keystone catalog or local_settings.py
|
|
if Freezer is not set in keystone, the fallback will be
|
|
'FREEZER_API_URL' in local_settings.py
|
|
"""
|
|
catalog = (getattr(request.user, "service_catalog", None))
|
|
if not catalog:
|
|
return get_hardcoded_url()
|
|
|
|
for c in catalog:
|
|
if c['name'] == 'freezer':
|
|
for e in c['endpoints']:
|
|
return e['publicURL']
|
|
else:
|
|
return get_hardcoded_url()
|
|
|
|
|
|
@memoized
|
|
def _freezerclient(request):
|
|
api_url = get_service_url(request)
|
|
|
|
return freezer.apiclient.client.Client(
|
|
token=request.user.token.id,
|
|
auth_url=getattr(settings, 'OPENSTACK_KEYSTONE_URL'),
|
|
endpoint=api_url)
|
|
|
|
|
|
def job_create(request, context):
|
|
"""Create a new job file """
|
|
|
|
job = create_dict_action(**context)
|
|
|
|
schedule = {}
|
|
|
|
assign_value_from_source(job, schedule, 'schedule_end_date')
|
|
assign_value_from_source(job, schedule, 'schedule_interval')
|
|
assign_value_from_source(job, schedule, 'schedule_start_date')
|
|
|
|
job.pop('clients', None)
|
|
client_id = job.pop('client_id', None)
|
|
actions = job.pop('job_actions', [])
|
|
|
|
job['description'] = job.pop('description', None)
|
|
job['job_schedule'] = schedule
|
|
job['job_actions'] = actions
|
|
job['client_id'] = client_id
|
|
return _freezerclient(request).jobs.create(job)
|
|
|
|
|
|
def job_edit(request, context):
|
|
"""Edit an existing job file, but leave the actions to actions_edit"""
|
|
job = create_dict_action(**context)
|
|
|
|
schedule = {}
|
|
|
|
assign_value_from_source(job, schedule, 'schedule_end_date')
|
|
assign_value_from_source(job, schedule, 'schedule_interval')
|
|
assign_value_from_source(job, schedule, 'schedule_start_date')
|
|
|
|
job['description'] = job.pop('description', None)
|
|
actions = job.pop('job_actions', [])
|
|
|
|
job.pop('clients', None)
|
|
job.pop('client_id', None)
|
|
|
|
job['job_schedule'] = schedule
|
|
job['job_actions'] = actions
|
|
job_id = job.pop('original_name', None)
|
|
return _freezerclient(request).jobs.update(job_id, job)
|
|
|
|
|
|
def job_delete(request, obj_id):
|
|
return _freezerclient(request).jobs.delete(obj_id)
|
|
|
|
|
|
def job_clone(request, job_id):
|
|
job_file = _freezerclient(request).jobs.get(job_id)
|
|
job_file['description'] = \
|
|
'{0}_clone'.format(job_file['description'])
|
|
job_file.pop('job_id', None)
|
|
job_file.pop('_version', None)
|
|
return _freezerclient(request).jobs.create(job_file)
|
|
|
|
|
|
def job_get(request, job_id):
|
|
job_file = _freezerclient(request).jobs.get(job_id)
|
|
if job_file:
|
|
job_item = [job_file]
|
|
job = [Job(data) for data in job_item]
|
|
return job
|
|
return []
|
|
|
|
|
|
def job_list(request):
|
|
jobs = _freezerclient(request).jobs.list_all()
|
|
job_list = []
|
|
for j in jobs:
|
|
description = j['description']
|
|
job_id = j['job_id']
|
|
try:
|
|
result = j['job_schedule']['result']
|
|
except KeyError:
|
|
result = 'pending'
|
|
job_list.append(JobList(description, result, job_id))
|
|
return job_list
|
|
|
|
|
|
def action_create(request, context):
|
|
"""Create a new action for a job """
|
|
action = {}
|
|
|
|
assign_value_from_source(context, action, 'max_retries')
|
|
assign_value_from_source(context, action, 'max_retries_interval')
|
|
assign_value_from_source(context, action, 'mandatory')
|
|
|
|
job_id = context.pop('original_name')
|
|
job_action = create_dict_action(**context)
|
|
action['freezer_action'] = job_action
|
|
action_id = _freezerclient(request).actions.create(action)
|
|
action['action_id'] = action_id
|
|
job = _freezerclient(request).jobs.get(job_id)
|
|
job['job_actions'].append(action)
|
|
return _freezerclient(request).jobs.update(job_id, job)
|
|
|
|
|
|
def action_list(request):
|
|
actions = _freezerclient(request).actions.list()
|
|
actions = [Action(data) for data in actions]
|
|
return actions
|
|
|
|
|
|
def action_list_json(request):
|
|
return _freezerclient(request).actions.list()
|
|
|
|
|
|
def actions_in_job_json(request, job_id):
|
|
job = _freezerclient(request).jobs.get(job_id)
|
|
action_list = []
|
|
for action in job['job_actions']:
|
|
a = {
|
|
"action_id": action['action_id'],
|
|
"freezer_action": action['freezer_action']
|
|
}
|
|
action_list.append(a)
|
|
return action_list
|
|
|
|
|
|
def actions_in_job(request, job_id):
|
|
actions = []
|
|
try:
|
|
job = _freezerclient(request).jobs.get(job_id)
|
|
for a in job['job_actions']:
|
|
try:
|
|
action_id = a['action_id']
|
|
except (KeyError, TypeError):
|
|
action_id = create_dummy_id()
|
|
|
|
try:
|
|
action = a['freezer_action']['action']
|
|
except (KeyError, TypeError):
|
|
action = "backup"
|
|
|
|
try:
|
|
backup_name = a['freezer_action']['backup_name']
|
|
except (KeyError, TypeError):
|
|
backup_name = "NO BACKUP NAME AVAILABLE"
|
|
|
|
actions.append(ActionJob(job_id, action_id, action, backup_name))
|
|
except TypeError:
|
|
pass
|
|
|
|
return actions
|
|
|
|
|
|
def action_get(request, action_id):
|
|
action = _freezerclient(request).actions.get(action_id)
|
|
return action
|
|
|
|
|
|
def action_update(request, context):
|
|
job_id = context.pop('original_name')
|
|
action_id = context.pop('action_id')
|
|
|
|
job = _freezerclient(request).jobs.get(job_id)
|
|
|
|
for a in job['job_actions']:
|
|
if a['action_id'] == action_id:
|
|
|
|
assign_value_from_source(context, a, 'max_retries')
|
|
assign_value_from_source(context, a, 'max_retries_interval')
|
|
assign_value_from_source(context, a, 'mandatory')
|
|
|
|
updated_action = create_dict_action(**context)
|
|
|
|
a['freezer_action'].update(updated_action)
|
|
|
|
return _freezerclient(request).jobs.update(job_id, job)
|
|
|
|
|
|
def action_delete(request, ids):
|
|
action_id, job_id = ids.split('===')
|
|
job = _freezerclient(request).jobs.get(job_id)
|
|
for action in job['job_actions']:
|
|
if action['action_id'] == action_id:
|
|
job['job_actions'].remove(action)
|
|
return _freezerclient(request).jobs.update(job_id, job)
|
|
|
|
|
|
def client_list(request):
|
|
clients = _freezerclient(request).registration.list()
|
|
clients = [Client(c['uuid'],
|
|
c['client']['hostname'],
|
|
c['client']['client_id'])
|
|
for c in clients]
|
|
return clients
|
|
|
|
|
|
def client_list_json(request):
|
|
"""Return a list of clients directly form the api in json format"""
|
|
clients = _freezerclient(request).registration.list()
|
|
return clients
|
|
|
|
|
|
def client_get(request, client_id):
|
|
"""Get a single client"""
|
|
client = _freezerclient(request).registration.get(client_id)
|
|
client = Client(client['uuid'],
|
|
client['client']['hostname'],
|
|
client['client']['client_id'])
|
|
return client
|
|
|
|
|
|
def add_job_to_session(request, session_id, job_id):
|
|
"""This function will add a job to a session and the API will handle the
|
|
copy of job information to the session
|
|
"""
|
|
try:
|
|
return _freezerclient(request).sessions.add_job(session_id, job_id)
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
def remove_job_from_session(request, session_id, job_id):
|
|
"""Remove a job from a session will delete the job information but not the
|
|
job itself
|
|
"""
|
|
try:
|
|
return _freezerclient(request).sessions.remove_job(session_id, job_id)
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
def session_create(request, context):
|
|
"""A session is a group of jobs who share the same scheduling time. """
|
|
session = create_dict_action(**context)
|
|
session['description'] = session.pop('description', None)
|
|
schedule = {}
|
|
|
|
assign_value_from_source(session, schedule, 'schedule_start_date')
|
|
assign_value_from_source(session, schedule, 'schedule_end_date')
|
|
assign_value_from_source(session, schedule, 'schedule_interval')
|
|
|
|
session['job_schedule'] = schedule
|
|
return _freezerclient(request).sessions.create(session)
|
|
|
|
|
|
def session_update(request, context):
|
|
"""Update session information """
|
|
session = create_dict_action(**context)
|
|
session_id = session.pop('session_id', None)
|
|
session['description'] = session.pop('description', None)
|
|
schedule = {}
|
|
|
|
assign_value_from_source(session, schedule, 'schedule_start_date')
|
|
assign_value_from_source(session, schedule, 'schedule_end_date')
|
|
assign_value_from_source(session, schedule, 'schedule_interval')
|
|
|
|
session['job_schedule'] = schedule
|
|
return _freezerclient(request).sessions.update(session_id, session)
|
|
|
|
|
|
def session_delete(request, session_id):
|
|
"""Delete session from API """
|
|
return _freezerclient(request).sessions.delete(session_id)
|
|
|
|
|
|
def session_list(request):
|
|
"""List all sessions """
|
|
sessions = _freezerclient(request).sessions.list_all()
|
|
sessions = [Session(s['session_id'],
|
|
s['description'],
|
|
s['status'],
|
|
s['jobs'],
|
|
s['job_schedule'].get('schedule_start_date'),
|
|
s['job_schedule'].get('schedule_interval'),
|
|
s['job_schedule'].get('schedule_end_date'))
|
|
for s in sessions]
|
|
return sessions
|
|
|
|
|
|
def session_get(request, session_id):
|
|
"""Get a single session """
|
|
session = _freezerclient(request).sessions.get(session_id)
|
|
session = Session(session['session_id'],
|
|
session['description'],
|
|
session['status'],
|
|
session['jobs'],
|
|
session['job_schedule'].get('schedule_start_date'),
|
|
session['job_schedule'].get('schedule_interval'),
|
|
session['job_schedule'].get('schedule_end_date'))
|
|
return session
|
|
|
|
|
|
def backups_list(request, offset=0, time_after=None, time_before=None,
|
|
text_match=None):
|
|
"""List all backups and optionally you can provide filters and pagination
|
|
values
|
|
"""
|
|
page_size = utils.get_page_size(request)
|
|
|
|
search = {}
|
|
|
|
if time_after:
|
|
search['time_after'] = time_after
|
|
if time_before:
|
|
search['time_before'] = time_before
|
|
|
|
if text_match:
|
|
search['match'] = [
|
|
{
|
|
"_all": text_match,
|
|
}
|
|
]
|
|
|
|
backups = _freezerclient(request).backups.list(
|
|
limit=page_size + 1,
|
|
offset=offset,
|
|
search=search)
|
|
|
|
if len(backups) > page_size:
|
|
backups.pop()
|
|
has_more = True
|
|
else:
|
|
has_more = False
|
|
|
|
# Wrap data in object for easier handling
|
|
backups = [Backup(data) for data in backups]
|
|
|
|
return backups, has_more
|
|
|
|
|
|
def backup_get(request, backup_id):
|
|
"""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 = Backup(backup)
|
|
return backup
|