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