##// END OF EJS Templates
automation: moved update groups task into celery task
marcink -
r4145:bf25ce62 default
parent child Browse files
Show More
@@ -1,343 +1,349 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2019 RhodeCode GmbH
3 # Copyright (C) 2012-2019 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 RhodeCode task modules, containing all task that suppose to be run
22 RhodeCode task modules, containing all task that suppose to be run
23 by celery daemon
23 by celery daemon
24 """
24 """
25
25
26 import os
26 import os
27 import time
27 import time
28
28
29 from pyramid import compat
29 from pyramid import compat
30 from pyramid_mailer.mailer import Mailer
30 from pyramid_mailer.mailer import Mailer
31 from pyramid_mailer.message import Message
31 from pyramid_mailer.message import Message
32
32
33 import rhodecode
33 import rhodecode
34 from rhodecode.lib import audit_logger
34 from rhodecode.lib import audit_logger
35 from rhodecode.lib.celerylib import get_logger, async_task, RequestContextTask
35 from rhodecode.lib.celerylib import get_logger, async_task, RequestContextTask
36 from rhodecode.lib.hooks_base import log_create_repository
36 from rhodecode.lib.hooks_base import log_create_repository
37 from rhodecode.lib.utils2 import safe_int, str2bool
37 from rhodecode.lib.utils2 import safe_int, str2bool
38 from rhodecode.model.db import Session, IntegrityError, Repository, User, true
38 from rhodecode.model.db import Session, IntegrityError, Repository, User, true
39
39
40
40
41 @async_task(ignore_result=True, base=RequestContextTask)
41 @async_task(ignore_result=True, base=RequestContextTask)
42 def send_email(recipients, subject, body='', html_body='', email_config=None):
42 def send_email(recipients, subject, body='', html_body='', email_config=None):
43 """
43 """
44 Sends an email with defined parameters from the .ini files.
44 Sends an email with defined parameters from the .ini files.
45
45
46 :param recipients: list of recipients, it this is empty the defined email
46 :param recipients: list of recipients, it this is empty the defined email
47 address from field 'email_to' is used instead
47 address from field 'email_to' is used instead
48 :param subject: subject of the mail
48 :param subject: subject of the mail
49 :param body: body of the mail
49 :param body: body of the mail
50 :param html_body: html version of body
50 :param html_body: html version of body
51 """
51 """
52 log = get_logger(send_email)
52 log = get_logger(send_email)
53
53
54 email_config = email_config or rhodecode.CONFIG
54 email_config = email_config or rhodecode.CONFIG
55
55
56 mail_server = email_config.get('smtp_server') or None
56 mail_server = email_config.get('smtp_server') or None
57 if mail_server is None:
57 if mail_server is None:
58 log.error("SMTP server information missing. Sending email failed. "
58 log.error("SMTP server information missing. Sending email failed. "
59 "Make sure that `smtp_server` variable is configured "
59 "Make sure that `smtp_server` variable is configured "
60 "inside the .ini file")
60 "inside the .ini file")
61 return False
61 return False
62
62
63 subject = "%s %s" % (email_config.get('email_prefix', ''), subject)
63 subject = "%s %s" % (email_config.get('email_prefix', ''), subject)
64
64
65 if recipients:
65 if recipients:
66 if isinstance(recipients, compat.string_types):
66 if isinstance(recipients, compat.string_types):
67 recipients = recipients.split(',')
67 recipients = recipients.split(',')
68 else:
68 else:
69 # if recipients are not defined we send to email_config + all admins
69 # if recipients are not defined we send to email_config + all admins
70 admins = []
70 admins = []
71 for u in User.query().filter(User.admin == true()).all():
71 for u in User.query().filter(User.admin == true()).all():
72 if u.email:
72 if u.email:
73 admins.append(u.email)
73 admins.append(u.email)
74 recipients = []
74 recipients = []
75 config_email = email_config.get('email_to')
75 config_email = email_config.get('email_to')
76 if config_email:
76 if config_email:
77 recipients += [config_email]
77 recipients += [config_email]
78 recipients += admins
78 recipients += admins
79
79
80 # translate our LEGACY config into the one that pyramid_mailer supports
80 # translate our LEGACY config into the one that pyramid_mailer supports
81 email_conf = dict(
81 email_conf = dict(
82 host=mail_server,
82 host=mail_server,
83 port=email_config.get('smtp_port', 25),
83 port=email_config.get('smtp_port', 25),
84 username=email_config.get('smtp_username'),
84 username=email_config.get('smtp_username'),
85 password=email_config.get('smtp_password'),
85 password=email_config.get('smtp_password'),
86
86
87 tls=str2bool(email_config.get('smtp_use_tls')),
87 tls=str2bool(email_config.get('smtp_use_tls')),
88 ssl=str2bool(email_config.get('smtp_use_ssl')),
88 ssl=str2bool(email_config.get('smtp_use_ssl')),
89
89
90 # SSL key file
90 # SSL key file
91 # keyfile='',
91 # keyfile='',
92
92
93 # SSL certificate file
93 # SSL certificate file
94 # certfile='',
94 # certfile='',
95
95
96 # Location of maildir
96 # Location of maildir
97 # queue_path='',
97 # queue_path='',
98
98
99 default_sender=email_config.get('app_email_from', 'RhodeCode'),
99 default_sender=email_config.get('app_email_from', 'RhodeCode'),
100
100
101 debug=str2bool(email_config.get('smtp_debug')),
101 debug=str2bool(email_config.get('smtp_debug')),
102 # /usr/sbin/sendmail Sendmail executable
102 # /usr/sbin/sendmail Sendmail executable
103 # sendmail_app='',
103 # sendmail_app='',
104
104
105 # {sendmail_app} -t -i -f {sender} Template for sendmail execution
105 # {sendmail_app} -t -i -f {sender} Template for sendmail execution
106 # sendmail_template='',
106 # sendmail_template='',
107 )
107 )
108
108
109 try:
109 try:
110 mailer = Mailer(**email_conf)
110 mailer = Mailer(**email_conf)
111
111
112 message = Message(subject=subject,
112 message = Message(subject=subject,
113 sender=email_conf['default_sender'],
113 sender=email_conf['default_sender'],
114 recipients=recipients,
114 recipients=recipients,
115 body=body, html=html_body)
115 body=body, html=html_body)
116 mailer.send_immediately(message)
116 mailer.send_immediately(message)
117
117
118 except Exception:
118 except Exception:
119 log.exception('Mail sending failed')
119 log.exception('Mail sending failed')
120 return False
120 return False
121 return True
121 return True
122
122
123
123
124 @async_task(ignore_result=True, base=RequestContextTask)
124 @async_task(ignore_result=True, base=RequestContextTask)
125 def create_repo(form_data, cur_user):
125 def create_repo(form_data, cur_user):
126 from rhodecode.model.repo import RepoModel
126 from rhodecode.model.repo import RepoModel
127 from rhodecode.model.user import UserModel
127 from rhodecode.model.user import UserModel
128 from rhodecode.model.scm import ScmModel
128 from rhodecode.model.scm import ScmModel
129 from rhodecode.model.settings import SettingsModel
129 from rhodecode.model.settings import SettingsModel
130
130
131 log = get_logger(create_repo)
131 log = get_logger(create_repo)
132
132
133 cur_user = UserModel()._get_user(cur_user)
133 cur_user = UserModel()._get_user(cur_user)
134 owner = cur_user
134 owner = cur_user
135
135
136 repo_name = form_data['repo_name']
136 repo_name = form_data['repo_name']
137 repo_name_full = form_data['repo_name_full']
137 repo_name_full = form_data['repo_name_full']
138 repo_type = form_data['repo_type']
138 repo_type = form_data['repo_type']
139 description = form_data['repo_description']
139 description = form_data['repo_description']
140 private = form_data['repo_private']
140 private = form_data['repo_private']
141 clone_uri = form_data.get('clone_uri')
141 clone_uri = form_data.get('clone_uri')
142 repo_group = safe_int(form_data['repo_group'])
142 repo_group = safe_int(form_data['repo_group'])
143 copy_fork_permissions = form_data.get('copy_permissions')
143 copy_fork_permissions = form_data.get('copy_permissions')
144 copy_group_permissions = form_data.get('repo_copy_permissions')
144 copy_group_permissions = form_data.get('repo_copy_permissions')
145 fork_of = form_data.get('fork_parent_id')
145 fork_of = form_data.get('fork_parent_id')
146 state = form_data.get('repo_state', Repository.STATE_PENDING)
146 state = form_data.get('repo_state', Repository.STATE_PENDING)
147
147
148 # repo creation defaults, private and repo_type are filled in form
148 # repo creation defaults, private and repo_type are filled in form
149 defs = SettingsModel().get_default_repo_settings(strip_prefix=True)
149 defs = SettingsModel().get_default_repo_settings(strip_prefix=True)
150 enable_statistics = form_data.get(
150 enable_statistics = form_data.get(
151 'enable_statistics', defs.get('repo_enable_statistics'))
151 'enable_statistics', defs.get('repo_enable_statistics'))
152 enable_locking = form_data.get(
152 enable_locking = form_data.get(
153 'enable_locking', defs.get('repo_enable_locking'))
153 'enable_locking', defs.get('repo_enable_locking'))
154 enable_downloads = form_data.get(
154 enable_downloads = form_data.get(
155 'enable_downloads', defs.get('repo_enable_downloads'))
155 'enable_downloads', defs.get('repo_enable_downloads'))
156
156
157 # set landing rev based on default branches for SCM
157 # set landing rev based on default branches for SCM
158 landing_ref, _label = ScmModel.backend_landing_ref(repo_type)
158 landing_ref, _label = ScmModel.backend_landing_ref(repo_type)
159
159
160 try:
160 try:
161 RepoModel()._create_repo(
161 RepoModel()._create_repo(
162 repo_name=repo_name_full,
162 repo_name=repo_name_full,
163 repo_type=repo_type,
163 repo_type=repo_type,
164 description=description,
164 description=description,
165 owner=owner,
165 owner=owner,
166 private=private,
166 private=private,
167 clone_uri=clone_uri,
167 clone_uri=clone_uri,
168 repo_group=repo_group,
168 repo_group=repo_group,
169 landing_rev=landing_ref,
169 landing_rev=landing_ref,
170 fork_of=fork_of,
170 fork_of=fork_of,
171 copy_fork_permissions=copy_fork_permissions,
171 copy_fork_permissions=copy_fork_permissions,
172 copy_group_permissions=copy_group_permissions,
172 copy_group_permissions=copy_group_permissions,
173 enable_statistics=enable_statistics,
173 enable_statistics=enable_statistics,
174 enable_locking=enable_locking,
174 enable_locking=enable_locking,
175 enable_downloads=enable_downloads,
175 enable_downloads=enable_downloads,
176 state=state
176 state=state
177 )
177 )
178 Session().commit()
178 Session().commit()
179
179
180 # now create this repo on Filesystem
180 # now create this repo on Filesystem
181 RepoModel()._create_filesystem_repo(
181 RepoModel()._create_filesystem_repo(
182 repo_name=repo_name,
182 repo_name=repo_name,
183 repo_type=repo_type,
183 repo_type=repo_type,
184 repo_group=RepoModel()._get_repo_group(repo_group),
184 repo_group=RepoModel()._get_repo_group(repo_group),
185 clone_uri=clone_uri,
185 clone_uri=clone_uri,
186 )
186 )
187 repo = Repository.get_by_repo_name(repo_name_full)
187 repo = Repository.get_by_repo_name(repo_name_full)
188 log_create_repository(created_by=owner.username, **repo.get_dict())
188 log_create_repository(created_by=owner.username, **repo.get_dict())
189
189
190 # update repo commit caches initially
190 # update repo commit caches initially
191 repo.update_commit_cache()
191 repo.update_commit_cache()
192
192
193 # set new created state
193 # set new created state
194 repo.set_state(Repository.STATE_CREATED)
194 repo.set_state(Repository.STATE_CREATED)
195 repo_id = repo.repo_id
195 repo_id = repo.repo_id
196 repo_data = repo.get_api_data()
196 repo_data = repo.get_api_data()
197
197
198 audit_logger.store(
198 audit_logger.store(
199 'repo.create', action_data={'data': repo_data},
199 'repo.create', action_data={'data': repo_data},
200 user=cur_user,
200 user=cur_user,
201 repo=audit_logger.RepoWrap(repo_name=repo_name, repo_id=repo_id))
201 repo=audit_logger.RepoWrap(repo_name=repo_name, repo_id=repo_id))
202
202
203 Session().commit()
203 Session().commit()
204 except Exception as e:
204 except Exception as e:
205 log.warning('Exception occurred when creating repository, '
205 log.warning('Exception occurred when creating repository, '
206 'doing cleanup...', exc_info=True)
206 'doing cleanup...', exc_info=True)
207 if isinstance(e, IntegrityError):
207 if isinstance(e, IntegrityError):
208 Session().rollback()
208 Session().rollback()
209
209
210 # rollback things manually !
210 # rollback things manually !
211 repo = Repository.get_by_repo_name(repo_name_full)
211 repo = Repository.get_by_repo_name(repo_name_full)
212 if repo:
212 if repo:
213 Repository.delete(repo.repo_id)
213 Repository.delete(repo.repo_id)
214 Session().commit()
214 Session().commit()
215 RepoModel()._delete_filesystem_repo(repo)
215 RepoModel()._delete_filesystem_repo(repo)
216 log.info('Cleanup of repo %s finished', repo_name_full)
216 log.info('Cleanup of repo %s finished', repo_name_full)
217 raise
217 raise
218
218
219 return True
219 return True
220
220
221
221
222 @async_task(ignore_result=True, base=RequestContextTask)
222 @async_task(ignore_result=True, base=RequestContextTask)
223 def create_repo_fork(form_data, cur_user):
223 def create_repo_fork(form_data, cur_user):
224 """
224 """
225 Creates a fork of repository using internal VCS methods
225 Creates a fork of repository using internal VCS methods
226 """
226 """
227 from rhodecode.model.repo import RepoModel
227 from rhodecode.model.repo import RepoModel
228 from rhodecode.model.user import UserModel
228 from rhodecode.model.user import UserModel
229
229
230 log = get_logger(create_repo_fork)
230 log = get_logger(create_repo_fork)
231
231
232 cur_user = UserModel()._get_user(cur_user)
232 cur_user = UserModel()._get_user(cur_user)
233 owner = cur_user
233 owner = cur_user
234
234
235 repo_name = form_data['repo_name'] # fork in this case
235 repo_name = form_data['repo_name'] # fork in this case
236 repo_name_full = form_data['repo_name_full']
236 repo_name_full = form_data['repo_name_full']
237 repo_type = form_data['repo_type']
237 repo_type = form_data['repo_type']
238 description = form_data['description']
238 description = form_data['description']
239 private = form_data['private']
239 private = form_data['private']
240 clone_uri = form_data.get('clone_uri')
240 clone_uri = form_data.get('clone_uri')
241 repo_group = safe_int(form_data['repo_group'])
241 repo_group = safe_int(form_data['repo_group'])
242 landing_ref = form_data['landing_rev']
242 landing_ref = form_data['landing_rev']
243 copy_fork_permissions = form_data.get('copy_permissions')
243 copy_fork_permissions = form_data.get('copy_permissions')
244 fork_id = safe_int(form_data.get('fork_parent_id'))
244 fork_id = safe_int(form_data.get('fork_parent_id'))
245
245
246 try:
246 try:
247 fork_of = RepoModel()._get_repo(fork_id)
247 fork_of = RepoModel()._get_repo(fork_id)
248 RepoModel()._create_repo(
248 RepoModel()._create_repo(
249 repo_name=repo_name_full,
249 repo_name=repo_name_full,
250 repo_type=repo_type,
250 repo_type=repo_type,
251 description=description,
251 description=description,
252 owner=owner,
252 owner=owner,
253 private=private,
253 private=private,
254 clone_uri=clone_uri,
254 clone_uri=clone_uri,
255 repo_group=repo_group,
255 repo_group=repo_group,
256 landing_rev=landing_ref,
256 landing_rev=landing_ref,
257 fork_of=fork_of,
257 fork_of=fork_of,
258 copy_fork_permissions=copy_fork_permissions
258 copy_fork_permissions=copy_fork_permissions
259 )
259 )
260
260
261 Session().commit()
261 Session().commit()
262
262
263 base_path = Repository.base_path()
263 base_path = Repository.base_path()
264 source_repo_path = os.path.join(base_path, fork_of.repo_name)
264 source_repo_path = os.path.join(base_path, fork_of.repo_name)
265
265
266 # now create this repo on Filesystem
266 # now create this repo on Filesystem
267 RepoModel()._create_filesystem_repo(
267 RepoModel()._create_filesystem_repo(
268 repo_name=repo_name,
268 repo_name=repo_name,
269 repo_type=repo_type,
269 repo_type=repo_type,
270 repo_group=RepoModel()._get_repo_group(repo_group),
270 repo_group=RepoModel()._get_repo_group(repo_group),
271 clone_uri=source_repo_path,
271 clone_uri=source_repo_path,
272 )
272 )
273 repo = Repository.get_by_repo_name(repo_name_full)
273 repo = Repository.get_by_repo_name(repo_name_full)
274 log_create_repository(created_by=owner.username, **repo.get_dict())
274 log_create_repository(created_by=owner.username, **repo.get_dict())
275
275
276 # update repo commit caches initially
276 # update repo commit caches initially
277 config = repo._config
277 config = repo._config
278 config.set('extensions', 'largefiles', '')
278 config.set('extensions', 'largefiles', '')
279 repo.update_commit_cache(config=config)
279 repo.update_commit_cache(config=config)
280
280
281 # set new created state
281 # set new created state
282 repo.set_state(Repository.STATE_CREATED)
282 repo.set_state(Repository.STATE_CREATED)
283
283
284 repo_id = repo.repo_id
284 repo_id = repo.repo_id
285 repo_data = repo.get_api_data()
285 repo_data = repo.get_api_data()
286 audit_logger.store(
286 audit_logger.store(
287 'repo.fork', action_data={'data': repo_data},
287 'repo.fork', action_data={'data': repo_data},
288 user=cur_user,
288 user=cur_user,
289 repo=audit_logger.RepoWrap(repo_name=repo_name, repo_id=repo_id))
289 repo=audit_logger.RepoWrap(repo_name=repo_name, repo_id=repo_id))
290
290
291 Session().commit()
291 Session().commit()
292 except Exception as e:
292 except Exception as e:
293 log.warning('Exception occurred when forking repository, '
293 log.warning('Exception occurred when forking repository, '
294 'doing cleanup...', exc_info=True)
294 'doing cleanup...', exc_info=True)
295 if isinstance(e, IntegrityError):
295 if isinstance(e, IntegrityError):
296 Session().rollback()
296 Session().rollback()
297
297
298 # rollback things manually !
298 # rollback things manually !
299 repo = Repository.get_by_repo_name(repo_name_full)
299 repo = Repository.get_by_repo_name(repo_name_full)
300 if repo:
300 if repo:
301 Repository.delete(repo.repo_id)
301 Repository.delete(repo.repo_id)
302 Session().commit()
302 Session().commit()
303 RepoModel()._delete_filesystem_repo(repo)
303 RepoModel()._delete_filesystem_repo(repo)
304 log.info('Cleanup of repo %s finished', repo_name_full)
304 log.info('Cleanup of repo %s finished', repo_name_full)
305 raise
305 raise
306
306
307 return True
307 return True
308
308
309
309
310 @async_task(ignore_result=True)
310 @async_task(ignore_result=True)
311 def repo_maintenance(repoid):
311 def repo_maintenance(repoid):
312 from rhodecode.lib import repo_maintenance as repo_maintenance_lib
312 from rhodecode.lib import repo_maintenance as repo_maintenance_lib
313 log = get_logger(repo_maintenance)
313 log = get_logger(repo_maintenance)
314 repo = Repository.get_by_id_or_repo_name(repoid)
314 repo = Repository.get_by_id_or_repo_name(repoid)
315 if repo:
315 if repo:
316 maintenance = repo_maintenance_lib.RepoMaintenance()
316 maintenance = repo_maintenance_lib.RepoMaintenance()
317 tasks = maintenance.get_tasks_for_repo(repo)
317 tasks = maintenance.get_tasks_for_repo(repo)
318 log.debug('Executing %s tasks on repo `%s`', tasks, repoid)
318 log.debug('Executing %s tasks on repo `%s`', tasks, repoid)
319 executed_types = maintenance.execute(repo)
319 executed_types = maintenance.execute(repo)
320 log.debug('Got execution results %s', executed_types)
320 log.debug('Got execution results %s', executed_types)
321 else:
321 else:
322 log.debug('Repo `%s` not found or without a clone_url', repoid)
322 log.debug('Repo `%s` not found or without a clone_url', repoid)
323
323
324
324
325 @async_task(ignore_result=True)
325 @async_task(ignore_result=True)
326 def check_for_update():
326 def check_for_update():
327 from rhodecode.model.update import UpdateModel
327 from rhodecode.model.update import UpdateModel
328 update_url = UpdateModel().get_update_url()
328 update_url = UpdateModel().get_update_url()
329 cur_ver = rhodecode.__version__
329 cur_ver = rhodecode.__version__
330
330
331 try:
331 try:
332 data = UpdateModel().get_update_data(update_url)
332 data = UpdateModel().get_update_data(update_url)
333 latest = data['versions'][0]
333 latest = data['versions'][0]
334 UpdateModel().store_version(latest['version'])
334 UpdateModel().store_version(latest['version'])
335 except Exception:
335 except Exception:
336 pass
336 pass
337
337
338
338
339 @async_task(ignore_result=False)
339 @async_task(ignore_result=False)
340 def beat_check(*args, **kwargs):
340 def beat_check(*args, **kwargs):
341 log = get_logger(beat_check)
341 log = get_logger(beat_check)
342 log.info('Got args: %r and kwargs %r', args, kwargs)
342 log.info('Got args: %r and kwargs %r', args, kwargs)
343 return time.time()
343 return time.time()
344
345
346 @async_task(ignore_result=True)
347 def sync_repo_groups_last_update(*args, **kwargs):
348 from rhodecode.model.repo_group import RepoGroupModel
349 return RepoGroupModel().update_commit_cache()
General Comments 0
You need to be logged in to leave comments. Login now