##// END OF EJS Templates
system-info: fetch default locale to the provided system info data.
marcink -
r2914:57425d44 default
parent child Browse files
Show More
@@ -1,200 +1,201 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2018 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 import logging
21 import logging
22 import urllib2
22 import urllib2
23
23
24 from pyramid.view import view_config
24 from pyramid.view import view_config
25
25
26 import rhodecode
26 import rhodecode
27 from rhodecode.apps._base import BaseAppView
27 from rhodecode.apps._base import BaseAppView
28 from rhodecode.apps.admin.navigation import navigation_list
28 from rhodecode.apps.admin.navigation import navigation_list
29 from rhodecode.lib import helpers as h
29 from rhodecode.lib import helpers as h
30 from rhodecode.lib.auth import (LoginRequired, HasPermissionAllDecorator)
30 from rhodecode.lib.auth import (LoginRequired, HasPermissionAllDecorator)
31 from rhodecode.lib.utils2 import str2bool
31 from rhodecode.lib.utils2 import str2bool
32 from rhodecode.lib import system_info
32 from rhodecode.lib import system_info
33 from rhodecode.model.update import UpdateModel
33 from rhodecode.model.update import UpdateModel
34
34
35 log = logging.getLogger(__name__)
35 log = logging.getLogger(__name__)
36
36
37
37
38 class AdminSystemInfoSettingsView(BaseAppView):
38 class AdminSystemInfoSettingsView(BaseAppView):
39 def load_default_context(self):
39 def load_default_context(self):
40 c = self._get_local_tmpl_context()
40 c = self._get_local_tmpl_context()
41 return c
41 return c
42
42
43 @LoginRequired()
43 @LoginRequired()
44 @HasPermissionAllDecorator('hg.admin')
44 @HasPermissionAllDecorator('hg.admin')
45 @view_config(
45 @view_config(
46 route_name='admin_settings_system', request_method='GET',
46 route_name='admin_settings_system', request_method='GET',
47 renderer='rhodecode:templates/admin/settings/settings.mako')
47 renderer='rhodecode:templates/admin/settings/settings.mako')
48 def settings_system_info(self):
48 def settings_system_info(self):
49 _ = self.request.translate
49 _ = self.request.translate
50 c = self.load_default_context()
50 c = self.load_default_context()
51
51
52 c.active = 'system'
52 c.active = 'system'
53 c.navlist = navigation_list(self.request)
53 c.navlist = navigation_list(self.request)
54
54
55 # TODO(marcink), figure out how to allow only selected users to do this
55 # TODO(marcink), figure out how to allow only selected users to do this
56 c.allowed_to_snapshot = self._rhodecode_user.admin
56 c.allowed_to_snapshot = self._rhodecode_user.admin
57
57
58 snapshot = str2bool(self.request.params.get('snapshot'))
58 snapshot = str2bool(self.request.params.get('snapshot'))
59
59
60 c.rhodecode_update_url = UpdateModel().get_update_url()
60 c.rhodecode_update_url = UpdateModel().get_update_url()
61 server_info = system_info.get_system_info(self.request.environ)
61 server_info = system_info.get_system_info(self.request.environ)
62
62
63 for key, val in server_info.items():
63 for key, val in server_info.items():
64 setattr(c, key, val)
64 setattr(c, key, val)
65
65
66 def val(name, subkey='human_value'):
66 def val(name, subkey='human_value'):
67 return server_info[name][subkey]
67 return server_info[name][subkey]
68
68
69 def state(name):
69 def state(name):
70 return server_info[name]['state']
70 return server_info[name]['state']
71
71
72 def val2(name):
72 def val2(name):
73 val = server_info[name]['human_value']
73 val = server_info[name]['human_value']
74 state = server_info[name]['state']
74 state = server_info[name]['state']
75 return val, state
75 return val, state
76
76
77 update_info_msg = _('Note: please make sure this server can '
77 update_info_msg = _('Note: please make sure this server can '
78 'access `${url}` for the update link to work',
78 'access `${url}` for the update link to work',
79 mapping=dict(url=c.rhodecode_update_url))
79 mapping=dict(url=c.rhodecode_update_url))
80 version = UpdateModel().get_stored_version()
80 version = UpdateModel().get_stored_version()
81 is_outdated = UpdateModel().is_outdated(
81 is_outdated = UpdateModel().is_outdated(
82 rhodecode.__version__, version)
82 rhodecode.__version__, version)
83 update_state = {
83 update_state = {
84 'type': 'warning',
84 'type': 'warning',
85 'message': 'New version available: {}'.format(version)
85 'message': 'New version available: {}'.format(version)
86 } \
86 } \
87 if is_outdated else {}
87 if is_outdated else {}
88 c.data_items = [
88 c.data_items = [
89 # update info
89 # update info
90 (_('Update info'), h.literal(
90 (_('Update info'), h.literal(
91 '<span class="link" id="check_for_update" >%s.</span>' % (
91 '<span class="link" id="check_for_update" >%s.</span>' % (
92 _('Check for updates')) +
92 _('Check for updates')) +
93 '<br/> <span >%s.</span>' % (update_info_msg)
93 '<br/> <span >%s.</span>' % (update_info_msg)
94 ), ''),
94 ), ''),
95
95
96 # RhodeCode specific
96 # RhodeCode specific
97 (_('RhodeCode Version'), val('rhodecode_app')['text'], state('rhodecode_app')),
97 (_('RhodeCode Version'), val('rhodecode_app')['text'], state('rhodecode_app')),
98 (_('Latest version'), version, update_state),
98 (_('Latest version'), version, update_state),
99 (_('RhodeCode Server IP'), val('server')['server_ip'], state('server')),
99 (_('RhodeCode Server IP'), val('server')['server_ip'], state('server')),
100 (_('RhodeCode Server ID'), val('server')['server_id'], state('server')),
100 (_('RhodeCode Server ID'), val('server')['server_id'], state('server')),
101 (_('RhodeCode Configuration'), val('rhodecode_config')['path'], state('rhodecode_config')),
101 (_('RhodeCode Configuration'), val('rhodecode_config')['path'], state('rhodecode_config')),
102 (_('RhodeCode Certificate'), val('rhodecode_config')['cert_path'], state('rhodecode_config')),
102 (_('RhodeCode Certificate'), val('rhodecode_config')['cert_path'], state('rhodecode_config')),
103 (_('Workers'), val('rhodecode_config')['config']['server:main'].get('workers', '?'), state('rhodecode_config')),
103 (_('Workers'), val('rhodecode_config')['config']['server:main'].get('workers', '?'), state('rhodecode_config')),
104 (_('Worker Type'), val('rhodecode_config')['config']['server:main'].get('worker_class', 'sync'), state('rhodecode_config')),
104 (_('Worker Type'), val('rhodecode_config')['config']['server:main'].get('worker_class', 'sync'), state('rhodecode_config')),
105 ('', '', ''), # spacer
105 ('', '', ''), # spacer
106
106
107 # Database
107 # Database
108 (_('Database'), val('database')['url'], state('database')),
108 (_('Database'), val('database')['url'], state('database')),
109 (_('Database version'), val('database')['version'], state('database')),
109 (_('Database version'), val('database')['version'], state('database')),
110 ('', '', ''), # spacer
110 ('', '', ''), # spacer
111
111
112 # Platform/Python
112 # Platform/Python
113 (_('Platform'), val('platform')['name'], state('platform')),
113 (_('Platform'), val('platform')['name'], state('platform')),
114 (_('Platform UUID'), val('platform')['uuid'], state('platform')),
114 (_('Platform UUID'), val('platform')['uuid'], state('platform')),
115 (_('Lang'), val('locale'), state('locale')),
115 (_('Python version'), val('python')['version'], state('python')),
116 (_('Python version'), val('python')['version'], state('python')),
116 (_('Python path'), val('python')['executable'], state('python')),
117 (_('Python path'), val('python')['executable'], state('python')),
117 ('', '', ''), # spacer
118 ('', '', ''), # spacer
118
119
119 # Systems stats
120 # Systems stats
120 (_('CPU'), val('cpu')['text'], state('cpu')),
121 (_('CPU'), val('cpu')['text'], state('cpu')),
121 (_('Load'), val('load')['text'], state('load')),
122 (_('Load'), val('load')['text'], state('load')),
122 (_('Memory'), val('memory')['text'], state('memory')),
123 (_('Memory'), val('memory')['text'], state('memory')),
123 (_('Uptime'), val('uptime')['text'], state('uptime')),
124 (_('Uptime'), val('uptime')['text'], state('uptime')),
124 ('', '', ''), # spacer
125 ('', '', ''), # spacer
125
126
126 # ulimit
127 # ulimit
127 (_('Ulimit'), val('ulimit')['text'], state('ulimit')),
128 (_('Ulimit'), val('ulimit')['text'], state('ulimit')),
128
129
129 # Repo storage
130 # Repo storage
130 (_('Storage location'), val('storage')['path'], state('storage')),
131 (_('Storage location'), val('storage')['path'], state('storage')),
131 (_('Storage info'), val('storage')['text'], state('storage')),
132 (_('Storage info'), val('storage')['text'], state('storage')),
132 (_('Storage inodes'), val('storage_inodes')['text'], state('storage_inodes')),
133 (_('Storage inodes'), val('storage_inodes')['text'], state('storage_inodes')),
133
134
134 (_('Gist storage location'), val('storage_gist')['path'], state('storage_gist')),
135 (_('Gist storage location'), val('storage_gist')['path'], state('storage_gist')),
135 (_('Gist storage info'), val('storage_gist')['text'], state('storage_gist')),
136 (_('Gist storage info'), val('storage_gist')['text'], state('storage_gist')),
136
137
137 (_('Archive cache storage location'), val('storage_archive')['path'], state('storage_archive')),
138 (_('Archive cache storage location'), val('storage_archive')['path'], state('storage_archive')),
138 (_('Archive cache info'), val('storage_archive')['text'], state('storage_archive')),
139 (_('Archive cache info'), val('storage_archive')['text'], state('storage_archive')),
139
140
140 (_('Temp storage location'), val('storage_temp')['path'], state('storage_temp')),
141 (_('Temp storage location'), val('storage_temp')['path'], state('storage_temp')),
141 (_('Temp storage info'), val('storage_temp')['text'], state('storage_temp')),
142 (_('Temp storage info'), val('storage_temp')['text'], state('storage_temp')),
142
143
143 (_('Search info'), val('search')['text'], state('search')),
144 (_('Search info'), val('search')['text'], state('search')),
144 (_('Search location'), val('search')['location'], state('search')),
145 (_('Search location'), val('search')['location'], state('search')),
145 ('', '', ''), # spacer
146 ('', '', ''), # spacer
146
147
147 # VCS specific
148 # VCS specific
148 (_('VCS Backends'), val('vcs_backends'), state('vcs_backends')),
149 (_('VCS Backends'), val('vcs_backends'), state('vcs_backends')),
149 (_('VCS Server'), val('vcs_server')['text'], state('vcs_server')),
150 (_('VCS Server'), val('vcs_server')['text'], state('vcs_server')),
150 (_('GIT'), val('git'), state('git')),
151 (_('GIT'), val('git'), state('git')),
151 (_('HG'), val('hg'), state('hg')),
152 (_('HG'), val('hg'), state('hg')),
152 (_('SVN'), val('svn'), state('svn')),
153 (_('SVN'), val('svn'), state('svn')),
153
154
154 ]
155 ]
155
156
156 if snapshot:
157 if snapshot:
157 if c.allowed_to_snapshot:
158 if c.allowed_to_snapshot:
158 c.data_items.pop(0) # remove server info
159 c.data_items.pop(0) # remove server info
159 self.request.override_renderer = 'admin/settings/settings_system_snapshot.mako'
160 self.request.override_renderer = 'admin/settings/settings_system_snapshot.mako'
160 else:
161 else:
161 h.flash('You are not allowed to do this', category='warning')
162 h.flash('You are not allowed to do this', category='warning')
162 return self._get_template_context(c)
163 return self._get_template_context(c)
163
164
164 @LoginRequired()
165 @LoginRequired()
165 @HasPermissionAllDecorator('hg.admin')
166 @HasPermissionAllDecorator('hg.admin')
166 @view_config(
167 @view_config(
167 route_name='admin_settings_system_update', request_method='GET',
168 route_name='admin_settings_system_update', request_method='GET',
168 renderer='rhodecode:templates/admin/settings/settings_system_update.mako')
169 renderer='rhodecode:templates/admin/settings/settings_system_update.mako')
169 def settings_system_info_check_update(self):
170 def settings_system_info_check_update(self):
170 _ = self.request.translate
171 _ = self.request.translate
171 c = self.load_default_context()
172 c = self.load_default_context()
172
173
173 update_url = UpdateModel().get_update_url()
174 update_url = UpdateModel().get_update_url()
174
175
175 _err = lambda s: '<div style="color:#ff8888; padding:4px 0px">{}</div>'.format(s)
176 _err = lambda s: '<div style="color:#ff8888; padding:4px 0px">{}</div>'.format(s)
176 try:
177 try:
177 data = UpdateModel().get_update_data(update_url)
178 data = UpdateModel().get_update_data(update_url)
178 except urllib2.URLError as e:
179 except urllib2.URLError as e:
179 log.exception("Exception contacting upgrade server")
180 log.exception("Exception contacting upgrade server")
180 self.request.override_renderer = 'string'
181 self.request.override_renderer = 'string'
181 return _err('Failed to contact upgrade server: %r' % e)
182 return _err('Failed to contact upgrade server: %r' % e)
182 except ValueError as e:
183 except ValueError as e:
183 log.exception("Bad data sent from update server")
184 log.exception("Bad data sent from update server")
184 self.request.override_renderer = 'string'
185 self.request.override_renderer = 'string'
185 return _err('Bad data sent from update server')
186 return _err('Bad data sent from update server')
186
187
187 latest = data['versions'][0]
188 latest = data['versions'][0]
188
189
189 c.update_url = update_url
190 c.update_url = update_url
190 c.latest_data = latest
191 c.latest_data = latest
191 c.latest_ver = latest['version']
192 c.latest_ver = latest['version']
192 c.cur_ver = rhodecode.__version__
193 c.cur_ver = rhodecode.__version__
193 c.should_upgrade = False
194 c.should_upgrade = False
194
195
195 is_oudated = UpdateModel().is_outdated(c.cur_ver, c.latest_ver)
196 is_oudated = UpdateModel().is_outdated(c.cur_ver, c.latest_ver)
196 if is_oudated:
197 if is_oudated:
197 c.should_upgrade = True
198 c.should_upgrade = True
198 c.important_notices = latest['general']
199 c.important_notices = latest['general']
199 UpdateModel().store_version(latest['version'])
200 UpdateModel().store_version(latest['version'])
200 return self._get_template_context(c)
201 return self._get_template_context(c)
@@ -1,748 +1,763 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2018 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 import os
22 import os
23 import sys
23 import sys
24 import time
24 import time
25 import platform
25 import platform
26 import collections
26 import collections
27 import pkg_resources
27 import pkg_resources
28 import logging
28 import logging
29 import resource
29 import resource
30
30
31 from pyramid.compat import configparser
31 from pyramid.compat import configparser
32
32
33 log = logging.getLogger(__name__)
33 log = logging.getLogger(__name__)
34
34
35
35
36 psutil = None
36 psutil = None
37
37
38 try:
38 try:
39 # cygwin cannot have yet psutil support.
39 # cygwin cannot have yet psutil support.
40 import psutil as psutil
40 import psutil as psutil
41 except ImportError:
41 except ImportError:
42 pass
42 pass
43
43
44
44
45 _NA = 'NOT AVAILABLE'
45 _NA = 'NOT AVAILABLE'
46
46
47 STATE_OK = 'ok'
47 STATE_OK = 'ok'
48 STATE_ERR = 'error'
48 STATE_ERR = 'error'
49 STATE_WARN = 'warning'
49 STATE_WARN = 'warning'
50
50
51 STATE_OK_DEFAULT = {'message': '', 'type': STATE_OK}
51 STATE_OK_DEFAULT = {'message': '', 'type': STATE_OK}
52
52
53
53
54 # HELPERS
54 # HELPERS
55 def percentage(part, whole):
55 def percentage(part, whole):
56 whole = float(whole)
56 whole = float(whole)
57 if whole > 0:
57 if whole > 0:
58 return round(100 * float(part) / whole, 1)
58 return round(100 * float(part) / whole, 1)
59 return 0.0
59 return 0.0
60
60
61
61
62 def get_storage_size(storage_path):
62 def get_storage_size(storage_path):
63 sizes = []
63 sizes = []
64 for file_ in os.listdir(storage_path):
64 for file_ in os.listdir(storage_path):
65 storage_file = os.path.join(storage_path, file_)
65 storage_file = os.path.join(storage_path, file_)
66 if os.path.isfile(storage_file):
66 if os.path.isfile(storage_file):
67 try:
67 try:
68 sizes.append(os.path.getsize(storage_file))
68 sizes.append(os.path.getsize(storage_file))
69 except OSError:
69 except OSError:
70 log.exception('Failed to get size of storage file %s',
70 log.exception('Failed to get size of storage file %s',
71 storage_file)
71 storage_file)
72 pass
72 pass
73
73
74 return sum(sizes)
74 return sum(sizes)
75
75
76
76
77 class SysInfoRes(object):
77 class SysInfoRes(object):
78 def __init__(self, value, state=STATE_OK_DEFAULT, human_value=None):
78 def __init__(self, value, state=STATE_OK_DEFAULT, human_value=None):
79 self.value = value
79 self.value = value
80 self.state = state
80 self.state = state
81 self.human_value = human_value or value
81 self.human_value = human_value or value
82
82
83 def __json__(self):
83 def __json__(self):
84 return {
84 return {
85 'value': self.value,
85 'value': self.value,
86 'state': self.state,
86 'state': self.state,
87 'human_value': self.human_value,
87 'human_value': self.human_value,
88 }
88 }
89
89
90 def get_value(self):
90 def get_value(self):
91 return self.__json__()
91 return self.__json__()
92
92
93 def __str__(self):
93 def __str__(self):
94 return '<SysInfoRes({})>'.format(self.__json__())
94 return '<SysInfoRes({})>'.format(self.__json__())
95
95
96
96
97 class SysInfo(object):
97 class SysInfo(object):
98
98
99 def __init__(self, func_name, **kwargs):
99 def __init__(self, func_name, **kwargs):
100 self.func_name = func_name
100 self.func_name = func_name
101 self.value = _NA
101 self.value = _NA
102 self.state = None
102 self.state = None
103 self.kwargs = kwargs or {}
103 self.kwargs = kwargs or {}
104
104
105 def __call__(self):
105 def __call__(self):
106 computed = self.compute(**self.kwargs)
106 computed = self.compute(**self.kwargs)
107 if not isinstance(computed, SysInfoRes):
107 if not isinstance(computed, SysInfoRes):
108 raise ValueError(
108 raise ValueError(
109 'computed value for {} is not instance of '
109 'computed value for {} is not instance of '
110 '{}, got {} instead'.format(
110 '{}, got {} instead'.format(
111 self.func_name, SysInfoRes, type(computed)))
111 self.func_name, SysInfoRes, type(computed)))
112 return computed.__json__()
112 return computed.__json__()
113
113
114 def __str__(self):
114 def __str__(self):
115 return '<SysInfo({})>'.format(self.func_name)
115 return '<SysInfo({})>'.format(self.func_name)
116
116
117 def compute(self, **kwargs):
117 def compute(self, **kwargs):
118 return self.func_name(**kwargs)
118 return self.func_name(**kwargs)
119
119
120
120
121 # SysInfo functions
121 # SysInfo functions
122 def python_info():
122 def python_info():
123 value = dict(version=' '.join(platform._sys_version()),
123 value = dict(version=' '.join(platform._sys_version()),
124 executable=sys.executable)
124 executable=sys.executable)
125 return SysInfoRes(value=value)
125 return SysInfoRes(value=value)
126
126
127
127
128 def py_modules():
128 def py_modules():
129 mods = dict([(p.project_name, p.version)
129 mods = dict([(p.project_name, p.version)
130 for p in pkg_resources.working_set])
130 for p in pkg_resources.working_set])
131 value = sorted(mods.items(), key=lambda k: k[0].lower())
131 value = sorted(mods.items(), key=lambda k: k[0].lower())
132 return SysInfoRes(value=value)
132 return SysInfoRes(value=value)
133
133
134
134
135 def platform_type():
135 def platform_type():
136 from rhodecode.lib.utils import safe_unicode, generate_platform_uuid
136 from rhodecode.lib.utils import safe_unicode, generate_platform_uuid
137
137
138 value = dict(
138 value = dict(
139 name=safe_unicode(platform.platform()),
139 name=safe_unicode(platform.platform()),
140 uuid=generate_platform_uuid()
140 uuid=generate_platform_uuid()
141 )
141 )
142 return SysInfoRes(value=value)
142 return SysInfoRes(value=value)
143
143
144
144
145 def locale_info():
146 import locale
147
148 value = dict(
149 locale_default=locale.getdefaultlocale(),
150 locale_lc_all=locale.getlocale(locale.LC_ALL),
151 lang_env=os.environ.get('LANG'),
152 lc_all_env=os.environ.get('LC_ALL'),
153 local_archive_env=os.environ.get('LOCALE_ARCHIVE'),
154 )
155 human_value = 'LANG: {}, locale LC_ALL: {}, Default locales: {}'.format(
156 value['lang_env'], value['locale_lc_all'], value['locale_default'])
157 return SysInfoRes(value=value, human_value=human_value)
158
159
145 def ulimit_info():
160 def ulimit_info():
146 data = collections.OrderedDict([
161 data = collections.OrderedDict([
147 ('cpu time (seconds)', resource.getrlimit(resource.RLIMIT_CPU)),
162 ('cpu time (seconds)', resource.getrlimit(resource.RLIMIT_CPU)),
148 ('file size', resource.getrlimit(resource.RLIMIT_FSIZE)),
163 ('file size', resource.getrlimit(resource.RLIMIT_FSIZE)),
149 ('stack size', resource.getrlimit(resource.RLIMIT_STACK)),
164 ('stack size', resource.getrlimit(resource.RLIMIT_STACK)),
150 ('core file size', resource.getrlimit(resource.RLIMIT_CORE)),
165 ('core file size', resource.getrlimit(resource.RLIMIT_CORE)),
151 ('address space size', resource.getrlimit(resource.RLIMIT_AS)),
166 ('address space size', resource.getrlimit(resource.RLIMIT_AS)),
152 ('locked in mem size', resource.getrlimit(resource.RLIMIT_MEMLOCK)),
167 ('locked in mem size', resource.getrlimit(resource.RLIMIT_MEMLOCK)),
153 ('heap size', resource.getrlimit(resource.RLIMIT_DATA)),
168 ('heap size', resource.getrlimit(resource.RLIMIT_DATA)),
154 ('rss size', resource.getrlimit(resource.RLIMIT_RSS)),
169 ('rss size', resource.getrlimit(resource.RLIMIT_RSS)),
155 ('number of processes', resource.getrlimit(resource.RLIMIT_NPROC)),
170 ('number of processes', resource.getrlimit(resource.RLIMIT_NPROC)),
156 ('open files', resource.getrlimit(resource.RLIMIT_NOFILE)),
171 ('open files', resource.getrlimit(resource.RLIMIT_NOFILE)),
157 ])
172 ])
158
173
159 text = ', '.join('{}:{}'.format(k,v) for k,v in data.items())
174 text = ', '.join('{}:{}'.format(k,v) for k,v in data.items())
160
175
161 value = {
176 value = {
162 'limits': data,
177 'limits': data,
163 'text': text,
178 'text': text,
164 }
179 }
165 return SysInfoRes(value=value)
180 return SysInfoRes(value=value)
166
181
167
182
168 def uptime():
183 def uptime():
169 from rhodecode.lib.helpers import age, time_to_datetime
184 from rhodecode.lib.helpers import age, time_to_datetime
170 from rhodecode.translation import TranslationString
185 from rhodecode.translation import TranslationString
171
186
172 value = dict(boot_time=0, uptime=0, text='')
187 value = dict(boot_time=0, uptime=0, text='')
173 state = STATE_OK_DEFAULT
188 state = STATE_OK_DEFAULT
174 if not psutil:
189 if not psutil:
175 return SysInfoRes(value=value, state=state)
190 return SysInfoRes(value=value, state=state)
176
191
177 boot_time = psutil.boot_time()
192 boot_time = psutil.boot_time()
178 value['boot_time'] = boot_time
193 value['boot_time'] = boot_time
179 value['uptime'] = time.time() - boot_time
194 value['uptime'] = time.time() - boot_time
180
195
181 date_or_age = age(time_to_datetime(boot_time))
196 date_or_age = age(time_to_datetime(boot_time))
182 if isinstance(date_or_age, TranslationString):
197 if isinstance(date_or_age, TranslationString):
183 date_or_age = date_or_age.interpolate()
198 date_or_age = date_or_age.interpolate()
184
199
185 human_value = value.copy()
200 human_value = value.copy()
186 human_value['boot_time'] = time_to_datetime(boot_time)
201 human_value['boot_time'] = time_to_datetime(boot_time)
187 human_value['uptime'] = age(time_to_datetime(boot_time), show_suffix=False)
202 human_value['uptime'] = age(time_to_datetime(boot_time), show_suffix=False)
188
203
189 human_value['text'] = u'Server started {}'.format(date_or_age)
204 human_value['text'] = u'Server started {}'.format(date_or_age)
190 return SysInfoRes(value=value, human_value=human_value)
205 return SysInfoRes(value=value, human_value=human_value)
191
206
192
207
193 def memory():
208 def memory():
194 from rhodecode.lib.helpers import format_byte_size_binary
209 from rhodecode.lib.helpers import format_byte_size_binary
195 value = dict(available=0, used=0, used_real=0, cached=0, percent=0,
210 value = dict(available=0, used=0, used_real=0, cached=0, percent=0,
196 percent_used=0, free=0, inactive=0, active=0, shared=0,
211 percent_used=0, free=0, inactive=0, active=0, shared=0,
197 total=0, buffers=0, text='')
212 total=0, buffers=0, text='')
198
213
199 state = STATE_OK_DEFAULT
214 state = STATE_OK_DEFAULT
200 if not psutil:
215 if not psutil:
201 return SysInfoRes(value=value, state=state)
216 return SysInfoRes(value=value, state=state)
202
217
203 value.update(dict(psutil.virtual_memory()._asdict()))
218 value.update(dict(psutil.virtual_memory()._asdict()))
204 value['used_real'] = value['total'] - value['available']
219 value['used_real'] = value['total'] - value['available']
205 value['percent_used'] = psutil._common.usage_percent(
220 value['percent_used'] = psutil._common.usage_percent(
206 value['used_real'], value['total'], 1)
221 value['used_real'], value['total'], 1)
207
222
208 human_value = value.copy()
223 human_value = value.copy()
209 human_value['text'] = '%s/%s, %s%% used' % (
224 human_value['text'] = '%s/%s, %s%% used' % (
210 format_byte_size_binary(value['used_real']),
225 format_byte_size_binary(value['used_real']),
211 format_byte_size_binary(value['total']),
226 format_byte_size_binary(value['total']),
212 value['percent_used'],)
227 value['percent_used'],)
213
228
214 keys = value.keys()[::]
229 keys = value.keys()[::]
215 keys.pop(keys.index('percent'))
230 keys.pop(keys.index('percent'))
216 keys.pop(keys.index('percent_used'))
231 keys.pop(keys.index('percent_used'))
217 keys.pop(keys.index('text'))
232 keys.pop(keys.index('text'))
218 for k in keys:
233 for k in keys:
219 human_value[k] = format_byte_size_binary(value[k])
234 human_value[k] = format_byte_size_binary(value[k])
220
235
221 if state['type'] == STATE_OK and value['percent_used'] > 90:
236 if state['type'] == STATE_OK and value['percent_used'] > 90:
222 msg = 'Critical: your available RAM memory is very low.'
237 msg = 'Critical: your available RAM memory is very low.'
223 state = {'message': msg, 'type': STATE_ERR}
238 state = {'message': msg, 'type': STATE_ERR}
224
239
225 elif state['type'] == STATE_OK and value['percent_used'] > 70:
240 elif state['type'] == STATE_OK and value['percent_used'] > 70:
226 msg = 'Warning: your available RAM memory is running low.'
241 msg = 'Warning: your available RAM memory is running low.'
227 state = {'message': msg, 'type': STATE_WARN}
242 state = {'message': msg, 'type': STATE_WARN}
228
243
229 return SysInfoRes(value=value, state=state, human_value=human_value)
244 return SysInfoRes(value=value, state=state, human_value=human_value)
230
245
231
246
232 def machine_load():
247 def machine_load():
233 value = {'1_min': _NA, '5_min': _NA, '15_min': _NA, 'text': ''}
248 value = {'1_min': _NA, '5_min': _NA, '15_min': _NA, 'text': ''}
234 state = STATE_OK_DEFAULT
249 state = STATE_OK_DEFAULT
235 if not psutil:
250 if not psutil:
236 return SysInfoRes(value=value, state=state)
251 return SysInfoRes(value=value, state=state)
237
252
238 # load averages
253 # load averages
239 if hasattr(psutil.os, 'getloadavg'):
254 if hasattr(psutil.os, 'getloadavg'):
240 value.update(dict(
255 value.update(dict(
241 zip(['1_min', '5_min', '15_min'], psutil.os.getloadavg())))
256 zip(['1_min', '5_min', '15_min'], psutil.os.getloadavg())))
242
257
243 human_value = value.copy()
258 human_value = value.copy()
244 human_value['text'] = '1min: {}, 5min: {}, 15min: {}'.format(
259 human_value['text'] = '1min: {}, 5min: {}, 15min: {}'.format(
245 value['1_min'], value['5_min'], value['15_min'])
260 value['1_min'], value['5_min'], value['15_min'])
246
261
247 if state['type'] == STATE_OK and value['15_min'] > 5:
262 if state['type'] == STATE_OK and value['15_min'] > 5:
248 msg = 'Warning: your machine load is very high.'
263 msg = 'Warning: your machine load is very high.'
249 state = {'message': msg, 'type': STATE_WARN}
264 state = {'message': msg, 'type': STATE_WARN}
250
265
251 return SysInfoRes(value=value, state=state, human_value=human_value)
266 return SysInfoRes(value=value, state=state, human_value=human_value)
252
267
253
268
254 def cpu():
269 def cpu():
255 value = {'cpu': 0, 'cpu_count': 0, 'cpu_usage': []}
270 value = {'cpu': 0, 'cpu_count': 0, 'cpu_usage': []}
256 state = STATE_OK_DEFAULT
271 state = STATE_OK_DEFAULT
257
272
258 if not psutil:
273 if not psutil:
259 return SysInfoRes(value=value, state=state)
274 return SysInfoRes(value=value, state=state)
260
275
261 value['cpu'] = psutil.cpu_percent(0.5)
276 value['cpu'] = psutil.cpu_percent(0.5)
262 value['cpu_usage'] = psutil.cpu_percent(0.5, percpu=True)
277 value['cpu_usage'] = psutil.cpu_percent(0.5, percpu=True)
263 value['cpu_count'] = psutil.cpu_count()
278 value['cpu_count'] = psutil.cpu_count()
264
279
265 human_value = value.copy()
280 human_value = value.copy()
266 human_value['text'] = '{} cores at {} %'.format(
281 human_value['text'] = '{} cores at {} %'.format(
267 value['cpu_count'], value['cpu'])
282 value['cpu_count'], value['cpu'])
268
283
269 return SysInfoRes(value=value, state=state, human_value=human_value)
284 return SysInfoRes(value=value, state=state, human_value=human_value)
270
285
271
286
272 def storage():
287 def storage():
273 from rhodecode.lib.helpers import format_byte_size_binary
288 from rhodecode.lib.helpers import format_byte_size_binary
274 from rhodecode.model.settings import VcsSettingsModel
289 from rhodecode.model.settings import VcsSettingsModel
275 path = VcsSettingsModel().get_repos_location()
290 path = VcsSettingsModel().get_repos_location()
276
291
277 value = dict(percent=0, used=0, total=0, path=path, text='')
292 value = dict(percent=0, used=0, total=0, path=path, text='')
278 state = STATE_OK_DEFAULT
293 state = STATE_OK_DEFAULT
279 if not psutil:
294 if not psutil:
280 return SysInfoRes(value=value, state=state)
295 return SysInfoRes(value=value, state=state)
281
296
282 try:
297 try:
283 value.update(dict(psutil.disk_usage(path)._asdict()))
298 value.update(dict(psutil.disk_usage(path)._asdict()))
284 except Exception as e:
299 except Exception as e:
285 log.exception('Failed to fetch disk info')
300 log.exception('Failed to fetch disk info')
286 state = {'message': str(e), 'type': STATE_ERR}
301 state = {'message': str(e), 'type': STATE_ERR}
287
302
288 human_value = value.copy()
303 human_value = value.copy()
289 human_value['used'] = format_byte_size_binary(value['used'])
304 human_value['used'] = format_byte_size_binary(value['used'])
290 human_value['total'] = format_byte_size_binary(value['total'])
305 human_value['total'] = format_byte_size_binary(value['total'])
291 human_value['text'] = "{}/{}, {}% used".format(
306 human_value['text'] = "{}/{}, {}% used".format(
292 format_byte_size_binary(value['used']),
307 format_byte_size_binary(value['used']),
293 format_byte_size_binary(value['total']),
308 format_byte_size_binary(value['total']),
294 value['percent'])
309 value['percent'])
295
310
296 if state['type'] == STATE_OK and value['percent'] > 90:
311 if state['type'] == STATE_OK and value['percent'] > 90:
297 msg = 'Critical: your disk space is very low.'
312 msg = 'Critical: your disk space is very low.'
298 state = {'message': msg, 'type': STATE_ERR}
313 state = {'message': msg, 'type': STATE_ERR}
299
314
300 elif state['type'] == STATE_OK and value['percent'] > 70:
315 elif state['type'] == STATE_OK and value['percent'] > 70:
301 msg = 'Warning: your disk space is running low.'
316 msg = 'Warning: your disk space is running low.'
302 state = {'message': msg, 'type': STATE_WARN}
317 state = {'message': msg, 'type': STATE_WARN}
303
318
304 return SysInfoRes(value=value, state=state, human_value=human_value)
319 return SysInfoRes(value=value, state=state, human_value=human_value)
305
320
306
321
307 def storage_inodes():
322 def storage_inodes():
308 from rhodecode.model.settings import VcsSettingsModel
323 from rhodecode.model.settings import VcsSettingsModel
309 path = VcsSettingsModel().get_repos_location()
324 path = VcsSettingsModel().get_repos_location()
310
325
311 value = dict(percent=0, free=0, used=0, total=0, path=path, text='')
326 value = dict(percent=0, free=0, used=0, total=0, path=path, text='')
312 state = STATE_OK_DEFAULT
327 state = STATE_OK_DEFAULT
313 if not psutil:
328 if not psutil:
314 return SysInfoRes(value=value, state=state)
329 return SysInfoRes(value=value, state=state)
315
330
316 try:
331 try:
317 i_stat = os.statvfs(path)
332 i_stat = os.statvfs(path)
318 value['free'] = i_stat.f_ffree
333 value['free'] = i_stat.f_ffree
319 value['used'] = i_stat.f_files-i_stat.f_favail
334 value['used'] = i_stat.f_files-i_stat.f_favail
320 value['total'] = i_stat.f_files
335 value['total'] = i_stat.f_files
321 value['percent'] = percentage(value['used'], value['total'])
336 value['percent'] = percentage(value['used'], value['total'])
322 except Exception as e:
337 except Exception as e:
323 log.exception('Failed to fetch disk inodes info')
338 log.exception('Failed to fetch disk inodes info')
324 state = {'message': str(e), 'type': STATE_ERR}
339 state = {'message': str(e), 'type': STATE_ERR}
325
340
326 human_value = value.copy()
341 human_value = value.copy()
327 human_value['text'] = "{}/{}, {}% used".format(
342 human_value['text'] = "{}/{}, {}% used".format(
328 value['used'], value['total'], value['percent'])
343 value['used'], value['total'], value['percent'])
329
344
330 if state['type'] == STATE_OK and value['percent'] > 90:
345 if state['type'] == STATE_OK and value['percent'] > 90:
331 msg = 'Critical: your disk free inodes are very low.'
346 msg = 'Critical: your disk free inodes are very low.'
332 state = {'message': msg, 'type': STATE_ERR}
347 state = {'message': msg, 'type': STATE_ERR}
333
348
334 elif state['type'] == STATE_OK and value['percent'] > 70:
349 elif state['type'] == STATE_OK and value['percent'] > 70:
335 msg = 'Warning: your disk free inodes are running low.'
350 msg = 'Warning: your disk free inodes are running low.'
336 state = {'message': msg, 'type': STATE_WARN}
351 state = {'message': msg, 'type': STATE_WARN}
337
352
338 return SysInfoRes(value=value, state=state, human_value=human_value)
353 return SysInfoRes(value=value, state=state, human_value=human_value)
339
354
340
355
341 def storage_archives():
356 def storage_archives():
342 import rhodecode
357 import rhodecode
343 from rhodecode.lib.utils import safe_str
358 from rhodecode.lib.utils import safe_str
344 from rhodecode.lib.helpers import format_byte_size_binary
359 from rhodecode.lib.helpers import format_byte_size_binary
345
360
346 msg = 'Enable this by setting ' \
361 msg = 'Enable this by setting ' \
347 'archive_cache_dir=/path/to/cache option in the .ini file'
362 'archive_cache_dir=/path/to/cache option in the .ini file'
348 path = safe_str(rhodecode.CONFIG.get('archive_cache_dir', msg))
363 path = safe_str(rhodecode.CONFIG.get('archive_cache_dir', msg))
349
364
350 value = dict(percent=0, used=0, total=0, items=0, path=path, text='')
365 value = dict(percent=0, used=0, total=0, items=0, path=path, text='')
351 state = STATE_OK_DEFAULT
366 state = STATE_OK_DEFAULT
352 try:
367 try:
353 items_count = 0
368 items_count = 0
354 used = 0
369 used = 0
355 for root, dirs, files in os.walk(path):
370 for root, dirs, files in os.walk(path):
356 if root == path:
371 if root == path:
357 items_count = len(files)
372 items_count = len(files)
358
373
359 for f in files:
374 for f in files:
360 try:
375 try:
361 used += os.path.getsize(os.path.join(root, f))
376 used += os.path.getsize(os.path.join(root, f))
362 except OSError:
377 except OSError:
363 pass
378 pass
364 value.update({
379 value.update({
365 'percent': 100,
380 'percent': 100,
366 'used': used,
381 'used': used,
367 'total': used,
382 'total': used,
368 'items': items_count
383 'items': items_count
369 })
384 })
370
385
371 except Exception as e:
386 except Exception as e:
372 log.exception('failed to fetch archive cache storage')
387 log.exception('failed to fetch archive cache storage')
373 state = {'message': str(e), 'type': STATE_ERR}
388 state = {'message': str(e), 'type': STATE_ERR}
374
389
375 human_value = value.copy()
390 human_value = value.copy()
376 human_value['used'] = format_byte_size_binary(value['used'])
391 human_value['used'] = format_byte_size_binary(value['used'])
377 human_value['total'] = format_byte_size_binary(value['total'])
392 human_value['total'] = format_byte_size_binary(value['total'])
378 human_value['text'] = "{} ({} items)".format(
393 human_value['text'] = "{} ({} items)".format(
379 human_value['used'], value['items'])
394 human_value['used'], value['items'])
380
395
381 return SysInfoRes(value=value, state=state, human_value=human_value)
396 return SysInfoRes(value=value, state=state, human_value=human_value)
382
397
383
398
384 def storage_gist():
399 def storage_gist():
385 from rhodecode.model.gist import GIST_STORE_LOC
400 from rhodecode.model.gist import GIST_STORE_LOC
386 from rhodecode.model.settings import VcsSettingsModel
401 from rhodecode.model.settings import VcsSettingsModel
387 from rhodecode.lib.utils import safe_str
402 from rhodecode.lib.utils import safe_str
388 from rhodecode.lib.helpers import format_byte_size_binary
403 from rhodecode.lib.helpers import format_byte_size_binary
389 path = safe_str(os.path.join(
404 path = safe_str(os.path.join(
390 VcsSettingsModel().get_repos_location(), GIST_STORE_LOC))
405 VcsSettingsModel().get_repos_location(), GIST_STORE_LOC))
391
406
392 # gist storage
407 # gist storage
393 value = dict(percent=0, used=0, total=0, items=0, path=path, text='')
408 value = dict(percent=0, used=0, total=0, items=0, path=path, text='')
394 state = STATE_OK_DEFAULT
409 state = STATE_OK_DEFAULT
395
410
396 try:
411 try:
397 items_count = 0
412 items_count = 0
398 used = 0
413 used = 0
399 for root, dirs, files in os.walk(path):
414 for root, dirs, files in os.walk(path):
400 if root == path:
415 if root == path:
401 items_count = len(dirs)
416 items_count = len(dirs)
402
417
403 for f in files:
418 for f in files:
404 try:
419 try:
405 used += os.path.getsize(os.path.join(root, f))
420 used += os.path.getsize(os.path.join(root, f))
406 except OSError:
421 except OSError:
407 pass
422 pass
408 value.update({
423 value.update({
409 'percent': 100,
424 'percent': 100,
410 'used': used,
425 'used': used,
411 'total': used,
426 'total': used,
412 'items': items_count
427 'items': items_count
413 })
428 })
414 except Exception as e:
429 except Exception as e:
415 log.exception('failed to fetch gist storage items')
430 log.exception('failed to fetch gist storage items')
416 state = {'message': str(e), 'type': STATE_ERR}
431 state = {'message': str(e), 'type': STATE_ERR}
417
432
418 human_value = value.copy()
433 human_value = value.copy()
419 human_value['used'] = format_byte_size_binary(value['used'])
434 human_value['used'] = format_byte_size_binary(value['used'])
420 human_value['total'] = format_byte_size_binary(value['total'])
435 human_value['total'] = format_byte_size_binary(value['total'])
421 human_value['text'] = "{} ({} items)".format(
436 human_value['text'] = "{} ({} items)".format(
422 human_value['used'], value['items'])
437 human_value['used'], value['items'])
423
438
424 return SysInfoRes(value=value, state=state, human_value=human_value)
439 return SysInfoRes(value=value, state=state, human_value=human_value)
425
440
426
441
427 def storage_temp():
442 def storage_temp():
428 import tempfile
443 import tempfile
429 from rhodecode.lib.helpers import format_byte_size_binary
444 from rhodecode.lib.helpers import format_byte_size_binary
430
445
431 path = tempfile.gettempdir()
446 path = tempfile.gettempdir()
432 value = dict(percent=0, used=0, total=0, items=0, path=path, text='')
447 value = dict(percent=0, used=0, total=0, items=0, path=path, text='')
433 state = STATE_OK_DEFAULT
448 state = STATE_OK_DEFAULT
434
449
435 if not psutil:
450 if not psutil:
436 return SysInfoRes(value=value, state=state)
451 return SysInfoRes(value=value, state=state)
437
452
438 try:
453 try:
439 value.update(dict(psutil.disk_usage(path)._asdict()))
454 value.update(dict(psutil.disk_usage(path)._asdict()))
440 except Exception as e:
455 except Exception as e:
441 log.exception('Failed to fetch temp dir info')
456 log.exception('Failed to fetch temp dir info')
442 state = {'message': str(e), 'type': STATE_ERR}
457 state = {'message': str(e), 'type': STATE_ERR}
443
458
444 human_value = value.copy()
459 human_value = value.copy()
445 human_value['used'] = format_byte_size_binary(value['used'])
460 human_value['used'] = format_byte_size_binary(value['used'])
446 human_value['total'] = format_byte_size_binary(value['total'])
461 human_value['total'] = format_byte_size_binary(value['total'])
447 human_value['text'] = "{}/{}, {}% used".format(
462 human_value['text'] = "{}/{}, {}% used".format(
448 format_byte_size_binary(value['used']),
463 format_byte_size_binary(value['used']),
449 format_byte_size_binary(value['total']),
464 format_byte_size_binary(value['total']),
450 value['percent'])
465 value['percent'])
451
466
452 return SysInfoRes(value=value, state=state, human_value=human_value)
467 return SysInfoRes(value=value, state=state, human_value=human_value)
453
468
454
469
455 def search_info():
470 def search_info():
456 import rhodecode
471 import rhodecode
457 from rhodecode.lib.index import searcher_from_config
472 from rhodecode.lib.index import searcher_from_config
458
473
459 backend = rhodecode.CONFIG.get('search.module', '')
474 backend = rhodecode.CONFIG.get('search.module', '')
460 location = rhodecode.CONFIG.get('search.location', '')
475 location = rhodecode.CONFIG.get('search.location', '')
461
476
462 try:
477 try:
463 searcher = searcher_from_config(rhodecode.CONFIG)
478 searcher = searcher_from_config(rhodecode.CONFIG)
464 searcher = searcher.__class__.__name__
479 searcher = searcher.__class__.__name__
465 except Exception:
480 except Exception:
466 searcher = None
481 searcher = None
467
482
468 value = dict(
483 value = dict(
469 backend=backend, searcher=searcher, location=location, text='')
484 backend=backend, searcher=searcher, location=location, text='')
470 state = STATE_OK_DEFAULT
485 state = STATE_OK_DEFAULT
471
486
472 human_value = value.copy()
487 human_value = value.copy()
473 human_value['text'] = "backend:`{}`".format(human_value['backend'])
488 human_value['text'] = "backend:`{}`".format(human_value['backend'])
474
489
475 return SysInfoRes(value=value, state=state, human_value=human_value)
490 return SysInfoRes(value=value, state=state, human_value=human_value)
476
491
477
492
478 def git_info():
493 def git_info():
479 from rhodecode.lib.vcs.backends import git
494 from rhodecode.lib.vcs.backends import git
480 state = STATE_OK_DEFAULT
495 state = STATE_OK_DEFAULT
481 value = human_value = ''
496 value = human_value = ''
482 try:
497 try:
483 value = git.discover_git_version(raise_on_exc=True)
498 value = git.discover_git_version(raise_on_exc=True)
484 human_value = 'version reported from VCSServer: {}'.format(value)
499 human_value = 'version reported from VCSServer: {}'.format(value)
485 except Exception as e:
500 except Exception as e:
486 state = {'message': str(e), 'type': STATE_ERR}
501 state = {'message': str(e), 'type': STATE_ERR}
487
502
488 return SysInfoRes(value=value, state=state, human_value=human_value)
503 return SysInfoRes(value=value, state=state, human_value=human_value)
489
504
490
505
491 def hg_info():
506 def hg_info():
492 from rhodecode.lib.vcs.backends import hg
507 from rhodecode.lib.vcs.backends import hg
493 state = STATE_OK_DEFAULT
508 state = STATE_OK_DEFAULT
494 value = human_value = ''
509 value = human_value = ''
495 try:
510 try:
496 value = hg.discover_hg_version(raise_on_exc=True)
511 value = hg.discover_hg_version(raise_on_exc=True)
497 human_value = 'version reported from VCSServer: {}'.format(value)
512 human_value = 'version reported from VCSServer: {}'.format(value)
498 except Exception as e:
513 except Exception as e:
499 state = {'message': str(e), 'type': STATE_ERR}
514 state = {'message': str(e), 'type': STATE_ERR}
500 return SysInfoRes(value=value, state=state, human_value=human_value)
515 return SysInfoRes(value=value, state=state, human_value=human_value)
501
516
502
517
503 def svn_info():
518 def svn_info():
504 from rhodecode.lib.vcs.backends import svn
519 from rhodecode.lib.vcs.backends import svn
505 state = STATE_OK_DEFAULT
520 state = STATE_OK_DEFAULT
506 value = human_value = ''
521 value = human_value = ''
507 try:
522 try:
508 value = svn.discover_svn_version(raise_on_exc=True)
523 value = svn.discover_svn_version(raise_on_exc=True)
509 human_value = 'version reported from VCSServer: {}'.format(value)
524 human_value = 'version reported from VCSServer: {}'.format(value)
510 except Exception as e:
525 except Exception as e:
511 state = {'message': str(e), 'type': STATE_ERR}
526 state = {'message': str(e), 'type': STATE_ERR}
512 return SysInfoRes(value=value, state=state, human_value=human_value)
527 return SysInfoRes(value=value, state=state, human_value=human_value)
513
528
514
529
515 def vcs_backends():
530 def vcs_backends():
516 import rhodecode
531 import rhodecode
517 value = rhodecode.CONFIG.get('vcs.backends')
532 value = rhodecode.CONFIG.get('vcs.backends')
518 human_value = 'Enabled backends in order: {}'.format(','.join(value))
533 human_value = 'Enabled backends in order: {}'.format(','.join(value))
519 return SysInfoRes(value=value, human_value=human_value)
534 return SysInfoRes(value=value, human_value=human_value)
520
535
521
536
522 def vcs_server():
537 def vcs_server():
523 import rhodecode
538 import rhodecode
524 from rhodecode.lib.vcs.backends import get_vcsserver_service_data
539 from rhodecode.lib.vcs.backends import get_vcsserver_service_data
525
540
526 server_url = rhodecode.CONFIG.get('vcs.server')
541 server_url = rhodecode.CONFIG.get('vcs.server')
527 enabled = rhodecode.CONFIG.get('vcs.server.enable')
542 enabled = rhodecode.CONFIG.get('vcs.server.enable')
528 protocol = rhodecode.CONFIG.get('vcs.server.protocol') or 'http'
543 protocol = rhodecode.CONFIG.get('vcs.server.protocol') or 'http'
529 state = STATE_OK_DEFAULT
544 state = STATE_OK_DEFAULT
530 version = None
545 version = None
531 workers = 0
546 workers = 0
532
547
533 try:
548 try:
534 data = get_vcsserver_service_data()
549 data = get_vcsserver_service_data()
535 if data and 'version' in data:
550 if data and 'version' in data:
536 version = data['version']
551 version = data['version']
537
552
538 if data and 'config' in data:
553 if data and 'config' in data:
539 conf = data['config']
554 conf = data['config']
540 workers = conf.get('workers', 'NOT AVAILABLE')
555 workers = conf.get('workers', 'NOT AVAILABLE')
541
556
542 connection = 'connected'
557 connection = 'connected'
543 except Exception as e:
558 except Exception as e:
544 connection = 'failed'
559 connection = 'failed'
545 state = {'message': str(e), 'type': STATE_ERR}
560 state = {'message': str(e), 'type': STATE_ERR}
546
561
547 value = dict(
562 value = dict(
548 url=server_url,
563 url=server_url,
549 enabled=enabled,
564 enabled=enabled,
550 protocol=protocol,
565 protocol=protocol,
551 connection=connection,
566 connection=connection,
552 version=version,
567 version=version,
553 text='',
568 text='',
554 )
569 )
555
570
556 human_value = value.copy()
571 human_value = value.copy()
557 human_value['text'] = \
572 human_value['text'] = \
558 '{url}@ver:{ver} via {mode} mode[workers:{workers}], connection:{conn}'.format(
573 '{url}@ver:{ver} via {mode} mode[workers:{workers}], connection:{conn}'.format(
559 url=server_url, ver=version, workers=workers, mode=protocol,
574 url=server_url, ver=version, workers=workers, mode=protocol,
560 conn=connection)
575 conn=connection)
561
576
562 return SysInfoRes(value=value, state=state, human_value=human_value)
577 return SysInfoRes(value=value, state=state, human_value=human_value)
563
578
564
579
565 def rhodecode_app_info():
580 def rhodecode_app_info():
566 import rhodecode
581 import rhodecode
567 edition = rhodecode.CONFIG.get('rhodecode.edition')
582 edition = rhodecode.CONFIG.get('rhodecode.edition')
568
583
569 value = dict(
584 value = dict(
570 rhodecode_version=rhodecode.__version__,
585 rhodecode_version=rhodecode.__version__,
571 rhodecode_lib_path=os.path.abspath(rhodecode.__file__),
586 rhodecode_lib_path=os.path.abspath(rhodecode.__file__),
572 text=''
587 text=''
573 )
588 )
574 human_value = value.copy()
589 human_value = value.copy()
575 human_value['text'] = 'RhodeCode {edition}, version {ver}'.format(
590 human_value['text'] = 'RhodeCode {edition}, version {ver}'.format(
576 edition=edition, ver=value['rhodecode_version']
591 edition=edition, ver=value['rhodecode_version']
577 )
592 )
578 return SysInfoRes(value=value, human_value=human_value)
593 return SysInfoRes(value=value, human_value=human_value)
579
594
580
595
581 def rhodecode_config():
596 def rhodecode_config():
582 import rhodecode
597 import rhodecode
583 path = rhodecode.CONFIG.get('__file__')
598 path = rhodecode.CONFIG.get('__file__')
584 rhodecode_ini_safe = rhodecode.CONFIG.copy()
599 rhodecode_ini_safe = rhodecode.CONFIG.copy()
585
600
586 try:
601 try:
587 config = configparser.ConfigParser()
602 config = configparser.ConfigParser()
588 config.read(path)
603 config.read(path)
589 parsed_ini = config
604 parsed_ini = config
590 if parsed_ini.has_section('server:main'):
605 if parsed_ini.has_section('server:main'):
591 parsed_ini = dict(parsed_ini.items('server:main'))
606 parsed_ini = dict(parsed_ini.items('server:main'))
592 except Exception:
607 except Exception:
593 log.exception('Failed to read .ini file for display')
608 log.exception('Failed to read .ini file for display')
594 parsed_ini = {}
609 parsed_ini = {}
595
610
596 cert_path = os.path.join(
611 cert_path = os.path.join(
597 os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(path)))),
612 os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(path)))),
598 '.rccontrol-profile/etc/ca-bundle.crt')
613 '.rccontrol-profile/etc/ca-bundle.crt')
599
614
600 rhodecode_ini_safe['server:main'] = parsed_ini
615 rhodecode_ini_safe['server:main'] = parsed_ini
601
616
602 blacklist = [
617 blacklist = [
603 'rhodecode_license_key',
618 'rhodecode_license_key',
604 'routes.map',
619 'routes.map',
605 'sqlalchemy.db1.url',
620 'sqlalchemy.db1.url',
606 'channelstream.secret',
621 'channelstream.secret',
607 'beaker.session.secret',
622 'beaker.session.secret',
608 'rhodecode.encrypted_values.secret',
623 'rhodecode.encrypted_values.secret',
609 'rhodecode_auth_github_consumer_key',
624 'rhodecode_auth_github_consumer_key',
610 'rhodecode_auth_github_consumer_secret',
625 'rhodecode_auth_github_consumer_secret',
611 'rhodecode_auth_google_consumer_key',
626 'rhodecode_auth_google_consumer_key',
612 'rhodecode_auth_google_consumer_secret',
627 'rhodecode_auth_google_consumer_secret',
613 'rhodecode_auth_bitbucket_consumer_secret',
628 'rhodecode_auth_bitbucket_consumer_secret',
614 'rhodecode_auth_bitbucket_consumer_key',
629 'rhodecode_auth_bitbucket_consumer_key',
615 'rhodecode_auth_twitter_consumer_secret',
630 'rhodecode_auth_twitter_consumer_secret',
616 'rhodecode_auth_twitter_consumer_key',
631 'rhodecode_auth_twitter_consumer_key',
617
632
618 'rhodecode_auth_twitter_secret',
633 'rhodecode_auth_twitter_secret',
619 'rhodecode_auth_github_secret',
634 'rhodecode_auth_github_secret',
620 'rhodecode_auth_google_secret',
635 'rhodecode_auth_google_secret',
621 'rhodecode_auth_bitbucket_secret',
636 'rhodecode_auth_bitbucket_secret',
622
637
623 'appenlight.api_key',
638 'appenlight.api_key',
624 ('app_conf', 'sqlalchemy.db1.url')
639 ('app_conf', 'sqlalchemy.db1.url')
625 ]
640 ]
626 for k in blacklist:
641 for k in blacklist:
627 if isinstance(k, tuple):
642 if isinstance(k, tuple):
628 section, key = k
643 section, key = k
629 if section in rhodecode_ini_safe:
644 if section in rhodecode_ini_safe:
630 rhodecode_ini_safe[section] = '**OBFUSCATED**'
645 rhodecode_ini_safe[section] = '**OBFUSCATED**'
631 else:
646 else:
632 rhodecode_ini_safe.pop(k, None)
647 rhodecode_ini_safe.pop(k, None)
633
648
634 # TODO: maybe put some CONFIG checks here ?
649 # TODO: maybe put some CONFIG checks here ?
635 return SysInfoRes(value={'config': rhodecode_ini_safe,
650 return SysInfoRes(value={'config': rhodecode_ini_safe,
636 'path': path, 'cert_path': cert_path})
651 'path': path, 'cert_path': cert_path})
637
652
638
653
639 def database_info():
654 def database_info():
640 import rhodecode
655 import rhodecode
641 from sqlalchemy.engine import url as engine_url
656 from sqlalchemy.engine import url as engine_url
642 from rhodecode.model.meta import Base as sql_base, Session
657 from rhodecode.model.meta import Base as sql_base, Session
643 from rhodecode.model.db import DbMigrateVersion
658 from rhodecode.model.db import DbMigrateVersion
644
659
645 state = STATE_OK_DEFAULT
660 state = STATE_OK_DEFAULT
646
661
647 db_migrate = DbMigrateVersion.query().filter(
662 db_migrate = DbMigrateVersion.query().filter(
648 DbMigrateVersion.repository_id == 'rhodecode_db_migrations').one()
663 DbMigrateVersion.repository_id == 'rhodecode_db_migrations').one()
649
664
650 db_url_obj = engine_url.make_url(rhodecode.CONFIG['sqlalchemy.db1.url'])
665 db_url_obj = engine_url.make_url(rhodecode.CONFIG['sqlalchemy.db1.url'])
651
666
652 try:
667 try:
653 engine = sql_base.metadata.bind
668 engine = sql_base.metadata.bind
654 db_server_info = engine.dialect._get_server_version_info(
669 db_server_info = engine.dialect._get_server_version_info(
655 Session.connection(bind=engine))
670 Session.connection(bind=engine))
656 db_version = '.'.join(map(str, db_server_info))
671 db_version = '.'.join(map(str, db_server_info))
657 except Exception:
672 except Exception:
658 log.exception('failed to fetch db version')
673 log.exception('failed to fetch db version')
659 db_version = 'UNKNOWN'
674 db_version = 'UNKNOWN'
660
675
661 db_info = dict(
676 db_info = dict(
662 migrate_version=db_migrate.version,
677 migrate_version=db_migrate.version,
663 type=db_url_obj.get_backend_name(),
678 type=db_url_obj.get_backend_name(),
664 version=db_version,
679 version=db_version,
665 url=repr(db_url_obj)
680 url=repr(db_url_obj)
666 )
681 )
667 current_version = db_migrate.version
682 current_version = db_migrate.version
668 expected_version = rhodecode.__dbversion__
683 expected_version = rhodecode.__dbversion__
669 if state['type'] == STATE_OK and current_version != expected_version:
684 if state['type'] == STATE_OK and current_version != expected_version:
670 msg = 'Critical: database schema mismatch, ' \
685 msg = 'Critical: database schema mismatch, ' \
671 'expected version {}, got {}. ' \
686 'expected version {}, got {}. ' \
672 'Please run migrations on your database.'.format(
687 'Please run migrations on your database.'.format(
673 expected_version, current_version)
688 expected_version, current_version)
674 state = {'message': msg, 'type': STATE_ERR}
689 state = {'message': msg, 'type': STATE_ERR}
675
690
676 human_value = db_info.copy()
691 human_value = db_info.copy()
677 human_value['url'] = "{} @ migration version: {}".format(
692 human_value['url'] = "{} @ migration version: {}".format(
678 db_info['url'], db_info['migrate_version'])
693 db_info['url'], db_info['migrate_version'])
679 human_value['version'] = "{} {}".format(db_info['type'], db_info['version'])
694 human_value['version'] = "{} {}".format(db_info['type'], db_info['version'])
680 return SysInfoRes(value=db_info, state=state, human_value=human_value)
695 return SysInfoRes(value=db_info, state=state, human_value=human_value)
681
696
682
697
683 def server_info(environ):
698 def server_info(environ):
684 import rhodecode
699 import rhodecode
685 from rhodecode.lib.base import get_server_ip_addr, get_server_port
700 from rhodecode.lib.base import get_server_ip_addr, get_server_port
686
701
687 value = {
702 value = {
688 'server_ip': '%s:%s' % (
703 'server_ip': '%s:%s' % (
689 get_server_ip_addr(environ, log_errors=False),
704 get_server_ip_addr(environ, log_errors=False),
690 get_server_port(environ)
705 get_server_port(environ)
691 ),
706 ),
692 'server_id': rhodecode.CONFIG.get('instance_id'),
707 'server_id': rhodecode.CONFIG.get('instance_id'),
693 }
708 }
694 return SysInfoRes(value=value)
709 return SysInfoRes(value=value)
695
710
696
711
697 def usage_info():
712 def usage_info():
698 from rhodecode.model.db import User, Repository
713 from rhodecode.model.db import User, Repository
699 value = {
714 value = {
700 'users': User.query().count(),
715 'users': User.query().count(),
701 'users_active': User.query().filter(User.active == True).count(),
716 'users_active': User.query().filter(User.active == True).count(),
702 'repositories': Repository.query().count(),
717 'repositories': Repository.query().count(),
703 'repository_types': {
718 'repository_types': {
704 'hg': Repository.query().filter(
719 'hg': Repository.query().filter(
705 Repository.repo_type == 'hg').count(),
720 Repository.repo_type == 'hg').count(),
706 'git': Repository.query().filter(
721 'git': Repository.query().filter(
707 Repository.repo_type == 'git').count(),
722 Repository.repo_type == 'git').count(),
708 'svn': Repository.query().filter(
723 'svn': Repository.query().filter(
709 Repository.repo_type == 'svn').count(),
724 Repository.repo_type == 'svn').count(),
710 },
725 },
711 }
726 }
712 return SysInfoRes(value=value)
727 return SysInfoRes(value=value)
713
728
714
729
715
716 def get_system_info(environ):
730 def get_system_info(environ):
717 environ = environ or {}
731 environ = environ or {}
718 return {
732 return {
719 'rhodecode_app': SysInfo(rhodecode_app_info)(),
733 'rhodecode_app': SysInfo(rhodecode_app_info)(),
720 'rhodecode_config': SysInfo(rhodecode_config)(),
734 'rhodecode_config': SysInfo(rhodecode_config)(),
721 'rhodecode_usage': SysInfo(usage_info)(),
735 'rhodecode_usage': SysInfo(usage_info)(),
722 'python': SysInfo(python_info)(),
736 'python': SysInfo(python_info)(),
723 'py_modules': SysInfo(py_modules)(),
737 'py_modules': SysInfo(py_modules)(),
724
738
725 'platform': SysInfo(platform_type)(),
739 'platform': SysInfo(platform_type)(),
740 'locale': SysInfo(locale_info)(),
726 'server': SysInfo(server_info, environ=environ)(),
741 'server': SysInfo(server_info, environ=environ)(),
727 'database': SysInfo(database_info)(),
742 'database': SysInfo(database_info)(),
728 'ulimit': SysInfo(ulimit_info)(),
743 'ulimit': SysInfo(ulimit_info)(),
729 'storage': SysInfo(storage)(),
744 'storage': SysInfo(storage)(),
730 'storage_inodes': SysInfo(storage_inodes)(),
745 'storage_inodes': SysInfo(storage_inodes)(),
731 'storage_archive': SysInfo(storage_archives)(),
746 'storage_archive': SysInfo(storage_archives)(),
732 'storage_gist': SysInfo(storage_gist)(),
747 'storage_gist': SysInfo(storage_gist)(),
733 'storage_temp': SysInfo(storage_temp)(),
748 'storage_temp': SysInfo(storage_temp)(),
734
749
735 'search': SysInfo(search_info)(),
750 'search': SysInfo(search_info)(),
736
751
737 'uptime': SysInfo(uptime)(),
752 'uptime': SysInfo(uptime)(),
738 'load': SysInfo(machine_load)(),
753 'load': SysInfo(machine_load)(),
739 'cpu': SysInfo(cpu)(),
754 'cpu': SysInfo(cpu)(),
740 'memory': SysInfo(memory)(),
755 'memory': SysInfo(memory)(),
741
756
742 'vcs_backends': SysInfo(vcs_backends)(),
757 'vcs_backends': SysInfo(vcs_backends)(),
743 'vcs_server': SysInfo(vcs_server)(),
758 'vcs_server': SysInfo(vcs_server)(),
744
759
745 'git': SysInfo(git_info)(),
760 'git': SysInfo(git_info)(),
746 'hg': SysInfo(hg_info)(),
761 'hg': SysInfo(hg_info)(),
747 'svn': SysInfo(svn_info)(),
762 'svn': SysInfo(svn_info)(),
748 }
763 }
General Comments 0
You need to be logged in to leave comments. Login now