list backups stored in API
The freezer-scheduler can now be used to query the list of backups stored in the API. Two new fields are added to the backup-metadata doc to better identify the resources: client-id job-id Adds the following action to the freezer-scheduler: backup-list Adds the following options to the freezer-scheduler parameters: --all Used when querying the API, to retrieve any document regardless of the client-id --long List additional fields in output Implements blueprint: list-stored-backups Change-Id: I7c6e666d94c64c25d340fc9826628fb001b4b7f6
This commit is contained in:
parent
1bf965888f
commit
87b4ab66b8
@ -32,6 +32,8 @@ class BackupsManager(object):
|
||||
return {'X-Auth-Token': self.client.auth_token}
|
||||
|
||||
def create(self, backup_metadata):
|
||||
if not backup_metadata.get('client_id', ''):
|
||||
backup_metadata['client_id'] = self.client.client_id
|
||||
r = requests.post(self.endpoint,
|
||||
data=json.dumps(backup_metadata),
|
||||
headers=self.headers,
|
||||
@ -48,7 +50,7 @@ class BackupsManager(object):
|
||||
if r.status_code != 204:
|
||||
raise exceptions.ApiClientException(r)
|
||||
|
||||
def list(self, limit=10, offset=0, search=None):
|
||||
def list_all(self, limit=10, offset=0, search=None):
|
||||
"""
|
||||
Retrieves a list of backup infos
|
||||
|
||||
@ -70,6 +72,13 @@ class BackupsManager(object):
|
||||
|
||||
return r.json()['backups']
|
||||
|
||||
def list(self, limit=10, offset=0, search={}, client_id=None):
|
||||
client_id = client_id or self.client.client_id
|
||||
new_search = search.copy()
|
||||
new_search['match'] = search.get('match', [])
|
||||
new_search['match'].append({'client_id': client_id})
|
||||
return self.list_all(limit, offset, new_search)
|
||||
|
||||
def get(self, backup_id):
|
||||
endpoint = self.endpoint + backup_id
|
||||
r = requests.get(endpoint, headers=self.headers, verify=self.verify)
|
||||
|
@ -105,7 +105,16 @@ def get_common_opts():
|
||||
default=False,
|
||||
dest='disable_exec',
|
||||
help='Allow Freezer Scheduler to deny jobs that execute '
|
||||
'commands for security reasons')
|
||||
'commands for security reasons'),
|
||||
cfg.BoolOpt('all',
|
||||
default=False,
|
||||
dest='all',
|
||||
help='Used when querying the API, to retrieve any '
|
||||
'document regardless of the client-id'),
|
||||
cfg.BoolOpt('long',
|
||||
default=False,
|
||||
dest='long',
|
||||
help='List additional fields in output')
|
||||
]
|
||||
|
||||
return _COMMON
|
||||
|
@ -275,6 +275,7 @@ class Job(object):
|
||||
try:
|
||||
metadata = json.loads(metadata_string)
|
||||
if metadata:
|
||||
metadata['job_id'] = self.id
|
||||
self.scheduler.upload_metadata(metadata)
|
||||
logging.info("[*] Job {0}, freezer action metadata uploaded"
|
||||
.format(self.id))
|
||||
|
@ -21,6 +21,8 @@ import os
|
||||
import six
|
||||
import utils
|
||||
|
||||
from freezer.utils.utils import DateTime
|
||||
|
||||
from prettytable import PrettyTable
|
||||
|
||||
try:
|
||||
@ -191,21 +193,22 @@ def do_job_upload(client, args):
|
||||
|
||||
|
||||
def _job_list(client, args):
|
||||
list_func = client.jobs.list_all if args.all else client.jobs.list
|
||||
search = {}
|
||||
if args.active_only:
|
||||
search = {"match_not": [{"status": "completed"}]}
|
||||
client_docs = client.jobs.list(search=search)
|
||||
client_docs = list_func(search=search)
|
||||
offset = 0
|
||||
while client_docs:
|
||||
offset += len(client_docs)
|
||||
for doc in client_docs:
|
||||
yield doc
|
||||
client_docs = client.jobs.list(offset=offset, search=search)
|
||||
client_docs = list_func(offset=offset, search=search)
|
||||
raise StopIteration
|
||||
|
||||
|
||||
def do_job_list(client, args):
|
||||
table = PrettyTable(["job_id", "description", "# actions",
|
||||
table = PrettyTable(["job_id", "client-id", "description", "# actions",
|
||||
"status", "event", "result", "session_id"])
|
||||
for doc in _job_list(client, args):
|
||||
job_scheduling = doc.get('job_schedule', {})
|
||||
@ -213,6 +216,7 @@ def do_job_list(client, args):
|
||||
job_event = job_scheduling.get('event', '')
|
||||
job_result = job_scheduling.get('result', '')
|
||||
table.add_row([doc['job_id'],
|
||||
doc.get('client_id'),
|
||||
doc.get('description', ''),
|
||||
len(doc.get('job_actions', [])),
|
||||
job_status,
|
||||
@ -235,3 +239,41 @@ def do_client_list(client, args):
|
||||
client_doc.get('description', '')])
|
||||
l = client.registration.list(offset=offset)
|
||||
print(table)
|
||||
|
||||
|
||||
def do_backup_list(client, args):
|
||||
list_func = client.backups.list_all if args.all else client.backups.list
|
||||
if args.long:
|
||||
fields = ["backup uuid", "job-id", "client-id", "container",
|
||||
"hostname", "backup name", "timestamp", "level", "path"]
|
||||
else:
|
||||
fields = ["backup uuid", "container", "backup name", "timestamp",
|
||||
"level", "path"]
|
||||
table = PrettyTable(fields)
|
||||
l = list_func()
|
||||
offset = 0
|
||||
while l:
|
||||
offset += len(l)
|
||||
for doc in l:
|
||||
metadata_doc = doc['backup_metadata']
|
||||
timestamp = int(metadata_doc.get('time_stamp', 0))
|
||||
if args.long:
|
||||
row = [doc['backup_uuid'],
|
||||
metadata_doc.get('job_id', ''),
|
||||
metadata_doc.get('client_id', ''),
|
||||
metadata_doc.get('container', ''),
|
||||
metadata_doc.get('hostname', ''),
|
||||
metadata_doc.get('backup_name', ''),
|
||||
str(DateTime(timestamp)),
|
||||
metadata_doc.get('curr_backup_level', ''),
|
||||
metadata_doc.get('fs_real_path', '')]
|
||||
else:
|
||||
row = [doc['backup_uuid'],
|
||||
metadata_doc.get('container', ''),
|
||||
metadata_doc.get('backup_name', ''),
|
||||
str(DateTime(timestamp)),
|
||||
metadata_doc.get('curr_backup_level', ''),
|
||||
metadata_doc.get('fs_real_path', '')]
|
||||
table.add_row(row)
|
||||
l = list_func(offset=offset)
|
||||
print(table)
|
||||
|
@ -15,6 +15,7 @@ limitations under the License.
|
||||
|
||||
"""
|
||||
|
||||
import json
|
||||
import unittest
|
||||
from mock import Mock, patch
|
||||
|
||||
@ -22,10 +23,30 @@ from freezer.apiclient import exceptions
|
||||
from freezer.apiclient import backups
|
||||
|
||||
|
||||
class CallArgs(object):
|
||||
|
||||
def __init__(self, mock_obj=Mock()):
|
||||
self.args = mock_obj.call_args[0]
|
||||
self.kwargs = mock_obj.call_args[1]
|
||||
|
||||
def _check_arg(self, arg, value, load_json):
|
||||
if load_json:
|
||||
arg = json.loads(arg)
|
||||
if (arg != value):
|
||||
raise Exception("Argument doesn't match: {0} != {1}".format(arg, value))
|
||||
return
|
||||
|
||||
def check_arg(self, pos, value, load_json=False):
|
||||
if isinstance(pos, int):
|
||||
return self._check_arg(self.args[pos], value, load_json)
|
||||
return self._check_arg(self.kwargs[pos], value, load_json)
|
||||
|
||||
|
||||
class TestBackupManager(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.mock_client = Mock()
|
||||
self.mock_client.client_id = "jumpingjack"
|
||||
self.mock_client.endpoint = 'http://testendpoint:9999'
|
||||
self.mock_client.auth_token = 'testtoken'
|
||||
self.b = backups.BackupsManager(self.mock_client)
|
||||
@ -42,6 +63,25 @@ class TestBackupManager(unittest.TestCase):
|
||||
mock_response.json.return_value = {'backup_id': 'qwerqwer'}
|
||||
mock_requests.post.return_value = mock_response
|
||||
retval = self.b.create(backup_metadata={'backup': 'metadata'})
|
||||
ca = CallArgs(mock_requests.post)
|
||||
ca.check_arg(0, 'http://testendpoint:9999/v1/backups/')
|
||||
ca.check_arg('data', {"backup": "metadata", "client_id": "jumpingjack"}, load_json=True)
|
||||
ca.check_arg('headers', {'X-Auth-Token': 'testtoken'})
|
||||
ca.check_arg('verify', True)
|
||||
self.assertEqual('qwerqwer', retval)
|
||||
|
||||
@patch('freezer.apiclient.backups.requests')
|
||||
def test_create_ok_with_client_id(self, mock_requests):
|
||||
mock_response = Mock()
|
||||
mock_response.status_code = 201
|
||||
mock_response.json.return_value = {'backup_id': 'qwerqwer'}
|
||||
mock_requests.post.return_value = mock_response
|
||||
retval = self.b.create(backup_metadata={'backup': 'metadata', 'client_id': 'wahwah'})
|
||||
ca = CallArgs(mock_requests.post)
|
||||
ca.check_arg(0, 'http://testendpoint:9999/v1/backups/')
|
||||
ca.check_arg('data', {"backup": "metadata", "client_id": "wahwah"}, load_json=True)
|
||||
ca.check_arg('headers', {'X-Auth-Token': 'testtoken'})
|
||||
ca.check_arg('verify', True)
|
||||
self.assertEqual('qwerqwer', retval)
|
||||
|
||||
@patch('freezer.apiclient.backups.requests')
|
||||
@ -112,12 +152,11 @@ class TestBackupManager(unittest.TestCase):
|
||||
retval = self.b.list(limit=5,
|
||||
offset=5,
|
||||
search={"time_before": 1428529956})
|
||||
mock_requests.get.assert_called_with(
|
||||
'http://testendpoint:9999/v1/backups/',
|
||||
params={'limit': 5, 'offset': 5},
|
||||
data='{"time_before": 1428529956}',
|
||||
headers={'X-Auth-Token': 'testtoken'},
|
||||
verify=True)
|
||||
ca = CallArgs(mock_requests.get)
|
||||
ca.check_arg(0, 'http://testendpoint:9999/v1/backups/')
|
||||
ca.check_arg('data', {"time_before": 1428529956, "match": [{"client_id": "jumpingjack"}]}, load_json=True)
|
||||
ca.check_arg('headers', {'X-Auth-Token': 'testtoken'})
|
||||
ca.check_arg('verify', True)
|
||||
self.assertEqual(backup_list, retval)
|
||||
|
||||
@patch('freezer.apiclient.backups.requests')
|
||||
|
Loading…
Reference in New Issue
Block a user