[NetApp] Fix svm scoped account
When the NetApp backend starts, it needs to know whether the `revert_to_snapshot` support exist. So, it was retrieving the licenses and checking if the `SnapRestore` is included. Using a scoped account, the backend cannot retrieve that information, though. So, this patch solves it by sending a fake operation `revert_to_snapshot` that must fail. Analyzing the given error, it sets the backend support field. Closes-Bug: #1882590 Change-Id: Ib71a6cec939288498e48736f129fbfdacaabe9da
This commit is contained in:
parent
bbea70d044
commit
6f58af1ae3
@ -30,6 +30,7 @@ from oslo_log import log
|
||||
from oslo_service import loopingcall
|
||||
from oslo_utils import timeutils
|
||||
from oslo_utils import units
|
||||
from oslo_utils import uuidutils
|
||||
import six
|
||||
|
||||
from manila.common import constants
|
||||
@ -129,6 +130,7 @@ class NetAppCmodeFileStorageLibrary(object):
|
||||
self._clients = {}
|
||||
self._ssc_stats = {}
|
||||
self._have_cluster_creds = None
|
||||
self._revert_to_snapshot_support = False
|
||||
self._cluster_info = {}
|
||||
|
||||
self._app_version = kwargs.get('app_version', 'unknown')
|
||||
@ -145,6 +147,9 @@ class NetAppCmodeFileStorageLibrary(object):
|
||||
if self._have_cluster_creds is True:
|
||||
self._set_cluster_info()
|
||||
|
||||
self._licenses = self._get_licenses()
|
||||
self._revert_to_snapshot_support = self._check_snaprestore_license()
|
||||
|
||||
# Performance monitoring library
|
||||
self._perf_library = performance.PerformanceLibrary(self._client)
|
||||
|
||||
@ -156,7 +161,6 @@ class NetAppCmodeFileStorageLibrary(object):
|
||||
|
||||
@na_utils.trace
|
||||
def check_for_setup_error(self):
|
||||
self._licenses = self._get_licenses()
|
||||
self._start_periodic_tasks()
|
||||
|
||||
def _get_vserver(self, share_server=None):
|
||||
@ -260,10 +264,30 @@ class NetAppCmodeFileStorageLibrary(object):
|
||||
@na_utils.trace
|
||||
def _check_snaprestore_license(self):
|
||||
"""Check if snaprestore license is enabled."""
|
||||
if not self._licenses:
|
||||
self._licenses = self._client.get_licenses()
|
||||
if self._have_cluster_creds:
|
||||
return 'snaprestore' in self._licenses
|
||||
else:
|
||||
# NOTE: (felipe_rodrigues): workaround to find out whether the
|
||||
# backend has the license: since without cluster credentials it
|
||||
# cannot retrieve the ontap licenses, it sends a fake ONTAP
|
||||
# "snapshot-restore-volume" request which is only available when
|
||||
# the license exists. By the got error, it checks whether license
|
||||
# is installed or not.
|
||||
try:
|
||||
self._client.restore_snapshot(
|
||||
"fake_%s" % uuidutils.generate_uuid(dashed=False), "")
|
||||
except netapp_api.NaApiError as e:
|
||||
no_license = 'is not licensed'
|
||||
LOG.debug('Fake restore_snapshot request failed: %s', e)
|
||||
return not (e.code == netapp_api.EAPIERROR and
|
||||
no_license in e.message)
|
||||
|
||||
return 'snaprestore' in self._licenses
|
||||
# since it passed an empty snapshot, it should never get here
|
||||
msg = _("Caught an unexpected behavior: the fake restore to "
|
||||
"snapshot request using 'fake' volume and empty string "
|
||||
"snapshot as argument has not failed.")
|
||||
LOG.exception(msg)
|
||||
raise exception.NetAppException(msg)
|
||||
|
||||
@na_utils.trace
|
||||
def _get_aggregate_node(self, aggregate_name):
|
||||
@ -335,8 +359,6 @@ class NetAppCmodeFileStorageLibrary(object):
|
||||
netapp_flexvol_encryption = self._cluster_info.get(
|
||||
'nve_support', False)
|
||||
|
||||
revert_to_snapshot_support = self._check_snaprestore_license()
|
||||
|
||||
for aggr_name in sorted(aggregates):
|
||||
|
||||
reserved_percentage = self.configuration.reserved_share_percentage
|
||||
@ -368,7 +390,7 @@ class NetAppCmodeFileStorageLibrary(object):
|
||||
'thin_provisioning': [True, False],
|
||||
'snapshot_support': True,
|
||||
'create_share_from_snapshot_support': True,
|
||||
'revert_to_snapshot_support': revert_to_snapshot_support,
|
||||
'revert_to_snapshot_support': self._revert_to_snapshot_support,
|
||||
}
|
||||
|
||||
# Add storage service catalog data.
|
||||
|
@ -118,8 +118,16 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
||||
self.mock_object(
|
||||
self.library._client, 'check_for_cluster_credentials',
|
||||
mock.Mock(return_value=True))
|
||||
self.mock_object(
|
||||
self.library, '_check_snaprestore_license',
|
||||
mock.Mock(return_value=True))
|
||||
self.mock_object(
|
||||
self.library,
|
||||
'_get_licenses',
|
||||
mock.Mock(return_value=fake.LICENSES))
|
||||
self.library.do_setup(self.context)
|
||||
|
||||
self.assertEqual(fake.LICENSES, self.library._licenses)
|
||||
mock_get_api_client.assert_called_once_with()
|
||||
(self.library._client.check_for_cluster_credentials.
|
||||
assert_called_once_with())
|
||||
@ -127,6 +135,9 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
||||
self.mock_object(self.library._client,
|
||||
'check_for_cluster_credentials',
|
||||
mock.Mock(return_value=True))
|
||||
self.mock_object(
|
||||
self.library, '_check_snaprestore_license',
|
||||
mock.Mock(return_value=True))
|
||||
mock_set_cluster_info = self.mock_object(
|
||||
self.library, '_set_cluster_info')
|
||||
self.library.do_setup(self.context)
|
||||
@ -138,17 +149,10 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
||||
fake.CLUSTER_NODES)
|
||||
|
||||
def test_check_for_setup_error(self):
|
||||
|
||||
self.library._licenses = []
|
||||
self.mock_object(self.library,
|
||||
'_get_licenses',
|
||||
mock.Mock(return_value=['fake_license']))
|
||||
mock_start_periodic_tasks = self.mock_object(self.library,
|
||||
'_start_periodic_tasks')
|
||||
|
||||
self.library.check_for_setup_error()
|
||||
|
||||
self.assertEqual(['fake_license'], self.library._licenses)
|
||||
mock_start_periodic_tasks.assert_called_once_with()
|
||||
|
||||
def test_get_vserver(self):
|
||||
@ -333,7 +337,8 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
||||
assert_called_once_with(fake.AGGREGATES))
|
||||
self.assertDictEqual(fake.AGGREGATE_CAPACITIES, result)
|
||||
|
||||
def test_check_snaprestore_license_notfound(self):
|
||||
def test_check_snaprestore_license_admin_notfound(self):
|
||||
self.library._have_cluster_creds = True
|
||||
licenses = list(fake.LICENSES)
|
||||
licenses.remove('snaprestore')
|
||||
self.mock_object(self.client,
|
||||
@ -342,13 +347,44 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
||||
result = self.library._check_snaprestore_license()
|
||||
self.assertIs(False, result)
|
||||
|
||||
def test_check_snaprestore_license_found(self):
|
||||
self.mock_object(self.client,
|
||||
'get_licenses',
|
||||
mock.Mock(return_value=fake.LICENSES))
|
||||
def test_check_snaprestore_license_admin_found(self):
|
||||
self.library._have_cluster_creds = True
|
||||
self.library._licenses = fake.LICENSES
|
||||
result = self.library._check_snaprestore_license()
|
||||
self.assertIs(True, result)
|
||||
|
||||
def test_check_snaprestore_license_svm_scoped_notfound(self):
|
||||
self.library._have_cluster_creds = False
|
||||
self.mock_object(self.library._client,
|
||||
'restore_snapshot',
|
||||
mock.Mock(side_effect=netapp_api.NaApiError(
|
||||
code=netapp_api.EAPIERROR,
|
||||
message=fake.NO_SNAPRESTORE_LICENSE)))
|
||||
result = self.library._check_snaprestore_license()
|
||||
self.assertIs(False, result)
|
||||
|
||||
def test_check_snaprestore_license_svm_scoped_found(self):
|
||||
self.library._have_cluster_creds = False
|
||||
self.mock_object(self.library._client,
|
||||
'restore_snapshot',
|
||||
mock.Mock(side_effect=netapp_api.NaApiError(
|
||||
code=netapp_api.EAPIERROR,
|
||||
message='Other error')))
|
||||
result = self.library._check_snaprestore_license()
|
||||
self.assertIs(True, result)
|
||||
|
||||
def test_check_snaprestore_license_svm_scoped_found_exception(self):
|
||||
self.mock_object(lib_base.LOG, 'exception')
|
||||
self.library._have_cluster_creds = False
|
||||
self.mock_object(self.library._client,
|
||||
'restore_snapshot',
|
||||
mock.Mock(return_value=None))
|
||||
|
||||
self.assertRaises(
|
||||
exception.NetAppException,
|
||||
self.library._check_snaprestore_license)
|
||||
lib_base.LOG.exception.assert_called_once()
|
||||
|
||||
def test_get_aggregate_node_cluster_creds(self):
|
||||
|
||||
self.library._have_cluster_creds = True
|
||||
@ -449,13 +485,11 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
||||
self.library, '_get_aggregate_space',
|
||||
mock.Mock(return_value=fake.AGGREGATE_CAPACITIES))
|
||||
self.library._have_cluster_creds = True
|
||||
self.library._revert_to_snapshot_support = True
|
||||
self.library._cluster_info = fake.CLUSTER_INFO
|
||||
self.library._ssc_stats = fake.SSC_INFO
|
||||
self.library._perf_library.get_node_utilization_for_pool = (
|
||||
mock.Mock(side_effect=[30.0, 42.0]))
|
||||
self.mock_object(self.library,
|
||||
'_check_snaprestore_license',
|
||||
mock.Mock(return_value=True))
|
||||
|
||||
result = self.library._get_pools(filter_function='filter',
|
||||
goodness_function='goodness')
|
||||
@ -468,13 +502,11 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
||||
self.library, '_get_aggregate_space',
|
||||
mock.Mock(return_value=fake.AGGREGATE_CAPACITIES_VSERVER_CREDS))
|
||||
self.library._have_cluster_creds = False
|
||||
self.library._revert_to_snapshot_support = True
|
||||
self.library._cluster_info = fake.CLUSTER_INFO
|
||||
self.library._ssc_stats = fake.SSC_INFO_VSERVER_CREDS
|
||||
self.library._perf_library.get_node_utilization_for_pool = (
|
||||
mock.Mock(side_effect=[50.0, 50.0]))
|
||||
self.mock_object(self.library,
|
||||
'_check_snaprestore_license',
|
||||
mock.Mock(return_value=True))
|
||||
|
||||
result = self.library._get_pools()
|
||||
|
||||
|
@ -18,6 +18,7 @@ import copy
|
||||
from manila.common import constants
|
||||
import manila.tests.share.drivers.netapp.fakes as na_fakes
|
||||
|
||||
NO_SNAPRESTORE_LICENSE = '"SnapRestore" is not licensed in the cluster.'
|
||||
CLUSTER_NAME = 'fake_cluster'
|
||||
CLUSTER_NAME_2 = 'fake_cluster_2'
|
||||
BACKEND_NAME = 'fake_backend_name'
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
Fixed `bug #1882590 <https://bugs.launchpad.net/manila/+bug/1882590>`_
|
||||
that caused an error on starting a NetApp backend when using the SVM
|
||||
scoped account.
|
Loading…
Reference in New Issue
Block a user