Merge "EMC VNX: Add multi-pools support"
This commit is contained in:
commit
940531512f
@ -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."""
|
||||||
|
@ -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(
|
||||||
|
@ -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."""
|
||||||
|
@ -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,
|
||||||
|
@ -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')
|
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user