##// END OF EJS Templates
events: Move subscriber classes from svn_support to rhodecode.subscribers....
Martin Bornhold -
r1019:1a069e4a default
parent child Browse files
Show More
@@ -1,70 +1,143 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21
21
22 import logging
22 import pylons
23 import pylons
24 import Queue
25 import subprocess32
23
26
24 from pyramid.i18n import get_localizer
27 from pyramid.i18n import get_localizer
25 from pyramid.threadlocal import get_current_request
28 from pyramid.threadlocal import get_current_request
29 from threading import Thread
26
30
27 from rhodecode.translation import _ as tsf
31 from rhodecode.translation import _ as tsf
28
32
29
33
34 log = logging.getLogger(__name__)
35
36
30 def add_renderer_globals(event):
37 def add_renderer_globals(event):
31 # Put pylons stuff into the context. This will be removed as soon as
38 # Put pylons stuff into the context. This will be removed as soon as
32 # migration to pyramid is finished.
39 # migration to pyramid is finished.
33 conf = pylons.config._current_obj()
40 conf = pylons.config._current_obj()
34 event['h'] = conf.get('pylons.h')
41 event['h'] = conf.get('pylons.h')
35 event['c'] = pylons.tmpl_context
42 event['c'] = pylons.tmpl_context
36 event['url'] = pylons.url
43 event['url'] = pylons.url
37
44
38 # TODO: When executed in pyramid view context the request is not available
45 # TODO: When executed in pyramid view context the request is not available
39 # in the event. Find a better solution to get the request.
46 # in the event. Find a better solution to get the request.
40 request = event['request'] or get_current_request()
47 request = event['request'] or get_current_request()
41
48
42 # Add Pyramid translation as '_' to context
49 # Add Pyramid translation as '_' to context
43 event['_'] = request.translate
50 event['_'] = request.translate
44 event['localizer'] = request.localizer
51 event['localizer'] = request.localizer
45
52
46
53
47 def add_localizer(event):
54 def add_localizer(event):
48 request = event.request
55 request = event.request
49 localizer = get_localizer(request)
56 localizer = get_localizer(request)
50
57
51 def auto_translate(*args, **kwargs):
58 def auto_translate(*args, **kwargs):
52 return localizer.translate(tsf(*args, **kwargs))
59 return localizer.translate(tsf(*args, **kwargs))
53
60
54 request.localizer = localizer
61 request.localizer = localizer
55 request.translate = auto_translate
62 request.translate = auto_translate
56
63
57
64
58 def scan_repositories_if_enabled(event):
65 def scan_repositories_if_enabled(event):
59 """
66 """
60 This is subscribed to the `pyramid.events.ApplicationCreated` event. It
67 This is subscribed to the `pyramid.events.ApplicationCreated` event. It
61 does a repository scan if enabled in the settings.
68 does a repository scan if enabled in the settings.
62 """
69 """
63 from rhodecode.model.scm import ScmModel
70 from rhodecode.model.scm import ScmModel
64 from rhodecode.lib.utils import repo2db_mapper, get_rhodecode_base_path
71 from rhodecode.lib.utils import repo2db_mapper, get_rhodecode_base_path
65 settings = event.app.registry.settings
72 settings = event.app.registry.settings
66 vcs_server_enabled = settings['vcs.server.enable']
73 vcs_server_enabled = settings['vcs.server.enable']
67 import_on_startup = settings['startup.import_repos']
74 import_on_startup = settings['startup.import_repos']
68 if vcs_server_enabled and import_on_startup:
75 if vcs_server_enabled and import_on_startup:
69 repositories = ScmModel().repo_scan(get_rhodecode_base_path())
76 repositories = ScmModel().repo_scan(get_rhodecode_base_path())
70 repo2db_mapper(repositories, remove_obsolete=False)
77 repo2db_mapper(repositories, remove_obsolete=False)
78
79
80 class Subscriber(object):
81 def __call__(self, event):
82 self.run(event)
83
84 def run(self, event):
85 raise NotImplementedError('Subclass has to implement this.')
86
87
88 class AsyncSubscriber(Subscriber):
89 def __init__(self):
90 self._stop = False
91 self._eventq = Queue.Queue()
92 self._worker = self.create_worker()
93 self._worker.start()
94
95 def __call__(self, event):
96 self._eventq.put(event)
97
98 def create_worker(self):
99 worker = Thread(target=self.do_work)
100 worker.daemon = True
101 return worker
102
103 def stop_worker(self):
104 self._stop = False
105 self._eventq.put(None)
106 self._worker.join()
107
108 def do_work(self):
109 while not self._stop:
110 event = self._eventq.get()
111 if event is not None:
112 self.run(event)
113
114
115 class AsyncSubprocessSubscriber(AsyncSubscriber):
116
117 def __init__(self, cmd, timeout=None):
118 super(AsyncSubprocessSubscriber, self).__init__()
119 self._cmd = cmd
120 self._timeout = timeout
121
122 def run(self, event):
123 cmd = self._cmd
124 timeout = self._timeout
125 log.debug('Executing command %s.', cmd)
126
127 try:
128 output = subprocess32.check_output(
129 cmd, timeout=timeout, stderr=subprocess32.STDOUT)
130 log.debug('Command finished %s', cmd)
131 if output:
132 log.debug('Command output: %s', output)
133 except subprocess32.TimeoutExpired as e:
134 log.exception('Timeout while executing command.')
135 if e.output:
136 log.error('Command output: %s', e.output)
137 except subprocess32.CalledProcessError as e:
138 log.exception('Error while executing command.')
139 if e.output:
140 log.error('Command output: %s', e.output)
141 except:
142 log.exception(
143 'Exception while executing command %s.', cmd)
@@ -1,87 +1,88 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2016 RhodeCode GmbH
3 # Copyright (C) 2016-2016 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import logging
21 import logging
22 import os
22 import os
23 import shlex
23 import shlex
24
24
25 # Do not use `from rhodecode import events` here, it will be overridden by the
25 # Do not use `from rhodecode import events` here, it will be overridden by the
26 # events module in this package due to pythons import mechanism.
26 # events module in this package due to pythons import mechanism.
27 from rhodecode.events import RepoGroupEvent
27 from rhodecode.events import RepoGroupEvent
28 from rhodecode.subscribers import AsyncSubprocessSubscriber
28 from rhodecode.config.middleware import (
29 from rhodecode.config.middleware import (
29 _bool_setting, _string_setting, _int_setting)
30 _bool_setting, _string_setting, _int_setting)
30
31
31 from .events import ModDavSvnConfigChange
32 from .events import ModDavSvnConfigChange
32 from .subscribers import generate_config_subscriber, AsyncSubprocessSubscriber
33 from .subscribers import generate_config_subscriber
33 from . import config_keys
34 from . import config_keys
34
35
35
36
36 log = logging.getLogger(__name__)
37 log = logging.getLogger(__name__)
37
38
38
39
39 def includeme(config):
40 def includeme(config):
40 settings = config.registry.settings
41 settings = config.registry.settings
41 _sanitize_settings_and_apply_defaults(settings)
42 _sanitize_settings_and_apply_defaults(settings)
42
43
43 if settings[config_keys.generate_config]:
44 if settings[config_keys.generate_config]:
44 # Add subscriber to generate the Apache mod dav svn configuration on
45 # Add subscriber to generate the Apache mod dav svn configuration on
45 # repository group events.
46 # repository group events.
46 config.add_subscriber(generate_config_subscriber, RepoGroupEvent)
47 config.add_subscriber(generate_config_subscriber, RepoGroupEvent)
47
48
48 # Prepare reload command to pass it to the subprocess module and add a
49 # Prepare reload command to pass it to the subprocess module and add a
49 # subscriber to execute it on configuration changes.
50 # subscriber to execute it on configuration changes.
50 reload_cmd = shlex.split(settings[config_keys.reload_command])
51 reload_cmd = shlex.split(settings[config_keys.reload_command])
51 reload_timeout = settings[config_keys.reload_timeout] or None
52 reload_timeout = settings[config_keys.reload_timeout] or None
52 config_change_subscriber = AsyncSubprocessSubscriber(
53 config_change_subscriber = AsyncSubprocessSubscriber(
53 cmd=reload_cmd, timeout=reload_timeout)
54 cmd=reload_cmd, timeout=reload_timeout)
54 config.add_subscriber(config_change_subscriber, ModDavSvnConfigChange)
55 config.add_subscriber(config_change_subscriber, ModDavSvnConfigChange)
55
56
56
57
57 def _sanitize_settings_and_apply_defaults(settings):
58 def _sanitize_settings_and_apply_defaults(settings):
58 """
59 """
59 Set defaults, convert to python types and validate settings.
60 Set defaults, convert to python types and validate settings.
60 """
61 """
61 _bool_setting(settings, config_keys.generate_config, 'false')
62 _bool_setting(settings, config_keys.generate_config, 'false')
62 _bool_setting(settings, config_keys.list_parent_path, 'true')
63 _bool_setting(settings, config_keys.list_parent_path, 'true')
63 _int_setting(settings, config_keys.reload_timeout, 10)
64 _int_setting(settings, config_keys.reload_timeout, 10)
64 _string_setting(settings, config_keys.config_file_path, '', lower=False)
65 _string_setting(settings, config_keys.config_file_path, '', lower=False)
65 _string_setting(settings, config_keys.location_root, '/', lower=False)
66 _string_setting(settings, config_keys.location_root, '/', lower=False)
66 _string_setting(settings, config_keys.reload_command, '', lower=False)
67 _string_setting(settings, config_keys.reload_command, '', lower=False)
67
68
68 # Convert negative timeout values to zero.
69 # Convert negative timeout values to zero.
69 if settings[config_keys.reload_timeout] < 0:
70 if settings[config_keys.reload_timeout] < 0:
70 settings[config_keys.reload_timeout] = 0
71 settings[config_keys.reload_timeout] = 0
71
72
72 # Append path separator to location root.
73 # Append path separator to location root.
73 settings[config_keys.location_root] = _append_path_sep(
74 settings[config_keys.location_root] = _append_path_sep(
74 settings[config_keys.location_root])
75 settings[config_keys.location_root])
75
76
76 # Validate settings.
77 # Validate settings.
77 if settings[config_keys.generate_config]:
78 if settings[config_keys.generate_config]:
78 assert len(settings[config_keys.config_file_path]) > 0
79 assert len(settings[config_keys.config_file_path]) > 0
79
80
80
81
81 def _append_path_sep(path):
82 def _append_path_sep(path):
82 """
83 """
83 Append the path separator if missing.
84 Append the path separator if missing.
84 """
85 """
85 if isinstance(path, basestring) and not path.endswith(os.path.sep):
86 if isinstance(path, basestring) and not path.endswith(os.path.sep):
86 path += os.path.sep
87 path += os.path.sep
87 return path
88 return path
@@ -1,109 +1,40 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2016 RhodeCode GmbH
3 # Copyright (C) 2016-2016 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import logging
21 import logging
22 import Queue
23 import subprocess32
24 from threading import Thread
25
22
26
23
27 from .utils import generate_mod_dav_svn_config
24 from .utils import generate_mod_dav_svn_config
28
25
29
26
30 log = logging.getLogger(__name__)
27 log = logging.getLogger(__name__)
31
28
32
29
33 def generate_config_subscriber(event):
30 def generate_config_subscriber(event):
34 """
31 """
35 Subscriber to the `rhodcode.events.RepoGroupEvent`. This triggers the
32 Subscriber to the `rhodcode.events.RepoGroupEvent`. This triggers the
36 automatic generation of mod_dav_svn config file on repository group
33 automatic generation of mod_dav_svn config file on repository group
37 changes.
34 changes.
38 """
35 """
39 try:
36 try:
40 generate_mod_dav_svn_config(event.request.registry)
37 generate_mod_dav_svn_config(event.request.registry)
41 except Exception:
38 except Exception:
42 log.exception(
39 log.exception(
43 'Exception while generating subversion mod_dav_svn configuration.')
40 'Exception while generating subversion mod_dav_svn configuration.')
44
45
46 class Subscriber(object):
47 def __call__(self, event):
48 self.run(event)
49
50 def run(self, event):
51 raise NotImplementedError('Subclass has to implement this.')
52
53
54 class AsyncSubscriber(Subscriber):
55 def __init__(self):
56 self._stop = False
57 self._eventq = Queue.Queue()
58 self._worker = self.create_worker()
59 self._worker.start()
60
61 def __call__(self, event):
62 self._eventq.put(event)
63
64 def create_worker(self):
65 worker = Thread(target=self.do_work)
66 worker.daemon = True
67 return worker
68
69 def stop_worker(self):
70 self._stop = False
71 self._eventq.put(None)
72 self._worker.join()
73
74 def do_work(self):
75 while not self._stop:
76 event = self._eventq.get()
77 if event is not None:
78 self.run(event)
79
80
81 class AsyncSubprocessSubscriber(AsyncSubscriber):
82
83 def __init__(self, cmd, timeout=None):
84 super(AsyncSubprocessSubscriber, self).__init__()
85 self._cmd = cmd
86 self._timeout = timeout
87
88 def run(self, event):
89 cmd = self._cmd
90 timeout = self._timeout
91 log.debug('Executing command %s.', cmd)
92
93 try:
94 output = subprocess32.check_output(
95 cmd, timeout=timeout, stderr=subprocess32.STDOUT)
96 log.debug('Command finished %s', cmd)
97 if output:
98 log.debug('Command output: %s', output)
99 except subprocess32.TimeoutExpired as e:
100 log.exception('Timeout while executing command.')
101 if e.output:
102 log.error('Command output: %s', e.output)
103 except subprocess32.CalledProcessError as e:
104 log.exception('Error while executing command.')
105 if e.output:
106 log.error('Command output: %s', e.output)
107 except:
108 log.exception(
109 'Exception while executing command %s.', cmd)
General Comments 0
You need to be logged in to leave comments. Login now