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