View | Details | Raw Unified | Return to bug 37458
Collapse All | Expand All

(-)a/ucs-4.0-0/management/univention-management-console/doc/core_api.rst (-10 lines)
 Lines 53-65   Helper functions Link Here 
53
	:members:
53
	:members:
54
	:undoc-members:
54
	:undoc-members:
55
	:show-inheritance:
55
	:show-inheritance:
56
57
----------
58
Statistics
59
----------
60
61
.. automodule:: univention.management.console.statistics
62
	:members:
63
	:undoc-members:
64
	:show-inheritance:
65
(-)a/ucs-4.0-0/management/univention-management-console/src/univention/management/console/protocol/definitions.py (-4 lines)
 Lines 70-79   COMMANDS = ( Link Here 
70
	CommandDefinition('VERSION', False),
70
	CommandDefinition('VERSION', False),
71
	CommandDefinition('GET', True),
71
	CommandDefinition('GET', True),
72
	CommandDefinition('SET', True),
72
	CommandDefinition('SET', True),
73
	CommandDefinition('CLOSE', False),
74
	CommandDefinition('STATISTICS', False),
75
	CommandDefinition('CANCEL', False, 'ids'),
76
	CommandDefinition('STATUS', False, 'ids'),
77
	CommandDefinition('EXIT', True),
73
	CommandDefinition('EXIT', True),
78
	CommandDefinition('UPLOAD', True),
74
	CommandDefinition('UPLOAD', True),
79
)
75
)
(-)a/ucs-4.0-0/management/univention-management-console/src/univention/management/console/protocol/server.py (-25 lines)
 Lines 39-45   Defines the basic class for an UMC server. Link Here 
