Add policy support to dispersion tools

Doesn't work for anything other than policy 0. updated to allow user
to specify policy name on cmd line (as with object-info) which
then makes populate/report work with 3x, 2x, or EC style policies

Change-Id: Ib7c298f0f6d666b1ecca25315b88539f45cf9f95
Closes-Bug: 1458688
This commit is contained in:
paul luse 2015-05-25 14:41:42 -07:00 committed by Kota Tsuyuzaki
parent e9a032f896
commit e6165a7879
3 changed files with 60 additions and 19 deletions

View File

@ -31,16 +31,17 @@ except ImportError:
from swift.common.internal_client import SimpleClient from swift.common.internal_client import SimpleClient
from swift.common.ring import Ring from swift.common.ring import Ring
from swift.common.utils import compute_eta, get_time_units, config_true_value from swift.common.utils import compute_eta, get_time_units, config_true_value
from swift.common.storage_policy import POLICIES
insecure = False insecure = False
def put_container(connpool, container, report): def put_container(connpool, container, report, headers):
global retries_done global retries_done
try: try:
with connpool.item() as conn: with connpool.item() as conn:
conn.put_container(container) conn.put_container(container, headers=headers)
retries_done += conn.attempts - 1 retries_done += conn.attempts - 1
if report: if report:
report(True) report(True)
@ -105,6 +106,9 @@ Usage: %%prog [options] [conf_file]
help='No overlap of partitions if running populate \ help='No overlap of partitions if running populate \
more than once. Will increase coverage by amount shown \ more than once. Will increase coverage by amount shown \
in dispersion.conf file') in dispersion.conf file')
parser.add_option('-P', '--policy-name', dest='policy_name',
help="Specify storage policy name")
options, args = parser.parse_args() options, args = parser.parse_args()
if args: if args:
@ -114,6 +118,15 @@ Usage: %%prog [options] [conf_file]
if not c.read(conffile): if not c.read(conffile):
exit('Unable to read config file: %s' % conffile) exit('Unable to read config file: %s' % conffile)
conf = dict(c.items('dispersion')) conf = dict(c.items('dispersion'))
if options.policy_name is None:
policy = POLICIES.default
else:
policy = POLICIES.get_by_name(options.policy_name)
if policy is None:
exit('Unable to find policy: %s' % options.policy_name)
print 'Using storage policy: %s ' % policy.name
swift_dir = conf.get('swift_dir', '/etc/swift') swift_dir = conf.get('swift_dir', '/etc/swift')
dispersion_coverage = float(conf.get('dispersion_coverage', 1)) dispersion_coverage = float(conf.get('dispersion_coverage', 1))
retries = int(conf.get('retries', 5)) retries = int(conf.get('retries', 5))
@ -141,6 +154,8 @@ Usage: %%prog [options] [conf_file]
insecure=insecure) insecure=insecure)
account = url.rsplit('/', 1)[1] account = url.rsplit('/', 1)[1]
connpool = Pool(max_size=concurrency) connpool = Pool(max_size=concurrency)
headers = {}
headers['X-Storage-Policy'] = policy.name
connpool.create = lambda: SimpleClient( connpool.create = lambda: SimpleClient(
url=url, token=token, retries=retries) url=url, token=token, retries=retries)
@ -152,7 +167,7 @@ Usage: %%prog [options] [conf_file]
if options.no_overlap: if options.no_overlap:
with connpool.item() as conn: with connpool.item() as conn:
containers = [cont['name'] for cont in conn.get_account( containers = [cont['name'] for cont in conn.get_account(
prefix='dispersion_', full_listing=True)[1]] prefix='dispersion_%d' % policy.idx, full_listing=True)[1]]
containers_listed = len(containers) containers_listed = len(containers)
if containers_listed > 0: if containers_listed > 0:
for container in containers: for container in containers:
@ -170,11 +185,12 @@ Usage: %%prog [options] [conf_file]
next_report += 2 next_report += 2
suffix = 0 suffix = 0
while need_to_queue >= 1 and parts_left: while need_to_queue >= 1 and parts_left:
container = 'dispersion_%d' % suffix container = 'dispersion_%d_%d' % (policy.idx, suffix)
part = container_ring.get_part(account, container) part = container_ring.get_part(account, container)
if part in parts_left: if part in parts_left:
if suffix >= options.container_suffix_start: if suffix >= options.container_suffix_start:
coropool.spawn(put_container, connpool, container, report) coropool.spawn(put_container, connpool, container, report,
headers)
sleep() sleep()
else: else:
report(True) report(True)
@ -195,9 +211,9 @@ Usage: %%prog [options] [conf_file]
stdout.flush() stdout.flush()
if object_populate: if object_populate:
container = 'dispersion_objects' container = 'dispersion_objects_%d' % policy.idx
put_container(connpool, container, None) put_container(connpool, container, None, headers)
object_ring = Ring(swift_dir, ring_name='object') object_ring = Ring(swift_dir, ring_name=policy.ring_name)
parts_left = dict((x, x) for x in xrange(object_ring.partition_count)) parts_left = dict((x, x) for x in xrange(object_ring.partition_count))
if options.no_overlap: if options.no_overlap:

