diff --git a/web/pgadmin/browser/server_groups/servers/utils.py b/web/pgadmin/browser/server_groups/servers/utils.py index 59fa30ce7..6ca882b92 100644 --- a/web/pgadmin/browser/server_groups/servers/utils.py +++ b/web/pgadmin/browser/server_groups/servers/utils.py @@ -262,3 +262,21 @@ def remove_saved_passwords(user_id): except Exception as _: db.session.rollback() raise + + +def does_server_exists(sid, user_id): + + """ + This function will return True if server is existing for a user + :param sid: server id + :param user_id: user id + :return: Boolean + """ + # **kwargs parameter can be added to function to filter with more + # parameters. + try: + return True if Server.query.filter_by( + id=sid, user_id=user_id + ).first() is not None else False + except Exception: + return False diff --git a/web/pgadmin/misc/bgprocess/processes.py b/web/pgadmin/misc/bgprocess/processes.py index 22f76be86..4957b057f 100644 --- a/web/pgadmin/misc/bgprocess/processes.py +++ b/web/pgadmin/misc/bgprocess/processes.py @@ -23,6 +23,7 @@ import logging from pgadmin.utils import u_encode, file_quote, fs_encoding, \ get_complete_file_path, get_storage_directory, IS_WIN +from pgadmin.browser.server_groups.servers.utils import does_server_exists import pytz from dateutil import parser @@ -68,9 +69,9 @@ class IProcessDesc(object, metaclass=ABCMeta): try: # check if file name is encoded with UTF-8 file = self.bfile.decode('utf-8') - except Exception as e: - str(e) + except Exception: # do nothing if bfile is not encoded. + pass path = get_complete_file_path(file) path = file if path is None else path @@ -87,14 +88,7 @@ class IProcessDesc(object, metaclass=ABCMeta): else: last_dir = file - if IS_WIN: - if '\\' in last_dir: - if len(last_dir) == 1: - last_dir = last_dir.replace('\\', '\\\\') - else: - last_dir = last_dir.replace('\\', '/') - else: - last_dir = last_dir.replace('\\', '/') + last_dir = replace_path_for_win(last_dir) return None if hasattr(self, 'is_import') and self.is_import \ else last_dir @@ -102,6 +96,16 @@ class IProcessDesc(object, metaclass=ABCMeta): return None +def replace_path_for_win(last_dir=None): + if IS_WIN: + if '\\' in last_dir and len(last_dir) == 1: + last_dir = last_dir.replace('\\', '\\\\') + else: + last_dir = last_dir.replace('\\', '/') + + return last_dir + + class BatchProcess(object): def __init__(self, **kwargs): @@ -625,6 +629,9 @@ class BatchProcess(object): ): continue + if BatchProcess._operate_orphan_process(p): + continue + execution_time = None stime = parser.parse(p.start_time) @@ -654,6 +661,29 @@ class BatchProcess(object): return res + @staticmethod + def _operate_orphan_process(p): + + if p and p.desc: + desc = loads(p.desc) + if does_server_exists(desc.sid, current_user.id) is False: + current_app.logger.warning( + _("Server with id '{0}' is either removed or does " + "not exists for the background process " + "'{1}'").format(desc.sid, p.pid) + ) + try: + BatchProcess.acknowledge(p.pid) + except LookupError as lerr: + current_app.logger.warning( + _("Status for the background process '{0}' could " + "not be loaded.").format(p.pid) + ) + current_app.logger.exception(lerr) + return True + + return False + @staticmethod def total_seconds(dt): return round(dt.total_seconds(), 2) diff --git a/web/pgadmin/tools/backup/__init__.py b/web/pgadmin/tools/backup/__init__.py index 6ddd38db4..da388ad26 100644 --- a/web/pgadmin/tools/backup/__init__.py +++ b/web/pgadmin/tools/backup/__init__.py @@ -141,11 +141,6 @@ class BackupMessage(IProcessDesc): # It should never reach here. return _("Unknown Backup") - # @property - # def current_storage_dir(self): - # return self.bfile if os.path.isdir(self.bfile) \ - # else os.path.dirname(self.bfile) - @property def message(self): name, host, port = self.get_server_details() diff --git a/web/pgadmin/tools/backup/tests/test_batch_process.py b/web/pgadmin/tools/backup/tests/test_batch_process.py index 7d2c8e712..db547382c 100644 --- a/web/pgadmin/tools/backup/tests/test_batch_process.py +++ b/web/pgadmin/tools/backup/tests/test_batch_process.py @@ -199,11 +199,18 @@ class BatchProcessTest(BaseTestGenerator): self.assertTrue(popen_mock.called) + @patch('os.path.realpath') + @patch('pgadmin.misc.bgprocess.processes.get_storage_directory') + @patch('pgadmin.misc.bgprocess.processes.get_complete_file_path') @patch('pgadmin.misc.bgprocess.processes.Process') @patch('pgadmin.misc.bgprocess.processes.BatchProcess.' 'update_process_info') - def _check_list(self, p, backup_obj, update_process_info_mock, - process_mock): + @patch('pgadmin.misc.bgprocess.processes.BatchProcess.' + '_operate_orphan_process') + def _check_list(self, p, backup_obj, _operate_orphan_process_mock, + update_process_info_mock, process_mock, + get_complete_file_path_mock, get_storage_directory_mock, + realpath_mock): class TestMockProcess(): def __init__(self, desc, args, cmd): self.pid = 1 @@ -222,6 +229,10 @@ class BatchProcessTest(BaseTestGenerator): self.class_params['cmd'])] update_process_info_mock.return_value = [True, True] + 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)) diff --git a/web/pgadmin/tools/import_export/tests/test_batch_process.py b/web/pgadmin/tools/import_export/tests/test_batch_process.py index 241c3a06f..e933fb99b 100644 --- a/web/pgadmin/tools/import_export/tests/test_batch_process.py +++ b/web/pgadmin/tools/import_export/tests/test_batch_process.py @@ -212,9 +212,11 @@ class BatchProcessTest(BaseTestGenerator): @patch('pgadmin.misc.bgprocess.processes.Process') @patch('pgadmin.misc.bgprocess.processes.BatchProcess.' 'update_process_info') - def _check_list(self, p, import_export_obj, update_process_info_mock, - process_mock, - get_storage_directory_mock, get_complete_file_path_mock, + @patch('pgadmin.misc.bgprocess.processes.BatchProcess.' + '_operate_orphan_process') + def _check_list(self, p, import_export_obj, _operate_orphan_process_mock, + update_process_info_mock, process_mock, + get_complete_file_path_mock, get_storage_directory_mock, realpath_mock): class TestMockProcess(): def __init__(self, desc, args, cmd): @@ -237,6 +239,7 @@ class BatchProcessTest(BaseTestGenerator): get_complete_file_path_mock.return_value = self.params['filename'] realpath_mock.return_value = self.params['filename'] get_storage_directory_mock.return_value = '//' + _operate_orphan_process_mock.return_value = False ret_value = p.list() self.assertEqual(1, len(ret_value)) diff --git a/web/pgadmin/tools/storage_manager/static/js/storage_manager.js b/web/pgadmin/tools/storage_manager/static/js/storage_manager.js index 1f5b1ff42..a1b7044a4 100644 --- a/web/pgadmin/tools/storage_manager/static/js/storage_manager.js +++ b/web/pgadmin/tools/storage_manager/static/js/storage_manager.js @@ -65,7 +65,7 @@ define([ var params = { supported_types: ['sql', 'csv', '*'], dialog_type: 'storage_dialog', - dialog_title: 'Storage Manager...', + dialog_title: 'Storage Manager', btn_primary: undefined, };