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

2621 lines
95 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.
#
from unittest import mock
from xml.etree import ElementTree
import six
from cinder import context
from cinder import exception
from cinder import objects
from cinder.objects import fields
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import test
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',
volume_type_id=self.vt['id'])
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',
volume_type_id=self.vt['id'])
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=self.vt['id'])
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,
volume_type_id=self.vt['id'])
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,
volume_type_id=self.vt['id'])
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,
volume_type_id=self.vt['id'])
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,
volume_type_id=self.vt['id'])
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.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.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=self.vt['id'])
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=self.vt['id'])
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=self.vt['id'])
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,
volume_type_id=self.vt['id'])
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,
volume_type_id=self.vt['id'])
src_volume = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
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,
volume_type_id=self.vt['id'])
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,
volume_type_id=self.vt['id'])
src_volume = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
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,
volume_type_id=self.vt['id'])
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,
volume_type_id=self.vt['id'])
src_volume = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
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,
volume_type_id=self.vt['id'])
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,
volume_type_id=self.vt['id'])
src_volume = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
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',
volume_type_id=self.vt['id'])
vol_remove = testutils.create_volume(self.ctxt, display_name='WTF64',
volume_type_id=self.vt['id'])
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',
volume_type_id=self.vt['id'])
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,
volume_type_id=self.vt['id'])
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,
volume_type_id=self.vt['id'])
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.volume_utils.group_get_by_id", mock.MagicMock())
@mock.patch("cinder.volume.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,
volume_type_id=self.vt['id'])
vol_trg = testutils.create_volume(self.ctxt, display_name='bla',
size=17,
volume_type_id=self.vt['id'])
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.volume_utils.group_get_by_id", mock.MagicMock())
@mock.patch("cinder.volume.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_type_id=self.vt['id'])
volume.group = grp
ret_val = p.handle_created_vol_properties({'enabled': True}, volume)
self.assertEqual(ret_val, {'replication_status': 'enabled'})