Example #1
0
def delete(avatar, fullpath, on_behalf=None):
    """ Delete a blob. """
    log.msg("Deleting %s" % fullpath)
    uid, vals = vcdm.env['ds'].find_by_path(fullpath, object_type='blob',
                                            fields=['parent_container',
                                                    'metadata','backend_name'])
    if uid is None:
        return NOT_FOUND
    else:
        try:
            # authorize call
            acls = vals['metadata'].get('cdmi_acl', None)
            if not authorize(avatar, fullpath, "delete_blob", acls):
                return UNAUTHORIZED
            vcdm.env['blobs'][vals['backend_name']].delete(uid)
            vcdm.env['ds'].delete(uid)
            # find parent container and update its children range
            from vcdm.container import _remove_child
            _remove_child(vals['parent_container'], uid)
            log.msg(type='accounting', avatar=avatar if not on_behalf else on_behalf,
                    amount=1, acc_type='blob_delete')
            return NO_CONTENT
        except:
            #TODO: - how do we handle failed delete?
            return CONFLICT
Example #2
0
def delete(avatar, fullpath, on_behalf=None):
    """ Delete a blob. """
    log.msg("Deleting %s" % fullpath)
    uid, vals = vcdm.env['ds'].find_by_path(
        fullpath,
        object_type='blob',
        fields=['parent_container', 'metadata', 'backend_name'])
    if uid is None:
        return NOT_FOUND
    else:
        try:
            # authorize call
            acls = vals['metadata'].get('cdmi_acl', None)
            if not authorize(avatar, fullpath, "delete_blob", acls):
                return UNAUTHORIZED
            vcdm.env['blobs'][vals['backend_name']].delete(uid)
            vcdm.env['ds'].delete(uid)
            # find parent container and update its children range
            from vcdm.container import _remove_child
            _remove_child(vals['parent_container'], uid)
            log.msg(type='accounting',
                    avatar=avatar if not on_behalf else on_behalf,
                    amount=1,
                    acc_type='blob_delete')
            return NO_CONTENT
        except:
            #TODO: - how do we handle failed delete?
            return CONFLICT
Example #3
0
def delete(avatar, fullpath, on_behalf=None):
    """ Delete a container."""
    log.msg("Deleting a container %s" % fullpath)
    uid, vals = vcdm.env["ds"].find_by_path(
        fullpath, object_type="container", fields=["children", "parent_container", "metadata"]
    )
    if uid is None:
        return NOT_FOUND
    else:
        # authorize call
        acls = vals["metadata"].get("cdmi_acl", None)
        if not authorize(avatar, fullpath, "delete_container", acls):
            log.err("Authorization failed.")
            return UNAUTHORIZED
        # fail if we are deleting a non-empty container
        if len(vals["children"]) != 0:
            log.err("Cannot delete non-empty container %s. Existing children: %s." % (fullpath, vals["children"]))
            # we do not allow deleting non-empty containers
            return CONFLICT
        vcdm.env["ds"].delete(uid)
        if fullpath != "/":
            _remove_child(vals["parent_container"], uid)
        ## XXX: delete all children?
        log.msg(type="accounting", avatar=avatar if not on_behalf else on_behalf, amount=1, acc_type="container_delete")
        return NO_CONTENT
Example #4
0
def read(avatar, requested_path, on_behalf=None):
    """ Read a specified container."""
    expected_fields = ['children', 'metadata', 'mtime']
    unique_request = re.match('/cdmi_objectid/\w+$', requested_path)
    if unique_request is not None:
        requested_uid = unique_request.group(0).split('/')[2]
        uid, vals = vcdm.env['ds'].find_by_uid(requested_uid,
                                               object_type='container',
                                               fields=expected_fields +
                                               ['fullpath'])
        fullpath = vals['fullpath']
    else:
        fullpath = requested_path
        uid, vals = vcdm.env['ds'].find_by_path(fullpath,
                                                object_type='container',
                                                fields=expected_fields)
    if uid is None:
        return (NOT_FOUND, None)
    else:
        # authorize call
        acls = vals['metadata'].get('cdmi_acl')
        if not authorize(avatar, fullpath, 'read_container', acls):
            return (UNAUTHORIZED, None)
        vals['uid'] = uid
        log.msg(type='accounting',
                avatar=avatar if not on_behalf else on_behalf,
                amount=1,
                acc_type='container_read')
        return (OK, vals)
