Handle IPv6 addresses in swift-get-nodes.

The curl commands needed a little tweaking.

Change-Id: I6551d65241950c65e7160587cc414deb4a2122f5
Closes-Bug: 1555860
This commit is contained in:
Samuel Merritt 2016-03-11 16:15:17 -08:00 committed by Clay Gerrard
parent 902cb8f8d7
commit 457cea864c
2 changed files with 122 additions and 14 deletions

View File

@ -20,7 +20,7 @@ from six.moves import urllib
from swift.common.utils import hash_path, storage_directory, \
Timestamp
from swift.common.ring import Ring
from swift.common.ring import Ring, utils as ring_utils
from swift.common.request_helpers import is_sys_meta, is_user_meta, \
strip_sys_meta_prefix, strip_user_meta_prefix
from swift.account.backend import AccountBroker, DATADIR as ABDATADIR
@ -37,6 +37,32 @@ class InfoSystemExit(Exception):
pass
def curl_head_command(ip, port, device, part, target, policy_index):
"""
Provide a string that is a well formatted curl command to HEAD an object
on a storage node.
:param ip: the ip of the node
:param port: the port of the node
:param device: the device of the node
:param target: the path of the target resource
:param policy_index: the policy_index of the target resource (can be None)
:returns: a string, a well formatted curl command
"""
if ring_utils.is_valid_ipv6(ip):
formatted_ip = '[%s]' % ip
else:
formatted_ip = ip
cmd = 'curl -g -I -XHEAD "http://%s:%s/%s/%s/%s"' % (
formatted_ip, port, device, part, urllib.parse.quote(target))
if policy_index is not None:
cmd += ' -H "%s: %s"' % ('X-Backend-Storage-Policy-Index',
policy_index)
return cmd
def print_ring_locations(ring, datadir, account, container=None, obj=None,
tpart=None, all_nodes=False, policy_index=None):
"""
@ -99,20 +125,12 @@ def print_ring_locations(ring, datadir, account, container=None, obj=None,
print("\n")
for node in primary_nodes:
cmd = 'curl -I -XHEAD "http://%s:%s/%s/%s/%s"' \
% (node['ip'], node['port'], node['device'], part,
urllib.parse.quote(target))
if policy_index is not None:
cmd += ' -H "%s: %s"' % ('X-Backend-Storage-Policy-Index',
policy_index)
cmd = curl_head_command(node['ip'], node['port'], node['device'],
part, target, policy_index)
print(cmd)
for node in handoff_nodes:
cmd = 'curl -I -XHEAD "http://%s:%s/%s/%s/%s"' \
% (node['ip'], node['port'], node['device'], part,
urllib.parse.quote(target))
if policy_index is not None:
cmd += ' -H "%s: %s"' % ('X-Backend-Storage-Policy-Index',
policy_index)
cmd = curl_head_command(node['ip'], node['port'], node['device'],
part, target, policy_index)
cmd += ' # [Handoff]'
print(cmd)

View File

@ -34,7 +34,8 @@ from swift.obj.diskfile import write_metadata
@patch_policies([StoragePolicy(0, 'zero', True),
StoragePolicy(1, 'one', False),
StoragePolicy(2, 'two', False)])
StoragePolicy(2, 'two', False),
StoragePolicy(3, 'three', False)])
class TestCliInfoBase(unittest.TestCase):
def setUp(self):
self.orig_hp = utils.HASH_PATH_PREFIX, utils.HASH_PATH_SUFFIX
@ -72,6 +73,13 @@ class TestCliInfoBase(unittest.TestCase):
# ... and another for policy 2
self.two_ring_path = os.path.join(self.testdir, 'object-2.ring.gz')
write_fake_ring(self.two_ring_path, *object_devs)
# ... and one for policy 3 with some v6 IPs in it
object_devs_ipv6 = [
{'ip': 'feed:face::dead:beef', 'port': 42},
{'ip': 'deca:fc0f:feeb:ad11::1', 'port': 43}
]
self.three_ring_path = os.path.join(self.testdir, 'object-3.ring.gz')
write_fake_ring(self.three_ring_path, *object_devs_ipv6)
def tearDown(self):
utils.HASH_PATH_PREFIX, utils.HASH_PATH_SUFFIX = self.orig_hp
@ -569,6 +577,88 @@ class TestPrintObjFullMeta(TestCliInfoBase):
os.chdir(cwd)
self.assertTrue('X-Backend-Storage-Policy-Index: 1' in out.getvalue())
def test_print_obj_curl_command_ipv4(self):
# Note: policy 2 has IPv4 addresses in its ring
datafile2 = os.path.join(
self.testdir,
'sda', 'objects-2', '1', 'ea8',
'db4449e025aca992307c7c804a67eea8', '1402017884.18202.data')
utils.mkdirs(os.path.dirname(datafile2))
with open(datafile2, 'wb') as fp:
md = {'name': '/AUTH_admin/c/obj',
'Content-Type': 'application/octet-stream',
'ETag': 'd41d8cd98f00b204e9800998ecf8427e',
'Content-Length': 0}
write_metadata(fp, md)
object_ring = ring.Ring(self.testdir, ring_name='object-2')
part, nodes = object_ring.get_nodes('AUTH_admin', 'c', 'obj')
node = nodes[0]
out = StringIO()
hash_dir = os.path.dirname(datafile2)
file_name = os.path.basename(datafile2)
# Change working directory to object hash dir
cwd = os.getcwd()
try:
os.chdir(hash_dir)
with mock.patch('sys.stdout', out):
print_obj(file_name, swift_dir=self.testdir)
finally:
os.chdir(cwd)
exp_curl = (
'curl -g -I -XHEAD '
'"http://{host}:{port}/{device}/{part}/AUTH_admin/c/obj" '
'-H "X-Backend-Storage-Policy-Index: 2"').format(
host=node['ip'],
port=node['port'],
device=node['device'],
part=part)
self.assertIn(exp_curl, out.getvalue())
def test_print_obj_curl_command_ipv6(self):
# Note: policy 3 has IPv6 addresses in its ring
datafile3 = os.path.join(
self.testdir,
'sda', 'objects-3', '1', 'ea8',
'db4449e025aca992307c7c804a67eea8', '1402017884.18202.data')
utils.mkdirs(os.path.dirname(datafile3))
with open(datafile3, 'wb') as fp:
md = {'name': '/AUTH_admin/c/obj',
'Content-Type': 'application/octet-stream',
'ETag': 'd41d8cd98f00b204e9800998ecf8427e',
'Content-Length': 0}
write_metadata(fp, md)
object_ring = ring.Ring(self.testdir, ring_name='object-3')
part, nodes = object_ring.get_nodes('AUTH_admin', 'c', 'obj')
node = nodes[0]
out = StringIO()
hash_dir = os.path.dirname(datafile3)
file_name = os.path.basename(datafile3)
# Change working directory to object hash dir
cwd = os.getcwd()
try:
os.chdir(hash_dir)
with mock.patch('sys.stdout', out):
print_obj(file_name, swift_dir=self.testdir)
finally:
os.chdir(cwd)
exp_curl = (
'curl -g -I -XHEAD '
'"http://[{host}]:{port}'
'/{device}/{part}/AUTH_admin/c/obj" ').format(
host=node['ip'],
port=node['port'],
device=node['device'],
part=part)
self.assertIn(exp_curl, out.getvalue())
def test_print_obj_meta_and_ts_files(self):
# verify that print_obj will also read from meta and ts files
base = os.path.splitext(self.datafile)[0]