RHEV: recovery VM in Unknown state

If an operation that implies a state change on a VM fails, sometimes RHEV sets the VM status to ‘Unknown’.
This morning, after a fail of a ‘Power off’ operation on a VM in panic – due to a bug ([vdsm] AttributeError: GuestAgent instance has no attribute ‘_sock’) – the VM state was set to ‘Unknown’.
In this case basically you don’t can do anything…
If you know the real state of your VM, you can manually change it and restart the VM. So I set the state of my VM to 0 (stopped) and I restarted it.

[root@rhevm ~]# psql -U engine
psql (8.4.20)
Digita "help" per avere un aiuto.

engine=> select vm_guid from vm_static where vm_name='server.example.com';
vm_guid
--------------------------------------
2d1e72a1-16c4-4f38-a21e-78113669dd98
(1 riga)

engine=> select status from vm_dynamic where vm_guid='2d1e72a1-16c4-4f38-a21e-78113669dd98';
status
--------
7
(1 riga)

engine=> update vm_dynamic set status=0 where vm_guid='2d1e72a1-16c4-4f38-a21e-78113669dd98';
UPDATE 1
[oVirt shell (connected)]# action vm server.example.com start

job-id : 7f1ac179-047c-4d50-932f-3ae7970c96e2
status-state: complete
vm-id : 2d1e72a1-16c4-4f38-a21e-78113669dd98

Bash: using fifo

I wrote two bash scripts with consumer-producer paradigm on a fifo (named pipe).

This is a simple example:

## producer.sh
...
fifo="/path/to/fifo"

consumer.sh &
while [ ! -p "${fifo}" ]; do
sleep 1
done

while [...]; do
echo "message for logging"
echo "message for fifo" >"${fifo}"
done

...

## consumer.sh
...
fifo="/path/to/fifo"

trap "rm -f ${fifo}" INT EXIT TERM

[ -p "${fifo}" ] || mkfifo "${fifo}"

while read line <"${fifo}"; do
echo ${line}
done

...

These scripts have two problems: (1) for each echo (write) in the producer, bash open the fifo, write on it and close it (but this is not a real problem…); (2)  for each read in the consumer (in the while loop), bash has the same behaviour (open, read, close). This causes a failure on the write in the producer (errno==EPIPE) when the fifo is closed for reading.

Solution: use the standard template open -> read/write (in the while loop) -> close

## producer.sh
...
fifo="/path/to/fifo"

consumer.sh &
while [ ! -p "${fifo}" ]; do
sleep 1
done

exec 10>"${fifo}"

while [...]; do
echo "message for logging"
echo "message for fifo" >&10
done

exec 10>&-
...

## consumer.sh
...
fifo="/path/to/fifo"
trap "rm -f ${fifo}" INT EXIT TERM

[ -p "${fifo}" ] || mkfifo "${fifo}"

exec 10<"${fifo}"

while read line <&10; do
echo ${line}
done

exec 10<&-
...

Change the stdin/out/err of a running process

If you have a running process (es. a daemon) and you want modify his stdin, stdout or stderr, this is the way you can do it:

$ gdb -p 4227

(gdb) p close(0)
$1 = 0
(gdb) p close(1)
$2 = 0
(gdb) p close(2)
$3 = 0
(gdb) p creat(“/tmp/test_input”, 0644)
$4 = 0
(gdb) p creat(“/tmp/test_output”, 0644)
$5 = 1
(gdb) p creat(“/tmp/test_error”, 0644)
$6 = 2
(gdb) quit

$ ls -l /proc/4227/fd
totale 0
lrwx—— 1 francesco users 64 23 apr 09:50 0 -> /tmp/test_input
lrwx—— 1 francesco users 64 23 apr 09:50 1 -> /tmp/test_output
lrwx—— 1 francesco users 64 23 apr 09:50 2 -> /tmp/test_error