Example #5
0
def delete(avatar, fullpath, on_behalf=None):
    """ Delete a container."""
    log.msg("Deleting a container %s" % fullpath)
    uid, vals = vcdm.env['ds'].find_by_path(
        fullpath,
        object_type='container',
        fields=['children', 'parent_container', 'metadata'])
    if uid is None:
        return NOT_FOUND
    else:
        # authorize call
        acls = vals['metadata'].get('cdmi_acl', None)
        if not authorize(avatar, fullpath, "delete_container", acls):
            log.err("Authorization failed.")
            return UNAUTHORIZED
        # fail if we are deleting a non-empty container
        if len(vals['children']) != 0:
            log.err(
                "Cannot delete non-empty container %s. Existing children: %s."
                % (fullpath, vals['children']))
            # we do not allow deleting non-empty containers
            return CONFLICT
        vcdm.env['ds'].delete(uid)
        if fullpath != '/':
            _remove_child(vals['parent_container'], uid)
        ## XXX: delete all children?
        log.msg(type='accounting',
                avatar=avatar if not on_behalf else on_behalf,
                amount=1,
                acc_type='container_delete')
        return NO_CONTENT
Example #6
0
def read(avatar, fullpath, tre_request=False, on_behalf=None):
    """ Return contents of a blob.
    Returns:
    (HTTP_STATUS_CODE, dictionary_of_metadata)
    """
    # if the object was requested with a 'cdmi_objectid/' prefix, we query for that
    expected_fields = [
        'metadata', 'mimetype', 'mtime', 'size', 'actual_uri',
        'valuetransferencoding', 'backend_name'
    ]
    unique_request = re.match('/cdmi_objectid/\w+$', fullpath)
    if unique_request is not None:
        log.msg('Looking up a blob  by a unique key.')
        requested_uid = unique_request.group(0).split('/')[2]
        uid, vals = vcdm.env['ds'].find_by_uid(requested_uid,
                                               object_type='blob',
                                               fields=expected_fields)
    else:
        uid, vals = vcdm.env['ds'].find_by_path(fullpath,
                                                object_type='blob',
                                                fields=expected_fields)

    log.msg("Reading path %s, uid: %s" % (fullpath, uid))
    if uid is None:
        return (NOT_FOUND, None)
    else:
        # authorize call
        acls = vals['metadata'].get('cdmi_acl')
        if not authorize(avatar, fullpath, "read_blob", acls):
            log.msg("Authorization failed for %s on %s (%s)" %
                    (avatar, fullpath, acls))
            return (UNAUTHORIZED, None)

        # read the content from the corresponding backend
        vals['content'] = vcdm.env['blobs'][vals['backend_name']].read(uid)

        # update access time
        vcdm.env['ds'].write({
            'atime': str(time.time()),
        }, uid)
        log.msg(type='accounting',
                avatar=avatar if not on_behalf else on_behalf,
                amount=vals['size'],
                acc_type='blob_read')
        vals['uid'] = uid
        # TRE-request?
        if tre_request:
            if not vcdm.env['tre_enabled']:
                return (NOT_IMPLEMENTED, None)
            # XXX only local blob backend supports that at the moment
            vcdm.env['blob'].move_to_tre_server(uid)
            return (FOUND, vals)
        return (OK, vals)
