##// 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 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21
22 import logging
22 23 import pylons
24 import Queue
25 import subprocess32
23 26
24 27 from pyramid.i18n import get_localizer
25 28 from pyramid.threadlocal import get_current_request
29 from threading import Thread
26 30
27 31 from rhodecode.translation import _ as tsf
28 32
29 33
34 log = logging.getLogger(__name__)
35
36
30 37 def add_renderer_globals(event):
31 38 # Put pylons stuff into the context. This will be removed as soon as
32 39 # migration to pyramid is finished.
33 40 conf = pylons.config._current_obj()
34 41 event['h'] = conf.get('pylons.h')
35 42 event['c'] = pylons.tmpl_context
36 43 event['url'] = pylons.url
37 44
38 45 # TODO: When executed in pyramid view context the request is not available
39 46 # in the event. Find a better solution to get the request.
40 47 request = event['request'] or get_current_request()
41 48
42 49 # Add Pyramid translation as '_' to context
43 50 event['_'] = request.translate
44 51 event['localizer'] = request.localizer
45 52
46 53
47 54 def add_localizer(event):
48 55 request = event.request
49 56 localizer = get_localizer(request)
50 57
51 58 def auto_translate(*args, **kwargs):
52 59 return localizer.translate(tsf(*args, **kwargs))
53 60
54 61 request.localizer = localizer
55 62 request.translate = auto_translate
56 63
57 64
58 65 def scan_repositories_if_enabled(event):
59 66 """
60 67 This is subscribed to the `pyramid.events.ApplicationCreated` event. It
61 68 does a repository scan if enabled in the settings.
62 69 """
63 70 from rhodecode.model.scm import ScmModel
64 71 from rhodecode.lib.utils import repo2db_mapper, get_rhodecode_base_path
65 72 settings = event.app.registry.settings
66 73 vcs_server_enabled = settings['vcs.server.enable']
67 74 import_on_startup = settings['startup.import_repos']
68 75 if vcs_server_enabled and import_on_startup:
69 76 repositories = ScmModel().repo_scan(get_rhodecode_base_path())
70 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 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 22 import os
23 23 import shlex
24 24
25 25 # Do not use `from rhodecode import events` here, it will be overridden by the
26 26 # events module in this package due to pythons import mechanism.
27 27 from rhodecode.events import RepoGroupEvent
28 from rhodecode.subscribers import AsyncSubprocessSubscriber
28 29 from rhodecode.config.middleware import (
29 30 _bool_setting, _string_setting, _int_setting)
30 31
31 32 from .events import ModDavSvnConfigChange
32 from .subscribers import generate_config_subscriber, AsyncSubprocessSubscriber
33 from .subscribers import generate_config_subscriber
33 34 from . import config_keys
34 35
35 36
36 37 log = logging.getLogger(__name__)
37 38
38 39
39 40 def includeme(config):
40 41 settings = config.registry.settings
41 42 _sanitize_settings_and_apply_defaults(settings)
42 43
43 44 if settings[config_keys.generate_config]:
44 45 # Add subscriber to generate the Apache mod dav svn configuration on
45 46 # repository group events.
46 47 config.add_subscriber(generate_config_subscriber, RepoGroupEvent)
47 48
48 49 # Prepare reload command to pass it to the subprocess module and add a
49 50 # subscriber to execute it on configuration changes.
50 51 reload_cmd = shlex.split(settings[config_keys.reload_command])
51 52 reload_timeout = settings[config_keys.reload_timeout] or None
52 53 config_change_subscriber = AsyncSubprocessSubscriber(
53 54 cmd=reload_cmd, timeout=reload_timeout)
54 55 config.add_subscriber(config_change_subscriber, ModDavSvnConfigChange)
55 56
56 57
57 58 def _sanitize_settings_and_apply_defaults(settings):
58 59 """
59 60 Set defaults, convert to python types and validate settings.
60 61 """
61 62 _bool_setting(settings, config_keys.generate_config, 'false')
62 63 _bool_setting(settings, config_keys.list_parent_path, 'true')
63 64 _int_setting(settings, config_keys.reload_timeout, 10)
64 65 _string_setting(settings, config_keys.config_file_path, '', lower=False)
65 66 _string_setting(settings, config_keys.location_root, '/', lower=False)
66 67 _string_setting(settings, config_keys.reload_command, '', lower=False)
67 68
68 69 # Convert negative timeout values to zero.
69 70 if settings[config_keys.reload_timeout] < 0:
70 71 settings[config_keys.reload_timeout] = 0
71 72
72 73 # Append path separator to location root.
73 74 settings[config_keys.location_root] = _append_path_sep(
74 75 settings[config_keys.location_root])
75 76
76 77 # Validate settings.
77 78 if settings[config_keys.generate_config]:
78 79 assert len(settings[config_keys.config_file_path]) > 0
79 80
80 81
81 82 def _append_path_sep(path):
82 83 """
83 84 Append the path separator if missing.
84 85 """
85 86 if isinstance(path, basestring) and not path.endswith(os.path.sep):
86 87 path += os.path.sep
87 88 return path
@@ -1,109 +1,40 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 import Queue
23 import subprocess32
24 from threading import Thread
25 22
26 23
27 24 from .utils import generate_mod_dav_svn_config
28 25
29 26
30 27 log = logging.getLogger(__name__)
31 28
32 29
33 30 def generate_config_subscriber(event):
34 31 """
35 32 Subscriber to the `rhodcode.events.RepoGroupEvent`. This triggers the
36 33 automatic generation of mod_dav_svn config file on repository group
37 34 changes.
38 35 """
39 36 try:
40 37 generate_mod_dav_svn_config(event.request.registry)
41 38 except Exception:
42 39 log.exception(
43 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