# # Copyright 2008 Google Inc. All Rights Reserved. """ The shard module contains the objects and methods used to manage shards in Autotest. The valid actions are: create: creates shard remove: deletes shard(s) list: lists shards with label See topic_common.py for a High Level Design and Algorithm. """ import sys from autotest_lib.cli import topic_common, action_common class shard(topic_common.atest): """shard class atest shard [create|delete|list] <options>""" usage_action = '[create|delete|list]' topic = msg_topic = 'shard' msg_items = '<shards>' def __init__(self): """Add to the parser the options common to all the shard actions""" super(shard, self).__init__() self.topic_parse_info = topic_common.item_parse_info( attribute_name='shards', use_leftover=True) def get_items(self): return self.shards class shard_help(shard): """Just here to get the atest logic working. Usage is set by its parent""" pass class shard_list(action_common.atest_list, shard): """Class for running atest shard list""" def execute(self): filters = {} if self.shards: filters['hostname__in'] = self.shards return super(shard_list, self).execute(op='get_shards', filters=filters) def warn_if_label_assigned_to_multiple_shards(self, results): """Prints a warning if one label is assigned to multiple shards. This should never happen, but if it does, better be safe. @param results: Results as passed to output(). """ assigned_labels = set() for line in results: for label in line['labels']: if label in assigned_labels: sys.stderr.write('WARNING: label %s is assigned to ' 'multiple shards.\n' 'This will lead to unpredictable behavor ' 'in which hosts and jobs will be assigned ' 'to which shard.\n') assigned_labels.add(label) def output(self, results): self.warn_if_label_assigned_to_multiple_shards(results) super(shard_list, self).output(results, ['hostname', 'labels']) class shard_create(action_common.atest_create, shard): """Class for running atest shard create -l <label> <shard>""" def __init__(self): super(shard_create, self).__init__() self.parser.add_option('-l', '--labels', help=('Assign LABELs to the SHARD. All jobs that ' 'require one of the labels will be run on ' 'the shard. List multiple labels separated ' 'by a comma.'), type='string', metavar='LABELS') def parse(self): (options, leftover) = super(shard_create, self).parse( req_items='shards') if not options.labels: print ('Must provide one or more labels separated by a comma ' 'with -l <labels>') self.parser.print_help() sys.exit(1) self.data_item_key = 'hostname' self.data['labels'] = options.labels return (options, leftover) class shard_delete(action_common.atest_delete, shard): """Class for running atest shard delete <shards>""" def parse(self): (options, leftover) = super(shard_delete, self).parse() self.data_item_key = 'hostname' return (options, leftover) def execute(self, *args, **kwargs): print 'Please ensure the shard host is powered off.' print ('Otherwise DUTs might be used by multiple shards at the same ' 'time, which will lead to serious correctness problems.') return super(shard_delete, self).execute(*args, **kwargs)