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

(-)a/branches/ucs-3.1/ucs-3.1-2/base/univention-config-registry/python/univention/service_info.py (-65 / +67 lines)
 Lines 31-94    Link Here 
31
# /usr/share/common-licenses/AGPL-3; if not, see
31
# /usr/share/common-licenses/AGPL-3; if not, see
32
# <http://www.gnu.org/licenses/>.
32
# <http://www.gnu.org/licenses/>.
33
33
34
import locale
35
import os
34
import os
36
import re
35
import re
37
import string
38
import shlex
36
import shlex
39
37
40
import univention.info_tools as uit
38
import univention.info_tools as uit
41
39
42
class Service( uit.LocalizedDictionary ):
40
class Service(uit.LocalizedDictionary):
43
	def __init__( self ):
41
	def __init__(self):
44
		uit.LocalizedDictionary.__init__( self )
42
		uit.LocalizedDictionary.__init__(self)
45
		self.start_runlevel = []
43
		self.start_runlevel = []
46
		self.stop_runlevel = []
44
		self.stop_runlevel = []
47
		self.start_code = 0
45
		self.start_code = 0
48
		self.stop_code = 0
46
		self.stop_code = 0
49
		self.running = False
47
		self.running = False
50
48
51
	def check( self ):
49
	def check(self):
52
		"""Check service entry for validity, returning list of incomplete entries."""
50
		"""Check service entry for validity, returning list of incomplete entries."""
53
		incomplete = []
51
		incomplete = []
54
		for key in ( 'description', 'programs' ):
52
		for key in ('description', 'programs'):
55
			if not self.get( key, None ):
53
			if not self.get(key, None):
56
				incomplete.append(key)
54
				incomplete.append(key)
57
		return incomplete
55
		return incomplete
58
56
59
def pidof( name ):
57
60
	result = []
58
def pidof(name):
61
	for file in os.listdir( '/proc' ):
59
	"""
62
		dir = os.path.join( '/proc', file )
60
	Return list of process IDs matching name.
63
		if not os.path.isdir( dir ):
61
	>>> import os,sys;str(os.getpid()) in pidof(sys.executable)
64
			continue
62
	True
65
		if not os.path.isfile( os.path.join( dir, 'stat' ) ):
63
	"""
66
			continue
64
	cmd = shlex.split(name)
67
		cmdline = os.path.join( dir, 'cmdline' )
65
	for proc in os.listdir('/proc'):
68
		if not os.path.isfile( cmdline ):
66
		cmdline = os.path.join('/proc', proc, 'cmdline')
67
		try:
68
			with open(cmdline, 'r') as fd:
69
				commandline = fd.read()
70
		except EnvironmentError:
69
			continue
71
			continue
70
		fd = open( cmdline )
71
		cmd = fd.readline()
72
		# kernel thread
72
		# kernel thread
73
		if not cmd:
73
		if not commandline:
74
			continue
74
			continue
75
		if '\x00' in cmd: 
75
		if '\x00' in commandline:
76
			args = cmd.split( '\x00' )
76
			args = commandline.split('\x00')
77
		else:
77
		else:
78
			args = cmd.split(' ')
78
			args = commandline.split(' ')
79
		cmd = shlex.split( name )
80
		if cmd[0] in args:
79
		if cmd[0] in args:
81
			if len( cmd ) > 1 and len( args ) >= len( cmd ):
80
			if len(args) >= len(cmd) > 1:
82
				for i in range( 1, len( cmd ) ):
81
				if all(a == c for a, c in zip(args, cmd)):
83
					print cmd[ i ], args[ i ]
82
					yield proc
84
					if cmd[ i ] != args[ i ]:
85
						break
86
				else:
87
					result.append( file )
88
			else:
83
			else:
89
				result.append( file )
84
				yield proc
90
85
91
	return result
92
86
93
class ServiceInfo( object ):
87
class ServiceInfo( object ):
94
	BASE_DIR = '/etc/univention/service.info'
88
	BASE_DIR = '/etc/univention/service.info'
 Lines 96-103   class ServiceInfo( object ): Link Here 
