3025 lines
127 KiB
Python
3025 lines
127 KiB
Python
# Copyright 2015 Hewlett Packard Enterprise Development LP
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import sys
|
|
from unittest import mock
|
|
|
|
import ddt
|
|
if 'hpe3parclient' not in sys.modules:
|
|
sys.modules['hpe3parclient'] = mock.Mock()
|
|
from oslo_utils import units
|
|
|
|
from manila.data import utils as data_utils
|
|
from manila import exception
|
|
from manila.share.drivers.hpe import hpe_3par_mediator as hpe3parmediator
|
|
from manila import test
|
|
from manila.tests.share.drivers.hpe import test_hpe_3par_constants as constants
|
|
from manila import utils
|
|
|
|
|
|
CLIENT_VERSION_MIN_OK = hpe3parmediator.MIN_CLIENT_VERSION
|
|
TEST_WSAPI_VERSION_STR = '30201292'
|
|
|
|
|
|
@ddt.ddt
|
|
class HPE3ParMediatorTestCase(test.TestCase):
|
|
|
|
def setUp(self):
|
|
super(HPE3ParMediatorTestCase, self).setUp()
|
|
|
|
# Fake utils.execute
|
|
self.mock_object(utils, 'execute', mock.Mock(return_value={}))
|
|
|
|
# Fake data_utils.Copy
|
|
class FakeCopy(object):
|
|
|
|
def run(self):
|
|
pass
|
|
|
|
def get_progress(self):
|
|
return {'total_progress': 100}
|
|
|
|
self.mock_copy = self.mock_object(
|
|
data_utils, 'Copy', mock.Mock(return_value=FakeCopy()))
|
|
|
|
# This is the fake client to use.
|
|
self.mock_client = mock.Mock()
|
|
|
|
# Take over the hpe3parclient module and stub the constructor.
|
|
hpe3parclient = sys.modules['hpe3parclient']
|
|
hpe3parclient.version_tuple = CLIENT_VERSION_MIN_OK
|
|
|
|
# Need a fake constructor to return the fake client.
|
|
# This is also be used for constructor error tests.
|
|
self.mock_object(hpe3parclient.file_client, 'HPE3ParFilePersonaClient')
|
|
self.mock_client_constructor = (
|
|
hpe3parclient.file_client.HPE3ParFilePersonaClient
|
|
)
|
|
self.mock_client = self.mock_client_constructor()
|
|
|
|
# Set the mediator to use in tests.
|
|
self.mediator = hpe3parmediator.HPE3ParMediator(
|
|
hpe3par_username=constants.USERNAME,
|
|
hpe3par_password=constants.PASSWORD,
|
|
hpe3par_api_url=constants.API_URL,
|
|
hpe3par_debug=constants.EXPECTED_HPE_DEBUG,
|
|
hpe3par_san_ip=constants.EXPECTED_IP_1234,
|
|
hpe3par_san_login=constants.SAN_LOGIN,
|
|
hpe3par_san_password=constants.SAN_PASSWORD,
|
|
hpe3par_san_ssh_port=constants.PORT,
|
|
hpe3par_cifs_admin_access_username=constants.USERNAME,
|
|
hpe3par_cifs_admin_access_password=constants.PASSWORD,
|
|
hpe3par_cifs_admin_access_domain=constants.EXPECTED_CIFS_DOMAIN,
|
|
hpe3par_share_mount_path=constants.EXPECTED_MOUNT_PATH,
|
|
ssh_conn_timeout=constants.TIMEOUT,
|
|
my_ip=constants.EXPECTED_MY_IP)
|
|
|
|
def test_mediator_no_client(self):
|
|
"""Test missing hpe3parclient error."""
|
|
|
|
mock_log = self.mock_object(hpe3parmediator, 'LOG')
|
|
self.mock_object(hpe3parmediator.HPE3ParMediator, 'no_client', None)
|
|
|
|
self.assertRaises(exception.HPE3ParInvalidClient,
|
|
self.mediator.do_setup)
|
|
|
|
mock_log.error.assert_called_once_with(mock.ANY)
|
|
|
|
def test_mediator_setup_client_init_error(self):
|
|
"""Any client init exceptions should result in a ManilaException."""
|
|
|
|
self.mock_client_constructor.side_effect = (
|
|
Exception('Any exception. E.g., bad version or some other '
|
|
'non-Manila Exception.'))
|
|
self.assertRaises(exception.ManilaException, self.mediator.do_setup)
|
|
|
|
def test_mediator_setup_client_ssh_error(self):
|
|
|
|
# This could be anything the client comes up with, but the
|
|
# mediator should turn it into a ManilaException.
|
|
non_manila_exception = Exception('non-manila-except')
|
|
self.mock_client.setSSHOptions.side_effect = non_manila_exception
|
|
|
|
self.assertRaises(exception.ManilaException, self.mediator.do_setup)
|
|
self.mock_client.assert_has_calls(
|
|
[mock.call.setSSHOptions(constants.EXPECTED_IP_1234,
|
|
constants.SAN_LOGIN,
|
|
constants.SAN_PASSWORD,
|
|
port=constants.PORT,
|
|
conn_timeout=constants.TIMEOUT)])
|
|
|
|
def test_mediator_vfs_exception(self):
|
|
"""Backend exception during get_vfs."""
|
|
|
|
self.init_mediator()
|
|
self.mock_client.getvfs.side_effect = Exception('non-manila-except')
|
|
self.assertRaises(exception.ManilaException,
|
|
self.mediator.get_vfs,
|
|
fpg=constants.EXPECTED_FPG)
|
|
expected_calls = [
|
|
mock.call.getvfs(fpg=constants.EXPECTED_FPG, vfs=None),
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_vfs_not_found(self):
|
|
"""VFS not found."""
|
|
self.init_mediator()
|
|
self.mock_client.getvfs.return_value = {'total': 0}
|
|
self.assertRaises(exception.ManilaException,
|
|
self.mediator.get_vfs,
|
|
fpg=constants.EXPECTED_FPG)
|
|
expected_calls = [
|
|
mock.call.getvfs(fpg=constants.EXPECTED_FPG, vfs=None),
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
@ddt.data((constants.EXPECTED_CLIENT_GET_VFS_RETURN_VALUE,
|
|
constants.EXPECTED_MEDIATOR_GET_VFS_RET_VAL),
|
|
(constants.EXPECTED_CLIENT_GET_VFS_RETURN_VALUE_MULTI,
|
|
constants.EXPECTED_MEDIATOR_GET_VFS_RET_VAL_MULTI))
|
|
@ddt.unpack
|
|
def test_mediator_get_vfs(self, get_vfs_val, exp_vfs_val):
|
|
"""VFS not found."""
|
|
self.init_mediator()
|
|
self.mock_client.getvfs.return_value = get_vfs_val
|
|
|
|
ret_val = self.mediator.get_vfs(constants.EXPECTED_FPG)
|
|
self.assertEqual(exp_vfs_val, ret_val)
|
|
expected_calls = [
|
|
mock.call.getvfs(fpg=constants.EXPECTED_FPG, vfs=None),
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def init_mediator(self):
|
|
"""Basic mediator setup for re-use with tests that need one."""
|
|
|
|
self.mock_client.getWsApiVersion.return_value = {
|
|
'build': TEST_WSAPI_VERSION_STR,
|
|
}
|
|
|
|
self.mock_client.getvfs.return_value = {
|
|
'total': 1,
|
|
'members': [{'vfsname': constants.EXPECTED_VFS}]
|
|
}
|
|
self.mock_client.getfshare.return_value = {
|
|
'total': 1,
|
|
'members': [
|
|
{'fstoreName': constants.EXPECTED_FSTORE,
|
|
'shareName': constants.EXPECTED_SHARE_ID,
|
|
'shareDir': constants.EXPECTED_SHARE_PATH,
|
|
'share_proto': constants.NFS,
|
|
'sharePath': constants.EXPECTED_SHARE_PATH,
|
|
'comment': constants.EXPECTED_COMMENT,
|
|
}]
|
|
}
|
|
self.mock_client.setfshare.return_value = []
|
|
self.mock_client.setfsquota.return_value = []
|
|
self.mock_client.getfsquota.return_value = constants.GET_FSQUOTA
|
|
self.mediator.do_setup()
|
|
|
|
def test_mediator_setup_success(self):
|
|
"""Do a mediator setup without errors."""
|
|
|
|
self.init_mediator()
|
|
self.assertIsNotNone(self.mediator._client)
|
|
|
|
expected_calls = [
|
|
mock.call.setSSHOptions(constants.EXPECTED_IP_1234,
|
|
constants.SAN_LOGIN,
|
|
constants.SAN_PASSWORD,
|
|
port=constants.PORT,
|
|
conn_timeout=constants.TIMEOUT),
|
|
mock.call.getWsApiVersion(),
|
|
mock.call.debug_rest(constants.EXPECTED_HPE_DEBUG)
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_client_login_error(self):
|
|
"""Test exception during login."""
|
|
self.init_mediator()
|
|
|
|
self.mock_client.login.side_effect = constants.FAKE_EXCEPTION
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator._wsapi_login)
|
|
|
|
expected_calls = [mock.call.login(constants.USERNAME,
|
|
constants.PASSWORD)]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_client_logout_error(self):
|
|
"""Test exception during logout."""
|
|
self.init_mediator()
|
|
|
|
mock_log = self.mock_object(hpe3parmediator, 'LOG')
|
|
fake_exception = constants.FAKE_EXCEPTION
|
|
self.mock_client.http.unauthenticate.side_effect = fake_exception
|
|
|
|
self.mediator._wsapi_logout()
|
|
|
|
# Warning is logged (no exception thrown).
|
|
self.assertTrue(mock_log.warning.called)
|
|
expected_calls = [mock.call.http.unauthenticate()]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_client_version_unsupported(self):
|
|
"""Try a client with version less than minimum."""
|
|
|
|
self.hpe3parclient = sys.modules['hpe3parclient']
|
|
self.hpe3parclient.version_tuple = (CLIENT_VERSION_MIN_OK[0],
|
|
CLIENT_VERSION_MIN_OK[1],
|
|
CLIENT_VERSION_MIN_OK[2] - 1)
|
|
mock_log = self.mock_object(hpe3parmediator, 'LOG')
|
|
|
|
self.assertRaises(exception.HPE3ParInvalidClient,
|
|
self.init_mediator)
|
|
|
|
mock_log.error.assert_called_once_with(mock.ANY)
|
|
|
|
def test_mediator_client_version_supported(self):
|
|
"""Try a client with a version greater than the minimum."""
|
|
|
|
# The setup success already tests the min version. Try version > min.
|
|
self.hpe3parclient = sys.modules['hpe3parclient']
|
|
self.hpe3parclient.version_tuple = (CLIENT_VERSION_MIN_OK[0],
|
|
CLIENT_VERSION_MIN_OK[1],
|
|
CLIENT_VERSION_MIN_OK[2] + 1)
|
|
self.init_mediator()
|
|
expected_calls = [
|
|
mock.call.setSSHOptions(constants.EXPECTED_IP_1234,
|
|
constants.SAN_LOGIN,
|
|
constants.SAN_PASSWORD,
|
|
port=constants.PORT,
|
|
conn_timeout=constants.TIMEOUT),
|
|
mock.call.getWsApiVersion(),
|
|
mock.call.debug_rest(constants.EXPECTED_HPE_DEBUG)
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_client_version_exception(self):
|
|
"""Test the getWsApiVersion exception handling."""
|
|
|
|
self.mock_client.getWsApiVersion.side_effect = constants.FAKE_EXCEPTION
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.init_mediator)
|
|
|
|
def test_mediator_client_version_bad_return_value(self):
|
|
"""Test the getWsApiVersion exception handling with bad value."""
|
|
|
|
# Expecting a dict with 'build' in it. This would fail badly.
|
|
self.mock_client.getWsApiVersion.return_value = 'bogus'
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.do_setup)
|
|
|
|
def get_expected_calls_for_create_share(self,
|
|
client_version,
|
|
expected_fpg,
|
|
expected_vfsname,
|
|
expected_protocol,
|
|
extra_specs,
|
|
expected_project_id,
|
|
expected_share_id):
|
|
expected_sharedir = expected_share_id
|
|
|
|
createfshare_kwargs = dict(comment=mock.ANY,
|
|
fpg=expected_fpg,
|
|
sharedir=expected_sharedir,
|
|
fstore=expected_project_id)
|
|
|
|
if expected_protocol == constants.NFS_LOWER:
|
|
|
|
createfshare_kwargs['clientip'] = '127.0.0.1'
|
|
|
|
# Options from extra-specs.
|
|
opt_string = extra_specs.get('hpe3par:nfs_options', [])
|
|
opt_list = opt_string.split(',')
|
|
# Options that the mediator adds.
|
|
nfs_options = ['rw', 'no_root_squash', 'insecure']
|
|
nfs_options += opt_list
|
|
expected_options = ','.join(nfs_options)
|
|
|
|
createfshare_kwargs['options'] = OptionMatcher(
|
|
self.assertListEqual, expected_options)
|
|
|
|
expected_calls = [
|
|
mock.call.createfstore(expected_vfsname, expected_project_id,
|
|
comment=mock.ANY,
|
|
fpg=expected_fpg),
|
|
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,
|
|
**createfshare_kwargs),
|
|
mock.call.getfshare(expected_protocol, expected_share_id,
|
|
fpg=expected_fpg, vfs=expected_vfsname,
|
|
fstore=expected_project_id)]
|
|
else:
|
|
|
|
smb_opts = (hpe3parmediator.ACCESS_BASED_ENUM,
|
|
hpe3parmediator.CONTINUOUS_AVAIL,
|
|
hpe3parmediator.CACHE)
|
|
|
|
for smb_opt in smb_opts:
|
|
opt_value = extra_specs.get('hpe3par:smb_%s' % smb_opt)
|
|
if opt_value:
|
|
opt_key = hpe3parmediator.SMB_EXTRA_SPECS_MAP[smb_opt]
|
|
createfshare_kwargs[opt_key] = opt_value
|
|
|
|
expected_calls = [
|
|
mock.call.createfstore(expected_vfsname, expected_project_id,
|
|
comment=mock.ANY,
|
|
fpg=expected_fpg),
|
|
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,
|
|
**createfshare_kwargs),
|
|
mock.call.getfshare(expected_protocol, expected_share_id,
|
|
fpg=expected_fpg, vfs=expected_vfsname,
|
|
fstore=expected_project_id)]
|
|
return expected_calls
|
|
|
|
@staticmethod
|
|
def _build_smb_extra_specs(**kwargs):
|
|
extra_specs = {'driver_handles_share_servers': False}
|
|
for k, v in kwargs.items():
|
|
extra_specs['hpe3par:smb_%s' % k] = v
|
|
return extra_specs
|
|
|
|
@ddt.data(((4, 0, 0), None, None, None),
|
|
((4, 0, 0), 'true', None, None),
|
|
((4, 0, 0), None, 'false', None),
|
|
((4, 0, 0), None, 'false', None),
|
|
((4, 0, 0), None, None, 'optimized'),
|
|
((4, 0, 0), 'true', 'false', 'optimized'))
|
|
@ddt.unpack
|
|
def test_mediator_create_cifs_share(self, client_version, abe, ca, cache):
|
|
self.hpe3parclient = sys.modules['hpe3parclient']
|
|
self.hpe3parclient.version_tuple = client_version
|
|
self.init_mediator()
|
|
|
|
self.mock_client.getfshare.return_value = {
|
|
'message': None,
|
|
'total': 1,
|
|
'members': [{'shareName': constants.EXPECTED_SHARE_NAME}]
|
|
}
|
|
|
|
extra_specs = self._build_smb_extra_specs(access_based_enum=abe,
|
|
continuous_avail=ca,
|
|
cache=cache)
|
|
|
|
location = self.mediator.create_share(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.CIFS,
|
|
extra_specs,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
size=constants.EXPECTED_SIZE_1)
|
|
|
|
self.assertEqual(constants.EXPECTED_SHARE_NAME, location)
|
|
|
|
expected_calls = self.get_expected_calls_for_create_share(
|
|
client_version,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
constants.SMB_LOWER,
|
|
extra_specs,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID)
|
|
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
@ddt.data('ro',
|
|
'rw',
|
|
'no_root_squash',
|
|
'root_squash',
|
|
'secure',
|
|
'insecure',
|
|
'hide,insecure,no_wdelay,ro,bogus,root_squash,test')
|
|
def test_mediator_create_nfs_share_bad_options(self, nfs_options):
|
|
self.init_mediator()
|
|
|
|
extra_specs = {'hpe3par:nfs_options': nfs_options}
|
|
|
|
self.assertRaises(exception.InvalidInput,
|
|
self.mediator.create_share,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS.lower(),
|
|
extra_specs,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
size=constants.EXPECTED_SIZE_1)
|
|
|
|
self.assertFalse(self.mock_client.createfshare.called)
|
|
|
|
@ddt.data('sync',
|
|
'no_wdelay,sec=sys,hide,sync')
|
|
def test_mediator_create_nfs_share(self, nfs_options):
|
|
self.init_mediator()
|
|
|
|
self.mock_client.getfshare.return_value = {
|
|
'message': None,
|
|
'total': 1,
|
|
'members': [{'sharePath': constants.EXPECTED_SHARE_PATH}]
|
|
}
|
|
|
|
extra_specs = {'hpe3par:nfs_options': nfs_options}
|
|
|
|
location = self.mediator.create_share(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS.lower(),
|
|
extra_specs,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
size=constants.EXPECTED_SIZE_1)
|
|
|
|
self.assertEqual(constants.EXPECTED_SHARE_PATH, location)
|
|
|
|
expected_calls = self.get_expected_calls_for_create_share(
|
|
hpe3parmediator.MIN_CLIENT_VERSION,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
constants.NFS.lower(),
|
|
extra_specs,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID)
|
|
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_create_nfs_share_get_exception(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_client.getfshare.side_effect = constants.FAKE_EXCEPTION
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.create_share,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS.lower(),
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
size=constants.EXPECTED_SIZE_1)
|
|
|
|
@ddt.data(0, 2)
|
|
def test_mediator_create_nfs_share_get_fail(self, count):
|
|
self.init_mediator()
|
|
|
|
self.mock_client.getfshare.return_value = {'total': count}
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.create_share,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS.lower(),
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
size=constants.EXPECTED_SIZE_1)
|
|
|
|
@ddt.data(True, False)
|
|
def test_mediator_create_cifs_share_from_snapshot(self, require_cifs_ip):
|
|
self.init_mediator()
|
|
self.mediator.hpe3par_require_cifs_ip = require_cifs_ip
|
|
|
|
self.mock_client.getfsnap.return_value = {
|
|
'message': None,
|
|
'total': 1,
|
|
'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_EXTRA_SPECS,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.EXPECTED_SNAP_ID,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
[constants.EXPECTED_IP_10203040])
|
|
|
|
self.assertEqual(constants.EXPECTED_SHARE_ID, location)
|
|
|
|
expected_kwargs_ro = {
|
|
'comment': mock.ANY,
|
|
'fpg': constants.EXPECTED_FPG,
|
|
'fstore': constants.EXPECTED_FSTORE,
|
|
}
|
|
expected_kwargs_rw = expected_kwargs_ro.copy()
|
|
|
|
expected_kwargs_ro['sharedir'] = '.snapshot/%s/%s' % (
|
|
constants.EXPECTED_SNAP_ID, constants.EXPECTED_SHARE_ID)
|
|
expected_kwargs_rw['sharedir'] = constants.EXPECTED_SHARE_ID
|
|
|
|
if require_cifs_ip:
|
|
expected_kwargs_ro['allowip'] = constants.EXPECTED_MY_IP
|
|
expected_kwargs_rw['allowip'] = (
|
|
','.join((constants.EXPECTED_MY_IP,
|
|
constants.EXPECTED_IP_127)))
|
|
|
|
expected_calls = [
|
|
mock.call.getfsnap('*_%s' % constants.EXPECTED_SNAP_ID,
|
|
vfs=constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG,
|
|
pat=True,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
mock.call.createfshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
**expected_kwargs_ro),
|
|
mock.call.getfshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_SHARE_ID,
|
|
fpg=constants.EXPECTED_FPG,
|
|
vfs=constants.EXPECTED_VFS,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
mock.call.createfshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
**expected_kwargs_rw),
|
|
mock.call.getfshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_SHARE_ID,
|
|
fpg=constants.EXPECTED_FPG,
|
|
vfs=constants.EXPECTED_VFS,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
mock.call.setfshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
allowperm=constants.ADD_USERNAME,
|
|
comment=mock.ANY,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
mock.call.setfshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
allowperm=constants.ADD_USERNAME,
|
|
comment=mock.ANY,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
mock.call.setfshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SUPER_SHARE,
|
|
allowperm=constants.DROP_USERNAME,
|
|
comment=mock.ANY,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
mock.call.removefshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
]
|
|
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_create_cifs_share_from_snapshot_ro(self):
|
|
self.init_mediator()
|
|
|
|
# RO because CIFS admin access username is not configured
|
|
self.mediator.hpe3par_cifs_admin_access_username = None
|
|
|
|
self.mock_client.getfsnap.return_value = {
|
|
'message': None,
|
|
'total': 1,
|
|
'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_EXTRA_SPECS,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.EXPECTED_SNAP_ID,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
[constants.EXPECTED_IP_10203040],
|
|
comment=constants.EXPECTED_COMMENT)
|
|
|
|
self.assertEqual(constants.EXPECTED_SHARE_ID, location)
|
|
|
|
share_dir = '.snapshot/%s/%s' % (
|
|
constants.EXPECTED_SNAP_ID, constants.EXPECTED_SHARE_ID)
|
|
|
|
expected_kwargs_ro = {
|
|
'comment': constants.EXPECTED_COMMENT,
|
|
'fpg': constants.EXPECTED_FPG,
|
|
'fstore': constants.EXPECTED_FSTORE,
|
|
'sharedir': share_dir,
|
|
}
|
|
|
|
self.mock_client.createfshare.assert_called_once_with(
|
|
constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
**expected_kwargs_ro
|
|
)
|
|
|
|
def test_mediator_create_nfs_share_from_snapshot(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_client.getfsnap.return_value = {
|
|
'message': None,
|
|
'total': 1,
|
|
'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_EXTRA_SPECS,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.EXPECTED_SNAP_ID,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
[constants.EXPECTED_IP_10203040])
|
|
|
|
self.assertEqual(constants.EXPECTED_SHARE_PATH, location)
|
|
|
|
expected_calls = [
|
|
mock.call.getfsnap('*_%s' % constants.EXPECTED_SNAP_ID,
|
|
vfs=constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG,
|
|
pat=True,
|
|
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/%s' %
|
|
(constants.EXPECTED_SNAP_ID,
|
|
constants.EXPECTED_SHARE_ID),
|
|
fstore=constants.EXPECTED_FSTORE,
|
|
clientip=constants.EXPECTED_MY_IP,
|
|
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_FSTORE),
|
|
mock.call.createfshare(constants.NFS_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
comment=mock.ANY,
|
|
fpg=constants.EXPECTED_FPG,
|
|
sharedir=constants.EXPECTED_SHARE_ID,
|
|
fstore=constants.EXPECTED_FSTORE,
|
|
clientip=','.join((
|
|
constants.EXPECTED_MY_IP,
|
|
constants.EXPECTED_IP_127)),
|
|
options='rw,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_FSTORE),
|
|
mock.call.getfshare(constants.NFS_LOWER,
|
|
constants.EXPECTED_SHARE_ID,
|
|
fpg=constants.EXPECTED_FPG,
|
|
vfs=constants.EXPECTED_VFS,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
mock.call.setfshare(constants.NFS_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
clientip=''.join(('-',
|
|
constants.EXPECTED_MY_IP)),
|
|
comment=mock.ANY,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
mock.call.removefshare(constants.NFS_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
]
|
|
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_create_share_from_snap_copy_incomplete(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_client.getfsnap.return_value = {
|
|
'message': None,
|
|
'total': 1,
|
|
'members': [{'snapName': constants.EXPECTED_SNAP_ID,
|
|
'fstoreName': constants.EXPECTED_FSTORE}]
|
|
}
|
|
|
|
mock_bad_copy = mock.Mock()
|
|
mock_bad_copy.get_progress.return_value = {'total_progress': 99}
|
|
self.mock_object(
|
|
data_utils, 'Copy', mock.Mock(return_value=mock_bad_copy))
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.create_share_from_snapshot,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.EXPECTED_SNAP_ID,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
[constants.EXPECTED_IP_10203040])
|
|
self.assertTrue(mock_bad_copy.run.called)
|
|
self.assertTrue(mock_bad_copy.get_progress.called)
|
|
|
|
def test_mediator_create_share_from_snap_copy_exception(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_client.getfsnap.return_value = {
|
|
'message': None,
|
|
'total': 1,
|
|
'members': [{'snapName': constants.EXPECTED_SNAP_ID,
|
|
'fstoreName': constants.EXPECTED_FSTORE}]
|
|
}
|
|
|
|
mock_bad_copy = mock.Mock()
|
|
mock_bad_copy.run.side_effect = Exception('run exception')
|
|
self.mock_object(
|
|
data_utils, 'Copy', mock.Mock(return_value=mock_bad_copy))
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.create_share_from_snapshot,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.EXPECTED_SNAP_ID,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
[constants.EXPECTED_IP_10203040])
|
|
self.assertTrue(mock_bad_copy.run.called)
|
|
|
|
def test_mediator_create_share_from_snap_not_found(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_client.getfsnap.return_value = {
|
|
'message': None,
|
|
'total': 0,
|
|
'members': []
|
|
}
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.create_share_from_snapshot,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.EXPECTED_SNAP_ID,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
[constants.EXPECTED_IP_10203040])
|
|
|
|
def test_mediator_delete_nfs_share(self):
|
|
self.init_mediator()
|
|
|
|
share_id = 'foo'
|
|
osf_share_id = '-'.join(('osf', share_id))
|
|
osf_ro_share_id = '-ro-'.join(('osf', share_id))
|
|
fstore = osf_share_id
|
|
|
|
self.mock_object(self.mediator,
|
|
'_find_fstore',
|
|
mock.Mock(return_value=fstore))
|
|
self.mock_object(self.mediator, '_delete_file_tree')
|
|
self.mock_object(self.mediator, '_update_capacity_quotas')
|
|
|
|
self.mediator.delete_share(constants.EXPECTED_PROJECT_ID,
|
|
share_id,
|
|
constants.EXPECTED_SIZE_1,
|
|
constants.NFS,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_IP)
|
|
|
|
expected_calls = [
|
|
mock.call.removefshare(constants.NFS_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
osf_share_id,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=fstore),
|
|
mock.call.removefshare(constants.NFS_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
osf_ro_share_id,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=fstore),
|
|
mock.call.removefstore(constants.EXPECTED_VFS,
|
|
fstore,
|
|
fpg=constants.EXPECTED_FPG),
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
self.assertFalse(self.mediator._delete_file_tree.called)
|
|
self.assertFalse(self.mediator._update_capacity_quotas.called)
|
|
|
|
def test_mediator_delete_share_not_found(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_object(self.mediator,
|
|
'_find_fstore',
|
|
mock.Mock(return_value=None))
|
|
self.mock_object(self.mediator, '_delete_file_tree')
|
|
self.mock_object(self.mediator, '_update_capacity_quotas')
|
|
|
|
self.mediator.delete_share(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.EXPECTED_SIZE_1,
|
|
constants.CIFS,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_IP_10203040)
|
|
|
|
self.assertFalse(self.mock_client.removefshare.called)
|
|
|
|
self.assertFalse(self.mediator._delete_file_tree.called)
|
|
self.assertFalse(self.mediator._update_capacity_quotas.called)
|
|
|
|
def test_mediator_delete_nfs_share_only_readonly(self):
|
|
self.init_mediator()
|
|
|
|
fstores = (None, constants.EXPECTED_FSTORE)
|
|
self.mock_object(self.mediator,
|
|
'_find_fstore',
|
|
mock.Mock(side_effect=fstores))
|
|
self.mock_object(self.mediator, '_delete_file_tree')
|
|
self.mock_object(self.mediator, '_update_capacity_quotas')
|
|
|
|
self.mediator.delete_share(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.EXPECTED_SIZE_1,
|
|
constants.NFS,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_IP_10203040)
|
|
|
|
self.mock_client.removefshare.assert_called_once_with(
|
|
constants.NFS_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE
|
|
)
|
|
|
|
self.assertFalse(self.mediator._delete_file_tree.called)
|
|
self.assertFalse(self.mediator._update_capacity_quotas.called)
|
|
|
|
def test_mediator_delete_share_exception(self):
|
|
self.init_mediator()
|
|
self.mock_client.removefshare.side_effect = Exception(
|
|
'removeshare fail.')
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.delete_share,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.EXPECTED_SIZE_1,
|
|
constants.CIFS,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_IP_10203040)
|
|
|
|
expected_calls = [
|
|
mock.call.removefshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
]
|
|
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_delete_fstore_exception(self):
|
|
self.init_mediator()
|
|
self.mock_object(self.mediator,
|
|
'_find_fstore',
|
|
mock.Mock(return_value=constants.EXPECTED_SHARE_ID))
|
|
self.mock_object(self.mediator, '_delete_file_tree')
|
|
self.mock_object(self.mediator, '_update_capacity_quotas')
|
|
self.mock_client.removefstore.side_effect = Exception(
|
|
'removefstore fail.')
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.delete_share,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.SHARE_ID,
|
|
constants.EXPECTED_SIZE_1,
|
|
constants.CIFS,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_IP_10203040)
|
|
|
|
expected_calls = [
|
|
mock.call.removefshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_SHARE_ID),
|
|
mock.call.removefshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID_RO,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_SHARE_ID),
|
|
mock.call.removefstore(constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
fpg=constants.EXPECTED_FPG),
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
self.assertFalse(self.mediator._delete_file_tree.called)
|
|
self.assertFalse(self.mediator._update_capacity_quotas.called)
|
|
|
|
def test_mediator_delete_file_tree_exception(self):
|
|
self.init_mediator()
|
|
mock_log = self.mock_object(hpe3parmediator, 'LOG')
|
|
self.mock_object(self.mediator,
|
|
'_find_fstore',
|
|
mock.Mock(return_value=constants.EXPECTED_FSTORE))
|
|
self.mock_object(self.mediator,
|
|
'_delete_file_tree',
|
|
mock.Mock(side_effect=Exception('test')))
|
|
self.mock_object(self.mediator, '_update_capacity_quotas')
|
|
|
|
self.mediator.delete_share(constants.EXPECTED_PROJECT_ID,
|
|
constants.SHARE_ID,
|
|
constants.EXPECTED_SIZE_1,
|
|
constants.CIFS,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_IP_10203040)
|
|
|
|
expected_calls = [
|
|
mock.call.removefshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
mock.call.removefshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID_RO,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
self.assertTrue(self.mediator._delete_file_tree.called)
|
|
self.assertFalse(self.mediator._update_capacity_quotas.called)
|
|
mock_log.warning.assert_called_once_with(mock.ANY, mock.ANY)
|
|
|
|
def test_mediator_delete_cifs_share(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_object(self.mediator,
|
|
'_find_fstore',
|
|
mock.Mock(return_value=constants.EXPECTED_FSTORE))
|
|
self.mock_object(self.mediator,
|
|
'_create_mount_directory',
|
|
mock.Mock(return_value={}))
|
|
self.mock_object(self.mediator,
|
|
'_mount_super_share',
|
|
mock.Mock(return_value={}))
|
|
self.mock_object(self.mediator,
|
|
'_delete_share_directory',
|
|
mock.Mock(return_value={}))
|
|
self.mock_object(self.mediator,
|
|
'_unmount_share',
|
|
mock.Mock(return_value={}))
|
|
self.mock_object(self.mediator,
|
|
'_update_capacity_quotas',
|
|
mock.Mock(return_value={}))
|
|
|
|
self.mediator.delete_share(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.EXPECTED_SIZE_1,
|
|
constants.CIFS,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_IP_10203040)
|
|
|
|
expected_calls = [
|
|
mock.call.removefshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
mock.call.createfshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SUPER_SHARE,
|
|
allowip=constants.EXPECTED_MY_IP,
|
|
comment=(
|
|
constants.EXPECTED_SUPER_SHARE_COMMENT),
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE,
|
|
sharedir=''),
|
|
mock.call.setfshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SUPER_SHARE,
|
|
comment=(
|
|
constants.EXPECTED_SUPER_SHARE_COMMENT),
|
|
allowperm=(
|
|
'+' + constants.USERNAME + ':fullcontrol'),
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
expected_mount_path = constants.EXPECTED_MOUNT_PATH + (
|
|
constants.EXPECTED_SHARE_ID)
|
|
|
|
expected_share_path = '/'.join((expected_mount_path,
|
|
constants.EXPECTED_SHARE_ID))
|
|
self.mediator._create_mount_directory.assert_called_once_with(
|
|
expected_mount_path)
|
|
self.mediator._mount_super_share.assert_called_once_with(
|
|
constants.SMB_LOWER,
|
|
expected_mount_path,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_FSTORE,
|
|
constants.EXPECTED_IP_10203040)
|
|
self.mediator._delete_share_directory.assert_has_calls([
|
|
mock.call(expected_share_path),
|
|
mock.call(expected_mount_path),
|
|
])
|
|
self.mediator._unmount_share.assert_called_once_with(
|
|
expected_mount_path)
|
|
self.mediator._update_capacity_quotas.assert_called_once_with(
|
|
constants.EXPECTED_FSTORE,
|
|
0,
|
|
constants.EXPECTED_SIZE_1,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
def test_mediator_delete_cifs_share_and_fstore(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_object(self.mediator,
|
|
'_find_fstore',
|
|
mock.Mock(return_value=constants.EXPECTED_SHARE_ID))
|
|
self.mock_object(self.mediator, '_delete_file_tree')
|
|
self.mock_object(self.mediator, '_update_capacity_quotas')
|
|
|
|
self.mediator.delete_share(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.EXPECTED_SIZE_1,
|
|
constants.CIFS,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_IP_10203040)
|
|
|
|
expected_calls = [
|
|
mock.call.removefshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_SHARE_ID),
|
|
mock.call.removefstore(constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
fpg=constants.EXPECTED_FPG),
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
self.assertFalse(self.mediator._delete_file_tree.called)
|
|
self.assertFalse(self.mediator._update_capacity_quotas.called)
|
|
|
|
def test_mediator_delete_share_with_fstore_per_share_false(self):
|
|
self.init_mediator()
|
|
self.mediator.hpe3par_fstore_per_share = False
|
|
share_size = int(constants.EXPECTED_SIZE_1)
|
|
fstore_init_size = int(
|
|
constants.GET_FSQUOTA['members'][0]['hardBlock'])
|
|
|
|
expected_capacity = (0 - share_size) * units.Ki + fstore_init_size
|
|
self.mock_object(self.mediator,
|
|
'_find_fstore',
|
|
mock.Mock(return_value=constants.EXPECTED_FSTORE))
|
|
self.mock_object(self.mediator,
|
|
'_create_mount_directory',
|
|
mock.Mock(return_value={}))
|
|
self.mock_object(self.mediator,
|
|
'_mount_super_share',
|
|
mock.Mock(return_value={}))
|
|
self.mock_object(self.mediator,
|
|
'_delete_share_directory',
|
|
mock.Mock(return_value={}))
|
|
self.mock_object(self.mediator,
|
|
'_unmount_share',
|
|
mock.Mock(return_value={}))
|
|
|
|
self.mediator.delete_share(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.EXPECTED_SIZE_1,
|
|
constants.CIFS,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_IP_10203040)
|
|
|
|
expected_calls = [
|
|
mock.call.removefshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
mock.call.createfshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SUPER_SHARE,
|
|
allowip=constants.EXPECTED_MY_IP,
|
|
comment=(
|
|
constants.EXPECTED_SUPER_SHARE_COMMENT),
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE,
|
|
sharedir=''),
|
|
mock.call.setfshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SUPER_SHARE,
|
|
comment=(
|
|
constants.EXPECTED_SUPER_SHARE_COMMENT),
|
|
allowperm=(
|
|
'+' + constants.USERNAME + ':fullcontrol'),
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
mock.call.getfsquota(fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE,
|
|
vfs=constants.EXPECTED_VFS),
|
|
mock.call.setfsquota(constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE,
|
|
scapacity=str(expected_capacity),
|
|
hcapacity=str(expected_capacity))]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
expected_mount_path = constants.EXPECTED_MOUNT_PATH + (
|
|
constants.EXPECTED_SHARE_ID)
|
|
self.mediator._create_mount_directory.assert_called_with(
|
|
expected_mount_path)
|
|
self.mediator._mount_super_share.assert_called_with(
|
|
constants.SMB_LOWER, expected_mount_path, constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS, constants.EXPECTED_FSTORE,
|
|
constants.EXPECTED_IP_10203040)
|
|
self.mediator._delete_share_directory.assert_called_with(
|
|
expected_mount_path)
|
|
self.mediator._unmount_share.assert_called_with(
|
|
expected_mount_path)
|
|
|
|
def test_mediator_create_snapshot(self):
|
|
self.init_mediator()
|
|
|
|
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_PROJECT_ID,
|
|
constants.EXPECTED_SNAP_NAME,
|
|
fpg=constants.EXPECTED_FPG)
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_create_snapshot_not_allowed(self):
|
|
self.init_mediator()
|
|
self.mock_client.getfshare.return_value['members'][0]['shareDir'] = (
|
|
None)
|
|
self.mock_client.getfshare.return_value['members'][0]['sharePath'] = (
|
|
'foo/.snapshot/foo')
|
|
|
|
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)
|
|
|
|
def test_mediator_create_snapshot_share_not_found(self):
|
|
self.init_mediator()
|
|
|
|
mock_find_fshare = self.mock_object(self.mediator,
|
|
'_find_fshare',
|
|
mock.Mock(return_value=None))
|
|
|
|
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)
|
|
|
|
mock_find_fshare.assert_called_once_with(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
def test_mediator_create_snapshot_backend_exception(self):
|
|
self.init_mediator()
|
|
|
|
# createfsnap exception
|
|
self.mock_client.createfsnap.side_effect = Exception(
|
|
'createfsnap fail.')
|
|
|
|
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)
|
|
|
|
def test_mediator_delete_snapshot(self):
|
|
self.init_mediator()
|
|
|
|
expected_name_from_array = 'name-from-array'
|
|
|
|
self.mock_client.getfsnap.return_value = {
|
|
'total': 1,
|
|
'members': [
|
|
{
|
|
'snapName': expected_name_from_array,
|
|
'fstoreName': constants.EXPECTED_PROJECT_ID,
|
|
}
|
|
],
|
|
'message': None
|
|
}
|
|
|
|
self.mock_client.getfshare.side_effect = [
|
|
# some typical independent NFS share (path) and SMB share (dir)
|
|
{
|
|
'total': 1,
|
|
'members': [{'sharePath': '/anyfpg/anyvfs/anyfstore'}]
|
|
},
|
|
{
|
|
'total': 1,
|
|
'members': [{'shareDir': []}],
|
|
}
|
|
]
|
|
|
|
self.mediator.delete_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.getfsnap('*_%s' % constants.EXPECTED_SNAP_NAME,
|
|
vfs=constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG,
|
|
pat=True,
|
|
fstore=constants.EXPECTED_PROJECT_ID),
|
|
mock.call.getfshare(constants.NFS_LOWER,
|
|
fpg=constants.EXPECTED_FPG,
|
|
vfs=constants.EXPECTED_VFS,
|
|
fstore=constants.EXPECTED_PROJECT_ID),
|
|
mock.call.getfshare(constants.SMB_LOWER,
|
|
fpg=constants.EXPECTED_FPG,
|
|
vfs=constants.EXPECTED_VFS,
|
|
fstore=constants.EXPECTED_PROJECT_ID),
|
|
mock.call.removefsnap(constants.EXPECTED_VFS,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
fpg=constants.EXPECTED_FPG,
|
|
snapname=expected_name_from_array),
|
|
mock.call.startfsnapclean(constants.EXPECTED_FPG,
|
|
reclaimStrategy='maxspeed')
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_delete_snapshot_not_found(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_client.getfsnap.return_value = {
|
|
'total': 0,
|
|
'members': [],
|
|
}
|
|
|
|
self.mediator.delete_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.getfsnap('*_%s' % constants.EXPECTED_SNAP_NAME,
|
|
vfs=constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG,
|
|
pat=True,
|
|
fstore=constants.EXPECTED_SHARE_ID),
|
|
]
|
|
|
|
# Code coverage for early exit when nothing to delete.
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
self.assertFalse(self.mock_client.getfshare.called)
|
|
self.assertFalse(self.mock_client.removefsnap.called)
|
|
self.assertFalse(self.mock_client.startfsnapclean.called)
|
|
|
|
def test_mediator_delete_snapshot_shared_nfs(self):
|
|
self.init_mediator()
|
|
|
|
# Mock a share under this snapshot for NFS
|
|
snapshot_dir = '.snapshot/DT_%s' % constants.EXPECTED_SNAP_NAME
|
|
snapshot_path = '%s/%s' % (constants.EXPECTED_SHARE_PATH, snapshot_dir)
|
|
|
|
self.mock_client.getfsnap.return_value = {
|
|
'total': 1,
|
|
'members': [{'snapName': constants.EXPECTED_SNAP_NAME}]
|
|
}
|
|
|
|
self.mock_client.getfshare.side_effect = [
|
|
# some typical independent NFS share (path) and SMB share (dir)
|
|
{
|
|
'total': 1,
|
|
'members': [{'sharePath': snapshot_path}],
|
|
},
|
|
{
|
|
'total': 0,
|
|
'members': [],
|
|
}
|
|
]
|
|
|
|
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)
|
|
|
|
def test_mediator_delete_snapshot_shared_smb(self):
|
|
self.init_mediator()
|
|
|
|
# Mock a share under this snapshot for SMB
|
|
snapshot_dir = '.snapshot/DT_%s' % constants.EXPECTED_SNAP_NAME
|
|
|
|
self.mock_client.getfsnap.return_value = {
|
|
'total': 1,
|
|
'members': [{'snapName': constants.EXPECTED_SNAP_NAME}]
|
|
}
|
|
|
|
self.mock_client.getfshare.side_effect = [
|
|
# some typical independent NFS share (path) and SMB share (dir)
|
|
{
|
|
'total': 1,
|
|
'members': [{'sharePath': constants.EXPECTED_SHARE_PATH}],
|
|
},
|
|
{
|
|
'total': 1,
|
|
'members': [{'shareDir': snapshot_dir}],
|
|
}
|
|
]
|
|
|
|
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)
|
|
|
|
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)
|
|
|
|
def test_mediator_delete_snapshot_backend_exceptions(self):
|
|
self.init_mediator()
|
|
|
|
# getfsnap exception
|
|
self.mock_client.getfsnap.side_effect = Exception('getfsnap fail.')
|
|
self._assert_delete_snapshot_raises()
|
|
|
|
# getfsnap OK
|
|
self.mock_client.getfsnap.side_effect = None
|
|
self.mock_client.getfsnap.return_value = {
|
|
'total': 1,
|
|
'members': [{'snapName': constants.EXPECTED_SNAP_NAME,
|
|
'fstoreName': constants.EXPECTED_FSTORE}]
|
|
}
|
|
|
|
# getfshare exception
|
|
self.mock_client.getfshare.side_effect = Exception('getfshare fail.')
|
|
self._assert_delete_snapshot_raises()
|
|
|
|
# getfshare OK
|
|
def mock_fshare(*args, **kwargs):
|
|
if args[0] == constants.NFS_LOWER:
|
|
return {
|
|
'total': 1,
|
|
'members': [{'sharePath': '/anyfpg/anyvfs/anyfstore',
|
|
'fstoreName': constants.EXPECTED_FSTORE}]
|
|
}
|
|
else:
|
|
return {
|
|
'total': 1,
|
|
'members': [{'shareDir': [],
|
|
'fstoreName': constants.EXPECTED_FSTORE}]
|
|
}
|
|
|
|
self.mock_client.getfshare.side_effect = mock_fshare
|
|
|
|
# removefsnap exception
|
|
self.mock_client.removefsnap.side_effect = Exception(
|
|
'removefsnap fail.')
|
|
self._assert_delete_snapshot_raises()
|
|
|
|
# removefsnap OK
|
|
self.mock_client.removefsnap.side_effect = None
|
|
self.mock_client.removefsnap.return_value = []
|
|
|
|
# startfsnapclean exception (logged, not raised)
|
|
self.mock_client.startfsnapclean.side_effect = Exception(
|
|
'startfsnapclean fail.')
|
|
mock_log = self.mock_object(hpe3parmediator, 'LOG')
|
|
|
|
self.mediator.delete_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.getfsnap('*_%s' % constants.EXPECTED_SNAP_NAME,
|
|
vfs=constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG,
|
|
pat=True,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
mock.call.getfshare(constants.NFS_LOWER,
|
|
fpg=constants.EXPECTED_FPG,
|
|
vfs=constants.EXPECTED_VFS,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
mock.call.getfshare(constants.SMB_LOWER,
|
|
fpg=constants.EXPECTED_FPG,
|
|
vfs=constants.EXPECTED_VFS,
|
|
fstore=constants.EXPECTED_FSTORE),
|
|
mock.call.removefsnap(constants.EXPECTED_VFS,
|
|
constants.EXPECTED_FSTORE,
|
|
fpg=constants.EXPECTED_FPG,
|
|
snapname=constants.EXPECTED_SNAP_NAME),
|
|
mock.call.startfsnapclean(constants.EXPECTED_FPG,
|
|
reclaimStrategy='maxspeed'),
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
self.assertTrue(mock_log.debug.called)
|
|
self.assertTrue(mock_log.exception.called)
|
|
|
|
@ddt.data('volname.1', ['volname.2', 'volname.3'])
|
|
def test_mediator_get_fpg_status(self, volume_name_or_list):
|
|
"""Mediator converts client stats to capacity result."""
|
|
expected_capacity = constants.EXPECTED_SIZE_2
|
|
expected_free = constants.EXPECTED_SIZE_1
|
|
|
|
self.init_mediator()
|
|
self.mock_client.getfpg.return_value = {
|
|
'total': 1,
|
|
'members': [
|
|
{
|
|
'capacityKiB': str(expected_capacity * units.Mi),
|
|
'availCapacityKiB': str(expected_free * units.Mi),
|
|
'vvs': volume_name_or_list,
|
|
}
|
|
],
|
|
'message': None,
|
|
}
|
|
|
|
self.mock_client.getfsquota.return_value = {
|
|
'total': 3,
|
|
'members': [
|
|
{'hardBlock': 1 * units.Ki},
|
|
{'hardBlock': 2 * units.Ki},
|
|
{'hardBlock': 3 * units.Ki},
|
|
],
|
|
'message': None,
|
|
}
|
|
|
|
self.mock_client.getVolume.return_value = {
|
|
'provisioningType': hpe3parmediator.DEDUPE}
|
|
|
|
expected_result = {
|
|
'pool_name': constants.EXPECTED_FPG,
|
|
'free_capacity_gb': expected_free,
|
|
'hpe3par_flash_cache': False,
|
|
'hp3par_flash_cache': False,
|
|
'dedupe': True,
|
|
'thin_provisioning': True,
|
|
'total_capacity_gb': expected_capacity,
|
|
'provisioned_capacity_gb': 6,
|
|
}
|
|
|
|
result = self.mediator.get_fpg_status(constants.EXPECTED_FPG)
|
|
self.assertEqual(expected_result, result)
|
|
expected_calls = [
|
|
mock.call.getfpg(constants.EXPECTED_FPG)
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_get_fpg_status_exception(self):
|
|
"""Exception during get_fpg_status call to getfpg."""
|
|
self.init_mediator()
|
|
|
|
self.mock_client.getfpg.side_effect = constants.FAKE_EXCEPTION
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.get_fpg_status,
|
|
constants.EXPECTED_FPG)
|
|
|
|
expected_calls = [mock.call.getfpg(constants.EXPECTED_FPG)]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_get_fpg_status_error(self):
|
|
"""Unexpected result from getfpg during get_fpg_status."""
|
|
self.init_mediator()
|
|
|
|
self.mock_client.getfpg.return_value = {'total': 0}
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.get_fpg_status,
|
|
constants.EXPECTED_FPG)
|
|
|
|
expected_calls = [mock.call.getfpg(constants.EXPECTED_FPG)]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_get_fpg_status_bad_prov_type(self):
|
|
"""Test get_fpg_status handling of unexpected provisioning type."""
|
|
self.init_mediator()
|
|
|
|
self.mock_client.getfpg.return_value = {
|
|
'total': 1,
|
|
'members': [
|
|
{
|
|
'capacityKiB': '1',
|
|
'availCapacityKiB': '1',
|
|
'vvs': 'foo',
|
|
}
|
|
],
|
|
'message': None,
|
|
}
|
|
self.mock_client.getVolume.return_value = {
|
|
'provisioningType': 'BOGUS'}
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.get_fpg_status,
|
|
constants.EXPECTED_FPG)
|
|
|
|
expected_calls = [mock.call.getfpg(constants.EXPECTED_FPG)]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_get_provisioned_error(self):
|
|
"""Test error during get provisioned GB."""
|
|
self.init_mediator()
|
|
|
|
error_return = {'message': 'Some error happened.'}
|
|
self.mock_client.getfsquota.return_value = error_return
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.get_provisioned_gb,
|
|
constants.EXPECTED_FPG)
|
|
|
|
expected_calls = [mock.call.getfsquota(fpg=constants.EXPECTED_FPG)]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_get_provisioned_exception(self):
|
|
"""Test exception during get provisioned GB."""
|
|
self.init_mediator()
|
|
|
|
self.mock_client.getfsquota.side_effect = constants.FAKE_EXCEPTION
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.get_provisioned_gb,
|
|
constants.EXPECTED_FPG)
|
|
|
|
expected_calls = [mock.call.getfsquota(fpg=constants.EXPECTED_FPG)]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_update_access_resync_rules_nfs(self):
|
|
self.init_mediator()
|
|
|
|
getfshare_result = {
|
|
'shareName': constants.EXPECTED_SHARE_NAME,
|
|
'fstoreName': constants.EXPECTED_FSTORE,
|
|
'clients': [constants.EXPECTED_IP_127],
|
|
'comment': constants.EXPECTED_COMMENT,
|
|
}
|
|
self.mock_client.getfshare.return_value = {
|
|
'total': 1,
|
|
'members': [getfshare_result],
|
|
'message': None,
|
|
}
|
|
|
|
self.mediator.update_access(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_NFS],
|
|
None,
|
|
None,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
expected_calls = [
|
|
mock.call.setfshare(
|
|
constants.NFS_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_NAME,
|
|
clientip='+' + constants.EXPECTED_IP_1234,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE,
|
|
comment=constants.EXPECTED_COMMENT),
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_update_access_resync_rules_cifs(self):
|
|
self.init_mediator()
|
|
|
|
getfshare_result = {
|
|
'shareName': constants.EXPECTED_SHARE_NAME,
|
|
'fstoreName': constants.EXPECTED_FSTORE,
|
|
'allowPerm': [['foo_user', 'fullcontrol']],
|
|
'allowIP': '',
|
|
'comment': constants.EXPECTED_COMMENT,
|
|
}
|
|
self.mock_client.getfshare.return_value = {
|
|
'total': 1,
|
|
'members': [getfshare_result],
|
|
'message': None,
|
|
}
|
|
|
|
self.mediator.update_access(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.CIFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_CIFS],
|
|
None,
|
|
None,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
expected_calls = [
|
|
mock.call.setfshare(
|
|
constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_NAME,
|
|
allowperm='+' + constants.USERNAME + ':fullcontrol',
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE,
|
|
comment=constants.EXPECTED_COMMENT),
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_allow_ip_ro_access_cifs_error(self):
|
|
self.init_mediator()
|
|
|
|
self.assertRaises(exception.InvalidShareAccess,
|
|
self.mediator.update_access,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.CIFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_NFS],
|
|
[constants.ADD_RULE_IP_RO],
|
|
[],
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
@ddt.data(constants.CIFS, constants.NFS)
|
|
def test_mediator_allow_rw_snapshot_error(self, proto):
|
|
self.init_mediator()
|
|
getfshare_result = {
|
|
'shareName': 'foo_ro_name',
|
|
'fstoreName': 'foo_fstore',
|
|
'comment': 'foo_comment',
|
|
}
|
|
path = 'foo/.snapshot/foo'
|
|
if proto == constants.NFS:
|
|
getfshare_result['sharePath'] = path
|
|
else:
|
|
getfshare_result['shareDir'] = path
|
|
|
|
self.mock_client.getfshare.return_value = {
|
|
'total': 1,
|
|
'members': [getfshare_result],
|
|
'message': None,
|
|
}
|
|
|
|
self.assertRaises(exception.InvalidShareAccess,
|
|
self.mediator.update_access,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.CIFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_NFS],
|
|
[constants.ADD_RULE_IP],
|
|
[],
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
@ddt.data((constants.READ_WRITE, True),
|
|
(constants.READ_WRITE, False),
|
|
(constants.READ_ONLY, True),
|
|
(constants.READ_ONLY, False))
|
|
@ddt.unpack
|
|
def test_mediator_allow_user_access_cifs(self, access_level, use_other):
|
|
""""Allow user access to cifs share."""
|
|
self.init_mediator()
|
|
|
|
if use_other: # Don't find share until second attempt.
|
|
findings = (None,
|
|
self.mock_client.getfshare.return_value['members'][0])
|
|
mock_find_fshare = self.mock_object(
|
|
self.mediator, '_find_fshare', mock.Mock(side_effect=findings))
|
|
|
|
if access_level == constants.READ_ONLY:
|
|
expected_allowperm = '+%s:read' % constants.USERNAME
|
|
else:
|
|
expected_allowperm = '+%s:fullcontrol' % constants.USERNAME
|
|
|
|
constants.ADD_RULE_USER['access_level'] = access_level
|
|
self.mediator.update_access(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.CIFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_CIFS],
|
|
[constants.ADD_RULE_USER],
|
|
[],
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
expected_calls = [
|
|
mock.call.setfshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
allowperm=expected_allowperm,
|
|
comment=constants.EXPECTED_COMMENT,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE)
|
|
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
if use_other:
|
|
readonly = access_level == constants.READ_ONLY
|
|
expected_find_calls = [
|
|
mock.call(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.SMB_LOWER,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
readonly=readonly),
|
|
mock.call(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.SMB_LOWER,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
readonly=not readonly),
|
|
]
|
|
mock_find_fshare.assert_has_calls(expected_find_calls)
|
|
|
|
@ddt.data(constants.CIFS, constants.NFS)
|
|
def test_mediator_deny_rw_snapshot_error(self, proto):
|
|
self.init_mediator()
|
|
getfshare_result = {
|
|
'shareName': 'foo_ro_name',
|
|
'fstoreName': 'foo_fstore',
|
|
'comment': 'foo_comment',
|
|
}
|
|
path = 'foo/.snapshot/foo'
|
|
if proto == constants.NFS:
|
|
getfshare_result['sharePath'] = path
|
|
else:
|
|
getfshare_result['shareDir'] = path
|
|
|
|
self.mock_client.getfshare.return_value = {
|
|
'total': 1,
|
|
'members': [getfshare_result],
|
|
'message': None,
|
|
}
|
|
mock_log = self.mock_object(hpe3parmediator, 'LOG')
|
|
|
|
self.mediator.update_access(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
proto,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_NFS],
|
|
[],
|
|
[constants.DELETE_RULE_IP],
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
self.assertFalse(self.mock_client.setfshare.called)
|
|
self.assertTrue(mock_log.error.called)
|
|
|
|
def test_mediator_deny_user_access_cifs(self):
|
|
""""Deny user access to cifs share."""
|
|
self.init_mediator()
|
|
|
|
expected_denyperm = '-%s:fullcontrol' % constants.USERNAME
|
|
|
|
self.mediator.update_access(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.CIFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_CIFS],
|
|
[],
|
|
[constants.DELETE_RULE_USER],
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
expected_calls = [
|
|
mock.call.setfshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
allowperm=expected_denyperm,
|
|
comment=constants.EXPECTED_COMMENT,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE)
|
|
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_allow_ip_access_cifs(self):
|
|
""""Allow ip access to cifs share."""
|
|
self.init_mediator()
|
|
|
|
expected_allowip = '+%s' % constants.EXPECTED_IP_1234
|
|
|
|
self.mediator.update_access(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.CIFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_NFS],
|
|
[constants.ADD_RULE_IP],
|
|
[],
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
expected_calls = [
|
|
mock.call.setfshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
allowip=expected_allowip,
|
|
comment=constants.EXPECTED_COMMENT,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE)
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_deny_ip_access_cifs(self):
|
|
""""Deny ip access to cifs share."""
|
|
self.init_mediator()
|
|
|
|
expected_denyip = '-%s' % constants.EXPECTED_IP_1234
|
|
|
|
self.mediator.update_access(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.CIFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_NFS],
|
|
[],
|
|
[constants.DELETE_RULE_IP],
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
expected_calls = [
|
|
mock.call.setfshare(constants.SMB_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
allowip=expected_denyip,
|
|
comment=constants.EXPECTED_COMMENT,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE)
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_allow_ip_access_nfs(self):
|
|
""""Allow ip access to nfs share."""
|
|
self.init_mediator()
|
|
already_exists = (hpe3parmediator.IP_ALREADY_EXISTS %
|
|
constants.EXPECTED_IP_1234)
|
|
self.mock_client.setfshare.side_effect = ([], [already_exists])
|
|
|
|
expected_clientip = '+%s' % constants.EXPECTED_IP_1234
|
|
|
|
for _ in range(2): # Test 2nd allow w/ already exists message.
|
|
self.mediator.update_access(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_NFS],
|
|
[constants.ADD_RULE_IP],
|
|
[],
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
expected_calls = 2 * [
|
|
mock.call.setfshare(constants.NFS.lower(),
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
clientip=expected_clientip,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE,
|
|
comment=constants.EXPECTED_COMMENT),
|
|
]
|
|
|
|
self.mock_client.assert_has_calls(expected_calls, any_order=True)
|
|
|
|
def test_mediator_deny_ip_access_nfs(self):
|
|
""""Deny ip access to nfs share."""
|
|
self.init_mediator()
|
|
|
|
expected_clientip = '-%s' % constants.EXPECTED_IP_1234
|
|
|
|
self.mediator.update_access(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_NFS],
|
|
[],
|
|
[constants.DELETE_RULE_IP],
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
expected_calls = [
|
|
mock.call.setfshare(constants.NFS.lower(),
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_SHARE_ID,
|
|
clientip=expected_clientip,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=constants.EXPECTED_FSTORE,
|
|
comment=constants.EXPECTED_COMMENT)
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_deny_ip_ro_access_nfs_legacy(self):
|
|
self.init_mediator()
|
|
|
|
# Fail to find share with new naming. Succeed finding legacy naming.
|
|
legacy = {
|
|
'shareName': 'foo_name',
|
|
'fstoreName': 'foo_fstore',
|
|
'comment': 'foo_comment',
|
|
'sharePath': 'foo/.snapshot/foo',
|
|
}
|
|
fshares = (None, legacy)
|
|
mock_find_fshare = self.mock_object(self.mediator,
|
|
'_find_fshare',
|
|
mock.Mock(side_effect=fshares))
|
|
|
|
expected_clientip = '-%s' % constants.EXPECTED_IP_1234
|
|
|
|
self.mediator.update_access(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_NFS],
|
|
[],
|
|
[constants.DELETE_RULE_IP_RO],
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
expected_calls = [
|
|
mock.call.setfshare(constants.NFS.lower(),
|
|
constants.EXPECTED_VFS,
|
|
legacy['shareName'],
|
|
clientip=expected_clientip,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=legacy['fstoreName'],
|
|
comment=legacy['comment'])
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
expected_find_fshare_calls = [
|
|
mock.call(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS_LOWER,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
readonly=True),
|
|
mock.call(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS_LOWER,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
readonly=False),
|
|
]
|
|
mock_find_fshare.assert_has_calls(expected_find_fshare_calls)
|
|
|
|
def test_mediator_allow_user_access_nfs(self):
|
|
""""Allow user access to nfs share is not supported."""
|
|
self.init_mediator()
|
|
|
|
self.assertRaises(exception.HPE3ParInvalid,
|
|
self.mediator.update_access,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_NFS],
|
|
[constants.ADD_RULE_USER],
|
|
[],
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
def test_mediator_allow_access_bad_proto(self):
|
|
""""Allow user access to unsupported protocol."""
|
|
self.init_mediator()
|
|
|
|
self.assertRaises(exception.InvalidShareAccess,
|
|
self.mediator.update_access,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
'unsupported_other_protocol',
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_NFS],
|
|
[constants.ADD_RULE_IP],
|
|
[],
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
def test_mediator_allow_access_bad_type(self):
|
|
""""Allow user access to unsupported access type."""
|
|
self.init_mediator()
|
|
|
|
self.assertRaises(exception.InvalidInput,
|
|
self.mediator.update_access,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.CIFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_NFS],
|
|
[constants.ADD_RULE_BAD_TYPE],
|
|
[],
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
def test_mediator_allow_access_missing_nfs_share(self):
|
|
self.init_mediator()
|
|
mock_find_fshare = self.mock_object(self.mediator,
|
|
'_find_fshare',
|
|
mock.Mock(return_value=None))
|
|
|
|
self.assertRaises(exception.HPE3ParInvalid,
|
|
self.mediator.update_access,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_NFS],
|
|
[constants.ADD_RULE_IP],
|
|
[],
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
expected_calls = [
|
|
mock.call(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS_LOWER,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
readonly=False),
|
|
mock.call(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS_LOWER,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
readonly=True),
|
|
]
|
|
mock_find_fshare.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_allow_nfs_ro_access(self):
|
|
self.init_mediator()
|
|
getfshare_result = {
|
|
'shareName': 'foo_ro_name',
|
|
'fstoreName': 'foo_fstore',
|
|
'shareDir': 'foo_dir',
|
|
'comment': 'foo_comment',
|
|
}
|
|
findings = (None, getfshare_result)
|
|
mock_find_fshare = self.mock_object(self.mediator,
|
|
'_find_fshare',
|
|
mock.Mock(side_effect=findings))
|
|
self.mock_client.getfshare.return_value = {
|
|
'total': 1,
|
|
'members': [getfshare_result],
|
|
'message': None,
|
|
}
|
|
|
|
share_id = 'foo'
|
|
|
|
self.mediator.update_access(constants.EXPECTED_PROJECT_ID,
|
|
share_id,
|
|
constants.NFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_NFS],
|
|
[constants.ADD_RULE_IP_RO],
|
|
[],
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
expected_calls = [
|
|
mock.call(constants.EXPECTED_PROJECT_ID,
|
|
share_id,
|
|
constants.NFS_LOWER,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
readonly=True),
|
|
mock.call(constants.EXPECTED_PROJECT_ID,
|
|
share_id,
|
|
constants.NFS_LOWER,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
readonly=False),
|
|
]
|
|
mock_find_fshare.assert_has_calls(expected_calls)
|
|
|
|
ro_share = 'osf-ro-%s' % share_id
|
|
|
|
expected_calls = [
|
|
mock.call.createfshare(constants.NFS_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
ro_share,
|
|
clientip=constants.EXPECTED_IP_127_2,
|
|
comment=getfshare_result['comment'],
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=getfshare_result['fstoreName'],
|
|
options='ro,no_root_squash,insecure',
|
|
sharedir=getfshare_result['shareDir']),
|
|
mock.call.getfshare(constants.NFS_LOWER,
|
|
ro_share,
|
|
fstore=getfshare_result['fstoreName'],
|
|
fpg=constants.EXPECTED_FPG,
|
|
vfs=constants.EXPECTED_VFS),
|
|
mock.call.setfshare(constants.NFS_LOWER,
|
|
constants.EXPECTED_VFS,
|
|
getfshare_result['shareName'],
|
|
clientip='+%s' % constants.EXPECTED_IP_1234,
|
|
comment=getfshare_result['comment'],
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=getfshare_result['fstoreName']),
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_mediator_deny_access_missing_nfs_share(self):
|
|
self.init_mediator()
|
|
mock_find_fshare = self.mock_object(self.mediator,
|
|
'_find_fshare',
|
|
mock.Mock(return_value=None))
|
|
|
|
self.mediator.update_access(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS,
|
|
constants.EXPECTED_EXTRA_SPECS,
|
|
[constants.ACCESS_RULE_NFS],
|
|
[],
|
|
[constants.DELETE_RULE_IP],
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
expected_calls = [
|
|
mock.call(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS_LOWER,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
readonly=False),
|
|
]
|
|
mock_find_fshare.assert_has_calls(expected_calls)
|
|
|
|
@ddt.data((hpe3parmediator.ALLOW, 'ip', True,
|
|
['IP address foo already exists']),
|
|
(hpe3parmediator.ALLOW, 'ip', False,
|
|
['Another share already exists for this path and client']),
|
|
(hpe3parmediator.ALLOW, 'user', True,
|
|
['"allow" permission already exists for "foo"']),
|
|
(hpe3parmediator.DENY, 'ip', True,
|
|
['foo does not exist, cannot be removed']),
|
|
(hpe3parmediator.DENY, 'user', True,
|
|
['foo:fullcontrol" does not exist, cannot delete it.']),
|
|
(hpe3parmediator.DENY, 'user', False,
|
|
['SMB share osf-foo does not exist']),
|
|
(hpe3parmediator.ALLOW, 'ip', True, ['\r']),
|
|
(hpe3parmediator.ALLOW, 'user', True, ['\r']),
|
|
(hpe3parmediator.DENY, 'ip', True, ['\r']),
|
|
(hpe3parmediator.DENY, 'user', True, ['\r']),
|
|
(hpe3parmediator.ALLOW, 'ip', True, []),
|
|
(hpe3parmediator.ALLOW, 'user', True, []),
|
|
(hpe3parmediator.DENY, 'ip', True, []),
|
|
(hpe3parmediator.DENY, 'user', True, []))
|
|
@ddt.unpack
|
|
def test_ignore_benign_access_results(self, access, access_type,
|
|
expect_false, results):
|
|
|
|
returned = self.mediator.ignore_benign_access_results(
|
|
access, access_type, 'foo', results)
|
|
|
|
if expect_false:
|
|
self.assertFalse(returned)
|
|
else:
|
|
self.assertEqual(results, returned)
|
|
|
|
@ddt.data((2, 1, True),
|
|
(2, 1, False),
|
|
(1, 2, True),
|
|
(1, 2, False),
|
|
(1024, 2048, True),
|
|
(1024, 2048, False),
|
|
(2048, 1024, True),
|
|
(2048, 1024, False),
|
|
(99999999, 1, True),
|
|
(99999999, 1, False),
|
|
(1, 99999999, True),
|
|
(1, 99999999, False),
|
|
)
|
|
@ddt.unpack
|
|
def test_mediator_resize_share(self, new_size, old_size, fstore_per_share):
|
|
self.init_mediator()
|
|
fstore = 'foo_fstore'
|
|
mock_find_fstore = self.mock_object(self.mediator,
|
|
'_find_fstore',
|
|
mock.Mock(return_value=fstore))
|
|
fstore_init_size = int(
|
|
constants.GET_FSQUOTA['members'][0]['hardBlock'])
|
|
self.mediator.hpe3par_fstore_per_share = fstore_per_share
|
|
|
|
if fstore_per_share:
|
|
expected_capacity = new_size * units.Ki
|
|
else:
|
|
expected_capacity = (
|
|
(new_size - old_size) * units.Ki + fstore_init_size)
|
|
|
|
self.mediator.resize_share(
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS,
|
|
new_size,
|
|
old_size,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
mock_find_fstore.assert_called_with(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
allow_cross_protocol=False)
|
|
self.mock_client.setfsquota.assert_called_with(
|
|
constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=fstore,
|
|
scapacity=str(expected_capacity),
|
|
hcapacity=str(expected_capacity))
|
|
|
|
@ddt.data(['This is a fake setfsquota returned error'], Exception('boom'))
|
|
def test_mediator_resize_share_setfsquota_side_effects(self, side_effect):
|
|
self.init_mediator()
|
|
fstore_init_size = int(
|
|
constants.GET_FSQUOTA['members'][0]['hardBlock'])
|
|
fstore = 'foo_fstore'
|
|
new_size = 2
|
|
old_size = 1
|
|
expected_capacity = (new_size - old_size) * units.Ki + fstore_init_size
|
|
mock_find_fstore = self.mock_object(self.mediator,
|
|
'_find_fstore',
|
|
mock.Mock(return_value=fstore))
|
|
self.mock_client.setfsquota.side_effect = side_effect
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.resize_share,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS,
|
|
new_size,
|
|
old_size,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
mock_find_fstore.assert_called_with(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
allow_cross_protocol=False)
|
|
self.mock_client.setfsquota.assert_called_with(
|
|
constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG,
|
|
fstore=fstore,
|
|
scapacity=str(expected_capacity),
|
|
hcapacity=str(expected_capacity))
|
|
|
|
def test_mediator_resize_share_not_found(self):
|
|
self.init_mediator()
|
|
mock_find_fshare = self.mock_object(self.mediator,
|
|
'_find_fshare',
|
|
mock.Mock(return_value=None))
|
|
|
|
self.assertRaises(exception.InvalidShare,
|
|
self.mediator.resize_share,
|
|
constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS,
|
|
999,
|
|
99,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
mock_find_fshare.assert_called_with(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.NFS,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
allow_cross_protocol=False)
|
|
|
|
@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,
|
|
hpe3parmediator.HPE3ParMediator().other_protocol(
|
|
protocol))
|
|
|
|
@ddt.data('', 'bogus')
|
|
def test_other_protocol_exception(self, protocol):
|
|
self.assertRaises(exception.InvalidShareAccess,
|
|
hpe3parmediator.HPE3ParMediator().other_protocol,
|
|
protocol)
|
|
|
|
@ddt.data(('osf-uid', None, None, 'osf-uid'),
|
|
('uid', None, True, 'osf-ro-uid'),
|
|
('uid', None, False, 'osf-uid'),
|
|
('uid', 'smb', True, 'osf-smb-ro-uid'),
|
|
('uid', 'smb', False, 'osf-smb-uid'),
|
|
('uid', 'nfs', True, 'osf-nfs-ro-uid'),
|
|
('uid', 'nfs', False, 'osf-nfs-uid'))
|
|
@ddt.unpack
|
|
def test_ensure_prefix(self, uid, protocol, readonly, expected):
|
|
self.assertEqual(expected,
|
|
hpe3parmediator.HPE3ParMediator().ensure_prefix(
|
|
uid, protocol=protocol, readonly=readonly))
|
|
|
|
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,
|
|
allow_cross_protocol=False)
|
|
self.assertIsNone(result)
|
|
|
|
def test_find_fstore_search_xproto(self):
|
|
self.init_mediator()
|
|
|
|
mock_find_fshare = self.mock_object(self.mediator,
|
|
'_find_fshare_with_proto',
|
|
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,
|
|
readonly=False),
|
|
mock.call(constants.EXPECTED_PROJECT_ID,
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.SMB_LOWER,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
readonly=False),
|
|
]
|
|
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)
|
|
|
|
def test_fsip_exists(self):
|
|
self.init_mediator()
|
|
|
|
# Make the result member a superset of the fsip items.
|
|
fsip_plus = constants.EXPECTED_FSIP.copy()
|
|
fsip_plus.update({'k': 'v', 'k2': 'v2'})
|
|
|
|
self.mock_client.getfsip.return_value = {
|
|
'total': 3,
|
|
'members': [{'bogus1': 1}, fsip_plus, {'bogus2': '2'}]
|
|
}
|
|
|
|
self.assertTrue(self.mediator.fsip_exists(constants.EXPECTED_FSIP))
|
|
|
|
self.mock_client.getfsip.assert_called_once_with(
|
|
constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG)
|
|
|
|
def test_fsip_does_not_exist(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_client.getfsip.return_value = {
|
|
'total': 3,
|
|
'members': [{'bogus1': 1}, constants.OTHER_FSIP, {'bogus2': '2'}]
|
|
}
|
|
|
|
self.assertFalse(self.mediator.fsip_exists(constants.EXPECTED_FSIP))
|
|
|
|
self.mock_client.getfsip.assert_called_once_with(
|
|
constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG)
|
|
|
|
def test_fsip_exists_exception(self):
|
|
self.init_mediator()
|
|
|
|
class FakeException(Exception):
|
|
pass
|
|
|
|
self.mock_client.getfsip.side_effect = FakeException()
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.fsip_exists,
|
|
constants.EXPECTED_FSIP)
|
|
|
|
self.mock_client.getfsip.assert_called_once_with(
|
|
constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG)
|
|
|
|
def test_create_fsip_success(self):
|
|
self.init_mediator()
|
|
|
|
# Make the result member a superset of the fsip items.
|
|
fsip_plus = constants.EXPECTED_FSIP.copy()
|
|
fsip_plus.update({'k': 'v', 'k2': 'v2'})
|
|
|
|
self.mock_client.getfsip.return_value = {
|
|
'total': 3,
|
|
'members': [{'bogus1': 1}, fsip_plus, {'bogus2': '2'}]
|
|
}
|
|
|
|
self.mediator.create_fsip(constants.EXPECTED_IP_1234,
|
|
constants.EXPECTED_SUBNET,
|
|
constants.EXPECTED_VLAN_TAG,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
self.mock_client.getfsip.assert_called_once_with(
|
|
constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG)
|
|
|
|
expected_calls = [
|
|
mock.call.createfsip(constants.EXPECTED_IP_1234,
|
|
constants.EXPECTED_SUBNET,
|
|
constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG,
|
|
vlantag=constants.EXPECTED_VLAN_TAG),
|
|
mock.call.getfsip(constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG),
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_create_fsip_exception(self):
|
|
self.init_mediator()
|
|
|
|
class FakeException(Exception):
|
|
pass
|
|
|
|
self.mock_client.createfsip.side_effect = FakeException()
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.create_fsip,
|
|
constants.EXPECTED_IP_1234,
|
|
constants.EXPECTED_SUBNET,
|
|
constants.EXPECTED_VLAN_TAG,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
self.mock_client.createfsip.assert_called_once_with(
|
|
constants.EXPECTED_IP_1234,
|
|
constants.EXPECTED_SUBNET,
|
|
constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG,
|
|
vlantag=constants.EXPECTED_VLAN_TAG)
|
|
|
|
def test_create_fsip_get_none(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_client.getfsip.return_value = {'members': []}
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.create_fsip,
|
|
constants.EXPECTED_IP_1234,
|
|
constants.EXPECTED_SUBNET,
|
|
constants.EXPECTED_VLAN_TAG,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
expected_calls = [
|
|
mock.call.createfsip(constants.EXPECTED_IP_1234,
|
|
constants.EXPECTED_SUBNET,
|
|
constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG,
|
|
vlantag=constants.EXPECTED_VLAN_TAG),
|
|
mock.call.getfsip(constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG),
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_remove_fsip_success(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_client.getfsip.return_value = {
|
|
'members': [constants.OTHER_FSIP]
|
|
}
|
|
|
|
self.mediator.remove_fsip(constants.EXPECTED_IP_1234,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
expected_calls = [
|
|
mock.call.removefsip(constants.EXPECTED_VFS,
|
|
constants.EXPECTED_IP_1234,
|
|
fpg=constants.EXPECTED_FPG),
|
|
mock.call.getfsip(constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG),
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
@ddt.data(('ip', None),
|
|
('ip', ''),
|
|
(None, 'vfs'),
|
|
('', 'vfs'),
|
|
(None, None),
|
|
('', ''))
|
|
@ddt.unpack
|
|
def test_remove_fsip_without_ip_or_vfs(self, ip, vfs):
|
|
self.init_mediator()
|
|
self.mediator.remove_fsip(ip, constants.EXPECTED_FPG, vfs)
|
|
self.assertFalse(self.mock_client.removefsip.called)
|
|
|
|
def test_remove_fsip_not_gone(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_client.getfsip.return_value = {
|
|
'members': [constants.EXPECTED_FSIP]
|
|
}
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.remove_fsip,
|
|
constants.EXPECTED_IP_1234,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
expected_calls = [
|
|
mock.call.removefsip(constants.EXPECTED_VFS,
|
|
constants.EXPECTED_IP_1234,
|
|
fpg=constants.EXPECTED_FPG),
|
|
mock.call.getfsip(constants.EXPECTED_VFS,
|
|
fpg=constants.EXPECTED_FPG),
|
|
]
|
|
self.mock_client.assert_has_calls(expected_calls)
|
|
|
|
def test_remove_fsip_exception(self):
|
|
self.init_mediator()
|
|
|
|
class FakeException(Exception):
|
|
pass
|
|
|
|
self.mock_client.removefsip.side_effect = FakeException()
|
|
|
|
self.assertRaises(exception.ShareBackendException,
|
|
self.mediator.remove_fsip,
|
|
constants.EXPECTED_IP_1234,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS)
|
|
|
|
self.mock_client.removefsip.assert_called_once_with(
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_IP_1234,
|
|
fpg=constants.EXPECTED_FPG)
|
|
|
|
def test__create_mount_directory(self):
|
|
self.init_mediator()
|
|
|
|
mount_location = '/mnt/foo'
|
|
self.mediator._create_mount_directory(mount_location)
|
|
|
|
utils.execute.assert_called_with('mkdir', mount_location,
|
|
run_as_root=True)
|
|
|
|
def test__create_mount_directory_error(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_object(utils, 'execute',
|
|
mock.Mock(side_effect=Exception('mkdir error.')))
|
|
mock_log = self.mock_object(hpe3parmediator, 'LOG')
|
|
|
|
mount_location = '/mnt/foo'
|
|
self.mediator._create_mount_directory(mount_location)
|
|
utils.execute.assert_called_with('mkdir', mount_location,
|
|
run_as_root=True)
|
|
|
|
# Warning is logged (no exception thrown).
|
|
self.assertTrue(mock_log.warning.called)
|
|
|
|
def test__mount_super_share(self):
|
|
self.init_mediator()
|
|
|
|
# Test mounting NFS share.
|
|
protocol = 'nfs'
|
|
mount_location = '/mnt/foo'
|
|
fpg = 'foo-fpg'
|
|
vfs = 'bar-vfs'
|
|
fstore = 'fstore'
|
|
mount_path = '%s:/%s/%s/%s/' % (constants.EXPECTED_IP_10203040, fpg,
|
|
vfs, fstore)
|
|
self.mediator._mount_super_share(protocol, mount_location, fpg, vfs,
|
|
fstore,
|
|
constants.EXPECTED_IP_10203040)
|
|
|
|
utils.execute.assert_called_with('mount', '-t', protocol, mount_path,
|
|
mount_location, run_as_root=True)
|
|
|
|
# Test mounting CIFS share.
|
|
protocol = 'smb'
|
|
mount_path = '//%s/%s/' % (constants.EXPECTED_IP_10203040,
|
|
constants.EXPECTED_SUPER_SHARE)
|
|
user = 'username=%s,password=%s,domain=%s' % (
|
|
constants.USERNAME, constants.PASSWORD,
|
|
constants.EXPECTED_CIFS_DOMAIN)
|
|
self.mediator._mount_super_share(protocol, mount_location, fpg, vfs,
|
|
fstore,
|
|
constants.EXPECTED_IP_10203040)
|
|
|
|
utils.execute.assert_called_with('mount', '-t', 'cifs', mount_path,
|
|
mount_location, '-o', user,
|
|
run_as_root=True)
|
|
|
|
def test__mount_super_share_error(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_object(utils, 'execute',
|
|
mock.Mock(side_effect=Exception('mount error.')))
|
|
mock_log = self.mock_object(hpe3parmediator, 'LOG')
|
|
|
|
protocol = 'nfs'
|
|
mount_location = '/mnt/foo'
|
|
fpg = 'foo-fpg'
|
|
vfs = 'bar-vfs'
|
|
fstore = 'fstore'
|
|
self.mediator._mount_super_share(protocol, mount_location, fpg, vfs,
|
|
fstore,
|
|
constants.EXPECTED_IP_10203040)
|
|
|
|
# Warning is logged (no exception thrown).
|
|
self.assertTrue(mock_log.warning.called)
|
|
|
|
def test__delete_share_directory(self):
|
|
self.init_mediator()
|
|
|
|
mount_location = '/mnt/foo'
|
|
self.mediator._delete_share_directory(mount_location)
|
|
|
|
utils.execute.assert_called_with('rm', '-rf', mount_location,
|
|
run_as_root=True)
|
|
|
|
def test__delete_share_directory_error(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_object(utils, 'execute',
|
|
mock.Mock(side_effect=Exception('rm error.')))
|
|
mock_log = self.mock_object(hpe3parmediator, 'LOG')
|
|
|
|
mount_location = '/mnt/foo'
|
|
self.mediator._delete_share_directory(mount_location)
|
|
|
|
# Warning is logged (no exception thrown).
|
|
self.assertTrue(mock_log.warning.called)
|
|
|
|
def test__unmount_share(self):
|
|
self.init_mediator()
|
|
|
|
mount_dir = '/mnt/foo'
|
|
self.mediator._unmount_share(mount_dir)
|
|
|
|
utils.execute.assert_called_with('umount', mount_dir, run_as_root=True)
|
|
|
|
def test__unmount_share_error(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_object(utils, 'execute',
|
|
mock.Mock(side_effect=Exception('umount error.')))
|
|
mock_log = self.mock_object(hpe3parmediator, 'LOG')
|
|
|
|
mount_dir = '/mnt/foo'
|
|
self.mediator._unmount_share(mount_dir)
|
|
|
|
# Warning is logged (no exception thrown).
|
|
self.assertTrue(mock_log.warning.called)
|
|
|
|
def test__delete_file_tree_no_config_options(self):
|
|
self.init_mediator()
|
|
|
|
mock_log = self.mock_object(hpe3parmediator, 'LOG')
|
|
|
|
self.mediator.hpe3par_cifs_admin_access_username = None
|
|
self.mediator._delete_file_tree(
|
|
constants.EXPECTED_SHARE_ID,
|
|
constants.SMB_LOWER,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_FSTORE,
|
|
constants.EXPECTED_SHARE_IP)
|
|
|
|
# Warning is logged (no exception thrown).
|
|
self.assertTrue(mock_log.warning.called)
|
|
|
|
def test__create_super_share_createfshare_exception(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_client.createfshare.side_effect = (
|
|
Exception("createfshare error."))
|
|
|
|
self.assertRaises(
|
|
exception.ShareBackendException,
|
|
self.mediator._create_super_share,
|
|
constants.NFS_LOWER,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_FSTORE)
|
|
|
|
def test__create_super_share_setfshare_exception(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_client.setfshare.side_effect = (
|
|
Exception("setfshare error."))
|
|
|
|
self.assertRaises(
|
|
exception.ShareBackendException,
|
|
self.mediator._create_super_share,
|
|
constants.SMB_LOWER,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_FSTORE)
|
|
|
|
def test__revoke_admin_smb_access_error(self):
|
|
self.init_mediator()
|
|
|
|
self.mock_client.setfshare.side_effect = (
|
|
Exception("setfshare error"))
|
|
|
|
self.assertRaises(
|
|
exception.ShareBackendException,
|
|
self.mediator._revoke_admin_smb_access,
|
|
constants.SMB_LOWER,
|
|
constants.EXPECTED_FPG,
|
|
constants.EXPECTED_VFS,
|
|
constants.EXPECTED_FSTORE,
|
|
constants.EXPECTED_COMMENT)
|
|
|
|
def test_build_export_locations_bad_protocol(self):
|
|
self.assertRaises(exception.InvalidShareAccess,
|
|
self.mediator.build_export_locations,
|
|
"BOGUS",
|
|
[constants.EXPECTED_IP_1234],
|
|
constants.EXPECTED_SHARE_PATH)
|
|
|
|
def test_build_export_locations_bad_ip(self):
|
|
self.assertRaises(exception.InvalidInput,
|
|
self.mediator.build_export_locations,
|
|
constants.NFS,
|
|
None,
|
|
None)
|
|
|
|
def test_build_export_locations_bad_path(self):
|
|
self.assertRaises(exception.InvalidInput,
|
|
self.mediator.build_export_locations,
|
|
constants.NFS,
|
|
[constants.EXPECTED_IP_1234],
|
|
None)
|
|
|
|
|
|
class OptionMatcher(object):
|
|
"""Options string order can vary. Compare as lists."""
|
|
|
|
def __init__(self, assert_func, expected_string):
|
|
self.assert_func = assert_func
|
|
self.expected = expected_string.split(',')
|
|
|
|
def __eq__(self, actual_string):
|
|
actual = actual_string.split(',')
|
|
self.assert_func(sorted(self.expected), sorted(actual))
|
|
return True
|