1054 lines
48 KiB
Python
1054 lines
48 KiB
Python
# Copyright (c) 2015 Alex Meade. All rights reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import copy
|
|
import time
|
|
from unittest import mock
|
|
|
|
import ddt
|
|
from oslo_config import cfg
|
|
|
|
from manila import exception
|
|
from manila.share import configuration
|
|
from manila.share import driver
|
|
from manila.share.drivers.netapp.dataontap.client import api as netapp_api
|
|
from manila.share.drivers.netapp.dataontap.client import client_cmode
|
|
from manila.share.drivers.netapp.dataontap.cluster_mode import data_motion
|
|
from manila.share.drivers.netapp import options as na_opts
|
|
from manila import test
|
|
from manila.tests.share.drivers.netapp.dataontap import fakes as fake
|
|
from manila.tests.share.drivers.netapp import fakes as na_fakes
|
|
|
|
|
|
CONF = cfg.CONF
|
|
|
|
|
|
@ddt.ddt
|
|
class NetAppCDOTDataMotionTestCase(test.TestCase):
|
|
|
|
def setUp(self):
|
|
super(NetAppCDOTDataMotionTestCase, self).setUp()
|
|
self.backend = 'backend1'
|
|
self.mock_cmode_client = self.mock_object(client_cmode,
|
|
"NetAppCmodeClient",
|
|
mock.Mock())
|
|
self.config = configuration.Configuration(driver.share_opts,
|
|
config_group=self.backend)
|
|
self.config.append_config_values(na_opts.netapp_cluster_opts)
|
|
self.config.append_config_values(na_opts.netapp_connection_opts)
|
|
self.config.append_config_values(na_opts.netapp_basicauth_opts)
|
|
self.config.append_config_values(na_opts.netapp_transport_opts)
|
|
self.config.append_config_values(na_opts.netapp_support_opts)
|
|
self.config.append_config_values(na_opts.netapp_provisioning_opts)
|
|
self.config.append_config_values(na_opts.netapp_data_motion_opts)
|
|
CONF.set_override("share_backend_name", self.backend,
|
|
group=self.backend)
|
|
CONF.set_override("netapp_transport_type", "https",
|
|
group=self.backend)
|
|
CONF.set_override("netapp_login", "fake_user",
|
|
group=self.backend)
|
|
CONF.set_override("netapp_password", "fake_password",
|
|
group=self.backend)
|
|
CONF.set_override("netapp_server_hostname", "fake.hostname",
|
|
group=self.backend)
|
|
CONF.set_override("netapp_server_port", 8866,
|
|
group=self.backend)
|
|
CONF.set_override("netapp_ssl_cert_path", "/etc/ssl/certs",
|
|
group=self.backend)
|
|
|
|
def test_get_client_for_backend(self):
|
|
self.mock_object(data_motion, "get_backend_configuration",
|
|
mock.Mock(return_value=self.config))
|
|
|
|
data_motion.get_client_for_backend(self.backend)
|
|
|
|
self.mock_cmode_client.assert_called_once_with(
|
|
hostname='fake.hostname', password='fake_password',
|
|
username='fake_user', transport_type='https', port=8866,
|
|
ssl_cert_path='/etc/ssl/certs', trace=mock.ANY, vserver=None)
|
|
|
|
def test_get_client_for_backend_with_vserver(self):
|
|
self.mock_object(data_motion, "get_backend_configuration",
|
|
mock.Mock(return_value=self.config))
|
|
|
|
CONF.set_override("netapp_vserver", 'fake_vserver',
|
|
group=self.backend)
|
|
|
|
data_motion.get_client_for_backend(self.backend)
|
|
|
|
self.mock_cmode_client.assert_called_once_with(
|
|
hostname='fake.hostname', password='fake_password',
|
|
username='fake_user', transport_type='https', port=8866,
|
|
ssl_cert_path='/etc/ssl/certs', trace=mock.ANY,
|
|
vserver='fake_vserver')
|
|
|
|
def test_get_config_for_backend(self):
|
|
self.mock_object(data_motion, "CONF")
|
|
CONF.set_override("netapp_vserver", 'fake_vserver',
|
|
group=self.backend)
|
|
data_motion.CONF.list_all_sections.return_value = [self.backend]
|
|
|
|
config = data_motion.get_backend_configuration(self.backend)
|
|
|
|
self.assertEqual('fake_vserver', config.netapp_vserver)
|
|
|
|
def test_get_config_for_backend_different_backend_name(self):
|
|
self.mock_object(data_motion, "CONF")
|
|
CONF.set_override("netapp_vserver", 'fake_vserver',
|
|
group=self.backend)
|
|
CONF.set_override("share_backend_name", "fake_backend_name",
|
|
group=self.backend)
|
|
data_motion.CONF.list_all_sections.return_value = [self.backend]
|
|
|
|
config = data_motion.get_backend_configuration(self.backend)
|
|
|
|
self.assertEqual('fake_vserver', config.netapp_vserver)
|
|
self.assertEqual('fake_backend_name', config.share_backend_name)
|
|
|
|
@ddt.data([], ['fake_backend1', 'fake_backend2'])
|
|
def test_get_config_for_backend_not_configured(self, conf_sections):
|
|
self.mock_object(data_motion, "CONF")
|
|
data_motion.CONF.list_all_sections.return_value = conf_sections
|
|
|
|
self.assertRaises(exception.BadConfigurationException,
|
|
data_motion.get_backend_configuration,
|
|
self.backend)
|
|
|
|
|
|
@ddt.ddt
|
|
class NetAppCDOTDataMotionSessionTestCase(test.TestCase):
|
|
|
|
def setUp(self):
|
|
super(NetAppCDOTDataMotionSessionTestCase, self).setUp()
|
|
self.source_backend = 'backend1'
|
|
self.dest_backend = 'backend2'
|
|
|
|
config = configuration.Configuration(driver.share_opts,
|
|
config_group=self.source_backend)
|
|
config.append_config_values(na_opts.netapp_cluster_opts)
|
|
config.append_config_values(na_opts.netapp_connection_opts)
|
|
config.append_config_values(na_opts.netapp_basicauth_opts)
|
|
config.append_config_values(na_opts.netapp_transport_opts)
|
|
config.append_config_values(na_opts.netapp_support_opts)
|
|
config.append_config_values(na_opts.netapp_provisioning_opts)
|
|
config.append_config_values(na_opts.netapp_data_motion_opts)
|
|
|
|
self.mock_object(data_motion, "get_backend_configuration",
|
|
mock.Mock(return_value=config))
|
|
|
|
self.mock_cmode_client = self.mock_object(client_cmode,
|
|
"NetAppCmodeClient",
|
|
mock.Mock())
|
|
self.dm_session = data_motion.DataMotionSession()
|
|
self.fake_src_share = copy.deepcopy(fake.SHARE)
|
|
self.fake_src_share_server = copy.deepcopy(fake.SHARE_SERVER)
|
|
self.source_vserver = 'source_vserver'
|
|
self.source_backend_name = (
|
|
self.fake_src_share_server['host'].split('@')[1])
|
|
self.fake_src_share_server['backend_details']['vserver_name'] = (
|
|
self.source_vserver
|
|
)
|
|
self.fake_src_share['share_server'] = self.fake_src_share_server
|
|
self.fake_src_share['id'] = 'c02d497a-236c-4852-812a-0d39373e312a'
|
|
self.fake_src_vol_name = 'share_c02d497a_236c_4852_812a_0d39373e312a'
|
|
self.fake_dest_share = copy.deepcopy(fake.SHARE)
|
|
self.fake_dest_share_server = copy.deepcopy(fake.SHARE_SERVER_2)
|
|
self.dest_vserver = 'dest_vserver'
|
|
self.dest_backend_name = (
|
|
self.fake_dest_share_server['host'].split('@')[1])
|
|
self.fake_dest_share_server['backend_details']['vserver_name'] = (
|
|
self.dest_vserver
|
|
)
|
|
self.fake_dest_share['share_server'] = self.fake_dest_share_server
|
|
self.fake_dest_share['id'] = '34fbaf57-745d-460f-8270-3378c2945e30'
|
|
self.fake_dest_vol_name = 'share_34fbaf57_745d_460f_8270_3378c2945e30'
|
|
|
|
self.mock_src_client = mock.Mock()
|
|
self.mock_dest_client = mock.Mock()
|
|
self.mock_object(data_motion, 'get_client_for_backend',
|
|
mock.Mock(side_effect=[self.mock_dest_client,
|
|
self.mock_src_client]))
|
|
self.mock_object(self.dm_session, 'get_client_and_vserver_name',
|
|
mock.Mock(side_effect=[
|
|
(self.mock_src_client, self.source_vserver),
|
|
(self.mock_dest_client, self.dest_vserver)]))
|
|
|
|
def test_get_client_and_vserver_name(self):
|
|
dm_session = data_motion.DataMotionSession()
|
|
client = mock.Mock()
|
|
self.mock_object(data_motion, 'get_client_for_backend',
|
|
mock.Mock(return_value=client))
|
|
|
|
result = dm_session.get_client_and_vserver_name(fake.SHARE_SERVER)
|
|
expected = (client,
|
|
fake.SHARE_SERVER['backend_details']['vserver_name'])
|
|
|
|
self.assertEqual(expected, result)
|
|
data_motion.get_client_for_backend.assert_called_once_with(
|
|
fake.BACKEND_NAME, vserver_name=fake.VSERVER1
|
|
)
|
|
|
|
def test_create_snapmirror(self):
|
|
mock_dest_client = mock.Mock()
|
|
self.mock_object(data_motion, 'get_client_for_backend',
|
|
mock.Mock(return_value=mock_dest_client))
|
|
|
|
self.dm_session.create_snapmirror(self.fake_src_share,
|
|
self.fake_dest_share)
|
|
|
|
mock_dest_client.create_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name, schedule='hourly'
|
|
)
|
|
mock_dest_client.initialize_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name
|
|
)
|
|
|
|
def test_create_snapmirror_svm(self):
|
|
mock_dest_client = mock.Mock()
|
|
self.mock_object(self.dm_session, 'get_client_and_vserver_name',
|
|
mock.Mock(return_value=(mock_dest_client,
|
|
self.dest_vserver)))
|
|
self.mock_object(self.dm_session, 'get_vserver_from_share_server',
|
|
mock.Mock(return_value=self.source_vserver))
|
|
policy_name = 'policy_' + self.dest_vserver
|
|
get_snapmirro_policy_name = self.mock_object(
|
|
self.dm_session, '_get_backend_snapmirror_policy_name_svm',
|
|
mock.Mock(return_value=policy_name))
|
|
|
|
self.dm_session.create_snapmirror_svm(self.fake_src_share_server,
|
|
self.fake_dest_share_server)
|
|
|
|
self.dm_session.get_client_and_vserver_name.assert_called_once_with(
|
|
self.fake_dest_share_server
|
|
)
|
|
self.dm_session.get_vserver_from_share_server.assert_called_once_with(
|
|
self.fake_src_share_server
|
|
)
|
|
get_snapmirro_policy_name.assert_called_once_with(
|
|
self.fake_dest_share_server['id'], self.dest_backend_name
|
|
)
|
|
mock_dest_client.create_snapmirror_policy.assert_called_once_with(
|
|
policy_name
|
|
)
|
|
mock_dest_client.create_snapmirror_svm.assert_called_once_with(
|
|
self.source_vserver, self.dest_vserver,
|
|
policy=policy_name, schedule='hourly'
|
|
)
|
|
mock_dest_client.initialize_snapmirror_svm.assert_called_once_with(
|
|
self.source_vserver, self.dest_vserver
|
|
)
|
|
|
|
def test_delete_snapmirror(self):
|
|
mock_src_client = mock.Mock()
|
|
mock_dest_client = mock.Mock()
|
|
self.mock_object(data_motion, 'get_client_for_backend',
|
|
mock.Mock(side_effect=[mock_dest_client,
|
|
mock_src_client]))
|
|
|
|
self.dm_session.delete_snapmirror(self.fake_src_share,
|
|
self.fake_dest_share)
|
|
|
|
mock_dest_client.abort_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name, clear_checkpoint=False
|
|
)
|
|
mock_dest_client.delete_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name
|
|
)
|
|
mock_src_client.release_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name
|
|
)
|
|
|
|
@ddt.data(True, False)
|
|
def test_delete_snapmirror_svm(self, call_release):
|
|
self.mock_object(self.dm_session, 'wait_for_snapmirror_release_svm')
|
|
mock_backend_config = na_fakes.create_configuration()
|
|
mock_backend_config.netapp_snapmirror_release_timeout = 30
|
|
self.mock_object(data_motion, 'get_backend_configuration',
|
|
mock.Mock(return_value=mock_backend_config))
|
|
|
|
self.dm_session.delete_snapmirror_svm(self.fake_src_share_server,
|
|
self.fake_dest_share_server,
|
|
release=call_release)
|
|
|
|
self.mock_dest_client.abort_snapmirror_svm.assert_called_once_with(
|
|
self.source_vserver, self.dest_vserver
|
|
)
|
|
self.mock_dest_client.delete_snapmirror_svm.assert_called_once_with(
|
|
self.source_vserver, self.dest_vserver
|
|
)
|
|
if call_release:
|
|
release_mock = self.dm_session.wait_for_snapmirror_release_svm
|
|
release_mock.assert_called_once_with(
|
|
self.source_vserver, self.dest_vserver, self.mock_src_client,
|
|
timeout=mock_backend_config.netapp_snapmirror_release_timeout
|
|
)
|
|
|
|
def test_delete_snapmirror_does_not_exist(self):
|
|
"""Ensure delete succeeds when the snapmirror does not exist."""
|
|
mock_src_client = mock.Mock()
|
|
mock_dest_client = mock.Mock()
|
|
mock_dest_client.abort_snapmirror_vol.side_effect = (
|
|
netapp_api.NaApiError(code=netapp_api.EAPIERROR))
|
|
self.mock_object(data_motion, 'get_client_for_backend',
|
|
mock.Mock(side_effect=[mock_dest_client,
|
|
mock_src_client]))
|
|
|
|
self.dm_session.delete_snapmirror(self.fake_src_share,
|
|
self.fake_dest_share)
|
|
|
|
mock_dest_client.abort_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name, clear_checkpoint=False
|
|
)
|
|
mock_dest_client.delete_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name
|
|
)
|
|
mock_src_client.release_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name
|
|
)
|
|
|
|
def test_delete_snapmirror_svm_does_not_exist(self):
|
|
"""Ensure delete succeeds when the snapmirror does not exist."""
|
|
self.mock_dest_client.abort_snapmirror_svm.side_effect = (
|
|
netapp_api.NaApiError(code=netapp_api.EAPIERROR))
|
|
self.mock_object(self.dm_session, 'wait_for_snapmirror_release_svm')
|
|
mock_backend_config = na_fakes.create_configuration()
|
|
mock_backend_config.netapp_snapmirror_release_timeout = 30
|
|
self.mock_object(data_motion, 'get_backend_configuration',
|
|
mock.Mock(return_value=mock_backend_config))
|
|
|
|
self.dm_session.delete_snapmirror_svm(self.fake_src_share_server,
|
|
self.fake_dest_share_server)
|
|
|
|
self.mock_dest_client.abort_snapmirror_svm.assert_called_once_with(
|
|
self.source_vserver, self.dest_vserver
|
|
)
|
|
self.mock_dest_client.delete_snapmirror_svm.assert_called_once_with(
|
|
self.source_vserver, self.dest_vserver
|
|
)
|
|
release_mock = self.dm_session.wait_for_snapmirror_release_svm
|
|
release_mock.assert_called_once_with(
|
|
self.source_vserver, self.dest_vserver, self.mock_src_client,
|
|
timeout=mock_backend_config.netapp_snapmirror_release_timeout
|
|
)
|
|
|
|
def test_delete_snapmirror_error_deleting(self):
|
|
"""Ensure delete succeeds when the snapmirror does not exist."""
|
|
mock_src_client = mock.Mock()
|
|
mock_dest_client = mock.Mock()
|
|
mock_dest_client.delete_snapmirror_vol.side_effect = (
|
|
netapp_api.NaApiError(code=netapp_api.ESOURCE_IS_DIFFERENT))
|
|
self.mock_object(data_motion, 'get_client_for_backend',
|
|
mock.Mock(side_effect=[mock_dest_client,
|
|
mock_src_client]))
|
|
|
|
self.dm_session.delete_snapmirror(self.fake_src_share,
|
|
self.fake_dest_share)
|
|
|
|
mock_dest_client.abort_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name, clear_checkpoint=False
|
|
)
|
|
mock_dest_client.delete_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name
|
|
)
|
|
mock_src_client.release_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name
|
|
)
|
|
|
|
def test_delete_snapmirror_svm_error_deleting(self):
|
|
"""Ensure delete succeeds when the snapmirror does not exist."""
|
|
self.mock_dest_client.delete_snapmirror_svm.side_effect = (
|
|
netapp_api.NaApiError(code=netapp_api.ESOURCE_IS_DIFFERENT))
|
|
self.mock_object(self.dm_session, 'wait_for_snapmirror_release_svm')
|
|
mock_backend_config = na_fakes.create_configuration()
|
|
mock_backend_config.netapp_snapmirror_release_timeout = 30
|
|
self.mock_object(data_motion, 'get_backend_configuration',
|
|
mock.Mock(return_value=mock_backend_config))
|
|
|
|
self.dm_session.delete_snapmirror_svm(self.fake_src_share_server,
|
|
self.fake_dest_share_server)
|
|
|
|
self.mock_dest_client.abort_snapmirror_svm.assert_called_once_with(
|
|
self.source_vserver, self.dest_vserver
|
|
)
|
|
self.mock_dest_client.delete_snapmirror_svm.assert_called_once_with(
|
|
self.source_vserver, self.dest_vserver
|
|
)
|
|
release_mock = self.dm_session.wait_for_snapmirror_release_svm
|
|
release_mock.assert_called_once_with(
|
|
self.source_vserver, self.dest_vserver, self.mock_src_client,
|
|
timeout=mock_backend_config.netapp_snapmirror_release_timeout
|
|
)
|
|
|
|
def test_delete_snapmirror_error_releasing(self):
|
|
"""Ensure delete succeeds when the snapmirror does not exist."""
|
|
mock_src_client = mock.Mock()
|
|
mock_dest_client = mock.Mock()
|
|
mock_src_client.release_snapmirror_vol.side_effect = (
|
|
netapp_api.NaApiError(code=netapp_api.EOBJECTNOTFOUND))
|
|
self.mock_object(data_motion, 'get_client_for_backend',
|
|
mock.Mock(side_effect=[mock_dest_client,
|
|
mock_src_client]))
|
|
|
|
self.dm_session.delete_snapmirror(self.fake_src_share,
|
|
self.fake_dest_share)
|
|
|
|
mock_dest_client.abort_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name, clear_checkpoint=False
|
|
)
|
|
mock_dest_client.delete_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name
|
|
)
|
|
mock_src_client.release_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name
|
|
)
|
|
|
|
def test_delete_snapmirror_without_release(self):
|
|
mock_src_client = mock.Mock()
|
|
mock_dest_client = mock.Mock()
|
|
self.mock_object(data_motion, 'get_client_for_backend',
|
|
mock.Mock(side_effect=[mock_dest_client,
|
|
mock_src_client]))
|
|
|
|
self.dm_session.delete_snapmirror(self.fake_src_share,
|
|
self.fake_dest_share,
|
|
release=False)
|
|
|
|
mock_dest_client.abort_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name, clear_checkpoint=False
|
|
)
|
|
mock_dest_client.delete_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name
|
|
)
|
|
self.assertFalse(mock_src_client.release_snapmirror_vol.called)
|
|
|
|
def test_delete_snapmirror_source_unreachable(self):
|
|
mock_src_client = mock.Mock()
|
|
mock_dest_client = mock.Mock()
|
|
self.mock_object(data_motion, 'get_client_for_backend',
|
|
mock.Mock(side_effect=[mock_dest_client,
|
|
Exception]))
|
|
|
|
self.dm_session.delete_snapmirror(self.fake_src_share,
|
|
self.fake_dest_share)
|
|
|
|
mock_dest_client.abort_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name, clear_checkpoint=False
|
|
)
|
|
mock_dest_client.delete_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, self.fake_src_vol_name, mock.ANY,
|
|
self.fake_dest_vol_name
|
|
)
|
|
|
|
self.assertFalse(mock_src_client.release_snapmirror_vol.called)
|
|
|
|
def test_break_snapmirror(self):
|
|
self.mock_object(self.dm_session, 'quiesce_then_abort')
|
|
|
|
self.dm_session.break_snapmirror(self.fake_src_share,
|
|
self.fake_dest_share)
|
|
|
|
self.mock_dest_client.break_snapmirror_vol.assert_called_once_with(
|
|
self.source_vserver, self.fake_src_vol_name,
|
|
self.dest_vserver, self.fake_dest_vol_name)
|
|
|
|
self.dm_session.quiesce_then_abort.assert_called_once_with(
|
|
self.fake_src_share, self.fake_dest_share)
|
|
|
|
self.mock_dest_client.mount_volume.assert_called_once_with(
|
|
self.fake_dest_vol_name)
|
|
|
|
def test_break_snapmirror_no_mount(self):
|
|
self.mock_object(self.dm_session, 'quiesce_then_abort')
|
|
|
|
self.dm_session.break_snapmirror(self.fake_src_share,
|
|
self.fake_dest_share,
|
|
mount=False)
|
|
|
|
self.mock_dest_client.break_snapmirror_vol.assert_called_once_with(
|
|
self.source_vserver, self.fake_src_vol_name,
|
|
self.dest_vserver, self.fake_dest_vol_name)
|
|
|
|
self.dm_session.quiesce_then_abort.assert_called_once_with(
|
|
self.fake_src_share, self.fake_dest_share)
|
|
|
|
self.assertFalse(self.mock_dest_client.mount_volume.called)
|
|
|
|
def test_break_snapmirror_wait_for_quiesced(self):
|
|
self.mock_object(self.dm_session, 'quiesce_then_abort')
|
|
|
|
self.dm_session.break_snapmirror(self.fake_src_share,
|
|
self.fake_dest_share)
|
|
|
|
self.dm_session.quiesce_then_abort.assert_called_once_with(
|
|
self.fake_src_share, self.fake_dest_share)
|
|
|
|
self.mock_dest_client.break_snapmirror_vol.assert_called_once_with(
|
|
self.source_vserver, self.fake_src_vol_name,
|
|
self.dest_vserver, self.fake_dest_vol_name)
|
|
|
|
self.mock_dest_client.mount_volume.assert_called_once_with(
|
|
self.fake_dest_vol_name)
|
|
|
|
def test_quiesce_then_abort_timeout(self):
|
|
self.mock_object(time, 'sleep')
|
|
mock_get_snapmirrors = mock.Mock(
|
|
return_value=[{'relationship-status': "transferring"}])
|
|
self.mock_object(self.mock_dest_client, 'get_snapmirrors',
|
|
mock_get_snapmirrors)
|
|
mock_backend_config = na_fakes.create_configuration()
|
|
mock_backend_config.netapp_snapmirror_quiesce_timeout = 10
|
|
self.mock_object(data_motion, 'get_backend_configuration',
|
|
mock.Mock(return_value=mock_backend_config))
|
|
|
|
self.dm_session.quiesce_then_abort(self.fake_src_share,
|
|
self.fake_dest_share)
|
|
|
|
self.mock_dest_client.get_snapmirrors.assert_called_with(
|
|
source_vserver=self.source_vserver,
|
|
dest_vserver=self.dest_vserver,
|
|
source_volume=self.fake_src_vol_name,
|
|
dest_volume=self.fake_dest_vol_name,
|
|
desired_attributes=['relationship-status', 'mirror-state']
|
|
)
|
|
self.assertEqual(2, self.mock_dest_client.get_snapmirrors.call_count)
|
|
|
|
self.mock_dest_client.quiesce_snapmirror_vol.assert_called_with(
|
|
self.source_vserver, self.fake_src_vol_name,
|
|
self.dest_vserver, self.fake_dest_vol_name)
|
|
|
|
self.mock_dest_client.abort_snapmirror_vol.assert_called_once_with(
|
|
self.source_vserver, self.fake_src_vol_name,
|
|
self.dest_vserver, self.fake_dest_vol_name,
|
|
clear_checkpoint=False
|
|
)
|
|
|
|
def test_quiesce_then_abort_svm_timeout(self):
|
|
self.mock_object(time, 'sleep')
|
|
mock_get_snapmirrors = mock.Mock(
|
|
return_value=[{'relationship-status': "transferring"}])
|
|
self.mock_object(self.mock_dest_client, 'get_snapmirrors_svm',
|
|
mock_get_snapmirrors)
|
|
mock_backend_config = na_fakes.create_configuration()
|
|
mock_backend_config.netapp_snapmirror_quiesce_timeout = 10
|
|
self.mock_object(data_motion, 'get_backend_configuration',
|
|
mock.Mock(return_value=mock_backend_config))
|
|
|
|
self.dm_session.quiesce_then_abort_svm(self.fake_src_share_server,
|
|
self.fake_dest_share_server)
|
|
|
|
self.mock_dest_client.get_snapmirrors_svm.assert_called_with(
|
|
source_vserver=self.source_vserver,
|
|
dest_vserver=self.dest_vserver,
|
|
desired_attributes=['relationship-status', 'mirror-state']
|
|
)
|
|
self.assertEqual(2,
|
|
self.mock_dest_client.get_snapmirrors_svm.call_count)
|
|
|
|
self.mock_dest_client.quiesce_snapmirror_svm.assert_called_with(
|
|
self.source_vserver, self.dest_vserver)
|
|
|
|
self.mock_dest_client.abort_snapmirror_svm.assert_called_once_with(
|
|
self.source_vserver, self.dest_vserver,
|
|
clear_checkpoint=False
|
|
)
|
|
|
|
def test_quiesce_then_abort_wait_for_quiesced(self):
|
|
self.mock_object(time, 'sleep')
|
|
self.mock_object(self.mock_dest_client, 'get_snapmirrors',
|
|
mock.Mock(side_effect=[
|
|
[{'relationship-status': "transferring"}],
|
|
[{'relationship-status': "quiesced"}]]))
|
|
|
|
self.dm_session.quiesce_then_abort(self.fake_src_share,
|
|
self.fake_dest_share)
|
|
|
|
self.mock_dest_client.get_snapmirrors.assert_called_with(
|
|
source_vserver=self.source_vserver,
|
|
dest_vserver=self.dest_vserver,
|
|
source_volume=self.fake_src_vol_name,
|
|
dest_volume=self.fake_dest_vol_name,
|
|
desired_attributes=['relationship-status', 'mirror-state']
|
|
)
|
|
self.assertEqual(2, self.mock_dest_client.get_snapmirrors.call_count)
|
|
|
|
self.mock_dest_client.quiesce_snapmirror_vol.assert_called_once_with(
|
|
self.source_vserver, self.fake_src_vol_name,
|
|
self.dest_vserver, self.fake_dest_vol_name)
|
|
|
|
def test_quiesce_then_abort_svm_wait_for_quiesced(self):
|
|
self.mock_object(time, 'sleep')
|
|
self.mock_object(self.mock_dest_client, 'get_snapmirrors_svm',
|
|
mock.Mock(side_effect=[
|
|
[{'relationship-status': "transferring"}],
|
|
[{'relationship-status': "quiesced"}]]))
|
|
|
|
self.dm_session.quiesce_then_abort_svm(self.fake_src_share_server,
|
|
self.fake_dest_share_server)
|
|
|
|
self.mock_dest_client.get_snapmirrors_svm.assert_called_with(
|
|
source_vserver=self.source_vserver,
|
|
dest_vserver=self.dest_vserver,
|
|
desired_attributes=['relationship-status', 'mirror-state']
|
|
)
|
|
self.assertEqual(2,
|
|
self.mock_dest_client.get_snapmirrors_svm.call_count)
|
|
|
|
self.mock_dest_client.quiesce_snapmirror_svm.assert_called_once_with(
|
|
self.source_vserver, self.dest_vserver)
|
|
|
|
def test_resync_snapmirror(self):
|
|
self.dm_session.resync_snapmirror(self.fake_src_share,
|
|
self.fake_dest_share)
|
|
|
|
self.mock_dest_client.resync_snapmirror_vol.assert_called_once_with(
|
|
self.source_vserver, self.fake_src_vol_name,
|
|
self.dest_vserver, self.fake_dest_vol_name)
|
|
|
|
def test_change_snapmirror_source(self):
|
|
fake_new_src_share = copy.deepcopy(fake.SHARE)
|
|
fake_new_src_share['id'] = 'd02d497a-236c-4852-812a-0d39373e312a'
|
|
fake_new_src_share_name = 'share_d02d497a_236c_4852_812a_0d39373e312a'
|
|
mock_new_src_client = mock.Mock()
|
|
self.mock_object(self.dm_session, 'delete_snapmirror')
|
|
self.mock_object(data_motion, 'get_client_for_backend',
|
|
mock.Mock(side_effect=[self.mock_dest_client,
|
|
self.mock_src_client,
|
|
self.mock_dest_client,
|
|
mock_new_src_client]))
|
|
|
|
self.dm_session.change_snapmirror_source(
|
|
self.fake_dest_share, self.fake_src_share, fake_new_src_share,
|
|
[self.fake_dest_share, self.fake_src_share, fake_new_src_share])
|
|
|
|
self.assertFalse(self.mock_src_client.release_snapmirror_vol.called)
|
|
|
|
self.assertEqual(4, self.dm_session.delete_snapmirror.call_count)
|
|
self.dm_session.delete_snapmirror.assert_called_with(
|
|
mock.ANY, mock.ANY, release=False
|
|
)
|
|
|
|
self.mock_dest_client.create_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, fake_new_src_share_name, mock.ANY,
|
|
self.fake_dest_vol_name, schedule='hourly'
|
|
)
|
|
|
|
self.mock_dest_client.resync_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, fake_new_src_share_name, mock.ANY,
|
|
self.fake_dest_vol_name
|
|
)
|
|
|
|
def test_change_snapmirror_source_dhss_true(self):
|
|
fake_new_src_share = copy.deepcopy(self.fake_src_share)
|
|
fake_new_src_share['id'] = 'd02d497a-236c-4852-812a-0d39373e312a'
|
|
fake_new_src_share_name = 'share_d02d497a_236c_4852_812a_0d39373e312a'
|
|
fake_new_src_share_server = fake_new_src_share['share_server']
|
|
fake_new_src_ss_name = (
|
|
fake_new_src_share_server['backend_details']['vserver_name'])
|
|
self.mock_object(self.dm_session, 'delete_snapmirror')
|
|
self.mock_object(data_motion, 'get_client_for_backend',
|
|
mock.Mock(side_effect=[self.mock_dest_client,
|
|
self.mock_src_client]))
|
|
mock_backend_config = na_fakes.create_configuration()
|
|
mock_backend_config.driver_handles_share_servers = True
|
|
self.mock_object(data_motion, 'get_backend_configuration',
|
|
mock.Mock(return_value=mock_backend_config))
|
|
self.mock_object(self.mock_dest_client, 'get_vserver_peers',
|
|
mock.Mock(return_value=[]))
|
|
peer_cluster_name = 'new_src_cluster_name'
|
|
self.mock_object(self.mock_src_client, 'get_cluster_name',
|
|
mock.Mock(return_value=peer_cluster_name))
|
|
|
|
self.dm_session.change_snapmirror_source(
|
|
self.fake_dest_share, self.fake_src_share, fake_new_src_share,
|
|
[self.fake_dest_share, self.fake_src_share, fake_new_src_share])
|
|
|
|
self.assertEqual(4, self.dm_session.delete_snapmirror.call_count)
|
|
|
|
self.mock_dest_client.get_vserver_peers.assert_called_once_with(
|
|
self.dest_vserver, fake_new_src_ss_name
|
|
)
|
|
self.assertTrue(self.mock_src_client.get_cluster_name.called)
|
|
self.mock_dest_client.create_vserver_peer.assert_called_once_with(
|
|
self.dest_vserver, fake_new_src_ss_name,
|
|
peer_cluster_name=peer_cluster_name
|
|
)
|
|
self.mock_src_client.accept_vserver_peer.assert_called_once_with(
|
|
fake_new_src_ss_name, self.dest_vserver
|
|
)
|
|
self.dm_session.delete_snapmirror.assert_called_with(
|
|
mock.ANY, mock.ANY, release=False
|
|
)
|
|
self.mock_dest_client.create_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, fake_new_src_share_name, mock.ANY,
|
|
self.fake_dest_vol_name, schedule='hourly'
|
|
)
|
|
self.mock_dest_client.resync_snapmirror_vol.assert_called_once_with(
|
|
mock.ANY, fake_new_src_share_name, mock.ANY,
|
|
self.fake_dest_vol_name
|
|
)
|
|
|
|
def test_get_snapmirrors(self):
|
|
self.mock_object(self.mock_dest_client, 'get_snapmirrors')
|
|
|
|
self.dm_session.get_snapmirrors(self.fake_src_share,
|
|
self.fake_dest_share)
|
|
|
|
self.mock_dest_client.get_snapmirrors.assert_called_with(
|
|
source_vserver=self.source_vserver,
|
|
dest_vserver=self.dest_vserver,
|
|
source_volume=self.fake_src_vol_name,
|
|
dest_volume=self.fake_dest_vol_name,
|
|
desired_attributes=['relationship-status',
|
|
'mirror-state',
|
|
'source-vserver',
|
|
'source-volume',
|
|
'last-transfer-end-timestamp']
|
|
)
|
|
self.assertEqual(1, self.mock_dest_client.get_snapmirrors.call_count)
|
|
|
|
def test_get_snapmirrors_svm(self):
|
|
mock_dest_client = mock.Mock()
|
|
self.mock_object(self.dm_session, 'get_client_and_vserver_name',
|
|
mock.Mock(return_value=(mock_dest_client,
|
|
self.dest_vserver)))
|
|
self.mock_object(mock_dest_client, 'get_snapmirrors_svm')
|
|
|
|
self.dm_session.get_snapmirrors_svm(self.fake_src_share_server,
|
|
self.fake_dest_share_server)
|
|
|
|
mock_dest_client.get_snapmirrors_svm.assert_called_with(
|
|
source_vserver=self.source_vserver,
|
|
dest_vserver=self.dest_vserver,
|
|
desired_attributes=['relationship-status',
|
|
'mirror-state',
|
|
'last-transfer-end-timestamp']
|
|
)
|
|
self.assertEqual(1, mock_dest_client.get_snapmirrors_svm.call_count)
|
|
|
|
def test_get_snapmirror_destinations_svm(self):
|
|
mock_dest_client = mock.Mock()
|
|
self.mock_object(self.dm_session, 'get_client_and_vserver_name',
|
|
mock.Mock(return_value=(mock_dest_client,
|
|
self.dest_vserver)))
|
|
self.mock_object(mock_dest_client, 'get_snapmirror_destinations_svm')
|
|
|
|
self.dm_session.get_snapmirror_destinations_svm(
|
|
self.fake_src_share_server, self.fake_dest_share_server)
|
|
|
|
mock_dest_client.get_snapmirror_destinations_svm.assert_called_with(
|
|
source_vserver=self.source_vserver,
|
|
dest_vserver=self.dest_vserver,
|
|
)
|
|
self.assertEqual(1, mock_dest_client.get_snapmirror_destinations_svm
|
|
.call_count)
|
|
|
|
def test_update_snapmirror(self):
|
|
self.mock_object(self.mock_dest_client, 'get_snapmirrors')
|
|
|
|
self.dm_session.update_snapmirror(self.fake_src_share,
|
|
self.fake_dest_share)
|
|
|
|
self.mock_dest_client.update_snapmirror_vol.assert_called_once_with(
|
|
self.source_vserver, self.fake_src_vol_name,
|
|
self.dest_vserver, self.fake_dest_vol_name)
|
|
|
|
def test_update_snapmirror_svm(self):
|
|
mock_dest_client = mock.Mock()
|
|
self.mock_object(self.dm_session, 'get_client_and_vserver_name',
|
|
mock.Mock(return_value=(mock_dest_client,
|
|
self.dest_vserver)))
|
|
|
|
self.dm_session.update_snapmirror_svm(self.fake_src_share_server,
|
|
self.fake_dest_share_server)
|
|
|
|
mock_dest_client.update_snapmirror_svm.assert_called_once_with(
|
|
self.source_vserver, self.dest_vserver)
|
|
|
|
def test_abort_and_break_snapmirror_svm(self):
|
|
mock_dest_client = mock.Mock()
|
|
self.mock_object(self.dm_session, 'get_client_and_vserver_name',
|
|
mock.Mock(return_value=(mock_dest_client,
|
|
self.dest_vserver)))
|
|
self.mock_object(self.dm_session, 'quiesce_then_abort_svm')
|
|
|
|
self.dm_session.quiesce_and_break_snapmirror_svm(
|
|
self.fake_src_share_server, self.fake_dest_share_server
|
|
)
|
|
|
|
self.dm_session.get_client_and_vserver_name.assert_called_once_with(
|
|
self.fake_dest_share_server
|
|
)
|
|
self.dm_session.quiesce_then_abort_svm.assert_called_once_with(
|
|
self.fake_src_share_server, self.fake_dest_share_server
|
|
)
|
|
mock_dest_client.break_snapmirror_svm(self.source_vserver,
|
|
self.dest_vserver)
|
|
|
|
@ddt.data({'snapmirrors': ['fake_snapmirror'],
|
|
'vserver_subtype': 'default'},
|
|
{'snapmirrors': [],
|
|
'vserver_subtype': 'default'},
|
|
{'snapmirrors': [],
|
|
'vserver_subtype': 'dp_destination'})
|
|
@ddt.unpack
|
|
def test_cancel_snapmirror_svm(self, snapmirrors, vserver_subtype):
|
|
mock_dest_client = mock.Mock()
|
|
self.mock_object(self.dm_session, 'get_client_and_vserver_name',
|
|
mock.Mock(return_value=(mock_dest_client,
|
|
self.dest_vserver)))
|
|
mock_backend_config = na_fakes.create_configuration()
|
|
mock_backend_config.netapp_server_migration_state_change_timeout = 30
|
|
self.mock_object(data_motion, 'get_backend_configuration',
|
|
mock.Mock(return_value=mock_backend_config))
|
|
self.mock_object(self.dm_session, 'get_snapmirrors_svm',
|
|
mock.Mock(return_value=snapmirrors))
|
|
self.mock_object(self.dm_session, 'quiesce_and_break_snapmirror_svm')
|
|
self.mock_object(self.dm_session, 'wait_for_vserver_state')
|
|
self.mock_object(self.dm_session, 'delete_snapmirror_svm')
|
|
vserver_info = copy.deepcopy(fake.VSERVER_INFO)
|
|
vserver_info['subtype'] = vserver_subtype
|
|
self.mock_object(mock_dest_client, 'get_vserver_info',
|
|
mock.Mock(return_value=vserver_info))
|
|
self.mock_object(self.dm_session, 'convert_svm_to_default_subtype')
|
|
|
|
self.dm_session.cancel_snapmirror_svm(self.fake_src_share_server,
|
|
self.fake_dest_share_server)
|
|
|
|
data_motion.get_backend_configuration.assert_called_once_with(
|
|
self.dest_backend_name
|
|
)
|
|
self.dm_session.get_client_and_vserver_name.assert_called_once_with(
|
|
self.fake_dest_share_server
|
|
)
|
|
self.dm_session.get_snapmirrors_svm.assert_called_once_with(
|
|
self.fake_src_share_server, self.fake_dest_share_server
|
|
)
|
|
if snapmirrors:
|
|
quiesce_mock = self.dm_session.quiesce_and_break_snapmirror_svm
|
|
quiesce_mock.assert_called_once_with(
|
|
self.fake_src_share_server, self.fake_dest_share_server
|
|
)
|
|
self.dm_session.wait_for_vserver_state.assert_called_once_with(
|
|
self.dest_vserver, mock_dest_client, subtype='default',
|
|
state='running', operational_state='stopped',
|
|
timeout=(mock_backend_config
|
|
.netapp_server_migration_state_change_timeout)
|
|
)
|
|
self.dm_session.delete_snapmirror_svm.assert_called_once_with(
|
|
self.fake_src_share_server, self.fake_dest_share_server
|
|
)
|
|
else:
|
|
mock_dest_client.get_vserver_info.assert_called_once_with(
|
|
self.dest_vserver
|
|
)
|
|
convert_svm = self.dm_session.convert_svm_to_default_subtype
|
|
if vserver_subtype == 'dp_destination':
|
|
convert_svm.assert_called_once_with(
|
|
self.dest_vserver, mock_dest_client,
|
|
timeout=(mock_backend_config
|
|
.netapp_server_migration_state_change_timeout)
|
|
)
|
|
else:
|
|
self.assertFalse(convert_svm.called)
|
|
|
|
def test_resume_snapmirror(self):
|
|
self.mock_object(self.mock_dest_client, 'get_snapmirrors')
|
|
|
|
self.dm_session.resume_snapmirror(self.fake_src_share,
|
|
self.fake_dest_share)
|
|
|
|
self.mock_dest_client.resume_snapmirror_vol.assert_called_once_with(
|
|
self.source_vserver, self.fake_src_vol_name,
|
|
self.dest_vserver, self.fake_dest_vol_name)
|
|
|
|
@ddt.data((None, exception.StorageCommunicationException),
|
|
(exception.StorageCommunicationException, None))
|
|
@ddt.unpack
|
|
def test_remove_qos_on_old_active_replica_unreachable_backend(self,
|
|
side_eff_1,
|
|
side_eff_2):
|
|
mock_source_client = mock.Mock()
|
|
self.mock_object(data_motion, 'get_client_for_backend',
|
|
mock.Mock(return_value=mock_source_client))
|
|
self.mock_object(
|
|
mock_source_client, 'set_qos_policy_group_for_volume',
|
|
mock.Mock(side_effect=side_eff_1))
|
|
self.mock_object(
|
|
mock_source_client, 'mark_qos_policy_group_for_deletion',
|
|
mock.Mock(side_effect=side_eff_2))
|
|
self.mock_object(data_motion.LOG, 'exception')
|
|
|
|
retval = self.dm_session.remove_qos_on_old_active_replica(
|
|
self.fake_src_share)
|
|
|
|
self.assertIsNone(retval)
|
|
(mock_source_client.set_qos_policy_group_for_volume
|
|
.assert_called_once_with(self.fake_src_vol_name, 'none'))
|
|
data_motion.LOG.exception.assert_called_once()
|
|
|
|
def test_remove_qos_on_old_active_replica(self):
|
|
mock_source_client = mock.Mock()
|
|
self.mock_object(data_motion, 'get_client_for_backend',
|
|
mock.Mock(return_value=mock_source_client))
|
|
self.mock_object(data_motion.LOG, 'exception')
|
|
|
|
retval = self.dm_session.remove_qos_on_old_active_replica(
|
|
self.fake_src_share)
|
|
|
|
self.assertIsNone(retval)
|
|
(mock_source_client.set_qos_policy_group_for_volume
|
|
.assert_called_once_with(self.fake_src_vol_name, 'none'))
|
|
data_motion.LOG.exception.assert_not_called()
|
|
|
|
@ddt.data(True, False)
|
|
def test_convert_svm_to_default_subtype(self, is_dest):
|
|
mock_client = mock.Mock()
|
|
vserver_info_default = copy.deepcopy(fake.VSERVER_INFO)
|
|
vserver_info_default['subtype'] = 'default'
|
|
vserver_info_dp = copy.deepcopy(fake.VSERVER_INFO)
|
|
vserver_info_dp['subtype'] = 'dp_destination'
|
|
self.mock_object(mock_client, 'get_vserver_info',
|
|
mock.Mock(side_effect=[vserver_info_dp,
|
|
vserver_info_default]))
|
|
self.mock_object(mock_client, 'break_snapmirror_svm')
|
|
|
|
self.dm_session.convert_svm_to_default_subtype(fake.VSERVER1,
|
|
mock_client,
|
|
is_dest_path=is_dest,
|
|
timeout=20)
|
|
|
|
mock_client.get_vserver_info.assert_has_calls([
|
|
mock.call(fake.VSERVER1), mock.call(fake.VSERVER1)])
|
|
if is_dest:
|
|
mock_client.break_snapmirror_svm.assert_called_once_with(
|
|
dest_vserver=fake.VSERVER1
|
|
)
|
|
else:
|
|
mock_client.break_snapmirror_svm.assert_called_once_with(
|
|
source_vserver=fake.VSERVER1
|
|
)
|
|
|
|
def test_convert_svm_to_default_subtype_timeout(self):
|
|
mock_client = mock.Mock()
|
|
vserver_info_dp = copy.deepcopy(fake.VSERVER_INFO)
|
|
vserver_info_dp['subtype'] = 'dp_destination'
|
|
self.mock_object(mock_client, 'get_vserver_info',
|
|
mock.Mock(side_effect=[vserver_info_dp]))
|
|
self.mock_object(mock_client, 'break_snapmirror_svm')
|
|
|
|
self.assertRaises(
|
|
exception.NetAppException,
|
|
self.dm_session.convert_svm_to_default_subtype,
|
|
fake.VSERVER1, mock_client, is_dest_path=True, timeout=10)
|
|
|
|
mock_client.get_vserver_info.assert_called_once_with(fake.VSERVER1)
|
|
mock_client.break_snapmirror_svm.assert_called_once_with(
|
|
dest_vserver=fake.VSERVER1)
|
|
|
|
def test_wait_for_vserver_state(self,):
|
|
mock_client = mock.Mock()
|
|
vserver_info_default = copy.deepcopy(fake.VSERVER_INFO)
|
|
vserver_info_default['subtype'] = 'default'
|
|
vserver_info_dp = copy.deepcopy(fake.VSERVER_INFO)
|
|
vserver_info_dp['subtype'] = 'dp_destination'
|
|
self.mock_object(mock_client, 'get_vserver_info',
|
|
mock.Mock(side_effect=[vserver_info_dp,
|
|
vserver_info_default]))
|
|
|
|
self.dm_session.wait_for_vserver_state(fake.VSERVER1, mock_client,
|
|
state='running',
|
|
operational_state='running',
|
|
subtype='default', timeout=20)
|
|
|
|
mock_client.get_vserver_info.assert_has_calls([
|
|
mock.call(fake.VSERVER1), mock.call(fake.VSERVER1)])
|
|
|
|
def test_wait_for_vserver_state_timeout(self):
|
|
mock_client = mock.Mock()
|
|
vserver_info_dp = copy.deepcopy(fake.VSERVER_INFO)
|
|
vserver_info_dp['subtype'] = 'dp_destination'
|
|
self.mock_object(mock_client, 'get_vserver_info',
|
|
mock.Mock(side_effect=[vserver_info_dp]))
|
|
|
|
self.assertRaises(
|
|
exception.NetAppException,
|
|
self.dm_session.wait_for_vserver_state,
|
|
fake.VSERVER1, mock_client, state='running',
|
|
operational_state='running', subtype='default', timeout=10)
|
|
|
|
mock_client.get_vserver_info.assert_called_once_with(fake.VSERVER1)
|
|
|
|
@ddt.data(mock.Mock(),
|
|
mock.Mock(side_effect=netapp_api.NaApiError(
|
|
code=netapp_api.EOBJECTNOTFOUND)))
|
|
def test_wait_for_snapmirror_release_svm(self, release_snapmirror_ret):
|
|
src_mock_client = mock.Mock()
|
|
get_snapmirrors_mock = self.mock_object(
|
|
src_mock_client, 'get_snapmirror_destinations_svm',
|
|
mock.Mock(side_effect=[['fake_snapmirror'], []]))
|
|
self.mock_object(src_mock_client, 'release_snapmirror_svm',
|
|
release_snapmirror_ret)
|
|
|
|
self.dm_session.wait_for_snapmirror_release_svm(fake.VSERVER1,
|
|
fake.VSERVER2,
|
|
src_mock_client,
|
|
timeout=20)
|
|
get_snapmirrors_mock.assert_has_calls([
|
|
mock.call(source_vserver=fake.VSERVER1,
|
|
dest_vserver=fake.VSERVER2),
|
|
mock.call(source_vserver=fake.VSERVER1,
|
|
dest_vserver=fake.VSERVER2)])
|
|
if release_snapmirror_ret.side_effect is None:
|
|
src_mock_client.release_snapmirror_svm.assert_called_once_with(
|
|
fake.VSERVER1, fake.VSERVER2)
|
|
else:
|
|
src_mock_client.release_snapmirror_svm.assert_called_once_with(
|
|
fake.VSERVER1, fake.VSERVER2
|
|
)
|
|
|
|
def test_wait_for_snapmirror_release_svm_timeout(self):
|
|
src_mock_client = mock.Mock()
|
|
get_snapmirrors_mock = self.mock_object(
|
|
src_mock_client, 'get_snapmirror_destinations_svm',
|
|
mock.Mock(side_effect=[['fake_snapmirror']]))
|
|
self.mock_object(src_mock_client, 'release_snapmirror_svm')
|
|
|
|
self.assertRaises(exception.NetAppException,
|
|
self.dm_session.wait_for_snapmirror_release_svm,
|
|
fake.VSERVER1, fake.VSERVER2,
|
|
src_mock_client, timeout=10)
|
|
|
|
get_snapmirrors_mock.assert_called_once_with(
|
|
source_vserver=fake.VSERVER1, dest_vserver=fake.VSERVER2)
|
|
src_mock_client.release_snapmirror_svm.assert_called_once_with(
|
|
fake.VSERVER1, fake.VSERVER2
|
|
)
|