--- a/branches/ucs-3.1/ucs-3.1-1/management/univention-directory-manager-modules/univention-cli-client
+++ a/branches/ucs-3.1/ucs-3.1-1/management/univention-directory-manager-modules/univention-cli-client
@@ -1,10 +1,9 @@
#!/usr/bin/python2.6
# -*- coding: utf-8 -*-
#
-# Univention Admin Modules
-# the command line client program
+"""Univention Directory Manager command line client program"""
#
-# Copyright 2004-2012 Univention GmbH
+# Copyright 2004-2013 Univention GmbH
#
# http://www.univention.de/
#
@@ -31,130 +30,148 @@
# /usr/share/common-licenses/AGPL-3; if not, see
# .
-
import locale
import socket
import time
import os
import sys
-import string
-import codecs
from univention.config_registry import ConfigRegistry
-socket_dir='/tmp/admincli_%s/' % os.getuid()
-socket_filename='sock'
-socket_path=(socket_dir+socket_filename)
-
-s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-cmd=''
-data=''
-output=[]
-logfile=''
-
-pos = 0
-for arg in sys.argv:
- pos += 1
- if '--logfile' == arg[:9]:
- if len(arg) > 10 and arg[9] == "=":
- logfile = arg[10:]
- else:
+def get_logfile():
+ """Extract logfile from command line arguments."""
+ logfile = ''
+ for pos, arg in enumerate(sys.argv):
+ if arg.startswith('--logfile='):
+ logfile = arg[len('--logfile='):]
+ elif arg.startswith('--logfile'):
try:
- logfile=sys.argv[pos]
- except:
- print "E: Option --logfile requires an argument"
+ logfile = sys.argv[pos + 1]
+ except IndexError:
+ print >> sys.stderr, "E: Option --logfile requires an argument"
sys.exit(1)
-
-try:
- s.connect(socket_path)
-except:
- pid=os.fork()
- if not pid:
- null = os.open('/dev/null', os.O_RDWR)
+ return logfile
+
+
+def fork_server(sock, socket_path):
+ """Fork UDM command line server."""
+ # start new server
+ pid = os.fork()
+ if pid == 0: # child
+ null = os.open(os.path.devnull, os.O_RDWR)
os.dup2(null, sys.stdin.fileno())
os.dup2(null, sys.stdout.fileno())
os.dup2(null, sys.stderr.fileno())
- if len(logfile) >0:
- os.execv('/usr/share/univention-directory-manager-tools/univention-cli-server', ['univention-cli-server', logfile])
- else:
- os.execv('/usr/share/univention-directory-manager-tools/univention-cli-server', ['univention-cli-server'])
- else:
+ argv = ['univention-cli-server']
+ logfile = get_logfile()
+ if logfile:
+ argv.append(logfile)
+ os.execv(
+ '/usr/share/univention-directory-manager-tools/univention-cli-server',
+ argv
+ )
+ else: # parent
os.waitpid(pid, os.P_NOWAIT)
ucr = ConfigRegistry()
ucr.load()
- socket_timeout = int(ucr.get('directory/manager/cmd/sockettimeout', '50'))
- stime=int(time.time())
- while not os.path.exists('%s' % socket_path):
+ socket_timeout = float(ucr.get('directory/manager/cmd/sockettimeout', 50))
+ stime = time.time() + socket_timeout
+ while not os.path.exists(socket_path):
time.sleep(0.1)
- if int(time.time()) > stime+socket_timeout:
- print 'E: Can`t find running daemon after %s Seconds. (No socketfile)' % socket_timeout
+ if time.time() > stime:
+ print >> sys.stderr, \
+ 'E: Can`t find running daemon after %s seconds. (No socketfile)' % \
+ socket_timeout
sys.exit(1)
-
- connection_timeout=30 # this took a long time if getfqdn(host) was used in cli-server
- stime=int(time.time())
- socking=0
- while socking == 0:
+
+ # this takes a long time if getfqdn(host) is used in cli-server
+ connection_timeout = 30
+ stime = time.time() + connection_timeout
+ while True:
try:
- s.connect(socket_path)
- socking=1
- except:
+ sock.connect(socket_path)
+ break
+ except socket.error:
time.sleep(0.1)
- if int(time.time()) > stime+connection_timeout:
- print 'E: Can`t connect daemon after %s seconds.' % connection_timeout
+ if time.time() > stime:
+ print >> sys.stderr, \
+ 'E: Can`t connect daemon after %s seconds.' % \
+ connection_timeout
sys.exit(1)
-
- #sys.exit(1)
-
-cmdfile=os.path.basename(sys.argv[0])
-if cmdfile == 'univention-passwd':
- pwd1='x'
- pwd2='y'
- while pwd1 != pwd2:
- pwd1=raw_input('New password ')
- pwd2=raw_input('Re-enter new password ')
- if pwd1 != pwd2:
- print 'password missmatch'
- sys.argv.append('--pwd')
- sys.argv.append(pwd1)
-
-
-
-s.send(repr(sys.argv)+'\0')
-
-while 1:
- buf = s.recv(1024)
- if len(buf) <= 0:
- print 'E: Daemon died.'
- sys.exit(1)
- elif buf[-1] == '\0':
- buf = buf[0:-1]
- data += buf
- break
- else:
- data += buf
-
-rc=0
-output = eval(data)
-s.close()
-if cmdfile == 'univention-passwd':
- for line in output:
- if line.startswith('passwd error: '):
- print line
+
+
+def get_password():
+ """Query for interactive password."""
+ while True:
+ pwd1 = raw_input('New password ')
+ pwd2 = raw_input('Re-enter new password ')
+ if pwd1 == pwd2:
+ return pwd1
+ print >> sys.stderr, 'password missmatch'
+
+
+def receive_answer(sock):
+ """Receive complete answer from server."""
+ data = ''
+ while True:
+ buf = sock.recv(1024)
+ if len(buf) == 0:
+ print >> sys.stderr, 'E: Daemon died.'
+ sys.exit(1)
+ elif buf[-1] == '\0':
+ buf = buf[0:-1]
+ data += buf
+ break
+ else:
+ data += buf
+ return data
+
+
+def process_output(output, cmdfile):
+ """Print output and check for errors."""
+ result = 0
+ if cmdfile == 'univention-passwd':
+ for line in output:
if line == 'passwd error: password alreay used':
- rc=1
+ result = 1
elif line.startswith('passwd error: The password is to short'):
- rc=2
- else:
+ result = 2
print line
-else:
- if output[-1] == "OPERATION FAILED":
- rc = 3
- output = output [:-1]
- for i in output:
- if type(i) is unicode:
- print i.encode(locale.getpreferredencoding(), 'replace')
- else:
- print i
+ else:
+ if output[-1] == "OPERATION FAILED":
+ result = 3
+ output = output [:-1]
+ for line in output:
+ if isinstance(line, unicode):
+ line = line.encode(locale.getpreferredencoding(), 'replace')
+ print line
+ return result
+
+
+def main():
+ """Forward request to udm-cli-server."""
+ socket_path = '/tmp/admincli_%d/sock' % os.getuid()
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ try:
+ # connect to already running server
+ sock.connect(socket_path)
+ except socket.error:
+ fork_server(sock, socket_path)
+
+ cmdfile = os.path.basename(sys.argv[0])
+ if cmdfile == 'univention-passwd':
+ password = get_password()
+ sys.argv += ['--pwd', password]
+
+ sock.send(repr(sys.argv) + '\0')
+ data = receive_answer(sock)
+ sock.close()
+
+ output = eval(data)
+ result = process_output(output, cmdfile)
+ sys.exit(result)
+
-sys.exit(rc)
+if __name__ == '__main__':
+ main()
--- a/branches/ucs-3.1/ucs-3.1-1/management/univention-directory-manager-modules/univention-cli-server
+++ a/branches/ucs-3.1/ucs-3.1-1/management/univention-directory-manager-modules/univention-cli-server
@@ -1,10 +1,9 @@
#!/usr/bin/python2.6
# -*- coding: utf-8 -*-
#
-# Univention Admin Modules
-# the comannd line server
+"""Univention Directory Manager command line server"""
#
-# Copyright 2004-2012 Univention GmbH
+# Copyright 2004-2013 Univention GmbH
#
# http://www.univention.de/
#
@@ -31,262 +30,224 @@
# /usr/share/common-licenses/AGPL-3; if not, see
# .
-
import SocketServer
import socket
-import select
+from select import select
import os
import sys
import traceback
-import univention.config_registry
-import univention.debug
+from univention.config_registry import ConfigRegistry
+import univention.debug as ud
import univention.admincli.adduser
import univention.admincli.admin
import univention.admincli.passwd
+import signal
try:
import univention.admincli.license_check
- licenseImportError=False
+ licenseImportError = False
except ImportError:
- licenseImportError=True
+ licenseImportError = True
-logfile=''
+logfile = ''
-class myRequestHandler(SocketServer.BaseRequestHandler):
+class MyRequestHandler(SocketServer.BaseRequestHandler):
+ """Handle request on listeneing socket to open new connection."""
def handle(self):
- univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'daemon [%s] new connection [%s]' % (os.getppid(), os.getpid()))
- sarglist=''
- while 1:
+ ud.debug(ud.ADMIN, ud.INFO, 'daemon [%s] new connection [%s]' % (os.getppid(), os.getpid()))
+ sarglist = ''
+ while True:
buf = self.request.recv(1024)
if buf[-1] == '\0':
- buf = buf[0:-1]
+ buf = buf[:-1]
sarglist += buf
break
else:
sarglist += buf
doit(sarglist, self.request)
- univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'daemon [%s] connection closed [%s]' % (os.getppid(), os.getpid()))
-
+ ud.debug(ud.ADMIN, ud.INFO, 'daemon [%s] connection closed [%s]' % (os.getppid(), os.getpid()))
def finish(self):
pass
-class ForkingTCPServer(SocketServer.ForkingTCPServer):
- address_family=socket.AF_UNIX
+class ForkingTCPServer(SocketServer.ForkingTCPServer):
+ """UDM server listening on UNIX socket."""
+ address_family = socket.AF_UNIX
allow_reuse_address = 1
def server_bind(self):
SocketServer.TCPServer.server_bind(self)
- host, port = self.socket.getsockname()[:2]
+ _host, port = self.socket.getsockname()[:2]
self.server_name = 'localhost' #socket.getfqdn(host)
self.server_port = port
+
def main():
+ """UDM command line server."""
global logfile
- logfile=''
- if len(sys.argv) < 2:
- logfile='/var/log/univention/directory-manager-cmd.log'
- else:
- logfile=sys.argv[1]
+ try:
+ logfile = sys.argv[1]
+ except IndexError:
+ logfile = '/var/log/univention/directory-manager-cmd.log'
- socket_dir='/tmp/admincli_%s/' % os.getuid()
- socket_filename='sock'
- socket_path=(socket_dir+socket_filename)
+ socket_dir = '/tmp/admincli_%s/' % os.getuid()
+ socket_filename = 'sock'
+ socket_path = (socket_dir+socket_filename)
- univention.debug.init(logfile, 1, 0)
+ ud.init(logfile, ud.FLUSH, ud.NO_FUNCTION)
- if os.path.isfile('%s.run' % socket_path):
- runs=1
- runfile=open('%s.run' % socket_path, 'r')
- line=runfile.readlines()
- runfile.close()
+ runfilename = '%s.run' % socket_path
+ if os.path.isfile(runfilename):
try:
- pid=line[0]
- except:
- pid=''
- if len(pid)>0 and pid[-1:] == '\n':
- pid = pid[:-1]
- if pid:
- try:
- os.kill(int(pid), 18)
- except OSError:
- pid=''
+ with open(runfilename, 'r') as runfile:
+ line = runfile.readline().strip()
+ pid = int(line)
+ os.kill(pid, signal.SIGCONT)
+ except (ValueError, OSError):
+ pid = 0
if not pid: # no pid found or no server running
- runs=0
os.unlink(socket_path)
- os.unlink('%s.run' % socket_path)
+ os.unlink(runfilename)
os.rmdir(socket_dir)
- if not runs==0:
- print 'E: Server already running [Pid: %s]' % pid
+ else:
+ print >> sys.stderr, 'E: Server already running [Pid: %s]' % pid
sys.exit(1)
- configRegistry=univention.config_registry.ConfigRegistry()
+ configRegistry = ConfigRegistry()
configRegistry.load()
- if configRegistry.has_key('directory/manager/cmd/debug/level'):
- debug_level=configRegistry['directory/manager/cmd/debug/level']
- else:
- debug_level=1
- univention.debug.set_level(univention.debug.ADMIN, int(debug_level))
- univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'daemon [%s] forked to background' % os.getpid())
+ debug_level = configRegistry.get('directory/manager/cmd/debug/level', 1)
+ ud.set_level(ud.ADMIN, int(debug_level))
+ ud.debug(ud.ADMIN, ud.INFO, 'daemon [%s] forked to background' % os.getpid())
try:
os.mkdir(socket_dir)
os.chmod(socket_dir, 0700)
except:
- print 'E: Socket directory exists (%s)' % socket_dir
+ print >> sys.stderr, 'E: socket directory exists (%s)' % socket_dir
- if configRegistry.has_key('directory/manager/cmd/timeout'):
- timeout=configRegistry['directory/manager/cmd/timeout']
+ timeout = configRegistry.get('directory/manager/cmd/timeout')
+ if timeout:
if int(timeout) > 2147483647:
- timeout=2147483647
+ timeout = 2147483647
else:
- timeout=300
- univention.debug.debug(univention.debug.ADMIN, univention.debug.WARN, 'daemon [%s] baseconfig key directory/manager/cmd/timeout not set, setting to default (%s seconds)' % (os.getpid(), timeout))
+ timeout = 300
+ ud.debug(ud.ADMIN, ud.WARN, 'daemon [%s] baseconfig key directory/manager/cmd/timeout not set, setting to default (%s seconds)' % (os.getpid(), timeout))
+
try:
- s=ForkingTCPServer(socket_path, myRequestHandler)
+ sock = ForkingTCPServer(socket_path, MyRequestHandler)
os.chmod(socket_path, 0600)
except:
- print 'E: Failed creating socket (%s). Daemon stopped.' % socket_path
- univention.debug.debug(univention.debug.ADMIN, univention.debug.ERROR, 'daemon [%s] Failed creating socket (%s). Daemon stopped.' %
- (os.getpid(), socket_filename))
+ print >> sys.stderr, 'E: Failed creating socket (%s). Daemon stopped.' % socket_path
+ ud.debug(ud.ADMIN, ud.ERROR, 'daemon [%s] Failed creating socket (%s). Daemon stopped.' % (os.getpid(), socket_filename))
sys.exit(1)
- #s.listen(2)
+ #sock.listen(2)
try:
- runfile=open('%s.run' % socket_path, 'w')
+ runfile = open(runfilename, 'w')
+ runfile.write(str(os.getpid()))
+ runfile.close()
except IOError:
- print 'E: Can`t write runfile'
+ print >> sys.stderr, 'E: Can`t write runfile'
- runfile.write(str(os.getpid()))
- runfile.close()
try:
- while 1:
- input=[]
- output=[]
- exc=[]
- input, output, exc = select.select([s],[],[],float(timeout))
- for handler in input:
+ while True:
+ rlist, _wlist, _xlist = select([sock], [], [], float(timeout))
+ for handler in rlist:
handler.handle_request()
- if not input:
- univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'daemon [%s] stopped after %s seconds idle' % (os.getpid(), timeout))
+ if not rlist:
+ ud.debug(ud.ADMIN, ud.INFO, 'daemon [%s] stopped after %s seconds idle' % (os.getpid(), timeout))
sys.exit(0)
finally:
os.unlink(socket_path)
- os.unlink('%s.run' % socket_path)
+ os.unlink(runfilename)
os.rmdir(socket_dir)
- univention.debug.exit()
+ ud.exit()
def doit(sarglist, conn):
+ """Process single UDM request."""
- def sendMessage(output):
- back=u''
- back=repr(output)
- conn.send(back+'\0')
+ def send_message(output):
+ """Send answer back."""
+ back = repr(output)
+ conn.send(back + '\0')
conn.close()
global logfile
- arglist=eval(sarglist)
-
- l=0
- b=0
- h=0
- lsf=1
- oldlogfile=logfile
- for i in arglist:
- if l == 1:
- logfile=i
- l=0
- if i[:9] == '--logfile':
- if len(i) > 10 and i[9] == "=":
- logfile=i[10:]
- else:
- l=1
- if i[:8] == '--binddn':
- b=1
- if i[:6] == '--help':
- h=1
- if i[:2] == '-h':
- h=1
- if i[:2] == '-?':
- h=1
- if i[:9] == '--version':
- h=1
-
- if b == 0:
- try:
- ls=open('/etc/ldap.secret', 'r')
- except IOError:
+ arglist = eval(sarglist)
+
+ next_is_logfile = False
+ secret = False
+ show_help = False
+ oldlogfile = logfile
+ for arg in arglist:
+ if next_is_logfile == 1:
+ logfile = arg
+ next_is_logfile = False
+ continue
+ if arg.startswith('--logfile='):
+ logfile = arg[len('--logfile='):]
+ elif arg.startswith('--logfile'):
+ next_is_logfile = True
+ secret |= arg == '--binddn'
+ show_help |= arg in ('--help', '-h', '-?', '--version')
+
+ if not secret:
+ for filename in ('/etc/ldap.secret', '/etc/machine.secret'):
try:
- ls=open('/etc/machine.secret', 'r')
+ open(filename, 'r').close()
+ secret = True
+ break
except IOError:
- lsf=0
- if h == 0:
- sendMessage(["E: Permission denied, try --logfile, --binddn and --bindpwd"])
- sys.exit(1)
+ continue
+ else:
+ if not show_help:
+ send_message(["E: Permission denied, try --logfile, --binddn and --bindpwd"])
+ sys.exit(1)
- if logfile!=oldlogfile:
- univention.debug.exit()
- univention.debug.init(logfile, 1, 0)
+ if logfile != oldlogfile:
+ ud.exit()
+ ud.init(logfile, ud.FLUSH, ud.NO_FUNCTION)
- cmdfile=os.path.basename(arglist[0])
- if cmdfile == 'univention-admin' or cmdfile == 'univention-directory-manager' or cmdfile == 'udm':
- univention.debug.debug(univention.debug.ADMIN, univention.debug.PROCESS, 'daemon [%s] [%s] Calling univention-directory-manager' % (os.getppid(), os.getpid()))
- univention.debug.debug(univention.debug.ADMIN, univention.debug.ALL, 'daemon [%s] [%s] arglist: %s' % (os.getppid(), os.getpid(), arglist))
- try:
+ cmdfile = os.path.basename(arglist[0])
+ try:
+ if cmdfile in ('univention-admin', 'univention-directory-manager', 'udm'):
+ ud.debug(ud.ADMIN, ud.PROCESS, 'daemon [%s] [%s] Calling univention-directory-manager' % (os.getppid(), os.getpid()))
+ ud.debug(ud.ADMIN, ud.ALL, 'daemon [%s] [%s] arglist: %s' % (os.getppid(), os.getpid(), arglist))
output = univention.admincli.admin.doit(arglist)
- except:
- info = sys.exc_info()
- output = apply(traceback.format_exception, info)
- output = [line[:-1] for line in output]
- output.append("OPERATION FAILED")
-
- elif cmdfile == 'univention-passwd':
- univention.debug.debug(univention.debug.ADMIN, univention.debug.PROCESS, 'daemon [%s] [%s] Calling univention-passwd' % (os.getppid(), os.getpid()))
- univention.debug.debug(univention.debug.ADMIN, univention.debug.ALL, 'daemon [%s] [%s] arglist: %s' % (os.getppid(), os.getpid(), arglist))
- try:
+ elif cmdfile == 'univention-passwd':
+ ud.debug(ud.ADMIN, ud.PROCESS, 'daemon [%s] [%s] Calling univention-passwd' % (os.getppid(), os.getpid()))
+ ud.debug(ud.ADMIN, ud.ALL, 'daemon [%s] [%s] arglist: %s' % (os.getppid(), os.getpid(), arglist))
output = univention.admincli.passwd.doit(arglist)
- except:
- info = sys.exc_info()
- output = apply(traceback.format_exception, info)
- output = [line[:-1] for line in output]
- output.append("OPERATION FAILED")
- elif cmdfile == 'univention-license-check':
- if licenseImportError:
- output=['The license check is disabled. You are using the GPL version without any support or maintenance by Univention.']
- else:
- univention.debug.debug(univention.debug.ADMIN, univention.debug.PROCESS, 'daemon [%s] [%s] Calling univention-license-check' % (os.getppid(), os.getpid()))
- univention.debug.debug(univention.debug.ADMIN, univention.debug.ALL, 'daemon [%s] [%s] arglist: %s' % (os.getppid(), os.getpid(), arglist))
- try:
+ elif cmdfile == 'univention-license-check':
+ if licenseImportError:
+ output = ['The license check is disabled. You are using the GPL version without any support or maintenance by Univention.']
+ else:
+ ud.debug(ud.ADMIN, ud.PROCESS, 'daemon [%s] [%s] Calling univention-license-check' % (os.getppid(), os.getpid()))
+ ud.debug(ud.ADMIN, ud.ALL, 'daemon [%s] [%s] arglist: %s' % (os.getppid(), os.getpid(), arglist))
output = univention.admincli.license_check.doit(arglist)
- except:
- info = sys.exc_info()
- output = apply(traceback.format_exception, info)
- output = [line[:-1] for line in output]
- output.append("OPERATION FAILED")
- else:
- univention.debug.debug(univention.debug.ADMIN, univention.debug.PROCESS, 'daemon [%s] [%s] Calling univention-adduser' % (os.getppid(), os.getpid()))
- univention.debug.debug(univention.debug.ADMIN, univention.debug.ALL, 'daemon [%s] [%s] arglist: %s' % (os.getppid(), os.getpid(), arglist))
- try:
+ else:
+ ud.debug(ud.ADMIN, ud.PROCESS, 'daemon [%s] [%s] Calling univention-adduser' % (os.getppid(), os.getpid()))
+ ud.debug(ud.ADMIN, ud.ALL, 'daemon [%s] [%s] arglist: %s' % (os.getppid(), os.getpid(), arglist))
output = univention.admincli.adduser.doit(arglist)
- except:
- info = sys.exc_info()
- output = apply(traceback.format_exception, info)
- output = [line[:-1] for line in output]
- output.append("OPERATION FAILED")
+ except:
+ ext, exv, extb = sys.exc_info()
+ output = traceback.format_exception(ext, exv, extb)
+ output = [line[:-1] for line in output]
+ output.append("OPERATION FAILED")
- sendMessage(output)
+ send_message(output)
- if h == 1 and b == 0 and lsf == 0:
- univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'daemon [%s] [%s] stopped, because User has no read/write permissions' % (os.getppid(), os.getpid()))
+ if show_help and not secret:
+ ud.debug(ud.ADMIN, ud.INFO, 'daemon [%s] [%s] stopped, because User has no read/write permissions' % (os.getppid(), os.getpid()))
sys.exit(0)
if __name__ == "__main__":
pid = os.fork()
- if not pid:
+ if pid == 0: # child
os.setsid()
main()
sys.exit(0)
- else:
- os.waitpid(pid,os.P_NOWAIT)
+ else: # parent
+ os.waitpid(pid, os.P_NOWAIT)