Mounting LVM nested Partitons

With this post, I want to describe how you can mount partitions, nested within LVM volumes. A possible use-case includes file based backup of virtual machines running on LVM volumes.

In the example below, I use a Windows Server 2008 system partition (NTFS). The Windows server is running on a Debian KVM system.

You will need:

  • kpartx
  • (In this exampe also ntfs-3g)

Lets get started – first some information about the LVM setup:


root@SERVER:/# lvdisplay
  --- Logical volume ---
  LV Name                /dev/lvm/windoze2k8
  VG Name                lvm
  LV UUID                836UYu-lmuT-qCUg-2lRx-QNgZ-COf7-h6NUH6
  LV Write Access        read/write
  LV Status              available
  # open                 0
  LV Size                19.53 GiB
  Current LE             5000
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           254:1

The partition table of our LVM volume:


root@SERVER:/# fdisk -l /dev/lvm/windoze2k8

Disk /dev/lvm/windoze2k8: 21.0 GB, 20971520000 bytes
255 heads, 63 sectors/track, 2549 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x1a13ce21

                       Device Boot      Start         End      Blocks   Id  System
/dev/lvm/windoze2k81   *           1        2550    20477952    7  HPFS/NTFS

Now, lets move on to the the actual doing:


root@SERVER:~# kpartx -a /dev/lvm/windoze2k8
root@SERVER:~# mkdir /mnt/lvm-windoze2k81 && mount /dev/mapper/lvm-windoze2k81 /mnt/lvm-windoze2k81

Et voila:


root@SERVER:~# ls /mnt/lvm-windoze2k81
autoexec.bat  bootmgr       config.sys              hiberfil.sys  PerfLogs     Program Files  System Volume Information  Windows
Boot          BOOTSECT.BAK  Documents and Settings  pagefile.sys  ProgramData  $RECYCLE.BIN   Users

To remove the mapping, do the following:


root@SERVER:/# umount /mnt/lvm-windoze2k81
root@SERVER:/# kpartx -d /dev/lvm/windoze2k8

Note
If you want to use such a setup to do file based backup of running virtual machines, it is wise to create a LVM snapshot first and applying kpartx on the snapshot device.

Application backup – Scripted pre- and postbackup actions

Many of today’s businesses rely heavily on their application servers. The times of simple fileshares and single-document based processes are over and with them the time of simple filecopy as a method of backing up is over.

In this article I want to describe a method to backup the two most common components of a modern application service: filesystem and database.
No matter how you solve your backup, the approach should always make sure, that the database integrity is given and that the filesystem is in sync with the database state.

The following two scripts are deployed as a Pre- and a Post backup script. The Pre- Backup script stops the application, dumps the database contents, creates a LVM snapshot and re-starts the application. Post- Backup removes the snapshot.

The fileset for the backup application would then look like this:
Database dumps: /dbdump
Filesystem snapshot: /volume-snapshot

appbackup-run-before.sh


#!/bin/bash
#
# Application Service Backup - Part 1 of 2
#
# Pre-Backup script
# - Stops Service
# - Takes a MySQL Dump
# - Creates a LVM Snapshot
# - Restarts Service
# - Mounts the LVM Snapshot
#
# 2010, Looke
#

# Which service to mess with
SERVICE="service"

# LVM Stuff
LVMVOLUME="/dev/lvm/volume"
LVMSNAPSHOT="volume-snapshot"
LVMSNAPSHOTSIZE="50G"

# MySQL Properties
DBDUMPDIR="/dbdump"
DBNAME="aaa"
DBHOST="zzz"
DBUSER="xxx"
DBPASSWORD="yyy"

echo "Shutting down Service..."
/etc/init.d/${SERVICE} stop

while ps ax | grep -v grep | grep ${SERVICE} > /dev/null;
do
  echo "...stopping..."
  sleep 5
done

echo "Creating MySQL Dump..."
if [ ! -d "${DBDUMPDIR}" ]; then
  mkdir -p ${DBDUMPDIR}
fi
mysqldump --host=${DBHOST} --user=${DBUSER} --password=${DBPASSWORD} ${DBNAME} > ${DBDUMPDIR}/${DBNAME}.sql

echo "Creating LVM Snapshot..."
modprobe dm-snapshot
lvm lvcreate --size ${LVMSNAPSHOTSIZE} --snapshot --name ${LVMSNAPSHOT} ${LVMVOLUME}
sleep 5

echo "Restarting Service..."
/etc/init.d/${SERVICE} start

while ! ps ax | grep -v grep | grep ${SERVICE} > /dev/null;
do
  echo "...starting..."
  sleep 5
done

echo "Mounting LVM Snapshot..."
if [ ! -d "/${LVMSNAPSHOT}" ]; then
  mkdir -p /${LVMSNAPSHOT}
fi
mount -o ro /dev/lvm/${LVMSNAPSHOT} /${LVMSNAPSHOT}

exit 0

appbackup-run-after.sh


#!/bin/bash
#
# Application Service Backup - Part 2 of 2
#
# Post-Backup script
# - Unmounts the LVM Snapshot
# - Destroys the LVM Snapshot
#
# 2010, Looke
#

# LVM Stuff
LVMSNAPSHOT="volume-snapshot"

echo "Unmounting LVM Snapshot..."
umount /${LVMSNAPSHOT}

echo "Destroying LVM Snapshot..."
lvm lvremove -f /dev/lvm/${LVMSNAPSHOT}

exit 0

One backdraw of this method is, that the service has to be stopped in order to get a consistent state of the data. If the service has to be online 24/7 you would have to consider clustering (anyways, you would have to come up with something to cover unplanned downtimes).

Here is a small excerpt to show you how to configure the Pre- and Post backup scripts with the open source backup software Bacula. I assume if you use some other backup software, you can click your way through the GUI yourself :)



Job {
  Name = "Appbackup"
  ...
  Client Run Before Job = "/opt/bacula/scripts/appbackup-run-before.sh"
  Client Run After Job = "/opt/bacula/scripts/appbackup-run-after.sh"
  ...
}

Useful links:
Bacula Documentation – Job Ressource
Ubuntuusers Wiki – LVM (german)