Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR: Tunnel comm port to make all features that depend on comms work for remote kernels #14447

Merged
merged 2 commits into from
Feb 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions spyder/plugins/ipythonconsole/comms/kernelcomm.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@
"""
from contextlib import contextmanager
import logging
import os
import pickle

import jupyter_client
from qtpy.QtCore import QEventLoop, QObject, QTimer, Signal
import zmq
from zmq.ssh import tunnel as zmqtunnel

from spyder_kernels.comms.commbase import CommBase, CommError
from spyder.py3compat import TimeoutError
from spyder.plugins.ipythonconsole.utils.ssh import openssh_tunnel

logger = logging.getLogger(__name__)

Expand All @@ -37,18 +40,38 @@ class KernelComm(CommBase, QObject):

def __init__(self):
super(KernelComm, self).__init__()
self.comm_port = None
self.remote_comm_port = None
self.kernel_client = None

# Register handlers
self.register_call_handler('_async_error', self._async_error)
self.register_call_handler('_set_comm_port', self._set_comm_port)

def ssh_tunnel(self, *args, **kwargs):
if os.name == 'nt':
return zmqtunnel.paramiko_tunnel(*args, **kwargs)
else:
return openssh_tunnel(None, *args, **kwargs)

def _set_comm_port(self, port):
"""Set comm port."""
if port is None:
if port is None or port == self.remote_comm_port:
return
self.remote_comm_port = port

client = self.kernel_client

if hasattr(client, 'ssh_parameters'):
# Need to tunnel port
hostname, sshkey, password = client.ssh_parameters
local_port = zmqtunnel.select_random_ports(1)[0]
remote_port = port
remote_ip = client.ip
self.ssh_tunnel(
local_port, remote_port, hostname, remote_ip, sshkey,
password, timeout=10)
port = local_port

if not (hasattr(client, 'comm_port') and client.comm_port == port):
client.comm_port = port
identity = client.session.bsession
Expand Down
2 changes: 2 additions & 0 deletions spyder/plugins/ipythonconsole/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1757,6 +1757,8 @@ def _create_client_for_kernel(self, connection_file, hostname, sshkey,
kernel_client.iopub_port,
kernel_client.stdin_port,
kernel_client.hb_port) = newports
# Save parameters to connect comm later
kernel_client.ssh_parameters = (hostname, sshkey, password)
except Exception as e:
QMessageBox.critical(self, _('Connection error'),
_("Could not open ssh tunnel. The "
Expand Down