Example #7
0
def read(avatar, fullpath, tre_request=False, on_behalf=None):
    """ Return contents of a blob.
    Returns:
    (HTTP_STATUS_CODE, dictionary_of_metadata)
    """
    # if the object was requested with a 'cdmi_objectid/' prefix, we query for that
    expected_fields = ['metadata', 'mimetype',
                       'mtime', 'size', 'actual_uri',
                       'valuetransferencoding','backend_name']
    unique_request = re.match('/cdmi_objectid/\w+$', fullpath)
    if unique_request is not None:
        log.msg('Looking up a blob  by a unique key.')
        requested_uid = unique_request.group(0).split('/')[2]
        uid, vals = vcdm.env['ds'].find_by_uid(requested_uid, object_type='blob',
                                            fields=expected_fields)
    else:
        uid, vals = vcdm.env['ds'].find_by_path(fullpath, object_type='blob',
                                            fields=expected_fields)

    log.msg("Reading path %s, uid: %s" % (fullpath, uid))
    if uid is None:
        return (NOT_FOUND, None)
    else:
        # authorize call
        acls = vals['metadata'].get('cdmi_acl')
        if not authorize(avatar, fullpath, "read_blob", acls):
            log.msg("Authorization failed for %s on %s (%s)" % (avatar, fullpath, acls))
            return (UNAUTHORIZED, None)
        
        
        # read the content from the corresponding backend
        vals['content'] = vcdm.env['blobs'][vals['backend_name']].read(uid)
        
        # update access time
        vcdm.env['ds'].write({
                        'atime': str(time.time()),
                        },
                        uid)
        log.msg(type='accounting', avatar=avatar if not on_behalf else on_behalf,
                amount=vals['size'], acc_type='blob_read')
        vals['uid'] = uid
        # TRE-request?
        if tre_request:
            if not vcdm.env['tre_enabled']:
                return (NOT_IMPLEMENTED, None)
            # XXX only local blob backend supports that at the moment
            vcdm.env['blob'].move_to_tre_server(uid)
            return (FOUND, vals)
        return (OK, vals)
Example #8
0
File: blob.py Project: csleex/vcdm
def read(avatar, fullpath, tre_request=False, on_behalf=None):
    """ Return contents of a blob.
    Returns:
    (HTTP_STATUS_CODE, dictionary_of_metadata)
    """
    # if the object was requested with a 'cdmi_objectid/' prefix, we query for that
    expected_fields = ["metadata", "mimetype", "mtime", "size", "actual_uri", "valuetransferencoding"]
    unique_request = re.match("/cdmi_objectid/\w+$", fullpath)
    if unique_request is not None:
        log.msg("Looking up a blob  by a unique key.")
        requested_uid = unique_request.group(0).split("/")[2]
        uid, vals = vcdm.env["ds"].find_by_uid(requested_uid, object_type="blob", fields=expected_fields)
    else:
        uid, vals = vcdm.env["ds"].find_by_path(fullpath, object_type="blob", fields=expected_fields)

    log.msg("Reading path %s, uid: %s" % (fullpath, uid))
    if uid is None:
        return (NOT_FOUND, None)
    else:
        # authorize call
        acls = vals["metadata"].get("cdmi_acl")
        if not authorize(avatar, fullpath, "read_blob", acls):
            log.msg("Authorization failed for %s on %s (%s)" % (avatar, fullpath, acls))
            return (UNAUTHORIZED, None)
        vals["content"] = vcdm.env["blob"].read(uid)
        # update access time
        vcdm.env["ds"].write({"atime": str(time.time())}, uid)
        log.msg(
            type="accounting", avatar=avatar if not on_behalf else on_behalf, amount=vals["size"], acc_type="blob_read"
        )
        vals["uid"] = uid
        # TRE-request?
        if tre_request:
            if not vcdm.env["tre_enabled"]:
                return (NOT_IMPLEMENTED, None)
            # XXX only local blob backend supports that at the moment
            vcdm.env["blob"].move_to_tre_server(uid)
            return (FOUND, vals)
        return (OK, vals)
