I've interspersed some comments. I've also appended a python script that I use for taking shanpshots of _mounted_ logical volumes, and mounting the snapshot. The same script is used for unmounting and releasing the snapshot.
This is not a solution for your problem because your LV is not a file-system, but contains partitions with file-systems. Nevertheless, you may be able to use it as a starting point and make appropriate modifications for your case. Hope this helps - Kel Raywood On Sun, 18 Sep 2011, Tobias Schenk wrote: > I try use bacula 5.0.3 on suse linux to backup lvm snapshots. > Basically, I create a lvm snapshot called /dev/vmguests/backup using the > RunScript directive. Unfortunately, this is a sym link to /dev/dm-6. I > cannot be sure it is always dm-6. I would like to follow the sym link > and backup /dev/dm-6 as raw device. There is a command "readlink" which you can use to find the target of a symbolic link. e.g. tgt=$( readlink --canonicalize /dev/vmguests/backup ) > The hints I found while googling are are not working (like appending /. > to the File directive) or obscure (like using bash scripting to resolve > File names). Hmm ... I then I guess you would classify using readlink in a script as obscure. > I cannot simply mount /dev/dm-6 to somewhere because the contents is a > partitioned raw device of a kvm instance. Then you need to use kpartx to create device maps from the partition tables. These devices would contain the file-systems which you could mount. > Maybe it is possible resolve the link using a bash script in the file > directive but I have not found information about when the File directive > will be evaluated relative to RunScript. A RunScript with "RunsWhen = Before" will do exactly that. ie. nothing else will be evaluated until after the script has returned. > Has anyone a working solution for lvm snapshots? As mentioned at the top, I have a client-side script for backing up mounted LVs. ie. You don't pass it the LV name, you pass it the mount-point (e.g. /home) and where you want to mount the snapshot (e.g. /.snap/home) . In the FileSet I use "strip path = 1" My job resources contain: RunScript { Runs When = Before Runs On Client = yes Abort Job On Error = yes Command = "/etc/bacula/scripts/snapshot -L 4G /home /.snap/home" } RunScript { Runs When = After Runs On Client = yes Runs On Failure = yes Command = "/etc/bacula/scripts/snapshot -d /.snap/home" } Client-seide python-script "/etc/bacula/scripts/snapshot": #!/bin/env python import sys def usage(): prg = sys.argv[0] print "Usage: %s [-L size] FileSystemPath SnapshotPath" % prg print "___or: %s -d SnapshotPath" % prg sys.exit(2) class snapshotError(Exception): pass from commands import getstatusoutput def do_or_die( cmd ): stat,msg = getstatusoutput( cmd ) if stat: raise snapshotError( msg ) return msg from os import path GET_LV_ATTR = '/usr/sbin/lvs --noheadings -o lv_attr %s' CREATE_SS = '/usr/sbin/lvcreate --size %s --snapshot --name %s %s' REMOVE_LV = '/usr/sbin/lvremove -f %s' LOAD_SS_MOD = '/sbin/modprobe dm-snapshot' class Volume(object): """A mounted logical-volume""" def __init__( self, dir ): """ Read /proc/mounts to determine the device and file-system type. Read /etc/mtab to get the mount options. """ self.dev = None for line in open( '/proc/mounts' ).readlines(): tokens = line.split()[:3] if tokens[1] == dir: self.attr = do_or_die( GET_LV_ATTR % tokens[0] ).strip() self.dev, self.mnt, self.fs = tokens break if not self.dev: raise snapshotError( '"%s" not a mount point' % dir) self.opts = None for line in open( '/etc/mtab' ).readlines(): tokens = line.split()[:4] if tokens[1] == dir: self.opts = tokens[3] break def take_snapshot( self, size, ss_mnt ): # Require that this is a primary logical-volume if self.attr[0] not in '-o': raise snapshotError('"%s" not a primary logical-volume' % self.dev ) # Ensure that the snapshot kernel-module is loaded do_or_die( LOAD_SS_MOD ) # Change option "rw" to "ro" if self.opts: opts = ','.join( [ s == 'rw' and 'ro' or s for s in self.opts.split(',') ] ) else: opts = 'ro' # Add options for xfs if self.fs == 'xfs': opts = ','.join( [ opts, 'nouuid' ] ) # Create the snapshot and its mount point, then mount it. # Use the prefix SS_ for the name of the snapshot head, tail = path.split( self.dev ) ss_name = 'SS_' + tail ss_dev = path.join( head, ss_name ) print do_or_die( CREATE_SS % (size, ss_name, self.dev) ) # Release the snapshot if mkdir or mount fail try: print do_or_die( '/bin/mkdir -v -p %s' % ss_mnt ) cmd = '/bin/mount -v -r -t %s -o %s %s %s' \ % (self.fs, opts, ss_dev, ss_mnt) print cmd print do_or_die( cmd ) except: print do_or_die( REMOVE_LV % ss_dev ) raise def release_snapshot( self ): # Require that this is a snapshot logical-volume""" if self.attr[0] not in 'sS': raise snapshotError( '"%s" not a snapshot logical-volume' ) do_or_die( '/bin/umount %s' % self.mnt ) do_or_die( REMOVE_LV % self.dev ) self.dev = None do_or_die( 'rmdir --ignore-fail-on-non-empty %s' % self.mnt ) self.mnt = None from getopt import getopt, GetoptError def main(): try: opts, args = getopt( sys.argv[1:], 'L:d' ) except GetoptError: usage() nargs = len( args ) delete = False size = '2G' # Default size for COW space for opt, parm in opts: if opt == "-L": size = parm elif opt == "-d": delete = True try: if delete: if nargs != 1 : usage() Volume( args[0] ).release_snapshot() else: if nargs != 2: usage() Volume( args[0] ).take_snapshot( size, args[1] ) except snapshotError, msg: print "ERROR:", msg sys.exit(1) if __name__ == "__main__": main() ------------------------------------------------------------------------------ BlackBerry® DevCon Americas, Oct. 18-20, San Francisco, CA http://p.sf.net/sfu/rim-devcon-copy2 _______________________________________________ Bacula-users mailing list Bacula-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/bacula-users