96
	CUSTOMIZED = '_customized'
90
	CUSTOMIZED = '_customized'
97
	FILE_SUFFIX = '.cfg'
91
	FILE_SUFFIX = '.cfg'
98
92
99
	RUNLEVELS = map(str, range(7)) + ['S']
93
	RUNLEVELS = "0123456S"
100
	INIT_SCRIPT_REGEX = re.compile( '(?P<action>[SK])(?P<code>[0-9]+)(?P<name>.*)' )
94
	INIT_SCRIPT_REGEX = re.compile('(?P<action>[SK])(?P<code>[0-9]{2})(?P<name>.+)')
101
95
102
	def __init__( self, install_mode = False ):
96
	def __init__( self, install_mode = False ):
103
		self.services = {}
97
		self.services = {}
 Lines 106-143   class ServiceInfo( object ): Link Here 
106
			self.update_services()
100
			self.update_services()
107
101
108
	def sysv_infos( self ):
102
	def sysv_infos( self ):
109
		global _runlevels, _init_link
103
		"""Read start/stop levels of services."""
110
104
		for level in ServiceInfo.RUNLEVELS:
111
		for level in _runlevels:
105
			for link in os.listdir('/etc/rc%s.d/' % (level,)):
112
			for link in os.listdir( '/etc/rc%s.d/' % level ):
113
				if not os.path.islink( link ):
106
				if not os.path.islink( link ):
114
					continue
107
					continue
115
				matches = _init_link.match( link )
108
				match = ServiceInfo.INIT_SCRIPT_REGEX.match(link)
116
				if not matches:
109
				if not match:
117
					continue
110
					continue
118
				grp = matches.groupdict()
111
				action, code, name = match.groups()
119
112
				try:
120
				name = grp.get( 'name', '' )
113
					service = self.service[name]
121
				if not name or not name in self.services.keys():
114
				except LookupError:
122
					continue
115
					continue
123
				if grp.get( 'action', '' ) == 'S':
116
				if action == 'S':
124
					self.services[ name ].start_runlevels.append( level )
117
					service.start_runlevels.append(level)
125
					self.services[ name ].start_code = int( grp[ 'code' ] )
118
					service.start_code = int(code)
126
				elif grp.get( 'action', '' ) == 'K':
119
				elif action == 'K':
127
					self.services[ name ].start_runlevels.append( level )
120
					service.stop_runlevels.append(level)
128
					self.services[ name ].start_code = int( grp[ 'code' ] )
121
					service.stop_code = int(code)
129
122
130
	def __update_status( self, name, service ):
123
	def __update_status(self, name, service):
131
		for prog in service[ 'programs' ].split( ',' ):
124
		for prog in service['programs'].split(','):
132
			if prog and not pidof( prog.strip() ):
125
			if prog and not pidof(prog.strip()):
133
				service.running = False
126
				service.running = False
134
				break
127
				break
135
		else:
128
		else:
136
			service.running = True
129
			service.running = True
137
130
138
	def update_services( self ):
131
	def update_services( self ):
132
		"""Update the run state of all services."""
139
		for name, serv in self.services.items():
133
		for name, serv in self.services.items():
140
			self.__update_status( name, serv )
134
			self.__update_status(name, serv)
141
135
142
	def check_services( self ):
136
	def check_services( self ):
143
		"""Return dictionary of incomplete service descriptions."""
137
		"""Return dictionary of incomplete service descriptions."""
 Lines 149-159   class ServiceInfo( object ): Link Here 
149
		return incomplete
143
		return incomplete
150
144
151
	def write_customized( self ):
145
	def write_customized( self ):
146
		"""Save service cusomization."""
152
		filename = os.path.join( ServiceInfo.BASE_DIR, ServiceInfo.SERVICES,
147
		filename = os.path.join( ServiceInfo.BASE_DIR, ServiceInfo.SERVICES,
153
								 ServiceInfo.CUSTOMIZED )
148
								 ServiceInfo.CUSTOMIZED )
154
		try:
149
		try:
