Esempio n. 1
0
def __reparent_children(opq, callbacks, journal_entries):
    """
    Reparent the children of a node after it has been coalesced
    """
    for child in journal_entries:
        child_path = callbacks.volumeGetPath(opq, str(child.id))
        with callbacks.db_context(opq) as db:
            child_volume = db.get_volume_by_id(child.id)

            # Find all leaves having child as an ancestor
            leaves = []
            log.debug('Find active leaves of {}'.format(child.id))
            find_active_leaves(child_volume, db, leaves)

        image_utils = ImageFormat.get_format(
            child_volume.image_type).image_utils

        # reparent child to grandparent
        log.debug("Reparenting {} to {}".format(child.id, child.new_parent_id))
        with callbacks.db_context(opq) as db:
            db.update_volume_parent(child.id, child.new_parent_id)
            new_parent_path = callbacks.volumeGetPath(opq,
                                                      str(child.new_parent_id))
            image_utils.set_parent(GC, child_path, new_parent_path)
            db.remove_journal_entry(child.id)
            # Add leaves to database
            if leaves:
                # Refresh all leaves having child as an ancestor
                leaves_to_refresh = db.add_refresh_entries(
                    child.id, child.parent_id, child.new_parent_id, leaves)
                log.debug("Children {}: leaves: {} will be refreshed".format(
                    child.id, [str(x) for x in leaves_to_refresh]))
Esempio n. 2
0
def non_leaf_coalesce(node, parent, uri, callbacks):
    """
    Perform non-leaf (mid tree) volume coalesce
    """
    node_volume = node.volume
    parent_volume = parent.volume

    log.debug("non_leaf_coalesce key={}, parent={}".format(
        node_volume.id, parent_volume.id))

    with VolumeContext(callbacks, uri, 'w') as opq:
        node_path = callbacks.volumeGetPath(opq, str(node_volume.id))
        parent_path = callbacks.volumeGetPath(opq, str(parent_volume.id))
        log.debug("Running cow-coalesce on {}".format(node_volume.id))
        image_utils = ImageFormat.get_format(
            node_volume.image_type).image_utils
        image_utils.coalesce(GC, node_path, parent_path)

        with PollLock(opq, 'gl', callbacks, PRIO_GC):
            with callbacks.db_context(opq) as db:
                # reparent all of the children to this node's parent
                children = db.get_children(node_volume.id)
                journal_entries = db.add_journal_entries(
                    node_volume.id, parent_volume.id, children)

            __reparent_children(opq, callbacks, journal_entries)

            callbacks.volumeUnlock(opq, node.lock)
            callbacks.volumeUnlock(opq, parent.lock)
Esempio n. 3
0
def refresh_live_cow_chain(vdi, refresh, callbacks, opq):
    """
    Refresh the datapath for the vdi
    """
    assert vdi.active_on
    vdi_meta_path = callbacks.get_data_metadata_path(opq, vdi.uuid)
    image_utils = ImageFormat.get_format(vdi.image_type).image_utils
    image_utils.refresh_datapath_coalesce(
        GC, vdi_meta_path, callbacks.volumeGetPath(opq,
                                                   str(refresh.old_parent)),
        callbacks.volumeGetPath(opq, str(refresh.new_parent)))
