def non_leaf_coalesce(node, parent, uri, cb):
    node_vhd = node.vhd
    parent_vhd = parent.vhd

    log.debug("non_leaf_coalesce key={}, parent={}".format(node_vhd.id, parent_vhd.id))

    opq = cb.volumeStartOperations(uri, 'w')
    meta_path = cb.volumeMetadataGetPath(opq)

    node_path = cb.volumeGetPath(opq, str(node_vhd.id))
    log.debug("Running vhd-coalesce on {}".format(node_vhd.id))
    VHDUtil.coalesce(GC, node_path)

    db = VHDMetabase(meta_path)
    with Lock(opq, 'gl', cb):
        # reparent all of the children to this node's parent
        children = db.get_children(node_vhd.id)

        with db.write_context():
            journal_entries = db.add_journal_entries(node_vhd.id, parent_vhd.id, children)

        __reparent_children(opq, db, cb, journal_entries)

        # remove key
        log.debug("Destroy {}".format(node_vhd.id))
        cb.volumeDestroy(opq, str(node_vhd.id))
        with db.write_context():
            db.delete_vhd(node_vhd.id)

        cb.volumeUnlock(opq, node.lock)
        cb.volumeUnlock(opq, parent.lock)

    db.close()
    cb.volumeStopOperations(opq)
def __reparent_children(opq, db, cb, journal_entries):
    for child in journal_entries:
        child_path = cb.volumeGetPath(opq, str(child.id))

        # Find all leaves having child as an ancestor
        leaves = []
        find_leaves(db.get_vhd_by_id(child.id), db, leaves)

        # reparent child to grandparent
        log.debug("Reparenting {} to {}".format(child.id, child.new_parent_id))
        with db.write_context():
            db.update_vhd_parent(child.id, child.new_parent_id)
            new_parent_path = cb.volumeGetPath(opq, str(child.new_parent_id))
            VHDUtil.set_parent(GC, child_path, new_parent_path)
            db.remove_journal_entry(child.id)
            # Add leaves to database
            leaves_to_refresh = db.add_refresh_entries(child.id, leaves)

        # Refresh all leaves having child as an ancestor
        log.debug(
            ("Children {}: refreshing all "
             "leaves: {}").format(child.id, leaves_to_refresh))
        __refresh_leaf_vdis(opq, db, cb, leaves_to_refresh)