Merge "QNAP: Fix inconsistent cases while create/manage from snapshot"
This commit is contained in:
commit
77fe6ae7d6
|
@ -467,13 +467,14 @@ class QnapAPIExecutor(object):
|
|||
raise exception.ShareBackendException(msg=msg)
|
||||
|
||||
@_connection_checker
|
||||
def clone_snapshot(self, snapshot_id, new_sharename):
|
||||
def clone_snapshot(self, snapshot_id, new_sharename, clone_size):
|
||||
"""Execute CGI to clone snapshot as share."""
|
||||
params = {
|
||||
'func': 'clone_qsnapshot',
|
||||
'by_vol': '1',
|
||||
'snapshotID': snapshot_id,
|
||||
'new_name': new_sharename,
|
||||
'clone_size': '{}g'.format(clone_size),
|
||||
'sid': self.sid,
|
||||
}
|
||||
sanitized_params = self._sanitize_params(params)
|
||||
|
|
|
@ -77,6 +77,8 @@ class QnapShareDriver(driver.ShareDriver):
|
|||
1.0.7 - Add support for QES fw on TDS series NAS model.
|
||||
1.0.8 - Fix bug, driver should not manage snapshot which does not
|
||||
exist in NAS.
|
||||
Fix bug, driver should create share from snapshot with
|
||||
specified size.
|
||||
"""
|
||||
|
||||
DRIVER_VERSION = '1.0.8'
|
||||
|
@ -540,7 +542,8 @@ class QnapShareDriver(driver.ShareDriver):
|
|||
msg = _("Failed to create an unused share name.")
|
||||
raise exception.ShareBackendException(msg=msg)
|
||||
|
||||
self.api_executor.clone_snapshot(snapshot_id, create_share_name)
|
||||
self.api_executor.clone_snapshot(snapshot_id,
|
||||
create_share_name, share['size'])
|
||||
|
||||
create_volID = ""
|
||||
created_share = self.api_executor.get_share_info(
|
||||
|
@ -553,10 +556,6 @@ class QnapShareDriver(driver.ShareDriver):
|
|||
msg = _("Failed to clone a snapshot in time.")
|
||||
raise exception.ShareBackendException(msg=msg)
|
||||
|
||||
snap_share = self.share_api.get(
|
||||
context, snapshot['share_instance']['share_id'])
|
||||
LOG.debug('snap_share[size]: %s', snap_share['size'])
|
||||
|
||||
thin_provision = self.private_storage.get(
|
||||
snapshot['share_instance_id'], 'thin_provision')
|
||||
compression = self.private_storage.get(
|
||||
|
@ -574,19 +573,6 @@ class QnapShareDriver(driver.ShareDriver):
|
|||
'deduplication': deduplication,
|
||||
'ssd_cache': ssd_cache})
|
||||
|
||||
if (share['size'] > snap_share['size']):
|
||||
share_dict = {
|
||||
'sharename': create_share_name,
|
||||
'old_sharename': create_share_name,
|
||||
'new_size': share['size'],
|
||||
'thin_provision': thin_provision == 'True',
|
||||
'compression': compression == 'True',
|
||||
'deduplication': deduplication == 'True',
|
||||
'ssd_cache': ssd_cache == 'True',
|
||||
'share_proto': share['share_proto']
|
||||
}
|
||||
self.api_executor.edit_share(share_dict)
|
||||
|
||||
# Use private_storage to record volume ID and Name created in the NAS.
|
||||
_metadata = {
|
||||
'volID': create_volID,
|
||||
|
@ -930,6 +916,11 @@ class QnapShareDriver(driver.ShareDriver):
|
|||
'snapshot_id': snapshot_id,
|
||||
}
|
||||
self.private_storage.update(snapshot['id'], _metadata)
|
||||
parent_size = check_snapshot.find('parent_size')
|
||||
snap_size_gb = None
|
||||
if parent_size is not None:
|
||||
snap_size_gb = math.ceil(float(parent_size.text) / units.Gi)
|
||||
return {'size': snap_size_gb}
|
||||
|
||||
def unmanage_snapshot(self, snapshot):
|
||||
"""Remove the specified snapshot from Manila management."""
|
||||
|
|
|
@ -173,62 +173,6 @@ FAKE_RES_DETAIL_DATA_GETBASIC_INFO_TES_ES_2_2_0 = """
|
|||
</firmware>
|
||||
</QDocRoot>"""
|
||||
|
||||
FAKE_RES_DETAIL_DATA_GETBASIC_INFO_TDS_TS_4_0_0 = """
|
||||
<QDocRoot version="1.0">
|
||||
<model>
|
||||
<displayModelName><![CDATA[TDS-16489U R2]]></displayModelName>
|
||||
<internalModelName><![CDATA[TS-X89]]></internalModelName>
|
||||
</model>
|
||||
<firmware>
|
||||
<version><![CDATA[4.0.0]]></version>
|
||||
</firmware>
|
||||
</QDocRoot>"""
|
||||
|
||||
FAKE_RES_DETAIL_DATA_GETBASIC_INFO_TDS_TS_4_3_0 = """
|
||||
<QDocRoot version="1.0">
|
||||
<model>
|
||||
<displayModelName><![CDATA[TDS-16489U R2]]></displayModelName>
|
||||
<internalModelName><![CDATA[TS-X89]]></internalModelName>
|
||||
</model>
|
||||
<firmware>
|
||||
<version><![CDATA[4.3.0]]></version>
|
||||
</firmware>
|
||||
</QDocRoot>"""
|
||||
|
||||
FAKE_RES_DETAIL_DATA_GETBASIC_INFO_TDS_ES_1_1_1 = """
|
||||
<QDocRoot version="1.0">
|
||||
<model>
|
||||
<displayModelName><![CDATA[TDS-16489U R2]]></displayModelName>
|
||||
<internalModelName><![CDATA[ES-X85U]]></internalModelName>
|
||||
</model>
|
||||
<firmware>
|
||||
<version><![CDATA[1.1.1]]></version>
|
||||
</firmware>
|
||||
</QDocRoot>"""
|
||||
|
||||
FAKE_RES_DETAIL_DATA_GETBASIC_INFO_TDS_ES_2_1_0 = """
|
||||
<QDocRoot version="1.0">
|
||||
<model>
|
||||
<displayModelName><![CDATA[TDS-16489U R2]]></displayModelName>
|
||||
<internalModelName><![CDATA[ES-X85U]]></internalModelName>
|
||||
</model>
|
||||
<firmware>
|
||||
<version><![CDATA[2.1.0]]></version>
|
||||
</firmware>
|
||||
</QDocRoot>"""
|
||||
|
||||
FAKE_RES_DETAIL_DATA_GETBASIC_INFO_TDS_ES_2_2_0 = """
|
||||
<QDocRoot version="1.0">
|
||||
<model>
|
||||
<displayModelName><![CDATA[TDS-16489U R2]]></displayModelName>
|
||||
<internalModelName><![CDATA[ES-X85U]]></internalModelName>
|
||||
</model>
|
||||
<firmware>
|
||||
<version><![CDATA[2.2.0]]></version>
|
||||
</firmware>
|
||||
</QDocRoot>"""
|
||||
|
||||
|
||||
FAKE_RES_DETAIL_DATA_GETBASIC_INFO_ERROR = """
|
||||
<QDocRoot version="1.0">
|
||||
<model>
|
||||
|
@ -276,6 +220,7 @@ FAKE_RES_DETAIL_DATA_SNAPSHOT = """
|
|||
<row>
|
||||
<snapshot_id><![CDATA[fakeSnapshotId]]></snapshot_id>
|
||||
<snapshot_name><![CDATA[fakeSnapshotName]]></snapshot_name>
|
||||
<parent_size>10</parent_size>
|
||||
</row>
|
||||
</SnapshotList>
|
||||
<result><![CDATA[0]]></result>
|
||||
|
@ -681,56 +626,6 @@ class FakeGetBasicInfoResponseTesEs_2_2_0(object):
|
|||
return FAKE_RES_DETAIL_DATA_GETBASIC_INFO_TES_ES_2_2_0
|
||||
|
||||
|
||||
class FakeGetBasicInfoResponseTdsTs_4_0_0(object):
|
||||
"""Fake GetBasicInfoTS response from TS nas."""
|
||||
|
||||
status = 'fackStatus'
|
||||
|
||||
def read(self):
|
||||
"""Mock response.read."""
|
||||
return FAKE_RES_DETAIL_DATA_GETBASIC_INFO_TDS_TS_4_0_0
|
||||
|
||||
|
||||
class FakeGetBasicInfoResponseTdsTs_4_3_0(object):
|
||||
"""Fake GetBasicInfoTS response from TS nas."""
|
||||
|
||||
status = 'fackStatus'
|
||||
|
||||
def read(self):
|
||||
"""Mock response.read."""
|
||||
return FAKE_RES_DETAIL_DATA_GETBASIC_INFO_TDS_TS_4_3_0
|
||||
|
||||
|
||||
class FakeGetBasicInfoResponseTdsEs_1_1_1(object):
|
||||
"""Fake GetBasicInfoTS response from ES nas."""
|
||||
|
||||
status = 'fackStatus'
|
||||
|
||||
def read(self):
|
||||
"""Mock response.read."""
|
||||
return FAKE_RES_DETAIL_DATA_GETBASIC_INFO_TDS_ES_1_1_1
|
||||
|
||||
|
||||
class FakeGetBasicInfoResponseTdsEs_2_1_0(object):
|
||||
"""Fake GetBasicInfoTS response from ES nas."""
|
||||
|
||||
status = 'fackStatus'
|
||||
|
||||
def read(self):
|
||||
"""Mock response.read."""
|
||||
return FAKE_RES_DETAIL_DATA_GETBASIC_INFO_TDS_ES_2_1_0
|
||||
|
||||
|
||||
class FakeGetBasicInfoResponseTdsEs_2_2_0(object):
|
||||
"""Fake GetBasicInfoTS response from ES nas."""
|
||||
|
||||
status = 'fackStatus'
|
||||
|
||||
def read(self):
|
||||
"""Mock response.read."""
|
||||
return FAKE_RES_DETAIL_DATA_GETBASIC_INFO_TDS_ES_2_2_0
|
||||
|
||||
|
||||
class FakeGetBasicInfoResponseError(object):
|
||||
"""Fake GetBasicInfoTS response from TS nas."""
|
||||
|
||||
|
|
|
@ -424,13 +424,15 @@ class QnapAPITestCase(QnapShareDriverBaseTestCase):
|
|||
'qnapadmin', 'Storage Pool 1')
|
||||
self.driver.api_executor.clone_snapshot(
|
||||
'fakeSnapshotId',
|
||||
'fakeNewShareName')
|
||||
'fakeNewShareName',
|
||||
'fakeCloneSize')
|
||||
|
||||
fake_params = {
|
||||
'func': 'clone_qsnapshot',
|
||||
'by_vol': '1',
|
||||
'snapshotID': 'fakeSnapshotId',
|
||||
'new_name': 'fakeNewShareName',
|
||||
'clone_size': '{}g'.format('fakeCloneSize'),
|
||||
'sid': 'fakeSid',
|
||||
}
|
||||
sanitized_params = self._sanitize_params(fake_params)
|
||||
|
@ -804,12 +806,14 @@ class QnapAPITestCase(QnapShareDriverBaseTestCase):
|
|||
fakes.FakeGetBasicInfoResponseEs_1_1_3()],
|
||||
['self.driver.api_executor.clone_snapshot',
|
||||
{'snapshot_id': 'fakeSnapshotId',
|
||||
'new_sharename': 'fakeNewShareName'},
|
||||
'new_sharename': 'fakeNewShareName',
|
||||
'clone_size': 'fakeCloneSize'},
|
||||
fakes.FakeResultNegativeResponse(),
|
||||
fakes.FakeGetBasicInfoResponseEs_1_1_3()],
|
||||
['self.driver.api_executor.clone_snapshot',
|
||||
{'snapshot_id': 'fakeSnapshotId',
|
||||
'new_sharename': 'fakeNewShareName'},
|
||||
'new_sharename': 'fakeNewShareName',
|
||||
'clone_size': 'fakeCloneSize'},
|
||||
fakes.FakeAuthPassFailResponse(),
|
||||
fakes.FakeGetBasicInfoResponseEs_1_1_3()],
|
||||
['self.driver.api_executor.edit_share',
|
||||
|
|
|
@ -159,12 +159,6 @@ class QnapShareDriverLoginTestCase(QnapShareDriverBaseTestCase):
|
|||
}, {
|
||||
'fake_basic_info': fakes.FakeGetBasicInfoResponseTesEs_2_1_0(),
|
||||
'expect_result': api.QnapAPIExecutor
|
||||
}, {
|
||||
'fake_basic_info': fakes.FakeGetBasicInfoResponseTdsTs_4_3_0(),
|
||||
'expect_result': api.QnapAPIExecutorTS
|
||||
}, {
|
||||
'fake_basic_info': fakes.FakeGetBasicInfoResponseTdsEs_2_1_0(),
|
||||
'expect_result': api.QnapAPIExecutor
|
||||
}, {
|
||||
'fake_basic_info': fakes.FakeGetBasicInfoResponseEs_1_1_3(),
|
||||
'expect_result': api.QnapAPIExecutor
|
||||
|
@ -200,15 +194,6 @@ class QnapShareDriverLoginTestCase(QnapShareDriverBaseTestCase):
|
|||
}, {
|
||||
'fake_basic_info': fakes.FakeGetBasicInfoResponseTesEs_2_2_0(),
|
||||
'expect_result': exception.ShareBackendException
|
||||
}, {
|
||||
'fake_basic_info': fakes.FakeGetBasicInfoResponseTdsTs_4_0_0(),
|
||||
'expect_result': exception.ShareBackendException
|
||||
}, {
|
||||
'fake_basic_info': fakes.FakeGetBasicInfoResponseTdsEs_1_1_1(),
|
||||
'expect_result': exception.ShareBackendException
|
||||
}, {
|
||||
'fake_basic_info': fakes.FakeGetBasicInfoResponseTdsEs_2_2_0(),
|
||||
'expect_result': exception.ShareBackendException
|
||||
}, {
|
||||
'fake_basic_info': fakes.FakeGetBasicInfoResponseEs_1_1_1(),
|
||||
'expect_result': exception.ShareBackendException
|
||||
|
@ -730,15 +715,13 @@ class QnapShareDriverTestCase(QnapShareDriverBaseTestCase):
|
|||
expected_call_list,
|
||||
mock_api_return.get_share_info.call_args_list)
|
||||
mock_api_return.clone_snapshot.assert_called_once_with(
|
||||
'fakeShareName@fakeSnapshotName', 'fakeShareName')
|
||||
'fakeShareName@fakeSnapshotName', 'fakeShareName', 10)
|
||||
|
||||
@mock.patch.object(qnap.QnapShareDriver, '_get_location_path')
|
||||
@mock.patch('manila.share.API')
|
||||
@mock.patch.object(qnap.QnapShareDriver, '_gen_random_name')
|
||||
def test_create_share_from_snapshot_diff_size(
|
||||
self,
|
||||
mock_gen_random_name,
|
||||
mock_share_api,
|
||||
mock_get_location_path):
|
||||
"""Test create share from snapshot."""
|
||||
fake_snapshot = fakes.SnapshotClass(
|
||||
|
@ -755,9 +738,6 @@ class QnapShareDriverTestCase(QnapShareDriverBaseTestCase):
|
|||
'False',
|
||||
'False',
|
||||
'fakeVolName']
|
||||
mock_share_api.return_value.get.return_value = {'size': 5}
|
||||
mock_api_executor.return_value.edit_share.return_value = (
|
||||
None)
|
||||
|
||||
self._do_setup('http://1.2.3.4:8080', '1.2.3.4', 'admin',
|
||||
'qnapadmin', 'Storage Pool 1',
|
||||
|
@ -775,19 +755,7 @@ class QnapShareDriverTestCase(QnapShareDriverBaseTestCase):
|
|||
expected_call_list,
|
||||
mock_api_return.get_share_info.call_args_list)
|
||||
mock_api_return.clone_snapshot.assert_called_once_with(
|
||||
'fakeShareName@fakeSnapshotName', 'fakeShareName')
|
||||
expect_share_dict = {
|
||||
'sharename': 'fakeShareName',
|
||||
'old_sharename': 'fakeShareName',
|
||||
'new_size': 10,
|
||||
'thin_provision': True,
|
||||
'compression': True,
|
||||
'deduplication': False,
|
||||
'ssd_cache': False,
|
||||
'share_proto': 'NFS'
|
||||
}
|
||||
mock_api_return.edit_share.assert_called_once_with(
|
||||
expect_share_dict)
|
||||
'fakeShareName@fakeSnapshotName', 'fakeShareName', 10)
|
||||
|
||||
def test_create_share_from_snapshot_without_snapshot_id(self):
|
||||
"""Test create share from snapshot."""
|
||||
|
@ -1129,6 +1097,8 @@ class QnapShareDriverTestCase(QnapShareDriverBaseTestCase):
|
|||
mock_api_executor = qnap.QnapShareDriver._create_api_executor
|
||||
mock_api_executor.return_value.get_share_info.return_value = (
|
||||
self.get_share_info_return_value())
|
||||
mock_api_executor.return_value.get_snapshot_info.return_value = (
|
||||
self.get_snapshot_info_return_value())
|
||||
mock_private_storage = mock.Mock()
|
||||
mock_private_storage.update.return_value = None
|
||||
mock_private_storage.get.side_effect = [
|
||||
|
@ -1147,35 +1117,6 @@ class QnapShareDriverTestCase(QnapShareDriverBaseTestCase):
|
|||
mock_private_storage.update.assert_called_once_with(
|
||||
'fakeSnapshotId', fake_metadata)
|
||||
|
||||
@mock.patch.object(qnap.QnapShareDriver, '_get_location_path')
|
||||
def test_manage_existing_snapshot_not_exist(
|
||||
self,
|
||||
mock_get_location_path):
|
||||
"""Test manage existing snapshot with snapshot which does not exist."""
|
||||
fake_snapshot = fakes.SnapshotClass(
|
||||
10, 'fakeShareName@fakeSnapshotName')
|
||||
|
||||
mock_api_executor = qnap.QnapShareDriver._create_api_executor
|
||||
mock_api_executor.return_value.get_share_info.return_value = (
|
||||
self.get_share_info_return_value())
|
||||
mock_api_executor.return_value.get_snapshot_info.return_value = None
|
||||
mock_private_storage = mock.Mock()
|
||||
mock_private_storage.get.side_effect = [
|
||||
'fakeVolId', 'fakeVolName']
|
||||
|
||||
self._do_setup('http://1.2.3.4:8080', '1.2.3.4', 'admin',
|
||||
'qnapadmin', 'Storage Pool 1',
|
||||
private_storage=mock_private_storage)
|
||||
|
||||
mock_api_return = mock_api_executor.return_value
|
||||
self.assertRaises(
|
||||
exception.InvalidParameterValue,
|
||||
self.driver.manage_existing_snapshot,
|
||||
snapshot=fake_snapshot,
|
||||
driver_options='driver_options')
|
||||
mock_api_return.get_share_info.assert_called_once_with(
|
||||
'Storage Pool 1', vol_no='fakeVolId')
|
||||
|
||||
def test_unmanage_snapshot(self):
|
||||
"""Test unmanage snapshot."""
|
||||
fake_snapshot = fakes.SnapshotClass(
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
fixes:
|
||||
- |
|
||||
Fixed the QNAP driver so that the managed snapshot and the share which
|
||||
created from snapshot will not be inconsistent in some cases.
|
Loading…
Reference in New Issue