HP 3PAR use one filestore per tenant

Using one filestore per tenant allows more shares to be
created on an array.  The original behavior of one filestore
per share can still be used with the hp3par_fstore_per_share=True
configuration (default is False).

Change-Id: I17a8ee138eef0157819ea33c74a43c30ee644817
Implements: blueprint hp3par-filestore-per-tenant
This commit is contained in:
Mark Sturdevant 2015-02-27 01:12:02 -08:00
parent ca582354ed
commit b3aee0a201
5 changed files with 654 additions and 210 deletions

View File

@ -59,6 +59,9 @@ HP3PAR_OPTS = [
cfg.StrOpt('hp3par_share_ip_address',
default='',
help="The IP address for shares not using a share server"),
cfg.BoolOpt('hp3par_fstore_per_share',
default=False,
help="Use one filestore per share"),
cfg.BoolOpt('hp3par_debug',
default=False,
help="Enable HTTP debugging to 3PAR"),
@ -105,6 +108,7 @@ class HP3ParShareDriver(driver.ShareDriver):
hp3par_san_login=self.configuration.hp3par_san_login,
hp3par_san_password=self.configuration.hp3par_san_password,
hp3par_san_ssh_port=self.configuration.hp3par_san_ssh_port,
hp3par_fstore_per_share=self.configuration.hp3par_fstore_per_share,
ssh_conn_timeout=self.configuration.ssh_conn_timeout,
)
@ -170,6 +174,7 @@ class HP3ParShareDriver(driver.ShareDriver):
protocol = share['share_proto']
path = self._hp3par.create_share(
share['project_id'],
share['id'],
protocol,
self.fpg, self.vfs,
@ -188,7 +193,9 @@ class HP3ParShareDriver(driver.ShareDriver):
path = self._hp3par.create_share_from_snapshot(
share['id'],
protocol,
snapshot['share']['project_id'],
snapshot['share']['id'],
snapshot['share']['share_proto'],
snapshot['id'],
self.fpg,
self.vfs
@ -199,7 +206,8 @@ class HP3ParShareDriver(driver.ShareDriver):
def delete_share(self, context, share, share_server=None):
"""Deletes share and its fstore."""
self._hp3par.delete_share(share['id'],
self._hp3par.delete_share(share['project_id'],
share['id'],
share['share_proto'],
self.fpg,
self.vfs)
@ -207,7 +215,9 @@ class HP3ParShareDriver(driver.ShareDriver):
def create_snapshot(self, context, snapshot, share_server=None):
"""Creates a snapshot of a share."""
self._hp3par.create_snapshot(snapshot['share']['id'],
self._hp3par.create_snapshot(snapshot['share']['project_id'],
snapshot['share']['id'],
snapshot['share']['share_proto'],
snapshot['id'],
self.fpg,
self.vfs)
@ -215,7 +225,9 @@ class HP3ParShareDriver(driver.ShareDriver):
def delete_snapshot(self, context, snapshot, share_server=None):
"""Deletes a snapshot of a share."""
self._hp3par.delete_snapshot(snapshot['share']['id'],
self._hp3par.delete_snapshot(snapshot['share']['project_id'],
snapshot['share']['id'],
snapshot['share']['share_proto'],
snapshot['id'],
self.fpg,
self.vfs)
@ -225,7 +237,8 @@ class HP3ParShareDriver(driver.ShareDriver):
def allow_access(self, context, share, access, share_server=None):
"""Allow access to the share."""
self._hp3par.allow_access(share['id'],
self._hp3par.allow_access(share['project_id'],
share['id'],
share['share_proto'],
access['access_type'],
access['access_to'],
@ -234,7 +247,8 @@ class HP3ParShareDriver(driver.ShareDriver):
def deny_access(self, context, share, access, share_server=None):
"""Deny access to the share."""
self._hp3par.deny_access(share['id'],
self._hp3par.deny_access(share['project_id'],
share['id'],
share['share_proto'],
access['access_type'],
access['access_to'],

View File

@ -24,7 +24,6 @@ import six
from manila import exception
from manila.i18n import _
from manila.i18n import _LI
from manila.openstack.common import log as logging
hp3parclient = importutils.try_import("hp3parclient")
@ -51,6 +50,7 @@ class HP3ParMediator(object):
self.hp3par_san_password = kwargs.get('hp3par_san_password')
self.hp3par_san_ssh_port = kwargs.get('hp3par_san_ssh_port')
self.hp3par_san_private_key = kwargs.get('hp3par_san_private_key')
self.hp3par_fstore_per_share = kwargs.get('hp3par_fstore_per_share')
self.ssh_conn_timeout = kwargs.get('ssh_conn_timeout')
self._client = None
@ -132,13 +132,22 @@ class HP3ParMediator(object):
return protocol
@staticmethod
def ensure_prefix(id):
if id.startswith('osf-'):
return id
else:
return 'osf-%s' % id
def other_protocol(share_proto):
"""Given 'nfs' or 'smb' (or equivalent) return the other one."""
protocol = HP3ParMediator.ensure_supported_protocol(share_proto)
return 'nfs' if protocol == 'smb' else 'smb'
def create_share(self, share_id, share_proto, fpg, vfs,
@staticmethod
def ensure_prefix(uid, protocol=None):
if uid.startswith('osf-'):
return uid
elif protocol:
return 'osf-%s-%s' % (
HP3ParMediator.ensure_supported_protocol(protocol), uid)
else:
return 'osf-%s' % uid
def create_share(self, project_id, share_id, share_proto, fpg, vfs,
fstore=None, sharedir=None, readonly=False, size=None):
"""Create the share and return its path.
@ -146,6 +155,7 @@ class HP3ParMediator(object):
called locally from create_share_from_snapshot(). The optional
parameters allow re-use.
:param project_id: The tenant ID.
:param share_id: The share-id with or without osf- prefix.
:param share_proto: The protocol (to map to smb or nfs)
:param fpg: The file provisioning group
@ -162,7 +172,11 @@ class HP3ParMediator(object):
share_name = self.ensure_prefix(share_id)
if not fstore:
fstore = share_name
if self.hp3par_fstore_per_share:
fstore = share_name
else:
fstore = self.ensure_prefix(project_id, protocol)
try:
result = self._client.createfstore(
vfs, fstore, fpg=fpg,
@ -175,11 +189,26 @@ class HP3ParMediator(object):
raise exception.ShareBackendException(msg)
if size:
if self.hp3par_fstore_per_share:
hcapacity = six.text_type(size * units.Ki)
scapacity = hcapacity
else:
hard_size_mb = size * units.Ki
soft_size_mb = hard_size_mb
result = self._client.getfsquota(
fpg=fpg, vfs=vfs, fstore=fstore)
LOG.debug("getfsquota result=%s", result)
quotas = result['members']
if len(quotas) == 1:
hard_size_mb += int(quotas[0].get('hardBlock', '0'))
soft_size_mb += int(quotas[0].get('softBlock', '0'))
hcapacity = six.text_type(hard_size_mb)
scapacity = six.text_type(soft_size_mb)
try:
size_str = six.text_type(size)
result = self._client.setfsquota(
vfs, fpg=fpg, fstore=fstore,
scapacity=size_str, hcapacity=size_str)
scapacity=scapacity, hcapacity=hcapacity)
LOG.debug("setfsquota result=%s", result)
except Exception as e:
msg = (_('Failed to setfsquota on %(fstore)s: %(e)s') %
@ -187,6 +216,9 @@ class HP3ParMediator(object):
LOG.exception(msg)
raise exception.ShareBackendException(msg)
if not (sharedir or self.hp3par_fstore_per_share):
sharedir = share_name
try:
if protocol == 'nfs':
if readonly:
@ -239,30 +271,45 @@ class HP3ParMediator(object):
else:
return result['members'][0]['shareName']
def create_share_from_snapshot(self, share_id, share_proto, orig_share_id,
def create_share_from_snapshot(self, share_id, share_proto,
orig_project_id, orig_share_id, orig_proto,
snapshot_id, fpg, vfs):
share_name = self.ensure_prefix(share_id)
orig_share_name = self.ensure_prefix(orig_share_id)
fstore = orig_share_name
protocol = self.ensure_supported_protocol(share_proto)
snapshot_tag = self.ensure_prefix(snapshot_id)
snapshots = self.get_snapshots(fstore, snapshot_tag, fpg, vfs)
orig_share_name = self.ensure_prefix(orig_share_id)
if len(snapshots) != 1:
snapshot = self._find_fsnap(orig_project_id,
orig_share_name,
orig_proto,
snapshot_tag,
fpg,
vfs)
if not snapshot:
msg = (_('Failed to create share from snapshot for '
'FPG/VFS/fstore/tag %(fpg)s/%(vfs)s/%(fstore)s/%(tag)s.'
' Expected to find 1 snapshot, found %(count)s.') %
{'fpg': fpg, 'vfs': vfs, 'fstore': fstore,
'tag': snapshot_tag, 'count': len(snapshots)})
'FPG/VFS/tag %(fpg)s/%(vfs)s/%(tag)s. '
'Snapshot not found.') %
{
'fpg': fpg,
'vfs': vfs,
'tag': snapshot_tag})
LOG.exception(msg)
raise exception.ShareBackendException(msg)
snapshot = snapshots[0]
sharedir = '.snapshot/%s' % snapshot['snapName']
fstore = snapshot['fstoreName']
share_name = self.ensure_prefix(share_id)
if fstore == orig_share_name:
# No subdir for original share created with fstore_per_share
sharedir = '.snapshot/%s' % snapshot['snapName']
else:
sharedir = '.snapshot/%s/%s' % (snapshot['snapName'],
orig_share_name)
return self.create_share(
orig_project_id,
share_name,
share_proto,
protocol,
fpg,
vfs,
fstore=fstore,
@ -270,11 +317,12 @@ class HP3ParMediator(object):
readonly=True,
)
def delete_share(self, share_id, share_proto, fpg, vfs):
def delete_share(self, project_id, share_id, share_proto, fpg, vfs):
share_name = self.ensure_prefix(share_id)
fstore = self.get_fstore(share_id, share_proto, fpg, vfs)
protocol = self.ensure_supported_protocol(share_proto)
share_name = self.ensure_prefix(share_id)
fstore = self._find_fstore(project_id, share_name, protocol, fpg, vfs,
allow_cross_protocol=True)
if not fstore:
# Share does not exist.
@ -289,13 +337,14 @@ class HP3ParMediator(object):
LOG.exception(msg)
raise exception.ShareBackendException(message=msg)
try:
self._client.removefstore(vfs, fstore, fpg=fpg)
except Exception as e:
msg = (_('Failed to remove fstore %(fstore)s: %(e)s') %
{'fstore': fstore, 'e': six.text_type(e)})
LOG.exception(msg)
raise exception.ShareBackendException(message=msg)
if fstore == share_name:
try:
self._client.removefstore(vfs, fstore, fpg=fpg)
except Exception as e:
msg = (_('Failed to remove fstore %(fstore)s: %(e)s') %
{'fstore': fstore, 'e': six.text_type(e)})
LOG.exception(msg)
raise exception.ShareBackendException(message=msg)
def get_vfs_name(self, fpg):
return self.get_vfs(fpg)['vfsname']
@ -331,10 +380,33 @@ class HP3ParMediator(object):
return result['members'][0]
def create_snapshot(self, orig_share_id, snapshot_id, fpg, vfs):
def create_snapshot(self, orig_project_id, orig_share_id, orig_share_proto,
snapshot_id, fpg, vfs):
"""Creates a snapshot of a share."""
fstore = self.ensure_prefix(orig_share_id)
fshare = self._find_fshare(orig_project_id,
orig_share_id,
orig_share_proto,
fpg,
vfs)
if not fshare:
msg = (_('Failed to create snapshot for FPG/VFS/fshare '
'%(fpg)s/%(vfs)s/%(fshare)s: Failed to find fshare.') %
{'fpg': fpg, 'vfs': vfs, 'fshare': orig_share_id})
LOG.exception(msg)
raise exception.ShareBackendException(msg)
sharedir = fshare.get('shareDir')
if sharedir and sharedir.startswith('.snapshot'):
msg = (_('Failed to create snapshot for FPG/VFS/fshare '
'%(fpg)s/%(vfs)s/%(fshare)s: Share is a read-only '
'share of an existing snapshot.') %
{'fpg': fpg, 'vfs': vfs, 'fshare': orig_share_id})
LOG.exception(msg)
raise exception.ShareBackendException(msg)
fstore = fshare.get('fstoreName')
snapshot_tag = self.ensure_prefix(snapshot_id)
try:
result = self._client.createfsnap(
@ -350,41 +422,20 @@ class HP3ParMediator(object):
LOG.exception(msg)
raise exception.ShareBackendException(msg)
def get_snapshots(self, orig_share_id, snapshot_tag, fpg, vfs):
fstore = self.ensure_prefix(orig_share_id)
try:
pattern = '*_%s' % snapshot_tag
result = self._client.getfsnap(
pattern, fpg=fpg, vfs=vfs, fstore=fstore, pat=True)
LOG.debug("getfsnap result=%s", result)
except Exception as e:
msg = (_('Failed to get snapshot for FPG/VFS/fstore/tag '
'%(fpg)s/%(vfs)s/%(fstore)s/%(tag)s: %(e)s') %
{'fpg': fpg, 'vfs': vfs, 'fstore': fstore,
'tag': snapshot_tag, 'e': six.text_type(e)})
LOG.exception(msg)
raise exception.ShareBackendException(msg)
if result['total'] == 0:
LOG.info((_LI('Found zero snapshots for FPG/VFS/fstore/tag '
'%(fpg)s/%(vfs)s/%(fstore)s/%(tag)s.') %
{'fpg': fpg, 'vfs': vfs, 'fstore': fstore,
'tag': snapshot_tag}))
return result['members']
def delete_snapshot(self, orig_share_id, snapshot_id, fpg, vfs):
def delete_snapshot(self, orig_project_id, orig_share_id, orig_proto,
snapshot_id, fpg, vfs):
"""Deletes a snapshot of a share."""
fstore = self.ensure_prefix(orig_share_id)
snapshot_tag = self.ensure_prefix(snapshot_id)
snapshots = self.get_snapshots(fstore, snapshot_tag, fpg, vfs)
if not snapshots:
snapshot = self._find_fsnap(orig_project_id, orig_share_id, orig_proto,
snapshot_tag, fpg, vfs)
if not snapshot:
return
fstore = snapshot.get('fstoreName')
for protocol in ('nfs', 'smb'):
try:
shares = self._client.getfshare(protocol,
@ -417,23 +468,24 @@ class HP3ParMediator(object):
'dependent share.'))
raise exception.Invalid(msg)
# Tag should be unique enough to only return one, but this method
# doesn't really need to know that. So just loop.
for snapshot in snapshots:
try:
snapname = snapshot['snapName']
result = self._client.removefsnap(
vfs, fstore, snapname=snapname, fpg=fpg)
snapname = snapshot['snapName']
try:
result = self._client.removefsnap(
vfs, fstore, snapname=snapname, fpg=fpg)
LOG.debug("removefsnap result=%s", result)
LOG.debug("removefsnap result=%s", result)
except Exception as e:
msg = (_('Failed to delete snapshot for FPG/VFS/fstore '
'%(fpg)s/%(vfs)s/%(fstore)s: %(e)s') %
{'fpg': fpg, 'vfs': vfs, 'fstore': fstore,
'e': six.text_type(e)})
LOG.exception(msg)
raise exception.ShareBackendException(msg)
except Exception as e:
msg = (_('Failed to delete snapshot for FPG/VFS/fstore/snapshot '
'%(fpg)s/%(vfs)s/%(fstore)s/%(snapname)s: %(e)s') %
{
'fpg': fpg,
'vfs': vfs,
'fstore': fstore,
'snapname': snapname,
'e': six.text_type(e)})
LOG.exception(msg)
raise exception.ShareBackendException(msg)
# Try to reclaim the space
try:
@ -461,7 +513,7 @@ class HP3ParMediator(object):
return protocol
def _change_access(self, plus_or_minus, fstore, share_id, share_proto,
def _change_access(self, plus_or_minus, project_id, share_id, share_proto,
access_type, access_to, fpg, vfs):
"""Allow or deny access to a share.
@ -469,12 +521,13 @@ class HP3ParMediator(object):
allow list (-).
"""
share_name = self.ensure_prefix(share_id)
fstore = self.ensure_prefix(fstore)
protocol = self.ensure_supported_protocol(share_proto)
self.validate_access_type(protocol, access_type)
share_name = self.ensure_prefix(share_id)
fstore = self._find_fstore(project_id, share_id, protocol, fpg, vfs,
allow_cross_protocol=True)
try:
if protocol == 'nfs':
result = self._client.setfshare(
@ -507,37 +560,80 @@ class HP3ParMediator(object):
LOG.exception(msg)
raise exception.ShareBackendException(msg)
def get_fstore(self, share_id, share_proto, fpg, vfs):
def _find_fstore(self, project_id, share_id, share_proto, fpg, vfs,
allow_cross_protocol=False):
share = self._find_fshare(project_id, share_id, share_proto, fpg, vfs)
if not share and allow_cross_protocol:
share = self._find_fshare(project_id,
share_id,
self.other_protocol(share_proto),
fpg,
vfs)
return share.get('fstoreName') if share else None
def _find_fshare(self, project_id, share_id, share_proto, fpg, vfs):
protocol = self.ensure_supported_protocol(share_proto)
share_name = self.ensure_prefix(share_id)
project_fstore = self.ensure_prefix(project_id, share_proto)
search_order = [
{'fpg': fpg, 'vfs': vfs, 'fstore': project_fstore},
{'fpg': fpg, 'vfs': vfs, 'fstore': share_name},
{'fpg': fpg},
{}
]
try:
shares = self._client.getfshare(protocol,
share_name,
fpg=fpg,
vfs=vfs)
for search_params in search_order:
result = self._client.getfshare(protocol, share_name,
**search_params)
shares = result.get('members', [])
if len(shares) == 1:
return shares[0]
except Exception as e:
msg = (_('Unexpected exception while getting share list: %s') %
six.text_type(e))
raise exception.ShareBackendException(msg)
members = shares['members']
if members:
return members[0].get('fstoreName')
def _find_fsnap(self, project_id, share_id, orig_proto, snapshot_tag,
fpg, vfs):
def allow_access(self, share_id, share_proto, access_type, access_to,
fpg, vfs):
share_name = self.ensure_prefix(share_id)
osf_project_id = self.ensure_prefix(project_id, orig_proto)
pattern = '*_%s' % self.ensure_prefix(snapshot_tag)
search_order = [
{'pat': True, 'fpg': fpg, 'vfs': vfs, 'fstore': osf_project_id},
{'pat': True, 'fpg': fpg, 'vfs': vfs, 'fstore': share_name},
{'pat': True, 'fpg': fpg},
{'pat': True},
]
try:
for search_params in search_order:
result = self._client.getfsnap(pattern, **search_params)
snapshots = result.get('members', [])
if len(snapshots) == 1:
return snapshots[0]
except Exception as e:
msg = (_('Unexpected exception while getting snapshots: %s') %
six.text_type(e))
raise exception.ShareBackendException(msg)
def allow_access(self, project_id, share_id, share_proto, access_type,
access_to, fpg, vfs):
"""Grant access to a share."""
fstore = self.get_fstore(share_id, share_proto, fpg, vfs)
self._change_access(ALLOW, fstore, share_id, share_proto,
self._change_access(ALLOW, project_id, share_id, share_proto,
access_type, access_to, fpg, vfs)
def deny_access(self, share_id, share_proto, access_type, access_to,
fpg, vfs):
def deny_access(self, project_id, share_id, share_proto, access_type,
access_to, fpg, vfs):
"""Deny access to a share."""
fstore = self.get_fstore(share_id, share_proto, fpg, vfs)
if fstore:
self._change_access(DENY, fstore, share_id, share_proto,
access_type, access_to, fpg, vfs)
self._change_access(DENY, project_id, share_id, share_proto,
access_type, access_to, fpg, vfs)

View File

@ -29,6 +29,7 @@ PORT = 22
EXPECTED_IP_10203040 = '10.20.30.40'
EXPECTED_IP_1234 = '1.2.3.4'
EXPECTED_IP_127 = '127.0.0.1'
EXPECTED_PROJECT_ID = 'osf-nfs-project-id'
EXPECTED_SHARE_ID = 'osf-share-id'
EXPECTED_SHARE_NAME = 'share-name'
EXPECTED_SHARE_PATH = '/anyfpg/anyvfs/anyfstore'
@ -38,11 +39,12 @@ EXPECTED_SNAP_NAME = 'osf-snap-name'
EXPECTED_SNAP_ID = 'osf-snap-id'
EXPECTED_STATS = {'test': 'stats'}
EXPECTED_FPG = 'FPG_1'
EXPECTED_FSTORE = 'osf-test_fstore'
EXPECTED_FSTORE = EXPECTED_PROJECT_ID
EXPECTED_VFS = 'test_vfs'
EXPECTED_HP_DEBUG = True
NFS_SHARE_INFO = {
'project_id': EXPECTED_PROJECT_ID,
'id': EXPECTED_SHARE_ID,
'share_proto': NFS,
}
@ -55,5 +57,9 @@ ACCESS_INFO = {
SNAPSHOT_INFO = {
'name': EXPECTED_SNAP_NAME,
'id': EXPECTED_SNAP_ID,
'share': {'id': EXPECTED_SHARE_ID},
'share': {
'project_id': EXPECTED_PROJECT_ID,
'id': EXPECTED_SHARE_ID,
'share_proto': NFS,
},
}

View File

@ -39,11 +39,12 @@ class HP3ParDriverTestCase(test.TestCase):
self.conf.hp3par_api_url = constants.API_URL
self.conf.hp3par_san_login = constants.SAN_LOGIN
self.conf.hp3par_san_password = constants.SAN_PASSWORD
self.conf.hp3par.san_ip = constants.EXPECTED_IP_1234
self.conf.hp3par_san_ip = constants.EXPECTED_IP_1234
self.conf.hp3par_fpg = constants.EXPECTED_FPG
self.conf.hp3par_san_ssh_port = constants.PORT
self.conf.ssh_conn_timeout = constants.TIMEOUT
self.conf.hp3par_share_ip_address = constants.EXPECTED_IP_10203040
self.conf.hp3par_fstore_per_share = False
self.conf.network_config_group = 'test_network_config_group'
def safe_get(attr):
@ -66,20 +67,22 @@ class HP3ParDriverTestCase(test.TestCase):
self.mock_mediator.get_vfs_name.return_value = constants.EXPECTED_VFS
self.driver.do_setup(None)
conf = self.conf
self.mock_mediator_constructor.assert_has_calls([
mock.call(hp3par_san_ssh_port=self.conf.hp3par_san_ssh_port,
hp3par_san_password=self.conf.hp3par_san_password,
hp3par_username=self.conf.hp3par_username,
hp3par_san_login=self.conf.hp3par_san_login,
hp3par_debug=self.conf.hp3par_debug,
hp3par_api_url=self.conf.hp3par_api_url,
hp3par_password=self.conf.hp3par_password,
hp3par_san_ip=self.conf.hp3par_san_ip,
ssh_conn_timeout=self.conf.ssh_conn_timeout)])
mock.call(hp3par_san_ssh_port=conf.hp3par_san_ssh_port,
hp3par_san_password=conf.hp3par_san_password,
hp3par_username=conf.hp3par_username,
hp3par_san_login=conf.hp3par_san_login,
hp3par_debug=conf.hp3par_debug,
hp3par_api_url=conf.hp3par_api_url,
hp3par_password=conf.hp3par_password,
hp3par_san_ip=conf.hp3par_san_ip,
hp3par_fstore_per_share=conf.hp3par_fstore_per_share,
ssh_conn_timeout=conf.ssh_conn_timeout)])
self.mock_mediator.assert_has_calls([
mock.call.do_setup(),
mock.call.get_vfs_name(self.conf.hp3par_fpg)])
mock.call.get_vfs_name(conf.hp3par_fpg)])
self.assertEqual(constants.EXPECTED_VFS, self.driver.vfs)
@ -92,16 +95,18 @@ class HP3ParDriverTestCase(test.TestCase):
self.assertRaises(exception.ShareBackendException,
self.driver.do_setup, None)
conf = self.conf
self.mock_mediator_constructor.assert_has_calls([
mock.call(hp3par_san_ssh_port=self.conf.hp3par_san_ssh_port,
hp3par_san_password=self.conf.hp3par_san_password,
hp3par_username=self.conf.hp3par_username,
hp3par_san_login=self.conf.hp3par_san_login,
hp3par_debug=self.conf.hp3par_debug,
hp3par_api_url=self.conf.hp3par_api_url,
hp3par_password=self.conf.hp3par_password,
hp3par_san_ip=self.conf.hp3par_san_ip,
ssh_conn_timeout=self.conf.ssh_conn_timeout)])
mock.call(hp3par_san_ssh_port=conf.hp3par_san_ssh_port,
hp3par_san_password=conf.hp3par_san_password,
hp3par_username=conf.hp3par_username,
hp3par_san_login=conf.hp3par_san_login,
hp3par_debug=conf.hp3par_debug,
hp3par_api_url=conf.hp3par_api_url,
hp3par_password=conf.hp3par_password,
hp3par_san_ip=conf.hp3par_san_ip,
hp3par_fstore_per_share=conf.hp3par_fstore_per_share,
ssh_conn_timeout=conf.ssh_conn_timeout)])
self.mock_mediator.assert_has_calls([mock.call.do_setup()])
@ -114,20 +119,22 @@ class HP3ParDriverTestCase(test.TestCase):
self.assertRaises(exception.ShareBackendException,
self.driver.do_setup, None)
conf = self.conf
self.mock_mediator_constructor.assert_has_calls([
mock.call(hp3par_san_ssh_port=self.conf.hp3par_san_ssh_port,
hp3par_san_password=self.conf.hp3par_san_password,
hp3par_username=self.conf.hp3par_username,
hp3par_san_login=self.conf.hp3par_san_login,
hp3par_debug=self.conf.hp3par_debug,
hp3par_api_url=self.conf.hp3par_api_url,
hp3par_password=self.conf.hp3par_password,
hp3par_san_ip=self.conf.hp3par_san_ip,
ssh_conn_timeout=self.conf.ssh_conn_timeout)])
mock.call(hp3par_san_ssh_port=conf.hp3par_san_ssh_port,
hp3par_san_password=conf.hp3par_san_password,
hp3par_username=conf.hp3par_username,
hp3par_san_login=conf.hp3par_san_login,
hp3par_debug=conf.hp3par_debug,
hp3par_api_url=conf.hp3par_api_url,
hp3par_password=conf.hp3par_password,
hp3par_san_ip=conf.hp3par_san_ip,
hp3par_fstore_per_share=conf.hp3par_fstore_per_share,
ssh_conn_timeout=conf.ssh_conn_timeout)])
self.mock_mediator.assert_has_calls([
mock.call.do_setup(),
mock.call.get_vfs_name(self.conf.hp3par_fpg)])
mock.call.get_vfs_name(conf.hp3par_fpg)])
def init_driver(self):
"""Simple driver setup for re-use with tests that need one."""
@ -137,11 +144,13 @@ class HP3ParDriverTestCase(test.TestCase):
self.driver.fpg = constants.EXPECTED_FPG
self.driver.share_ip_address = self.conf.hp3par_share_ip_address
def do_create_share(self, protocol, expected_share_id, expected_size):
def do_create_share(self, protocol, expected_project_id, expected_share_id,
expected_size):
"""Re-usable code for create share."""
context = None
share_server = None
share = {
'project_id': expected_project_id,
'id': expected_share_id,
'share_proto': protocol,
'size': expected_size,
@ -188,11 +197,13 @@ class HP3ParDriverTestCase(test.TestCase):
constants.EXPECTED_SHARE_NAME)
location = self.do_create_share(constants.CIFS,
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.EXPECTED_SIZE_2)
self.assertEqual(expected_location, location)
expected_calls = [mock.call.create_share(
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.CIFS,
constants.EXPECTED_FPG,
@ -210,12 +221,14 @@ class HP3ParDriverTestCase(test.TestCase):
constants.EXPECTED_SHARE_PATH)
location = self.do_create_share(constants.NFS,
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.EXPECTED_SIZE_1)
self.assertEqual(expected_location, location)
expected_calls = [
mock.call.create_share(constants.EXPECTED_SHARE_ID,
mock.call.create_share(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS,
@ -242,7 +255,9 @@ class HP3ParDriverTestCase(test.TestCase):
expected_calls = [
mock.call.create_share_from_snapshot(constants.EXPECTED_SHARE_ID,
constants.CIFS,
constants.EXPECTED_FSTORE,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_ID,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)]
@ -267,7 +282,9 @@ class HP3ParDriverTestCase(test.TestCase):
expected_calls = [
mock.call.create_share_from_snapshot(constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_ID,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)]
@ -280,6 +297,7 @@ class HP3ParDriverTestCase(test.TestCase):
context = None
share_server = None
share = {
'project_id': constants.EXPECTED_PROJECT_ID,
'id': constants.EXPECTED_SHARE_ID,
'share_proto': constants.CIFS,
'size': constants.EXPECTED_SIZE_1,
@ -288,7 +306,8 @@ class HP3ParDriverTestCase(test.TestCase):
self.driver.delete_share(context, share, share_server)
expected_calls = [
mock.call.delete_share(constants.EXPECTED_SHARE_ID,
mock.call.delete_share(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.CIFS,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)]
@ -305,7 +324,9 @@ class HP3ParDriverTestCase(test.TestCase):
share_server)
expected_calls = [
mock.call.create_snapshot(constants.EXPECTED_SHARE_ID,
mock.call.create_snapshot(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_ID,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)]
@ -321,7 +342,9 @@ class HP3ParDriverTestCase(test.TestCase):
share_server)
expected_calls = [
mock.call.delete_snapshot(constants.EXPECTED_SHARE_ID,
mock.call.delete_snapshot(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_ID,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
@ -337,7 +360,8 @@ class HP3ParDriverTestCase(test.TestCase):
constants.ACCESS_INFO)
expected_calls = [
mock.call.allow_access(constants.EXPECTED_SHARE_ID,
mock.call.allow_access(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.IP,
constants.EXPECTED_IP_1234,
@ -355,7 +379,8 @@ class HP3ParDriverTestCase(test.TestCase):
constants.ACCESS_INFO)
expected_calls = [
mock.call.deny_access(constants.EXPECTED_SHARE_ID,
mock.call.deny_access(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.IP,
constants.EXPECTED_IP_1234,

View File

@ -14,10 +14,10 @@
import sys
import ddt
import mock
if 'hp3parclient' not in sys.modules:
sys.modules['hp3parclient'] = mock.Mock()
import six
from manila import exception
from manila.share.drivers.hp import hp_3par_mediator as hp3parmediator
@ -27,6 +27,7 @@ from manila.tests.share.drivers.hp import test_hp_3par_constants as constants
from oslo_utils import units
@ddt.ddt
class HP3ParMediatorTestCase(test.TestCase):
def setUp(self):
@ -143,20 +144,23 @@ class HP3ParMediatorTestCase(test.TestCase):
expected_fpg,
expected_vfsname,
expected_protocol,
expected_share_id,
expected_size):
size = six.text_type(expected_size)
expected_sharedir = None
expected_project_id,
expected_share_id):
expected_sharedir = expected_share_id
if expected_protocol == constants.NFS_LOWER:
expected_calls = [
mock.call.createfstore(expected_vfsname, expected_share_id,
mock.call.createfstore(expected_vfsname, expected_project_id,
comment='OpenStack Manila fstore',
fpg=expected_fpg),
mock.call.setfsquota(expected_vfsname, fpg=expected_fpg,
hcapacity=size,
scapacity=size,
fstore=expected_share_id),
mock.call.getfsquota(fpg=expected_fpg,
vfs=expected_vfsname,
fstore=expected_project_id),
mock.call.setfsquota(expected_vfsname,
fpg=expected_fpg,
hcapacity='2048',
scapacity='2048',
fstore=expected_project_id),
mock.call.createfshare(expected_protocol, expected_vfsname,
expected_share_id,
comment='OpenStack Manila fshare',
@ -164,29 +168,33 @@ class HP3ParMediatorTestCase(test.TestCase):
sharedir=expected_sharedir,
clientip='127.0.0.1',
options='rw,no_root_squash,insecure',
fstore=expected_share_id),
fstore=expected_project_id),
mock.call.getfshare(expected_protocol, expected_share_id,
fpg=expected_fpg, vfs=expected_vfsname,
fstore=expected_share_id)]
fstore=expected_project_id)]
else:
expected_calls = [
mock.call.createfstore(expected_vfsname, expected_share_id,
mock.call.createfstore(expected_vfsname, expected_project_id,
comment='OpenStack Manila fstore',
fpg=expected_fpg),
mock.call.setfsquota(expected_vfsname, fpg=expected_fpg,
hcapacity=size,
scapacity=size,
fstore=expected_share_id),
mock.call.getfsquota(fpg=expected_fpg,
vfs=expected_vfsname,
fstore=expected_project_id),
mock.call.setfsquota(expected_vfsname,
fpg=expected_fpg,
hcapacity='2048',
scapacity='2048',
fstore=expected_project_id),
mock.call.createfshare(expected_protocol, expected_vfsname,
expected_share_id,
comment='OpenStack Manila fshare',
fpg=expected_fpg,
sharedir=expected_sharedir,
allowip='127.0.0.1',
fstore=expected_share_id),
fstore=expected_project_id),
mock.call.getfshare(expected_protocol, expected_share_id,
fpg=expected_fpg, vfs=expected_vfsname,
fstore=expected_share_id)]
fstore=expected_project_id)]
return expected_calls
def test_mediator_create_cifs_share(self):
@ -198,11 +206,18 @@ class HP3ParMediatorTestCase(test.TestCase):
'members': [{'shareName': constants.EXPECTED_SHARE_NAME}]
}
location = self.mediator.create_share(constants.EXPECTED_SHARE_ID,
self.mock_client.getfsquota.return_value = {
'message': None,
'total': 1,
'members': [{'hardBlock': '1024', 'softBlock': '1024'}]
}
location = self.mediator.create_share(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.CIFS,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS,
size=constants.EXPECTED_SIZE_2)
size=constants.EXPECTED_SIZE_1)
self.assertEqual(constants.EXPECTED_SHARE_NAME, location)
@ -210,8 +225,8 @@ class HP3ParMediatorTestCase(test.TestCase):
constants.EXPECTED_FPG,
constants.EXPECTED_VFS,
constants.SMB_LOWER,
constants.EXPECTED_SHARE_ID,
constants.EXPECTED_SIZE_2)
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID)
self.mock_client.assert_has_calls(expected_calls)
@ -224,7 +239,14 @@ class HP3ParMediatorTestCase(test.TestCase):
'members': [{'sharePath': constants.EXPECTED_SHARE_PATH}]
}
location = self.mediator.create_share(constants.EXPECTED_SHARE_ID,
self.mock_client.getfsquota.return_value = {
'message': None,
'total': 1,
'members': [{'hardBlock': '1024', 'softBlock': '1024'}]
}
location = self.mediator.create_share(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS.lower(),
constants.EXPECTED_FPG,
constants.EXPECTED_VFS,
@ -233,10 +255,11 @@ class HP3ParMediatorTestCase(test.TestCase):
self.assertEqual(constants.EXPECTED_SHARE_PATH, location)
expected_calls = self.get_expected_calls_for_create_share(
constants.EXPECTED_FPG, constants.EXPECTED_VFS,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS,
constants.NFS.lower(),
constants.EXPECTED_SHARE_ID,
constants.EXPECTED_SIZE_1)
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID)
self.mock_client.assert_has_calls(expected_calls)
@ -246,13 +269,16 @@ class HP3ParMediatorTestCase(test.TestCase):
self.mock_client.getfsnap.return_value = {
'message': None,
'total': 1,
'members': [{'snapName': constants.EXPECTED_SNAP_ID}]
'members': [{'snapName': constants.EXPECTED_SNAP_ID,
'fstoreName': constants.EXPECTED_FSTORE}]
}
location = self.mediator.create_share_from_snapshot(
constants.EXPECTED_SHARE_ID,
constants.CIFS,
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_ID,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
@ -264,21 +290,22 @@ class HP3ParMediatorTestCase(test.TestCase):
vfs=constants.EXPECTED_VFS,
fpg=constants.EXPECTED_FPG,
pat=True,
fstore=constants.EXPECTED_SHARE_ID),
fstore=constants.EXPECTED_FSTORE),
mock.call.createfshare(constants.SMB_LOWER,
constants.EXPECTED_VFS,
constants.EXPECTED_SHARE_ID,
comment=mock.ANY,
fpg=constants.EXPECTED_FPG,
sharedir='.snapshot/%s' %
sharedir='.snapshot/%s/%s' % (
constants.EXPECTED_SNAP_ID,
fstore=constants.EXPECTED_SHARE_ID,
constants.EXPECTED_SHARE_ID),
fstore=constants.EXPECTED_FSTORE,
allowip=constants.EXPECTED_IP_127),
mock.call.getfshare(constants.SMB_LOWER,
constants.EXPECTED_SHARE_ID,
fpg=constants.EXPECTED_FPG,
vfs=constants.EXPECTED_VFS,
fstore=constants.EXPECTED_SHARE_ID)]
fstore=constants.EXPECTED_FSTORE)]
self.mock_client.assert_has_calls(expected_calls)
@ -288,13 +315,16 @@ class HP3ParMediatorTestCase(test.TestCase):
self.mock_client.getfsnap.return_value = {
'message': None,
'total': 1,
'members': [{'snapName': constants.EXPECTED_SNAP_ID}]
'members': [{'snapName': constants.EXPECTED_SNAP_ID,
'fstoreName': constants.EXPECTED_FSTORE}]
}
location = self.mediator.create_share_from_snapshot(
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_ID,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
@ -306,22 +336,23 @@ class HP3ParMediatorTestCase(test.TestCase):
vfs=constants.EXPECTED_VFS,
fpg=constants.EXPECTED_FPG,
pat=True,
fstore=constants.EXPECTED_SHARE_ID),
fstore=constants.EXPECTED_FSTORE),
mock.call.createfshare(constants.NFS_LOWER,
constants.EXPECTED_VFS,
constants.EXPECTED_SHARE_ID,
comment=mock.ANY,
fpg=constants.EXPECTED_FPG,
sharedir='.snapshot/%s' %
constants.EXPECTED_SNAP_ID,
fstore=constants.EXPECTED_SHARE_ID,
sharedir='.snapshot/%s/%s' %
(constants.EXPECTED_SNAP_ID,
constants.EXPECTED_SHARE_ID),
fstore=constants.EXPECTED_FSTORE,
clientip=constants.EXPECTED_IP_127,
options='ro,no_root_squash,insecure'),
mock.call.getfshare(constants.NFS_LOWER,
constants.EXPECTED_SHARE_ID,
fpg=constants.EXPECTED_FPG,
vfs=constants.EXPECTED_VFS,
fstore=constants.EXPECTED_SHARE_ID)]
fstore=constants.EXPECTED_FSTORE)]
self.mock_client.assert_has_calls(expected_calls)
@ -338,7 +369,9 @@ class HP3ParMediatorTestCase(test.TestCase):
self.mediator.create_share_from_snapshot,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_ID,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
@ -346,7 +379,12 @@ class HP3ParMediatorTestCase(test.TestCase):
def test_mediator_delete_share(self):
self.init_mediator()
self.mediator.delete_share(constants.EXPECTED_SHARE_ID,
self.mock_object(self.mediator,
'_find_fstore',
mock.Mock(return_value=constants.EXPECTED_SHARE_ID))
self.mediator.delete_share(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.CIFS,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
@ -356,10 +394,10 @@ class HP3ParMediatorTestCase(test.TestCase):
constants.EXPECTED_VFS,
constants.EXPECTED_SHARE_ID,
fpg=constants.EXPECTED_FPG,
fstore=constants.EXPECTED_FSTORE),
fstore=constants.EXPECTED_SHARE_ID),
mock.call.removefstore(constants.EXPECTED_VFS,
constants.EXPECTED_FSTORE,
fpg=constants.EXPECTED_FPG)
constants.EXPECTED_SHARE_ID,
fpg=constants.EXPECTED_FPG),
]
self.mock_client.assert_has_calls(expected_calls)
@ -367,14 +405,16 @@ class HP3ParMediatorTestCase(test.TestCase):
def test_mediator_create_snapshot(self):
self.init_mediator()
self.mediator.create_snapshot(constants.EXPECTED_SHARE_ID,
self.mediator.create_snapshot(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_NAME,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
expected_calls = [
mock.call.createfsnap(constants.EXPECTED_VFS,
constants.EXPECTED_SHARE_ID,
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SNAP_NAME,
fpg=constants.EXPECTED_FPG)
]
@ -389,7 +429,9 @@ class HP3ParMediatorTestCase(test.TestCase):
self.assertRaises(exception.ShareBackendException,
self.mediator.create_snapshot,
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_NAME,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
@ -401,7 +443,13 @@ class HP3ParMediatorTestCase(test.TestCase):
self.mock_client.getfsnap.return_value = {
'total': 1,
'members': [{'snapName': expected_name_from_array}]
'members': [
{
'snapName': expected_name_from_array,
'fstoreName': constants.EXPECTED_PROJECT_ID,
}
],
'message': None
}
self.mock_client.getfshare.side_effect = [
@ -416,7 +464,9 @@ class HP3ParMediatorTestCase(test.TestCase):
}
]
self.mediator.delete_snapshot(constants.EXPECTED_SHARE_ID,
self.mediator.delete_snapshot(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_NAME,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
@ -426,17 +476,17 @@ class HP3ParMediatorTestCase(test.TestCase):
vfs=constants.EXPECTED_VFS,
fpg=constants.EXPECTED_FPG,
pat=True,
fstore=constants.EXPECTED_SHARE_ID),
fstore=constants.EXPECTED_PROJECT_ID),
mock.call.getfshare(constants.NFS_LOWER,
fpg=constants.EXPECTED_FPG,
vfs=constants.EXPECTED_VFS,
fstore=constants.EXPECTED_SHARE_ID),
fstore=constants.EXPECTED_PROJECT_ID),
mock.call.getfshare(constants.SMB_LOWER,
fpg=constants.EXPECTED_FPG,
vfs=constants.EXPECTED_VFS,
fstore=constants.EXPECTED_SHARE_ID),
fstore=constants.EXPECTED_PROJECT_ID),
mock.call.removefsnap(constants.EXPECTED_VFS,
constants.EXPECTED_SHARE_ID,
constants.EXPECTED_PROJECT_ID,
fpg=constants.EXPECTED_FPG,
snapname=expected_name_from_array),
mock.call.startfsnapclean(constants.EXPECTED_FPG,
@ -452,7 +502,9 @@ class HP3ParMediatorTestCase(test.TestCase):
'members': [],
}
self.mediator.delete_snapshot(constants.EXPECTED_SHARE_ID,
self.mediator.delete_snapshot(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_NAME,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
@ -497,7 +549,9 @@ class HP3ParMediatorTestCase(test.TestCase):
self.assertRaises(exception.Invalid,
self.mediator.delete_snapshot,
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_NAME,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
@ -527,7 +581,9 @@ class HP3ParMediatorTestCase(test.TestCase):
self.assertRaises(exception.Invalid,
self.mediator.delete_snapshot,
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_NAME,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
@ -535,7 +591,9 @@ class HP3ParMediatorTestCase(test.TestCase):
def _assert_delete_snapshot_raises(self):
self.assertRaises(exception.ShareBackendException,
self.mediator.delete_snapshot,
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_NAME,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
@ -551,7 +609,8 @@ class HP3ParMediatorTestCase(test.TestCase):
self.mock_client.getfsnap.side_effect = None
self.mock_client.getfsnap.return_value = {
'total': 1,
'members': [{'snapName': constants.EXPECTED_SNAP_NAME}]
'members': [{'snapName': constants.EXPECTED_SNAP_NAME,
'fstoreName': constants.EXPECTED_FSTORE}]
}
# getfshare exception
@ -563,12 +622,14 @@ class HP3ParMediatorTestCase(test.TestCase):
if args[0] == constants.NFS_LOWER:
return {
'total': 1,
'members': [{'sharePath': '/anyfpg/anyvfs/anyfstore'}]
'members': [{'sharePath': '/anyfpg/anyvfs/anyfstore',
'fstoreName': constants.EXPECTED_FSTORE}]
}
else:
return {
'total': 1,
'members': [{'shareDir': []}]
'members': [{'shareDir': [],
'fstoreName': constants.EXPECTED_FSTORE}]
}
self.mock_client.getfshare.side_effect = mock_fshare
@ -587,7 +648,9 @@ class HP3ParMediatorTestCase(test.TestCase):
'startfsnapclean fail.')
mock_log = self.mock_object(hp3parmediator, 'LOG')
self.mediator.delete_snapshot(constants.EXPECTED_SHARE_ID,
self.mediator.delete_snapshot(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_NAME,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
@ -597,17 +660,17 @@ class HP3ParMediatorTestCase(test.TestCase):
vfs=constants.EXPECTED_VFS,
fpg=constants.EXPECTED_FPG,
pat=True,
fstore=constants.EXPECTED_SHARE_ID),
fstore=constants.EXPECTED_FSTORE),
mock.call.getfshare(constants.NFS_LOWER,
fpg=constants.EXPECTED_FPG,
vfs=constants.EXPECTED_VFS,
fstore=constants.EXPECTED_SHARE_ID),
fstore=constants.EXPECTED_FSTORE),
mock.call.getfshare(constants.SMB_LOWER,
fpg=constants.EXPECTED_FPG,
vfs=constants.EXPECTED_VFS,
fstore=constants.EXPECTED_SHARE_ID),
fstore=constants.EXPECTED_FSTORE),
mock.call.removefsnap(constants.EXPECTED_VFS,
constants.EXPECTED_SHARE_ID,
constants.EXPECTED_FSTORE,
fpg=constants.EXPECTED_FPG,
snapname=constants.EXPECTED_SNAP_NAME),
mock.call.startfsnapclean(constants.EXPECTED_FPG,
@ -651,7 +714,8 @@ class HP3ParMediatorTestCase(test.TestCase):
expected_allowperm = '+%s:fullcontrol' % constants.USERNAME
self.mediator.allow_access(constants.EXPECTED_SHARE_ID,
self.mediator.allow_access(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.CIFS,
constants.USER,
constants.USERNAME,
@ -675,7 +739,8 @@ class HP3ParMediatorTestCase(test.TestCase):
expected_denyperm = '-%s:fullcontrol' % constants.USERNAME
self.mediator.deny_access(constants.EXPECTED_SHARE_ID,
self.mediator.deny_access(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.CIFS,
constants.USER,
constants.USERNAME,
@ -699,7 +764,8 @@ class HP3ParMediatorTestCase(test.TestCase):
expected_allowip = '+%s' % constants.EXPECTED_IP_1234
self.mediator.allow_access(constants.EXPECTED_SHARE_ID,
self.mediator.allow_access(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.CIFS,
constants.IP,
constants.EXPECTED_IP_1234,
@ -722,7 +788,8 @@ class HP3ParMediatorTestCase(test.TestCase):
expected_denyip = '-%s' % constants.EXPECTED_IP_1234
self.mediator.deny_access(constants.EXPECTED_SHARE_ID,
self.mediator.deny_access(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.CIFS,
constants.IP,
constants.EXPECTED_IP_1234,
@ -745,7 +812,8 @@ class HP3ParMediatorTestCase(test.TestCase):
expected_clientip = '+%s' % constants.EXPECTED_IP_1234
self.mediator.allow_access(constants.EXPECTED_SHARE_ID,
self.mediator.allow_access(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.IP,
constants.EXPECTED_IP_1234,
@ -768,7 +836,8 @@ class HP3ParMediatorTestCase(test.TestCase):
expected_clientip = '-%s' % constants.EXPECTED_IP_1234
self.mediator.deny_access(constants.EXPECTED_SHARE_ID,
self.mediator.deny_access(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.IP,
constants.EXPECTED_IP_1234,
@ -791,6 +860,7 @@ class HP3ParMediatorTestCase(test.TestCase):
self.assertRaises(exception.HP3ParInvalid,
self.mediator.allow_access,
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.USER,
@ -804,6 +874,7 @@ class HP3ParMediatorTestCase(test.TestCase):
self.assertRaises(exception.InvalidInput,
self.mediator.allow_access,
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
'unsupported_other_protocol',
constants.USER,
@ -817,9 +888,241 @@ class HP3ParMediatorTestCase(test.TestCase):
self.assertRaises(exception.InvalidInput,
self.mediator.allow_access,
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.CIFS,
'unsupported_other_type',
constants.USERNAME,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
@ddt.data((('nfs', 'NFS', 'nFs'), 'smb'),
(('smb', 'SMB', 'SmB', 'CIFS', 'cifs', 'CiFs'), 'nfs'))
@ddt.unpack
def test_other_protocol(self, protocols, expected_other):
for protocol in protocols:
self.assertEqual(expected_other,
hp3parmediator.HP3ParMediator().other_protocol(
protocol))
@ddt.data('', 'bogus')
def test_other_protocol_exception(self, protocol):
self.assertRaises(exception.InvalidInput,
hp3parmediator.HP3ParMediator().other_protocol,
protocol)
@ddt.data(('osf-uid', None, 'osf-uid'),
('uid', None, 'osf-uid'),
('uid', 'smb', 'osf-smb-uid'),
('uid', 'smb', 'osf-smb-uid'))
@ddt.unpack
def test_ensure_prefix(self, uid, protocol, expected):
self.assertEqual(expected,
hp3parmediator.HP3ParMediator().ensure_prefix(
uid, protocol=protocol))
def test_find_fstore_search(self):
self.init_mediator()
mock_find_fshare = self.mock_object(self.mediator,
'_find_fshare',
mock.Mock(return_value=None))
result = self.mediator._find_fstore(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
mock_find_fshare.assert_called_once_with(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
self.assertIsNone(result)
def test_find_fstore_search_xproto(self):
self.init_mediator()
mock_find_fshare = self.mock_object(self.mediator,
'_find_fshare',
mock.Mock(return_value=None))
result = self.mediator._find_fstore(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS,
allow_cross_protocol=True)
expected_calls = [
mock.call(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS),
mock.call(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.SMB_LOWER,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS),
]
mock_find_fshare.assert_has_calls(expected_calls)
self.assertIsNone(result)
def test_find_fshare_search(self):
self.init_mediator()
self.mock_client.getfshare.return_value = {}
result = self.mediator._find_fshare(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
expected_calls = [
mock.call.getfshare(constants.NFS_LOWER,
constants.EXPECTED_SHARE_ID,
fpg=constants.EXPECTED_FPG,
vfs=constants.EXPECTED_VFS,
fstore=constants.EXPECTED_PROJECT_ID),
mock.call.getfshare(constants.NFS_LOWER,
constants.EXPECTED_SHARE_ID,
fpg=constants.EXPECTED_FPG,
vfs=constants.EXPECTED_VFS,
fstore=constants.EXPECTED_SHARE_ID),
mock.call.getfshare(constants.NFS_LOWER,
constants.EXPECTED_SHARE_ID,
fpg=constants.EXPECTED_FPG),
mock.call.getfshare(constants.NFS_LOWER,
constants.EXPECTED_SHARE_ID),
]
self.mock_client.assert_has_calls(expected_calls)
self.assertIsNone(result)
def test_find_fshare_exception(self):
self.init_mediator()
self.mock_client.getfshare.side_effect = Exception('test unexpected')
self.assertRaises(exception.ShareBackendException,
self.mediator._find_fshare,
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
self.mock_client.getfshare.assert_called_once_with(
constants.NFS_LOWER,
constants.EXPECTED_SHARE_ID,
fpg=constants.EXPECTED_FPG,
vfs=constants.EXPECTED_VFS,
fstore=constants.EXPECTED_PROJECT_ID)
def test_find_fshare_hit(self):
self.init_mediator()
expected_result = {'shareName': 'hit'}
self.mock_client.getfshare.return_value = {
'total': 1,
'members': [expected_result]
}
result = self.mediator._find_fshare(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
self.mock_client.getfshare.assert_called_once_with(
constants.NFS_LOWER,
constants.EXPECTED_SHARE_ID,
fpg=constants.EXPECTED_FPG,
vfs=constants.EXPECTED_VFS,
fstore=constants.EXPECTED_PROJECT_ID),
self.assertEqual(expected_result, result)
def test_find_fsnap_search(self):
self.init_mediator()
self.mock_client.getfsnap.return_value = {}
result = self.mediator._find_fsnap(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_ID,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
expected_snap_pattern = '*_%s' % constants.EXPECTED_SNAP_ID
expected_calls = [
mock.call.getfsnap(expected_snap_pattern,
vfs=constants.EXPECTED_VFS,
fpg=constants.EXPECTED_FPG,
pat=True,
fstore=constants.EXPECTED_PROJECT_ID),
mock.call.getfsnap(expected_snap_pattern,
vfs=constants.EXPECTED_VFS,
fpg=constants.EXPECTED_FPG,
pat=True,
fstore=constants.EXPECTED_SHARE_ID),
mock.call.getfsnap(expected_snap_pattern,
fpg=constants.EXPECTED_FPG,
pat=True),
mock.call.getfsnap(expected_snap_pattern, pat=True),
]
self.mock_client.assert_has_calls(expected_calls)
self.assertIsNone(result)
def test_find_fsnap_exception(self):
self.init_mediator()
self.mock_client.getfsnap.side_effect = Exception('test unexpected')
self.assertRaises(exception.ShareBackendException,
self.mediator._find_fsnap,
constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_ID,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
expected_snap_pattern = '*_%s' % constants.EXPECTED_SNAP_ID
self.mock_client.getfsnap.assert_called_once_with(
expected_snap_pattern,
vfs=constants.EXPECTED_VFS,
fpg=constants.EXPECTED_FPG,
pat=True,
fstore=constants.EXPECTED_PROJECT_ID)
def test_find_fsnap_hit(self):
self.init_mediator()
expected_result = {'snapName': 'hit'}
self.mock_client.getfsnap.return_value = {
'total': 1,
'members': [expected_result]
}
result = self.mediator._find_fsnap(constants.EXPECTED_PROJECT_ID,
constants.EXPECTED_SHARE_ID,
constants.NFS,
constants.EXPECTED_SNAP_ID,
constants.EXPECTED_FPG,
constants.EXPECTED_VFS)
expected_snap_pattern = '*_%s' % constants.EXPECTED_SNAP_ID
self.mock_client.getfsnap.assert_called_once_with(
expected_snap_pattern,
vfs=constants.EXPECTED_VFS,
fpg=constants.EXPECTED_FPG,
pat=True,
fstore=constants.EXPECTED_PROJECT_ID)
self.assertEqual(expected_result, result)