Skip to content
This repository has been archived by the owner on Mar 22, 2018. It is now read-only.

CloudBlockBlob.StartCopyAsync fails with NotFound #157

Closed
thisisthekap opened this issue Feb 16, 2018 · 19 comments
Closed

CloudBlockBlob.StartCopyAsync fails with NotFound #157

thisisthekap opened this issue Feb 16, 2018 · 19 comments
Assignees
Labels

Comments

@thisisthekap
Copy link
Contributor

CloudBlockBlob.StartCopyAsync fails with NotFound when using azurite, works properly using azure storage account.

CloudBlobContainer targetContainer = blobClient.GetContainerReference("target-container");
await targetContainer.CreateIfNotExistsAsync();

CloudBlobContainer sourceContainer = blobClient.GetContainerReference("source-container");
var sourceBlobs = await sourceContainer.ListBlobsAsync();

foreach (var sourceBlob in sourceBlobs)
{
    var targetBlob = targetContainer.GetBlockBlobReference(blob.Name);

    // fails with "NotFound" when using azurite, works properly with azure blob storage
    await targetBlob.StartCopyAsync(blob);
}
@thisisthekap
Copy link
Contributor Author

I was able to reproduce the issue using with WindowsAzure.Storage version 9.0.0 with NETStandard.Library version 2.0.1.

@thisisthekap
Copy link
Contributor Author

Small .NET Core project to reproduce the issue: https://github.com/thisisthekap/Azurite157Repro

@arafato arafato self-assigned this Feb 20, 2018
@arafato arafato added the bug label Feb 20, 2018
@arafato
Copy link
Owner

arafato commented Feb 20, 2018

Thanks for reporting this @thisisthekap ! I will look into this within the next few days and try to release a fix asap.

@arafato
Copy link
Owner

arafato commented Feb 21, 2018

@thisisthekap : fix is released as part of v1.9.3. Please reopen in case it does not work for you. Thanks!

@thisisthekap
Copy link
Contributor Author

thisisthekap commented Feb 21, 2018

@arafato Thank you for your effort, I just tried your fix. Even tough StartCopyAsync proceeds without error, an DownloadTextAsync call made right afterwards blocks forever. Also, it seems that the blob storage gets entirely unusable after calling StartCopyAsync (until restart). I updated the test project hosted at https://github.com/thisisthekap/Azurite157Repro to reproduce the new issue.

// proceeds without error now
await targetBlob.StartCopyAsync(sourceBlob);

// This call blocks for azurite, the blob storage seems to get entirely unusable after using StartCopyAsync.
var str = await targetBlob.DownloadTextAsync();
Console.WriteLine("Copied: " + str);

Edit: It seems that I am unable to reopen the issue. Could you please grant me the appropriate permission, or reopen the issue yourself?

@arafato arafato reopened this Feb 21, 2018
@arafato
Copy link
Owner

arafato commented Feb 21, 2018

@thisisthekap : this is strange, I cannot repro with your code. Code finishes (and outputs) as expected. Can you paste in the log output of Azurite? Also, what happens if you do a simple
$ curl localhost:10000/devstoreaccount1/target-container/the-blob ?

@thisisthekap
Copy link
Contributor Author

@arafato I have got no clue why, but now the issue is gone (the only thing which I have done in the meantime was to upgrade node, but I do not know the version it was before).

@thisisthekap
Copy link
Contributor Author

thisisthekap commented Feb 21, 2018

@arafato When using the docker container version 1.9.3, the NotFound issues arises again.
Here the logs of the docker container:

PUT /devstoreaccount1/source-container?restype=container 409 2.053 ms - 146
PUT /devstoreaccount1/source-container/the-blob 201 26.445 ms - 0
PUT /devstoreaccount1/target-container?restype=container 409 0.849 ms - 146
PUT /devstoreaccount1/target-container/the-blob 404 1.165 ms - 131

@arafato
Copy link
Owner

arafato commented Feb 21, 2018

@thisisthekap strange again, I cannot repro. Running the code against arafato/azurite:1.9.3 works fine on my side. Are you sure that you are using v1.9.3?
Did you start the container with
$ docker run -d -t -p 10000:10000 -p 10001:10001 -v azurite-testdrive:/opt/azurite/folder arafato/azurite:1.9.3 ?

@thisisthekap
Copy link
Contributor Author

thisisthekap commented Feb 21, 2018

@arafato I am using it with docker compose. This is my compose file:

version: "2.1"

services:
    local-storage:
        image: arafato/azurite:1.9.3
        ports:
            - 10010:10000
        volumes:
            - ./Data/:/opt/azurite/folder
        environment:
            - executable=blob

Edit: The container that is running during the test is definitely using 1.9.3 (just double-checked).

@arafato
Copy link
Owner

arafato commented Feb 21, 2018

Ok, just to make sure: can you repro the bug when you start Azurite like so
$ docker run -d -t -p 10000:10000 -p 10001:10001 -v azurite-testdrive:/opt/azurite/folder arafato/azurite:1.9.3 and run your program against it?

@thisisthekap
Copy link
Contributor Author

When using docker directly, everything works fine. When using docker-compose, I experience the issue described above. My suggestion: docker-compose creates a software defined network (SDN) by default. So I think that the address given to your validation logic is neither 127.0.0.1 nor localhost.

@arafato
Copy link
Owner

arafato commented Feb 21, 2018

@thisisthekap ahhh, good point! In this case I will need to soften the validation rule to allow arbitrary prefixes before devstoreaccount1... what do you think?

@thisisthekap
Copy link
Contributor Author

@arafato Yeah, so either you have to support all possible names of the host, or ignore the hostname entirely (which also would be not that good).

@thisisthekap
Copy link
Contributor Author

Maybe we could solve it by using an environment variable to specify the whitelisted hostnames. The appropriate environment variables could then be specified in the docker-compose yaml file.

@arafato
Copy link
Owner

arafato commented Feb 22, 2018

@thisisthekap I think this might also be related to the port that is being exposed. You are exposing Azurite at 10010. The regex I'm using, however, checks for the port number 10000. At the end it depends how the SDK populates the x-ms-copy-source header... in case of the .NET SDK it takes whatever you are giving to CloudStorageAccount.Parse

I assume your code looks like the following (note the port) :
var account = CloudStorageAccount.Parse("BlobEndpoint=http://127.0.0.1:10010/devstoreaccount1;

Can you confirm? In this case there is no way to know what hostname or IP address, and port was given to this method (and hence check for in a regex / validation).

So either the validation ignores the hostname and port, or (as you suggested) takes into account some environment variables. In order to keep it simple I would just ignore the hostname and port. At the end all I care is to get the right blobname after .../devstoreaccount1/... it was never meant as a validation (and shouldn't be). What do you think?

@thisisthekap
Copy link
Contributor Author

@arafato As azurite is not a production system and therefore security is not that big issue, I am fine with just ignoring host and port.

arafato added a commit that referenced this issue Feb 22, 2018
@arafato
Copy link
Owner

arafato commented Feb 22, 2018

@thisisthekap just released fix as part of v2.0.0 (initial table storage support). Let me know if it works for you!

@thisisthekap
Copy link
Contributor Author

@arafato Everything is working just fine now. Thank you once again for your effort!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants