##// END OF EJS Templates
feat(system-info): update report and made a ver option be passed via GET param to test check for update logic
super-admin -
r5432:81f383de default
parent child Browse files
Show More
@@ -1,238 +1,243 b''
1
1
2
2
3 # Copyright (C) 2016-2023 RhodeCode GmbH
3 # Copyright (C) 2016-2023 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 urllib.request
22 import urllib.request
23 import urllib.error
23 import urllib.error
24 import urllib.parse
24 import urllib.parse
25 import os
25 import os
26
26
27 import rhodecode
27 import rhodecode
28 from rhodecode.apps._base import BaseAppView
28 from rhodecode.apps._base import BaseAppView
29 from rhodecode.apps._base.navigation import navigation_list
29 from rhodecode.apps._base.navigation import navigation_list
30 from rhodecode.lib import helpers as h
30 from rhodecode.lib import helpers as h
31 from rhodecode.lib.auth import (LoginRequired, HasPermissionAllDecorator)
31 from rhodecode.lib.auth import (LoginRequired, HasPermissionAllDecorator)
32 from rhodecode.lib.utils2 import str2bool
32 from rhodecode.lib.utils2 import str2bool
33 from rhodecode.lib import system_info
33 from rhodecode.lib import system_info
34 from rhodecode.model.update import UpdateModel
34 from rhodecode.model.update import UpdateModel
35
35
36 log = logging.getLogger(__name__)
36 log = logging.getLogger(__name__)
37
37
38
38
39 class AdminSystemInfoSettingsView(BaseAppView):
39 class AdminSystemInfoSettingsView(BaseAppView):
40 def load_default_context(self):
40 def load_default_context(self):
41 c = self._get_local_tmpl_context()
41 c = self._get_local_tmpl_context()
42 return c
42 return c
43
43
44 def get_env_data(self):
44 def get_env_data(self):
45 black_list = [
45 black_list = [
46 'NIX_LDFLAGS',
46 'NIX_LDFLAGS',
47 'NIX_CFLAGS_COMPILE',
47 'NIX_CFLAGS_COMPILE',
48 'propagatedBuildInputs',
48 'propagatedBuildInputs',
49 'propagatedNativeBuildInputs',
49 'propagatedNativeBuildInputs',
50 'postInstall',
50 'postInstall',
51 'buildInputs',
51 'buildInputs',
52 'buildPhase',
52 'buildPhase',
53 'preShellHook',
53 'preShellHook',
54 'preShellHook',
54 'preShellHook',
55 'preCheck',
55 'preCheck',
56 'preBuild',
56 'preBuild',
57 'postShellHook',
57 'postShellHook',
58 'postFixup',
58 'postFixup',
59 'postCheck',
59 'postCheck',
60 'nativeBuildInputs',
60 'nativeBuildInputs',
61 'installPhase',
61 'installPhase',
62 'installCheckPhase',
62 'installCheckPhase',
63 'checkPhase',
63 'checkPhase',
64 'configurePhase',
64 'configurePhase',
65 'shellHook'
65 'shellHook'
66 ]
66 ]
67 secret_list = [
67 secret_list = [
68 'RHODECODE_USER_PASS'
68 'RHODECODE_USER_PASS'
69 ]
69 ]
70
70
71 for k, v in sorted(os.environ.items()):
71 for k, v in sorted(os.environ.items()):
72 if k in black_list:
72 if k in black_list:
73 continue
73 continue
74 if k in secret_list:
74 if k in secret_list:
75 v = '*****'
75 v = '*****'
76 yield k, v
76 yield k, v
77
77
78 @LoginRequired()
78 @LoginRequired()
79 @HasPermissionAllDecorator('hg.admin')
79 @HasPermissionAllDecorator('hg.admin')
80 def settings_system_info(self):
80 def settings_system_info(self):
81 _ = self.request.translate
81 _ = self.request.translate
82 c = self.load_default_context()
82 c = self.load_default_context()
83
83
84 c.active = 'system'
84 c.active = 'system'
85 c.navlist = navigation_list(self.request)
85 c.navlist = navigation_list(self.request)
86
86
87 # TODO(marcink), figure out how to allow only selected users to do this
87 # TODO(marcink), figure out how to allow only selected users to do this
88 c.allowed_to_snapshot = self._rhodecode_user.admin
88 c.allowed_to_snapshot = self._rhodecode_user.admin
89
89
90 snapshot = str2bool(self.request.params.get('snapshot'))
90 snapshot = str2bool(self.request.params.get('snapshot'))
91
91
92 c.rhodecode_update_url = UpdateModel().get_update_url()
92 c.rhodecode_update_url = UpdateModel().get_update_url()
93 c.env_data = self.get_env_data()
93 c.env_data = self.get_env_data()
94 server_info = system_info.get_system_info(self.request.environ)
94 server_info = system_info.get_system_info(self.request.environ)
95
95
96 for key, val in server_info.items():
96 for key, val in server_info.items():
97 setattr(c, key, val)
97 setattr(c, key, val)
98
98
99 def val(name, subkey='human_value'):
99 def val(name, subkey='human_value'):
100 return server_info[name][subkey]
100 return server_info[name][subkey]
101
101
102 def state(name):
102 def state(name):
103 return server_info[name]['state']
103 return server_info[name]['state']
104
104
105 def val2(name):
105 def val2(name):
106 val = server_info[name]['human_value']
106 val = server_info[name]['human_value']
107 state = server_info[name]['state']
107 state = server_info[name]['state']
108 return val, state
108 return val, state
109
109
110 update_info_msg = _('Note: please make sure this server can '
110 update_info_msg = _('Note: please make sure this server can '
111 'access `${url}` for the update link to work',
111 'access `${url}` for the update link to work',
112 mapping=dict(url=c.rhodecode_update_url))
112 mapping=dict(url=c.rhodecode_update_url))
113 version = UpdateModel().get_stored_version()
113 version = UpdateModel().get_stored_version()
114 is_outdated = UpdateModel().is_outdated(
114 is_outdated = UpdateModel().is_outdated(
115 rhodecode.__version__, version)
115 rhodecode.__version__, version)
116 update_state = {
116 update_state = {
117 'type': 'warning',
117 'type': 'warning',
118 'message': 'New version available: {}'.format(version)
118 'message': 'New version available: {}'.format(version)
119 } \
119 } \
120 if is_outdated else {}
120 if is_outdated else {}
121 c.data_items = [
121 c.data_items = [
122 # update info
122 # update info
123 (_('Update info'), h.literal(
123 (_('Update info'), h.literal(
124 '<span class="link" id="check_for_update" >%s.</span>' % (
124 '<span class="link" id="check_for_update" >%s.</span>' % (
125 _('Check for updates')) +
125 _('Check for updates')) +
126 '<br/> <span >%s.</span>' % (update_info_msg)
126 '<br/> <span >%s.</span>' % (update_info_msg)
127 ), ''),
127 ), ''),
128
128
129 # RhodeCode specific
129 # RhodeCode specific
130 (_('RhodeCode Version'), val('rhodecode_app')['text'], state('rhodecode_app')),
130 (_('RhodeCode Version'), val('rhodecode_app')['text'], state('rhodecode_app')),
131 (_('Latest version'), version, update_state),
131 (_('Latest version'), version, update_state),
132 (_('RhodeCode Base URL'), val('rhodecode_config')['config'].get('app.base_url'), state('rhodecode_config')),
132 (_('RhodeCode Base URL'), val('rhodecode_config')['config'].get('app.base_url'), state('rhodecode_config')),
133 (_('RhodeCode Server IP'), val('server')['server_ip'], state('server')),
133 (_('RhodeCode Server IP'), val('server')['server_ip'], state('server')),
134 (_('RhodeCode Server ID'), val('server')['server_id'], state('server')),
134 (_('RhodeCode Server ID'), val('server')['server_id'], state('server')),
135 (_('RhodeCode Configuration'), val('rhodecode_config')['path'], state('rhodecode_config')),
135 (_('RhodeCode Configuration'), val('rhodecode_config')['path'], state('rhodecode_config')),
136 (_('RhodeCode Certificate'), val('rhodecode_config')['cert_path'], state('rhodecode_config')),
136 (_('RhodeCode Certificate'), val('rhodecode_config')['cert_path'], state('rhodecode_config')),
137 (_('Workers'), val('rhodecode_config')['config']['server:main'].get('workers', '?'), state('rhodecode_config')),
137 (_('Workers'), val('rhodecode_config')['config']['server:main'].get('workers', '?'), state('rhodecode_config')),
138 (_('Worker Type'), val('rhodecode_config')['config']['server:main'].get('worker_class', 'sync'), state('rhodecode_config')),
138 (_('Worker Type'), val('rhodecode_config')['config']['server:main'].get('worker_class', 'sync'), state('rhodecode_config')),
139 ('', '', ''), # spacer
139 ('', '', ''), # spacer
140
140
141 # Database
141 # Database
142 (_('Database'), val('database')['url'], state('database')),
142 (_('Database'), val('database')['url'], state('database')),
143 (_('Database version'), val('database')['version'], state('database')),
143 (_('Database version'), val('database')['version'], state('database')),
144 ('', '', ''), # spacer
144 ('', '', ''), # spacer
145
145
146 # Platform/Python
146 # Platform/Python
147 (_('Platform'), val('platform')['name'], state('platform')),
147 (_('Platform'), val('platform')['name'], state('platform')),
148 (_('Platform UUID'), val('platform')['uuid'], state('platform')),
148 (_('Platform UUID'), val('platform')['uuid'], state('platform')),
149 (_('Lang'), val('locale'), state('locale')),
149 (_('Lang'), val('locale'), state('locale')),
150 (_('Python version'), val('python')['version'], state('python')),
150 (_('Python version'), val('python')['version'], state('python')),
151 (_('Python path'), val('python')['executable'], state('python')),
151 (_('Python path'), val('python')['executable'], state('python')),
152 ('', '', ''), # spacer
152 ('', '', ''), # spacer
153
153
154 # Systems stats
154 # Systems stats
155 (_('CPU'), val('cpu')['text'], state('cpu')),
155 (_('CPU'), val('cpu')['text'], state('cpu')),
156 (_('Load'), val('load')['text'], state('load')),
156 (_('Load'), val('load')['text'], state('load')),
157 (_('Memory'), val('memory')['text'], state('memory')),
157 (_('Memory'), val('memory')['text'], state('memory')),
158 (_('Uptime'), val('uptime')['text'], state('uptime')),
158 (_('Uptime'), val('uptime')['text'], state('uptime')),
159 ('', '', ''), # spacer
159 ('', '', ''), # spacer
160
160
161 # ulimit
161 # ulimit
162 (_('Ulimit'), val('ulimit')['text'], state('ulimit')),
162 (_('Ulimit'), val('ulimit')['text'], state('ulimit')),
163
163
164 # Repo storage
164 # Repo storage
165 (_('Storage location'), val('storage')['path'], state('storage')),
165 (_('Storage location'), val('storage')['path'], state('storage')),
166 (_('Storage info'), val('storage')['text'], state('storage')),
166 (_('Storage info'), val('storage')['text'], state('storage')),
167 (_('Storage inodes'), val('storage_inodes')['text'], state('storage_inodes')),
167 (_('Storage inodes'), val('storage_inodes')['text'], state('storage_inodes')),
168 ('', '', ''), # spacer
168
169
169 (_('Gist storage location'), val('storage_gist')['path'], state('storage_gist')),
170 (_('Gist storage location'), val('storage_gist')['path'], state('storage_gist')),
170 (_('Gist storage info'), val('storage_gist')['text'], state('storage_gist')),
171 (_('Gist storage info'), val('storage_gist')['text'], state('storage_gist')),
172 ('', '', ''), # spacer
171
173
172 (_('Archive cache storage type'), val('storage_archive')['type'], state('storage_archive')),
174 (_('Archive cache storage type'), val('storage_archive')['type'], state('storage_archive')),
173 (_('Archive cache storage location'), val('storage_archive')['path'], state('storage_archive')),
175 (_('Archive cache storage location'), val('storage_archive')['path'], state('storage_archive')),
174 (_('Archive cache info'), val('storage_archive')['text'], state('storage_archive')),
176 (_('Archive cache info'), val('storage_archive')['text'], state('storage_archive')),
177 ('', '', ''), # spacer
175
178
176 (_('Temp storage location'), val('storage_temp')['path'], state('storage_temp')),
179 (_('Temp storage location'), val('storage_temp')['path'], state('storage_temp')),
177 (_('Temp storage info'), val('storage_temp')['text'], state('storage_temp')),
180 (_('Temp storage info'), val('storage_temp')['text'], state('storage_temp')),
181 ('', '', ''), # spacer
178
182
179 (_('Search info'), val('search')['text'], state('search')),
183 (_('Search info'), val('search')['text'], state('search')),
180 (_('Search location'), val('search')['location'], state('search')),
184 (_('Search location'), val('search')['location'], state('search')),
181 ('', '', ''), # spacer
185 ('', '', ''), # spacer
182
186
183 # VCS specific
187 # VCS specific
184 (_('VCS Backends'), val('vcs_backends'), state('vcs_backends')),
188 (_('VCS Backends'), val('vcs_backends'), state('vcs_backends')),
185 (_('VCS Server'), val('vcs_server')['text'], state('vcs_server')),
189 (_('VCS Server'), val('vcs_server')['text'], state('vcs_server')),
186 (_('GIT'), val('git'), state('git')),
190 (_('GIT'), val('git'), state('git')),
187 (_('HG'), val('hg'), state('hg')),
191 (_('HG'), val('hg'), state('hg')),
188 (_('SVN'), val('svn'), state('svn')),
192 (_('SVN'), val('svn'), state('svn')),
189
193
190 ]
194 ]
191
195
192 c.vcsserver_data_items = [
196 c.vcsserver_data_items = [
193 (k, v) for k,v in (val('vcs_server_config') or {}).items()
197 (k, v) for k, v in (val('vcs_server_config') or {}).items()
194 ]
198 ]
195
199
196 if snapshot:
200 if snapshot:
197 if c.allowed_to_snapshot:
201 if c.allowed_to_snapshot:
198 c.data_items.pop(0) # remove server info
202 c.data_items.pop(0) # remove server info
199 self.request.override_renderer = 'admin/settings/settings_system_snapshot.mako'
203 self.request.override_renderer = 'admin/settings/settings_system_snapshot.mako'
200 else:
204 else:
201 h.flash('You are not allowed to do this', category='warning')
205 h.flash('You are not allowed to do this', category='warning')
202 return self._get_template_context(c)
206 return self._get_template_context(c)
203
207
204 @LoginRequired()
208 @LoginRequired()
205 @HasPermissionAllDecorator('hg.admin')
209 @HasPermissionAllDecorator('hg.admin')
206 def settings_system_info_check_update(self):
210 def settings_system_info_check_update(self):
207 _ = self.request.translate
211 _ = self.request.translate
208 c = self.load_default_context()
212 c = self.load_default_context()
209
213
210 update_url = UpdateModel().get_update_url()
214 update_url = UpdateModel().get_update_url()
211
215
212 def _err(s):
216 def _err(s):
213 return '<div style="color:#ff8888; padding:4px 0px">{}</div>'.format(s)
217 return f'<div style="color:#ff8888; padding:4px 0px">{s}</div>'
218
214 try:
219 try:
215 data = UpdateModel().get_update_data(update_url)
220 data = UpdateModel().get_update_data(update_url)
216 except urllib.error.URLError as e:
221 except urllib.error.URLError as e:
217 log.exception("Exception contacting upgrade server")
222 log.exception("Exception contacting upgrade server")
218 self.request.override_renderer = 'string'
223 self.request.override_renderer = 'string'
219 return _err('Failed to contact upgrade server: %r' % e)
224 return _err('Failed to contact upgrade server: %r' % e)
220 except ValueError as e:
225 except ValueError as e:
221 log.exception("Bad data sent from update server")
226 log.exception("Bad data sent from update server")
222 self.request.override_renderer = 'string'
227 self.request.override_renderer = 'string'
223 return _err('Bad data sent from update server')
228 return _err('Bad data sent from update server')
224
229
225 latest = data['versions'][0]
230 latest = data['versions'][0]
226
231
227 c.update_url = update_url
232 c.update_url = update_url
228 c.latest_data = latest
233 c.latest_data = latest
229 c.latest_ver = latest['version']
234 c.latest_ver = (latest['version'] or '').strip()
230 c.cur_ver = rhodecode.__version__
235 c.cur_ver = self.request.GET.get('ver') or rhodecode.__version__
231 c.should_upgrade = False
236 c.should_upgrade = False
232
237
233 is_oudated = UpdateModel().is_outdated(c.cur_ver, c.latest_ver)
238 is_outdated = UpdateModel().is_outdated(c.cur_ver, c.latest_ver)
234 if is_oudated:
239 if is_outdated:
235 c.should_upgrade = True
240 c.should_upgrade = True
236 c.important_notices = latest['general']
241 c.important_notices = latest['general']
237 UpdateModel().store_version(latest['version'])
242 UpdateModel().store_version(latest['version'])
238 return self._get_template_context(c)
243 return self._get_template_context(c)
General Comments 0
You need to be logged in to leave comments. Login now