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