Blob Blame History Raw
From e5ca9b110954900f30bf32d66ea3440a4203e84c Mon Sep 17 00:00:00 2001
From: Lukas Czerner <lczerner@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@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