2012-02-18 9 views
6

Sto cercando di evitare una condizione di gara quando si sostituisce il software dietro un servizio fantoccio.Come posso fare in modo che puppet interrompa un servizio prima di sostituire un file?

Per fare questo, fantoccio ha bisogno di fermare il servizio, sostituire l'eseguibile, quindi inizio il servizio. C'è un modo per parlare di burattini per farlo? Il suo modo preferito di fare le cose sembra essere quello di sostituire l'eseguibile, quindi controllare lo stato e riavviare il servizio se necessario.

(. Questo esempio è artificiosa la condizione di competizione vera e propria non è neanche lontanamente questo semplice ...)

Ecco il burattino manifesto che sto usando per simulare questo problema:

$O = '1' 
$I = '2' 

exec { hi : 
     command => '/bin/echo "$(/bin/date +%s) puppet says hello" >> /tmp/freebird.log' , 
     } 

file { exe : 
     name => "/tmp/freebird" , 
     ensure => present , 
     owner => "root" , 
     group => "root" , 
     mode => "0555" , 
     source => "/root/test-v$I" , 
     } 

file { init : 
     name => '/etc/init.d/freebird' , 
     ensure => present, 
     owner => "root", 
     group => "root", 
     mode => "0555", 
     source => "/root/test.init" , 
     } 

service { freebird : 
     ensure => running, 
     enable => true, 
     hasrestart => true, 
     hasstatus => true, 
     require => [ File[init], File[exe] ], 
     } 

Ecco il test-v1 file. Il file test-v2 è lo stesso ma con v=2.

#!/bin/bash 
v=1 

while true 
do 
     echo "$(date +%s) $v" >> /tmp/freebird-v.log 
     sleep 1 
done 

e lo script init.d: ​​

#!/bin/bash 
# 
# /etc/rc.d/init.d/freebird 

# chkconfig: 2345 90 10 
# description:  freebird 
# Provides:   freebird 
# Required-Start: $syslog $remote_fs 
# Should-Start: 
# Required-Stop:  $syslog $remote_fs 
# Should-Stop: 
# Default-Start:  2 3 4 5 
# Default-Stop:  0 1 6 
# Short-Description: freebird 


# Source function library. 
. /etc/rc.d/init.d/functions 

xme=freebird 
export PATH=/sbin:/bin:/usr/sbin:/usr/bin 

function L() { 
     echo "$(date +%s) $*" 1>&2 
     echo "$(date +%s) $*" >> /tmp/$xme.log 
     } 


case "$1" in 
     (start) L $1 $xme 
       (/tmp/$xme &) 
       ;; 
     (stop) L $1 $xme 
       fuser -k /tmp/$xme 
       ;; 
     (status) L $1 $xme 
       /sbin/fuser /tmp/$xme >/dev/null 2>&1 
       ;; 
     (restart) L $1 $xme 
       $0 stop 
       $0 start 
       ;; 
     (*) 
       echo "Usage: $xme {start|stop|status|restart]" 
       exit 1 
       ;; 
esac 

risposta

2

Sto cercando di evitare una condizione di competizione quando si sostituisce il software dietro a un servizio di marionette.

Per fare ciò, puppet deve interrompere il servizio, sostituire l'eseguibile, quindi avviare il servizio. C'è un modo per parlare di burattini per farlo? Il suo modo preferito di fare le cose sembra essere quello di sostituire l'eseguibile, quindi controllare lo stato e riavviare il servizio se necessario.

Quindi il problema con ciò che Puppet sta facendo attualmente è che dovrebbe sempre essere riavviato il servizio dopo la sostituzione di determinati file?

In tal caso, è necessario utilizzare una relazione di notifica/sottoscrizione per attivare sempre il riavvio del servizio dopo la sostituzione dei file. Prendendo il tuo esempio service, possiamo aggiungere abbonamenti ai file che lo compongono (allo stesso modo che potresti con una configurazione) e questo attiverà un riavvio se uno di loro cambia.

service { freebird : 
     ensure => running, 
     enable => true, 
     hasrestart => true, 
     hasstatus => true, 
     require => [ File[init], File[exe] ], 
     subscribe => [ File[init], File[exe] ], 
     } 

L'altro modo di farlo è utilizzare la gestione dei pacchetti del sistema operativo, a cui Puppet ha un valido supporto. Dovresti quindi attivare il riavvio (o un arresto/avvio nell'installazione pre/post) dagli script del pacchetto, lasciando a Puppet la certezza che il servizio sia configurato e in esecuzione. Dai uno sguardo a Jordan Sissel fpm project per uno strumento per creare facilmente molti formati di pacchetti.

+0

M0dlx, grazie. Il tuo commento mi ha spinto sulla strada giusta. Se dovessi fare tutto da zero, utilizzerei sicuramente la funzione di pre-installazione del pacchetto del sistema operativo invece di forzare puppet a gestirlo. E fpm lo rende molto più facile ... – bugi

+0

