Set initial quota in Quobyte and correct resizing

Ensure a shares initial quota is set in the backend,
and do quota size conversion when resizing.

Closes-Bug: #1771958
Closes-Bug: #1771970

Change-Id: I64a1e591c2682bc8bb62554a95399b5651253f59
This commit is contained in:
Silvan Kaiser 2018-05-18 09:53:10 +02:00
parent 1095fb7478
commit fa5c0fd2ce
3 changed files with 28 additions and 9 deletions

View File

@ -77,9 +77,10 @@ class QuobyteShareDriver(driver.ExecuteMixin, driver.ShareDriver,):
1.2.2 - Minor optimizations 1.2.2 - Minor optimizations
1.2.3 - Updated RPC layer for improved stability 1.2.3 - Updated RPC layer for improved stability
1.2.4 - Fixed handling updated QB API error codes 1.2.4 - Fixed handling updated QB API error codes
1.2.5 - Fixed two quota handling bugs
""" """
DRIVER_VERSION = '1.2.4' DRIVER_VERSION = '1.2.5'
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(QuobyteShareDriver, self).__init__(False, *args, **kwargs) super(QuobyteShareDriver, self).__init__(False, *args, **kwargs)
@ -179,12 +180,14 @@ class QuobyteShareDriver(driver.ExecuteMixin, driver.ShareDriver,):
return project_id return project_id
def _resize_share(self, share, new_size): def _resize_share(self, share, new_size):
newsize_bytes = new_size * units.Gi
self.rpc.call('setQuota', {"quotas": [ self.rpc.call('setQuota', {"quotas": [
{"consumer": {"consumer":
[{"type": "VOLUME", [{"type": "VOLUME",
"identifier": share["name"]}], "identifier": share["name"],
"tenant_id": share["project_id"]}],
"limits": [{"type": "LOGICAL_DISK_SPACE", "limits": [{"type": "LOGICAL_DISK_SPACE",
"value": new_size}]} "value": newsize_bytes}]}
]}) ]})
def _resolve_volume_name(self, volume_name, tenant_domain): def _resolve_volume_name(self, volume_name, tenant_domain):
@ -242,6 +245,8 @@ class QuobyteShareDriver(driver.ExecuteMixin, driver.ShareDriver,):
volume_uuid=volume_uuid, volume_uuid=volume_uuid,
protocol='NFS')) protocol='NFS'))
self._resize_share(share, share['size'])
return '%(nfs_server_ip)s:%(nfs_export_path)s' % result return '%(nfs_server_ip)s:%(nfs_export_path)s' % result
def delete_share(self, context, share, share_server=None): def delete_share(self, context, share, share_server=None):
@ -326,7 +331,7 @@ class QuobyteShareDriver(driver.ExecuteMixin, driver.ShareDriver,):
self.rpc.call('exportVolume', call_params) self.rpc.call('exportVolume', call_params)
def extend_share(self, ext_share, ext_size, share_server=None): def extend_share(self, ext_share, ext_size, share_server=None):
"""Uses resize_share to extend a share. """Uses _resize_share to extend a share.
:param ext_share: Share model. :param ext_share: Share model.
:param ext_size: New size of share (new_size > share['size']). :param ext_size: New size of share (new_size > share['size']).
@ -335,7 +340,7 @@ class QuobyteShareDriver(driver.ExecuteMixin, driver.ShareDriver,):
self._resize_share(share=ext_share, new_size=ext_size) self._resize_share(share=ext_share, new_size=ext_size)
def shrink_share(self, shrink_share, shrink_size, share_server=None): def shrink_share(self, shrink_share, shrink_size, share_server=None):
"""Uses resize_share to shrink a share. """Uses _resize_share to shrink a share.
Quobyte uses soft quotas. If a shares current size is bigger than Quobyte uses soft quotas. If a shares current size is bigger than
the new shrunken size no data is lost. Data can be continuously read the new shrunken size no data is lost. Data can be continuously read

View File

@ -15,6 +15,7 @@
import mock import mock
from oslo_config import cfg from oslo_config import cfg
from oslo_utils import units
import six import six
from manila import context from manila import context
@ -114,7 +115,8 @@ class QuobyteShareDriverTestCase(test.TestCase):
self.assertRaises(exception.QBException, self.assertRaises(exception.QBException,
self._driver.do_setup, self._context) self._driver.do_setup, self._context)
def test_create_share_new_volume(self): @mock.patch.object(quobyte.QuobyteShareDriver, "_resize_share")
def test_create_share_new_volume(self, qb_resize_mock):
self._driver.rpc.call = mock.Mock(wraps=fake_rpc_handler) self._driver.rpc.call = mock.Mock(wraps=fake_rpc_handler)
result = self._driver.create_share(self._context, self.share) result = self._driver.create_share(self._context, self.share)
@ -130,8 +132,10 @@ class QuobyteShareDriverTestCase(test.TestCase):
)), )),
mock.call('exportVolume', mock.call('exportVolume',
dict(protocol='NFS', volume_uuid='voluuid'))]) dict(protocol='NFS', volume_uuid='voluuid'))])
qb_resize_mock.assert_called_once_with(self.share, self.share['size'])
def test_create_share_existing_volume(self): @mock.patch.object(quobyte.QuobyteShareDriver, "_resize_share")
def test_create_share_existing_volume(self, qb_resize_mock):
self._driver.rpc.call = mock.Mock(wraps=fake_rpc_handler) self._driver.rpc.call = mock.Mock(wraps=fake_rpc_handler)
self._driver.create_share(self._context, self.share) self._driver.create_share(self._context, self.share)
@ -153,6 +157,7 @@ class QuobyteShareDriverTestCase(test.TestCase):
mock.call('createVolume', create_params), mock.call('createVolume', create_params),
mock.call('exportVolume', dict(protocol='NFS', mock.call('exportVolume', dict(protocol='NFS',
volume_uuid='voluuid'))]) volume_uuid='voluuid'))])
qb_resize_mock.assert_called_once_with(self.share, self.share['size'])
def test_create_share_wrong_protocol(self): def test_create_share_wrong_protocol(self):
share = {'share_proto': 'WRONG_PROTOCOL'} share = {'share_proto': 'WRONG_PROTOCOL'}
@ -413,18 +418,21 @@ class QuobyteShareDriverTestCase(test.TestCase):
def test_resize_share(self): def test_resize_share(self):
self._driver.rpc.call = mock.Mock(wraps=fake_rpc_handler) self._driver.rpc.call = mock.Mock(wraps=fake_rpc_handler)
manila_size = 7
newsize_bytes = manila_size * units.Gi
self._driver._resize_share(share=self.share, new_size=7) self._driver._resize_share(share=self.share, new_size=manila_size)
exp_params = { exp_params = {
"quotas": [{ "quotas": [{
"consumer": [{ "consumer": [{
"type": "VOLUME", "type": "VOLUME",
"identifier": self.share["name"], "identifier": self.share["name"],
"tenant_id": self.share["project_id"]
}], }],
"limits": [{ "limits": [{
"type": "LOGICAL_DISK_SPACE", "type": "LOGICAL_DISK_SPACE",
"value": 7, "value": newsize_bytes,
}], }],
}]} }]}
self._driver.rpc.call.assert_has_calls([ self._driver.rpc.call.assert_has_calls([

View File

@ -0,0 +1,6 @@
---
fixes:
- |
New shares created on a Quobyte backend are now initialized with the correct quota.
- |
fixes a bug causing incorrect quotas being set in the backend when resizing Quobyte shares.