首页 文章

使用Azure Storage SDK for Java将VM页面blob从一个Azure订阅复制到另一个Azure订阅

提问于
浏览
1

我正在尝试使用Azure Storage SDK for Java将Azure VM的页面blob(已停止和取消分配)从一个Azure订阅复制到另一个Azure订阅 .

这是我正在使用的代码:

public class BlobCopyExampleClean {

    public static final String sourceStorageConnectionString =
            "DefaultEndpointsProtocol=https;"
            + "AccountName=sourceStorageAccount;"
            + "AccountKey=key123";

    public static final String destinationStorageConnectionString =
            "DefaultEndpointsProtocol=https;"
            + "AccountName=destinationStorageAccount;"
            + "AccountKey=key321";

    public static void main(String[] args) {

        try {
            CloudStorageAccount srcAccount = CloudStorageAccount.parse(sourceStorageConnectionString);
            CloudBlobClient srcSrvClient = srcAccount.createCloudBlobClient();
            CloudBlobContainer srcContainer = srcSrvClient.getContainerReference("vhds");

            CloudStorageAccount destAccount = CloudStorageAccount.parse(destinationStorageConnectionString);
            CloudBlobClient destSrvClient = destAccount.createCloudBlobClient();
            CloudBlobContainer destContainer = destSrvClient.getContainerReference("vhds");

            boolean result = destContainer.createIfNotExists();

            CloudBlob srcBlob = srcContainer.getPageBlobReference("testvm-2015-11-06.vhd");
            if (srcBlob.exists()) {
                CloudBlob destBlob = destContainer.getPageBlobReference("testvm-2015-11-06-copied.vhd");
                System.out.println("Starting blob copy...");
                String copyJobId = destBlob.startCopyFromBlob(srcBlob);

                CopyState copyState = destBlob.getCopyState();

                while (copyState.getStatus().equals(CopyStatus.PENDING)) {
                    System.out.println("... copying ...");
                    Thread.sleep(30000);
            }

                System.out.println("Copy complete, status was: " + copyState.getStatus() + "!");
            } else {
                System.out.println("Source blob does not exist!");
            }
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        } catch (StorageException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

无论我尝试什么,我总是得到以下错误返回给我:

Starting blob copy...
com.microsoft.azure.storage.StorageException: The specified resource does not exist.
    at com.microsoft.azure.storage.StorageException.translateException(StorageException.java:89)
    at com.microsoft.azure.storage.core.StorageRequest.materializeException(StorageRequest.java:305)
    at com.microsoft.azure.storage.core.ExecutionEngine.executeWithRetry(ExecutionEngine.java:175)
    at com.microsoft.azure.storage.blob.CloudBlob.startCopy(CloudBlob.java:883)
    at com.microsoft.azure.storage.blob.CloudBlob.startCopyFromBlob(CloudBlob.java:788)
    at com.company.azure.storage.BlobCopyExampleClean.main(BlobCopyExampleClean.java:44)

我尝试使用SDK库的v1.3.1,v3.1.0和v4.0.0,并使用blob.startCopyFromBlob()(v1.3.1和v3.1.0)和blob.startCopy()(v4)获得相同的错误 . 0.0) .

有问题的页面blob没有租约,因为Azure管理门户说租约状态是“Unlocked”并且它确实存在,即使Azure API通过在第42行输入代码块来确认这一点 .

我已经尝试将blob复制到同一订阅中的另一个存储帐户,并且也会产生相同的错误 .

更详细地查看异常,错误代码是“CannotVerifyCopySource” .

1 回答

  • 3

    重复发布在azure-storage-java库issue 59中 . 从那里复制我和mirobers答案:

    要跨帐户复制blob,您需要为源使用SAS令牌或将源容器标记为公共访问 . 请参阅以下页面的"Authorization"部分:https://msdn.microsoft.com/en-us/library/azure/dd894037.aspx

    因此,例如,您的代码可以生成SAS令牌,授予对源blob的读访问权限,将其附加到源blob URL的查询字符串,然后从URL启动副本 . 如果您正在寻找特定的API,请查看blob对象上的generateSharedAccessSignature . 您可以使用此返回的标记创建新的CloudStorageAccount,并按照上面的代码流从中获取blob引用,或将其附加到blob URL并使用CloudBlockBlob(URL)构造函数直接获取blob引用 .

    您的代码还有一个问题,即getCopyState不进行服务调用 . 这只是获取之前由startCopy设置的blob复制状态 . 在while循环中,您应该尝试使用downloadAttributes,它实际上会进行服务调用以从blob获取更新的复制信息 .

相关问题