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