##// END OF EJS Templates
enable IPC transport for kernels...
MinRK -
Show More
@@ -24,6 +24,7 b' Authors:'
24 import atexit
24 import atexit
25 import json
25 import json
26 import os
26 import os
27 import shutil
27 import signal
28 import signal
28 import sys
29 import sys
29 import uuid
30 import uuid
@@ -38,7 +39,7 b' from IPython.zmq.blockingkernelmanager import BlockingKernelManager'
38 from IPython.utils.path import filefind
39 from IPython.utils.path import filefind
39 from IPython.utils.py3compat import str_to_bytes
40 from IPython.utils.py3compat import str_to_bytes
40 from IPython.utils.traitlets import (
41 from IPython.utils.traitlets import (
41 Dict, List, Unicode, CUnicode, Int, CBool, Any
42 Dict, List, Unicode, CUnicode, Int, CBool, Any, CaselessStrEnum
42 )
43 )
43 from IPython.zmq.ipkernel import (
44 from IPython.zmq.ipkernel import (
44 flags as ipkernel_flags,
45 flags as ipkernel_flags,
@@ -151,12 +152,27 b' class IPythonConsoleApp(Configurable):'
151 # create requested profiles by default, if they don't exist:
152 # create requested profiles by default, if they don't exist:
152 auto_create = CBool(True)
153 auto_create = CBool(True)
153 # connection info:
154 # connection info:
154 ip = Unicode(LOCALHOST, config=True,
155
156 transport = CaselessStrEnum(['tcp', 'ipc'], default_value='tcp', config=True)
157
158 ip = Unicode(config=True,
155 help="""Set the kernel\'s IP address [default localhost].
159 help="""Set the kernel\'s IP address [default localhost].
156 If the IP address is something other than localhost, then
160 If the IP address is something other than localhost, then
157 Consoles on other machines will be able to connect
161 Consoles on other machines will be able to connect
158 to the Kernel, so be careful!"""
162 to the Kernel, so be careful!"""
159 )
163 )
164 def _ip_default(self):
165 if self.transport == 'tcp':
166 return LOCALHOST
167 else:
168 # this can fire early if ip is given,
169 # in which case our return value is meaningless
170 if not hasattr(self, 'profile_dir'):
171 return ''
172 ipcdir = os.path.join(self.profile_dir.security_dir, 'kernel-%s' % os.getpid())
173 os.makedirs(ipcdir)
174 atexit.register(lambda : shutil.rmtree(ipcdir))
175 return os.path.join(ipcdir, 'ipc')
160
176
161 sshserver = Unicode('', config=True,
177 sshserver = Unicode('', config=True,
162 help="""The SSH server to use to connect to the kernel.""")
178 help="""The SSH server to use to connect to the kernel.""")
@@ -166,11 +182,11 b' class IPythonConsoleApp(Configurable):'
166 hb_port = Int(0, config=True,
182 hb_port = Int(0, config=True,
167 help="set the heartbeat port [default: random]")
183 help="set the heartbeat port [default: random]")
168 shell_port = Int(0, config=True,
184 shell_port = Int(0, config=True,
169 help="set the shell (XREP) port [default: random]")
185 help="set the shell (ROUTER) port [default: random]")
170 iopub_port = Int(0, config=True,
186 iopub_port = Int(0, config=True,
171 help="set the iopub (PUB) port [default: random]")
187 help="set the iopub (PUB) port [default: random]")
172 stdin_port = Int(0, config=True,
188 stdin_port = Int(0, config=True,
173 help="set the stdin (XREQ) port [default: random]")
189 help="set the stdin (DEALER) port [default: random]")
174 connection_file = Unicode('', config=True,
190 connection_file = Unicode('', config=True,
175 help="""JSON file in which to store connection info [default: kernel-<pid>.json]
191 help="""JSON file in which to store connection info [default: kernel-<pid>.json]
176
192
@@ -256,10 +272,10 b' class IPythonConsoleApp(Configurable):'
256 return
272 return
257 self.log.debug(u"Loading connection file %s", fname)
273 self.log.debug(u"Loading connection file %s", fname)
258 with open(fname) as f:
274 with open(fname) as f:
259 s = f.read()
275 cfg = json.load(f)
260 cfg = json.loads(s)
276
261 if self.ip == LOCALHOST and 'ip' in cfg:
277 self.transport = cfg.get('transport', 'tcp')
262 # not overridden by config or cl_args
278 if 'ip' in cfg:
263 self.ip = cfg['ip']
279 self.ip = cfg['ip']
264 for channel in ('hb', 'shell', 'iopub', 'stdin'):
280 for channel in ('hb', 'shell', 'iopub', 'stdin'):
265 name = channel + '_port'
281 name = channel + '_port'
@@ -268,12 +284,17 b' class IPythonConsoleApp(Configurable):'
268 setattr(self, name, cfg[name])
284 setattr(self, name, cfg[name])
269 if 'key' in cfg:
285 if 'key' in cfg:
270 self.config.Session.key = str_to_bytes(cfg['key'])
286 self.config.Session.key = str_to_bytes(cfg['key'])
287
271
288
272 def init_ssh(self):
289 def init_ssh(self):
273 """set up ssh tunnels, if needed."""
290 """set up ssh tunnels, if needed."""
274 if not self.sshserver and not self.sshkey:
291 if not self.sshserver and not self.sshkey:
275 return
292 return
276
293
294 if self.transport != 'tcp':
295 self.log.error("Can only use ssh tunnels with TCP sockets, not %s", self.transport)
296 return
297
277 if self.sshkey and not self.sshserver:
298 if self.sshkey and not self.sshserver:
278 # specifying just the key implies that we are connecting directly
299 # specifying just the key implies that we are connecting directly
279 self.sshserver = self.ip
300 self.sshserver = self.ip
@@ -326,6 +347,7 b' class IPythonConsoleApp(Configurable):'
326
347
327 # Create a KernelManager and start a kernel.
348 # Create a KernelManager and start a kernel.
328 self.kernel_manager = self.kernel_manager_class(
349 self.kernel_manager = self.kernel_manager_class(
350 transport=self.transport,
329 ip=self.ip,
351 ip=self.ip,
330 shell_port=self.shell_port,
352 shell_port=self.shell_port,
331 iopub_port=self.iopub_port,
353 iopub_port=self.iopub_port,
@@ -21,7 +21,7 b' from IPython.utils.py3compat import bytes_to_str'
21 from parentpoller import ParentPollerWindows
21 from parentpoller import ParentPollerWindows
22
22
23 def write_connection_file(fname=None, shell_port=0, iopub_port=0, stdin_port=0, hb_port=0,
23 def write_connection_file(fname=None, shell_port=0, iopub_port=0, stdin_port=0, hb_port=0,
24 ip=LOCALHOST, key=b''):
24 ip=LOCALHOST, key=b'', transport='tcp'):
25 """Generates a JSON config file, including the selection of random ports.
25 """Generates a JSON config file, including the selection of random ports.
26
26
27 Parameters
27 Parameters
@@ -54,17 +54,26 b' def write_connection_file(fname=None, shell_port=0, iopub_port=0, stdin_port=0, '
54 fname = tempfile.mktemp('.json')
54 fname = tempfile.mktemp('.json')
55
55
56 # Find open ports as necessary.
56 # Find open ports as necessary.
57
57 ports = []
58 ports = []
58 ports_needed = int(shell_port <= 0) + int(iopub_port <= 0) + \
59 ports_needed = int(shell_port <= 0) + int(iopub_port <= 0) + \
59 int(stdin_port <= 0) + int(hb_port <= 0)
60 int(stdin_port <= 0) + int(hb_port <= 0)
60 for i in xrange(ports_needed):
61 if transport == 'tcp':
61 sock = socket.socket()
62 for i in range(ports_needed):
62 sock.bind(('', 0))
63 sock = socket.socket()
63 ports.append(sock)
64 sock.bind(('', 0))
64 for i, sock in enumerate(ports):
65 ports.append(sock)
65 port = sock.getsockname()[1]
66 for i, sock in enumerate(ports):
66 sock.close()
67 port = sock.getsockname()[1]
67 ports[i] = port
68 sock.close()
69 ports[i] = port
70 else:
71 N = 1
72 for i in range(ports_needed):
73 while os.path.exists("%s-%s" % (ip, str(N))):
74 N += 1
75 ports.append(N)
76 N += 1
68 if shell_port <= 0:
77 if shell_port <= 0:
69 shell_port = ports.pop(0)
78 shell_port = ports.pop(0)
70 if iopub_port <= 0:
79 if iopub_port <= 0:
@@ -81,6 +90,7 b' def write_connection_file(fname=None, shell_port=0, iopub_port=0, stdin_port=0, '
81 )
90 )
82 cfg['ip'] = ip
91 cfg['ip'] = ip
83 cfg['key'] = bytes_to_str(key)
92 cfg['key'] = bytes_to_str(key)
93 cfg['transport'] = transport
84
94
85 with open(fname, 'w') as f:
95 with open(fname, 'w') as f:
86 f.write(json.dumps(cfg, indent=2))
96 f.write(json.dumps(cfg, indent=2))
@@ -12,6 +12,7 b''
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 import os
15 import socket
16 import socket
16 import sys
17 import sys
17 from threading import Thread
18 from threading import Thread
@@ -28,21 +29,28 b' from IPython.utils.localinterfaces import LOCALHOST'
28 class Heartbeat(Thread):
29 class Heartbeat(Thread):
29 "A simple ping-pong style heartbeat that runs in a thread."
30 "A simple ping-pong style heartbeat that runs in a thread."
30
31
31 def __init__(self, context, addr=(LOCALHOST, 0)):
32 def __init__(self, context, addr=('tcp', LOCALHOST, 0)):
32 Thread.__init__(self)
33 Thread.__init__(self)
33 self.context = context
34 self.context = context
34 self.ip, self.port = addr
35 self.transport, self.ip, self.port = addr
35 if self.port == 0:
36 if self.port == 0:
36 s = socket.socket()
37 if addr[0] == 'tcp':
37 # '*' means all interfaces to 0MQ, which is '' to socket.socket
38 s = socket.socket()
38 s.bind(('' if self.ip == '*' else self.ip, 0))
39 # '*' means all interfaces to 0MQ, which is '' to socket.socket
39 self.port = s.getsockname()[1]
40 s.bind(('' if self.ip == '*' else self.ip, 0))
40 s.close()
41 self.port = s.getsockname()[1]
42 s.close()
43 elif addr[0] == 'ipc':
44 while os.path.exists(self.ip + '-' + self.port):
45 self.port = self.port + 1
46 else:
47 raise ValueError("Unrecognized zmq transport: %s" % addr[0])
41 self.addr = (self.ip, self.port)
48 self.addr = (self.ip, self.port)
42 self.daemon = True
49 self.daemon = True
43
50
44 def run(self):
51 def run(self):
45 self.socket = self.context.socket(zmq.REP)
52 self.socket = self.context.socket(zmq.REP)
46 self.socket.bind('tcp://%s:%i' % self.addr)
53 c = ':' if self.transport == 'tcp' else '-'
54 self.socket.bind('%s://%s' % (self.transport, self.ip) + c + str(self.port))
47 zmq.device(zmq.FORWARDER, self.socket, self.socket)
55 zmq.device(zmq.FORWARDER, self.socket, self.socket)
48
56
@@ -35,8 +35,10 b' from IPython.utils import io'
35 from IPython.utils.localinterfaces import LOCALHOST
35 from IPython.utils.localinterfaces import LOCALHOST
36 from IPython.utils.path import filefind
36 from IPython.utils.path import filefind
37 from IPython.utils.py3compat import str_to_bytes
37 from IPython.utils.py3compat import str_to_bytes
38 from IPython.utils.traitlets import (Any, Instance, Dict, Unicode, Integer, Bool,
38 from IPython.utils.traitlets import (
39 DottedObjectName)
39 Any, Instance, Dict, Unicode, Integer, Bool, CaselessStrEnum,
40 DottedObjectName,
41 )
40 from IPython.utils.importstring import import_item
42 from IPython.utils.importstring import import_item
41 # local imports
43 # local imports
42 from IPython.zmq.entry_point import write_connection_file
44 from IPython.zmq.entry_point import write_connection_file
@@ -109,6 +111,7 b' class KernelApp(BaseIPythonApplication):'
109 self.config_file_specified = False
111 self.config_file_specified = False
110
112
111 # connection info:
113 # connection info:
114 transport = CaselessStrEnum(['tcp', 'ipc'], default_value='tcp', config=True)
112 ip = Unicode(LOCALHOST, config=True,
115 ip = Unicode(LOCALHOST, config=True,
113 help="Set the IP or interface on which the kernel will listen.")
116 help="Set the IP or interface on which the kernel will listen.")
114 hb_port = Integer(0, config=True, help="set the heartbeat port [default: random]")
117 hb_port = Integer(0, config=True, help="set the heartbeat port [default: random]")
@@ -154,11 +157,12 b' class KernelApp(BaseIPythonApplication):'
154 self.poller = ParentPollerUnix()
157 self.poller = ParentPollerUnix()
155
158
156 def _bind_socket(self, s, port):
159 def _bind_socket(self, s, port):
157 iface = 'tcp://%s' % self.ip
160 iface = '%s://%s' % (self.transport, self.ip)
158 if port <= 0:
161 if port <= 0 and self.transport == 'tcp':
159 port = s.bind_to_random_port(iface)
162 port = s.bind_to_random_port(iface)
160 else:
163 else:
161 s.bind(iface + ':%i'%port)
164 c = ':' if self.transport == 'tcp' else '-'
165 s.bind(iface + c + str(port))
162 return port
166 return port
163
167
164 def load_connection_file(self):
168 def load_connection_file(self):
@@ -174,6 +178,7 b' class KernelApp(BaseIPythonApplication):'
174 with open(fname) as f:
178 with open(fname) as f:
175 s = f.read()
179 s = f.read()
176 cfg = json.loads(s)
180 cfg = json.loads(s)
181 self.transport = cfg.get('transport', self.transport)
177 if self.ip == LOCALHOST and 'ip' in cfg:
182 if self.ip == LOCALHOST and 'ip' in cfg:
178 # not overridden by config or cl_args
183 # not overridden by config or cl_args
179 self.ip = cfg['ip']
184 self.ip = cfg['ip']
@@ -191,7 +196,7 b' class KernelApp(BaseIPythonApplication):'
191 cf = os.path.join(self.profile_dir.security_dir, self.connection_file)
196 cf = os.path.join(self.profile_dir.security_dir, self.connection_file)
192 else:
197 else:
193 cf = self.connection_file
198 cf = self.connection_file
194 write_connection_file(cf, ip=self.ip, key=self.session.key,
199 write_connection_file(cf, ip=self.ip, key=self.session.key, transport=self.transport,
195 shell_port=self.shell_port, stdin_port=self.stdin_port, hb_port=self.hb_port,
200 shell_port=self.shell_port, stdin_port=self.stdin_port, hb_port=self.hb_port,
196 iopub_port=self.iopub_port)
201 iopub_port=self.iopub_port)
197
202
@@ -204,6 +209,19 b' class KernelApp(BaseIPythonApplication):'
204 os.remove(cf)
209 os.remove(cf)
205 except (IOError, OSError):
210 except (IOError, OSError):
206 pass
211 pass
212
213 self._cleanup_ipc_files()
214
215 def _cleanup_ipc_files(self):
216 """cleanup ipc files if we wrote them"""
217 if self.transport != 'ipc':
218 return
219 for port in (self.shell_port, self.iopub_port, self.stdin_port, self.hb_port):
220 ipcfile = "%s-%i" % (self.ip, port)
221 try:
222 os.remove(ipcfile)
223 except (IOError, OSError):
224 pass
207
225
208 def init_connection_file(self):
226 def init_connection_file(self):
209 if not self.connection_file:
227 if not self.connection_file:
@@ -238,7 +256,7 b' class KernelApp(BaseIPythonApplication):'
238 # heartbeat doesn't share context, because it mustn't be blocked
256 # heartbeat doesn't share context, because it mustn't be blocked
239 # by the GIL, which is accessed by libzmq when freeing zero-copy messages
257 # by the GIL, which is accessed by libzmq when freeing zero-copy messages
240 hb_ctx = zmq.Context()
258 hb_ctx = zmq.Context()
241 self.heartbeat = Heartbeat(hb_ctx, (self.ip, self.hb_port))
259 self.heartbeat = Heartbeat(hb_ctx, (self.transport, self.ip, self.hb_port))
242 self.hb_port = self.heartbeat.port
260 self.hb_port = self.heartbeat.port
243 self.log.debug("Heartbeat REP Channel on port: %i"%self.hb_port)
261 self.log.debug("Heartbeat REP Channel on port: %i"%self.hb_port)
244 self.heartbeat.start()
262 self.heartbeat.start()
@@ -37,7 +37,7 b' from zmq.eventloop import ioloop, zmqstream'
37 from IPython.config.loader import Config
37 from IPython.config.loader import Config
38 from IPython.utils.localinterfaces import LOCALHOST, LOCAL_IPS
38 from IPython.utils.localinterfaces import LOCALHOST, LOCAL_IPS
39 from IPython.utils.traitlets import (
39 from IPython.utils.traitlets import (
40 HasTraits, Any, Instance, Type, Unicode, Integer, Bool
40 HasTraits, Any, Instance, Type, Unicode, Integer, Bool, CaselessStrEnum
41 )
41 )
42 from IPython.utils.py3compat import str_to_bytes
42 from IPython.utils.py3compat import str_to_bytes
43 from IPython.zmq.entry_point import write_connection_file
43 from IPython.zmq.entry_point import write_connection_file
@@ -103,7 +103,7 b' class ZMQSocketChannel(Thread):'
103 The ZMQ context to use.
103 The ZMQ context to use.
104 session : :class:`session.Session`
104 session : :class:`session.Session`
105 The session to use.
105 The session to use.
106 address : tuple
106 address : zmq url
107 Standard (ip, port) tuple that the kernel is listening on.
107 Standard (ip, port) tuple that the kernel is listening on.
108 """
108 """
109 super(ZMQSocketChannel, self).__init__()
109 super(ZMQSocketChannel, self).__init__()
@@ -111,9 +111,11 b' class ZMQSocketChannel(Thread):'
111
111
112 self.context = context
112 self.context = context
113 self.session = session
113 self.session = session
114 if address[1] == 0:
114 if isinstance(address, tuple):
115 message = 'The port number for a channel cannot be 0.'
115 if address[1] == 0:
116 raise InvalidPortNumber(message)
116 message = 'The port number for a channel cannot be 0.'
117 raise InvalidPortNumber(message)
118 address = "tcp://%s:%i" % address
117 self._address = address
119 self._address = address
118 atexit.register(self._notice_exit)
120 atexit.register(self._notice_exit)
119
121
@@ -149,10 +151,7 b' class ZMQSocketChannel(Thread):'
149
151
150 @property
152 @property
151 def address(self):
153 def address(self):
152 """Get the channel's address as an (ip, port) tuple.
154 """Get the channel's address as a zmq url string ('tcp://127.0.0.1:5555').
153
154 By the default, the address is (localhost, 0), where 0 means a random
155 port.
156 """
155 """
157 return self._address
156 return self._address
158
157
@@ -196,7 +195,7 b' class ShellSocketChannel(ZMQSocketChannel):'
196 """The thread's main activity. Call start() instead."""
195 """The thread's main activity. Call start() instead."""
197 self.socket = self.context.socket(zmq.DEALER)
196 self.socket = self.context.socket(zmq.DEALER)
198 self.socket.setsockopt(zmq.IDENTITY, self.session.bsession)
197 self.socket.setsockopt(zmq.IDENTITY, self.session.bsession)
199 self.socket.connect('tcp://%s:%i' % self.address)
198 self.socket.connect(self.address)
200 self.stream = zmqstream.ZMQStream(self.socket, self.ioloop)
199 self.stream = zmqstream.ZMQStream(self.socket, self.ioloop)
201 self.stream.on_recv(self._handle_recv)
200 self.stream.on_recv(self._handle_recv)
202 self._run_loop()
201 self._run_loop()
@@ -390,7 +389,7 b' class SubSocketChannel(ZMQSocketChannel):'
390 self.socket = self.context.socket(zmq.SUB)
389 self.socket = self.context.socket(zmq.SUB)
391 self.socket.setsockopt(zmq.SUBSCRIBE,b'')
390 self.socket.setsockopt(zmq.SUBSCRIBE,b'')
392 self.socket.setsockopt(zmq.IDENTITY, self.session.bsession)
391 self.socket.setsockopt(zmq.IDENTITY, self.session.bsession)
393 self.socket.connect('tcp://%s:%i' % self.address)
392 self.socket.connect(self.address)
394 self.stream = zmqstream.ZMQStream(self.socket, self.ioloop)
393 self.stream = zmqstream.ZMQStream(self.socket, self.ioloop)
395 self.stream.on_recv(self._handle_recv)
394 self.stream.on_recv(self._handle_recv)
396 self._run_loop()
395 self._run_loop()
@@ -456,7 +455,7 b' class StdInSocketChannel(ZMQSocketChannel):'
456 """The thread's main activity. Call start() instead."""
455 """The thread's main activity. Call start() instead."""
457 self.socket = self.context.socket(zmq.DEALER)
456 self.socket = self.context.socket(zmq.DEALER)
458 self.socket.setsockopt(zmq.IDENTITY, self.session.bsession)
457 self.socket.setsockopt(zmq.IDENTITY, self.session.bsession)
459 self.socket.connect('tcp://%s:%i' % self.address)
458 self.socket.connect(self.address)
460 self.stream = zmqstream.ZMQStream(self.socket, self.ioloop)
459 self.stream = zmqstream.ZMQStream(self.socket, self.ioloop)
461 self.stream.on_recv(self._handle_recv)
460 self.stream.on_recv(self._handle_recv)
462 self._run_loop()
461 self._run_loop()
@@ -515,7 +514,7 b' class HBSocketChannel(ZMQSocketChannel):'
515 self.socket.close()
514 self.socket.close()
516 self.socket = self.context.socket(zmq.REQ)
515 self.socket = self.context.socket(zmq.REQ)
517 self.socket.setsockopt(zmq.LINGER, 0)
516 self.socket.setsockopt(zmq.LINGER, 0)
518 self.socket.connect('tcp://%s:%i' % self.address)
517 self.socket.connect(self.address)
519
518
520 self.poller.register(self.socket, zmq.POLLIN)
519 self.poller.register(self.socket, zmq.POLLIN)
521
520
@@ -654,6 +653,10 b' class KernelManager(HasTraits):'
654
653
655 # The addresses for the communication channels.
654 # The addresses for the communication channels.
656 connection_file = Unicode('')
655 connection_file = Unicode('')
656
657 transport = CaselessStrEnum(['tcp', 'ipc'], default_value='tcp')
658
659
657 ip = Unicode(LOCALHOST)
660 ip = Unicode(LOCALHOST)
658 def _ip_changed(self, name, old, new):
661 def _ip_changed(self, name, old, new):
659 if new == '*':
662 if new == '*':
@@ -742,7 +745,20 b' class KernelManager(HasTraits):'
742 self._connection_file_written = False
745 self._connection_file_written = False
743 try:
746 try:
744 os.remove(self.connection_file)
747 os.remove(self.connection_file)
745 except OSError:
748 except (IOError, OSError):
749 pass
750
751 self._cleanup_ipc_files()
752
753 def _cleanup_ipc_files(self):
754 """cleanup ipc files if we wrote them"""
755 if self.transport != 'ipc':
756 return
757 for port in (self.shell_port, self.iopub_port, self.stdin_port, self.hb_port):
758 ipcfile = "%s-%i" % (self.ip, port)
759 try:
760 os.remove(ipcfile)
761 except (IOError, OSError):
746 pass
762 pass
747
763
748 def load_connection_file(self):
764 def load_connection_file(self):
@@ -750,6 +766,9 b' class KernelManager(HasTraits):'
750 with open(self.connection_file) as f:
766 with open(self.connection_file) as f:
751 cfg = json.loads(f.read())
767 cfg = json.loads(f.read())
752
768
769 from pprint import pprint
770 pprint(cfg)
771 self.transport = cfg.get('transport', 'tcp')
753 self.ip = cfg['ip']
772 self.ip = cfg['ip']
754 self.shell_port = cfg['shell_port']
773 self.shell_port = cfg['shell_port']
755 self.stdin_port = cfg['stdin_port']
774 self.stdin_port = cfg['stdin_port']
@@ -762,7 +781,7 b' class KernelManager(HasTraits):'
762 if self._connection_file_written:
781 if self._connection_file_written:
763 return
782 return
764 self.connection_file,cfg = write_connection_file(self.connection_file,
783 self.connection_file,cfg = write_connection_file(self.connection_file,
765 ip=self.ip, key=self.session.key,
784 transport=self.transport, ip=self.ip, key=self.session.key,
766 stdin_port=self.stdin_port, iopub_port=self.iopub_port,
785 stdin_port=self.stdin_port, iopub_port=self.iopub_port,
767 shell_port=self.shell_port, hb_port=self.hb_port)
786 shell_port=self.shell_port, hb_port=self.hb_port)
768 # write_connection_file also sets default ports:
787 # write_connection_file also sets default ports:
@@ -789,7 +808,7 b' class KernelManager(HasTraits):'
789 **kw : optional
808 **kw : optional
790 See respective options for IPython and Python kernels.
809 See respective options for IPython and Python kernels.
791 """
810 """
792 if self.ip not in LOCAL_IPS:
811 if self.transport == 'tcp' and self.ip not in LOCAL_IPS:
793 raise RuntimeError("Can only launch a kernel on a local interface. "
812 raise RuntimeError("Can only launch a kernel on a local interface. "
794 "Make sure that the '*_address' attributes are "
813 "Make sure that the '*_address' attributes are "
795 "configured properly. "
814 "configured properly. "
@@ -956,13 +975,21 b' class KernelManager(HasTraits):'
956 # Channels used for communication with the kernel:
975 # Channels used for communication with the kernel:
957 #--------------------------------------------------------------------------
976 #--------------------------------------------------------------------------
958
977
978 def _make_url(self, port):
979 """make a zmq url with a port"""
980 if self.transport == 'tcp':
981 return "tcp://%s:%i" % (self.ip, port)
982 else:
983 return "%s://%s-%s" % (self.transport, self.ip, port)
984
959 @property
985 @property
960 def shell_channel(self):
986 def shell_channel(self):
961 """Get the REQ socket channel object to make requests of the kernel."""
987 """Get the REQ socket channel object to make requests of the kernel."""
962 if self._shell_channel is None:
988 if self._shell_channel is None:
963 self._shell_channel = self.shell_channel_class(self.context,
989 self._shell_channel = self.shell_channel_class(self.context,
964 self.session,
990 self.session,
965 (self.ip, self.shell_port))
991 self._make_url(self.shell_port),
992 )
966 return self._shell_channel
993 return self._shell_channel
967
994
968 @property
995 @property
@@ -971,7 +998,8 b' class KernelManager(HasTraits):'
971 if self._sub_channel is None:
998 if self._sub_channel is None:
972 self._sub_channel = self.sub_channel_class(self.context,
999 self._sub_channel = self.sub_channel_class(self.context,
973 self.session,
1000 self.session,
974 (self.ip, self.iopub_port))
1001 self._make_url(self.iopub_port),
1002 )
975 return self._sub_channel
1003 return self._sub_channel
976
1004
977 @property
1005 @property
@@ -979,8 +1007,9 b' class KernelManager(HasTraits):'
979 """Get the REP socket channel object to handle stdin (raw_input)."""
1007 """Get the REP socket channel object to handle stdin (raw_input)."""
980 if self._stdin_channel is None:
1008 if self._stdin_channel is None:
981 self._stdin_channel = self.stdin_channel_class(self.context,
1009 self._stdin_channel = self.stdin_channel_class(self.context,
982 self.session,
1010 self.session,
983 (self.ip, self.stdin_port))
1011 self._make_url(self.stdin_port),
1012 )
984 return self._stdin_channel
1013 return self._stdin_channel
985
1014
986 @property
1015 @property
@@ -989,6 +1018,7 b' class KernelManager(HasTraits):'
989 kernel is alive."""
1018 kernel is alive."""
990 if self._hb_channel is None:
1019 if self._hb_channel is None:
991 self._hb_channel = self.hb_channel_class(self.context,
1020 self._hb_channel = self.hb_channel_class(self.context,
992 self.session,
1021 self.session,
993 (self.ip, self.hb_port))
1022 self._make_url(self.hb_port),
1023 )
994 return self._hb_channel
1024 return self._hb_channel
General Comments 0
You need to be logged in to leave comments. Login now