Example #9
0
File: blob.py Project: csleex/vcdm
def delete(avatar, fullpath, on_behalf=None):
    """ Delete a blob. """
    log.msg("Deleting %s" % fullpath)
    uid, vals = vcdm.env["ds"].find_by_path(fullpath, object_type="blob", fields=["parent_container", "metadata"])
    if uid is None:
        return NOT_FOUND
    else:
        try:
            # authorize call
            acls = vals["metadata"].get("cdmi_acl", None)
            if not authorize(avatar, fullpath, "delete_blob", acls):
                return UNAUTHORIZED
            vcdm.env["blob"].delete(uid)
            vcdm.env["ds"].delete(uid)
            # find parent container and update its children range
            from vcdm.container import _remove_child

            _remove_child(vals["parent_container"], uid)
            log.msg(type="accounting", avatar=avatar if not on_behalf else on_behalf, amount=1, acc_type="blob_delete")
            return NO_CONTENT
        except:
            # TODO: - how do we handle failed delete?
            return CONFLICT
Example #10
0
def read(avatar, requested_path, on_behalf=None):
    """ Read a specified container."""
    expected_fields = ["children", "metadata", "mtime"]
    unique_request = re.match("/cdmi_objectid/\w+$", requested_path)
    if unique_request is not None:
        requested_uid = unique_request.group(0).split("/")[2]
        uid, vals = vcdm.env["ds"].find_by_uid(
            requested_uid, object_type="container", fields=expected_fields + ["fullpath"]
        )
        fullpath = vals["fullpath"]
    else:
        fullpath = requested_path
        uid, vals = vcdm.env["ds"].find_by_path(fullpath, object_type="container", fields=expected_fields)
    if uid is None:
        return (NOT_FOUND, None)
    else:
        # authorize call
        acls = vals["metadata"].get("cdmi_acl")
        if not authorize(avatar, fullpath, "read_container", acls):
            return (UNAUTHORIZED, None)
        vals["uid"] = uid
        log.msg(type="accounting", avatar=avatar if not on_behalf else on_behalf, amount=1, acc_type="container_read")
        return (OK, vals)
