
This patchset adds a support for Swift Global Cluster feature as described at: https://docs.openstack.org/swift/latest/overview_global_cluster.html It allows specifying affinity settings as parrt of the deployment. Moreover, the master - slave relation is introduced for the purpose of rings distribution across proxy nodes participating in the Swift Global Cluster. Change-Id: I406445493e2226aa5ae40a09c9053ac8633a46e9 Closes-Bug: 1815879 Depends-On: I11b6c7802e5bfbd61b06e4d11c65804a165781b6
124 lines
3.9 KiB
Python
124 lines
3.9 KiB
Python
import mock
|
|
import unittest
|
|
|
|
import manager
|
|
|
|
|
|
def create_mock_load_builder_fn(mock_rings):
|
|
"""To avoid the need for swift.common.ring library, mock a basic rings
|
|
dictionary, keyed by path. Each ring has enough logic to hold a dictionary
|
|
with a single 'devs' key, which stores the list of passed dev(s) by
|
|
add_dev().
|
|
|
|
If swift (actual) ring representation diverges (see _load_builder),
|
|
this mock will need to be adapted.
|
|
|
|
:param mock_rings: a dict containing the dict form of the rings
|
|
"""
|
|
def mock_load_builder_fn(path):
|
|
class mock_ring(object):
|
|
def __init__(self, path):
|
|
self.path = path
|
|
|
|
def to_dict(self):
|
|
return mock_rings[self.path]
|
|
|
|
def add_dev(self, dev):
|
|
mock_rings[self.path]['devs'].append(dev)
|
|
|
|
return mock_ring(path)
|
|
return mock_load_builder_fn
|
|
|
|
|
|
MOCK_SWIFT_RINGS = {
|
|
'account': 'account.builder',
|
|
'container': 'container.builder',
|
|
'object': 'object.builder'
|
|
}
|
|
|
|
|
|
class TestSwiftManager(unittest.TestCase):
|
|
|
|
@mock.patch('os.path.isfile')
|
|
@mock.patch.object(manager, '_load_builder')
|
|
def test_has_minimum_zones(self, mock_load_builder, mock_is_file):
|
|
mock_rings = {}
|
|
|
|
mock_load_builder.side_effect = create_mock_load_builder_fn(mock_rings)
|
|
for ring in MOCK_SWIFT_RINGS:
|
|
mock_rings[ring] = {
|
|
'replicas': 3,
|
|
'devs': [{'region': 1, 'zone': 1},
|
|
{'region': 1, 'zone': 2},
|
|
None,
|
|
{'region': 1, 'zone': 3}],
|
|
}
|
|
ret = manager.has_minimum_zones(MOCK_SWIFT_RINGS)
|
|
self.assertTrue(ret['result'])
|
|
|
|
# Increase the replicas to make sure that it returns false
|
|
for ring in MOCK_SWIFT_RINGS:
|
|
mock_rings[ring]['replicas'] = 4
|
|
|
|
ret = manager.has_minimum_zones(MOCK_SWIFT_RINGS)
|
|
self.assertFalse(ret['result'])
|
|
|
|
@mock.patch.object(manager, '_load_builder')
|
|
def test_exists_in_ring(self, mock_load_builder):
|
|
mock_rings = {}
|
|
|
|
mock_load_builder.side_effect = create_mock_load_builder_fn(mock_rings)
|
|
ring = 'account'
|
|
mock_rings[ring] = {
|
|
'devs': [
|
|
{'replication_port': 6000, 'zone': 1, 'weight': 100.0,
|
|
'ip': '172.16.0.2', 'region': 1, 'port': 6000,
|
|
'replication_ip': '172.16.0.2', 'parts': 2, 'meta': '',
|
|
'device': u'bcache10', 'parts_wanted': 0, 'id': 199},
|
|
None, # Ring can have holes, so add None to simulate
|
|
{'replication_port': 6000, 'zone': 1, 'weight': 100.0,
|
|
'ip': '172.16.0.2', 'region': 1, 'id': 198,
|
|
'replication_ip': '172.16.0.2', 'parts': 2, 'meta': '',
|
|
'device': u'bcache13', 'parts_wanted': 0, 'port': 6000},
|
|
]
|
|
}
|
|
|
|
node = {
|
|
'ip': '172.16.0.2',
|
|
'region': 1,
|
|
'account_port': 6000,
|
|
'zone': 1,
|
|
'replication_port': 6000,
|
|
'weight': 100.0,
|
|
'device': u'bcache10',
|
|
}
|
|
|
|
ret = manager.exists_in_ring(ring, node)
|
|
self.assertTrue(ret)
|
|
|
|
node['region'] = 2
|
|
ret = manager.exists_in_ring(ring, node)
|
|
self.assertFalse(ret)
|
|
|
|
@mock.patch.object(manager, '_write_ring')
|
|
@mock.patch.object(manager, '_load_builder')
|
|
def test_add_dev(self, mock_load_builder, mock_write_ring):
|
|
mock_rings = {}
|
|
mock_load_builder.side_effect = create_mock_load_builder_fn(mock_rings)
|
|
ring = 'account'
|
|
mock_rings[ring] = {
|
|
'devs': []
|
|
}
|
|
|
|
new_dev = {
|
|
'meta': '',
|
|
'zone': 1,
|
|
'ip': '172.16.0.2',
|
|
'device': '/dev/sdb',
|
|
'port': 6000,
|
|
'weight': 100
|
|
}
|
|
manager.add_dev(ring, new_dev)
|
|
mock_write_ring.assert_called_once()
|
|
self.assertTrue('id' not in mock_rings[ring]['devs'][0])
|