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