Index: update-fotos-ldap/trunk/actualizafotosldap.py
===================================================================
--- update-fotos-ldap/trunk/actualizafotosldap.py	(nonexistent)
+++ update-fotos-ldap/trunk/actualizafotosldap.py	(revision 47)
@@ -0,0 +1,247 @@
+#!/usr/bin/python -tt
+# -*- coding: utf-8 -*-
+
+""" Programa para actualizar las fotos de los alumnos
+en el servidor ldap a partir del fichero de alumnos generado por
+Rayuela. Tambien depura las entradas del grupo students, eliminando
+aquellas membresias cuyos uids no están en la rama People, si lo queremos.
+
+Necesita paquetes instalados python python-ldap python-imaging
+
+En los servidores de terminales está todo instalado excepto python-ldap
+que se carga ejecutando la orden como superusuario:
+
+apt-get install python-ldap
+
+Uso: crearemos una carpeta donde copiaremos este programa y además 
+pondremos el ZIP generado por Rayuela, denominado
+ExportacionDatosAlumnado.zip, ejecutaremos el script pasando como 
+parámetros como mínimo la contraseña del administrador ldap, por defecto
+el programa establece el URI ldap de nuesto servidor ldap y la ruta a la 
+carpeta con el ZIP de rayuela en la propia carpeta.
+
+Existe un parámetro, denominado --depurastudents {on|off} el cual si lo 
+establecemos a on, eliminará del grupos students de ldap aquellas entradas
+que no tienen un uid en el grupo People, normalmente son residuos de
+uids de alumnos que ya no están en el centro.
+
+OJO: Realizar copias de seguridad de ldap antes de ejecutar el script...
+
+
+Francisco Mora Sánchez
+IES Maestro Juan Calero
+adminies.maestrojuancalero@edu.juntaextremadura.net
+
+
+"""
+
+import sys,os,shutil,zipfile,ldap,Image,glob,time,copy
+import ldap.modlist as modlist
+
+# Set debugging level
+#ldap.set_option(ldap.OPT_DEBUG_LEVEL,255)
+#ldap.set_option(ldap.OPT_DEBUG_LEVEL,0)
+#ldapmodule_trace_level = 1
+#ldapmodule_trace_level = 0
+#ldapmodule_trace_file = sys.stderr
+
+def descomprime_zip_en_directorio(fichero, carpeta):
+	"""Funcion que dado un fichero zip lo descomprime en la
+	carpeta indicada."""
+	if os.path.exists(carpeta):
+		shutil.rmtree(carpeta)
+	os.mkdir(carpeta, 0777)
+	zfobj = zipfile.ZipFile(fichero)
+	for name in zfobj.namelist():
+		if name.endswith('/'):
+			os.mkdir(os.path.join(carpeta, name))
+		else:
+			outfile = open(os.path.join(carpeta, name), 'wb')
+			outfile.write(zfobj.read(name))
+			outfile.close()
+			
+def lee_parametros(lista,params):
+	"""Funcion que crea un diccionario para leer el valor de los 
+	parametros que se pasan en la linea de comandos."""
+	for i in range(1,len(lista)):
+		if lista[i][:2] == "--":
+			#veamos si tiene valor
+			if i+1 < len(lista) and lista[i+1] <> "--":
+				#estamos en un parametro y valor
+				params[lista[i][2:]] = lista[i+1]
+
+def conecta_a_ldap(uri,contra):
+	""" Conexión al servidor ldap
+	"""
+	try:
+		usuario_admin = "cn=admin,ou=People,dc=instituto,dc=extremadura,dc=es"
+		#conexion_ldap = ldap.initialize(uri,trace_level=ldapmodule_trace_level,trace_file=ldapmodule_trace_file)
+		conexion_ldap = ldap.initialize(uri)
+		conexion_ldap.protocol_version=ldap.VERSION3
+		conexion_ldap.bind_s(usuario_admin, contra)
+	except ldap.LDAPError, e:
+		return None
+	
+	return conexion_ldap
+
+def desconecta_de_ldap(conexion_ldap):
+	""" Desconectar del servidor ldap
+	"""
+	conexion_ldap.unbind_s()
+
+def buscar_en_ldap(conexion_ldap, filtro, atributos, baseDN = "ou=People,dc=instituto,dc=extremadura,dc=es", alcance = ldap.SCOPE_SUBTREE):
+	## Realiza una consulta al servidor ldap, utilizando un filtro y delvolviendo unos atributos, la salida es una lista de tuplas
+	try:
+		return conexion_ldap.search_s(baseDN, alcance, filtro, atributos)
+	except:
+		pass
+	else:
+		return []
+
+def existeArchivoImagen(archivo):
+	""" Funcion que determina si existe un archivo 
+	"""
+	return os.path.exists(archivo)
+
+def main():
+	params = {}
+	lista = sys.argv
+	lee_parametros(lista,params)
+	#comprobaremos las combinaciones de parametros en linea de comandos
+	if not params.has_key("contra"):
+		print 'uso: ./actualizafotosldap.py --contra contraseña_ldap [--depurastudents {on,off}] [--urildap ldaps://servidor_ldap:puerto] [--ruta rutaalarchivozipderayuela]'
+		sys.exit(1)
+	if not params.has_key("urildap"):
+		print "No se ha establecido el servidor ldap, usando por defecto 'ldaps://ldap:636'"
+		params["urildap"] = "ldaps://ldap:636"
+	if not params.has_key("ruta"):
+		print "No se ha establecido la ruta del archivo, usando por defecto './ExportacionDatosAlumnado.zip'"
+		params["ruta"] = "./ExportacionDatosAlumnado.zip"
+	if not params.has_key("depurastudents"):
+		print "No se ha establecido depurastudents, no se eliminarán alumnos del grupo students que no existan en la rama People"
+		params["depurastudents"] = "off"
+	
+	#Emite mensajes
+	print "Los valores pasado son los siguientes:"
+	print "URI Servidor ldap: ",params["urildap"]
+	print "Ruta al archivo: ",params["ruta"]
+	print "Eliminar alumn@s del grupo students no existentes en People:",params["depurastudents"]
+	print "Si estás conforme, pulsa intro, sino pulsa CTRL+C y aborta la ejecución"
+	raw_input()
+	#Comprobemos la existencia del archivo
+	if not os.path.exists(params["ruta"]):
+		print params['ruta']," no existe"
+		exit(2)
+	print "Intentando la conexión al URI de ldap '"+params["urildap"]+"'"
+
+	conexion_ldap = conecta_a_ldap(params["urildap"],params["contra"])
+		
+	if conexion_ldap == None:
+		print "Error en la conexión al servidor ldap:",params["urildap"],"revise nombre servidor y/o contraseña"
+		exit(3)
+	
+	#busqueda de los alumnos(pertenecen al grupo students
+	resultado_busqueda_alumnos = buscar_en_ldap(conexion_ldap, 'member=*', ['member','memberUid'],baseDN="cn=students,ou=Group,dc=instituto,dc=extremadura,dc=es")
+
+	if resultado_busqueda_alumnos is None:
+		print "No existen alumnos que pertenezcan al grupo students..."
+		exit(4)
+
+	print "Descomprimiendo ZIP de alumnos de rayuela en la carpeta actual..."
+	descomprime_zip_en_directorio(params["ruta"], "temp")
+
+			
+	alumnos = resultado_busqueda_alumnos[0][1]["memberUid"]
+	encontrados = 0
+	alumnos_a_borrar_grupo_students = []
+	print "Total de alumnos encontrados",len(alumnos)
+	print "Procesando alumnos..."
+	separador = os.sep
+	tipos_imagen = ['.jpg', '.png', '.jpeg' , '.bmp', '.tiff','.jpg']
+	alumnos_sin_foto = []
+	for alumno in alumnos:
+		datos_alumno = buscar_en_ldap(conexion_ldap, 'uid='+alumno, ['cn','uid','employeeNumber'])
+		if len(datos_alumno) == 0:
+			alumnos_a_borrar_grupo_students.append(alumno)
+		else:
+			encontrados += 1
+			try:
+				if not datos_alumno[0][1].has_key('employeeNumber'):
+					print "El alumno",alumno,"no tiene atributo 'employeeNumber'... saltando"
+					continue
+				if not datos_alumno[0][1].has_key('uid'):
+					print "El alumno",alumno,"no tiene atributo 'uid'... saltando"
+					continue
+				
+				nie = datos_alumno[0][1]['employeeNumber'][0]
+				print "Actualizando foto del alumno",datos_alumno[0][1]['cn'][0],'Nie:',nie
+				archivo_imagen_sin_tipo = '.'+separador+'temp'+separador+nie
+				encontrada_foto = False
+				for patron in tipos_imagen:
+					archivo_imagen = archivo_imagen_sin_tipo+patron
+					if existeArchivoImagen(archivo_imagen):
+						print "encontrado archivo de imagen",archivo_imagen
+						encontrada_foto = True
+						break
+				if not encontrada_foto:
+					alumnos_sin_foto.append(datos_alumno[0][1]['cn'][0]+' Nie:'+nie)
+					print "alumno sin archivo de imagen"
+					continue
+					
+				foto = Image.open(archivo_imagen)
+				if (not foto.format == 'JPEG'):
+					foto.save('foto', 'JPEG')
+					foto = Image.open('foto')
+				foto.thumbnail((80, 100), Image.ANTIALIAS)
+				foto.save('foto', 'JPEG')
+				uid = datos_alumno[0][1]['uid'][0]
+				dn='uid='+uid+',ou=People,dc=instituto,dc=extremadura,dc=es'
+				atributos = [ (ldap.MOD_DELETE,'jpegPhoto',None) ]
+				conexion_ldap.modify_s(dn,atributos)
+				atributos = [ (ldap.MOD_ADD,'jpegPhoto',open('foto',"rb").read()) ]
+				conexion_ldap.modify_s(dn,atributos)
+			except ldap.LDAPError,e:
+				pass  
+				#puede pasar que no exista el nie o bien no tenga atributo, pero 
+				#la acción es ignorar los errores...
+
+	os.remove('foto')	
+	
+	print "Se han procesado",encontrados,"alumn@s..."
+	print ""
+	print ""
+	print "No se han encontrado las fotos de estos",len(alumnos_sin_foto),"alumn@s"
+	print "Estos son los alumno@s sin foto:"
+	for asinfoto in alumnos_sin_foto:
+		print asinfoto
+		
+	print ""
+	print ""
+	print "No se han encontrado en la rama People",len(alumnos)-encontrados,"alumn@s"
+	if params["depurastudents"] == "on" and len(alumnos) > encontrados:
+		print ""
+		print ""
+		print "Procediendo al borrado de alumnos del grupo students no existentes en la rama People"
+		resultado_busqueda_alumnos_modificado = copy.deepcopy(resultado_busqueda_alumnos)
+		for aborrar in alumnos_a_borrar_grupo_students:
+			print "Borrando membresía de students para el alumno no existente ...",aborrar
+			#Eliminamos de la lista de memberUid ese alumno
+			resultado_busqueda_alumnos_modificado[0][1]['memberUid'].remove(aborrar)
+			#Eliminamos de la lista de member ese alumno
+			resultado_busqueda_alumnos_modificado[0][1]['member'].remove('uid='+aborrar+',ou=People,dc=instituto,dc=extremadura,dc=es')
+	
+		print "Ejecutando modificación en el árbol ldap..."
+		dn = 'cn=students,ou=Group,dc=instituto,dc=extremadura,dc=es'
+		ldif = modlist.modifyModlist(resultado_busqueda_alumnos[0][1],resultado_busqueda_alumnos_modificado[0][1])
+		conexion_ldap.modify_s(dn,ldif)
+
+	print ""
+	print ""
+	print "Eliminando carpeta temporal..."
+	shutil.rmtree("temp")
+	print "Desconectando del servidor ldap '"+params["urildap"]+"'"
+	desconecta_de_ldap(conexion_ldap)
+
+
+if __name__ == '__main__':
+	main()

Property changes on: update-fotos-ldap/trunk/actualizafotosldap.py
___________________________________________________________________
Added: svn:executable
