PDA

Ver la Versión Completa : Recompilar módulo de VirtualBox automáticamente.



jcsl
25-mar-2013, 22:24
Hola.

Estoy haciendo un script en Python para que se recompile automáticamente el módulo del kernel cada vez que se actualice éste (si es que se instaló VirtualBox usando su repositorio y no el que viene con openSUSE). De momento llevo ésto:



#!/usr/bin/python
# -*- coding: utf-8 -*-


from pyinotify import *
from Queue import Queue
import time
import subprocess
import random
import re


_DEPURACION_ACTIVA = True



class ProcesadorNotificacion (ProcessEvent):

_DIRECTORIO_REGISTRO = "/var/log/zypp"
_ARCHIVO_REGISTRO = "history"
_RUTA_ARCHIVO_REGISTRO = os.path.join (_DIRECTORIO_REGISTRO, _ARCHIVO_REGISTRO)
_MASCARA_DIRECTORIO = IN_CREATE
_MASCARA_ARCHIVO = IN_MODIFY


def __init__ (self, watchManager):
if _DEPURACION_ACTIVA:
print "Iniciando ProcesadorNotificacion"

self._colaEventos = Queue ()
self._watchManager = watchManager

try:
# Abrir el archivo de registro en modo solo lectura
self._fichero = open (self._RUTA_ARCHIVO_REGISTRO, "r")

# Avanzar en el fichero hasta el final: solo interesan las líneas nuevas
while True:
linea = self._fichero.readline()
if not linea:
break

# Iniciar un objeto Consumidor y añadir el observador del fichero del historial
self._consumidor = Consumidor (self._colaEventos)
self._consumidor.start ()
self._watchManager.add_watch (self._RUTA_ARCHIVO_REGISTRO, self._MASCARA_ARCHIVO)

except IOError:
# Si aún no existe el fichero que se quiere observar
# se observa el directorio que lo debería contener
# a la espera de que se cree dicho fichero
self._fichero = None
self._consumidor = None
self._watchDescriptor = self._watchManager.add_watch (self._DIRECTORIO_REGISTRO, _MASCARA_DIRECTORIO).get (self._DIRECTORIO_REGISTRO)

if _DEPURACION_ACTIVA:
print "\tProcesadorNotificacion: " + self._RUTA_ARCHIVO_REGISTRO + " no existe aún"


def process_IN_CREATE (self, event):
if _DEPURACION_ACTIVA:
print "ProcesadorNotificacion (IN_CREATE): %s " % os.path.join (event.path, event.name)

# Comprobar si el fichero que se acaba de crear es el que interesa
if event.path == self._DIRECTORIO_REGISTRO and event.name == self._ARCHIVO_REGISTRO:
try:
self._consumidor = Consumidor (self._colaEventos)
self._consumidor.start ()
self._fichero = open (self._RUTA_ARCHIVO_REGISTRO, "r")
self._watchManager.rm_watch (self._watchDescriptors)
self._watchManager.add_watch (self._RUTA_ARCHIVO_REGISTRO, self._MASCARA_ARCHIVO)
except IOError:
if _DEPURACION_ACTIVA:
print "ERROR: no se pudo abrir el archivo '" + self._RUTA_ARCHIVO_REGISTRO + "' para su monitorización"


def process_IN_MODIFY (self, event):
if _DEPURACION_ACTIVA:
print "ProcesadorNotificacion (IN_MODIFY): %s " % os.path.join (event.path, event.name)

self._colaEventos.put (self._fichero.readline ())

"""
QUIZÁS DEBERÍA CONTROLAR TAMBIÉN IN_DELETE SOBRE EL FICHERO
"""

def termina (self):
if _DEPURACION_ACTIVA:
print "ProcesadorNotificacion.termina ()"

if self._fichero is not None:
self._fichero.close ()

if self._consumidor is not None:
self._consumidor.termina ()
self._colaEventos.put ("Terminar")



class Consumidor (threading.Thread):

def __init__ (self, queue):
if _DEPURACION_ACTIVA:
print "Iniciado Consumidor"

threading.Thread.__init__(self)
self._colaEventos = queue
self._terminar = False


def run (self):
if _DEPURACION_ACTIVA:
print "Consumidor.run (): Iniciando bucle de proceso"

while not self._terminar:
linea = self._colaEventos.get ()

if _DEPURACION_ACTIVA:
print "Procesando línea: " + linea

