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