'Wait for a list of object ids to appear in the AWS API. Requires a
function that fetches the objects and also takes a filters kwarg. The
id_filter specifies the id filter to use for the objects and
obj_name describes the objects for log messages.'

def _wait_for_propagation(self, obj_ids, fetch_func, id_filter, obj_name, max_retries=60, interval=5):

    filters = {id_filter: obj_ids}
    num_objs = len(obj_ids)
    num_reqs = 0
    reqs_ids = []
    max_retries = max(1, max_retries)
    interval = max(1, interval)
    widgets = ['', progressbar.Fraction(), '    ', progressbar.Bar(marker=progressbar.RotatingMarker()), '    ', progressbar.Percentage(), '    ', '    ']
    log.info(('Waiting    for    %s    to    propagate...' % obj_name))
    pbar = progressbar.ProgressBar(widgets=widgets, maxval=num_objs).start()
    try:
        for i in range((max_retries + 1)):
            reqs = fetch_func(filters=filters)
            reqs_ids = [req.id for req in reqs]
            num_reqs = len(reqs)
            pbar.update(num_reqs)
            if (num_reqs != num_objs):
                log.debug(('%d:    only    %d/%d    %s    have    propagated    -    sleeping...' % (i, num_reqs, num_objs, obj_name)))
                if (i != max_retries):
                    time.sleep(interval)
            else:
                return
    finally:
        if (not pbar.finished):
            pbar.finish()
    missing = [oid for oid in obj_ids if (oid not in reqs_ids)]
    raise exception.PropagationException(('Failed    to    fetch    %d/%d    %s    after    %d    seconds:    %s' % (num_reqs, num_objs, obj_name, (max_retries * interval), ',    '.join(missing))))