"""
Líneas de prueba:

2013-03-16 02:18:12|install|kernel-desktop|3.7.10-1.1.1|x86_64|2783:y2base|openSUSE-12.3-1.7|15ecf7915419c5b0fc620e62b935aee3a352da084ebc75 12bb68043b7eae7423|
2013-03-17 20:27:09|install|kernel-devel|3.7.10-1.1.1|noarch||repo-oss|1db8bc637a404d206f01b0a254eeb26713f0bdf2aa74df a9ce2c38714d959ffc|
2013-03-17 20:27:12|install|kernel-xen-devel|3.7.10-1.1.1|x86_64||repo-oss|337e97646062889a88d2c80800ea826286f74a958b1fa6 0f8d19aa1eaef78d1f|
2013-03-17 20:27:12|install|kernel-desktop-devel|3.7.10-1.1.1|x86_64|root@jcsl.phenom|repo-oss|dcc7a1bcf807600586f18eb92fb4e3a07b1862121a4d3c a51d0486b5490b0cb6|
2013-03-17 20:27:13|install|kernel-default-devel|3.7.10-1.1.1|x86_64||repo-oss|faad7fba66bf4a8de0b772efa2d922b1ab160055e37a28 fadea102e998f3bce8|
2013-03-17 20:27:14|install|kernel-syms|3.7.10-1.1.1|x86_64|root@jcsl.phenom|repo-oss|b555bbe9fff88463498fc32158641e64718af7c6564227 662c36afbed5653389|
"""
kernel = re.match ("^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\|install\|kernel-(desktop|pae|default)(\|*\|)+", linea)
if not kernel is None:
print "\tIniciando compilación del módulo"
#subprocess.call (["/etc/init.d/vboxdrv", "setup"])
print "\tFinalizada la compilación del módulo"
else:
print "\tLínea no significativa: no se hace nada"

if _DEPURACION_ACTIVA:
print "Consumidor.run (): Finalizado bucle de proceso"


def termina (self):
if _DEPURACION_ACTIVA:
print "Consumidor.termina ()"

self._terminar = True



def main (args):
watchManager = WatchManager()
procesadorNotificacion = ProcesadorNotificacion (watchManager)
notificador = Notifier (watchManager, procesadorNotificacion)

while True:
try:
notificador.process_events()
if notificador.check_events():
# Leer los eventos notificados y añadirlos a la cola
notificador.read_events()
except KeyboardInterrupt:
# Destruir la instacia de inotify cuando ocurra esta interrupción (detener monitorización)
notificador.stop()
procesadorNotificacion.termina ()
break



if __name__ == '__main__':
main(sys.argv)



¿Cómo lo veis? ¿Qué se os ocurre que pueda añadir (o que sobre)?

Un saludo.

DiabloRojo
27-mar-2013, 12:11
¿Cómo lo veis? ¿Qué se os ocurre que pueda añadir (o que sobre)?

Un saludo.Menos mal que estudio python y entiendo lo que escribes. :D

Pero ¿cuando ejecutaria el script?, ¿cuando se instale una nueva versión de VirtualBox o cuando se instale un nuevo kernel o ambos casos?

Anda, amplia la información o pon mas comentarios en el script de lo que hay que poner en las partes que te falta. :adios:

jcsl
27-mar-2013, 22:07
Hola.


Menos mal que estudio python y entiendo lo que escribes. :D

Pero ¿cuando ejecutaria el script?, ¿cuando se instale una nueva versión de VirtualBox o cuando se instale un nuevo kernel o ambos casos?

Anda, amplia la información o pon mas comentarios en el script de lo que hay que poner en las partes que te falta. :adios:

El script se ejecutaría o bien creando un servicio para systemd o lanzándolo desde after.local. Una vez en marcha lo que hace es comprobar los cambios en el fichero /var/log/zypp/history cada vez que desde algún programa (zypper, rpm, Apper o YaST) se instale o desinstale algo. Si detecta que se ha actualizado el kernel entonces ejecuta la orden /etc/init.d/vboxdrv setup para recompilar el módulo de VirtualBox del kernel. El programa está siempre durmiendo mientras no reciba una notificación del sistema indicando que se ha modificado el archivo history (para eso es pyinotify) por lo que no consume recursos innecesariamente. En resumidas cuentas es una especie de dkms, aunque tiene otros usos potenciales: puedes añadir cualquier orden que quieras ejecutar cada vez que se (des)instalen programas.

Obviamente esto es solo útil en el caso de que instales VirtualBox con el paquete que ellos ofrecen en su repositorio. Si lo instalas desde el de openSUSE al actualizar el kernel se actualizarán también los paquetes de VirtualBox sin recompilar nada.

Estar está completo. Lo que preguntaba es si ya que estoy puesto se le ocurre a alguien algo que le pueda añadir o que sobre por lo que sea (por ejemplo, el comprobar si el archivo existe no creo que sea necesario pero aún así lo he añadido por si acaso). En realidad es una chorrada porque tampoco cuesta nada ejecutar el vboxdrv setup cuando se actualiza el kernel, pero uno es vago y andaba aburrido, XD.

Un saludo.

DiabloRojo
27-mar-2013, 22:52
Coño, pues dedicarte a otras cosas XDDDDD.

Mira si yo soy como tu: Acabo de hacerle a otro un script (http://www.forosuse.org/forosuse/showthread.php?t=29610). :adios: