mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
1) Fix network disconnect issue while establishing the connection via SSH Tunnel and it impossible to expand the Servers node. Fixes #4724.
2) Fix server connection drops out issue in query tool. Fixes #4818 3) Fix VPN network disconnect issue where pgAdmin4 hangs on expanding the Servers node. Fixes #4926. 4) Ensure that the Servers collection node should expand independently of server connections. Fixes #4933. Set the default connection timeout to 10 seconds instead of 0.
This commit is contained in:
committed by
Akshay Joshi
parent
700e01708b
commit
4ed2d74d9c
@@ -14,19 +14,21 @@ object.
|
||||
|
||||
"""
|
||||
import datetime
|
||||
from flask import session, request
|
||||
from flask import session
|
||||
from flask_login import current_user
|
||||
from flask_babelex import gettext
|
||||
import psycopg2
|
||||
from psycopg2.extensions import adapt
|
||||
from threading import Lock
|
||||
|
||||
import config
|
||||
from pgadmin.model import Server, User
|
||||
from pgadmin.model import Server
|
||||
from .keywords import ScanKeyword
|
||||
from ..abstract import BaseDriver
|
||||
from .connection import Connection
|
||||
from .server_manager import ServerManager
|
||||
|
||||
connection_restore_lock = Lock()
|
||||
|
||||
|
||||
class Driver(BaseDriver):
|
||||
"""
|
||||
@@ -80,21 +82,30 @@ class Driver(BaseDriver):
|
||||
return None
|
||||
|
||||
if session.sid not in self.managers:
|
||||
self.managers[session.sid] = managers = dict()
|
||||
if '__pgsql_server_managers' in session:
|
||||
session_managers = session['__pgsql_server_managers'].copy()
|
||||
with connection_restore_lock:
|
||||
# The wait is over but the object might have been loaded
|
||||
# by some other thread check again
|
||||
if session.sid not in self.managers:
|
||||
self.managers[session.sid] = managers = dict()
|
||||
if '__pgsql_server_managers' in session:
|
||||
session_managers =\
|
||||
session['__pgsql_server_managers'].copy()
|
||||
for server in \
|
||||
Server.query.filter_by(
|
||||
user_id=current_user.id):
|
||||
manager = managers[str(server.id)] =\
|
||||
ServerManager(server)
|
||||
if server.id in session_managers:
|
||||
manager._restore(session_managers[server.id])
|
||||
manager.update_session()
|
||||
|
||||
for server in Server.query.filter_by(user_id=current_user.id):
|
||||
manager = managers[str(server.id)] = ServerManager(server)
|
||||
if server.id in session_managers:
|
||||
manager._restore(session_managers[server.id])
|
||||
manager.update_session()
|
||||
else:
|
||||
managers = self.managers[session.sid]
|
||||
if str(sid) in managers:
|
||||
manager = managers[str(sid)]
|
||||
manager._restore_connections()
|
||||
manager.update_session()
|
||||
with connection_restore_lock:
|
||||
manager._restore_connections()
|
||||
manager.update_session()
|
||||
|
||||
managers['pinged'] = datetime.datetime.now()
|
||||
if str(sid) not in managers:
|
||||
|
@@ -25,13 +25,10 @@ from pgadmin.model import Server, User
|
||||
from pgadmin.utils.exception import ConnectionLost, SSHTunnelConnectionLost,\
|
||||
CryptKeyMissing
|
||||
from pgadmin.utils.master_password import get_crypt_key
|
||||
from threading import Lock
|
||||
|
||||
if config.SUPPORT_SSH_TUNNEL:
|
||||
from sshtunnel import SSHTunnelForwarder, BaseSSHTunnelForwarderError
|
||||
|
||||
connection_restore_lock = Lock()
|
||||
|
||||
|
||||
class ServerManager(object):
|
||||
"""
|
||||
@@ -292,80 +289,79 @@ WHERE db.oid = {0}""".format(did))
|
||||
|
||||
connections = data['connections']
|
||||
|
||||
with connection_restore_lock:
|
||||
for conn_id in connections:
|
||||
conn_info = connections[conn_id]
|
||||
if conn_info['conn_id'] in self.connections:
|
||||
conn = self.connections[conn_info['conn_id']]
|
||||
else:
|
||||
conn = self.connections[conn_info['conn_id']] = Connection(
|
||||
self, conn_info['conn_id'], conn_info['database'],
|
||||
conn_info['auto_reconnect'], conn_info['async_'],
|
||||
use_binary_placeholder=conn_info[
|
||||
'use_binary_placeholder'],
|
||||
array_to_string=conn_info['array_to_string']
|
||||
for conn_id in connections:
|
||||
conn_info = connections[conn_id]
|
||||
if conn_info['conn_id'] in self.connections:
|
||||
conn = self.connections[conn_info['conn_id']]
|
||||
else:
|
||||
conn = self.connections[conn_info['conn_id']] = Connection(
|
||||
self, conn_info['conn_id'], conn_info['database'],
|
||||
conn_info['auto_reconnect'], conn_info['async_'],
|
||||
use_binary_placeholder=conn_info[
|
||||
'use_binary_placeholder'],
|
||||
array_to_string=conn_info['array_to_string']
|
||||
)
|
||||
|
||||
# only try to reconnect if connection was connected previously
|
||||
# and auto_reconnect is true.
|
||||
if conn_info['wasConnected'] and conn_info['auto_reconnect']:
|
||||
try:
|
||||
# Check SSH Tunnel needs to be created
|
||||
if self.use_ssh_tunnel == 1 and \
|
||||
not self.tunnel_created:
|
||||
status, error = self.create_ssh_tunnel(
|
||||
data['tunnel_password'])
|
||||
|
||||
# Check SSH Tunnel is alive or not.
|
||||
self.check_ssh_tunnel_alive()
|
||||
|
||||
conn.connect(
|
||||
password=data['password'],
|
||||
server_types=ServerType.types()
|
||||
)
|
||||
|
||||
# only try to reconnect if connection was connected previously
|
||||
# and auto_reconnect is true.
|
||||
if conn_info['wasConnected'] and conn_info['auto_reconnect']:
|
||||
try:
|
||||
# Check SSH Tunnel needs to be created
|
||||
if self.use_ssh_tunnel == 1 and \
|
||||
not self.tunnel_created:
|
||||
status, error = self.create_ssh_tunnel(
|
||||
data['tunnel_password'])
|
||||
|
||||
# Check SSH Tunnel is alive or not.
|
||||
self.check_ssh_tunnel_alive()
|
||||
|
||||
conn.connect(
|
||||
password=data['password'],
|
||||
server_types=ServerType.types()
|
||||
)
|
||||
# This will also update wasConnected flag in
|
||||
# connection so no need to update the flag manually.
|
||||
except CryptKeyMissing:
|
||||
# maintain the status as this will help to restore once
|
||||
# the key is available
|
||||
conn.wasConnected = conn_info['wasConnected']
|
||||
conn.auto_reconnect = conn_info['auto_reconnect']
|
||||
except Exception as e:
|
||||
current_app.logger.exception(e)
|
||||
self.connections.pop(conn_info['conn_id'])
|
||||
raise
|
||||
# This will also update wasConnected flag in
|
||||
# connection so no need to update the flag manually.
|
||||
except CryptKeyMissing:
|
||||
# maintain the status as this will help to restore once
|
||||
# the key is available
|
||||
conn.wasConnected = conn_info['wasConnected']
|
||||
conn.auto_reconnect = conn_info['auto_reconnect']
|
||||
except Exception as e:
|
||||
current_app.logger.exception(e)
|
||||
self.connections.pop(conn_info['conn_id'])
|
||||
raise
|
||||
|
||||
def _restore_connections(self):
|
||||
with connection_restore_lock:
|
||||
for conn_id in self.connections:
|
||||
conn = self.connections[conn_id]
|
||||
# only try to reconnect if connection was connected previously
|
||||
# and auto_reconnect is true.
|
||||
wasConnected = conn.wasConnected
|
||||
auto_reconnect = conn.auto_reconnect
|
||||
if conn.wasConnected and conn.auto_reconnect:
|
||||
try:
|
||||
# Check SSH Tunnel needs to be created
|
||||
if self.use_ssh_tunnel == 1 and \
|
||||
not self.tunnel_created:
|
||||
status, error = self.create_ssh_tunnel(
|
||||
self.tunnel_password
|
||||
)
|
||||
for conn_id in self.connections:
|
||||
conn = self.connections[conn_id]
|
||||
# only try to reconnect if connection was connected previously
|
||||
# and auto_reconnect is true.
|
||||
wasConnected = conn.wasConnected
|
||||
auto_reconnect = conn.auto_reconnect
|
||||
if conn.wasConnected and conn.auto_reconnect:
|
||||
try:
|
||||
# Check SSH Tunnel needs to be created
|
||||
if self.use_ssh_tunnel == 1 and \
|
||||
not self.tunnel_created:
|
||||
status, error = self.create_ssh_tunnel(
|
||||
self.tunnel_password
|
||||
)
|
||||
|
||||
# Check SSH Tunnel is alive or not.
|
||||
self.check_ssh_tunnel_alive()
|
||||
# Check SSH Tunnel is alive or not.
|
||||
self.check_ssh_tunnel_alive()
|
||||
|
||||
conn.connect()
|
||||
# This will also update wasConnected flag in
|
||||
# connection so no need to update the flag manually.
|
||||
except CryptKeyMissing:
|
||||
# maintain the status as this will help to restore once
|
||||
# the key is available
|
||||
conn.wasConnected = wasConnected
|
||||
conn.auto_reconnect = auto_reconnect
|
||||
except Exception as e:
|
||||
current_app.logger.exception(e)
|
||||
raise
|
||||
conn.connect()
|
||||
# This will also update wasConnected flag in
|
||||
# connection so no need to update the flag manually.
|
||||
except CryptKeyMissing:
|
||||
# maintain the status as this will help to restore once
|
||||
# the key is available
|
||||
conn.wasConnected = wasConnected
|
||||
conn.auto_reconnect = auto_reconnect
|
||||
except Exception as e:
|
||||
self.connections.pop(conn_id)
|
||||
current_app.logger.exception(e)
|
||||
raise
|
||||
|
||||
def release(self, database=None, conn_id=None, did=None):
|
||||
# Stop the SSH tunnel if release() function calls without
|
||||
|
Reference in New Issue
Block a user