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