INFINIDAT: load-balance shares inside network space

Instead of always using the first IP from the INFINIDAT InfiniBox
network space, utilize the export_locations attribute of the share
and return the IPs of all enabled network space IPs.

Change-Id: I2319d574cb95f8cc688e608a7e455743e4e63f93
This commit is contained in:
Amit Oren 2018-01-28 18:25:18 +02:00
parent a07d522970
commit 6a85a6f5e3
3 changed files with 66 additions and 21 deletions

View File

@ -220,23 +220,31 @@ class InfiniboxShareDriver(driver.ShareDriver):
network_space = self._system.network_spaces.safe_get( network_space = self._system.network_spaces.safe_get(
name=self._network_space_name) name=self._network_space_name)
if network_space is None: if network_space is None:
msg = _('Network space "%s" not found') % self._network_space_name msg = _('INFINIDAT InfiniBox NAS network space "%s" '
'not found') % self._network_space_name
LOG.error(msg) LOG.error(msg)
raise exception.ShareBackendException(msg=msg) raise exception.ShareBackendException(msg=msg)
network_space_ips = network_space.get_ips() network_space_ips = network_space.get_ips()
if not network_space_ips: if not network_space_ips:
msg = _('INFINIDAT InfiniBox NAS Network Space "%s" has no IPs ' msg = _('INFINIDAT InfiniBox NAS network space "%s" has no IP '
'defined') % self._network_space_name 'addresses defined') % self._network_space_name
LOG.error(msg) LOG.error(msg)
raise exception.ShareBackendException(msg=msg) raise exception.ShareBackendException(msg=msg)
return [ip_munch.ip_address for ip_munch in network_space_ips] ip_addresses = (
[ip_munch.ip_address for ip_munch in network_space_ips if
ip_munch.enabled])
if not ip_addresses:
msg = _('INFINIDAT InfiniBox NAS network space "%s" has no '
'enabled IP addresses') % self._network_space_name
LOG.error(msg)
raise exception.ShareBackendException(msg=msg)
return ip_addresses
@infinisdk_to_manila_exceptions def _get_full_nfs_export_paths(self, export_path):
def _get_full_nfs_export_path(self, export_path):
network_space_ips = self._get_infinidat_nas_network_space_ips() network_space_ips = self._get_infinidat_nas_network_space_ips()
return '{network_space_ip}:{export_path}'.format( return ['{network_space_ip}:{export_path}'.format(
network_space_ip=network_space_ips[0], network_space_ip=network_space_ip,
export_path=export_path) export_path=export_path) for network_space_ip in network_space_ips]
@infinisdk_to_manila_exceptions @infinisdk_to_manila_exceptions
def _get_infinidat_filesystem_by_name(self, name): def _get_infinidat_filesystem_by_name(self, name):
@ -310,12 +318,14 @@ class InfiniboxShareDriver(driver.ShareDriver):
@infinisdk_to_manila_exceptions @infinisdk_to_manila_exceptions
def _create_filesystem_export(self, infinidat_filesystem): def _create_filesystem_export(self, infinidat_filesystem):
infinidat_export = infinidat_filesystem.add_export(permissions=[]) infinidat_export = infinidat_filesystem.add_export(permissions=[])
return { export_paths = self._get_full_nfs_export_paths(
'path': self._get_full_nfs_export_path( infinidat_export.get_export_path())
infinidat_export.get_export_path()), export_locations = [{
'path': export_path,
'is_admin_only': False, 'is_admin_only': False,
'metadata': {}, 'metadata': {},
} } for export_path in export_paths]
return export_locations
@infinisdk_to_manila_exceptions @infinisdk_to_manila_exceptions
def _delete_share(self, share, is_snapshot): def _delete_share(self, share, is_snapshot):
@ -399,7 +409,7 @@ class InfiniboxShareDriver(driver.ShareDriver):
# extending is needed # extending is needed
self._set_manila_object_metadata(infinidat_snapshot, snapshot) self._set_manila_object_metadata(infinidat_snapshot, snapshot)
return {'export_locations': return {'export_locations':
[self._create_filesystem_export(infinidat_snapshot)]} self._create_filesystem_export(infinidat_snapshot)}
def delete_share(self, context, share, share_server=None): def delete_share(self, context, share, share_server=None):
try: try:
@ -421,16 +431,14 @@ class InfiniboxShareDriver(driver.ShareDriver):
infinidat_filesystem = self._get_infinidat_filesystem(share) infinidat_filesystem = self._get_infinidat_filesystem(share)
try: try:
infinidat_export = self._get_export(infinidat_filesystem) infinidat_export = self._get_export(infinidat_filesystem)
return self._get_full_nfs_export_paths(
infinidat_export.get_export_path())
except exception.ShareBackendException: except exception.ShareBackendException:
# export not found, need to re-export # export not found, need to re-export
message = ("missing export for share %(share)s, trying to " message = ("missing export for share %(share)s, trying to "
"re-export") "re-export")
LOG.info(message, {"share": share}) LOG.info(message, {"share": share})
infinidat_export = ( return self._create_filesystem_export(infinidat_filesystem)
self._create_filesystem_export(infinidat_filesystem))
return [self._get_full_nfs_export_path(infinidat_export['path'])]
return [self._get_full_nfs_export_path(
infinidat_export.get_export_path())]
def update_access(self, context, share, access_rules, add_rules, def update_access(self, context, share, access_rules, add_rules,
delete_rules, share_server=None): delete_rules, share_server=None):

