Merge "EMC VNX: Add multi-pools support"

This commit is contained in:
Jenkins 2015-12-24 19:21:43 +00:00 committed by Gerrit Code Review
commit 940531512f
7 changed files with 436 additions and 105 deletions

View File

@ -29,6 +29,7 @@ from manila.share.drivers.emc import plugin_manager as manager
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
EMC_NAS_OPTS = [ EMC_NAS_OPTS = [
cfg.StrOpt('emc_nas_login', cfg.StrOpt('emc_nas_login',
help='User name for the EMC server.'), help='User name for the EMC server.'),
@ -47,8 +48,10 @@ EMC_NAS_OPTS = [
cfg.StrOpt('emc_nas_server_container', cfg.StrOpt('emc_nas_server_container',
default='server_2', default='server_2',
help='Container of share servers.'), help='Container of share servers.'),
cfg.StrOpt('emc_nas_pool_name', cfg.StrOpt('emc_nas_pool_names',
help='EMC pool name.'), deprecated_name='emc_nas_pool_name',
default=None,
help='EMC pool names.'),
cfg.StrOpt('emc_nas_root_dir', cfg.StrOpt('emc_nas_root_dir',
help='The root directory where shares will be located.'), help='The root directory where shares will be located.'),
] ]
@ -118,7 +121,7 @@ class EMCShareDriver(driver.ShareDriver):
def check_for_setup_error(self): def check_for_setup_error(self):
"""Check for setup error.""" """Check for setup error."""
pass self.plugin.check_for_setup_error()
def do_setup(self, context): def do_setup(self, context):
"""Any initialization the share driver does while starting.""" """Any initialization the share driver does while starting."""

View File

@ -283,6 +283,9 @@ class IsilonStorageConnection(base.StorageConnection):
resp = self._isilon_api.request('PUT', url, data=share_params) resp = self._isilon_api.request('PUT', url, data=share_params)
resp.raise_for_status() resp.raise_for_status()
def check_for_setup_error(self):
"""Check for setup error."""
def connect(self, emc_share_driver, context): def connect(self, emc_share_driver, context):
"""Connect to an Isilon cluster.""" """Connect to an Isilon cluster."""
self._server = emc_share_driver.configuration.safe_get( self._server = emc_share_driver.configuration.safe_get(

View File

@ -15,6 +15,7 @@
"""VNX backend for the EMC Manila driver.""" """VNX backend for the EMC Manila driver."""
import copy import copy
import fnmatch
import random import random
from oslo_log import log from oslo_log import log
@ -30,6 +31,7 @@ from manila.share.drivers.emc.plugins import base as driver
from manila.share.drivers.emc.plugins.vnx import constants from manila.share.drivers.emc.plugins.vnx import constants
from manila.share.drivers.emc.plugins.vnx import object_manager as manager from manila.share.drivers.emc.plugins.vnx import object_manager as manager
from manila.share.drivers.emc.plugins.vnx import utils as vnx_utils from manila.share.drivers.emc.plugins.vnx import utils as vnx_utils
from manila.share import utils as share_utils
from manila import utils from manila import utils
VERSION = "2.0.0" VERSION = "2.0.0"
@ -46,8 +48,10 @@ class VNXStorageConnection(driver.StorageConnection):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(VNXStorageConnection, self).__init__(*args, **kwargs) super(VNXStorageConnection, self).__init__(*args, **kwargs)
self.mover_name = None self.mover_name = None
self.pool_name = None self.pools = None
self.manager = None self.manager = None
self.pool_conf = None
self.reserved_percentage = None
self.driver_handles_share_servers = True self.driver_handles_share_servers = True
def create_share(self, context, share, share_server=None): def create_share(self, context, share, share_server=None):
@ -57,11 +61,20 @@ class VNXStorageConnection(driver.StorageConnection):
share_proto = share['share_proto'] share_proto = share['share_proto']
# Validate the share protocol
if share_proto.upper() not in ('NFS', 'CIFS'): if share_proto.upper() not in ('NFS', 'CIFS'):
raise exception.InvalidShare( raise exception.InvalidShare(
reason=(_('Invalid NAS protocol supplied: %s.') reason=(_('Invalid NAS protocol supplied: %s.')
% share_proto)) % share_proto))
# Get the pool name from share host field
pool_name = share_utils.extract_host(share['host'], level='pool')
if not pool_name:
message = (_("Pool is not available in the share host %s.") %
share['host'])
raise exception.InvalidHost(reason=message)
# Validate share server
self._share_server_validation(share_server) self._share_server_validation(share_server)
if share_proto == 'CIFS': if share_proto == 'CIFS':
@ -76,7 +89,7 @@ class VNXStorageConnection(driver.StorageConnection):
LOG.error(message) LOG.error(message)
raise exception.EMCVnxXMLAPIError(err=message) raise exception.EMCVnxXMLAPIError(err=message)
self._allocate_container(share_name, size, share_server) self._allocate_container(share_name, size, share_server, pool_name)
if share_proto == 'NFS': if share_proto == 'NFS':
location = self._create_nfs_share(share_name, share_server) location = self._create_nfs_share(share_name, share_server)
@ -100,14 +113,15 @@ class VNXStorageConnection(driver.StorageConnection):
LOG.error(message) LOG.error(message)
raise exception.EMCVnxXMLAPIError(err=message) raise exception.EMCVnxXMLAPIError(err=message)
def _allocate_container(self, share_name, size, share_server): def _allocate_container(self, share_name, size, share_server, pool_name):
"""Allocate file system for share.""" """Allocate file system for share."""
vdm_name = self._get_share_server_name(share_server) vdm_name = self._get_share_server_name(share_server)
self._get_context('FileSystem').create( self._get_context('FileSystem').create(
share_name, size, self.pool_name, vdm_name) share_name, size, pool_name, vdm_name)
def _allocate_container_from_snapshot(self, share, snapshot, share_server): def _allocate_container_from_snapshot(self, share, snapshot, share_server,
pool_name):
"""Allocate file system from snapshot.""" """Allocate file system from snapshot."""
vdm_name = self._get_share_server_name(share_server) vdm_name = self._get_share_server_name(share_server)
@ -116,10 +130,10 @@ class VNXStorageConnection(driver.StorageConnection):
self._get_context('FileSystem').create_from_snapshot( self._get_context('FileSystem').create_from_snapshot(
share['id'], snapshot['id'], snapshot['share_id'], share['id'], snapshot['id'], snapshot['share_id'],
self.pool_name, vdm_name, interconn_id) pool_name, vdm_name, interconn_id)
nwe_size = share['size'] * units.Ki nwe_size = share['size'] * units.Ki
self._get_context('FileSystem').extend(share['id'], self.pool_name, self._get_context('FileSystem').extend(share['id'], pool_name,
nwe_size) nwe_size)
@vnx_utils.log_enter_exit @vnx_utils.log_enter_exit
@ -170,14 +184,23 @@ class VNXStorageConnection(driver.StorageConnection):
share_proto = share['share_proto'] share_proto = share['share_proto']
# Validate the share protocol
if share_proto.upper() not in ('NFS', 'CIFS'): if share_proto.upper() not in ('NFS', 'CIFS'):
raise exception.InvalidShare( raise exception.InvalidShare(
reason=(_('Invalid NAS protocol supplied: %s.') reason=(_('Invalid NAS protocol supplied: %s.')
% share_proto)) % share_proto))
# Get the pool name from share host field
pool_name = share_utils.extract_host(share['host'], level='pool')
if not pool_name:
message = (_("Pool is not available in the share host %s.") %
share['host'])
raise exception.InvalidHost(reason=message)
self._share_server_validation(share_server) self._share_server_validation(share_server)
self._allocate_container_from_snapshot(share, snapshot, share_server) self._allocate_container_from_snapshot(
share, snapshot, share_server, pool_name)
if share_proto == 'NFS': if share_proto == 'NFS':
self._create_nfs_share(share_name, share_server) self._create_nfs_share(share_name, share_server)
@ -191,9 +214,18 @@ class VNXStorageConnection(driver.StorageConnection):
def create_snapshot(self, context, snapshot, share_server=None): def create_snapshot(self, context, snapshot, share_server=None):
"""Create snapshot from share.""" """Create snapshot from share."""
share_name = snapshot['share_id']
status, filesystem = self._get_context('FileSystem').get(share_name)
if status != constants.STATUS_OK:
message = (_("File System %s not found.") % share_name)
LOG.error(message)
raise exception.EMCVnxXMLAPIError(err=message)
pool_id = filesystem['pools_id'][0]
self._get_context('Snapshot').create(snapshot['id'], self._get_context('Snapshot').create(snapshot['id'],
snapshot['share_id'], snapshot['share_id'],
self.pool_name) pool_id)
def delete_share(self, context, share, share_server=None): def delete_share(self, context, share, share_server=None):
"""Delete a share.""" """Delete a share."""
@ -261,9 +293,17 @@ class VNXStorageConnection(driver.StorageConnection):
"""Ensure that the share is exported.""" """Ensure that the share is exported."""
def extend_share(self, share, new_size, share_server=None): def extend_share(self, share, new_size, share_server=None):
# Get the pool name from share host field
pool_name = share_utils.extract_host(share['host'], level='pool')
if not pool_name:
message = (_("Pool is not available in the share host %s.") %
share['host'])
raise exception.InvalidHost(reason=message)
share_name = share['id'] share_name = share['id']
self._get_context('FileSystem').extend( self._get_context('FileSystem').extend(
share_name, self.pool_name, new_size * units.Ki) share_name, pool_name, new_size * units.Ki)
def allow_access(self, context, share, access, share_server=None): def allow_access(self, context, share, access, share_server=None):
"""Allow access to a share.""" """Allow access to a share."""
@ -395,20 +435,7 @@ class VNXStorageConnection(driver.StorageConnection):
def check_for_setup_error(self): def check_for_setup_error(self):
"""Check for setup error.""" """Check for setup error."""
pass # To verify the input from Manila configuration
def connect(self, emc_share_driver, context):
"""Connect to VNX NAS server."""
self.mover_name = (
emc_share_driver.configuration.emc_nas_server_container)
self.pool_name = emc_share_driver.configuration.emc_nas_pool_name
configuration = emc_share_driver.configuration
self.manager = manager.StorageObjectManager(configuration)
# To verify the input from manila configuration
status, out = self._get_context('Mover').get_ref(self.mover_name, status, out = self._get_context('Mover').get_ref(self.mover_name,
True) True)
if constants.STATUS_ERROR == status: if constants.STATUS_ERROR == status:
@ -417,13 +444,68 @@ class VNXStorageConnection(driver.StorageConnection):
LOG.error(message) LOG.error(message)
raise exception.InvalidParameterValue(err=message) raise exception.InvalidParameterValue(err=message)
status, out = self._get_context('StoragePool').get(self.pool_name, self.pools = self._get_managed_storage_pools(self.pool_conf)
True)
if constants.STATUS_ERROR == status: def _get_managed_storage_pools(self, pools):
message = (_("Could not find storage pool by name: %s.") % matched_pools = set()
self.pool_name) if pools:
LOG.error(message) # Get the real pools from the backend storage
raise exception.InvalidParameterValue(err=message) status, backend_pools = self._get_context('StoragePool').get_all()
if status != constants.STATUS_OK:
message = (_("Failed to get storage pool information. "
"Reason: %s") % backend_pools)
LOG.error(message)
raise exception.EMCVnxXMLAPIError(err=message)
real_pools = set([item for item in backend_pools])
conf_pools = set([item.strip() for item in pools.split(",")])
for pool in real_pools:
for matcher in conf_pools:
if fnmatch.fnmatchcase(pool, matcher):
matched_pools.add(pool)
nonexistent_pools = real_pools.difference(matched_pools)
if not matched_pools:
msg = (_("All the specified storage pools to be managed "
"do not exist. Please check your configuration "
"emc_nas_pool_names in manila.conf. "
"The available pools in the backend are %s") %
",".join(real_pools))
raise exception.InvalidParameterValue(err=msg)
if nonexistent_pools:
LOG.warning(_LW("The following specified storage pools "
"do not exist: %(unexist)s. "
"This host will only manage the storage "
"pools: %(exist)s"),
{'unexist': ",".join(nonexistent_pools),
'exist': ",".join(matched_pools)})
else:
LOG.debug("Storage pools: %s will be managed.",
",".join(matched_pools))
else:
LOG.debug("No storage pool is specified, so all pools "
"in storage system will be managed.")
return matched_pools
def connect(self, emc_share_driver, context):
"""Connect to VNX NAS server."""
self.mover_name = (
emc_share_driver.configuration.emc_nas_server_container)
self.pool_conf = emc_share_driver.configuration.safe_get(
'emc_nas_pool_names')
self.reserved_percentage = emc_share_driver.configuration.safe_get(
'reserved_share_percentage')
if self.reserved_percentage is None:
self.reserved_percentage = 0
configuration = emc_share_driver.configuration
self.manager = manager.StorageObjectManager(configuration)
def update_share_stats(self, stats_dict): def update_share_stats(self, stats_dict):
"""Communicate with EMCNASClient to get the stats.""" """Communicate with EMCNASClient to get the stats."""
@ -431,12 +513,58 @@ class VNXStorageConnection(driver.StorageConnection):
self._get_context('Mover').get_ref(self.mover_name, True) self._get_context('Mover').get_ref(self.mover_name, True)
status, pool = self._get_context('StoragePool').get(self.pool_name, stats_dict['pools'] = []
True)
stats_dict['total_capacity_gb'] = int(pool['total_size']) status, pools = self._get_context('StoragePool').get_all()
stats_dict['free_capacity_gb'] = ( for name, pool in pools.items():
int(pool['total_size']) - int(pool['used_size'])) if not self.pools or pool['name'] in self.pools:
total_size = float(pool['total_size'])
used_size = float(pool['used_size'])
pool_stat = dict(
pool_name=pool['name'],
total_capacity_gb=total_size,
free_capacity_gb=total_size - used_size,
QoS_support=False,
reserved_percentage=self.reserved_percentage,
)
stats_dict['pools'].append(pool_stat)
if not stats_dict['pools']:
message = _("Failed to update storage pool.")
LOG.error(message)
raise exception.EMCVnxXMLAPIError(err=message)
def get_pool(self, share):
"""Get the pool name of the share."""
share_name = share['id']
status, filesystem = self._get_context('FileSystem').get(share_name)
if status != constants.STATUS_OK:
message = (_("File System %(name)s not found. "
"Reason: %(err)s") %
{'name': share_name, 'err': filesystem})
LOG.error(message)
raise exception.EMCVnxXMLAPIError(err=message)
pool_id = filesystem['pools_id'][0]
# Get the real pools from the backend storage
status, backend_pools = self._get_context('StoragePool').get_all()
if status != constants.STATUS_OK:
message = (_("Failed to get storage pool information. "
"Reason: %s") % backend_pools)
LOG.error(message)
raise exception.EMCVnxXMLAPIError(err=message)
for name, pool_info in backend_pools.items():
if pool_info['id'] == pool_id:
return name
available_pools = [item for item in backend_pools]
message = (_("No matched pool name for share: %(share)s. "
"Available pools: %(pools)s") %
{'share': share_name, 'pools': available_pools})
raise exception.EMCVnxXMLAPIError(err=message)
def get_network_allocations_number(self): def get_network_allocations_number(self):
"""Returns number of network allocations for creating VIFs.""" """Returns number of network allocations for creating VIFs."""

View File

@ -1026,11 +1026,9 @@ class Snapshot(StorageObject):
super(Snapshot, self).__init__(conn, elt_maker, xml_parser, manager) super(Snapshot, self).__init__(conn, elt_maker, xml_parser, manager)
self.snap_map = dict() self.snap_map = dict()
def create(self, name, fs_name, pool_name, ckpt_size=None): def create(self, name, fs_name, pool_id, ckpt_size=None):
fs_id = self.get_context('FileSystem').get_id(fs_name) fs_id = self.get_context('FileSystem').get_id(fs_name)
pool_id = self.get_context('StoragePool').get_id(pool_name)
if ckpt_size: if ckpt_size:
elt_pool = self.elt_maker.StoragePool( elt_pool = self.elt_maker.StoragePool(
pool=pool_id, pool=pool_id,

View File

@ -62,6 +62,7 @@ def response(func):
class FakeData(object): class FakeData(object):
# Share informaiton # Share informaiton
share_id = '7cf7c200_d3af_4e05_b87e_9167c95df4f9' share_id = '7cf7c200_d3af_4e05_b87e_9167c95df4f9'
host = 'HostA@BackendB#fake_pool_name'
share_name = share_id share_name = share_id
share_size = 10 share_size = 10
new_size = 20 new_size = 20
@ -769,9 +770,11 @@ class PoolTestData(StorageObjectTestData):
) )
@response @response
def resp_get_succeed(self, name=None): def resp_get_succeed(self, name=None, id=None):
if not name: if not name:
name = self.pool_name name = self.pool_name
if not id:
id = self.pool_id
return ( return (
'<QueryStatus maxSeverity="ok"/>' '<QueryStatus maxSeverity="ok"/>'
'<StoragePool movers="1 2" memberVolumes="98" storageSystems="1" ' '<StoragePool movers="1 2" memberVolumes="98" storageSystems="1" '
@ -800,7 +803,7 @@ class PoolTestData(StorageObjectTestData):
'potentialAdditionalSize="0" isBackendPool="true"/>' 'potentialAdditionalSize="0" isBackendPool="true"/>'
'</StoragePool>' % '</StoragePool>' %
{'name': name, {'name': name,
'id': self.pool_id, 'id': id,
'pool_used_size': self.pool_used_size, 'pool_used_size': self.pool_used_size,
'pool_total_size': self.pool_total_size} 'pool_total_size': self.pool_total_size}
) )
@ -1404,7 +1407,6 @@ class FakeEMCShareDriver(object):
self.configuration.append_config_values = mock.Mock(return_value=0) self.configuration.append_config_values = mock.Mock(return_value=0)
self.configuration.emc_share_backend = FakeData.emc_share_backend self.configuration.emc_share_backend = FakeData.emc_share_backend
self.configuration.emc_nas_server_container = FakeData.mover_name self.configuration.emc_nas_server_container = FakeData.mover_name
self.configuration.emc_nas_pool_name = FakeData.pool_name
self.configuration.emc_nas_server = FakeData.emc_nas_server self.configuration.emc_nas_server = FakeData.emc_nas_server
self.configuration.emc_nas_login = FakeData.emc_nas_login self.configuration.emc_nas_login = FakeData.emc_nas_login
self.configuration.emc_nas_password = FakeData.emc_nas_password self.configuration.emc_nas_password = FakeData.emc_nas_password
@ -1416,6 +1418,7 @@ CIFS_SHARE = fake_share.fake_share(
size=FakeData.share_size, size=FakeData.share_size,
share_network_id=FakeData.share_network_id, share_network_id=FakeData.share_network_id,
share_server_id=FakeData.share_server_id, share_server_id=FakeData.share_server_id,
host=FakeData.host,
share_proto='CIFS') share_proto='CIFS')
NFS_SHARE = fake_share.fake_share( NFS_SHARE = fake_share.fake_share(
@ -1424,6 +1427,7 @@ NFS_SHARE = fake_share.fake_share(
size=FakeData.share_size, size=FakeData.share_size,
share_network_id=FakeData.share_network_id, share_network_id=FakeData.share_network_id,
share_server_id=FakeData.share_server_id, share_server_id=FakeData.share_server_id,
host=FakeData.host,
share_proto='NFS') share_proto='NFS')
CIFS_RW_ACCESS = fake_share.fake_access( CIFS_RW_ACCESS = fake_share.fake_access(
@ -1500,6 +1504,4 @@ STATS = dict(
share_backend_name='VNX', share_backend_name='VNX',
vendor_name='EMC', vendor_name='EMC',
storage_protocol='NFS_CIFS', storage_protocol='NFS_CIFS',
driver_version='2.0.0,', driver_version='2.0.0,')
total_capacity_gb='unknown',
free_capacity_gb='unknow')

View File

@ -15,12 +15,14 @@
import copy import copy
import ddt
import mock import mock
from oslo_log import log from oslo_log import log
from manila import exception from manila import exception
from manila.share.drivers.emc.plugins.vnx import connection from manila.share.drivers.emc.plugins.vnx import connection
from manila.share.drivers.emc.plugins.vnx import connector from manila.share.drivers.emc.plugins.vnx import connector
from manila.share.drivers.emc.plugins.vnx import object_manager
from manila import test from manila import test
from manila.tests import fake_share from manila.tests import fake_share
from manila.tests.share.drivers.emc.plugins.vnx import fakes from manila.tests.share.drivers.emc.plugins.vnx import fakes
@ -29,17 +31,13 @@ from manila.tests.share.drivers.emc.plugins.vnx import utils
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
@ddt.ddt
class StorageConnectionTestCase(test.TestCase): class StorageConnectionTestCase(test.TestCase):
@mock.patch.object(connector.XMLAPIConnector, "_do_setup", mock.Mock()) @mock.patch.object(connector.XMLAPIConnector, "_do_setup", mock.Mock())
def setUp(self): def setUp(self):
super(StorageConnectionTestCase, self).setUp() super(StorageConnectionTestCase, self).setUp()
self.emc_share_driver = fakes.FakeEMCShareDriver() self.emc_share_driver = fakes.FakeEMCShareDriver()
self.cifs_server_name = fakes.FakeData.vdm_name
self.pool_name = fakes.FakeData.pool_name
self.vdm_name = fakes.FakeData.vdm_name
self.mover_name = fakes.FakeData.mover_name
self.connection = connection.VNXStorageConnection(LOG) self.connection = connection.VNXStorageConnection(LOG)
self.pool = fakes.PoolTestData() self.pool = fakes.PoolTestData()
@ -53,51 +51,91 @@ class StorageConnectionTestCase(test.TestCase):
self.cifs_server = fakes.CIFSServerTestData() self.cifs_server = fakes.CIFSServerTestData()
self.dns = fakes.DNSDomainTestData() self.dns = fakes.DNSDomainTestData()
hook = utils.RequestSideEffect()
hook.append(self.mover.resp_get_ref_succeed())
hook.append(self.pool.resp_get_succeed())
with mock.patch.object(connector.XMLAPIConnector, 'request', with mock.patch.object(connector.XMLAPIConnector, 'request',
mock.Mock(side_effect=hook)): mock.Mock()):
self.connection.connect(self.emc_share_driver, None) self.connection.connect(self.emc_share_driver, None)
expected_calls = [ def test_check_for_setup_error(self):
mock.call(self.mover.req_get_ref()),
mock.call(self.pool.req_get()),
]
connector.XMLAPIConnector.request.assert_has_calls(expected_calls)
@mock.patch.object(connector.XMLAPIConnector, "_do_setup", mock.Mock())
def test_connect_with_invalid_mover_name(self):
hook = utils.RequestSideEffect()
hook.append(self.mover.resp_get_error())
with mock.patch.object(connector.XMLAPIConnector, 'request',
mock.Mock(side_effect=hook)):
self.assertRaises(exception.InvalidParameterValue,
self.connection.connect,
self.emc_share_driver, None)
expected_calls = [mock.call(self.mover.req_get_ref())]
connector.XMLAPIConnector.request.assert_has_calls(expected_calls)
@mock.patch.object(connector.XMLAPIConnector, "_do_setup", mock.Mock())
def test_connect_with_invalid_pool_name(self):
hook = utils.RequestSideEffect() hook = utils.RequestSideEffect()
hook.append(self.mover.resp_get_ref_succeed()) hook.append(self.mover.resp_get_ref_succeed())
xml_req_mock = utils.EMCMock(side_effect=hook)
self.connection.manager.connectors['XML'].request = xml_req_mock
with mock.patch.object(connection.VNXStorageConnection,
'_get_managed_storage_pools',
mock.Mock()):
self.connection.check_for_setup_error()
expected_calls = [mock.call(self.mover.req_get_ref())]
xml_req_mock.assert_has_calls(expected_calls)
def test_check_for_setup_error_with_invalid_mover_name(self):
hook = utils.RequestSideEffect()
hook.append(self.mover.resp_get_error())
xml_req_mock = utils.EMCMock(side_effect=hook)
self.connection.manager.connectors['XML'].request = xml_req_mock
self.assertRaises(exception.InvalidParameterValue,
self.connection.check_for_setup_error)
expected_calls = [mock.call(self.mover.req_get_ref())]
xml_req_mock.assert_has_calls(expected_calls)
@ddt.data({'pool_conf': None,
'real_pools': ['fake_pool', 'nas_pool'],
'matched_pool': set()},
{'pool_conf': '*',
'real_pools': ['fake_pool', 'nas_pool'],
'matched_pool': {'fake_pool', 'nas_pool'}},
{'pool_conf': 'fake_*',
'real_pools': ['fake_pool', 'nas_pool', 'Perf_Pool'],
'matched_pool': {'fake_pool'}},
{'pool_conf': '*pool',
'real_pools': ['fake_pool', 'NAS_Pool', 'Perf_POOL'],
'matched_pool': {'fake_pool'}},
{'pool_conf': 'nas_pool',
'real_pools': ['fake_pool', 'nas_pool', 'perf_pool'],
'matched_pool': {'nas_pool'}})
@ddt.unpack
def test__get_managed_storage_pools(self, pool_conf, real_pools,
matched_pool):
with mock.patch.object(object_manager.StoragePool,
'get_all',
mock.Mock(return_value=('ok', real_pools))):
pool = self.connection._get_managed_storage_pools(pool_conf)
self.assertEqual(matched_pool, pool)
def test__get_managed_storage_pools_failed_to_get_pool_info(self):
hook = utils.RequestSideEffect()
hook.append(self.pool.resp_get_error()) hook.append(self.pool.resp_get_error())
xml_req_mock = utils.EMCMock(side_effect=hook)
self.connection.manager.connectors['XML'].request = xml_req_mock
with mock.patch.object(connector.XMLAPIConnector, 'request', pool_conf = fakes.FakeData.pool_name
mock.Mock(side_effect=hook)): self.assertRaises(exception.EMCVnxXMLAPIError,
self.connection._get_managed_storage_pools,
pool_conf)
expected_calls = [mock.call(self.pool.req_get())]
xml_req_mock.assert_has_calls(expected_calls)
@ddt.data(
{'pool_conf': 'fake_*',
'real_pools': ['nas_pool', 'Perf_Pool']},
{'pool_conf': '*pool',
'real_pools': ['NAS_Pool', 'Perf_POOL']},
{'pool_conf': 'nas_pool',
'real_pools': ['fake_pool', 'perf_pool']},
)
@ddt.unpack
def test__get_managed_storage_pools_without_matched_pool(self, pool_conf,
real_pools):
with mock.patch.object(object_manager.StoragePool,
'get_all',
mock.Mock(return_value=('ok', real_pools))):
self.assertRaises(exception.InvalidParameterValue, self.assertRaises(exception.InvalidParameterValue,
self.connection.connect, self.connection._get_managed_storage_pools,
self.emc_share_driver, None) pool_conf)
expected_calls = [
mock.call(self.mover.req_get_ref()),
mock.call(self.pool.req_get()),
]
connector.XMLAPIConnector.request.assert_has_calls(expected_calls)
def test_create_cifs_share(self): def test_create_cifs_share(self):
share_server = fakes.SHARE_SERVER share_server = fakes.SHARE_SERVER
@ -107,6 +145,7 @@ class StorageConnectionTestCase(test.TestCase):
hook.append(self.vdm.resp_get_succeed()) hook.append(self.vdm.resp_get_succeed())
hook.append(self.cifs_server.resp_get_succeed( hook.append(self.cifs_server.resp_get_succeed(
mover_id=self.vdm.vdm_id, is_vdm=True, join_domain=True)) mover_id=self.vdm.vdm_id, is_vdm=True, join_domain=True))
hook.append(self.pool.resp_get_succeed())
hook.append(self.fs.resp_task_succeed()) hook.append(self.fs.resp_task_succeed())
hook.append(self.cifs_share.resp_task_succeed()) hook.append(self.cifs_share.resp_task_succeed())
xml_req_mock = utils.EMCMock(side_effect=hook) xml_req_mock = utils.EMCMock(side_effect=hook)
@ -122,6 +161,7 @@ class StorageConnectionTestCase(test.TestCase):
expected_calls = [ expected_calls = [
mock.call(self.vdm.req_get()), mock.call(self.vdm.req_get()),
mock.call(self.cifs_server.req_get(self.vdm.vdm_id)), mock.call(self.cifs_server.req_get(self.vdm.vdm_id)),
mock.call(self.pool.req_get()),
mock.call(self.fs.req_create_on_vdm()), mock.call(self.fs.req_create_on_vdm()),
mock.call(self.cifs_share.req_create(self.vdm.vdm_id)), mock.call(self.cifs_share.req_create(self.vdm.vdm_id)),
] ]
@ -138,6 +178,7 @@ class StorageConnectionTestCase(test.TestCase):
share = fakes.NFS_SHARE share = fakes.NFS_SHARE
hook = utils.RequestSideEffect() hook = utils.RequestSideEffect()
hook.append(self.pool.resp_get_succeed())
hook.append(self.vdm.resp_get_succeed()) hook.append(self.vdm.resp_get_succeed())
hook.append(self.fs.resp_task_succeed()) hook.append(self.fs.resp_task_succeed())
xml_req_mock = utils.EMCMock(side_effect=hook) xml_req_mock = utils.EMCMock(side_effect=hook)
@ -151,6 +192,7 @@ class StorageConnectionTestCase(test.TestCase):
location = self.connection.create_share(None, share, share_server) location = self.connection.create_share(None, share, share_server)
expected_calls = [ expected_calls = [
mock.call(self.pool.req_get()),
mock.call(self.vdm.req_get()), mock.call(self.vdm.req_get()),
mock.call(self.fs.req_create_on_vdm()), mock.call(self.fs.req_create_on_vdm()),
] ]
@ -206,6 +248,7 @@ class StorageConnectionTestCase(test.TestCase):
hook.append(self.vdm.resp_get_succeed()) hook.append(self.vdm.resp_get_succeed())
hook.append(self.cifs_server.resp_get_without_interface( hook.append(self.cifs_server.resp_get_without_interface(
mover_id=self.vdm.vdm_id, is_vdm=True, join_domain=True)) mover_id=self.vdm.vdm_id, is_vdm=True, join_domain=True))
hook.append(self.pool.resp_get_succeed())
hook.append(self.fs.resp_task_succeed()) hook.append(self.fs.resp_task_succeed())
xml_req_mock = utils.EMCMock(side_effect=hook) xml_req_mock = utils.EMCMock(side_effect=hook)
self.connection.manager.connectors['XML'].request = xml_req_mock self.connection.manager.connectors['XML'].request = xml_req_mock
@ -217,11 +260,21 @@ class StorageConnectionTestCase(test.TestCase):
expected_calls = [ expected_calls = [
mock.call(self.vdm.req_get()), mock.call(self.vdm.req_get()),
mock.call(self.cifs_server.req_get(self.vdm.vdm_id)), mock.call(self.cifs_server.req_get(self.vdm.vdm_id)),
mock.call(self.pool.req_get()),
mock.call(self.fs.req_create_on_vdm()), mock.call(self.fs.req_create_on_vdm()),
] ]
xml_req_mock.assert_has_calls(expected_calls) xml_req_mock.assert_has_calls(expected_calls)
def test_create_cifs_share_without_pool_name(self):
share_server = fakes.SHARE_SERVER
share = fake_share.fake_share(host='HostA@BackendB',
share_proto='CIFS')
self.assertRaises(exception.InvalidHost,
self.connection.create_share,
None, share, share_server)
def test_create_cifs_share_from_snapshot(self): def test_create_cifs_share_from_snapshot(self):
share_server = fakes.SHARE_SERVER share_server = fakes.SHARE_SERVER
share = fakes.CIFS_SHARE share = fakes.CIFS_SHARE
@ -348,6 +401,16 @@ class StorageConnectionTestCase(test.TestCase):
self.connection.create_share_from_snapshot, self.connection.create_share_from_snapshot,
None, share, snapshot, share_server) None, share, snapshot, share_server)
def test_create_share_from_snapshot_without_pool_name(self):
share_server = fakes.SHARE_SERVER
share = fake_share.fake_share(host='HostA@BackendB',
share_proto='CIFS')
snapshot = fake_share.fake_snapshot()
self.assertRaises(exception.InvalidHost,
self.connection.create_share_from_snapshot,
None, share, snapshot, share_server)
def test_delete_cifs_share(self): def test_delete_cifs_share(self):
share_server = fakes.SHARE_SERVER share_server = fakes.SHARE_SERVER
share = fakes.CIFS_SHARE share = fakes.CIFS_SHARE
@ -458,8 +521,8 @@ class StorageConnectionTestCase(test.TestCase):
hook = utils.RequestSideEffect() hook = utils.RequestSideEffect()
hook.append(self.fs.resp_get_succeed()) hook.append(self.fs.resp_get_succeed())
hook.append(self.pool.resp_get_succeed())
hook.append(self.fs.resp_task_succeed()) hook.append(self.fs.resp_task_succeed())
xml_req_mock = utils.EMCMock(side_effect=hook) xml_req_mock = utils.EMCMock(side_effect=hook)
self.connection.manager.connectors['XML'].request = xml_req_mock self.connection.manager.connectors['XML'].request = xml_req_mock
@ -467,10 +530,21 @@ class StorageConnectionTestCase(test.TestCase):
expected_calls = [ expected_calls = [
mock.call(self.fs.req_get()), mock.call(self.fs.req_get()),
mock.call(self.pool.req_get()),
mock.call(self.fs.req_extend()), mock.call(self.fs.req_extend()),
] ]
xml_req_mock.assert_has_calls(expected_calls) xml_req_mock.assert_has_calls(expected_calls)
def test_extend_share_without_pool_name(self):
share_server = fakes.SHARE_SERVER
share = fake_share.fake_share(host='HostA@BackendB',
share_proto='CIFS')
new_size = fakes.FakeData.new_size
self.assertRaises(exception.InvalidHost,
self.connection.extend_share,
share, new_size, share_server)
def test_create_snapshot(self): def test_create_snapshot(self):
share_server = fakes.SHARE_SERVER share_server = fakes.SHARE_SERVER
snapshot = fake_share.fake_snapshot( snapshot = fake_share.fake_snapshot(
@ -492,6 +566,25 @@ class StorageConnectionTestCase(test.TestCase):
] ]
xml_req_mock.assert_has_calls(expected_calls) xml_req_mock.assert_has_calls(expected_calls)
def test_create_snapshot_with_incorrect_share_info(self):
share_server = fakes.SHARE_SERVER
snapshot = fake_share.fake_snapshot(
id=fakes.FakeData.snapshot_name,
share_id=fakes.FakeData.filesystem_name,
share_name=fakes.FakeData.share_name)
hook = utils.RequestSideEffect()
hook.append(self.fs.resp_get_but_not_found())
xml_req_mock = utils.EMCMock(side_effect=hook)
self.connection.manager.connectors['XML'].request = xml_req_mock
self.assertRaises(exception.EMCVnxXMLAPIError,
self.connection.create_snapshot,
None, snapshot, share_server)
expected_calls = [mock.call(self.fs.req_get())]
xml_req_mock.assert_has_calls(expected_calls)
def test_delete_snapshot(self): def test_delete_snapshot(self):
share_server = fakes.SHARE_SERVER share_server = fakes.SHARE_SERVER
snapshot = fake_share.fake_snapshot( snapshot = fake_share.fake_snapshot(
@ -516,6 +609,7 @@ class StorageConnectionTestCase(test.TestCase):
def test_setup_server(self): def test_setup_server(self):
hook = utils.RequestSideEffect() hook = utils.RequestSideEffect()
hook.append(self.vdm.resp_get_but_not_found()) hook.append(self.vdm.resp_get_but_not_found())
hook.append(self.mover.resp_get_ref_succeed())
hook.append(self.vdm.resp_task_succeed()) hook.append(self.vdm.resp_task_succeed())
hook.append(self.mover.resp_task_succeed()) hook.append(self.mover.resp_task_succeed())
hook.append(self.mover.resp_task_succeed()) hook.append(self.mover.resp_task_succeed())
@ -538,6 +632,7 @@ class StorageConnectionTestCase(test.TestCase):
expected_calls = [ expected_calls = [
mock.call(self.vdm.req_get()), mock.call(self.vdm.req_get()),
mock.call(self.mover.req_get_ref()),
mock.call(self.vdm.req_create()), mock.call(self.vdm.req_create()),
mock.call(self.mover.req_create_interface( mock.call(self.mover.req_create_interface(
if_name=if_name_1, if_name=if_name_1,
@ -560,6 +655,7 @@ class StorageConnectionTestCase(test.TestCase):
def test_setup_server_with_existing_vdm(self): def test_setup_server_with_existing_vdm(self):
hook = utils.RequestSideEffect() hook = utils.RequestSideEffect()
hook.append(self.vdm.resp_get_succeed()) hook.append(self.vdm.resp_get_succeed())
hook.append(self.mover.resp_get_ref_succeed())
hook.append(self.mover.resp_task_succeed()) hook.append(self.mover.resp_task_succeed())
hook.append(self.mover.resp_task_succeed()) hook.append(self.mover.resp_task_succeed())
hook.append(self.dns.resp_task_succeed()) hook.append(self.dns.resp_task_succeed())
@ -580,6 +676,7 @@ class StorageConnectionTestCase(test.TestCase):
expected_calls = [ expected_calls = [
mock.call(self.vdm.req_get()), mock.call(self.vdm.req_get()),
mock.call(self.mover.req_get_ref()),
mock.call(self.mover.req_create_interface( mock.call(self.mover.req_create_interface(
if_name=if_name_1, if_name=if_name_1,
ip=fakes.FakeData.network_allocations_ip1)), ip=fakes.FakeData.network_allocations_ip1)),
@ -608,6 +705,7 @@ class StorageConnectionTestCase(test.TestCase):
def test_setup_server_without_valid_physical_device(self): def test_setup_server_without_valid_physical_device(self):
hook = utils.RequestSideEffect() hook = utils.RequestSideEffect()
hook.append(self.vdm.resp_get_but_not_found()) hook.append(self.vdm.resp_get_but_not_found())
hook.append(self.mover.resp_get_ref_succeed())
hook.append(self.vdm.resp_task_succeed()) hook.append(self.vdm.resp_task_succeed())
hook.append(self.vdm.resp_get_succeed()) hook.append(self.vdm.resp_get_succeed())
hook.append(self.cifs_server.resp_get_without_value()) hook.append(self.cifs_server.resp_get_without_value())
@ -627,6 +725,7 @@ class StorageConnectionTestCase(test.TestCase):
expected_calls = [ expected_calls = [
mock.call(self.vdm.req_get()), mock.call(self.vdm.req_get()),
mock.call(self.mover.req_get_ref()),
mock.call(self.vdm.req_create()), mock.call(self.vdm.req_create()),
mock.call(self.vdm.req_get()), mock.call(self.vdm.req_get()),
mock.call(self.cifs_server.req_get(self.vdm.vdm_id)), mock.call(self.cifs_server.req_get(self.vdm.vdm_id)),
@ -643,6 +742,7 @@ class StorageConnectionTestCase(test.TestCase):
def test_setup_server_with_exception(self): def test_setup_server_with_exception(self):
hook = utils.RequestSideEffect() hook = utils.RequestSideEffect()
hook.append(self.vdm.resp_get_but_not_found()) hook.append(self.vdm.resp_get_but_not_found())
hook.append(self.mover.resp_get_ref_succeed())
hook.append(self.vdm.resp_task_succeed()) hook.append(self.vdm.resp_task_succeed())
hook.append(self.mover.resp_task_succeed()) hook.append(self.mover.resp_task_succeed())
hook.append(self.mover.resp_task_error()) hook.append(self.mover.resp_task_error())
@ -668,6 +768,7 @@ class StorageConnectionTestCase(test.TestCase):
expected_calls = [ expected_calls = [
mock.call(self.vdm.req_get()), mock.call(self.vdm.req_get()),
mock.call(self.mover.req_get_ref()),
mock.call(self.vdm.req_create()), mock.call(self.vdm.req_create()),
mock.call(self.mover.req_create_interface( mock.call(self.mover.req_create_interface(
if_name=if_name_1, if_name=if_name_1,
@ -697,6 +798,7 @@ class StorageConnectionTestCase(test.TestCase):
hook.append(self.cifs_server.resp_task_succeed()) hook.append(self.cifs_server.resp_task_succeed())
hook.append(self.cifs_server.resp_get_succeed( hook.append(self.cifs_server.resp_get_succeed(
mover_id=self.vdm.vdm_id, is_vdm=True, join_domain=False)) mover_id=self.vdm.vdm_id, is_vdm=True, join_domain=False))
hook.append(self.mover.resp_get_ref_succeed())
hook.append(self.mover.resp_task_succeed()) hook.append(self.mover.resp_task_succeed())
hook.append(self.mover.resp_task_succeed()) hook.append(self.mover.resp_task_succeed())
hook.append(self.vdm.resp_task_succeed()) hook.append(self.vdm.resp_task_succeed())
@ -718,6 +820,7 @@ class StorageConnectionTestCase(test.TestCase):
mock.call(self.cifs_server.req_modify( mock.call(self.cifs_server.req_modify(
mover_id=self.vdm.vdm_id, is_vdm=True, join_domain=False)), mover_id=self.vdm.vdm_id, is_vdm=True, join_domain=False)),
mock.call(self.cifs_server.req_delete(self.vdm.vdm_id)), mock.call(self.cifs_server.req_delete(self.vdm.vdm_id)),
mock.call(self.mover.req_get_ref()),
mock.call(self.mover.req_delete_interface( mock.call(self.mover.req_delete_interface(
fakes.FakeData.network_allocations_ip1)), fakes.FakeData.network_allocations_ip1)),
mock.call(self.mover.req_delete_interface( mock.call(self.mover.req_delete_interface(
@ -738,6 +841,7 @@ class StorageConnectionTestCase(test.TestCase):
def test_teardown_server_without_security_services(self): def test_teardown_server_without_security_services(self):
hook = utils.RequestSideEffect() hook = utils.RequestSideEffect()
hook.append(self.vdm.resp_get_succeed()) hook.append(self.vdm.resp_get_succeed())
hook.append(self.mover.resp_get_ref_succeed())
hook.append(self.mover.resp_task_succeed()) hook.append(self.mover.resp_task_succeed())
hook.append(self.mover.resp_task_succeed()) hook.append(self.mover.resp_task_succeed())
hook.append(self.vdm.resp_task_succeed()) hook.append(self.vdm.resp_task_succeed())
@ -754,6 +858,7 @@ class StorageConnectionTestCase(test.TestCase):
expected_calls = [ expected_calls = [
mock.call(self.vdm.req_get()), mock.call(self.vdm.req_get()),
mock.call(self.mover.req_get_ref()),
mock.call(self.mover.req_delete_interface( mock.call(self.mover.req_delete_interface(
fakes.FakeData.network_allocations_ip1)), fakes.FakeData.network_allocations_ip1)),
mock.call(self.mover.req_delete_interface( mock.call(self.mover.req_delete_interface(
@ -791,6 +896,7 @@ class StorageConnectionTestCase(test.TestCase):
hook = utils.RequestSideEffect() hook = utils.RequestSideEffect()
hook.append(self.vdm.resp_get_succeed()) hook.append(self.vdm.resp_get_succeed())
hook.append(self.cifs_server.resp_get_error()) hook.append(self.cifs_server.resp_get_error())
hook.append(self.mover.resp_get_ref_succeed())
hook.append(self.cifs_server.resp_task_succeed()) hook.append(self.cifs_server.resp_task_succeed())
hook.append(self.cifs_server.resp_get_succeed( hook.append(self.cifs_server.resp_get_succeed(
mover_id=self.vdm.vdm_id, is_vdm=True, join_domain=False)) mover_id=self.vdm.vdm_id, is_vdm=True, join_domain=False))
@ -812,6 +918,7 @@ class StorageConnectionTestCase(test.TestCase):
expected_calls = [ expected_calls = [
mock.call(self.vdm.req_get()), mock.call(self.vdm.req_get()),
mock.call(self.cifs_server.req_get(self.vdm.vdm_id)), mock.call(self.cifs_server.req_get(self.vdm.vdm_id)),
mock.call(self.mover.req_get_ref()),
mock.call(self.mover.req_delete_interface( mock.call(self.mover.req_delete_interface(
fakes.FakeData.network_allocations_ip1)), fakes.FakeData.network_allocations_ip1)),
mock.call(self.mover.req_delete_interface( mock.call(self.mover.req_delete_interface(
@ -833,6 +940,7 @@ class StorageConnectionTestCase(test.TestCase):
mover_id=self.vdm.vdm_id, is_vdm=True, join_domain=True)) mover_id=self.vdm.vdm_id, is_vdm=True, join_domain=True))
hook.append(self.cifs_server.resp_task_error()) hook.append(self.cifs_server.resp_task_error())
hook.append(self.cifs_server.resp_task_succeed()) hook.append(self.cifs_server.resp_task_succeed())
hook.append(self.mover.resp_get_ref_succeed())
hook.append(self.mover.resp_task_succeed()) hook.append(self.mover.resp_task_succeed())
hook.append(self.mover.resp_task_succeed()) hook.append(self.mover.resp_task_succeed())
hook.append(self.vdm.resp_task_succeed()) hook.append(self.vdm.resp_task_succeed())
@ -853,6 +961,7 @@ class StorageConnectionTestCase(test.TestCase):
mock.call(self.cifs_server.req_get(self.vdm.vdm_id)), mock.call(self.cifs_server.req_get(self.vdm.vdm_id)),
mock.call(self.cifs_server.req_modify(self.vdm.vdm_id)), mock.call(self.cifs_server.req_modify(self.vdm.vdm_id)),
mock.call(self.cifs_server.req_delete(self.vdm.vdm_id)), mock.call(self.cifs_server.req_delete(self.vdm.vdm_id)),
mock.call(self.mover.req_get_ref()),
mock.call(self.mover.req_delete_interface( mock.call(self.mover.req_delete_interface(
fakes.FakeData.network_allocations_ip1)), fakes.FakeData.network_allocations_ip1)),
mock.call(self.mover.req_delete_interface( mock.call(self.mover.req_delete_interface(
@ -1198,9 +1307,103 @@ class StorageConnectionTestCase(test.TestCase):
] ]
xml_req_mock.assert_has_calls(expected_calls) xml_req_mock.assert_has_calls(expected_calls)
self.assertEqual(fakes.FakeData.pool_total_size, for pool in fakes.STATS['pools']:
fakes.STATS['total_capacity_gb']) if pool['pool_name'] == fakes.FakeData.pool_name:
self.assertEqual(fakes.FakeData.pool_total_size,
pool['total_capacity_gb'])
free_size = (fakes.FakeData.pool_total_size - free_size = (fakes.FakeData.pool_total_size -
fakes.FakeData.pool_used_size) fakes.FakeData.pool_used_size)
self.assertEqual(free_size, fakes.STATS['free_capacity_gb']) self.assertEqual(free_size, pool['free_capacity_gb'])
def test_update_share_stats_without_matched_config_pools(self):
self.connection.pools = set('fake_pool')
hook = utils.RequestSideEffect()
hook.append(self.mover.resp_get_ref_succeed())
hook.append(self.pool.resp_get_succeed())
xml_req_mock = utils.EMCMock(side_effect=hook)
self.connection.manager.connectors['XML'].request = xml_req_mock
self.assertRaises(exception.EMCVnxXMLAPIError,
self.connection.update_share_stats,
fakes.STATS)
expected_calls = [
mock.call(self.mover.req_get_ref()),
mock.call(self.pool.req_get()),
]
xml_req_mock.assert_has_calls(expected_calls)
def test_get_pool(self):
share = fakes.CIFS_SHARE
hook = utils.RequestSideEffect()
hook.append(self.fs.resp_get_succeed())
hook.append(self.pool.resp_get_succeed())
xml_req_mock = utils.EMCMock(side_effect=hook)
self.connection.manager.connectors['XML'].request = xml_req_mock
pool_name = self.connection.get_pool(share)
expected_calls = [
mock.call(self.fs.req_get()),
mock.call(self.pool.req_get()),
]
xml_req_mock.assert_has_calls(expected_calls)
self.assertEqual(fakes.FakeData.pool_name, pool_name)
def test_get_pool_failed_to_get_filesystem_info(self):
share = fakes.CIFS_SHARE
hook = utils.RequestSideEffect()
hook.append(self.fs.resp_get_error())
xml_req_mock = utils.EMCMock(side_effect=hook)
self.connection.manager.connectors['XML'].request = xml_req_mock
self.assertRaises(exception.EMCVnxXMLAPIError,
self.connection.get_pool,
share)
expected_calls = [mock.call(self.fs.req_get())]
xml_req_mock.assert_has_calls(expected_calls)
def test_get_pool_failed_to_get_pool_info(self):
share = fakes.CIFS_SHARE
hook = utils.RequestSideEffect()
hook.append(self.fs.resp_get_succeed())
hook.append(self.pool.resp_get_error())
xml_req_mock = utils.EMCMock(side_effect=hook)
self.connection.manager.connectors['XML'].request = xml_req_mock
self.assertRaises(exception.EMCVnxXMLAPIError,
self.connection.get_pool,
share)
expected_calls = [
mock.call(self.fs.req_get()),
mock.call(self.pool.req_get()),
]
xml_req_mock.assert_has_calls(expected_calls)
def test_get_pool_failed_to_find_matched_pool_name(self):
share = fakes.CIFS_SHARE
hook = utils.RequestSideEffect()
hook.append(self.fs.resp_get_succeed())
hook.append(self.pool.resp_get_succeed(name='unmatch_pool_name',
id='unmatch_pool_id'))
xml_req_mock = utils.EMCMock(side_effect=hook)
self.connection.manager.connectors['XML'].request = xml_req_mock
self.assertRaises(exception.EMCVnxXMLAPIError,
self.connection.get_pool,
share)
expected_calls = [
mock.call(self.fs.req_get()),
mock.call(self.pool.req_get()),
]
xml_req_mock.assert_has_calls(expected_calls)

View File

@ -1338,7 +1338,6 @@ class SnapshotTestCase(StorageObjectTestCase):
def test_create_snapshot(self): def test_create_snapshot(self):
self.hook.append(self.fs.resp_get_succeed()) self.hook.append(self.fs.resp_get_succeed())
self.hook.append(self.pool.resp_get_succeed())
self.hook.append(self.snap.resp_task_succeed()) self.hook.append(self.snap.resp_task_succeed())
context = self.manager.getStorageContext('Snapshot') context = self.manager.getStorageContext('Snapshot')
@ -1346,18 +1345,16 @@ class SnapshotTestCase(StorageObjectTestCase):
context.create(name=self.snap.snapshot_name, context.create(name=self.snap.snapshot_name,
fs_name=self.fs.filesystem_name, fs_name=self.fs.filesystem_name,
pool_name=self.pool.pool_name) pool_id=self.pool.pool_id)
expected_calls = [ expected_calls = [
mock.call(self.fs.req_get()), mock.call(self.fs.req_get()),
mock.call(self.pool.req_get()),
mock.call(self.snap.req_create()), mock.call(self.snap.req_create()),
] ]
context.conn['XML'].request.assert_has_calls(expected_calls) context.conn['XML'].request.assert_has_calls(expected_calls)
def test_create_snapshot_but_already_exist(self): def test_create_snapshot_but_already_exist(self):
self.hook.append(self.fs.resp_get_succeed()) self.hook.append(self.fs.resp_get_succeed())
self.hook.append(self.pool.resp_get_succeed())
self.hook.append(self.snap.resp_create_but_already_exist()) self.hook.append(self.snap.resp_create_but_already_exist())
context = self.manager.getStorageContext('Snapshot') context = self.manager.getStorageContext('Snapshot')
@ -1365,19 +1362,17 @@ class SnapshotTestCase(StorageObjectTestCase):
context.create(name=self.snap.snapshot_name, context.create(name=self.snap.snapshot_name,
fs_name=self.fs.filesystem_name, fs_name=self.fs.filesystem_name,
pool_name=self.pool.pool_name, pool_id=self.pool.pool_id,
ckpt_size=self.snap.snapshot_size) ckpt_size=self.snap.snapshot_size)
expected_calls = [ expected_calls = [
mock.call(self.fs.req_get()), mock.call(self.fs.req_get()),
mock.call(self.pool.req_get()),
mock.call(self.snap.req_create_with_size()), mock.call(self.snap.req_create_with_size()),
] ]
context.conn['XML'].request.assert_has_calls(expected_calls) context.conn['XML'].request.assert_has_calls(expected_calls)
def test_create_snapshot_with_error(self): def test_create_snapshot_with_error(self):
self.hook.append(self.fs.resp_get_succeed()) self.hook.append(self.fs.resp_get_succeed())
self.hook.append(self.pool.resp_get_succeed())
self.hook.append(self.snap.resp_task_error()) self.hook.append(self.snap.resp_task_error())
context = self.manager.getStorageContext('Snapshot') context = self.manager.getStorageContext('Snapshot')
@ -1387,12 +1382,11 @@ class SnapshotTestCase(StorageObjectTestCase):
context.create, context.create,
name=self.snap.snapshot_name, name=self.snap.snapshot_name,
fs_name=self.fs.filesystem_name, fs_name=self.fs.filesystem_name,
pool_name=self.pool.pool_name, pool_id=self.pool.pool_id,
ckpt_size=self.snap.snapshot_size) ckpt_size=self.snap.snapshot_size)
expected_calls = [ expected_calls = [
mock.call(self.fs.req_get()), mock.call(self.fs.req_get()),
mock.call(self.pool.req_get()),
mock.call(self.snap.req_create_with_size()), mock.call(self.snap.req_create_with_size()),
] ]
context.conn['XML'].request.assert_has_calls(expected_calls) context.conn['XML'].request.assert_has_calls(expected_calls)