Example #11
0
def write(avatar, name, container_path, fullpath, mimetype, metadata, content,
          valueencoding, on_behalf=None, desired_backend=None):
    """ Write or update content of a blob. """
    from vcdm.server.cdmi.generic import get_parent
    parent_container = get_parent(fullpath)

    uid, vals = vcdm.env['ds'].find_by_path(fullpath, object_type='blob',
                                            fields=['parent_container','backend_name'])
    # assert that we have a consistency in case of an existig blob
    if uid is not None and parent_container != vals['parent_container']:
        log.err("ERROR: Inconsistent information! path: %s, parent_container in db: %s" %
                                                    (fullpath,
                                                     vals['parent_container']))
        return (INTERNAL_SERVER_ERROR, uid)

    # assert we can write to the defined path
    # TODO: expensive check for consistency, make optional
    if config.getboolean('general', 'check_for_existing_parents'):
        if not check_path(container_path):
            log.err("Writing to a container is not allowed. Container path: %s" %
                    '/'.join(container_path))
            return (FORBIDDEN, uid)

    # authorize call
    if uid is None:
        # the new file
        # take parent permissions
        _, cvals = vcdm.env['ds'].find_by_path(parent_container,
                                           object_type='container',
                                           fields=['metadata'])
    else:
        # updating the file
        # take file permissions
        _, cvals = vcdm.env['ds'].find_by_path(fullpath,
                                           object_type='blob',
                                           fields=['metadata'])
    
    acl = cvals['metadata'].get('cdmi_acl', {})
    
    if not authorize(avatar, parent_container, "write_blob", acl):
        return (UNAUTHORIZED, uid)

    # ok, time for action
    # pick a blob back-end
    # if file going to be updated take backend_name from metadata 
    # otherwise use backend is specified in the request 
    # if it is not available in the system - resolve to default one.
    if uid is not None:
        desired_backend=vals['backend_name']
    blob_backend = vcdm.env['blobs'].get(desired_backend, vcdm.env['blob'])

    # add default acls
    if avatar is None:
        avatar = 'Anonymous'
    blob_acl = metadata.get('cdmi_acl')
    if blob_acl is None:
        metadata['cdmi_acl'] = acl  # append parent ACLs for a new folder
    metadata['cdmi_acl'].update({avatar: 'rwd'})  # and creator's ACLs just in case

    # if uid is None, create a new entry, update otherwise
    if uid is None:
        uid = uuid4().hex
        actual_uri = blob_backend.create(uid, content)
        vcdm.env['ds'].write({
                        'object': 'blob',
                        'owner': avatar,
                        'fullpath': fullpath,
                        'mimetype': mimetype,
                        'metadata': metadata,
                        'valuetransferencoding': valueencoding,
                        'filename': name,
                        'actual_uri': actual_uri,
                        'parent_container': parent_container,
                        'ctime': str(time.time()),
                        'mtime': str(time.time()),
                        'atime': str(time.time()),
                        'size': int(content[1]),  # length
                        'backend_type': blob_backend.backend_type,
                        'backend_name': blob_backend.backend_name},
                        uid)
        # update the parent container as well
        from vcdm.container import _append_child
        _append_child(parent_container, uid, name)
        log.msg(type='accounting', avatar=avatar if not on_behalf else on_behalf,
                    amount=int(content[1]), acc_type='blob_creation')
        return (CREATED, uid)
    else:
        actual_uri = blob_backend.update(uid, content)
        uid = vcdm.env['ds'].write({
                        'metadata': metadata,
                        'mimetype': mimetype,
                        'mtime': str(time.time()),
                        'actual_uri': actual_uri,
                        'atime': str(time.time()),
                        'size': int(content[1]),  # length
                        'backend_type': blob_backend.backend_type,
                        'backend_name': blob_backend.backend_name},
                        uid)
        log.msg(type='accounting', avatar=avatar if not on_behalf else on_behalf,
                amount=int(content[1]), acc_type='blob_update')

        return (NO_CONTENT, uid)
