Esempio n. 1
0
def DELETE(request, api_library, app):
    """
    DELETE /file/:file_id

    Delete a file

    An application can delete a file by issuing an HTTP DELETE request to the URL of the file resource.
    It's a good idea to precede DELETE requests like this with a caution note in your application's user
    interface.
    """

    try:
        _, _, file_id = split_path(request.path, 3, 3, False)
    except:
        app.logger.error("StackSync API: file_resource DELETE: Wrong resource path: %s path_info: %s", str(400),
                         str(request.path_info))
        return create_error_response(400, "Wrong resource path. Expected /file/:file_id")

    app.logger.info('StackSync API: file_resource DELETE: path info: %s', request.path_info)
    user_id = request.environ["stacksync_user_id"]

    message = api_library.get_metadata(user_id, file_id, is_folder=False, include_chunks=True)

    response = create_response(message, status_code=200)
    if not is_valid_status(response.status_int):
        app.logger.error("StackSync API: data_resource DELETE: status code: %s. body: %s", str(response.status_int),
                         str(response.body))
        return response
    workspace_info = api_library.get_workspace_info(user_id, file_id)

    response = create_response(workspace_info, status_code=200)
    if not is_valid_status(response.status_int):
        app.logger.error("StackSync API: data_resource PUT: status code: %s. body: %s", str(response.status_int),
                             str(response.body))
        return response

    workspace_info = json.loads(workspace_info)
    data_handler = DataHandler(app)
    file_metadata = json.loads(message)
    container_name = workspace_info['swift_container']
    response = data_handler.remove_old_chunks(request.environ, file_metadata['chunks'], container_name)
    response = create_response(message, status_code=200)
    if not is_valid_status(response.status_int):
        app.logger.error("StackSync API: data_resource DELETE: status code: %s. body: %s", str(response.status_int),
                         str(response.body))
        return response

    message_delete = api_library.delete_item(user_id, file_id, is_folder=False)

    response = create_response(message_delete, status_code=200)
    if not is_valid_status(response.status_int):
        app.logger.error("StackSync API: file_resource DELETE: error deleting file in StackSync Server: %s.",
                         str(response.status_int))
    return response
Esempio n. 2
0
def PUT(request, api_library, app):
    """
    PUT /file/:file_id/data

    Upload file data

    An application can upload data to a file by issuing an HTTP PUT request to the file data resource
    that represents the data for the file. The file binary will be sent in the request body.
    Uploading data to a file creates a new file version in the StackSync datastore and associates the
    uploaded data with the newly created file version.
    """
    content = request.body
    try:
        _, _, file_id, _ = split_path(request.path, 4, 4, False)
    except:
        app.logger.error(
            "StackSync API: data_resource PUT: Wrong resource path: %s path_info: %s",
            str(400), str(request.path_info))
        return create_error_response(
            400, "Wrong resource path. Expected /file/:file_id/data")

    app.logger.info(
        'StackSync API: data_resource PUT: path info: %s content length: %i ',
        str(request.path_info), len(content))

    user_id = request.environ["stacksync_user_id"]

    # We look up the name of file, and full path, to update it.
    #TODO: addChunks true
    message = api_library.get_metadata(user_id,
                                       file_id,
                                       is_folder=False,
                                       include_chunks=True)

    response = create_response(message, status_code=200)
    if not is_valid_status(response.status_int):
        app.logger.error(
            "StackSync API: data_resource PUT: status code: %s. body: %s",
            str(response.status_int), str(response.body))
        return response

    if len(content) > 0:
        file_metadata = json.loads(message)
        # get the workspace info (includes the container) from the file_id
        workspace_info = api_library.get_workspace_info(user_id, file_id)

        response = create_response(workspace_info, status_code=200)
        if not is_valid_status(response.status_int):
            app.logger.error(
                "StackSync API: data_resource PUT: status code: %s. body: %s",
                str(response.status_int), str(response.body))
            return response

        workspace_info = json.loads(workspace_info)
        old_chunks = file_metadata['chunks']
        app.logger.info("StackSync API: old_chunks: %s", old_chunks)
        container_name = workspace_info['swift_container']

        #Get the quota information
        quota_limit = long(workspace_info['quota_limit'])
        quota_used = long(workspace_info['quota_used'])
        old_file_size = long(file_metadata['size'])

        #check if the new file exceed the quota limit
        quota_used = quota_used - old_file_size
        quota_used_after_put = quota_used + long(len(content))
        if (quota_used_after_put > quota_limit):
            return create_error_response(413, "Upload exceeds quota.")

        chunked_file = BuildFile(content, [])
        chunked_file.separate(file_id)
        chunks_to_remove = list(set(old_chunks) - set(chunked_file.name_list))
        data_handler = DataHandler(app)

        #upload new chunks
        chunks_to_upload = list(set(chunked_file.name_list) - set(old_chunks))
        chunks_already_uploaded = list(
            set(chunked_file.name_list) - set(chunks_to_upload))

        chunks = list(chunked_file.name_list)

        for chunk_name in chunks_already_uploaded:
            index = chunked_file.name_list.index(chunk_name)
            del chunked_file.name_list[index]
            del chunked_file.chunks[index]
        response = data_handler.upload_file_chunks(request.environ,
                                                   chunked_file,
                                                   container_name)

        if not is_valid_status(response.status_int):
            app.logger.error(
                "StackSync API: data_resource PUT: error uploading file chunks: %s path info: %s",
                str(response.status), str(request.path_info))
            return create_error_response(
                500, "Could not upload chunks to storage backend.")

        checksum = str((zlib.adler32(content) & 0xffffffff))
        file_size = str(len(content))
        mimetype = magic.from_buffer(content, mime=True)

    else:
        #Empty body
        chunks = []
        checksum = 0
        file_size = 0
        mimetype = 'inode/x-empty'

    new_version_response = api_library.update_data(user_id, file_id, checksum,
                                                   file_size, mimetype, chunks)

    response = create_response(new_version_response, status_code=201)
    if not is_valid_status(response.status_int):
        app.logger.error(
            "StackSync API: data_resource PUT: error updating data in StackSync Server: %s. body: %s",
            str(response.status_int), str(response.body))
    else:
        #delete old chunks
        response = data_handler.remove_old_chunks(request.environ,
                                                  chunks_to_remove,
                                                  container_name)
        if not is_valid_status(response.status_int):
            app.logger.error(
                "StackSync API: data_resource PUT: error uploading file chunks: %s path info: %s",
                str(response.status), str(request.path_info))
            return create_error_response(
                500, "Could not upload chunks to storage backend.")

    return response
