NetApp SolidFire: Add options for replication mode

This adds the option to specify the replication mode as:
Synchronous, Asynchronous or SnapshotOnly.

Depends-On: I920f958db1d48e52b548082d852c03f427a279ca
Change-Id: I74d31e7a262f3a59f5e82c710f3ca5fd84e3ea60
This commit is contained in:
Thiago Correa 2019-08-28 11:40:33 -03:00 committed by Fernando F. Silva
parent 33b32d9820
commit ddc91052e4
3 changed files with 57 additions and 21 deletions

View File

@ -18,7 +18,10 @@ import datetime
import re
import six
import ddt
from ddt import data
from ddt import ddt
from ddt import file_data
from ddt import unpack
import mock
from oslo_utils import timeutils
from oslo_utils import units
@ -63,7 +66,7 @@ f_uuid = ['262b9ce2-a71a-4fbe-830c-c20c5596caea',
'362b9ce2-a71a-4fbe-830c-c20c5596caea']
@ddt.ddt
@ddt
class SolidFireVolumeTestCase(test.TestCase):
EXPECTED_QOS = {'minIOPS': 110, 'burstIOPS': 1530, 'maxIOPS': 1020}
@ -1237,8 +1240,8 @@ class SolidFireVolumeTestCase(test.TestCase):
qos = sfv._set_qos_by_volume_type(self.ctxt, type_ref['id'], size)
self.assertEqual(self.expected_qos_results, qos)
@ddt.file_data("scaled_iops_test_data.json")
@ddt.unpack
@file_data("scaled_iops_test_data.json")
@unpack
def test_scaled_qos_spec_by_type(self, argument):
sfv = solidfire.SolidFireDriver(configuration=self.configuration)
size = argument[0].pop('size')
@ -1246,8 +1249,8 @@ class SolidFireVolumeTestCase(test.TestCase):
qos = sfv._set_qos_by_volume_type(self.ctxt, type_ref['id'], size)
self.assertEqual(argument[1], qos)
@ddt.file_data("scaled_iops_invalid_data.json")
@ddt.unpack
@file_data("scaled_iops_invalid_data.json")
@unpack
def test_set_scaled_qos_by_type_invalid(self, inputs):
sfv = solidfire.SolidFireDriver(configuration=self.configuration)
size = inputs[0].pop('size')
@ -2684,22 +2687,31 @@ class SolidFireVolumeTestCase(test.TestCase):
except Exception:
pass
def test_set_rep_by_volume_type(self):
@data('Async', 'Sync', 'SnapshotsOnly')
@mock.patch.object(volume_types, 'get_volume_type')
def test_set_rep_by_volume_type(self, mode, mock_get_volume_type):
mock_get_volume_type.return_value = {
'name': 'sf-1', 'deleted': False,
'created_at': '2014-02-06 04:58:11',
'updated_at': None, 'extra_specs':
{'replication_enabled': '<is> True',
'solidfire:replication_mode': mode},
'deleted_at': None,
'id': '290edb2a-f5ea-11e5-9ce9-5e5517507c66'}
rep_opts = {}
sfv = solidfire.SolidFireDriver(configuration=self.configuration)
sfv.cluster_pairs = self.cluster_pairs
ctxt = None
type_id = '290edb2a-f5ea-11e5-9ce9-5e5517507c66'
fake_type = {'extra_specs': {'replication_enabled': '<is> True'}}
with mock.patch.object(volume_types,
'get_volume_type',
return_value=fake_type):
self.assertEqual('Async', sfv._set_rep_by_volume_type(
ctxt, type_id))
rep_opts['rep_type'] = mode
self.assertEqual(rep_opts, sfv._set_rep_by_volume_type(ctxt, type_id))
mock_get_volume_type.assert_called()
def test_replicate_volume(self):
replication_status = fields.ReplicationStatus.ENABLED
fake_vol = {'project_id': 1, 'volumeID': 1, 'size': 1}
params = {'attributes': {}}
rep_info = {'rep_type': 'Async'}
sf_account = {'initiatorSecret': 'shhh', 'targetSecret': 'dont-tell'}
model_update = {'provider_id': '1 2 xxxx'}
sfv = solidfire.SolidFireDriver(configuration=self.configuration)
@ -2716,7 +2728,7 @@ class SolidFireVolumeTestCase(test.TestCase):
return_value=model_update):
self.assertEqual({'replication_status': replication_status},
sfv._replicate_volume(fake_vol, params,
sf_account, {}))
sf_account, rep_info))
def test_pythons_try_except(self):
def _fake_retrieve_rep(vol):

View File

@ -221,9 +221,11 @@ class SolidFireDriver(san.SanISCSIDriver):
2.0.12 - Fix bug #1744005
2.0.14 - Fix bug #1782588 qos settings on extend
2.0.15 - Fix bug #1834013 NetApp SolidFire replication errors
2.0.16 - Add options for replication mode (Async, Sync and
SnapshotsOnly)
"""
VERSION = '2.0.15'
VERSION = '2.0.16'
# ThirdPartySystems wiki page
CI_WIKI_NAME = "NetApp_SolidFire_CI"
@ -323,6 +325,18 @@ class SolidFireDriver(san.SanISCSIDriver):
def get_driver_options():
return sf_opts
def _init_vendor_properties(self):
properties = {}
self._set_property(
properties,
"solidfire:replication_mode",
"Replication mode",
_("Specifies replication mode."),
"string",
enum=["Async", "Sync", "SnapshotsOnly"])
return properties, 'solidfire'
def __getattr__(self, attr):
if hasattr(self.target_driver, attr):
return getattr(self.target_driver, attr)
@ -1412,15 +1426,17 @@ class SolidFireDriver(san.SanISCSIDriver):
return rep_data
def _set_rep_by_volume_type(self, ctxt, type_id):
rep_type = None
rep_modes = ['Async', 'Sync', 'SnapshotsOnly']
rep_opts = {}
type_ref = volume_types.get_volume_type(ctxt, type_id)
specs = type_ref.get('extra_specs')
# TODO(erlon): Add support for sync/snapshot replication
if specs.get('replication_enabled', "") == "<is> True":
rep_type = 'Async'
if specs.get('solidfire:replication_mode') in rep_modes:
rep_opts['rep_type'] = specs.get('solidfire:replication_mode')
else:
rep_opts['rep_type'] = 'Async'
return rep_type
return rep_opts
def _replicate_volume(self, volume, params,
parent_sfaccount, rep_info):
@ -1476,7 +1492,8 @@ class SolidFireDriver(san.SanISCSIDriver):
volume['volumeID'])
# Make sure we split any pair the volume have
params = {'volumeID': volume['volumeID'], 'mode': rep_info}
params = {'volumeID': volume['volumeID'],
'mode': rep_info['rep_type']}
self._issue_api_request('RemoveVolumePair', params, '8.0')
rep_key = self._issue_api_request(

View File

@ -0,0 +1,7 @@
---
upgrade:
- |
SolidFire supports Synchronous, Asynchronous and SnapshotsOnly replication
modes. This adds the config option `solidfire:replication_mode` to specify
the mode to be used by Cinder. Its value can be `Sync`, `Async` or
`SnapshotsOnly`.