root/wifi-ltsp/trunk/transformaArchivos.py @ 56
50 | jredrejo | #!/usr/bin/python
|
|
44 | jredrejo | # -*- coding: utf-8 -*-
|
|
50 | jredrejo | # Project: wifi-ltsp
|
|
# Module: transformaArchivos.py
|
|||
# Purpose: Genera archivo de macs con horarios desde Rayuela y Ldap
|
|||
# Language: Python 2.5
|
|||
# Date: 03-Feb-2011.
|
|||
# Ver: 07-Feb-2011.
|
|||
# Author: Francisco Mora Sánchez
|
|||
# Copyright: 2011 - Francisco Mora Sánchez <adminies.maestrojuancalero@edu.juntaextremadura.net>
|
|||
#
|
|||
# wifi-ltsp is free software: you can redistribute it and/or modify
|
|||
# it under the terms of the GNU General Public License as published by
|
|||
# the Free Software Foundation, either version 3 of the License, or
|
|||
# (at your option) any later version.
|
|||
# Script2 is distributed in the hope that it will be useful,
|
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|||
# GNU General Public License for more details.
|
|||
# You should have received a copy of the GNU General Public License
|
|||
# along with wifi-ltsp. If not, see <http://www.gnu.org/licenses/>.
|
|||
44 | jredrejo | ||
""" Programa para generar los archivos necesarios para permitir
|
|||
que los portátiles de los alumnos puedan unirse al punto de acceso
|
|||
hostapd del profesor, según el horario del propio profesor, y los
|
|||
alumnos que tienen clase con él a esa hora.
|
|||
Partiremos de los archivos de datos generados por Rayuela, el formato
|
|||
de estos archivos es: por cada centro hay un directorio con cinco archivos
|
|||
uno por cada día de la semana, llamados Lunes.txt, Martes.txt, Miercoles.txt,
|
|||
Jueves.txt y Viernes.txt. Cada uno de estos archivos de texto contienen
|
|||
la siguiente información:
|
|||
D.N.I. del docente|N.I.A. del alumno|Hora de inicio|Hora de fin
|
|||
08848648L|3251023|815|870|
|
|||
08848648L|3383767|815|870|
|
|||
08848648L|3383770|815|870|
|
|||
la primera línea indica la estructura y a partir de ésta están los datos
|
|||
que son: dni del profesor, nie del alumno y horas de inicio y fin expresadas
|
|||
como minutos transcurridos desde las 00:00 horas.
|
|||
Los ficheros que se generan, deben copiarse al directorio de destino
|
|||
especificado como parámetro, y que en caso de no darse será por defecto
|
|||
"/var/www/wifi/(lunes.txt|martex.txt|miercoles.txt|jueves.txt|viernes.txt)"
|
|||
si la ruta no existe, ésta se creará. Para escribir en el destino debemos
|
|||
tener los privilegios adecuados.
|
|||
Los archivos que generaremos, tendrán el mismo nombre, sin mayúsculas, pero
|
|||
el formato será el siguiente:
|
|||
login_profesor|mac_alumno|inicio|fin|
|
|||
no tenemos línea descriptora de estructura, y los datos se obtienen de
|
|||
realizar consulta al directorio ldap del centro, para lo cual es necesario
|
|||
que tengamos instalado el paquete python-ldap, además de python, claro está.
|
|||
El dato de login_profesor es directo en la consulta a ldap, así como la
|
|||
generación de las horas y minutos, pero el dato de mac_alumno, se realiza
|
|||
consultando ldap para obtener el login del alumno, que concuerda con el
|
|||
nombre del portátil asignado al alumno. A partir de este dato accederemos
|
|||
a la información recogida por puppet de cada ordenador, que se encuentra
|
|||
en /var/lib/puppet/yaml/node/(login_del_alumno.dominiodelcentro).yaml,
|
|||
para obtener la mac de la interfaz wifi asociada a ese portátil. Las
|
|||
líneas importantes son: macaddress_wlan0 o macaddress_eth1 que se
|
|||
establece en algunos modelos de portátiles.
|
|||
Uso: crearemos una carpeta donde copiaremos este programa y además
|
|||
pondremos los txts obtenidos por Rayuela, ejecutaremos el script pasando
|
|||
como parámetros el lugar donde están los archivos con el parámetro
|
|||
--datosrayuela rutarayuela, y tambien el lugar donde queremos depositar los
|
|||
archivos generados, con el parámetros --datosservidor rutaservidor.
|
|||
Si --datosrayuela no se establece, asumiremos el directorio actual, si
|
|||
--datosservidor no está establecido, se establecerá internamente en
|
|||
/var/www/wifi, creando la estructura de directorios mencionada si es que
|
|||
no existe, además comprobaremos que disponemos de privilegios para escribir
|
|||
en el directorio de destino.
|
|||
Francisco Mora Sánchez
|
|||
IES Maestro Juan Calero
|
|||
adminies.maestrojuancalero@edu.juntaextremadura.net
|
|||
"""
|
|||
import sys,os,ldap,time,errno,re
|
|||
import ldap
|
|||
# Expresiones Regulares.
|
|||
_re_mode = (re.I | re.M | re.S)
|
|||
macwlan0_pattern = re.compile('.*macaddress_wlan0: (.*?)\n', _re_mode)
|
|||
maceth1_pattern = re.compile('.*macaddress_eth1: (.*?)\n', _re_mode)
|
|||
def EjecutaRegex(regex, cadena):
|
|||
""" ejecuta búsqueda de expresión regular en una cadena """
|
|||
m = regex.search(cadena)
|
|||
if m:
|
|||
return m.groups()[0]
|
|||
else:
|
|||
return None
|
|||
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 dameDatosLineaRayuela(linea):
|
|||
"""Funcion que trocea la linea de datos de rayuela y
|
|||
devuelve un diccionario cuyas claves son login_profesor
|
|||
login_alumno, inicio y final
|
|||
"""
|
|||
datos = linea.split("|")
|
|||
return { "dni_profesor" : datos[0], "nie_alumno" : datos[1], "inicio" : datos[2], "final" : datos[3]}
|
|||
def consultaLdap(identificador):
|
|||
"""Función que consulta el servidor ldap, con el atributo
|
|||
employeeNumber. Devuelve el login asociado al profesor o al alumno
|
|||
"""
|
|||
try:
|
|||
l = ldap.open("ldap")
|
|||
except ldap.LDAPError, e:
|
|||
print e
|
|||
return "ERRORLDAP"
|
|||
base_dn='ou=People,dc=instituto,dc=extremadura,dc=es'
|
|||
searchFilter = '(employeeNumber='+identificador+')'
|
|||
searchScope = ldap.SCOPE_SUBTREE
|
|||
retrieveAttributes = ['uid']
|
|||
try:
|
|||
ldap_result_id = l.search(base_dn, searchScope, searchFilter, retrieveAttributes)
|
|||
result_type, result_data = l.result(ldap_result_id, 0)
|
|||
if len(result_data)==0:
|
|||
#print "la búsqueda no da ningún resultado"
|
|||
return "NO ENCONTRADO"
|
|||
elif len(result_data)>1:
|
|||
#print "La búsqueda da más de un resultado"
|
|||
resultado= result_data[0]
|
|||
else:
|
|||
resultado=result_data[0]
|
|||
#print resultado[1]['uid'][0]
|
|||
except ldap.LDAPError, e:
|
|||
print e
|
|||
print "ERRORLDAP"
|
|||
return resultado[1]['uid'][0]
|
|||
def obtenerMac(login_alumno, archivosYaml, datosyaml):
|
|||
"""Función que dado un login de alumno, buscará en el archivo yaml
|
|||
de puppet asociado a ese login de alumno, la cadena macaddress_wlan0,
|
|||
o bien macaddress_eth1 en caso que no exista la primera. Esta función
|
|||
quizá se deba testear bien.
|
|||
Tenemos disponible la lista archivosYaml con todos los archivos yaml
|
|||
de puppet, incluyendo sus rutas...
|
|||
"""
|
|||
#Primero buscamos el archivo en cuestion, tendrá el login_alumno mas
|
|||
#un punto, dominio, punto y terminación yaml, busquemos el patrón con dos puntos
|
|||
#ya que suele haber archivos fantasmas con el nombre solamente.
|
|||
for a in archivosYaml:
|
|||
if a.count(".") == 2:
|
|||
#Estamos en un patrón de archivo correcto.
|
|||
pos = a.find(".")
|
|||
sufijo = a[pos:]
|
|||
break
|
|||
archivoDatosYaml = login_alumno + sufijo
|
|||
try:
|
|||
filearchivoDatosYaml = open(os.path.join(datosyaml,archivoDatosYaml), "r")
|
|||
except:
|
|||
pass
|
|||
return "NO:EN:CO:NT:RA:DA"
|
|||
contenidoyaml = filearchivoDatosYaml.read()
|
|||
filearchivoDatosYaml.close()
|
|||
#print contenidoyaml
|
|||
mac = EjecutaRegex(macwlan0_pattern, contenidoyaml)
|
|||
if mac == None:
|
|||
mac = EjecutaRegex(maceth1_pattern, contenidoyaml)
|
|||
#print mac
|
|||
if mac == None:
|
|||
mac = "NO:EN:CO:NT:RA:DA"
|
|||
return mac
|
|||
def transformaHora(datohora):
|
|||
"""Función que pasado un parámetro numérico que almacena los minutos
|
|||
desde las 00:00.
|
|||
Devuelve una cadena en la forma "08:35", con la hora y los minutos.
|
|||
"""
|
|||
hora = datohora // 60
|
|||
minutos = datohora % 60
|
|||
48 | elisa_apar | return "%02d%02d" % (hora,minutos)
|
|
44 | jredrejo | ||
def transformaArchivos(datosrayuela, datosservidor, datosyaml, debug = False):
|
|||
#Comprobemos la existencia del directorio de datos de Rayuela
|
|||
if not os.path.exists(datosrayuela):
|
|||
if debug:
|
|||
print "Directorio para datos de rayuela",datosrayuela,"no existe, abortando ejecución..."
|
|||
return 1
|
|||
#Comprobemos que sea un directorio
|
|||
if not os.path.isdir(datosrayuela):
|
|||
if debug:
|
|||
print "Directorio para datos de rayuela",datosrayuela,"no es un directorio, abortando ejecución..."
|
|||
return 2
|
|||
#Comprobemos que tengamos permisos de apertura y lectura de archivos
|
|||
if os.path.isdir(datosrayuela):
|
|||
try:
|
|||
archivosRayuela = os.listdir(datosrayuela)
|
|||
except:
|
|||
if debug:
|
|||
print "Directorio para datos de rayuela",datosrayuela,"problemas de permisos en carpeta, abortando ejecución..."
|
|||
return 3
|
|||
#Comprobemos que existe el directorio de destino
|
|||
if not os.path.exists(datosservidor):
|
|||
#No existe directorio de destino, debemos crearlo
|
|||
if debug:
|
|||
print "No existe directorio de destino en servidor",datosservidor,"se intentará crear directorio..."
|
|||
try:
|
|||
os.makedirs(datosservidor)
|
|||
except OSError:
|
|||
if debug:
|
|||
print "Hay algún problema con la creación del directorio de destino, abortando ejecución..."
|
|||
return 4
|
|||
#Comprobemos que tenemos permisos de escritura
|
|||
if os.path.exists(datosservidor):
|
|||
if not os.access(datosservidor, os.W_OK):
|
|||
if debug:
|
|||
print "Hay algún problema de permisos para la creación de archivos en el directorio de destino del servidor, abortando ejecución..."
|
|||
return 5
|
|||
#Comprobemos la existencia del directorio de datos yaml de puppet
|
|||
if not os.path.exists(datosyaml):
|
|||
if debug:
|
|||
print "Directorio para datos yaml de puppet",datosyaml,"no existe, abortando ejecución..."
|
|||
return 6
|
|||
#Comprobemos que sea un directorio
|
|||
if not os.path.isdir(datosyaml):
|
|||
if debug:
|
|||
print "Directorio para datos yaml de puppet",datosyaml,"no es un directorio, abortando ejecución..."
|
|||
return 7
|
|||
#Comprobemos que tengamos permisos de apertura y lectura de archivos
|
|||
if os.path.isdir(datosyaml):
|
|||
try:
|
|||
#archivosYaml = glob.glob(os.path.join(params["datosyaml"],"*.*.yaml"))
|
|||
archivosYaml = os.listdir(datosyaml)
|
|||
except:
|
|||
if debug:
|
|||
print "Directorio para datos yaml de puppet",datosyaml,"problemas de permisos en directorio, abortando ejecución..."
|
|||
return 8
|
|||
#Limpiemos las listas de archivos
|
|||
archivosRayuela = [ archivo for archivo in archivosRayuela if archivo in ["Lunes.txt","Martes.txt","Miercoles.txt","Jueves.txt","Viernes.txt"]]
|
|||
archivosYaml = [ archivo for archivo in archivosYaml if archivo[-5:] == ".yaml"]
|
|||
#print archivosRayuela
|
|||
#print archivosYaml
|
|||
#Para evitar consultar al servidor ldap varias veces para un mismo dni o nie crearemos
|
|||
#dos diccionarios, uno para profesores y otro para alumnos con los datos que
|
|||
#recuperaremos del servidor ldap, además otro con los logins de alumnos y
|
|||
#las macs
|
|||
#profesores = { "dni" : "login_profesor", ... }
|
|||
#alumnos = { "nie" : "login_alumno", ... }
|
|||
#macs = { "login_alumno" : "mac", ... }
|
|||
profesores = {}
|
|||
alumnos = {}
|
|||
macs = {}
|
|||
#Procesemos cada archivo de Rayuela
|
|||
for archivoRayuela in archivosRayuela:
|
|||
if debug:
|
|||
print "Procesando archivo",os.path.join(datosrayuela,archivoRayuela)
|
|||
filearchivoRayuela = open(os.path.join(datosrayuela,archivoRayuela), 'r')
|
|||
archivoServidor = os.path.join(datosservidor,archivoRayuela.lower())
|
|||
if debug:
|
|||
print "Generando archivo",archivoServidor
|
|||
filearchivoServidor = open(archivoServidor, 'w')
|
|||
while True:
|
|||
linea = filearchivoRayuela.readline()
|
|||
if not linea:
|
|||
break
|
|||
if linea[:6] == "D.N.I.":
|
|||
continue
|
|||
#Procesemos cada linea de Rayuela
|
|||
#datosLineaRayuela es un diccionario cuyas claves son dni_profesor, nie_alumno, inicio, final
|
|||
datosLineaRayuela = dameDatosLineaRayuela(linea)
|
|||
datosLineaServidor = ""
|
|||
#Consultemos el login del profesor en ldap por su dni y el nie del alumno
|
|||
#comprobando que no lo hemos encontrado previamente
|
|||
if profesores.has_key(datosLineaRayuela["dni_profesor"]):
|
|||
login_profesor = profesores[datosLineaRayuela["dni_profesor"]]
|
|||
#if debug:
|
|||
# print "Nooooo se consulta a ldap, profesor dni",datosLineaRayuela["dni_profesor"],"pertenece a",login_profesor
|
|||
else:
|
|||
login_profesor = consultaLdap(datosLineaRayuela["dni_profesor"])
|
|||
profesores[datosLineaRayuela["dni_profesor"]] = login_profesor
|
|||
if debug:
|
|||
print "Se consulta a ldap, profesor dni",datosLineaRayuela["dni_profesor"],"pertenece a",login_profesor
|
|||
if alumnos.has_key(datosLineaRayuela["nie_alumno"]):
|
|||
login_alumno = alumnos[datosLineaRayuela["nie_alumno"]]
|
|||
#if debug:
|
|||
# print "Nooooo se consulta a ldap, alumno nie",datosLineaRayuela["nie_alumno"],"pertenece a",login_alumno
|
|||
else:
|
|||
login_alumno = consultaLdap(datosLineaRayuela["nie_alumno"])
|
|||
alumnos[datosLineaRayuela["nie_alumno"]] = login_alumno
|
|||
if debug:
|
|||
print "Se consulta a ldap, alumno nie",datosLineaRayuela["nie_alumno"],"pertenece a",login_alumno
|
|||
if macs.has_key(login_alumno):
|
|||
mac_alumno = macs[login_alumno]
|
|||
#if debug:
|
|||
# print "Nooooo se consultan datos yaml, alumno login",login_alumno,"tiene mac",mac_alumno
|
|||
else:
|
|||
mac_alumno = obtenerMac(login_alumno, archivosYaml, datosyaml)
|
|||
#mac_alumno = obtenerMac("dmoral01", archivosYaml, datosyaml)
|
|||
macs[login_alumno] = mac_alumno
|
|||
if debug:
|
|||
print "Se consultan datos yaml, alumno login",login_alumno,"tiene mac",mac_alumno
|
|||
48 | elisa_apar | inicio = transformaHora(int(datosLineaRayuela["inicio"]))
|
|
final = transformaHora(int(datosLineaRayuela["final"]))
|
|||
datosLineaServidor = login_profesor+"|"+mac_alumno+"|"+str(inicio)+"|"+str(final)+"|"+"\n"
|
|||
#datosLineaServidor = login_profesor+"|"+mac_alumno+"|"+datosLineaRayuela["inicio"]+"|"+datosLineaRayuela["final"]+"|"+"\n"
|
|||
44 | jredrejo | if debug:
|
|
print datosLineaServidor
|
|||
filearchivoServidor.write(datosLineaServidor)
|
|||
filearchivoRayuela.close()
|
|||
filearchivoServidor.close()
|
|||
return 0
|
|||
if __name__ == '__main__':
|
|||
params = {}
|
|||
lista = sys.argv
|
|||
lee_parametros(lista,params)
|
|||
#comprobaremos las combinaciones de parametros en linea de comandos
|
|||
if len(lista) == 2 and lista[1] == "--help":
|
|||
print 'uso: ./transformaArchivos.py [--datosrayuela rutadatosrayuela] [--datosservidor rutadatosservidor] [--datosyaml rutadatosyaml]'
|
|||
sys.exit(1)
|
|||
if not params.has_key("datosrayuela"):
|
|||
print "No se ha establecido la ruta a la carpeta con los datos de rayuela, usando por defecto '"+os.getcwd()+"'"
|
|||
params["datosrayuela"] = os.getcwd()
|
|||
if not params.has_key("datosservidor"):
|
|||
print "No se ha establecido la ruta dónde depositar los archivos generados, usando por defecto '/var/www/wifi'"
|
|||
params["datosservidor"] = "/var/www/wifi"
|
|||
if not params.has_key("datosyaml"):
|
|||
print "No se ha establecido la ruta dónde se encuentran los datos yaml de puppet, usando por defecto '/var/lib/puppet/yaml/node'"
|
|||
params["datosyaml"] = "/var/lib/puppet/yaml/node"
|
|||
print
|
|||
print "Los valores pasado son los siguientes:"
|
|||
print "Directorio de datos de Rayuela:",params["datosrayuela"]
|
|||
print "Directorio de datos de para el servidor:",params["datosservidor"]
|
|||
print "Directorio de datos yaml de puppet:",params["datosyaml"]
|
|||
resultado = transformaArchivos(params["datosrayuela"], params["datosservidor"], params["datosyaml"], True)
|
|||
if resultado > 0:
|
|||
print "Se ha producido errores en el procesamiento, código de error",resultado
|
|||
else:
|
|||
print "Se ha ejecutado correctamente"
|
|||
exit(resultado)
|