Merge "Unmount NetApp active share after replica promote"
This commit is contained in:
commit
da4b33344c
@ -1658,6 +1658,12 @@ class NetAppCmodeFileStorageLibrary(object):
|
|||||||
replica_list)
|
replica_list)
|
||||||
new_replica_list.append(r)
|
new_replica_list.append(r)
|
||||||
|
|
||||||
|
# Unmount the original active replica.
|
||||||
|
orig_active_vserver = dm_session.get_vserver_from_share(
|
||||||
|
orig_active_replica)
|
||||||
|
self._unmount_orig_active_replica(orig_active_replica,
|
||||||
|
orig_active_vserver)
|
||||||
|
|
||||||
self._handle_qos_on_replication_change(dm_session,
|
self._handle_qos_on_replication_change(dm_session,
|
||||||
new_active_replica,
|
new_active_replica,
|
||||||
orig_active_replica,
|
orig_active_replica,
|
||||||
@ -1665,6 +1671,25 @@ class NetAppCmodeFileStorageLibrary(object):
|
|||||||
|
|
||||||
return new_replica_list
|
return new_replica_list
|
||||||
|
|
||||||
|
def _unmount_orig_active_replica(self, orig_active_replica,
|
||||||
|
orig_active_vserver=None):
|
||||||
|
orig_active_replica_backend = (
|
||||||
|
share_utils.extract_host(orig_active_replica['host'],
|
||||||
|
level='backend_name'))
|
||||||
|
orig_active_vserver_client = data_motion.get_client_for_backend(
|
||||||
|
orig_active_replica_backend,
|
||||||
|
vserver_name=orig_active_vserver)
|
||||||
|
share_name = self._get_backend_share_name(
|
||||||
|
orig_active_replica['id'])
|
||||||
|
try:
|
||||||
|
orig_active_vserver_client.unmount_volume(share_name,
|
||||||
|
force=True)
|
||||||
|
LOG.info("Unmount of the original active replica %s successful.",
|
||||||
|
orig_active_replica['id'])
|
||||||
|
except exception.StorageCommunicationException:
|
||||||
|
LOG.exception("Could not unmount the original active replica %s.",
|
||||||
|
orig_active_replica['id'])
|
||||||
|
|
||||||
def _handle_qos_on_replication_change(self, dm_session, new_active_replica,
|
def _handle_qos_on_replication_change(self, dm_session, new_active_replica,
|
||||||
orig_active_replica,
|
orig_active_replica,
|
||||||
share_server=None):
|
share_server=None):
|
||||||
|
@ -2974,13 +2974,20 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
mock.Mock(return_value=mock.Mock()))
|
mock.Mock(return_value=mock.Mock()))
|
||||||
self.mock_object(self.library, '_create_export',
|
self.mock_object(self.library, '_create_export',
|
||||||
mock.Mock(return_value='fake_export_location'))
|
mock.Mock(return_value='fake_export_location'))
|
||||||
|
self.mock_object(self.library, '_unmount_orig_active_replica')
|
||||||
self.mock_object(self.library, '_handle_qos_on_replication_change')
|
self.mock_object(self.library, '_handle_qos_on_replication_change')
|
||||||
|
|
||||||
|
mock_dm_session = mock.Mock()
|
||||||
|
self.mock_object(data_motion, "DataMotionSession",
|
||||||
|
mock.Mock(return_value=mock_dm_session))
|
||||||
|
self.mock_object(mock_dm_session, 'get_vserver_from_share',
|
||||||
|
mock.Mock(return_value=fake.VSERVER1))
|
||||||
|
|
||||||
replicas = self.library.promote_replica(
|
replicas = self.library.promote_replica(
|
||||||
None, [self.fake_replica, self.fake_replica_2],
|
None, [self.fake_replica, self.fake_replica_2],
|
||||||
self.fake_replica_2, [], share_server=None)
|
self.fake_replica_2, [], share_server=None)
|
||||||
|
|
||||||
self.mock_dm_session.change_snapmirror_source.assert_called_once_with(
|
mock_dm_session.change_snapmirror_source.assert_called_once_with(
|
||||||
self.fake_replica, self.fake_replica, self.fake_replica_2,
|
self.fake_replica, self.fake_replica, self.fake_replica_2,
|
||||||
mock.ANY
|
mock.ANY
|
||||||
)
|
)
|
||||||
@ -2997,6 +3004,8 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
actual_replica_2['export_locations'])
|
actual_replica_2['export_locations'])
|
||||||
self.assertEqual(constants.STATUS_ACTIVE,
|
self.assertEqual(constants.STATUS_ACTIVE,
|
||||||
actual_replica_2['access_rules_status'])
|
actual_replica_2['access_rules_status'])
|
||||||
|
self.library._unmount_orig_active_replica.assert_called_once_with(
|
||||||
|
self.fake_replica, fake.VSERVER1)
|
||||||
self.library._handle_qos_on_replication_change.assert_called_once()
|
self.library._handle_qos_on_replication_change.assert_called_once()
|
||||||
|
|
||||||
def test_promote_replica_destination_unreachable(self):
|
def test_promote_replica_destination_unreachable(self):
|
||||||
@ -3007,6 +3016,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
self.mock_object(self.library,
|
self.mock_object(self.library,
|
||||||
'_get_helper',
|
'_get_helper',
|
||||||
mock.Mock(return_value=mock.Mock()))
|
mock.Mock(return_value=mock.Mock()))
|
||||||
|
self.mock_object(self.library, '_unmount_orig_active_replica')
|
||||||
self.mock_object(self.library, '_handle_qos_on_replication_change')
|
self.mock_object(self.library, '_handle_qos_on_replication_change')
|
||||||
|
|
||||||
self.mock_object(self.library, '_create_export',
|
self.mock_object(self.library, '_create_export',
|
||||||
@ -3025,6 +3035,8 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
actual_replica['replica_state'])
|
actual_replica['replica_state'])
|
||||||
self.assertEqual(constants.STATUS_ERROR,
|
self.assertEqual(constants.STATUS_ERROR,
|
||||||
actual_replica['status'])
|
actual_replica['status'])
|
||||||
|
self.assertFalse(
|
||||||
|
self.library._unmount_orig_active_replica.called)
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
self.library._handle_qos_on_replication_change.called)
|
self.library._handle_qos_on_replication_change.called)
|
||||||
|
|
||||||
@ -3036,6 +3048,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
'_get_vserver',
|
'_get_vserver',
|
||||||
mock.Mock(return_value=(fake.VSERVER1,
|
mock.Mock(return_value=(fake.VSERVER1,
|
||||||
mock.Mock())))
|
mock.Mock())))
|
||||||
|
self.mock_object(self.library, '_unmount_orig_active_replica')
|
||||||
self.mock_object(self.library, '_handle_qos_on_replication_change')
|
self.mock_object(self.library, '_handle_qos_on_replication_change')
|
||||||
self.mock_object(self.library,
|
self.mock_object(self.library,
|
||||||
'_get_helper',
|
'_get_helper',
|
||||||
@ -3043,12 +3056,17 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
|
|
||||||
self.mock_object(self.library, '_create_export',
|
self.mock_object(self.library, '_create_export',
|
||||||
mock.Mock(return_value='fake_export_location'))
|
mock.Mock(return_value='fake_export_location'))
|
||||||
|
mock_dm_session = mock.Mock()
|
||||||
|
self.mock_object(data_motion, "DataMotionSession",
|
||||||
|
mock.Mock(return_value=mock_dm_session))
|
||||||
|
self.mock_object(mock_dm_session, 'get_vserver_from_share',
|
||||||
|
mock.Mock(return_value=fake.VSERVER1))
|
||||||
|
|
||||||
replicas = self.library.promote_replica(
|
replicas = self.library.promote_replica(
|
||||||
None, [self.fake_replica, self.fake_replica_2, fake_replica_3],
|
None, [self.fake_replica, self.fake_replica_2, fake_replica_3],
|
||||||
self.fake_replica_2, [], share_server=None)
|
self.fake_replica_2, [], share_server=None)
|
||||||
|
|
||||||
self.mock_dm_session.change_snapmirror_source.assert_has_calls([
|
mock_dm_session.change_snapmirror_source.assert_has_calls([
|
||||||
mock.call(fake_replica_3, self.fake_replica, self.fake_replica_2,
|
mock.call(fake_replica_3, self.fake_replica, self.fake_replica_2,
|
||||||
mock.ANY),
|
mock.ANY),
|
||||||
mock.call(self.fake_replica, self.fake_replica,
|
mock.call(self.fake_replica, self.fake_replica,
|
||||||
@ -3070,6 +3088,8 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
lambda x: x['id'] == fake_replica_3['id'], replicas))[0]
|
lambda x: x['id'] == fake_replica_3['id'], replicas))[0]
|
||||||
self.assertEqual(constants.REPLICA_STATE_OUT_OF_SYNC,
|
self.assertEqual(constants.REPLICA_STATE_OUT_OF_SYNC,
|
||||||
actual_replica_3['replica_state'])
|
actual_replica_3['replica_state'])
|
||||||
|
self.library._unmount_orig_active_replica.assert_called_once_with(
|
||||||
|
self.fake_replica, fake.VSERVER1)
|
||||||
self.library._handle_qos_on_replication_change.assert_called_once()
|
self.library._handle_qos_on_replication_change.assert_called_once()
|
||||||
|
|
||||||
def test_promote_replica_with_access_rules(self):
|
def test_promote_replica_with_access_rules(self):
|
||||||
@ -3077,6 +3097,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
'_get_vserver',
|
'_get_vserver',
|
||||||
mock.Mock(return_value=(fake.VSERVER1,
|
mock.Mock(return_value=(fake.VSERVER1,
|
||||||
mock.Mock())))
|
mock.Mock())))
|
||||||
|
self.mock_object(self.library, '_unmount_orig_active_replica')
|
||||||
self.mock_object(self.library, '_handle_qos_on_replication_change')
|
self.mock_object(self.library, '_handle_qos_on_replication_change')
|
||||||
mock_helper = mock.Mock()
|
mock_helper = mock.Mock()
|
||||||
self.mock_object(self.library,
|
self.mock_object(self.library,
|
||||||
@ -3085,11 +3106,17 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
self.mock_object(self.library, '_create_export',
|
self.mock_object(self.library, '_create_export',
|
||||||
mock.Mock(return_value='fake_export_location'))
|
mock.Mock(return_value='fake_export_location'))
|
||||||
|
|
||||||
|
mock_dm_session = mock.Mock()
|
||||||
|
self.mock_object(data_motion, "DataMotionSession",
|
||||||
|
mock.Mock(return_value=mock_dm_session))
|
||||||
|
self.mock_object(mock_dm_session, 'get_vserver_from_share',
|
||||||
|
mock.Mock(return_value=fake.VSERVER1))
|
||||||
|
|
||||||
replicas = self.library.promote_replica(
|
replicas = self.library.promote_replica(
|
||||||
None, [self.fake_replica, self.fake_replica_2],
|
None, [self.fake_replica, self.fake_replica_2],
|
||||||
self.fake_replica_2, [fake.SHARE_ACCESS], share_server=None)
|
self.fake_replica_2, [fake.SHARE_ACCESS], share_server=None)
|
||||||
|
|
||||||
self.mock_dm_session.change_snapmirror_source.assert_has_calls([
|
mock_dm_session.change_snapmirror_source.assert_has_calls([
|
||||||
mock.call(self.fake_replica, self.fake_replica,
|
mock.call(self.fake_replica, self.fake_replica,
|
||||||
self.fake_replica_2, mock.ANY)
|
self.fake_replica_2, mock.ANY)
|
||||||
], any_order=True)
|
], any_order=True)
|
||||||
@ -3099,8 +3126,20 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
mock_helper.update_access.assert_called_once_with(self.fake_replica_2,
|
mock_helper.update_access.assert_called_once_with(self.fake_replica_2,
|
||||||
share_name,
|
share_name,
|
||||||
[fake.SHARE_ACCESS])
|
[fake.SHARE_ACCESS])
|
||||||
|
self.library._unmount_orig_active_replica.assert_called_once_with(
|
||||||
|
self.fake_replica, fake.VSERVER1)
|
||||||
self.library._handle_qos_on_replication_change.assert_called_once()
|
self.library._handle_qos_on_replication_change.assert_called_once()
|
||||||
|
|
||||||
|
def test_unmount_orig_active_replica(self):
|
||||||
|
self.mock_object(share_utils, 'extract_host', mock.Mock(
|
||||||
|
return_value=fake.MANILA_HOST_NAME))
|
||||||
|
self.mock_object(data_motion, 'get_client_for_backend')
|
||||||
|
self.mock_object(self.library, '_get_backend_share_name', mock.Mock(
|
||||||
|
return_value=fake.SHARE_NAME))
|
||||||
|
|
||||||
|
result = self.library._unmount_orig_active_replica(fake.SHARE)
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
@ddt.data({'extra_specs': {'netapp:snapshot_policy': 'none'},
|
@ddt.data({'extra_specs': {'netapp:snapshot_policy': 'none'},
|
||||||
'have_cluster_creds': True},
|
'have_cluster_creds': True},
|
||||||
# Test Case 2 isn't possible input
|
# Test Case 2 isn't possible input
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- The NetApp ONTAP driver is now fixed to unmount
|
||||||
|
the original active share volume after one of its
|
||||||
|
replica gets promoted.
|
Loading…
Reference in New Issue
Block a user