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