##// END OF EJS Templates
system-info: added missing license header.
marcink -
r1552:8033e1d3 default
parent child Browse files
Show More
@@ -1,693 +1,714 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2017-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
1 import os
22 import os
2 import sys
23 import sys
3 import time
24 import time
4 import platform
25 import platform
5 import pkg_resources
26 import pkg_resources
6 import logging
27 import logging
7 import string
28 import string
8
29
9
30
10 log = logging.getLogger(__name__)
31 log = logging.getLogger(__name__)
11
32
12
33
13 psutil = None
34 psutil = None
14
35
15 try:
36 try:
16 # cygwin cannot have yet psutil support.
37 # cygwin cannot have yet psutil support.
17 import psutil as psutil
38 import psutil as psutil
18 except ImportError:
39 except ImportError:
19 pass
40 pass
20
41
21
42
22 _NA = 'NOT AVAILABLE'
43 _NA = 'NOT AVAILABLE'
23
44
24 STATE_OK = 'ok'
45 STATE_OK = 'ok'
25 STATE_ERR = 'error'
46 STATE_ERR = 'error'
26 STATE_WARN = 'warning'
47 STATE_WARN = 'warning'
27
48
28 STATE_OK_DEFAULT = {'message': '', 'type': STATE_OK}
49 STATE_OK_DEFAULT = {'message': '', 'type': STATE_OK}
29
50
30
51
31 # HELPERS
52 # HELPERS
32 def percentage(part, whole):
53 def percentage(part, whole):
33 whole = float(whole)
54 whole = float(whole)
34 if whole > 0:
55 if whole > 0:
35 return round(100 * float(part) / whole, 1)
56 return round(100 * float(part) / whole, 1)
36 return 0.0
57 return 0.0
37
58
38
59
39 def get_storage_size(storage_path):
60 def get_storage_size(storage_path):
40 sizes = []
61 sizes = []
41 for file_ in os.listdir(storage_path):
62 for file_ in os.listdir(storage_path):
42 storage_file = os.path.join(storage_path, file_)
63 storage_file = os.path.join(storage_path, file_)
43 if os.path.isfile(storage_file):
64 if os.path.isfile(storage_file):
44 try:
65 try:
45 sizes.append(os.path.getsize(storage_file))
66 sizes.append(os.path.getsize(storage_file))
46 except OSError:
67 except OSError:
47 log.exception('Failed to get size of storage file %s',
68 log.exception('Failed to get size of storage file %s',
48 storage_file)
69 storage_file)
49 pass
70 pass
50
71
51 return sum(sizes)
72 return sum(sizes)
52
73
53
74
54 class SysInfoRes(object):
75 class SysInfoRes(object):
55 def __init__(self, value, state=STATE_OK_DEFAULT, human_value=None):
76 def __init__(self, value, state=STATE_OK_DEFAULT, human_value=None):
56 self.value = value
77 self.value = value
57 self.state = state
78 self.state = state
58 self.human_value = human_value or value
79 self.human_value = human_value or value
59
80
60 def __json__(self):
81 def __json__(self):
61 return {
82 return {
62 'value': self.value,
83 'value': self.value,
63 'state': self.state,
84 'state': self.state,
64 'human_value': self.human_value,
85 'human_value': self.human_value,
65 }
86 }
66
87
67 def get_value(self):
88 def get_value(self):
68 return self.__json__()
89 return self.__json__()
69
90
70 def __str__(self):
91 def __str__(self):
71 return '<SysInfoRes({})>'.format(self.__json__())
92 return '<SysInfoRes({})>'.format(self.__json__())
72
93
73
94
74 class SysInfo(object):
95 class SysInfo(object):
75
96
76 def __init__(self, func_name, **kwargs):
97 def __init__(self, func_name, **kwargs):
77 self.func_name = func_name
98 self.func_name = func_name
78 self.value = _NA
99 self.value = _NA
79 self.state = None
100 self.state = None
80 self.kwargs = kwargs or {}
101 self.kwargs = kwargs or {}
81
102
82 def __call__(self):
103 def __call__(self):
83 computed = self.compute(**self.kwargs)
104 computed = self.compute(**self.kwargs)
84 if not isinstance(computed, SysInfoRes):
105 if not isinstance(computed, SysInfoRes):
85 raise ValueError(
106 raise ValueError(
86 'computed value for {} is not instance of '
107 'computed value for {} is not instance of '
87 '{}, got {} instead'.format(
108 '{}, got {} instead'.format(
88 self.func_name, SysInfoRes, type(computed)))
109 self.func_name, SysInfoRes, type(computed)))
89 return computed.__json__()
110 return computed.__json__()
90
111
91 def __str__(self):
112 def __str__(self):
92 return '<SysInfo({})>'.format(self.func_name)
113 return '<SysInfo({})>'.format(self.func_name)
93
114
94 def compute(self, **kwargs):
115 def compute(self, **kwargs):
95 return self.func_name(**kwargs)
116 return self.func_name(**kwargs)
96
117
97
118
98 # SysInfo functions
119 # SysInfo functions
99 def python_info():
120 def python_info():
100 value = dict(version=' '.join(platform._sys_version()),
121 value = dict(version=' '.join(platform._sys_version()),
101 executable=sys.executable)
122 executable=sys.executable)
102 return SysInfoRes(value=value)
123 return SysInfoRes(value=value)
103
124
104
125
105 def py_modules():
126 def py_modules():
106 mods = dict([(p.project_name, p.version)
127 mods = dict([(p.project_name, p.version)
107 for p in pkg_resources.working_set])
128 for p in pkg_resources.working_set])
108 value = sorted(mods.items(), key=lambda k: k[0].lower())
129 value = sorted(mods.items(), key=lambda k: k[0].lower())
109 return SysInfoRes(value=value)
130 return SysInfoRes(value=value)
110
131
111
132
112 def platform_type():
133 def platform_type():
113 from rhodecode.lib.utils import safe_unicode, generate_platform_uuid
134 from rhodecode.lib.utils import safe_unicode, generate_platform_uuid
114
135
115 value = dict(
136 value = dict(
116 name=safe_unicode(platform.platform()),
137 name=safe_unicode(platform.platform()),
117 uuid=generate_platform_uuid()
138 uuid=generate_platform_uuid()
118 )
139 )
119 return SysInfoRes(value=value)
140 return SysInfoRes(value=value)
120
141
121
142
122 def uptime():
143 def uptime():
123 from rhodecode.lib.helpers import age, time_to_datetime
144 from rhodecode.lib.helpers import age, time_to_datetime
124 from rhodecode.translation import TranslationString
145 from rhodecode.translation import TranslationString
125
146
126 value = dict(boot_time=0, uptime=0, text='')
147 value = dict(boot_time=0, uptime=0, text='')
127 state = STATE_OK_DEFAULT
148 state = STATE_OK_DEFAULT
128 if not psutil:
149 if not psutil:
129 return SysInfoRes(value=value, state=state)
150 return SysInfoRes(value=value, state=state)
130
151
131 boot_time = psutil.boot_time()
152 boot_time = psutil.boot_time()
132 value['boot_time'] = boot_time
153 value['boot_time'] = boot_time
133 value['uptime'] = time.time() - boot_time
154 value['uptime'] = time.time() - boot_time
134
155
135 date_or_age = age(time_to_datetime(boot_time))
156 date_or_age = age(time_to_datetime(boot_time))
136 if isinstance(date_or_age, TranslationString):
157 if isinstance(date_or_age, TranslationString):
137 date_or_age = date_or_age.interpolate()
158 date_or_age = date_or_age.interpolate()
138
159
139 human_value = value.copy()
160 human_value = value.copy()
140 human_value['boot_time'] = time_to_datetime(boot_time)
161 human_value['boot_time'] = time_to_datetime(boot_time)
141 human_value['uptime'] = age(time_to_datetime(boot_time), show_suffix=False)
162 human_value['uptime'] = age(time_to_datetime(boot_time), show_suffix=False)
142
163
143 human_value['text'] = u'Server started {}'.format(date_or_age)
164 human_value['text'] = u'Server started {}'.format(date_or_age)
144 return SysInfoRes(value=value, human_value=human_value)
165 return SysInfoRes(value=value, human_value=human_value)
145
166
146
167
147 def memory():
168 def memory():
148 from rhodecode.lib.helpers import format_byte_size_binary
169 from rhodecode.lib.helpers import format_byte_size_binary
149 value = dict(available=0, used=0, used_real=0, cached=0, percent=0,
170 value = dict(available=0, used=0, used_real=0, cached=0, percent=0,
150 percent_used=0, free=0, inactive=0, active=0, shared=0,
171 percent_used=0, free=0, inactive=0, active=0, shared=0,
151 total=0, buffers=0, text='')
172 total=0, buffers=0, text='')
152
173
153 state = STATE_OK_DEFAULT
174 state = STATE_OK_DEFAULT
154 if not psutil:
175 if not psutil:
155 return SysInfoRes(value=value, state=state)
176 return SysInfoRes(value=value, state=state)
156
177
157 value.update(dict(psutil.virtual_memory()._asdict()))
178 value.update(dict(psutil.virtual_memory()._asdict()))
158 value['used_real'] = value['total'] - value['available']
179 value['used_real'] = value['total'] - value['available']
159 value['percent_used'] = psutil._common.usage_percent(
180 value['percent_used'] = psutil._common.usage_percent(
160 value['used_real'], value['total'], 1)
181 value['used_real'], value['total'], 1)
161
182
162 human_value = value.copy()
183 human_value = value.copy()
163 human_value['text'] = '%s/%s, %s%% used' % (
184 human_value['text'] = '%s/%s, %s%% used' % (
164 format_byte_size_binary(value['used_real']),
185 format_byte_size_binary(value['used_real']),
165 format_byte_size_binary(value['total']),
186 format_byte_size_binary(value['total']),
166 value['percent_used'],)
187 value['percent_used'],)
167
188
168 keys = value.keys()[::]
189 keys = value.keys()[::]
169 keys.pop(keys.index('percent'))
190 keys.pop(keys.index('percent'))
170 keys.pop(keys.index('percent_used'))
191 keys.pop(keys.index('percent_used'))
171 keys.pop(keys.index('text'))
192 keys.pop(keys.index('text'))
172 for k in keys:
193 for k in keys:
173 human_value[k] = format_byte_size_binary(value[k])
194 human_value[k] = format_byte_size_binary(value[k])
174
195
175 if state['type'] == STATE_OK and value['percent_used'] > 90:
196 if state['type'] == STATE_OK and value['percent_used'] > 90:
176 msg = 'Critical: your available RAM memory is very low.'
197 msg = 'Critical: your available RAM memory is very low.'
177 state = {'message': msg, 'type': STATE_ERR}
198 state = {'message': msg, 'type': STATE_ERR}
178
199
179 elif state['type'] == STATE_OK and value['percent_used'] > 70:
200 elif state['type'] == STATE_OK and value['percent_used'] > 70:
180 msg = 'Warning: your available RAM memory is running low.'
201 msg = 'Warning: your available RAM memory is running low.'
181 state = {'message': msg, 'type': STATE_WARN}
202 state = {'message': msg, 'type': STATE_WARN}
182
203
183 return SysInfoRes(value=value, state=state, human_value=human_value)
204 return SysInfoRes(value=value, state=state, human_value=human_value)
184
205
185
206
186 def machine_load():
207 def machine_load():
187 value = {'1_min': _NA, '5_min': _NA, '15_min': _NA, 'text': ''}
208 value = {'1_min': _NA, '5_min': _NA, '15_min': _NA, 'text': ''}
188 state = STATE_OK_DEFAULT
209 state = STATE_OK_DEFAULT
189 if not psutil:
210 if not psutil:
190 return SysInfoRes(value=value, state=state)
211 return SysInfoRes(value=value, state=state)
191
212
192 # load averages
213 # load averages
193 if hasattr(psutil.os, 'getloadavg'):
214 if hasattr(psutil.os, 'getloadavg'):
194 value.update(dict(
215 value.update(dict(
195 zip(['1_min', '5_min', '15_min'], psutil.os.getloadavg())))
216 zip(['1_min', '5_min', '15_min'], psutil.os.getloadavg())))
196
217
197 human_value = value.copy()
218 human_value = value.copy()
198 human_value['text'] = '1min: {}, 5min: {}, 15min: {}'.format(
219 human_value['text'] = '1min: {}, 5min: {}, 15min: {}'.format(
199 value['1_min'], value['5_min'], value['15_min'])
220 value['1_min'], value['5_min'], value['15_min'])
200
221
201 if state['type'] == STATE_OK and value['15_min'] > 5:
222 if state['type'] == STATE_OK and value['15_min'] > 5:
202 msg = 'Warning: your machine load is very high.'
223 msg = 'Warning: your machine load is very high.'
203 state = {'message': msg, 'type': STATE_WARN}
224 state = {'message': msg, 'type': STATE_WARN}
204
225
205 return SysInfoRes(value=value, state=state, human_value=human_value)
226 return SysInfoRes(value=value, state=state, human_value=human_value)
206
227
207
228
208 def cpu():
229 def cpu():
209 value = {'cpu': 0, 'cpu_count': 0, 'cpu_usage': []}
230 value = {'cpu': 0, 'cpu_count': 0, 'cpu_usage': []}
210 state = STATE_OK_DEFAULT
231 state = STATE_OK_DEFAULT
211
232
212 if not psutil:
233 if not psutil:
213 return SysInfoRes(value=value, state=state)
234 return SysInfoRes(value=value, state=state)
214
235
215 value['cpu'] = psutil.cpu_percent(0.5)
236 value['cpu'] = psutil.cpu_percent(0.5)
216 value['cpu_usage'] = psutil.cpu_percent(0.5, percpu=True)
237 value['cpu_usage'] = psutil.cpu_percent(0.5, percpu=True)
217 value['cpu_count'] = psutil.cpu_count()
238 value['cpu_count'] = psutil.cpu_count()
218
239
219 human_value = value.copy()
240 human_value = value.copy()
220 human_value['text'] = '{} cores at {} %'.format(
241 human_value['text'] = '{} cores at {} %'.format(
221 value['cpu_count'], value['cpu'])
242 value['cpu_count'], value['cpu'])
222
243
223 return SysInfoRes(value=value, state=state, human_value=human_value)
244 return SysInfoRes(value=value, state=state, human_value=human_value)
224
245
225
246
226 def storage():
247 def storage():
227 from rhodecode.lib.helpers import format_byte_size_binary
248 from rhodecode.lib.helpers import format_byte_size_binary
228 from rhodecode.model.settings import VcsSettingsModel
249 from rhodecode.model.settings import VcsSettingsModel
229 path = VcsSettingsModel().get_repos_location()
250 path = VcsSettingsModel().get_repos_location()
230
251
231 value = dict(percent=0, used=0, total=0, path=path, text='')
252 value = dict(percent=0, used=0, total=0, path=path, text='')
232 state = STATE_OK_DEFAULT
253 state = STATE_OK_DEFAULT
233 if not psutil:
254 if not psutil:
234 return SysInfoRes(value=value, state=state)
255 return SysInfoRes(value=value, state=state)
235
256
236 try:
257 try:
237 value.update(dict(psutil.disk_usage(path)._asdict()))
258 value.update(dict(psutil.disk_usage(path)._asdict()))
238 except Exception as e:
259 except Exception as e:
239 log.exception('Failed to fetch disk info')
260 log.exception('Failed to fetch disk info')
240 state = {'message': str(e), 'type': STATE_ERR}
261 state = {'message': str(e), 'type': STATE_ERR}
241
262
242 human_value = value.copy()
263 human_value = value.copy()
243 human_value['used'] = format_byte_size_binary(value['used'])
264 human_value['used'] = format_byte_size_binary(value['used'])
244 human_value['total'] = format_byte_size_binary(value['total'])
265 human_value['total'] = format_byte_size_binary(value['total'])
245 human_value['text'] = "{}/{}, {}% used".format(
266 human_value['text'] = "{}/{}, {}% used".format(
246 format_byte_size_binary(value['used']),
267 format_byte_size_binary(value['used']),
247 format_byte_size_binary(value['total']),
268 format_byte_size_binary(value['total']),
248 value['percent'])
269 value['percent'])
249
270
250 if state['type'] == STATE_OK and value['percent'] > 90:
271 if state['type'] == STATE_OK and value['percent'] > 90:
251 msg = 'Critical: your disk space is very low.'
272 msg = 'Critical: your disk space is very low.'
252 state = {'message': msg, 'type': STATE_ERR}
273 state = {'message': msg, 'type': STATE_ERR}
253
274
254 elif state['type'] == STATE_OK and value['percent'] > 70:
275 elif state['type'] == STATE_OK and value['percent'] > 70:
255 msg = 'Warning: your disk space is running low.'
276 msg = 'Warning: your disk space is running low.'
256 state = {'message': msg, 'type': STATE_WARN}
277 state = {'message': msg, 'type': STATE_WARN}
257
278
258 return SysInfoRes(value=value, state=state, human_value=human_value)
279 return SysInfoRes(value=value, state=state, human_value=human_value)
259
280
260
281
261 def storage_inodes():
282 def storage_inodes():
262 from rhodecode.model.settings import VcsSettingsModel
283 from rhodecode.model.settings import VcsSettingsModel
263 path = VcsSettingsModel().get_repos_location()
284 path = VcsSettingsModel().get_repos_location()
264
285
265 value = dict(percent=0, free=0, used=0, total=0, path=path, text='')
286 value = dict(percent=0, free=0, used=0, total=0, path=path, text='')
266 state = STATE_OK_DEFAULT
287 state = STATE_OK_DEFAULT
267 if not psutil:
288 if not psutil:
268 return SysInfoRes(value=value, state=state)
289 return SysInfoRes(value=value, state=state)
269
290
270 try:
291 try:
271 i_stat = os.statvfs(path)
292 i_stat = os.statvfs(path)
272 value['free'] = i_stat.f_ffree
293 value['free'] = i_stat.f_ffree
273 value['used'] = i_stat.f_files-i_stat.f_favail
294 value['used'] = i_stat.f_files-i_stat.f_favail
274 value['total'] = i_stat.f_files
295 value['total'] = i_stat.f_files
275 value['percent'] = percentage(value['used'], value['total'])
296 value['percent'] = percentage(value['used'], value['total'])
276 except Exception as e:
297 except Exception as e:
277 log.exception('Failed to fetch disk inodes info')
298 log.exception('Failed to fetch disk inodes info')
278 state = {'message': str(e), 'type': STATE_ERR}
299 state = {'message': str(e), 'type': STATE_ERR}
279
300
280 human_value = value.copy()
301 human_value = value.copy()
281 human_value['text'] = "{}/{}, {}% used".format(
302 human_value['text'] = "{}/{}, {}% used".format(
282 value['used'], value['total'], value['percent'])
303 value['used'], value['total'], value['percent'])
283
304
284 if state['type'] == STATE_OK and value['percent'] > 90:
305 if state['type'] == STATE_OK and value['percent'] > 90:
285 msg = 'Critical: your disk free inodes are very low.'
306 msg = 'Critical: your disk free inodes are very low.'
286 state = {'message': msg, 'type': STATE_ERR}
307 state = {'message': msg, 'type': STATE_ERR}
287
308
288 elif state['type'] == STATE_OK and value['percent'] > 70:
309 elif state['type'] == STATE_OK and value['percent'] > 70:
289 msg = 'Warning: your disk free inodes are running low.'
310 msg = 'Warning: your disk free inodes are running low.'
290 state = {'message': msg, 'type': STATE_WARN}
311 state = {'message': msg, 'type': STATE_WARN}
291
312
292 return SysInfoRes(value=value, state=state, human_value=human_value)
313 return SysInfoRes(value=value, state=state, human_value=human_value)
293
314
294
315
295 def storage_archives():
316 def storage_archives():
296 import rhodecode
317 import rhodecode
297 from rhodecode.lib.utils import safe_str
318 from rhodecode.lib.utils import safe_str
298 from rhodecode.lib.helpers import format_byte_size_binary
319 from rhodecode.lib.helpers import format_byte_size_binary
299
320
300 msg = 'Enable this by setting ' \
321 msg = 'Enable this by setting ' \
301 'archive_cache_dir=/path/to/cache option in the .ini file'
322 'archive_cache_dir=/path/to/cache option in the .ini file'
302 path = safe_str(rhodecode.CONFIG.get('archive_cache_dir', msg))
323 path = safe_str(rhodecode.CONFIG.get('archive_cache_dir', msg))
303
324
304 value = dict(percent=0, used=0, total=0, items=0, path=path, text='')
325 value = dict(percent=0, used=0, total=0, items=0, path=path, text='')
305 state = STATE_OK_DEFAULT
326 state = STATE_OK_DEFAULT
306 try:
327 try:
307 items_count = 0
328 items_count = 0
308 used = 0
329 used = 0
309 for root, dirs, files in os.walk(path):
330 for root, dirs, files in os.walk(path):
310 if root == path:
331 if root == path:
311 items_count = len(files)
332 items_count = len(files)
312
333
313 for f in files:
334 for f in files:
314 try:
335 try:
315 used += os.path.getsize(os.path.join(root, f))
336 used += os.path.getsize(os.path.join(root, f))
316 except OSError:
337 except OSError:
317 pass
338 pass
318 value.update({
339 value.update({
319 'percent': 100,
340 'percent': 100,
320 'used': used,
341 'used': used,
321 'total': used,
342 'total': used,
322 'items': items_count
343 'items': items_count
323 })
344 })
324
345
325 except Exception as e:
346 except Exception as e:
326 log.exception('failed to fetch archive cache storage')
347 log.exception('failed to fetch archive cache storage')
327 state = {'message': str(e), 'type': STATE_ERR}
348 state = {'message': str(e), 'type': STATE_ERR}
328
349
329 human_value = value.copy()
350 human_value = value.copy()
330 human_value['used'] = format_byte_size_binary(value['used'])
351 human_value['used'] = format_byte_size_binary(value['used'])
331 human_value['total'] = format_byte_size_binary(value['total'])
352 human_value['total'] = format_byte_size_binary(value['total'])
332 human_value['text'] = "{} ({} items)".format(
353 human_value['text'] = "{} ({} items)".format(
333 human_value['used'], value['items'])
354 human_value['used'], value['items'])
334
355
335 return SysInfoRes(value=value, state=state, human_value=human_value)
356 return SysInfoRes(value=value, state=state, human_value=human_value)
336
357
337
358
338 def storage_gist():
359 def storage_gist():
339 from rhodecode.model.gist import GIST_STORE_LOC
360 from rhodecode.model.gist import GIST_STORE_LOC
340 from rhodecode.model.settings import VcsSettingsModel
361 from rhodecode.model.settings import VcsSettingsModel
341 from rhodecode.lib.utils import safe_str
362 from rhodecode.lib.utils import safe_str
342 from rhodecode.lib.helpers import format_byte_size_binary
363 from rhodecode.lib.helpers import format_byte_size_binary
343 path = safe_str(os.path.join(
364 path = safe_str(os.path.join(
344 VcsSettingsModel().get_repos_location(), GIST_STORE_LOC))
365 VcsSettingsModel().get_repos_location(), GIST_STORE_LOC))
345
366
346 # gist storage
367 # gist storage
347 value = dict(percent=0, used=0, total=0, items=0, path=path, text='')
368 value = dict(percent=0, used=0, total=0, items=0, path=path, text='')
348 state = STATE_OK_DEFAULT
369 state = STATE_OK_DEFAULT
349
370
350 try:
371 try:
351 items_count = 0
372 items_count = 0
352 used = 0
373 used = 0
353 for root, dirs, files in os.walk(path):
374 for root, dirs, files in os.walk(path):
354 if root == path:
375 if root == path:
355 items_count = len(dirs)
376 items_count = len(dirs)
356
377
357 for f in files:
378 for f in files:
358 try:
379 try:
359 used += os.path.getsize(os.path.join(root, f))
380 used += os.path.getsize(os.path.join(root, f))
360 except OSError:
381 except OSError:
361 pass
382 pass
362 value.update({
383 value.update({
363 'percent': 100,
384 'percent': 100,
364 'used': used,
385 'used': used,
365 'total': used,
386 'total': used,
366 'items': items_count
387 'items': items_count
367 })
388 })
368 except Exception as e:
389 except Exception as e:
369 log.exception('failed to fetch gist storage items')
390 log.exception('failed to fetch gist storage items')
370 state = {'message': str(e), 'type': STATE_ERR}
391 state = {'message': str(e), 'type': STATE_ERR}
371
392
372 human_value = value.copy()
393 human_value = value.copy()
373 human_value['used'] = format_byte_size_binary(value['used'])
394 human_value['used'] = format_byte_size_binary(value['used'])
374 human_value['total'] = format_byte_size_binary(value['total'])
395 human_value['total'] = format_byte_size_binary(value['total'])
375 human_value['text'] = "{} ({} items)".format(
396 human_value['text'] = "{} ({} items)".format(
376 human_value['used'], value['items'])
397 human_value['used'], value['items'])
377
398
378 return SysInfoRes(value=value, state=state, human_value=human_value)
399 return SysInfoRes(value=value, state=state, human_value=human_value)
379
400
380
401
381 def storage_temp():
402 def storage_temp():
382 import tempfile
403 import tempfile
383 from rhodecode.lib.helpers import format_byte_size_binary
404 from rhodecode.lib.helpers import format_byte_size_binary
384
405
385 path = tempfile.gettempdir()
406 path = tempfile.gettempdir()
386 value = dict(percent=0, used=0, total=0, items=0, path=path, text='')
407 value = dict(percent=0, used=0, total=0, items=0, path=path, text='')
387 state = STATE_OK_DEFAULT
408 state = STATE_OK_DEFAULT
388
409
389 if not psutil:
410 if not psutil:
390 return SysInfoRes(value=value, state=state)
411 return SysInfoRes(value=value, state=state)
391
412
392 try:
413 try:
393 value.update(dict(psutil.disk_usage(path)._asdict()))
414 value.update(dict(psutil.disk_usage(path)._asdict()))
394 except Exception as e:
415 except Exception as e:
395 log.exception('Failed to fetch temp dir info')
416 log.exception('Failed to fetch temp dir info')
396 state = {'message': str(e), 'type': STATE_ERR}
417 state = {'message': str(e), 'type': STATE_ERR}
397
418
398 human_value = value.copy()
419 human_value = value.copy()
399 human_value['used'] = format_byte_size_binary(value['used'])
420 human_value['used'] = format_byte_size_binary(value['used'])
400 human_value['total'] = format_byte_size_binary(value['total'])
421 human_value['total'] = format_byte_size_binary(value['total'])
401 human_value['text'] = "{}/{}, {}% used".format(
422 human_value['text'] = "{}/{}, {}% used".format(
402 format_byte_size_binary(value['used']),
423 format_byte_size_binary(value['used']),
403 format_byte_size_binary(value['total']),
424 format_byte_size_binary(value['total']),
404 value['percent'])
425 value['percent'])
405
426
406 return SysInfoRes(value=value, state=state, human_value=human_value)
427 return SysInfoRes(value=value, state=state, human_value=human_value)
407
428
408
429
409 def search_info():
430 def search_info():
410 import rhodecode
431 import rhodecode
411 from rhodecode.lib.index import searcher_from_config
432 from rhodecode.lib.index import searcher_from_config
412
433
413 backend = rhodecode.CONFIG.get('search.module', '')
434 backend = rhodecode.CONFIG.get('search.module', '')
414 location = rhodecode.CONFIG.get('search.location', '')
435 location = rhodecode.CONFIG.get('search.location', '')
415
436
416 try:
437 try:
417 searcher = searcher_from_config(rhodecode.CONFIG)
438 searcher = searcher_from_config(rhodecode.CONFIG)
418 searcher = searcher.__class__.__name__
439 searcher = searcher.__class__.__name__
419 except Exception:
440 except Exception:
420 searcher = None
441 searcher = None
421
442
422 value = dict(
443 value = dict(
423 backend=backend, searcher=searcher, location=location, text='')
444 backend=backend, searcher=searcher, location=location, text='')
424 state = STATE_OK_DEFAULT
445 state = STATE_OK_DEFAULT
425
446
426 human_value = value.copy()
447 human_value = value.copy()
427 human_value['text'] = "backend:`{}`".format(human_value['backend'])
448 human_value['text'] = "backend:`{}`".format(human_value['backend'])
428
449
429 return SysInfoRes(value=value, state=state, human_value=human_value)
450 return SysInfoRes(value=value, state=state, human_value=human_value)
430
451
431
452
432 def git_info():
453 def git_info():
433 from rhodecode.lib.vcs.backends import git
454 from rhodecode.lib.vcs.backends import git
434 state = STATE_OK_DEFAULT
455 state = STATE_OK_DEFAULT
435 value = human_value = ''
456 value = human_value = ''
436 try:
457 try:
437 value = git.discover_git_version(raise_on_exc=True)
458 value = git.discover_git_version(raise_on_exc=True)
438 human_value = 'version reported from VCSServer: {}'.format(value)
459 human_value = 'version reported from VCSServer: {}'.format(value)
439 except Exception as e:
460 except Exception as e:
440 state = {'message': str(e), 'type': STATE_ERR}
461 state = {'message': str(e), 'type': STATE_ERR}
441
462
442 return SysInfoRes(value=value, state=state, human_value=human_value)
463 return SysInfoRes(value=value, state=state, human_value=human_value)
443
464
444
465
445 def hg_info():
466 def hg_info():
446 from rhodecode.lib.vcs.backends import hg
467 from rhodecode.lib.vcs.backends import hg
447 state = STATE_OK_DEFAULT
468 state = STATE_OK_DEFAULT
448 value = human_value = ''
469 value = human_value = ''
449 try:
470 try:
450 value = hg.discover_hg_version(raise_on_exc=True)
471 value = hg.discover_hg_version(raise_on_exc=True)
451 human_value = 'version reported from VCSServer: {}'.format(value)
472 human_value = 'version reported from VCSServer: {}'.format(value)
452 except Exception as e:
473 except Exception as e:
453 state = {'message': str(e), 'type': STATE_ERR}
474 state = {'message': str(e), 'type': STATE_ERR}
454 return SysInfoRes(value=value, state=state, human_value=human_value)
475 return SysInfoRes(value=value, state=state, human_value=human_value)
455
476
456
477
457 def svn_info():
478 def svn_info():
458 from rhodecode.lib.vcs.backends import svn
479 from rhodecode.lib.vcs.backends import svn
459 state = STATE_OK_DEFAULT
480 state = STATE_OK_DEFAULT
460 value = human_value = ''
481 value = human_value = ''
461 try:
482 try:
462 value = svn.discover_svn_version(raise_on_exc=True)
483 value = svn.discover_svn_version(raise_on_exc=True)
463 human_value = 'version reported from VCSServer: {}'.format(value)
484 human_value = 'version reported from VCSServer: {}'.format(value)
464 except Exception as e:
485 except Exception as e:
465 state = {'message': str(e), 'type': STATE_ERR}
486 state = {'message': str(e), 'type': STATE_ERR}
466 return SysInfoRes(value=value, state=state, human_value=human_value)
487 return SysInfoRes(value=value, state=state, human_value=human_value)
467
488
468
489
469 def vcs_backends():
490 def vcs_backends():
470 import rhodecode
491 import rhodecode
471 value = map(
492 value = map(
472 string.strip, rhodecode.CONFIG.get('vcs.backends', '').split(','))
493 string.strip, rhodecode.CONFIG.get('vcs.backends', '').split(','))
473 human_value = 'Enabled backends in order: {}'.format(','.join(value))
494 human_value = 'Enabled backends in order: {}'.format(','.join(value))
474 return SysInfoRes(value=value, human_value=human_value)
495 return SysInfoRes(value=value, human_value=human_value)
475
496
476
497
477 def vcs_server():
498 def vcs_server():
478 import rhodecode
499 import rhodecode
479 from rhodecode.lib.vcs.backends import get_vcsserver_service_data
500 from rhodecode.lib.vcs.backends import get_vcsserver_service_data
480
501
481 server_url = rhodecode.CONFIG.get('vcs.server')
502 server_url = rhodecode.CONFIG.get('vcs.server')
482 enabled = rhodecode.CONFIG.get('vcs.server.enable')
503 enabled = rhodecode.CONFIG.get('vcs.server.enable')
483 protocol = rhodecode.CONFIG.get('vcs.server.protocol') or 'http'
504 protocol = rhodecode.CONFIG.get('vcs.server.protocol') or 'http'
484 state = STATE_OK_DEFAULT
505 state = STATE_OK_DEFAULT
485 version = None
506 version = None
486 workers = 0
507 workers = 0
487
508
488 try:
509 try:
489 data = get_vcsserver_service_data()
510 data = get_vcsserver_service_data()
490 if data and 'version' in data:
511 if data and 'version' in data:
491 version = data['version']
512 version = data['version']
492
513
493 if data and 'config' in data:
514 if data and 'config' in data:
494 conf = data['config']
515 conf = data['config']
495 workers = conf.get('workers', '?')
516 workers = conf.get('workers', '?')
496
517
497 connection = 'connected'
518 connection = 'connected'
498 except Exception as e:
519 except Exception as e:
499 connection = 'failed'
520 connection = 'failed'
500 state = {'message': str(e), 'type': STATE_ERR}
521 state = {'message': str(e), 'type': STATE_ERR}
501
522
502 value = dict(
523 value = dict(
503 url=server_url,
524 url=server_url,
504 enabled=enabled,
525 enabled=enabled,
505 protocol=protocol,
526 protocol=protocol,
506 connection=connection,
527 connection=connection,
507 version=version,
528 version=version,
508 text='',
529 text='',
509 )
530 )
510
531
511 human_value = value.copy()
532 human_value = value.copy()
512 human_value['text'] = \
533 human_value['text'] = \
513 '{url}@ver:{ver} via {mode} mode[workers:{workers}], connection:{conn}'.format(
534 '{url}@ver:{ver} via {mode} mode[workers:{workers}], connection:{conn}'.format(
514 url=server_url, ver=version, workers=workers, mode=protocol,
535 url=server_url, ver=version, workers=workers, mode=protocol,
515 conn=connection)
536 conn=connection)
516
537
517 return SysInfoRes(value=value, state=state, human_value=human_value)
538 return SysInfoRes(value=value, state=state, human_value=human_value)
518
539
519
540
520 def rhodecode_app_info():
541 def rhodecode_app_info():
521 import rhodecode
542 import rhodecode
522 edition = rhodecode.CONFIG.get('rhodecode.edition')
543 edition = rhodecode.CONFIG.get('rhodecode.edition')
523
544
524 value = dict(
545 value = dict(
525 rhodecode_version=rhodecode.__version__,
546 rhodecode_version=rhodecode.__version__,
526 rhodecode_lib_path=os.path.abspath(rhodecode.__file__),
547 rhodecode_lib_path=os.path.abspath(rhodecode.__file__),
527 text=''
548 text=''
528 )
549 )
529 human_value = value.copy()
550 human_value = value.copy()
530 human_value['text'] = 'RhodeCode {edition}, version {ver}'.format(
551 human_value['text'] = 'RhodeCode {edition}, version {ver}'.format(
531 edition=edition, ver=value['rhodecode_version']
552 edition=edition, ver=value['rhodecode_version']
532 )
553 )
533 return SysInfoRes(value=value, human_value=human_value)
554 return SysInfoRes(value=value, human_value=human_value)
534
555
535
556
536 def rhodecode_config():
557 def rhodecode_config():
537 import rhodecode
558 import rhodecode
538 import ConfigParser as configparser
559 import ConfigParser as configparser
539 path = rhodecode.CONFIG.get('__file__')
560 path = rhodecode.CONFIG.get('__file__')
540 rhodecode_ini_safe = rhodecode.CONFIG.copy()
561 rhodecode_ini_safe = rhodecode.CONFIG.copy()
541
562
542 try:
563 try:
543 config = configparser.ConfigParser()
564 config = configparser.ConfigParser()
544 config.read(path)
565 config.read(path)
545 parsed_ini = config
566 parsed_ini = config
546 if parsed_ini.has_section('server:main'):
567 if parsed_ini.has_section('server:main'):
547 parsed_ini = dict(parsed_ini.items('server:main'))
568 parsed_ini = dict(parsed_ini.items('server:main'))
548 except Exception:
569 except Exception:
549 log.exception('Failed to read .ini file for display')
570 log.exception('Failed to read .ini file for display')
550 parsed_ini = {}
571 parsed_ini = {}
551
572
552 rhodecode_ini_safe['server:main'] = parsed_ini
573 rhodecode_ini_safe['server:main'] = parsed_ini
553
574
554 blacklist = [
575 blacklist = [
555 'rhodecode_license_key',
576 'rhodecode_license_key',
556 'routes.map',
577 'routes.map',
557 'pylons.h',
578 'pylons.h',
558 'pylons.app_globals',
579 'pylons.app_globals',
559 'pylons.environ_config',
580 'pylons.environ_config',
560 'sqlalchemy.db1.url',
581 'sqlalchemy.db1.url',
561 'channelstream.secret',
582 'channelstream.secret',
562 'beaker.session.secret',
583 'beaker.session.secret',
563 'rhodecode.encrypted_values.secret',
584 'rhodecode.encrypted_values.secret',
564 'rhodecode_auth_github_consumer_key',
585 'rhodecode_auth_github_consumer_key',
565 'rhodecode_auth_github_consumer_secret',
586 'rhodecode_auth_github_consumer_secret',
566 'rhodecode_auth_google_consumer_key',
587 'rhodecode_auth_google_consumer_key',
567 'rhodecode_auth_google_consumer_secret',
588 'rhodecode_auth_google_consumer_secret',
568 'rhodecode_auth_bitbucket_consumer_secret',
589 'rhodecode_auth_bitbucket_consumer_secret',
569 'rhodecode_auth_bitbucket_consumer_key',
590 'rhodecode_auth_bitbucket_consumer_key',
570 'rhodecode_auth_twitter_consumer_secret',
591 'rhodecode_auth_twitter_consumer_secret',
571 'rhodecode_auth_twitter_consumer_key',
592 'rhodecode_auth_twitter_consumer_key',
572
593
573 'rhodecode_auth_twitter_secret',
594 'rhodecode_auth_twitter_secret',
574 'rhodecode_auth_github_secret',
595 'rhodecode_auth_github_secret',
575 'rhodecode_auth_google_secret',
596 'rhodecode_auth_google_secret',
576 'rhodecode_auth_bitbucket_secret',
597 'rhodecode_auth_bitbucket_secret',
577
598
578 'appenlight.api_key',
599 'appenlight.api_key',
579 ('app_conf', 'sqlalchemy.db1.url')
600 ('app_conf', 'sqlalchemy.db1.url')
580 ]
601 ]
581 for k in blacklist:
602 for k in blacklist:
582 if isinstance(k, tuple):
603 if isinstance(k, tuple):
583 section, key = k
604 section, key = k
584 if section in rhodecode_ini_safe:
605 if section in rhodecode_ini_safe:
585 rhodecode_ini_safe[section] = '**OBFUSCATED**'
606 rhodecode_ini_safe[section] = '**OBFUSCATED**'
586 else:
607 else:
587 rhodecode_ini_safe.pop(k, None)
608 rhodecode_ini_safe.pop(k, None)
588
609
589 # TODO: maybe put some CONFIG checks here ?
610 # TODO: maybe put some CONFIG checks here ?
590 return SysInfoRes(value={'config': rhodecode_ini_safe, 'path': path})
611 return SysInfoRes(value={'config': rhodecode_ini_safe, 'path': path})
591
612
592
613
593 def database_info():
614 def database_info():
594 import rhodecode
615 import rhodecode
595 from sqlalchemy.engine import url as engine_url
616 from sqlalchemy.engine import url as engine_url
596 from rhodecode.model.meta import Base as sql_base, Session
617 from rhodecode.model.meta import Base as sql_base, Session
597 from rhodecode.model.db import DbMigrateVersion
618 from rhodecode.model.db import DbMigrateVersion
598
619
599 state = STATE_OK_DEFAULT
620 state = STATE_OK_DEFAULT
600
621
601 db_migrate = DbMigrateVersion.query().filter(
622 db_migrate = DbMigrateVersion.query().filter(
602 DbMigrateVersion.repository_id == 'rhodecode_db_migrations').one()
623 DbMigrateVersion.repository_id == 'rhodecode_db_migrations').one()
603
624
604 db_url_obj = engine_url.make_url(rhodecode.CONFIG['sqlalchemy.db1.url'])
625 db_url_obj = engine_url.make_url(rhodecode.CONFIG['sqlalchemy.db1.url'])
605
626
606 try:
627 try:
607 engine = sql_base.metadata.bind
628 engine = sql_base.metadata.bind
608 db_server_info = engine.dialect._get_server_version_info(
629 db_server_info = engine.dialect._get_server_version_info(
609 Session.connection(bind=engine))
630 Session.connection(bind=engine))
610 db_version = '.'.join(map(str, db_server_info))
631 db_version = '.'.join(map(str, db_server_info))
611 except Exception:
632 except Exception:
612 log.exception('failed to fetch db version')
633 log.exception('failed to fetch db version')
613 db_version = 'UNKNOWN'
634 db_version = 'UNKNOWN'
614
635
615 db_info = dict(
636 db_info = dict(
616 migrate_version=db_migrate.version,
637 migrate_version=db_migrate.version,
617 type=db_url_obj.get_backend_name(),
638 type=db_url_obj.get_backend_name(),
618 version=db_version,
639 version=db_version,
619 url=repr(db_url_obj)
640 url=repr(db_url_obj)
620 )
641 )
621
642
622 human_value = db_info.copy()
643 human_value = db_info.copy()
623 human_value['url'] = "{} @ migration version: {}".format(
644 human_value['url'] = "{} @ migration version: {}".format(
624 db_info['url'], db_info['migrate_version'])
645 db_info['url'], db_info['migrate_version'])
625 human_value['version'] = "{} {}".format(db_info['type'], db_info['version'])
646 human_value['version'] = "{} {}".format(db_info['type'], db_info['version'])
626 return SysInfoRes(value=db_info, state=state, human_value=human_value)
647 return SysInfoRes(value=db_info, state=state, human_value=human_value)
627
648
628
649
629 def server_info(environ):
650 def server_info(environ):
630 import rhodecode
651 import rhodecode
631 from rhodecode.lib.base import get_server_ip_addr, get_server_port
652 from rhodecode.lib.base import get_server_ip_addr, get_server_port
632
653
633 value = {
654 value = {
634 'server_ip': '%s:%s' % (
655 'server_ip': '%s:%s' % (
635 get_server_ip_addr(environ, log_errors=False),
656 get_server_ip_addr(environ, log_errors=False),
636 get_server_port(environ)
657 get_server_port(environ)
637 ),
658 ),
638 'server_id': rhodecode.CONFIG.get('instance_id'),
659 'server_id': rhodecode.CONFIG.get('instance_id'),
639 }
660 }
640 return SysInfoRes(value=value)
661 return SysInfoRes(value=value)
641
662
642
663
643 def usage_info():
664 def usage_info():
644 from rhodecode.model.db import User, Repository
665 from rhodecode.model.db import User, Repository
645 value = {
666 value = {
646 'users': User.query().count(),
667 'users': User.query().count(),
647 'users_active': User.query().filter(User.active == True).count(),
668 'users_active': User.query().filter(User.active == True).count(),
648 'repositories': Repository.query().count(),
669 'repositories': Repository.query().count(),
649 'repository_types': {
670 'repository_types': {
650 'hg': Repository.query().filter(
671 'hg': Repository.query().filter(
651 Repository.repo_type == 'hg').count(),
672 Repository.repo_type == 'hg').count(),
652 'git': Repository.query().filter(
673 'git': Repository.query().filter(
653 Repository.repo_type == 'git').count(),
674 Repository.repo_type == 'git').count(),
654 'svn': Repository.query().filter(
675 'svn': Repository.query().filter(
655 Repository.repo_type == 'svn').count(),
676 Repository.repo_type == 'svn').count(),
656 },
677 },
657 }
678 }
658 return SysInfoRes(value=value)
679 return SysInfoRes(value=value)
659
680
660
681
661 def get_system_info(environ):
682 def get_system_info(environ):
662 environ = environ or {}
683 environ = environ or {}
663 return {
684 return {
664 'rhodecode_app': SysInfo(rhodecode_app_info)(),
685 'rhodecode_app': SysInfo(rhodecode_app_info)(),
665 'rhodecode_config': SysInfo(rhodecode_config)(),
686 'rhodecode_config': SysInfo(rhodecode_config)(),
666 'rhodecode_usage': SysInfo(usage_info)(),
687 'rhodecode_usage': SysInfo(usage_info)(),
667 'python': SysInfo(python_info)(),
688 'python': SysInfo(python_info)(),
668 'py_modules': SysInfo(py_modules)(),
689 'py_modules': SysInfo(py_modules)(),
669
690
670 'platform': SysInfo(platform_type)(),
691 'platform': SysInfo(platform_type)(),
671 'server': SysInfo(server_info, environ=environ)(),
692 'server': SysInfo(server_info, environ=environ)(),
672 'database': SysInfo(database_info)(),
693 'database': SysInfo(database_info)(),
673
694
674 'storage': SysInfo(storage)(),
695 'storage': SysInfo(storage)(),
675 'storage_inodes': SysInfo(storage_inodes)(),
696 'storage_inodes': SysInfo(storage_inodes)(),
676 'storage_archive': SysInfo(storage_archives)(),
697 'storage_archive': SysInfo(storage_archives)(),
677 'storage_gist': SysInfo(storage_gist)(),
698 'storage_gist': SysInfo(storage_gist)(),
678 'storage_temp': SysInfo(storage_temp)(),
699 'storage_temp': SysInfo(storage_temp)(),
679
700
680 'search': SysInfo(search_info)(),
701 'search': SysInfo(search_info)(),
681
702
682 'uptime': SysInfo(uptime)(),
703 'uptime': SysInfo(uptime)(),
683 'load': SysInfo(machine_load)(),
704 'load': SysInfo(machine_load)(),
684 'cpu': SysInfo(cpu)(),
705 'cpu': SysInfo(cpu)(),
685 'memory': SysInfo(memory)(),
706 'memory': SysInfo(memory)(),
686
707
687 'vcs_backends': SysInfo(vcs_backends)(),
708 'vcs_backends': SysInfo(vcs_backends)(),
688 'vcs_server': SysInfo(vcs_server)(),
709 'vcs_server': SysInfo(vcs_server)(),
689
710
690 'git': SysInfo(git_info)(),
711 'git': SysInfo(git_info)(),
691 'hg': SysInfo(hg_info)(),
712 'hg': SysInfo(hg_info)(),
692 'svn': SysInfo(svn_info)(),
713 'svn': SysInfo(svn_info)(),
693 }
714 }
General Comments 0
You need to be logged in to leave comments. Login now