155
			fd = open( filename, 'w' )
150
			fd = open(filename, 'w')
156
		except:
151
		except IOError:
157
			return False
152
			return False
158
153
159
		cfg = uit.UnicodeConfig()
154
		cfg = uit.UnicodeConfig()
 Lines 176-189   class ServiceInfo( object ): Link Here 
176
			filename = os.path.join( ServiceInfo.BASE_DIR, ServiceInfo.SERVICES,
171
			filename = os.path.join( ServiceInfo.BASE_DIR, ServiceInfo.SERVICES,
177
									 package + ServiceInfo.FILE_SUFFIX )
172
									 package + ServiceInfo.FILE_SUFFIX )
178
		cfg = uit.UnicodeConfig()
173
		cfg = uit.UnicodeConfig()
179
		cfg.read( filename )
174
		cfg.read(filename)
180
		for sec in cfg.sections():
175
		for sec in cfg.sections():
181
			# service already known?
176
			# service already known?
182
			if not override and sec in self.services.keys():
177
			if not override and sec in self.services:
183
				continue
178
				continue
184
			srv = Service()
179
			srv = Service()
185
			for name, value in cfg.items( sec ):
180
			for name, value in cfg.items(sec):
186
				srv[ name ] = value
181
				srv[name] = value
187
			for path in srv.get('programs', '').split(','):
182
			for path in srv.get('programs', '').split(','):
188
				# "programs" defines the "/proc/self/cmdline" of the service,
183
				# "programs" defines the "/proc/self/cmdline" of the service,
189
				# not the executable, therefore we test for a leading "/":
184
				# not the executable, therefore we test for a leading "/":
 Lines 191-199   class ServiceInfo( object ): Link Here 
191
				if path.startswith('/') and not os.path.exists(path.split(' ', 1)[0]):
186
				if path.startswith('/') and not os.path.exists(path.split(' ', 1)[0]):
192
					break # ==> do not execute else
187
					break # ==> do not execute else
193
			else:
188
			else:
194
				self.services[ sec ] = srv
189
				self.services[sec] = srv
195
190
196
	def __load_services( self ):
191
	def __load_services( self ):
192
		"""Load definition of all defined services."""
197
		path = os.path.join( ServiceInfo.BASE_DIR, ServiceInfo.SERVICES )
193
		path = os.path.join( ServiceInfo.BASE_DIR, ServiceInfo.SERVICES )
198
		for entry in os.listdir( path ):
194
		for entry in os.listdir( path ):
199
			# customized service descrptions are read afterwards
195
			# customized service descrptions are read afterwards
 Lines 206-211   class ServiceInfo( object ): Link Here 
206
		self.read_customized()
202
		self.read_customized()
207
203
208
	def read_customized( self ):
204
	def read_customized( self ):
205
		"""Read service cusomization."""
209
		custom = os.path.join( ServiceInfo.BASE_DIR, ServiceInfo.SERVICES,
206
		custom = os.path.join( ServiceInfo.BASE_DIR, ServiceInfo.SERVICES,
210
							   ServiceInfo.CUSTOMIZED )
207
							   ServiceInfo.CUSTOMIZED )
211
		self.read_services( custom, override = True )
208
		self.read_services( custom, override = True )
 Lines 217-226   class ServiceInfo( object ): Link Here 
217
	def get_service( self, name ):
214
	def get_service( self, name ):
218
		'''returns a service object associated with the given name or
215
		'''returns a service object associated with the given name or
219
		None if it does not exist'''
216
		None if it does not exist'''
220
		self.services.get( name, None )
217
		return self.services.get( name, None )
221
218
222
	def add_service( self, name, service ):
219
	def add_service( self, name, service ):
223
		'''this methods adds a new service object or overrides an old
220
		'''this methods adds a new service object or overrides an old
224
		entry'''
221
		entry'''
225
		if not service.check():
222
		if not service.check():
226
			self.services[ name ] = service
223
			self.services[ name ] = service
224
225
226
if __name__ == '__main__':
227
	import doctest
228
	doctest.testmod()

Return to bug 31030