Example #12
0
File: blob.py Project: csleex/vcdm
def write(
    avatar,
    name,
    container_path,
    fullpath,
    mimetype,
    metadata,
    content,
    valueencoding,
    on_behalf=None,
    desired_backend=None,
):
    """ Write or update content of a blob. """
    from vcdm.server.cdmi.generic import get_parent

    parent_container = get_parent(fullpath)

    uid, vals = vcdm.env["ds"].find_by_path(fullpath, object_type="blob", fields=["parent_container"])
    # assert that we have a consistency in case of an existig blob
    if uid is not None and parent_container != vals["parent_container"]:
        log.err(
            "ERROR: Inconsistent information! path: %s, parent_container in db: %s"
            % (fullpath, vals["parent_container"])
        )
        return (INTERNAL_SERVER_ERROR, uid)

    # assert we can write to the defined path
    # TODO: expensive check for consistency, make optional
    if config.getboolean("general", "check_for_existing_parents"):
        if not check_path(container_path):
            log.err("Writing to a container is not allowed. Container path: %s" % "/".join(container_path))
            return (FORBIDDEN, uid)

    # authorize call, take parent permissions
    _, cvals = vcdm.env["ds"].find_by_path(parent_container, object_type="container", fields=["metadata"])
    acl = cvals["metadata"].get("cdmi_acl", {})
    if not authorize(avatar, parent_container, "write_blob", acl):
        return (UNAUTHORIZED, uid)

    # ok, time for action
    # pick a blob back-end - if request_backend is specified in the metadata and
    # available in the system - use it. Else - resolve to default one.
    blob_backend = vcdm.env["blobs"].get(desired_backend, vcdm.env["blob"])

    # add default acls
    if avatar is None:
        avatar = "Anonymous"
    blob_acl = metadata.get("cdmi_acl")
    if blob_acl is None:
        metadata["cdmi_acl"] = acl  # append parent ACLs for a new folder
    metadata["cdmi_acl"].update({avatar: "rwd"})  # and creator's ACLs just in case

    # if uid is None, create a new entry, update otherwise
    if uid is None:
        uid = uuid4().hex
        actual_uri = blob_backend.create(uid, content)
        vcdm.env["ds"].write(
            {
                "object": "blob",
                "owner": avatar,
                "fullpath": fullpath,
                "mimetype": mimetype,
                "metadata": metadata,
                "valuetransferencoding": valueencoding,
                "filename": name,
                "actual_uri": actual_uri,
                "parent_container": parent_container,
                "ctime": str(time.time()),
                "mtime": str(time.time()),
                "atime": str(time.time()),
                "size": int(content[1]),  # length
                "backend_type": blob_backend.backend_type,
                "backend_name": blob_backend.backend_name,
            },
            uid,
        )
        # update the parent container as well
        from vcdm.container import _append_child

        _append_child(parent_container, uid, name)
        log.msg(
            type="accounting",
            avatar=avatar if not on_behalf else on_behalf,
            amount=int(content[1]),
            acc_type="blob_creation",
        )
        return (CREATED, uid)
    else:
        actual_uri = blob_backend.update(uid, content)
        uid = vcdm.env["ds"].write(
            {
                "metadata": metadata,
                "mimetype": mimetype,
                "mtime": str(time.time()),
                "actual_uri": actual_uri,
                "atime": str(time.time()),
                "size": int(content[1]),  # length
                "backend_type": blob_backend.backend_type,
                "backend_name": blob_backend.backend_name,
            },
            uid,
        )
        log.msg(
            type="accounting",
            avatar=avatar if not on_behalf else on_behalf,
            amount=int(content[1]),
            acc_type="blob_update",
        )

        return (NO_CONTENT, uid)
Example #13
0
def create_or_update(avatar, name, container_path, fullpath, metadata=None, on_behalf=None):
    """Create or update a container."""
    log.msg("Container create/update: %s" % fullpath)

    parent_container = get_parent(fullpath)
    uid, vals = vcdm.env["ds"].find_by_path(
        fullpath, object_type="container", fields=["children", "parent_container", "owner"]
    )
    vals["uid"] = uid
    # XXX: duplication of checks with blob (vcdm). Refactor.
    if uid is not None and parent_container != vals["parent_container"]:
        log.err("Inconsistency! path: %s, parent_container in db: %s" % (fullpath, vals["parent_container"]))
        return (FORBIDDEN, vals)

    # assert we can write to the defined path
    if not check_path(container_path):
        log.err("Writing to a container is not allowed. Container path: %s" % "/".join(container_path))
        return (FORBIDDEN, vals)

    # authorize call, take parent permissions
    _, cvals = vcdm.env["ds"].find_by_path(parent_container, object_type="container", fields=["metadata"])
    acl = cvals["metadata"].get("cdmi_acl", {})
    if not authorize(avatar, parent_container, "write_container", acl):
        return (UNAUTHORIZED, vals)

    # add default acls
    if avatar is None:
        avatar = "Anonymous"
    container_acl = metadata.get("cdmi_acl")
    if container_acl is None:
        metadata["cdmi_acl"] = acl  # append parent ACLs for a new folder
    metadata["cdmi_acl"].update({avatar: "rwd"})  # and creator's ACLs

    # if uid is None, it shall create a new entry, update otherwise
    if uid is None:
        uid = vcdm.env["ds"].write(
            {
                "object": "container",
                "metadata": metadata,
                "owner": avatar,
                "fullpath": fullpath,
                "name": name,
                "parent_container": parent_container,
                "children": {},
                "ctime": str(time.time()),
                "mtime": str(time.time()),
            },
            uid,
        )
        vals["uid"] = uid
        # update the parent container as well, unless it's a top-level container
        if fullpath != "/":
            _append_child(parent_container, uid, name + "/")
        log.msg(type="accounting", avatar=avatar if not on_behalf else on_behalf, amount=1, acc_type="container_create")
        return (CREATED, vals)
    else:
        # update container
        # forbid rewrites of containers by other users
        if vals.get("owner") is not None and vals.get("owner") != avatar:
            return (UNAUTHORIZED, vals)
        uid = vcdm.env["ds"].write({"metadata": metadata, "mtime": str(time.time())}, uid)
        log.msg(type="accounting", avatar=avatar if not on_behalf else on_behalf, amount=1, acc_type="container_update")
        return (NO_CONTENT, vals)
