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