mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
1) Added support to show all background processes in separate panel. Fixes #3709
2) Port process watcher to React. Fixes #7404
This commit is contained in:
committed by
Akshay Joshi
parent
271b6d91fc
commit
c2b23465cc
@@ -6,7 +6,6 @@
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
"""Implements Backup Utility"""
|
||||
|
||||
import simplejson as json
|
||||
@@ -103,9 +102,12 @@ class BackupMessage(IProcessDesc):
|
||||
else:
|
||||
self.cmd += cmd_arg(arg)
|
||||
|
||||
def get_server_details(self):
|
||||
def get_server_name(self):
|
||||
s = get_server(self.sid)
|
||||
|
||||
if s is None:
|
||||
return _("Not available")
|
||||
|
||||
from pgadmin.utils.driver import get_driver
|
||||
driver = get_driver(PG_DEFAULT_DRIVER)
|
||||
manager = driver.connection_manager(self.sid)
|
||||
@@ -113,7 +115,10 @@ class BackupMessage(IProcessDesc):
|
||||
host = manager.local_bind_host if manager.use_ssh_tunnel else s.host
|
||||
port = manager.local_bind_port if manager.use_ssh_tunnel else s.port
|
||||
|
||||
return s.name, host, port
|
||||
s.name = html.safe_str(s.name)
|
||||
host = html.safe_str(host)
|
||||
port = html.safe_str(port)
|
||||
return "{0} ({1}:{2})".format(s.name, host, port)
|
||||
|
||||
@property
|
||||
def type_desc(self):
|
||||
@@ -129,77 +134,45 @@ class BackupMessage(IProcessDesc):
|
||||
|
||||
@property
|
||||
def message(self):
|
||||
name, host, port = self.get_server_details()
|
||||
name = html.safe_str(name)
|
||||
host = html.safe_str(host)
|
||||
port = html.safe_str(port)
|
||||
server_name = self.get_server_name()
|
||||
|
||||
if self.backup_type == BACKUP.OBJECT:
|
||||
return _(
|
||||
"Backing up an object on the server '{0}' "
|
||||
"from database '{1}'"
|
||||
).format(self.args_str.format(name, host, port),
|
||||
).format(server_name,
|
||||
html.safe_str(self.database)
|
||||
)
|
||||
if self.backup_type == BACKUP.GLOBALS:
|
||||
return _("Backing up the global objects on "
|
||||
"the server '{0}'").format(
|
||||
self.args_str.format(
|
||||
name, host, port
|
||||
)
|
||||
server_name
|
||||
)
|
||||
elif self.backup_type == BACKUP.SERVER:
|
||||
return _("Backing up the server '{0}'").format(
|
||||
self.args_str.format(
|
||||
name, host, port
|
||||
)
|
||||
server_name
|
||||
)
|
||||
else:
|
||||
# It should never reach here.
|
||||
return "Unknown Backup"
|
||||
|
||||
def details(self, cmd, args):
|
||||
name, host, port = self.get_server_details()
|
||||
|
||||
res = '<div>'
|
||||
|
||||
server_name = self.get_server_name()
|
||||
backup_type = _("Backup")
|
||||
if self.backup_type == BACKUP.OBJECT:
|
||||
msg = _(
|
||||
"Backing up an object on the server '{0}' "
|
||||
"from database '{1}'..."
|
||||
).format(
|
||||
self.args_str.format(
|
||||
name, host, port
|
||||
),
|
||||
self.database
|
||||
)
|
||||
res += html.safe_str(msg)
|
||||
backup_type = _("Backup Object")
|
||||
elif self.backup_type == BACKUP.GLOBALS:
|
||||
msg = _("Backing up the global objects on "
|
||||
"the server '{0}'...").format(
|
||||
self.args_str.format(
|
||||
name, host, port
|
||||
)
|
||||
)
|
||||
res += html.safe_str(msg)
|
||||
backup_type = _("Backup Globals")
|
||||
elif self.backup_type == BACKUP.SERVER:
|
||||
msg = _("Backing up the server '{0}'...").format(
|
||||
self.args_str.format(
|
||||
name, host, port
|
||||
)
|
||||
)
|
||||
res += html.safe_str(msg)
|
||||
else:
|
||||
# It should never reach here.
|
||||
res += "Backup"
|
||||
backup_type = _("Backup Server")
|
||||
|
||||
res += '</div><div class="py-1">'
|
||||
res += _("Running command:")
|
||||
res += '<div class="pg-bg-cmd enable-selection p-1">'
|
||||
res += html.safe_str(cmd + self.cmd)
|
||||
res += '</div></div>'
|
||||
|
||||
return res
|
||||
return {
|
||||
"message": self.message,
|
||||
"cmd": cmd + self.cmd,
|
||||
"server": server_name,
|
||||
"object": self.database,
|
||||
"type": backup_type,
|
||||
}
|
||||
|
||||
|
||||
@blueprint.route("/")
|
||||
@@ -487,7 +460,7 @@ def create_backup_objects_job(sid):
|
||||
|
||||
# Return response
|
||||
return make_json_response(
|
||||
data={'job_id': jid, 'Success': 1}
|
||||
data={'job_id': jid, 'desc': p.desc.message, 'Success': 1}
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ define([
|
||||
gettext(data.errormsg)
|
||||
);
|
||||
} else {
|
||||
pgBrowser.Events.trigger('pgadmin-bgprocess:created');
|
||||
pgBrowser.BgProcessManager.startProcess(data.data.job_id, data.data.desc);
|
||||
}
|
||||
},
|
||||
url_for_utility_exists(id, params){
|
||||
|
||||
@@ -731,6 +731,7 @@ class BackupCreateJobTest(BaseTestGenerator):
|
||||
self.class_params['username'],
|
||||
self.class_params['database']
|
||||
)
|
||||
|
||||
mock_result = server_mock.query.filter_by.return_value
|
||||
mock_result.first.return_value = mock_obj
|
||||
|
||||
@@ -743,7 +744,8 @@ class BackupCreateJobTest(BaseTestGenerator):
|
||||
batch_process_mock.return_value.start = MagicMock(
|
||||
return_value=True
|
||||
)
|
||||
|
||||
backup_message_mock.message = 'test'
|
||||
batch_process_mock.return_value.desc = backup_message_mock
|
||||
export_password_env_mock.return_value = True
|
||||
|
||||
server_response = server_utils.connect_server(self, self.server_id)
|
||||
|
||||
@@ -125,12 +125,13 @@ class BackupMessageTest(BaseTestGenerator):
|
||||
]
|
||||
|
||||
@patch('pgadmin.utils.get_storage_directory')
|
||||
@patch('pgadmin.tools.backup.BackupMessage.get_server_details')
|
||||
def runTest(self, get_server_details_mock, get_storage_directory_mock):
|
||||
get_server_details_mock.return_value = \
|
||||
self.class_params['name'],\
|
||||
self.class_params['host'],\
|
||||
self.class_params['port']
|
||||
@patch('pgadmin.tools.backup.BackupMessage.get_server_name')
|
||||
def runTest(self, get_server_name_mock, get_storage_directory_mock):
|
||||
get_server_name_mock.return_value = "{0} ({1}:{2})"\
|
||||
.format(
|
||||
self.class_params['name'],
|
||||
self.class_params['host'],
|
||||
self.class_params['port'])
|
||||
|
||||
backup_obj = BackupMessage(
|
||||
self.class_params['type'],
|
||||
@@ -149,4 +150,4 @@ class BackupMessageTest(BaseTestGenerator):
|
||||
obj_details = backup_obj.details(self.class_params['cmd'],
|
||||
self.class_params['args'])
|
||||
|
||||
self.assertIn(self.expected_details_cmd, obj_details)
|
||||
self.assertEqual(self.expected_details_cmd, obj_details['cmd'])
|
||||
|
||||
@@ -56,16 +56,16 @@ def run_backup_job(tester, job_id, expected_params, assert_in, assert_not_in,
|
||||
|
||||
backup_file = None
|
||||
if 'details' in the_process:
|
||||
backup_det = the_process['details']
|
||||
backup_file = backup_det[int(backup_det.find('--file')) +
|
||||
8:int(backup_det.find('--host')) - 2]
|
||||
backup_cmd = the_process['details']['cmd']
|
||||
backup_file = backup_cmd[int(backup_cmd.find('--file')) +
|
||||
8:int(backup_cmd.find('--host')) - 2]
|
||||
|
||||
if expected_params['expected_cmd_opts']:
|
||||
for opt in expected_params['expected_cmd_opts']:
|
||||
assert_in(opt, the_process['details'])
|
||||
assert_in(opt, the_process['details']['cmd'])
|
||||
if expected_params['not_expected_cmd_opts']:
|
||||
for opt in expected_params['not_expected_cmd_opts']:
|
||||
assert_not_in(opt, the_process['details'])
|
||||
assert_not_in(opt, the_process['details']['cmd'])
|
||||
|
||||
# Check the process details
|
||||
p_details = tester.get('/misc/bgprocess/{0}?_={1}'.format(
|
||||
|
||||
@@ -13,6 +13,12 @@ from pgadmin.tools.backup import BackupMessage, BACKUP
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from pickle import dumps, loads
|
||||
from unittest.mock import patch, MagicMock
|
||||
from pgadmin.utils.preferences import Preferences
|
||||
import datetime
|
||||
import pytz
|
||||
|
||||
start_time = \
|
||||
datetime.datetime.now(pytz.utc).strftime("%Y-%m-%d %H:%M:%S.%f %z")
|
||||
|
||||
|
||||
class BatchProcessTest(BaseTestGenerator):
|
||||
@@ -101,13 +107,14 @@ class BatchProcessTest(BaseTestGenerator):
|
||||
))
|
||||
]
|
||||
|
||||
@patch('pgadmin.tools.backup.BackupMessage.get_server_details')
|
||||
@patch.object(Preferences, 'module', return_value=MagicMock())
|
||||
@patch('pgadmin.tools.backup.BackupMessage.get_server_name')
|
||||
@patch('pgadmin.misc.bgprocess.processes.Popen')
|
||||
@patch('pgadmin.misc.bgprocess.processes.db')
|
||||
@patch('pgadmin.tools.backup.current_user')
|
||||
@patch('pgadmin.misc.bgprocess.processes.current_user')
|
||||
def runTest(self, current_user_mock, current_user, db_mock,
|
||||
popen_mock, get_server_details_mock):
|
||||
popen_mock, get_server_name_mock, pref_module):
|
||||
with self.app.app_context():
|
||||
current_user.id = 1
|
||||
current_user_mock.id = 1
|
||||
@@ -137,10 +144,14 @@ class BatchProcessTest(BaseTestGenerator):
|
||||
db_mock.session.add.side_effect = db_session_add_mock
|
||||
db_mock.session.commit = MagicMock(return_value=True)
|
||||
|
||||
get_server_details_mock.return_value = \
|
||||
self.class_params['name'], \
|
||||
self.class_params['host'], \
|
||||
self.class_params['port']
|
||||
pref_module.return_value.preference.return_value.get.\
|
||||
return_value = 5
|
||||
|
||||
get_server_name_mock.return_value = "{0} ({1}:{2})" \
|
||||
.format(
|
||||
self.class_params['name'],
|
||||
self.class_params['host'],
|
||||
self.class_params['port'])
|
||||
|
||||
backup_obj = BackupMessage(
|
||||
self.class_params['type'],
|
||||
@@ -171,13 +182,15 @@ class BatchProcessTest(BaseTestGenerator):
|
||||
def __init__(self, desc, args, cmd):
|
||||
self.pid = 1
|
||||
self.exit_code = 1
|
||||
self.start_time = '2018-04-17 06:18:56.315445 +0000'
|
||||
self.start_time = start_time
|
||||
self.end_time = None
|
||||
self.desc = dumps(desc)
|
||||
self.arguments = " ".join(args)
|
||||
self.command = cmd
|
||||
self.acknowledge = None
|
||||
self.process_state = 0
|
||||
self.utility_pid = 123
|
||||
self.server_id = None
|
||||
|
||||
mock_result = process_mock.query.filter_by.return_value
|
||||
mock_result.first.return_value = TestMockProcess(
|
||||
@@ -205,9 +218,7 @@ class BatchProcessTest(BaseTestGenerator):
|
||||
@patch('pgadmin.misc.bgprocess.processes.Process')
|
||||
@patch('pgadmin.misc.bgprocess.processes.BatchProcess.'
|
||||
'update_process_info')
|
||||
@patch('pgadmin.misc.bgprocess.processes.BatchProcess.'
|
||||
'_operate_orphan_process')
|
||||
def _check_list(self, p, backup_obj, _operate_orphan_process_mock,
|
||||
def _check_list(self, p, backup_obj,
|
||||
update_process_info_mock, process_mock,
|
||||
get_complete_file_path_mock, get_storage_directory_mock,
|
||||
realpath_mock):
|
||||
@@ -215,13 +226,15 @@ class BatchProcessTest(BaseTestGenerator):
|
||||
def __init__(self, desc, args, cmd):
|
||||
self.pid = 1
|
||||
self.exit_code = 1
|
||||
self.start_time = '2018-04-17 06:18:56.315445 +0000'
|
||||
self.start_time = start_time
|
||||
self.end_time = None
|
||||
self.desc = dumps(desc)
|
||||
self.arguments = " ".join(args)
|
||||
self.command = cmd
|
||||
self.acknowledge = None
|
||||
self.process_state = 0
|
||||
self.utility_pid = 123
|
||||
self.server_id = None
|
||||
|
||||
process_mock.query.filter_by.return_value = [
|
||||
TestMockProcess(backup_obj,
|
||||
@@ -232,7 +245,6 @@ class BatchProcessTest(BaseTestGenerator):
|
||||
get_complete_file_path_mock.return_value = self.class_params['bfile']
|
||||
realpath_mock.return_value = self.class_params['bfile']
|
||||
get_storage_directory_mock.return_value = '//'
|
||||
_operate_orphan_process_mock.return_value = False
|
||||
|
||||
ret_value = p.list()
|
||||
self.assertEqual(1, len(ret_value))
|
||||
|
||||
Reference in New Issue
Block a user