"Después del juego es antes del juego"
Sepp Herberger

martes, 27 de octubre de 2015

Desactivar el audio HDMI y dejar solo el sonido analógico mediante una tarea puppet.

En algunos de nuestros PC el sistema identifica 2 tarjetas de sonido: la tarjeta analógica tradicional y otra salida digital vinculada a la salida HDMI de la tarjeta VGA. Tenemos los altavoces conectados a la salida analógica, de tal manera que si por cualquier motivo en pulseaudio se selecciona (y pasa, no sabemos como, pero pasa) de forma espontánea la salida digital, el sonido deja de salir por los altavoces normales, que quedan mudos ante el desconcierto de los usuarios.

Lo solucionaremos en dos partes: primero veremos como hacer desaparecer la tarjeta de sonido digital y luego como automatizarlo vía puppet.

1. Desactivar la tarjeta de sonido.

En Debian Squeeze esto se evitaba blacklistando el módulo del kernel que maneja la tarjeta digital de audio (snd_hda_codec_hdmi), pero en Wheezy este método no funcionaba así como así. Menos mal que nuestro compañero Ricardo encontró la solución con el siguiente comando:
# echo 1 > "/sys/bus/pci/devices/..../remove"
Este comando enviado al dispositivo pci en concreto que representa nuestra tarjeta digital de audio hace que se vaporice, desapareciendo del hardware de la máquina, de pulseaudio y de todos lados. La tarjeta analógica queda como única salida de audio.

Antes hay que saber exactamente cual es el dispositivo pci asociado a la tarjeta de audio:
bus=$(lspci | grep "RV620 HDMI Audio" | cut -d" " -f1)
if [ -n $bus ]
then
      echo 1 > "/sys/bus/pci/devices/0000:00:01.0/0000:$bus/remove"
fi
Siendo "RV620 HDMI Audio" la cadena que identifica nuestra tarjeta de audio HDMI (la descripción se saca con la orden lspci) y debería adaptarse la tarjeta que tenga cada cual. Escrito de forma mas breve sería:
bus=$(lspci | grep "RV620 HDMI Audio" | cut -d" " -f1); test -n $bus && echo 1 > "/sys/bus/pci/devices/0000:00:01.0/0000:$bus/remove"
Como debe ejecutarse al arrancar el sistema, para que quede desactivado desde el principio, el sitio mas adecuado es en /etc/rc.local, antes del exit 0 con el que acaba dicho script.

2. Insertar una línea en rc.local de forma automatizada vía puppet.

Si queremos meter esta línea en rc.local vía puppet (para así poder aplicarlo de forma automatizada en un grupo de máquinas) tenemos que encontrar la manera de añadir dicha línea en el fichero antes del exit 0, verificando que no estuviera ya. Hay varias maneras de hacerlo, pero me he decantado por usar un define de puppet.

Actualmente tengo en /etc/puppet/defines/* de mi servidor puppet un conjunto de funciones puppet útiles para tratar con ficheros y lineas de texto. Es una gran idea cogida de mi compañero Esteban Navas y son una serie de funciones descritas en https://projects.puppetlabs.com/projects/puppet/wiki/Simple_Text_Patterns/1:

  • delete_lines.pp
  • line.pp
  • prepend_if_no_such_line.pp
  • replace.pp

Aunque ninguna servía para hacer lo que quiero (añadir una línea que no está antes del "exit 0" del rc.local), los defines anteriores me sirven de base para hacerlo. El nuevo define en cuestión queda:
# cat /etc/puppet/defines/add_line_above.pp

#Añade la linea "line" al fichero "file", siempre que la cadena "search" no esté en el fichero.
#La línea la añade inmediatamente por encima de la línea que contenga la cadena "above".
#Usado por ejemplo para añadir lineas a /etc/rc.local por encima del "exit 0" con el cual
#siempre finaliza dicho script.

define add_line_above($file, $line, $search, $above) {
    exec { "/bin/sed -i '/${above}/i\\${line}' '${file}' ":
           unless => "/bin/grep -q '${search}' '${file}'"
    }
}
A continuación tenemos que referenciar este define metiéndolo en el init.pp de una tarea puppet específica que hagamos o bien añadiéndolo a una ya hecha (yo prefiero eso: hacer tareas omnibús que aplican conjuntos de pequeños ajustes de configuración antes que llenar todo de pequeñas tareitas haiku muy especializadas)

Sea como fuere, en el init.pp que escojamos tenemos que importar los .pp de /etc/puppet/defines, poniendo al principio del fichero, antes del "class":
import "/etc/puppet/defines/*.pp"
Y luego dentro del "class":
add_line_above { desactiva_audio_hdmi:
              file=> "/etc/rc.local",
              line=> 'bus=$(lspci | grep "RV620 HDMI Audio" | cut -d" " -f1); test -n $bus && echo 1 > "/sys/bus/pci/devices/0000:00:01.0/0000:$bus/remove"',
              search=> "RV620",
              above=> "^exit 0$"
}

Y ya está. Eso lo que hará será modificar el fichero rc.local de todos los equipos que usen la clase puppet para añadir:
bus=$(lspci | grep "RV620 HDMI Audio" | cut -d" " -f1); test -n $bus && echo 1 > "/sys/bus/pci/devices/0000:00:01.0/0000:$bus/remove"
Justo antes del exit 0 con el que finaliza dicho fichero. Y con esto ya tenemos ambos objetivos conseguidos, trabajo hecho :-).


No hay comentarios:

Publicar un comentario