
Situation: The function get_part_nodes is being called by Openstack-Swift's proxy/controllers/base.py: https://github.com/openstack/swift/blob/1.7.4/swift/proxy/controllers/base.py#L410 https://github.com/openstack/swift/blob/1.7.6/swift/proxy/controllers/base.py#L447 As this was not implemented in the current GlusterFS version of ring.py, it was calling swift's original get_part_nodes, which would often return the incorrect node, resulting in the incorrect drive being associated with a request. There is another function that the original ring.py implements -- get_other_nodes, which has to do with replication. Since GlusterFS is handling replication, this function should never be called. However, in the interest of completeness, that function is also being replaced. Code changes: The two functions, get_part_nodes, and get_other_nodes have been implemented to override the default functions, and get_nodes has been updated to store information in self vars, about the account being operated on, as the two new functions are not called with that info, and get_nodes appears to always be called first. The code has be refactored to all call _get_part_nodes, much like swift has refactored their code. Reason for implementation this way: I didn't see a better way to do it, but am open to suggestions. Test cases: A mock ring is created with two different devices, test and iops test_first_device: Ensure that the first device, test, is returned for both get_nodes, and get_part_node, and get_more_nodes returns volume_not_in_ring. test_invalid_device: Ensure that a request for a non-existant device returns volume_not_in_ring. test_second_device: Same as test_first_device, but for the second device, iops instead of test. test_second_device_with_reseller_prefix: Test that calling with the reseller prefix, AUTH_ will still return the correct data. Change-Id: I2f3d526934a47b01e9c065d0edf0fbf06f300369 BUG: 924792 Signed-off-by: Alex Wheeler <wheelear@gmail.com> Reviewed-on: http://review.gluster.org/4748 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com> Reviewed-by: Jeff Darcy <jdarcy@redhat.com> Reviewed-by: Anand Avati <avati@redhat.com>
82 lines
2.8 KiB
Python
82 lines
2.8 KiB
Python
# Copyright (c) 2013 Red Hat, Inc.
|
|
#
|
|
# 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 unittest
|
|
import gluster.swift.common.constraints
|
|
from gluster.swift.common.ring import *
|
|
from gluster.swift.common.Glusterfs import SWIFT_DIR
|
|
|
|
def _mock_ring_data():
|
|
return [{'zone': 1, 'weight': 100.0, 'ip': '127.0.0.1', 'port': 6012, \
|
|
'meta': '', 'device': 'test', 'id': 0},
|
|
{'zone': 2, 'weight': 100.0, 'ip': '127.0.0.1', 'id': 1, \
|
|
'meta': '', 'device': 'iops', 'port': 6012}]
|
|
|
|
class TestRing(unittest.TestCase):
|
|
""" Tests for common.utils """
|
|
|
|
def setUp(self):
|
|
self.ring = Ring(SWIFT_DIR, ring_name='object')
|
|
|
|
def test_first_device(self):
|
|
try:
|
|
__devs = self.ring._devs
|
|
self.ring._devs = _mock_ring_data()
|
|
|
|
part, node = self.ring.get_nodes('test')
|
|
assert node[0]['device'] == 'test'
|
|
node = self.ring.get_part_nodes(0)
|
|
assert node[0]['device'] == 'test'
|
|
for node in self.ring.get_more_nodes(0):
|
|
assert node['device'] == 'volume_not_in_ring'
|
|
finally:
|
|
self.ring._devs = __devs
|
|
|
|
def test_invalid_device(self):
|
|
try:
|
|
__devs = self.ring._devs
|
|
self.ring._devs = _mock_ring_data()
|
|
|
|
part, node = self.ring.get_nodes('test2')
|
|
assert node[0]['device'] == 'volume_not_in_ring'
|
|
node = self.ring.get_part_nodes(0)
|
|
assert node[0]['device'] == 'volume_not_in_ring'
|
|
finally:
|
|
self.ring._devs = __devs
|
|
|
|
def test_second_device(self):
|
|
try:
|
|
__devs = self.ring._devs
|
|
self.ring._devs = _mock_ring_data()
|
|
|
|
part, node = self.ring.get_nodes('iops')
|
|
assert node[0]['device'] == 'iops'
|
|
node = self.ring.get_part_nodes(0)
|
|
assert node[0]['device'] == 'iops'
|
|
for node in self.ring.get_more_nodes(0):
|
|
assert node['device'] == 'volume_not_in_ring'
|
|
finally:
|
|
self.ring._devs = __devs
|
|
|
|
def test_second_device_with_reseller_prefix(self):
|
|
try:
|
|
__devs = self.ring._devs
|
|
self.ring._devs = _mock_ring_data()
|
|
|
|
part, node = self.ring.get_nodes('AUTH_iops')
|
|
assert node[0]['device'] == 'iops'
|
|
finally:
|
|
self.ring._devs = __devs
|