Example #14
0
def write(avatar,
          name,
          container_path,
          fullpath,
          mimetype,
          metadata,
          content,
          valueencoding,
          on_behalf=None,
          desired_backend=None):
    """ Write or update content of a blob. """
    from vcdm.server.cdmi.generic import get_parent
    parent_container = get_parent(fullpath)

    uid, vals = vcdm.env['ds'].find_by_path(
        fullpath,
        object_type='blob',
        fields=['parent_container', 'backend_name'])
    # assert that we have a consistency in case of an existig blob
    if uid is not None and parent_container != vals['parent_container']:
        log.err(
            "ERROR: Inconsistent information! path: %s, parent_container in db: %s"
            % (fullpath, vals['parent_container']))
        return (INTERNAL_SERVER_ERROR, uid)

    # assert we can write to the defined path
    # TODO: expensive check for consistency, make optional
    if config.getboolean('general', 'check_for_existing_parents'):
        if not check_path(container_path):
            log.err(
                "Writing to a container is not allowed. Container path: %s" %
                '/'.join(container_path))
            return (FORBIDDEN, uid)

    # authorize call
    if uid is None:
        # the new file
        # take parent permissions
        _, cvals = vcdm.env['ds'].find_by_path(parent_container,
                                               object_type='container',
                                               fields=['metadata'])
    else:
        # updating the file
        # take file permissions
        _, cvals = vcdm.env['ds'].find_by_path(fullpath,
                                               object_type='blob',
                                               fields=['metadata'])

    acl = cvals['metadata'].get('cdmi_acl', {})

    if not authorize(avatar, parent_container, "write_blob", acl):
        return (UNAUTHORIZED, uid)

    # ok, time for action
    # pick a blob back-end
    # if file going to be updated take backend_name from metadata
    # otherwise use backend is specified in the request
    # if it is not available in the system - resolve to default one.
    if uid is not None:
        desired_backend = vals['backend_name']
    blob_backend = vcdm.env['blobs'].get(desired_backend, vcdm.env['blob'])

    # add default acls
    if avatar is None:
        avatar = 'Anonymous'
    blob_acl = metadata.get('cdmi_acl')
    if blob_acl is None:
        metadata['cdmi_acl'] = acl  # append parent ACLs for a new folder
    metadata['cdmi_acl'].update({avatar:
                                 'rwd'})  # and creator's ACLs just in case

    # if uid is None, create a new entry, update otherwise
    if uid is None:
        uid = uuid4().hex
        actual_uri = blob_backend.create(uid, content)
        vcdm.env['ds'].write(
            {
                'object': 'blob',
                'owner': avatar,
                'fullpath': fullpath,
                'mimetype': mimetype,
                'metadata': metadata,
                'valuetransferencoding': valueencoding,
                'filename': name,
                'actual_uri': actual_uri,
                'parent_container': parent_container,
                'ctime': str(time.time()),
                'mtime': str(time.time()),
                'atime': str(time.time()),
                'size': int(content[1]),  # length
                'backend_type': blob_backend.backend_type,
                'backend_name': blob_backend.backend_name
            },
            uid)
        # update the parent container as well
        from vcdm.container import _append_child
        _append_child(parent_container, uid, name)
        log.msg(type='accounting',
                avatar=avatar if not on_behalf else on_behalf,
                amount=int(content[1]),
                acc_type='blob_creation')
        return (CREATED, uid)
    else:
        actual_uri = blob_backend.update(uid, content)
        uid = vcdm.env['ds'].write(
            {
                'metadata': metadata,
                'mimetype': mimetype,
                'mtime': str(time.time()),
                'actual_uri': actual_uri,
                'atime': str(time.time()),
                'size': int(content[1]),  # length
                'backend_type': blob_backend.backend_type,
                'backend_name': blob_backend.backend_name
            },
            uid)
        log.msg(type='accounting',
                avatar=avatar if not on_behalf else on_behalf,
                amount=int(content[1]),
                acc_type='blob_update')

        return (NO_CONTENT, uid)
