Fix lock decorator usage for LVM and Generic drivers

DHSS=False mode of LVM and Generic drivers uses not safe locking
for NFS helper. So, several instances of same driver may suffer
from race conditions for modification of NFS config files.

So, make this lock external (inter-process) and add possibility to
set up "lock_name", that is useful in case of LVM driver. Also,
make Generic driver use "instance_id" instead of IP address.
In those both cases we avoid race conditions.

Change-Id: I0687b1080cb6a0e1d3bf7c87066fa46c06977181
Closes-Bug: #1550378
This commit is contained in:
vponomaryov 2016-03-14 14:57:06 +02:00
parent 8b6cedf077
commit e49324f671
4 changed files with 32 additions and 2 deletions

View File

@ -121,9 +121,12 @@ class NASHelperBase(object):
def nfs_synchronized(f):
def wrapped_func(self, *args, **kwargs):
key = "nfs-%s" % args[0]["public_address"]
key = "nfs-%s" % args[0].get("lock_name", args[0]["instance_id"])
@utils.synchronized(key)
# NOTE(vponomaryov): 'external' lock is required for DHSS=False
# mode of LVM and Generic drivers, that may have lots of
# driver instances on single host.
@utils.synchronized(key, external=True)
def source_func(self, *args, **kwargs):
return f(self, *args, **kwargs)

View File

@ -143,6 +143,7 @@ class LVMShareDriver(LVMMixin, driver.ShareDriver):
self.share_server = {
'public_address': self.configuration.lvm_share_export_ip,
'instance_id': self.backend_name,
'lock_name': 'manila_lvm',
}
def _ssh_exec_as_root(self, server, command, check_exit_code=True):

View File

@ -598,3 +598,28 @@ class CIFSHelperUserAccessTestCase(test.TestCase):
self.server_details,
self.share_name,
access_rules)
@ddt.ddt
class NFSSynchronizedTestCase(test.TestCase):
@helpers.nfs_synchronized
def wrapped_method(self, server, share_name):
return server['instance_id'] + share_name
@ddt.data(
({'lock_name': 'FOO', 'instance_id': 'QUUZ'}, 'nfs-FOO'),
({'instance_id': 'QUUZ'}, 'nfs-QUUZ'),
)
@ddt.unpack
def test_with_lock_name(self, server, expected_lock_name):
share_name = 'fake_share_name'
self.mock_object(
helpers.utils, 'synchronized',
mock.Mock(side_effect=helpers.utils.synchronized))
result = self.wrapped_method(server, share_name)
self.assertEqual(server['instance_id'] + share_name, result)
helpers.utils.synchronized.assert_called_once_with(
expected_lock_name, external=True)

View File

@ -105,6 +105,7 @@ class LVMShareDriverTestCase(test.TestCase):
self.server = {
'public_address': self.fake_conf.lvm_share_export_ip,
'instance_id': 'LVM',
'lock_name': 'manila_lvm',
}
# Used only to test compatibility with share manager