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