cinder/cinder/tests/unit/volume/drivers/ibm/test_xiv_proxy.py

2594 lines
93 KiB
Python

# Copyright (c) 2016 IBM Corporation
# 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 mock
import six
from xml.etree import ElementTree
from cinder import context
from cinder import exception
from cinder import objects
from cinder.objects import fields
from cinder import test
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import utils as testutils
from cinder.tests.unit.volume.drivers.ibm import fake_pyxcli
import cinder.volume.drivers.ibm.ibm_storage as storage
from cinder.volume.drivers.ibm.ibm_storage import cryptish
from cinder.volume.drivers.ibm.ibm_storage.xiv_proxy import XIVProxy
from cinder.volume.drivers.ibm.ibm_storage import xiv_replication
from cinder.volume import group_types
errors = fake_pyxcli.pyxcli_client.errors
mirroring = fake_pyxcli.pyxcli_client.mirroring
mirrored_entities = fake_pyxcli.pyxcli_client.mirroring.mirrored_entities
test_mock = mock.MagicMock()
module_patcher = mock.MagicMock()
test_mock.cinder.exception = exception
TEST_LOG_PREFIX = storage.XIV_LOG_PREFIX
TEST_VOLUME = {
'name': 'BLA',
'id': 23,
'size': 17,
'group_id': fake.CONSISTENCY_GROUP_ID,
}
TEST_GROUP_SPECS = {
'group_replication_enabled': '<is> True',
'replication_type': 'sync',
}
TEST_EXTRA_SPECS = {
'replication_enabled': '<is> False',
}
TEST_EXTRA_SPECS_REPL = {
'replication_enabled': '<is> True',
'replication_type': 'sync',
}
TEST_WWPNS = ["50017380FE020160", "50017380FE020161", "50017380FE020162"]
TEST_INITIATOR = 'c5507606d5680e05'
TEST_CONNECTOR = {
'ip': '129.123.123.123',
'initiator': TEST_INITIATOR,
'wwpns': [TEST_INITIATOR],
}
TEST_TARGET_MAP = {TEST_INITIATOR: TEST_WWPNS}
TEST_HOST_ID = 11
TEST_HOST_NAME = 'WTF32'
TEST_CHAP_NAME = 'WTF64'
TEST_CHAP_SECRET = 'V1RGNjRfXw=='
FC_TARGETS_OPTIMIZED = [
"50017380FE020160", "50017380FE020190", "50017380FE020192"]
FC_TARGETS_OPTIMIZED_WITH_HOST = [
"50017380FE020160", "50017380FE020192"]
FC_TARGETS_BEFORE_SORTING = [
"50017380FE020160", "50017380FE020161", "50017380FE020162",
"50017380FE020190", "50017380FE020191", "50017380FE020192"]
FC_TARGETS_AFTER_SORTING = [
"50017380FE020190", "50017380FE020160", "50017380FE020191",
"50017380FE020161", "50017380FE020162", "50017380FE020192"]
FC_PORT_LIST_OUTPUT = [
{'component_id': '1:FC_Port:4:1', 'port_state': 'Online', 'role': 'Target',
'wwpn': '50017380FE020160'},
{'component_id': '1:FC_Port:5:1', 'port_state': 'Link Problem',
'role': 'Target', 'wwpn': '50017380FE020161'},
{'component_id': '1:FC_Port:6:1', 'port_state': 'Online',
'role': 'Initiator', 'wwpn': '50017380FE020162'},
{'component_id': '1:FC_Port:7:1', 'port_state': 'Link Problem',
'role': 'Initiator', 'wwpn': '50017380FE020163'},
{'component_id': '1:FC_Port:8:1', 'port_state': 'Online', 'role': 'Target',
'wwpn': '50017380FE020190'},
{'component_id': '1:FC_Port:9:1', 'port_state': 'Link Problem',
'role': 'Target', 'wwpn': '50017380FE020191'},
{'component_id': '1:FC_Port:4:1', 'port_state': 'Online', 'role': 'Target',
'wwpn': '50017380FE020192'},
{'component_id': '1:FC_Port:5:1', 'port_state': 'Link Problem',
'role': 'Initiator', 'wwpn': '50017380FE020193'}]
HOST_CONNECTIVITY_LIST = [
{'host': 'nova-compute-c5507606d5680e05', 'host_port': '10000000C97D26DB',
'local_fc_port': '1:FC_Port:4:1', 'local_iscsi_port': '',
'module': '1:Module:4', 'type': 'FC'}]
HOST_CONNECTIVITY_LIST_UNKNOWN_HOST = [
{'host': 'nova-compute-c5507606d5680f115', 'host_port': '10000000C97D26DE',
'local_fc_port': '1:FC_Port:3:1', 'local_iscsi_port': '',
'module': '1:Module:3', 'type': 'FC'}]
REPLICA_ID = 'WTF32'
REPLICA_IP = '1.2.3.4'
REPLICA_USER = 'WTF64'
REPLICA_PASSWORD = 'WTFWTF'
REPLICA_POOL = 'WTF64'
REPLICA_PARAMS = {
'san_ip': REPLICA_IP,
'san_login': REPLICA_USER,
'san_password': cryptish.encrypt(REPLICA_PASSWORD),
'san_clustername': REPLICA_POOL
}
TEST_POOL = [
{'name': 'WTF32', 'size': 10026, 'empty_space': 6925}]
class XIVProxyTest(test.TestCase):
"""Tests the main Proxy driver"""
def setUp(self):
"""import at setup to ensure module patchers are in place"""
super(XIVProxyTest, self).setUp()
self.proxy = XIVProxy
self.version = "cinder"
self.proxy.configuration = {}
self.ctxt = context.get_admin_context()
self.default_storage_info = {
'user': "WTF32",
'password': cryptish.encrypt("WTF32"),
'address': "WTF32",
'vol_pool': "WTF32",
'management_ips': "WTF32",
'system_id': "WTF32"
}
self.proxy.configuration['replication_device'] = {
'backend_id': REPLICA_ID,
'san_ip': REPLICA_IP,
'san_user': REPLICA_USER,
'san_password': REPLICA_PASSWORD,
}
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.pyxcli")
def test_wrong_pyxcli(self, mock_pyxcli):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
mock_pyxcli.version = '1.1.4'
self.assertRaises(test_mock.cinder.exception.CinderException,
p.setup, {})
@mock.patch("cinder.volume.drivers.ibm.ibm_storage"
".xiv_proxy.socket.getfqdn", new=mock.MagicMock(
return_value='test_hostname'))
def test_setup_should_fail_if_password_is_not_encrypted(self):
"""Passing an unencrypted password should raise an error"""
storage_info = self.default_storage_info.copy()
storage_info['password'] = "WTF32"
p = self.proxy(storage_info, mock.MagicMock(),
test_mock.cinder.exception)
self.assertRaises(test_mock.cinder.exception.InvalidParameterValue,
p.setup, {})
@mock.patch("cinder.volume.drivers.ibm.ibm_storage.xiv_proxy.client."
"XCLIClient")
def test_setup_should_fail_if_pool_is_invalid(self, mock_xcli):
"""Setup should raise exception if pool is invalid"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
cmd = mock_xcli.connect_multiendpoint_ssl.return_value.cmd
cmd.pool_list.return_value.as_list = []
self.assertRaises(test_mock.cinder.exception.VolumeBackendAPIException,
p.setup, {})
@mock.patch("cinder.volume.drivers.ibm.ibm_storage.xiv_proxy.client."
"XCLIClient")
@mock.patch("cinder.volume.drivers.ibm.ibm_storage.xiv_proxy.socket."
"getfqdn", new=mock.MagicMock(
return_value='test_hostname'))
def test_setup_should_fail_if_credentials_are_invalid(self, mock_xcli):
"""Passing invalid credentials should raise an error"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
mock_xcli.connect_multiendpoint_ssl = mock.MagicMock(
side_effect=errors.CredentialsError(
'bla', 'bla', ElementTree.Element("bla")))
self.assertRaises(test_mock.cinder.exception.NotAuthorized,
p.setup, {})
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.client.XCLIClient")
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.socket.getfqdn", new=mock.MagicMock(
return_value='test_hostname'))
def test_setup_should_fail_if_connection_is_invalid(self, mock_xcli):
"""Passing an invalid host to the setup should raise an error"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
mock_xcli.connect_multiendpoint_ssl = mock.MagicMock(
side_effect=errors.ConnectionError(
'bla', 'bla', ElementTree.Element("bla")))
self.assertRaises(test_mock.cinder.exception.HostNotFound,
p.setup, {})
@mock.patch("cinder.volume.drivers.ibm.ibm_storage.xiv_proxy."
"client.XCLIClient")
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.storage.get_online_iscsi_ports",
mock.MagicMock(return_value=['WTF32']))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.socket.getfqdn", new=mock.MagicMock(
return_value='test_hostname'))
def test_setup_should_set_iqn_and_portal(self, mock_xcli):
"""Test setup
Setup should retrieve values from xcli
and set the IQN and Portal
"""
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception)
cmd = mock_xcli.connect_multiendpoint_ssl.return_value.cmd
item = cmd.config_get.return_value.as_dict.return_value.__getitem__
item.return_value.value = "BLA"
p.setup({})
self.assertEqual("BLA", p.meta.get('ibm_storage_iqn'))
self.assertEqual("WTF32:3260", p.meta.get('ibm_storage_portal'))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage.xiv_proxy."
"client.XCLIClient")
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.storage.get_online_iscsi_ports",
mock.MagicMock(return_value=['WTF32']))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.socket.getfqdn", new=mock.MagicMock(
return_value='test_hostname'))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_target_params",
mock.MagicMock(return_value=REPLICA_PARAMS))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_target",
mock.MagicMock(return_value="BLABLA"))
def test_setup_should_succeed_if_replica_is_set(self, mock_xcli):
"""Test setup
Setup should succeed if replica is set
"""
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception)
cmd = mock_xcli.connect_multiendpoint_ssl.return_value.cmd
item = cmd.config_get.return_value.as_dict.return_value.__getitem__
item.return_value.value = "BLA"
SCHEDULE_LIST_RESPONSE = {
'00:01:00': {'interval': 120},
'00:02:00': {'interval': 300},
'00:05:00': {'interval': 600},
'00:10:00': {'interval': 1200},
}
cmd = mock_xcli.connect_multiendpoint_ssl.return_value.cmd
cmd.schedule_list.return_value\
.as_dict.return_value = SCHEDULE_LIST_RESPONSE
p.setup({})
@mock.patch("cinder.volume.drivers.ibm.ibm_storage.xiv_proxy."
"client.XCLIClient")
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.storage.get_online_iscsi_ports",
mock.MagicMock(return_value=['WTF32']))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.socket.getfqdn", new=mock.MagicMock(
return_value='test_hostname'))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_target_params",
mock.MagicMock(return_value=REPLICA_PARAMS))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_target",
mock.MagicMock(return_value="BLABLA"))
def test_setup_should_fail_if_schedule_create_fails(self, mock_xcli):
"""Test setup
Setup should fail if replica is set and schedule_create fails
"""
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception)
cmd = mock_xcli.connect_multiendpoint_ssl.return_value.cmd
item = cmd.config_get.return_value.as_dict.return_value.__getitem__
item.return_value.value = "BLA"
cmd.schedule_list.return_value.as_dict.return_value = {}
cmd.schedule_create.side_effect = (
errors.XCLIError('bla'))
self.assertRaises(exception.VolumeBackendAPIException, p.setup, {})
def test_get_volume_stats(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.pool_list.return_value.as_list = TEST_POOL
stats = p.get_volume_stats()
self.assertEqual("up", stats['backend_state'])
p.ibm_storage_cli.cmd.pool_list.return_value.as_list = None
stats = p.get_volume_stats(refresh=True)
self.assertEqual("down", stats['backend_state'])
def test_create_volume_should_call_xcli(self):
"""Create volume should call xcli with the correct parameters"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
volume = testutils.create_volume(
self.ctxt, size=16, display_name='WTF32')
p.create_volume(volume)
p.ibm_storage_cli.cmd.vol_create.assert_called_once_with(
vol=volume.name,
size_blocks=storage.gigabytes_to_blocks(16),
pool='WTF32')
def test_create_volume_from_snapshot(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
volume = testutils.create_volume(
self.ctxt, size=16, display_name='WTF32')
snapshot = testutils.create_snapshot(self.ctxt, volume.id)
p.create_volume_from_snapshot(volume, snapshot)
p.ibm_storage_cli.cmd.vol_copy.assert_called_once_with(
vol_src=snapshot.name,
vol_trg=volume.name)
def test_create_volume_should_fail_if_no_pool_space(self):
"""Test create volume
Create volume should raise an error
if there's no pool space left
"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.vol_create.side_effect = (
errors.PoolOutOfSpaceError(
'bla', 'bla', ElementTree.Element('bla')))
volume = testutils.create_volume(
self.ctxt, size=16, display_name='WTF32',
volume_type_id='b3fcacb5-fbd8-4394-8c00-06853bc13929')
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_volume, volume)
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_replication.VolumeReplication.create_replication",
mock.MagicMock())
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_replication.GroupReplication.create_replication",
mock.MagicMock())
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_target_params",
mock.MagicMock(return_value=REPLICA_PARAMS))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_target",
mock.MagicMock(return_value="BLABLA"))
def test_enable_replication(self):
"""Test enable_replication"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p._call_remote_xiv_xcli = mock.MagicMock()
p._update_consistencygroup = mock.MagicMock()
p.targets = {'tgt1': 'info1'}
group = self._create_test_group('WTF')
vol = testutils.create_volume(self.ctxt)
ret = p.enable_replication(self.ctxt, group, [vol])
self.assertEqual((
{'replication_status': fields.ReplicationStatus.ENABLED},
[{'id': vol['id'],
'replication_status': fields.ReplicationStatus.ENABLED}]), ret)
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_replication.VolumeReplication.create_replication",
mock.MagicMock())
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_replication.GroupReplication.create_replication",
mock.MagicMock())
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_target_params",
mock.MagicMock(return_value=REPLICA_PARAMS))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_target",
mock.MagicMock(return_value="BLABLA"))
@mock.patch("cinder.volume.group_types.get_group_type_specs",
mock.MagicMock(return_value=TEST_GROUP_SPECS))
def test_enable_replication_remote_cg_exists(self):
"""Test enable_replication"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p._call_remote_xiv_xcli = mock.MagicMock()
p._update_consistencygroup = mock.MagicMock()
p.targets = {'tgt1': 'info1'}
error = errors.CgNameExistsError('bla', 'bla',
ElementTree.Element('bla'))
p._call_remote_xiv_xcli.cmd.cg_create.side_effect = error
group = self._create_test_group('WTF')
vol = testutils.create_volume(self.ctxt)
ret = p.enable_replication(self.ctxt, group, [vol])
self.assertEqual((
{'replication_status': fields.ReplicationStatus.ENABLED},
[{'id': vol['id'],
'replication_status': fields.ReplicationStatus.ENABLED}]), ret)
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_replication.VolumeReplication.delete_replication",
mock.MagicMock())
@mock.patch("cinder.volume.group_types.get_group_type_specs",
mock.MagicMock(return_value=TEST_GROUP_SPECS))
def test_disable_replication(self):
"""Test disable_replication"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p._call_remote_xiv_xcli = mock.MagicMock()
p._update_consistencygroup = mock.MagicMock()
group = self._create_test_group('WTF')
ret = p.disable_replication(self.ctxt, group, [])
self.assertEqual((
{'replication_status': fields.ReplicationStatus.DISABLED}, []),
ret)
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._using_default_backend",
mock.MagicMock(return_value=False))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_target_params",
mock.MagicMock(return_value={'san_clustername': "master"}))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._init_xcli",
mock.MagicMock())
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._init_xcli",
mock.MagicMock())
@mock.patch("cinder.volume.group_types.get_group_type_specs",
mock.MagicMock(return_value=TEST_GROUP_SPECS))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_replication.GroupReplication.failover",
mock.MagicMock(return_value=(True, 'good')))
def test_failover_replication_with_default(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
group = self._create_test_group('WTF')
group.replication_status = fields.ReplicationStatus.FAILED_OVER
vol = testutils.create_volume(self.ctxt)
group_update, vol_update = p.failover_replication(self.ctxt, group,
[vol], 'default')
updates = {'status': 'available'}
self.assertEqual(({'replication_status': 'enabled'},
[{'id': vol['id'],
'updates': updates}]), (group_update, vol_update))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._using_default_backend",
mock.MagicMock(return_value=True))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_target_params",
mock.MagicMock(return_value={'san_clustername': "master"}))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._init_xcli",
mock.MagicMock())
@mock.patch("cinder.volume.group_types.get_group_type_specs",
mock.MagicMock(return_value=TEST_GROUP_SPECS))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_replication.GroupReplication.failover",
mock.MagicMock(return_value=(True, 'good')))
def test_failover_replication(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
group = self._create_test_group('WTF')
failed_over = fields.ReplicationStatus.FAILED_OVER
group.replication_status = failed_over
vol = testutils.create_volume(self.ctxt)
group_update, vol_update = p.failover_replication(self.ctxt, group,
[vol],
'secondary_id')
failed_over = fields.ReplicationStatus.FAILED_OVER
updates = {'status': failed_over}
self.assertEqual(({'replication_status': failed_over},
[{'id': vol['id'],
'updates': updates}]), (group_update, vol_update))
def test_failover_resource_no_mirror(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
recovery_mgr = mock.MagicMock()
recovery_mgr.is_mirror_active = mock.MagicMock()
recovery_mgr.is_mirror_active.return_value = False
group = self._create_test_group('WTF')
ret = xiv_replication.Replication(p)._failover_resource(
group, recovery_mgr, mock.MagicMock, 'cg', True)
msg = ("%(rep_type)s %(res)s: no active mirroring and can not "
"failback" % {'rep_type': 'cg',
'res': group['name']})
self.assertEqual((False, msg), ret)
def test_failover_resource_mirror(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
recovery_mgr = mock.MagicMock()
recovery_mgr.is_mirror_active = mock.MagicMock()
recovery_mgr.is_mirror_active.return_value = True
group = self._create_test_group('WTF')
ret = xiv_replication.Replication(p)._failover_resource(
group, recovery_mgr, mock.MagicMock, 'cg', True)
self.assertEqual((True, None), ret)
def test_failover_resource_change_role(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
recovery_mgr = mock.MagicMock()
recovery_mgr.is_mirror_active = mock.MagicMock()
recovery_mgr.is_mirror_active.return_value = True
recovery_mgr.switch_roles.side_effect = (
errors.XCLIError(''))
failover_rep_mgr = mock.MagicMock()
failover_rep_mgr.change_role = mock.MagicMock()
group = self._create_test_group('WTF')
xiv_replication.Replication(p)._failover_resource(
group, recovery_mgr, failover_rep_mgr, 'cg', True)
failover_rep_mgr.change_role.assert_called_once_with(
resource_id=group['name'],
new_role='Slave')
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_target_params",
mock.MagicMock(return_value=REPLICA_PARAMS))
def test_pool_with_replication_failover_back(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
pool_name = p._get_backend_pool()
self.assertEqual(self.default_storage_info['vol_pool'], pool_name)
p_failback = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver,
REPLICA_ID)
pool_name = p_failback._get_backend_pool()
self.assertEqual(REPLICA_POOL, pool_name)
@mock.patch("cinder.volume.utils.is_group_a_cg_snapshot_type",
mock.MagicMock(return_value=True))
def test_create_volume_with_consistency_group(self):
"""Test Create volume with consistency_group"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p._cg_name_from_volume = mock.MagicMock(return_value="cg")
vol_type = testutils.create_volume_type(self.ctxt, name='WTF')
volume = testutils.create_volume(
self.ctxt, size=16, volume_type_id=vol_type.id)
grp = self._create_test_group('WTF')
volume.group = grp
p.create_volume(volume)
p.ibm_storage_cli.cmd.vol_create.assert_called_once_with(
vol=volume['name'],
size_blocks=storage.gigabytes_to_blocks(16),
pool='WTF32')
p.ibm_storage_cli.cmd.cg_add_vol.assert_called_once_with(
vol=volume['name'],
cg='cg')
@mock.patch('pyxcli.mirroring.mirrored_entities.'
'MirroredEntities', mock.MagicMock())
@mock.patch('cinder.volume.utils.is_group_a_type',
mock.MagicMock(return_value=True))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_extra_specs",
mock.MagicMock(return_value=TEST_EXTRA_SPECS_REPL))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_replication.VolumeReplication.create_replication",
mock.MagicMock())
def test_create_volume_with_consistency_group_diff_state(self):
"""Test Create volume with consistency_group but diff state"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p._cg_name_from_volume = mock.MagicMock(return_value="cg")
vol_type = testutils.create_volume_type(self.ctxt, name='WTF')
volume = testutils.create_volume(
self.ctxt, size=16, volume_type_id=vol_type.id,
host=self._get_test_host()['name'])
grp = self._create_test_group('WTF')
grp['replication_status'] = 'enabled'
volume.group = grp
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_volume, volume)
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_replication.VolumeReplication.create_replication",
mock.MagicMock())
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_qos_specs",
mock.MagicMock(return_value=None))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_extra_specs",
mock.MagicMock(return_value=TEST_EXTRA_SPECS_REPL))
def test_create_volume_with_replication(self):
"""Test Create volume with replication"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
volume = testutils.create_volume(
self.ctxt, size=16, display_name='WTF32',
volume_type_id='b3fcacb5-fbd8-4394-8c00-06853bc13929')
volume.group = None
p.create_volume(volume)
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_replication.VolumeReplication.create_replication",
mock.MagicMock())
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_qos_specs",
mock.MagicMock(return_value=None))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_extra_specs",
mock.MagicMock(return_value=TEST_EXTRA_SPECS_REPL))
def test_create_volume_with_replication_and_cg(self):
"""Test Create volume with replication and CG"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
volume = testutils.create_volume(
self.ctxt, size=16, display_name='WTF32',
volume_type_id='b3fcacb5-fbd8-4394-8c00-06853bc13929')
grp = testutils.create_group(self.ctxt, name='bla', group_type_id='1')
volume.group = grp
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_volume, volume)
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_qos_specs",
mock.MagicMock(return_value=None))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_extra_specs",
mock.MagicMock(return_value=TEST_EXTRA_SPECS_REPL))
def test_create_volume_with_replication_multiple_targets(self):
"""Test Create volume with replication and multiple targets"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
volume = testutils.create_volume(
self.ctxt, size=16, display_name='WTF32',
volume_type_id='b3fcacb5-fbd8-4394-8c00-06853bc13929')
volume.group = None
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_volume, volume)
def test_delete_volume_should_pass_the_correct_parameters(self):
"""Delete volume should call xcli with the correct parameters"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.vol_list.return_value.as_list = ['aa']
p.delete_volume({'name': 'WTF32'})
p.ibm_storage_cli.cmd.vol_delete.assert_called_once_with(vol='WTF32')
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_replication.VolumeReplication.delete_replication",
mock.MagicMock())
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_extra_specs",
mock.MagicMock(return_value=TEST_EXTRA_SPECS_REPL))
def test_delete_volume_with_replication(self):
"""Test Delete volume with replication"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
volume = {'size': 16, 'name': 'WTF32', 'volume_type_id': 'WTF'}
p.delete_volume(volume)
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_extra_specs",
mock.MagicMock(return_value=TEST_EXTRA_SPECS_REPL))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.client.XCLIClient")
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_target_params",
mock.MagicMock(return_value=REPLICA_PARAMS))
def test_failover_host(self, mock_xcli):
"""Test failover_host with valid target"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock_xcli
p.ibm_storage_cli.connect_multiendpoint_ssl.return_value
mock_xcli.connect_multiendpoint_ssl.return_value = mock_xcli
volume = {'id': 'WTF64', 'size': 16,
'name': 'WTF32', 'volume_type_id': 'WTF'}
target = REPLICA_ID
p.failover_host({}, [volume], target, [])
def test_failover_host_invalid_target(self):
"""Test failover_host with invalid target"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
volume = {'id': 'WTF64', 'size': 16,
'name': 'WTF32', 'volume_type_id': 'WTF'}
target = 'Invalid'
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.failover_host, {}, [volume], target, [])
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.client.XCLIClient")
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_target_params",
mock.MagicMock(return_value=REPLICA_PARAMS))
def test_failover_host_no_connection_to_target(self, mock_xcli):
"""Test failover_host that fails to connect to target"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock_xcli
p.ibm_storage_cli.connect_multiendpoint_ssl.return_value
mock_xcli.connect_multiendpoint_ssl.side_effect = errors.XCLIError('')
volume = {'id': 'WTF64', 'size': 16,
'name': 'WTF32', 'volume_type_id': 'WTF'}
target = REPLICA_ID
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.failover_host, {}, [volume], target, [])
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.client.XCLIClient")
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_target_params",
mock.MagicMock(return_value=REPLICA_PARAMS))
def test_failback_host(self, mock_xcli):
"""Test failing back after DR"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
volume = {'id': 'WTF64', 'size': 16,
'name': 'WTF32', 'volume_type_id': 'WTF'}
target = 'default'
p.failover_host(None, [volume], target, [])
def qos_test_empty_name_if_no_specs(self):
"""Test empty name in case no specs are specified"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
perf_name = p._check_perf_class_on_backend({})
self.assertEqual('', perf_name)
def test_qos_class_name_contains_qos_type(self):
"""Test backend naming
Test if the naming convention is correct
when getting the right specs with qos type
"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.perf_class_list.return_value.as_list = []
perf_name = p._check_perf_class_on_backend({'bw': '100',
'type': 'independent'})
self.assertEqual('cinder-qos_bw_100_type_independent', perf_name)
def test_qos_called_with_type_parameter(self):
"""Test xcli call for qos creation with type"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.perf_class_list.return_value.as_list = []
perf_name = p._check_perf_class_on_backend({'bw': '100',
'type': 'independent'})
p.ibm_storage_cli.cmd.perf_class_create.assert_called_once_with(
perf_class=perf_name,
type='independent')
def test_qos_called_with_wrong_type_parameter(self):
"""Test xcli call for qos creation with wrong type"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.perf_class_list.return_value.as_list = []
p.ibm_storage_cli.cmd.perf_class_create.side_effect = (
errors.XCLIError('llegal value'))
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p._check_perf_class_on_backend,
{'bw': '100', 'type': 'BAD'})
def test_qos_class_on_backend_name_correct(self):
"""Test backend naming
Test if the naming convention is correct
when getting the right specs
"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.perf_class_list.return_value.as_list = []
perf_name = p._check_perf_class_on_backend({'bw': '100'})
self.assertEqual('cinder-qos_bw_100', perf_name)
def test_qos_xcli_exception(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.perf_class_list.side_effect = (
errors.XCLIError(''))
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p._check_perf_class_on_backend, {'bw': '100'})
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._qos_create_kwargs_for_xcli",
mock.MagicMock(return_value={}))
def test_regex_from_perf_class_name(self):
"""Test type extraction from perf_class with Regex"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
perf_class_names_list = [
{'class_name': 'cinder-qos_iops_1000_type_independent_bw_1000',
'type': 'independent'},
{'class_name': 'cinder-qos_iops_1000_bw_1000_type_shared',
'type': 'shared'},
{'class_name': 'cinder-qos_type_badtype_bw_1000',
'type': None}]
for element in perf_class_names_list:
_type = p._get_type_from_perf_class_name(
perf_class_name=element['class_name'])
self.assertEqual(element['type'], _type)
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._qos_create_kwargs_for_xcli",
mock.MagicMock(return_value={}))
def test_create_qos_class_with_type(self):
"""Test performance class creation with type"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.perf_class_set_rate.return_value = None
p.ibm_storage_cli.cmd.perf_class_create.return_value = None
perf_class_name = 'cinder-qos_iops_1000_type_independent_bw_1000'
p_class_name = p._create_qos_class(perf_class_name=perf_class_name,
specs=None)
p.ibm_storage_cli.cmd.perf_class_create.assert_called_once_with(
perf_class=perf_class_name,
type='independent')
self.assertEqual('cinder-qos_iops_1000_type_independent_bw_1000',
p_class_name)
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._check_storage_version_for_qos_support",
mock.MagicMock(return_value=True))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_qos_specs",
mock.MagicMock(return_value='specs'))
def test_qos_specs_exist_if_type_exists(self):
"""Test a case where type was found and qos were found"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
volume = {'name': 'bla', 'volume_type_id': '7'}
specs = p._qos_specs_from_volume(volume)
self.assertEqual('specs', specs)
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._check_storage_version_for_qos_support",
mock.MagicMock(return_value=True))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_qos_specs",
mock.MagicMock(return_value=None))
def test_no_qos_but_type_exists(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
volume = {'name': 'bla', 'volume_type_id': '7'}
specs = p._qos_specs_from_volume(volume)
self.assertIsNone(specs)
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._check_storage_version_for_qos_support",
mock.MagicMock(return_value=True))
@mock.patch("cinder.volume.drivers.ibm.ibm_storage."
"xiv_proxy.XIVProxy._get_qos_specs",
mock.MagicMock(return_value=None))
def test_qos_specs_doesnt_exist_if_no_type(self):
"""Test _qos_specs_from_volume
Test a case where no type was defined
and therefore no specs exist
"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
volume = {'name': 'bla'}
specs = p._qos_specs_from_volume(volume)
self.assertIsNone(specs)
def test_manage_volume_should_call_xcli(self):
"""Manage volume should call xcli with the correct parameters"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.vol_list.return_value.as_list = [
{'name': 'WTF64', 'size': 34}]
p.manage_volume(volume={'name': 'WTF32'},
reference={'source-name': 'WTF64'})
p.ibm_storage_cli.cmd.vol_list.assert_called_once_with(
vol='WTF64')
def test_manage_volume_should_return_volume_if_exists(self):
"""Manage volume should return with no errors"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.vol_list.return_value.as_list = [
{'name': 'WTF64', 'size': 34}]
volume = {'name': 'WTF32'}
p.manage_volume(volume=volume,
reference={'source-name': 'WTF64'})
self.assertEqual(34, volume['size'])
def test_manage_volume_should_raise_exception_if_not_exists(self):
"""Test manage_volume
Manage volume should return with exception
if volume does not exist
"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.vol_list.return_value.as_list = []
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.manage_volume, volume={'name': 'WTF32'},
reference={'source-name': 'WTF64'})
def test_manage_volume_get_size_if_volume_exists(self):
"""Manage volume get size should return size"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.vol_list.return_value.as_list = [
{'name': 'WTF64', 'size': 34}]
volume = {'name': 'WTF32'}
size = p.manage_volume_get_size(volume=volume,
reference={'source-name': 'WTF64'})
self.assertEqual(34, size)
def test_retype_false_if_no_location(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
volume = {'display_name': 'vol'}
new_type = {}
new_type['name'] = "type1"
host = {'capabilities': ''}
diff = {}
ret = p.retype({}, volume, new_type, diff, host)
self.assertFalse(ret)
def test_retype_false_if_dest_not_xiv_backend(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
host = {'capabilities': {'location_info': "IBM-XIV:host:pool"}}
volume = {'display_name': 'vol', 'host': "origdest_orighost_origpool"}
new_type = {'name': "type1"}
diff = {}
ret = p.retype({}, volume, new_type, diff, host)
self.assertFalse(ret)
def test_retype_true_if_dest_is_xiv_backend(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.migrate_volume = mock.MagicMock()
p.migrate_volume.return_value = (True, None)
p._qos_specs_from_volume = mock.MagicMock()
p._get_qos_specs = mock.MagicMock()
p._qos_specs_from_volume.return_value = {}
p._get_qos_specs.return_value = {}
host = {'capabilities': {'location_info': "IBM-XIV:host:pool"}}
volume = {'display_name': 'vol', 'host': "IBM-XIV_host_pool"}
new_type = {'name': "type1"}
diff = {}
ret = p.retype({}, volume, new_type, diff, host)
self.assertTrue(ret)
def test_manage_volume_get_size_should_raise_exception_if_not_exists(self):
"""Test manage_volume
Manage volume get size should raise exception
if volume does not exist
"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.vol_list.return_value.as_list = []
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.manage_volume_get_size,
volume={'name': 'WTF32'},
reference={'source-name': 'WTF64'})
def test_initialize_connection(self):
"""Test initialize_connection
Ensure that initialize connection returns,
all the correct connection values
"""
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception)
p.ibm_storage_iqn = "BLAIQN"
p.ibm_storage_portal = "BLAPORTAL"
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.vol_list.return_value.as_list = ['aa']
host = self._get_test_host()
setattr(
p, '_get_host_and_fc_targets', mock.MagicMock(return_value=(
[], host)))
setattr(
p, '_vol_map_and_get_lun_id', mock.MagicMock(return_value=100))
p.volume_exists = mock.MagicMock(return_value=True)
info = p.initialize_connection(TEST_VOLUME, {})
self.assertEqual(
p.meta.get('ibm_storage_portal'),
info['data']['target_portal'])
self.assertEqual(
p.meta.get('ibm_storage_iqn'),
info['data']['target_iqn'])
self.assertEqual(100, info['data']['target_lun'])
def test_initialize_connection_no_initiator(self):
"""Initialize connection raises exception on missing initiator"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
connector = TEST_CONNECTOR.copy()
connector['initiator'] = None
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.initialize_connection, TEST_VOLUME,
connector)
def test_initialize_connection_bad_iqn(self):
"""Initialize connection raises exception on bad formatted IQN"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
connector = TEST_CONNECTOR.copy()
# any string would pass for initiator
connector['initiator'] = 5555
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.initialize_connection, TEST_VOLUME,
connector)
def test_get_fc_targets_returns_optimized_wwpns_list(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.fc_port_list.return_value = FC_PORT_LIST_OUTPUT
fc_targets = p._get_fc_targets(None)
six.assertCountEqual(self, FC_TARGETS_OPTIMIZED, fc_targets)
def test_get_fc_targets_returns_host_optimized_wwpns_list(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
hostname = storage.get_host_or_create_from_iqn(TEST_CONNECTOR)
host = {'name': hostname}
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.fc_port_list.return_value = FC_PORT_LIST_OUTPUT
p.ibm_storage_cli.cmd.host_connectivity_list.return_value = (
HOST_CONNECTIVITY_LIST)
fc_targets = p._get_fc_targets(host)
six.assertCountEqual(self,
FC_TARGETS_OPTIMIZED_WITH_HOST, fc_targets,
"FC targets are different from the expected")
def test_get_fc_targets_returns_host_all_wwpns_list(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
hostname = storage.get_host_or_create_from_iqn(TEST_CONNECTOR)
host = {'name': hostname}
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.fc_port_list.return_value = FC_PORT_LIST_OUTPUT
p.ibm_storage_cli.cmd.host_connectivity_list.return_value = (
HOST_CONNECTIVITY_LIST_UNKNOWN_HOST)
fc_targets = p._get_fc_targets(host)
six.assertCountEqual(self,
FC_TARGETS_OPTIMIZED, fc_targets,
"FC targets are different from the expected")
def test_define_fc_returns_all_wwpns_list(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.fc_port_list.return_value = FC_PORT_LIST_OUTPUT
p.ibm_storage_cli.fc_connectivity_list.return_value = ()
fc_targets = p._define_fc(p._define_host(TEST_CONNECTOR))
six.assertCountEqual(self,
FC_TARGETS_OPTIMIZED, fc_targets,
"FC targets are different from the expected")
def test_define_ports_returns_sorted_wwpns_list(self):
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p._get_connection_type = mock.MagicMock(
return_value=storage.XIV_CONNECTION_TYPE_FC)
p._define_fc = mock.MagicMock(return_value=FC_TARGETS_BEFORE_SORTING)
fc_targets = p._define_ports(self._get_test_host())
fc_result = list(map(lambda x: x[-1:], fc_targets))
expected_result = list(map(lambda x: x[-1:], FC_TARGETS_AFTER_SORTING))
self.assertEqual(expected_result, fc_result,
"FC targets are different from the expected")
def test_get_host_and_fc_targets_if_host_not_defined(self):
"""Test host and FC targets
Tests that host and fc targets are provided
if the host is not defined
"""
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception)
p.meta = mock.MagicMock()
p.meta.ibm_storage_iqn = "BLAIQN"
p.meta.ibm_storage_portal = "BLAPORTAL"
p.meta.openstack_version = "cinder-2013.2"
pool = {'name': "WTF32", 'domain': 'pool_domain_bla'}
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.host_list.return_value.as_list = []
p.ibm_storage_cli.cmd.host_list_ports.return_value = []
p.ibm_storage_cli.cmd.pool_list.return_value.as_list = [pool]
p._get_bunch_from_host = mock.MagicMock()
p._get_bunch_from_host.return_value = {
'name': "nova-compute-%s" % TEST_INITIATOR,
'initiator': TEST_INITIATOR,
'id': 123, 'wwpns': 111, 'chap': 'chap', }
fc_targets, host = getattr(p, '_get_host_and_fc_targets')(
TEST_VOLUME, TEST_CONNECTOR)
hostname = storage.get_host_or_create_from_iqn(TEST_CONNECTOR)
p.ibm_storage_cli.cmd.host_define.assert_called_once_with(
host=hostname, domain=pool.get('domain'))
p.ibm_storage_cli.cmd.host_add_port.assert_called_once_with(
host=hostname, iscsi_name=TEST_CONNECTOR['initiator'])
def test_get_lun_id_if_host_already_mapped(self):
"""Test lun id
Tests that a lun is provided if host is already
mapped to other volumes
"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
vol_mapping_list = p.ibm_storage_cli.cmd.vol_mapping_list
vol_mapping_list.return_value.as_dict.return_value = {}
lun1 = {'lun': 1}
lun2 = {'lun': 2}
p.ibm_storage_cli.cmd.mapping_list.return_value.as_list = [lun1, lun2]
host = self._get_test_host()
self.assertEqual(
3, getattr(p, '_vol_map_and_get_lun_id')(
TEST_VOLUME, TEST_CONNECTOR, host))
def test_terminate_connection_should_call_unmap_vol(self):
"""Terminate connection should call unmap vol"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p._get_connection_type = mock.MagicMock(
return_value=storage.XIV_CONNECTION_TYPE_FC)
p._get_fc_targets = mock.MagicMock(return_value=TEST_WWPNS)
p.ibm_storage_cli = mock.MagicMock()
vol_mapping_ret = p.ibm_storage_cli.cmd.vol_mapping_list.return_value
vol_mapping_ret.as_dict.return_value.has_keys.return_value = True
p.ibm_storage_cli.cmd.vol_list.return_value.as_list = ['aa']
hostname = storage.get_host_or_create_from_iqn(TEST_CONNECTOR)
host = {
'name': hostname,
'initiator': TEST_CONNECTOR['initiator'],
'id': 1
}
TEST_CONNECTOR['wwpns'] = [TEST_INITIATOR]
setattr(p, "_get_host", mock.MagicMock(return_value=host))
meta = p.terminate_connection(TEST_VOLUME, TEST_CONNECTOR)
self.assertEqual(
TEST_TARGET_MAP, meta['data']['initiator_target_map'])
p.ibm_storage_cli.cmd.unmap_vol.assert_called_once_with(
vol=TEST_VOLUME['name'], host=hostname)
def test_terminate_connection_multiple_connections(self):
# Terminate connection should not return meta if host is still
# connected
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception)
p.ibm_storage_cli = mock.MagicMock()
vol_dict = p.ibm_storage_cli.cmd.vol_mapping_list.return_value.as_dict
vol_dict.return_value.has_keys.return_value = True
p.ibm_storage_cli.cmd.vol_list.return_value.as_list = ['aa']
hostname = storage.get_host_or_create_from_iqn(TEST_CONNECTOR)
host = {
'name': hostname,
'initiator': TEST_CONNECTOR['initiator'],
'id': 1
}
TEST_CONNECTOR['wwpns'] = [TEST_INITIATOR]
map_dict = p.ibm_storage_cli.cmd.mapping_list.return_value.as_dict
map_dict.return_value.has_keys.return_value = host
setattr(p, "_get_host", mock.MagicMock(return_value=host))
meta = p.terminate_connection(TEST_VOLUME, TEST_CONNECTOR)
self.assertIsNone(meta)
p.ibm_storage_cli.cmd.unmap_vol.assert_called_once_with(
vol=TEST_VOLUME['name'], host=hostname)
def test_attach_deleted_volume_should_fail_with_info_to_log(self):
"""Test attach deleted volume should fail with info to log"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
mock_log = mock.MagicMock()
setattr(p, "_log", mock_log)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.vol_mapping_list.side_effect = (
errors.VolumeBadNameError('bla', 'bla',
ElementTree.Element('Bla')))
p._define_host_according_to_chap = mock.MagicMock()
p._define_host_according_to_chap.return_value = dict(id=100)
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.initialize_connection, TEST_VOLUME,
TEST_CONNECTOR)
def _get_test_host(self):
host = {
'name': TEST_HOST_NAME,
'initiator': TEST_INITIATOR,
'id': TEST_HOST_ID,
'wwpns': [TEST_INITIATOR],
'chap': (TEST_CHAP_NAME, TEST_CHAP_SECRET)
}
return host
def _create_test_group(self, g_name='group', is_cg=True):
extra_specs = {}
if is_cg:
extra_specs['consistent_group_snapshot_enabled'] = '<is> True'
group_type = group_types.create(self.ctxt, g_name, extra_specs)
return testutils.create_group(self.ctxt,
host=self._get_test_host()['name'],
group_type_id=group_type.id,
volume_type_ids=[])
def _create_test_cgsnapshot(self, group_id):
group_type = group_types.create(
self.ctxt, 'group_snapshot',
{'consistent_group_snapshot_enabled': '<is> True'})
return testutils.create_group_snapshot(self.ctxt, group_id=group_id,
group_type_id=group_type.id)
def test_create_generic_group(self):
"""test create generic group"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
group_obj = self._create_test_group(is_cg=False)
self.assertRaises(NotImplementedError,
p.create_group, {}, group_obj)
def test_create_consistencygroup(self):
"""test a successful cg create"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
group_obj = self._create_test_group()
model_update = p.create_group({}, group_obj)
p.ibm_storage_cli.cmd.cg_create.assert_called_once_with(
cg=p._cg_name_from_id(group_obj.id),
pool='WTF32')
self.assertEqual('available', model_update['status'])
def test_create_consistencygroup_already_exists(self):
"""test create_consistenygroup when cg already exists"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.cg_create.side_effect = errors.CgNameExistsError(
'bla', 'bla', ElementTree.Element('bla'))
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_group, {}, self._create_test_group())
def test_create_consistencygroup_reached_limit(self):
"""test create_consistenygroup when reached maximum CGs"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.cg_create.side_effect = (
errors.CgLimitReachedError(
'bla', 'bla', ElementTree.Element('bla')))
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_group, {}, self._create_test_group())
@mock.patch("cinder.volume.drivers.ibm.ibm_storage.xiv_proxy."
"client.XCLIClient")
def test_create_consistencygroup_with_replication(self, mock_xcli):
"""test create_consistenygroup when replication is set"""
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception)
p.ibm_storage_cli = mock.MagicMock()
group_obj = self._create_test_group()
vol_type = objects.VolumeType(context=self.ctxt,
name='volume_type_rep',
extra_specs=(
{'replication_enabled': '<is> True',
'replication_type': 'sync'}))
group_obj.volume_types = objects.VolumeTypeList(context=self.ctxt,
objects=[vol_type])
model_update = p.create_group({}, group_obj)
self.assertEqual('available', model_update['status'])
def test_create_consistencygroup_from_src_cgsnapshot(self):
"""test a successful cg create from cgsnapshot"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.create_volume_from_snapshot.return_value = []
group_obj = self._create_test_group()
cgsnap_group_obj = self._create_test_cgsnapshot(group_obj.id)
volume = testutils.create_volume(self.ctxt)
snapshot = testutils.create_snapshot(self.ctxt, volume.id)
model_update, vols_model_update = p.create_group_from_src(
{}, group_obj, [volume],
cgsnap_group_obj, [snapshot], None, None)
p.ibm_storage_cli.cmd.cg_create.assert_called_once_with(
cg=p._cg_name_from_id(group_obj.id), pool='WTF32')
self.assertEqual('available', model_update['status'])
def test_create_consistencygroup_from_src_cg(self):
"""test a successful cg create from consistencygroup"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.create_volume_from_snapshot.return_value = []
group_obj = self._create_test_group()
src_group_obj = self._create_test_group(g_name='src_group')
volume = testutils.create_volume(self.ctxt)
src_volume = testutils.create_volume(self.ctxt)
model_update, vols_model_update = p.create_group_from_src(
{}, group_obj, [volume],
None, None, src_group_obj, [src_volume])
p.ibm_storage_cli.cmd.cg_create.assert_called_once_with(cg=group_obj,
pool='WTF32')
self.assertEqual('available', model_update['status'])
def test_create_consistencygroup_from_src_fails_cg_create_from_cgsnapshot(
self):
"""test cg create from cgsnapshot fails on cg_create"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.cg_create.side_effect = errors.XCLIError(
'bla', 'bla', ElementTree.Element('bla'))
group_obj = self._create_test_group()
cgsnap_group_obj = self._create_test_cgsnapshot(group_obj.id)
volume = testutils.create_volume(self.ctxt)
snapshot = testutils.create_snapshot(self.ctxt, volume.id)
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_group_from_src, {},
group_obj, [volume], cgsnap_group_obj,
[snapshot], None, None)
def test_create_consistencygroup_from_src_fails_cg_create_from_cg(self):
"""test cg create from cg fails on cg_create"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.cg_create.side_effect = errors.XCLIError(
'bla', 'bla', ElementTree.Element('bla'))
group_obj = self._create_test_group()
src_group_obj = self._create_test_group(g_name='src_group')
volume = testutils.create_volume(self.ctxt)
src_volume = testutils.create_volume(self.ctxt)
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_group_from_src, {},
group_obj, [volume], None, None,
src_group_obj, [src_volume])
def test_create_consistencygroup_from_src_fails_vol_create_from_cgsnapshot(
self):
"""test cg create from cgsnapshot fails on vol_create"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.vol_create.side_effect = errors.XCLIError(
'bla', 'bla', ElementTree.Element('bla'))
group_obj = self._create_test_group()
cgsnap_group_obj = self._create_test_cgsnapshot(group_obj.id)
volume = testutils.create_volume(self.ctxt)
snapshot = testutils.create_snapshot(self.ctxt, volume.id)
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_group_from_src, {},
group_obj, [volume], cgsnap_group_obj,
[snapshot], None, None)
def test_create_consistencygroup_from_src_fails_vol_create_from_cg(self):
"""test cg create from cg fails on vol_create"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.vol_create.side_effect = errors.XCLIError(
'bla', 'bla', ElementTree.Element('bla'))
group_obj = self._create_test_group()
src_group_obj = self._create_test_group(g_name='src_group')
volume = testutils.create_volume(self.ctxt)
src_volume = testutils.create_volume(self.ctxt)
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_group_from_src, {},
group_obj, [volume], None, None,
src_group_obj, [src_volume])
def test_create_consistencygroup_from_src_fails_vol_copy_from_cgsnapshot(
self):
"""test cg create from cgsnapshot fails on vol_copy"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.vol_copy.side_effect = errors.XCLIError(
'bla', 'bla', ElementTree.Element('bla'))
group_obj = self._create_test_group()
cgsnap_group_obj = self._create_test_cgsnapshot(group_obj.id)
volume = testutils.create_volume(self.ctxt)
snapshot = testutils.create_snapshot(self.ctxt, volume.id)
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_group_from_src, {}, group_obj,
[volume], cgsnap_group_obj, [snapshot],
None, None)
def test_create_consistencygroup_from_src_fails_vol_copy_from_cg(self):
"""test cg create from cg fails on vol_copy"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.vol_copy.side_effect = errors.XCLIError(
'bla', 'bla', ElementTree.Element('bla'))
group_obj = self._create_test_group()
src_group_obj = self._create_test_group(g_name='src_group')
volume = testutils.create_volume(self.ctxt)
src_volume = testutils.create_volume(self.ctxt)
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_group_from_src, {},
group_obj, [volume], None, None,
src_group_obj, [src_volume])
def test_delete_consistencygroup_with_no_volumes(self):
"""test a successful cg delete"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
group_obj = self._create_test_group()
model_update, volumes = p.delete_group({}, group_obj, [])
p.ibm_storage_cli.cmd.cg_delete.assert_called_once_with(
cg=p._cg_name_from_id(group_obj.id))
self.assertEqual('deleted', model_update['status'])
def test_delete_consistencygroup_not_exists(self):
"""test delete_consistenygroup when CG does not exist"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.cg_delete.side_effect = (
errors.CgDoesNotExistError(
'bla', 'bla', ElementTree.Element('bla')))
group_obj = self._create_test_group()
model_update, volumes = p.delete_group({}, group_obj, [])
p.ibm_storage_cli.cmd.cg_delete.assert_called_once_with(
cg=p._cg_name_from_id(group_obj.id))
self.assertEqual('deleted', model_update['status'])
def test_delete_consistencygroup_not_exists_2(self):
"""test delete_consistenygroup when CG does not exist bad name"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.cg_delete.side_effect = (
errors.CgBadNameError(
'bla', 'bla', ElementTree.Element('bla')))
group_obj = self._create_test_group()
model_update, volumes = p.delete_group({}, group_obj, [])
p.ibm_storage_cli.cmd.cg_delete.assert_called_once_with(
cg=p._cg_name_from_id(group_obj.id))
self.assertEqual('deleted', model_update['status'])
def test_delete_consistencygroup_not_empty(self):
"""test delete_consistenygroup when CG is not empty"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.cg_delete.side_effect = errors.CgNotEmptyError(
'bla', 'bla', ElementTree.Element('bla'))
group_obj = self._create_test_group()
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.delete_group, {}, group_obj, [])
def test_delete_consistencygroup_replicated(self):
"""test delete cg when CG is not empty and replicated"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
group_obj = self._create_test_group()
group_obj['replication_status'] = fields.ReplicationStatus.ENABLED
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.delete_group, {}, group_obj, [])
def test_delete_consistencygroup_faildover(self):
"""test delete cg when CG is faildover"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
group_obj = self._create_test_group()
group_obj['replication_status'] = fields.ReplicationStatus.FAILED_OVER
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.delete_group, {}, group_obj, [])
def test_delete_consistencygroup_is_mirrored(self):
"""test delete_consistenygroup when CG is mirroring"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.cg_delete.side_effect = errors.CgHasMirrorError(
'bla', 'bla', ElementTree.Element('bla'))
group_obj = self._create_test_group()
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.delete_group, {}, group_obj, [])
def test_update_consistencygroup(self):
"""test update_consistencygroup"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
group_obj = self._create_test_group()
vol_add = testutils.create_volume(self.ctxt, display_name='WTF32')
vol_remove = testutils.create_volume(self.ctxt, display_name='WTF64')
model_update, add_model_update, remove_model_update = (
p.update_group({}, group_obj, [vol_add], [vol_remove]))
p.ibm_storage_cli.cmd.cg_add_vol.assert_called_once_with(
vol=vol_add['name'], cg=p._cg_name_from_id(group_obj.id))
p.ibm_storage_cli.cmd.cg_remove_vol.assert_called_once_with(
vol=vol_remove['name'])
self.assertEqual('available', model_update['status'])
def test_update_consistencygroup_exception_in_add_vol(self):
"""test update_consistencygroup with exception in cg_add_vol"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.cg_add_vol.side_effect = errors.XCLIError(
'bla', 'bla', ElementTree.Element('bla'))
group_obj = self._create_test_group()
vol_add = testutils.create_volume(self.ctxt, display_name='WTF32')
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.update_group, {}, group_obj, [vol_add], [])
def test_update_consistencygroup_exception_in_remove_vol(self):
"""test update_consistencygroup with exception in cg_remove_vol"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.cg_remove_vol.side_effect = errors.XCLIError(
'bla', 'bla', ElementTree.Element('bla'))
group_obj = self._create_test_group()
vol_remove = testutils.create_volume(self.ctxt)
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.update_group, {},
group_obj, [], [vol_remove])
def test_update_consistencygroup_remove_non_exist_vol_(self):
"""test update_group with exception in cg_remove_vol"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.cg_remove_vol.side_effect = (
errors.VolumeNotInConsGroup(
'bla', 'bla', ElementTree.Element('bla')))
group_obj = self._create_test_group()
vol_remove = testutils.create_volume(self.ctxt)
model_update, add_model_update, remove_model_update = (
p.update_group({}, group_obj, [], [vol_remove]))
p.ibm_storage_cli.cmd.cg_remove_vol.assert_called_once_with(
vol=vol_remove['name'])
self.assertEqual('available', model_update['status'])
def test_create_cgsnapshot(self):
"""test a successful cgsnapshot create"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
group_obj = self._create_test_group()
cgsnap_group_obj = self._create_test_cgsnapshot(group_obj.id)
model_update, snapshots_model_update = (
p.create_group_snapshot({}, cgsnap_group_obj, []))
p.ibm_storage_cli.cmd.cg_snapshots_create.assert_called_once_with(
cg=p._cg_name_from_cgsnapshot(cgsnap_group_obj),
snap_group=p._group_name_from_cgsnapshot_id(
cgsnap_group_obj['id']))
self.assertEqual('available', model_update['status'])
def test_create_cgsnapshot_is_empty(self):
"""test create_cgsnapshot when CG is empty"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
group_obj = self._create_test_group()
cgsnap_group_obj = self._create_test_cgsnapshot(group_obj.id)
p.ibm_storage_cli.cmd.cg_snapshots_create.side_effect = (
errors.CgEmptyError('bla', 'bla', ElementTree.Element('bla')))
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_group_snapshot, {},
cgsnap_group_obj, [])
def test_create_cgsnapshot_cg_not_exist(self):
"""test create_cgsnapshot when CG does not exist"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
group_obj = self._create_test_group()
cgsnap_group_obj = self._create_test_cgsnapshot(group_obj.id)
p.ibm_storage_cli.cmd.cg_snapshots_create.side_effect = (
errors.CgDoesNotExistError(
'bla', 'bla', ElementTree.Element('bla')))
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_group_snapshot, {},
cgsnap_group_obj, [])
def test_create_cgsnapshot_snapshot_limit(self):
"""test create_cgsnapshot when reached snapshot limit"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
group_obj = self._create_test_group()
cgsnap_group_obj = self._create_test_cgsnapshot(group_obj.id)
p.ibm_storage_cli.cmd.cg_snapshots_create.side_effect = (
errors.PoolSnapshotLimitReachedError(
'bla', 'bla', ElementTree.Element('bla')))
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_group_snapshot, {},
cgsnap_group_obj, [])
def test_delete_cgsnapshot(self):
"""test a successful cgsnapshot delete"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
group_obj = self._create_test_group()
cgsnap_group_obj = self._create_test_cgsnapshot(group_obj.id)
model_update, snapshots_model_update = p.delete_group_snapshot(
{}, cgsnap_group_obj, [])
p.ibm_storage_cli.cmd.snap_group_delete.assert_called_once_with(
snap_group=p._group_name_from_cgsnapshot_id(
cgsnap_group_obj['id']))
self.assertEqual('deleted', model_update['status'])
def test_delete_cgsnapshot_cg_does_not_exist(self):
"""test delete_cgsnapshot with bad CG name"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
group_obj = self._create_test_group()
cgsnap_group_obj = self._create_test_cgsnapshot(group_obj.id)
p.ibm_storage_cli.cmd.snap_group_delete.side_effect = (
errors.CgDoesNotExistError(
'bla', 'bla', ElementTree.Element('bla')))
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.delete_group_snapshot, {},
cgsnap_group_obj, [])
def test_delete_cgsnapshot_no_space_left_for_snapshots(self):
"""test delete_cgsnapshot when no space left for snapshots"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
group_obj = self._create_test_group()
cgsnap_group_obj = self._create_test_cgsnapshot(group_obj.id)
p.ibm_storage_cli.cmd.snap_group_delete.side_effect = (
errors.PoolSnapshotLimitReachedError(
'bla', 'bla', ElementTree.Element('bla')))
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.delete_group_snapshot, {},
cgsnap_group_obj, [])
def test_delete_cgsnapshot_with_empty_consistency_group(self):
"""test delete_cgsnapshot with empty consistency group"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
group_obj = self._create_test_group()
cgsnap_group_obj = self._create_test_cgsnapshot(group_obj.id)
p.ibm_storage_cli.cmd.snap_group_delete.side_effect = (
errors.CgEmptyError('bla', 'bla', ElementTree.Element('bla')))
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.delete_group_snapshot, {},
cgsnap_group_obj, [])
def test_silent_delete_volume(self):
"""test _silent_delete_volume fails silently without exception"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
p.ibm_storage_cli = mock.MagicMock()
p.ibm_storage_cli.cmd.vol_delete.side_effect = errors.XCLIError(
'bla', 'bla', ElementTree.Element('bla'))
# check no assertion occurs
p._silent_delete_volume(TEST_VOLUME)
@mock.patch("cinder.volume.utils.group_get_by_id", mock.MagicMock())
@mock.patch("cinder.volume.utils.is_group_a_cg_snapshot_type",
mock.MagicMock(return_value=False))
def test_create_cloned_volume_calls_vol_create_and_copy(self):
"""test create_cloned_volume
check if calls the appropriate xiv_backend functions
are being called
"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
vol_src = testutils.create_volume(self.ctxt, display_name='bla',
size=17)
vol_trg = testutils.create_volume(self.ctxt, display_name='bla',
size=17)
p.ibm_storage_cli = mock.MagicMock()
p._cg_name_from_volume = mock.MagicMock(return_value="cg")
p.create_cloned_volume(vol_trg, vol_src)
p._create_volume = test_mock.MagicMock()
p.ibm_storage_cli.cmd.vol_create.assert_called_once_with(
pool='WTF32',
size_blocks=storage.gigabytes_to_blocks(17),
vol=vol_trg['name'])
p.ibm_storage_cli.cmd.vol_copy.assert_called_once_with(
vol_src=vol_src['name'],
vol_trg=vol_trg['name'])
@mock.patch("cinder.volume.utils.group_get_by_id", mock.MagicMock())
@mock.patch("cinder.volume.utils.is_group_a_cg_snapshot_type",
mock.MagicMock(return_value=False))
def test_handle_created_vol_properties_returns_vol_update(self):
"""test handle_created_vol_props
returns replication enables if replication info is True
"""
driver = mock.MagicMock()
driver.VERSION = "VERSION"
p = self.proxy(
self.default_storage_info,
mock.MagicMock(),
test_mock.cinder.exception,
driver)
xiv_replication.VolumeReplication = mock.MagicMock()
grp = testutils.create_group(self.ctxt, name='bla', group_type_id='1')
volume = testutils.create_volume(self.ctxt, display_name='bla')
volume.group = grp
ret_val = p.handle_created_vol_properties({'enabled': True}, volume)
self.assertEqual(ret_val, {'replication_status': 'enabled'})