[system-storage-manager/f19] Update to a new upstream release v0.4 and more fixes

Lukas Czerner lczerner at fedoraproject.org
Mon Jan 20 16:42:30 UTC 2014


commit 5d844463f56b31f25acc1ceb22c135e84334b1e7
Author: Lukas Czerner <lczerner at redhat.com>
Date:   Mon Jan 20 14:35:57 2014 +0100

    Update to a new upstream release v0.4 and more fixes
    
    - Remove btrfs resize support
    - Unmount all btrfs subvolumes when removing a filesystem
    - Fix size argument parsing for create and snapshot command
    - Fix list output for some cases
    - Add support to create encrypted volumes with crypt backend
    - Add dry-run option
    - Fix removing volumes with crypt backend
    - Add raid1 and raid10 support for lvm backend
    - Allow to check btrfs volumes
    - Fix error handling when trying to resize btrfs subvolume
    - Fix ssm mount command so it detects directory properly
    - Suppress backtrace when a command fails
    - Fix ssm to recognize units in new btrfs output properly
    - Use correct sysfs file to get size for a partition
    - Fix ssm to be able add a device with signature to btrfs file system
    - Resognize btrfs devices from new btrfs output properly
    
    Signed-off-by: Lukas Czerner <lczerner at redhat.com>

 .gitignore                                         |    1 +
 ...-new-upstream-release-v0.4-and-more-fixes.patch | 4652 ++++++++++++++++++++
 sources                                            |    2 +-
 ...t_device_size-to-work-with-partitions-cor.patch |   39 +
 ...4-misc-Use-wipefs-a-in-misc.wipefs-helper.patch |  103 +
 ...t_unit_size-accept-different-unit-formats.patch |  221 +
 ...-SSM_PRINT_BACKTRACE-environment-variable.patch |   57 +
 ...-ssm-Fix-various-problems-found-by-pylint.patch |  222 +
 ...ssm-Remove-unnecessary-usr-bin-env-python.patch |  124 +
 ...-ssm-Suppress-backtrace-if-command-failed.patch |   39 +
 ssm-0.4-ssm-big-update-no-1.patch                  | 3126 +++++++++++++
 ...btrfs-backend-try-to-find-the-real-device.patch |   31 +
 ssm-0.4-ssm-force-btrfs-device-add.patch           |  341 ++
 ...vice-count-should-go-down-after-removing-.patch |   27 +
 ...hey-way-we-gather-information-about-btrfs.patch |   27 +
 ...btrfs-recognize-devices-from-tests-suite-.patch |   38 +
 system-storage-manager.spec                        |   69 +-
 17 files changed, 9116 insertions(+), 3 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 927b346..4ac3cf3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
 /system-storage-manager-0.2.tar.gz
+/system-storage-manager-0.4.tar.gz
diff --git a/0001-Update-to-a-new-upstream-release-v0.4-and-more-fixes.patch b/0001-Update-to-a-new-upstream-release-v0.4-and-more-fixes.patch
new file mode 100644
index 0000000..55271e2
--- /dev/null
+++ b/0001-Update-to-a-new-upstream-release-v0.4-and-more-fixes.patch
@@ -0,0 +1,4652 @@
+From 82aefe2b0f9332b6ad60958377216a721e01b452 Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner at redhat.com>
+Date: Mon, 20 Jan 2014 14:35:57 +0100
+Subject: [PATCH] Update to a new upstream release v0.4 and more fixes
+
+- Remove btrfs resize support
+- Unmount all btrfs subvolumes when removing a filesystem
+- Fix size argument parsing for create and snapshot command
+- Fix list output for some cases
+- Add support to create encrypted volumes with crypt backend
+- Add dry-run option
+- Fix removing volumes with crypt backend
+- Add raid1 and raid10 support for lvm backend
+- Allow to check btrfs volumes
+- Fix error handling when trying to resize btrfs subvolume
+- Fix ssm mount command so it detects directory properly
+- Suppress backtrace when a command fails
+- Fix ssm to recognize units in new btrfs output properly
+- Use correct sysfs file to get size for a partition
+- Fix ssm to be able add a device with signature to btrfs file system
+- Resognize btrfs devices from new btrfs output properly
+
+Signed-off-by: Lukas Czerner <lczerner at redhat.com>
+---
+ .gitignore                                         |    1 +
+ sources                                            |    2 +-
+ ...t_device_size-to-work-with-partitions-cor.patch |   39 +
+ ...4-misc-Use-wipefs-a-in-misc.wipefs-helper.patch |  103 +
+ ...t_unit_size-accept-different-unit-formats.patch |  221 ++
+ ...-SSM_PRINT_BACKTRACE-environment-variable.patch |   57 +
+ ...-ssm-Fix-various-problems-found-by-pylint.patch |  222 ++
+ ...ssm-Remove-unnecessary-usr-bin-env-python.patch |  124 +
+ ...-ssm-Suppress-backtrace-if-command-failed.patch |   39 +
+ ssm-0.4-ssm-big-update-no-1.patch                  | 3126 ++++++++++++++++++++
+ ...btrfs-backend-try-to-find-the-real-device.patch |   31 +
+ ssm-0.4-ssm-force-btrfs-device-add.patch           |  341 +++
+ ...vice-count-should-go-down-after-removing-.patch |   27 +
+ ...hey-way-we-gather-information-about-btrfs.patch |   27 +
+ ...btrfs-recognize-devices-from-tests-suite-.patch |   38 +
+ system-storage-manager.spec                        |   68 +-
+ 16 files changed, 4464 insertions(+), 2 deletions(-)
+ create mode 100644 ssm-0.4-misc-Fix-get_device_size-to-work-with-partitions-cor.patch
+ create mode 100644 ssm-0.4-misc-Use-wipefs-a-in-misc.wipefs-helper.patch
+ create mode 100644 ssm-0.4-misc-get_unit_size-accept-different-unit-formats.patch
+ create mode 100644 ssm-0.4-ssm-Add-SSM_PRINT_BACKTRACE-environment-variable.patch
+ create mode 100644 ssm-0.4-ssm-Fix-various-problems-found-by-pylint.patch
+ create mode 100644 ssm-0.4-ssm-Remove-unnecessary-usr-bin-env-python.patch
+ create mode 100644 ssm-0.4-ssm-Suppress-backtrace-if-command-failed.patch
+ create mode 100644 ssm-0.4-ssm-big-update-no-1.patch
+ create mode 100644 ssm-0.4-ssm-btrfs-backend-try-to-find-the-real-device.patch
+ create mode 100644 ssm-0.4-ssm-force-btrfs-device-add.patch
+ create mode 100644 ssm-0.4-test-008-Device-count-should-go-down-after-removing-.patch
+ create mode 100644 ssm-0.4-tests-Fix-they-way-we-gather-information-about-btrfs.patch
+ create mode 100644 ssm-0.4-tests-Make-btrfs-recognize-devices-from-tests-suite-.patch
+
+diff --git a/.gitignore b/.gitignore
+index 927b346..4ac3cf3 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -1 +1,2 @@
+ /system-storage-manager-0.2.tar.gz
++/system-storage-manager-0.4.tar.gz
+diff --git a/sources b/sources
+index 038df21..f176aa7 100644
+--- a/sources
++++ b/sources
+@@ -1 +1 @@
+-524654f3b7bab544c4e612470b5d2392  system-storage-manager-0.2.tar.gz
++43235208daf95f8ada1b0632bf7bc756  system-storage-manager-0.4.tar.gz
+diff --git a/ssm-0.4-misc-Fix-get_device_size-to-work-with-partitions-cor.patch b/ssm-0.4-misc-Fix-get_device_size-to-work-with-partitions-cor.patch
+new file mode 100644
+index 0000000..3aac93c
+--- /dev/null
++++ b/ssm-0.4-misc-Fix-get_device_size-to-work-with-partitions-cor.patch
+@@ -0,0 +1,39 @@
++From 5b917ffbddfbb7366d2ad7d5f0e9c016ced29ca5 Mon Sep 17 00:00:00 2001
++From: Lukas Czerner <lczerner at redhat.com>
++Date: Wed, 15 Jan 2014 17:52:28 +0100
++Subject: [PATCH 07/10] misc: Fix get_device_size to work with partitions
++ correctly
++
++Currently get_device_size() searches for the size in sysfs specifically
++(/sys/block/<devname>/size) however that is not the right palce for
++partitions since partitions are subdirectories in /sys/block/<devname>
++directory.
++
++So change get_device_size() to get major and minor numbers of the device
++in question and use sysfs file /sys/dev/block/<major>:<minor>/size to
++get the size.
++
++Signed-off-by: Lukas Czerner <lczerner at redhat.com>
++---
++ ssmlib/misc.py | 5 +++--
++ 1 file changed, 3 insertions(+), 2 deletions(-)
++
++diff --git a/ssmlib/misc.py b/ssmlib/misc.py
++index bfaa1c4..dbfa6b1 100644
++--- a/ssmlib/misc.py
+++++ b/ssmlib/misc.py
++@@ -608,8 +608,9 @@ def is_bdevice(path):
++ 
++ 
++ def get_device_size(device):
++-    devname = device.split('/')[-1]
++-    with open("/sys/block/{0}/size".format(devname), 'r') as f:
+++    info = os.stat(device)
+++    major, minor = divmod(info.st_rdev, 256)
+++    with open("/sys/dev/block/{0}:{1}/size".format(major, minor), 'r') as f:
++         for line in f:
++             size = int(line)/2
++             return size
++-- 
++1.8.3.1
++
+diff --git a/ssm-0.4-misc-Use-wipefs-a-in-misc.wipefs-helper.patch b/ssm-0.4-misc-Use-wipefs-a-in-misc.wipefs-helper.patch
+new file mode 100644
+index 0000000..9a11955
+--- /dev/null
++++ b/ssm-0.4-misc-Use-wipefs-a-in-misc.wipefs-helper.patch
+@@ -0,0 +1,103 @@
++From 37b31373b1408c299270e3134b88eff4528ca75a Mon Sep 17 00:00:00 2001
++From: Lukas Czerner <lczerner at redhat.com>
++Date: Thu, 16 Jan 2014 17:31:57 +0100
++Subject: [PATCH 10/10] misc: Use wipefs -a in misc.wipefs() helper
++
++Currently we only wipe the first signature we can find with wipefs.
++However wipefs has an ability to wipe all the signatures of given type
++from the device (yes this is once again about btrfs) with option '-a'.
++So use that instead. This also simplify the wipefs helper a lot.
++
++Signed-off-by: Lukas Czerner <lczerner at redhat.com>
++---
++ ssmlib/misc.py                | 14 ++------------
++ tests/unittests/test_btrfs.py | 34 +++++++++++++++++-----------------
++ 2 files changed, 19 insertions(+), 29 deletions(-)
++
++diff --git a/ssmlib/misc.py b/ssmlib/misc.py
++index 3d99c07..915cad1 100644
++--- a/ssmlib/misc.py
+++++ b/ssmlib/misc.py
++@@ -363,18 +363,8 @@ def get_dmnumber(name):
++ def wipefs(device, signatures):
++     if type(signatures) is not list:
++         signatures = [signatures]
++-    command = ['wipefs', '-p', device]
++-    output = run(command)[1]
++-    offset = []
++-    for line in output[1:].split('\n'):
++-        if not line:
++-            continue
++-        array = line.split(",")
++-        if array[-1] in signatures:
++-            offset.extend(['--offset', array[0]])
++-    if len(offset) > 1:
++-        command = ['wipefs'] + offset + [device]
++-        run(command)
+++    command = ['wipefs', '-a', '-t', ','.join(signatures), device]
+++    run(command)
++ 
++ 
++ def humanize_size(arg):
++diff --git a/tests/unittests/test_btrfs.py b/tests/unittests/test_btrfs.py
++index 2fb04bc..2b6cd8e 100644
++--- a/tests/unittests/test_btrfs.py
+++++ b/tests/unittests/test_btrfs.py
++@@ -167,12 +167,12 @@ class BtrfsFunctionCheck(MockSystemDataSource):
++         self._addPool('my_pool', ['/dev/sdc2', '/dev/sdc3', '/dev/sdc1'])
++ 
++         # remove volume
++-        self._checkCmd("ssm remove default_pool", [], "wipefs -p /dev/sda")
++-        self._cmdEq("wipefs -p /dev/sdb", -2)
+++        self._checkCmd("ssm remove default_pool", [], "wipefs -a -t btrfs /dev/sda")
+++        self._cmdEq("wipefs -a -t btrfs /dev/sdb", -2)
++ 
++-        self._checkCmd("ssm remove my_pool", [], "wipefs -p /dev/sdc3")
++-        self._cmdEq("wipefs -p /dev/sdc1", -2)
++-        self._cmdEq("wipefs -p /dev/sdc2", -3)
+++        self._checkCmd("ssm remove my_pool", [], "wipefs -a -t btrfs /dev/sdc3")
+++        self._cmdEq("wipefs -a -t btrfs /dev/sdc1", -2)
+++        self._cmdEq("wipefs -a -t btrfs /dev/sdc2", -3)
++ 
++         # remove subvolume
++         self._addVol('vol001', 117283225, 1, 'default_pool', ['/dev/sda'], '/mnt/test')
++@@ -189,24 +189,24 @@ class BtrfsFunctionCheck(MockSystemDataSource):
++         self._addPool('other_pool', ['/dev/sdd', '/dev/sde'])
++         self._checkCmd("ssm remove /dev/sdd /dev/sdb other_pool my_pool default_pool:/dev/default_pool/vol001", [],
++             "btrfs subvolume delete /mnt/test")
++-        self._cmdEq("wipefs -p /dev/sdc1", -2)
++-        self._cmdEq("wipefs -p /dev/sdc3", -3)
++-        self._cmdEq("wipefs -p /dev/sdc2", -4)
++-        self._cmdEq("wipefs -p /dev/sde", -5)
++-        self._cmdEq("wipefs -p /dev/sdd", -6)
+++        self._cmdEq("wipefs -a -t btrfs /dev/sdc1", -2)
+++        self._cmdEq("wipefs -a -t btrfs /dev/sdc3", -3)
+++        self._cmdEq("wipefs -a -t btrfs /dev/sdc2", -4)
+++        self._cmdEq("wipefs -a -t btrfs /dev/sde", -5)
+++        self._cmdEq("wipefs -a -t btrfs /dev/sdd", -6)
++         self._cmdEq("btrfs device delete /dev/sdb /mnt/test", -7)
++         self._cmdEq("btrfs device delete /dev/sdd /tmp/mount", -8)
++ 
++         self._removeMount("/dev/sda")
++         # remove all
++         self._checkCmd("ssm remove --all", [],
++-            "wipefs -p /dev/sde")
++-        self._cmdEq("wipefs -p /dev/sdd", -2)
++-        self._cmdEq("wipefs -p /dev/sdc1", -3)
++-        self._cmdEq("wipefs -p /dev/sdc3", -4)
++-        self._cmdEq("wipefs -p /dev/sdc2", -5)
++-        self._cmdEq("wipefs -p /dev/sda", -6)
++-        self._cmdEq("wipefs -p /dev/sdb", -7)
+++            "wipefs -a -t btrfs /dev/sde")
+++        self._cmdEq("wipefs -a -t btrfs /dev/sdd", -2)
+++        self._cmdEq("wipefs -a -t btrfs /dev/sdc1", -3)
+++        self._cmdEq("wipefs -a -t btrfs /dev/sdc3", -4)
+++        self._cmdEq("wipefs -a -t btrfs /dev/sdc2", -5)
+++        self._cmdEq("wipefs -a -t btrfs /dev/sda", -6)
+++        self._cmdEq("wipefs -a -t btrfs /dev/sdb", -7)
++ 
++         # TODO
++         # remove force
++-- 
++1.8.3.1
++
+diff --git a/ssm-0.4-misc-get_unit_size-accept-different-unit-formats.patch b/ssm-0.4-misc-get_unit_size-accept-different-unit-formats.patch
+new file mode 100644
+index 0000000..e74536a
+--- /dev/null
++++ b/ssm-0.4-misc-get_unit_size-accept-different-unit-formats.patch
+@@ -0,0 +1,221 @@
++From ef26cf6fb0e33ca52f35fcf219fd21db7788c200 Mon Sep 17 00:00:00 2001
++From: Lukas Czerner <lczerner at redhat.com>
++Date: Mon, 13 Jan 2014 16:29:01 +0100
++Subject: [PATCH 01/10] misc: get_unit_size() accept different unit formats
++
++Because btrfs recently changed it's output to use MiB format instead of
++MB format the function handling this within the btrfs is broken.
++
++Fix this my making get_unit_size() to handle different unit formats (M,
++MB, MiB) and use that in btrfs as well.
++
++Signed-off-by: Lukas Czerner <lczerner at redhat.com>
++---
++ ssmlib/backends/btrfs.py | 18 ++---------
++ ssmlib/misc.py           | 82 ++++++++++++++++++++++++++++++++++--------------
++ test.py                  | 13 ++++----
++ 3 files changed, 69 insertions(+), 44 deletions(-)
++
++diff --git a/ssmlib/backends/btrfs.py b/ssmlib/backends/btrfs.py
++index a4aedda..eb23403 100644
++--- a/ssmlib/backends/btrfs.py
+++++ b/ssmlib/backends/btrfs.py
++@@ -33,18 +33,6 @@ except KeyError:
++     SSM_BTRFS_DEFAULT_POOL = "btrfs_pool"
++ 
++ 
++-def get_real_number(string):
++-    number = float(string[0:-2])
++-    unit = string[-2:-1]
++-    # The result will be in kilobytes
++-    units = ["K", "M", "G", "T", "P", "E", "Z", "Y"]
++-    for i, u in enumerate(units):
++-        if u == unit:
++-            number *= (2 ** (i * 10))
++-            break
++-    return number
++-
++-
++ def get_btrfs_version():
++     try:
++         output = misc.run(['btrfs', '--version'], can_fail=True)[1]
++@@ -128,7 +116,7 @@ class Btrfs(template.Backend):
++ 
++             elif array[0] == 'Total':
++                 pool['dev_count'] = array[2]
++-                fs_used = get_real_number(array[6])
+++                fs_used = float(misc.get_real_size(array[6]))
++ 
++             elif array[0] == 'devid':
++                 dev['dev_name'] = array[7]
++@@ -154,9 +142,9 @@ class Btrfs(template.Backend):
++                                 vol['real_dev'] = found[0].split(':')[0]
++                                 break
++ 
++-                dev_used = get_real_number(array[5])
+++                dev_used = float(misc.get_real_size(array[5]))
++                 dev['dev_used'] = str(dev_used)
++-                fs_size += get_real_number(array[3])
+++                fs_size += float(misc.get_real_size(array[3]))
++ 
++                 dev_size = \
++                     int(partitions[dev['dev_name'].rpartition("/")[-1]][2])
++diff --git a/ssmlib/misc.py b/ssmlib/misc.py
++index 3ff1577..bfaa1c4 100644
++--- a/ssmlib/misc.py
+++++ b/ssmlib/misc.py
++@@ -32,34 +32,57 @@ TMP_MOUNTED = []
++ 
++ def get_unit_size(string):
++     """
++-    Check the last character of the string for the unit and return the unit
++-    value, otherwise return zero. It check only the last character of the
++-    string.
+++    Check the last character of the string for the unit and return the tuple
+++    of unit value, unit name, otherwise return zero. It check only the first
+++    character of the unit string.
++ 
++     >>> get_unit_size("B")
++-    1
+++    (1, 'B')
++     >>> get_unit_size("k")
++-    1024
++-    >>> get_unit_size("M")
++-    1048576
++-    >>> get_unit_size("g")
++-    1073741824
++-    >>> get_unit_size("T")
++-    1099511627776...
++-    >>> get_unit_size("p")
++-    1125899906842624...
+++    (1024, 'k')
+++    >>> get_unit_size("KiB")
+++    (1024, 'KiB')
+++    >>> get_unit_size("KB")
+++    (1024, 'KB')
+++    >>> get_unit_size("10M")
+++    (1048576, 'M')
+++    >>> get_unit_size("-99.99g")
+++    (1073741824, 'g')
+++    >>> get_unit_size("-99.99GiB")
+++    (1073741824, 'GiB')
+++    >>> get_unit_size("+99.99G")
+++    (1073741824, 'G')
+++    >>> get_unit_size("+99.99gb")
+++    (1073741824, 'gb')
+++    >>> get_unit_size("99.99g")
+++    (1073741824, 'g')
+++    >>> get_unit_size("0.84T")
+++    (1099511627776, 'T')
+++    >>> get_unit_size("0.84TiB")
+++    (1099511627776, 'TiB')
+++    >>> get_unit_size("0p")
+++    (1125899906842624, 'p')
+++    >>> get_unit_size("99kit")
+++    (0, '')
++     >>> get_unit_size("")
++-    0
+++    (0, '')
++     >>> get_unit_size("H")
++-    0
+++    (0, '')
++     """
++ 
++     mult = 0
++     units = {'B': 1, 'K': 2 ** 10, 'M': 2 ** 20, 'G': 2 ** 30, 'T': 2 ** 40,
++              'P': 2 ** 50}
++-    if len(string) > 0 and string[-1].upper() in units:
++-        mult = units[string[-1].upper()]
++-    return mult
+++    unit = re.sub(r'^\+?-?\d+(\.\d*)?', '', string)
+++    if len(unit) > 0 and unit[0].upper() in units:
+++        mult = units[unit[0].upper()]
+++    all_units = {'B', 'K', 'M', 'G', 'T', 'P',
+++                 'KB', 'MB', 'GB', 'TB', 'PB',
+++                 'KIB', 'MIB', 'GIB', 'TIB', 'PIB'}
+++    if unit.upper() in all_units:
+++        return mult, unit
+++    else:
+++        return 0, ""
++ 
++ 
++ def is_number(string):
++@@ -92,8 +115,14 @@ def get_real_size(size):
++ 
++     >>> get_real_size("3141")
++     '3141'
+++    >>> get_real_size("3141B")
+++    '3.07'
++     >>> get_real_size("3141K")
++     '3141.00'
+++    >>> get_real_size("3141KB")
+++    '3141.00'
+++    >>> get_real_size("3141KiB")
+++    '3141.00'
++     >>> get_real_size("3141k")
++     '3141.00'
++     >>> get_real_size("3141M")
++@@ -118,6 +147,10 @@ def get_real_size(size):
++     '-3.14'
++     >>> get_real_size("3.14G")
++     '3292528.64'
+++    >>> get_real_size("3.14GB")
+++    '3292528.64'
+++    >>> get_real_size("3.14GiB")
+++    '3292528.64'
++     >>> get_real_size("+3.14g")
++     '+3292528.64'
++     >>> get_real_size("-3.14G")
++@@ -133,12 +166,15 @@ def get_real_size(size):
++     """
++     if is_number(size):
++         return size
++-    elif is_number(size[:-1]):
+++    else:
++         # Always use kilobytes in ssm
++-        mult = get_unit_size(size) / 1024
++-        sign = '+' if size[0] == '+' else ''
++-        if mult:
++-            return '{0}{1:.2f}'.format(sign, float(size[:-1]) * mult)
+++        mult, unit = get_unit_size(size)
+++        mult /= float(1024)
+++        number = re.sub(unit + "$", '', size)
+++        if is_number(number):
+++            sign = '+' if size[0] == '+' else ''
+++            if mult:
+++                return '{0}{1:.2f}'.format(sign, float(number) * mult)
++     raise Exception("Not supported unit in the " +
++                     "size \'{0}\' argument.".format(size))
++ 
++diff --git a/test.py b/test.py
++index 2ca542c..7c91ae8 100644
++--- a/test.py
+++++ b/test.py
++@@ -89,17 +89,18 @@ def run_bash_tests():
++ 
++ def quick_test():
++     print "[+] Running doctests"
++-    doctest_flags = doctest.IGNORE_EXCEPTION_DETAIL | doctest.ELLIPSIS
+++    doctest_flags = doctest.IGNORE_EXCEPTION_DETAIL | doctest.ELLIPSIS | \
+++                    doctest.REPORT_ONLY_FIRST_FAILURE
++     result = doctest.testmod(main, exclude_empty=True, report=True,
++-            raise_on_error=True, optionflags=doctest_flags)
+++            raise_on_error=False, optionflags=doctest_flags)
++     result = doctest.testmod(lvm, exclude_empty=True, report=True,
++-            raise_on_error=True, optionflags=doctest_flags)
+++            raise_on_error=False, optionflags=doctest_flags)
++     result = doctest.testmod(crypt, exclude_empty=True, report=True,
++-            raise_on_error=True, optionflags=doctest_flags)
+++            raise_on_error=False, optionflags=doctest_flags)
++     result = doctest.testmod(btrfs, exclude_empty=True, report=True,
++-            raise_on_error=True, optionflags=doctest_flags)
+++            raise_on_error=False, optionflags=doctest_flags)
++     result = doctest.testmod(misc, exclude_empty=True, report=True,
++-            raise_on_error=True, optionflags=doctest_flags)
+++            raise_on_error=False, optionflags=doctest_flags)
++     print "[+] Running unittests"
++     test_loader = unittest.TestLoader()
++     tests_lvm = test_loader.loadTestsFromModule(test_lvm)
++-- 
++1.8.3.1
++
+diff --git a/ssm-0.4-ssm-Add-SSM_PRINT_BACKTRACE-environment-variable.patch b/ssm-0.4-ssm-Add-SSM_PRINT_BACKTRACE-environment-variable.patch
+new file mode 100644
+index 0000000..e305100
+--- /dev/null
++++ b/ssm-0.4-ssm-Add-SSM_PRINT_BACKTRACE-environment-variable.patch
+@@ -0,0 +1,57 @@
++From e5577724d859ca19e6b3074f05f25bc43c748a43 Mon Sep 17 00:00:00 2001
++From: Lukas Czerner <lczerner at redhat.com>
++Date: Thu, 16 Jan 2014 15:08:11 +0100
++Subject: [PATCH 09/10] ssm: Add SSM_PRINT_BACKTRACE environment variable
++
++Currently we're catching all the SsmError exception and just print out
++simple error message. This is fine, however it makes debugging harder in
++some cases, so add SSM_PRINT_BACKTRACE environment variable which
++enables us to print traceback when needed. Simply set the variable to
++yes, true, or 1 and ssm will print traceback in case of error.
++
++Signed-off-by: Lukas Czerner <lczerner at redhat.com>
++---
++ bin/ssm | 20 +++++++++++++++++++-
++ 1 file changed, 19 insertions(+), 1 deletion(-)
++
++diff --git a/bin/ssm b/bin/ssm
++index baa3c60..6058f64 100755
++--- a/bin/ssm
+++++ b/bin/ssm
++@@ -19,8 +19,23 @@
++ 
++ import os
++ import sys
+++import traceback
++ from ssmlib import problem
++ 
+++
+++# Should we print backtrace on error, or suppress it ?
+++# Suppress it by default.
+++try:
+++    SSM_PRINT_BACKTRACE = os.environ['SSM_PRINT_BACKTRACE']
+++    if SSM_PRINT_BACKTRACE.upper() in ['YES', 'TRUE', '1']:
+++        SSM_PRINT_BACKTRACE = True
+++    else:
+++        SSM_PRINT_BACKTRACE = False
+++except KeyError:
+++    SSM_PRINT_BACKTRACE = False
+++
+++
+++
++ try:
++     from ssmlib import main
++ 
++@@ -32,5 +47,8 @@ try:
++                 sys.exit("\nRoot privileges required to run this script!\n")
++         sys.exit(main.main())
++ except problem.SsmError, err:
++-    print str(err)
+++    if SSM_PRINT_BACKTRACE is True:
+++        traceback.print_exc(file=sys.stdout)
+++    else:
+++        print str(err)
++     sys.exit(err.errcode)
++-- 
++1.8.3.1
++
+diff --git a/ssm-0.4-ssm-Fix-various-problems-found-by-pylint.patch b/ssm-0.4-ssm-Fix-various-problems-found-by-pylint.patch
+new file mode 100644
+index 0000000..f436c38
+--- /dev/null
++++ b/ssm-0.4-ssm-Fix-various-problems-found-by-pylint.patch
+@@ -0,0 +1,222 @@
++From 0dcf4bcee5c5f6503905dac298dee77f1141f783 Mon Sep 17 00:00:00 2001
++From: Lukas Czerner <lczerner at redhat.com>
++Date: Fri, 17 Jan 2014 16:05:56 +0100
++Subject: [PATCH] ssm: Fix various problems found by pylint
++
++Signed-off-by: Lukas Czerner <lczerner at redhat.com>
++---
++ ssmlib/__init__.py       |  2 +-
++ ssmlib/backends/btrfs.py | 12 +++++-------
++ ssmlib/backends/crypt.py |  5 ++---
++ ssmlib/backends/lvm.py   |  3 +--
++ ssmlib/backends/md.py    |  3 ---
++ ssmlib/main.py           |  6 +++---
++ ssmlib/misc.py           | 12 ++++++------
++ 7 files changed, 18 insertions(+), 25 deletions(-)
++
++diff --git a/ssmlib/__init__.py b/ssmlib/__init__.py
++index f1bcfdb..0a49de2 100644
++--- a/ssmlib/__init__.py
+++++ b/ssmlib/__init__.py
++@@ -15,4 +15,4 @@
++ # You should have received a copy of the GNU General Public License
++ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
++ 
++-__all__ = ["backends", "misc", "main", "problem"]
+++__all__ = ["backend", "misc", "main", "problem"]
++diff --git a/ssmlib/backends/btrfs.py b/ssmlib/backends/btrfs.py
++index 836f108..acd5446 100644
++--- a/ssmlib/backends/btrfs.py
+++++ b/ssmlib/backends/btrfs.py
++@@ -19,10 +19,8 @@
++ 
++ import re
++ import os
++-import sys
++ import datetime
++ from ssmlib import misc
++-from ssmlib import problem
++ from ssmlib.backends import template
++ 
++ __all__ = ["BtrfsVolume", "BtrfsPool", "BtrfsDev"]
++@@ -37,7 +35,7 @@ def get_btrfs_version():
++     try:
++         output = misc.run(['btrfs', '--version'], can_fail=True)[1]
++         output = output.strip().split("\n")[-1]
++-        version = re.search('(?<=v)\d+\.\d+', output).group(0)
+++        version = re.search(r'(?<=v)\d+\.\d+', output).group(0)
++     except (OSError, AttributeError):
++         version = "0.0"
++     return float(version)
++@@ -262,7 +260,7 @@ class Btrfs(template.Backend):
++                 new['hide'] = False
++                 # Store snapshot info
++                 if 'mount' in new and \
++-                    re.match("snap-\d{4}-\d{2}-\d{2}-T\d{6}",
+++                    re.match(r"snap-\d{4}-\d{2}-\d{2}-T\d{6}",
++                              os.path.basename(new['mount'])):
++                     new['snap_name'] = "{0}:{1}".format(name,
++                             os.path.basename(new['path']))
++@@ -279,8 +277,8 @@ class Btrfs(template.Backend):
++                 continue
++             # For the version with screwed 'subvolume list' command
++             line = re.sub("<FS_TREE>/*", "", line)
++-            volume['ID'] = re.search('(?<=ID )\d+', line).group(0)
++-            volume['top_level'] = re.search('(?<=top level )\d+', line).group(0)
+++            volume['ID'] = re.search(r'(?<=ID )\d+', line).group(0)
+++            volume['top_level'] = re.search(r'(?<=top level )\d+', line).group(0)
++             volume['path'] = re.search('(?<=path ).*$', line).group(0)
++             volume['subvolume'] = True
++             yield volume
++@@ -450,7 +448,7 @@ class BtrfsPool(Btrfs, template.BackendPool):
++                 command.extend(['-m', 'raid10', '-d', 'raid10'])
++             else:
++                 raise Exception("Btrfs backed currently does not support " +
++-                                "RAID level {0}".format(raid['level']))
+++                                "RAID level {0}".format(options['raid']))
++ 
++         if size:
++             command.extend(['-b', "{0}".format(int(float(size) * 1024))])
++diff --git a/ssmlib/backends/crypt.py b/ssmlib/backends/crypt.py
++index 4aad266..8c1b48c 100644
++--- a/ssmlib/backends/crypt.py
+++++ b/ssmlib/backends/crypt.py
++@@ -21,7 +21,6 @@ import re
++ import os
++ import stat
++ from ssmlib import misc
++-from ssmlib import problem
++ from ssmlib.backends import template
++ 
++ __all__ = ["DmCryptVolume"]
++@@ -240,7 +239,7 @@ class DmCryptDevice(DmObject, template.BackendDevice):
++             device = {}
++             devname = "/dev/" + line[3]
++             signature = misc.get_signature(devname)
++-            if misc.get_signature(devname) in CRYPT_SIGNATURES:
+++            if signature in CRYPT_SIGNATURES:
++                 device['hide'] = False
++                 device['dev_name'] = devname
++                 device['pool_name'] = self.default_pool_name
++@@ -250,4 +249,4 @@ class DmCryptDevice(DmObject, template.BackendDevice):
++ 
++ 
++     def remove(self, devices):
++-        misc.wipefs(device, CRYPT_SIGNATURES)
+++        misc.wipefs(devices, CRYPT_SIGNATURES)
++diff --git a/ssmlib/backends/lvm.py b/ssmlib/backends/lvm.py
++index 955c705..4c7c0ad 100644
++--- a/ssmlib/backends/lvm.py
+++++ b/ssmlib/backends/lvm.py
++@@ -22,7 +22,6 @@ import os
++ import stat
++ import datetime
++ from ssmlib import misc
++-from ssmlib import problem
++ from ssmlib.backends import template
++ 
++ __all__ = ["PvsInfo", "VgsInfo", "LvsInfo"]
++@@ -47,7 +46,7 @@ def get_lvm_version():
++         for line in output:
++             if pattern.match(line.strip()):
++                 match = " ".join(line.split())
++-                tmp = re.search('(?<=LVM version: )\d+\.\d+\.\d+',
+++                tmp = re.search(r'(?<=LVM version: )\d+\.\d+\.\d+',
++                                     match).group(0)
++                 version = map(int, tmp.split(".", 3))
++     except (OSError, AttributeError):
++diff --git a/ssmlib/backends/md.py b/ssmlib/backends/md.py
++index f33243c..1e3c6e2 100644
++--- a/ssmlib/backends/md.py
+++++ b/ssmlib/backends/md.py
++@@ -18,11 +18,8 @@
++ # md module for System Storage Manager
++ 
++ import os
++-import stat
++ import socket
++-import datetime
++ from ssmlib import misc
++-from ssmlib import problem
++ from ssmlib.backends import template
++ 
++ try:
++diff --git a/ssmlib/main.py b/ssmlib/main.py
++index 7aab312..c294aec 100644
++--- a/ssmlib/main.py
+++++ b/ssmlib/main.py
++@@ -1284,7 +1284,7 @@ class StorageHandle(object):
++                 try:
++                     pool.remove()
++                     removed += 1
++-                except (RuntimeError, problem.SsmError), ex:
+++                except (RuntimeError, problem.SsmError):
++                     PR.info("Unable to remove '{0}'".format(pool['pool_name']))
++                     ret = False
++             if removed == 0:
++@@ -1378,7 +1378,6 @@ class StorageHandle(object):
++         dev = self.dev[real]
++         if dev and 'fs_info' in dev:
++             return dev
++-        err = "'{0}' does not contain valid file system".format(real)
++         return False
++ 
++     def _find_device_record(self, path):
++@@ -1544,6 +1543,7 @@ def valid_resize_size(size):
++ 
++ def is_directory(string):
++     if string is None:
+++        err = "Directory name not defined."
++         raise argparse.ArgumentTypeError(err)
++     try:
++         mode = os.stat(string).st_mode
++@@ -1847,7 +1847,7 @@ def main(args=None):
++     sys.exitfunc = misc.do_cleanup
++ 
++     if args.dry_run:
++-        return 0;
+++        return 0
++ 
++     try:
++         args.func(args)
++diff --git a/ssmlib/misc.py b/ssmlib/misc.py
++index 915cad1..77ddc2d 100644
++--- a/ssmlib/misc.py
+++++ b/ssmlib/misc.py
++@@ -77,9 +77,9 @@ def get_unit_size(string):
++     unit = re.sub(r'^\+?-?\d+(\.\d*)?', '', string)
++     if len(unit) > 0 and unit[0].upper() in units:
++         mult = units[unit[0].upper()]
++-    all_units = {'B', 'K', 'M', 'G', 'T', 'P',
+++    all_units = ['B', 'K', 'M', 'G', 'T', 'P',
++                  'KB', 'MB', 'GB', 'TB', 'PB',
++-                 'KIB', 'MIB', 'GIB', 'TIB', 'PIB'}
+++                 'KIB', 'MIB', 'GIB', 'TIB', 'PIB']
++     if unit.upper() in all_units:
++         return mult, unit
++     else:
++@@ -198,9 +198,9 @@ def get_device_by_uuid(uuid):
++ 
++ def get_major_minor(device):
++     real_dev = get_real_device(device)
++-    stat = os.stat(real_dev)
++-    major = os.major(stat.st_rdev)
++-    minor = os.minor(stat.st_rdev)
+++    info = os.stat(real_dev)
+++    major = os.major(info.st_rdev)
+++    minor = os.minor(info.st_rdev)
++     return major, minor
++ 
++ 
++@@ -579,7 +579,7 @@ def terminal_size(default=(25, 80)):
++             except:
++                 pass
++         if not cr:
++-            cr = (25, 80)
+++            cr = default
++     return int(cr[1]), int(cr[0])
++ 
++ 
++-- 
++1.8.3.1
++
+diff --git a/ssm-0.4-ssm-Remove-unnecessary-usr-bin-env-python.patch b/ssm-0.4-ssm-Remove-unnecessary-usr-bin-env-python.patch
+new file mode 100644
+index 0000000..d72922c
+--- /dev/null
++++ b/ssm-0.4-ssm-Remove-unnecessary-usr-bin-env-python.patch
+@@ -0,0 +1,124 @@
++From 7a27177855ea2466d01dd201571f66ddea6c7cc8 Mon Sep 17 00:00:00 2001
++From: Lukas Czerner <lczerner at redhat.com>
++Date: Fri, 17 Jan 2014 16:29:50 +0100
++Subject: [PATCH] ssm: Remove unnecessary /usr/bin/env python
++
++Those are not executable script and should not contain this line.
++
++Signed-off-by: Lukas Czerner <lczerner at redhat.com>
++---
++ ssmlib/__init__.py          | 2 --
++ ssmlib/backends/__init__.py | 2 --
++ ssmlib/backends/btrfs.py    | 2 --
++ ssmlib/backends/crypt.py    | 2 --
++ ssmlib/backends/lvm.py      | 2 --
++ ssmlib/backends/md.py       | 2 --
++ ssmlib/backends/template.py | 2 --
++ ssmlib/main.py              | 2 --
++ ssmlib/misc.py              | 2 --
++ ssmlib/problem.py           | 2 --
++ 10 files changed, 20 deletions(-)
++
++diff --git a/ssmlib/__init__.py b/ssmlib/__init__.py
++index 0a49de2..7e5e4fd 100644
++--- a/ssmlib/__init__.py
+++++ b/ssmlib/__init__.py
++@@ -1,5 +1,3 @@
++-#!/usr/bin/env python
++-#
++ # (C)2011 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
++ #
++ # This program is free software: you can redistribute it and/or modify
++diff --git a/ssmlib/backends/__init__.py b/ssmlib/backends/__init__.py
++index 5720e3d..2046e83 100644
++--- a/ssmlib/backends/__init__.py
+++++ b/ssmlib/backends/__init__.py
++@@ -1,5 +1,3 @@
++-#!/usr/bin/env python
++-#
++ # (C)2011 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
++ #
++ # This program is free software: you can redistribute it and/or modify
++diff --git a/ssmlib/backends/btrfs.py b/ssmlib/backends/btrfs.py
++index acd5446..b0a486f 100644
++--- a/ssmlib/backends/btrfs.py
+++++ b/ssmlib/backends/btrfs.py
++@@ -1,5 +1,3 @@
++-#!/usr/bin/env python
++-#
++ # (C)2011 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
++ #
++ # This program is free software: you can redistribute it and/or modify
++diff --git a/ssmlib/backends/crypt.py b/ssmlib/backends/crypt.py
++index 8c1b48c..642b905 100644
++--- a/ssmlib/backends/crypt.py
+++++ b/ssmlib/backends/crypt.py
++@@ -1,5 +1,3 @@
++-#!/usr/bin/env python
++-#
++ # (C)2011 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
++ #
++ # This program is free software: you can redistribute it and/or modify
++diff --git a/ssmlib/backends/lvm.py b/ssmlib/backends/lvm.py
++index 4c7c0ad..4022034 100644
++--- a/ssmlib/backends/lvm.py
+++++ b/ssmlib/backends/lvm.py
++@@ -1,5 +1,3 @@
++-#!/usr/bin/env python
++-#
++ # (C)2011 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
++ #
++ # This program is free software: you can redistribute it and/or modify
++diff --git a/ssmlib/backends/md.py b/ssmlib/backends/md.py
++index 1e3c6e2..fca2c98 100644
++--- a/ssmlib/backends/md.py
+++++ b/ssmlib/backends/md.py
++@@ -1,5 +1,3 @@
++-#!/usr/bin/env python
++-#
++ # (C)2012 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
++ #
++ # This program is free software: you can redistribute it and/or modify
++diff --git a/ssmlib/backends/template.py b/ssmlib/backends/template.py
++index 94f4b40..bf1b6ad 100644
++--- a/ssmlib/backends/template.py
+++++ b/ssmlib/backends/template.py
++@@ -1,5 +1,3 @@
++-#!/usr/bin/env python
++-#
++ # (C)2013 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
++ #
++ # This program is free software: you can redistribute it and/or modify
++diff --git a/ssmlib/main.py b/ssmlib/main.py
++index c294aec..5213000 100644
++--- a/ssmlib/main.py
+++++ b/ssmlib/main.py
++@@ -1,5 +1,3 @@
++-#!/usr/bin/env python
++-#
++ # (C)2011 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
++ #
++ # This program is free software: you can redistribute it and/or modify
++diff --git a/ssmlib/misc.py b/ssmlib/misc.py
++index 77ddc2d..24b7dd9 100644
++--- a/ssmlib/misc.py
+++++ b/ssmlib/misc.py
++@@ -1,5 +1,3 @@
++-#!/usr/bin/env python
++-#
++ # (C)2011 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
++ #
++ # This program is free software: you can redistribute it and/or modify
++diff --git a/ssmlib/problem.py b/ssmlib/problem.py
++index dfa6ec6..f8fb4ce 100644
++--- a/ssmlib/problem.py
+++++ b/ssmlib/problem.py
++@@ -1,5 +1,3 @@
++-#!/usr/bin/env python
++-#
++ # (C)2012 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
++ #
++ # This program is free software: you can redistribute it and/or modify
++-- 
++1.8.3.1
++
+diff --git a/ssm-0.4-ssm-Suppress-backtrace-if-command-failed.patch b/ssm-0.4-ssm-Suppress-backtrace-if-command-failed.patch
+new file mode 100644
+index 0000000..9938a47
+--- /dev/null
++++ b/ssm-0.4-ssm-Suppress-backtrace-if-command-failed.patch
+@@ -0,0 +1,39 @@
++From e2c869393f9c1c0f1c84e1a817f411a2056d820e Mon Sep 17 00:00:00 2001
++From: Lukas Czerner <lczerner at redhat.com>
++Date: Thu, 16 Jan 2014 14:44:10 +0100
++Subject: [PATCH 08/10] ssm: Suppress backtrace if command failed
++
++Currently when command failed in misc.run(), RuntimeError() exception is
++raised and backtrace is printed to the output. However this is not
++desirable, so use problem.CommandFailed() exception which allows us to
++catch it and print out reasonable error message.
++
++Signed-off-by: Lukas Czerner <lczerner at redhat.com>
++---
++ ssmlib/misc.py | 3 ++-
++ 1 file changed, 2 insertions(+), 1 deletion(-)
++
++diff --git a/ssmlib/misc.py b/ssmlib/misc.py
++index dbfa6b1..3d99c07 100644
++--- a/ssmlib/misc.py
+++++ b/ssmlib/misc.py
++@@ -24,6 +24,7 @@ import stat
++ import tempfile
++ import threading
++ import subprocess
+++from ssmlib import problem
++ 
++ # List of temporary mount points which should be cleaned up
++ # before exiting
++@@ -480,7 +481,7 @@ def run(cmd, show_cmd=False, stdout=False, stderr=True, can_fail=False,
++             print output
++         if error is not None:
++             print error
++-        raise RuntimeError(err_msg)
+++        raise problem.CommandFailed(err_msg)
++ 
++     if not return_stdout:
++         output = None
++-- 
++1.8.3.1
++
+diff --git a/ssm-0.4-ssm-big-update-no-1.patch b/ssm-0.4-ssm-big-update-no-1.patch
+new file mode 100644
+index 0000000..11b98f3
+--- /dev/null
++++ b/ssm-0.4-ssm-big-update-no-1.patch
+@@ -0,0 +1,3126 @@
++diff --git a/Makefile b/Makefile
++index 629a83f..2d887c4 100644
++--- a/Makefile
+++++ b/Makefile
++@@ -1,3 +1,6 @@
+++PYTHONPATH := $(shell pwd)
+++export PYTHONPATH
+++
++ all: help
++ 
++ help:
++@@ -53,4 +56,7 @@ source: test clean
++ test:
++ 	@python test.py
++ 
+++push_html:
+++	scp -r doc/_build/singlehtml/* lczerner at shell.sourceforge.net:/home/project-web/storagemanager/htdocs/
+++
++ release: git-clean clean check_vars authors spec log docs source
++diff --git a/README b/README
++index ea3d3c3..71b09e8 100644
++--- a/README
+++++ b/README
++@@ -162,6 +162,9 @@ In some cases file system has to be mounted in order to resize. This
++ will be handled by **ssm** automatically by mounting the **volume**
++ temporarily.
++ 
+++Note that resizing btrfs subvolume is not supported, only the whole
+++file system can be resized.
+++
++ 
++ Check command
++ *************
++@@ -256,8 +259,8 @@ volume
++    Volume in btrfs back-end is actually just btrfs subvolume with the
++    exception of the first volume created on btrfs pool creation, which
++    is the file system itself. Subvolumes can only be created on btrfs
++-   file system when the it is mounted, but user does not have to worry
++-   about that, since **ssm** will automatically mount the file system
+++   file system when it is mounted, but user does not have to worry
+++   about that since **ssm** will automatically mount the file system
++    temporarily in order to create a new subvolume.
++ 
++    Volume name is used as subvolume path in the btrfs file system and
++@@ -270,6 +273,10 @@ volume
++    system is mounted, with the exception of the main btrfs volume -
++    the file system itself.
++ 
+++   Also note that btrfs volumes and subvolumes can not be resized.
+++   This is mainly limitation of the btrfs tools which currently does
+++   not work reliably.
+++
++    New btrfs volume can be created with **create** command.
++ 
++ snapshot
++@@ -323,10 +330,40 @@ device
++ Crypt backend
++ *************
++ 
++-Crypt backend in **ssm** is currently limited to only gather the
++-information about encrypted volumes in the system. You can not create
++-or manage encrypted volumes or pools, but it will be extended in the
++-future.
+++Crypt backend in **ssm** uses cryptsetup and dm-crypt target to manage
+++encrypted volumes. Crypt backend can be used as a regular backend for
+++creating encrypted volumes on top of regular block devices, or even
+++other volumes (lvm or md volumes for example). Or it can be used to
+++create encrypted lvm volumes right away in a single step.
+++
+++Only volumes can be created with crypt backend. This backend does not
+++support pooling and does not require special devices.
+++
+++pool
+++   Crypt backend does not support pooling it is not possible to create
+++   crypt pool or add a device into a pool.
+++
+++volume
+++   Volume in crypt backend is the volume created by dm-crypt which
+++   represent the data on the original encrypted device in unencrypted
+++   form. Crypt backend does not support pooling, so only one device
+++   can be used to create crypt volume. It also does not support raid
+++   or any device concatenation.
+++
+++   Currently two modes, or extensions are supported luks and plain.
+++   Luks is used by default.For more information about the extensions
+++   please see **cryptsetup** manual page.
+++
+++snapshot
+++   Crypt backend does not support snapshotting, however if the
+++   encrypted volume is created on top of the lvm volume, the lvm
+++   volume itself can be snapshotted. The snapshot can be then opened
+++   by using **cryptsetup**. It is possible that this might change in
+++   the future so that **ssm** will be able to activate the volume
+++   directly without the extra step.
+++
+++device
+++   Crypt backend does not require any special device to be created on.
++ 
++ 
++ Environment variables
++diff --git a/bin/ssm b/bin/ssm
++index fc1ce48..baa3c60 100755
++--- a/bin/ssm
+++++ b/bin/ssm
++@@ -32,4 +32,5 @@ try:
++                 sys.exit("\nRoot privileges required to run this script!\n")
++         sys.exit(main.main())
++ except problem.SsmError, err:
+++    print str(err)
++     sys.exit(err.errcode)
++diff --git a/doc/_build/man/ssm.8 b/doc/_build/man/ssm.8
++index 16ac1e8..ab777bf 100644
++--- a/doc/_build/man/ssm.8
+++++ b/doc/_build/man/ssm.8
++@@ -1,6 +1,6 @@
++ .\" Man page generated from reStructuredText.
++ .
++-.TH "SSM" "8" "August 07, 2013" "0.4" "System Storage Manager"
+++.TH "SSM" "8" "October 02, 2013" "0.4" "System Storage Manager"
++ .SH NAME
++ ssm \- System Storage Manager: a single tool to manage your storage
++ .
++@@ -59,9 +59,9 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
++ ..
++ .SH SYNOPSIS
++ .sp
++-\fBssm\fP [\fB\-h\fP] [\fB\-\-version\fP] [\fB\-v\fP] [\fB\-f\fP] [\fB\-b\fP BACKEND] {check,resize,create,list,add,remove,snapshot,mount} ...
+++\fBssm\fP [\fB\-h\fP] [\fB\-\-version\fP] [\fB\-v\fP] [\fB\-f\fP] [\fB\-b\fP BACKEND] [\fB\-n\fP] {check,resize,create,list,add,remove,snapshot,mount} ...
++ .sp
++-\fBssm\fP \fBcreate\fP [\fB\-h\fP] [\fB\-s\fP SIZE] [\fB\-n\fP NAME] [\fB\-\-fstype\fP FSTYPE] [\fB\-r\fP LEVEL] [\fB\-I\fP STRIPESIZE] [\fB\-i\fP STRIPES] [\fB\-p\fP POOL] [\fBdevice\fP [\fBdevice\fP ...]] [mount]
+++\fBssm\fP \fBcreate\fP [\fB\-h\fP] [\fB\-s\fP SIZE] [\fB\-n\fP NAME] [\fB\-\-fstype\fP FSTYPE] [\fB\-r\fP LEVEL] [\fB\-I\fP STRIPESIZE] [\fB\-i\fP STRIPES] [\fB\-p\fP POOL] [\fB\-e\fP [{luks,plain}]] [\fBdevice\fP [\fBdevice\fP ...]] [mount]
++ .sp
++ \fBssm\fP \fBlist\fP [\fB\-h\fP] [{volumes,vol,dev,devices,pool,pools,fs,filesystems,snap,snapshots}]
++ .sp
++@@ -110,7 +110,15 @@ or questions.
++ .TP
++ .BI \-b \ BACKEND\fP,\fB \ \-\-backend \ BACKEND
++ Choose backend to use. Currently you can choose from
++-(lvm,btrfs).
+++(lvm,btrfs,crypt).
+++.TP
+++.B \-n\fP,\fB  \-\-dry\-run
+++Dry run. Do not do anything, just parse the command
+++line options and gather system information if
+++necessary. Note that with this option ssm will not
+++perform all the check as some of them are done by the
+++backends themselves. This option is mainly used for
+++debugging purposes.
++ .UNINDENT
++ .SH SYSTEM STORAGE MANAGER COMMANDS
++ .SS Introduction
++@@ -120,7 +128,7 @@ line as a first argument to the ssm. They all have specific use and its own
++ arguments, but global ssm arguments are propagated to all commands.
++ .SS Create command
++ .sp
++-\fBssm\fP \fBcreate\fP [\fB\-h\fP] [\fB\-s\fP SIZE] [\fB\-n\fP NAME] [\fB\-\-fstype\fP FSTYPE] [\fB\-r\fP LEVEL] [\fB\-I\fP STRIPESIZE] [\fB\-i\fP STRIPES] [\fB\-p\fP POOL] [\fBdevice\fP [\fBdevice\fP ...]] [mount]
+++\fBssm\fP \fBcreate\fP [\fB\-h\fP] [\fB\-s\fP SIZE] [\fB\-n\fP NAME] [\fB\-\-fstype\fP FSTYPE] [\fB\-r\fP LEVEL] [\fB\-I\fP STRIPESIZE] [\fB\-i\fP STRIPES] [\fB\-p\fP POOL] [\fB\-e\fP [{luks,plain}]] [\fBdevice\fP [\fBdevice\fP ...]] [mount]
++ .sp
++ This command creates a new volume with defined parameters. If \fBdevice\fP is
++ provided it will be used to create a volume, hence it will be added into the
++@@ -195,6 +203,12 @@ you have to specify RAID level as well.
++ .BI \-p \ POOL\fP,\fB \ \-\-pool \ POOL
++ Pool to use to create the new volume.
++ .UNINDENT
+++.INDENT 0.0
+++.TP
+++.B \-e [{luks,plain}], \-\-encrypt [{luks,plain}]
+++Create encrpted volume. Extension to use can be
+++specified.
+++.UNINDENT
++ .SS List command
++ .sp
++ \fBssm\fP \fBlist\fP [\fB\-h\fP] [{volumes,vol,dev,devices,pool,pools,fs,filesystems,snap,snapshots}]
++@@ -280,6 +294,9 @@ ask you whether you want to remove it from the original pool.
++ .sp
++ In some cases file system has to be mounted in order to resize. This will be
++ handled by \fBssm\fP automatically by mounting the \fBvolume\fP temporarily.
+++.sp
+++Note that resizing btrfs subvolume is not supported, only the whole file
+++system can be resized.
++ .INDENT 0.0
++ .TP
++ .B \-h\fP,\fB  \-\-help
++@@ -435,8 +452,8 @@ devices specified and non existing pool name.
++ Volume in btrfs back\-end is actually just btrfs subvolume with the
++ exception of the first volume created on btrfs pool creation, which is
++ the file system itself. Subvolumes can only be created on btrfs file
++-system when the it is mounted, but user does not have to
++-worry about that, since \fBssm\fP will automatically mount the file
+++system when it is mounted, but user does not have to
+++worry about that since \fBssm\fP will automatically mount the file
++ system temporarily in order to create a new subvolume.
++ .sp
++ Volume name is used as subvolume path in the btrfs file system and every
++@@ -449,6 +466,10 @@ Btrfs volumes are only shown in the \fIlist\fP output, when the file system is
++ mounted, with the exception of the main btrfs volume \- the file system
++ itself.
++ .sp
+++Also note that btrfs volumes and subvolumes can not be resized. This is
+++mainly limitation of the btrfs tools which currently does not work
+++reliably.
+++.sp
++ New btrfs volume can be created with \fBcreate\fP command.
++ .TP
++ .B snapshot
++@@ -498,9 +519,41 @@ Lvm requires \fIphysical device\fP to be created on the device, but with
++ .UNINDENT
++ .SS Crypt backend
++ .sp
++-Crypt backend in \fBssm\fP is currently limited to only gather the information
++-about encrypted volumes in the system. You can not create or manage encrypted
++-volumes or pools, but it will be extended in the future.
+++Crypt backend in \fBssm\fP uses cryptsetup and dm\-crypt target to manage
+++encrypted volumes. Crypt backend can be used as a regular backend for
+++creating encrypted volumes on top of regular block devices, or even other
+++volumes (lvm or md volumes for example). Or it can be used to create
+++encrypted lvm volumes right away in a single step.
+++.sp
+++Only volumes can be created with crypt backend. This backend does not
+++support pooling and does not require special devices.
+++.INDENT 0.0
+++.TP
+++.B pool
+++Crypt backend does not support pooling it is not possible to create
+++crypt pool or add a device into a pool.
+++.TP
+++.B volume
+++Volume in crypt backend is the volume created by dm\-crypt which
+++represent the data on the original encrypted device in unencrypted form.
+++Crypt backend does not support pooling, so only one device can be used
+++to create crypt volume. It also does not support raid or any device
+++concatenation.
+++.sp
+++Currently two modes, or extensions are supported luks and plain. Luks
+++is used by default.For more information about the extensions please see
+++\fBcryptsetup\fP manual page.
+++.TP
+++.B snapshot
+++Crypt backend does not support snapshotting, however if the encrypted
+++volume is created on top of the lvm volume, the lvm volume itself can
+++be snapshotted. The snapshot can be then opened by using \fBcryptsetup\fP\&.
+++It is possible that this might change in the future so that \fBssm\fP will
+++be able to activate the volume directly without the extra step.
+++.TP
+++.B device
+++Crypt backend does not require any special device to be created on.
+++.UNINDENT
++ .SS MD backend
++ .sp
++ MD backend in \fBssm\fP is currently limited to only gather the information
++diff --git a/ssmlib/backends/btrfs.py b/ssmlib/backends/btrfs.py
++index 04e405c..a4aedda 100644
++--- a/ssmlib/backends/btrfs.py
+++++ b/ssmlib/backends/btrfs.py
++@@ -23,6 +23,7 @@ import sys
++ import datetime
++ from ssmlib import misc
++ from ssmlib import problem
+++from ssmlib.backends import template
++ 
++ __all__ = ["BtrfsVolume", "BtrfsPool", "BtrfsDev"]
++ 
++@@ -56,12 +57,11 @@ def get_btrfs_version():
++ BTRFS_VERSION = get_btrfs_version()
++ 
++ 
++-class Btrfs(object):
+++class Btrfs(template.Backend):
++ 
++-    def __init__(self, options, data=None):
+++    def __init__(self, *args, **kwargs):
+++        super(Btrfs, self).__init__(*args, **kwargs)
++         self.type = 'btrfs'
++-        self.data = data or {}
++-        self.options = options
++         self.default_pool_name = SSM_BTRFS_DEFAULT_POOL
++         self._vol = {}
++         self._pool = {}
++@@ -69,13 +69,12 @@ class Btrfs(object):
++         self._snap = {}
++         self._subvolumes = {}
++         self._binary = misc.check_binary('btrfs')
++-        self.problem = problem.ProblemSet(options)
++         self.modified_list_version = True
++ 
++         if not self._binary:
++             return
++ 
++-        self.mounts = misc.get_mounts('/dev/')
+++        self.mounts = misc.get_mounts('btrfs')
++         command = ['btrfs', 'filesystem', 'show']
++         self.output = misc.run(command, stderr=False)[1]
++ 
++@@ -107,12 +106,12 @@ class Btrfs(object):
++                 pool['uuid'] = vol['uuid'] = uuid
++ 
++                 try:
++-                    fallback = False
++                     vol['real_dev'] = misc.get_device_by_uuid(uuid)
++ 
++                     if vol['real_dev'] in self.mounts:
++                         pool['mount'] = self.mounts[vol['real_dev']]['mp']
++                         vol['mount'] = self.mounts[vol['real_dev']]['mp']
+++
++                     else:
++                         for dev_i in self.mounts:
++                             found = re.findall(r'{0}:/.*'.format(vol['real_dev']), dev_i)
++@@ -121,7 +120,6 @@ class Btrfs(object):
++                                 break
++                 except OSError:
++                     # udev is "hard-to-work-with" sometimes so this is fallback
++-                    fallback = True
++                     vol['real_dev'] = ""
++ 
++                 if label != 'none':
++@@ -140,7 +138,7 @@ class Btrfs(object):
++                 dev['pool_name'] = pool_name
++ 
++                 # Fallback in case we could not find real_dev by uuid
++-                if fallback and 'mount' not in pool:
+++                if 'mount' not in pool:
++                     if dev['dev_name'] in self.mounts:
++                         pool['mount'] = self.mounts[dev['dev_name']]['mp']
++                         vol['real_dev'] = dev['dev_name']
++@@ -153,6 +151,7 @@ class Btrfs(object):
++                             found = re.findall(r'{0}:/.*'.format(dev['dev_name']), dev_i)
++                             if found:
++                                 pool['mount'] = self.mounts[found[0]]['mp']
+++                                vol['real_dev'] = found[0].split(':')[0]
++                                 break
++ 
++                 dev_used = get_real_number(array[5])
++@@ -313,26 +312,18 @@ class Btrfs(object):
++         self._pool[pool['pool_name']] = pool
++         self._vol[vol['dev_name']] = vol
++ 
++-    def __iter__(self):
++-        for item in sorted(self.data.iterkeys()):
++-            yield item
++-
++-    def __getitem__(self, key):
++-        if key in self.data.iterkeys():
++-            return self.data[key]
++-
++     def _remove_filesystem(self, name):
++         if 'mount' in self._vol[name]:
++             if self.problem.check(self.problem.FS_MOUNTED,
++                                   [name, self._vol[name]['mount']]):
++-                misc.do_umount(self._vol[name]['mount'])
+++                misc.do_umount(self._vol[name]['real_dev'], all_targets=True)
++         for dev in self._dev.itervalues():
++             if dev['pool_name'] != name:
++                 continue
++             misc.wipefs(dev['dev_name'], 'btrfs')
++ 
++ 
++-class BtrfsVolume(Btrfs):
+++class BtrfsVolume(Btrfs, template.BackendVolume):
++ 
++     def __init__(self, *args, **kwargs):
++         super(BtrfsVolume, self).__init__(*args, **kwargs)
++@@ -374,11 +365,18 @@ class BtrfsVolume(Btrfs):
++         else:
++             self._remove_filesystem(vol)
++ 
+++    def check(self, vol):
+++        vol = self.data[vol]
+++        return self.run_btrfs(['check', vol['real_dev']])[0]
+++
++     def resize(self, vol, size, resize_fs=True):
++         vol = self.data[vol]
++         if 'mount' not in vol:
++             tmp = misc.temp_mount("UUID={0}".format(vol['uuid']))
++             vol['mount'] = tmp
+++        if 'subvolume' in vol and vol['subvolume'] is True:
+++            self.problem.check(self.problem.NOT_SUPPORTED,
+++                               'Resizing btrfs subvolume')
++         command = ['filesystem', 'resize', str(int(size)) + "K", vol['mount']]
++         self.run_btrfs(command)
++ 
++@@ -402,7 +400,7 @@ class BtrfsVolume(Btrfs):
++         self.run_btrfs(command)
++ 
++ 
++-class BtrfsDev(Btrfs):
+++class BtrfsDev(Btrfs, template.BackendDevice):
++ 
++     def __init__(self, *args, **kwargs):
++         super(BtrfsDev, self).__init__(*args, **kwargs)
++@@ -416,7 +414,7 @@ class BtrfsDev(Btrfs):
++                         "achieve by removing {0}".format(devices))
++ 
++ 
++-class BtrfsPool(Btrfs):
+++class BtrfsPool(Btrfs, template.BackendPool):
++ 
++     def __init__(self, *args, **kwargs):
++         super(BtrfsPool, self).__init__(*args, **kwargs)
++@@ -425,7 +423,22 @@ class BtrfsPool(Btrfs):
++         else:
++             self.data = self._pool
++ 
++-    def _create_filesystem(self, pool, name, devs, size=None, raid=None):
+++    def _can_btrfs_force(self):
+++        """
+++        This is just ridiculous. Unfortunately btrfs tools usually change
+++        behaviour and options without bumping version number. So we have
+++        to check whether btrfs allows to 'force' file system creation.
+++        """
+++        command=['mkfs.btrfs', '-f']
+++        output = misc.run(command, can_fail=True)[1]
+++        found = re.search('invalid option', output)
+++        if found:
+++            return False
+++        else:
+++            return True
+++
+++    def _create_filesystem(self, pool, name, devs, size=None, options=None):
+++        options = options or {}
++         if not devs:
++             raise Exception("To create btrfs volume, some devices must be " +
++                             "provided")
++@@ -434,12 +447,12 @@ class BtrfsPool(Btrfs):
++             self.problem.check(self.problem.TOOL_MISSING, 'mkfs.btrfs')
++         command = ['mkfs.btrfs', '-L', name]
++ 
++-        if raid:
++-            if raid['level'] == '0':
+++        if 'raid' in options:
+++            if options['raid'] == '0':
++                 command.extend(['-m', 'raid0', '-d', 'raid0'])
++-            elif raid['level'] == '1':
+++            elif options['raid'] == '1':
++                 command.extend(['-m', 'raid1', '-d', 'raid1'])
++-            elif raid['level'] == '10':
+++            elif options['raid'] == '10':
++                 command.extend(['-m', 'raid10', '-d', 'raid10'])
++             else:
++                 raise Exception("Btrfs backed currently does not support " +
++@@ -455,7 +468,8 @@ class BtrfsPool(Btrfs):
++         # have tried to remove the device from the respective pool already.
++         # So at this point there should not be any useful signatures to
++         # speak of. However as I mentioned btrfs is broken, so force it.
++-        command.extend(['-f'])
+++        if self._can_btrfs_force():
+++            command.extend(['-f'])
++         command.extend(devs)
++         misc.run(command, stdout=True)
++         misc.send_udev_event(devs[0], "change")
++@@ -507,10 +521,11 @@ class BtrfsPool(Btrfs):
++         self._remove_filesystem(pool)
++ 
++     def create(self, pool, size=None, name=None, devs=None,
++-               raid=None):
+++               options=None):
+++        options = options or {}
++         if pool in self._pool:
++             vol = None
++-            if size or raid:
+++            if size or 'raid' in options:
++                 self.problem.warn("Only name, volume name and pool name " +
++                                   "can be specified when creating btrfs " +
++                                   "subvolume, the rest will be ignored")
++@@ -535,7 +550,7 @@ class BtrfsPool(Btrfs):
++             if name:
++                 self.problem.warn("Creating new pool. Argument (--name " +
++                                   "{0}) will be ignored!".format(name))
++-            vol = self._create_filesystem(pool, pool, devs, size, raid)
+++            vol = self._create_filesystem(pool, pool, devs, size, options)
++         return vol
++ 
++ 
++diff --git a/ssmlib/backends/crypt.py b/ssmlib/backends/crypt.py
++index 3c44f58..4aad266 100644
++--- a/ssmlib/backends/crypt.py
+++++ b/ssmlib/backends/crypt.py
++@@ -19,36 +19,147 @@
++ 
++ import re
++ import os
+++import stat
++ from ssmlib import misc
++ from ssmlib import problem
+++from ssmlib.backends import template
++ 
++ __all__ = ["DmCryptVolume"]
++ 
+++SUPPORTED_CRYPT = ['luks', 'plain']
+++CRYPT_SIGNATURES = ['crypto_LUKS']
+++CRYPT_DEFAULT_EXTENSION = "luks"
+++
++ try:
++     SSM_CRYPT_DEFAULT_POOL = os.environ['SSM_CRYPT_DEFAULT_POOL']
++ except KeyError:
++     SSM_CRYPT_DEFAULT_POOL = "crypt_pool"
++ 
++ try:
++-    DM_DEV_DIR = os.environ['DM_DEV_DIR']
+++    SSM_CRYPT_DEFAULT_VOL_PREFIX = os.environ['SSM_CRYPT_DEFAULT_VOL_PREFIX']
++ except KeyError:
++-    DM_DEV_DIR = "/dev"
++-
++-
++-class DmCryptVolume(object):
++-
++-    def __init__(self, options, data=None):
+++    SSM_CRYPT_DEFAULT_VOL_PREFIX = "encrypted"
+++
+++# cryptsetup against my expectations does not take into account
+++# DM_DEV_DIR so set it to /dev pernamently for now.
+++#try:
+++#    DM_DEV_DIR = os.environ['DM_DEV_DIR']
+++#except KeyError:
+++#    DM_DEV_DIR = "/dev"
+++DM_DEV_DIR = "/dev"
+++MAX_DEVS = 999
+++
+++def get_cryptsetup_version():
+++    try:
+++        output = misc.run(['cryptsetup', '--version'], can_fail=True)[1]
+++        version = map(int, output.strip().split()[-1].split('.', 3))
+++    except (OSError, AttributeError):
+++        version = [0, 0, 0]
+++    return version
+++
+++CRYPTSETUP_VERSION = get_cryptsetup_version()
+++
+++class DmObject(template.Backend):
+++    def __init__(self, *args, **kwargs):
+++        super(DmObject, self).__init__(*args, **kwargs)
++         self.type = 'crypt'
++-        self.data = data or {}
++-        self.output = None
++-        self.options = options
++         self.mounts = misc.get_mounts('{0}/mapper'.format(DM_DEV_DIR))
++         self.default_pool_name = SSM_CRYPT_DEFAULT_POOL
++-        self.problem = problem.ProblemSet(options)
++ 
++         if not misc.check_binary('dmsetup') or \
++            not misc.check_binary('cryptsetup'):
++             return
+++
+++    def run_cryptsetup(self, command, stdout=True):
+++        if not misc.check_binary('cryptsetup'):
+++            self.problem.check(self.problem.TOOL_MISSING, 'cryptsetup')
+++        command.insert(0, "cryptsetup")
+++        return misc.run(command, stdout=stdout)
+++
+++
+++class DmCryptPool(DmObject, template.BackendPool):
+++    def __init__(self, *args, **kwargs):
+++        super(DmCryptPool, self).__init__(*args, **kwargs)
+++        '''
+++        pool = {'pool_name': self.default_pool_name,
+++                'type': 'crypt',
+++                'dev_count': '0',
+++                'pool_free': '0',
+++                'pool_used': '0',
+++                'pool_size': '0',
+++                'hide': True}
+++        self.data[self.default_pool_name] = pool
+++        '''
+++
+++
+++    def create(self, pool, size=None, name=None, devs=None,
+++               options=None):
+++
+++        if CRYPTSETUP_VERSION < [1, 6, 0]:
+++            msg = "You need at least cryptsetup version " + \
+++                  "{0}. Creating encrypted volumes".format('1.6.0')
+++            self.problem.check(self.problem.NOT_SUPPORTED, msg)
+++        options = options or {}
+++        if 'encrypt' in options:
+++            if options['encrypt'] is True:
+++                options['encrypt'] = CRYPT_DEFAULT_EXTENSION
+++            if options['encrypt'] not in SUPPORTED_CRYPT:
+++                self.problem.not_supported("Extension "
+++                                           "\'{0}\'".format(options['encrypt']))
+++        else:
+++            # So the options is not crypt specific. It's ok, just use defaults
+++            options['encrypt'] = CRYPT_DEFAULT_EXTENSION
+++
+++        if len(devs) > 1:
+++            self.problem.not_supported("Device concatenation" +
+++                                       " with \"crypt\" backend")
+++        if not name:
+++            name = self._generate_devname()
+++        device = devs[0]
+++        args = []
+++        command = []
+++        if self.options.verbose:
+++            args.append('-v')
+++        else:
+++            args.append('-q')
+++        if options['encrypt'] == "luks":
+++            command.extend(args)
+++            if self.options.force:
+++                command.append('--force-password')
+++            if self.options.interactive:
+++                command.append('-y')
+++            command.extend(['luksFormat', device])
+++            self.run_cryptsetup(command)
+++        command = []
+++        command.extend(args)
+++        command.append('open')
+++        if size:
+++            # Size is in KiB but cryptsetup accepts it in 512 byte blocks
+++            size = str(float(size) * 2).split('.')[0]
+++            command.extend(['--size', size])
+++        command.extend(['--type', options['encrypt'], device, name])
+++        self.run_cryptsetup(command)
+++        return "{0}/mapper/{1}".format(DM_DEV_DIR, name)
+++
+++    def _generate_devname(self):
+++        for i in range(1, MAX_DEVS):
+++            name = "{0}{1:0>{align}}".format(SSM_CRYPT_DEFAULT_VOL_PREFIX, i,
+++                                            align=len(str(MAX_DEVS)))
+++            path = "{0}/mapper/{1}".format(DM_DEV_DIR, name)
+++            try:
+++                if stat.S_ISBLK(os.stat(path).st_mode):
+++                    continue
+++            except OSError:
+++                pass
+++            return name
+++        self.problem.error("Can not find proper device name. Specify one!")
+++
+++
+++class DmCryptVolume(DmObject, template.BackendVolume):
+++
+++    def __init__(self, *args, **kwargs):
+++        super(DmCryptVolume, self).__init__(*args, **kwargs)
+++
++         command = ['dmsetup', 'table']
++         self.output = misc.run(command, stderr=False)[1]
++         for line in self.output.split("\n"):
++@@ -63,9 +174,9 @@ class DmCryptVolume(object):
++             devname = re.sub(":$", "",
++                              "{0}/mapper/{1}".format(DM_DEV_DIR, array[0]))
++             dm['dm_name'] = devname
++-            dm['pool_name'] = 'dm-crypt'
++-            dm['dev_name'] = misc.get_real_device(devname)
++-            dm['real_dev'] = dm['dev_name']
+++            dm['pool_name'] = self.default_pool_name
+++            dm['dev_name'] = devname
+++            dm['real_dev'] = misc.get_real_device(devname)
++             if dm['real_dev'] in self.mounts:
++                 dm['mount'] = self.mounts[dm['real_dev']]['mp']
++ 
++@@ -78,12 +189,6 @@ class DmCryptVolume(object):
++             self._parse_cryptsetup(command, dm)
++             self.data[dm['dev_name']] = dm
++ 
++-    def run_cryptsetup(self, command, stdout=True):
++-        if not self._binary:
++-            self.problem.check(self.problem.TOOL_MISSING, 'cryptsetup')
++-        command.insert(0, "cryptsetup")
++-        return misc.run(command, stdout=stdout)
++-
++     def _parse_cryptsetup(self, cmd, dm):
++         self.output = misc.run(cmd, stderr=False)[1]
++         for line in self.output.split("\n"):
++@@ -97,19 +202,52 @@ class DmCryptVolume(object):
++             elif array[0].strip() == 'device:':
++                 dm['crypt_device'] = array[1]
++ 
+++    def __getitem__(self, name):
+++        if name in self.data.iterkeys():
+++            return self.data[name]
+++        device = name
+++        if not os.path.exists(name):
+++            device = DM_DEV_DIR + "/" + name
+++            if not os.path.exists(device):
+++                return None
+++        device = misc.get_real_device(device)
+++        if device in self.data.iterkeys():
+++            return self.data[device]
+++        return None
+++
++     def remove(self, dm):
+++        vol = self[dm]
+++        if 'mount' in vol:
+++            if self.problem.check(self.problem.FS_MOUNTED,
+++                                  [vol['dev_name'], vol['mount']]):
+++                misc.do_umount(vol['mount'])
++         command = ['remove', dm]
++         self.run_cryptsetup(command)
+++        misc.wipefs(vol['crypt_device'], CRYPT_SIGNATURES)
++ 
++     def resize(self, dm, size, resize_fs=True):
++         size = str(int(size) * 2)
++         command = ['resize', '--size', size, dm]
++         self.run_cryptsetup(command)
++ 
++-    def __iter__(self):
++-        for item in sorted(self.data.iterkeys()):
++-            yield item
++ 
++-    def __getitem__(self, key):
++-        if key in self.data.iterkeys():
++-            return self.data[key]
+++class DmCryptDevice(DmObject, template.BackendDevice):
+++
+++    def __init__(self, *args, **kwargs):
+++        super(DmCryptDevice, self).__init__(*args, **kwargs)
+++
+++        for line in misc.get_partitions():
+++            device = {}
+++            devname = "/dev/" + line[3]
+++            signature = misc.get_signature(devname)
+++            if misc.get_signature(devname) in CRYPT_SIGNATURES:
+++                device['hide'] = False
+++                device['dev_name'] = devname
+++                device['pool_name'] = self.default_pool_name
+++                device['dev_free'] = '0'
+++                device['dev_used'] = str(misc.get_device_size(devname))
+++                self.data[devname] = device
+++
+++
+++    def remove(self, devices):
+++        misc.wipefs(device, CRYPT_SIGNATURES)
++diff --git a/ssmlib/backends/lvm.py b/ssmlib/backends/lvm.py
++index 9cc8079..955c705 100644
++--- a/ssmlib/backends/lvm.py
+++++ b/ssmlib/backends/lvm.py
++@@ -17,11 +17,13 @@
++ 
++ # lvm module for System Storage Manager
++ 
+++import re
++ import os
++ import stat
++ import datetime
++ from ssmlib import misc
++ from ssmlib import problem
+++from ssmlib.backends import template
++ 
++ __all__ = ["PvsInfo", "VgsInfo", "LvsInfo"]
++ 
++@@ -37,17 +39,32 @@ except KeyError:
++ MAX_LVS = 999
++ 
++ 
++-class LvmInfo(object):
+++def get_lvm_version():
+++    try:
+++        output = misc.run(['lvm', 'version'], can_fail=True)[1]
+++        output = output.strip().split("\n")
+++        pattern = re.compile("LVM version:")
+++        for line in output:
+++            if pattern.match(line.strip()):
+++                match = " ".join(line.split())
+++                tmp = re.search('(?<=LVM version: )\d+\.\d+\.\d+',
+++                                    match).group(0)
+++                version = map(int, tmp.split(".", 3))
+++    except (OSError, AttributeError):
+++        version = [0, 0, 0]
+++    return version
++ 
++-    def __init__(self, options, data=None):
+++LVM_VERSION = get_lvm_version()
+++
+++
+++class LvmInfo(template.Backend):
+++
+++    def __init__(self, *args, **kwargs):
+++        super(LvmInfo, self).__init__(*args, **kwargs)
++         self.type = 'lvm'
++-        self.data = data or {}
++         self.attrs = []
++-        self.output = None
++-        self.options = options
++         self.binary = misc.check_binary('lvm')
++         self.default_pool_name = SSM_LVM_DEFAULT_POOL
++-        self.problem = problem.ProblemSet(options)
++ 
++     def run_lvm(self, command, noforce=False):
++         if not self.binary:
++@@ -59,9 +76,6 @@ class LvmInfo(object):
++         command.insert(0, "lvm")
++         misc.run(command, stdout=True)
++ 
++-    def __str__(self):
++-        return self.output
++-
++     def _data_index(self, row):
++         return row.values()[len(row.values()) - 1]
++ 
++@@ -86,16 +100,16 @@ class LvmInfo(object):
++     def _fill_aditional_info(self, row):
++         pass
++ 
++-    def __iter__(self):
++-        for item in sorted(self.data.iterkeys()):
++-            yield item
+++    def supported_since(self, version, string):
+++        if version > LVM_VERSION:
+++            msg = "ERROR: You need at least lvm version " + \
+++                  "{0}. Feature \"{1}\"".format(".".join(map(str, version)),
+++                                                string)
+++            self.problem.check(self.problem.NOT_SUPPORTED, msg)
+++        return True
++ 
++-    def __getitem__(self, key):
++-        if key in self.data.iterkeys():
++-            return self.data[key]
++ 
++-
++-class VgsInfo(LvmInfo):
+++class VgsInfo(LvmInfo, template.BackendPool):
++ 
++     def __init__(self, *args, **kwargs):
++         super(VgsInfo, self).__init__(*args, **kwargs)
++@@ -149,40 +163,85 @@ class VgsInfo(LvmInfo):
++         self.run_lvm(command)
++ 
++     def create(self, vg, size=None, name=None, devs=None,
++-               raid=None):
+++               options=None):
+++        options = options or {}
++         devices = devs or []
++         command = ['lvcreate', vg]
++-        if size:
++-            command.extend(['-L', size + 'K'])
++-        else:
++-            if len(devices) > 0:
++-                size = "100%PVS"
++-            else:
++-                size = "100%FREE"
++-            command.extend(['-l', size])
++ 
++         if name:
++             lvname = name
++         else:
++             lvname = self._generate_lvname(vg)
++ 
+++        if size:
+++            command.extend(['-L', size + 'K'])
+++        else:
+++            if len(devices) > 0:
+++                tmp = "100%PVS"
+++            else:
+++                tmp = "100%FREE"
+++            command.extend(['-l', tmp])
+++
++         command.extend(['-n', lvname.rpartition("/")[-1]])
++ 
++-        if raid:
++-            if raid['level'] == '0':
++-                if not raid['stripesize']:
++-                    raid['stripesize'] = "64"
++-                if not raid['stripes'] and len(devices) > 0:
++-                    raid['stripes'] = str(len(devices))
++-                if not raid['stripes']:
+++        if 'raid' in options:
+++            if options['raid'] == '0':
+++                if not options['stripesize']:
+++                    options['stripesize'] = "64"
+++                if not options['stripes'] and len(devices) > 0:
+++                    options['stripes'] = str(len(devices))
+++                if not options['stripes']:
++                     self.problem.error("Devices or number of " +
++                                        "stripes should be defined!")
++-                if raid['stripesize']:
++-                    command.extend(['-I', raid['stripesize']])
++-                if raid['stripes']:
++-                    command.extend(['-i', raid['stripes']])
+++                if options['stripesize']:
+++                    command.extend(['-I', options['stripesize']])
+++                if options['stripes']:
+++                    command.extend(['-i', options['stripes']])
+++            elif options['raid'] == '1' and \
+++                 self.supported_since([2,2,89],"raid1"):
+++                if options['stripesize'] or options['stripes']:
+++                    msg = "ERROR: Specifying stripe size or number of " + \
+++                          "stripes when creating raid1 volume with lvm backend"
+++                    self.problem.check(self.problem.NOT_SUPPORTED, msg)
+++                # Unfortunately 50%PVS does not work here because it does not
+++                # take in account metadata needed to create mirrored volume.
+++                # Using 49%PVS is not viable either because it will cut off
+++                # a lot of potential storage. So we'll require to specify
+++                # size in this case.
+++                if not size:
+++                    msg = "ERROR: Creating raid1 with lvm backend without " + \
+++                          "specifying size"
+++                    self.problem.check(self.problem.NOT_SUPPORTED, msg)
+++                command.extend(["--type", "raid1"])
+++            elif options['raid'] == '10' and \
+++                 self.supported_since([2,2,98],"raid10"):
+++                if not options['stripesize']:
+++                    options['stripesize'] = "64"
+++                if not options['stripes'] and len(devices) > 0:
+++                    if len(devices) < 4:
+++                        self.problem.error("Number of devices should be at " +
+++                                           "least 4 in raid 10 setup")
+++                    if len(devices) % 2 != 0:
+++                        self.problem.error("Number of devices should be " +
+++                                           "even in raid 10 setup")
+++                    options['stripes'] = str(len(devices)/2)
+++                if not options['stripes']:
+++                    self.problem.error("Devices or number of " +
+++                                       "stripes should be defined")
+++                if int(options['stripes']) < 2:
+++                    self.problem.error("Number of stripes should be at " +
+++                                       "least 2 in raid 10 setup")
+++                if options['stripesize']:
+++                    command.extend(['-I', options['stripesize']])
+++                if options['stripes']:
+++                    command.extend(['-i', options['stripes']])
+++                if not size:
+++                    msg = "ERROR: Creating raid10 with lvm backend without " + \
+++                          "specifying size"
+++                    self.problem.check(self.problem.NOT_SUPPORTED, msg)
+++                command.extend(["--type", "raid10"])
++             else:
++-                self.problem.not_supported("RAID level {0}".format(raid['level']) +
+++                self.problem.not_supported("RAID level {0}".format(options['raid']) +
++                                            " with \"lvm\" backend")
++ 
++         command.extend(devices)
++@@ -190,7 +249,7 @@ class VgsInfo(LvmInfo):
++         return "{0}/{1}/{2}".format(DM_DEV_DIR, vg, lvname)
++ 
++ 
++-class PvsInfo(LvmInfo):
+++class PvsInfo(LvmInfo, template.BackendDevice):
++ 
++     def __init__(self, *args, **kwargs):
++         super(PvsInfo, self).__init__(*args, **kwargs)
++@@ -221,7 +280,7 @@ class PvsInfo(LvmInfo):
++         self.run_lvm(command)
++ 
++ 
++-class LvsInfo(LvmInfo):
+++class LvsInfo(LvmInfo, template.BackendVolume):
++ 
++     def __init__(self, *args, **kwargs):
++         super(LvsInfo, self).__init__(*args, **kwargs)
++diff --git a/ssmlib/backends/md.py b/ssmlib/backends/md.py
++index 9e902d7..f33243c 100644
++--- a/ssmlib/backends/md.py
+++++ b/ssmlib/backends/md.py
++@@ -23,6 +23,7 @@ import socket
++ import datetime
++ from ssmlib import misc
++ from ssmlib import problem
+++from ssmlib.backends import template
++ 
++ try:
++     SSM_DM_DEFAULT_POOL = os.environ['SSM_DM_DEFAULT_POOL']
++@@ -32,15 +33,14 @@ except KeyError:
++ MDADM = "mdadm"
++ 
++ 
++-class MdRaid(object):
+++class MdRaid(template.Backend):
++ 
++-    def __init__(self, options, data=None):
+++    def __init__(self, *args, **kwargs):
+++        super(MdRaid, self).__init__(*args, **kwargs)
++         self.type = 'dm'
++-        self.data = data or {}
++         self._vol = {}
++         self._pool = {}
++         self._dev = {}
++-        self.options = options
++         self.hostname = socket.gethostname()
++         self._binary = misc.check_binary(MDADM)
++         self.default_pool_name = SSM_DM_DEFAULT_POOL
++@@ -50,7 +50,6 @@ class MdRaid(object):
++         if not self._binary:
++             return
++ 
++-        self.problem = problem.ProblemSet(options)
++         self.mounts = misc.get_mounts('/dev/md')
++ 
++         mdnumber = misc.get_dmnumber("md")
++@@ -109,16 +108,8 @@ class MdRaid(object):
++         command.insert(0, MDADM)
++         return misc.run(command, stdout=True)
++ 
++-    def __iter__(self):
++-        for item in sorted(self.data.iterkeys()):
++-            yield item
++-
++-    def __getitem__(self, key):
++-        if key in self.data.iterkeys():
++-            return self.data[key]
++-
++ 
++-class MdRaidVolume(MdRaid):
+++class MdRaidVolume(MdRaid, template.BackendVolume):
++ 
++     def __init__(self, *args, **kwargs):
++         super(MdRaidVolume, self).__init__(*args, **kwargs)
++@@ -135,7 +126,7 @@ class MdRaidVolume(MdRaid):
++         self.problem.not_supported("Resizing with \"md\" backend")
++ 
++ 
++-class MdRaidDevice(MdRaid):
+++class MdRaidDevice(MdRaid, template.BackendDevice):
++ 
++     def __init__(self, *args, **kwargs):
++         super(MdRaidDevice, self).__init__(*args, **kwargs)
++diff --git a/ssmlib/backends/template.py b/ssmlib/backends/template.py
++new file mode 100644
++index 0000000..94f4b40
++--- /dev/null
+++++ b/ssmlib/backends/template.py
++@@ -0,0 +1,95 @@
+++#!/usr/bin/env python
+++#
+++# (C)2013 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
+++#
+++# This program is free software: you can redistribute it and/or modify
+++# it under the terms of the GNU General Public License as published by
+++# the Free Software Foundation, either version 2 of the License, or
+++# (at your option) any later version.
+++#
+++# This program is distributed in the hope that it will be useful,
+++# but WITHOUT ANY WARRANTY; without even the implied warranty of
+++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+++# GNU General Public License for more details.
+++#
+++# You should have received a copy of the GNU General Public License
+++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+++
+++# template module for System Storage Manager contains template classes
+++# to use when creating new backend
+++
+++import os
+++from ssmlib import misc
+++from ssmlib import problem
+++
+++__all__ = ["Backend", "BackendPool", "BackendVolume", "BackendDevice"]
+++
+++try:
+++    SSM_TEMPLATE_DEFAULT_POOL = os.environ['SSM_TEMPLATE_DEFAULT_POOL']
+++except KeyError:
+++    SSM_TEMPLATE_DEFAULT_POOL = "template_pool"
+++
+++
+++class Backend(object):
+++    def __init__(self, options, data=None):
+++        self.type = 'template'
+++        self.data = data or {}
+++        self.options = options
+++        self.output = None
+++        self.default_pool_name = SSM_TEMPLATE_DEFAULT_POOL
+++        self.problem = problem.ProblemSet(options)
+++
+++    def __str__(self):
+++        return repr(self.data)
+++
+++    def __iter__(self):
+++        for item in sorted(self.data.iterkeys()):
+++            yield item
+++
+++    def __getitem__(self, key):
+++        if key in self.data.iterkeys():
+++            return self.data[key]
+++
+++
+++class BackendPool(Backend):
+++    def __init__(self, *args, **kwargs):
+++        super(BackendPool, self).__init__(*args, **kwargs)
+++
+++    def reduce(self, pool, device):
+++        self.problem.check(self.problem.NOT_SUPPORTED,
+++                        "Reducing pool with {0} backend".format(self.type))
+++
+++    def new(self, pool, devices):
+++        self.problem.check(self.problem.NOT_SUPPORTED,
+++                        "Creating new pool with {0} backend".format(self.type))
+++
+++    def extend(self, pool, devices):
+++        self.problem.check(self.problem.NOT_SUPPORTED,
+++                        "Extending pool with {0} backend".format(self.type))
+++
+++    def remove(self, pool):
+++        self.problem.check(self.problem.NOT_SUPPORTED,
+++                        "Removing pool with {0} backend".format(self.type))
+++
+++    def create(self, pool, size=None, name=None, devs=None,
+++               options=None):
+++        self.problem.check(self.problem.NOT_IMPLEMENTED,
+++                        "Creating volume with {0} backend".format(self.type))
+++
+++
+++class BackendVolume(Backend):
+++    def __init__(self, *args, **kwargs):
+++        super(BackendVolume, self).__init__(*args, **kwargs)
+++
+++    def remove(self, volume):
+++        self.problem.check(self.problem.NOT_SUPPORTED,
+++                        "Removing volume with {0} backend".format(self.type))
+++
+++
+++class BackendDevice(Backend):
+++    def __init__(self, *args, **kwargs):
+++        super(BackendDevice, self).__init__(*args, **kwargs)
+++
+++    def remove(self, devices):
+++        self.problem.check(self.problem.NOT_SUPPORTED,
+++                        "Removing device with {0} backend".format(self.type))
++diff --git a/ssmlib/main.py b/ssmlib/main.py
++index ef9232d..7aab312 100644
++--- a/ssmlib/main.py
+++++ b/ssmlib/main.py
++@@ -30,7 +30,7 @@ from ssmlib.backends import lvm, crypt, btrfs, md
++ 
++ EXTN = ['ext2', 'ext3', 'ext4']
++ SUPPORTED_FS = ['xfs', 'btrfs'] + EXTN
++-SUPPORTED_BACKENDS = ['lvm', 'btrfs']
+++SUPPORTED_BACKENDS = ['lvm', 'btrfs', 'crypt']
++ SUPPORTED_RAID = ['0', '1', '10']
++ os.environ['LC_NUMERIC'] = "C"
++ 
++@@ -222,7 +222,7 @@ class FsInfo(object):
++             raise Exception("File system on {0} is not ".format(self.device) +
++                             "clean, I will not attempt to resize it. Please," +
++                             "fix the problem first.")
++-        misc.run(command, stdout=True)
+++        return misc.run(command, stdout=True)[0]
++ 
++     def xfs_get_info(self, dev):
++         command = ["xfs_db", "-r", "-c", "sb", "-c", "print", dev]
++@@ -341,6 +341,11 @@ class DeviceInfo(object):
++                 dev['mount'] = "PARTITIONED"
++                 dev['type'] = 'disk'
++ 
+++    def remove(self, device):
+++        PR.error("It is not clear what do you want " +
+++                 "to achieve by removing " +
+++                 "{0}!".format(device))
+++
++     def set_globals(self, options):
++         self.options = options
++ 
++@@ -410,6 +415,9 @@ class Item(object):
++         else:
++             name = self.data['dev_name']
++         fs = FsInfo(name, self.obj.options)
+++        if 'fs_type' not in fs.data:
+++            # Not a file system
+++            return
++         try:
++             fs.mounted = self.data['mount']
++         except KeyError:
++@@ -639,6 +647,11 @@ class Pool(Storage):
++         except RuntimeError, err:
++             PR.warn(err)
++             PR.warn("Can not get information about btrfs pools")
+++        try:
+++            self._data['crypt'] = crypt.DmCryptPool(options=self.options)
+++        except RuntimeError, err:
+++            PR.warn(err)
+++            PR.warn("Can not get information about crypt pools")
++ 
++         backend = self.get_backend(SSM_DEFAULT_BACKEND)
++         self.default = Item(backend, backend.default_pool_name)
++@@ -682,10 +695,18 @@ class Devices(Storage):
++             PR.warn("Can not get information about MD devices")
++             my_md = Struct()
++             my_md.data = {}
+++        try:
+++            my_crypt = crypt.DmCryptDevice(options=self.options)
+++        except RuntimeError, err:
+++            PR.warn(err)
+++            PR.warn("Can not get information about crypt devices")
+++            my_crypt = Struct()
+++            my_crypt.data = {}
++ 
++         self._data['dev'] = DeviceInfo(data=dict(my_lvm.data.items() +
++                                                  my_btrfs.data.items() +
++-                                                 my_md.data.items()),
+++                                                 my_md.data.items() +
+++                                                 my_crypt.data.items()),
++                                        options=self.options)
++         self.header = ['Device', 'Free', 'Used',
++                        'Total', 'Pool', 'Mount point']
++@@ -862,30 +883,41 @@ class StorageHandle(object):
++     def check(self, args):
++         """
++         Check the file system on the volume. FsInfo is used for that purpose,
++-        except for btrfs.
+++        except for btrfs. Or check the volume itself if backend supports it.
++         """
++         err = 0
++         checked = 0
++-        for fs in args.device:
++-            print "Checking {0} file system on \'{1}\':".format(fs.fstype,
++-                                                                fs.device),
++-            if fs.mounted:
++-                print
+++        for dev in args.device:
+++            if 'mount' in dev:
++                 try:
++-                    if PR.check(PR.FS_MOUNTED, [fs.device, fs.mounted]):
++-                        misc.do_umount(fs.device)
+++                    if PR.check(PR.FS_MOUNTED, [dev['real_dev'], dev['mount']]):
+++                        misc.do_umount(dev['real_dev'])
++                 except problem.FsMounted:
++                     PR.warn("Unable to check file system " +
++-                            "\'{0}\' on volume \'{1}\'".format(fs.fstype,
++-                                                               fs.device))
+++                            "\'{0}\' on volume \'{1}\'".format(dev['fs_type'],
+++                                                               dev['real_dev']))
++                     continue
++-            ret = fs.fsck()
++-            checked += 1
++-            err += ret
++-            if ret:
++-                print "FAIL"
++-            else:
++-                print "OK"
+++
+++            # Does backend support check ?
+++            try:
+++                if getattr(dev, "check"):
+++                    print "Checking volume \'{0}\'.".format(dev['real_dev'])
+++                    ret = dev.check()
+++                    checked += 1
+++                    err += ret
+++                    if ret:
+++                        continue
+++            except AttributeError:
+++                pass
+++
+++            # Do we have a file system to check ?
+++            if 'fs_info' in dev:
+++                fs = dev['fs_info']
+++                print "Checking {0} file system on \'{1}\'.".format(fs.fstype,
+++                                                                    fs.device)
+++                ret = fs.fsck()
+++                checked += 1
+++                err += ret
++         if checked == 0:
++             PR.error("Nothing was checked")
++         if err > 0:
++@@ -944,6 +976,14 @@ class StorageHandle(object):
++             if not self.dev[dev] or 'pool_name' not in self.dev[dev]:
++                 # Check signature of existing file system on the device
++                 # and ask user whether to use it or not.
+++                if self.dev[dev] and 'mount' in self.dev[dev]:
+++                    try:
+++                        if PR.check(PR.FS_MOUNTED,
+++                                    [dev, self.dev[dev]['mount']]):
+++                            misc.do_umount(dev)
+++                    except problem.FsMounted:
+++                        args.device.remove(dev)
+++                        continue
++                 signature = misc.get_fs_type(dev)
++                 if signature and \
++                    not PR.check(PR.EXISTING_FILESYSTEM, [signature, dev]):
++@@ -977,6 +1017,10 @@ class StorageHandle(object):
++         args.pool = self.pool[args.volume['pool_name']]
++         vol_size = float(args.volume['vol_size'])
++ 
+++        if args.pool.type == 'btrfs':
+++            msg = "Resizing btrfs volume is not supported"
+++            raise problem.NotSupported(msg)
+++
++         if not args.size:
++             new_size = vol_size
++         elif args.size[0] == '+':
++@@ -987,7 +1031,7 @@ class StorageHandle(object):
++             new_size = float(args.size)
++         size_change = new_size - vol_size
++ 
++-        fs = True if 'fs_type' in args.volume else False
+++        fs = True if 'fs_info' in args.volume else False
++ 
++         if new_size <= 0:
++             PR.error("New volume size \'{0} KB\' is too small".format(new_size))
++@@ -996,28 +1040,39 @@ class StorageHandle(object):
++             # Try to grow the file system, since there is nothing to
++             # do with the volume itself.
++             if fs:
++-                args.volume['fs_info'].resize()
+++                ret = args.volume['fs_info'].resize()
+++                if ret:
+++                    PR.error("File system on {0} can not be resized".format(args.volume.name))
++             else:
++                 PR.check(PR.RESIZE_ALREADY_MATCH, [args.volume.name, new_size])
++             return
++ 
++         # Backend might not support pooling
++         if args.pool is None:
++-            pool_free = None
+++            pool_free = 0.0
++             pool_name = "none"
++         else:
++             pool_free = float(args.pool['pool_free'])
++             pool_name = args.pool.name
++ 
++-        have_size, devices = self._filter_device_list(args,
++-                                                      pool_free,
++-                                                      new_size)
+++        # No need to do anything with provided devices since
+++        # we do have enough space to cover the resize
+++        if (pool_free < size_change):
+++            have_size, devices = self._filter_device_list(args,
+++                                                          pool_free,
+++                                                          new_size)
+++        else:
+++            have_size = pool_free
++ 
++         if have_size < size_change:
++             PR.check(PR.RESIZE_NOT_ENOUGH_SPACE,
++                      [pool_name, args.volume.name, new_size])
++-        elif len(args.device) > 0 and new_size > vol_size:
++-            self.add(args, True)
+++        elif len(args.device) > 0 and size_change > pool_free:
+++            try:
+++                self.add(args, True)
+++            except problem.NotSupported:
+++                # Some backends might not support pooling at all.
+++                pass
++ 
++         if new_size != vol_size:
++             args.volume.resize(new_size, fs)
++@@ -1028,9 +1083,30 @@ class StorageHandle(object):
++         provided as arguments. If the device is not in the selected pool, then
++         add() is called on the pool prior to create().
++         """
+++
+++        lvname = self.create_volume(args)
+++
+++        if args.encrypt and misc.is_bdevice(lvname) and \
+++           SSM_DEFAULT_BACKEND != 'crypt':
+++            crypt = self.pool.get_backend("crypt")
+++            args.pool = Item(crypt, crypt.default_pool_name)
+++            options = {'encrypt': args.encrypt}
+++            lvname = args.pool.create(devs=[lvname],
+++                                      size=None,
+++                                      options=options,
+++                                      name=args.name)
+++
+++        if args.fstype and args.pool.type != 'btrfs':
+++            if self._create_fs(args.fstype, lvname) != 0:
+++                self._mpoint = None
+++        if self._mpoint:
+++            self.reinit_vol()
+++            self._do_mount(self.vol[lvname])
+++
+++    def create_volume(self, args):
++         # Get the size in kilobytes
++-        if args.size:
++-            args.size = misc.get_real_size(args.size)
+++#        if args.size:
+++#            args.size = misc.get_real_size(args.size)
++ 
++         if self._mpoint and not (args.fstype or args.pool.type == 'btrfs'):
++             if PR.check(PR.CREATE_MOUNT_NOFS, self._mpoint):
++@@ -1049,6 +1125,12 @@ class StorageHandle(object):
++         have_size, devices = self._filter_device_list(args, pool_free,
++                                                       args.size)
++ 
+++        # When the pool does not exist and there is no device usable
+++        # for creating the new pool, then there is no point of trying to
+++        # create a volume, since it would fail in the backend anyway.
+++        if not args.pool.exists() and len(devices) == 0:
+++            PR.check(PR.NO_DEVICES, args.pool.name)
+++
++         # Currently we do not allow setting subvolume size with btrfs. This
++         # should change in the future (quotas maybe) so the check should
++         # be removed or pushed to the backend itself.
++@@ -1058,12 +1140,6 @@ class StorageHandle(object):
++                         [have_size, args.pool.name]):
++                 args.size = None
++ 
++-        # When the pool does not exist and there is no device usable
++-        # for creating the new pool, then there is no point of trying to
++-        # create a volume, since it would fail in the backend anyway.
++-        if not args.pool.exists() and len(devices) == 0:
++-            PR.check(PR.NO_DEVICES, args.pool.name)
++-
++         if have_size == 0:
++             PR.error("Not enough space ({0} KB) to".format(have_size) +
++                      "to create volume")
++@@ -1080,32 +1156,52 @@ class StorageHandle(object):
++                          "must not exceed number of devices " +
++                          "({0})".format(tmp))
++ 
+++        if args.raid:
+++            # In raid we might has a requirement on a number of devices
+++            # available as well as different requirements on the size
+++            # available. We do not do any complicated math to figure out
+++            # whether we really do have enough space on the devices which
+++            # might differ in size. Let the respective backend tool deal
+++            # with that, it's always ok to fail, but we might cover the
+++            # most obvious cases here.
+++            dev_count = len(args.device)
+++            if args.pool.exists():
+++                dev_count += int(args.pool['dev_count'])
+++            if args.raid == '10' and args.stripes:
+++                if args.stripes * 2 > dev_count:
+++                    PR.error("Not enough devices ({0}) ".format(dev_count) +
+++                             "for specified number of ".format(args.stripes) +
+++                             "stripes ({0}). You need ".format(args.stripes) +
+++                             "at least {0} devices".format(args.stripes * 2))
+++            if args.raid == '1' and dev_count < 2:
+++                PR.error("You need at least 2 devices to create " +
+++                         "raid1 volume")
+++
++         # If we want btrfs pool and it does not exist yet, we do not
++         # want to call add since it would create it. Note that when
++         # btrfs pool is created the new btrfs volume is created as well
++         # because it is actually the same thing
++         if len(args.device) > 0 and \
++            not (not args.pool.exists() and args.pool.type == 'btrfs'):
++-            self.add(args, True)
+++            try:
+++                self.add(args, True)
+++            except problem.NotSupported:
+++                # Some backends might not support pooling at all.
+++                pass
++ 
+++        options = {}
+++        if args.encrypt:
+++            options['encrypt'] = args.encrypt
++         if args.raid:
++-            raid = {'level': args.raid,
++-                    'stripesize': args.stripesize,
++-                    'stripes': args.stripes}
++-        else:
++-            raid = None
+++            options['raid'] = args.raid
+++            options['stripesize'] = args.stripesize
+++            options['stripes'] = args.stripes
++ 
++         lvname = args.pool.create(devs=devices,
++                                   size=args.size,
++-                                  raid=raid,
+++                                  options=options,
++                                   name=args.name)
++-
++-        if args.fstype and args.pool.type != 'btrfs':
++-            if self._create_fs(args.fstype, lvname) != 0:
++-                self._mpoint = None
++-        if self._mpoint:
++-            self.reinit_vol()
++-            self._do_mount(self.vol[lvname])
+++        return lvname
++ 
++     def list(self, args):
++         """
++@@ -1150,11 +1246,20 @@ class StorageHandle(object):
++                 else:
++                     # Check signature of existing file system on the device
++                     # and as user whether to use it or not.
++-                    signature = misc.get_fs_type(dev)
++-                    if signature and \
++-                       not PR.check(PR.EXISTING_FILESYSTEM, [signature, dev]):
++-                        args.device.remove(dev)
++-                        continue
+++                    if item and 'mount' in item:
+++                        try:
+++                            if PR.check(PR.FS_MOUNTED, [dev, item['mount']]):
+++                                misc.do_umount(dev)
+++                        except problem.FsMounted:
+++                            args.device.remove(dev)
+++                            continue
+++                    else:
+++                        signature = misc.get_fs_type(dev)
+++                        if signature and \
+++                           not PR.check(PR.EXISTING_FILESYSTEM,
+++                                        [signature, dev]):
+++                            args.device.remove(dev)
+++                            continue
++ 
++         if args.pool.exists():
++             if len(args.device) > 0:
++@@ -1196,10 +1301,7 @@ class StorageHandle(object):
++                         pool.reduce(item.name)
++                         removed += 1
++                         continue
++-                    else:
++-                        PR.error("It is not clear what do you want " +
++-                                 "to achieve by removing " +
++-                                 "{0}!".format(item.name))
+++
++                 item.remove()
++                 removed += 1
++             except (RuntimeError, problem.SsmError), ex:
++@@ -1222,7 +1324,8 @@ class StorageHandle(object):
++             snap_size = vol_size * 0.20
++             user_set_size = False
++         else:
++-            snap_size = float(misc.get_real_size(args.size))
+++            snap_size = float(args.size)
+++            #snap_size = float(misc.get_real_size(args.size))
++             user_set_size = True
++ 
++         if pool_free < snap_size:
++@@ -1249,17 +1352,34 @@ class StorageHandle(object):
++                      "{0} with options \'{1}\'".format(args.directory,
++                                                        args.options))
++ 
+++    def can_check(self, device):
+++        fs = self.is_fs(device)
+++        if fs is False:
+++            real = misc.get_real_device(device)
+++            vol = self.vol[real]
+++            err = "'{0}' is not valid volume to check.".format(device)
+++            try:
+++                if not getattr(vol, "check"):
+++                    raise argparse.ArgumentTypeError(err)
+++                else:
+++                    return vol
+++            except AttributeError:
+++                raise argparse.ArgumentTypeError(err)
+++        else:
+++            return fs
+++
+++
++     def is_fs(self, device):
++         real = misc.get_real_device(device)
++ 
++         vol = self.vol[real]
++-        if vol and 'fs_type' in vol:
++-            return vol['fs_info']
+++        if vol and 'fs_info' in vol:
+++            return vol
++         dev = self.dev[real]
++-        if dev and 'fs_type' in dev:
++-            return dev['fs_info']
+++        if dev and 'fs_info' in dev:
+++            return dev
++         err = "'{0}' does not contain valid file system".format(real)
++-        raise argparse.ArgumentTypeError(err)
+++        return False
++ 
++     def _find_device_record(self, path):
++         """
++@@ -1294,7 +1414,10 @@ class StorageHandle(object):
++         return self.get_bdevice(path)
++ 
++     def get_bdevice(self, path):
++-        path = is_bdevice(path)
+++        path = misc.is_bdevice(path)
+++        if path == False:
+++            err = "'{0}' is not valid block device".format(path)
+++            raise argparse.ArgumentTypeError(err)
++         return self._find_device_record(path)
++ 
++     def is_pool(self, string):
++@@ -1310,7 +1433,7 @@ class StorageHandle(object):
++         if vol:
++             return vol
++         dev = self.dev[string]
++-        if dev and 'fs_type' in dev:
+++        if dev and 'fs_info' in dev:
++             return dev
++         err = "'{0}' is not a valid volume to resize".format(string)
++         raise argparse.ArgumentTypeError(err)
++@@ -1366,6 +1489,21 @@ class StorageHandle(object):
++         err = "'{0}' is not valid pool nor volume".format(string)
++         raise argparse.ArgumentTypeError(err)
++ 
+++def valid_size(size):
+++    """ Validate that the 'size' is usable size argument. This is almost the
+++    same as valid_resize_size() except we do not allow '+' and '-' signs
+++    """
+++
+++    err = "'{0}' is not valid size.".format(size)
+++    if len(size) and size[0] in ['+', '-']:
+++        raise argparse.ArgumentTypeError(err)
+++    try:
+++        ret = misc.get_real_size(size)
+++        if float(ret) < 0:
+++            raise argparse.ArgumentTypeError(err)
+++    except:
+++        raise argparse.ArgumentTypeError(err)
+++    return ret
++ 
++ def valid_resize_size(size):
++     """
++@@ -1404,7 +1542,9 @@ def valid_resize_size(size):
++         raise argparse.ArgumentTypeError(err)
++ 
++ 
++-def is_directory(self, string):
+++def is_directory(string):
+++    if string is None:
+++        raise argparse.ArgumentTypeError(err)
++     try:
++         mode = os.stat(string).st_mode
++     except OSError:
++@@ -1417,19 +1557,6 @@ def is_directory(self, string):
++         raise argparse.ArgumentTypeError(err)
++ 
++ 
++-def is_bdevice(path):
++-    path = misc.get_real_device(path)
++-    try:
++-        mode = os.lstat(path).st_mode
++-    except OSError:
++-        err = "'{0}' is not valid block device".format(path)
++-        raise argparse.ArgumentTypeError(err)
++-    if not stat.S_ISBLK(mode):
++-        err = "'{0}' is not valid block device".format(path)
++-        raise argparse.ArgumentTypeError(err)
++-    return path
++-
++-
++ def is_supported_fs(fs):
++     if fs in SUPPORTED_FS:
++         return fs
++@@ -1484,6 +1611,14 @@ class SsmParser(object):
++                      "({0}).".format(",".join(SUPPORTED_BACKENDS)),
++                 choices=SUPPORTED_BACKENDS,
++                 action=SetBackend)
+++        parser.add_argument('-n', '--dry-run',
+++                help='''Dry run. Do not do anything, just parse the command
+++                     line options and gather system information if necessary.
+++                     Note that with this option ssm will not perform all the
+++                     check as some of them are done by the backends
+++                     themselves. This option is mainly used for debugging
+++                     purposes.''',
+++                action="store_true")
++         return parser
++ 
++     def _get_parser_check(self):
++@@ -1494,7 +1629,7 @@ class SsmParser(object):
++                 help="Check consistency of the file system on the device.")
++         parser_check.add_argument('device', nargs='+',
++                 help="Device with file system to check.",
++-                type=self.storage.is_fs)
+++                type=self.storage.can_check)
++         parser_check.set_defaults(func=self.storage.check)
++         return parser_check
++ 
++@@ -1535,7 +1670,8 @@ class SsmParser(object):
++                      A size suffix K|k, M|m, G|g, T|t, P|p, E|e can be used
++                      to define 'power of two' units. If no unit is provided, it
++                      defaults to kilobytes. This is optional if if
++-                     not given maximum possible size will be used.''')
+++                     not given maximum possible size will be used.''',
+++                type=valid_size)
++         parser_create.add_argument('-n', '--name',
++                 help='''The name for the new logical volume. This is optional
++                      and if omitted, name will be generated by the
++@@ -1571,6 +1707,10 @@ class SsmParser(object):
++         parser_create.add_argument('-p', '--pool', default="",
++                 help="Pool to use to create the new volume.",
++                 type=self.storage.is_pool)
+++        parser_create.add_argument('-e', '--encrypt', nargs='?',
+++                choices=crypt.SUPPORTED_CRYPT, const=True,
+++                help='''Create encrpted volume. Extension to use can be
+++                     specified.''')
++         parser_create.add_argument('device', nargs='*',
++                 help='''Devices to use for creating the volume. If the device
++                      is not in any pool, it is added into the pool prior the
++@@ -1637,7 +1777,8 @@ class SsmParser(object):
++                      A size suffix K|k, M|m, G|g, T|t, P|p, E|e can be used
++                      to define 'power of two' units. If no unit is provided, it
++                      defaults to kilobytes. This is option and if not give,
++-                     the size will be determined automatically.''')
+++                     the size will be determined automatically.''',
+++                type=valid_size)
++         group = parser_snapshot.add_mutually_exclusive_group()
++         group.add_argument('-d', '--dest',
++                 help='''Destination of the snapshot specified with absolute
++@@ -1705,6 +1846,9 @@ def main(args=None):
++     # Register clean-up function on exit
++     sys.exitfunc = misc.do_cleanup
++ 
+++    if args.dry_run:
+++        return 0;
+++
++     try:
++         args.func(args)
++     except argparse.ArgumentTypeError, ex:
++diff --git a/ssmlib/misc.py b/ssmlib/misc.py
++index 8e731ff..3ff1577 100644
++--- a/ssmlib/misc.py
+++++ b/ssmlib/misc.py
++@@ -20,6 +20,7 @@
++ import os
++ import re
++ import sys
+++import stat
++ import tempfile
++ import threading
++ import subprocess
++@@ -191,13 +192,15 @@ def do_mount(device, directory, options=None):
++     run(command)
++ 
++ 
++-def do_umount(mpoint):
++-    command = ['umount', mpoint]
+++def do_umount(mpoint, all_targets=False):
+++    command = ['umount']
+++    if all_targets:
+++        command.append('--all-targets')
++     try:
++-        run(command)
+++        run(command + [mpoint])
++     except RuntimeError:
++-        command = ['umount', '-l', mpoint]
++-        run(command)
+++        command.append('-l')
+++        run(command + mpoint)
++ 
++ 
++ def temp_mount(device, options=None):
++@@ -228,12 +231,13 @@ def get_signature(device, types=None):
++         command.extend(['-u', types])
++     command.append(device)
++ 
++-    output = run(command, can_fail=True)[1].strip()
+++    ret, output = run(command, can_fail=True, stderr=False)
+++    output = output.strip()
++ 
++-    if len(output) > 0:
++-        return output
++-    else:
+++    if ret:
++         return None
+++    else:
+++        return output
++ 
++ 
++ def get_fs_type(device):
++@@ -319,16 +323,21 @@ def get_dmnumber(name):
++     return dmnumber
++ 
++ 
++-def wipefs(device, typ):
+++def wipefs(device, signatures):
+++    if type(signatures) is not list:
+++        signatures = [signatures]
++     command = ['wipefs', '-p', device]
++     output = run(command)[1]
+++    offset = []
++     for line in output[1:].split('\n'):
++         if not line:
++             continue
++         array = line.split(",")
++-        if array[-1] == typ:
++-            command = ['wipefs', '--offset', array[0], device]
++-            run(command)
+++        if array[-1] in signatures:
+++            offset.extend(['--offset', array[0]])
+++    if len(offset) > 1:
+++        command = ['wipefs'] + offset + [device]
+++        run(command)
++ 
++ 
++ def humanize_size(arg):
++@@ -545,3 +554,26 @@ def terminal_size(default=(25, 80)):
++         if not cr:
++             cr = (25, 80)
++     return int(cr[1]), int(cr[0])
+++
+++
+++def is_bdevice(path):
+++    """
+++    Check whether the path is block device. If it is return
+++    the path to the real block device, otherwise return False
+++    """
+++    path = get_real_device(path)
+++    try:
+++        mode = os.lstat(path).st_mode
+++    except OSError:
+++        return False
+++    if not stat.S_ISBLK(mode):
+++        return False
+++    return path
+++
+++
+++def get_device_size(device):
+++    devname = device.split('/')[-1]
+++    with open("/sys/block/{0}/size".format(devname), 'r') as f:
+++        for line in f:
+++            size = int(line)/2
+++            return size
++diff --git a/ssmlib/problem.py b/ssmlib/problem.py
++index 56846df..dfa6ec6 100644
++--- a/ssmlib/problem.py
+++++ b/ssmlib/problem.py
++@@ -22,7 +22,8 @@ import sys
++ __all__ = ["ProblemSet", "SsmError", "GeneralError", "ProgrammingError",
++            "BadEnvVariable", "NotEnoughSpace", "ResizeMatch", "FsNotSpecified",
++            "DeviceUsed", "ExistingFilesystem", "NoDevices", "ToolMissing",
++-           "CanNotRun", "CommandFailed", "UserInterrupted", "NotSupported"]
+++           "CanNotRun", "CommandFailed", "UserInterrupted", "NotSupported",
+++           "NotImplemented"]
++ 
++ # Define prompt codes
++ PROMPT_NONE =           0
++@@ -52,9 +53,10 @@ FL_DEFAULT_NO =         16
++ FL_SILENT =             32
++ FL_EXIT_ON_NO =         64
++ FL_EXIT_ON_YES =        128
++-FL_FATAL =              256
+++FL_NO_MESSAGE =         256
++ FL_FORCE_YES =          512
++ FL_FORCE_NO =           1024
+++FL_FATAL =              (2048 | FL_NO_MESSAGE)
++ 
++ 
++ class SsmError(Exception):
++@@ -65,7 +67,7 @@ class SsmError(Exception):
++         self.errcode = errcode
++ 
++     def __str__(self):
++-        return repr("Error ({0}): {1}".format(self.errcode, self.msg))
+++        return "SSM Error ({0}): {1}".format(self.errcode, self.msg)
++ 
++ 
++ class GeneralError(SsmError):
++@@ -142,6 +144,10 @@ class ExistingFilesystem(SsmError):
++     def __init__(self, msg, errcode=2015):
++         super(ExistingFilesystem, self).__init__(msg, errcode)
++ 
+++class NotImplemented(SsmError):
+++    def __init__(self, msg, errcode=2016):
+++        super(NotImplemented, self).__init__(msg, errcode)
+++
++ 
++ class ProblemSet(object):
++ 
++@@ -158,7 +164,7 @@ class ProblemSet(object):
++              PROMPT_NONE, FL_FATAL, ProgrammingError]
++ 
++         self.GENERAL_ERROR = \
++-            ['SSM Error: {0}!', PROMPT_NONE, FL_FATAL, GeneralError]
+++            ['{0}!', PROMPT_NONE, FL_FATAL, GeneralError]
++ 
++         self.GENERAL_INFO = \
++             ['SSM Info: {0}', PROMPT_NONE, FL_NONE, None]
++@@ -222,11 +228,17 @@ class ProblemSet(object):
++             ['{0} is not supported!',
++              PROMPT_NONE, FL_FATAL, NotSupported]
++ 
+++        self.NOT_IMPLEMENTED = \
+++            ['\'{0}\' function is not implemented by {1}!',
+++            PROMPT_NONE, FL_FATAL, NotImplemented]
+++
++     def _can_print_message(self, flags):
++         if (flags & FL_DEBUG_ONLY):
++             return self.options.debug
++         elif (flags & FL_VERBOSE_ONLY):
++             return self.options.verbose
+++        elif (flags & FL_NO_MESSAGE):
+++            return False
++         else:
++             return True
++ 
++@@ -289,14 +301,10 @@ class ProblemSet(object):
++ 
++         if self._can_print_message(flags) and \
++            (flags & FL_MSG_ONLY or prompt_msg is None):
++-            print >> sys.stderr, message,
++-        else:
++-            print message,
+++            print >> sys.stderr, message
++         if not flags & FL_MSG_ONLY and prompt_msg is not None:
++-            print '{0}'.format(prompt_msg),
+++            print message, '{0}'.format(prompt_msg),
++             res = self._ask_question(flags)
++-        else:
++-            print >> sys.stderr
++ 
++         if (flags & FL_FATAL):
++             if exc:
++diff --git a/tests/bashtests/001-lvm-add.sh b/tests/bashtests/001-lvm-add.sh
++index fee51a8..cfe95da 100755
++--- a/tests/bashtests/001-lvm-add.sh
+++++ b/tests/bashtests/001-lvm-add.sh
++@@ -131,6 +131,16 @@ mkfs.ext3 $dev1
++ # Default answer is No
++ not ssm add $dev1
++ not check vg_field $SSM_LVM_DEFAULT_POOL pv_count 1
+++# It can be forced though
+++ssm -f add $dev1
+++check vg_field $SSM_LVM_DEFAULT_POOL pv_count 1
+++ssm -f remove $SSM_LVM_DEFAULT_POOL
+++
+++# Try to use device with existing file system
+++mkfs.ext3 $dev1
+++# Default answer is No
+++not ssm add $dev1
+++not check vg_field $SSM_LVM_DEFAULT_POOL pv_count 1
++ ssm add $dev1 $dev2
++ check vg_field $SSM_LVM_DEFAULT_POOL pv_count 1
++ ssm -f remove --all
++diff --git a/tests/bashtests/002-lvm-create.sh b/tests/bashtests/002-lvm-create.sh
++index aceea6d..d316e5d 100755
++--- a/tests/bashtests/002-lvm-create.sh
+++++ b/tests/bashtests/002-lvm-create.sh
++@@ -115,6 +115,64 @@ check list_table "$(ssm list pool)" $SSM_LVM_DEFAULT_POOL lvm 10 none none 960.0
++ check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol1 $SSM_LVM_DEFAULT_POOL 960.00MB striped
++ ssm  -f remove $SSM_LVM_DEFAULT_POOL
++ 
+++# Create a raid 1 logical volume
+++# Size of the volume must be specified for lvm raid1
+++not ssm create -r 1 $dev1 $dev2
+++size=$((DEV_SIZE/2))
+++size=$(align_size_up $size)
+++ssm create -s ${size}M -r 1 $dev1 $dev2
+++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 segtype raid1
+++check list_table "$(ssm list pool)" $SSM_LVM_DEFAULT_POOL lvm 2 none none 192.00MB
+++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol1 $SSM_LVM_DEFAULT_POOL ${size}.00MB raid1
+++
+++ssm add $TEST_DEVS
+++size=$((DEV_SIZE*2))
+++size=$(align_size_up $size)
+++ssm create -s ${size}M -r 1
+++check list_table "$(ssm list pool)" $SSM_LVM_DEFAULT_POOL lvm 10 none none 960.00MB
+++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol2 $SSM_LVM_DEFAULT_POOL ${size}.00MB raid1
+++ssm  -f remove $SSM_LVM_DEFAULT_POOL
+++
+++# Create a raid 10 logical volume
+++# Size of the volume must be specified for lvm raid10
+++not ssm create -r 10 $dev1 $dev2 $dev3 $dev4
+++# Minimum is 4 devices
+++not ssm create -s ${DEV_SIZE}M -r 10 $dev1 $dev2
+++# Number of device has to be even
+++not ssm create -s ${DEV_SIZE}M -r 10 $dev1 $dev2 $dev3 $dev4 $dev5
+++ssm remove $dev5
+++ssm create -s ${DEV_SIZE}M -r 10 $dev1 $dev2 $dev3 $dev4
+++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 stripes 4
+++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 segtype raid10
+++check list_table "$(ssm list pool)" $SSM_LVM_DEFAULT_POOL lvm 4 none none 384.00MB
+++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol1 $SSM_LVM_DEFAULT_POOL 104.00MB raid1
+++size=56
+++# Stripes or device has to be specified
+++not ssm create -s ${size}M -r 10
+++ssm create -s ${size}M -r 10 --stripes 2
+++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol2 stripes 4
+++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol2 segtype raid10
+++check list_table "$(ssm list pool)" $SSM_LVM_DEFAULT_POOL lvm 4 none none 384.00MB
+++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol2 $SSM_LVM_DEFAULT_POOL ${size}.00MB raid10
+++ssm add $TEST_DEVS
+++size=60
+++ssm create -s ${size}M -r 10 --stripes 3
+++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol3 stripes 6
+++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol3 segtype raid10
+++check list_table "$(ssm list pool)" $SSM_LVM_DEFAULT_POOL lvm 10 none none 960.00MB
+++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol3 $SSM_LVM_DEFAULT_POOL ${size}.00MB raid10
+++ssm  -f remove $SSM_LVM_DEFAULT_POOL
+++ssm add $TEST_DEVS
+++size=$((DEV_SIZE*2))
+++size=$(align_size_up $size)
+++ssm create -s ${size}M -r 10 $TEST_DEVS
+++ssm list
+++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 stripes 10
+++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 segtype raid10
+++check list_table "$(ssm list pool)" $SSM_LVM_DEFAULT_POOL lvm 10 none none 960.00MB
+++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol1 $SSM_LVM_DEFAULT_POOL ${size}.00MB raid10
+++ssm  -f remove $SSM_LVM_DEFAULT_POOL
+++
++ # Create several volumes with different parameters
++ ssm  add $TEST_DEVS
++ not ssm create -I 8 -i $(($DEV_COUNT/2)) -s $(($DEV_SIZE*2))M
++@@ -174,7 +232,8 @@ for fs in $TEST_FS; do
++ 	check vg_field $SSM_LVM_DEFAULT_POOL pv_count 3
++ 
++ 	# pool doesn't exist
++-	ssm create --fstype $fs -s $((DEV_SIZE/2))m -n randvol $dev4 $mnt2
+++	ssm create --fstype $fs -s $((DEV_SIZE/2))m -n randvol $dev4
+++	ssm mount  $SSM_LVM_DEFAULT_POOL/randvol $mnt2
++ 	size=`align_size_up $((DEV_SIZE/2))`
++ 	check lv_field $SSM_LVM_DEFAULT_POOL/randvol lv_size $size.00m
++ 	check mountpoint $SSM_LVM_DEFAULT_POOL-randvol $mnt2
++@@ -282,4 +341,8 @@ not ssm create
++ ssm add $TEST_DEVS
++ not ssm create -p $pool1
++ not ssm create -r 0 -I 16 -i 3 $dev1 $dev2
+++not ssm create -s-20M
+++not ssm create -s+20M
+++not ssm create --size 25.8.1991
+++not ssm create --size linux
++ ssm  -f remove --all
++diff --git a/tests/bashtests/004-lvm-resize.sh b/tests/bashtests/004-lvm-resize.sh
++index f430851..c863f36 100755
++--- a/tests/bashtests/004-lvm-resize.sh
+++++ b/tests/bashtests/004-lvm-resize.sh
++@@ -48,20 +48,79 @@ TEST_MNT=$TESTDIR/mnt
++ 
++ _test_resize()
++ {
++-	size=$((TEST_MAX_SIZE/2))
++-	echo 'y' | ssm -f resize --size ${size}M ${DM_DEV_DIR}/$DEFAULT_VOLUME
+++	# Test with no device
+++	# Test size increase
+++	size=$DEV_SIZE
+++	check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
+++	size=$((DEV_SIZE + 12))
+++	ssm resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1
+++	check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
+++	size=$((size + 3))
+++	ssm resize -s +3M $SSM_LVM_DEFAULT_POOL/$lvol1
++ 	size=$(align_size_up $size)
++ 	check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
+++	# Test size decrese
+++	if [ "$fs" != "xfs" ]; then
+++		size=$((size - 8))
+++		ssm -f resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1
+++		check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
+++		size=$((size - 7))
+++		ssm -f resize -s-7M $SSM_LVM_DEFAULT_POOL/$lvol1
+++		size=$(align_size_up $size)
+++		check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
+++		# Test with devcie belongs to no pool
+++		# size decrease
+++		size=$((size - 12))
+++		ssm -f resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev4
+++		check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
+++		check vg_field $SSM_LVM_DEFAULT_POOL pv_count 3
+++		check vg_field $pool1 pv_count 3
+++	fi
+++	# If the volume is already of the given size ssm will attempt to resize
+++	# file system to cover the whole device. Note that we do not check for
+++	# the file system size because it's not really necessary. So this would
+++	# fail if the file system is present. This might change in future, so
+++	# comment it out for now.
+++	# size doesn't change
+++	#not ssm -f resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev4
+++	#check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
+++	#check vg_field $SSM_LVM_DEFAULT_POOL pv_count 3
+++	#check vg_field $pool1 pv_count 3
+++	# size increase
+++	size=$((size + 12))
+++	ssm resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev4
+++	check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
+++	check vg_field $SSM_LVM_DEFAULT_POOL pv_count 3
+++	check vg_field $pool1 pv_count 3
++ 
++-	# xfs does not support shrinking (xfs only grows big!! :))
+++	# Test with device belongs to other pool
+++	# size decrease
++ 	if [ "$fs" != "xfs" ]; then
++-		ssm -f -v resize -s-$(($TEST_MAX_SIZE/4))M $DEFAULT_VOLUME
++-		size=$(align_size_up $(($size-($TEST_MAX_SIZE/4))))
+++		size=$((size - 12))
+++		ssm -f resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev6
++ 		check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
+++		check vg_field $SSM_LVM_DEFAULT_POOL pv_count 3
+++		check vg_field $pool1 pv_count 3
++ 	fi
++-	echo 'y' | ssm -f resize --size +$(($TEST_MAX_SIZE/5))M $DEFAULT_VOLUME
++-	size=$(align_size_up $(($size+($TEST_MAX_SIZE/5))))
+++	# size doesn't change
+++	#not ssm -f resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev6
+++	#check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
+++	#check vg_field $SSM_LVM_DEFAULT_POOL pv_count 3
+++	#check vg_field $pool1 pv_count 3
+++	# size increase
+++	size=$((size + 12))
+++	ssm -f resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev6
+++	check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
+++	check vg_field $SSM_LVM_DEFAULT_POOL pv_count 3
+++	check vg_field $pool1 pv_count 3
+++
+++	# when resize to excessive amount
+++	size=$((DEV_SIZE*4))
+++	not ssm resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1
+++	ssm resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev8 $dev9
++ 	check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
+++	check vg_field $SSM_LVM_DEFAULT_POOL pv_count 5
+++
++ }
++ 
++ ssm add $TEST_DEVS
++@@ -100,46 +159,37 @@ ssm -f remove $SSM_LVM_DEFAULT_POOL
++ ssm create --size $((DEV_SIZE/2))M $dev1
++ check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 1
++ ssm resize --size +$((DEV_SIZE/3))M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev2
++-check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 2
+++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 1
++ ssm -f resize -s-$((DEV_SIZE/3))M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev2 $dev3
++ ssm resize --size +$((DEV_SIZE/3))M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev2 $dev3
++-check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 3
+++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 1
++ ssm -f resize -s-$((DEV_SIZE/3))M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev2 $dev3
++-check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 3
+++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 1
++ ssm resize --size +${DEV_SIZE}M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev2 $dev3
++ check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 3
++ ssm -f remove $SSM_LVM_DEFAULT_POOL
++ 
+++
+++ssm add $dev{1,2,3}
+++ssm create -s ${DEV_SIZE}M
+++ssm add -p $pool1 $dev{5,6,7}
+++_test_resize
+++ssm -f remove $SSM_LVM_DEFAULT_POOL
+++ssm -f remove $pool1
+++
+++
++ [ ! -d $TEST_MNT ] && mkdir $TEST_MNT &> /dev/null
++ for fs in $TEST_FS; do
++-	# umounted test
++-	ssm add $TEST_DEVS
++-	size=$((TEST_MAX_SIZE/4))
++-	ssm create --fs $fs --size ${size}M $TEST_DEVS
++-
+++	ssm add $dev{1,2,3}
+++	ssm create -s ${DEV_SIZE}M --fs $fs
+++	ssm -f check $DEFAULT_VOLUME
+++	ssm add -p $pool1 $dev{5,6,7}
++ 	_test_resize
++ 	ssm -f check $DEFAULT_VOLUME
++ 	ssm -f remove $SSM_LVM_DEFAULT_POOL
++-
++-        echo $fs
++-        if [ $fs == 'ext2' ]; then
++-            continue
++-        fi
++-
++-        # Disable this for now, since fsadm does not handle -f and -y correctly
++-	# mounted test
++-	#ssm add $TEST_DEVS
++-	size=$((TEST_MAX_SIZE/4))
++-	#ssm create --fs $fs --size ${size}M $TEST_DEVS
++-
++-	#mount ${DM_DEV_DIR}/$DEFAULT_VOLUME $TEST_MNT
++-
++-	#_test_resize
++-
++-	#umount $TEST_MNT
++-	#ssm -f check $DEFAULT_VOLUME
++-	#ssm -f remove $SSM_LVM_DEFAULT_POOL
+++	ssm -f remove $pool1
++ done
+++# There should not be anything to remove
++ not ssm  -f remove --all
++ 
++ ssm create $dev1
++diff --git a/tests/bashtests/007-btrfs-create.sh b/tests/bashtests/007-btrfs-create.sh
++index 1ea27df..c971a76 100755
++--- a/tests/bashtests/007-btrfs-create.sh
+++++ b/tests/bashtests/007-btrfs-create.sh
++@@ -88,6 +88,7 @@ ssm -f remove $SSM_BTRFS_DEFAULT_POOL
++ 
++ # Create raid 10 volume with just one device
++ ssm create -r 10 $dev1 $dev2 $dev3 $dev4
+++ssm check $SSM_BTRFS_DEFAULT_POOL
++ not ssm create $dev1 -p $pool1
++ ssm -f remove $SSM_BTRFS_DEFAULT_POOL
++ 
++diff --git a/tests/bashtests/011-lvm-list.sh b/tests/bashtests/011-lvm-list.sh
++index 66567a1..73cea90 100755
++--- a/tests/bashtests/011-lvm-list.sh
+++++ b/tests/bashtests/011-lvm-list.sh
++@@ -1,6 +1,6 @@
++ #!/bin/bash
++ #
++-# (C)2012 Red Hat, Inc., Tom Marek <tmarek at redhat.com>
+++# (C)2013 Red Hat, Inc., Jimmy Pan <jipan at redhat.com>
++ #
++ # This program is free software: you can redistribute it and/or modify
++ # it under the terms of the GNU General Public License as published by
++@@ -21,9 +21,10 @@ export test_description='Check whether list command prints correct values for lv
++ . lib/test
++ 
++ DEV_COUNT=10
++-DEV_SIZE=100
+++DEV_SIZE=128
++ TEST_MAX_SIZE=$(($DEV_COUNT*$DEV_SIZE))
++ aux prepare_devs $DEV_COUNT $DEV_SIZE
+++aux prepare_mnts 10
++ TEST_DEVS=$(cat DEVICES)
++ export LVOL_PREFIX="lvol"
++ export SSM_DEFAULT_BACKEND='lvm'
++@@ -33,8 +34,14 @@ export SSM_NONINTERACTIVE='1'
++ snap1="snap1"
++ snap2="snap2"
++ 
+++lvol1=${LVOL_PREFIX}001
+++lvol2=${LVOL_PREFIX}002
+++lvol3=${LVOL_PREFIX}003
+++
+++pool0=$vg1
++ pool1=$vg2
++ pool2=$vg3
+++pool3=$vg4
++ 
++ TEST_FS=
++ which mkfs.ext2 && TEST_FS+="ext2 "
++@@ -45,28 +52,262 @@ which mkfs.xfs  && TEST_FS+="xfs"
++ TEST_MNT=$TESTDIR/mnt
++ [ ! -d $TEST_MNT ] && mkdir $TEST_MNT &> /dev/null
++ 
++-##LVM
++-# Check devices
++-ssm add $TEST_DEVS
++-ssm_output=$(ssm list dev)
++-for device in ${TEST_DEVS}; do
++-     check list_table "$ssm_output" $device 96.00MB 0.00KB 96.00MB $SSM_LVM_DEFAULT_POOL
+++# Prepare pools and volumes
+++
+++vol1=volsf
+++vol2=volss
+++vol3=volmf
+++vol4=volms1
+++vol5=volms2
+++vol6=volms3
+++maxvolsz=$((DEV_SIZE-4))
+++size1=$maxvolsz
+++size2=$((DEV_SIZE/2))
+++size3=$((maxvolsz*2))
+++size4=$((DEV_SIZE/2))
+++size5=$((DEV_SIZE*2))
+++size6=$((DEV_SIZE/4))
+++size4s=$((size4-20))
+++size2r=$((size2-4))
+++size5r=$((size5+16))
+++
+++
+++# Test without a filesystem
+++ssm -f create -n $vol1 $dev1
+++ssm create -n $vol2 -p $pool1 -s ${size2}M $dev2
+++ssm create -n $vol3 -p $pool2 $dev3 $dev4
+++ssm add -p $pool3 $dev{5,6,7,8}
+++ssm create -p $pool3 -s ${size4}m -n $vol4
+++ssm create -p $pool3 -s ${size5}m -n $vol5
+++ssm create -p $pool3 -s ${size6}m -n $vol6
+++
+++# We shouldn't see ssm list fs here
+++test `ssm list fs | wc -l` -le 1
+++# Check vol, dev, pool, resized vol, and snapshot
+++output=`ssm list vol`
+++check list_table "$output" $pool0/$vol1 $pool0 $((size1)).00MB linear
+++check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB linear
+++check list_table "$output" $pool2/$vol3 $pool2 $((size3)).00MB linear
+++check list_table "$output" $pool3/$vol4 $pool3 $((size4)).00MB linear
+++check list_table "$output" $pool3/$vol5 $pool3 $((size5)).00MB linear
+++check list_table "$output" $pool3/$vol6 $pool3 $((size6)).00MB linear
+++output=`ssm list dev`
+++check list_table "$output" $dev1 0.00KB $((size1)).00MB 124.00MB $pool0
+++check list_table "$output" $dev2 $((maxvolsz-size2)).00MB $((size2)).00MB 124.00MB $pool1
+++check list_table "$output" $dev3 0.00KB $((maxvolsz)).00MB 124.00MB $pool2
+++check list_table "$output" $dev4 0.00KB $((maxvolsz)).00MB 124.00MB $pool2
+++check list_table "$output" $dev5 none none 124.00MB $pool3
+++check list_table "$output" $dev6 none none 124.00MB $pool3
+++check list_table "$output" $dev7 none none 124.00MB $pool3
+++check list_table "$output" $dev8 none none 124.00MB $pool3
+++output=`ssm list pool`
+++check list_table "$output" $pool0 lvm 1 0.00KB $((size1)).00MB $((maxvolsz)).00MB
+++check list_table "$output" $pool1 lvm 1 $((maxvolsz-size2)).00MB $((size2)).00MB $((maxvolsz)).00MB
+++check list_table "$output" $pool2 lvm 2 0.00KB $((size3)).00MB $((maxvolsz*2)).00MB
+++check list_table "$output" $pool3 lvm 4 $((maxvolsz*4-size4-size5-size6)).00MB $((size4+size5+size6)).00MB $((maxvolsz*4)).00MB
+++
+++# Check ssm vol after resize
+++ssm -f resize $pool1/$vol2 -s ${size2r}M
+++ssm resize -s ${size5r}m $pool3/$vol5
+++output=`ssm list vol`
+++check list_table "$output" $pool1/$vol2 $pool1 $size2r.00MB linear
+++check list_table "$output" $pool3/$vol5 $pool3 $((size5r)).00MB linear
+++
+++ssm snapshot $pool3/$vol4 -n snap1
+++ssm snapshot $pool3/$vol4 -s ${size4s}m -n snap2
+++output=`ssm list snap`
+++check list_table "$output" $pool3/snap1 $vol4 $pool3 none none linear
+++check list_table "$output" $pool3/snap2 $vol4 $pool3 $size4s.00MB none linear
+++
+++
+++ssm -f remove -a
+++
+++
+++# Test with filesystem
+++for fs in $TEST_FS ; do
+++	ssm -f create -n $vol1 $dev1 --fs $fs
+++	ssm create -n $vol2 -p $pool1 -s ${size2}M $dev2 --fs $fs
+++	ssm create -n $vol3 -p $pool2 $dev3 $dev4 --fs $fs
+++	ssm add -p $pool3 $dev{5,6,7,8}
+++	ssm create -p $pool3 -s ${size4}m -n $vol4 --fs $fs
+++	ssm create -p $pool3 -s ${size5}m -n $vol5 --fs $fs
+++	ssm create -p $pool3 -s ${size6}m -n $vol6 --fs $fs
+++
+++	# Check fs, vol, dev, pool, resized vol, and snapshot
+++	output=`ssm list fs`
+++	# xfs has some strange used size, so we don't check it
+++	if [ $fs == xfs ] ; then
+++		check list_table "$output" $pool0/$vol1 $pool0 $size1.00MB $fs none none linear
+++		check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB $fs none none linear
+++		check list_table "$output" $pool2/$vol3 $pool2 $size3.00MB $fs none none linear
+++		check list_table "$output" $pool3/$vol4 $pool3 $size4.00MB $fs none none linear
+++		check list_table "$output" $pool3/$vol5 $pool3 $size5.00MB $fs none none linear
+++		check list_table "$output" $pool3/$vol6 $pool3 $size6.00MB $fs none none linear
+++	else
+++		check list_table "$output" $pool0/$vol1 $pool0 $size1.00MB $fs $size1.00MB none linear
+++		check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB $fs $size2.00MB none linear
+++		check list_table "$output" $pool2/$vol3 $pool2 $size3.00MB $fs $size3.00MB none linear
+++		check list_table "$output" $pool3/$vol4 $pool3 $size4.00MB $fs $size4.00MB none linear
+++		check list_table "$output" $pool3/$vol5 $pool3 $size5.00MB $fs $size5.00MB none linear
+++		check list_table "$output" $pool3/$vol6 $pool3 $size6.00MB $fs $size6.00MB none linear
+++	fi
+++
+++	output=`ssm list vol`
+++	# xfs has some strange used size, so we don't check it
+++	if [ $fs == xfs ] ; then
+++		check list_table "$output" $pool0/$vol1 $pool0 $size1.00MB $fs none none linear
+++		check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB $fs none none linear
+++		check list_table "$output" $pool2/$vol3 $pool2 $size3.00MB $fs none none linear
+++		check list_table "$output" $pool3/$vol4 $pool3 $size4.00MB $fs none none linear
+++		check list_table "$output" $pool3/$vol5 $pool3 $size5.00MB $fs none none linear
+++		check list_table "$output" $pool3/$vol6 $pool3 $size6.00MB $fs none none linear
+++	else
+++		check list_table "$output" $pool0/$vol1 $pool0 $size1.00MB $fs $size1.00MB none linear
+++		check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB $fs $size2.00MB none linear
+++		check list_table "$output" $pool2/$vol3 $pool2 $size3.00MB $fs $size3.00MB none linear
+++		check list_table "$output" $pool3/$vol4 $pool3 $size4.00MB $fs $size4.00MB none linear
+++		check list_table "$output" $pool3/$vol5 $pool3 $size5.00MB $fs $size5.00MB none linear
+++		check list_table "$output" $pool3/$vol6 $pool3 $size6.00MB $fs $size6.00MB none linear
+++	fi
+++
+++	output=`ssm list dev`
+++	check list_table "$output" $dev1 0.00KB $((size1)).00MB 124.00MB $pool0
+++	check list_table "$output" $dev2 $((maxvolsz-size2)).00MB $((size2)).00MB 124.00MB $pool1
+++	check list_table "$output" $dev3 0.00KB $((maxvolsz)).00MB 124.00MB $pool2
+++	check list_table "$output" $dev4 0.00KB $((maxvolsz)).00MB 124.00MB $pool2
+++	check list_table "$output" $dev5 none none 124.00MB $pool3
+++	check list_table "$output" $dev6 none none 124.00MB $pool3
+++	check list_table "$output" $dev7 none none 124.00MB $pool3
+++	check list_table "$output" $dev8 none none 124.00MB $pool3
+++	output=`ssm list pool`
+++	check list_table "$output" $pool0 lvm 1 0.00KB $((size1)).00MB $((maxvolsz)).00MB
+++	check list_table "$output" $pool1 lvm 1 $((maxvolsz-size2)).00MB $((size2)).00MB $((maxvolsz)).00MB
+++	check list_table "$output" $pool2 lvm 2 0.00KB $((size3)).00MB $((maxvolsz*2)).00MB
+++	check list_table "$output" $pool3 lvm 4 $((maxvolsz*4-size4-size5-size6)).00MB $((size4+size5+size6)).00MB $((maxvolsz*4)).00MB
+++
+++	# Check ssm vol after resize
+++	# xfs size cannot reduce
+++	if [ "$fs" != xfs ] ; then
+++		ssm -f resize $pool1/$vol2 -s ${size2r}M
+++	fi
+++	ssm resize -s ${size5r}m $pool3/$vol5
+++
+++	output=`ssm list vol`
+++	# xfs has some strange used size, so we don't check it
+++	if [ "$fs" != xfs ] ; then
+++		check list_table "$output" $pool1/$vol2 $pool1 $size2r.00MB $fs $size2r none linear
+++		check list_table "$output" $pool3/$vol5 $pool3 $size5r.00MB $fs $size5r none linear
+++	else
+++		check list_table "$output" $pool3/$vol5 $pool3 $size5r.00MB $fs none none linear
+++	fi
+++
+++	ssm snapshot $pool3/$vol4 -n snap1
+++	ssm snapshot $pool3/$vol4 -s ${size4s}m -n snap2
+++
+++	output=`ssm list snap`
+++	check list_table "$output" $pool3/snap1 $vol4 $pool3 none none linear
+++	check list_table "$output" $pool3/snap2 $vol4 $pool3 $size4s.00MB none linear
+++
+++	ssm -f remove -a
+++
++ done
++ 
++-# Check pools
++-check list_table "$(ssm list pool)" $SSM_LVM_DEFAULT_POOL $SSM_DEFAULT_BACKEND $DEV_COUNT none none 960.00MB
++-ssm -f remove --all
+++# Test with a mountpoint
+++for fs in $TEST_FS ; do
+++	ssm -f create -n $vol1 --fs $fs $dev1 $mnt1
+++	ssm create -n $vol2 -p $pool1 -s ${size2}M --fs $fs $dev2 $mnt2
+++	ssm create -n $vol3 -p $pool2 --fs $fs $dev3 $dev4 $mnt3
+++	ssm add -p $pool3 $dev{5,6,7,8}
+++	ssm create -p $pool3 -s ${size4}m -n $vol4 --fs $fs $mnt4
+++	ssm create -p $pool3 -s ${size5}m -n $vol5 --fs $fs $mnt5
+++	ssm create -p $pool3 -s ${size6}m -n $vol6 --fs $fs $mnt6
++ 
++-# create multiple pools
++-ssm create --pool $pool1 $dev1 $dev2 $dev3 $dev4
++-ssm create --pool $pool2 $dev5 $dev6 $dev7 $dev8
++-ssm_output=$(ssm list pool)
++-check list_table "$ssm_output" $pool1 lvm 4 none none 384.00MB
++-check list_table "$ssm_output" $pool2 lvm 4 none none 384.00MB
++-ssm -f remove --all
+++	# Check fs, vol, dev, pool, resized vol, and snapshot
+++	output=`ssm list fs`
+++	# xfs has some strange used size, so we don't check it
+++	if [ $fs == xfs ] ; then
+++		check list_table "$output" $pool0/$vol1 $pool0 $size1.00MB $fs none none linear $mnt1
+++		check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB $fs none none linear $mnt2
+++		check list_table "$output" $pool2/$vol3 $pool2 $size3.00MB $fs none none linear $mnt3
+++		check list_table "$output" $pool3/$vol4 $pool3 $size4.00MB $fs none none linear $mnt4
+++		check list_table "$output" $pool3/$vol5 $pool3 $size5.00MB $fs none none linear $mnt5
+++		check list_table "$output" $pool3/$vol6 $pool3 $size6.00MB $fs none none linear $mnt6
+++	else
+++		check list_table "$output" $pool0/$vol1 $pool0 $size1.00MB $fs $size1.00MB none linear $mnt1
+++		check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB $fs $size2.00MB none linear $mnt2
+++		check list_table "$output" $pool2/$vol3 $pool2 $size3.00MB $fs $size3.00MB none linear $mnt3
+++		check list_table "$output" $pool3/$vol4 $pool3 $size4.00MB $fs $size4.00MB none linear $mnt4
+++		check list_table "$output" $pool3/$vol5 $pool3 $size5.00MB $fs $size5.00MB none linear $mnt5
+++		check list_table "$output" $pool3/$vol6 $pool3 $size6.00MB $fs $size6.00MB none linear $mnt6
+++	fi
++ 
++-ssm add $TEST_DEVS
+++	output=`ssm list vol`
+++	# xfs has some strange used size, so we don't check it
+++	if [ $fs == xfs ] ; then
+++		check list_table "$output" $pool0/$vol1 $pool0 $size1.00MB $fs none none linear $mnt1
+++		check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB $fs none none linear $mnt2
+++		check list_table "$output" $pool2/$vol3 $pool2 $size3.00MB $fs none none linear $mnt3
+++		check list_table "$output" $pool3/$vol4 $pool3 $size4.00MB $fs none none linear $mnt4
+++		check list_table "$output" $pool3/$vol5 $pool3 $size5.00MB $fs none none linear $mnt5
+++		check list_table "$output" $pool3/$vol6 $pool3 $size6.00MB $fs none none linear $mnt6
+++	else
+++		check list_table "$output" $pool0/$vol1 $pool0 $size1.00MB $fs $size1.00MB none linear $mnt1
+++		check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB $fs $size2.00MB none linear $mnt2
+++		check list_table "$output" $pool2/$vol3 $pool2 $size3.00MB $fs $size3.00MB none linear $mnt3
+++		check list_table "$output" $pool3/$vol4 $pool3 $size4.00MB $fs $size4.00MB none linear $mnt4
+++		check list_table "$output" $pool3/$vol5 $pool3 $size5.00MB $fs $size5.00MB none linear $mnt5
+++		check list_table "$output" $pool3/$vol6 $pool3 $size6.00MB $fs $size6.00MB none linear $mnt6
+++	fi
+++
+++	output=`ssm list dev`
+++	check list_table "$output" $dev1 0.00KB $((size1)).00MB 124.00MB $pool0
+++	check list_table "$output" $dev2 $((maxvolsz-size2)).00MB $((size2)).00MB 124.00MB $pool1
+++	check list_table "$output" $dev3 0.00KB $((maxvolsz)).00MB 124.00MB $pool2
+++	check list_table "$output" $dev4 0.00KB $((maxvolsz)).00MB 124.00MB $pool2
+++	check list_table "$output" $dev5 none none 124.00MB $pool3
+++	check list_table "$output" $dev6 none none 124.00MB $pool3
+++	check list_table "$output" $dev7 none none 124.00MB $pool3
+++	check list_table "$output" $dev8 none none 124.00MB $pool3
+++	output=`ssm list pool`
+++	check list_table "$output" $pool0 lvm 1 0.00KB $((size1)).00MB $((maxvolsz)).00MB
+++	check list_table "$output" $pool1 lvm 1 $((maxvolsz-size2)).00MB $((size2)).00MB $((maxvolsz)).00MB
+++	check list_table "$output" $pool2 lvm 2 0.00KB $((size3)).00MB $((maxvolsz*2)).00MB
+++	check list_table "$output" $pool3 lvm 4 $((maxvolsz*4-size4-size5-size6)).00MB $((size4+size5+size6)).00MB $((maxvolsz*4)).00MB
+++
+++	# Check ssm vol after resize
+++	# xfs size cannot reduce
+++	if [ "$fs" != xfs ] ; then
+++		umount $mnt2
+++		ssm -f resize $pool1/$vol2 -s ${size2r}M
+++	fi
+++	ssm resize -s ${size5r}m $pool3/$vol5
+++
+++	output=`ssm list vol`
+++	# xfs has some strange used size, so we don't check it
+++	if [ "$fs" != xfs ] ; then
+++		check list_table "$output" $pool1/$vol2 $pool1 $size2r.00MB $fs $size2r none linear
+++		check list_table "$output" $pool3/$vol5 $pool3 $size5r.00MB $fs $size5r none linear
+++	else
+++		check list_table "$output" $pool3/$vol5 $pool3 $size5r.00MB $fs none none linear
+++	fi
++ 
+++	ssm snapshot $pool3/$vol4 -n snap1
+++	ssm snapshot $pool3/$vol4 -s ${size4s}m -n snap2
+++
+++	output=`ssm list snap`
+++	check list_table "$output" $pool3/snap1 $vol4 $pool3 none none linear
+++	check list_table "$output" $pool3/snap2 $vol4 $pool3 $size4s.00MB none linear
+++
+++	for i in {1..6} ; do
+++		mntdir=`eval echo '$mnt'$i`
+++		umount $mntdir || true
+++	done
+++
+++	ssm -f remove -a
+++
+++done
+++
+++ssm add $TEST_DEVS
++ # Check LVM volume listings with various fs
++ for fs in $TEST_FS; do
++     name="${fs}vol"
++@@ -85,30 +326,5 @@ for fs in $TEST_FS; do
++ done
++ ssm -f remove $SSM_LVM_DEFAULT_POOL
++ 
++-# Check lvm snapshot
++-lvol1=${LVOL_PREFIX}001
++-# Create volume with all devices at once
++-size=$(($DEV_SIZE*6))
++-snap_size1=$(($DEV_SIZE))
++-snap_size2=$(($size/5))
++-ssm create --size ${size}M $TEST_DEVS
++-ssm snapshot --name $snap1 --size ${snap_size1}M $SSM_LVM_DEFAULT_POOL/$lvol1
++-ssm snapshot --name $snap2 --size ${snap_size2}M $SSM_LVM_DEFAULT_POOL/$lvol1
++-ssm_output=$(ssm list snap)
++-check list_table "$ssm_output" $snap1 $lvol1 $SSM_LVM_DEFAULT_POOL ${snap_size1}.00MB 0.00KB linear
++-check list_table "$ssm_output" $snap2 $lvol1 $SSM_LVM_DEFAULT_POOL ${snap_size2}.00MB 0.00KB linear
++-ssm -f remove --all
++-
++-# Snapshot of the volumes in defferent pools
++-ssm create --pool $pool1 $dev1 $dev2
++-ssm add $dev3 $dev4 --pool $pool1
++-ssm create --pool $pool2 $dev5 $dev6
++-ssm add $dev7 $dev8 --pool $pool2
++-ssm snapshot --name $snap1 $pool1/$lvol1
++-ssm snapshot --name $snap1 $pool2/$lvol1
++-ssm_output=$(ssm list snap)
++-check list_table "$ssm_output" "$pool1/$snap1" $lvol1 $pool1 40.00MB 0.00KB linear
++-check list_table "$ssm_output" "$pool2/$snap1" $lvol1 $pool2 40.00MB 0.00KB linear
++-ssm -f remove --all
++-
++-# all_done!!!
+++# Some situation should fail
+++not ssm list wrong_type
++diff --git a/tests/bashtests/012-crypt-create.sh b/tests/bashtests/012-crypt-create.sh
++new file mode 100644
++index 0000000..8a5fddb
++--- /dev/null
+++++ b/tests/bashtests/012-crypt-create.sh
++@@ -0,0 +1,143 @@
+++#!/bin/bash
+++#
+++# (C)2013 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
+++#
+++# This program is free software: you can redistribute it and/or modify
+++# it under the terms of the GNU General Public License as published by
+++# the Free Software Foundation, either version 2 of the License, or
+++# (at your option) any later version.
+++#
+++# This program is distributed in the hope that it will be useful,
+++# but WITHOUT ANY WARRANTY; without even the implied warranty of
+++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+++# GNU General Public License for more details.
+++#
+++# You should have received a copy of the GNU General Public License
+++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+++
+++export test_name='012-crypt-create'
+++test_description='Exercise crypt create'
+++
+++. lib/test
+++
+++DEV_COUNT=10
+++DEV_SIZE=100
+++TEST_MAX_SIZE=$(($DEV_COUNT*$DEV_SIZE))
+++aux prepare_devs $DEV_COUNT $DEV_SIZE
+++aux prepare_mnts 4
+++TEST_DEVS=$(cat DEVICES)
+++export SSM_DEFAULT_BACKEND='crypt'
+++export SSM_CRYPT_DEFAULT_POOL=$vg1
+++export CRYPT_VOL_PREFIX="${SSM_PREFIX_FILTER}enc"
+++export SSM_NONINTERACTIVE='1'
+++export SSM_CRYPT_DEFAULT_VOL_PREFIX=$CRYPT_VOL_PREFIX
+++crypt_vol1=${CRYPT_VOL_PREFIX}001
+++crypt_vol2=${CRYPT_VOL_PREFIX}002
+++crypt_vol3=${CRYPT_VOL_PREFIX}003
+++crypt_vol4=${CRYPT_VOL_PREFIX}004
+++passwd="cai0ohMo8M"
+++
+++pool1=$vg2
+++pool2=$vg3
+++DEV="/dev/mapper"
+++
+++# cryptsetup will ask for password. If luks extension is used
+++# it will ask when creating header and then when opening the device
+++pass() {
+++	echo -e "${passwd}\n${passwd}"
+++}
+++
+++
+++# Create encrypted volume
+++pass | ssm create $dev1
+++check crypt_vol_field $crypt_vol1 type LUKS1
+++check crypt_vol_field $crypt_vol1 device $dev1
+++check list_table "$(ssm list vol)" $crypt_vol1 $SSM_CRYPT_DEFAULT_POOL none crypt
+++
+++pass | ssm create $dev2 -e
+++check crypt_vol_field $crypt_vol2 type LUKS1
+++check crypt_vol_field $crypt_vol2 device $dev2
+++check list_table "$(ssm list vol)" $crypt_vol2 $SSM_CRYPT_DEFAULT_POOL none crypt
+++
+++pass | ssm create -e luks $dev3
+++check crypt_vol_field $crypt_vol3 type LUKS1
+++check crypt_vol_field $crypt_vol3 device $dev3
+++check list_table "$(ssm list vol)" $crypt_vol3 $SSM_CRYPT_DEFAULT_POOL none crypt
+++
+++pass | ssm create --fs ext4 -e plain $dev4 $mnt1
+++check mountpoint $crypt_vol4 $mnt1
+++check crypt_vol_field $crypt_vol4 type PLAIN
+++check crypt_vol_field $crypt_vol4 device $dev4
+++check list_table "$(ssm list vol)" $crypt_vol4 $SSM_CRYPT_DEFAULT_POOL none ext4 none none crypt
+++ssm list
+++umount $mnt1
+++ssm -f remove ${DEV}/$crypt_vol1
+++
+++pass | ssm create --fs ext3 -s 50M -e plain $dev1 $mnt1
+++check mountpoint $crypt_vol1 $mnt1
+++check crypt_vol_field $crypt_vol1 type PLAIN
+++check crypt_vol_field $crypt_vol1 device $dev1
+++check crypt_vol_field $crypt_vol1 size 102400
+++check list_table "$(ssm list vol)" $crypt_vol1 $SSM_CRYPT_DEFAULT_POOL none ext3 none none crypt
+++umount $mnt1
+++
+++ssm remove ${DEV}/$crypt_vol1 ${DEV}/$crypt_vol3 ${DEV}/$crypt_vol2 ${DEV}/$crypt_vol4
+++
+++# Try non existing extension
+++not ssm create -e enigma $dev1
+++
+++# Create encrypted lvm volume
+++export SSM_LVM_DEFAULT_POOL=${vg1}_lvm
+++export LVOL_PREFIX="lvol"
+++lvol1=${LVOL_PREFIX}001
+++lvol2=${LVOL_PREFIX}002
+++lvol3=${LVOL_PREFIX}003
+++lvol4=${LVOL_PREFIX}004
+++export SSM_DEFAULT_BACKEND='lvm'
+++
+++pass | ssm create --fs xfs $dev1 $dev2 $mnt1 -e
+++check mountpoint $crypt_vol1 $mnt1
+++check crypt_vol_field $crypt_vol1 type LUKS1
+++check crypt_vol_field $crypt_vol1 device ${SSM_LVM_DEFAULT_POOL}-$lvol1
+++check list_table "$(ssm list vol)" $crypt_vol1 $SSM_CRYPT_DEFAULT_POOL none xfs none none crypt
+++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol1 $SSM_LVM_DEFAULT_POOL none linear
+++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 2
+++
+++pass | ssm create -r0 $dev3 $dev4 -e plain
+++check crypt_vol_field $crypt_vol2 type PLAIN
+++check crypt_vol_field $crypt_vol2 device ${SSM_LVM_DEFAULT_POOL}-$lvol2
+++check list_table "$(ssm list vol)" $crypt_vol2 $SSM_CRYPT_DEFAULT_POOL none crypt
+++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol2 $SSM_LVM_DEFAULT_POOL none striped
+++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol2 pv_count 4
+++
+++pass | ssm create $dev5 -e luks
+++check crypt_vol_field $crypt_vol3 type LUKS1
+++check crypt_vol_field $crypt_vol3 device ${SSM_LVM_DEFAULT_POOL}-$lvol3
+++check list_table "$(ssm list vol)" $crypt_vol3 $SSM_CRYPT_DEFAULT_POOL none crypt
+++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol3 $SSM_LVM_DEFAULT_POOL none linear
+++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol3 pv_count 5
+++
+++pass | ssm create -e plain --fs xfs -r10 -s ${DEV_SIZE}M $dev6 $dev7 $dev8 $dev9 $mnt2
+++check mountpoint $crypt_vol4 $mnt2
+++check crypt_vol_field $crypt_vol4 type PLAIN
+++check crypt_vol_field $crypt_vol4 device ${SSM_LVM_DEFAULT_POOL}-$lvol4
+++check list_table "$(ssm list vol)" $crypt_vol4 $SSM_CRYPT_DEFAULT_POOL 104.00M xfs none none crypt
+++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol4 $SSM_LVM_DEFAULT_POOL 104.00M raid10
+++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol4 pv_count 9
+++
+++ssm list
+++umount $mnt1
+++umount $mnt2
+++ssm -f remove ${DEV}/$crypt_vol1 ${DEV}/$crypt_vol3 ${DEV}/$crypt_vol2 ${DEV}/$crypt_vol4
+++ssm  -f remove $SSM_LVM_DEFAULT_POOL
+++
+++ssm create $dev1 $dev2
+++ssm list
+++pass | ssm -b crypt create $DM_DEV_DIR/$SSM_LVM_DEFAULT_POOL/$lvol1
+++check crypt_vol_field $crypt_vol1 type LUKS1
+++check crypt_vol_field $crypt_vol1 device ${SSM_LVM_DEFAULT_POOL}-$lvol1
+++check list_table "$(ssm list vol)" $crypt_vol1 $SSM_CRYPT_DEFAULT_POOL none crypt
+++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol1 $SSM_LVM_DEFAULT_POOL none linear
+++
+++ssm remove ${DEV}/$crypt_vol1
+++ssm  -f remove $SSM_LVM_DEFAULT_POOL
++diff --git a/tests/bashtests/013-lvm-check.sh b/tests/bashtests/013-lvm-check.sh
++new file mode 100644
++index 0000000..11a70cb
++--- /dev/null
+++++ b/tests/bashtests/013-lvm-check.sh
++@@ -0,0 +1,130 @@
+++#!/bin/bash
+++#
+++# (C)2013 Red Hat, Inc., Jimmy Pan <jipan at redhat.com>
+++#
+++# This program is free software: you can redistribute it and/or modify
+++# it under the terms of the GNU General Public License as published by
+++# the Free Software Foundation, either version 2 of the License, or
+++# (at your option) any later version.
+++#
+++# This program is distributed in the hope that it will be useful,
+++# but WITHOUT ANY WARRANTY; without even the implied warranty of
+++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+++# GNU General Public License for more details.
+++#
+++# You should have received a copy of the GNU General Public License
+++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+++
+++
+++export test_name='013-lvm-check'
+++export test_description='Exercise ssm lvm check'
+++
+++. lib/test
+++
+++DEV_COUNT=10
+++DEV_SIZE=100
+++aux prepare_devs $DEV_COUNT $DEV_SIZE
+++TEST_DEVS=$(cat DEVICES)
+++export SSM_DEFAULT_BACKEND='lvm'
+++export LVOL_PREFIX="lvol"
+++export SSM_LVM_DEFAULT_POOL=$vg1
+++export SSM_NONINTERACTIVE='1'
+++lvol1=${LVOL_PREFIX}001
+++lvol2=${LVOL_PREFIX}002
+++lvol3=${LVOL_PREFIX}003
+++
+++
+++pool1=$vg2
+++pool2=$vg3
+++
+++TEST_FS=
+++which mkfs.ext2 && grep -E "^\sext[234]$" /proc/filesystems && TEST_FS+="ext2 "
+++which mkfs.ext3 && grep -E "^\sext[34]$" /proc/filesystems && TEST_FS+="ext3 "
+++which mkfs.ext4 && grep -E "^\sext4$" /proc/filesystems && TEST_FS+="ext4 "
+++which mkfs.xfs  && grep -E "^\sxfs$" /proc/filesystems && TEST_FS+="xfs"
+++
+++filesystem_check()
+++{
+++	if [ $# -lt 3 ] ; then
+++		echo Usage: filesystem_check pool volume filesystem
+++		exit 1
+++	fi
+++	local pool=$1
+++	local vol=$2
+++	local fs=$3
+++	local name=$pool/$vol
+++	local path=`lvs --noheadings -o lv_path $name`
+++	if [[ $fs == ext[234] ]] ; then
+++		e2fsck -n $path
+++	elif [[ $fs == xfs ]] ; then
+++		xfs_repair -n $path
+++	else
+++		echo Invalid fs type
+++		exit 1
+++	fi
+++}
+++
+++
+++# No filesystem should fail
+++ssm create $dev1
+++not ssm check $SSM_LVM_DEFAULT_POOL/$lvol1
+++ssm -f remove -a
+++
+++# Loop for different filesystems
+++for fs in $TEST_FS ; do
+++	# Test check of a volume with one device
+++	ssm create --fs $fs -p $SSM_LVM_DEFAULT_POOL $dev1
+++	ret1=0
+++	filesystem_check $SSM_LVM_DEFAULT_POOL $lvol1 $fs || ret1=$?
+++	ret2=0
+++	ssm check $SSM_LVM_DEFAULT_POOL/$lvol1 || ret2=$?
+++	test "$ret1" -eq "$ret2" || [[ "$ret1" -ne 0 && "$ret2" -ne 0 ]]
+++	ret2=0
+++	ssm check `lvs --noheadings -o lv_path $SSM_LVM_DEFAULT_POOL/$lvol1` || ret2=$?
+++	test "$ret1" -eq "$ret2" || [[ "$ret1" -ne 0 && "$ret2" -ne 0 ]]
+++
+++	# Test check of a volume with one device with one device has specified
+++	# size and on two devices
+++	ssm create -p $pool1 --fs $fs -s $((DEV_SIZE+20))m $dev{2,3}
+++	ret1=0
+++	filesystem_check $pool1 $lvol1 $fs || ret1=$?
+++	ret2=0
+++	ssm check $pool1/$lvol1 | ret2=$?
+++	test "$ret1" -eq "$ret2" || [[ "$ret1" -ne 0 && "$ret2" -ne 0 ]]
+++	ret2=0
+++	ssm check `lvs --noheadings -o lv_path $pool1/$lvol1` || ret2=$?
+++	test "$ret1" -eq "$ret2" || [[ "$ret1" -ne 0 && "$ret2" -ne 0 ]]
+++
+++	# Test check of volumes from the same pools
+++	ssm create -p $pool2 --fs $fs $dev{4,5,6}
+++	ssm create --fs $fs $dev{7,8} -p $pool2
+++	ret1=0
+++	filesystem_check $pool2 $lvol1 $fs || ret1=$?
+++	ret2=0
+++	ssm check $pool2/$lvol1 || ret2=$?
+++	test "$ret1" -eq "$ret2" || [[ "$ret1" -ne 0 && "$ret2" -ne 0 ]]
+++	ret2=0
+++	ssm check `lvs --noheadings -o lv_path $pool2/$lvol1` || ret2=$?
+++	test "$ret1" -eq "$ret2" || [[ "$ret1" -ne 0 && "$ret2" -ne 0 ]]
+++	ret1=0
+++	filesystem_check $pool2 $lvol2 $fs || ret1=$?
+++	ret2=0
+++	ssm check $pool2/$lvol2 || ret2=$?
+++	test "$ret1" -eq "$ret2" || [[ "$ret1" -ne 0 && "$ret2" -ne 0 ]]
+++
+++	# Test check of volumes from different pools at once
+++	ret2=0
+++	ssm check `lvs --noheadings -o lv_path $pool2/$lvol2` || ret2=$?
+++	test "$ret1" -eq "$ret2" || [[ "$ret1" -ne 0 && "$ret2" -ne 0 ]]
+++	vols="$SSM_LVM_DEFAULT_POOL/$lvol1 $pool1/$lvol1 $pool2/$lvol1 $pool2/$lvol2"
+++	ssm check $vols | not grep -i fail
+++	ssm check `lvs --noheadings -o lv_path $vols` | not grep -i fail
+++
+++	# Check invalid volume name should fail
+++	not ssm check $pool2/$lvol2"nsdf"
+++	ssm -f remove -a
+++done
+++
+++# Some should fail
+++not ssm check
+++not ssm check non_existing
++diff --git a/tests/bashtests/lib/aux.sh b/tests/bashtests/lib/aux.sh
++index 6add5c3..11a101f 100644
++--- a/tests/bashtests/lib/aux.sh
+++++ b/tests/bashtests/lib/aux.sh
++@@ -347,6 +347,7 @@ activation/polling_interval = 0
++ activation/snapshot_autoextend_percent = 50
++ activation/snapshot_autoextend_threshold = 50
++ activation/monitoring = 0
+++global/use_lvmetad = 0
++ EOF
++     }
++ 
++diff --git a/tests/bashtests/lib/check.sh b/tests/bashtests/lib/check.sh
++index 31d8c2d..9a8f853 100644
++--- a/tests/bashtests/lib/check.sh
+++++ b/tests/bashtests/lib/check.sh
++@@ -292,6 +292,35 @@ pvlv_counts()
++ 	vg_field $local_vg snap_count $num_snaps
++ }
++ 
+++crypt_vol_field()
+++{
+++	data=$(cryptsetup status $1 2> /dev/null | grep $2 | sed -e 's/^[ \t]*//' || true)
+++
+++	expected=$3
+++	case $2 in
+++		"type")
+++			actual=$(echo ${data##*type:} | sed -e 's/^[ \t]*//') ;;
+++		"device")
+++			actual=$(echo ${data##*device:} | sed -e 's/^[ \t]*//')
+++			actual=$(basename $actual)
+++			expected=$(basename $expected)
+++			;;
+++		"size")
+++			actual=$(echo ${data##*size:} | sed -e 's/^[ \t]*//')
+++			actual=${actual%% sectors}
+++			;;
+++		*)
+++			echo "Unknown field $2"
+++			exit 1
+++			;;
+++	esac
+++
+++	test "$actual" = "$expected" || {
+++		echo "crypt_vol_field: volume=$1, field=$2, actual=$actual, expected=$expected"
+++		exit 1
+++	}
+++}
+++
++ btrfs_fs_field()
++ {
++ 	lines=$(btrfs filesystem show 2> /dev/null | grep -A 1 "'$1'" || true)
++diff --git a/tests/bashtests/set.sh b/tests/bashtests/set.sh
++index 1306a4e..d2fcf7d 100755
++--- a/tests/bashtests/set.sh
+++++ b/tests/bashtests/set.sh
++@@ -15,6 +15,7 @@
++ # You should have received a copy of the GNU General Public License
++ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
++ 
+++chmod +x *.sh
++ for i in $(ls lib/*.sh); do
++ 	echo "$i -> ${i%%.sh}"
++ 	cp $i ${i%%.sh}
++diff --git a/tests/unittests/common.py b/tests/unittests/common.py
++index ec60ae2..58c5637 100644
++--- a/tests/unittests/common.py
+++++ b/tests/unittests/common.py
++@@ -74,8 +74,8 @@ class MockSystemDataSource(unittest.TestCase):
++         misc.run = self.mock_run
++         self.get_partitions_orig = misc.get_partitions
++         misc.get_partitions = self.mock_get_partitions
++-        self.is_bdevice_orig = main.is_bdevice
++-        main.is_bdevice = self.mock_is_bdevice
+++        self.is_bdevice_orig = misc.is_bdevice
+++        misc.is_bdevice = self.mock_is_bdevice
++         self.is_directory_orig = main.is_directory
++         main.is_directory = self.mock_is_directory
++         self.check_create_item_orig = main.StorageHandle.check_create_item
++@@ -88,6 +88,8 @@ class MockSystemDataSource(unittest.TestCase):
++         misc.check_binary = self.mock_check_binary
++         self.send_udev_event_orig = misc.send_udev_event
++         misc.send_udev_event = self.mock_send_udev_event
+++        self.get_fs_type_orig = misc.get_fs_type
+++        misc.get_fs_type = self.mock_get_fs_type
++         self.dev_data = {}
++         self.vol_data = {}
++         self.pool_data = {}
++@@ -104,25 +106,32 @@ class MockSystemDataSource(unittest.TestCase):
++         self.mount_data = {}
++         misc.run = self.run_orig
++         misc.get_partitions = self.get_partitions_orig
++-        main.is_bdevice = self.is_bdevice_orig
+++        misc.is_bdevice = self.is_bdevice_orig
++         main.is_directory = self.is_directory_orig
++         misc.get_mounts = self.get_mounts_orig
++         main.StorageHandle.check_create_item = self.check_create_item_orig
++         misc.temp_mount = self.temp_mount_orig
++         misc.check_binary = self.check_binary_orig
++         misc.send_udev_event = self.send_udev_event_orig
+++        misc.get_fs_type = self.get_fs_type_orig
++         main.SSM_NONINTERACTIVE = False
++ 
++     def _cmdEq(self, out, index=-1):
++         self.assertEqual(self.run_data[index], out)
++ 
++-    def _checkCmd(self, command, args, expected=None):
+++    def _cmdNotEq(self, out, index=-1):
+++        self.assertNotEqual(self.run_data[index], out)
+++
+++    def _checkCmd(self, command, args, expected=None, NotEq=False):
++         self.run_data = []
++         for case in misc.permutations(args):
++             cmd = command + " " + " ".join(case)
++             main.main(cmd)
++             if expected:
++-                self._cmdEq(expected)
+++		if NotEq:
+++			self._cmdNotEq(expected)
+++		else:
+++			self._cmdEq(expected)
++ 
++     def mock_run(self, cmd, *args, **kwargs):
++         self.run_data.append(" ".join(cmd))
++@@ -166,7 +175,21 @@ class MockSystemDataSource(unittest.TestCase):
++             if path in self.directories:
++                 self._mpoint = path
++                 return
++-        return main.is_bdevice(path)
+++        return misc.is_bdevice(path)
+++
+++    def mock_get_fs_type(self, device):
+++        if device in self.vol_data:
+++            if 'fstype' in self.vol_data[device]:
+++                return self.vol_data[device]['fstype']
+++            else:
+++                return None
+++        elif device in self.dev_data:
+++            if 'fstype' in self.dev_data[device]:
+++                return self.dev_data[device]['fstype']
+++            else:
+++                return None
+++        else:
+++                return None
++ 
++     def mock_send_udev_event(self, device, event):
++         pass
++@@ -211,6 +234,8 @@ class MockSystemDataSource(unittest.TestCase):
++         pool_data = self.pool_data[pool_name]
++         pool_free = float(pool_data['pool_free']) - vol_size
++         pool_used = float(pool_data['pool_used']) + vol_size
+++	pool_data['pool_free'] = pool_free
+++	pool_data['pool_used'] = pool_used
++         if mount:
++             self.pool_data[pool_name]['mount'] = mount
++             self._addDir(mount)
++diff --git a/tests/unittests/test_btrfs.py b/tests/unittests/test_btrfs.py
++index b755414..d1f8135 100644
++--- a/tests/unittests/test_btrfs.py
+++++ b/tests/unittests/test_btrfs.py
++@@ -30,11 +30,11 @@ class BtrfsFunctionCheck(MockSystemDataSource):
++         self._addDevice('/dev/sda', 11489037516)
++         self._addDevice('/dev/sdb', 234566451)
++         self._addDevice('/dev/sdc', 2684354560)
++-        self._addDevice('/dev/sdc1', 894784853, 1)
+++        self._addDevice('/dev/sdc1', 2042177280, 1)
++         self._addDevice('/dev/sdc2', 29826161, 2)
++         self._addDevice('/dev/sdc3', 1042177280, 3)
++         self._addDevice('/dev/sdd', 11673)
++-        self._addDevice('/dev/sde', 1042177280)
+++        self._addDevice('/dev/sde', 1073741824)
++         main.SSM_DEFAULT_BACKEND = 'btrfs'
++ 
++         self.check_new_path_orig = btrfs.BtrfsPool._check_new_path
++@@ -118,8 +118,8 @@ class BtrfsFunctionCheck(MockSystemDataSource):
++             "mkfs.btrfs -L btrfs_pool -m raid0 -d raid0 -b 2858730232217 -f /dev/sda".format(default_pool))
++         self._checkCmd("ssm create", ['-r 0', '-s 2.6T', '/dev/sda'],
++             "mkfs.btrfs -L btrfs_pool -m raid0 -d raid0 -b 2858730232217 -f /dev/sda".format(default_pool))
++-        self._checkCmd("ssm create", ['-r 1', '-s 512k', '/dev/sda'],
++-            "mkfs.btrfs -L btrfs_pool -m raid1 -d raid1 -b 524288 -f /dev/sda".format(default_pool))
+++        self._checkCmd("ssm create", ['-r 1', '-s 512k', '/dev/sda /dev/sdb'],
+++            "mkfs.btrfs -L btrfs_pool -m raid1 -d raid1 -b 524288 -f /dev/sda /dev/sdb".format(default_pool))
++         self._checkCmd("ssm create", ['-r 10', '-s 10M', '/dev/sda'],
++             "mkfs.btrfs -L btrfs_pool -m raid10 -d raid10 -b 10485760 -f /dev/sda".format(default_pool))
++ 
++@@ -244,6 +244,8 @@ class BtrfsFunctionCheck(MockSystemDataSource):
++             "btrfs subvolume snapshot /mnt/mount /mnt/mount/new_snap")
++ 
++     def test_btrfs_resize(self):
+++	# Btrfs resize not supported for now because it simply does not work
+++	return
++         # Generate some storage data
++         self._addPool('default_pool', ['/dev/sda', '/dev/sdb'])
++         self._addPool('my_pool', ['/dev/sdc2', '/dev/sdc3'])
++@@ -265,9 +267,16 @@ class BtrfsFunctionCheck(MockSystemDataSource):
++             "btrfs filesystem resize 11723608063K /tmp/mount")
++         main.SSM_DEFAULT_BACKEND = 'btrfs'
++ 
++-        self._cmdEq("btrfs device add /dev/sde /tmp/mount", -2)
+++        self._cmdNotEq("btrfs device add /dev/sde /tmp/mount", -2)
+++
+++	# Resize with enough space in the pool
++         self._checkCmd("ssm resize --size +1g", ['my_pool /dev/sde'],
++             "btrfs filesystem resize 1073052017K /mnt/test1")
+++        self._cmdNotEq("btrfs device add /dev/sde /mnt/test1", -2)
+++
+++	# Resize without enough space in the pool
+++        self._checkCmd("ssm resize --size +1t", ['my_pool /dev/sde'],
+++            "btrfs filesystem resize 2145745265K /mnt/test1")
++         self._cmdEq("btrfs device add /dev/sde /mnt/test1", -2)
++ 
++         # Shrink volume
++@@ -285,16 +294,23 @@ class BtrfsFunctionCheck(MockSystemDataSource):
++             "btrfs filesystem resize 10240K /mnt/test1")
++ 
++         # Set volume and add devices
++-        self._checkCmd("ssm resize -s 12T default_pool /dev/sdc1 /dev/sde",
++-            [], "btrfs filesystem resize 12884901888K /tmp/mount")
+++        self._checkCmd("ssm resize -s 20T default_pool /dev/sdc1 /dev/sde",
+++            [], "btrfs filesystem resize 21474836480K /tmp/mount")
+++        self.assertNotEqual(self.run_data[-2],
+++            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
+++
+++        self._checkCmd("ssm resize -s 22T default_pool /dev/sdc1 /dev/sde",
+++            [], "btrfs filesystem resize 23622320128K /tmp/mount")
++         self.assertEqual(self.run_data[-2],
++             "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
++-        self._checkCmd("ssm resize -s 1T my_pool /dev/sdc1 /dev/sde",
++-            [], "btrfs filesystem resize 1073741824K /mnt/test1")
+++
+++        self._checkCmd("ssm resize -s 3T my_pool /dev/sdc1 /dev/sde",
+++            [], "btrfs filesystem resize 3221225472K /mnt/test1")
++         self.assertEqual(self.run_data[-2],
++             "btrfs device add /dev/sdc1 /dev/sde /mnt/test1")
++-        self._checkCmd("ssm resize -s 1T my_pool /dev/sde /dev/sdc2",
++-            [], "btrfs filesystem resize 1073741824K /mnt/test1")
+++
+++        self._checkCmd("ssm resize -s 3T my_pool /dev/sde /dev/sdc2",
+++            [], "btrfs filesystem resize 3221225472K /mnt/test1")
++         self.assertEqual(self.run_data[-2],
++             "btrfs device add /dev/sde /mnt/test1")
++ 
++@@ -308,6 +324,8 @@ class BtrfsFunctionCheck(MockSystemDataSource):
++         self.assertNotEqual(self.run_data[-2],
++             "btrfs device add /dev/sdc1 /dev/sde /mnt/test1")
++ 
+++        self._checkCmd("ssm list",
+++            [], "btrfs filesystem resize 12247891967K /tmp/mount")
++         # Extend volume and add devices
++         self._checkCmd("ssm resize -s +500G default_pool /dev/sdc1 /dev/sde",
++             [], "btrfs filesystem resize 12247891967K /tmp/mount")
++diff --git a/tests/unittests/test_lvm.py b/tests/unittests/test_lvm.py
++index 6f63fae..7af8a78 100644
++--- a/tests/unittests/test_lvm.py
+++++ b/tests/unittests/test_lvm.py
++@@ -287,10 +287,16 @@ class LvmFunctionCheck(MockSystemDataSource):
++         self.assertEqual(self.run_data[-2],
++             "lvm vgextend default_pool /dev/sdc1 /dev/sde")
++ 
++-        # Set volume size
+++        # Set volume size with sufficient amount of space
++         self._checkCmd("ssm resize -s 10G /dev/default_pool/vol003 /dev/sdc1 /dev/sde",
++             [], "lvm lvresize -L 10485760.0k /dev/default_pool/vol003")
++-        self.assertEqual(self.run_data[-2],
+++        self.assertNotEqual(self.run_data[-2],
+++            "lvm vgextend default_pool /dev/sdc1 /dev/sde")
+++
+++        # Set volume size without sufficient amount of space
+++        self._checkCmd("ssm resize -s 10T /dev/default_pool/vol003 /dev/sdc1 /dev/sde",
+++            [], "lvm lvresize -L 10737418240.0k /dev/default_pool/vol003")
+++        self.assertNotEqual(self.run_data[-2],
++             "lvm vgextend default_pool /dev/sdc1 /dev/sde")
++ 
++         # Extend volume and add devices
++@@ -299,9 +305,15 @@ class LvmFunctionCheck(MockSystemDataSource):
++         self.assertEqual(self.run_data[-2],
++             "lvm vgextend default_pool /dev/sdc1 /dev/sde")
++ 
++-        # Extend volume
+++        # Extend volume with ehough space in pool
++         self._checkCmd("ssm resize -s +10G /dev/default_pool/vol003 /dev/sdc1 /dev/sde",
++             [], "lvm lvresize -L 10486784.0k /dev/default_pool/vol003")
+++        self.assertNotEqual(self.run_data[-2],
+++            "lvm vgextend default_pool /dev/sdc1 /dev/sde")
+++
+++        # Extend volume without ehough space in pool
+++        self._checkCmd("ssm resize -s +20T /dev/default_pool/vol003 /dev/sdc1 /dev/sde",
+++            [], "lvm lvresize -L 21474837504.0k /dev/default_pool/vol003")
++         self.assertEqual(self.run_data[-2],
++             "lvm vgextend default_pool /dev/sdc1 /dev/sde")
++ 
++diff --git a/tests/unittests/test_ssm.py b/tests/unittests/test_ssm.py
++index 9a5d82d..e0a1d99 100644
++--- a/tests/unittests/test_ssm.py
+++++ b/tests/unittests/test_ssm.py
++@@ -365,12 +365,12 @@ class SsmFunctionCheck(MockSystemDataSource):
++         # Set volume size
++         self._checkCmd("ssm resize -s 10G /dev/default_pool/vol003 /dev/sdc1 /dev/sde",
++             [], "vol resize /dev/default_pool/vol003 10485760.0 False")
++-        self.assertEqual(self.run_data[-2],
+++        self.assertNotEqual(self.run_data[-2],
++             "pool extend default_pool /dev/sdc1 /dev/sde")
++ 
++         # Extend volume size with adding more devices
++-        self._checkCmd("ssm resize -s +10G /dev/default_pool/vol003 /dev/sdc1 /dev/sde",
++-            [], "vol resize /dev/default_pool/vol003 10486784.0 False")
+++        self._checkCmd("ssm resize -s +12t /dev/default_pool/vol003 /dev/sdc1 /dev/sde",
+++            [], "vol resize /dev/default_pool/vol003 12884902912.0 False")
++         self.assertEqual(self.run_data[-2],
++             "pool extend default_pool /dev/sdc1 /dev/sde")
++ 
++@@ -428,9 +428,9 @@ class SsmFunctionCheck(MockSystemDataSource):
++         # Number of stripes must not exceed number of devices
++         self.assertRaises(problem.GeneralError, main.main, "ssm create -r 1 -s 2.6T -I 16 -i 4 /dev/sda")
++ 
++-        self._checkCmd("ssm create", ['-r 1', '-s 2.6T', '-I 16', '/dev/sda'],
++-            "pool create {0} 2791728742.40 1 16 /dev/sda".format(main.DEFAULT_DEVICE_POOL))
++-        self._cmdEq("pool new {0} /dev/sda".format(main.DEFAULT_DEVICE_POOL), -2)
+++        self._checkCmd("ssm create", ['-r 1', '-s 2.6T', '-I 16', '/dev/sda /dev/sdb'],
+++            "pool create {0} 2791728742.40 1 16 /dev/sda /dev/sdb".format(main.DEFAULT_DEVICE_POOL))
+++        self._cmdEq("pool new {0} /dev/sda /dev/sdb".format(main.DEFAULT_DEVICE_POOL), -2)
++ 
++         # Create volume using single device from non existent my_pool
++         self._checkCmd("ssm create", ['--pool my_pool', '/dev/sda'],
++@@ -760,13 +760,14 @@ class PoolInfo(MyInfo):
++         misc.run(cmd)
++ 
++     def create(self, pool, size='', name='', devs='',
++-               raid=None):
+++               options=None):
+++        options = options or {}
++         if type(devs) is not list:
++             devices = [devs]
++-        if raid:
++-            stripes = raid['stripes']
++-            stripesize = raid['stripesize']
++-            level = raid['level']
+++        if 'raid' in options:
+++            stripes = options['stripes']
+++            stripesize = options['stripesize']
+++            level = options['raid']
++         else:
++             stripes = stripesize = level = ""
++         misc.run([self.f, self.v, self.y, 'pool create', pool, size, name,
+diff --git a/ssm-0.4-ssm-btrfs-backend-try-to-find-the-real-device.patch b/ssm-0.4-ssm-btrfs-backend-try-to-find-the-real-device.patch
+new file mode 100644
+index 0000000..6d5cf6e
+--- /dev/null
++++ b/ssm-0.4-ssm-btrfs-backend-try-to-find-the-real-device.patch
+@@ -0,0 +1,31 @@
++From dbc8ab76b9f50048f8cf73a792cfded7c1061023 Mon Sep 17 00:00:00 2001
++From: Lukas Czerner <lczerner at redhat.com>
++Date: Wed, 15 Jan 2014 12:19:08 +0100
++Subject: [PATCH 02/10] ssm: btrfs backend: try to find the real device
++
++Currently btrfs backend is trying to use the "device" directly from the
++output. However in recent btrfs it has been changed to print out device
++names in format (/dev/mapper/whatever) so we should really use
++get_real_device() function to obtain the "real" device name.
++
++Signed-off-by: Lukas Czerner <lczerner at redhat.com>
++---
++ ssmlib/backends/btrfs.py | 2 +-
++ 1 file changed, 1 insertion(+), 1 deletion(-)
++
++diff --git a/ssmlib/backends/btrfs.py b/ssmlib/backends/btrfs.py
++index eb23403..750a517 100644
++--- a/ssmlib/backends/btrfs.py
+++++ b/ssmlib/backends/btrfs.py
++@@ -119,7 +119,7 @@ class Btrfs(template.Backend):
++                 fs_used = float(misc.get_real_size(array[6]))
++ 
++             elif array[0] == 'devid':
++-                dev['dev_name'] = array[7]
+++                dev['dev_name'] = misc.get_real_device(array[7])
++ 
++                 if not pool_name:
++                     pool_name = self._find_uniq_pool_name(label, array[7])
++-- 
++1.8.3.1
++
+diff --git a/ssm-0.4-ssm-force-btrfs-device-add.patch b/ssm-0.4-ssm-force-btrfs-device-add.patch
+new file mode 100644
+index 0000000..fd8d80f
+--- /dev/null
++++ b/ssm-0.4-ssm-force-btrfs-device-add.patch
+@@ -0,0 +1,341 @@
++From e5ca9b110954900f30bf32d66ea3440a4203e84c Mon Sep 17 00:00:00 2001
++From: Lukas Czerner <lczerner at redhat.com>
++Date: Wed, 15 Jan 2014 13:59:44 +0100
++Subject: [PATCH 03/10] ssm: force btrfs device add
++
++Btrfs is broken. It does not recognize the btrfs signature properly and
++even when the device has been wiped with wipefs btrfs would still claim
++that the device actually is 'btrfs' device which it is not!
++
++We've already fixed the case for mkfs.btrfs, howeve btrfs recently added
++the check for 'btrfs device add' as well, so we need to do the same
++thing. So make _can_btrfs_force() more generic and use it in extend()
++method as well.
++
++Signed-off-by: Lukas Czerner <lczerner at redhat.com>
++---
++ ssmlib/backends/btrfs.py      |  19 +++++---
++ tests/unittests/test_btrfs.py | 102 +++++++++++++++++++++---------------------
++ 2 files changed, 65 insertions(+), 56 deletions(-)
++
++diff --git a/ssmlib/backends/btrfs.py b/ssmlib/backends/btrfs.py
++index 750a517..b238d52 100644
++--- a/ssmlib/backends/btrfs.py
+++++ b/ssmlib/backends/btrfs.py
++@@ -411,14 +411,13 @@ class BtrfsPool(Btrfs, template.BackendPool):
++         else:
++             self.data = self._pool
++ 
++-    def _can_btrfs_force(self):
+++    def _can_btrfs_force(self, command):
++         """
++         This is just ridiculous. Unfortunately btrfs tools usually change
++         behaviour and options without bumping version number. So we have
++         to check whether btrfs allows to 'force' file system creation.
++         """
++-        command=['mkfs.btrfs', '-f']
++-        output = misc.run(command, can_fail=True)[1]
+++        output = misc.run(command + ['--force'], can_fail=True)[1]
++         found = re.search('invalid option', output)
++         if found:
++             return False
++@@ -456,8 +455,8 @@ class BtrfsPool(Btrfs, template.BackendPool):
++         # have tried to remove the device from the respective pool already.
++         # So at this point there should not be any useful signatures to
++         # speak of. However as I mentioned btrfs is broken, so force it.
++-        if self._can_btrfs_force():
++-            command.extend(['-f'])
+++        if self._can_btrfs_force(command):
+++            command.extend(['--force'])
++         command.extend(devs)
++         misc.run(command, stdout=True)
++         misc.send_udev_event(devs[0], "change")
++@@ -499,6 +498,16 @@ class BtrfsPool(Btrfs, template.BackendPool):
++         if type(devices) is not list:
++             devices = [devices]
++         command = ['device', 'add']
+++        # This might seem weird, but btrfs is mostly broken when it comes to
+++        # checking existing signatures because it will for example check for
+++        # backup superblocks as well, which is wrong. Also we have check for
+++        # existing file system signatures in the ssm itself. Other things
+++        # than file system should be covered by the backend and we should
+++        # have tried to remove the device from the respective pool already.
+++        # So at this point there should not be any useful signatures to
+++        # speak of. However as I mentioned btrfs is broken, so force it.
+++        if self._can_btrfs_force(['btrfs', 'device', 'add']):
+++            command.extend(['--force'])
++         command.extend(devices)
++         command.append(pool['mount'])
++         self.run_btrfs(command)
++diff --git a/tests/unittests/test_btrfs.py b/tests/unittests/test_btrfs.py
++index d1f8135..2fb04bc 100644
++--- a/tests/unittests/test_btrfs.py
+++++ b/tests/unittests/test_btrfs.py
++@@ -91,48 +91,48 @@ class BtrfsFunctionCheck(MockSystemDataSource):
++ 
++         # Create volume using single device from non existent default pool
++         self._checkCmd("ssm create", ['/dev/sda'],
++-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
+++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
++ 
++         # Specify default backend
++         self._checkCmd("ssm -b btrfs create", ['/dev/sda'],
++-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
+++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
++ 
++         main.SSM_DEFAULT_BACKEND = 'lvm'
++         self._checkCmd("ssm --backend btrfs create", ['/dev/sda'],
++-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
+++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
++         main.SSM_DEFAULT_BACKEND = 'btrfs'
++ 
++-        self._checkCmd("ssm -f create", ['/dev/sda'],
++-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
+++        self._checkCmd("ssm --force create", ['/dev/sda'],
+++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
++ 
++         self._checkCmd("ssm -v create", ['/dev/sda'],
++-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
+++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
++ 
++-        self._checkCmd("ssm -f -v create", ['/dev/sda'],
++-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
+++        self._checkCmd("ssm --force -v create", ['/dev/sda'],
+++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
++ 
++         self._checkCmd("ssm create", ['-s 2.6T', '/dev/sda'],
++-            "mkfs.btrfs -L {0} -b 2858730232217 -f /dev/sda".format(default_pool))
+++            "mkfs.btrfs -L {0} -b 2858730232217 --force /dev/sda".format(default_pool))
++ 
++         self._checkCmd("ssm create", ['-r 0', '-s 2.6T', '/dev/sda'],
++-            "mkfs.btrfs -L btrfs_pool -m raid0 -d raid0 -b 2858730232217 -f /dev/sda".format(default_pool))
+++            "mkfs.btrfs -L btrfs_pool -m raid0 -d raid0 -b 2858730232217 --force /dev/sda".format(default_pool))
++         self._checkCmd("ssm create", ['-r 0', '-s 2.6T', '/dev/sda'],
++-            "mkfs.btrfs -L btrfs_pool -m raid0 -d raid0 -b 2858730232217 -f /dev/sda".format(default_pool))
+++            "mkfs.btrfs -L btrfs_pool -m raid0 -d raid0 -b 2858730232217 --force /dev/sda".format(default_pool))
++         self._checkCmd("ssm create", ['-r 1', '-s 512k', '/dev/sda /dev/sdb'],
++-            "mkfs.btrfs -L btrfs_pool -m raid1 -d raid1 -b 524288 -f /dev/sda /dev/sdb".format(default_pool))
+++            "mkfs.btrfs -L btrfs_pool -m raid1 -d raid1 -b 524288 --force /dev/sda /dev/sdb".format(default_pool))
++         self._checkCmd("ssm create", ['-r 10', '-s 10M', '/dev/sda'],
++-            "mkfs.btrfs -L btrfs_pool -m raid10 -d raid10 -b 10485760 -f /dev/sda".format(default_pool))
+++            "mkfs.btrfs -L btrfs_pool -m raid10 -d raid10 -b 10485760 --force /dev/sda".format(default_pool))
++ 
++         # Create volume using single device from non existent my_pool
++         self._checkCmd("ssm create", ['--pool my_pool', '/dev/sda'],
++-            "mkfs.btrfs -L my_pool -f /dev/sda")
+++            "mkfs.btrfs -L my_pool --force /dev/sda")
++ 
++         self._checkCmd("ssm create", ['-p my_pool', '-r 0', '-s 2.6T', '/dev/sda'],
++-            "mkfs.btrfs -L my_pool -m raid0 -d raid0 -b 2858730232217 -f /dev/sda")
+++            "mkfs.btrfs -L my_pool -m raid0 -d raid0 -b 2858730232217 --force /dev/sda")
++ 
++         # Create volume using multiple devices
++         self._checkCmd("ssm create /dev/sda /dev/sdb", [],
++-            "mkfs.btrfs -L {0} -f /dev/sda /dev/sdb".format(default_pool))
+++            "mkfs.btrfs -L {0} --force /dev/sda /dev/sdb".format(default_pool))
++ 
++         # Create volume using single device from existing pool
++         self._addPool(default_pool, ['/dev/sdb', '/dev/sdd'])
++@@ -151,15 +151,15 @@ class BtrfsFunctionCheck(MockSystemDataSource):
++         # in the pool
++         self._checkCmd("ssm create", ['-n myvolume', '/dev/sda /dev/sdb'],
++             "btrfs subvolume create /tmp/mount/myvolume")
++-        self._cmdEq("btrfs device add /dev/sda /tmp/mount", -2)
+++        self._cmdEq("btrfs device add --force /dev/sda /tmp/mount", -2)
++ 
++         self._checkCmd("ssm create", ['-p my_pool', '-n myvolume', '/dev/sdc2 /dev/sda'],
++             "btrfs subvolume create /tmp/mount/myvolume")
++-        self._cmdEq("btrfs device add /dev/sda /mnt/test", -2)
+++        self._cmdEq("btrfs device add --force /dev/sda /mnt/test", -2)
++ 
++         self._checkCmd("ssm create", ['-n myvolume', '/dev/sda /dev/sdb /dev/sde'],
++             "btrfs subvolume create /tmp/mount/myvolume")
++-        self._cmdEq("btrfs device add /dev/sda /dev/sde /tmp/mount", -2)
+++        self._cmdEq("btrfs device add --force /dev/sda /dev/sde /tmp/mount", -2)
++ 
++     def test_btrfs_remove(self):
++         # Generate some storage data
++@@ -267,17 +267,17 @@ class BtrfsFunctionCheck(MockSystemDataSource):
++             "btrfs filesystem resize 11723608063K /tmp/mount")
++         main.SSM_DEFAULT_BACKEND = 'btrfs'
++ 
++-        self._cmdNotEq("btrfs device add /dev/sde /tmp/mount", -2)
+++        self._cmdNotEq("btrfs device add --force /dev/sde /tmp/mount", -2)
++ 
++ 	# Resize with enough space in the pool
++         self._checkCmd("ssm resize --size +1g", ['my_pool /dev/sde'],
++             "btrfs filesystem resize 1073052017K /mnt/test1")
++-        self._cmdNotEq("btrfs device add /dev/sde /mnt/test1", -2)
+++        self._cmdNotEq("btrfs device add --force /dev/sde /mnt/test1", -2)
++ 
++ 	# Resize without enough space in the pool
++         self._checkCmd("ssm resize --size +1t", ['my_pool /dev/sde'],
++             "btrfs filesystem resize 2145745265K /mnt/test1")
++-        self._cmdEq("btrfs device add /dev/sde /mnt/test1", -2)
+++        self._cmdEq("btrfs device add --force /dev/sde /mnt/test1", -2)
++ 
++         # Shrink volume
++         self._checkCmd("ssm resize", ['-s-100G', 'default_pool'],
++@@ -285,7 +285,7 @@ class BtrfsFunctionCheck(MockSystemDataSource):
++         self._checkCmd("ssm resize -s-500G", ['my_pool /dev/sde'],
++             "btrfs filesystem resize 547715441K /mnt/test1")
++         self.assertNotEqual(self.run_data[-2],
++-            "btrfs device add /dev/sde /mnt/test1")
+++            "btrfs device add --force /dev/sde /mnt/test1")
++ 
++         # Set volume size
++         self._checkCmd("ssm resize", ['-s 10M', 'default_pool'],
++@@ -297,32 +297,32 @@ class BtrfsFunctionCheck(MockSystemDataSource):
++         self._checkCmd("ssm resize -s 20T default_pool /dev/sdc1 /dev/sde",
++             [], "btrfs filesystem resize 21474836480K /tmp/mount")
++         self.assertNotEqual(self.run_data[-2],
++-            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
+++            "btrfs device add --force /dev/sdc1 /dev/sde /tmp/mount")
++ 
++         self._checkCmd("ssm resize -s 22T default_pool /dev/sdc1 /dev/sde",
++             [], "btrfs filesystem resize 23622320128K /tmp/mount")
++         self.assertEqual(self.run_data[-2],
++-            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
+++            "btrfs device add --force /dev/sdc1 /dev/sde /tmp/mount")
++ 
++         self._checkCmd("ssm resize -s 3T my_pool /dev/sdc1 /dev/sde",
++             [], "btrfs filesystem resize 3221225472K /mnt/test1")
++         self.assertEqual(self.run_data[-2],
++-            "btrfs device add /dev/sdc1 /dev/sde /mnt/test1")
+++            "btrfs device add --force /dev/sdc1 /dev/sde /mnt/test1")
++ 
++         self._checkCmd("ssm resize -s 3T my_pool /dev/sde /dev/sdc2",
++             [], "btrfs filesystem resize 3221225472K /mnt/test1")
++         self.assertEqual(self.run_data[-2],
++-            "btrfs device add /dev/sde /mnt/test1")
+++            "btrfs device add --force /dev/sde /mnt/test1")
++ 
++         # Set volume in without the need adding more devices
++         self._checkCmd("ssm resize -s 10G default_pool /dev/sdc1 /dev/sde",
++             [], "btrfs filesystem resize 10485760K /tmp/mount")
++         self.assertNotEqual(self.run_data[-2],
++-            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
+++            "btrfs device add --force /dev/sdc1 /dev/sde /tmp/mount")
++         self._checkCmd("ssm resize -s 10G my_pool /dev/sdd /dev/sde",
++             [], "btrfs filesystem resize 10485760K /mnt/test1")
++         self.assertNotEqual(self.run_data[-2],
++-            "btrfs device add /dev/sdc1 /dev/sde /mnt/test1")
+++            "btrfs device add --force /dev/sdc1 /dev/sde /mnt/test1")
++ 
++         self._checkCmd("ssm list",
++             [], "btrfs filesystem resize 12247891967K /tmp/mount")
++@@ -330,23 +330,23 @@ class BtrfsFunctionCheck(MockSystemDataSource):
++         self._checkCmd("ssm resize -s +500G default_pool /dev/sdc1 /dev/sde",
++             [], "btrfs filesystem resize 12247891967K /tmp/mount")
++         self.assertEqual(self.run_data[-2],
++-            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
+++            "btrfs device add --force /dev/sdc1 /dev/sde /tmp/mount")
++ 
++         # Extend volume in without the need adding more devices
++         self._checkCmd("ssm resize -s 1k default_pool /dev/sdc1 /dev/sde",
++             [], "btrfs filesystem resize 1K /tmp/mount")
++         self.assertNotEqual(self.run_data[-2],
++-            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
+++            "btrfs device add --force /dev/sdc1 /dev/sde /tmp/mount")
++         self.assertNotEqual(self.run_data[-2],
++-            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
+++            "btrfs device add --force /dev/sdc1 /dev/sde /tmp/mount")
++ 
++         # Shrink volume with devices provided
++         self._checkCmd("ssm resize -s-10G default_pool /dev/sdc1 /dev/sde",
++             [], "btrfs filesystem resize 11713118207K /tmp/mount")
++         self.assertNotEqual(self.run_data[-2],
++-            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
+++            "btrfs device add --force /dev/sdc1 /dev/sde /tmp/mount")
++         self.assertNotEqual(self.run_data[-2],
++-            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
+++            "btrfs device add --force /dev/sdc1 /dev/sde /tmp/mount")
++ 
++     def test_btrfs_add(self):
++         default_pool = btrfs.SSM_BTRFS_DEFAULT_POOL
++@@ -354,39 +354,39 @@ class BtrfsFunctionCheck(MockSystemDataSource):
++         # Adding to non existent pool
++         # Add device into default pool
++         self._checkCmd("ssm add", ['/dev/sda'],
++-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
+++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
++ 
++         # Specify backend
++         self._checkCmd("ssm --backend btrfs add", ['/dev/sda'],
++-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
+++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
++ 
++         main.SSM_DEFAULT_BACKEND = 'lvm'
++         self._checkCmd("ssm -b btrfs add", ['/dev/sda'],
++-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
+++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
++         main.SSM_DEFAULT_BACKEND = 'btrfs'
++ 
++         # Add more devices into default pool
++         self._checkCmd("ssm add", ['/dev/sda /dev/sdc1'],
++-            "mkfs.btrfs -L {0} -f /dev/sda /dev/sdc1".format(default_pool))
+++            "mkfs.btrfs -L {0} --force /dev/sda /dev/sdc1".format(default_pool))
++         # Add device into defined pool
++         self._checkCmd("ssm add", ['-p my_pool', '/dev/sda'],
++-            "mkfs.btrfs -L my_pool -f /dev/sda")
+++            "mkfs.btrfs -L my_pool --force /dev/sda")
++         self._checkCmd("ssm add", ['--pool my_pool', '/dev/sda'],
++-            "mkfs.btrfs -L my_pool -f /dev/sda")
+++            "mkfs.btrfs -L my_pool --force /dev/sda")
++         # Add more devices into defined pool
++         self._checkCmd("ssm add", ['-p my_pool', '/dev/sda /dev/sdc1'],
++-            "mkfs.btrfs -L my_pool -f /dev/sda /dev/sdc1")
+++            "mkfs.btrfs -L my_pool --force /dev/sda /dev/sdc1")
++         self._checkCmd("ssm add", ['--pool my_pool', '/dev/sda /dev/sdc1'],
++-            "mkfs.btrfs -L my_pool -f /dev/sda /dev/sdc1")
+++            "mkfs.btrfs -L my_pool --force /dev/sda /dev/sdc1")
++ 
++         # Adding to existing default pool
++         self._addPool(default_pool, ['/dev/sdb', '/dev/sdd'])
++         # Add device into default pool
++         self._checkCmd("ssm add", ['/dev/sda'],
++-            "btrfs device add /dev/sda /tmp/mount")
+++            "btrfs device add --force /dev/sda /tmp/mount")
++         # Add more devices into default pool
++         self._checkCmd("ssm add", ['/dev/sda /dev/sdc1'],
++-            "btrfs device add /dev/sda /dev/sdc1 /tmp/mount")
+++            "btrfs device add --force /dev/sda /dev/sdc1 /tmp/mount")
++ 
++         # Adding to existing defined pool
++         self._addPool('my_pool', ['/dev/sdc2', '/dev/sdc3'])
++@@ -394,25 +394,25 @@ class BtrfsFunctionCheck(MockSystemDataSource):
++                     '/mnt/test1')
++         # Add device into defined pool
++         self._checkCmd("ssm add", ['-p my_pool', '/dev/sda'],
++-            "btrfs device add /dev/sda /mnt/test1")
+++            "btrfs device add --force /dev/sda /mnt/test1")
++         self._checkCmd("ssm add", ['--pool my_pool', '/dev/sda'],
++-            "btrfs device add /dev/sda /mnt/test1")
+++            "btrfs device add --force /dev/sda /mnt/test1")
++         # Add more devices into defined pool
++         self._checkCmd("ssm add", ['-p my_pool', '/dev/sda /dev/sdc1'],
++-            "btrfs device add /dev/sda /dev/sdc1 /mnt/test1")
+++            "btrfs device add --force /dev/sda /dev/sdc1 /mnt/test1")
++         self._checkCmd("ssm add", ['--pool my_pool', '/dev/sda /dev/sdc1'],
++-            "btrfs device add /dev/sda /dev/sdc1 /mnt/test1")
+++            "btrfs device add --force /dev/sda /dev/sdc1 /mnt/test1")
++         # Add verbose
++         self._checkCmd("ssm -v add", ['--pool {0}'.format(default_pool),
++             '/dev/sda /dev/sdc1'],
++-            "btrfs device add /dev/sda /dev/sdc1 /tmp/mount")
+++            "btrfs device add --force /dev/sda /dev/sdc1 /tmp/mount")
++ 
++         # Add two devices into existing pool (one of the devices already is in
++         # the pool
++         self._checkCmd("ssm add", ['--pool my_pool', '/dev/sdc2 /dev/sda'],
++-            "btrfs device add /dev/sda /mnt/test1")
+++            "btrfs device add --force /dev/sda /mnt/test1")
++         self._checkCmd("ssm add", ['/dev/sda /dev/sdb'],
++-            "btrfs device add /dev/sda /tmp/mount")
+++            "btrfs device add --force /dev/sda /tmp/mount")
++ 
++     def test_btrfs_mount(self):
++         self._addDir("/mnt/test")
++-- 
++1.8.3.1
++
+diff --git a/ssm-0.4-test-008-Device-count-should-go-down-after-removing-.patch b/ssm-0.4-test-008-Device-count-should-go-down-after-removing-.patch
+new file mode 100644
+index 0000000..890a04f
+--- /dev/null
++++ b/ssm-0.4-test-008-Device-count-should-go-down-after-removing-.patch
+@@ -0,0 +1,27 @@
++From 0e461e0fb15c47513faf0f27b553624ea51b069b Mon Sep 17 00:00:00 2001
++From: Lukas Czerner <lczerner at redhat.com>
++Date: Wed, 15 Jan 2014 17:39:00 +0100
++Subject: [PATCH 06/10] test 008: Device count should go down after removing a
++ device
++
++Signed-off-by: Lukas Czerner <lczerner at redhat.com>
++---
++ tests/bashtests/008-btrfs-remove.sh | 2 +-
++ 1 file changed, 1 insertion(+), 1 deletion(-)
++
++diff --git a/tests/bashtests/008-btrfs-remove.sh b/tests/bashtests/008-btrfs-remove.sh
++index fd9b91e..4e40e99 100755
++--- a/tests/bashtests/008-btrfs-remove.sh
+++++ b/tests/bashtests/008-btrfs-remove.sh
++@@ -93,7 +93,7 @@ export SSM_DEFAULT_BACKEND='btrfs'
++ not check btrfs_fs_field $pool1 label $pool1
++ not check btrfs_vol_field $mnt1 subvolume $vol1
++ not check btrfs_vol_field $mnt2 subvolume $vol2
++-check btrfs_fs_field $SSM_BTRFS_DEFAULT_POOL dev_count 5
+++check btrfs_fs_field $SSM_BTRFS_DEFAULT_POOL dev_count 4
++ umount_all
++ ssm -f remove --all
++ 
++-- 
++1.8.3.1
++
+diff --git a/ssm-0.4-tests-Fix-they-way-we-gather-information-about-btrfs.patch b/ssm-0.4-tests-Fix-they-way-we-gather-information-about-btrfs.patch
+new file mode 100644
+index 0000000..64c658e
+--- /dev/null
++++ b/ssm-0.4-tests-Fix-they-way-we-gather-information-about-btrfs.patch
+@@ -0,0 +1,27 @@
++From a5da549a380d83db0ee4b9bed70ec3575e6c2f37 Mon Sep 17 00:00:00 2001
++From: Lukas Czerner <lczerner at redhat.com>
++Date: Wed, 15 Jan 2014 15:52:34 +0100
++Subject: [PATCH 04/10] tests: Fix they way we gather information about btrfs
++ file system
++
++Signed-off-by: Lukas Czerner <lczerner at redhat.com>
++---
++ tests/bashtests/lib/check.sh | 2 +-
++ 1 file changed, 1 insertion(+), 1 deletion(-)
++
++diff --git a/tests/bashtests/lib/check.sh b/tests/bashtests/lib/check.sh
++index 9a8f853..e9a7f39 100644
++--- a/tests/bashtests/lib/check.sh
+++++ b/tests/bashtests/lib/check.sh
++@@ -323,7 +323,7 @@ crypt_vol_field()
++ 
++ btrfs_fs_field()
++ {
++-	lines=$(btrfs filesystem show 2> /dev/null | grep -A 1 "'$1'" || true)
+++	lines=$(btrfs filesystem show 2> /dev/null | grep -A 1 "^Label:.*$1" || true)
++ 
++ 	case $2 in
++ 		"label")
++-- 
++1.8.3.1
++
+diff --git a/ssm-0.4-tests-Make-btrfs-recognize-devices-from-tests-suite-.patch b/ssm-0.4-tests-Make-btrfs-recognize-devices-from-tests-suite-.patch
+new file mode 100644
+index 0000000..f690ff3
+--- /dev/null
++++ b/ssm-0.4-tests-Make-btrfs-recognize-devices-from-tests-suite-.patch
+@@ -0,0 +1,38 @@
++From c3609263094816eee96bef416f7ed72b49c8f2b8 Mon Sep 17 00:00:00 2001
++From: Lukas Czerner <lczerner at redhat.com>
++Date: Wed, 15 Jan 2014 16:51:18 +0100
++Subject: [PATCH 05/10] tests: Make btrfs recognize devices from tests suite
++ properly
++
++This is ugly hack to fix a problem with test suite and btrfs
++where ?sometimes? btrfs prints out device name in the path
++of the test suite rather than path in the real '/dev/'
++directory. This should cover that without any impact on
++real usage.
++
++Signed-off-by: Lukas Czerner <lczerner at redhat.com>
++---
++ ssmlib/backends/btrfs.py | 7 +++++++
++ 1 file changed, 7 insertions(+)
++
++diff --git a/ssmlib/backends/btrfs.py b/ssmlib/backends/btrfs.py
++index b238d52..836f108 100644
++--- a/ssmlib/backends/btrfs.py
+++++ b/ssmlib/backends/btrfs.py
++@@ -119,6 +119,13 @@ class Btrfs(template.Backend):
++                 fs_used = float(misc.get_real_size(array[6]))
++ 
++             elif array[0] == 'devid':
+++                # This is ugly hack to fix a problem with test suite and btrfs
+++                # where ?sometimes? btrfs prints out device name in the path
+++                # of the test suite rather than path in the real '/dev/'
+++                # directory. This should cover that without any impact on
+++                # real usage
+++                if not os.path.islink(array[7]):
+++                    array[7] = re.sub(r'.*/dev/', '/dev/', array[7])
++                 dev['dev_name'] = misc.get_real_device(array[7])
++ 
++                 if not pool_name:
++-- 
++1.8.3.1
++
+diff --git a/system-storage-manager.spec b/system-storage-manager.spec
+index 7f1947d..ed384ba 100644
+--- a/system-storage-manager.spec
++++ b/system-storage-manager.spec
+@@ -1,7 +1,7 @@
+ %{!?_pkgdocdir: %global _pkgdocdir %{_docdir}/%{name}-%{version}}
+ 
+ Name:           system-storage-manager
+-Version:        0.2
++Version:        0.4
+ Release:        4%{?dist}
+ Summary:        A single tool to manage your storage
+ 
+@@ -10,6 +10,22 @@ License:        GPLv2+
+ URL:            http://storagemanager.sf.net
+ Source0:        http://downloads.sourceforge.net/storagemanager/%{name}-%{version}.tar.gz
+ 
++
++Patch1: ssm-0.4-ssm-big-update-no-1.patch
++Patch2: ssm-0.4-misc-get_unit_size-accept-different-unit-formats.patch
++Patch3: ssm-0.4-ssm-btrfs-backend-try-to-find-the-real-device.patch
++Patch4: ssm-0.4-ssm-force-btrfs-device-add.patch
++Patch5: ssm-0.4-tests-Fix-they-way-we-gather-information-about-btrfs.patch
++Patch6: ssm-0.4-tests-Make-btrfs-recognize-devices-from-tests-suite-.patch
++Patch7: ssm-0.4-test-008-Device-count-should-go-down-after-removing-.patch
++Patch8: ssm-0.4-misc-Fix-get_device_size-to-work-with-partitions-cor.patch
++Patch9: ssm-0.4-ssm-Suppress-backtrace-if-command-failed.patch
++Patch10: ssm-0.4-ssm-Add-SSM_PRINT_BACKTRACE-environment-variable.patch
++Patch11: ssm-0.4-misc-Use-wipefs-a-in-misc.wipefs-helper.patch
++Patch12: ssm-0.4-ssm-Fix-various-problems-found-by-pylint.patch
++Patch13: ssm-0.4-ssm-Remove-unnecessary-usr-bin-env-python.patch
++
++
+ BuildArch:      noarch
+ BuildRequires:  python-devel >= 2.6
+ Requires:       python >= 2.6
+@@ -43,6 +59,33 @@ technologies via a single unified interface.
+ %prep
+ %setup -q
+ 
++# Contains upstream patches
++# 39eb3058a02a2b482c4c5bdf0120b70605a6b23a..4210d7560585f2a241eaa5ebc364c98d49f565d2
++%patch1 -p1
++# misc: get_unit_size() accept different unit formats
++%patch2 -p1
++# ssm: btrfs backend: try to find the real device
++%patch3 -p1
++# ssm: force btrfs device add
++%patch4 -p1
++# tests: Fix they way we gather information about btrfs
++%patch5 -p1
++# tests: Make btrfs recognize devices from tests suite properly
++%patch6 -p1
++# test 008: Device count should go down after removing a device
++%patch7 -p1
++# misc: Fix get_device_size to work with partitions correctly
++%patch8 -p1
++# ssm: Suppress backtrace if command failed
++%patch9 -p1
++# ssm: Add SSM_PRINT_BACKTRACE environment variable
++%patch10 -p1
++# misc: Use wipefs -a in misc.wipefs() helper
++%patch11 -p1
++# ssm: Fix various problems found by pylint
++%patch12 -p1
++# ssm: Remove unnecessary /usr/bin/env python
++%patch13 -p1
+ 
+ %build
+ # nothing to build
+@@ -55,6 +98,9 @@ if [ "%{_pkgdocdir}" != "%{_docdir}/%{name}-%{version}" ]; then
+     mv ${RPM_BUILD_ROOT}/{%{_docdir}/%{name}-%{version},%{_pkgdocdir}}
+ fi
+ 
++%check
++make test
++
+ 
+ %files
+ %{_bindir}/ssm
+@@ -65,6 +111,26 @@ fi
+ 
+ 
+ %changelog
++* Mon Jan 20 2014 Lukas Czerner <lczerner at redhat.com> 0.4-4
++- Update to a new upstream release v0.4
++- Remove btrfs resize support
++- Unmount all btrfs subvolumes when removing a filesystem
++- Fix size argument parsing for create and snapshot command
++- Fix list output for some cases
++- Add support to create encrypted volumes with crypt backend
++- Add dry-run option
++- Fix removing volumes with crypt backend
++- Add raid1 and raid10 support for lvm backend
++- Allow to check btrfs volumes
++- Fix error handling when trying to resize btrfs subvolume
++- Fix ssm mount command so it detects directory properly
++- Suppress backtrace when a command fails
++- Fix ssm to recognize units in new btrfs output properly
++- Use correct sysfs file to get size for a partition
++- Fix ssm to be able add a device with signature to btrfs file system
++- Resognize btrfs devices from new btrfs output properly
++
++
+ * Mon Dec 16 2013 Ville Skyttä <ville.skytta at iki.fi> - 0.2-4
+ - Install docs to %%{_pkgdocdir} where available (#994122).
+ 
+-- 
+1.8.3.1
+
diff --git a/sources b/sources
index 038df21..f176aa7 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-524654f3b7bab544c4e612470b5d2392  system-storage-manager-0.2.tar.gz
+43235208daf95f8ada1b0632bf7bc756  system-storage-manager-0.4.tar.gz
diff --git a/ssm-0.4-misc-Fix-get_device_size-to-work-with-partitions-cor.patch b/ssm-0.4-misc-Fix-get_device_size-to-work-with-partitions-cor.patch
new file mode 100644
index 0000000..3aac93c
--- /dev/null
+++ b/ssm-0.4-misc-Fix-get_device_size-to-work-with-partitions-cor.patch
@@ -0,0 +1,39 @@
+From 5b917ffbddfbb7366d2ad7d5f0e9c016ced29ca5 Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner at redhat.com>
+Date: Wed, 15 Jan 2014 17:52:28 +0100
+Subject: [PATCH 07/10] misc: Fix get_device_size to work with partitions
+ correctly
+
+Currently get_device_size() searches for the size in sysfs specifically
+(/sys/block/<devname>/size) however that is not the right palce for
+partitions since partitions are subdirectories in /sys/block/<devname>
+directory.
+
+So change get_device_size() to get major and minor numbers of the device
+in question and use sysfs file /sys/dev/block/<major>:<minor>/size to
+get the size.
+
+Signed-off-by: Lukas Czerner <lczerner at redhat.com>
+---
+ ssmlib/misc.py | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/ssmlib/misc.py b/ssmlib/misc.py
+index bfaa1c4..dbfa6b1 100644
+--- a/ssmlib/misc.py
++++ b/ssmlib/misc.py
+@@ -608,8 +608,9 @@ def is_bdevice(path):
+ 
+ 
+ def get_device_size(device):
+-    devname = device.split('/')[-1]
+-    with open("/sys/block/{0}/size".format(devname), 'r') as f:
++    info = os.stat(device)
++    major, minor = divmod(info.st_rdev, 256)
++    with open("/sys/dev/block/{0}:{1}/size".format(major, minor), 'r') as f:
+         for line in f:
+             size = int(line)/2
+             return size
+-- 
+1.8.3.1
+
diff --git a/ssm-0.4-misc-Use-wipefs-a-in-misc.wipefs-helper.patch b/ssm-0.4-misc-Use-wipefs-a-in-misc.wipefs-helper.patch
new file mode 100644
index 0000000..9a11955
--- /dev/null
+++ b/ssm-0.4-misc-Use-wipefs-a-in-misc.wipefs-helper.patch
@@ -0,0 +1,103 @@
+From 37b31373b1408c299270e3134b88eff4528ca75a Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner at redhat.com>
+Date: Thu, 16 Jan 2014 17:31:57 +0100
+Subject: [PATCH 10/10] misc: Use wipefs -a in misc.wipefs() helper
+
+Currently we only wipe the first signature we can find with wipefs.
+However wipefs has an ability to wipe all the signatures of given type
+from the device (yes this is once again about btrfs) with option '-a'.
+So use that instead. This also simplify the wipefs helper a lot.
+
+Signed-off-by: Lukas Czerner <lczerner at redhat.com>
+---
+ ssmlib/misc.py                | 14 ++------------
+ tests/unittests/test_btrfs.py | 34 +++++++++++++++++-----------------
+ 2 files changed, 19 insertions(+), 29 deletions(-)
+
+diff --git a/ssmlib/misc.py b/ssmlib/misc.py
+index 3d99c07..915cad1 100644
+--- a/ssmlib/misc.py
++++ b/ssmlib/misc.py
+@@ -363,18 +363,8 @@ def get_dmnumber(name):
+ def wipefs(device, signatures):
+     if type(signatures) is not list:
+         signatures = [signatures]
+-    command = ['wipefs', '-p', device]
+-    output = run(command)[1]
+-    offset = []
+-    for line in output[1:].split('\n'):
+-        if not line:
+-            continue
+-        array = line.split(",")
+-        if array[-1] in signatures:
+-            offset.extend(['--offset', array[0]])
+-    if len(offset) > 1:
+-        command = ['wipefs'] + offset + [device]
+-        run(command)
++    command = ['wipefs', '-a', '-t', ','.join(signatures), device]
++    run(command)
+ 
+ 
+ def humanize_size(arg):
+diff --git a/tests/unittests/test_btrfs.py b/tests/unittests/test_btrfs.py
+index 2fb04bc..2b6cd8e 100644
+--- a/tests/unittests/test_btrfs.py
++++ b/tests/unittests/test_btrfs.py
+@@ -167,12 +167,12 @@ class BtrfsFunctionCheck(MockSystemDataSource):
+         self._addPool('my_pool', ['/dev/sdc2', '/dev/sdc3', '/dev/sdc1'])
+ 
+         # remove volume
+-        self._checkCmd("ssm remove default_pool", [], "wipefs -p /dev/sda")
+-        self._cmdEq("wipefs -p /dev/sdb", -2)
++        self._checkCmd("ssm remove default_pool", [], "wipefs -a -t btrfs /dev/sda")
++        self._cmdEq("wipefs -a -t btrfs /dev/sdb", -2)
+ 
+-        self._checkCmd("ssm remove my_pool", [], "wipefs -p /dev/sdc3")
+-        self._cmdEq("wipefs -p /dev/sdc1", -2)
+-        self._cmdEq("wipefs -p /dev/sdc2", -3)
++        self._checkCmd("ssm remove my_pool", [], "wipefs -a -t btrfs /dev/sdc3")
++        self._cmdEq("wipefs -a -t btrfs /dev/sdc1", -2)
++        self._cmdEq("wipefs -a -t btrfs /dev/sdc2", -3)
+ 
+         # remove subvolume
+         self._addVol('vol001', 117283225, 1, 'default_pool', ['/dev/sda'], '/mnt/test')
+@@ -189,24 +189,24 @@ class BtrfsFunctionCheck(MockSystemDataSource):
+         self._addPool('other_pool', ['/dev/sdd', '/dev/sde'])
+         self._checkCmd("ssm remove /dev/sdd /dev/sdb other_pool my_pool default_pool:/dev/default_pool/vol001", [],
+             "btrfs subvolume delete /mnt/test")
+-        self._cmdEq("wipefs -p /dev/sdc1", -2)
+-        self._cmdEq("wipefs -p /dev/sdc3", -3)
+-        self._cmdEq("wipefs -p /dev/sdc2", -4)
+-        self._cmdEq("wipefs -p /dev/sde", -5)
+-        self._cmdEq("wipefs -p /dev/sdd", -6)
++        self._cmdEq("wipefs -a -t btrfs /dev/sdc1", -2)
++        self._cmdEq("wipefs -a -t btrfs /dev/sdc3", -3)
++        self._cmdEq("wipefs -a -t btrfs /dev/sdc2", -4)
++        self._cmdEq("wipefs -a -t btrfs /dev/sde", -5)
++        self._cmdEq("wipefs -a -t btrfs /dev/sdd", -6)
+         self._cmdEq("btrfs device delete /dev/sdb /mnt/test", -7)
+         self._cmdEq("btrfs device delete /dev/sdd /tmp/mount", -8)
+ 
+         self._removeMount("/dev/sda")
+         # remove all
+         self._checkCmd("ssm remove --all", [],
+-            "wipefs -p /dev/sde")
+-        self._cmdEq("wipefs -p /dev/sdd", -2)
+-        self._cmdEq("wipefs -p /dev/sdc1", -3)
+-        self._cmdEq("wipefs -p /dev/sdc3", -4)
+-        self._cmdEq("wipefs -p /dev/sdc2", -5)
+-        self._cmdEq("wipefs -p /dev/sda", -6)
+-        self._cmdEq("wipefs -p /dev/sdb", -7)
++            "wipefs -a -t btrfs /dev/sde")
++        self._cmdEq("wipefs -a -t btrfs /dev/sdd", -2)
++        self._cmdEq("wipefs -a -t btrfs /dev/sdc1", -3)
++        self._cmdEq("wipefs -a -t btrfs /dev/sdc3", -4)
++        self._cmdEq("wipefs -a -t btrfs /dev/sdc2", -5)
++        self._cmdEq("wipefs -a -t btrfs /dev/sda", -6)
++        self._cmdEq("wipefs -a -t btrfs /dev/sdb", -7)
+ 
+         # TODO
+         # remove force
+-- 
+1.8.3.1
+
diff --git a/ssm-0.4-misc-get_unit_size-accept-different-unit-formats.patch b/ssm-0.4-misc-get_unit_size-accept-different-unit-formats.patch
new file mode 100644
index 0000000..e74536a
--- /dev/null
+++ b/ssm-0.4-misc-get_unit_size-accept-different-unit-formats.patch
@@ -0,0 +1,221 @@
+From ef26cf6fb0e33ca52f35fcf219fd21db7788c200 Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner at redhat.com>
+Date: Mon, 13 Jan 2014 16:29:01 +0100
+Subject: [PATCH 01/10] misc: get_unit_size() accept different unit formats
+
+Because btrfs recently changed it's output to use MiB format instead of
+MB format the function handling this within the btrfs is broken.
+
+Fix this my making get_unit_size() to handle different unit formats (M,
+MB, MiB) and use that in btrfs as well.
+
+Signed-off-by: Lukas Czerner <lczerner at redhat.com>
+---
+ ssmlib/backends/btrfs.py | 18 ++---------
+ ssmlib/misc.py           | 82 ++++++++++++++++++++++++++++++++++--------------
+ test.py                  | 13 ++++----
+ 3 files changed, 69 insertions(+), 44 deletions(-)
+
+diff --git a/ssmlib/backends/btrfs.py b/ssmlib/backends/btrfs.py
+index a4aedda..eb23403 100644
+--- a/ssmlib/backends/btrfs.py
++++ b/ssmlib/backends/btrfs.py
+@@ -33,18 +33,6 @@ except KeyError:
+     SSM_BTRFS_DEFAULT_POOL = "btrfs_pool"
+ 
+ 
+-def get_real_number(string):
+-    number = float(string[0:-2])
+-    unit = string[-2:-1]
+-    # The result will be in kilobytes
+-    units = ["K", "M", "G", "T", "P", "E", "Z", "Y"]
+-    for i, u in enumerate(units):
+-        if u == unit:
+-            number *= (2 ** (i * 10))
+-            break
+-    return number
+-
+-
+ def get_btrfs_version():
+     try:
+         output = misc.run(['btrfs', '--version'], can_fail=True)[1]
+@@ -128,7 +116,7 @@ class Btrfs(template.Backend):
+ 
+             elif array[0] == 'Total':
+                 pool['dev_count'] = array[2]
+-                fs_used = get_real_number(array[6])
++                fs_used = float(misc.get_real_size(array[6]))
+ 
+             elif array[0] == 'devid':
+                 dev['dev_name'] = array[7]
+@@ -154,9 +142,9 @@ class Btrfs(template.Backend):
+                                 vol['real_dev'] = found[0].split(':')[0]
+                                 break
+ 
+-                dev_used = get_real_number(array[5])
++                dev_used = float(misc.get_real_size(array[5]))
+                 dev['dev_used'] = str(dev_used)
+-                fs_size += get_real_number(array[3])
++                fs_size += float(misc.get_real_size(array[3]))
+ 
+                 dev_size = \
+                     int(partitions[dev['dev_name'].rpartition("/")[-1]][2])
+diff --git a/ssmlib/misc.py b/ssmlib/misc.py
+index 3ff1577..bfaa1c4 100644
+--- a/ssmlib/misc.py
++++ b/ssmlib/misc.py
+@@ -32,34 +32,57 @@ TMP_MOUNTED = []
+ 
+ def get_unit_size(string):
+     """
+-    Check the last character of the string for the unit and return the unit
+-    value, otherwise return zero. It check only the last character of the
+-    string.
++    Check the last character of the string for the unit and return the tuple
++    of unit value, unit name, otherwise return zero. It check only the first
++    character of the unit string.
+ 
+     >>> get_unit_size("B")
+-    1
++    (1, 'B')
+     >>> get_unit_size("k")
+-    1024
+-    >>> get_unit_size("M")
+-    1048576
+-    >>> get_unit_size("g")
+-    1073741824
+-    >>> get_unit_size("T")
+-    1099511627776...
+-    >>> get_unit_size("p")
+-    1125899906842624...
++    (1024, 'k')
++    >>> get_unit_size("KiB")
++    (1024, 'KiB')
++    >>> get_unit_size("KB")
++    (1024, 'KB')
++    >>> get_unit_size("10M")
++    (1048576, 'M')
++    >>> get_unit_size("-99.99g")
++    (1073741824, 'g')
++    >>> get_unit_size("-99.99GiB")
++    (1073741824, 'GiB')
++    >>> get_unit_size("+99.99G")
++    (1073741824, 'G')
++    >>> get_unit_size("+99.99gb")
++    (1073741824, 'gb')
++    >>> get_unit_size("99.99g")
++    (1073741824, 'g')
++    >>> get_unit_size("0.84T")
++    (1099511627776, 'T')
++    >>> get_unit_size("0.84TiB")
++    (1099511627776, 'TiB')
++    >>> get_unit_size("0p")
++    (1125899906842624, 'p')
++    >>> get_unit_size("99kit")
++    (0, '')
+     >>> get_unit_size("")
+-    0
++    (0, '')
+     >>> get_unit_size("H")
+-    0
++    (0, '')
+     """
+ 
+     mult = 0
+     units = {'B': 1, 'K': 2 ** 10, 'M': 2 ** 20, 'G': 2 ** 30, 'T': 2 ** 40,
+              'P': 2 ** 50}
+-    if len(string) > 0 and string[-1].upper() in units:
+-        mult = units[string[-1].upper()]
+-    return mult
++    unit = re.sub(r'^\+?-?\d+(\.\d*)?', '', string)
++    if len(unit) > 0 and unit[0].upper() in units:
++        mult = units[unit[0].upper()]
++    all_units = {'B', 'K', 'M', 'G', 'T', 'P',
++                 'KB', 'MB', 'GB', 'TB', 'PB',
++                 'KIB', 'MIB', 'GIB', 'TIB', 'PIB'}
++    if unit.upper() in all_units:
++        return mult, unit
++    else:
++        return 0, ""
+ 
+ 
+ def is_number(string):
+@@ -92,8 +115,14 @@ def get_real_size(size):
+ 
+     >>> get_real_size("3141")
+     '3141'
++    >>> get_real_size("3141B")
++    '3.07'
+     >>> get_real_size("3141K")
+     '3141.00'
++    >>> get_real_size("3141KB")
++    '3141.00'
++    >>> get_real_size("3141KiB")
++    '3141.00'
+     >>> get_real_size("3141k")
+     '3141.00'
+     >>> get_real_size("3141M")
+@@ -118,6 +147,10 @@ def get_real_size(size):
+     '-3.14'
+     >>> get_real_size("3.14G")
+     '3292528.64'
++    >>> get_real_size("3.14GB")
++    '3292528.64'
++    >>> get_real_size("3.14GiB")
++    '3292528.64'
+     >>> get_real_size("+3.14g")
+     '+3292528.64'
+     >>> get_real_size("-3.14G")
+@@ -133,12 +166,15 @@ def get_real_size(size):
+     """
+     if is_number(size):
+         return size
+-    elif is_number(size[:-1]):
++    else:
+         # Always use kilobytes in ssm
+-        mult = get_unit_size(size) / 1024
+-        sign = '+' if size[0] == '+' else ''
+-        if mult:
+-            return '{0}{1:.2f}'.format(sign, float(size[:-1]) * mult)
++        mult, unit = get_unit_size(size)
++        mult /= float(1024)
++        number = re.sub(unit + "$", '', size)
++        if is_number(number):
++            sign = '+' if size[0] == '+' else ''
++            if mult:
++                return '{0}{1:.2f}'.format(sign, float(number) * mult)
+     raise Exception("Not supported unit in the " +
+                     "size \'{0}\' argument.".format(size))
+ 
+diff --git a/test.py b/test.py
+index 2ca542c..7c91ae8 100644
+--- a/test.py
++++ b/test.py
+@@ -89,17 +89,18 @@ def run_bash_tests():
+ 
+ def quick_test():
+     print "[+] Running doctests"
+-    doctest_flags = doctest.IGNORE_EXCEPTION_DETAIL | doctest.ELLIPSIS
++    doctest_flags = doctest.IGNORE_EXCEPTION_DETAIL | doctest.ELLIPSIS | \
++                    doctest.REPORT_ONLY_FIRST_FAILURE
+     result = doctest.testmod(main, exclude_empty=True, report=True,
+-            raise_on_error=True, optionflags=doctest_flags)
++            raise_on_error=False, optionflags=doctest_flags)
+     result = doctest.testmod(lvm, exclude_empty=True, report=True,
+-            raise_on_error=True, optionflags=doctest_flags)
++            raise_on_error=False, optionflags=doctest_flags)
+     result = doctest.testmod(crypt, exclude_empty=True, report=True,
+-            raise_on_error=True, optionflags=doctest_flags)
++            raise_on_error=False, optionflags=doctest_flags)
+     result = doctest.testmod(btrfs, exclude_empty=True, report=True,
+-            raise_on_error=True, optionflags=doctest_flags)
++            raise_on_error=False, optionflags=doctest_flags)
+     result = doctest.testmod(misc, exclude_empty=True, report=True,
+-            raise_on_error=True, optionflags=doctest_flags)
++            raise_on_error=False, optionflags=doctest_flags)
+     print "[+] Running unittests"
+     test_loader = unittest.TestLoader()
+     tests_lvm = test_loader.loadTestsFromModule(test_lvm)
+-- 
+1.8.3.1
+
diff --git a/ssm-0.4-ssm-Add-SSM_PRINT_BACKTRACE-environment-variable.patch b/ssm-0.4-ssm-Add-SSM_PRINT_BACKTRACE-environment-variable.patch
new file mode 100644
index 0000000..e305100
--- /dev/null
+++ b/ssm-0.4-ssm-Add-SSM_PRINT_BACKTRACE-environment-variable.patch
@@ -0,0 +1,57 @@
+From e5577724d859ca19e6b3074f05f25bc43c748a43 Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner at redhat.com>
+Date: Thu, 16 Jan 2014 15:08:11 +0100
+Subject: [PATCH 09/10] ssm: Add SSM_PRINT_BACKTRACE environment variable
+
+Currently we're catching all the SsmError exception and just print out
+simple error message. This is fine, however it makes debugging harder in
+some cases, so add SSM_PRINT_BACKTRACE environment variable which
+enables us to print traceback when needed. Simply set the variable to
+yes, true, or 1 and ssm will print traceback in case of error.
+
+Signed-off-by: Lukas Czerner <lczerner at redhat.com>
+---
+ bin/ssm | 20 +++++++++++++++++++-
+ 1 file changed, 19 insertions(+), 1 deletion(-)
+
+diff --git a/bin/ssm b/bin/ssm
+index baa3c60..6058f64 100755
+--- a/bin/ssm
++++ b/bin/ssm
+@@ -19,8 +19,23 @@
+ 
+ import os
+ import sys
++import traceback
+ from ssmlib import problem
+ 
++
++# Should we print backtrace on error, or suppress it ?
++# Suppress it by default.
++try:
++    SSM_PRINT_BACKTRACE = os.environ['SSM_PRINT_BACKTRACE']
++    if SSM_PRINT_BACKTRACE.upper() in ['YES', 'TRUE', '1']:
++        SSM_PRINT_BACKTRACE = True
++    else:
++        SSM_PRINT_BACKTRACE = False
++except KeyError:
++    SSM_PRINT_BACKTRACE = False
++
++
++
+ try:
+     from ssmlib import main
+ 
+@@ -32,5 +47,8 @@ try:
+                 sys.exit("\nRoot privileges required to run this script!\n")
+         sys.exit(main.main())
+ except problem.SsmError, err:
+-    print str(err)
++    if SSM_PRINT_BACKTRACE is True:
++        traceback.print_exc(file=sys.stdout)
++    else:
++        print str(err)
+     sys.exit(err.errcode)
+-- 
+1.8.3.1
+
diff --git a/ssm-0.4-ssm-Fix-various-problems-found-by-pylint.patch b/ssm-0.4-ssm-Fix-various-problems-found-by-pylint.patch
new file mode 100644
index 0000000..f436c38
--- /dev/null
+++ b/ssm-0.4-ssm-Fix-various-problems-found-by-pylint.patch
@@ -0,0 +1,222 @@
+From 0dcf4bcee5c5f6503905dac298dee77f1141f783 Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner at redhat.com>
+Date: Fri, 17 Jan 2014 16:05:56 +0100
+Subject: [PATCH] ssm: Fix various problems found by pylint
+
+Signed-off-by: Lukas Czerner <lczerner at redhat.com>
+---
+ ssmlib/__init__.py       |  2 +-
+ ssmlib/backends/btrfs.py | 12 +++++-------
+ ssmlib/backends/crypt.py |  5 ++---
+ ssmlib/backends/lvm.py   |  3 +--
+ ssmlib/backends/md.py    |  3 ---
+ ssmlib/main.py           |  6 +++---
+ ssmlib/misc.py           | 12 ++++++------
+ 7 files changed, 18 insertions(+), 25 deletions(-)
+
+diff --git a/ssmlib/__init__.py b/ssmlib/__init__.py
+index f1bcfdb..0a49de2 100644
+--- a/ssmlib/__init__.py
++++ b/ssmlib/__init__.py
+@@ -15,4 +15,4 @@
+ # You should have received a copy of the GNU General Public License
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ 
+-__all__ = ["backends", "misc", "main", "problem"]
++__all__ = ["backend", "misc", "main", "problem"]
+diff --git a/ssmlib/backends/btrfs.py b/ssmlib/backends/btrfs.py
+index 836f108..acd5446 100644
+--- a/ssmlib/backends/btrfs.py
++++ b/ssmlib/backends/btrfs.py
+@@ -19,10 +19,8 @@
+ 
+ import re
+ import os
+-import sys
+ import datetime
+ from ssmlib import misc
+-from ssmlib import problem
+ from ssmlib.backends import template
+ 
+ __all__ = ["BtrfsVolume", "BtrfsPool", "BtrfsDev"]
+@@ -37,7 +35,7 @@ def get_btrfs_version():
+     try:
+         output = misc.run(['btrfs', '--version'], can_fail=True)[1]
+         output = output.strip().split("\n")[-1]
+-        version = re.search('(?<=v)\d+\.\d+', output).group(0)
++        version = re.search(r'(?<=v)\d+\.\d+', output).group(0)
+     except (OSError, AttributeError):
+         version = "0.0"
+     return float(version)
+@@ -262,7 +260,7 @@ class Btrfs(template.Backend):
+                 new['hide'] = False
+                 # Store snapshot info
+                 if 'mount' in new and \
+-                    re.match("snap-\d{4}-\d{2}-\d{2}-T\d{6}",
++                    re.match(r"snap-\d{4}-\d{2}-\d{2}-T\d{6}",
+                              os.path.basename(new['mount'])):
+                     new['snap_name'] = "{0}:{1}".format(name,
+                             os.path.basename(new['path']))
+@@ -279,8 +277,8 @@ class Btrfs(template.Backend):
+                 continue
+             # For the version with screwed 'subvolume list' command
+             line = re.sub("<FS_TREE>/*", "", line)
+-            volume['ID'] = re.search('(?<=ID )\d+', line).group(0)
+-            volume['top_level'] = re.search('(?<=top level )\d+', line).group(0)
++            volume['ID'] = re.search(r'(?<=ID )\d+', line).group(0)
++            volume['top_level'] = re.search(r'(?<=top level )\d+', line).group(0)
+             volume['path'] = re.search('(?<=path ).*$', line).group(0)
+             volume['subvolume'] = True
+             yield volume
+@@ -450,7 +448,7 @@ class BtrfsPool(Btrfs, template.BackendPool):
+                 command.extend(['-m', 'raid10', '-d', 'raid10'])
+             else:
+                 raise Exception("Btrfs backed currently does not support " +
+-                                "RAID level {0}".format(raid['level']))
++                                "RAID level {0}".format(options['raid']))
+ 
+         if size:
+             command.extend(['-b', "{0}".format(int(float(size) * 1024))])
+diff --git a/ssmlib/backends/crypt.py b/ssmlib/backends/crypt.py
+index 4aad266..8c1b48c 100644
+--- a/ssmlib/backends/crypt.py
++++ b/ssmlib/backends/crypt.py
+@@ -21,7 +21,6 @@ import re
+ import os
+ import stat
+ from ssmlib import misc
+-from ssmlib import problem
+ from ssmlib.backends import template
+ 
+ __all__ = ["DmCryptVolume"]
+@@ -240,7 +239,7 @@ class DmCryptDevice(DmObject, template.BackendDevice):
+             device = {}
+             devname = "/dev/" + line[3]
+             signature = misc.get_signature(devname)
+-            if misc.get_signature(devname) in CRYPT_SIGNATURES:
++            if signature in CRYPT_SIGNATURES:
+                 device['hide'] = False
+                 device['dev_name'] = devname
+                 device['pool_name'] = self.default_pool_name
+@@ -250,4 +249,4 @@ class DmCryptDevice(DmObject, template.BackendDevice):
+ 
+ 
+     def remove(self, devices):
+-        misc.wipefs(device, CRYPT_SIGNATURES)
++        misc.wipefs(devices, CRYPT_SIGNATURES)
+diff --git a/ssmlib/backends/lvm.py b/ssmlib/backends/lvm.py
+index 955c705..4c7c0ad 100644
+--- a/ssmlib/backends/lvm.py
++++ b/ssmlib/backends/lvm.py
+@@ -22,7 +22,6 @@ import os
+ import stat
+ import datetime
+ from ssmlib import misc
+-from ssmlib import problem
+ from ssmlib.backends import template
+ 
+ __all__ = ["PvsInfo", "VgsInfo", "LvsInfo"]
+@@ -47,7 +46,7 @@ def get_lvm_version():
+         for line in output:
+             if pattern.match(line.strip()):
+                 match = " ".join(line.split())
+-                tmp = re.search('(?<=LVM version: )\d+\.\d+\.\d+',
++                tmp = re.search(r'(?<=LVM version: )\d+\.\d+\.\d+',
+                                     match).group(0)
+                 version = map(int, tmp.split(".", 3))
+     except (OSError, AttributeError):
+diff --git a/ssmlib/backends/md.py b/ssmlib/backends/md.py
+index f33243c..1e3c6e2 100644
+--- a/ssmlib/backends/md.py
++++ b/ssmlib/backends/md.py
+@@ -18,11 +18,8 @@
+ # md module for System Storage Manager
+ 
+ import os
+-import stat
+ import socket
+-import datetime
+ from ssmlib import misc
+-from ssmlib import problem
+ from ssmlib.backends import template
+ 
+ try:
+diff --git a/ssmlib/main.py b/ssmlib/main.py
+index 7aab312..c294aec 100644
+--- a/ssmlib/main.py
++++ b/ssmlib/main.py
+@@ -1284,7 +1284,7 @@ class StorageHandle(object):
+                 try:
+                     pool.remove()
+                     removed += 1
+-                except (RuntimeError, problem.SsmError), ex:
++                except (RuntimeError, problem.SsmError):
+                     PR.info("Unable to remove '{0}'".format(pool['pool_name']))
+                     ret = False
+             if removed == 0:
+@@ -1378,7 +1378,6 @@ class StorageHandle(object):
+         dev = self.dev[real]
+         if dev and 'fs_info' in dev:
+             return dev
+-        err = "'{0}' does not contain valid file system".format(real)
+         return False
+ 
+     def _find_device_record(self, path):
+@@ -1544,6 +1543,7 @@ def valid_resize_size(size):
+ 
+ def is_directory(string):
+     if string is None:
++        err = "Directory name not defined."
+         raise argparse.ArgumentTypeError(err)
+     try:
+         mode = os.stat(string).st_mode
+@@ -1847,7 +1847,7 @@ def main(args=None):
+     sys.exitfunc = misc.do_cleanup
+ 
+     if args.dry_run:
+-        return 0;
++        return 0
+ 
+     try:
+         args.func(args)
+diff --git a/ssmlib/misc.py b/ssmlib/misc.py
+index 915cad1..77ddc2d 100644
+--- a/ssmlib/misc.py
++++ b/ssmlib/misc.py
+@@ -77,9 +77,9 @@ def get_unit_size(string):
+     unit = re.sub(r'^\+?-?\d+(\.\d*)?', '', string)
+     if len(unit) > 0 and unit[0].upper() in units:
+         mult = units[unit[0].upper()]
+-    all_units = {'B', 'K', 'M', 'G', 'T', 'P',
++    all_units = ['B', 'K', 'M', 'G', 'T', 'P',
+                  'KB', 'MB', 'GB', 'TB', 'PB',
+-                 'KIB', 'MIB', 'GIB', 'TIB', 'PIB'}
++                 'KIB', 'MIB', 'GIB', 'TIB', 'PIB']
+     if unit.upper() in all_units:
+         return mult, unit
+     else:
+@@ -198,9 +198,9 @@ def get_device_by_uuid(uuid):
+ 
+ def get_major_minor(device):
+     real_dev = get_real_device(device)
+-    stat = os.stat(real_dev)
+-    major = os.major(stat.st_rdev)
+-    minor = os.minor(stat.st_rdev)
++    info = os.stat(real_dev)
++    major = os.major(info.st_rdev)
++    minor = os.minor(info.st_rdev)
+     return major, minor
+ 
+ 
+@@ -579,7 +579,7 @@ def terminal_size(default=(25, 80)):
+             except:
+                 pass
+         if not cr:
+-            cr = (25, 80)
++            cr = default
+     return int(cr[1]), int(cr[0])
+ 
+ 
+-- 
+1.8.3.1
+
diff --git a/ssm-0.4-ssm-Remove-unnecessary-usr-bin-env-python.patch b/ssm-0.4-ssm-Remove-unnecessary-usr-bin-env-python.patch
new file mode 100644
index 0000000..d72922c
--- /dev/null
+++ b/ssm-0.4-ssm-Remove-unnecessary-usr-bin-env-python.patch
@@ -0,0 +1,124 @@
+From 7a27177855ea2466d01dd201571f66ddea6c7cc8 Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner at redhat.com>
+Date: Fri, 17 Jan 2014 16:29:50 +0100
+Subject: [PATCH] ssm: Remove unnecessary /usr/bin/env python
+
+Those are not executable script and should not contain this line.
+
+Signed-off-by: Lukas Czerner <lczerner at redhat.com>
+---
+ ssmlib/__init__.py          | 2 --
+ ssmlib/backends/__init__.py | 2 --
+ ssmlib/backends/btrfs.py    | 2 --
+ ssmlib/backends/crypt.py    | 2 --
+ ssmlib/backends/lvm.py      | 2 --
+ ssmlib/backends/md.py       | 2 --
+ ssmlib/backends/template.py | 2 --
+ ssmlib/main.py              | 2 --
+ ssmlib/misc.py              | 2 --
+ ssmlib/problem.py           | 2 --
+ 10 files changed, 20 deletions(-)
+
+diff --git a/ssmlib/__init__.py b/ssmlib/__init__.py
+index 0a49de2..7e5e4fd 100644
+--- a/ssmlib/__init__.py
++++ b/ssmlib/__init__.py
+@@ -1,5 +1,3 @@
+-#!/usr/bin/env python
+-#
+ # (C)2011 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
+ #
+ # This program is free software: you can redistribute it and/or modify
+diff --git a/ssmlib/backends/__init__.py b/ssmlib/backends/__init__.py
+index 5720e3d..2046e83 100644
+--- a/ssmlib/backends/__init__.py
++++ b/ssmlib/backends/__init__.py
+@@ -1,5 +1,3 @@
+-#!/usr/bin/env python
+-#
+ # (C)2011 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
+ #
+ # This program is free software: you can redistribute it and/or modify
+diff --git a/ssmlib/backends/btrfs.py b/ssmlib/backends/btrfs.py
+index acd5446..b0a486f 100644
+--- a/ssmlib/backends/btrfs.py
++++ b/ssmlib/backends/btrfs.py
+@@ -1,5 +1,3 @@
+-#!/usr/bin/env python
+-#
+ # (C)2011 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
+ #
+ # This program is free software: you can redistribute it and/or modify
+diff --git a/ssmlib/backends/crypt.py b/ssmlib/backends/crypt.py
+index 8c1b48c..642b905 100644
+--- a/ssmlib/backends/crypt.py
++++ b/ssmlib/backends/crypt.py
+@@ -1,5 +1,3 @@
+-#!/usr/bin/env python
+-#
+ # (C)2011 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
+ #
+ # This program is free software: you can redistribute it and/or modify
+diff --git a/ssmlib/backends/lvm.py b/ssmlib/backends/lvm.py
+index 4c7c0ad..4022034 100644
+--- a/ssmlib/backends/lvm.py
++++ b/ssmlib/backends/lvm.py
+@@ -1,5 +1,3 @@
+-#!/usr/bin/env python
+-#
+ # (C)2011 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
+ #
+ # This program is free software: you can redistribute it and/or modify
+diff --git a/ssmlib/backends/md.py b/ssmlib/backends/md.py
+index 1e3c6e2..fca2c98 100644
+--- a/ssmlib/backends/md.py
++++ b/ssmlib/backends/md.py
+@@ -1,5 +1,3 @@
+-#!/usr/bin/env python
+-#
+ # (C)2012 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
+ #
+ # This program is free software: you can redistribute it and/or modify
+diff --git a/ssmlib/backends/template.py b/ssmlib/backends/template.py
+index 94f4b40..bf1b6ad 100644
+--- a/ssmlib/backends/template.py
++++ b/ssmlib/backends/template.py
+@@ -1,5 +1,3 @@
+-#!/usr/bin/env python
+-#
+ # (C)2013 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
+ #
+ # This program is free software: you can redistribute it and/or modify
+diff --git a/ssmlib/main.py b/ssmlib/main.py
+index c294aec..5213000 100644
+--- a/ssmlib/main.py
++++ b/ssmlib/main.py
+@@ -1,5 +1,3 @@
+-#!/usr/bin/env python
+-#
+ # (C)2011 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
+ #
+ # This program is free software: you can redistribute it and/or modify
+diff --git a/ssmlib/misc.py b/ssmlib/misc.py
+index 77ddc2d..24b7dd9 100644
+--- a/ssmlib/misc.py
++++ b/ssmlib/misc.py
+@@ -1,5 +1,3 @@
+-#!/usr/bin/env python
+-#
+ # (C)2011 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
+ #
+ # This program is free software: you can redistribute it and/or modify
+diff --git a/ssmlib/problem.py b/ssmlib/problem.py
+index dfa6ec6..f8fb4ce 100644
+--- a/ssmlib/problem.py
++++ b/ssmlib/problem.py
+@@ -1,5 +1,3 @@
+-#!/usr/bin/env python
+-#
+ # (C)2012 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
+ #
+ # This program is free software: you can redistribute it and/or modify
+-- 
+1.8.3.1
+
diff --git a/ssm-0.4-ssm-Suppress-backtrace-if-command-failed.patch b/ssm-0.4-ssm-Suppress-backtrace-if-command-failed.patch
new file mode 100644
index 0000000..9938a47
--- /dev/null
+++ b/ssm-0.4-ssm-Suppress-backtrace-if-command-failed.patch
@@ -0,0 +1,39 @@
+From e2c869393f9c1c0f1c84e1a817f411a2056d820e Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner at redhat.com>
+Date: Thu, 16 Jan 2014 14:44:10 +0100
+Subject: [PATCH 08/10] ssm: Suppress backtrace if command failed
+
+Currently when command failed in misc.run(), RuntimeError() exception is
+raised and backtrace is printed to the output. However this is not
+desirable, so use problem.CommandFailed() exception which allows us to
+catch it and print out reasonable error message.
+
+Signed-off-by: Lukas Czerner <lczerner at redhat.com>
+---
+ ssmlib/misc.py | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/ssmlib/misc.py b/ssmlib/misc.py
+index dbfa6b1..3d99c07 100644
+--- a/ssmlib/misc.py
++++ b/ssmlib/misc.py
+@@ -24,6 +24,7 @@ import stat
+ import tempfile
+ import threading
+ import subprocess
++from ssmlib import problem
+ 
+ # List of temporary mount points which should be cleaned up
+ # before exiting
+@@ -480,7 +481,7 @@ def run(cmd, show_cmd=False, stdout=False, stderr=True, can_fail=False,
+             print output
+         if error is not None:
+             print error
+-        raise RuntimeError(err_msg)
++        raise problem.CommandFailed(err_msg)
+ 
+     if not return_stdout:
+         output = None
+-- 
+1.8.3.1
+
diff --git a/ssm-0.4-ssm-big-update-no-1.patch b/ssm-0.4-ssm-big-update-no-1.patch
new file mode 100644
index 0000000..11b98f3
--- /dev/null
+++ b/ssm-0.4-ssm-big-update-no-1.patch
@@ -0,0 +1,3126 @@
+diff --git a/Makefile b/Makefile
+index 629a83f..2d887c4 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,3 +1,6 @@
++PYTHONPATH := $(shell pwd)
++export PYTHONPATH
++
+ all: help
+ 
+ help:
+@@ -53,4 +56,7 @@ source: test clean
+ test:
+ 	@python test.py
+ 
++push_html:
++	scp -r doc/_build/singlehtml/* lczerner at shell.sourceforge.net:/home/project-web/storagemanager/htdocs/
++
+ release: git-clean clean check_vars authors spec log docs source
+diff --git a/README b/README
+index ea3d3c3..71b09e8 100644
+--- a/README
++++ b/README
+@@ -162,6 +162,9 @@ In some cases file system has to be mounted in order to resize. This
+ will be handled by **ssm** automatically by mounting the **volume**
+ temporarily.
+ 
++Note that resizing btrfs subvolume is not supported, only the whole
++file system can be resized.
++
+ 
+ Check command
+ *************
+@@ -256,8 +259,8 @@ volume
+    Volume in btrfs back-end is actually just btrfs subvolume with the
+    exception of the first volume created on btrfs pool creation, which
+    is the file system itself. Subvolumes can only be created on btrfs
+-   file system when the it is mounted, but user does not have to worry
+-   about that, since **ssm** will automatically mount the file system
++   file system when it is mounted, but user does not have to worry
++   about that since **ssm** will automatically mount the file system
+    temporarily in order to create a new subvolume.
+ 
+    Volume name is used as subvolume path in the btrfs file system and
+@@ -270,6 +273,10 @@ volume
+    system is mounted, with the exception of the main btrfs volume -
+    the file system itself.
+ 
++   Also note that btrfs volumes and subvolumes can not be resized.
++   This is mainly limitation of the btrfs tools which currently does
++   not work reliably.
++
+    New btrfs volume can be created with **create** command.
+ 
+ snapshot
+@@ -323,10 +330,40 @@ device
+ Crypt backend
+ *************
+ 
+-Crypt backend in **ssm** is currently limited to only gather the
+-information about encrypted volumes in the system. You can not create
+-or manage encrypted volumes or pools, but it will be extended in the
+-future.
++Crypt backend in **ssm** uses cryptsetup and dm-crypt target to manage
++encrypted volumes. Crypt backend can be used as a regular backend for
++creating encrypted volumes on top of regular block devices, or even
++other volumes (lvm or md volumes for example). Or it can be used to
++create encrypted lvm volumes right away in a single step.
++
++Only volumes can be created with crypt backend. This backend does not
++support pooling and does not require special devices.
++
++pool
++   Crypt backend does not support pooling it is not possible to create
++   crypt pool or add a device into a pool.
++
++volume
++   Volume in crypt backend is the volume created by dm-crypt which
++   represent the data on the original encrypted device in unencrypted
++   form. Crypt backend does not support pooling, so only one device
++   can be used to create crypt volume. It also does not support raid
++   or any device concatenation.
++
++   Currently two modes, or extensions are supported luks and plain.
++   Luks is used by default.For more information about the extensions
++   please see **cryptsetup** manual page.
++
++snapshot
++   Crypt backend does not support snapshotting, however if the
++   encrypted volume is created on top of the lvm volume, the lvm
++   volume itself can be snapshotted. The snapshot can be then opened
++   by using **cryptsetup**. It is possible that this might change in
++   the future so that **ssm** will be able to activate the volume
++   directly without the extra step.
++
++device
++   Crypt backend does not require any special device to be created on.
+ 
+ 
+ Environment variables
+diff --git a/bin/ssm b/bin/ssm
+index fc1ce48..baa3c60 100755
+--- a/bin/ssm
++++ b/bin/ssm
+@@ -32,4 +32,5 @@ try:
+                 sys.exit("\nRoot privileges required to run this script!\n")
+         sys.exit(main.main())
+ except problem.SsmError, err:
++    print str(err)
+     sys.exit(err.errcode)
+diff --git a/doc/_build/man/ssm.8 b/doc/_build/man/ssm.8
+index 16ac1e8..ab777bf 100644
+--- a/doc/_build/man/ssm.8
++++ b/doc/_build/man/ssm.8
+@@ -1,6 +1,6 @@
+ .\" Man page generated from reStructuredText.
+ .
+-.TH "SSM" "8" "August 07, 2013" "0.4" "System Storage Manager"
++.TH "SSM" "8" "October 02, 2013" "0.4" "System Storage Manager"
+ .SH NAME
+ ssm \- System Storage Manager: a single tool to manage your storage
+ .
+@@ -59,9 +59,9 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+ ..
+ .SH SYNOPSIS
+ .sp
+-\fBssm\fP [\fB\-h\fP] [\fB\-\-version\fP] [\fB\-v\fP] [\fB\-f\fP] [\fB\-b\fP BACKEND] {check,resize,create,list,add,remove,snapshot,mount} ...
++\fBssm\fP [\fB\-h\fP] [\fB\-\-version\fP] [\fB\-v\fP] [\fB\-f\fP] [\fB\-b\fP BACKEND] [\fB\-n\fP] {check,resize,create,list,add,remove,snapshot,mount} ...
+ .sp
+-\fBssm\fP \fBcreate\fP [\fB\-h\fP] [\fB\-s\fP SIZE] [\fB\-n\fP NAME] [\fB\-\-fstype\fP FSTYPE] [\fB\-r\fP LEVEL] [\fB\-I\fP STRIPESIZE] [\fB\-i\fP STRIPES] [\fB\-p\fP POOL] [\fBdevice\fP [\fBdevice\fP ...]] [mount]
++\fBssm\fP \fBcreate\fP [\fB\-h\fP] [\fB\-s\fP SIZE] [\fB\-n\fP NAME] [\fB\-\-fstype\fP FSTYPE] [\fB\-r\fP LEVEL] [\fB\-I\fP STRIPESIZE] [\fB\-i\fP STRIPES] [\fB\-p\fP POOL] [\fB\-e\fP [{luks,plain}]] [\fBdevice\fP [\fBdevice\fP ...]] [mount]
+ .sp
+ \fBssm\fP \fBlist\fP [\fB\-h\fP] [{volumes,vol,dev,devices,pool,pools,fs,filesystems,snap,snapshots}]
+ .sp
+@@ -110,7 +110,15 @@ or questions.
+ .TP
+ .BI \-b \ BACKEND\fP,\fB \ \-\-backend \ BACKEND
+ Choose backend to use. Currently you can choose from
+-(lvm,btrfs).
++(lvm,btrfs,crypt).
++.TP
++.B \-n\fP,\fB  \-\-dry\-run
++Dry run. Do not do anything, just parse the command
++line options and gather system information if
++necessary. Note that with this option ssm will not
++perform all the check as some of them are done by the
++backends themselves. This option is mainly used for
++debugging purposes.
+ .UNINDENT
+ .SH SYSTEM STORAGE MANAGER COMMANDS
+ .SS Introduction
+@@ -120,7 +128,7 @@ line as a first argument to the ssm. They all have specific use and its own
+ arguments, but global ssm arguments are propagated to all commands.
+ .SS Create command
+ .sp
+-\fBssm\fP \fBcreate\fP [\fB\-h\fP] [\fB\-s\fP SIZE] [\fB\-n\fP NAME] [\fB\-\-fstype\fP FSTYPE] [\fB\-r\fP LEVEL] [\fB\-I\fP STRIPESIZE] [\fB\-i\fP STRIPES] [\fB\-p\fP POOL] [\fBdevice\fP [\fBdevice\fP ...]] [mount]
++\fBssm\fP \fBcreate\fP [\fB\-h\fP] [\fB\-s\fP SIZE] [\fB\-n\fP NAME] [\fB\-\-fstype\fP FSTYPE] [\fB\-r\fP LEVEL] [\fB\-I\fP STRIPESIZE] [\fB\-i\fP STRIPES] [\fB\-p\fP POOL] [\fB\-e\fP [{luks,plain}]] [\fBdevice\fP [\fBdevice\fP ...]] [mount]
+ .sp
+ This command creates a new volume with defined parameters. If \fBdevice\fP is
+ provided it will be used to create a volume, hence it will be added into the
+@@ -195,6 +203,12 @@ you have to specify RAID level as well.
+ .BI \-p \ POOL\fP,\fB \ \-\-pool \ POOL
+ Pool to use to create the new volume.
+ .UNINDENT
++.INDENT 0.0
++.TP
++.B \-e [{luks,plain}], \-\-encrypt [{luks,plain}]
++Create encrpted volume. Extension to use can be
++specified.
++.UNINDENT
+ .SS List command
+ .sp
+ \fBssm\fP \fBlist\fP [\fB\-h\fP] [{volumes,vol,dev,devices,pool,pools,fs,filesystems,snap,snapshots}]
+@@ -280,6 +294,9 @@ ask you whether you want to remove it from the original pool.
+ .sp
+ In some cases file system has to be mounted in order to resize. This will be
+ handled by \fBssm\fP automatically by mounting the \fBvolume\fP temporarily.
++.sp
++Note that resizing btrfs subvolume is not supported, only the whole file
++system can be resized.
+ .INDENT 0.0
+ .TP
+ .B \-h\fP,\fB  \-\-help
+@@ -435,8 +452,8 @@ devices specified and non existing pool name.
+ Volume in btrfs back\-end is actually just btrfs subvolume with the
+ exception of the first volume created on btrfs pool creation, which is
+ the file system itself. Subvolumes can only be created on btrfs file
+-system when the it is mounted, but user does not have to
+-worry about that, since \fBssm\fP will automatically mount the file
++system when it is mounted, but user does not have to
++worry about that since \fBssm\fP will automatically mount the file
+ system temporarily in order to create a new subvolume.
+ .sp
+ Volume name is used as subvolume path in the btrfs file system and every
+@@ -449,6 +466,10 @@ Btrfs volumes are only shown in the \fIlist\fP output, when the file system is
+ mounted, with the exception of the main btrfs volume \- the file system
+ itself.
+ .sp
++Also note that btrfs volumes and subvolumes can not be resized. This is
++mainly limitation of the btrfs tools which currently does not work
++reliably.
++.sp
+ New btrfs volume can be created with \fBcreate\fP command.
+ .TP
+ .B snapshot
+@@ -498,9 +519,41 @@ Lvm requires \fIphysical device\fP to be created on the device, but with
+ .UNINDENT
+ .SS Crypt backend
+ .sp
+-Crypt backend in \fBssm\fP is currently limited to only gather the information
+-about encrypted volumes in the system. You can not create or manage encrypted
+-volumes or pools, but it will be extended in the future.
++Crypt backend in \fBssm\fP uses cryptsetup and dm\-crypt target to manage
++encrypted volumes. Crypt backend can be used as a regular backend for
++creating encrypted volumes on top of regular block devices, or even other
++volumes (lvm or md volumes for example). Or it can be used to create
++encrypted lvm volumes right away in a single step.
++.sp
++Only volumes can be created with crypt backend. This backend does not
++support pooling and does not require special devices.
++.INDENT 0.0
++.TP
++.B pool
++Crypt backend does not support pooling it is not possible to create
++crypt pool or add a device into a pool.
++.TP
++.B volume
++Volume in crypt backend is the volume created by dm\-crypt which
++represent the data on the original encrypted device in unencrypted form.
++Crypt backend does not support pooling, so only one device can be used
++to create crypt volume. It also does not support raid or any device
++concatenation.
++.sp
++Currently two modes, or extensions are supported luks and plain. Luks
++is used by default.For more information about the extensions please see
++\fBcryptsetup\fP manual page.
++.TP
++.B snapshot
++Crypt backend does not support snapshotting, however if the encrypted
++volume is created on top of the lvm volume, the lvm volume itself can
++be snapshotted. The snapshot can be then opened by using \fBcryptsetup\fP\&.
++It is possible that this might change in the future so that \fBssm\fP will
++be able to activate the volume directly without the extra step.
++.TP
++.B device
++Crypt backend does not require any special device to be created on.
++.UNINDENT
+ .SS MD backend
+ .sp
+ MD backend in \fBssm\fP is currently limited to only gather the information
+diff --git a/ssmlib/backends/btrfs.py b/ssmlib/backends/btrfs.py
+index 04e405c..a4aedda 100644
+--- a/ssmlib/backends/btrfs.py
++++ b/ssmlib/backends/btrfs.py
+@@ -23,6 +23,7 @@ import sys
+ import datetime
+ from ssmlib import misc
+ from ssmlib import problem
++from ssmlib.backends import template
+ 
+ __all__ = ["BtrfsVolume", "BtrfsPool", "BtrfsDev"]
+ 
+@@ -56,12 +57,11 @@ def get_btrfs_version():
+ BTRFS_VERSION = get_btrfs_version()
+ 
+ 
+-class Btrfs(object):
++class Btrfs(template.Backend):
+ 
+-    def __init__(self, options, data=None):
++    def __init__(self, *args, **kwargs):
++        super(Btrfs, self).__init__(*args, **kwargs)
+         self.type = 'btrfs'
+-        self.data = data or {}
+-        self.options = options
+         self.default_pool_name = SSM_BTRFS_DEFAULT_POOL
+         self._vol = {}
+         self._pool = {}
+@@ -69,13 +69,12 @@ class Btrfs(object):
+         self._snap = {}
+         self._subvolumes = {}
+         self._binary = misc.check_binary('btrfs')
+-        self.problem = problem.ProblemSet(options)
+         self.modified_list_version = True
+ 
+         if not self._binary:
+             return
+ 
+-        self.mounts = misc.get_mounts('/dev/')
++        self.mounts = misc.get_mounts('btrfs')
+         command = ['btrfs', 'filesystem', 'show']
+         self.output = misc.run(command, stderr=False)[1]
+ 
+@@ -107,12 +106,12 @@ class Btrfs(object):
+                 pool['uuid'] = vol['uuid'] = uuid
+ 
+                 try:
+-                    fallback = False
+                     vol['real_dev'] = misc.get_device_by_uuid(uuid)
+ 
+                     if vol['real_dev'] in self.mounts:
+                         pool['mount'] = self.mounts[vol['real_dev']]['mp']
+                         vol['mount'] = self.mounts[vol['real_dev']]['mp']
++
+                     else:
+                         for dev_i in self.mounts:
+                             found = re.findall(r'{0}:/.*'.format(vol['real_dev']), dev_i)
+@@ -121,7 +120,6 @@ class Btrfs(object):
+                                 break
+                 except OSError:
+                     # udev is "hard-to-work-with" sometimes so this is fallback
+-                    fallback = True
+                     vol['real_dev'] = ""
+ 
+                 if label != 'none':
+@@ -140,7 +138,7 @@ class Btrfs(object):
+                 dev['pool_name'] = pool_name
+ 
+                 # Fallback in case we could not find real_dev by uuid
+-                if fallback and 'mount' not in pool:
++                if 'mount' not in pool:
+                     if dev['dev_name'] in self.mounts:
+                         pool['mount'] = self.mounts[dev['dev_name']]['mp']
+                         vol['real_dev'] = dev['dev_name']
+@@ -153,6 +151,7 @@ class Btrfs(object):
+                             found = re.findall(r'{0}:/.*'.format(dev['dev_name']), dev_i)
+                             if found:
+                                 pool['mount'] = self.mounts[found[0]]['mp']
++                                vol['real_dev'] = found[0].split(':')[0]
+                                 break
+ 
+                 dev_used = get_real_number(array[5])
+@@ -313,26 +312,18 @@ class Btrfs(object):
+         self._pool[pool['pool_name']] = pool
+         self._vol[vol['dev_name']] = vol
+ 
+-    def __iter__(self):
+-        for item in sorted(self.data.iterkeys()):
+-            yield item
+-
+-    def __getitem__(self, key):
+-        if key in self.data.iterkeys():
+-            return self.data[key]
+-
+     def _remove_filesystem(self, name):
+         if 'mount' in self._vol[name]:
+             if self.problem.check(self.problem.FS_MOUNTED,
+                                   [name, self._vol[name]['mount']]):
+-                misc.do_umount(self._vol[name]['mount'])
++                misc.do_umount(self._vol[name]['real_dev'], all_targets=True)
+         for dev in self._dev.itervalues():
+             if dev['pool_name'] != name:
+                 continue
+             misc.wipefs(dev['dev_name'], 'btrfs')
+ 
+ 
+-class BtrfsVolume(Btrfs):
++class BtrfsVolume(Btrfs, template.BackendVolume):
+ 
+     def __init__(self, *args, **kwargs):
+         super(BtrfsVolume, self).__init__(*args, **kwargs)
+@@ -374,11 +365,18 @@ class BtrfsVolume(Btrfs):
+         else:
+             self._remove_filesystem(vol)
+ 
++    def check(self, vol):
++        vol = self.data[vol]
++        return self.run_btrfs(['check', vol['real_dev']])[0]
++
+     def resize(self, vol, size, resize_fs=True):
+         vol = self.data[vol]
+         if 'mount' not in vol:
+             tmp = misc.temp_mount("UUID={0}".format(vol['uuid']))
+             vol['mount'] = tmp
++        if 'subvolume' in vol and vol['subvolume'] is True:
++            self.problem.check(self.problem.NOT_SUPPORTED,
++                               'Resizing btrfs subvolume')
+         command = ['filesystem', 'resize', str(int(size)) + "K", vol['mount']]
+         self.run_btrfs(command)
+ 
+@@ -402,7 +400,7 @@ class BtrfsVolume(Btrfs):
+         self.run_btrfs(command)
+ 
+ 
+-class BtrfsDev(Btrfs):
++class BtrfsDev(Btrfs, template.BackendDevice):
+ 
+     def __init__(self, *args, **kwargs):
+         super(BtrfsDev, self).__init__(*args, **kwargs)
+@@ -416,7 +414,7 @@ class BtrfsDev(Btrfs):
+                         "achieve by removing {0}".format(devices))
+ 
+ 
+-class BtrfsPool(Btrfs):
++class BtrfsPool(Btrfs, template.BackendPool):
+ 
+     def __init__(self, *args, **kwargs):
+         super(BtrfsPool, self).__init__(*args, **kwargs)
+@@ -425,7 +423,22 @@ class BtrfsPool(Btrfs):
+         else:
+             self.data = self._pool
+ 
+-    def _create_filesystem(self, pool, name, devs, size=None, raid=None):
++    def _can_btrfs_force(self):
++        """
++        This is just ridiculous. Unfortunately btrfs tools usually change
++        behaviour and options without bumping version number. So we have
++        to check whether btrfs allows to 'force' file system creation.
++        """
++        command=['mkfs.btrfs', '-f']
++        output = misc.run(command, can_fail=True)[1]
++        found = re.search('invalid option', output)
++        if found:
++            return False
++        else:
++            return True
++
++    def _create_filesystem(self, pool, name, devs, size=None, options=None):
++        options = options or {}
+         if not devs:
+             raise Exception("To create btrfs volume, some devices must be " +
+                             "provided")
+@@ -434,12 +447,12 @@ class BtrfsPool(Btrfs):
+             self.problem.check(self.problem.TOOL_MISSING, 'mkfs.btrfs')
+         command = ['mkfs.btrfs', '-L', name]
+ 
+-        if raid:
+-            if raid['level'] == '0':
++        if 'raid' in options:
++            if options['raid'] == '0':
+                 command.extend(['-m', 'raid0', '-d', 'raid0'])
+-            elif raid['level'] == '1':
++            elif options['raid'] == '1':
+                 command.extend(['-m', 'raid1', '-d', 'raid1'])
+-            elif raid['level'] == '10':
++            elif options['raid'] == '10':
+                 command.extend(['-m', 'raid10', '-d', 'raid10'])
+             else:
+                 raise Exception("Btrfs backed currently does not support " +
+@@ -455,7 +468,8 @@ class BtrfsPool(Btrfs):
+         # have tried to remove the device from the respective pool already.
+         # So at this point there should not be any useful signatures to
+         # speak of. However as I mentioned btrfs is broken, so force it.
+-        command.extend(['-f'])
++        if self._can_btrfs_force():
++            command.extend(['-f'])
+         command.extend(devs)
+         misc.run(command, stdout=True)
+         misc.send_udev_event(devs[0], "change")
+@@ -507,10 +521,11 @@ class BtrfsPool(Btrfs):
+         self._remove_filesystem(pool)
+ 
+     def create(self, pool, size=None, name=None, devs=None,
+-               raid=None):
++               options=None):
++        options = options or {}
+         if pool in self._pool:
+             vol = None
+-            if size or raid:
++            if size or 'raid' in options:
+                 self.problem.warn("Only name, volume name and pool name " +
+                                   "can be specified when creating btrfs " +
+                                   "subvolume, the rest will be ignored")
+@@ -535,7 +550,7 @@ class BtrfsPool(Btrfs):
+             if name:
+                 self.problem.warn("Creating new pool. Argument (--name " +
+                                   "{0}) will be ignored!".format(name))
+-            vol = self._create_filesystem(pool, pool, devs, size, raid)
++            vol = self._create_filesystem(pool, pool, devs, size, options)
+         return vol
+ 
+ 
+diff --git a/ssmlib/backends/crypt.py b/ssmlib/backends/crypt.py
+index 3c44f58..4aad266 100644
+--- a/ssmlib/backends/crypt.py
++++ b/ssmlib/backends/crypt.py
+@@ -19,36 +19,147 @@
+ 
+ import re
+ import os
++import stat
+ from ssmlib import misc
+ from ssmlib import problem
++from ssmlib.backends import template
+ 
+ __all__ = ["DmCryptVolume"]
+ 
++SUPPORTED_CRYPT = ['luks', 'plain']
++CRYPT_SIGNATURES = ['crypto_LUKS']
++CRYPT_DEFAULT_EXTENSION = "luks"
++
+ try:
+     SSM_CRYPT_DEFAULT_POOL = os.environ['SSM_CRYPT_DEFAULT_POOL']
+ except KeyError:
+     SSM_CRYPT_DEFAULT_POOL = "crypt_pool"
+ 
+ try:
+-    DM_DEV_DIR = os.environ['DM_DEV_DIR']
++    SSM_CRYPT_DEFAULT_VOL_PREFIX = os.environ['SSM_CRYPT_DEFAULT_VOL_PREFIX']
+ except KeyError:
+-    DM_DEV_DIR = "/dev"
+-
+-
+-class DmCryptVolume(object):
+-
+-    def __init__(self, options, data=None):
++    SSM_CRYPT_DEFAULT_VOL_PREFIX = "encrypted"
++
++# cryptsetup against my expectations does not take into account
++# DM_DEV_DIR so set it to /dev pernamently for now.
++#try:
++#    DM_DEV_DIR = os.environ['DM_DEV_DIR']
++#except KeyError:
++#    DM_DEV_DIR = "/dev"
++DM_DEV_DIR = "/dev"
++MAX_DEVS = 999
++
++def get_cryptsetup_version():
++    try:
++        output = misc.run(['cryptsetup', '--version'], can_fail=True)[1]
++        version = map(int, output.strip().split()[-1].split('.', 3))
++    except (OSError, AttributeError):
++        version = [0, 0, 0]
++    return version
++
++CRYPTSETUP_VERSION = get_cryptsetup_version()
++
++class DmObject(template.Backend):
++    def __init__(self, *args, **kwargs):
++        super(DmObject, self).__init__(*args, **kwargs)
+         self.type = 'crypt'
+-        self.data = data or {}
+-        self.output = None
+-        self.options = options
+         self.mounts = misc.get_mounts('{0}/mapper'.format(DM_DEV_DIR))
+         self.default_pool_name = SSM_CRYPT_DEFAULT_POOL
+-        self.problem = problem.ProblemSet(options)
+ 
+         if not misc.check_binary('dmsetup') or \
+            not misc.check_binary('cryptsetup'):
+             return
++
++    def run_cryptsetup(self, command, stdout=True):
++        if not misc.check_binary('cryptsetup'):
++            self.problem.check(self.problem.TOOL_MISSING, 'cryptsetup')
++        command.insert(0, "cryptsetup")
++        return misc.run(command, stdout=stdout)
++
++
++class DmCryptPool(DmObject, template.BackendPool):
++    def __init__(self, *args, **kwargs):
++        super(DmCryptPool, self).__init__(*args, **kwargs)
++        '''
++        pool = {'pool_name': self.default_pool_name,
++                'type': 'crypt',
++                'dev_count': '0',
++                'pool_free': '0',
++                'pool_used': '0',
++                'pool_size': '0',
++                'hide': True}
++        self.data[self.default_pool_name] = pool
++        '''
++
++
++    def create(self, pool, size=None, name=None, devs=None,
++               options=None):
++
++        if CRYPTSETUP_VERSION < [1, 6, 0]:
++            msg = "You need at least cryptsetup version " + \
++                  "{0}. Creating encrypted volumes".format('1.6.0')
++            self.problem.check(self.problem.NOT_SUPPORTED, msg)
++        options = options or {}
++        if 'encrypt' in options:
++            if options['encrypt'] is True:
++                options['encrypt'] = CRYPT_DEFAULT_EXTENSION
++            if options['encrypt'] not in SUPPORTED_CRYPT:
++                self.problem.not_supported("Extension "
++                                           "\'{0}\'".format(options['encrypt']))
++        else:
++            # So the options is not crypt specific. It's ok, just use defaults
++            options['encrypt'] = CRYPT_DEFAULT_EXTENSION
++
++        if len(devs) > 1:
++            self.problem.not_supported("Device concatenation" +
++                                       " with \"crypt\" backend")
++        if not name:
++            name = self._generate_devname()
++        device = devs[0]
++        args = []
++        command = []
++        if self.options.verbose:
++            args.append('-v')
++        else:
++            args.append('-q')
++        if options['encrypt'] == "luks":
++            command.extend(args)
++            if self.options.force:
++                command.append('--force-password')
++            if self.options.interactive:
++                command.append('-y')
++            command.extend(['luksFormat', device])
++            self.run_cryptsetup(command)
++        command = []
++        command.extend(args)
++        command.append('open')
++        if size:
++            # Size is in KiB but cryptsetup accepts it in 512 byte blocks
++            size = str(float(size) * 2).split('.')[0]
++            command.extend(['--size', size])
++        command.extend(['--type', options['encrypt'], device, name])
++        self.run_cryptsetup(command)
++        return "{0}/mapper/{1}".format(DM_DEV_DIR, name)
++
++    def _generate_devname(self):
++        for i in range(1, MAX_DEVS):
++            name = "{0}{1:0>{align}}".format(SSM_CRYPT_DEFAULT_VOL_PREFIX, i,
++                                            align=len(str(MAX_DEVS)))
++            path = "{0}/mapper/{1}".format(DM_DEV_DIR, name)
++            try:
++                if stat.S_ISBLK(os.stat(path).st_mode):
++                    continue
++            except OSError:
++                pass
++            return name
++        self.problem.error("Can not find proper device name. Specify one!")
++
++
++class DmCryptVolume(DmObject, template.BackendVolume):
++
++    def __init__(self, *args, **kwargs):
++        super(DmCryptVolume, self).__init__(*args, **kwargs)
++
+         command = ['dmsetup', 'table']
+         self.output = misc.run(command, stderr=False)[1]
+         for line in self.output.split("\n"):
+@@ -63,9 +174,9 @@ class DmCryptVolume(object):
+             devname = re.sub(":$", "",
+                              "{0}/mapper/{1}".format(DM_DEV_DIR, array[0]))
+             dm['dm_name'] = devname
+-            dm['pool_name'] = 'dm-crypt'
+-            dm['dev_name'] = misc.get_real_device(devname)
+-            dm['real_dev'] = dm['dev_name']
++            dm['pool_name'] = self.default_pool_name
++            dm['dev_name'] = devname
++            dm['real_dev'] = misc.get_real_device(devname)
+             if dm['real_dev'] in self.mounts:
+                 dm['mount'] = self.mounts[dm['real_dev']]['mp']
+ 
+@@ -78,12 +189,6 @@ class DmCryptVolume(object):
+             self._parse_cryptsetup(command, dm)
+             self.data[dm['dev_name']] = dm
+ 
+-    def run_cryptsetup(self, command, stdout=True):
+-        if not self._binary:
+-            self.problem.check(self.problem.TOOL_MISSING, 'cryptsetup')
+-        command.insert(0, "cryptsetup")
+-        return misc.run(command, stdout=stdout)
+-
+     def _parse_cryptsetup(self, cmd, dm):
+         self.output = misc.run(cmd, stderr=False)[1]
+         for line in self.output.split("\n"):
+@@ -97,19 +202,52 @@ class DmCryptVolume(object):
+             elif array[0].strip() == 'device:':
+                 dm['crypt_device'] = array[1]
+ 
++    def __getitem__(self, name):
++        if name in self.data.iterkeys():
++            return self.data[name]
++        device = name
++        if not os.path.exists(name):
++            device = DM_DEV_DIR + "/" + name
++            if not os.path.exists(device):
++                return None
++        device = misc.get_real_device(device)
++        if device in self.data.iterkeys():
++            return self.data[device]
++        return None
++
+     def remove(self, dm):
++        vol = self[dm]
++        if 'mount' in vol:
++            if self.problem.check(self.problem.FS_MOUNTED,
++                                  [vol['dev_name'], vol['mount']]):
++                misc.do_umount(vol['mount'])
+         command = ['remove', dm]
+         self.run_cryptsetup(command)
++        misc.wipefs(vol['crypt_device'], CRYPT_SIGNATURES)
+ 
+     def resize(self, dm, size, resize_fs=True):
+         size = str(int(size) * 2)
+         command = ['resize', '--size', size, dm]
+         self.run_cryptsetup(command)
+ 
+-    def __iter__(self):
+-        for item in sorted(self.data.iterkeys()):
+-            yield item
+ 
+-    def __getitem__(self, key):
+-        if key in self.data.iterkeys():
+-            return self.data[key]
++class DmCryptDevice(DmObject, template.BackendDevice):
++
++    def __init__(self, *args, **kwargs):
++        super(DmCryptDevice, self).__init__(*args, **kwargs)
++
++        for line in misc.get_partitions():
++            device = {}
++            devname = "/dev/" + line[3]
++            signature = misc.get_signature(devname)
++            if misc.get_signature(devname) in CRYPT_SIGNATURES:
++                device['hide'] = False
++                device['dev_name'] = devname
++                device['pool_name'] = self.default_pool_name
++                device['dev_free'] = '0'
++                device['dev_used'] = str(misc.get_device_size(devname))
++                self.data[devname] = device
++
++
++    def remove(self, devices):
++        misc.wipefs(device, CRYPT_SIGNATURES)
+diff --git a/ssmlib/backends/lvm.py b/ssmlib/backends/lvm.py
+index 9cc8079..955c705 100644
+--- a/ssmlib/backends/lvm.py
++++ b/ssmlib/backends/lvm.py
+@@ -17,11 +17,13 @@
+ 
+ # lvm module for System Storage Manager
+ 
++import re
+ import os
+ import stat
+ import datetime
+ from ssmlib import misc
+ from ssmlib import problem
++from ssmlib.backends import template
+ 
+ __all__ = ["PvsInfo", "VgsInfo", "LvsInfo"]
+ 
+@@ -37,17 +39,32 @@ except KeyError:
+ MAX_LVS = 999
+ 
+ 
+-class LvmInfo(object):
++def get_lvm_version():
++    try:
++        output = misc.run(['lvm', 'version'], can_fail=True)[1]
++        output = output.strip().split("\n")
++        pattern = re.compile("LVM version:")
++        for line in output:
++            if pattern.match(line.strip()):
++                match = " ".join(line.split())
++                tmp = re.search('(?<=LVM version: )\d+\.\d+\.\d+',
++                                    match).group(0)
++                version = map(int, tmp.split(".", 3))
++    except (OSError, AttributeError):
++        version = [0, 0, 0]
++    return version
+ 
+-    def __init__(self, options, data=None):
++LVM_VERSION = get_lvm_version()
++
++
++class LvmInfo(template.Backend):
++
++    def __init__(self, *args, **kwargs):
++        super(LvmInfo, self).__init__(*args, **kwargs)
+         self.type = 'lvm'
+-        self.data = data or {}
+         self.attrs = []
+-        self.output = None
+-        self.options = options
+         self.binary = misc.check_binary('lvm')
+         self.default_pool_name = SSM_LVM_DEFAULT_POOL
+-        self.problem = problem.ProblemSet(options)
+ 
+     def run_lvm(self, command, noforce=False):
+         if not self.binary:
+@@ -59,9 +76,6 @@ class LvmInfo(object):
+         command.insert(0, "lvm")
+         misc.run(command, stdout=True)
+ 
+-    def __str__(self):
+-        return self.output
+-
+     def _data_index(self, row):
+         return row.values()[len(row.values()) - 1]
+ 
+@@ -86,16 +100,16 @@ class LvmInfo(object):
+     def _fill_aditional_info(self, row):
+         pass
+ 
+-    def __iter__(self):
+-        for item in sorted(self.data.iterkeys()):
+-            yield item
++    def supported_since(self, version, string):
++        if version > LVM_VERSION:
++            msg = "ERROR: You need at least lvm version " + \
++                  "{0}. Feature \"{1}\"".format(".".join(map(str, version)),
++                                                string)
++            self.problem.check(self.problem.NOT_SUPPORTED, msg)
++        return True
+ 
+-    def __getitem__(self, key):
+-        if key in self.data.iterkeys():
+-            return self.data[key]
+ 
+-
+-class VgsInfo(LvmInfo):
++class VgsInfo(LvmInfo, template.BackendPool):
+ 
+     def __init__(self, *args, **kwargs):
+         super(VgsInfo, self).__init__(*args, **kwargs)
+@@ -149,40 +163,85 @@ class VgsInfo(LvmInfo):
+         self.run_lvm(command)
+ 
+     def create(self, vg, size=None, name=None, devs=None,
+-               raid=None):
++               options=None):
++        options = options or {}
+         devices = devs or []
+         command = ['lvcreate', vg]
+-        if size:
+-            command.extend(['-L', size + 'K'])
+-        else:
+-            if len(devices) > 0:
+-                size = "100%PVS"
+-            else:
+-                size = "100%FREE"
+-            command.extend(['-l', size])
+ 
+         if name:
+             lvname = name
+         else:
+             lvname = self._generate_lvname(vg)
+ 
++        if size:
++            command.extend(['-L', size + 'K'])
++        else:
++            if len(devices) > 0:
++                tmp = "100%PVS"
++            else:
++                tmp = "100%FREE"
++            command.extend(['-l', tmp])
++
+         command.extend(['-n', lvname.rpartition("/")[-1]])
+ 
+-        if raid:
+-            if raid['level'] == '0':
+-                if not raid['stripesize']:
+-                    raid['stripesize'] = "64"
+-                if not raid['stripes'] and len(devices) > 0:
+-                    raid['stripes'] = str(len(devices))
+-                if not raid['stripes']:
++        if 'raid' in options:
++            if options['raid'] == '0':
++                if not options['stripesize']:
++                    options['stripesize'] = "64"
++                if not options['stripes'] and len(devices) > 0:
++                    options['stripes'] = str(len(devices))
++                if not options['stripes']:
+                     self.problem.error("Devices or number of " +
+                                        "stripes should be defined!")
+-                if raid['stripesize']:
+-                    command.extend(['-I', raid['stripesize']])
+-                if raid['stripes']:
+-                    command.extend(['-i', raid['stripes']])
++                if options['stripesize']:
++                    command.extend(['-I', options['stripesize']])
++                if options['stripes']:
++                    command.extend(['-i', options['stripes']])
++            elif options['raid'] == '1' and \
++                 self.supported_since([2,2,89],"raid1"):
++                if options['stripesize'] or options['stripes']:
++                    msg = "ERROR: Specifying stripe size or number of " + \
++                          "stripes when creating raid1 volume with lvm backend"
++                    self.problem.check(self.problem.NOT_SUPPORTED, msg)
++                # Unfortunately 50%PVS does not work here because it does not
++                # take in account metadata needed to create mirrored volume.
++                # Using 49%PVS is not viable either because it will cut off
++                # a lot of potential storage. So we'll require to specify
++                # size in this case.
++                if not size:
++                    msg = "ERROR: Creating raid1 with lvm backend without " + \
++                          "specifying size"
++                    self.problem.check(self.problem.NOT_SUPPORTED, msg)
++                command.extend(["--type", "raid1"])
++            elif options['raid'] == '10' and \
++                 self.supported_since([2,2,98],"raid10"):
++                if not options['stripesize']:
++                    options['stripesize'] = "64"
++                if not options['stripes'] and len(devices) > 0:
++                    if len(devices) < 4:
++                        self.problem.error("Number of devices should be at " +
++                                           "least 4 in raid 10 setup")
++                    if len(devices) % 2 != 0:
++                        self.problem.error("Number of devices should be " +
++                                           "even in raid 10 setup")
++                    options['stripes'] = str(len(devices)/2)
++                if not options['stripes']:
++                    self.problem.error("Devices or number of " +
++                                       "stripes should be defined")
++                if int(options['stripes']) < 2:
++                    self.problem.error("Number of stripes should be at " +
++                                       "least 2 in raid 10 setup")
++                if options['stripesize']:
++                    command.extend(['-I', options['stripesize']])
++                if options['stripes']:
++                    command.extend(['-i', options['stripes']])
++                if not size:
++                    msg = "ERROR: Creating raid10 with lvm backend without " + \
++                          "specifying size"
++                    self.problem.check(self.problem.NOT_SUPPORTED, msg)
++                command.extend(["--type", "raid10"])
+             else:
+-                self.problem.not_supported("RAID level {0}".format(raid['level']) +
++                self.problem.not_supported("RAID level {0}".format(options['raid']) +
+                                            " with \"lvm\" backend")
+ 
+         command.extend(devices)
+@@ -190,7 +249,7 @@ class VgsInfo(LvmInfo):
+         return "{0}/{1}/{2}".format(DM_DEV_DIR, vg, lvname)
+ 
+ 
+-class PvsInfo(LvmInfo):
++class PvsInfo(LvmInfo, template.BackendDevice):
+ 
+     def __init__(self, *args, **kwargs):
+         super(PvsInfo, self).__init__(*args, **kwargs)
+@@ -221,7 +280,7 @@ class PvsInfo(LvmInfo):
+         self.run_lvm(command)
+ 
+ 
+-class LvsInfo(LvmInfo):
++class LvsInfo(LvmInfo, template.BackendVolume):
+ 
+     def __init__(self, *args, **kwargs):
+         super(LvsInfo, self).__init__(*args, **kwargs)
+diff --git a/ssmlib/backends/md.py b/ssmlib/backends/md.py
+index 9e902d7..f33243c 100644
+--- a/ssmlib/backends/md.py
++++ b/ssmlib/backends/md.py
+@@ -23,6 +23,7 @@ import socket
+ import datetime
+ from ssmlib import misc
+ from ssmlib import problem
++from ssmlib.backends import template
+ 
+ try:
+     SSM_DM_DEFAULT_POOL = os.environ['SSM_DM_DEFAULT_POOL']
+@@ -32,15 +33,14 @@ except KeyError:
+ MDADM = "mdadm"
+ 
+ 
+-class MdRaid(object):
++class MdRaid(template.Backend):
+ 
+-    def __init__(self, options, data=None):
++    def __init__(self, *args, **kwargs):
++        super(MdRaid, self).__init__(*args, **kwargs)
+         self.type = 'dm'
+-        self.data = data or {}
+         self._vol = {}
+         self._pool = {}
+         self._dev = {}
+-        self.options = options
+         self.hostname = socket.gethostname()
+         self._binary = misc.check_binary(MDADM)
+         self.default_pool_name = SSM_DM_DEFAULT_POOL
+@@ -50,7 +50,6 @@ class MdRaid(object):
+         if not self._binary:
+             return
+ 
+-        self.problem = problem.ProblemSet(options)
+         self.mounts = misc.get_mounts('/dev/md')
+ 
+         mdnumber = misc.get_dmnumber("md")
+@@ -109,16 +108,8 @@ class MdRaid(object):
+         command.insert(0, MDADM)
+         return misc.run(command, stdout=True)
+ 
+-    def __iter__(self):
+-        for item in sorted(self.data.iterkeys()):
+-            yield item
+-
+-    def __getitem__(self, key):
+-        if key in self.data.iterkeys():
+-            return self.data[key]
+-
+ 
+-class MdRaidVolume(MdRaid):
++class MdRaidVolume(MdRaid, template.BackendVolume):
+ 
+     def __init__(self, *args, **kwargs):
+         super(MdRaidVolume, self).__init__(*args, **kwargs)
+@@ -135,7 +126,7 @@ class MdRaidVolume(MdRaid):
+         self.problem.not_supported("Resizing with \"md\" backend")
+ 
+ 
+-class MdRaidDevice(MdRaid):
++class MdRaidDevice(MdRaid, template.BackendDevice):
+ 
+     def __init__(self, *args, **kwargs):
+         super(MdRaidDevice, self).__init__(*args, **kwargs)
+diff --git a/ssmlib/backends/template.py b/ssmlib/backends/template.py
+new file mode 100644
+index 0000000..94f4b40
+--- /dev/null
++++ b/ssmlib/backends/template.py
+@@ -0,0 +1,95 @@
++#!/usr/bin/env python
++#
++# (C)2013 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
++#
++# This program is free software: you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation, either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++# template module for System Storage Manager contains template classes
++# to use when creating new backend
++
++import os
++from ssmlib import misc
++from ssmlib import problem
++
++__all__ = ["Backend", "BackendPool", "BackendVolume", "BackendDevice"]
++
++try:
++    SSM_TEMPLATE_DEFAULT_POOL = os.environ['SSM_TEMPLATE_DEFAULT_POOL']
++except KeyError:
++    SSM_TEMPLATE_DEFAULT_POOL = "template_pool"
++
++
++class Backend(object):
++    def __init__(self, options, data=None):
++        self.type = 'template'
++        self.data = data or {}
++        self.options = options
++        self.output = None
++        self.default_pool_name = SSM_TEMPLATE_DEFAULT_POOL
++        self.problem = problem.ProblemSet(options)
++
++    def __str__(self):
++        return repr(self.data)
++
++    def __iter__(self):
++        for item in sorted(self.data.iterkeys()):
++            yield item
++
++    def __getitem__(self, key):
++        if key in self.data.iterkeys():
++            return self.data[key]
++
++
++class BackendPool(Backend):
++    def __init__(self, *args, **kwargs):
++        super(BackendPool, self).__init__(*args, **kwargs)
++
++    def reduce(self, pool, device):
++        self.problem.check(self.problem.NOT_SUPPORTED,
++                        "Reducing pool with {0} backend".format(self.type))
++
++    def new(self, pool, devices):
++        self.problem.check(self.problem.NOT_SUPPORTED,
++                        "Creating new pool with {0} backend".format(self.type))
++
++    def extend(self, pool, devices):
++        self.problem.check(self.problem.NOT_SUPPORTED,
++                        "Extending pool with {0} backend".format(self.type))
++
++    def remove(self, pool):
++        self.problem.check(self.problem.NOT_SUPPORTED,
++                        "Removing pool with {0} backend".format(self.type))
++
++    def create(self, pool, size=None, name=None, devs=None,
++               options=None):
++        self.problem.check(self.problem.NOT_IMPLEMENTED,
++                        "Creating volume with {0} backend".format(self.type))
++
++
++class BackendVolume(Backend):
++    def __init__(self, *args, **kwargs):
++        super(BackendVolume, self).__init__(*args, **kwargs)
++
++    def remove(self, volume):
++        self.problem.check(self.problem.NOT_SUPPORTED,
++                        "Removing volume with {0} backend".format(self.type))
++
++
++class BackendDevice(Backend):
++    def __init__(self, *args, **kwargs):
++        super(BackendDevice, self).__init__(*args, **kwargs)
++
++    def remove(self, devices):
++        self.problem.check(self.problem.NOT_SUPPORTED,
++                        "Removing device with {0} backend".format(self.type))
+diff --git a/ssmlib/main.py b/ssmlib/main.py
+index ef9232d..7aab312 100644
+--- a/ssmlib/main.py
++++ b/ssmlib/main.py
+@@ -30,7 +30,7 @@ from ssmlib.backends import lvm, crypt, btrfs, md
+ 
+ EXTN = ['ext2', 'ext3', 'ext4']
+ SUPPORTED_FS = ['xfs', 'btrfs'] + EXTN
+-SUPPORTED_BACKENDS = ['lvm', 'btrfs']
++SUPPORTED_BACKENDS = ['lvm', 'btrfs', 'crypt']
+ SUPPORTED_RAID = ['0', '1', '10']
+ os.environ['LC_NUMERIC'] = "C"
+ 
+@@ -222,7 +222,7 @@ class FsInfo(object):
+             raise Exception("File system on {0} is not ".format(self.device) +
+                             "clean, I will not attempt to resize it. Please," +
+                             "fix the problem first.")
+-        misc.run(command, stdout=True)
++        return misc.run(command, stdout=True)[0]
+ 
+     def xfs_get_info(self, dev):
+         command = ["xfs_db", "-r", "-c", "sb", "-c", "print", dev]
+@@ -341,6 +341,11 @@ class DeviceInfo(object):
+                 dev['mount'] = "PARTITIONED"
+                 dev['type'] = 'disk'
+ 
++    def remove(self, device):
++        PR.error("It is not clear what do you want " +
++                 "to achieve by removing " +
++                 "{0}!".format(device))
++
+     def set_globals(self, options):
+         self.options = options
+ 
+@@ -410,6 +415,9 @@ class Item(object):
+         else:
+             name = self.data['dev_name']
+         fs = FsInfo(name, self.obj.options)
++        if 'fs_type' not in fs.data:
++            # Not a file system
++            return
+         try:
+             fs.mounted = self.data['mount']
+         except KeyError:
+@@ -639,6 +647,11 @@ class Pool(Storage):
+         except RuntimeError, err:
+             PR.warn(err)
+             PR.warn("Can not get information about btrfs pools")
++        try:
++            self._data['crypt'] = crypt.DmCryptPool(options=self.options)
++        except RuntimeError, err:
++            PR.warn(err)
++            PR.warn("Can not get information about crypt pools")
+ 
+         backend = self.get_backend(SSM_DEFAULT_BACKEND)
+         self.default = Item(backend, backend.default_pool_name)
+@@ -682,10 +695,18 @@ class Devices(Storage):
+             PR.warn("Can not get information about MD devices")
+             my_md = Struct()
+             my_md.data = {}
++        try:
++            my_crypt = crypt.DmCryptDevice(options=self.options)
++        except RuntimeError, err:
++            PR.warn(err)
++            PR.warn("Can not get information about crypt devices")
++            my_crypt = Struct()
++            my_crypt.data = {}
+ 
+         self._data['dev'] = DeviceInfo(data=dict(my_lvm.data.items() +
+                                                  my_btrfs.data.items() +
+-                                                 my_md.data.items()),
++                                                 my_md.data.items() +
++                                                 my_crypt.data.items()),
+                                        options=self.options)
+         self.header = ['Device', 'Free', 'Used',
+                        'Total', 'Pool', 'Mount point']
+@@ -862,30 +883,41 @@ class StorageHandle(object):
+     def check(self, args):
+         """
+         Check the file system on the volume. FsInfo is used for that purpose,
+-        except for btrfs.
++        except for btrfs. Or check the volume itself if backend supports it.
+         """
+         err = 0
+         checked = 0
+-        for fs in args.device:
+-            print "Checking {0} file system on \'{1}\':".format(fs.fstype,
+-                                                                fs.device),
+-            if fs.mounted:
+-                print
++        for dev in args.device:
++            if 'mount' in dev:
+                 try:
+-                    if PR.check(PR.FS_MOUNTED, [fs.device, fs.mounted]):
+-                        misc.do_umount(fs.device)
++                    if PR.check(PR.FS_MOUNTED, [dev['real_dev'], dev['mount']]):
++                        misc.do_umount(dev['real_dev'])
+                 except problem.FsMounted:
+                     PR.warn("Unable to check file system " +
+-                            "\'{0}\' on volume \'{1}\'".format(fs.fstype,
+-                                                               fs.device))
++                            "\'{0}\' on volume \'{1}\'".format(dev['fs_type'],
++                                                               dev['real_dev']))
+                     continue
+-            ret = fs.fsck()
+-            checked += 1
+-            err += ret
+-            if ret:
+-                print "FAIL"
+-            else:
+-                print "OK"
++
++            # Does backend support check ?
++            try:
++                if getattr(dev, "check"):
++                    print "Checking volume \'{0}\'.".format(dev['real_dev'])
++                    ret = dev.check()
++                    checked += 1
++                    err += ret
++                    if ret:
++                        continue
++            except AttributeError:
++                pass
++
++            # Do we have a file system to check ?
++            if 'fs_info' in dev:
++                fs = dev['fs_info']
++                print "Checking {0} file system on \'{1}\'.".format(fs.fstype,
++                                                                    fs.device)
++                ret = fs.fsck()
++                checked += 1
++                err += ret
+         if checked == 0:
+             PR.error("Nothing was checked")
+         if err > 0:
+@@ -944,6 +976,14 @@ class StorageHandle(object):
+             if not self.dev[dev] or 'pool_name' not in self.dev[dev]:
+                 # Check signature of existing file system on the device
+                 # and ask user whether to use it or not.
++                if self.dev[dev] and 'mount' in self.dev[dev]:
++                    try:
++                        if PR.check(PR.FS_MOUNTED,
++                                    [dev, self.dev[dev]['mount']]):
++                            misc.do_umount(dev)
++                    except problem.FsMounted:
++                        args.device.remove(dev)
++                        continue
+                 signature = misc.get_fs_type(dev)
+                 if signature and \
+                    not PR.check(PR.EXISTING_FILESYSTEM, [signature, dev]):
+@@ -977,6 +1017,10 @@ class StorageHandle(object):
+         args.pool = self.pool[args.volume['pool_name']]
+         vol_size = float(args.volume['vol_size'])
+ 
++        if args.pool.type == 'btrfs':
++            msg = "Resizing btrfs volume is not supported"
++            raise problem.NotSupported(msg)
++
+         if not args.size:
+             new_size = vol_size
+         elif args.size[0] == '+':
+@@ -987,7 +1031,7 @@ class StorageHandle(object):
+             new_size = float(args.size)
+         size_change = new_size - vol_size
+ 
+-        fs = True if 'fs_type' in args.volume else False
++        fs = True if 'fs_info' in args.volume else False
+ 
+         if new_size <= 0:
+             PR.error("New volume size \'{0} KB\' is too small".format(new_size))
+@@ -996,28 +1040,39 @@ class StorageHandle(object):
+             # Try to grow the file system, since there is nothing to
+             # do with the volume itself.
+             if fs:
+-                args.volume['fs_info'].resize()
++                ret = args.volume['fs_info'].resize()
++                if ret:
++                    PR.error("File system on {0} can not be resized".format(args.volume.name))
+             else:
+                 PR.check(PR.RESIZE_ALREADY_MATCH, [args.volume.name, new_size])
+             return
+ 
+         # Backend might not support pooling
+         if args.pool is None:
+-            pool_free = None
++            pool_free = 0.0
+             pool_name = "none"
+         else:
+             pool_free = float(args.pool['pool_free'])
+             pool_name = args.pool.name
+ 
+-        have_size, devices = self._filter_device_list(args,
+-                                                      pool_free,
+-                                                      new_size)
++        # No need to do anything with provided devices since
++        # we do have enough space to cover the resize
++        if (pool_free < size_change):
++            have_size, devices = self._filter_device_list(args,
++                                                          pool_free,
++                                                          new_size)
++        else:
++            have_size = pool_free
+ 
+         if have_size < size_change:
+             PR.check(PR.RESIZE_NOT_ENOUGH_SPACE,
+                      [pool_name, args.volume.name, new_size])
+-        elif len(args.device) > 0 and new_size > vol_size:
+-            self.add(args, True)
++        elif len(args.device) > 0 and size_change > pool_free:
++            try:
++                self.add(args, True)
++            except problem.NotSupported:
++                # Some backends might not support pooling at all.
++                pass
+ 
+         if new_size != vol_size:
+             args.volume.resize(new_size, fs)
+@@ -1028,9 +1083,30 @@ class StorageHandle(object):
+         provided as arguments. If the device is not in the selected pool, then
+         add() is called on the pool prior to create().
+         """
++
++        lvname = self.create_volume(args)
++
++        if args.encrypt and misc.is_bdevice(lvname) and \
++           SSM_DEFAULT_BACKEND != 'crypt':
++            crypt = self.pool.get_backend("crypt")
++            args.pool = Item(crypt, crypt.default_pool_name)
++            options = {'encrypt': args.encrypt}
++            lvname = args.pool.create(devs=[lvname],
++                                      size=None,
++                                      options=options,
++                                      name=args.name)
++
++        if args.fstype and args.pool.type != 'btrfs':
++            if self._create_fs(args.fstype, lvname) != 0:
++                self._mpoint = None
++        if self._mpoint:
++            self.reinit_vol()
++            self._do_mount(self.vol[lvname])
++
++    def create_volume(self, args):
+         # Get the size in kilobytes
+-        if args.size:
+-            args.size = misc.get_real_size(args.size)
++#        if args.size:
++#            args.size = misc.get_real_size(args.size)
+ 
+         if self._mpoint and not (args.fstype or args.pool.type == 'btrfs'):
+             if PR.check(PR.CREATE_MOUNT_NOFS, self._mpoint):
+@@ -1049,6 +1125,12 @@ class StorageHandle(object):
+         have_size, devices = self._filter_device_list(args, pool_free,
+                                                       args.size)
+ 
++        # When the pool does not exist and there is no device usable
++        # for creating the new pool, then there is no point of trying to
++        # create a volume, since it would fail in the backend anyway.
++        if not args.pool.exists() and len(devices) == 0:
++            PR.check(PR.NO_DEVICES, args.pool.name)
++
+         # Currently we do not allow setting subvolume size with btrfs. This
+         # should change in the future (quotas maybe) so the check should
+         # be removed or pushed to the backend itself.
+@@ -1058,12 +1140,6 @@ class StorageHandle(object):
+                         [have_size, args.pool.name]):
+                 args.size = None
+ 
+-        # When the pool does not exist and there is no device usable
+-        # for creating the new pool, then there is no point of trying to
+-        # create a volume, since it would fail in the backend anyway.
+-        if not args.pool.exists() and len(devices) == 0:
+-            PR.check(PR.NO_DEVICES, args.pool.name)
+-
+         if have_size == 0:
+             PR.error("Not enough space ({0} KB) to".format(have_size) +
+                      "to create volume")
+@@ -1080,32 +1156,52 @@ class StorageHandle(object):
+                          "must not exceed number of devices " +
+                          "({0})".format(tmp))
+ 
++        if args.raid:
++            # In raid we might has a requirement on a number of devices
++            # available as well as different requirements on the size
++            # available. We do not do any complicated math to figure out
++            # whether we really do have enough space on the devices which
++            # might differ in size. Let the respective backend tool deal
++            # with that, it's always ok to fail, but we might cover the
++            # most obvious cases here.
++            dev_count = len(args.device)
++            if args.pool.exists():
++                dev_count += int(args.pool['dev_count'])
++            if args.raid == '10' and args.stripes:
++                if args.stripes * 2 > dev_count:
++                    PR.error("Not enough devices ({0}) ".format(dev_count) +
++                             "for specified number of ".format(args.stripes) +
++                             "stripes ({0}). You need ".format(args.stripes) +
++                             "at least {0} devices".format(args.stripes * 2))
++            if args.raid == '1' and dev_count < 2:
++                PR.error("You need at least 2 devices to create " +
++                         "raid1 volume")
++
+         # If we want btrfs pool and it does not exist yet, we do not
+         # want to call add since it would create it. Note that when
+         # btrfs pool is created the new btrfs volume is created as well
+         # because it is actually the same thing
+         if len(args.device) > 0 and \
+            not (not args.pool.exists() and args.pool.type == 'btrfs'):
+-            self.add(args, True)
++            try:
++                self.add(args, True)
++            except problem.NotSupported:
++                # Some backends might not support pooling at all.
++                pass
+ 
++        options = {}
++        if args.encrypt:
++            options['encrypt'] = args.encrypt
+         if args.raid:
+-            raid = {'level': args.raid,
+-                    'stripesize': args.stripesize,
+-                    'stripes': args.stripes}
+-        else:
+-            raid = None
++            options['raid'] = args.raid
++            options['stripesize'] = args.stripesize
++            options['stripes'] = args.stripes
+ 
+         lvname = args.pool.create(devs=devices,
+                                   size=args.size,
+-                                  raid=raid,
++                                  options=options,
+                                   name=args.name)
+-
+-        if args.fstype and args.pool.type != 'btrfs':
+-            if self._create_fs(args.fstype, lvname) != 0:
+-                self._mpoint = None
+-        if self._mpoint:
+-            self.reinit_vol()
+-            self._do_mount(self.vol[lvname])
++        return lvname
+ 
+     def list(self, args):
+         """
+@@ -1150,11 +1246,20 @@ class StorageHandle(object):
+                 else:
+                     # Check signature of existing file system on the device
+                     # and as user whether to use it or not.
+-                    signature = misc.get_fs_type(dev)
+-                    if signature and \
+-                       not PR.check(PR.EXISTING_FILESYSTEM, [signature, dev]):
+-                        args.device.remove(dev)
+-                        continue
++                    if item and 'mount' in item:
++                        try:
++                            if PR.check(PR.FS_MOUNTED, [dev, item['mount']]):
++                                misc.do_umount(dev)
++                        except problem.FsMounted:
++                            args.device.remove(dev)
++                            continue
++                    else:
++                        signature = misc.get_fs_type(dev)
++                        if signature and \
++                           not PR.check(PR.EXISTING_FILESYSTEM,
++                                        [signature, dev]):
++                            args.device.remove(dev)
++                            continue
+ 
+         if args.pool.exists():
+             if len(args.device) > 0:
+@@ -1196,10 +1301,7 @@ class StorageHandle(object):
+                         pool.reduce(item.name)
+                         removed += 1
+                         continue
+-                    else:
+-                        PR.error("It is not clear what do you want " +
+-                                 "to achieve by removing " +
+-                                 "{0}!".format(item.name))
++
+                 item.remove()
+                 removed += 1
+             except (RuntimeError, problem.SsmError), ex:
+@@ -1222,7 +1324,8 @@ class StorageHandle(object):
+             snap_size = vol_size * 0.20
+             user_set_size = False
+         else:
+-            snap_size = float(misc.get_real_size(args.size))
++            snap_size = float(args.size)
++            #snap_size = float(misc.get_real_size(args.size))
+             user_set_size = True
+ 
+         if pool_free < snap_size:
+@@ -1249,17 +1352,34 @@ class StorageHandle(object):
+                      "{0} with options \'{1}\'".format(args.directory,
+                                                        args.options))
+ 
++    def can_check(self, device):
++        fs = self.is_fs(device)
++        if fs is False:
++            real = misc.get_real_device(device)
++            vol = self.vol[real]
++            err = "'{0}' is not valid volume to check.".format(device)
++            try:
++                if not getattr(vol, "check"):
++                    raise argparse.ArgumentTypeError(err)
++                else:
++                    return vol
++            except AttributeError:
++                raise argparse.ArgumentTypeError(err)
++        else:
++            return fs
++
++
+     def is_fs(self, device):
+         real = misc.get_real_device(device)
+ 
+         vol = self.vol[real]
+-        if vol and 'fs_type' in vol:
+-            return vol['fs_info']
++        if vol and 'fs_info' in vol:
++            return vol
+         dev = self.dev[real]
+-        if dev and 'fs_type' in dev:
+-            return dev['fs_info']
++        if dev and 'fs_info' in dev:
++            return dev
+         err = "'{0}' does not contain valid file system".format(real)
+-        raise argparse.ArgumentTypeError(err)
++        return False
+ 
+     def _find_device_record(self, path):
+         """
+@@ -1294,7 +1414,10 @@ class StorageHandle(object):
+         return self.get_bdevice(path)
+ 
+     def get_bdevice(self, path):
+-        path = is_bdevice(path)
++        path = misc.is_bdevice(path)
++        if path == False:
++            err = "'{0}' is not valid block device".format(path)
++            raise argparse.ArgumentTypeError(err)
+         return self._find_device_record(path)
+ 
+     def is_pool(self, string):
+@@ -1310,7 +1433,7 @@ class StorageHandle(object):
+         if vol:
+             return vol
+         dev = self.dev[string]
+-        if dev and 'fs_type' in dev:
++        if dev and 'fs_info' in dev:
+             return dev
+         err = "'{0}' is not a valid volume to resize".format(string)
+         raise argparse.ArgumentTypeError(err)
+@@ -1366,6 +1489,21 @@ class StorageHandle(object):
+         err = "'{0}' is not valid pool nor volume".format(string)
+         raise argparse.ArgumentTypeError(err)
+ 
++def valid_size(size):
++    """ Validate that the 'size' is usable size argument. This is almost the
++    same as valid_resize_size() except we do not allow '+' and '-' signs
++    """
++
++    err = "'{0}' is not valid size.".format(size)
++    if len(size) and size[0] in ['+', '-']:
++        raise argparse.ArgumentTypeError(err)
++    try:
++        ret = misc.get_real_size(size)
++        if float(ret) < 0:
++            raise argparse.ArgumentTypeError(err)
++    except:
++        raise argparse.ArgumentTypeError(err)
++    return ret
+ 
+ def valid_resize_size(size):
+     """
+@@ -1404,7 +1542,9 @@ def valid_resize_size(size):
+         raise argparse.ArgumentTypeError(err)
+ 
+ 
+-def is_directory(self, string):
++def is_directory(string):
++    if string is None:
++        raise argparse.ArgumentTypeError(err)
+     try:
+         mode = os.stat(string).st_mode
+     except OSError:
+@@ -1417,19 +1557,6 @@ def is_directory(self, string):
+         raise argparse.ArgumentTypeError(err)
+ 
+ 
+-def is_bdevice(path):
+-    path = misc.get_real_device(path)
+-    try:
+-        mode = os.lstat(path).st_mode
+-    except OSError:
+-        err = "'{0}' is not valid block device".format(path)
+-        raise argparse.ArgumentTypeError(err)
+-    if not stat.S_ISBLK(mode):
+-        err = "'{0}' is not valid block device".format(path)
+-        raise argparse.ArgumentTypeError(err)
+-    return path
+-
+-
+ def is_supported_fs(fs):
+     if fs in SUPPORTED_FS:
+         return fs
+@@ -1484,6 +1611,14 @@ class SsmParser(object):
+                      "({0}).".format(",".join(SUPPORTED_BACKENDS)),
+                 choices=SUPPORTED_BACKENDS,
+                 action=SetBackend)
++        parser.add_argument('-n', '--dry-run',
++                help='''Dry run. Do not do anything, just parse the command
++                     line options and gather system information if necessary.
++                     Note that with this option ssm will not perform all the
++                     check as some of them are done by the backends
++                     themselves. This option is mainly used for debugging
++                     purposes.''',
++                action="store_true")
+         return parser
+ 
+     def _get_parser_check(self):
+@@ -1494,7 +1629,7 @@ class SsmParser(object):
+                 help="Check consistency of the file system on the device.")
+         parser_check.add_argument('device', nargs='+',
+                 help="Device with file system to check.",
+-                type=self.storage.is_fs)
++                type=self.storage.can_check)
+         parser_check.set_defaults(func=self.storage.check)
+         return parser_check
+ 
+@@ -1535,7 +1670,8 @@ class SsmParser(object):
+                      A size suffix K|k, M|m, G|g, T|t, P|p, E|e can be used
+                      to define 'power of two' units. If no unit is provided, it
+                      defaults to kilobytes. This is optional if if
+-                     not given maximum possible size will be used.''')
++                     not given maximum possible size will be used.''',
++                type=valid_size)
+         parser_create.add_argument('-n', '--name',
+                 help='''The name for the new logical volume. This is optional
+                      and if omitted, name will be generated by the
+@@ -1571,6 +1707,10 @@ class SsmParser(object):
+         parser_create.add_argument('-p', '--pool', default="",
+                 help="Pool to use to create the new volume.",
+                 type=self.storage.is_pool)
++        parser_create.add_argument('-e', '--encrypt', nargs='?',
++                choices=crypt.SUPPORTED_CRYPT, const=True,
++                help='''Create encrpted volume. Extension to use can be
++                     specified.''')
+         parser_create.add_argument('device', nargs='*',
+                 help='''Devices to use for creating the volume. If the device
+                      is not in any pool, it is added into the pool prior the
+@@ -1637,7 +1777,8 @@ class SsmParser(object):
+                      A size suffix K|k, M|m, G|g, T|t, P|p, E|e can be used
+                      to define 'power of two' units. If no unit is provided, it
+                      defaults to kilobytes. This is option and if not give,
+-                     the size will be determined automatically.''')
++                     the size will be determined automatically.''',
++                type=valid_size)
+         group = parser_snapshot.add_mutually_exclusive_group()
+         group.add_argument('-d', '--dest',
+                 help='''Destination of the snapshot specified with absolute
+@@ -1705,6 +1846,9 @@ def main(args=None):
+     # Register clean-up function on exit
+     sys.exitfunc = misc.do_cleanup
+ 
++    if args.dry_run:
++        return 0;
++
+     try:
+         args.func(args)
+     except argparse.ArgumentTypeError, ex:
+diff --git a/ssmlib/misc.py b/ssmlib/misc.py
+index 8e731ff..3ff1577 100644
+--- a/ssmlib/misc.py
++++ b/ssmlib/misc.py
+@@ -20,6 +20,7 @@
+ import os
+ import re
+ import sys
++import stat
+ import tempfile
+ import threading
+ import subprocess
+@@ -191,13 +192,15 @@ def do_mount(device, directory, options=None):
+     run(command)
+ 
+ 
+-def do_umount(mpoint):
+-    command = ['umount', mpoint]
++def do_umount(mpoint, all_targets=False):
++    command = ['umount']
++    if all_targets:
++        command.append('--all-targets')
+     try:
+-        run(command)
++        run(command + [mpoint])
+     except RuntimeError:
+-        command = ['umount', '-l', mpoint]
+-        run(command)
++        command.append('-l')
++        run(command + mpoint)
+ 
+ 
+ def temp_mount(device, options=None):
+@@ -228,12 +231,13 @@ def get_signature(device, types=None):
+         command.extend(['-u', types])
+     command.append(device)
+ 
+-    output = run(command, can_fail=True)[1].strip()
++    ret, output = run(command, can_fail=True, stderr=False)
++    output = output.strip()
+ 
+-    if len(output) > 0:
+-        return output
+-    else:
++    if ret:
+         return None
++    else:
++        return output
+ 
+ 
+ def get_fs_type(device):
+@@ -319,16 +323,21 @@ def get_dmnumber(name):
+     return dmnumber
+ 
+ 
+-def wipefs(device, typ):
++def wipefs(device, signatures):
++    if type(signatures) is not list:
++        signatures = [signatures]
+     command = ['wipefs', '-p', device]
+     output = run(command)[1]
++    offset = []
+     for line in output[1:].split('\n'):
+         if not line:
+             continue
+         array = line.split(",")
+-        if array[-1] == typ:
+-            command = ['wipefs', '--offset', array[0], device]
+-            run(command)
++        if array[-1] in signatures:
++            offset.extend(['--offset', array[0]])
++    if len(offset) > 1:
++        command = ['wipefs'] + offset + [device]
++        run(command)
+ 
+ 
+ def humanize_size(arg):
+@@ -545,3 +554,26 @@ def terminal_size(default=(25, 80)):
+         if not cr:
+             cr = (25, 80)
+     return int(cr[1]), int(cr[0])
++
++
++def is_bdevice(path):
++    """
++    Check whether the path is block device. If it is return
++    the path to the real block device, otherwise return False
++    """
++    path = get_real_device(path)
++    try:
++        mode = os.lstat(path).st_mode
++    except OSError:
++        return False
++    if not stat.S_ISBLK(mode):
++        return False
++    return path
++
++
++def get_device_size(device):
++    devname = device.split('/')[-1]
++    with open("/sys/block/{0}/size".format(devname), 'r') as f:
++        for line in f:
++            size = int(line)/2
++            return size
+diff --git a/ssmlib/problem.py b/ssmlib/problem.py
+index 56846df..dfa6ec6 100644
+--- a/ssmlib/problem.py
++++ b/ssmlib/problem.py
+@@ -22,7 +22,8 @@ import sys
+ __all__ = ["ProblemSet", "SsmError", "GeneralError", "ProgrammingError",
+            "BadEnvVariable", "NotEnoughSpace", "ResizeMatch", "FsNotSpecified",
+            "DeviceUsed", "ExistingFilesystem", "NoDevices", "ToolMissing",
+-           "CanNotRun", "CommandFailed", "UserInterrupted", "NotSupported"]
++           "CanNotRun", "CommandFailed", "UserInterrupted", "NotSupported",
++           "NotImplemented"]
+ 
+ # Define prompt codes
+ PROMPT_NONE =           0
+@@ -52,9 +53,10 @@ FL_DEFAULT_NO =         16
+ FL_SILENT =             32
+ FL_EXIT_ON_NO =         64
+ FL_EXIT_ON_YES =        128
+-FL_FATAL =              256
++FL_NO_MESSAGE =         256
+ FL_FORCE_YES =          512
+ FL_FORCE_NO =           1024
++FL_FATAL =              (2048 | FL_NO_MESSAGE)
+ 
+ 
+ class SsmError(Exception):
+@@ -65,7 +67,7 @@ class SsmError(Exception):
+         self.errcode = errcode
+ 
+     def __str__(self):
+-        return repr("Error ({0}): {1}".format(self.errcode, self.msg))
++        return "SSM Error ({0}): {1}".format(self.errcode, self.msg)
+ 
+ 
+ class GeneralError(SsmError):
+@@ -142,6 +144,10 @@ class ExistingFilesystem(SsmError):
+     def __init__(self, msg, errcode=2015):
+         super(ExistingFilesystem, self).__init__(msg, errcode)
+ 
++class NotImplemented(SsmError):
++    def __init__(self, msg, errcode=2016):
++        super(NotImplemented, self).__init__(msg, errcode)
++
+ 
+ class ProblemSet(object):
+ 
+@@ -158,7 +164,7 @@ class ProblemSet(object):
+              PROMPT_NONE, FL_FATAL, ProgrammingError]
+ 
+         self.GENERAL_ERROR = \
+-            ['SSM Error: {0}!', PROMPT_NONE, FL_FATAL, GeneralError]
++            ['{0}!', PROMPT_NONE, FL_FATAL, GeneralError]
+ 
+         self.GENERAL_INFO = \
+             ['SSM Info: {0}', PROMPT_NONE, FL_NONE, None]
+@@ -222,11 +228,17 @@ class ProblemSet(object):
+             ['{0} is not supported!',
+              PROMPT_NONE, FL_FATAL, NotSupported]
+ 
++        self.NOT_IMPLEMENTED = \
++            ['\'{0}\' function is not implemented by {1}!',
++            PROMPT_NONE, FL_FATAL, NotImplemented]
++
+     def _can_print_message(self, flags):
+         if (flags & FL_DEBUG_ONLY):
+             return self.options.debug
+         elif (flags & FL_VERBOSE_ONLY):
+             return self.options.verbose
++        elif (flags & FL_NO_MESSAGE):
++            return False
+         else:
+             return True
+ 
+@@ -289,14 +301,10 @@ class ProblemSet(object):
+ 
+         if self._can_print_message(flags) and \
+            (flags & FL_MSG_ONLY or prompt_msg is None):
+-            print >> sys.stderr, message,
+-        else:
+-            print message,
++            print >> sys.stderr, message
+         if not flags & FL_MSG_ONLY and prompt_msg is not None:
+-            print '{0}'.format(prompt_msg),
++            print message, '{0}'.format(prompt_msg),
+             res = self._ask_question(flags)
+-        else:
+-            print >> sys.stderr
+ 
+         if (flags & FL_FATAL):
+             if exc:
+diff --git a/tests/bashtests/001-lvm-add.sh b/tests/bashtests/001-lvm-add.sh
+index fee51a8..cfe95da 100755
+--- a/tests/bashtests/001-lvm-add.sh
++++ b/tests/bashtests/001-lvm-add.sh
+@@ -131,6 +131,16 @@ mkfs.ext3 $dev1
+ # Default answer is No
+ not ssm add $dev1
+ not check vg_field $SSM_LVM_DEFAULT_POOL pv_count 1
++# It can be forced though
++ssm -f add $dev1
++check vg_field $SSM_LVM_DEFAULT_POOL pv_count 1
++ssm -f remove $SSM_LVM_DEFAULT_POOL
++
++# Try to use device with existing file system
++mkfs.ext3 $dev1
++# Default answer is No
++not ssm add $dev1
++not check vg_field $SSM_LVM_DEFAULT_POOL pv_count 1
+ ssm add $dev1 $dev2
+ check vg_field $SSM_LVM_DEFAULT_POOL pv_count 1
+ ssm -f remove --all
+diff --git a/tests/bashtests/002-lvm-create.sh b/tests/bashtests/002-lvm-create.sh
+index aceea6d..d316e5d 100755
+--- a/tests/bashtests/002-lvm-create.sh
++++ b/tests/bashtests/002-lvm-create.sh
+@@ -115,6 +115,64 @@ check list_table "$(ssm list pool)" $SSM_LVM_DEFAULT_POOL lvm 10 none none 960.0
+ check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol1 $SSM_LVM_DEFAULT_POOL 960.00MB striped
+ ssm  -f remove $SSM_LVM_DEFAULT_POOL
+ 
++# Create a raid 1 logical volume
++# Size of the volume must be specified for lvm raid1
++not ssm create -r 1 $dev1 $dev2
++size=$((DEV_SIZE/2))
++size=$(align_size_up $size)
++ssm create -s ${size}M -r 1 $dev1 $dev2
++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 segtype raid1
++check list_table "$(ssm list pool)" $SSM_LVM_DEFAULT_POOL lvm 2 none none 192.00MB
++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol1 $SSM_LVM_DEFAULT_POOL ${size}.00MB raid1
++
++ssm add $TEST_DEVS
++size=$((DEV_SIZE*2))
++size=$(align_size_up $size)
++ssm create -s ${size}M -r 1
++check list_table "$(ssm list pool)" $SSM_LVM_DEFAULT_POOL lvm 10 none none 960.00MB
++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol2 $SSM_LVM_DEFAULT_POOL ${size}.00MB raid1
++ssm  -f remove $SSM_LVM_DEFAULT_POOL
++
++# Create a raid 10 logical volume
++# Size of the volume must be specified for lvm raid10
++not ssm create -r 10 $dev1 $dev2 $dev3 $dev4
++# Minimum is 4 devices
++not ssm create -s ${DEV_SIZE}M -r 10 $dev1 $dev2
++# Number of device has to be even
++not ssm create -s ${DEV_SIZE}M -r 10 $dev1 $dev2 $dev3 $dev4 $dev5
++ssm remove $dev5
++ssm create -s ${DEV_SIZE}M -r 10 $dev1 $dev2 $dev3 $dev4
++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 stripes 4
++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 segtype raid10
++check list_table "$(ssm list pool)" $SSM_LVM_DEFAULT_POOL lvm 4 none none 384.00MB
++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol1 $SSM_LVM_DEFAULT_POOL 104.00MB raid1
++size=56
++# Stripes or device has to be specified
++not ssm create -s ${size}M -r 10
++ssm create -s ${size}M -r 10 --stripes 2
++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol2 stripes 4
++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol2 segtype raid10
++check list_table "$(ssm list pool)" $SSM_LVM_DEFAULT_POOL lvm 4 none none 384.00MB
++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol2 $SSM_LVM_DEFAULT_POOL ${size}.00MB raid10
++ssm add $TEST_DEVS
++size=60
++ssm create -s ${size}M -r 10 --stripes 3
++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol3 stripes 6
++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol3 segtype raid10
++check list_table "$(ssm list pool)" $SSM_LVM_DEFAULT_POOL lvm 10 none none 960.00MB
++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol3 $SSM_LVM_DEFAULT_POOL ${size}.00MB raid10
++ssm  -f remove $SSM_LVM_DEFAULT_POOL
++ssm add $TEST_DEVS
++size=$((DEV_SIZE*2))
++size=$(align_size_up $size)
++ssm create -s ${size}M -r 10 $TEST_DEVS
++ssm list
++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 stripes 10
++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 segtype raid10
++check list_table "$(ssm list pool)" $SSM_LVM_DEFAULT_POOL lvm 10 none none 960.00MB
++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol1 $SSM_LVM_DEFAULT_POOL ${size}.00MB raid10
++ssm  -f remove $SSM_LVM_DEFAULT_POOL
++
+ # Create several volumes with different parameters
+ ssm  add $TEST_DEVS
+ not ssm create -I 8 -i $(($DEV_COUNT/2)) -s $(($DEV_SIZE*2))M
+@@ -174,7 +232,8 @@ for fs in $TEST_FS; do
+ 	check vg_field $SSM_LVM_DEFAULT_POOL pv_count 3
+ 
+ 	# pool doesn't exist
+-	ssm create --fstype $fs -s $((DEV_SIZE/2))m -n randvol $dev4 $mnt2
++	ssm create --fstype $fs -s $((DEV_SIZE/2))m -n randvol $dev4
++	ssm mount  $SSM_LVM_DEFAULT_POOL/randvol $mnt2
+ 	size=`align_size_up $((DEV_SIZE/2))`
+ 	check lv_field $SSM_LVM_DEFAULT_POOL/randvol lv_size $size.00m
+ 	check mountpoint $SSM_LVM_DEFAULT_POOL-randvol $mnt2
+@@ -282,4 +341,8 @@ not ssm create
+ ssm add $TEST_DEVS
+ not ssm create -p $pool1
+ not ssm create -r 0 -I 16 -i 3 $dev1 $dev2
++not ssm create -s-20M
++not ssm create -s+20M
++not ssm create --size 25.8.1991
++not ssm create --size linux
+ ssm  -f remove --all
+diff --git a/tests/bashtests/004-lvm-resize.sh b/tests/bashtests/004-lvm-resize.sh
+index f430851..c863f36 100755
+--- a/tests/bashtests/004-lvm-resize.sh
++++ b/tests/bashtests/004-lvm-resize.sh
+@@ -48,20 +48,79 @@ TEST_MNT=$TESTDIR/mnt
+ 
+ _test_resize()
+ {
+-	size=$((TEST_MAX_SIZE/2))
+-	echo 'y' | ssm -f resize --size ${size}M ${DM_DEV_DIR}/$DEFAULT_VOLUME
++	# Test with no device
++	# Test size increase
++	size=$DEV_SIZE
++	check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
++	size=$((DEV_SIZE + 12))
++	ssm resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1
++	check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
++	size=$((size + 3))
++	ssm resize -s +3M $SSM_LVM_DEFAULT_POOL/$lvol1
+ 	size=$(align_size_up $size)
+ 	check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
++	# Test size decrese
++	if [ "$fs" != "xfs" ]; then
++		size=$((size - 8))
++		ssm -f resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1
++		check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
++		size=$((size - 7))
++		ssm -f resize -s-7M $SSM_LVM_DEFAULT_POOL/$lvol1
++		size=$(align_size_up $size)
++		check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
++		# Test with devcie belongs to no pool
++		# size decrease
++		size=$((size - 12))
++		ssm -f resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev4
++		check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
++		check vg_field $SSM_LVM_DEFAULT_POOL pv_count 3
++		check vg_field $pool1 pv_count 3
++	fi
++	# If the volume is already of the given size ssm will attempt to resize
++	# file system to cover the whole device. Note that we do not check for
++	# the file system size because it's not really necessary. So this would
++	# fail if the file system is present. This might change in future, so
++	# comment it out for now.
++	# size doesn't change
++	#not ssm -f resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev4
++	#check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
++	#check vg_field $SSM_LVM_DEFAULT_POOL pv_count 3
++	#check vg_field $pool1 pv_count 3
++	# size increase
++	size=$((size + 12))
++	ssm resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev4
++	check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
++	check vg_field $SSM_LVM_DEFAULT_POOL pv_count 3
++	check vg_field $pool1 pv_count 3
+ 
+-	# xfs does not support shrinking (xfs only grows big!! :))
++	# Test with device belongs to other pool
++	# size decrease
+ 	if [ "$fs" != "xfs" ]; then
+-		ssm -f -v resize -s-$(($TEST_MAX_SIZE/4))M $DEFAULT_VOLUME
+-		size=$(align_size_up $(($size-($TEST_MAX_SIZE/4))))
++		size=$((size - 12))
++		ssm -f resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev6
+ 		check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
++		check vg_field $SSM_LVM_DEFAULT_POOL pv_count 3
++		check vg_field $pool1 pv_count 3
+ 	fi
+-	echo 'y' | ssm -f resize --size +$(($TEST_MAX_SIZE/5))M $DEFAULT_VOLUME
+-	size=$(align_size_up $(($size+($TEST_MAX_SIZE/5))))
++	# size doesn't change
++	#not ssm -f resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev6
++	#check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
++	#check vg_field $SSM_LVM_DEFAULT_POOL pv_count 3
++	#check vg_field $pool1 pv_count 3
++	# size increase
++	size=$((size + 12))
++	ssm -f resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev6
++	check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
++	check vg_field $SSM_LVM_DEFAULT_POOL pv_count 3
++	check vg_field $pool1 pv_count 3
++
++	# when resize to excessive amount
++	size=$((DEV_SIZE*4))
++	not ssm resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1
++	ssm resize -s ${size}M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev8 $dev9
+ 	check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 lv_size ${size}.00m
++	check vg_field $SSM_LVM_DEFAULT_POOL pv_count 5
++
+ }
+ 
+ ssm add $TEST_DEVS
+@@ -100,46 +159,37 @@ ssm -f remove $SSM_LVM_DEFAULT_POOL
+ ssm create --size $((DEV_SIZE/2))M $dev1
+ check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 1
+ ssm resize --size +$((DEV_SIZE/3))M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev2
+-check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 2
++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 1
+ ssm -f resize -s-$((DEV_SIZE/3))M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev2 $dev3
+ ssm resize --size +$((DEV_SIZE/3))M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev2 $dev3
+-check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 3
++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 1
+ ssm -f resize -s-$((DEV_SIZE/3))M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev2 $dev3
+-check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 3
++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 1
+ ssm resize --size +${DEV_SIZE}M $SSM_LVM_DEFAULT_POOL/$lvol1 $dev2 $dev3
+ check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 3
+ ssm -f remove $SSM_LVM_DEFAULT_POOL
+ 
++
++ssm add $dev{1,2,3}
++ssm create -s ${DEV_SIZE}M
++ssm add -p $pool1 $dev{5,6,7}
++_test_resize
++ssm -f remove $SSM_LVM_DEFAULT_POOL
++ssm -f remove $pool1
++
++
+ [ ! -d $TEST_MNT ] && mkdir $TEST_MNT &> /dev/null
+ for fs in $TEST_FS; do
+-	# umounted test
+-	ssm add $TEST_DEVS
+-	size=$((TEST_MAX_SIZE/4))
+-	ssm create --fs $fs --size ${size}M $TEST_DEVS
+-
++	ssm add $dev{1,2,3}
++	ssm create -s ${DEV_SIZE}M --fs $fs
++	ssm -f check $DEFAULT_VOLUME
++	ssm add -p $pool1 $dev{5,6,7}
+ 	_test_resize
+ 	ssm -f check $DEFAULT_VOLUME
+ 	ssm -f remove $SSM_LVM_DEFAULT_POOL
+-
+-        echo $fs
+-        if [ $fs == 'ext2' ]; then
+-            continue
+-        fi
+-
+-        # Disable this for now, since fsadm does not handle -f and -y correctly
+-	# mounted test
+-	#ssm add $TEST_DEVS
+-	size=$((TEST_MAX_SIZE/4))
+-	#ssm create --fs $fs --size ${size}M $TEST_DEVS
+-
+-	#mount ${DM_DEV_DIR}/$DEFAULT_VOLUME $TEST_MNT
+-
+-	#_test_resize
+-
+-	#umount $TEST_MNT
+-	#ssm -f check $DEFAULT_VOLUME
+-	#ssm -f remove $SSM_LVM_DEFAULT_POOL
++	ssm -f remove $pool1
+ done
++# There should not be anything to remove
+ not ssm  -f remove --all
+ 
+ ssm create $dev1
+diff --git a/tests/bashtests/007-btrfs-create.sh b/tests/bashtests/007-btrfs-create.sh
+index 1ea27df..c971a76 100755
+--- a/tests/bashtests/007-btrfs-create.sh
++++ b/tests/bashtests/007-btrfs-create.sh
+@@ -88,6 +88,7 @@ ssm -f remove $SSM_BTRFS_DEFAULT_POOL
+ 
+ # Create raid 10 volume with just one device
+ ssm create -r 10 $dev1 $dev2 $dev3 $dev4
++ssm check $SSM_BTRFS_DEFAULT_POOL
+ not ssm create $dev1 -p $pool1
+ ssm -f remove $SSM_BTRFS_DEFAULT_POOL
+ 
+diff --git a/tests/bashtests/011-lvm-list.sh b/tests/bashtests/011-lvm-list.sh
+index 66567a1..73cea90 100755
+--- a/tests/bashtests/011-lvm-list.sh
++++ b/tests/bashtests/011-lvm-list.sh
+@@ -1,6 +1,6 @@
+ #!/bin/bash
+ #
+-# (C)2012 Red Hat, Inc., Tom Marek <tmarek at redhat.com>
++# (C)2013 Red Hat, Inc., Jimmy Pan <jipan at redhat.com>
+ #
+ # This program is free software: you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+@@ -21,9 +21,10 @@ export test_description='Check whether list command prints correct values for lv
+ . lib/test
+ 
+ DEV_COUNT=10
+-DEV_SIZE=100
++DEV_SIZE=128
+ TEST_MAX_SIZE=$(($DEV_COUNT*$DEV_SIZE))
+ aux prepare_devs $DEV_COUNT $DEV_SIZE
++aux prepare_mnts 10
+ TEST_DEVS=$(cat DEVICES)
+ export LVOL_PREFIX="lvol"
+ export SSM_DEFAULT_BACKEND='lvm'
+@@ -33,8 +34,14 @@ export SSM_NONINTERACTIVE='1'
+ snap1="snap1"
+ snap2="snap2"
+ 
++lvol1=${LVOL_PREFIX}001
++lvol2=${LVOL_PREFIX}002
++lvol3=${LVOL_PREFIX}003
++
++pool0=$vg1
+ pool1=$vg2
+ pool2=$vg3
++pool3=$vg4
+ 
+ TEST_FS=
+ which mkfs.ext2 && TEST_FS+="ext2 "
+@@ -45,28 +52,262 @@ which mkfs.xfs  && TEST_FS+="xfs"
+ TEST_MNT=$TESTDIR/mnt
+ [ ! -d $TEST_MNT ] && mkdir $TEST_MNT &> /dev/null
+ 
+-##LVM
+-# Check devices
+-ssm add $TEST_DEVS
+-ssm_output=$(ssm list dev)
+-for device in ${TEST_DEVS}; do
+-     check list_table "$ssm_output" $device 96.00MB 0.00KB 96.00MB $SSM_LVM_DEFAULT_POOL
++# Prepare pools and volumes
++
++vol1=volsf
++vol2=volss
++vol3=volmf
++vol4=volms1
++vol5=volms2
++vol6=volms3
++maxvolsz=$((DEV_SIZE-4))
++size1=$maxvolsz
++size2=$((DEV_SIZE/2))
++size3=$((maxvolsz*2))
++size4=$((DEV_SIZE/2))
++size5=$((DEV_SIZE*2))
++size6=$((DEV_SIZE/4))
++size4s=$((size4-20))
++size2r=$((size2-4))
++size5r=$((size5+16))
++
++
++# Test without a filesystem
++ssm -f create -n $vol1 $dev1
++ssm create -n $vol2 -p $pool1 -s ${size2}M $dev2
++ssm create -n $vol3 -p $pool2 $dev3 $dev4
++ssm add -p $pool3 $dev{5,6,7,8}
++ssm create -p $pool3 -s ${size4}m -n $vol4
++ssm create -p $pool3 -s ${size5}m -n $vol5
++ssm create -p $pool3 -s ${size6}m -n $vol6
++
++# We shouldn't see ssm list fs here
++test `ssm list fs | wc -l` -le 1
++# Check vol, dev, pool, resized vol, and snapshot
++output=`ssm list vol`
++check list_table "$output" $pool0/$vol1 $pool0 $((size1)).00MB linear
++check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB linear
++check list_table "$output" $pool2/$vol3 $pool2 $((size3)).00MB linear
++check list_table "$output" $pool3/$vol4 $pool3 $((size4)).00MB linear
++check list_table "$output" $pool3/$vol5 $pool3 $((size5)).00MB linear
++check list_table "$output" $pool3/$vol6 $pool3 $((size6)).00MB linear
++output=`ssm list dev`
++check list_table "$output" $dev1 0.00KB $((size1)).00MB 124.00MB $pool0
++check list_table "$output" $dev2 $((maxvolsz-size2)).00MB $((size2)).00MB 124.00MB $pool1
++check list_table "$output" $dev3 0.00KB $((maxvolsz)).00MB 124.00MB $pool2
++check list_table "$output" $dev4 0.00KB $((maxvolsz)).00MB 124.00MB $pool2
++check list_table "$output" $dev5 none none 124.00MB $pool3
++check list_table "$output" $dev6 none none 124.00MB $pool3
++check list_table "$output" $dev7 none none 124.00MB $pool3
++check list_table "$output" $dev8 none none 124.00MB $pool3
++output=`ssm list pool`
++check list_table "$output" $pool0 lvm 1 0.00KB $((size1)).00MB $((maxvolsz)).00MB
++check list_table "$output" $pool1 lvm 1 $((maxvolsz-size2)).00MB $((size2)).00MB $((maxvolsz)).00MB
++check list_table "$output" $pool2 lvm 2 0.00KB $((size3)).00MB $((maxvolsz*2)).00MB
++check list_table "$output" $pool3 lvm 4 $((maxvolsz*4-size4-size5-size6)).00MB $((size4+size5+size6)).00MB $((maxvolsz*4)).00MB
++
++# Check ssm vol after resize
++ssm -f resize $pool1/$vol2 -s ${size2r}M
++ssm resize -s ${size5r}m $pool3/$vol5
++output=`ssm list vol`
++check list_table "$output" $pool1/$vol2 $pool1 $size2r.00MB linear
++check list_table "$output" $pool3/$vol5 $pool3 $((size5r)).00MB linear
++
++ssm snapshot $pool3/$vol4 -n snap1
++ssm snapshot $pool3/$vol4 -s ${size4s}m -n snap2
++output=`ssm list snap`
++check list_table "$output" $pool3/snap1 $vol4 $pool3 none none linear
++check list_table "$output" $pool3/snap2 $vol4 $pool3 $size4s.00MB none linear
++
++
++ssm -f remove -a
++
++
++# Test with filesystem
++for fs in $TEST_FS ; do
++	ssm -f create -n $vol1 $dev1 --fs $fs
++	ssm create -n $vol2 -p $pool1 -s ${size2}M $dev2 --fs $fs
++	ssm create -n $vol3 -p $pool2 $dev3 $dev4 --fs $fs
++	ssm add -p $pool3 $dev{5,6,7,8}
++	ssm create -p $pool3 -s ${size4}m -n $vol4 --fs $fs
++	ssm create -p $pool3 -s ${size5}m -n $vol5 --fs $fs
++	ssm create -p $pool3 -s ${size6}m -n $vol6 --fs $fs
++
++	# Check fs, vol, dev, pool, resized vol, and snapshot
++	output=`ssm list fs`
++	# xfs has some strange used size, so we don't check it
++	if [ $fs == xfs ] ; then
++		check list_table "$output" $pool0/$vol1 $pool0 $size1.00MB $fs none none linear
++		check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB $fs none none linear
++		check list_table "$output" $pool2/$vol3 $pool2 $size3.00MB $fs none none linear
++		check list_table "$output" $pool3/$vol4 $pool3 $size4.00MB $fs none none linear
++		check list_table "$output" $pool3/$vol5 $pool3 $size5.00MB $fs none none linear
++		check list_table "$output" $pool3/$vol6 $pool3 $size6.00MB $fs none none linear
++	else
++		check list_table "$output" $pool0/$vol1 $pool0 $size1.00MB $fs $size1.00MB none linear
++		check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB $fs $size2.00MB none linear
++		check list_table "$output" $pool2/$vol3 $pool2 $size3.00MB $fs $size3.00MB none linear
++		check list_table "$output" $pool3/$vol4 $pool3 $size4.00MB $fs $size4.00MB none linear
++		check list_table "$output" $pool3/$vol5 $pool3 $size5.00MB $fs $size5.00MB none linear
++		check list_table "$output" $pool3/$vol6 $pool3 $size6.00MB $fs $size6.00MB none linear
++	fi
++
++	output=`ssm list vol`
++	# xfs has some strange used size, so we don't check it
++	if [ $fs == xfs ] ; then
++		check list_table "$output" $pool0/$vol1 $pool0 $size1.00MB $fs none none linear
++		check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB $fs none none linear
++		check list_table "$output" $pool2/$vol3 $pool2 $size3.00MB $fs none none linear
++		check list_table "$output" $pool3/$vol4 $pool3 $size4.00MB $fs none none linear
++		check list_table "$output" $pool3/$vol5 $pool3 $size5.00MB $fs none none linear
++		check list_table "$output" $pool3/$vol6 $pool3 $size6.00MB $fs none none linear
++	else
++		check list_table "$output" $pool0/$vol1 $pool0 $size1.00MB $fs $size1.00MB none linear
++		check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB $fs $size2.00MB none linear
++		check list_table "$output" $pool2/$vol3 $pool2 $size3.00MB $fs $size3.00MB none linear
++		check list_table "$output" $pool3/$vol4 $pool3 $size4.00MB $fs $size4.00MB none linear
++		check list_table "$output" $pool3/$vol5 $pool3 $size5.00MB $fs $size5.00MB none linear
++		check list_table "$output" $pool3/$vol6 $pool3 $size6.00MB $fs $size6.00MB none linear
++	fi
++
++	output=`ssm list dev`
++	check list_table "$output" $dev1 0.00KB $((size1)).00MB 124.00MB $pool0
++	check list_table "$output" $dev2 $((maxvolsz-size2)).00MB $((size2)).00MB 124.00MB $pool1
++	check list_table "$output" $dev3 0.00KB $((maxvolsz)).00MB 124.00MB $pool2
++	check list_table "$output" $dev4 0.00KB $((maxvolsz)).00MB 124.00MB $pool2
++	check list_table "$output" $dev5 none none 124.00MB $pool3
++	check list_table "$output" $dev6 none none 124.00MB $pool3
++	check list_table "$output" $dev7 none none 124.00MB $pool3
++	check list_table "$output" $dev8 none none 124.00MB $pool3
++	output=`ssm list pool`
++	check list_table "$output" $pool0 lvm 1 0.00KB $((size1)).00MB $((maxvolsz)).00MB
++	check list_table "$output" $pool1 lvm 1 $((maxvolsz-size2)).00MB $((size2)).00MB $((maxvolsz)).00MB
++	check list_table "$output" $pool2 lvm 2 0.00KB $((size3)).00MB $((maxvolsz*2)).00MB
++	check list_table "$output" $pool3 lvm 4 $((maxvolsz*4-size4-size5-size6)).00MB $((size4+size5+size6)).00MB $((maxvolsz*4)).00MB
++
++	# Check ssm vol after resize
++	# xfs size cannot reduce
++	if [ "$fs" != xfs ] ; then
++		ssm -f resize $pool1/$vol2 -s ${size2r}M
++	fi
++	ssm resize -s ${size5r}m $pool3/$vol5
++
++	output=`ssm list vol`
++	# xfs has some strange used size, so we don't check it
++	if [ "$fs" != xfs ] ; then
++		check list_table "$output" $pool1/$vol2 $pool1 $size2r.00MB $fs $size2r none linear
++		check list_table "$output" $pool3/$vol5 $pool3 $size5r.00MB $fs $size5r none linear
++	else
++		check list_table "$output" $pool3/$vol5 $pool3 $size5r.00MB $fs none none linear
++	fi
++
++	ssm snapshot $pool3/$vol4 -n snap1
++	ssm snapshot $pool3/$vol4 -s ${size4s}m -n snap2
++
++	output=`ssm list snap`
++	check list_table "$output" $pool3/snap1 $vol4 $pool3 none none linear
++	check list_table "$output" $pool3/snap2 $vol4 $pool3 $size4s.00MB none linear
++
++	ssm -f remove -a
++
+ done
+ 
+-# Check pools
+-check list_table "$(ssm list pool)" $SSM_LVM_DEFAULT_POOL $SSM_DEFAULT_BACKEND $DEV_COUNT none none 960.00MB
+-ssm -f remove --all
++# Test with a mountpoint
++for fs in $TEST_FS ; do
++	ssm -f create -n $vol1 --fs $fs $dev1 $mnt1
++	ssm create -n $vol2 -p $pool1 -s ${size2}M --fs $fs $dev2 $mnt2
++	ssm create -n $vol3 -p $pool2 --fs $fs $dev3 $dev4 $mnt3
++	ssm add -p $pool3 $dev{5,6,7,8}
++	ssm create -p $pool3 -s ${size4}m -n $vol4 --fs $fs $mnt4
++	ssm create -p $pool3 -s ${size5}m -n $vol5 --fs $fs $mnt5
++	ssm create -p $pool3 -s ${size6}m -n $vol6 --fs $fs $mnt6
+ 
+-# create multiple pools
+-ssm create --pool $pool1 $dev1 $dev2 $dev3 $dev4
+-ssm create --pool $pool2 $dev5 $dev6 $dev7 $dev8
+-ssm_output=$(ssm list pool)
+-check list_table "$ssm_output" $pool1 lvm 4 none none 384.00MB
+-check list_table "$ssm_output" $pool2 lvm 4 none none 384.00MB
+-ssm -f remove --all
++	# Check fs, vol, dev, pool, resized vol, and snapshot
++	output=`ssm list fs`
++	# xfs has some strange used size, so we don't check it
++	if [ $fs == xfs ] ; then
++		check list_table "$output" $pool0/$vol1 $pool0 $size1.00MB $fs none none linear $mnt1
++		check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB $fs none none linear $mnt2
++		check list_table "$output" $pool2/$vol3 $pool2 $size3.00MB $fs none none linear $mnt3
++		check list_table "$output" $pool3/$vol4 $pool3 $size4.00MB $fs none none linear $mnt4
++		check list_table "$output" $pool3/$vol5 $pool3 $size5.00MB $fs none none linear $mnt5
++		check list_table "$output" $pool3/$vol6 $pool3 $size6.00MB $fs none none linear $mnt6
++	else
++		check list_table "$output" $pool0/$vol1 $pool0 $size1.00MB $fs $size1.00MB none linear $mnt1
++		check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB $fs $size2.00MB none linear $mnt2
++		check list_table "$output" $pool2/$vol3 $pool2 $size3.00MB $fs $size3.00MB none linear $mnt3
++		check list_table "$output" $pool3/$vol4 $pool3 $size4.00MB $fs $size4.00MB none linear $mnt4
++		check list_table "$output" $pool3/$vol5 $pool3 $size5.00MB $fs $size5.00MB none linear $mnt5
++		check list_table "$output" $pool3/$vol6 $pool3 $size6.00MB $fs $size6.00MB none linear $mnt6
++	fi
+ 
+-ssm add $TEST_DEVS
++	output=`ssm list vol`
++	# xfs has some strange used size, so we don't check it
++	if [ $fs == xfs ] ; then
++		check list_table "$output" $pool0/$vol1 $pool0 $size1.00MB $fs none none linear $mnt1
++		check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB $fs none none linear $mnt2
++		check list_table "$output" $pool2/$vol3 $pool2 $size3.00MB $fs none none linear $mnt3
++		check list_table "$output" $pool3/$vol4 $pool3 $size4.00MB $fs none none linear $mnt4
++		check list_table "$output" $pool3/$vol5 $pool3 $size5.00MB $fs none none linear $mnt5
++		check list_table "$output" $pool3/$vol6 $pool3 $size6.00MB $fs none none linear $mnt6
++	else
++		check list_table "$output" $pool0/$vol1 $pool0 $size1.00MB $fs $size1.00MB none linear $mnt1
++		check list_table "$output" $pool1/$vol2 $pool1 $size2.00MB $fs $size2.00MB none linear $mnt2
++		check list_table "$output" $pool2/$vol3 $pool2 $size3.00MB $fs $size3.00MB none linear $mnt3
++		check list_table "$output" $pool3/$vol4 $pool3 $size4.00MB $fs $size4.00MB none linear $mnt4
++		check list_table "$output" $pool3/$vol5 $pool3 $size5.00MB $fs $size5.00MB none linear $mnt5
++		check list_table "$output" $pool3/$vol6 $pool3 $size6.00MB $fs $size6.00MB none linear $mnt6
++	fi
++
++	output=`ssm list dev`
++	check list_table "$output" $dev1 0.00KB $((size1)).00MB 124.00MB $pool0
++	check list_table "$output" $dev2 $((maxvolsz-size2)).00MB $((size2)).00MB 124.00MB $pool1
++	check list_table "$output" $dev3 0.00KB $((maxvolsz)).00MB 124.00MB $pool2
++	check list_table "$output" $dev4 0.00KB $((maxvolsz)).00MB 124.00MB $pool2
++	check list_table "$output" $dev5 none none 124.00MB $pool3
++	check list_table "$output" $dev6 none none 124.00MB $pool3
++	check list_table "$output" $dev7 none none 124.00MB $pool3
++	check list_table "$output" $dev8 none none 124.00MB $pool3
++	output=`ssm list pool`
++	check list_table "$output" $pool0 lvm 1 0.00KB $((size1)).00MB $((maxvolsz)).00MB
++	check list_table "$output" $pool1 lvm 1 $((maxvolsz-size2)).00MB $((size2)).00MB $((maxvolsz)).00MB
++	check list_table "$output" $pool2 lvm 2 0.00KB $((size3)).00MB $((maxvolsz*2)).00MB
++	check list_table "$output" $pool3 lvm 4 $((maxvolsz*4-size4-size5-size6)).00MB $((size4+size5+size6)).00MB $((maxvolsz*4)).00MB
++
++	# Check ssm vol after resize
++	# xfs size cannot reduce
++	if [ "$fs" != xfs ] ; then
++		umount $mnt2
++		ssm -f resize $pool1/$vol2 -s ${size2r}M
++	fi
++	ssm resize -s ${size5r}m $pool3/$vol5
++
++	output=`ssm list vol`
++	# xfs has some strange used size, so we don't check it
++	if [ "$fs" != xfs ] ; then
++		check list_table "$output" $pool1/$vol2 $pool1 $size2r.00MB $fs $size2r none linear
++		check list_table "$output" $pool3/$vol5 $pool3 $size5r.00MB $fs $size5r none linear
++	else
++		check list_table "$output" $pool3/$vol5 $pool3 $size5r.00MB $fs none none linear
++	fi
+ 
++	ssm snapshot $pool3/$vol4 -n snap1
++	ssm snapshot $pool3/$vol4 -s ${size4s}m -n snap2
++
++	output=`ssm list snap`
++	check list_table "$output" $pool3/snap1 $vol4 $pool3 none none linear
++	check list_table "$output" $pool3/snap2 $vol4 $pool3 $size4s.00MB none linear
++
++	for i in {1..6} ; do
++		mntdir=`eval echo '$mnt'$i`
++		umount $mntdir || true
++	done
++
++	ssm -f remove -a
++
++done
++
++ssm add $TEST_DEVS
+ # Check LVM volume listings with various fs
+ for fs in $TEST_FS; do
+     name="${fs}vol"
+@@ -85,30 +326,5 @@ for fs in $TEST_FS; do
+ done
+ ssm -f remove $SSM_LVM_DEFAULT_POOL
+ 
+-# Check lvm snapshot
+-lvol1=${LVOL_PREFIX}001
+-# Create volume with all devices at once
+-size=$(($DEV_SIZE*6))
+-snap_size1=$(($DEV_SIZE))
+-snap_size2=$(($size/5))
+-ssm create --size ${size}M $TEST_DEVS
+-ssm snapshot --name $snap1 --size ${snap_size1}M $SSM_LVM_DEFAULT_POOL/$lvol1
+-ssm snapshot --name $snap2 --size ${snap_size2}M $SSM_LVM_DEFAULT_POOL/$lvol1
+-ssm_output=$(ssm list snap)
+-check list_table "$ssm_output" $snap1 $lvol1 $SSM_LVM_DEFAULT_POOL ${snap_size1}.00MB 0.00KB linear
+-check list_table "$ssm_output" $snap2 $lvol1 $SSM_LVM_DEFAULT_POOL ${snap_size2}.00MB 0.00KB linear
+-ssm -f remove --all
+-
+-# Snapshot of the volumes in defferent pools
+-ssm create --pool $pool1 $dev1 $dev2
+-ssm add $dev3 $dev4 --pool $pool1
+-ssm create --pool $pool2 $dev5 $dev6
+-ssm add $dev7 $dev8 --pool $pool2
+-ssm snapshot --name $snap1 $pool1/$lvol1
+-ssm snapshot --name $snap1 $pool2/$lvol1
+-ssm_output=$(ssm list snap)
+-check list_table "$ssm_output" "$pool1/$snap1" $lvol1 $pool1 40.00MB 0.00KB linear
+-check list_table "$ssm_output" "$pool2/$snap1" $lvol1 $pool2 40.00MB 0.00KB linear
+-ssm -f remove --all
+-
+-# all_done!!!
++# Some situation should fail
++not ssm list wrong_type
+diff --git a/tests/bashtests/012-crypt-create.sh b/tests/bashtests/012-crypt-create.sh
+new file mode 100644
+index 0000000..8a5fddb
+--- /dev/null
++++ b/tests/bashtests/012-crypt-create.sh
+@@ -0,0 +1,143 @@
++#!/bin/bash
++#
++# (C)2013 Red Hat, Inc., Lukas Czerner <lczerner at redhat.com>
++#
++# This program is free software: you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation, either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++export test_name='012-crypt-create'
++test_description='Exercise crypt create'
++
++. lib/test
++
++DEV_COUNT=10
++DEV_SIZE=100
++TEST_MAX_SIZE=$(($DEV_COUNT*$DEV_SIZE))
++aux prepare_devs $DEV_COUNT $DEV_SIZE
++aux prepare_mnts 4
++TEST_DEVS=$(cat DEVICES)
++export SSM_DEFAULT_BACKEND='crypt'
++export SSM_CRYPT_DEFAULT_POOL=$vg1
++export CRYPT_VOL_PREFIX="${SSM_PREFIX_FILTER}enc"
++export SSM_NONINTERACTIVE='1'
++export SSM_CRYPT_DEFAULT_VOL_PREFIX=$CRYPT_VOL_PREFIX
++crypt_vol1=${CRYPT_VOL_PREFIX}001
++crypt_vol2=${CRYPT_VOL_PREFIX}002
++crypt_vol3=${CRYPT_VOL_PREFIX}003
++crypt_vol4=${CRYPT_VOL_PREFIX}004
++passwd="cai0ohMo8M"
++
++pool1=$vg2
++pool2=$vg3
++DEV="/dev/mapper"
++
++# cryptsetup will ask for password. If luks extension is used
++# it will ask when creating header and then when opening the device
++pass() {
++	echo -e "${passwd}\n${passwd}"
++}
++
++
++# Create encrypted volume
++pass | ssm create $dev1
++check crypt_vol_field $crypt_vol1 type LUKS1
++check crypt_vol_field $crypt_vol1 device $dev1
++check list_table "$(ssm list vol)" $crypt_vol1 $SSM_CRYPT_DEFAULT_POOL none crypt
++
++pass | ssm create $dev2 -e
++check crypt_vol_field $crypt_vol2 type LUKS1
++check crypt_vol_field $crypt_vol2 device $dev2
++check list_table "$(ssm list vol)" $crypt_vol2 $SSM_CRYPT_DEFAULT_POOL none crypt
++
++pass | ssm create -e luks $dev3
++check crypt_vol_field $crypt_vol3 type LUKS1
++check crypt_vol_field $crypt_vol3 device $dev3
++check list_table "$(ssm list vol)" $crypt_vol3 $SSM_CRYPT_DEFAULT_POOL none crypt
++
++pass | ssm create --fs ext4 -e plain $dev4 $mnt1
++check mountpoint $crypt_vol4 $mnt1
++check crypt_vol_field $crypt_vol4 type PLAIN
++check crypt_vol_field $crypt_vol4 device $dev4
++check list_table "$(ssm list vol)" $crypt_vol4 $SSM_CRYPT_DEFAULT_POOL none ext4 none none crypt
++ssm list
++umount $mnt1
++ssm -f remove ${DEV}/$crypt_vol1
++
++pass | ssm create --fs ext3 -s 50M -e plain $dev1 $mnt1
++check mountpoint $crypt_vol1 $mnt1
++check crypt_vol_field $crypt_vol1 type PLAIN
++check crypt_vol_field $crypt_vol1 device $dev1
++check crypt_vol_field $crypt_vol1 size 102400
++check list_table "$(ssm list vol)" $crypt_vol1 $SSM_CRYPT_DEFAULT_POOL none ext3 none none crypt
++umount $mnt1
++
++ssm remove ${DEV}/$crypt_vol1 ${DEV}/$crypt_vol3 ${DEV}/$crypt_vol2 ${DEV}/$crypt_vol4
++
++# Try non existing extension
++not ssm create -e enigma $dev1
++
++# Create encrypted lvm volume
++export SSM_LVM_DEFAULT_POOL=${vg1}_lvm
++export LVOL_PREFIX="lvol"
++lvol1=${LVOL_PREFIX}001
++lvol2=${LVOL_PREFIX}002
++lvol3=${LVOL_PREFIX}003
++lvol4=${LVOL_PREFIX}004
++export SSM_DEFAULT_BACKEND='lvm'
++
++pass | ssm create --fs xfs $dev1 $dev2 $mnt1 -e
++check mountpoint $crypt_vol1 $mnt1
++check crypt_vol_field $crypt_vol1 type LUKS1
++check crypt_vol_field $crypt_vol1 device ${SSM_LVM_DEFAULT_POOL}-$lvol1
++check list_table "$(ssm list vol)" $crypt_vol1 $SSM_CRYPT_DEFAULT_POOL none xfs none none crypt
++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol1 $SSM_LVM_DEFAULT_POOL none linear
++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol1 pv_count 2
++
++pass | ssm create -r0 $dev3 $dev4 -e plain
++check crypt_vol_field $crypt_vol2 type PLAIN
++check crypt_vol_field $crypt_vol2 device ${SSM_LVM_DEFAULT_POOL}-$lvol2
++check list_table "$(ssm list vol)" $crypt_vol2 $SSM_CRYPT_DEFAULT_POOL none crypt
++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol2 $SSM_LVM_DEFAULT_POOL none striped
++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol2 pv_count 4
++
++pass | ssm create $dev5 -e luks
++check crypt_vol_field $crypt_vol3 type LUKS1
++check crypt_vol_field $crypt_vol3 device ${SSM_LVM_DEFAULT_POOL}-$lvol3
++check list_table "$(ssm list vol)" $crypt_vol3 $SSM_CRYPT_DEFAULT_POOL none crypt
++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol3 $SSM_LVM_DEFAULT_POOL none linear
++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol3 pv_count 5
++
++pass | ssm create -e plain --fs xfs -r10 -s ${DEV_SIZE}M $dev6 $dev7 $dev8 $dev9 $mnt2
++check mountpoint $crypt_vol4 $mnt2
++check crypt_vol_field $crypt_vol4 type PLAIN
++check crypt_vol_field $crypt_vol4 device ${SSM_LVM_DEFAULT_POOL}-$lvol4
++check list_table "$(ssm list vol)" $crypt_vol4 $SSM_CRYPT_DEFAULT_POOL 104.00M xfs none none crypt
++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol4 $SSM_LVM_DEFAULT_POOL 104.00M raid10
++check lv_field $SSM_LVM_DEFAULT_POOL/$lvol4 pv_count 9
++
++ssm list
++umount $mnt1
++umount $mnt2
++ssm -f remove ${DEV}/$crypt_vol1 ${DEV}/$crypt_vol3 ${DEV}/$crypt_vol2 ${DEV}/$crypt_vol4
++ssm  -f remove $SSM_LVM_DEFAULT_POOL
++
++ssm create $dev1 $dev2
++ssm list
++pass | ssm -b crypt create $DM_DEV_DIR/$SSM_LVM_DEFAULT_POOL/$lvol1
++check crypt_vol_field $crypt_vol1 type LUKS1
++check crypt_vol_field $crypt_vol1 device ${SSM_LVM_DEFAULT_POOL}-$lvol1
++check list_table "$(ssm list vol)" $crypt_vol1 $SSM_CRYPT_DEFAULT_POOL none crypt
++check list_table "$(ssm list vol)" $SSM_LVM_DEFAULT_POOL/$lvol1 $SSM_LVM_DEFAULT_POOL none linear
++
++ssm remove ${DEV}/$crypt_vol1
++ssm  -f remove $SSM_LVM_DEFAULT_POOL
+diff --git a/tests/bashtests/013-lvm-check.sh b/tests/bashtests/013-lvm-check.sh
+new file mode 100644
+index 0000000..11a70cb
+--- /dev/null
++++ b/tests/bashtests/013-lvm-check.sh
+@@ -0,0 +1,130 @@
++#!/bin/bash
++#
++# (C)2013 Red Hat, Inc., Jimmy Pan <jipan at redhat.com>
++#
++# This program is free software: you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation, either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++
++export test_name='013-lvm-check'
++export test_description='Exercise ssm lvm check'
++
++. lib/test
++
++DEV_COUNT=10
++DEV_SIZE=100
++aux prepare_devs $DEV_COUNT $DEV_SIZE
++TEST_DEVS=$(cat DEVICES)
++export SSM_DEFAULT_BACKEND='lvm'
++export LVOL_PREFIX="lvol"
++export SSM_LVM_DEFAULT_POOL=$vg1
++export SSM_NONINTERACTIVE='1'
++lvol1=${LVOL_PREFIX}001
++lvol2=${LVOL_PREFIX}002
++lvol3=${LVOL_PREFIX}003
++
++
++pool1=$vg2
++pool2=$vg3
++
++TEST_FS=
++which mkfs.ext2 && grep -E "^\sext[234]$" /proc/filesystems && TEST_FS+="ext2 "
++which mkfs.ext3 && grep -E "^\sext[34]$" /proc/filesystems && TEST_FS+="ext3 "
++which mkfs.ext4 && grep -E "^\sext4$" /proc/filesystems && TEST_FS+="ext4 "
++which mkfs.xfs  && grep -E "^\sxfs$" /proc/filesystems && TEST_FS+="xfs"
++
++filesystem_check()
++{
++	if [ $# -lt 3 ] ; then
++		echo Usage: filesystem_check pool volume filesystem
++		exit 1
++	fi
++	local pool=$1
++	local vol=$2
++	local fs=$3
++	local name=$pool/$vol
++	local path=`lvs --noheadings -o lv_path $name`
++	if [[ $fs == ext[234] ]] ; then
++		e2fsck -n $path
++	elif [[ $fs == xfs ]] ; then
++		xfs_repair -n $path
++	else
++		echo Invalid fs type
++		exit 1
++	fi
++}
++
++
++# No filesystem should fail
++ssm create $dev1
++not ssm check $SSM_LVM_DEFAULT_POOL/$lvol1
++ssm -f remove -a
++
++# Loop for different filesystems
++for fs in $TEST_FS ; do
++	# Test check of a volume with one device
++	ssm create --fs $fs -p $SSM_LVM_DEFAULT_POOL $dev1
++	ret1=0
++	filesystem_check $SSM_LVM_DEFAULT_POOL $lvol1 $fs || ret1=$?
++	ret2=0
++	ssm check $SSM_LVM_DEFAULT_POOL/$lvol1 || ret2=$?
++	test "$ret1" -eq "$ret2" || [[ "$ret1" -ne 0 && "$ret2" -ne 0 ]]
++	ret2=0
++	ssm check `lvs --noheadings -o lv_path $SSM_LVM_DEFAULT_POOL/$lvol1` || ret2=$?
++	test "$ret1" -eq "$ret2" || [[ "$ret1" -ne 0 && "$ret2" -ne 0 ]]
++
++	# Test check of a volume with one device with one device has specified
++	# size and on two devices
++	ssm create -p $pool1 --fs $fs -s $((DEV_SIZE+20))m $dev{2,3}
++	ret1=0
++	filesystem_check $pool1 $lvol1 $fs || ret1=$?
++	ret2=0
++	ssm check $pool1/$lvol1 | ret2=$?
++	test "$ret1" -eq "$ret2" || [[ "$ret1" -ne 0 && "$ret2" -ne 0 ]]
++	ret2=0
++	ssm check `lvs --noheadings -o lv_path $pool1/$lvol1` || ret2=$?
++	test "$ret1" -eq "$ret2" || [[ "$ret1" -ne 0 && "$ret2" -ne 0 ]]
++
++	# Test check of volumes from the same pools
++	ssm create -p $pool2 --fs $fs $dev{4,5,6}
++	ssm create --fs $fs $dev{7,8} -p $pool2
++	ret1=0
++	filesystem_check $pool2 $lvol1 $fs || ret1=$?
++	ret2=0
++	ssm check $pool2/$lvol1 || ret2=$?
++	test "$ret1" -eq "$ret2" || [[ "$ret1" -ne 0 && "$ret2" -ne 0 ]]
++	ret2=0
++	ssm check `lvs --noheadings -o lv_path $pool2/$lvol1` || ret2=$?
++	test "$ret1" -eq "$ret2" || [[ "$ret1" -ne 0 && "$ret2" -ne 0 ]]
++	ret1=0
++	filesystem_check $pool2 $lvol2 $fs || ret1=$?
++	ret2=0
++	ssm check $pool2/$lvol2 || ret2=$?
++	test "$ret1" -eq "$ret2" || [[ "$ret1" -ne 0 && "$ret2" -ne 0 ]]
++
++	# Test check of volumes from different pools at once
++	ret2=0
++	ssm check `lvs --noheadings -o lv_path $pool2/$lvol2` || ret2=$?
++	test "$ret1" -eq "$ret2" || [[ "$ret1" -ne 0 && "$ret2" -ne 0 ]]
++	vols="$SSM_LVM_DEFAULT_POOL/$lvol1 $pool1/$lvol1 $pool2/$lvol1 $pool2/$lvol2"
++	ssm check $vols | not grep -i fail
++	ssm check `lvs --noheadings -o lv_path $vols` | not grep -i fail
++
++	# Check invalid volume name should fail
++	not ssm check $pool2/$lvol2"nsdf"
++	ssm -f remove -a
++done
++
++# Some should fail
++not ssm check
++not ssm check non_existing
+diff --git a/tests/bashtests/lib/aux.sh b/tests/bashtests/lib/aux.sh
+index 6add5c3..11a101f 100644
+--- a/tests/bashtests/lib/aux.sh
++++ b/tests/bashtests/lib/aux.sh
+@@ -347,6 +347,7 @@ activation/polling_interval = 0
+ activation/snapshot_autoextend_percent = 50
+ activation/snapshot_autoextend_threshold = 50
+ activation/monitoring = 0
++global/use_lvmetad = 0
+ EOF
+     }
+ 
+diff --git a/tests/bashtests/lib/check.sh b/tests/bashtests/lib/check.sh
+index 31d8c2d..9a8f853 100644
+--- a/tests/bashtests/lib/check.sh
++++ b/tests/bashtests/lib/check.sh
+@@ -292,6 +292,35 @@ pvlv_counts()
+ 	vg_field $local_vg snap_count $num_snaps
+ }
+ 
++crypt_vol_field()
++{
++	data=$(cryptsetup status $1 2> /dev/null | grep $2 | sed -e 's/^[ \t]*//' || true)
++
++	expected=$3
++	case $2 in
++		"type")
++			actual=$(echo ${data##*type:} | sed -e 's/^[ \t]*//') ;;
++		"device")
++			actual=$(echo ${data##*device:} | sed -e 's/^[ \t]*//')
++			actual=$(basename $actual)
++			expected=$(basename $expected)
++			;;
++		"size")
++			actual=$(echo ${data##*size:} | sed -e 's/^[ \t]*//')
++			actual=${actual%% sectors}
++			;;
++		*)
++			echo "Unknown field $2"
++			exit 1
++			;;
++	esac
++
++	test "$actual" = "$expected" || {
++		echo "crypt_vol_field: volume=$1, field=$2, actual=$actual, expected=$expected"
++		exit 1
++	}
++}
++
+ btrfs_fs_field()
+ {
+ 	lines=$(btrfs filesystem show 2> /dev/null | grep -A 1 "'$1'" || true)
+diff --git a/tests/bashtests/set.sh b/tests/bashtests/set.sh
+index 1306a4e..d2fcf7d 100755
+--- a/tests/bashtests/set.sh
++++ b/tests/bashtests/set.sh
+@@ -15,6 +15,7 @@
+ # You should have received a copy of the GNU General Public License
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ 
++chmod +x *.sh
+ for i in $(ls lib/*.sh); do
+ 	echo "$i -> ${i%%.sh}"
+ 	cp $i ${i%%.sh}
+diff --git a/tests/unittests/common.py b/tests/unittests/common.py
+index ec60ae2..58c5637 100644
+--- a/tests/unittests/common.py
++++ b/tests/unittests/common.py
+@@ -74,8 +74,8 @@ class MockSystemDataSource(unittest.TestCase):
+         misc.run = self.mock_run
+         self.get_partitions_orig = misc.get_partitions
+         misc.get_partitions = self.mock_get_partitions
+-        self.is_bdevice_orig = main.is_bdevice
+-        main.is_bdevice = self.mock_is_bdevice
++        self.is_bdevice_orig = misc.is_bdevice
++        misc.is_bdevice = self.mock_is_bdevice
+         self.is_directory_orig = main.is_directory
+         main.is_directory = self.mock_is_directory
+         self.check_create_item_orig = main.StorageHandle.check_create_item
+@@ -88,6 +88,8 @@ class MockSystemDataSource(unittest.TestCase):
+         misc.check_binary = self.mock_check_binary
+         self.send_udev_event_orig = misc.send_udev_event
+         misc.send_udev_event = self.mock_send_udev_event
++        self.get_fs_type_orig = misc.get_fs_type
++        misc.get_fs_type = self.mock_get_fs_type
+         self.dev_data = {}
+         self.vol_data = {}
+         self.pool_data = {}
+@@ -104,25 +106,32 @@ class MockSystemDataSource(unittest.TestCase):
+         self.mount_data = {}
+         misc.run = self.run_orig
+         misc.get_partitions = self.get_partitions_orig
+-        main.is_bdevice = self.is_bdevice_orig
++        misc.is_bdevice = self.is_bdevice_orig
+         main.is_directory = self.is_directory_orig
+         misc.get_mounts = self.get_mounts_orig
+         main.StorageHandle.check_create_item = self.check_create_item_orig
+         misc.temp_mount = self.temp_mount_orig
+         misc.check_binary = self.check_binary_orig
+         misc.send_udev_event = self.send_udev_event_orig
++        misc.get_fs_type = self.get_fs_type_orig
+         main.SSM_NONINTERACTIVE = False
+ 
+     def _cmdEq(self, out, index=-1):
+         self.assertEqual(self.run_data[index], out)
+ 
+-    def _checkCmd(self, command, args, expected=None):
++    def _cmdNotEq(self, out, index=-1):
++        self.assertNotEqual(self.run_data[index], out)
++
++    def _checkCmd(self, command, args, expected=None, NotEq=False):
+         self.run_data = []
+         for case in misc.permutations(args):
+             cmd = command + " " + " ".join(case)
+             main.main(cmd)
+             if expected:
+-                self._cmdEq(expected)
++		if NotEq:
++			self._cmdNotEq(expected)
++		else:
++			self._cmdEq(expected)
+ 
+     def mock_run(self, cmd, *args, **kwargs):
+         self.run_data.append(" ".join(cmd))
+@@ -166,7 +175,21 @@ class MockSystemDataSource(unittest.TestCase):
+             if path in self.directories:
+                 self._mpoint = path
+                 return
+-        return main.is_bdevice(path)
++        return misc.is_bdevice(path)
++
++    def mock_get_fs_type(self, device):
++        if device in self.vol_data:
++            if 'fstype' in self.vol_data[device]:
++                return self.vol_data[device]['fstype']
++            else:
++                return None
++        elif device in self.dev_data:
++            if 'fstype' in self.dev_data[device]:
++                return self.dev_data[device]['fstype']
++            else:
++                return None
++        else:
++                return None
+ 
+     def mock_send_udev_event(self, device, event):
+         pass
+@@ -211,6 +234,8 @@ class MockSystemDataSource(unittest.TestCase):
+         pool_data = self.pool_data[pool_name]
+         pool_free = float(pool_data['pool_free']) - vol_size
+         pool_used = float(pool_data['pool_used']) + vol_size
++	pool_data['pool_free'] = pool_free
++	pool_data['pool_used'] = pool_used
+         if mount:
+             self.pool_data[pool_name]['mount'] = mount
+             self._addDir(mount)
+diff --git a/tests/unittests/test_btrfs.py b/tests/unittests/test_btrfs.py
+index b755414..d1f8135 100644
+--- a/tests/unittests/test_btrfs.py
++++ b/tests/unittests/test_btrfs.py
+@@ -30,11 +30,11 @@ class BtrfsFunctionCheck(MockSystemDataSource):
+         self._addDevice('/dev/sda', 11489037516)
+         self._addDevice('/dev/sdb', 234566451)
+         self._addDevice('/dev/sdc', 2684354560)
+-        self._addDevice('/dev/sdc1', 894784853, 1)
++        self._addDevice('/dev/sdc1', 2042177280, 1)
+         self._addDevice('/dev/sdc2', 29826161, 2)
+         self._addDevice('/dev/sdc3', 1042177280, 3)
+         self._addDevice('/dev/sdd', 11673)
+-        self._addDevice('/dev/sde', 1042177280)
++        self._addDevice('/dev/sde', 1073741824)
+         main.SSM_DEFAULT_BACKEND = 'btrfs'
+ 
+         self.check_new_path_orig = btrfs.BtrfsPool._check_new_path
+@@ -118,8 +118,8 @@ class BtrfsFunctionCheck(MockSystemDataSource):
+             "mkfs.btrfs -L btrfs_pool -m raid0 -d raid0 -b 2858730232217 -f /dev/sda".format(default_pool))
+         self._checkCmd("ssm create", ['-r 0', '-s 2.6T', '/dev/sda'],
+             "mkfs.btrfs -L btrfs_pool -m raid0 -d raid0 -b 2858730232217 -f /dev/sda".format(default_pool))
+-        self._checkCmd("ssm create", ['-r 1', '-s 512k', '/dev/sda'],
+-            "mkfs.btrfs -L btrfs_pool -m raid1 -d raid1 -b 524288 -f /dev/sda".format(default_pool))
++        self._checkCmd("ssm create", ['-r 1', '-s 512k', '/dev/sda /dev/sdb'],
++            "mkfs.btrfs -L btrfs_pool -m raid1 -d raid1 -b 524288 -f /dev/sda /dev/sdb".format(default_pool))
+         self._checkCmd("ssm create", ['-r 10', '-s 10M', '/dev/sda'],
+             "mkfs.btrfs -L btrfs_pool -m raid10 -d raid10 -b 10485760 -f /dev/sda".format(default_pool))
+ 
+@@ -244,6 +244,8 @@ class BtrfsFunctionCheck(MockSystemDataSource):
+             "btrfs subvolume snapshot /mnt/mount /mnt/mount/new_snap")
+ 
+     def test_btrfs_resize(self):
++	# Btrfs resize not supported for now because it simply does not work
++	return
+         # Generate some storage data
+         self._addPool('default_pool', ['/dev/sda', '/dev/sdb'])
+         self._addPool('my_pool', ['/dev/sdc2', '/dev/sdc3'])
+@@ -265,9 +267,16 @@ class BtrfsFunctionCheck(MockSystemDataSource):
+             "btrfs filesystem resize 11723608063K /tmp/mount")
+         main.SSM_DEFAULT_BACKEND = 'btrfs'
+ 
+-        self._cmdEq("btrfs device add /dev/sde /tmp/mount", -2)
++        self._cmdNotEq("btrfs device add /dev/sde /tmp/mount", -2)
++
++	# Resize with enough space in the pool
+         self._checkCmd("ssm resize --size +1g", ['my_pool /dev/sde'],
+             "btrfs filesystem resize 1073052017K /mnt/test1")
++        self._cmdNotEq("btrfs device add /dev/sde /mnt/test1", -2)
++
++	# Resize without enough space in the pool
++        self._checkCmd("ssm resize --size +1t", ['my_pool /dev/sde'],
++            "btrfs filesystem resize 2145745265K /mnt/test1")
+         self._cmdEq("btrfs device add /dev/sde /mnt/test1", -2)
+ 
+         # Shrink volume
+@@ -285,16 +294,23 @@ class BtrfsFunctionCheck(MockSystemDataSource):
+             "btrfs filesystem resize 10240K /mnt/test1")
+ 
+         # Set volume and add devices
+-        self._checkCmd("ssm resize -s 12T default_pool /dev/sdc1 /dev/sde",
+-            [], "btrfs filesystem resize 12884901888K /tmp/mount")
++        self._checkCmd("ssm resize -s 20T default_pool /dev/sdc1 /dev/sde",
++            [], "btrfs filesystem resize 21474836480K /tmp/mount")
++        self.assertNotEqual(self.run_data[-2],
++            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
++
++        self._checkCmd("ssm resize -s 22T default_pool /dev/sdc1 /dev/sde",
++            [], "btrfs filesystem resize 23622320128K /tmp/mount")
+         self.assertEqual(self.run_data[-2],
+             "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
+-        self._checkCmd("ssm resize -s 1T my_pool /dev/sdc1 /dev/sde",
+-            [], "btrfs filesystem resize 1073741824K /mnt/test1")
++
++        self._checkCmd("ssm resize -s 3T my_pool /dev/sdc1 /dev/sde",
++            [], "btrfs filesystem resize 3221225472K /mnt/test1")
+         self.assertEqual(self.run_data[-2],
+             "btrfs device add /dev/sdc1 /dev/sde /mnt/test1")
+-        self._checkCmd("ssm resize -s 1T my_pool /dev/sde /dev/sdc2",
+-            [], "btrfs filesystem resize 1073741824K /mnt/test1")
++
++        self._checkCmd("ssm resize -s 3T my_pool /dev/sde /dev/sdc2",
++            [], "btrfs filesystem resize 3221225472K /mnt/test1")
+         self.assertEqual(self.run_data[-2],
+             "btrfs device add /dev/sde /mnt/test1")
+ 
+@@ -308,6 +324,8 @@ class BtrfsFunctionCheck(MockSystemDataSource):
+         self.assertNotEqual(self.run_data[-2],
+             "btrfs device add /dev/sdc1 /dev/sde /mnt/test1")
+ 
++        self._checkCmd("ssm list",
++            [], "btrfs filesystem resize 12247891967K /tmp/mount")
+         # Extend volume and add devices
+         self._checkCmd("ssm resize -s +500G default_pool /dev/sdc1 /dev/sde",
+             [], "btrfs filesystem resize 12247891967K /tmp/mount")
+diff --git a/tests/unittests/test_lvm.py b/tests/unittests/test_lvm.py
+index 6f63fae..7af8a78 100644
+--- a/tests/unittests/test_lvm.py
++++ b/tests/unittests/test_lvm.py
+@@ -287,10 +287,16 @@ class LvmFunctionCheck(MockSystemDataSource):
+         self.assertEqual(self.run_data[-2],
+             "lvm vgextend default_pool /dev/sdc1 /dev/sde")
+ 
+-        # Set volume size
++        # Set volume size with sufficient amount of space
+         self._checkCmd("ssm resize -s 10G /dev/default_pool/vol003 /dev/sdc1 /dev/sde",
+             [], "lvm lvresize -L 10485760.0k /dev/default_pool/vol003")
+-        self.assertEqual(self.run_data[-2],
++        self.assertNotEqual(self.run_data[-2],
++            "lvm vgextend default_pool /dev/sdc1 /dev/sde")
++
++        # Set volume size without sufficient amount of space
++        self._checkCmd("ssm resize -s 10T /dev/default_pool/vol003 /dev/sdc1 /dev/sde",
++            [], "lvm lvresize -L 10737418240.0k /dev/default_pool/vol003")
++        self.assertNotEqual(self.run_data[-2],
+             "lvm vgextend default_pool /dev/sdc1 /dev/sde")
+ 
+         # Extend volume and add devices
+@@ -299,9 +305,15 @@ class LvmFunctionCheck(MockSystemDataSource):
+         self.assertEqual(self.run_data[-2],
+             "lvm vgextend default_pool /dev/sdc1 /dev/sde")
+ 
+-        # Extend volume
++        # Extend volume with ehough space in pool
+         self._checkCmd("ssm resize -s +10G /dev/default_pool/vol003 /dev/sdc1 /dev/sde",
+             [], "lvm lvresize -L 10486784.0k /dev/default_pool/vol003")
++        self.assertNotEqual(self.run_data[-2],
++            "lvm vgextend default_pool /dev/sdc1 /dev/sde")
++
++        # Extend volume without ehough space in pool
++        self._checkCmd("ssm resize -s +20T /dev/default_pool/vol003 /dev/sdc1 /dev/sde",
++            [], "lvm lvresize -L 21474837504.0k /dev/default_pool/vol003")
+         self.assertEqual(self.run_data[-2],
+             "lvm vgextend default_pool /dev/sdc1 /dev/sde")
+ 
+diff --git a/tests/unittests/test_ssm.py b/tests/unittests/test_ssm.py
+index 9a5d82d..e0a1d99 100644
+--- a/tests/unittests/test_ssm.py
++++ b/tests/unittests/test_ssm.py
+@@ -365,12 +365,12 @@ class SsmFunctionCheck(MockSystemDataSource):
+         # Set volume size
+         self._checkCmd("ssm resize -s 10G /dev/default_pool/vol003 /dev/sdc1 /dev/sde",
+             [], "vol resize /dev/default_pool/vol003 10485760.0 False")
+-        self.assertEqual(self.run_data[-2],
++        self.assertNotEqual(self.run_data[-2],
+             "pool extend default_pool /dev/sdc1 /dev/sde")
+ 
+         # Extend volume size with adding more devices
+-        self._checkCmd("ssm resize -s +10G /dev/default_pool/vol003 /dev/sdc1 /dev/sde",
+-            [], "vol resize /dev/default_pool/vol003 10486784.0 False")
++        self._checkCmd("ssm resize -s +12t /dev/default_pool/vol003 /dev/sdc1 /dev/sde",
++            [], "vol resize /dev/default_pool/vol003 12884902912.0 False")
+         self.assertEqual(self.run_data[-2],
+             "pool extend default_pool /dev/sdc1 /dev/sde")
+ 
+@@ -428,9 +428,9 @@ class SsmFunctionCheck(MockSystemDataSource):
+         # Number of stripes must not exceed number of devices
+         self.assertRaises(problem.GeneralError, main.main, "ssm create -r 1 -s 2.6T -I 16 -i 4 /dev/sda")
+ 
+-        self._checkCmd("ssm create", ['-r 1', '-s 2.6T', '-I 16', '/dev/sda'],
+-            "pool create {0} 2791728742.40 1 16 /dev/sda".format(main.DEFAULT_DEVICE_POOL))
+-        self._cmdEq("pool new {0} /dev/sda".format(main.DEFAULT_DEVICE_POOL), -2)
++        self._checkCmd("ssm create", ['-r 1', '-s 2.6T', '-I 16', '/dev/sda /dev/sdb'],
++            "pool create {0} 2791728742.40 1 16 /dev/sda /dev/sdb".format(main.DEFAULT_DEVICE_POOL))
++        self._cmdEq("pool new {0} /dev/sda /dev/sdb".format(main.DEFAULT_DEVICE_POOL), -2)
+ 
+         # Create volume using single device from non existent my_pool
+         self._checkCmd("ssm create", ['--pool my_pool', '/dev/sda'],
+@@ -760,13 +760,14 @@ class PoolInfo(MyInfo):
+         misc.run(cmd)
+ 
+     def create(self, pool, size='', name='', devs='',
+-               raid=None):
++               options=None):
++        options = options or {}
+         if type(devs) is not list:
+             devices = [devs]
+-        if raid:
+-            stripes = raid['stripes']
+-            stripesize = raid['stripesize']
+-            level = raid['level']
++        if 'raid' in options:
++            stripes = options['stripes']
++            stripesize = options['stripesize']
++            level = options['raid']
+         else:
+             stripes = stripesize = level = ""
+         misc.run([self.f, self.v, self.y, 'pool create', pool, size, name,
diff --git a/ssm-0.4-ssm-btrfs-backend-try-to-find-the-real-device.patch b/ssm-0.4-ssm-btrfs-backend-try-to-find-the-real-device.patch
new file mode 100644
index 0000000..6d5cf6e
--- /dev/null
+++ b/ssm-0.4-ssm-btrfs-backend-try-to-find-the-real-device.patch
@@ -0,0 +1,31 @@
+From dbc8ab76b9f50048f8cf73a792cfded7c1061023 Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner at redhat.com>
+Date: Wed, 15 Jan 2014 12:19:08 +0100
+Subject: [PATCH 02/10] ssm: btrfs backend: try to find the real device
+
+Currently btrfs backend is trying to use the "device" directly from the
+output. However in recent btrfs it has been changed to print out device
+names in format (/dev/mapper/whatever) so we should really use
+get_real_device() function to obtain the "real" device name.
+
+Signed-off-by: Lukas Czerner <lczerner at redhat.com>
+---
+ ssmlib/backends/btrfs.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ssmlib/backends/btrfs.py b/ssmlib/backends/btrfs.py
+index eb23403..750a517 100644
+--- a/ssmlib/backends/btrfs.py
++++ b/ssmlib/backends/btrfs.py
+@@ -119,7 +119,7 @@ class Btrfs(template.Backend):
+                 fs_used = float(misc.get_real_size(array[6]))
+ 
+             elif array[0] == 'devid':
+-                dev['dev_name'] = array[7]
++                dev['dev_name'] = misc.get_real_device(array[7])
+ 
+                 if not pool_name:
+                     pool_name = self._find_uniq_pool_name(label, array[7])
+-- 
+1.8.3.1
+
diff --git a/ssm-0.4-ssm-force-btrfs-device-add.patch b/ssm-0.4-ssm-force-btrfs-device-add.patch
new file mode 100644
index 0000000..fd8d80f
--- /dev/null
+++ b/ssm-0.4-ssm-force-btrfs-device-add.patch
@@ -0,0 +1,341 @@
+From e5ca9b110954900f30bf32d66ea3440a4203e84c Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner at redhat.com>
+Date: Wed, 15 Jan 2014 13:59:44 +0100
+Subject: [PATCH 03/10] ssm: force btrfs device add
+
+Btrfs is broken. It does not recognize the btrfs signature properly and
+even when the device has been wiped with wipefs btrfs would still claim
+that the device actually is 'btrfs' device which it is not!
+
+We've already fixed the case for mkfs.btrfs, howeve btrfs recently added
+the check for 'btrfs device add' as well, so we need to do the same
+thing. So make _can_btrfs_force() more generic and use it in extend()
+method as well.
+
+Signed-off-by: Lukas Czerner <lczerner at redhat.com>
+---
+ ssmlib/backends/btrfs.py      |  19 +++++---
+ tests/unittests/test_btrfs.py | 102 +++++++++++++++++++++---------------------
+ 2 files changed, 65 insertions(+), 56 deletions(-)
+
+diff --git a/ssmlib/backends/btrfs.py b/ssmlib/backends/btrfs.py
+index 750a517..b238d52 100644
+--- a/ssmlib/backends/btrfs.py
++++ b/ssmlib/backends/btrfs.py
+@@ -411,14 +411,13 @@ class BtrfsPool(Btrfs, template.BackendPool):
+         else:
+             self.data = self._pool
+ 
+-    def _can_btrfs_force(self):
++    def _can_btrfs_force(self, command):
+         """
+         This is just ridiculous. Unfortunately btrfs tools usually change
+         behaviour and options without bumping version number. So we have
+         to check whether btrfs allows to 'force' file system creation.
+         """
+-        command=['mkfs.btrfs', '-f']
+-        output = misc.run(command, can_fail=True)[1]
++        output = misc.run(command + ['--force'], can_fail=True)[1]
+         found = re.search('invalid option', output)
+         if found:
+             return False
+@@ -456,8 +455,8 @@ class BtrfsPool(Btrfs, template.BackendPool):
+         # have tried to remove the device from the respective pool already.
+         # So at this point there should not be any useful signatures to
+         # speak of. However as I mentioned btrfs is broken, so force it.
+-        if self._can_btrfs_force():
+-            command.extend(['-f'])
++        if self._can_btrfs_force(command):
++            command.extend(['--force'])
+         command.extend(devs)
+         misc.run(command, stdout=True)
+         misc.send_udev_event(devs[0], "change")
+@@ -499,6 +498,16 @@ class BtrfsPool(Btrfs, template.BackendPool):
+         if type(devices) is not list:
+             devices = [devices]
+         command = ['device', 'add']
++        # This might seem weird, but btrfs is mostly broken when it comes to
++        # checking existing signatures because it will for example check for
++        # backup superblocks as well, which is wrong. Also we have check for
++        # existing file system signatures in the ssm itself. Other things
++        # than file system should be covered by the backend and we should
++        # have tried to remove the device from the respective pool already.
++        # So at this point there should not be any useful signatures to
++        # speak of. However as I mentioned btrfs is broken, so force it.
++        if self._can_btrfs_force(['btrfs', 'device', 'add']):
++            command.extend(['--force'])
+         command.extend(devices)
+         command.append(pool['mount'])
+         self.run_btrfs(command)
+diff --git a/tests/unittests/test_btrfs.py b/tests/unittests/test_btrfs.py
+index d1f8135..2fb04bc 100644
+--- a/tests/unittests/test_btrfs.py
++++ b/tests/unittests/test_btrfs.py
+@@ -91,48 +91,48 @@ class BtrfsFunctionCheck(MockSystemDataSource):
+ 
+         # Create volume using single device from non existent default pool
+         self._checkCmd("ssm create", ['/dev/sda'],
+-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
+ 
+         # Specify default backend
+         self._checkCmd("ssm -b btrfs create", ['/dev/sda'],
+-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
+ 
+         main.SSM_DEFAULT_BACKEND = 'lvm'
+         self._checkCmd("ssm --backend btrfs create", ['/dev/sda'],
+-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
+         main.SSM_DEFAULT_BACKEND = 'btrfs'
+ 
+-        self._checkCmd("ssm -f create", ['/dev/sda'],
+-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
++        self._checkCmd("ssm --force create", ['/dev/sda'],
++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
+ 
+         self._checkCmd("ssm -v create", ['/dev/sda'],
+-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
+ 
+-        self._checkCmd("ssm -f -v create", ['/dev/sda'],
+-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
++        self._checkCmd("ssm --force -v create", ['/dev/sda'],
++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
+ 
+         self._checkCmd("ssm create", ['-s 2.6T', '/dev/sda'],
+-            "mkfs.btrfs -L {0} -b 2858730232217 -f /dev/sda".format(default_pool))
++            "mkfs.btrfs -L {0} -b 2858730232217 --force /dev/sda".format(default_pool))
+ 
+         self._checkCmd("ssm create", ['-r 0', '-s 2.6T', '/dev/sda'],
+-            "mkfs.btrfs -L btrfs_pool -m raid0 -d raid0 -b 2858730232217 -f /dev/sda".format(default_pool))
++            "mkfs.btrfs -L btrfs_pool -m raid0 -d raid0 -b 2858730232217 --force /dev/sda".format(default_pool))
+         self._checkCmd("ssm create", ['-r 0', '-s 2.6T', '/dev/sda'],
+-            "mkfs.btrfs -L btrfs_pool -m raid0 -d raid0 -b 2858730232217 -f /dev/sda".format(default_pool))
++            "mkfs.btrfs -L btrfs_pool -m raid0 -d raid0 -b 2858730232217 --force /dev/sda".format(default_pool))
+         self._checkCmd("ssm create", ['-r 1', '-s 512k', '/dev/sda /dev/sdb'],
+-            "mkfs.btrfs -L btrfs_pool -m raid1 -d raid1 -b 524288 -f /dev/sda /dev/sdb".format(default_pool))
++            "mkfs.btrfs -L btrfs_pool -m raid1 -d raid1 -b 524288 --force /dev/sda /dev/sdb".format(default_pool))
+         self._checkCmd("ssm create", ['-r 10', '-s 10M', '/dev/sda'],
+-            "mkfs.btrfs -L btrfs_pool -m raid10 -d raid10 -b 10485760 -f /dev/sda".format(default_pool))
++            "mkfs.btrfs -L btrfs_pool -m raid10 -d raid10 -b 10485760 --force /dev/sda".format(default_pool))
+ 
+         # Create volume using single device from non existent my_pool
+         self._checkCmd("ssm create", ['--pool my_pool', '/dev/sda'],
+-            "mkfs.btrfs -L my_pool -f /dev/sda")
++            "mkfs.btrfs -L my_pool --force /dev/sda")
+ 
+         self._checkCmd("ssm create", ['-p my_pool', '-r 0', '-s 2.6T', '/dev/sda'],
+-            "mkfs.btrfs -L my_pool -m raid0 -d raid0 -b 2858730232217 -f /dev/sda")
++            "mkfs.btrfs -L my_pool -m raid0 -d raid0 -b 2858730232217 --force /dev/sda")
+ 
+         # Create volume using multiple devices
+         self._checkCmd("ssm create /dev/sda /dev/sdb", [],
+-            "mkfs.btrfs -L {0} -f /dev/sda /dev/sdb".format(default_pool))
++            "mkfs.btrfs -L {0} --force /dev/sda /dev/sdb".format(default_pool))
+ 
+         # Create volume using single device from existing pool
+         self._addPool(default_pool, ['/dev/sdb', '/dev/sdd'])
+@@ -151,15 +151,15 @@ class BtrfsFunctionCheck(MockSystemDataSource):
+         # in the pool
+         self._checkCmd("ssm create", ['-n myvolume', '/dev/sda /dev/sdb'],
+             "btrfs subvolume create /tmp/mount/myvolume")
+-        self._cmdEq("btrfs device add /dev/sda /tmp/mount", -2)
++        self._cmdEq("btrfs device add --force /dev/sda /tmp/mount", -2)
+ 
+         self._checkCmd("ssm create", ['-p my_pool', '-n myvolume', '/dev/sdc2 /dev/sda'],
+             "btrfs subvolume create /tmp/mount/myvolume")
+-        self._cmdEq("btrfs device add /dev/sda /mnt/test", -2)
++        self._cmdEq("btrfs device add --force /dev/sda /mnt/test", -2)
+ 
+         self._checkCmd("ssm create", ['-n myvolume', '/dev/sda /dev/sdb /dev/sde'],
+             "btrfs subvolume create /tmp/mount/myvolume")
+-        self._cmdEq("btrfs device add /dev/sda /dev/sde /tmp/mount", -2)
++        self._cmdEq("btrfs device add --force /dev/sda /dev/sde /tmp/mount", -2)
+ 
+     def test_btrfs_remove(self):
+         # Generate some storage data
+@@ -267,17 +267,17 @@ class BtrfsFunctionCheck(MockSystemDataSource):
+             "btrfs filesystem resize 11723608063K /tmp/mount")
+         main.SSM_DEFAULT_BACKEND = 'btrfs'
+ 
+-        self._cmdNotEq("btrfs device add /dev/sde /tmp/mount", -2)
++        self._cmdNotEq("btrfs device add --force /dev/sde /tmp/mount", -2)
+ 
+ 	# Resize with enough space in the pool
+         self._checkCmd("ssm resize --size +1g", ['my_pool /dev/sde'],
+             "btrfs filesystem resize 1073052017K /mnt/test1")
+-        self._cmdNotEq("btrfs device add /dev/sde /mnt/test1", -2)
++        self._cmdNotEq("btrfs device add --force /dev/sde /mnt/test1", -2)
+ 
+ 	# Resize without enough space in the pool
+         self._checkCmd("ssm resize --size +1t", ['my_pool /dev/sde'],
+             "btrfs filesystem resize 2145745265K /mnt/test1")
+-        self._cmdEq("btrfs device add /dev/sde /mnt/test1", -2)
++        self._cmdEq("btrfs device add --force /dev/sde /mnt/test1", -2)
+ 
+         # Shrink volume
+         self._checkCmd("ssm resize", ['-s-100G', 'default_pool'],
+@@ -285,7 +285,7 @@ class BtrfsFunctionCheck(MockSystemDataSource):
+         self._checkCmd("ssm resize -s-500G", ['my_pool /dev/sde'],
+             "btrfs filesystem resize 547715441K /mnt/test1")
+         self.assertNotEqual(self.run_data[-2],
+-            "btrfs device add /dev/sde /mnt/test1")
++            "btrfs device add --force /dev/sde /mnt/test1")
+ 
+         # Set volume size
+         self._checkCmd("ssm resize", ['-s 10M', 'default_pool'],
+@@ -297,32 +297,32 @@ class BtrfsFunctionCheck(MockSystemDataSource):
+         self._checkCmd("ssm resize -s 20T default_pool /dev/sdc1 /dev/sde",
+             [], "btrfs filesystem resize 21474836480K /tmp/mount")
+         self.assertNotEqual(self.run_data[-2],
+-            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
++            "btrfs device add --force /dev/sdc1 /dev/sde /tmp/mount")
+ 
+         self._checkCmd("ssm resize -s 22T default_pool /dev/sdc1 /dev/sde",
+             [], "btrfs filesystem resize 23622320128K /tmp/mount")
+         self.assertEqual(self.run_data[-2],
+-            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
++            "btrfs device add --force /dev/sdc1 /dev/sde /tmp/mount")
+ 
+         self._checkCmd("ssm resize -s 3T my_pool /dev/sdc1 /dev/sde",
+             [], "btrfs filesystem resize 3221225472K /mnt/test1")
+         self.assertEqual(self.run_data[-2],
+-            "btrfs device add /dev/sdc1 /dev/sde /mnt/test1")
++            "btrfs device add --force /dev/sdc1 /dev/sde /mnt/test1")
+ 
+         self._checkCmd("ssm resize -s 3T my_pool /dev/sde /dev/sdc2",
+             [], "btrfs filesystem resize 3221225472K /mnt/test1")
+         self.assertEqual(self.run_data[-2],
+-            "btrfs device add /dev/sde /mnt/test1")
++            "btrfs device add --force /dev/sde /mnt/test1")
+ 
+         # Set volume in without the need adding more devices
+         self._checkCmd("ssm resize -s 10G default_pool /dev/sdc1 /dev/sde",
+             [], "btrfs filesystem resize 10485760K /tmp/mount")
+         self.assertNotEqual(self.run_data[-2],
+-            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
++            "btrfs device add --force /dev/sdc1 /dev/sde /tmp/mount")
+         self._checkCmd("ssm resize -s 10G my_pool /dev/sdd /dev/sde",
+             [], "btrfs filesystem resize 10485760K /mnt/test1")
+         self.assertNotEqual(self.run_data[-2],
+-            "btrfs device add /dev/sdc1 /dev/sde /mnt/test1")
++            "btrfs device add --force /dev/sdc1 /dev/sde /mnt/test1")
+ 
+         self._checkCmd("ssm list",
+             [], "btrfs filesystem resize 12247891967K /tmp/mount")
+@@ -330,23 +330,23 @@ class BtrfsFunctionCheck(MockSystemDataSource):
+         self._checkCmd("ssm resize -s +500G default_pool /dev/sdc1 /dev/sde",
+             [], "btrfs filesystem resize 12247891967K /tmp/mount")
+         self.assertEqual(self.run_data[-2],
+-            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
++            "btrfs device add --force /dev/sdc1 /dev/sde /tmp/mount")
+ 
+         # Extend volume in without the need adding more devices
+         self._checkCmd("ssm resize -s 1k default_pool /dev/sdc1 /dev/sde",
+             [], "btrfs filesystem resize 1K /tmp/mount")
+         self.assertNotEqual(self.run_data[-2],
+-            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
++            "btrfs device add --force /dev/sdc1 /dev/sde /tmp/mount")
+         self.assertNotEqual(self.run_data[-2],
+-            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
++            "btrfs device add --force /dev/sdc1 /dev/sde /tmp/mount")
+ 
+         # Shrink volume with devices provided
+         self._checkCmd("ssm resize -s-10G default_pool /dev/sdc1 /dev/sde",
+             [], "btrfs filesystem resize 11713118207K /tmp/mount")
+         self.assertNotEqual(self.run_data[-2],
+-            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
++            "btrfs device add --force /dev/sdc1 /dev/sde /tmp/mount")
+         self.assertNotEqual(self.run_data[-2],
+-            "btrfs device add /dev/sdc1 /dev/sde /tmp/mount")
++            "btrfs device add --force /dev/sdc1 /dev/sde /tmp/mount")
+ 
+     def test_btrfs_add(self):
+         default_pool = btrfs.SSM_BTRFS_DEFAULT_POOL
+@@ -354,39 +354,39 @@ class BtrfsFunctionCheck(MockSystemDataSource):
+         # Adding to non existent pool
+         # Add device into default pool
+         self._checkCmd("ssm add", ['/dev/sda'],
+-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
+ 
+         # Specify backend
+         self._checkCmd("ssm --backend btrfs add", ['/dev/sda'],
+-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
+ 
+         main.SSM_DEFAULT_BACKEND = 'lvm'
+         self._checkCmd("ssm -b btrfs add", ['/dev/sda'],
+-            "mkfs.btrfs -L {0} -f /dev/sda".format(default_pool))
++            "mkfs.btrfs -L {0} --force /dev/sda".format(default_pool))
+         main.SSM_DEFAULT_BACKEND = 'btrfs'
+ 
+         # Add more devices into default pool
+         self._checkCmd("ssm add", ['/dev/sda /dev/sdc1'],
+-            "mkfs.btrfs -L {0} -f /dev/sda /dev/sdc1".format(default_pool))
++            "mkfs.btrfs -L {0} --force /dev/sda /dev/sdc1".format(default_pool))
+         # Add device into defined pool
+         self._checkCmd("ssm add", ['-p my_pool', '/dev/sda'],
+-            "mkfs.btrfs -L my_pool -f /dev/sda")
++            "mkfs.btrfs -L my_pool --force /dev/sda")
+         self._checkCmd("ssm add", ['--pool my_pool', '/dev/sda'],
+-            "mkfs.btrfs -L my_pool -f /dev/sda")
++            "mkfs.btrfs -L my_pool --force /dev/sda")
+         # Add more devices into defined pool
+         self._checkCmd("ssm add", ['-p my_pool', '/dev/sda /dev/sdc1'],
+-            "mkfs.btrfs -L my_pool -f /dev/sda /dev/sdc1")
++            "mkfs.btrfs -L my_pool --force /dev/sda /dev/sdc1")
+         self._checkCmd("ssm add", ['--pool my_pool', '/dev/sda /dev/sdc1'],
+-            "mkfs.btrfs -L my_pool -f /dev/sda /dev/sdc1")
++            "mkfs.btrfs -L my_pool --force /dev/sda /dev/sdc1")
+ 
+         # Adding to existing default pool
+         self._addPool(default_pool, ['/dev/sdb', '/dev/sdd'])
+         # Add device into default pool
+         self._checkCmd("ssm add", ['/dev/sda'],
+-            "btrfs device add /dev/sda /tmp/mount")
++            "btrfs device add --force /dev/sda /tmp/mount")
+         # Add more devices into default pool
+         self._checkCmd("ssm add", ['/dev/sda /dev/sdc1'],
+-            "btrfs device add /dev/sda /dev/sdc1 /tmp/mount")
++            "btrfs device add --force /dev/sda /dev/sdc1 /tmp/mount")
+ 
+         # Adding to existing defined pool
+         self._addPool('my_pool', ['/dev/sdc2', '/dev/sdc3'])
+@@ -394,25 +394,25 @@ class BtrfsFunctionCheck(MockSystemDataSource):
+                     '/mnt/test1')
+         # Add device into defined pool
+         self._checkCmd("ssm add", ['-p my_pool', '/dev/sda'],
+-            "btrfs device add /dev/sda /mnt/test1")
++            "btrfs device add --force /dev/sda /mnt/test1")
+         self._checkCmd("ssm add", ['--pool my_pool', '/dev/sda'],
+-            "btrfs device add /dev/sda /mnt/test1")
++            "btrfs device add --force /dev/sda /mnt/test1")
+         # Add more devices into defined pool
+         self._checkCmd("ssm add", ['-p my_pool', '/dev/sda /dev/sdc1'],
+-            "btrfs device add /dev/sda /dev/sdc1 /mnt/test1")
++            "btrfs device add --force /dev/sda /dev/sdc1 /mnt/test1")
+         self._checkCmd("ssm add", ['--pool my_pool', '/dev/sda /dev/sdc1'],
+-            "btrfs device add /dev/sda /dev/sdc1 /mnt/test1")
++            "btrfs device add --force /dev/sda /dev/sdc1 /mnt/test1")
+         # Add verbose
+         self._checkCmd("ssm -v add", ['--pool {0}'.format(default_pool),
+             '/dev/sda /dev/sdc1'],
+-            "btrfs device add /dev/sda /dev/sdc1 /tmp/mount")
++            "btrfs device add --force /dev/sda /dev/sdc1 /tmp/mount")
+ 
+         # Add two devices into existing pool (one of the devices already is in
+         # the pool
+         self._checkCmd("ssm add", ['--pool my_pool', '/dev/sdc2 /dev/sda'],
+-            "btrfs device add /dev/sda /mnt/test1")
++            "btrfs device add --force /dev/sda /mnt/test1")
+         self._checkCmd("ssm add", ['/dev/sda /dev/sdb'],
+-            "btrfs device add /dev/sda /tmp/mount")
++            "btrfs device add --force /dev/sda /tmp/mount")
+ 
+     def test_btrfs_mount(self):
+         self._addDir("/mnt/test")
+-- 
+1.8.3.1
+
diff --git a/ssm-0.4-test-008-Device-count-should-go-down-after-removing-.patch b/ssm-0.4-test-008-Device-count-should-go-down-after-removing-.patch
new file mode 100644
index 0000000..890a04f
--- /dev/null
+++ b/ssm-0.4-test-008-Device-count-should-go-down-after-removing-.patch
@@ -0,0 +1,27 @@
+From 0e461e0fb15c47513faf0f27b553624ea51b069b Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner at redhat.com>
+Date: Wed, 15 Jan 2014 17:39:00 +0100
+Subject: [PATCH 06/10] test 008: Device count should go down after removing a
+ device
+
+Signed-off-by: Lukas Czerner <lczerner at redhat.com>
+---
+ tests/bashtests/008-btrfs-remove.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tests/bashtests/008-btrfs-remove.sh b/tests/bashtests/008-btrfs-remove.sh
+index fd9b91e..4e40e99 100755
+--- a/tests/bashtests/008-btrfs-remove.sh
++++ b/tests/bashtests/008-btrfs-remove.sh
+@@ -93,7 +93,7 @@ export SSM_DEFAULT_BACKEND='btrfs'
+ not check btrfs_fs_field $pool1 label $pool1
+ not check btrfs_vol_field $mnt1 subvolume $vol1
+ not check btrfs_vol_field $mnt2 subvolume $vol2
+-check btrfs_fs_field $SSM_BTRFS_DEFAULT_POOL dev_count 5
++check btrfs_fs_field $SSM_BTRFS_DEFAULT_POOL dev_count 4
+ umount_all
+ ssm -f remove --all
+ 
+-- 
+1.8.3.1
+
diff --git a/ssm-0.4-tests-Fix-they-way-we-gather-information-about-btrfs.patch b/ssm-0.4-tests-Fix-they-way-we-gather-information-about-btrfs.patch
new file mode 100644
index 0000000..64c658e
--- /dev/null
+++ b/ssm-0.4-tests-Fix-they-way-we-gather-information-about-btrfs.patch
@@ -0,0 +1,27 @@
+From a5da549a380d83db0ee4b9bed70ec3575e6c2f37 Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner at redhat.com>
+Date: Wed, 15 Jan 2014 15:52:34 +0100
+Subject: [PATCH 04/10] tests: Fix they way we gather information about btrfs
+ file system
+
+Signed-off-by: Lukas Czerner <lczerner at redhat.com>
+---
+ tests/bashtests/lib/check.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tests/bashtests/lib/check.sh b/tests/bashtests/lib/check.sh
+index 9a8f853..e9a7f39 100644
+--- a/tests/bashtests/lib/check.sh
++++ b/tests/bashtests/lib/check.sh
+@@ -323,7 +323,7 @@ crypt_vol_field()
+ 
+ btrfs_fs_field()
+ {
+-	lines=$(btrfs filesystem show 2> /dev/null | grep -A 1 "'$1'" || true)
++	lines=$(btrfs filesystem show 2> /dev/null | grep -A 1 "^Label:.*$1" || true)
+ 
+ 	case $2 in
+ 		"label")
+-- 
+1.8.3.1
+
diff --git a/ssm-0.4-tests-Make-btrfs-recognize-devices-from-tests-suite-.patch b/ssm-0.4-tests-Make-btrfs-recognize-devices-from-tests-suite-.patch
new file mode 100644
index 0000000..f690ff3
--- /dev/null
+++ b/ssm-0.4-tests-Make-btrfs-recognize-devices-from-tests-suite-.patch
@@ -0,0 +1,38 @@
+From c3609263094816eee96bef416f7ed72b49c8f2b8 Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner at redhat.com>
+Date: Wed, 15 Jan 2014 16:51:18 +0100
+Subject: [PATCH 05/10] tests: Make btrfs recognize devices from tests suite
+ properly
+
+This is ugly hack to fix a problem with test suite and btrfs
+where ?sometimes? btrfs prints out device name in the path
+of the test suite rather than path in the real '/dev/'
+directory. This should cover that without any impact on
+real usage.
+
+Signed-off-by: Lukas Czerner <lczerner at redhat.com>
+---
+ ssmlib/backends/btrfs.py | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/ssmlib/backends/btrfs.py b/ssmlib/backends/btrfs.py
+index b238d52..836f108 100644
+--- a/ssmlib/backends/btrfs.py
++++ b/ssmlib/backends/btrfs.py
+@@ -119,6 +119,13 @@ class Btrfs(template.Backend):
+                 fs_used = float(misc.get_real_size(array[6]))
+ 
+             elif array[0] == 'devid':
++                # This is ugly hack to fix a problem with test suite and btrfs
++                # where ?sometimes? btrfs prints out device name in the path
++                # of the test suite rather than path in the real '/dev/'
++                # directory. This should cover that without any impact on
++                # real usage
++                if not os.path.islink(array[7]):
++                    array[7] = re.sub(r'.*/dev/', '/dev/', array[7])
+                 dev['dev_name'] = misc.get_real_device(array[7])
+ 
+                 if not pool_name:
+-- 
+1.8.3.1
+
diff --git a/system-storage-manager.spec b/system-storage-manager.spec
index a0c7da1..7ffa1a2 100644
--- a/system-storage-manager.spec
+++ b/system-storage-manager.spec
@@ -1,6 +1,6 @@
 Name:           system-storage-manager
-Version:        0.2
-Release:        2%{?dist}
+Version:        0.4
+Release:        4%{?dist}
 Summary:        A single tool to manage your storage
 
 Group:          System Environment/Base
@@ -8,6 +8,22 @@ License:        GPLv2+
 URL:            http://storagemanager.sf.net
 Source0:        http://downloads.sourceforge.net/storagemanager/%{name}-%{version}.tar.gz
 
+
+Patch1: ssm-0.4-ssm-big-update-no-1.patch
+Patch2: ssm-0.4-misc-get_unit_size-accept-different-unit-formats.patch
+Patch3: ssm-0.4-ssm-btrfs-backend-try-to-find-the-real-device.patch
+Patch4: ssm-0.4-ssm-force-btrfs-device-add.patch
+Patch5: ssm-0.4-tests-Fix-they-way-we-gather-information-about-btrfs.patch
+Patch6: ssm-0.4-tests-Make-btrfs-recognize-devices-from-tests-suite-.patch
+Patch7: ssm-0.4-test-008-Device-count-should-go-down-after-removing-.patch
+Patch8: ssm-0.4-misc-Fix-get_device_size-to-work-with-partitions-cor.patch
+Patch9: ssm-0.4-ssm-Suppress-backtrace-if-command-failed.patch
+Patch10: ssm-0.4-ssm-Add-SSM_PRINT_BACKTRACE-environment-variable.patch
+Patch11: ssm-0.4-misc-Use-wipefs-a-in-misc.wipefs-helper.patch
+Patch12: ssm-0.4-ssm-Fix-various-problems-found-by-pylint.patch
+Patch13: ssm-0.4-ssm-Remove-unnecessary-usr-bin-env-python.patch
+
+
 BuildArch:      noarch
 BuildRequires:  python-devel >= 2.6
 Requires:       python >= 2.6
@@ -41,6 +57,33 @@ technologies via a single unified interface.
 %prep
 %setup -q
 
+# Contains upstream patches
+# 39eb3058a02a2b482c4c5bdf0120b70605a6b23a..4210d7560585f2a241eaa5ebc364c98d49f565d2
+%patch1 -p1
+# misc: get_unit_size() accept different unit formats
+%patch2 -p1
+# ssm: btrfs backend: try to find the real device
+%patch3 -p1
+# ssm: force btrfs device add
+%patch4 -p1
+# tests: Fix they way we gather information about btrfs
+%patch5 -p1
+# tests: Make btrfs recognize devices from tests suite properly
+%patch6 -p1
+# test 008: Device count should go down after removing a device
+%patch7 -p1
+# misc: Fix get_device_size to work with partitions correctly
+%patch8 -p1
+# ssm: Suppress backtrace if command failed
+%patch9 -p1
+# ssm: Add SSM_PRINT_BACKTRACE environment variable
+%patch10 -p1
+# misc: Use wipefs -a in misc.wipefs() helper
+%patch11 -p1
+# ssm: Fix various problems found by pylint
+%patch12 -p1
+# ssm: Remove unnecessary /usr/bin/env python
+%patch13 -p1
 
 %build
 # nothing to build
@@ -50,6 +93,9 @@ technologies via a single unified interface.
 rm -rf ${RPM_BUILD_ROOT}
 %{__python} setup.py install --root=${RPM_BUILD_ROOT}
 
+%check
+make test
+
 
 %files
 %{_bindir}/ssm
@@ -60,6 +106,25 @@ rm -rf ${RPM_BUILD_ROOT}
 
 
 %changelog
+* Mon Jan 20 2014 Lukas Czerner <lczerner at redhat.com> 0.4-4
+- Update to a new upstream release v0.4
+- Remove btrfs resize support
+- Unmount all btrfs subvolumes when removing a filesystem
+- Fix size argument parsing for create and snapshot command
+- Fix list output for some cases
+- Add support to create encrypted volumes with crypt backend
+- Add dry-run option
+- Fix removing volumes with crypt backend
+- Add raid1 and raid10 support for lvm backend
+- Allow to check btrfs volumes
+- Fix error handling when trying to resize btrfs subvolume
+- Fix ssm mount command so it detects directory properly
+- Suppress backtrace when a command fails
+- Fix ssm to recognize units in new btrfs output properly
+- Use correct sysfs file to get size for a partition
+- Fix ssm to be able add a device with signature to btrfs file system
+- Resognize btrfs devices from new btrfs output properly
+
 * Fri Feb 15 2013 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 0.2-2
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
 


More information about the scm-commits mailing list