Esempio n. 3
0
def PUT(request, api_library, app):
    """
    PUT /file/:file_id/data

    Upload file data

    An application can upload data to a file by issuing an HTTP PUT request to the file data resource
    that represents the data for the file. The file binary will be sent in the request body.
    Uploading data to a file creates a new file version in the StackSync datastore and associates the
    uploaded data with the newly created file version.
    """
    content = request.body
    try:
        _, _, file_id, _ = split_path(request.path, 4, 4, False)
    except:
        app.logger.error("StackSync API: data_resource PUT: Wrong resource path: %s path_info: %s", str(400),
                         str(request.path_info))
        return create_error_response(400, "Wrong resource path. Expected /file/:file_id/data")

    app.logger.info('StackSync API: data_resource PUT: path info: %s content length: %i ', str(request.path_info),
                    len(content))

    user_id = request.environ["stacksync_user_id"]

    # We look up the name of file, and full path, to update it.
    #TODO: addChunks true
    message = api_library.get_metadata(user_id, file_id, is_folder=False, include_chunks=True)

    response = create_response(message, status_code=200)
    if not is_valid_status(response.status_int):
        app.logger.error("StackSync API: data_resource PUT: status code: %s. body: %s", str(response.status_int),
                         str(response.body))
        return response

    if len(content) > 0:
        file_metadata = json.loads(message)
        # get the workspace info (includes the container) from the file_id
        workspace_info = api_library.get_workspace_info(user_id, file_id)

        response = create_response(workspace_info, status_code=200)
        if not is_valid_status(response.status_int):
            app.logger.error("StackSync API: data_resource PUT: status code: %s. body: %s", str(response.status_int),
                             str(response.body))
            return response

        workspace_info = json.loads(workspace_info)
        old_chunks = file_metadata['chunks']
        app.logger.info("StackSync API: old_chunks: %s", old_chunks)
        container_name = workspace_info['swift_container']

        #Get the quota information
        quota_limit = long(workspace_info['quota_limit'])
        quota_used = long(workspace_info['quota_used'])
        old_file_size = long(file_metadata['size'])

        #check if the new file exceed the quota limit
        quota_used = quota_used - old_file_size
        quota_used_after_put = quota_used + long(len(content))
        if (quota_used_after_put > quota_limit):
            return create_error_response(413, "Upload exceeds quota.")

        chunked_file = BuildFile(content, [])
        chunked_file.separate(file_id)
        chunks_to_remove = list(set(old_chunks) - set(chunked_file.name_list))
        data_handler = DataHandler(app)

        #upload new chunks
        chunks_to_upload = list(set(chunked_file.name_list)-set(old_chunks))
        chunks_already_uploaded =  list(set(chunked_file.name_list)-set(chunks_to_upload))

        chunks = list(chunked_file.name_list)

        for chunk_name in chunks_already_uploaded:
            index = chunked_file.name_list.index(chunk_name)
            del chunked_file.name_list[index]
            del chunked_file.chunks[index]
        response = data_handler.upload_file_chunks(request.environ, chunked_file, container_name)

        if not is_valid_status(response.status_int):
            app.logger.error("StackSync API: data_resource PUT: error uploading file chunks: %s path info: %s",
                             str(response.status),
                             str(request.path_info))
            return create_error_response(500, "Could not upload chunks to storage backend.")

        checksum = str((zlib.adler32(content) & 0xffffffff))
        file_size = str(len(content))
        mimetype = magic.from_buffer(content, mime=True)

    else:
        #Empty body
        chunks = []
        checksum = 0
        file_size = 0
        mimetype = 'inode/x-empty'

    new_version_response = api_library.update_data(user_id, file_id, checksum, file_size, mimetype, chunks)

    response = create_response(new_version_response, status_code=201)
    if not is_valid_status(response.status_int):
        app.logger.error("StackSync API: data_resource PUT: error updating data in StackSync Server: %s. body: %s",
                         str(response.status_int),
                         str(response.body))
    else:
        #delete old chunks
        response = data_handler.remove_old_chunks(request.environ, chunks_to_remove, container_name)
        if not is_valid_status(response.status_int):
            app.logger.error("StackSync API: data_resource PUT: error uploading file chunks: %s path info: %s",
                             str(response.status),
                             str(request.path_info))
            return create_error_response(500, "Could not upload chunks to storage backend.")

    return response