39
import fcntl
39
import fcntl
40
import gzip
40
import gzip
41
import os
41
import os
42
import pwd
43
import re
42
import re
44
import socket
43
import socket
45
44
 Lines 65-71   from .definitions import ( Link Here 
65
from ..resources import moduleManager, categoryManager
64
from ..resources import moduleManager, categoryManager
66
from ..log import CORE, CRYPT, RESOURCES
65
from ..log import CORE, CRYPT, RESOURCES
67
from ..config import ucr, SERVER_MAX_CONNECTIONS
66
from ..config import ucr, SERVER_MAX_CONNECTIONS
68
from ..statistics import statistics
69
67
70
68
71
class MagicBucket(object):
69
class MagicBucket(object):
 Lines 93-99   class MagicBucket(object): Link Here 
93
		state.signal_connect('authenticated', self._authenticated)
91
		state.signal_connect('authenticated', self._authenticated)
94
		self.__states[socket] = state
92
		self.__states[socket] = state
95
		notifier.socket_add(socket, self._receive)
93
		notifier.socket_add(socket, self._receive)
96
		statistics.connections.new()
97
94
98
	def exit(self):
95
	def exit(self):
99
		'''Closes all open connections.'''
96
		'''Closes all open connections.'''
 Lines 103-109   class MagicBucket(object): Link Here 
103
			if state.processor is not None:
100
			if state.processor is not None:
104
				state.processor.shutdown()
101
				state.processor.shutdown()
105
			notifier.socket_remove(sock)
102
			notifier.socket_remove(sock)
106
			statistics.connections.inactive()
107
		# delete states
103
		# delete states
108
		for state in self.__states.values():
104
		for state in self.__states.values():
109
			del state
105
			del state
 Lines 119-126   class MagicBucket(object): Link Here 
119
		state.authResponse.status = result.status
115
		state.authResponse.status = result.status
120
		if result.message:
116
		if result.message:
121
			state.authResponse.message = result.message
117
			state.authResponse.message = result.message
122
		if result:
123
			statistics.users.add(state.username)
124
		state.authenticated = bool(result)
118
		state.authenticated = bool(result)
125
		self._response(state.authResponse, state)
119
		self._response(state.authResponse, state)
126
		state.authResponse = None
120
		state.authResponse = None
 Lines 198-204   class MagicBucket(object): Link Here 
198
		All other valid commands are redirected to the processor.
192
		All other valid commands are redirected to the processor.
199
		"""
193
		"""
200
		state.requests[msg.id] = msg
194
		state.requests[msg.id] = msg
201
		statistics.requests.new()
202
		CORE.info('Incoming request of type %s' % msg.command)
195
		CORE.info('Incoming request of type %s' % msg.command)
203
		if not state.authenticated and msg.command != 'AUTH':
196
		if not state.authenticated and msg.command != 'AUTH':
204
			res = Response(msg)
197
			res = Response(msg)
 Lines 255-273   class MagicBucket(object): Link Here 
255
					pass
248
					pass
256
249
257
			self._response(response, state)
250
			self._response(response, state)
258
		elif msg.command == 'STATISTICS':
259
			response = Response(msg)
260
			try:
261
				pwent = pwd.getpwnam(state.username)
262
				if not pwent.pw_uid in (0, ):
263
					raise KeyError
264
				CORE.info('Sending statistic data to client')
265
				response.status = SUCCESS
266
				response.result = statistics.json()
267
			except KeyError:
268
				CORE.info('User not allowed to retrieve statistics')
269
				response.status = BAD_REQUEST_FORBIDDEN
270
			self._response(response, state)
271
		else:
251
		else:
272
			# inform processor
252
			# inform processor
273
			if not state.processor:
253
			if not state.processor:
 Lines 307-313   class MagicBucket(object): Link Here 
307
			return
287
			return
308
288
309
		try:
289
		try:
310
			statistics.requests.inactive()
311
			data = str(msg)
290
			data = str(msg)
312
			# there is no data from another request in the send queue
291
			# there is no data from another request in the send queue
313
			if not state.resend_queue:
292
			if not state.resend_queue:
 Lines 338-347   class MagicBucket(object): Link Here 
338
		if socket not in self.__states:
317
		if socket not in self.__states:
339
			return
318
			return
340
319
341
		statistics.connections.inactive()
342
		if self.__states[socket].username in statistics.users:
343
			statistics.users.remove(self.__states[socket].username)
344
345
		if self.__states[socket].processor is not None:
320
		if self.__states[socket].processor is not None:
346
			self.__states[socket].processor.shutdown()
321
			self.__states[socket].processor.shutdown()
347
322
(-)a/ucs-4.0-0/management/univention-management-console/src/univention/management/console/protocol/session.py (-2 lines)
 Lines 306-313   class Processor(signals.Provider): Link Here 
306
			self.handle_request_command(msg)
306
			self.handle_request_command(msg)
307
		elif msg.command == 'UPLOAD':
307
		elif msg.command == 'UPLOAD':
308
			self.handle_request_upload(msg)
308
			self.handle_request_upload(msg)
309
		elif msg.command in ('STATUS', 'CANCEL', 'CLOSE'):
310
			self.handle_request_unknown(msg)
311
		else:
309
		else:
312
			self.handle_request_unknown(msg)
310
			self.handle_request_unknown(msg)
313
311
(-)a/ucs-4.0-0/management/univention-management-console/src/univention/management/console/statistics.py (-77 lines)
 Lines 1-77    Link Here 
1
# -*- coding: utf-8 -*-
2
#
3
# Univention Management Console
4
#  runtime statistics of the UMC server
5
#
6
# Copyright 2011-2014 Univention GmbH
7
#
8
# http://www.univention.de/
9
#
10
# All rights reserved.
11
#
12
# The source code of this program is made available
13
# under the terms of the GNU Affero General Public License version 3
14
# (GNU AGPL V3) as published by the Free Software Foundation.
15
#
16
# Binary versions of this program provided by Univention to you as
17
# well as other copyrighted, protected or trademarked materials like
18
# Logos, graphics, fonts, specific documentations and configurations,
19
# cryptographic keys etc. are subject to a license agreement between
20
# you and Univention and not subject to the GNU AGPL V3.
21
#
22
# In the case you use this program under the terms of the GNU AGPL V3,
23
# the program is provided in the hope that it will be useful,
24
# but WITHOUT ANY WARRANTY; without even the implied warranty of
25
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26
# GNU Affero General Public License for more details.
27
#
28
# You should have received a copy of the GNU Affero General Public
29
# License with the Debian GNU/Linux or Univention distribution in file
30
# /usr/share/common-licenses/AGPL-3; if not, see
31
# <http://www.gnu.org/licenses/>.
32
33
34
class Counter(object):
35
36
	"""Implements a counter that counts available elements of
37
	any type that can be inactive."""
38
39
	def __init__(self):
40
		self._all = 0l
41
		self._active = 0l
42
43
	def new(self):
44
		"""Increase counter by one active element"""
45
		self._all += 1
46
		self._active += 1
47
48
	def inactive(self):
49
		"""Decrease counter of active elements by one"""
50
		self._active -= 1
51
52
	def json(self):
53
		"""Returns counter information in JSON compatible form"""
54
		return {'all': self._all, 'active': self._active}
55
56
57
class Statistics(object):
58
59
	"""Collects information about the connections, modules, requests and
60
	users processed and seen by the running UMC server instance"""
61
	connections = Counter()
62
	modules = Counter()
63
	requests = Counter()
64
	users = set()
65
66
	@staticmethod
67
	def json():
68
		"""Returns the statistics ina JSON compatible form"""
69
		return {
70
			'connections': Statistics.connections.json(),
71
			'modules': Statistics.modules.json(),
72
			'requests': Statistics.requests.json(),
73
			'users': list(Statistics.users)
74
		}
75
76
#: global :class:`Statistics` object
77
statistics = Statistics()

Return to bug 37458