##// END OF EJS Templates
system-info: improve formatting of snapshot info page.
marcink -
r1114:4074d5a1 default
parent child Browse files
Show More
@@ -1,837 +1,838 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 22 """
23 23 settings controller for rhodecode admin
24 24 """
25 25
26 26 import collections
27 27 import logging
28 28 import urllib2
29 29
30 30 import datetime
31 31 import formencode
32 32 from formencode import htmlfill
33 33 import packaging.version
34 34 from pylons import request, tmpl_context as c, url, config
35 35 from pylons.controllers.util import redirect
36 36 from pylons.i18n.translation import _, lazy_ugettext
37 37 from pyramid.threadlocal import get_current_registry
38 38 from webob.exc import HTTPBadRequest
39 39
40 40 import rhodecode
41 41 from rhodecode.admin.navigation import navigation_list
42 42 from rhodecode.lib import auth
43 43 from rhodecode.lib import helpers as h
44 44 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
45 45 from rhodecode.lib.base import BaseController, render
46 46 from rhodecode.lib.celerylib import tasks, run_task
47 47 from rhodecode.lib.utils import repo2db_mapper
48 48 from rhodecode.lib.utils2 import (
49 49 str2bool, safe_unicode, AttributeDict, safe_int)
50 50 from rhodecode.lib.compat import OrderedDict
51 51 from rhodecode.lib.ext_json import json
52 52 from rhodecode.lib.utils import jsonify
53 53
54 54 from rhodecode.model.db import RhodeCodeUi, Repository
55 55 from rhodecode.model.forms import ApplicationSettingsForm, \
56 56 ApplicationUiSettingsForm, ApplicationVisualisationForm, \
57 57 LabsSettingsForm, IssueTrackerPatternsForm
58 58 from rhodecode.model.repo_group import RepoGroupModel
59 59
60 60 from rhodecode.model.scm import ScmModel
61 61 from rhodecode.model.notification import EmailNotificationModel
62 62 from rhodecode.model.meta import Session
63 63 from rhodecode.model.settings import (
64 64 IssueTrackerSettingsModel, VcsSettingsModel, SettingNotFound,
65 65 SettingsModel)
66 66
67 67 from rhodecode.model.supervisor import SupervisorModel, SUPERVISOR_MASTER
68 68 from rhodecode.svn_support.config_keys import generate_config
69 69
70 70
71 71 log = logging.getLogger(__name__)
72 72
73 73
74 74 class SettingsController(BaseController):
75 75 """REST Controller styled on the Atom Publishing Protocol"""
76 76 # To properly map this controller, ensure your config/routing.py
77 77 # file has a resource setup:
78 78 # map.resource('setting', 'settings', controller='admin/settings',
79 79 # path_prefix='/admin', name_prefix='admin_')
80 80
81 81 @LoginRequired()
82 82 def __before__(self):
83 83 super(SettingsController, self).__before__()
84 84 c.labs_active = str2bool(
85 85 rhodecode.CONFIG.get('labs_settings_active', 'true'))
86 86 c.navlist = navigation_list(request)
87 87
88 88 def _get_hg_ui_settings(self):
89 89 ret = RhodeCodeUi.query().all()
90 90
91 91 if not ret:
92 92 raise Exception('Could not get application ui settings !')
93 93 settings = {}
94 94 for each in ret:
95 95 k = each.ui_key
96 96 v = each.ui_value
97 97 if k == '/':
98 98 k = 'root_path'
99 99
100 100 if k in ['push_ssl', 'publish']:
101 101 v = str2bool(v)
102 102
103 103 if k.find('.') != -1:
104 104 k = k.replace('.', '_')
105 105
106 106 if each.ui_section in ['hooks', 'extensions']:
107 107 v = each.ui_active
108 108
109 109 settings[each.ui_section + '_' + k] = v
110 110 return settings
111 111
112 112 @HasPermissionAllDecorator('hg.admin')
113 113 @auth.CSRFRequired()
114 114 @jsonify
115 115 def delete_svn_pattern(self):
116 116 if not request.is_xhr:
117 117 raise HTTPBadRequest()
118 118
119 119 delete_pattern_id = request.POST.get('delete_svn_pattern')
120 120 model = VcsSettingsModel()
121 121 try:
122 122 model.delete_global_svn_pattern(delete_pattern_id)
123 123 except SettingNotFound:
124 124 raise HTTPBadRequest()
125 125
126 126 Session().commit()
127 127 return True
128 128
129 129 @HasPermissionAllDecorator('hg.admin')
130 130 @auth.CSRFRequired()
131 131 def settings_vcs_update(self):
132 132 """POST /admin/settings: All items in the collection"""
133 133 # url('admin_settings_vcs')
134 134 c.active = 'vcs'
135 135
136 136 model = VcsSettingsModel()
137 137 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
138 138 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
139 139
140 140 # TODO: Replace with request.registry after migrating to pyramid.
141 141 pyramid_settings = get_current_registry().settings
142 142 c.svn_proxy_generate_config = pyramid_settings[generate_config]
143 143
144 144 application_form = ApplicationUiSettingsForm()()
145 145
146 146 try:
147 147 form_result = application_form.to_python(dict(request.POST))
148 148 except formencode.Invalid as errors:
149 149 h.flash(
150 150 _("Some form inputs contain invalid data."),
151 151 category='error')
152 152 return htmlfill.render(
153 153 render('admin/settings/settings.html'),
154 154 defaults=errors.value,
155 155 errors=errors.error_dict or {},
156 156 prefix_error=False,
157 157 encoding="UTF-8",
158 158 force_defaults=False
159 159 )
160 160
161 161 try:
162 162 if c.visual.allow_repo_location_change:
163 163 model.update_global_path_setting(
164 164 form_result['paths_root_path'])
165 165
166 166 model.update_global_ssl_setting(form_result['web_push_ssl'])
167 167 model.update_global_hook_settings(form_result)
168 168
169 169 model.create_or_update_global_svn_settings(form_result)
170 170 model.create_or_update_global_hg_settings(form_result)
171 171 model.create_or_update_global_pr_settings(form_result)
172 172 except Exception:
173 173 log.exception("Exception while updating settings")
174 174 h.flash(_('Error occurred during updating '
175 175 'application settings'), category='error')
176 176 else:
177 177 Session().commit()
178 178 h.flash(_('Updated VCS settings'), category='success')
179 179 return redirect(url('admin_settings_vcs'))
180 180
181 181 return htmlfill.render(
182 182 render('admin/settings/settings.html'),
183 183 defaults=self._form_defaults(),
184 184 encoding="UTF-8",
185 185 force_defaults=False)
186 186
187 187 @HasPermissionAllDecorator('hg.admin')
188 188 def settings_vcs(self):
189 189 """GET /admin/settings: All items in the collection"""
190 190 # url('admin_settings_vcs')
191 191 c.active = 'vcs'
192 192 model = VcsSettingsModel()
193 193 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
194 194 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
195 195
196 196 # TODO: Replace with request.registry after migrating to pyramid.
197 197 pyramid_settings = get_current_registry().settings
198 198 c.svn_proxy_generate_config = pyramid_settings[generate_config]
199 199
200 200 return htmlfill.render(
201 201 render('admin/settings/settings.html'),
202 202 defaults=self._form_defaults(),
203 203 encoding="UTF-8",
204 204 force_defaults=False)
205 205
206 206 @HasPermissionAllDecorator('hg.admin')
207 207 @auth.CSRFRequired()
208 208 def settings_mapping_update(self):
209 209 """POST /admin/settings/mapping: All items in the collection"""
210 210 # url('admin_settings_mapping')
211 211 c.active = 'mapping'
212 212 rm_obsolete = request.POST.get('destroy', False)
213 213 invalidate_cache = request.POST.get('invalidate', False)
214 214 log.debug(
215 215 'rescanning repo location with destroy obsolete=%s', rm_obsolete)
216 216
217 217 if invalidate_cache:
218 218 log.debug('invalidating all repositories cache')
219 219 for repo in Repository.get_all():
220 220 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
221 221
222 222 filesystem_repos = ScmModel().repo_scan()
223 223 added, removed = repo2db_mapper(filesystem_repos, rm_obsolete)
224 224 _repr = lambda l: ', '.join(map(safe_unicode, l)) or '-'
225 225 h.flash(_('Repositories successfully '
226 226 'rescanned added: %s ; removed: %s') %
227 227 (_repr(added), _repr(removed)),
228 228 category='success')
229 229 return redirect(url('admin_settings_mapping'))
230 230
231 231 @HasPermissionAllDecorator('hg.admin')
232 232 def settings_mapping(self):
233 233 """GET /admin/settings/mapping: All items in the collection"""
234 234 # url('admin_settings_mapping')
235 235 c.active = 'mapping'
236 236
237 237 return htmlfill.render(
238 238 render('admin/settings/settings.html'),
239 239 defaults=self._form_defaults(),
240 240 encoding="UTF-8",
241 241 force_defaults=False)
242 242
243 243 @HasPermissionAllDecorator('hg.admin')
244 244 @auth.CSRFRequired()
245 245 def settings_global_update(self):
246 246 """POST /admin/settings/global: All items in the collection"""
247 247 # url('admin_settings_global')
248 248 c.active = 'global'
249 249 c.personal_repo_group_default_pattern = RepoGroupModel()\
250 250 .get_personal_group_name_pattern()
251 251 application_form = ApplicationSettingsForm()()
252 252 try:
253 253 form_result = application_form.to_python(dict(request.POST))
254 254 except formencode.Invalid as errors:
255 255 return htmlfill.render(
256 256 render('admin/settings/settings.html'),
257 257 defaults=errors.value,
258 258 errors=errors.error_dict or {},
259 259 prefix_error=False,
260 260 encoding="UTF-8",
261 261 force_defaults=False)
262 262
263 263 try:
264 264 settings = [
265 265 ('title', 'rhodecode_title', 'unicode'),
266 266 ('realm', 'rhodecode_realm', 'unicode'),
267 267 ('pre_code', 'rhodecode_pre_code', 'unicode'),
268 268 ('post_code', 'rhodecode_post_code', 'unicode'),
269 269 ('captcha_public_key', 'rhodecode_captcha_public_key', 'unicode'),
270 270 ('captcha_private_key', 'rhodecode_captcha_private_key', 'unicode'),
271 271 ('create_personal_repo_group', 'rhodecode_create_personal_repo_group', 'bool'),
272 272 ('personal_repo_group_pattern', 'rhodecode_personal_repo_group_pattern', 'unicode'),
273 273 ]
274 274 for setting, form_key, type_ in settings:
275 275 sett = SettingsModel().create_or_update_setting(
276 276 setting, form_result[form_key], type_)
277 277 Session().add(sett)
278 278
279 279 Session().commit()
280 280 SettingsModel().invalidate_settings_cache()
281 281 h.flash(_('Updated application settings'), category='success')
282 282 except Exception:
283 283 log.exception("Exception while updating application settings")
284 284 h.flash(
285 285 _('Error occurred during updating application settings'),
286 286 category='error')
287 287
288 288 return redirect(url('admin_settings_global'))
289 289
290 290 @HasPermissionAllDecorator('hg.admin')
291 291 def settings_global(self):
292 292 """GET /admin/settings/global: All items in the collection"""
293 293 # url('admin_settings_global')
294 294 c.active = 'global'
295 295 c.personal_repo_group_default_pattern = RepoGroupModel()\
296 296 .get_personal_group_name_pattern()
297 297
298 298 return htmlfill.render(
299 299 render('admin/settings/settings.html'),
300 300 defaults=self._form_defaults(),
301 301 encoding="UTF-8",
302 302 force_defaults=False)
303 303
304 304 @HasPermissionAllDecorator('hg.admin')
305 305 @auth.CSRFRequired()
306 306 def settings_visual_update(self):
307 307 """POST /admin/settings/visual: All items in the collection"""
308 308 # url('admin_settings_visual')
309 309 c.active = 'visual'
310 310 application_form = ApplicationVisualisationForm()()
311 311 try:
312 312 form_result = application_form.to_python(dict(request.POST))
313 313 except formencode.Invalid as errors:
314 314 return htmlfill.render(
315 315 render('admin/settings/settings.html'),
316 316 defaults=errors.value,
317 317 errors=errors.error_dict or {},
318 318 prefix_error=False,
319 319 encoding="UTF-8",
320 320 force_defaults=False
321 321 )
322 322
323 323 try:
324 324 settings = [
325 325 ('show_public_icon', 'rhodecode_show_public_icon', 'bool'),
326 326 ('show_private_icon', 'rhodecode_show_private_icon', 'bool'),
327 327 ('stylify_metatags', 'rhodecode_stylify_metatags', 'bool'),
328 328 ('repository_fields', 'rhodecode_repository_fields', 'bool'),
329 329 ('dashboard_items', 'rhodecode_dashboard_items', 'int'),
330 330 ('admin_grid_items', 'rhodecode_admin_grid_items', 'int'),
331 331 ('show_version', 'rhodecode_show_version', 'bool'),
332 332 ('use_gravatar', 'rhodecode_use_gravatar', 'bool'),
333 333 ('markup_renderer', 'rhodecode_markup_renderer', 'unicode'),
334 334 ('gravatar_url', 'rhodecode_gravatar_url', 'unicode'),
335 335 ('clone_uri_tmpl', 'rhodecode_clone_uri_tmpl', 'unicode'),
336 336 ('support_url', 'rhodecode_support_url', 'unicode'),
337 337 ('show_revision_number', 'rhodecode_show_revision_number', 'bool'),
338 338 ('show_sha_length', 'rhodecode_show_sha_length', 'int'),
339 339 ]
340 340 for setting, form_key, type_ in settings:
341 341 sett = SettingsModel().create_or_update_setting(
342 342 setting, form_result[form_key], type_)
343 343 Session().add(sett)
344 344
345 345 Session().commit()
346 346 SettingsModel().invalidate_settings_cache()
347 347 h.flash(_('Updated visualisation settings'), category='success')
348 348 except Exception:
349 349 log.exception("Exception updating visualization settings")
350 350 h.flash(_('Error occurred during updating '
351 351 'visualisation settings'),
352 352 category='error')
353 353
354 354 return redirect(url('admin_settings_visual'))
355 355
356 356 @HasPermissionAllDecorator('hg.admin')
357 357 def settings_visual(self):
358 358 """GET /admin/settings/visual: All items in the collection"""
359 359 # url('admin_settings_visual')
360 360 c.active = 'visual'
361 361
362 362 return htmlfill.render(
363 363 render('admin/settings/settings.html'),
364 364 defaults=self._form_defaults(),
365 365 encoding="UTF-8",
366 366 force_defaults=False)
367 367
368 368 @HasPermissionAllDecorator('hg.admin')
369 369 @auth.CSRFRequired()
370 370 def settings_issuetracker_test(self):
371 371 if request.is_xhr:
372 372 return h.urlify_commit_message(
373 373 request.POST.get('test_text', ''),
374 374 'repo_group/test_repo1')
375 375 else:
376 376 raise HTTPBadRequest()
377 377
378 378 @HasPermissionAllDecorator('hg.admin')
379 379 @auth.CSRFRequired()
380 380 def settings_issuetracker_delete(self):
381 381 uid = request.POST.get('uid')
382 382 IssueTrackerSettingsModel().delete_entries(uid)
383 383 h.flash(_('Removed issue tracker entry'), category='success')
384 384 return redirect(url('admin_settings_issuetracker'))
385 385
386 386 @HasPermissionAllDecorator('hg.admin')
387 387 def settings_issuetracker(self):
388 388 """GET /admin/settings/issue-tracker: All items in the collection"""
389 389 # url('admin_settings_issuetracker')
390 390 c.active = 'issuetracker'
391 391 defaults = SettingsModel().get_all_settings()
392 392
393 393 entry_key = 'rhodecode_issuetracker_pat_'
394 394
395 395 c.issuetracker_entries = {}
396 396 for k, v in defaults.items():
397 397 if k.startswith(entry_key):
398 398 uid = k[len(entry_key):]
399 399 c.issuetracker_entries[uid] = None
400 400
401 401 for uid in c.issuetracker_entries:
402 402 c.issuetracker_entries[uid] = AttributeDict({
403 403 'pat': defaults.get('rhodecode_issuetracker_pat_' + uid),
404 404 'url': defaults.get('rhodecode_issuetracker_url_' + uid),
405 405 'pref': defaults.get('rhodecode_issuetracker_pref_' + uid),
406 406 'desc': defaults.get('rhodecode_issuetracker_desc_' + uid),
407 407 })
408 408
409 409 return render('admin/settings/settings.html')
410 410
411 411 @HasPermissionAllDecorator('hg.admin')
412 412 @auth.CSRFRequired()
413 413 def settings_issuetracker_save(self):
414 414 settings_model = IssueTrackerSettingsModel()
415 415
416 416 form = IssueTrackerPatternsForm()().to_python(request.POST)
417 417 if form:
418 418 for uid in form.get('delete_patterns', []):
419 419 settings_model.delete_entries(uid)
420 420
421 421 for pattern in form.get('patterns', []):
422 422 for setting, value, type_ in pattern:
423 423 sett = settings_model.create_or_update_setting(
424 424 setting, value, type_)
425 425 Session().add(sett)
426 426
427 427 Session().commit()
428 428
429 429 SettingsModel().invalidate_settings_cache()
430 430 h.flash(_('Updated issue tracker entries'), category='success')
431 431 return redirect(url('admin_settings_issuetracker'))
432 432
433 433 @HasPermissionAllDecorator('hg.admin')
434 434 @auth.CSRFRequired()
435 435 def settings_email_update(self):
436 436 """POST /admin/settings/email: All items in the collection"""
437 437 # url('admin_settings_email')
438 438 c.active = 'email'
439 439
440 440 test_email = request.POST.get('test_email')
441 441
442 442 if not test_email:
443 443 h.flash(_('Please enter email address'), category='error')
444 444 return redirect(url('admin_settings_email'))
445 445
446 446 email_kwargs = {
447 447 'date': datetime.datetime.now(),
448 448 'user': c.rhodecode_user,
449 449 'rhodecode_version': c.rhodecode_version
450 450 }
451 451
452 452 (subject, headers, email_body,
453 453 email_body_plaintext) = EmailNotificationModel().render_email(
454 454 EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs)
455 455
456 456 recipients = [test_email] if test_email else None
457 457
458 458 run_task(tasks.send_email, recipients, subject,
459 459 email_body_plaintext, email_body)
460 460
461 461 h.flash(_('Send email task created'), category='success')
462 462 return redirect(url('admin_settings_email'))
463 463
464 464 @HasPermissionAllDecorator('hg.admin')
465 465 def settings_email(self):
466 466 """GET /admin/settings/email: All items in the collection"""
467 467 # url('admin_settings_email')
468 468 c.active = 'email'
469 469 c.rhodecode_ini = rhodecode.CONFIG
470 470
471 471 return htmlfill.render(
472 472 render('admin/settings/settings.html'),
473 473 defaults=self._form_defaults(),
474 474 encoding="UTF-8",
475 475 force_defaults=False)
476 476
477 477 @HasPermissionAllDecorator('hg.admin')
478 478 @auth.CSRFRequired()
479 479 def settings_hooks_update(self):
480 480 """POST or DELETE /admin/settings/hooks: All items in the collection"""
481 481 # url('admin_settings_hooks')
482 482 c.active = 'hooks'
483 483 if c.visual.allow_custom_hooks_settings:
484 484 ui_key = request.POST.get('new_hook_ui_key')
485 485 ui_value = request.POST.get('new_hook_ui_value')
486 486
487 487 hook_id = request.POST.get('hook_id')
488 488 new_hook = False
489 489
490 490 model = SettingsModel()
491 491 try:
492 492 if ui_value and ui_key:
493 493 model.create_or_update_hook(ui_key, ui_value)
494 494 h.flash(_('Added new hook'), category='success')
495 495 new_hook = True
496 496 elif hook_id:
497 497 RhodeCodeUi.delete(hook_id)
498 498 Session().commit()
499 499
500 500 # check for edits
501 501 update = False
502 502 _d = request.POST.dict_of_lists()
503 503 for k, v in zip(_d.get('hook_ui_key', []),
504 504 _d.get('hook_ui_value_new', [])):
505 505 model.create_or_update_hook(k, v)
506 506 update = True
507 507
508 508 if update and not new_hook:
509 509 h.flash(_('Updated hooks'), category='success')
510 510 Session().commit()
511 511 except Exception:
512 512 log.exception("Exception during hook creation")
513 513 h.flash(_('Error occurred during hook creation'),
514 514 category='error')
515 515
516 516 return redirect(url('admin_settings_hooks'))
517 517
518 518 @HasPermissionAllDecorator('hg.admin')
519 519 def settings_hooks(self):
520 520 """GET /admin/settings/hooks: All items in the collection"""
521 521 # url('admin_settings_hooks')
522 522 c.active = 'hooks'
523 523
524 524 model = SettingsModel()
525 525 c.hooks = model.get_builtin_hooks()
526 526 c.custom_hooks = model.get_custom_hooks()
527 527
528 528 return htmlfill.render(
529 529 render('admin/settings/settings.html'),
530 530 defaults=self._form_defaults(),
531 531 encoding="UTF-8",
532 532 force_defaults=False)
533 533
534 534 @HasPermissionAllDecorator('hg.admin')
535 535 def settings_search(self):
536 536 """GET /admin/settings/search: All items in the collection"""
537 537 # url('admin_settings_search')
538 538 c.active = 'search'
539 539
540 540 from rhodecode.lib.index import searcher_from_config
541 541 searcher = searcher_from_config(config)
542 542 c.statistics = searcher.statistics()
543 543
544 544 return render('admin/settings/settings.html')
545 545
546 546 @HasPermissionAllDecorator('hg.admin')
547 547 def settings_system(self):
548 548 """GET /admin/settings/system: All items in the collection"""
549 549 # url('admin_settings_system')
550 550 snapshot = str2bool(request.GET.get('snapshot'))
551 551 defaults = self._form_defaults()
552 552
553 553 c.active = 'system'
554 554 c.rhodecode_update_url = defaults.get('rhodecode_update_url')
555 555 server_info = ScmModel().get_server_info(request.environ)
556 556
557 557 for key, val in server_info.iteritems():
558 558 setattr(c, key, val)
559 559
560 560 def val(name, subkey='human_value'):
561 561 return server_info[name][subkey]
562 562
563 563 def state(name):
564 564 return server_info[name]['state']
565 565
566 566 def val2(name):
567 567 val = server_info[name]['human_value']
568 568 state = server_info[name]['state']
569 569 return val, state
570 570
571 571 c.data_items = [
572 572 # update info
573 573 (_('Update info'), h.literal(
574 574 '<span class="link" id="check_for_update" >%s.</span>' % (
575 575 _('Check for updates')) +
576 576 '<br/> <span >%s.</span>' % (_('Note: please make sure this server can access `%s` for the update link to work') % c.rhodecode_update_url)
577 577 ), ''),
578 578
579 579 # RhodeCode specific
580 580 (_('RhodeCode Version'), val('rhodecode_app')['text'], state('rhodecode_app')),
581 581 (_('RhodeCode Server IP'), val('server')['server_ip'], state('server')),
582 582 (_('RhodeCode Server ID'), val('server')['server_id'], state('server')),
583 583 (_('RhodeCode Configuration'), val('rhodecode_config')['path'], state('rhodecode_config')),
584 584 ('', '', ''), # spacer
585 585
586 586 # Database
587 587 (_('Database'), val('database')['url'], state('database')),
588 588 (_('Database version'), val('database')['version'], state('database')),
589 589 ('', '', ''), # spacer
590 590
591 591 # Platform/Python
592 592 (_('Platform'), val('platform'), state('platform')),
593 593 (_('Python version'), val('python')['version'], state('python')),
594 594 (_('Python path'), val('python')['executable'], state('python')),
595 595 ('', '', ''), # spacer
596 596
597 597 # Systems stats
598 598 (_('CPU'), val('cpu'), state('cpu')),
599 599 (_('Load'), val('load')['text'], state('load')),
600 600 (_('Memory'), val('memory')['text'], state('memory')),
601 601 (_('Uptime'), val('uptime')['text'], state('uptime')),
602 602 ('', '', ''), # spacer
603 603
604 604 # Repo storage
605 605 (_('Storage location'), val('storage')['path'], state('storage')),
606 606 (_('Storage info'), val('storage')['text'], state('storage')),
607 607 (_('Storage inodes'), val('storage_inodes')['text'], state('storage_inodes')),
608 608
609 609 (_('Gist storage location'), val('storage_gist')['path'], state('storage_gist')),
610 610 (_('Gist storage info'), val('storage_gist')['text'], state('storage_gist')),
611 611
612 612 (_('Archive cache storage location'), val('storage_archive')['path'], state('storage_archive')),
613 613 (_('Archive cache info'), val('storage_archive')['text'], state('storage_archive')),
614 614
615 615 (_('Search info'), val('search')['text'], state('search')),
616 616 (_('Search location'), val('search')['location'], state('search')),
617 617 ('', '', ''), # spacer
618 618
619 619 # VCS specific
620 620 (_('VCS Backends'), val('vcs_backends'), state('vcs_backends')),
621 621 (_('VCS Server'), val('vcs_server')['text'], state('vcs_server')),
622 622 (_('GIT'), val('git'), state('git')),
623 623 (_('HG'), val('hg'), state('hg')),
624 624 (_('SVN'), val('svn'), state('svn')),
625 625
626 626 ]
627 627
628 628 # TODO: marcink, figure out how to allow only selected users to do this
629 629 c.allowed_to_snapshot = c.rhodecode_user.admin
630 630
631 631 if snapshot:
632 632 if c.allowed_to_snapshot:
633 c.data_items.pop(0) # remove server info
633 634 return render('admin/settings/settings_system_snapshot.html')
634 635 else:
635 636 h.flash('You are not allowed to do this', category='warning')
636 637
637 638 return htmlfill.render(
638 639 render('admin/settings/settings.html'),
639 640 defaults=defaults,
640 641 encoding="UTF-8",
641 642 force_defaults=False)
642 643
643 644 @staticmethod
644 645 def get_update_data(update_url):
645 646 """Return the JSON update data."""
646 647 ver = rhodecode.__version__
647 648 log.debug('Checking for upgrade on `%s` server', update_url)
648 649 opener = urllib2.build_opener()
649 650 opener.addheaders = [('User-agent', 'RhodeCode-SCM/%s' % ver)]
650 651 response = opener.open(update_url)
651 652 response_data = response.read()
652 653 data = json.loads(response_data)
653 654
654 655 return data
655 656
656 657 @HasPermissionAllDecorator('hg.admin')
657 658 def settings_system_update(self):
658 659 """GET /admin/settings/system/updates: All items in the collection"""
659 660 # url('admin_settings_system_update')
660 661 defaults = self._form_defaults()
661 662 update_url = defaults.get('rhodecode_update_url', '')
662 663
663 664 _err = lambda s: '<div style="color:#ff8888; padding:4px 0px">%s</div>' % (s)
664 665 try:
665 666 data = self.get_update_data(update_url)
666 667 except urllib2.URLError as e:
667 668 log.exception("Exception contacting upgrade server")
668 669 return _err('Failed to contact upgrade server: %r' % e)
669 670 except ValueError as e:
670 671 log.exception("Bad data sent from update server")
671 672 return _err('Bad data sent from update server')
672 673
673 674 latest = data['versions'][0]
674 675
675 676 c.update_url = update_url
676 677 c.latest_data = latest
677 678 c.latest_ver = latest['version']
678 679 c.cur_ver = rhodecode.__version__
679 680 c.should_upgrade = False
680 681
681 682 if (packaging.version.Version(c.latest_ver) >
682 683 packaging.version.Version(c.cur_ver)):
683 684 c.should_upgrade = True
684 685 c.important_notices = latest['general']
685 686
686 687 return render('admin/settings/settings_system_update.html')
687 688
688 689 @HasPermissionAllDecorator('hg.admin')
689 690 def settings_supervisor(self):
690 691 c.rhodecode_ini = rhodecode.CONFIG
691 692 c.active = 'supervisor'
692 693
693 694 c.supervisor_procs = OrderedDict([
694 695 (SUPERVISOR_MASTER, {}),
695 696 ])
696 697
697 698 c.log_size = 10240
698 699 supervisor = SupervisorModel()
699 700
700 701 _connection = supervisor.get_connection(
701 702 c.rhodecode_ini.get('supervisor.uri'))
702 703 c.connection_error = None
703 704 try:
704 705 _connection.supervisor.getAllProcessInfo()
705 706 except Exception as e:
706 707 c.connection_error = str(e)
707 708 log.exception("Exception reading supervisor data")
708 709 return render('admin/settings/settings.html')
709 710
710 711 groupid = c.rhodecode_ini.get('supervisor.group_id')
711 712
712 713 # feed our group processes to the main
713 714 for proc in supervisor.get_group_processes(_connection, groupid):
714 715 c.supervisor_procs[proc['name']] = {}
715 716
716 717 for k in c.supervisor_procs.keys():
717 718 try:
718 719 # master process info
719 720 if k == SUPERVISOR_MASTER:
720 721 _data = supervisor.get_master_state(_connection)
721 722 _data['name'] = 'supervisor master'
722 723 _data['description'] = 'pid %s, id: %s, ver: %s' % (
723 724 _data['pid'], _data['id'], _data['ver'])
724 725 c.supervisor_procs[k] = _data
725 726 else:
726 727 procid = groupid + ":" + k
727 728 c.supervisor_procs[k] = supervisor.get_process_info(_connection, procid)
728 729 except Exception as e:
729 730 log.exception("Exception reading supervisor data")
730 731 c.supervisor_procs[k] = {'_rhodecode_error': str(e)}
731 732
732 733 return render('admin/settings/settings.html')
733 734
734 735 @HasPermissionAllDecorator('hg.admin')
735 736 def settings_supervisor_log(self, procid):
736 737 import rhodecode
737 738 c.rhodecode_ini = rhodecode.CONFIG
738 739 c.active = 'supervisor_tail'
739 740
740 741 supervisor = SupervisorModel()
741 742 _connection = supervisor.get_connection(c.rhodecode_ini.get('supervisor.uri'))
742 743 groupid = c.rhodecode_ini.get('supervisor.group_id')
743 744 procid = groupid + ":" + procid if procid != SUPERVISOR_MASTER else procid
744 745
745 746 c.log_size = 10240
746 747 offset = abs(safe_int(request.GET.get('offset', c.log_size))) * -1
747 748 c.log = supervisor.read_process_log(_connection, procid, offset, 0)
748 749
749 750 return render('admin/settings/settings.html')
750 751
751 752 @HasPermissionAllDecorator('hg.admin')
752 753 @auth.CSRFRequired()
753 754 def settings_labs_update(self):
754 755 """POST /admin/settings/labs: All items in the collection"""
755 756 # url('admin_settings/labs', method={'POST'})
756 757 c.active = 'labs'
757 758
758 759 application_form = LabsSettingsForm()()
759 760 try:
760 761 form_result = application_form.to_python(dict(request.POST))
761 762 except formencode.Invalid as errors:
762 763 h.flash(
763 764 _('Some form inputs contain invalid data.'),
764 765 category='error')
765 766 return htmlfill.render(
766 767 render('admin/settings/settings.html'),
767 768 defaults=errors.value,
768 769 errors=errors.error_dict or {},
769 770 prefix_error=False,
770 771 encoding='UTF-8',
771 772 force_defaults=False
772 773 )
773 774
774 775 try:
775 776 session = Session()
776 777 for setting in _LAB_SETTINGS:
777 778 setting_name = setting.key[len('rhodecode_'):]
778 779 sett = SettingsModel().create_or_update_setting(
779 780 setting_name, form_result[setting.key], setting.type)
780 781 session.add(sett)
781 782
782 783 except Exception:
783 784 log.exception('Exception while updating lab settings')
784 785 h.flash(_('Error occurred during updating labs settings'),
785 786 category='error')
786 787 else:
787 788 Session().commit()
788 789 SettingsModel().invalidate_settings_cache()
789 790 h.flash(_('Updated Labs settings'), category='success')
790 791 return redirect(url('admin_settings_labs'))
791 792
792 793 return htmlfill.render(
793 794 render('admin/settings/settings.html'),
794 795 defaults=self._form_defaults(),
795 796 encoding='UTF-8',
796 797 force_defaults=False)
797 798
798 799 @HasPermissionAllDecorator('hg.admin')
799 800 def settings_labs(self):
800 801 """GET /admin/settings/labs: All items in the collection"""
801 802 # url('admin_settings_labs')
802 803 if not c.labs_active:
803 804 redirect(url('admin_settings'))
804 805
805 806 c.active = 'labs'
806 807 c.lab_settings = _LAB_SETTINGS
807 808
808 809 return htmlfill.render(
809 810 render('admin/settings/settings.html'),
810 811 defaults=self._form_defaults(),
811 812 encoding='UTF-8',
812 813 force_defaults=False)
813 814
814 815 def _form_defaults(self):
815 816 defaults = SettingsModel().get_all_settings()
816 817 defaults.update(self._get_hg_ui_settings())
817 818 defaults.update({
818 819 'new_svn_branch': '',
819 820 'new_svn_tag': '',
820 821 })
821 822 return defaults
822 823
823 824
824 825 # :param key: name of the setting including the 'rhodecode_' prefix
825 826 # :param type: the RhodeCodeSetting type to use.
826 827 # :param group: the i18ned group in which we should dispaly this setting
827 828 # :param label: the i18ned label we should display for this setting
828 829 # :param help: the i18ned help we should dispaly for this setting
829 830 LabSetting = collections.namedtuple(
830 831 'LabSetting', ('key', 'type', 'group', 'label', 'help'))
831 832
832 833
833 834 # This list has to be kept in sync with the form
834 835 # rhodecode.model.forms.LabsSettingsForm.
835 836 _LAB_SETTINGS = [
836 837
837 838 ]
@@ -1,41 +1,40 b''
1 1
2 2 <pre>
3 3 SYSTEM INFO
4 4 -----------
5 5
6 6 % for dt, dd, warn in c.data_items:
7 ${dt}${':' if dt else '---'}
8 ${dd}
7 ${dt.lower().replace(' ', '_')}${': '+dd if dt else '---'}
9 8 % if warn and warn['message']:
10 9 ALERT_${warn['type'].upper()} ${warn['message']}
11 10 % endif
12 11 % endfor
13 12
14 13 PYTHON PACKAGES
15 14 ---------------
16 15
17 16 % for key, value in c.py_modules['human_value']:
18 17 ${key}: ${value}
19 18 % endfor
20 19
21 20 SYSTEM SETTINGS
22 21 ---------------
23 22
24 23 % for key, value in sorted(c.rhodecode_config['human_value'].items()):
25 24 % if isinstance(value, dict):
26 25
27 26 % for key2, value2 in value.items():
28 27 [${key}]${key2}: ${value2}
29 28 % endfor
30 29
31 30 % else:
32 31 ${key}: ${value}
33 32 % endif
34 33 % endfor
35 34
36 35 </pre>
37 36
38 37
39 38
40 39
41 40
General Comments 0
You need to be logged in to leave comments. Login now