Modify Pure driver to configure PG/Pod names
Add two config options to the Pure Storage driver to allow setting the names for replication PGs and Pods. This is beneficial in multi-backend scenarios so that each backend can use a different PG/Pod. It also allows for the use of existing PGs/Pods. These options should not be modified after volumes exist on a backend. Change-Id: Ie0dbf00fb2ecea3344e58d2b84fd4dfd6ae1daee
This commit is contained in:
parent
45df029a4d
commit
030d893697
@ -538,6 +538,8 @@ class PureBaseSharedDriverTestCase(PureDriverTestCase):
|
|||||||
super(PureBaseSharedDriverTestCase, self).setUp()
|
super(PureBaseSharedDriverTestCase, self).setUp()
|
||||||
self.driver = pure.PureBaseVolumeDriver(configuration=self.mock_config)
|
self.driver = pure.PureBaseVolumeDriver(configuration=self.mock_config)
|
||||||
self.driver._array = self.array
|
self.driver._array = self.array
|
||||||
|
self.driver._replication_pod_name = 'cinder-pod'
|
||||||
|
self.driver._replication_pg_name = 'cinder-group'
|
||||||
self.array.get_rest_version.return_value = '1.4'
|
self.array.get_rest_version.return_value = '1.4'
|
||||||
self.purestorage_module.FlashArray.side_effect = None
|
self.purestorage_module.FlashArray.side_effect = None
|
||||||
self.async_array2.get_rest_version.return_value = '1.4'
|
self.async_array2.get_rest_version.return_value = '1.4'
|
||||||
@ -603,6 +605,9 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
REPLICATION_RETENTION_LONG_TERM)
|
REPLICATION_RETENTION_LONG_TERM)
|
||||||
self.mock_config.pure_replica_retention_long_term_default = (
|
self.mock_config.pure_replica_retention_long_term_default = (
|
||||||
REPLICATION_RETENTION_LONG_TERM_PER_DAY)
|
REPLICATION_RETENTION_LONG_TERM_PER_DAY)
|
||||||
|
|
||||||
|
self.mock_config.pure_replication_pg_name = 'cinder-group'
|
||||||
|
self.mock_config.pure_replication_pod_name = 'cinder-pod'
|
||||||
self.mock_config.safe_get.return_value = [
|
self.mock_config.safe_get.return_value = [
|
||||||
{"backend_id": self.driver._array.array_id,
|
{"backend_id": self.driver._array.array_id,
|
||||||
"managed_backend_name": None,
|
"managed_backend_name": None,
|
||||||
@ -2455,12 +2460,12 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
self.assertEqual(expected_model_update, model_update)
|
self.assertEqual(expected_model_update, model_update)
|
||||||
if expected_add_to_group:
|
if expected_add_to_group:
|
||||||
self.array.set_pgroup.assert_called_once_with(
|
self.array.set_pgroup.assert_called_once_with(
|
||||||
pure.REPLICATION_CG_NAME,
|
self.driver._replication_pg_name,
|
||||||
addvollist=[vol_name]
|
addvollist=[vol_name]
|
||||||
)
|
)
|
||||||
if expected_remove_from_pgroup:
|
if expected_remove_from_pgroup:
|
||||||
self.array.set_pgroup.assert_called_once_with(
|
self.array.set_pgroup.assert_called_once_with(
|
||||||
pure.REPLICATION_CG_NAME,
|
self.driver._replication_pg_name,
|
||||||
remvollist=[vol_name]
|
remvollist=[vol_name]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -72,6 +72,12 @@ PURE_OPTS = [
|
|||||||
cfg.IntOpt("pure_replica_retention_long_term_default", default=7,
|
cfg.IntOpt("pure_replica_retention_long_term_default", default=7,
|
||||||
help="Retain snapshots per day on target for this time "
|
help="Retain snapshots per day on target for this time "
|
||||||
"(in days.)"),
|
"(in days.)"),
|
||||||
|
cfg.StrOpt("pure_replication_pg_name", default="cinder-group",
|
||||||
|
help="Pure Protection Group name to use for async replication "
|
||||||
|
"(will be created if it does not exist)."),
|
||||||
|
cfg.StrOpt("pure_replication_pod_name", default="cinder-pod",
|
||||||
|
help="Pure Pod name to use for sync replication "
|
||||||
|
"(will be created if it does not exist)."),
|
||||||
cfg.BoolOpt("pure_eradicate_on_delete",
|
cfg.BoolOpt("pure_eradicate_on_delete",
|
||||||
default=False,
|
default=False,
|
||||||
help="When enabled, all Pure volumes, snapshots, and "
|
help="When enabled, all Pure volumes, snapshots, and "
|
||||||
@ -89,8 +95,6 @@ CONF.register_opts(PURE_OPTS, group=configuration.SHARED_CONF_GROUP)
|
|||||||
INVALID_CHARACTERS = re.compile(r"[^-a-zA-Z0-9]")
|
INVALID_CHARACTERS = re.compile(r"[^-a-zA-Z0-9]")
|
||||||
GENERATED_NAME = re.compile(r".*-[a-f0-9]{32}-cinder$")
|
GENERATED_NAME = re.compile(r".*-[a-f0-9]{32}-cinder$")
|
||||||
|
|
||||||
REPLICATION_CG_NAME = "cinder-group"
|
|
||||||
REPLICATION_POD_NAME = "cinder-pod"
|
|
||||||
REPLICATION_TYPE_SYNC = "sync"
|
REPLICATION_TYPE_SYNC = "sync"
|
||||||
REPLICATION_TYPE_ASYNC = "async"
|
REPLICATION_TYPE_ASYNC = "async"
|
||||||
REPLICATION_TYPES = [REPLICATION_TYPE_SYNC, REPLICATION_TYPE_ASYNC]
|
REPLICATION_TYPES = [REPLICATION_TYPE_SYNC, REPLICATION_TYPE_ASYNC]
|
||||||
@ -181,8 +185,8 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
self._replication_target_arrays = []
|
self._replication_target_arrays = []
|
||||||
self._active_cluster_target_arrays = []
|
self._active_cluster_target_arrays = []
|
||||||
self._uniform_active_cluster_target_arrays = []
|
self._uniform_active_cluster_target_arrays = []
|
||||||
self._replication_pg_name = REPLICATION_CG_NAME
|
self._replication_pg_name = None
|
||||||
self._replication_pod_name = REPLICATION_POD_NAME
|
self._replication_pod_name = None
|
||||||
self._replication_interval = None
|
self._replication_interval = None
|
||||||
self._replication_retention_short_term = None
|
self._replication_retention_short_term = None
|
||||||
self._replication_retention_long_term = None
|
self._replication_retention_long_term = None
|
||||||
@ -200,6 +204,10 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def parse_replication_configs(self):
|
def parse_replication_configs(self):
|
||||||
|
self._replication_pg_name = (
|
||||||
|
self.configuration.pure_replication_pg_name)
|
||||||
|
self._replication_pod_name = (
|
||||||
|
self.configuration.pure_replication_pod_name)
|
||||||
self._replication_interval = (
|
self._replication_interval = (
|
||||||
self.configuration.pure_replica_interval_default)
|
self.configuration.pure_replica_interval_default)
|
||||||
self._replication_retention_short_term = (
|
self._replication_retention_short_term = (
|
||||||
@ -1519,7 +1527,7 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
repl_type = self._get_replication_type_from_vol_type(
|
repl_type = self._get_replication_type_from_vol_type(
|
||||||
volume.volume_type)
|
volume.volume_type)
|
||||||
if repl_type == REPLICATION_TYPE_SYNC:
|
if repl_type == REPLICATION_TYPE_SYNC:
|
||||||
base_name = REPLICATION_POD_NAME + "::" + base_name
|
base_name = self._replication_pod_name + "::" + base_name
|
||||||
|
|
||||||
return base_name + "-cinder"
|
return base_name + "-cinder"
|
||||||
|
|
||||||
@ -1547,7 +1555,7 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
# pod.
|
# pod.
|
||||||
base_name = ""
|
base_name = ""
|
||||||
if REPLICATION_TYPE_SYNC in self._group_potential_repl_types(pgroup):
|
if REPLICATION_TYPE_SYNC in self._group_potential_repl_types(pgroup):
|
||||||
base_name = REPLICATION_POD_NAME + "::"
|
base_name = self._replication_pod_name + "::"
|
||||||
|
|
||||||
return "%(base)sconsisgroup-%(id)s-cinder" % {
|
return "%(base)sconsisgroup-%(id)s-cinder" % {
|
||||||
'base': base_name, 'id': pgroup.id}
|
'base': base_name, 'id': pgroup.id}
|
||||||
@ -2068,6 +2076,9 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
|
|
||||||
@pure_driver_debug_trace
|
@pure_driver_debug_trace
|
||||||
def _create_pod_if_not_exist(self, source_array, name):
|
def _create_pod_if_not_exist(self, source_array, name):
|
||||||
|
if not name:
|
||||||
|
raise exception.PureDriverException(
|
||||||
|
reason=_("Empty string passed for Pod name."))
|
||||||
try:
|
try:
|
||||||
source_array.create_pod(name)
|
source_array.create_pod(name)
|
||||||
except purestorage.PureHTTPError as err:
|
except purestorage.PureHTTPError as err:
|
||||||
@ -2088,6 +2099,9 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
|
|
||||||
@pure_driver_debug_trace
|
@pure_driver_debug_trace
|
||||||
def _create_protection_group_if_not_exist(self, source_array, pgname):
|
def _create_protection_group_if_not_exist(self, source_array, pgname):
|
||||||
|
if not pgname:
|
||||||
|
raise exception.PureDriverException(
|
||||||
|
reason=_("Empty string passed for PG name."))
|
||||||
try:
|
try:
|
||||||
source_array.create_pgroup(pgname)
|
source_array.create_pgroup(pgname)
|
||||||
except purestorage.PureHTTPError as err:
|
except purestorage.PureHTTPError as err:
|
||||||
@ -2154,7 +2168,7 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
try:
|
try:
|
||||||
secondary_array = array
|
secondary_array = array
|
||||||
# Ensure the pod is in a good state on the array
|
# Ensure the pod is in a good state on the array
|
||||||
pod_info = secondary_array.get_pod(REPLICATION_POD_NAME)
|
pod_info = secondary_array.get_pod(self._replication_pod_name)
|
||||||
for pod_array in pod_info["arrays"]:
|
for pod_array in pod_info["arrays"]:
|
||||||
# Compare against Purity ID's
|
# Compare against Purity ID's
|
||||||
if pod_array["array_id"] == secondary_array.array_id:
|
if pod_array["array_id"] == secondary_array.array_id:
|
||||||
@ -2251,7 +2265,7 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
replicated_vol_names = set()
|
replicated_vol_names = set()
|
||||||
for vol in array_volumes:
|
for vol in array_volumes:
|
||||||
name = vol['name']
|
name = vol['name']
|
||||||
if name.startswith(REPLICATION_POD_NAME):
|
if name.startswith(self._replication_pod_name):
|
||||||
replicated_vol_names.add(name)
|
replicated_vol_names.add(name)
|
||||||
|
|
||||||
model_updates = []
|
model_updates = []
|
||||||
|
@ -244,9 +244,9 @@ To create a volume type that specifies replication to remote back ends with asyn
|
|||||||
The following table contains the optional configuration parameters available
|
The following table contains the optional configuration parameters available
|
||||||
for async replication configuration with the Pure Storage array.
|
for async replication configuration with the Pure Storage array.
|
||||||
|
|
||||||
==================================================== ============= ======
|
==================================================== ============= ================
|
||||||
Option Description Default
|
Option Description Default
|
||||||
==================================================== ============= ======
|
==================================================== ============= ================
|
||||||
``pure_replica_interval_default`` Snapshot
|
``pure_replica_interval_default`` Snapshot
|
||||||
replication
|
replication
|
||||||
interval in
|
interval in
|
||||||
@ -267,8 +267,25 @@ Option Description Default
|
|||||||
on target
|
on target
|
||||||
for this
|
for this
|
||||||
time (in
|
time (in
|
||||||
days). ``7``
|
days). ``7``
|
||||||
==================================================== ============= ======
|
``pure_replication_pg_name`` Pure
|
||||||
|
Protection
|
||||||
|
Group name to
|
||||||
|
use for async
|
||||||
|
replication
|
||||||
|
(will be
|
||||||
|
created if
|
||||||
|
it does not
|
||||||
|
exist). ``cinder-group``
|
||||||
|
``pure_replication_pod_name`` Pure Pod name
|
||||||
|
to use for
|
||||||
|
sync
|
||||||
|
replication
|
||||||
|
(will be
|
||||||
|
created if
|
||||||
|
it does not
|
||||||
|
exist). ``cinder-pod``
|
||||||
|
==================================================== ============= ================
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
@ -277,6 +294,12 @@ Option Description Default
|
|||||||
multiple secondary arrays, but subsequent ``failover-host`` is only
|
multiple secondary arrays, but subsequent ``failover-host`` is only
|
||||||
supported back to the original primary array.
|
supported back to the original primary array.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
``pure_replication_pg_name`` and ``pure_replication_pod_name`` should not
|
||||||
|
be changed after volumes have been created in the Cinder backend, as this
|
||||||
|
could have unexpected results in both replication and failover.
|
||||||
|
|
||||||
Automatic thin-provisioning/oversubscription ratio
|
Automatic thin-provisioning/oversubscription ratio
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Pure Storage FlashArray driver has added configuration options
|
||||||
|
``pure_replication_pg_name`` and ``pure_replication_pod_name`` for setting
|
||||||
|
the names for replication PGs and Pods.
|
Loading…
Reference in New Issue
Block a user