# Preparing for Application Consistent backups

TrilioVault for RHV does provide the capabilties to take application consistent backups by utilizing the Qemu-Guest-Agent.

## The Qemu-Guest-Agent

The Qemu-Guest-Agent is a component of the qemu hypervisor, which is used by RHV. RHV automatically builds all VMs to be prepared to use the Qemu-Guest-Agent.

The Qemu-Guest-Agent provides many capabilities, including the possibility to freeze and thaw Virtual Machines Filesystems.

{% hint style="warning" %}
The Qemu-Guest-Agent is not developed or maintained by Trilio. Trilio does leverage standard capabilities of the Qemu-Guest-Agent to send freeze and thaw commands to the protected VMS during a backup process.
{% endhint %}

## Installing the Qemu-Guest-Agent

The Qemu-Guest-Agent needs to be installed inside the VM.

{% hint style="info" %}
The Qemu-Guest-Agent requires a special SCSI interface in the VM definition.\
This interface is automatically created by RHV upon spinning up the Virtual Machine.
{% endhint %}

The installation process depends on the Guest Operating System.

### RPM-based Guests

```
yum install qemu-guest-agent
systemctl start qemu-guest-agent
```

### Deb-based Guests

```
apt-get install qemu-guest-agent
systenctk start qemu-guest-agent
```

### Windows Guests

Windows Guests require the installation of the VirtIO drivers and tools.\
These are provided by Red Hat in a prepared ISO-file.\
\
For RHV 4.3 please follow this documentation: [RHV 4.3 Windows Guest Agents](https://access.redhat.com/documentation/en-us/red_hat_virtualization/4.3/html/virtual_machine_management_guide/installing_guest_agents_and_drivers_windows)\
For RHV 4.4 please follow this documentation: [RHV 4.4 Windows Guest Agents](https://access.redhat.com/documentation/en-us/red_hat_virtualization/4.4/html/virtual_machine_management_guide/installing_guest_agents_and_drivers_windows)

## Using the fsfreeze-hook.sh script

The Qemu-Guest-Agent is calling the fsfreeze-hook.sh script either with the freeze or the thaw argument depending on the current operation.

The fsfreeze-hook.sh script is a normal shell script.\
It is typically used to do all necessary steps to get an application into a consistent state for the freeze or to undo all freeze operations upon the thaw.

### Location of the fsfreeze-hook.sh script

The fs-freeze-hook.sh script default path is:

```
/etc/qemu/fsfreeze-hook
```

### Content of the fsfreeze-hook.sh script

The fsfreeze-hook.sh script does not require a special content.

It is recommended to provide a case identifier for the freeze and thaw argument.\
This can be achieved for example by the following bash code:

```
#!/bin/bash

case "$1" in
        freeze)
            #Commands for freeze
            ;;
         
        thaw)
            #Commands for thaw
            ;;
         
        *)
            echo $"Neither freeze nor thaw provided"
            exit 1
            ;;
 
esac
```

### Example fsfreeze-hook.sh for MYSQL

This example flushes the MySQL tables to the disks and keeps a read lock to prevent further write access until the thaw has been done.

```
#!/bin/sh

MYSQL="/usr/bin/mysql"
MYSQL_OPTS="-uroot" #"-prootpassword"
FIFO=/var/run/mysql-flush.fifo
# Check mysql is installed and the server running
[ -x "$MYSQL" ] && "$MYSQL" $MYSQL_OPTS < /dev/null || exit 0
flush_and_wait() {
    printf "FLUSH TABLES WITH READ LOCK \\G\n"
    trap 'printf "$(date): $0 is killed\n">&2' HUP INT QUIT ALRM TERM
    read < $FIFO
    printf "UNLOCK TABLES \\G\n"
    rm -f $FIFO
}
case "$1" in
    freeze)
        mkfifo $FIFO || exit 1
        flush_and_wait | "$MYSQL" $MYSQL_OPTS &
        # wait until every block is flushed
        while [ "$(echo 'SHOW STATUS LIKE "Key_blocks_not_flushed"' |\
                 "$MYSQL" $MYSQL_OPTS | tail -1 | cut -f 2)" -gt 0 ]; do
            sleep 1
        done
        # for InnoDB, wait until every log is flushed
        INNODB_STATUS=$(mktemp /tmp/mysql-flush.XXXXXX)
        [ $? -ne 0 ] && exit 2
        trap "rm -f $INNODB_STATUS; exit 1" HUP INT QUIT ALRM TERM
        while :; do
            printf "SHOW ENGINE INNODB STATUS \\G" |\
                "$MYSQL" $MYSQL_OPTS > $INNODB_STATUS
            LOG_CURRENT=$(grep 'Log sequence number' $INNODB_STATUS |\
                          tr -s ' ' | cut -d' ' -f4)
            LOG_FLUSHED=$(grep 'Log flushed up to' $INNODB_STATUS |\
                          tr -s ' ' | cut -d' ' -f5)
            [ "$LOG_CURRENT" = "$LOG_FLUSHED" ] && break
            sleep 1
        done
        rm -f $INNODB_STATUS
        ;;
    thaw)
        [ ! -p $FIFO ] && exit 1
        echo > $FIFO
        ;;
    *)
        echo $"Neither freeze nor thaw provided"
        exit 1
        ;;
esac
```
