"Fossies" - the Fresh Open Source Software Archive

Member "manila-11.0.1/manila/tests/share/drivers/test_lvm.py" (1 Feb 2021, 29738 Bytes) of package /linux/misc/openstack/manila-11.0.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "test_lvm.py": 11.0.0_vs_11.0.1.

    1 # Copyright 2012 NetApp
    2 # All Rights Reserved.
    3 #
    4 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
    5 #    not use this file except in compliance with the License. You may obtain
    6 #    a copy of the License at
    7 #
    8 #         http://www.apache.org/licenses/LICENSE-2.0
    9 #
   10 #    Unless required by applicable law or agreed to in writing, software
   11 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   12 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   13 #    License for the specific language governing permissions and limitations
   14 #    under the License.
   15 """Unit tests for the LVM driver module."""
   16 
   17 import os
   18 from unittest import mock
   19 
   20 import ddt
   21 from oslo_concurrency import processutils
   22 from oslo_config import cfg
   23 from oslo_utils import timeutils
   24 
   25 from manila.common import constants as const
   26 from manila import context
   27 from manila import exception
   28 from manila.share import configuration
   29 from manila.share.drivers import lvm
   30 from manila import test
   31 from manila.tests.db import fakes as db_fakes
   32 from manila.tests import fake_utils
   33 from manila.tests.share.drivers import test_generic
   34 
   35 
   36 CONF = cfg.CONF
   37 
   38 
   39 def fake_share(**kwargs):
   40     share = {
   41         'id': 'fakeid',
   42         'name': 'fakename',
   43         'size': 1,
   44         'share_proto': 'NFS',
   45         'export_location': '127.0.0.1:/mnt/nfs/volume-00002',
   46     }
   47     share.update(kwargs)
   48     return db_fakes.FakeModel(share)
   49 
   50 
   51 def fake_snapshot(**kwargs):
   52     snapshot = {
   53         'id': 'fakesnapshotid',
   54         'share_name': 'fakename',
   55         'share_id': 'fakeid',
   56         'name': 'fakesnapshotname',
   57         'share_proto': 'NFS',
   58         'export_location': '127.0.0.1:/mnt/nfs/volume-00002',
   59         'share': {
   60             'id': 'fakeid',
   61             'name': 'fakename',
   62             'size': 1,
   63             'share_proto': 'NFS',
   64         },
   65     }
   66     snapshot.update(kwargs)
   67     return db_fakes.FakeModel(snapshot)
   68 
   69 
   70 def fake_access(**kwargs):
   71     access = {
   72         'id': 'fakeaccid',
   73         'access_type': 'ip',
   74         'access_to': '10.0.0.2',
   75         'access_level': 'rw',
   76         'state': 'active',
   77     }
   78     access.update(kwargs)
   79     return db_fakes.FakeModel(access)
   80 
   81 
   82 @ddt.ddt
   83 class LVMShareDriverTestCase(test.TestCase):
   84     """Tests LVMShareDriver."""
   85 
   86     def setUp(self):
   87         super(LVMShareDriverTestCase, self).setUp()
   88         fake_utils.stub_out_utils_execute(self)
   89         self._context = context.get_admin_context()
   90 
   91         CONF.set_default('lvm_share_volume_group', 'fakevg')
   92         CONF.set_default('lvm_share_export_ips', ['10.0.0.1', '10.0.0.2'])
   93         CONF.set_default('driver_handles_share_servers', False)
   94         CONF.set_default('reserved_share_percentage', 50)
   95 
   96         self._helper_cifs = mock.Mock()
   97         self._helper_nfs = mock.Mock()
   98         self.fake_conf = configuration.Configuration(None)
   99         self._db = mock.Mock()
  100         self._os = lvm.os = mock.Mock()
  101         self._os.path.join = os.path.join
  102         self._driver = lvm.LVMShareDriver(self._db,
  103                                           configuration=self.fake_conf)
  104         self._driver._helpers = {
  105             'CIFS': self._helper_cifs,
  106             'NFS': self._helper_nfs,
  107         }
  108 
  109         self.share = fake_share()
  110         self.access = fake_access()
  111         self.snapshot = fake_snapshot()
  112         self.server = {
  113             'public_addresses': self.fake_conf.lvm_share_export_ips,
  114             'instance_id': 'LVM',
  115             'lock_name': 'manila_lvm',
  116         }
  117 
  118         # Used only to test compatibility with share manager
  119         self.share_server = "fake_share_server"
  120 
  121     def tearDown(self):
  122         super(LVMShareDriverTestCase, self).tearDown()
  123         fake_utils.fake_execute_set_repliers([])
  124         fake_utils.fake_execute_clear_log()
  125 
  126     def test_do_setup(self):
  127         CONF.set_default('lvm_share_helpers', ['NFS=fakenfs'])
  128         lvm.importutils = mock.Mock()
  129         lvm.importutils.import_class.return_value = self._helper_nfs
  130         self._driver.do_setup(self._context)
  131         lvm.importutils.import_class.assert_has_calls([
  132             mock.call('fakenfs')
  133         ])
  134 
  135     def test_check_for_setup_error(self):
  136         def exec_runner(*ignore_args, **ignore_kwargs):
  137             return '\n   fake1\n   fakevg\n   fake2\n', ''
  138 
  139         expected_exec = ['vgs --noheadings -o name']
  140         fake_utils.fake_execute_set_repliers([(expected_exec[0], exec_runner)])
  141         self._driver.check_for_setup_error()
  142         self.assertEqual(expected_exec, fake_utils.fake_execute_get_log())
  143 
  144     def test_check_for_setup_error_no_vg(self):
  145         def exec_runner(*ignore_args, **ignore_kwargs):
  146             return '\n   fake0\n   fake1\n   fake2\n', ''
  147 
  148         fake_utils.fake_execute_set_repliers([('vgs --noheadings -o name',
  149                                                exec_runner)])
  150         self.assertRaises(exception.InvalidParameterValue,
  151                           self._driver.check_for_setup_error)
  152 
  153     def test_check_for_setup_error_no_export_ips(self):
  154         def exec_runner(*ignore_args, **ignore_kwargs):
  155             return '\n   fake1\n   fakevg\n   fake2\n', ''
  156 
  157         fake_utils.fake_execute_set_repliers([('vgs --noheadings -o name',
  158                                                exec_runner)])
  159         CONF.set_default('lvm_share_export_ips', None)
  160         self.assertRaises(exception.InvalidParameterValue,
  161                           self._driver.check_for_setup_error)
  162 
  163     def test_local_path_normal(self):
  164         share = fake_share(name='fake_sharename')
  165         CONF.set_default('lvm_share_volume_group', 'fake_vg')
  166         ret = self._driver._get_local_path(share)
  167         self.assertEqual('/dev/mapper/fake_vg-fake_sharename', ret)
  168 
  169     def test_local_path_escapes(self):
  170         share = fake_share(name='fake-sharename')
  171         CONF.set_default('lvm_share_volume_group', 'fake-vg')
  172         ret = self._driver._get_local_path(share)
  173         self.assertEqual('/dev/mapper/fake--vg-fake--sharename', ret)
  174 
  175     def test_create_share(self):
  176         CONF.set_default('lvm_share_mirrors', 0)
  177         self._driver._mount_device = mock.Mock()
  178 
  179         ret = self._driver.create_share(self._context, self.share,
  180                                         self.share_server)
  181 
  182         self._driver._mount_device.assert_called_with(
  183             self.share, '/dev/mapper/fakevg-fakename')
  184         expected_exec = [
  185             'lvcreate -L 1G -n fakename fakevg',
  186             'mkfs.ext4 /dev/mapper/fakevg-fakename',
  187         ]
  188         self.assertEqual(expected_exec, fake_utils.fake_execute_get_log())
  189         self.assertEqual(self._helper_nfs.create_exports.return_value, ret)
  190 
  191     def test_create_share_from_snapshot(self):
  192         CONF.set_default('lvm_share_mirrors', 0)
  193         self._driver._mount_device = mock.Mock()
  194         snapshot_instance = {
  195             'snapshot_id': 'fakesnapshotid',
  196             'name': 'fakename'
  197         }
  198         mount_share = '/dev/mapper/fakevg-fakename'
  199         mount_snapshot = '/dev/mapper/fakevg-fakename'
  200         self._helper_nfs.create_export.return_value = 'fakelocation'
  201         self._driver.create_share_from_snapshot(self._context,
  202                                                 self.share,
  203                                                 snapshot_instance,
  204                                                 self.share_server)
  205 
  206         self._driver._mount_device.assert_called_with(self.share,
  207                                                       mount_snapshot)
  208         expected_exec = [
  209             'lvcreate -L 1G -n fakename fakevg',
  210             'mkfs.ext4 /dev/mapper/fakevg-fakename',
  211             'e2fsck -y -f %s' % mount_share,
  212             'tune2fs -U random %s' % mount_share,
  213             ("dd count=0 if=%s of=%s iflag=direct oflag=direct" %
  214              (mount_snapshot, mount_share)),
  215             ("dd if=%s of=%s count=1024 bs=1M iflag=direct oflag=direct" %
  216              (mount_snapshot, mount_share)),
  217         ]
  218         self.assertEqual(expected_exec, fake_utils.fake_execute_get_log())
  219 
  220     def test_create_share_mirrors(self):
  221         share = fake_share(size='2048')
  222         CONF.set_default('lvm_share_mirrors', 2)
  223         self._driver._mount_device = mock.Mock()
  224 
  225         ret = self._driver.create_share(self._context, share,
  226                                         self.share_server)
  227 
  228         self._driver._mount_device.assert_called_with(
  229             share, '/dev/mapper/fakevg-fakename')
  230         expected_exec = [
  231             'lvcreate -L 2048G -n fakename fakevg -m 2 --nosync -R 2',
  232             'mkfs.ext4 /dev/mapper/fakevg-fakename',
  233         ]
  234         self.assertEqual(expected_exec, fake_utils.fake_execute_get_log())
  235         self.assertEqual(self._helper_nfs.create_exports.return_value, ret)
  236 
  237     def test_deallocate_container(self):
  238         expected_exec = ['lvremove -f fakevg/fakename']
  239         self._driver._deallocate_container(self.share['name'])
  240         self.assertEqual(expected_exec, fake_utils.fake_execute_get_log())
  241 
  242     def test_deallocate_container_error(self):
  243         def _fake_exec(*args, **kwargs):
  244             raise exception.ProcessExecutionError(stderr="error")
  245 
  246         self.mock_object(self._driver, '_try_execute', _fake_exec)
  247         self.assertRaises(exception.ProcessExecutionError,
  248                           self._driver._deallocate_container,
  249                           self.share['name'])
  250 
  251     @ddt.data(
  252         'Logical volume "fake/fake-volume" not found\n',
  253         'Failed to find logical volume "fake/fake-volume"\n')
  254     def test_deallocate_container_not_found_error(self, error_msg):
  255         def _fake_exec(*args, **kwargs):
  256             raise exception.ProcessExecutionError(stderr=error_msg)
  257 
  258         self.mock_object(self._driver, '_try_execute', _fake_exec)
  259         self._driver._deallocate_container(self.share['name'])
  260 
  261     @mock.patch.object(lvm.LVMShareDriver, '_update_share_stats', mock.Mock())
  262     def test_get_share_stats(self):
  263         with mock.patch.object(self._driver, '_stats', mock.Mock) as stats:
  264             self.assertEqual(stats, self._driver.get_share_stats())
  265         self.assertFalse(self._driver._update_share_stats.called)
  266 
  267     @mock.patch.object(lvm.LVMShareDriver, '_update_share_stats', mock.Mock())
  268     def test_get_share_stats_refresh(self):
  269         with mock.patch.object(self._driver, '_stats', mock.Mock) as stats:
  270             self.assertEqual(stats,
  271                              self._driver.get_share_stats(refresh=True))
  272         self._driver._update_share_stats.assert_called_once_with()
  273 
  274     def test__unmount_device_not_mounted(self):
  275         def exec_runner(*ignore_args, **ignore_kwargs):
  276             umount_msg = (
  277                 "umount: /opt/stack/data/manila/mnt/share-fake-share: not "
  278                 "mounted.\n"
  279             )
  280             raise exception.ProcessExecutionError(stderr=umount_msg)
  281         self._os.path.exists.return_value = True
  282         mount_path = self._get_mount_path(self.share)
  283         expected_exec = "umount -f %s" % (mount_path)
  284         fake_utils.fake_execute_set_repliers([(expected_exec, exec_runner)])
  285 
  286         self._driver._unmount_device(self.share, raise_if_missing=False)
  287 
  288         self._os.path.exists.assert_called_with(mount_path)
  289 
  290     def test__unmount_device_is_busy_error(self):
  291         def exec_runner(*ignore_args, **ignore_kwargs):
  292             raise exception.ProcessExecutionError(stderr='device is busy')
  293         self._os.path.exists.return_value = True
  294         mount_path = self._get_mount_path(self.share)
  295         expected_exec = [
  296             "umount -f %s" % (mount_path),
  297         ]
  298         fake_utils.fake_execute_set_repliers([(expected_exec[0], exec_runner)])
  299 
  300         self.assertRaises(exception.ShareBusyException,
  301                           self._driver._unmount_device,
  302                           self.share)
  303         self.assertEqual(expected_exec, fake_utils.fake_execute_get_log())
  304 
  305     def test__unmount_device_error(self):
  306         def exec_runner(*ignore_args, **ignore_kwargs):
  307             raise exception.ProcessExecutionError(stderr='fake error')
  308         mount_path = self._get_mount_path(self.share)
  309         self._os.path.exists.return_value = True
  310         cmd = "umount -f %s" % (mount_path)
  311         fake_utils.fake_execute_set_repliers([(cmd, exec_runner)])
  312         self.assertRaises(processutils.ProcessExecutionError,
  313                           self._driver._unmount_device,
  314                           self.share)
  315         self._os.path.exists.assert_called_with(mount_path)
  316 
  317     def test__unmount_device_rmdir_error(self):
  318         def exec_runner(*ignore_args, **ignore_kwargs):
  319             raise exception.ProcessExecutionError(stderr='fake error')
  320         mount_path = self._get_mount_path(self.share)
  321         self._os.path.exists.return_value = True
  322         cmd = "rmdir %s" % (mount_path)
  323         fake_utils.fake_execute_set_repliers([(cmd, exec_runner)])
  324         self.assertRaises(processutils.ProcessExecutionError,
  325                           self._driver._unmount_device,
  326                           self.share)
  327         self._os.path.exists.assert_called_with(mount_path)
  328 
  329     def test_create_snapshot(self):
  330         self._driver.create_snapshot(self._context, self.snapshot,
  331                                      self.share_server)
  332         mount_path = self._get_mount_path(self.snapshot)
  333         expected_exec = [
  334             ("lvcreate -L 1G --name fakesnapshotname --snapshot "
  335              "%s/fakename" % (CONF.lvm_share_volume_group,)),
  336             "e2fsck -y -f /dev/mapper/fakevg-%s" % self.snapshot['name'],
  337             "tune2fs -U random /dev/mapper/fakevg-%s" % self.snapshot['name'],
  338             "mkdir -p " + mount_path,
  339             "mount /dev/mapper/fakevg-fakesnapshotname " + mount_path,
  340             "chmod 777 " + mount_path,
  341         ]
  342         self.assertEqual(expected_exec, fake_utils.fake_execute_get_log())
  343 
  344     def test_ensure_share(self):
  345         device_name = '/dev/mapper/fakevg-fakename'
  346         with mock.patch.object(self._driver,
  347                                '_mount_device',
  348                                mock.Mock(return_value='fake_location')):
  349             self._driver.ensure_share(self._context, self.share,
  350                                       self.share_server)
  351             self._driver._mount_device.assert_called_with(self.share,
  352                                                           device_name)
  353             self._helper_nfs.create_exports.assert_called_once_with(
  354                 self.server, self.share['name'], recreate=True)
  355 
  356     def test_delete_share(self):
  357         mount_path = self._get_mount_path(self.share)
  358         self._helper_nfs.remove_export(mount_path, self.share['name'])
  359         self._driver._delete_share(self._context, self.share)
  360 
  361     def test_delete_snapshot(self):
  362         mount_path = self._get_mount_path(self.snapshot)
  363         expected_exec = [
  364             'umount -f %s' % mount_path,
  365             'rmdir %s' % mount_path,
  366             'lvremove -f fakevg/fakesnapshotname',
  367         ]
  368         self._driver.delete_snapshot(self._context, self.snapshot,
  369                                      self.share_server)
  370         self.assertEqual(expected_exec, fake_utils.fake_execute_get_log())
  371 
  372     def test_delete_share_invalid_share(self):
  373         self._driver._get_helper = mock.Mock(
  374             side_effect=exception.InvalidShare(reason='fake'))
  375         self._driver.delete_share(self._context, self.share, self.share_server)
  376 
  377     def test_delete_share_process_execution_error(self):
  378         self.mock_object(
  379             self._helper_nfs,
  380             'remove_export',
  381             mock.Mock(side_effect=exception.ProcessExecutionError))
  382 
  383         self._driver._delete_share(self._context, self.share)
  384         self._helper_nfs.remove_exports.assert_called_once_with(
  385             self.server,
  386             self.share['name'])
  387 
  388     @ddt.data(const.ACCESS_LEVEL_RW, const.ACCESS_LEVEL_RO)
  389     def test_update_access(self, access_level):
  390         access_rules = [test_generic.get_fake_access_rule(
  391             '1.1.1.1', access_level), ]
  392         add_rules = [test_generic.get_fake_access_rule(
  393             '2.2.2.2', access_level), ]
  394         delete_rules = [test_generic.get_fake_access_rule(
  395             '3.3.3.3', access_level), ]
  396         self._driver.update_access(self._context, self.share, access_rules,
  397                                    add_rules=add_rules,
  398                                    delete_rules=delete_rules,
  399                                    share_server=self.server)
  400         (self._driver._helpers[self.share['share_proto']].
  401             update_access.assert_called_once_with(
  402                 self.server, self.share['name'],
  403                 access_rules, add_rules=add_rules, delete_rules=delete_rules))
  404 
  405     @ddt.data((['1001::1001/129'], False),
  406               (['1.1.1.256'], False),
  407               (['1001::1001'], [6]),
  408               ('1.1.1.0', [4]),
  409               (['1001::1001', '1.1.1.0'], [6, 4]),
  410               (['1001::1001/129', '1.1.1.0'], False))
  411     @ddt.unpack
  412     def test_get_configured_ip_versions(self, configured_ips,
  413                                         configured_ip_version):
  414         CONF.set_default('lvm_share_export_ips', configured_ips)
  415         if configured_ip_version:
  416             self.assertEqual(configured_ip_version,
  417                              self._driver.get_configured_ip_versions())
  418         else:
  419             self.assertRaises(exception.InvalidInput,
  420                               self._driver.get_configured_ip_versions)
  421 
  422     def test_mount_device(self):
  423         mount_path = self._get_mount_path(self.share)
  424         ret = self._driver._mount_device(self.share, 'fakedevice')
  425         expected_exec = [
  426             "mkdir -p %s" % (mount_path,),
  427             "mount fakedevice %s" % (mount_path,),
  428             "chmod 777 %s" % (mount_path,),
  429         ]
  430         self.assertEqual(expected_exec, fake_utils.fake_execute_get_log())
  431         self.assertEqual(mount_path, ret)
  432 
  433     def test_mount_device_already(self):
  434         def exec_runner(*args, **kwargs):
  435             if 'mount' in args and '-l' not in args:
  436                 raise exception.ProcessExecutionError()
  437             else:
  438                 return 'fakedevice', ''
  439 
  440         self.mock_object(self._driver, '_execute', exec_runner)
  441         mount_path = self._get_mount_path(self.share)
  442 
  443         ret = self._driver._mount_device(self.share, 'fakedevice')
  444         self.assertEqual(mount_path, ret)
  445 
  446     def test_mount_device_error(self):
  447         def exec_runner(*args, **kwargs):
  448             if 'mount' in args and '-l' not in args:
  449                 raise exception.ProcessExecutionError()
  450             else:
  451                 return 'fake', ''
  452 
  453         self.mock_object(self._driver, '_execute', exec_runner)
  454         self.assertRaises(exception.ProcessExecutionError,
  455                           self._driver._mount_device, self.share, 'fakedevice')
  456 
  457     def test_get_helper(self):
  458         share_cifs = fake_share(share_proto='CIFS')
  459         share_nfs = fake_share(share_proto='NFS')
  460         share_fake = fake_share(share_proto='FAKE')
  461         self.assertEqual(self._driver._get_helper(share_cifs),
  462                          self._helper_cifs)
  463         self.assertEqual(self._driver._get_helper(share_nfs),
  464                          self._helper_nfs)
  465         self.assertRaises(exception.InvalidShare, self._driver._get_helper,
  466                           share_fake)
  467 
  468     def _get_mount_path(self, share):
  469         return os.path.join(CONF.lvm_share_export_root, share['name'])
  470 
  471     @ddt.data(True, False)
  472     def test__unmount_device_with_retry_busy_device(self, retry_busy_device):
  473         execute_sideeffects = [
  474             exception.ProcessExecutionError(stderr='device is busy'),
  475             exception.ProcessExecutionError(stderr='target is busy'),
  476             None, None
  477         ] if retry_busy_device else [None, None]
  478         mount_path = self._get_mount_path(self.share)
  479         self._os.path.exists.return_value = True
  480         self.mock_object(self._driver, '_execute', mock.Mock(
  481             side_effect=execute_sideeffects))
  482 
  483         self._driver._unmount_device(self.share,
  484                                      retry_busy_device=retry_busy_device)
  485 
  486         num_of_times_umount_is_called = 3 if retry_busy_device else 1
  487 
  488         self._os.path.exists.assert_called_with(mount_path)
  489         self._driver._execute.assert_has_calls([
  490             mock.call('umount', '-f', mount_path, run_as_root=True),
  491         ] * num_of_times_umount_is_called + [
  492             mock.call('rmdir', mount_path, run_as_root=True)
  493         ])
  494 
  495     def test_extend_share(self):
  496         local_path = self._driver._get_local_path(self.share)
  497         self.mock_object(self._driver, '_extend_container')
  498         self.mock_object(self._driver, '_execute')
  499         self._driver.extend_share(self.share, 3)
  500         self._driver._extend_container.assert_called_once_with(self.share,
  501                                                                local_path, 3)
  502 
  503     def test_ssh_exec_as_root(self):
  504         command = ['fake_command']
  505         self.mock_object(self._driver, '_execute')
  506         self._driver._ssh_exec_as_root('fake_server', command)
  507         self._driver._execute.assert_called_once_with('fake_command',
  508                                                       check_exit_code=True)
  509 
  510     def test_ssh_exec_as_root_with_sudo(self):
  511         command = ['sudo', 'fake_command']
  512         self.mock_object(self._driver, '_execute')
  513         self._driver._ssh_exec_as_root('fake_server', command)
  514         self._driver._execute.assert_called_once_with(
  515             'fake_command', run_as_root=True, check_exit_code=True)
  516 
  517     def test_extend_container(self):
  518         self.mock_object(self._driver, '_try_execute')
  519         self._driver._extend_container(self.share, 'device_name', 3)
  520         self._driver._try_execute.assert_called_once_with(
  521             'lvextend',
  522             '-L',
  523             '3G',
  524             '-r',
  525             'device_name',
  526             run_as_root=True)
  527 
  528     def test_get_share_server_pools(self):
  529         expected_result = [{
  530             'pool_name': 'lvm-single-pool',
  531             'total_capacity_gb': 33,
  532             'free_capacity_gb': 22,
  533             'reserved_percentage': 0,
  534         }, ]
  535         self.mock_object(
  536             self._driver,
  537             '_execute',
  538             mock.Mock(return_value=("VSize 33g VFree 22g", None)))
  539 
  540         self.assertEqual(expected_result,
  541                          self._driver.get_share_server_pools())
  542         self._driver._execute.assert_called_once_with(
  543             'vgs', 'fakevg', '--rows', '--units', 'g', run_as_root=True)
  544 
  545     def test_copy_volume_error(self):
  546         def _fake_exec(*args, **kwargs):
  547             if 'count=0' in args:
  548                 raise exception.ProcessExecutionError()
  549 
  550         self.mock_object(self._driver, '_execute',
  551                          mock.Mock(side_effect=_fake_exec))
  552         self._driver._copy_volume('src', 'dest', 1)
  553         self._driver._execute.assert_any_call('dd', 'count=0', 'if=src',
  554                                               'of=dest', 'iflag=direct',
  555                                               'oflag=direct', run_as_root=True)
  556         self._driver._execute.assert_any_call('dd', 'if=src', 'of=dest',
  557                                               'count=1024', 'bs=1M',
  558                                               run_as_root=True)
  559 
  560     @ddt.data((['1.1.1.1'], 4), (['1001::1001'], 6))
  561     @ddt.unpack
  562     def test_update_share_stats(self, configured_ip, version):
  563         CONF.set_default('lvm_share_export_ips', configured_ip)
  564         self.mock_object(self._driver, 'get_share_server_pools',
  565                          mock.Mock(return_value='test-pool'))
  566 
  567         self._driver._update_share_stats()
  568         self.assertEqual('LVM', self._driver._stats['share_backend_name'])
  569         self.assertEqual('NFS_CIFS', self._driver._stats['storage_protocol'])
  570         self.assertEqual(50, self._driver._stats['reserved_percentage'])
  571         self.assertTrue(self._driver._stats['snapshot_support'])
  572         self.assertEqual('LVMShareDriver', self._driver._stats['driver_name'])
  573         self.assertEqual('test-pool', self._driver._stats['pools'])
  574         self.assertEqual(version == 4, self._driver._stats['ipv4_support'])
  575         self.assertEqual(version == 6, self._driver._stats['ipv6_support'])
  576 
  577     def test_revert_to_snapshot(self):
  578         mock_update_access = self.mock_object(self._helper_nfs,
  579                                               'update_access')
  580         self._driver.revert_to_snapshot(self._context, self.snapshot,
  581                                         [], [], self.share_server)
  582         snap_lv = "%s/fakesnapshotname" % (CONF.lvm_share_volume_group)
  583         share_lv = "%s/fakename" % (CONF.lvm_share_volume_group)
  584         share_mount_path = self._get_mount_path(self.snapshot['share'])
  585         snapshot_mount_path = self._get_mount_path(self.snapshot)
  586         expected_exec = [
  587             ('umount -f %s' % snapshot_mount_path),
  588             ("rmdir %s" % snapshot_mount_path),
  589             ("umount -f %s" % share_mount_path),
  590             ("rmdir %s" % share_mount_path),
  591             ("lvconvert --merge %s" % snap_lv),
  592             ("lvcreate -L 1G --name fakesnapshotname --snapshot %s" %
  593                 share_lv),
  594             ("e2fsck -y -f /dev/mapper/%s-fakesnapshotname" %
  595                 CONF.lvm_share_volume_group),
  596             ("tune2fs -U random /dev/mapper/%s-fakesnapshotname" %
  597                 CONF.lvm_share_volume_group),
  598             ("mkdir -p %s" % share_mount_path),
  599             ("mount /dev/mapper/%s-fakename %s" %
  600                 (CONF.lvm_share_volume_group, share_mount_path)),
  601             ("chmod 777 %s" % share_mount_path),
  602             ("mkdir -p %s" % snapshot_mount_path),
  603             ("mount /dev/mapper/fakevg-fakesnapshotname "
  604              "%s" % snapshot_mount_path),
  605             ("chmod 777 %s" % snapshot_mount_path),
  606         ]
  607         self.assertEqual(expected_exec, fake_utils.fake_execute_get_log())
  608         self.assertEqual(4, mock_update_access.call_count)
  609 
  610     def test_snapshot_update_access(self):
  611         access_rules = [{
  612             'access_type': 'ip',
  613             'access_to': '1.1.1.1',
  614             'access_level': 'ro',
  615         }]
  616 
  617         add_rules = [{
  618             'access_type': 'ip',
  619             'access_to': '2.2.2.2',
  620             'access_level': 'ro',
  621         }]
  622 
  623         delete_rules = [{
  624             'access_type': 'ip',
  625             'access_to': '3.3.3.3',
  626             'access_level': 'ro',
  627         }]
  628 
  629         self._driver.snapshot_update_access(self._context, self.snapshot,
  630                                             access_rules, add_rules,
  631                                             delete_rules)
  632 
  633         (self._driver._helpers[self.snapshot['share']['share_proto']].
  634             update_access.assert_called_once_with(
  635             self.server, self.snapshot['name'],
  636             access_rules, add_rules=add_rules, delete_rules=delete_rules))
  637 
  638     @mock.patch.object(timeutils, 'utcnow', mock.Mock(
  639                        return_value='fake_date'))
  640     def test_update_share_usage_size(self):
  641         mount_path = self._get_mount_path(self.share)
  642         self._os.path.exists.return_value = True
  643         self.mock_object(
  644             self._driver,
  645             '_execute',
  646             mock.Mock(return_value=(
  647                 "Mounted on                    Used "
  648                 + mount_path + "               1G", None)))
  649 
  650         update_shares = self._driver.update_share_usage_size(
  651             self._context, [self.share, ])
  652         self._os.path.exists.assert_called_with(mount_path)
  653         self.assertEqual(
  654             [{'id': 'fakeid', 'used_size': '1',
  655               'gathered_at': 'fake_date'}],
  656             update_shares)
  657         self._driver._execute.assert_called_once_with(
  658             'df', '-l', '--output=target,used',
  659             '--block-size=g')
  660 
  661     @mock.patch.object(timeutils, 'utcnow', mock.Mock(
  662                        return_value='fake_date'))
  663     def test_update_share_usage_size_multiple_share(self):
  664         share1 = fake_share(id='fakeid_get_fail', name='get_fail')
  665         share2 = fake_share(id='fakeid_success', name='get_success')
  666         share3 = fake_share(id='fakeid_not_exist', name='get_not_exist')
  667 
  668         mount_path2 = self._get_mount_path(share2)
  669         mount_path3 = self._get_mount_path(share3)
  670         self._os.path.exists.side_effect = [True, True, False]
  671         self.mock_object(
  672             self._driver,
  673             '_execute',
  674             mock.Mock(return_value=(
  675                 "Mounted on                    Used "
  676                 + mount_path2 + "               1G", None)))
  677 
  678         update_shares = self._driver.update_share_usage_size(
  679             self._context, [share1, share2, share3])
  680         self._os.path.exists.assert_called_with(mount_path3)
  681         self.assertEqual(
  682             [{'gathered_at': 'fake_date',
  683               'id': 'fakeid_success', 'used_size': '1'}],
  684             update_shares)
  685         self._driver._execute.assert_called_with(
  686             'df', '-l', '--output=target,used',
  687             '--block-size=g')
  688 
  689     def test_update_share_usage_size_fail(self):
  690         def _fake_exec(*args, **kwargs):
  691             raise exception.ProcessExecutionError(stderr="error")
  692 
  693         self.mock_object(self._driver, '_execute', _fake_exec)
  694         self.assertRaises(exception.ProcessExecutionError,
  695                           self._driver.update_share_usage_size,
  696                           self._context,
  697                           [self.share])
  698 
  699     def test_get_backend_info(self):
  700         backend_info = self._driver.get_backend_info(self._context)
  701 
  702         self.assertEqual(
  703             {'export_ips': ','.join(self.server['public_addresses']),
  704              'db_version': mock.ANY},
  705             backend_info)