Show More
@@ -88,11 +88,12 b' aliases = dict(ipkernel_aliases)' | |||||
88 |
|
88 | |||
89 | # also scrub aliases from the frontend |
|
89 | # also scrub aliases from the frontend | |
90 | app_aliases = dict( |
|
90 | app_aliases = dict( | |
|
91 | ip = 'KernelManager.ip', | |||
|
92 | transport = 'KernelManager.transport', | |||
91 | hb = 'IPythonConsoleApp.hb_port', |
|
93 | hb = 'IPythonConsoleApp.hb_port', | |
92 | shell = 'IPythonConsoleApp.shell_port', |
|
94 | shell = 'IPythonConsoleApp.shell_port', | |
93 | iopub = 'IPythonConsoleApp.iopub_port', |
|
95 | iopub = 'IPythonConsoleApp.iopub_port', | |
94 | stdin = 'IPythonConsoleApp.stdin_port', |
|
96 | stdin = 'IPythonConsoleApp.stdin_port', | |
95 | ip = 'IPythonConsoleApp.ip', |
|
|||
96 | existing = 'IPythonConsoleApp.existing', |
|
97 | existing = 'IPythonConsoleApp.existing', | |
97 | f = 'IPythonConsoleApp.connection_file', |
|
98 | f = 'IPythonConsoleApp.connection_file', | |
98 |
|
99 | |||
@@ -153,27 +154,6 b' class IPythonConsoleApp(Configurable):' | |||||
153 | auto_create = CBool(True) |
|
154 | auto_create = CBool(True) | |
154 | # connection info: |
|
155 | # connection info: | |
155 |
|
156 | |||
156 | transport = CaselessStrEnum(['tcp', 'ipc'], default_value='tcp', config=True) |
|
|||
157 |
|
||||
158 | ip = Unicode(config=True, |
|
|||
159 | help="""Set the kernel\'s IP address [default localhost]. |
|
|||
160 | If the IP address is something other than localhost, then |
|
|||
161 | Consoles on other machines will be able to connect |
|
|||
162 | to the Kernel, so be careful!""" |
|
|||
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') |
|
|||
176 |
|
||||
177 | sshserver = Unicode('', config=True, |
|
157 | sshserver = Unicode('', config=True, | |
178 | help="""The SSH server to use to connect to the kernel.""") |
|
158 | help="""The SSH server to use to connect to the kernel.""") | |
179 | sshkey = Unicode('', config=True, |
|
159 | sshkey = Unicode('', config=True, | |
@@ -274,9 +254,9 b' class IPythonConsoleApp(Configurable):' | |||||
274 | with open(fname) as f: |
|
254 | with open(fname) as f: | |
275 | cfg = json.load(f) |
|
255 | cfg = json.load(f) | |
276 |
|
256 | |||
277 | self.transport = cfg.get('transport', 'tcp') |
|
257 | self.config.KernelManager.transport = cfg.get('transport', 'tcp') | |
278 | if 'ip' in cfg: |
|
258 | self.config.KernelManager.ip = cfg.get('ip', LOCALHOST) | |
279 | self.ip = cfg['ip'] |
|
259 | ||
280 | for channel in ('hb', 'shell', 'iopub', 'stdin'): |
|
260 | for channel in ('hb', 'shell', 'iopub', 'stdin'): | |
281 | name = channel + '_port' |
|
261 | name = channel + '_port' | |
282 | if getattr(self, name) == 0 and name in cfg: |
|
262 | if getattr(self, name) == 0 and name in cfg: | |
@@ -284,34 +264,38 b' class IPythonConsoleApp(Configurable):' | |||||
284 | setattr(self, name, cfg[name]) |
|
264 | setattr(self, name, cfg[name]) | |
285 | if 'key' in cfg: |
|
265 | if 'key' in cfg: | |
286 | self.config.Session.key = str_to_bytes(cfg['key']) |
|
266 | self.config.Session.key = str_to_bytes(cfg['key']) | |
287 |
|
||||
288 |
|
267 | |||
289 | def init_ssh(self): |
|
268 | def init_ssh(self): | |
290 | """set up ssh tunnels, if needed.""" |
|
269 | """set up ssh tunnels, if needed.""" | |
291 | if not self.sshserver and not self.sshkey: |
|
270 | if not self.existing or (not self.sshserver and not self.sshkey): | |
292 | return |
|
271 | return | |
293 |
|
272 | |||
294 | if self.transport != 'tcp': |
|
273 | self.load_connection_file() | |
295 | self.log.error("Can only use ssh tunnels with TCP sockets, not %s", self.transport) |
|
274 | ||
296 | return |
|
275 | transport = self.config.KernelManager.transport | |
|
276 | ip = self.config.KernelManager.ip | |||
|
277 | ||||
|
278 | if transport != 'tcp': | |||
|
279 | self.log.error("Can only use ssh tunnels with TCP sockets, not %s", transport) | |||
|
280 | sys.exit(-1) | |||
297 |
|
281 | |||
298 | if self.sshkey and not self.sshserver: |
|
282 | if self.sshkey and not self.sshserver: | |
299 | # specifying just the key implies that we are connecting directly |
|
283 | # specifying just the key implies that we are connecting directly | |
300 |
self.sshserver = |
|
284 | self.sshserver = ip | |
301 |
|
|
285 | ip = LOCALHOST | |
302 |
|
286 | |||
303 | # build connection dict for tunnels: |
|
287 | # build connection dict for tunnels: | |
304 |
info = dict(ip= |
|
288 | info = dict(ip=ip, | |
305 | shell_port=self.shell_port, |
|
289 | shell_port=self.shell_port, | |
306 | iopub_port=self.iopub_port, |
|
290 | iopub_port=self.iopub_port, | |
307 | stdin_port=self.stdin_port, |
|
291 | stdin_port=self.stdin_port, | |
308 | hb_port=self.hb_port |
|
292 | hb_port=self.hb_port | |
309 | ) |
|
293 | ) | |
310 |
|
294 | |||
311 |
self.log.info("Forwarding connections to %s via %s"%( |
|
295 | self.log.info("Forwarding connections to %s via %s"%(ip, self.sshserver)) | |
312 |
|
296 | |||
313 | # tunnels return a new set of ports, which will be on localhost: |
|
297 | # tunnels return a new set of ports, which will be on localhost: | |
314 | self.ip = LOCALHOST |
|
298 | self.config.KernelManager.ip = LOCALHOST | |
315 | try: |
|
299 | try: | |
316 | newports = tunnel_to_kernel(info, self.sshserver, self.sshkey) |
|
300 | newports = tunnel_to_kernel(info, self.sshserver, self.sshkey) | |
317 | except: |
|
301 | except: | |
@@ -347,8 +331,6 b' class IPythonConsoleApp(Configurable):' | |||||
347 |
|
331 | |||
348 | # Create a KernelManager and start a kernel. |
|
332 | # Create a KernelManager and start a kernel. | |
349 | self.kernel_manager = self.kernel_manager_class( |
|
333 | self.kernel_manager = self.kernel_manager_class( | |
350 | transport=self.transport, |
|
|||
351 | ip=self.ip, |
|
|||
352 | shell_port=self.shell_port, |
|
334 | shell_port=self.shell_port, | |
353 | iopub_port=self.iopub_port, |
|
335 | iopub_port=self.iopub_port, | |
354 | stdin_port=self.stdin_port, |
|
336 | stdin_port=self.stdin_port, | |
@@ -359,6 +341,7 b' class IPythonConsoleApp(Configurable):' | |||||
359 | # start the kernel |
|
341 | # start the kernel | |
360 | if not self.existing: |
|
342 | if not self.existing: | |
361 | self.kernel_manager.start_kernel(extra_arguments=self.kernel_argv) |
|
343 | self.kernel_manager.start_kernel(extra_arguments=self.kernel_argv) | |
|
344 | atexit.register(self.kernel_manager.cleanup_ipc_files) | |||
362 | elif self.sshserver: |
|
345 | elif self.sshserver: | |
363 | # ssh, write new connection file |
|
346 | # ssh, write new connection file | |
364 | self.kernel_manager.write_connection_file() |
|
347 | self.kernel_manager.write_connection_file() |
@@ -242,6 +242,7 b' aliases.update({' | |||||
242 | 'ip': 'NotebookApp.ip', |
|
242 | 'ip': 'NotebookApp.ip', | |
243 | 'port': 'NotebookApp.port', |
|
243 | 'port': 'NotebookApp.port', | |
244 | 'port-retries': 'NotebookApp.port_retries', |
|
244 | 'port-retries': 'NotebookApp.port_retries', | |
|
245 | 'transport': 'KernelManager.transport', | |||
245 | 'keyfile': 'NotebookApp.keyfile', |
|
246 | 'keyfile': 'NotebookApp.keyfile', | |
246 | 'certfile': 'NotebookApp.certfile', |
|
247 | 'certfile': 'NotebookApp.certfile', | |
247 | 'notebook-dir': 'NotebookManager.notebook_dir', |
|
248 | 'notebook-dir': 'NotebookManager.notebook_dir', |
@@ -193,9 +193,7 b' class IPythonQtConsoleApp(BaseIPythonApplication, IPythonConsoleApp):' | |||||
193 | def new_frontend_master(self): |
|
193 | def new_frontend_master(self): | |
194 | """ Create and return new frontend attached to new kernel, launched on localhost. |
|
194 | """ Create and return new frontend attached to new kernel, launched on localhost. | |
195 | """ |
|
195 | """ | |
196 | ip = self.ip if self.ip in LOCAL_IPS else LOCALHOST |
|
|||
197 | kernel_manager = self.kernel_manager_class( |
|
196 | kernel_manager = self.kernel_manager_class( | |
198 | ip=ip, |
|
|||
199 | connection_file=self._new_connection_file(), |
|
197 | connection_file=self._new_connection_file(), | |
200 | config=self.config, |
|
198 | config=self.config, | |
201 | ) |
|
199 | ) | |
@@ -245,7 +243,11 b' class IPythonQtConsoleApp(BaseIPythonApplication, IPythonConsoleApp):' | |||||
245 | self.app.icon = QtGui.QIcon(icon_path) |
|
243 | self.app.icon = QtGui.QIcon(icon_path) | |
246 | QtGui.QApplication.setWindowIcon(self.app.icon) |
|
244 | QtGui.QApplication.setWindowIcon(self.app.icon) | |
247 |
|
245 | |||
248 | local_kernel = (not self.existing) or self.ip in LOCAL_IPS |
|
246 | try: | |
|
247 | ip = self.config.KernelManager.ip | |||
|
248 | except AttributeError: | |||
|
249 | ip = LOCALHOST | |||
|
250 | local_kernel = (not self.existing) or ip in LOCAL_IPS | |||
249 | self.widget = self.widget_factory(config=self.config, |
|
251 | self.widget = self.widget_factory(config=self.config, | |
250 | local_kernel=local_kernel) |
|
252 | local_kernel=local_kernel) | |
251 | self.init_colors(self.widget) |
|
253 | self.init_colors(self.widget) |
@@ -41,7 +41,8 b' class Heartbeat(Thread):' | |||||
41 | self.port = s.getsockname()[1] |
|
41 | self.port = s.getsockname()[1] | |
42 | s.close() |
|
42 | s.close() | |
43 | elif addr[0] == 'ipc': |
|
43 | elif addr[0] == 'ipc': | |
44 | while os.path.exists(self.ip + '-' + self.port): |
|
44 | self.port = 1 | |
|
45 | while os.path.exists("%s-%s" % (self.ip, self.port)): | |||
45 | self.port = self.port + 1 |
|
46 | self.port = self.port + 1 | |
46 | else: |
|
47 | else: | |
47 | raise ValueError("Unrecognized zmq transport: %s" % addr[0]) |
|
48 | raise ValueError("Unrecognized zmq transport: %s" % addr[0]) |
@@ -62,6 +62,7 b' kernel_aliases.update({' | |||||
62 | 'stdin' : 'KernelApp.stdin_port', |
|
62 | 'stdin' : 'KernelApp.stdin_port', | |
63 | 'f' : 'KernelApp.connection_file', |
|
63 | 'f' : 'KernelApp.connection_file', | |
64 | 'parent': 'KernelApp.parent', |
|
64 | 'parent': 'KernelApp.parent', | |
|
65 | 'transport': 'KernelApp.transport', | |||
65 | }) |
|
66 | }) | |
66 | if sys.platform.startswith('win'): |
|
67 | if sys.platform.startswith('win'): | |
67 | kernel_aliases['interrupt'] = 'KernelApp.interrupt' |
|
68 | kernel_aliases['interrupt'] = 'KernelApp.interrupt' | |
@@ -98,7 +99,6 b' class KernelApp(BaseIPythonApplication):' | |||||
98 | heartbeat = Instance(Heartbeat) |
|
99 | heartbeat = Instance(Heartbeat) | |
99 | session = Instance('IPython.zmq.session.Session') |
|
100 | session = Instance('IPython.zmq.session.Session') | |
100 | ports = Dict() |
|
101 | ports = Dict() | |
101 | _full_connection_file = Unicode() |
|
|||
102 |
|
102 | |||
103 | # inherit config file name from parent: |
|
103 | # inherit config file name from parent: | |
104 | parent_appname = Unicode(config=True) |
|
104 | parent_appname = Unicode(config=True) | |
@@ -112,8 +112,16 b' class KernelApp(BaseIPythonApplication):' | |||||
112 |
|
112 | |||
113 | # connection info: |
|
113 | # connection info: | |
114 | transport = CaselessStrEnum(['tcp', 'ipc'], default_value='tcp', config=True) |
|
114 | transport = CaselessStrEnum(['tcp', 'ipc'], default_value='tcp', config=True) | |
115 |
ip = Unicode( |
|
115 | ip = Unicode(config=True, | |
116 | 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.") | |
|
117 | def _ip_default(self): | |||
|
118 | if self.transport == 'ipc': | |||
|
119 | if self.connection_file: | |||
|
120 | return os.path.splitext(self.abs_connection_file)[0] + '-ipc' | |||
|
121 | else: | |||
|
122 | return 'kernel-ipc' | |||
|
123 | else: | |||
|
124 | return LOCALHOST | |||
117 | hb_port = Integer(0, config=True, help="set the heartbeat port [default: random]") |
|
125 | hb_port = Integer(0, config=True, help="set the heartbeat port [default: random]") | |
118 | shell_port = Integer(0, config=True, help="set the shell (ROUTER) port [default: random]") |
|
126 | shell_port = Integer(0, config=True, help="set the shell (ROUTER) port [default: random]") | |
119 | iopub_port = Integer(0, config=True, help="set the iopub (PUB) port [default: random]") |
|
127 | iopub_port = Integer(0, config=True, help="set the iopub (PUB) port [default: random]") | |
@@ -122,9 +130,16 b' class KernelApp(BaseIPythonApplication):' | |||||
122 | help="""JSON file in which to store connection info [default: kernel-<pid>.json] |
|
130 | help="""JSON file in which to store connection info [default: kernel-<pid>.json] | |
123 |
|
131 | |||
124 | This file will contain the IP, ports, and authentication key needed to connect |
|
132 | This file will contain the IP, ports, and authentication key needed to connect | |
125 |
clients to this kernel. By default, this file will be created in the security |
|
133 | clients to this kernel. By default, this file will be created in the security dir | |
126 | of the current profile, but can be specified by absolute path. |
|
134 | of the current profile, but can be specified by absolute path. | |
127 | """) |
|
135 | """) | |
|
136 | @property | |||
|
137 | def abs_connection_file(self): | |||
|
138 | if os.path.basename(self.connection_file) == self.connection_file: | |||
|
139 | return os.path.join(self.profile_dir.security_dir, self.connection_file) | |||
|
140 | else: | |||
|
141 | return self.connection_file | |||
|
142 | ||||
128 |
|
143 | |||
129 | # streams, etc. |
|
144 | # streams, etc. | |
130 | no_stdout = Bool(False, config=True, help="redirect stdout to the null device") |
|
145 | no_stdout = Bool(False, config=True, help="redirect stdout to the null device") | |
@@ -141,7 +156,7 b' class KernelApp(BaseIPythonApplication):' | |||||
141 | """) |
|
156 | """) | |
142 | interrupt = Integer(0, config=True, |
|
157 | interrupt = Integer(0, config=True, | |
143 | help="""ONLY USED ON WINDOWS |
|
158 | help="""ONLY USED ON WINDOWS | |
144 |
Interrupt this process when the parent is signal |
|
159 | Interrupt this process when the parent is signaled. | |
145 | """) |
|
160 | """) | |
146 |
|
161 | |||
147 | def init_crash_handler(self): |
|
162 | def init_crash_handler(self): | |
@@ -158,11 +173,21 b' class KernelApp(BaseIPythonApplication):' | |||||
158 |
|
173 | |||
159 | def _bind_socket(self, s, port): |
|
174 | def _bind_socket(self, s, port): | |
160 | iface = '%s://%s' % (self.transport, self.ip) |
|
175 | iface = '%s://%s' % (self.transport, self.ip) | |
161 |
if |
|
176 | if self.transport == 'tcp': | |
162 | port = s.bind_to_random_port(iface) |
|
177 | if port <= 0: | |
163 | else: |
|
178 | port = s.bind_to_random_port(iface) | |
164 | c = ':' if self.transport == 'tcp' else '-' |
|
179 | else: | |
165 | s.bind(iface + c + str(port)) |
|
180 | s.bind("tcp://%s:%i" % (self.ip, port)) | |
|
181 | elif self.transport == 'ipc': | |||
|
182 | if port <= 0: | |||
|
183 | port = 1 | |||
|
184 | path = "%s-%i" % (self.ip, port) | |||
|
185 | while os.path.exists(path): | |||
|
186 | port = port + 1 | |||
|
187 | path = "%s-%i" % (self.ip, port) | |||
|
188 | else: | |||
|
189 | path = "%s-%i" % (self.ip, port) | |||
|
190 | s.bind("ipc://%s" % path) | |||
166 | return port |
|
191 | return port | |
167 |
|
192 | |||
168 | def load_connection_file(self): |
|
193 | def load_connection_file(self): | |
@@ -179,7 +204,7 b' class KernelApp(BaseIPythonApplication):' | |||||
179 | s = f.read() |
|
204 | s = f.read() | |
180 | cfg = json.loads(s) |
|
205 | cfg = json.loads(s) | |
181 | self.transport = cfg.get('transport', self.transport) |
|
206 | self.transport = cfg.get('transport', self.transport) | |
182 |
if self.ip == |
|
207 | if self.ip == self._ip_default() and 'ip' in cfg: | |
183 | # not overridden by config or cl_args |
|
208 | # not overridden by config or cl_args | |
184 | self.ip = cfg['ip'] |
|
209 | self.ip = cfg['ip'] | |
185 | for channel in ('hb', 'shell', 'iopub', 'stdin'): |
|
210 | for channel in ('hb', 'shell', 'iopub', 'stdin'): | |
@@ -192,19 +217,15 b' class KernelApp(BaseIPythonApplication):' | |||||
192 |
|
217 | |||
193 | def write_connection_file(self): |
|
218 | def write_connection_file(self): | |
194 | """write connection info to JSON file""" |
|
219 | """write connection info to JSON file""" | |
195 | if os.path.basename(self.connection_file) == self.connection_file: |
|
220 | cf = self.abs_connection_file | |
196 | cf = os.path.join(self.profile_dir.security_dir, self.connection_file) |
|
221 | self.log.debug("Writing connection file: %s", cf) | |
197 | else: |
|
|||
198 | cf = self.connection_file |
|
|||
199 | write_connection_file(cf, ip=self.ip, key=self.session.key, transport=self.transport, |
|
222 | write_connection_file(cf, ip=self.ip, key=self.session.key, transport=self.transport, | |
200 | shell_port=self.shell_port, stdin_port=self.stdin_port, hb_port=self.hb_port, |
|
223 | shell_port=self.shell_port, stdin_port=self.stdin_port, hb_port=self.hb_port, | |
201 | iopub_port=self.iopub_port) |
|
224 | iopub_port=self.iopub_port) | |
202 |
|
||||
203 | self._full_connection_file = cf |
|
|||
204 |
|
225 | |||
205 | def cleanup_connection_file(self): |
|
226 | def cleanup_connection_file(self): | |
206 |
cf = self. |
|
227 | cf = self.abs_connection_file | |
207 |
self.log.debug(" |
|
228 | self.log.debug("Cleaning up connection file: %s", cf) | |
208 | try: |
|
229 | try: | |
209 | os.remove(cf) |
|
230 | os.remove(cf) | |
210 | except (IOError, OSError): |
|
231 | except (IOError, OSError): |
@@ -684,7 +684,20 b' class KernelManager(Configurable):' | |||||
684 |
|
684 | |||
685 | transport = CaselessStrEnum(['tcp', 'ipc'], default_value='tcp', config=True) |
|
685 | transport = CaselessStrEnum(['tcp', 'ipc'], default_value='tcp', config=True) | |
686 |
|
686 | |||
687 |
ip = Unicode(LOCALHOST, config=True |
|
687 | ip = Unicode(LOCALHOST, config=True, | |
|
688 | help="""Set the kernel\'s IP address [default localhost]. | |||
|
689 | If the IP address is something other than localhost, then | |||
|
690 | Consoles on other machines will be able to connect | |||
|
691 | to the Kernel, so be careful!""" | |||
|
692 | ) | |||
|
693 | def _ip_default(self): | |||
|
694 | if self.transport == 'ipc': | |||
|
695 | if self.connection_file: | |||
|
696 | return os.path.splitext(self.connection_file)[0] + '-ipc' | |||
|
697 | else: | |||
|
698 | return 'kernel-ipc' | |||
|
699 | else: | |||
|
700 | return LOCALHOST | |||
688 | def _ip_changed(self, name, old, new): |
|
701 | def _ip_changed(self, name, old, new): | |
689 | if new == '*': |
|
702 | if new == '*': | |
690 | self.ip = '0.0.0.0' |
|
703 | self.ip = '0.0.0.0' | |
@@ -706,8 +719,8 b' class KernelManager(Configurable):' | |||||
706 | _stdin_channel = Any |
|
719 | _stdin_channel = Any | |
707 | _hb_channel = Any |
|
720 | _hb_channel = Any | |
708 | _connection_file_written=Bool(False) |
|
721 | _connection_file_written=Bool(False) | |
709 |
|
722 | |||
710 |
def __del__(self): |
|
723 | def __del__(self): | |
711 | self.cleanup_connection_file() |
|
724 | self.cleanup_connection_file() | |
712 |
|
725 | |||
713 | #-------------------------------------------------------------------------- |
|
726 | #-------------------------------------------------------------------------- |
General Comments 0
You need to be logged in to leave comments.
Login now