[Dell EMC Unity] Support create share smaller than 3 GB

The minimum file system on Unity is 3 GB. This patch changes
driver to create 3 GB underlying file system for shares
smaller than 3 GB.

DocImpact
Change-Id: Ida6ad9ad7e752c25b53390f0fee327c594e03f9f
Closes-Bug: 1648316
This commit is contained in:
Tina Tang
2016-11-23 13:32:08 +08:00
parent ad2ce70233
commit bf9adef776
6 changed files with 68 additions and 8 deletions

View File

@@ -18,6 +18,7 @@ import six
from oslo_log import log from oslo_log import log
from oslo_utils import importutils from oslo_utils import importutils
from oslo_utils import units
storops = importutils.try_import('storops') storops = importutils.try_import('storops')
if storops: if storops:
@@ -30,6 +31,9 @@ from manila.i18n import _, _LI, _LE
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
# Minimun file system size in Unity
MIN_FS_SIZE_IN_GB = 3
class UnityClient(object): class UnityClient(object):
def __init__(self, host, username, password): def __init__(self, host, username, password):
@@ -69,16 +73,16 @@ class UnityClient(object):
except storops_ex.UnityNfsShareNameExistedError: except storops_ex.UnityNfsShareNameExistedError:
return self.get_share(share_name, 'NFS') return self.get_share(share_name, 'NFS')
@staticmethod def create_nfs_filesystem_and_share(self, pool, nas_server,
def create_nfs_filesystem_and_share( share_name, size_gb):
pool, nas_server, share_name, size):
"""Create filesystem and share from pool/NAS server. """Create filesystem and share from pool/NAS server.
:param pool: pool for file system creation :param pool: pool for file system creation
:param nas_server: nas server for file system creation :param nas_server: nas server for file system creation
:param share_name: file system and share name :param share_name: file system and share name
:param size: file system size :param size_gb: file system size
""" """
size = self.get_valid_fs_size_in_byte(size_gb)
pool.create_nfs_share( pool.create_nfs_share(
nas_server, share_name, size) nas_server, share_name, size)
@@ -98,8 +102,9 @@ class UnityClient(object):
def delete_share(share): def delete_share(share):
share.delete() share.delete()
def create_filesystem(self, pool, nas_server, share_name, size, proto): def create_filesystem(self, pool, nas_server, share_name, size_gb, proto):
try: try:
size = self.get_valid_fs_size_in_byte(size_gb)
return pool.create_filesystem(nas_server, return pool.create_filesystem(nas_server,
share_name, share_name,
size, size,
@@ -272,3 +277,20 @@ class UnityClient(object):
link_up_ports.append(port) link_up_ports.append(port)
return link_up_ports return link_up_ports
@staticmethod
def get_valid_fs_size_in_byte(size_gb):
if size_gb < MIN_FS_SIZE_IN_GB:
LOG.debug('Using %(min_size)s GB file system for shares less than '
'%(min_size)s GB.', {'min_size': MIN_FS_SIZE_IN_GB})
size_gb = MIN_FS_SIZE_IN_GB
return size_gb * units.Gi
def extend_filesystem(self, fs, new_size_gb):
size = self.get_valid_fs_size_in_byte(new_size_gb)
try:
fs.extend(size)
except storops_ex.UnityNothingToModifyError:
LOG.debug('The size of the file system %(id)s is %(size)s '
'bytes.', {'id': fs.get_id(), 'size': size})
return size

View File

@@ -17,7 +17,6 @@
from oslo_log import log from oslo_log import log
from oslo_utils import excutils from oslo_utils import excutils
from oslo_utils import importutils from oslo_utils import importutils
from oslo_utils import units
storops = importutils.try_import('storops') storops = importutils.try_import('storops')
if storops: if storops:
@@ -98,7 +97,7 @@ class UnityStorageConnection(driver.StorageConnection):
def create_share(self, context, share, share_server=None): def create_share(self, context, share, share_server=None):
"""Create a share and export it based on protocol used.""" """Create a share and export it based on protocol used."""
share_name = share['id'] share_name = share['id']
size = share['size'] * units.Gi size = share['size']
# Check share's protocol. # Check share's protocol.
# Throw an exception immediately if it is an invalid protocol. # Throw an exception immediately if it is an invalid protocol.
@@ -205,7 +204,8 @@ class UnityStorageConnection(driver.StorageConnection):
share['share_proto']) share['share_proto'])
if not self._is_share_from_snapshot(backend_share): if not self._is_share_from_snapshot(backend_share):
backend_share.filesystem.extend(new_size * units.Gi) self.client.extend_filesystem(backend_share.filesystem,
new_size)
else: else:
share_id = share['id'] share_id = share['id']
reason = _LE("Driver does not support extending a " reason = _LE("Driver does not support extending a "

View File

@@ -64,3 +64,7 @@ class UnityNfsAlreadyEnabledError(UnityException):
class UnityHostNotFoundException(UnityException): class UnityHostNotFoundException(UnityException):
pass pass
class UnityNothingToModifyError(UnityException):
pass

View File

@@ -972,3 +972,11 @@ test_get_storage_processor:
unity: unity:
_methods: _methods:
get_sp: *sp_a get_sp: *sp_a
test_extend_filesystem:
fs:
_methods:
get_id: 'svc_12'
extend:
_raise:
UnityNothingToModifyError:

View File

@@ -13,11 +13,15 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import ddt
from oslo_utils import units
from manila import exception from manila import exception
from manila import test from manila import test
from manila.tests.share.drivers.dell_emc.plugins.unity import res_mock from manila.tests.share.drivers.dell_emc.plugins.unity import res_mock
@ddt.ddt
class TestClient(test.TestCase): class TestClient(test.TestCase):
@res_mock.mock_client_input @res_mock.mock_client_input
@res_mock.patch_client @res_mock.patch_client
@@ -166,3 +170,20 @@ class TestClient(test.TestCase):
sp = client.get_storage_processor(sp_id='SPA') sp = client.get_storage_processor(sp_id='SPA')
self.assertEqual('SPA', sp.name) self.assertEqual('SPA', sp.name)
@ddt.data((1, 3), (2, 3), (3, 3), (4, 4), (10, 10))
@ddt.unpack
@res_mock.patch_client
def test_get_valid_fs_size(self, client, share_size_gb, fs_size_gb):
size = client.get_valid_fs_size_in_byte(share_size_gb)
self.assertEqual(fs_size_gb * units.Gi, size)
@res_mock.mock_client_input
@res_mock.patch_client
def test_extend_filesystem(self, client, mocked_input):
fs = mocked_input['fs']
size = client.extend_filesystem(fs, 5)
self.assertEqual(5 * units.Gi, size)

View File

@@ -0,0 +1,5 @@
---
fixes:
- Shares under 3 GB cannot be created on the Dell EMC Unity back end. If users
create shares smaller than 3 GB, they will be allocated a 3 GB file system on
the Unity system.