View File

@ -36,6 +36,7 @@ from swift.common.internal_client import SimpleClient
from swift.common.ring import Ring from swift.common.ring import Ring
from swift.common.exceptions import ClientException from swift.common.exceptions import ClientException
from swift.common.utils import compute_eta, get_time_units, config_true_value from swift.common.utils import compute_eta, get_time_units, config_true_value
from swift.common.storage_policy import POLICIES
unmounted = [] unmounted = []
@ -73,10 +74,10 @@ def get_error_log(prefix):
def container_dispersion_report(coropool, connpool, account, container_ring, def container_dispersion_report(coropool, connpool, account, container_ring,
retries, output_missing_partitions): retries, output_missing_partitions, policy):
with connpool.item() as conn: with connpool.item() as conn:
containers = [c['name'] for c in conn.get_account( containers = [c['name'] for c in conn.get_account(
prefix='dispersion_', full_listing=True)[1]] prefix='dispersion_%d' % policy.idx, full_listing=True)[1]]
containers_listed = len(containers) containers_listed = len(containers)
if not containers_listed: if not containers_listed:
print >>stderr, 'No containers to query. Has ' \ print >>stderr, 'No containers to query. Has ' \
@ -169,8 +170,8 @@ def container_dispersion_report(coropool, connpool, account, container_ring,
def object_dispersion_report(coropool, connpool, account, object_ring, def object_dispersion_report(coropool, connpool, account, object_ring,
retries, output_missing_partitions): retries, output_missing_partitions, policy):
container = 'dispersion_objects' container = 'dispersion_objects_%d' % policy.idx
with connpool.item() as conn: with connpool.item() as conn:
try: try:
objects = [o['name'] for o in conn.get_container( objects = [o['name'] for o in conn.get_container(
@ -196,6 +197,11 @@ def object_dispersion_report(coropool, connpool, account, object_ring,
begun = time() begun = time()
next_report = [time() + 2] next_report = [time() + 2]
headers = None
if policy is not None:
headers = {}
headers['X-Backend-Storage-Policy-Index'] = int(policy)
def direct(obj, part, nodes): def direct(obj, part, nodes):
found_count = 0 found_count = 0
for node in nodes: for node in nodes:
@ -203,7 +209,8 @@ def object_dispersion_report(coropool, connpool, account, object_ring,
try: try:
attempts, _junk = direct_client.retry( attempts, _junk = direct_client.retry(
direct_client.direct_head_object, node, part, account, direct_client.direct_head_object, node, part, account,
container, obj, error_log=error_log, retries=retries) container, obj, error_log=error_log, retries=retries,
headers=headers)
retries_done[0] += attempts - 1 retries_done[0] += attempts - 1
found_count += 1 found_count += 1
except ClientException as err: except ClientException as err:
@ -290,9 +297,9 @@ def missing_string(partition_count, missing_copies, copy_count):
verb_string = 'were' verb_string = 'were'
partition_string = 'partitions' partition_string = 'partitions'
copy_string = 'copy'
if missing_copies > 1:
copy_string = 'copies' copy_string = 'copies'
if missing_copies == 1:
copy_string = 'copy'
return '%sThere %s %d %s missing %s %s.' % ( return '%sThere %s %d %s missing %s %s.' % (
exclamations, verb_string, partition_count, partition_string, exclamations, verb_string, partition_count, partition_string,
@ -323,6 +330,9 @@ Usage: %%prog [options] [conf_file]
parser.add_option('--insecure', action='store_true', default=False, parser.add_option('--insecure', action='store_true', default=False,
help='Allow accessing insecure keystone server. ' help='Allow accessing insecure keystone server. '
'The keystone\'s certificate will not be verified.') 'The keystone\'s certificate will not be verified.')
parser.add_option('-P', '--policy-name', dest='policy_name',
help="Specify storage policy name")
options, args = parser.parse_args() options, args = parser.parse_args()
if args: if args:
@ -332,6 +342,15 @@ Usage: %%prog [options] [conf_file]
if not c.read(conffile): if not c.read(conffile):
exit('Unable to read config file: %s' % conffile) exit('Unable to read config file: %s' % conffile)
conf = dict(c.items('dispersion')) conf = dict(c.items('dispersion'))
if options.policy_name is None:
policy = POLICIES.default
else:
policy = POLICIES.get_by_name(options.policy_name)
if policy is None:
exit('Unable to find policy: %s' % options.policy_name)
print 'Using storage policy: %s ' % policy.name
swift_dir = conf.get('swift_dir', '/etc/swift') swift_dir = conf.get('swift_dir', '/etc/swift')
retries = int(conf.get('retries', 5)) retries = int(conf.get('retries', 5))
concurrency = int(conf.get('concurrency', 25)) concurrency = int(conf.get('concurrency', 25))
@ -364,16 +383,16 @@ Usage: %%prog [options] [conf_file]
url=url, token=token, retries=retries) url=url, token=token, retries=retries)
container_ring = Ring(swift_dir, ring_name='container') container_ring = Ring(swift_dir, ring_name='container')
object_ring = Ring(swift_dir, ring_name='object') object_ring = Ring(swift_dir, ring_name=policy.ring_name)
output = {} output = {}
if container_report: if container_report:
output['container'] = container_dispersion_report( output['container'] = container_dispersion_report(
coropool, connpool, account, container_ring, retries, coropool, connpool, account, container_ring, retries,
options.partitions) options.partitions, policy)
if object_report: if object_report:
output['object'] = object_dispersion_report( output['object'] = object_dispersion_report(
coropool, connpool, account, object_ring, retries, coropool, connpool, account, object_ring, retries,
options.partitions) options.partitions, policy)
if json_output: if json_output:
print json.dumps(output) print json.dumps(output)

View File

@ -339,6 +339,12 @@ allows it to be more easily consumed by third party utilities::
$ swift-dispersion-report -j $ swift-dispersion-report -j
{"object": {"retries:": 0, "missing_two": 0, "copies_found": 7863, "missing_one": 0, "copies_expected": 7863, "pct_found": 100.0, "overlapping": 0, "missing_all": 0}, "container": {"retries:": 0, "missing_two": 0, "copies_found": 12534, "missing_one": 0, "copies_expected": 12534, "pct_found": 100.0, "overlapping": 15, "missing_all": 0}} {"object": {"retries:": 0, "missing_two": 0, "copies_found": 7863, "missing_one": 0, "copies_expected": 7863, "pct_found": 100.0, "overlapping": 0, "missing_all": 0}, "container": {"retries:": 0, "missing_two": 0, "copies_found": 12534, "missing_one": 0, "copies_expected": 12534, "pct_found": 100.0, "overlapping": 15, "missing_all": 0}}
Note that you may select which storage policy to use by setting the option
'--policy-name silver' or '-P silver' (silver is the example policy name here).
If no policy is specified, the default will be used per the swift.conf file.
When you specify a policy the containers created also include the policy index,
thus even when running a container_only report, you will need to specify the
policy not using the default.
----------------------------------- -----------------------------------
Geographically Distributed Clusters Geographically Distributed Clusters