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