Exemplo n.º 1
0
def _update_host_attributes(afe, hostname, host_attrs):
    """Update the attributes for a given host.

    @param afe          AFE object for RPC calls.
    @param hostname     Host name of the DUT.
    @param host_attrs   Dictionary with attributes to be applied to the
                        host.
    """
    # Grab the servo hostname/port/serial from `host_attrs` if supplied.
    # For new servo V4 deployments, we require the user to supply the
    # attributes (because there are no appropriate defaults).  So, if
    # none are supplied, we assume it can't be V4, and apply the
    # defaults for servo V3.
    host_attr_servo_host = host_attrs.get(servo_host.SERVO_HOST_ATTR)
    host_attr_servo_port = host_attrs.get(servo_host.SERVO_PORT_ATTR)
    host_attr_servo_serial = host_attrs.get(servo_host.SERVO_SERIAL_ATTR)
    servo_hostname = (host_attr_servo_host
                      or servo_host.make_servo_hostname(hostname))
    servo_port = (host_attr_servo_port
                  or str(servo_host.ServoHost.DEFAULT_PORT))
    afe.set_host_attribute(servo_host.SERVO_HOST_ATTR,
                           servo_hostname,
                           hostname=hostname)
    afe.set_host_attribute(servo_host.SERVO_PORT_ATTR,
                           servo_port,
                           hostname=hostname)
    if host_attr_servo_serial:
        afe.set_host_attribute(servo_host.SERVO_SERIAL_ATTR,
                               host_attr_servo_serial,
                               hostname=hostname)
Exemplo n.º 2
0
def _update_host_attributes(afe, hostname, host_attr_dict):
    """Update the attributes for a given host.

    @param afe             AFE object for RPC calls.
    @param hostname        Name of the host to be updated.
    @param host_attr_dict  Dict of host attributes to store in the AFE.
    """
    # Let's grab the servo hostname/port/serial from host_attr_dict
    # if possible.
    host_attr_servo_host = None
    host_attr_servo_port = None
    host_attr_servo_serial = None
    if hostname in host_attr_dict:
        host_attr_servo_host = host_attr_dict[hostname].get(
                servo_host.SERVO_HOST_ATTR)
        host_attr_servo_port = host_attr_dict[hostname].get(
                servo_host.SERVO_PORT_ATTR)
        host_attr_servo_serial = host_attr_dict[hostname].get(
                servo_host.SERVO_SERIAL_ATTR)

    servo_hostname = (host_attr_servo_host or
                      servo_host.make_servo_hostname(hostname))
    servo_port = (host_attr_servo_port or
                  str(servo_host.ServoHost.DEFAULT_PORT))
    afe.set_host_attribute(servo_host.SERVO_HOST_ATTR,
                           servo_hostname,
                           hostname=hostname)
    afe.set_host_attribute(servo_host.SERVO_PORT_ATTR,
                           servo_port,
                           hostname=hostname)
    if host_attr_servo_serial:
        afe.set_host_attribute(servo_host.SERVO_SERIAL_ATTR,
                               host_attr_servo_serial,
                               hostname=hostname)
