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