##// END OF EJS Templates
remove deleted profiles from cluster list
MinRK -
Show More
@@ -1,173 +1,161 b''
1 """Manage IPython.parallel clusters in the notebook.
1 """Manage IPython.parallel clusters in the notebook."""
2
2
3 Authors:
3 # Copyright (c) IPython Development Team.
4
4 # Distributed under the terms of the Modified BSD License.
5 * Brian Granger
6 """
7
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2008-2011 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
14
15 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
18
5
19 from tornado import web
6 from tornado import web
20 from zmq.eventloop import ioloop
7 from zmq.eventloop import ioloop
21
8
22 from IPython.config.configurable import LoggingConfigurable
9 from IPython.config.configurable import LoggingConfigurable
23 from IPython.utils.traitlets import Dict, Instance, CFloat
10 from IPython.utils.traitlets import Dict, Instance, CFloat
24 from IPython.core.profileapp import list_profiles_in
11 from IPython.core.profileapp import list_profiles_in
25 from IPython.core.profiledir import ProfileDir
12 from IPython.core.profiledir import ProfileDir
26 from IPython.utils import py3compat
13 from IPython.utils import py3compat
27 from IPython.utils.path import get_ipython_dir
14 from IPython.utils.path import get_ipython_dir
28
15
29
16
30 #-----------------------------------------------------------------------------
31 # Classes
32 #-----------------------------------------------------------------------------
33
34
35
36
37 class ClusterManager(LoggingConfigurable):
17 class ClusterManager(LoggingConfigurable):
38
18
39 profiles = Dict()
19 profiles = Dict()
40
20
41 delay = CFloat(1., config=True,
21 delay = CFloat(1., config=True,
42 help="delay (in s) between starting the controller and the engines")
22 help="delay (in s) between starting the controller and the engines")
43
23
44 loop = Instance('zmq.eventloop.ioloop.IOLoop')
24 loop = Instance('zmq.eventloop.ioloop.IOLoop')
45 def _loop_default(self):
25 def _loop_default(self):
46 from zmq.eventloop.ioloop import IOLoop
26 from zmq.eventloop.ioloop import IOLoop
47 return IOLoop.instance()
27 return IOLoop.instance()
48
28
49 def build_launchers(self, profile_dir):
29 def build_launchers(self, profile_dir):
50 from IPython.parallel.apps.ipclusterapp import IPClusterStart
30 from IPython.parallel.apps.ipclusterapp import IPClusterStart
51
31
52 class DummyIPClusterStart(IPClusterStart):
32 class DummyIPClusterStart(IPClusterStart):
53 """Dummy subclass to skip init steps that conflict with global app.
33 """Dummy subclass to skip init steps that conflict with global app.
54
34
55 Instantiating and initializing this class should result in fully configured
35 Instantiating and initializing this class should result in fully configured
56 launchers, but no other side effects or state.
36 launchers, but no other side effects or state.
57 """
37 """
58
38
59 def init_signal(self):
39 def init_signal(self):
60 pass
40 pass
61 def reinit_logging(self):
41 def reinit_logging(self):
62 pass
42 pass
63
43
64 starter = DummyIPClusterStart(log=self.log)
44 starter = DummyIPClusterStart(log=self.log)
65 starter.initialize(['--profile-dir', profile_dir])
45 starter.initialize(['--profile-dir', profile_dir])
66 cl = starter.controller_launcher
46 cl = starter.controller_launcher
67 esl = starter.engine_launcher
47 esl = starter.engine_launcher
68 n = starter.n
48 n = starter.n
69 return cl, esl, n
49 return cl, esl, n
70
50
71 def get_profile_dir(self, name, path):
51 def get_profile_dir(self, name, path):
72 p = ProfileDir.find_profile_dir_by_name(path,name=name)
52 p = ProfileDir.find_profile_dir_by_name(path,name=name)
73 return p.location
53 return p.location
74
54
75 def update_profiles(self):
55 def update_profiles(self):
76 """List all profiles in the ipython_dir and cwd.
56 """List all profiles in the ipython_dir and cwd.
77 """
57 """
58
59 stale = set(self.profiles)
78 for path in [get_ipython_dir(), py3compat.getcwd()]:
60 for path in [get_ipython_dir(), py3compat.getcwd()]:
79 for profile in list_profiles_in(path):
61 for profile in list_profiles_in(path):
62 if profile in stale:
63 stale.remove(profile)
80 pd = self.get_profile_dir(profile, path)
64 pd = self.get_profile_dir(profile, path)
81 if profile not in self.profiles:
65 if profile not in self.profiles:
82 self.log.debug("Adding cluster profile '%s'" % profile)
66 self.log.debug("Adding cluster profile '%s'", profile)
83 self.profiles[profile] = {
67 self.profiles[profile] = {
84 'profile': profile,
68 'profile': profile,
85 'profile_dir': pd,
69 'profile_dir': pd,
86 'status': 'stopped'
70 'status': 'stopped'
87 }
71 }
72 for profile in stale:
73 # remove profiles that no longer exist
74 self.log.debug("Profile '%s' no longer exists", profile)
75 self.profiles.pop(stale)
88
76
89 def list_profiles(self):
77 def list_profiles(self):
90 self.update_profiles()
78 self.update_profiles()
91 # sorted list, but ensure that 'default' always comes first
79 # sorted list, but ensure that 'default' always comes first
92 default_first = lambda name: name if name != 'default' else ''
80 default_first = lambda name: name if name != 'default' else ''
93 result = [self.profile_info(p) for p in sorted(self.profiles, key=default_first)]
81 result = [self.profile_info(p) for p in sorted(self.profiles, key=default_first)]
94 return result
82 return result
95
83
96 def check_profile(self, profile):
84 def check_profile(self, profile):
97 if profile not in self.profiles:
85 if profile not in self.profiles:
98 raise web.HTTPError(404, u'profile not found')
86 raise web.HTTPError(404, u'profile not found')
99
87
100 def profile_info(self, profile):
88 def profile_info(self, profile):
101 self.check_profile(profile)
89 self.check_profile(profile)
102 result = {}
90 result = {}
103 data = self.profiles.get(profile)
91 data = self.profiles.get(profile)
104 result['profile'] = profile
92 result['profile'] = profile
105 result['profile_dir'] = data['profile_dir']
93 result['profile_dir'] = data['profile_dir']
106 result['status'] = data['status']
94 result['status'] = data['status']
107 if 'n' in data:
95 if 'n' in data:
108 result['n'] = data['n']
96 result['n'] = data['n']
109 return result
97 return result
110
98
111 def start_cluster(self, profile, n=None):
99 def start_cluster(self, profile, n=None):
112 """Start a cluster for a given profile."""
100 """Start a cluster for a given profile."""
113 self.check_profile(profile)
101 self.check_profile(profile)
114 data = self.profiles[profile]
102 data = self.profiles[profile]
115 if data['status'] == 'running':
103 if data['status'] == 'running':
116 raise web.HTTPError(409, u'cluster already running')
104 raise web.HTTPError(409, u'cluster already running')
117 cl, esl, default_n = self.build_launchers(data['profile_dir'])
105 cl, esl, default_n = self.build_launchers(data['profile_dir'])
118 n = n if n is not None else default_n
106 n = n if n is not None else default_n
119 def clean_data():
107 def clean_data():
120 data.pop('controller_launcher',None)
108 data.pop('controller_launcher',None)
121 data.pop('engine_set_launcher',None)
109 data.pop('engine_set_launcher',None)
122 data.pop('n',None)
110 data.pop('n',None)
123 data['status'] = 'stopped'
111 data['status'] = 'stopped'
124 def engines_stopped(r):
112 def engines_stopped(r):
125 self.log.debug('Engines stopped')
113 self.log.debug('Engines stopped')
126 if cl.running:
114 if cl.running:
127 cl.stop()
115 cl.stop()
128 clean_data()
116 clean_data()
129 esl.on_stop(engines_stopped)
117 esl.on_stop(engines_stopped)
130 def controller_stopped(r):
118 def controller_stopped(r):
131 self.log.debug('Controller stopped')
119 self.log.debug('Controller stopped')
132 if esl.running:
120 if esl.running:
133 esl.stop()
121 esl.stop()
134 clean_data()
122 clean_data()
135 cl.on_stop(controller_stopped)
123 cl.on_stop(controller_stopped)
136
124
137 dc = ioloop.DelayedCallback(lambda: cl.start(), 0, self.loop)
125 dc = ioloop.DelayedCallback(lambda: cl.start(), 0, self.loop)
138 dc.start()
126 dc.start()
139 dc = ioloop.DelayedCallback(lambda: esl.start(n), 1000*self.delay, self.loop)
127 dc = ioloop.DelayedCallback(lambda: esl.start(n), 1000*self.delay, self.loop)
140 dc.start()
128 dc.start()
141
129
142 self.log.debug('Cluster started')
130 self.log.debug('Cluster started')
143 data['controller_launcher'] = cl
131 data['controller_launcher'] = cl
144 data['engine_set_launcher'] = esl
132 data['engine_set_launcher'] = esl
145 data['n'] = n
133 data['n'] = n
146 data['status'] = 'running'
134 data['status'] = 'running'
147 return self.profile_info(profile)
135 return self.profile_info(profile)
148
136
149 def stop_cluster(self, profile):
137 def stop_cluster(self, profile):
150 """Stop a cluster for a given profile."""
138 """Stop a cluster for a given profile."""
151 self.check_profile(profile)
139 self.check_profile(profile)
152 data = self.profiles[profile]
140 data = self.profiles[profile]
153 if data['status'] == 'stopped':
141 if data['status'] == 'stopped':
154 raise web.HTTPError(409, u'cluster not running')
142 raise web.HTTPError(409, u'cluster not running')
155 data = self.profiles[profile]
143 data = self.profiles[profile]
156 cl = data['controller_launcher']
144 cl = data['controller_launcher']
157 esl = data['engine_set_launcher']
145 esl = data['engine_set_launcher']
158 if cl.running:
146 if cl.running:
159 cl.stop()
147 cl.stop()
160 if esl.running:
148 if esl.running:
161 esl.stop()
149 esl.stop()
162 # Return a temp info dict, the real one is updated in the on_stop
150 # Return a temp info dict, the real one is updated in the on_stop
163 # logic above.
151 # logic above.
164 result = {
152 result = {
165 'profile': data['profile'],
153 'profile': data['profile'],
166 'profile_dir': data['profile_dir'],
154 'profile_dir': data['profile_dir'],
167 'status': 'stopped'
155 'status': 'stopped'
168 }
156 }
169 return result
157 return result
170
158
171 def stop_all_clusters(self):
159 def stop_all_clusters(self):
172 for p in self.profiles.keys():
160 for p in self.profiles.keys():
173 self.stop_cluster(p)
161 self.stop_cluster(p)
General Comments 0
You need to be logged in to leave comments. Login now