Reconfigurar y reiniciar un esclavo Hudson/Jenkins como parte de una compilación
reboot slave (2)
Tengo una configuración de servidor Jenkins (Hudson) que ejecuta pruebas en una variedad de máquinas esclavas. Lo que quiero hacer es reconfigurar el esclavo (usando API remotas), reiniciar el esclavo para que los cambios tengan efecto, luego continuar con el resto de la prueba. Hay dos obstáculos que he encontrado hasta ahora:
- Una vez que un trabajo de Jenkins comienza a ejecutarse en el esclavo, el esclavo no puede bajar o interrumpir la conexión de red al servidor, de lo contrario, Jenkins inmediatamente falla la prueba. Normalmente, diría que esto es un comportamiento completamente deseable. Pero en este caso, me gustaría que Jenkins acepte la interrupción hasta que el esclavo vuelva a estar en línea y Jenkins pueda reconectarse con él, o el esclavo se vuelva a conectar con Jenkins.
- En un trabajo que se ha adjuntado al esclavo, necesito ejecutar algunas tareas de compilación en el maestro Jenkins, no en el esclavo.
es posible? Hasta el momento, no he encontrado una manera de hacerlo utilizando Jenkins o cualquiera de sus complementos.
EDITAR - Explicación adicional Realmente me gusta mucho la arquitectura esclava de Jenkins. Combinado con los complementos ya disponibles, hace que sea muy fácil conseguir trabajos para un esclavo, ejecutarlos y los resultados reducidos. Y la capacidad de elegir cualquier esclavo coincidente permite la distribución automática de trabajo / prueba.
En nuestra situación, usamos máquinas esclavas virtualizadas (VMware). Fue bastante fácil escribir una secuencia de comandos que haría que Jenkins utilizara VMware PowerCLI para iniciar la VM cuando necesitara ejecutarse en un esclavo, luego enviar el trabajo a la misma y recuperar los resultados. Todo bien.
EXCEPTO Parte de la configuración de cada prueba es reconfigurar ligeramente la máquina virtual de alguna manera. Deshabilite el UAC, inicie sesión como un usuario diferente, tenga un controlador diferente instalado, etc. - cada uno de estos cambios requiere que la VM / esclava de prueba se reinicie antes de que los cambios entren en vigencia. Aunque puedo escribir scripts esclavos a petición (Método de lanzamiento = Ejecutar esclavo mediante la ejecución del comando en el maestro) que manejan esta reconfiguración y reinicio, debe hacerse ANTES de ejecutar el trabajo. Ahí es donde ocurre el problema: no puedo configurar el esclavo tan temprano porque el tipo de cambios de configuración depende del trabajo que se está ejecutando, lo que ocurre solo después de que se inicia el esclavo.
Soluciones posibles
1) Usa múltiples instancias esclavas en una sola máquina virtual. Esto no funcionaría, varias de las configuraciones son mutuamente excluyentes, pero Jenkins no lo sabe. Por lo tanto, intentaría iniciar una configuración de esclavo para un trabajo, otro esclavo para un trabajo diferente, y ambos esclavos estarían en la misma máquina virtual. Los bloqueos en los trabajos no impiden esto, ya que el inicio esclavo no es parte del trabajo.
2) (Óptimo) Un paso de compilación que permite que un trabajo sepa que su conexión esclava PUEDE ser interrumpida. El paso de compilación puede incluir algunas opciones para que Jenkins sepa cómo volver a conectar el esclavo (¿se volverá a conectar el esclavo de forma automática? ¿Jenkins tendrá que ejecutar un script, bastará con SSH simple). El paso de compilación manejaría la desconexión del esclavo, ignoraría la desconexión que generalmente falla en el trabajo, luego realizaría la reconexión. Una vez que el esclavo vuelve a estar en funcionamiento, puede ocurrir el próximo paso de compilación. Tal vez un tiempo de espera para fallar en el trabajo si el esclavo no es reconectable en un cierto período de tiempo.
** Solución actual **: menos que óptima
En este momento, no puedo usar la función esclava de Jenkins. En su lugar, uso una serie de pasos de compilación, ejecutados en el maestro, que usan scripts de Windows y PowerShell para encender la VM, configurar las configuraciones y reiniciarla. La máquina virtual tiene un servidor SSH ejecutándose en ella y la utilizo para cargar archivos de prueba en la máquina virtual de prueba y luego ejecutarlos a distancia. A continuación, descargue los resultados a Jenkins para su manejo por el trabajo. Esta solución es funcional, pero mucho más trabajo que el enfoque típico de esclavos Jenkins. Además, los scripts están dirigidos a una única máquina virtual; No puedo usar fácilmente un grupo de esclavos.
Muy fácil. Usted crea un trabajo maestro que se ejecuta en el máster, desde el trabajo principal al que llama el trabajo del cliente como un paso de compilación (es un nuevo tipo de paso de compilación y me encanta). Debe verificar que el trabajo maestro debe esperar a que finalice el trabajo del cliente. Luego puede ejecutar su script para reconfigurar su cliente y ejecutar la segunda prueba en el cliente.
Una estrategia aún mejor es tener dos nodos ejecutándose en sus máquinas esclavas. Necesita configurar dos nodos en Jenkins. Utilicé esa estrategia con éxito con un esclavo Unix. La razón era que necesitaba configurar diferentes variables de entorno para configurar y no quería insertar eso en los trabajos. Usé clientes ssh, así que no sé si es posible con diferentes tipos de clientes. Puede ejecutar ambas pruebas al mismo tiempo o puede encadenar los trabajos o utilizar la estrategia maestra mencionada anteriormente.
No estoy seguro si esto funcionará para usted, pero puede tratar de hacer que el nodo del agente Jenkins le informe programáticamente al nodo principal que está fuera de línea.
Tuve una situación en la que necesitaba hacer un trabajo en Jenkins que realiza estos pasos (todo mientras se ejecuta en el nodo maestro):
- revertir la VM del nodo del agente Jenkins a una instantánea apagada
- decirle al maestro que el nodo del agente está desconectado (ya que el maestro no parece notar automáticamente que el agente está inactivo, siempre que revierte o apago mis máquinas virtuales)
- alimentar el nodo del agente VM de nuevo
- como una "acción posterior a la compilación", inicie un trabajo separado restringido para ejecutarse en la máquina virtual del nodo del agente
Realizo el paso de desconexión del agente con una solicitud POST de curl, pero puede haber una forma más clara de hacerlo:
curl -d "offlineMessage=&json=%7B%22offlineMessage%22%3A+%22%22%7D&Submit=Yes" http://JENKINS_HOST/computer/THE_NODE_TO_DISCONNECT/doDisconnect
Luego, cuando reinicio el nodo agente, el agente se inicia y se conecta automáticamente, y el maestro nota que el agente está nuevamente en línea (y luego le enviará trabajos).
También pude activar y desactivar la disponibilidad de un nodo con este comando (usando ''toggleOffline'' en lugar de ''doDisconnect''):
curl -d "offlineMessage=back_in_a_moment&json=%7B%22offlineMessage%22%3A+%22back_in_a_moment%22%7D&Submit=Mark+this+node+temporarily+offline" http://JENKINS_HOST/computer/NODE_TO_DISCONNECT/toggleOffline
(Ejecutar el mismo comando vuelve el estado del nodo a la normalidad).
Es posible que lo anterior no se aplique a usted, ya que parece que desea hacer todo lo posible desde un trabajo de jenkins que se ejecuta en el nodo agente. Y no estoy seguro de qué sucede si un nodo agente se desconecta o se marca a sí mismo fuera de línea en medio de la ejecución de un trabajo. :)
Aún así, puede explorar un poco en este documento de API de acceso remoto para ver qué más es posible con este tipo de enfoque.