def _generate_repair_recommendation(inventory, num_recommend):
    """Return a summary of selected DUTs needing repair.

    Returns a message recommending a list of broken DUTs to be
    repaired.  The list of DUTs is selected based on these
    criteria:
      * No more than `num_recommend` DUTs will be listed.
      * All DUTs must be in the same lab.
      * DUTs should be selected for some degree of physical
        proximity.
      * DUTs for boards with a low spares buffer are more important
        than DUTs with larger buffers.

    The algorithm used will guarantee that at least one DUT from a
    board with the smallest spares buffer will be recommended.  If
    the worst spares buffer number is shared by more than one board,
    the algorithm will tend to prefer repair sets that include more
    of those boards over sets that cover fewer boards.

    @param inventory      Inventory for generating recommendations.
    @param num_recommend  Number of DUTs to recommend for repair.

    """
    logging.debug('Creating DUT repair recommendations')
    board_buffer_counts = {}
    broken_list = []
    for board in inventory.get_managed_boards():
        logging.debug('Listing failed DUTs for %s', board)
        counts = inventory[board]
        if counts.get_broken() != 0:
            board_buffer_counts[board] = counts.get_spares_buffer()
            broken_list.extend(counts.get_broken_list())
    # N.B. The logic inside this loop may seem complicated, but
    # simplification is hard:
    #   * Calculating an initial recommendation outside of
    #     the loop likely would make things more complicated,
    #     not less.
    #   * It's necessary to calculate an initial lab slice once per
    #     lab _before_ the while loop, in case the number of broken
    #     DUTs in a lab is less than `num_recommend`.
    recommendation = None
    best_score = None
    for lab_duts in _sort_by_location(broken_list):
        start = 0
        end = num_recommend
        lab_slice = lab_duts[start:end]
        lab_score = _score_repair_set(board_buffer_counts, lab_slice)
        while end < len(lab_duts):
            start += 1
            end += 1
            new_slice = lab_duts[start:end]
            new_score = _score_repair_set(board_buffer_counts, new_slice)
            if new_score > lab_score:
                lab_slice = new_slice
                lab_score = new_score
        if recommendation is None or lab_score > best_score:
            recommendation = lab_slice
            best_score = lab_score
    message = [
        'Repair recommendations:\n',
        '%-30s %-16s %s' % ('Hostname', 'Board', 'Servo instructions')
    ]
    for h in recommendation:
        servo_name = servo_host.make_servo_hostname(h.host.hostname)
        if utils.host_is_in_lab_zone(servo_name):
            servo_message = 'Repair servo first'
        else:
            servo_message = 'No servo present'
        line = '%-30s %-16s %s' % (h.host.hostname, h.host_board,
                                   servo_message)
        message.append(line)
    return '\n'.join(message)
Exemplo n.º 4
0
def _generate_repair_recommendation(inventory, num_recommend):
    """Return a summary of selected DUTs needing repair.

    Returns a message recommending a list of broken DUTs to be repaired.
    The list of DUTs is selected based on these criteria:
      * No more than `num_recommend` DUTs will be listed.
      * All DUTs must be in the same lab.
      * DUTs should be selected for some degree of physical proximity.
      * DUTs for models with a low spares buffer are more important than
        DUTs with larger buffers.

    The algorithm used will guarantee that at least one DUT from a model
    with the lowest spares buffer will be recommended.  If the worst
    spares buffer number is shared by more than one model, the algorithm
    will tend to prefer repair sets that include more of those models
    over sets that cover fewer models.

    @param inventory      `_LabInventory` object from which to generate
                          recommendations.
    @param num_recommend  Number of DUTs to recommend for repair.

    """
    logging.debug('Creating DUT repair recommendations')
    model_buffer_counts = {}
    broken_list = []
    for model, counts in inventory.reportable_items():
        logging.debug('Listing failed DUTs for %s', model)
        if counts.get_broken() != 0:
            model_buffer_counts[model] = counts.get_spares_buffer()
            broken_list.extend(counts.get_broken_list())
    # N.B. The logic inside this loop may seem complicated, but
    # simplification is hard:
    #   * Calculating an initial recommendation outside of
    #     the loop likely would make things more complicated,
    #     not less.
    #   * It's necessary to calculate an initial lab slice once per
    #     lab _before_ the while loop, in case the number of broken
    #     DUTs in a lab is less than `num_recommend`.
    recommendation = None
    best_score = None
    for lab_duts in _sort_by_location(broken_list):
        start = 0
        end = num_recommend
        lab_slice = lab_duts[start:end]
        lab_score = _score_repair_set(model_buffer_counts, lab_slice)
        while end < len(lab_duts):
            start += 1
            end += 1
            new_slice = lab_duts[start:end]
            new_score = _score_repair_set(model_buffer_counts, new_slice)
            if new_score > lab_score:
                lab_slice = new_slice
                lab_score = new_score
        if recommendation is None or lab_score > best_score:
            recommendation = lab_slice
            best_score = lab_score
    # N.B. The trailing space in `line_fmt` is manadatory:  Without it,
    # Gmail will parse the URL wrong.  Don't ask.  If you simply _must_
    # know more, go try it yourself...
    line_fmt = '%-30s %-16s %-6s\n    %s '
    message = [
        'Repair recommendations:\n',
        line_fmt % ('Hostname', 'Model', 'Servo?', 'Logs URL')
    ]
    for h in recommendation:
        servo_name = servo_host.make_servo_hostname(h.host.hostname)
        servo_present = utils.host_is_in_lab_zone(servo_name)
        _, event = h.last_diagnosis()
        line = line_fmt % (h.host.hostname, h.host_model,
                           'Yes' if servo_present else 'No', event.job_url)
        message.append(line)
    return '\n'.join(message)