Merge "Make NFS exports in generic driver permanent"
This commit is contained in:
commit
b1a1ea8f61
|
@ -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)),
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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):
|
||||||
|
|
Loading…
Reference in New Issue