]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Add deactivate step to extend_lv
authorCurt Bruns <curt.e.bruns@intel.com>
Mon, 6 Jul 2015 15:09:41 +0000 (15:09 +0000)
committerCurt Bruns <curt.e.bruns@intel.com>
Tue, 28 Jul 2015 18:46:25 +0000 (11:46 -0700)
Extending a linear LVM volume that has a snapshot requires
that the LV be deactivated explicitly prior to extending.

This adds a deactivate_lv method and calls it prior to
issuing the extend call. If auto_activation_volume_list
is not defined lvm.conf, then volumes will be reactivated
automatically after the extend.  If auto_activation_volume_list
is defined, then volumes that should be automatically
reactivated should be added to the auto_activation_volume_list
or they won't be activated automatically.
NOTE: This doesn't apply to thin provisioned LVs as they don't
require the deactivation step.

DocImpact: When a user extends LVM Volumes with a snapshot, the
volumes will be deactivated.  Their re-activation is automatic,
unless auto_activation_volume_list is defined in lvm.conf.
See lvm.conf for more info.  Thin provisioned LVM Volumes
will not be deactivated as they don't require it.

Co-Authored-By: John Griffith <john.griffith8@gmail.com>
Change-Id: If746625cfe658c3528525dc7f4bf869f1c9704dc
Closes-Bug: #1470558

cinder/brick/local_dev/lvm.py
cinder/tests/unit/brick/test_brick_lvm.py
cinder/tests/unit/test_srb.py

index 83524856ff47c7fcc1d423c8f285e0f5c2cf0ad1..b830dd70280a028dc3c2cc35f4018e0aa0fdf812 100644 (file)
@@ -589,6 +589,21 @@ class LVM(executor.Executor):
             return name
         return '_' + name
 
+    def deactivate_lv(self, name):
+        lv_path = self.vg_name + '/' + self._mangle_lv_name(name)
+        cmd = ['lvchange', '-a', 'n']
+        cmd.append(lv_path)
+        try:
+            self._execute(*cmd,
+                          root_helper=self._root_helper,
+                          run_as_root=True)
+        except putils.ProcessExecutionError as err:
+            LOG.exception(_LE('Error deactivating LV'))
+            LOG.error(_LE('Cmd     :%s'), err.cmd)
+            LOG.error(_LE('StdOut  :%s'), err.stdout)
+            LOG.error(_LE('StdErr  :%s'), err.stderr)
+            raise
+
     def activate_lv(self, name, is_snapshot=False):
         """Ensure that logical volume/snapshot logical volume is activated.
 
@@ -696,7 +711,12 @@ class LVM(executor.Executor):
 
     def extend_volume(self, lv_name, new_size):
         """Extend the size of an existing volume."""
-
+        # Volumes with snaps have attributes 'o' or 'O' and will be
+        # deactivated, but Thin Volumes with snaps have attribute 'V'
+        # and won't be deactivated because the lv_has_snapshot method looks
+        # for 'o' or 'O'
+        if self.lv_has_snapshot(lv_name):
+            self.deactivate_lv(lv_name)
         try:
             self._execute('lvextend', '-L', new_size,
                           '%s/%s' % (self.vg_name, lv_name),
index 77744c688b507eba2f0ad3dacb274c2d8cd68392..ab276009147cb523acf3fcc17d59b9effc74e558 100644 (file)
@@ -12,6 +12,7 @@
 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 #    License for the specific language governing permissions and limitations
 #    under the License.
+import mock
 from mox3 import mox
 from oslo_concurrency import processutils
 
@@ -140,8 +141,12 @@ class BrickLvmTestCase(test.TestCase):
             pass
         elif 'lvcreate, -T, -V, ' in cmd_string:
             pass
+        elif 'lvcreate, -n, ' in cmd_string:
+            pass
         elif 'lvcreate, --name, ' in cmd_string:
             pass
+        elif 'lvextend, -L, ' in cmd_string:
+            pass
         else:
             raise AssertionError('unexpected command called: %s' % cmd_string)
 
@@ -351,3 +356,18 @@ class BrickLvmTestCase(test.TestCase):
 
     def test_get_mirrored_available_capacity(self):
         self.assertEqual(self.vg.vg_mirror_free_space(1), 2.0)
+
+    def test_lv_extend(self):
+        self.vg.deactivate_lv = mock.MagicMock()
+
+        # Extend lv with snapshot and make sure deactivate called
+        self.vg.create_volume("test", "1G")
+        self.vg.extend_volume("test", "2G")
+        self.vg.deactivate_lv.assert_called_once_with('test')
+        self.vg.deactivate_lv.reset_mock()
+
+        # Extend lv without snapshot so deactivate should not be called
+        self.vg.create_volume("test", "1G")
+        self.vg.vg_name = "test-volumes"
+        self.vg.extend_volume("test", "2G")
+        self.assertFalse(self.vg.deactivate_lv.called)
index 329b8a65afaba80fc1ad97af1db524e708d4e93c..b0100c15f79d9c8ffe27aebc1550ee93d3672304 100644 (file)
@@ -593,7 +593,8 @@ class SRBDriverTestCase(test.TestCase):
 
     def _fake_lvchange(self):
         def check(cmd_string):
-            return 'lvchange, -a, y, --yes' in cmd_string
+            return 'lvchange, -a, y, --yes' in cmd_string or \
+                   'lvchange, -a, n' in cmd_string
 
         def act(_):
             pass