##// END OF EJS Templates
Removed IPython.config.default from the default search path for ipcluster...
Brian Granger -
Show More
@@ -1,493 +1,493 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 The IPython cluster directory
4 The IPython cluster directory
5 """
5 """
6
6
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 # Copyright (C) 2008-2009 The IPython Development Team
8 # Copyright (C) 2008-2009 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 from __future__ import with_statement
18 from __future__ import with_statement
19
19
20 import os
20 import os
21 import shutil
21 import shutil
22 import sys
22 import sys
23 import warnings
23 import warnings
24
24
25 from twisted.python import log
25 from twisted.python import log
26
26
27 from IPython.config.loader import PyFileConfigLoader
27 from IPython.config.loader import PyFileConfigLoader
28 from IPython.core.application import Application, BaseAppConfigLoader
28 from IPython.core.application import Application, BaseAppConfigLoader
29 from IPython.core.component import Component
29 from IPython.core.component import Component
30 from IPython.utils.path import (
30 from IPython.utils.path import (
31 get_ipython_package_dir,
31 get_ipython_package_dir,
32 expand_path
32 expand_path
33 )
33 )
34 from IPython.utils.traitlets import Unicode
34 from IPython.utils.traitlets import Unicode
35
35
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37 # Warnings control
37 # Warnings control
38 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
39 # Twisted generates annoying warnings with Python 2.6, as will do other code
39 # Twisted generates annoying warnings with Python 2.6, as will do other code
40 # that imports 'sets' as of today
40 # that imports 'sets' as of today
41 warnings.filterwarnings('ignore', 'the sets module is deprecated',
41 warnings.filterwarnings('ignore', 'the sets module is deprecated',
42 DeprecationWarning )
42 DeprecationWarning )
43
43
44 # This one also comes from Twisted
44 # This one also comes from Twisted
45 warnings.filterwarnings('ignore', 'the sha module is deprecated',
45 warnings.filterwarnings('ignore', 'the sha module is deprecated',
46 DeprecationWarning)
46 DeprecationWarning)
47
47
48 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
49 # Module errors
49 # Module errors
50 #-----------------------------------------------------------------------------
50 #-----------------------------------------------------------------------------
51
51
52 class ClusterDirError(Exception):
52 class ClusterDirError(Exception):
53 pass
53 pass
54
54
55
55
56 class PIDFileError(Exception):
56 class PIDFileError(Exception):
57 pass
57 pass
58
58
59
59
60 #-----------------------------------------------------------------------------
60 #-----------------------------------------------------------------------------
61 # Class for managing cluster directories
61 # Class for managing cluster directories
62 #-----------------------------------------------------------------------------
62 #-----------------------------------------------------------------------------
63
63
64 class ClusterDir(Component):
64 class ClusterDir(Component):
65 """An object to manage the cluster directory and its resources.
65 """An object to manage the cluster directory and its resources.
66
66
67 The cluster directory is used by :command:`ipcontroller`,
67 The cluster directory is used by :command:`ipcontroller`,
68 :command:`ipcontroller` and :command:`ipcontroller` to manage the
68 :command:`ipcontroller` and :command:`ipcontroller` to manage the
69 configuration, logging and security of these applications.
69 configuration, logging and security of these applications.
70
70
71 This object knows how to find, create and manage these directories. This
71 This object knows how to find, create and manage these directories. This
72 should be used by any code that want's to handle cluster directories.
72 should be used by any code that want's to handle cluster directories.
73 """
73 """
74
74
75 security_dir_name = Unicode('security')
75 security_dir_name = Unicode('security')
76 log_dir_name = Unicode('log')
76 log_dir_name = Unicode('log')
77 pid_dir_name = Unicode('pid')
77 pid_dir_name = Unicode('pid')
78 security_dir = Unicode(u'')
78 security_dir = Unicode(u'')
79 log_dir = Unicode(u'')
79 log_dir = Unicode(u'')
80 pid_dir = Unicode(u'')
80 pid_dir = Unicode(u'')
81 location = Unicode(u'')
81 location = Unicode(u'')
82
82
83 def __init__(self, location):
83 def __init__(self, location):
84 super(ClusterDir, self).__init__(None)
84 super(ClusterDir, self).__init__(None)
85 self.location = location
85 self.location = location
86
86
87 def _location_changed(self, name, old, new):
87 def _location_changed(self, name, old, new):
88 if not os.path.isdir(new):
88 if not os.path.isdir(new):
89 os.makedirs(new)
89 os.makedirs(new)
90 self.security_dir = os.path.join(new, self.security_dir_name)
90 self.security_dir = os.path.join(new, self.security_dir_name)
91 self.log_dir = os.path.join(new, self.log_dir_name)
91 self.log_dir = os.path.join(new, self.log_dir_name)
92 self.pid_dir = os.path.join(new, self.pid_dir_name)
92 self.pid_dir = os.path.join(new, self.pid_dir_name)
93 self.check_dirs()
93 self.check_dirs()
94
94
95 def _log_dir_changed(self, name, old, new):
95 def _log_dir_changed(self, name, old, new):
96 self.check_log_dir()
96 self.check_log_dir()
97
97
98 def check_log_dir(self):
98 def check_log_dir(self):
99 if not os.path.isdir(self.log_dir):
99 if not os.path.isdir(self.log_dir):
100 os.mkdir(self.log_dir)
100 os.mkdir(self.log_dir)
101
101
102 def _security_dir_changed(self, name, old, new):
102 def _security_dir_changed(self, name, old, new):
103 self.check_security_dir()
103 self.check_security_dir()
104
104
105 def check_security_dir(self):
105 def check_security_dir(self):
106 if not os.path.isdir(self.security_dir):
106 if not os.path.isdir(self.security_dir):
107 os.mkdir(self.security_dir, 0700)
107 os.mkdir(self.security_dir, 0700)
108 os.chmod(self.security_dir, 0700)
108 os.chmod(self.security_dir, 0700)
109
109
110 def _pid_dir_changed(self, name, old, new):
110 def _pid_dir_changed(self, name, old, new):
111 self.check_pid_dir()
111 self.check_pid_dir()
112
112
113 def check_pid_dir(self):
113 def check_pid_dir(self):
114 if not os.path.isdir(self.pid_dir):
114 if not os.path.isdir(self.pid_dir):
115 os.mkdir(self.pid_dir, 0700)
115 os.mkdir(self.pid_dir, 0700)
116 os.chmod(self.pid_dir, 0700)
116 os.chmod(self.pid_dir, 0700)
117
117
118 def check_dirs(self):
118 def check_dirs(self):
119 self.check_security_dir()
119 self.check_security_dir()
120 self.check_log_dir()
120 self.check_log_dir()
121 self.check_pid_dir()
121 self.check_pid_dir()
122
122
123 def load_config_file(self, filename):
123 def load_config_file(self, filename):
124 """Load a config file from the top level of the cluster dir.
124 """Load a config file from the top level of the cluster dir.
125
125
126 Parameters
126 Parameters
127 ----------
127 ----------
128 filename : unicode or str
128 filename : unicode or str
129 The filename only of the config file that must be located in
129 The filename only of the config file that must be located in
130 the top-level of the cluster directory.
130 the top-level of the cluster directory.
131 """
131 """
132 loader = PyFileConfigLoader(filename, self.location)
132 loader = PyFileConfigLoader(filename, self.location)
133 return loader.load_config()
133 return loader.load_config()
134
134
135 def copy_config_file(self, config_file, path=None, overwrite=False):
135 def copy_config_file(self, config_file, path=None, overwrite=False):
136 """Copy a default config file into the active cluster directory.
136 """Copy a default config file into the active cluster directory.
137
137
138 Default configuration files are kept in :mod:`IPython.config.default`.
138 Default configuration files are kept in :mod:`IPython.config.default`.
139 This function moves these from that location to the working cluster
139 This function moves these from that location to the working cluster
140 directory.
140 directory.
141 """
141 """
142 if path is None:
142 if path is None:
143 import IPython.config.default
143 import IPython.config.default
144 path = IPython.config.default.__file__.split(os.path.sep)[:-1]
144 path = IPython.config.default.__file__.split(os.path.sep)[:-1]
145 path = os.path.sep.join(path)
145 path = os.path.sep.join(path)
146 src = os.path.join(path, config_file)
146 src = os.path.join(path, config_file)
147 dst = os.path.join(self.location, config_file)
147 dst = os.path.join(self.location, config_file)
148 if not os.path.isfile(dst) or overwrite:
148 if not os.path.isfile(dst) or overwrite:
149 shutil.copy(src, dst)
149 shutil.copy(src, dst)
150
150
151 def copy_all_config_files(self, path=None, overwrite=False):
151 def copy_all_config_files(self, path=None, overwrite=False):
152 """Copy all config files into the active cluster directory."""
152 """Copy all config files into the active cluster directory."""
153 for f in [u'ipcontroller_config.py', u'ipengine_config.py',
153 for f in [u'ipcontroller_config.py', u'ipengine_config.py',
154 u'ipcluster_config.py']:
154 u'ipcluster_config.py']:
155 self.copy_config_file(f, path=path, overwrite=overwrite)
155 self.copy_config_file(f, path=path, overwrite=overwrite)
156
156
157 @classmethod
157 @classmethod
158 def create_cluster_dir(csl, cluster_dir):
158 def create_cluster_dir(csl, cluster_dir):
159 """Create a new cluster directory given a full path.
159 """Create a new cluster directory given a full path.
160
160
161 Parameters
161 Parameters
162 ----------
162 ----------
163 cluster_dir : str
163 cluster_dir : str
164 The full path to the cluster directory. If it does exist, it will
164 The full path to the cluster directory. If it does exist, it will
165 be used. If not, it will be created.
165 be used. If not, it will be created.
166 """
166 """
167 return ClusterDir(cluster_dir)
167 return ClusterDir(cluster_dir)
168
168
169 @classmethod
169 @classmethod
170 def create_cluster_dir_by_profile(cls, path, profile=u'default'):
170 def create_cluster_dir_by_profile(cls, path, profile=u'default'):
171 """Create a cluster dir by profile name and path.
171 """Create a cluster dir by profile name and path.
172
172
173 Parameters
173 Parameters
174 ----------
174 ----------
175 path : str
175 path : str
176 The path (directory) to put the cluster directory in.
176 The path (directory) to put the cluster directory in.
177 profile : str
177 profile : str
178 The name of the profile. The name of the cluster directory will
178 The name of the profile. The name of the cluster directory will
179 be "cluster_<profile>".
179 be "cluster_<profile>".
180 """
180 """
181 if not os.path.isdir(path):
181 if not os.path.isdir(path):
182 raise ClusterDirError('Directory not found: %s' % path)
182 raise ClusterDirError('Directory not found: %s' % path)
183 cluster_dir = os.path.join(path, u'cluster_' + profile)
183 cluster_dir = os.path.join(path, u'cluster_' + profile)
184 return ClusterDir(cluster_dir)
184 return ClusterDir(cluster_dir)
185
185
186 @classmethod
186 @classmethod
187 def find_cluster_dir_by_profile(cls, ipython_dir, profile=u'default'):
187 def find_cluster_dir_by_profile(cls, ipython_dir, profile=u'default'):
188 """Find an existing cluster dir by profile name, return its ClusterDir.
188 """Find an existing cluster dir by profile name, return its ClusterDir.
189
189
190 This searches through a sequence of paths for a cluster dir. If it
190 This searches through a sequence of paths for a cluster dir. If it
191 is not found, a :class:`ClusterDirError` exception will be raised.
191 is not found, a :class:`ClusterDirError` exception will be raised.
192
192
193 The search path algorithm is:
193 The search path algorithm is:
194 1. ``os.getcwd()``
194 1. ``os.getcwd()``
195 2. ``ipython_dir``
195 2. ``ipython_dir``
196 3. The directories found in the ":" separated
196 3. The directories found in the ":" separated
197 :env:`IPCLUSTER_DIR_PATH` environment variable.
197 :env:`IPCLUSTER_DIR_PATH` environment variable.
198
198
199 Parameters
199 Parameters
200 ----------
200 ----------
201 ipython_dir : unicode or str
201 ipython_dir : unicode or str
202 The IPython directory to use.
202 The IPython directory to use.
203 profile : unicode or str
203 profile : unicode or str
204 The name of the profile. The name of the cluster directory
204 The name of the profile. The name of the cluster directory
205 will be "cluster_<profile>".
205 will be "cluster_<profile>".
206 """
206 """
207 dirname = u'cluster_' + profile
207 dirname = u'cluster_' + profile
208 cluster_dir_paths = os.environ.get('IPCLUSTER_DIR_PATH','')
208 cluster_dir_paths = os.environ.get('IPCLUSTER_DIR_PATH','')
209 if cluster_dir_paths:
209 if cluster_dir_paths:
210 cluster_dir_paths = cluster_dir_paths.split(':')
210 cluster_dir_paths = cluster_dir_paths.split(':')
211 else:
211 else:
212 cluster_dir_paths = []
212 cluster_dir_paths = []
213 paths = [os.getcwd(), ipython_dir] + cluster_dir_paths
213 paths = [os.getcwd(), ipython_dir] + cluster_dir_paths
214 for p in paths:
214 for p in paths:
215 cluster_dir = os.path.join(p, dirname)
215 cluster_dir = os.path.join(p, dirname)
216 if os.path.isdir(cluster_dir):
216 if os.path.isdir(cluster_dir):
217 return ClusterDir(cluster_dir)
217 return ClusterDir(cluster_dir)
218 else:
218 else:
219 raise ClusterDirError('Cluster directory not found in paths: %s' % dirname)
219 raise ClusterDirError('Cluster directory not found in paths: %s' % dirname)
220
220
221 @classmethod
221 @classmethod
222 def find_cluster_dir(cls, cluster_dir):
222 def find_cluster_dir(cls, cluster_dir):
223 """Find/create a cluster dir and return its ClusterDir.
223 """Find/create a cluster dir and return its ClusterDir.
224
224
225 This will create the cluster directory if it doesn't exist.
225 This will create the cluster directory if it doesn't exist.
226
226
227 Parameters
227 Parameters
228 ----------
228 ----------
229 cluster_dir : unicode or str
229 cluster_dir : unicode or str
230 The path of the cluster directory. This is expanded using
230 The path of the cluster directory. This is expanded using
231 :func:`IPython.utils.genutils.expand_path`.
231 :func:`IPython.utils.genutils.expand_path`.
232 """
232 """
233 cluster_dir = expand_path(cluster_dir)
233 cluster_dir = expand_path(cluster_dir)
234 if not os.path.isdir(cluster_dir):
234 if not os.path.isdir(cluster_dir):
235 raise ClusterDirError('Cluster directory not found: %s' % cluster_dir)
235 raise ClusterDirError('Cluster directory not found: %s' % cluster_dir)
236 return ClusterDir(cluster_dir)
236 return ClusterDir(cluster_dir)
237
237
238
238
239 #-----------------------------------------------------------------------------
239 #-----------------------------------------------------------------------------
240 # Command line options
240 # Command line options
241 #-----------------------------------------------------------------------------
241 #-----------------------------------------------------------------------------
242
242
243 class ClusterDirConfigLoader(BaseAppConfigLoader):
243 class ClusterDirConfigLoader(BaseAppConfigLoader):
244
244
245 def _add_cluster_profile(self, parser):
245 def _add_cluster_profile(self, parser):
246 paa = parser.add_argument
246 paa = parser.add_argument
247 paa('-p', '--profile',
247 paa('-p', '--profile',
248 dest='Global.profile',type=unicode,
248 dest='Global.profile',type=unicode,
249 help=
249 help=
250 """The string name of the profile to be used. This determines the name
250 """The string name of the profile to be used. This determines the name
251 of the cluster dir as: cluster_<profile>. The default profile is named
251 of the cluster dir as: cluster_<profile>. The default profile is named
252 'default'. The cluster directory is resolve this way if the
252 'default'. The cluster directory is resolve this way if the
253 --cluster-dir option is not used.""",
253 --cluster-dir option is not used.""",
254 metavar='Global.profile')
254 metavar='Global.profile')
255
255
256 def _add_cluster_dir(self, parser):
256 def _add_cluster_dir(self, parser):
257 paa = parser.add_argument
257 paa = parser.add_argument
258 paa('--cluster-dir',
258 paa('--cluster-dir',
259 dest='Global.cluster_dir',type=unicode,
259 dest='Global.cluster_dir',type=unicode,
260 help="""Set the cluster dir. This overrides the logic used by the
260 help="""Set the cluster dir. This overrides the logic used by the
261 --profile option.""",
261 --profile option.""",
262 metavar='Global.cluster_dir')
262 metavar='Global.cluster_dir')
263
263
264 def _add_work_dir(self, parser):
264 def _add_work_dir(self, parser):
265 paa = parser.add_argument
265 paa = parser.add_argument
266 paa('--work-dir',
266 paa('--work-dir',
267 dest='Global.work_dir',type=unicode,
267 dest='Global.work_dir',type=unicode,
268 help='Set the working dir for the process.',
268 help='Set the working dir for the process.',
269 metavar='Global.work_dir')
269 metavar='Global.work_dir')
270
270
271 def _add_clean_logs(self, parser):
271 def _add_clean_logs(self, parser):
272 paa = parser.add_argument
272 paa = parser.add_argument
273 paa('--clean-logs',
273 paa('--clean-logs',
274 dest='Global.clean_logs', action='store_true',
274 dest='Global.clean_logs', action='store_true',
275 help='Delete old log flies before starting.')
275 help='Delete old log flies before starting.')
276
276
277 def _add_no_clean_logs(self, parser):
277 def _add_no_clean_logs(self, parser):
278 paa = parser.add_argument
278 paa = parser.add_argument
279 paa('--no-clean-logs',
279 paa('--no-clean-logs',
280 dest='Global.clean_logs', action='store_false',
280 dest='Global.clean_logs', action='store_false',
281 help="Don't Delete old log flies before starting.")
281 help="Don't Delete old log flies before starting.")
282
282
283 def _add_arguments(self):
283 def _add_arguments(self):
284 super(ClusterDirConfigLoader, self)._add_arguments()
284 super(ClusterDirConfigLoader, self)._add_arguments()
285 self._add_cluster_profile(self.parser)
285 self._add_cluster_profile(self.parser)
286 self._add_cluster_dir(self.parser)
286 self._add_cluster_dir(self.parser)
287 self._add_work_dir(self.parser)
287 self._add_work_dir(self.parser)
288 self._add_clean_logs(self.parser)
288 self._add_clean_logs(self.parser)
289 self._add_no_clean_logs(self.parser)
289 self._add_no_clean_logs(self.parser)
290
290
291
291
292 #-----------------------------------------------------------------------------
292 #-----------------------------------------------------------------------------
293 # Main application
293 # Main application
294 #-----------------------------------------------------------------------------
294 #-----------------------------------------------------------------------------
295
295
296 class ApplicationWithClusterDir(Application):
296 class ApplicationWithClusterDir(Application):
297 """An application that puts everything into a cluster directory.
297 """An application that puts everything into a cluster directory.
298
298
299 Instead of looking for things in the ipython_dir, this type of application
299 Instead of looking for things in the ipython_dir, this type of application
300 will use its own private directory called the "cluster directory"
300 will use its own private directory called the "cluster directory"
301 for things like config files, log files, etc.
301 for things like config files, log files, etc.
302
302
303 The cluster directory is resolved as follows:
303 The cluster directory is resolved as follows:
304
304
305 * If the ``--cluster-dir`` option is given, it is used.
305 * If the ``--cluster-dir`` option is given, it is used.
306 * If ``--cluster-dir`` is not given, the application directory is
306 * If ``--cluster-dir`` is not given, the application directory is
307 resolve using the profile name as ``cluster_<profile>``. The search
307 resolve using the profile name as ``cluster_<profile>``. The search
308 path for this directory is then i) cwd if it is found there
308 path for this directory is then i) cwd if it is found there
309 and ii) in ipython_dir otherwise.
309 and ii) in ipython_dir otherwise.
310
310
311 The config file for the application is to be put in the cluster
311 The config file for the application is to be put in the cluster
312 dir and named the value of the ``config_file_name`` class attribute.
312 dir and named the value of the ``config_file_name`` class attribute.
313 """
313 """
314
314
315 command_line_loader = ClusterDirConfigLoader
315 command_line_loader = ClusterDirConfigLoader
316 auto_create_cluster_dir = True
316 auto_create_cluster_dir = True
317
317
318 def create_default_config(self):
318 def create_default_config(self):
319 super(ApplicationWithClusterDir, self).create_default_config()
319 super(ApplicationWithClusterDir, self).create_default_config()
320 self.default_config.Global.profile = u'default'
320 self.default_config.Global.profile = u'default'
321 self.default_config.Global.cluster_dir = u''
321 self.default_config.Global.cluster_dir = u''
322 self.default_config.Global.work_dir = os.getcwd()
322 self.default_config.Global.work_dir = os.getcwd()
323 self.default_config.Global.log_to_file = False
323 self.default_config.Global.log_to_file = False
324 self.default_config.Global.clean_logs = False
324 self.default_config.Global.clean_logs = False
325
325
326 def find_resources(self):
326 def find_resources(self):
327 """This resolves the cluster directory.
327 """This resolves the cluster directory.
328
328
329 This tries to find the cluster directory and if successful, it will
329 This tries to find the cluster directory and if successful, it will
330 have done:
330 have done:
331 * Sets ``self.cluster_dir_obj`` to the :class:`ClusterDir` object for
331 * Sets ``self.cluster_dir_obj`` to the :class:`ClusterDir` object for
332 the application.
332 the application.
333 * Sets ``self.cluster_dir`` attribute of the application and config
333 * Sets ``self.cluster_dir`` attribute of the application and config
334 objects.
334 objects.
335
335
336 The algorithm used for this is as follows:
336 The algorithm used for this is as follows:
337 1. Try ``Global.cluster_dir``.
337 1. Try ``Global.cluster_dir``.
338 2. Try using ``Global.profile``.
338 2. Try using ``Global.profile``.
339 3. If both of these fail and ``self.auto_create_cluster_dir`` is
339 3. If both of these fail and ``self.auto_create_cluster_dir`` is
340 ``True``, then create the new cluster dir in the IPython directory.
340 ``True``, then create the new cluster dir in the IPython directory.
341 4. If all fails, then raise :class:`ClusterDirError`.
341 4. If all fails, then raise :class:`ClusterDirError`.
342 """
342 """
343
343
344 try:
344 try:
345 cluster_dir = self.command_line_config.Global.cluster_dir
345 cluster_dir = self.command_line_config.Global.cluster_dir
346 except AttributeError:
346 except AttributeError:
347 cluster_dir = self.default_config.Global.cluster_dir
347 cluster_dir = self.default_config.Global.cluster_dir
348 cluster_dir = expand_path(cluster_dir)
348 cluster_dir = expand_path(cluster_dir)
349 try:
349 try:
350 self.cluster_dir_obj = ClusterDir.find_cluster_dir(cluster_dir)
350 self.cluster_dir_obj = ClusterDir.find_cluster_dir(cluster_dir)
351 except ClusterDirError:
351 except ClusterDirError:
352 pass
352 pass
353 else:
353 else:
354 self.log.info('Using existing cluster dir: %s' % \
354 self.log.info('Using existing cluster dir: %s' % \
355 self.cluster_dir_obj.location
355 self.cluster_dir_obj.location
356 )
356 )
357 self.finish_cluster_dir()
357 self.finish_cluster_dir()
358 return
358 return
359
359
360 try:
360 try:
361 self.profile = self.command_line_config.Global.profile
361 self.profile = self.command_line_config.Global.profile
362 except AttributeError:
362 except AttributeError:
363 self.profile = self.default_config.Global.profile
363 self.profile = self.default_config.Global.profile
364 try:
364 try:
365 self.cluster_dir_obj = ClusterDir.find_cluster_dir_by_profile(
365 self.cluster_dir_obj = ClusterDir.find_cluster_dir_by_profile(
366 self.ipython_dir, self.profile)
366 self.ipython_dir, self.profile)
367 except ClusterDirError:
367 except ClusterDirError:
368 pass
368 pass
369 else:
369 else:
370 self.log.info('Using existing cluster dir: %s' % \
370 self.log.info('Using existing cluster dir: %s' % \
371 self.cluster_dir_obj.location
371 self.cluster_dir_obj.location
372 )
372 )
373 self.finish_cluster_dir()
373 self.finish_cluster_dir()
374 return
374 return
375
375
376 if self.auto_create_cluster_dir:
376 if self.auto_create_cluster_dir:
377 self.cluster_dir_obj = ClusterDir.create_cluster_dir_by_profile(
377 self.cluster_dir_obj = ClusterDir.create_cluster_dir_by_profile(
378 self.ipython_dir, self.profile
378 self.ipython_dir, self.profile
379 )
379 )
380 self.log.info('Creating new cluster dir: %s' % \
380 self.log.info('Creating new cluster dir: %s' % \
381 self.cluster_dir_obj.location
381 self.cluster_dir_obj.location
382 )
382 )
383 self.finish_cluster_dir()
383 self.finish_cluster_dir()
384 else:
384 else:
385 raise ClusterDirError('Could not find a valid cluster directory.')
385 raise ClusterDirError('Could not find a valid cluster directory.')
386
386
387 def finish_cluster_dir(self):
387 def finish_cluster_dir(self):
388 # Set the cluster directory
388 # Set the cluster directory
389 self.cluster_dir = self.cluster_dir_obj.location
389 self.cluster_dir = self.cluster_dir_obj.location
390
390
391 # These have to be set because they could be different from the one
391 # These have to be set because they could be different from the one
392 # that we just computed. Because command line has the highest
392 # that we just computed. Because command line has the highest
393 # priority, this will always end up in the master_config.
393 # priority, this will always end up in the master_config.
394 self.default_config.Global.cluster_dir = self.cluster_dir
394 self.default_config.Global.cluster_dir = self.cluster_dir
395 self.command_line_config.Global.cluster_dir = self.cluster_dir
395 self.command_line_config.Global.cluster_dir = self.cluster_dir
396
396
397 def find_config_file_name(self):
397 def find_config_file_name(self):
398 """Find the config file name for this application."""
398 """Find the config file name for this application."""
399 # For this type of Application it should be set as a class attribute.
399 # For this type of Application it should be set as a class attribute.
400 if not hasattr(self, 'config_file_name'):
400 if not hasattr(self, 'config_file_name'):
401 self.log.critical("No config filename found")
401 self.log.critical("No config filename found")
402
402
403 def find_config_file_paths(self):
403 def find_config_file_paths(self):
404 # Include our own config directory last, so that users can still find
404 # Set the search path to to the cluster directory. We should NOT
405 # our shipped copies of builtin config files even if they don't have
405 # include IPython.config.default here as the default config files
406 # them in their ipython cluster directory.
406 # are ALWAYS automatically moved to the cluster directory.
407 conf_dir = os.path.join(get_ipython_package_dir(), 'config', 'default')
407 conf_dir = os.path.join(get_ipython_package_dir(), 'config', 'default')
408 self.config_file_paths = (self.cluster_dir, conf_dir)
408 self.config_file_paths = (self.cluster_dir,)
409
409
410 def pre_construct(self):
410 def pre_construct(self):
411 # The log and security dirs were set earlier, but here we put them
411 # The log and security dirs were set earlier, but here we put them
412 # into the config and log them.
412 # into the config and log them.
413 config = self.master_config
413 config = self.master_config
414 sdir = self.cluster_dir_obj.security_dir
414 sdir = self.cluster_dir_obj.security_dir
415 self.security_dir = config.Global.security_dir = sdir
415 self.security_dir = config.Global.security_dir = sdir
416 ldir = self.cluster_dir_obj.log_dir
416 ldir = self.cluster_dir_obj.log_dir
417 self.log_dir = config.Global.log_dir = ldir
417 self.log_dir = config.Global.log_dir = ldir
418 pdir = self.cluster_dir_obj.pid_dir
418 pdir = self.cluster_dir_obj.pid_dir
419 self.pid_dir = config.Global.pid_dir = pdir
419 self.pid_dir = config.Global.pid_dir = pdir
420 self.log.info("Cluster directory set to: %s" % self.cluster_dir)
420 self.log.info("Cluster directory set to: %s" % self.cluster_dir)
421 config.Global.work_dir = unicode(expand_path(config.Global.work_dir))
421 config.Global.work_dir = unicode(expand_path(config.Global.work_dir))
422 # Change to the working directory. We do this just before construct
422 # Change to the working directory. We do this just before construct
423 # is called so all the components there have the right working dir.
423 # is called so all the components there have the right working dir.
424 self.to_work_dir()
424 self.to_work_dir()
425
425
426 def to_work_dir(self):
426 def to_work_dir(self):
427 wd = self.master_config.Global.work_dir
427 wd = self.master_config.Global.work_dir
428 if unicode(wd) != unicode(os.getcwd()):
428 if unicode(wd) != unicode(os.getcwd()):
429 os.chdir(wd)
429 os.chdir(wd)
430 self.log.info("Changing to working dir: %s" % wd)
430 self.log.info("Changing to working dir: %s" % wd)
431
431
432 def start_logging(self):
432 def start_logging(self):
433 # Remove old log files
433 # Remove old log files
434 if self.master_config.Global.clean_logs:
434 if self.master_config.Global.clean_logs:
435 log_dir = self.master_config.Global.log_dir
435 log_dir = self.master_config.Global.log_dir
436 for f in os.listdir(log_dir):
436 for f in os.listdir(log_dir):
437 if f.startswith(self.name + u'-') and f.endswith('.log'):
437 if f.startswith(self.name + u'-') and f.endswith('.log'):
438 os.remove(os.path.join(log_dir, f))
438 os.remove(os.path.join(log_dir, f))
439 # Start logging to the new log file
439 # Start logging to the new log file
440 if self.master_config.Global.log_to_file:
440 if self.master_config.Global.log_to_file:
441 log_filename = self.name + u'-' + str(os.getpid()) + u'.log'
441 log_filename = self.name + u'-' + str(os.getpid()) + u'.log'
442 logfile = os.path.join(self.log_dir, log_filename)
442 logfile = os.path.join(self.log_dir, log_filename)
443 open_log_file = open(logfile, 'w')
443 open_log_file = open(logfile, 'w')
444 else:
444 else:
445 open_log_file = sys.stdout
445 open_log_file = sys.stdout
446 log.startLogging(open_log_file)
446 log.startLogging(open_log_file)
447
447
448 def write_pid_file(self, overwrite=False):
448 def write_pid_file(self, overwrite=False):
449 """Create a .pid file in the pid_dir with my pid.
449 """Create a .pid file in the pid_dir with my pid.
450
450
451 This must be called after pre_construct, which sets `self.pid_dir`.
451 This must be called after pre_construct, which sets `self.pid_dir`.
452 This raises :exc:`PIDFileError` if the pid file exists already.
452 This raises :exc:`PIDFileError` if the pid file exists already.
453 """
453 """
454 pid_file = os.path.join(self.pid_dir, self.name + u'.pid')
454 pid_file = os.path.join(self.pid_dir, self.name + u'.pid')
455 if os.path.isfile(pid_file):
455 if os.path.isfile(pid_file):
456 pid = self.get_pid_from_file()
456 pid = self.get_pid_from_file()
457 if not overwrite:
457 if not overwrite:
458 raise PIDFileError(
458 raise PIDFileError(
459 'The pid file [%s] already exists. \nThis could mean that this '
459 'The pid file [%s] already exists. \nThis could mean that this '
460 'server is already running with [pid=%s].' % (pid_file, pid)
460 'server is already running with [pid=%s].' % (pid_file, pid)
461 )
461 )
462 with open(pid_file, 'w') as f:
462 with open(pid_file, 'w') as f:
463 self.log.info("Creating pid file: %s" % pid_file)
463 self.log.info("Creating pid file: %s" % pid_file)
464 f.write(repr(os.getpid())+'\n')
464 f.write(repr(os.getpid())+'\n')
465
465
466 def remove_pid_file(self):
466 def remove_pid_file(self):
467 """Remove the pid file.
467 """Remove the pid file.
468
468
469 This should be called at shutdown by registering a callback with
469 This should be called at shutdown by registering a callback with
470 :func:`reactor.addSystemEventTrigger`. This needs to return
470 :func:`reactor.addSystemEventTrigger`. This needs to return
471 ``None``.
471 ``None``.
472 """
472 """
473 pid_file = os.path.join(self.pid_dir, self.name + u'.pid')
473 pid_file = os.path.join(self.pid_dir, self.name + u'.pid')
474 if os.path.isfile(pid_file):
474 if os.path.isfile(pid_file):
475 try:
475 try:
476 self.log.info("Removing pid file: %s" % pid_file)
476 self.log.info("Removing pid file: %s" % pid_file)
477 os.remove(pid_file)
477 os.remove(pid_file)
478 except:
478 except:
479 self.log.warn("Error removing the pid file: %s" % pid_file)
479 self.log.warn("Error removing the pid file: %s" % pid_file)
480
480
481 def get_pid_from_file(self):
481 def get_pid_from_file(self):
482 """Get the pid from the pid file.
482 """Get the pid from the pid file.
483
483
484 If the pid file doesn't exist a :exc:`PIDFileError` is raised.
484 If the pid file doesn't exist a :exc:`PIDFileError` is raised.
485 """
485 """
486 pid_file = os.path.join(self.pid_dir, self.name + u'.pid')
486 pid_file = os.path.join(self.pid_dir, self.name + u'.pid')
487 if os.path.isfile(pid_file):
487 if os.path.isfile(pid_file):
488 with open(pid_file, 'r') as f:
488 with open(pid_file, 'r') as f:
489 pid = int(f.read().strip())
489 pid = int(f.read().strip())
490 return pid
490 return pid
491 else:
491 else:
492 raise PIDFileError('pid file not found: %s' % pid_file)
492 raise PIDFileError('pid file not found: %s' % pid_file)
493
493
General Comments 0
You need to be logged in to leave comments. Login now