Example #15
0
def create_or_update(avatar,
                     name,
                     container_path,
                     fullpath,
                     metadata=None,
                     on_behalf=None):
    """Create or update a container."""
    log.msg("Container create/update: %s" % fullpath)

    parent_container = get_parent(fullpath)
    uid, vals = vcdm.env['ds'].find_by_path(
        fullpath,
        object_type='container',
        fields=['children', 'parent_container', 'owner'])
    vals['uid'] = uid
    # XXX: duplication of checks with blob (vcdm). Refactor.
    if uid is not None and parent_container != vals['parent_container']:
        log.err("Inconsistency! path: %s, parent_container in db: %s" %
                (fullpath, vals['parent_container']))
        return (FORBIDDEN, vals)

    # assert we can write to the defined path
    if not check_path(container_path):
        log.err("Writing to a container is not allowed. Container path: %s" %
                '/'.join(container_path))
        return (FORBIDDEN, vals)

    # authorize call, take parent permissions
    _, cvals = vcdm.env['ds'].find_by_path(parent_container,
                                           object_type='container',
                                           fields=['metadata'])
    acl = cvals['metadata'].get('cdmi_acl', {})
    if not authorize(avatar, parent_container, "write_container", acl):
        return (UNAUTHORIZED, vals)

    # add default acls
    if avatar is None:
        avatar = 'Anonymous'
    container_acl = metadata.get('cdmi_acl')
    if container_acl is None:
        metadata['cdmi_acl'] = acl  # append parent ACLs for a new folder
    metadata['cdmi_acl'].update({avatar: 'rwd'})  # and creator's ACLs

    # if uid is None, it shall create a new entry, update otherwise
    if uid is None:
        uid = vcdm.env['ds'].write(
            {
                'object': 'container',
                'metadata': metadata,
                'owner': avatar,
                'fullpath': fullpath,
                'name': name,
                'parent_container': parent_container,
                'children': {},
                'ctime': str(time.time()),
                'mtime': str(time.time())
            }, uid)
        vals['uid'] = uid
        # update the parent container as well, unless it's a top-level container
        if fullpath != '/':
            _append_child(parent_container, uid, name + "/")
        log.msg(type='accounting',
                avatar=avatar if not on_behalf else on_behalf,
                amount=1,
                acc_type='container_create')
        return (CREATED, vals)
    else:
        # update container
        # forbid rewrites of containers by other users
        if vals.get('owner') is not None and vals.get('owner') != avatar:
            return (UNAUTHORIZED, vals)
        uid = vcdm.env['ds'].write(
            {
                'metadata': metadata,
                'mtime': str(time.time())
            }, uid)
        log.msg(type='accounting',
                avatar=avatar if not on_behalf else on_behalf,
                amount=1,
                acc_type='container_update')
        return (NO_CONTENT, vals)