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