@ m0dlx, ho un dubbio. Cosa succede se il mio manifest è come 'File ['X'], File ['Y'], File ['Z'] -> Servizio ['XYZ'] {sottoscrivi: File ['X', 'Y']}' ? Il servizio verrà eseguito/riavviato solo dopo che il file 'Z' 'è stato creato o verrà riavviato @ ogni momento' il file X/Y/Z' è stato modificato. – harshad

1

Riformulerò la domanda per chiarezza e ricerca, quindi fornirò una soluzione.

Suggerirei tuttavia che, se si ha la possibilità di farlo, utilizzare la funzione di preinstallazione del proprio sistema di imballaggio nativo.

Q: Come emulare lo script di pre-installazione di rpm tramite puppet. Un caso d'uso è fermare il servizio fantoccio prima di installare l'eseguibile, quindi riavviarlo dopo aver sostituito il file. Questo è in contrasto con il normale ordinamento di puppet di sostituire il file, quindi riavviare il servizio.

Fortunatamente, il mio caso d'uso richiede già il pasticcio di symlink.Se il tuo no, per favore pubblica la tua soluzione.

Per eseguire il test che comprende i file qui sotto, posso modificare $tversion in test.pp quindi incollare questo nel mio terminale:

fuser /tmp/freebird-v.log /tmp/freebird 
: > /tmp/freebird.log 
echo ==== >> /tmp/freebird.log ; puppet apply --verbose --onetime --no-daemonize test.pp 2>&1 | tee ~/D ; cat /tmp/freebird.log 
ps auxww|grep freebird 
fuser /tmp/freebird-v.log /tmp/freebird 

File test.pp:

$tversion = '1' 

exec { hi : 
     command => '/bin/echo "$(/bin/date +%s) puppet says hello" >> /tmp/freebird.log' , 
     } 

file { exe : 
     name => "/tmp/freebird-v$tversion" , 
     ensure => present , 
     owner => "root" , 
     group => "root" , 
     mode => "0555" , 
     content => template("/root/test-template") , 
     } 

file { exe_ln : 
     name => "/tmp/freebird" , 
     ensure => link , 
     owner => "root" , 
     group => "root" , 
     mode => "0555" , 
     target => "/tmp/freebird-v$tversion" , 
     } 

file { init : 
     name => '/etc/init.d/freebird' , 
     ensure => present, 
     owner => "root", 
     group => "root", 
     mode => "0555", 
     source => "/root/test.init" , 
     } 

exec { freebird_stop_if_incoherent : 
     command => '/sbin/service freebird stop' , 
     refreshonly => false , # required for when entering at exe_ln 
     onlyif => "/sbin/service freebird status && ! test /tmp/freebird -ef '/tmp/freebird-v$tversion'" , # short-circuits the refreshonly for most cases 
     } 

service { freebird : 
     ensure => running, 
     enable => true, 
     hasrestart => true, 
     hasstatus => true, 
     } 

File[exe_ln]   <~ Exec[freebird_stop_if_incoherent] 
Service[freebird]  <- File[exe_ln] 

File modello di prova:

#!/bin/bash 
v=<%= tversion %> 

while true 
do 
     echo "$(date +%s) $v" >> /tmp/freebird-v.log 
     sleep 1 
done 

File test.init:

#!/bin/bash 
# 
# /etc/rc.d/init.d/freebird 

# chkconfig: 2345 90 10 
# description:  freebird 
# Provides:   freebird 
# Required-Start: $syslog $remote_fs 
# Should-Start: 
# Required-Stop:  $syslog $remote_fs 
# Should-Stop: 
# Default-Start:  2 3 4 5 
# Default-Stop:  0 1 6 
# Short-Description: freebird 


# Source function library. 
. /etc/rc.d/init.d/functions 

xme=freebird 
export PATH=/sbin:/bin:/usr/sbin:/usr/bin 

function L() { 
     local pid=$$ 
     local ppid=$(ps l $pid |awk '{print $4}' |tail -1) 
     local extra="-- $(ps $ppid|tail -1|sed 's,^[^/]*/,/, ; s,/[0-9][^/]*/,/,')" 
     echo "$(date +%s) $pid $ppid $* $extra" 1>&2 
     echo "$(date +%s) $pid $ppid $* $extra" >>/tmp/$xme.log 2>&1 
     } 


case "$1" in 
     (start) L $1 $xme 
       fuser /tmp/$xme >/dev/null 2>&1 || (/tmp/$xme &) 
       ;; 
     (stop) L $1 $xme 
       fuser /tmp/$xme 2>&1 
       fuser -k /tmp/$xme 1>&2 ||true 
       fuser /tmp/$xme 2>&1 
       true 
       ;; 
     (status) L $1 $xme 
       /sbin/fuser /tmp/$xme >/dev/null 2>&1 
       ;; 
     (restart) L $1 $xme 
       fuser -k /tmp/$xme 1>&2 ||true 
       (/tmp/$xme &) 
       ;; 
     (*) 
       echo "Usage: $xme {start|stop|status|restart]" 
       exit 1 
       ;; 
esac 
Problemi correlati