Warn about using EC with isa_l_rs_vand and nparity >= 5
We *know* there are combinations that will prevent decoding, and we're going to be increasingly aggressive about getting it out of clusters. Partial-Bug: 1639691 Change-Id: I50159c9d19f2385d5f60112e9aaefa1a68098313
This commit is contained in:
parent
3129a55d44
commit
bd75a97ad4
|
@ -12,8 +12,10 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import string
|
import string
|
||||||
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
import six
|
import six
|
||||||
from six.moves.configparser import ConfigParser
|
from six.moves.configparser import ConfigParser
|
||||||
|
@ -453,6 +455,26 @@ class ECStoragePolicy(BaseStoragePolicy):
|
||||||
raise PolicyError('Invalid ec_object_segment_size %r' %
|
raise PolicyError('Invalid ec_object_segment_size %r' %
|
||||||
ec_segment_size, index=self.idx)
|
ec_segment_size, index=self.idx)
|
||||||
|
|
||||||
|
if self._ec_type == 'isa_l_rs_vand' and self._ec_nparity >= 5:
|
||||||
|
logger = logging.getLogger("swift.common.storage_policy")
|
||||||
|
if not logger.handlers:
|
||||||
|
# If nothing else, log to stderr
|
||||||
|
logger.addHandler(logging.StreamHandler(sys.__stderr__))
|
||||||
|
logger.warning(
|
||||||
|
'Storage policy %s uses an EC configuration known to harm '
|
||||||
|
'data durability. Any data in this policy should be migrated. '
|
||||||
|
'See https://bugs.launchpad.net/swift/+bug/1639691 for '
|
||||||
|
'more information.' % self.name)
|
||||||
|
if not is_deprecated:
|
||||||
|
# TODO: To fully close bug 1639691, uncomment the raise and
|
||||||
|
# removing the warning below. This will be in the Pike release
|
||||||
|
# at the earliest.
|
||||||
|
logger.warning(
|
||||||
|
'In a future release, this will prevent services from '
|
||||||
|
'starting unless the policy is marked as deprecated.')
|
||||||
|
# raise PolicyError('Storage policy %s MUST be deprecated' %
|
||||||
|
# self.name)
|
||||||
|
|
||||||
# Initialize PyECLib EC backend
|
# Initialize PyECLib EC backend
|
||||||
try:
|
try:
|
||||||
self.pyeclib_driver = \
|
self.pyeclib_driver = \
|
||||||
|
|
|
@ -12,7 +12,9 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
""" Tests for swift.common.storage_policies """
|
""" Tests for swift.common.storage_policies """
|
||||||
|
import contextlib
|
||||||
import six
|
import six
|
||||||
|
import logging
|
||||||
import unittest
|
import unittest
|
||||||
import os
|
import os
|
||||||
import mock
|
import mock
|
||||||
|
@ -20,6 +22,7 @@ from functools import partial
|
||||||
from six.moves.configparser import ConfigParser
|
from six.moves.configparser import ConfigParser
|
||||||
from tempfile import NamedTemporaryFile
|
from tempfile import NamedTemporaryFile
|
||||||
from test.unit import patch_policies, FakeRing, temptree, DEFAULT_TEST_EC_TYPE
|
from test.unit import patch_policies, FakeRing, temptree, DEFAULT_TEST_EC_TYPE
|
||||||
|
import swift.common.storage_policy
|
||||||
from swift.common.storage_policy import (
|
from swift.common.storage_policy import (
|
||||||
StoragePolicyCollection, POLICIES, PolicyError, parse_storage_policies,
|
StoragePolicyCollection, POLICIES, PolicyError, parse_storage_policies,
|
||||||
reload_storage_policies, get_policy_string, split_policy_string,
|
reload_storage_policies, get_policy_string, split_policy_string,
|
||||||
|
@ -30,6 +33,26 @@ from swift.common.exceptions import RingLoadError
|
||||||
from pyeclib.ec_iface import ECDriver
|
from pyeclib.ec_iface import ECDriver
|
||||||
|
|
||||||
|
|
||||||
|
class CapturingHandler(logging.Handler):
|
||||||
|
def __init__(self):
|
||||||
|
super(CapturingHandler, self).__init__()
|
||||||
|
self._records = []
|
||||||
|
|
||||||
|
def emit(self, record):
|
||||||
|
self._records.append(record)
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def capture_logging(log_name):
|
||||||
|
captured = CapturingHandler()
|
||||||
|
logger = logging.getLogger(log_name)
|
||||||
|
logger.addHandler(captured)
|
||||||
|
try:
|
||||||
|
yield captured._records
|
||||||
|
finally:
|
||||||
|
logger.removeHandler(captured)
|
||||||
|
|
||||||
|
|
||||||
@BaseStoragePolicy.register('fake')
|
@BaseStoragePolicy.register('fake')
|
||||||
class FakeStoragePolicy(BaseStoragePolicy):
|
class FakeStoragePolicy(BaseStoragePolicy):
|
||||||
"""
|
"""
|
||||||
|
@ -582,6 +605,91 @@ class TestStoragePolicies(unittest.TestCase):
|
||||||
PolicyError, "must specify a storage policy section "
|
PolicyError, "must specify a storage policy section "
|
||||||
"for policy index 0", parse_storage_policies, bad_conf)
|
"for policy index 0", parse_storage_policies, bad_conf)
|
||||||
|
|
||||||
|
@mock.patch.object(swift.common.storage_policy, 'VALID_EC_TYPES',
|
||||||
|
['isa_l_rs_vand', 'isa_l_rs_cauchy'])
|
||||||
|
@mock.patch('swift.common.storage_policy.ECDriver')
|
||||||
|
def test_known_bad_ec_config(self, mock_driver):
|
||||||
|
good_conf = self._conf("""
|
||||||
|
[storage-policy:0]
|
||||||
|
name = bad-policy
|
||||||
|
policy_type = erasure_coding
|
||||||
|
ec_type = isa_l_rs_cauchy
|
||||||
|
ec_num_data_fragments = 10
|
||||||
|
ec_num_parity_fragments = 5
|
||||||
|
""")
|
||||||
|
|
||||||
|
with capture_logging('swift.common.storage_policy') as records:
|
||||||
|
parse_storage_policies(good_conf)
|
||||||
|
mock_driver.assert_called_once()
|
||||||
|
mock_driver.reset_mock()
|
||||||
|
self.assertFalse([(r.levelname, r.message) for r in records])
|
||||||
|
|
||||||
|
good_conf = self._conf("""
|
||||||
|
[storage-policy:0]
|
||||||
|
name = bad-policy
|
||||||
|
policy_type = erasure_coding
|
||||||
|
ec_type = isa_l_rs_vand
|
||||||
|
ec_num_data_fragments = 10
|
||||||
|
ec_num_parity_fragments = 4
|
||||||
|
""")
|
||||||
|
|
||||||
|
with capture_logging('swift.common.storage_policy') as records:
|
||||||
|
parse_storage_policies(good_conf)
|
||||||
|
mock_driver.assert_called_once()
|
||||||
|
mock_driver.reset_mock()
|
||||||
|
self.assertFalse([(r.levelname, r.message) for r in records])
|
||||||
|
|
||||||
|
bad_conf = self._conf("""
|
||||||
|
[storage-policy:0]
|
||||||
|
name = bad-policy
|
||||||
|
policy_type = erasure_coding
|
||||||
|
ec_type = isa_l_rs_vand
|
||||||
|
ec_num_data_fragments = 10
|
||||||
|
ec_num_parity_fragments = 5
|
||||||
|
""")
|
||||||
|
|
||||||
|
with capture_logging('swift.common.storage_policy') as records:
|
||||||
|
parse_storage_policies(bad_conf)
|
||||||
|
mock_driver.assert_called_once()
|
||||||
|
mock_driver.reset_mock()
|
||||||
|
self.assertEqual([r.levelname for r in records],
|
||||||
|
['WARNING', 'WARNING'])
|
||||||
|
for msg in ('known to harm data durability',
|
||||||
|
'Any data in this policy should be migrated',
|
||||||
|
'https://bugs.launchpad.net/swift/+bug/1639691'):
|
||||||
|
self.assertIn(msg, records[0].message)
|
||||||
|
self.assertIn('In a future release, this will prevent services from '
|
||||||
|
'starting', records[1].message)
|
||||||
|
|
||||||
|
slightly_less_bad_conf = self._conf("""
|
||||||
|
[storage-policy:0]
|
||||||
|
name = bad-policy
|
||||||
|
policy_type = erasure_coding
|
||||||
|
ec_type = isa_l_rs_vand
|
||||||
|
ec_num_data_fragments = 10
|
||||||
|
ec_num_parity_fragments = 5
|
||||||
|
deprecated = true
|
||||||
|
|
||||||
|
[storage-policy:1]
|
||||||
|
name = good-policy
|
||||||
|
policy_type = erasure_coding
|
||||||
|
ec_type = isa_l_rs_cauchy
|
||||||
|
ec_num_data_fragments = 10
|
||||||
|
ec_num_parity_fragments = 5
|
||||||
|
default = true
|
||||||
|
""")
|
||||||
|
|
||||||
|
with capture_logging('swift.common.storage_policy') as records:
|
||||||
|
parse_storage_policies(slightly_less_bad_conf)
|
||||||
|
self.assertEqual(2, mock_driver.call_count)
|
||||||
|
mock_driver.reset_mock()
|
||||||
|
self.assertEqual([r.levelname for r in records],
|
||||||
|
['WARNING'])
|
||||||
|
for msg in ('known to harm data durability',
|
||||||
|
'Any data in this policy should be migrated',
|
||||||
|
'https://bugs.launchpad.net/swift/+bug/1639691'):
|
||||||
|
self.assertIn(msg, records[0].message)
|
||||||
|
|
||||||
def test_no_default(self):
|
def test_no_default(self):
|
||||||
orig_conf = self._conf("""
|
orig_conf = self._conf("""
|
||||||
[storage-policy:0]
|
[storage-policy:0]
|
||||||
|
|
Loading…
Reference in New Issue