View File

@ -31,6 +31,9 @@ _MOCK_CLONE_ID = 3
_MOCK_SHARE_SIZE = 4 _MOCK_SHARE_SIZE = 4
_MOCK_NETWORK_SPACE_IP_1 = '1.2.3.4'
_MOCK_NETWORK_SPACE_IP_2 = '1.2.3.5'
def _create_mock__getitem__(mock): def _create_mock__getitem__(mock):
def mock__getitem__(self, key, default=None): def mock__getitem__(self, key, default=None):
@ -137,7 +140,8 @@ class InfiniboxDriverTestCaseBase(test.TestCase):
self._mock_network_space = mock.Mock() self._mock_network_space = mock.Mock()
self._mock_network_space.get_ips.return_value = ( self._mock_network_space.get_ips.return_value = (
[mock.Mock(ip_address='1.2.3.4'), mock.Mock(ip_address='1.2.3.5')]) [mock.Mock(ip_address=_MOCK_NETWORK_SPACE_IP_1, enabled=True),
mock.Mock(ip_address=_MOCK_NETWORK_SPACE_IP_2, enabled=True)])
result.network_spaces.safe_get.return_value = self._mock_network_space result.network_spaces.safe_get.return_value = self._mock_network_space
result.pools.safe_get.return_value = self._mock_pool result.pools.safe_get.return_value = self._mock_pool
@ -259,10 +263,21 @@ class InfiniboxDriverTestCase(InfiniboxDriverTestCaseBase):
self.driver._get_infinidat_pool) self.driver._get_infinidat_pool)
def test__get_infinidat_nas_network_space_ips(self): def test__get_infinidat_nas_network_space_ips(self):
self.driver._get_infinidat_nas_network_space_ips() network_space_ips = self.driver._get_infinidat_nas_network_space_ips()
self._system.network_spaces.safe_get.assert_called_once() self._system.network_spaces.safe_get.assert_called_once()
self._mock_network_space.get_ips.assert_called_once() self._mock_network_space.get_ips.assert_called_once()
for network_space_ip in \
(_MOCK_NETWORK_SPACE_IP_1, _MOCK_NETWORK_SPACE_IP_2):
self.assertIn(network_space_ip, network_space_ips)
def test__get_infinidat_nas_network_space_ips_only_one_ip_enabled(self):
self._mock_network_space.get_ips.return_value = (
[mock.Mock(ip_address=_MOCK_NETWORK_SPACE_IP_1, enabled=True),
mock.Mock(ip_address=_MOCK_NETWORK_SPACE_IP_2, enabled=False)])
self.assertEqual([_MOCK_NETWORK_SPACE_IP_1],
self.driver._get_infinidat_nas_network_space_ips())
def test__get_infinidat_nas_network_space_ips_no_network_space(self): def test__get_infinidat_nas_network_space_ips_no_network_space(self):
self._system.network_spaces.safe_get.return_value = None self._system.network_spaces.safe_get.return_value = None
self.assertRaises(exception.ShareBackendException, self.assertRaises(exception.ShareBackendException,
@ -273,12 +288,30 @@ class InfiniboxDriverTestCase(InfiniboxDriverTestCaseBase):
self.assertRaises(exception.ShareBackendException, self.assertRaises(exception.ShareBackendException,
self.driver._get_infinidat_nas_network_space_ips) self.driver._get_infinidat_nas_network_space_ips)
def test__get_infinidat_nas_network_space_ips_no_ips_enabled(self):
self._mock_network_space.get_ips.return_value = (
[mock.Mock(ip_address=_MOCK_NETWORK_SPACE_IP_1, enabled=False),
mock.Mock(ip_address=_MOCK_NETWORK_SPACE_IP_2, enabled=False)])
self.assertRaises(exception.ShareBackendException,
self.driver._get_infinidat_nas_network_space_ips)
def test__get_infinidat_nas_network_space_api_error(self): def test__get_infinidat_nas_network_space_api_error(self):
self._system.network_spaces.safe_get.side_effect = ( self._system.network_spaces.safe_get.side_effect = (
self._raise_infinisdk) self._raise_infinisdk)
self.assertRaises(exception.ShareBackendException, self.assertRaises(exception.ShareBackendException,
self.driver._get_infinidat_nas_network_space_ips) self.driver._get_infinidat_nas_network_space_ips)
def test__get_full_nfs_export_paths(self):
export_paths = self.driver._get_full_nfs_export_paths(
self._mock_export.get_export_path())
for network_space_ip in \
(_MOCK_NETWORK_SPACE_IP_1, _MOCK_NETWORK_SPACE_IP_2):
self.assertIn(
"{network_space_ip}:{export_path}".format(
network_space_ip=network_space_ip,
export_path=self._mock_export.get_export_path()),
export_paths)
def test__get_export(self): def test__get_export(self):
# The default return value of get_exports is [mock_export, ]: # The default return value of get_exports is [mock_export, ]:
export = self.driver._get_export(self._mock_filesystem) export = self.driver._get_export(self._mock_filesystem)

View File

@ -0,0 +1,4 @@
---
features:
- The INFINIDAT share driver now load balances shares between the IPs
of the chosen network space.