Merge "Make NFS exports in generic driver permanent"

This commit is contained in:
Jenkins 2014-09-05 17:18:43 +00:00 committed by Gerrit Code Review
commit b1a1ea8f61
3 changed files with 65 additions and 16 deletions

View File

@ -25,6 +25,9 @@ STATUS_DEACTIVATING = 'DEACTIVATING'
SECURITY_SERVICES_ALLOWED_TYPES = ['active_directory', 'ldap', 'kerberos'] SECURITY_SERVICES_ALLOWED_TYPES = ['active_directory', 'ldap', 'kerberos']
NFS_EXPORTS_FILE = '/etc/exports'
NFS_EXPORTS_FILE_TEMP = '/var/lib/nfs/etab'
# Below represented ports are ranges (from, to) # Below represented ports are ranges (from, to)
CIFS_PORTS = ( CIFS_PORTS = (
("tcp", (445, 445)), ("tcp", (445, 445)),

View File

@ -22,6 +22,7 @@ import time
from oslo.config import cfg from oslo.config import cfg
import six import six
from manila.common import constants as const
from manila import compute from manila import compute
from manila import context from manila import context
from manila import exception from manila import exception
@ -614,6 +615,20 @@ class NASHelperBase(object):
raise NotImplementedError() raise NotImplementedError()
def nfs_synchronized(f):
def wrapped_func(self, *args, **kwargs):
key = "nfs-%s" % args[0]["instance_id"]
@utils.synchronized(key)
def source_func(self, *args, **kwargs):
return f(self, *args, **kwargs)
return source_func(self, *args, **kwargs)
return wrapped_func
class NFSHelper(NASHelperBase): class NFSHelper(NASHelperBase):
"""Interface to work with share.""" """Interface to work with share."""
@ -637,6 +652,7 @@ class NFSHelper(NASHelperBase):
"""Remove export.""" """Remove export."""
pass pass
@nfs_synchronized
def allow_access(self, server, share_name, access_type, access): def allow_access(self, server, share_name, access_type, access):
"""Allow access to the host.""" """Allow access to the host."""
local_path = os.path.join(self.configuration.share_mount_path, local_path = os.path.join(self.configuration.share_mount_path,
@ -654,7 +670,9 @@ class NFSHelper(NASHelperBase):
self._ssh_exec(server, self._ssh_exec(server,
['sudo', 'exportfs', '-o', 'rw,no_subtree_check', ['sudo', 'exportfs', '-o', 'rw,no_subtree_check',
':'.join([access, local_path])]) ':'.join([access, local_path])])
self._sync_nfs_temp_and_perm_files(server)
@nfs_synchronized
def deny_access(self, server, share_name, access_type, access, def deny_access(self, server, share_name, access_type, access,
force=False): force=False):
"""Deny access to the host.""" """Deny access to the host."""
@ -662,6 +680,20 @@ class NFSHelper(NASHelperBase):
share_name) share_name)
self._ssh_exec(server, ['sudo', 'exportfs', '-u', self._ssh_exec(server, ['sudo', 'exportfs', '-u',
':'.join([access, local_path])]) ':'.join([access, local_path])])
self._sync_nfs_temp_and_perm_files(server)
def _sync_nfs_temp_and_perm_files(self, server):
"""Sync changes of exports with permanent NFS config file.
This is required to ensure, that after share server reboot, exports
still exist.
"""
sync_cmd = [
'sudo', 'cp ', const.NFS_EXPORTS_FILE_TEMP, const.NFS_EXPORTS_FILE,
'&&',
'sudo', 'exportfs', '-a',
]
self._ssh_exec(server, sync_cmd)
class CIFSHelper(NASHelperBase): class CIFSHelper(NASHelperBase):

View File

@ -793,39 +793,53 @@ class NFSHelperTestCase(test.TestCase):
self._execute = mock.Mock(return_value=('', '')) self._execute = mock.Mock(return_value=('', ''))
self._helper = generic.NFSHelper(self._execute, self._ssh_exec, self._helper = generic.NFSHelper(self._execute, self._ssh_exec,
self.fake_conf) self.fake_conf)
ip = '10.254.0.3'
self.server = fake_compute.FakeServer(
ip=ip, public_address=ip, instance_id='fake_instance_id')
def test_create_export(self): def test_create_export(self):
fake_server = fake_compute.FakeServer(public_address='10.254.0.3') ret = self._helper.create_export(self.server, 'fake_share')
ret = self._helper.create_export(fake_server, 'volume-00001') expected_location = ':'.join([self.server['public_address'],
expected_location = ':'.join([fake_server['public_address'],
os.path.join(CONF.share_mount_path, os.path.join(CONF.share_mount_path,
'volume-00001')]) 'fake_share')])
self.assertEqual(ret, expected_location) self.assertEqual(ret, expected_location)
def test_allow_access(self): def test_allow_access(self):
fake_server = fake_compute.FakeServer(ip='10.254.0.3') self.stubs.Set(self._helper, '_sync_nfs_temp_and_perm_files',
self._helper.allow_access(fake_server, 'volume-00001', mock.Mock())
self._helper.allow_access(self.server, 'fake_share',
'ip', '10.0.0.2') 'ip', '10.0.0.2')
local_path = os.path.join(CONF.share_mount_path, 'volume-00001') local_path = os.path.join(CONF.share_mount_path, 'fake_share')
self._ssh_exec.assert_has_calls([ self._ssh_exec.assert_has_calls([
mock.call(fake_server, ['sudo', 'exportfs']), mock.call(self.server, ['sudo', 'exportfs']),
mock.call(fake_server, ['sudo', 'exportfs', '-o', mock.call(self.server, ['sudo', 'exportfs', '-o',
'rw,no_subtree_check', 'rw,no_subtree_check',
':'.join(['10.0.0.2', local_path])]) ':'.join(['10.0.0.2', local_path])])
]) ])
self._helper._sync_nfs_temp_and_perm_files.assert_called_once_with(
self.server)
def test_allow_access_no_ip(self): def test_allow_access_no_ip(self):
self.assertRaises(exception.InvalidShareAccess, self.assertRaises(
self._helper.allow_access, 'fake_server', 'share0', exception.InvalidShareAccess,
'fake', 'fakerule') self._helper.allow_access,
self.server, 'fake_share', 'fake', 'fakerule',
)
def test_deny_access(self): def test_deny_access(self):
fake_server = fake_compute.FakeServer(ip='10.254.0.3') self.stubs.Set(self._helper, '_sync_nfs_temp_and_perm_files',
local_path = os.path.join(CONF.share_mount_path, 'volume-00001') mock.Mock())
self._helper.deny_access(fake_server, 'volume-00001', 'ip', '10.0.0.2') local_path = os.path.join(CONF.share_mount_path, 'fake_share')
self._helper.deny_access(self.server, 'fake_share', 'ip', '10.0.0.2')
export_string = ':'.join(['10.0.0.2', local_path]) export_string = ':'.join(['10.0.0.2', local_path])
expected_exec = ['sudo', 'exportfs', '-u', export_string] expected_exec = ['sudo', 'exportfs', '-u', export_string]
self._ssh_exec.assert_called_once_with(fake_server, expected_exec) self._ssh_exec.assert_called_once_with(self.server, expected_exec)
self._helper._sync_nfs_temp_and_perm_files.assert_called_once_with(
self.server)
def test_sync_nfs_temp_and_perm_files(self):
self._helper._sync_nfs_temp_and_perm_files(self.server)
self._helper._ssh_exec.assert_called_once_with(self.server, mock.ANY)
class CIFSHelperTestCase(test.TestCase): class CIFSHelperTestCase(test.TestCase):