Esempio n. 4
0
    def create(self, dbg, sr, name, description, size, sharable):
        devices = util.get_sr_metadata(dbg, 'file://' + sr)['devices']
        devices = map(lambda x: os.path.normpath(x), devices)

        with VolumeContext(self.callbacks, sr, 'w') as opq:
            image_type = ImageFormat.IMAGE_RAW
            image_format = ImageFormat.get_format(image_type)
            vdi_uuid = str(uuid.uuid4())

            with PollLock(opq, 'gl', self.callbacks, 0.5):
                with self.callbacks.db_context(opq) as db:
                    # List all used devices.
                    used_devices = map(
                        lambda x: os.path.realpath(
                            self.callbacks.volumeGetPath(opq, str(x.id))),
                        db.get_all_volumes())

                    # Find first free device with the best size.
                    free_device = None
                    psize = sys.maxint
                    for device in devices:
                        if os.path.realpath(device) not in used_devices:
                            device_size = util.get_physical_file_size(device)
                            if device_size >= size and device_size < psize:
                                free_device = device
                                psize = device_size

                    if not free_device:
                        # TODO: Maybe find a better exception.
                        raise ValueError('No free device found in config')

                    volume = db.insert_new_volume(psize, image_type)
                    db.insert_vdi(name, description, vdi_uuid, volume.id,
                                  sharable)
                    volume_path = self.callbacks.volumeGetPath(
                        opq, str(volume.id))
            os.symlink(free_device, volume_path)

            vdi_uri = self.callbacks.getVolumeUriPrefix(opq) + vdi_uuid

        return {
            'key': vdi_uuid,
            'uuid': vdi_uuid,
            'name': name,
            'description': description,
            'read_write': True,
            'virtual_size': psize,
            'physical_utilisation': psize,
            'uri': [image_format.uri_prefix + vdi_uri],
            'sharable': sharable,
            'keys': {}
        }
Esempio n. 5
0
def __leaf_coalesce(leaf, parent, opq, callbacks):
    """
    Perform leaf volume coalesce.

    Must be called from inside a global SR lock.
    """
    leaf_volume = leaf.volume
    parent_volume = parent.volume

    log.debug('leaf_coalesce key={}, parent={}'.format(leaf_volume.id,
                                                       parent_volume.id))

    leaf_path = callbacks.volumeGetPath(opq, str(leaf_volume.id))
    parent_path = callbacks.volumeGetPath(opq, str(parent_volume.id))
    leaf_psize = os.path.getsize(leaf_path)

    try:
        with callbacks.db_context(opq) as db:
            vdi = db.get_vdi_for_volume(leaf_volume.id)
        image_utils = ImageFormat.get_format(vdi.image_type).image_utils

        vdi_meta_path = callbacks.get_data_metadata_path(opq, vdi.uuid)

        if leaf_psize < _LEAF_COALESCE_MAX_SIZE:
            log.debug("Running leaf-coalesce on {}".format(leaf_volume.id))

            image_utils.coalesce(GC, leaf_path, parent_path)

            if vdi.active_on:
                image_utils.pause_datapath(GC, vdi_meta_path)

            with callbacks.db_context(opq) as db:
                db.update_vdi_volume_id(vdi.uuid, leaf_volume.parent_id)

            if vdi.active_on:
                image_utils.unpause_datapath(GC, vdi_meta_path, parent_path)

            with callbacks.db_context(opq) as db:
                db.delete_volume(leaf_volume.id)
                callbacks.volumeDestroy(opq, str(leaf_volume.id))
        else:
            # If the leaf is larger than the maximum size allowed for
            # a live leaf coalesce to happen, snapshot it and let
            # non_leaf_coalesce() take care of it.

            log.debug("Snapshot {} and let non-leaf-coalesce handle it".format(
                leaf_volume.id))

            with callbacks.db_context(opq) as db:
                new_leaf_volume = db.insert_child_volume(
                    leaf_volume.id, leaf_volume.vsize)

                new_leaf_path = callbacks.volumeCreate(opq,
                                                       str(new_leaf_volume.id),
                                                       leaf_volume.vsize)

                image_utils.online_snapshot(GC, new_leaf_path, leaf_path,
                                            False)

                db.update_vdi_volume_id(vdi.uuid, new_leaf_volume.id)

                if vdi.active_on:
                    image_utils.refresh_datapath_clone(GC, vdi_meta_path,
                                                       new_leaf_path)

    finally:
        callbacks.volumeUnlock(opq, leaf.lock)
        callbacks.volumeUnlock(opq, parent.lock)