Show More
@@ -21,26 +21,22 b' import glob' | |||||
21 | import os |
|
21 | import os | |
22 | import signal |
|
22 | import signal | |
23 | import sys |
|
23 | import sys | |
24 | from getpass import getpass |
|
|||
25 |
|
24 | |||
26 | # System library imports |
|
25 | # System library imports | |
27 | from IPython.external.qt import QtGui |
|
26 | from IPython.external.qt import QtGui | |
28 | from pygments.styles import get_all_styles |
|
27 | from pygments.styles import get_all_styles | |
29 | from zmq.utils import jsonapi as json |
|
28 | from zmq.utils import jsonapi as json | |
30 |
|
29 | |||
31 | # external imports |
|
|||
32 | from IPython.external.ssh import tunnel |
|
|||
33 |
|
||||
34 | # Local imports |
|
30 | # Local imports | |
35 | from IPython.config.application import boolean_flag |
|
31 | from IPython.config.application import boolean_flag | |
36 | from IPython.core.application import BaseIPythonApplication |
|
32 | from IPython.core.application import BaseIPythonApplication | |
37 | from IPython.core.profiledir import ProfileDir |
|
33 | from IPython.core.profiledir import ProfileDir | |
|
34 | from IPython.lib.kernel import tunnel_to_kernel | |||
38 | from IPython.frontend.qt.console.frontend_widget import FrontendWidget |
|
35 | from IPython.frontend.qt.console.frontend_widget import FrontendWidget | |
39 | from IPython.frontend.qt.console.ipython_widget import IPythonWidget |
|
36 | from IPython.frontend.qt.console.ipython_widget import IPythonWidget | |
40 | from IPython.frontend.qt.console.rich_ipython_widget import RichIPythonWidget |
|
37 | from IPython.frontend.qt.console.rich_ipython_widget import RichIPythonWidget | |
41 | from IPython.frontend.qt.console import styles |
|
38 | from IPython.frontend.qt.console import styles | |
42 | from IPython.frontend.qt.kernelmanager import QtKernelManager |
|
39 | from IPython.frontend.qt.kernelmanager import QtKernelManager | |
43 | from IPython.parallel.util import select_random_ports |
|
|||
44 | from IPython.utils.path import filefind |
|
40 | from IPython.utils.path import filefind | |
45 | from IPython.utils.py3compat import str_to_bytes |
|
41 | from IPython.utils.py3compat import str_to_bytes | |
46 | from IPython.utils.traitlets import ( |
|
42 | from IPython.utils.traitlets import ( | |
@@ -424,24 +420,30 b' class IPythonQtConsoleApp(BaseIPythonApplication):' | |||||
424 | return |
|
420 | return | |
425 |
|
421 | |||
426 | if self.sshkey and not self.sshserver: |
|
422 | if self.sshkey and not self.sshserver: | |
|
423 | # specifying just the key implies that we are connecting directly | |||
427 | self.sshserver = self.ip |
|
424 | self.sshserver = self.ip | |
428 | self.ip=LOCALHOST |
|
425 | self.ip = LOCALHOST | |
429 |
|
426 | |||
430 | lports = select_random_ports(4) |
|
427 | # build connection dict for tunnels: | |
431 | rports = self.shell_port, self.iopub_port, self.stdin_port, self.hb_port |
|
428 | info = dict(ip=self.ip, | |
432 | self.shell_port, self.iopub_port, self.stdin_port, self.hb_port = lports |
|
429 | shell_port=self.shell_port, | |
|
430 | iopub_port=self.iopub_port, | |||
|
431 | stdin_port=self.stdin_port, | |||
|
432 | hb_port=self.hb_port | |||
|
433 | ) | |||
|
434 | ||||
|
435 | self.log.info("Forwarding connections to %s via %s"%(self.ip, self.sshserver)) | |||
433 |
|
436 | |||
434 | remote_ip = self.ip |
|
437 | # tunnels return a new set of ports, which will be on localhost: | |
435 | self.ip = LOCALHOST |
|
438 | self.ip = LOCALHOST | |
436 | self.log.info("Forwarding connections to %s via %s"%(remote_ip, self.sshserver)) |
|
439 | try: | |
437 |
|
440 | newports = tunnel_to_kernel(info, self.sshserver, self.sshkey) | ||
438 | if tunnel.try_passwordless_ssh(self.sshserver, self.sshkey): |
|
441 | except: | |
439 | password=False |
|
442 | # even catch KeyboardInterrupt | |
440 | else: |
|
443 | self.log.error("Could not setup tunnels", exc_info=True) | |
441 | password = getpass("SSH Password for %s: "%self.sshserver) |
|
444 | self.exit(1) | |
442 |
|
445 | |||
443 | for lp,rp in zip(lports, rports): |
|
446 | self.shell_port, self.iopub_port, self.stdin_port, self.hb_port = newports | |
444 | tunnel.ssh_tunnel(lp, rp, self.sshserver, remote_ip, self.sshkey, password) |
|
|||
445 |
|
447 | |||
446 | cf = self.connection_file |
|
448 | cf = self.connection_file | |
447 | base,ext = os.path.splitext(cf) |
|
449 | base,ext = os.path.splitext(cf) |
@@ -19,8 +19,13 b' Authors:' | |||||
19 |
|
19 | |||
20 | import json |
|
20 | import json | |
21 | import sys |
|
21 | import sys | |
|
22 | from getpass import getpass | |||
22 | from subprocess import Popen, PIPE |
|
23 | from subprocess import Popen, PIPE | |
23 |
|
24 | |||
|
25 | # external imports | |||
|
26 | from IPython.external.ssh import tunnel | |||
|
27 | ||||
|
28 | # IPython imports | |||
24 | from IPython.utils.path import filefind |
|
29 | from IPython.utils.path import filefind | |
25 | from IPython.utils.py3compat import str_to_bytes |
|
30 | from IPython.utils.py3compat import str_to_bytes | |
26 |
|
31 | |||
@@ -96,4 +101,52 b' def connect_qtconsole(argv=None):' | |||||
96 |
|
101 | |||
97 | return Popen([sys.executable, '-c', cmd, '--existing', cf] + argv, stdout=PIPE, stderr=PIPE) |
|
102 | return Popen([sys.executable, '-c', cmd, '--existing', cf] + argv, stdout=PIPE, stderr=PIPE) | |
98 |
|
103 | |||
|
104 | def tunnel_to_kernel(connection_info, sshserver, sshkey=None): | |||
|
105 | """tunnel connections to a kernel via ssh | |||
|
106 | ||||
|
107 | This will open four SSH tunnels from localhost on this machine to the | |||
|
108 | ports associated with the kernel. They can be either direct | |||
|
109 | localhost-localhost tunnels, or if an intermediate server is necessary, | |||
|
110 | the kernel must be listening on a public IP. | |||
|
111 | ||||
|
112 | Parameters | |||
|
113 | ---------- | |||
|
114 | connection_info : dict or str (path) | |||
|
115 | Either a connection dict, or the path to a JSON connection file | |||
|
116 | sshserver : str | |||
|
117 | The ssh sever to use to tunnel to the kernel. Can be a full | |||
|
118 | `user@server:port` string. ssh config aliases are respected. | |||
|
119 | sshkey : str [optional] | |||
|
120 | Path to file containing ssh key to use for authentication. | |||
|
121 | Only necessary if your ssh config does not already associate | |||
|
122 | a keyfile with the host. | |||
|
123 | ||||
|
124 | Returns | |||
|
125 | ------- | |||
|
126 | ||||
|
127 | (shell, iopub, stdin, hb) : ints | |||
|
128 | The four ports on localhost that have been forwarded to the kernel. | |||
|
129 | """ | |||
|
130 | if isinstance(connection_info, basestring): | |||
|
131 | # it's a path, unpack it | |||
|
132 | with open(connection_info) as f: | |||
|
133 | connection_info = json.loads(f.read()) | |||
|
134 | ||||
|
135 | cf = connection_info | |||
|
136 | ||||
|
137 | lports = tunnel.select_random_ports(4) | |||
|
138 | rports = cf['shell_port'], cf['iopub_port'], cf['stdin_port'], cf['hb_port'] | |||
|
139 | ||||
|
140 | remote_ip = cf['ip'] | |||
|
141 | ||||
|
142 | if tunnel.try_passwordless_ssh(sshserver, sshkey): | |||
|
143 | password=False | |||
|
144 | else: | |||
|
145 | password = getpass("SSH Password for %s: "%sshserver) | |||
|
146 | ||||
|
147 | for lp,rp in zip(lports, rports): | |||
|
148 | tunnel.ssh_tunnel(lp, rp, sshserver, remote_ip, sshkey, password) | |||
|
149 | ||||
|
150 | return tuple(lports) | |||
|
151 | ||||
99 |
|
152 |
General Comments 0
You need to be logged in to leave comments.
Login now