【问题标题】:From the AWS Java API, how can I tell when my EBS Snapshot has been created?从 AWS Java API 中,我如何知道我的 EBS 快照何时创建?
【发布时间】:2012-08-17 09:36:49
【问题描述】:

我有多个 EBS 支持的 EC2 实例正在运行,我希望能够拍摄其中一个 EBS 卷的快照,从该快照创建一个新 EBS 卷,然后将该新 EBS 卷挂载到另一个上一个额外的驱动器。我知道如何通过 AWS Web 控制台执行此操作,但我想使用 AWS Java API 自动执行此过程。

如果我只是一个接一个地调用以下命令:

CreateSnapshotResult snapRes
    = ec2.createSnapshot(new CreateSnapshotRequest(oldVolumeID, "Test snapshot"));
Snapshot snap = snapRes.getSnapshot();
CreateVolumeResult volRes
    = ec2.createVolume(new CreateVolumeRequest(snap.getSnapshotId(), aZone));
String newVolumeID = volRes.getVolume().getVolumeId();
AttachVolumeResult attachRes 
    = ec2.attachVolume(new AttachVolumeRequest(newVolumeID, instanceID, "xvdg"));

我收到以下错误:

Caught Exception: Snapshot 'snap-8e822cfd' is not 'completed'.
Reponse Status Code: 400
Error Code: IncorrectState
Request ID: 40bc6bad-43e0-49e6-a89a-0489744d24e6

为了解决这个问题,我显然需要等到快照完成后,才能从快照创建新的 EBS 卷。根据Amazon docs,Snapshot.getState() 的可能值是“待处理、已完成或错误”,因此我决定与 AWS 联系以查看快照是否仍处于“待处理”状态。我写了以下代码,但它没有工作:

CreateSnapshotResult snapRes
    = ec2.createSnapshot(new CreateSnapshotRequest(oldVolumeID, "Test snapshot"));
 Snapshot snap = snapRes.getSnapshot();

 System.out.println("Snapshot request sent.");
 System.out.println("Waiting for snapshot to be created");

 String snapState = snap.getState();

 System.out.println("snapState is " + snapState);
 // Wait for the snapshot to be created
 while (snapState.equals("pending"))
 {
    Thread.sleep(1000);
    System.out.print(".");
    snapState = snapRes.getSnapshot().getState();
 }
 System.out.println("Done.");

当我运行它时,我得到以下输出:

Snapshot request sent.
Waiting for snapshot to be created
snapState is pending
.............................................

在我终止程序之前,这些点会继续打印。在 AWS Web 控制台中,我可以看到快照已创建(现在有一个绿色圆圈将其标记为“已完成”),但不知何故我的程序没有收到消息。

当我用简单的等待一秒钟替换 while 循环时(在第一个代码 sn-p 中的 Snapshot snap = snapRes.getSnapshot(); 之后插入行 Thread.sleep(1000)),程序通常会毫无怨言地创建一个新的 EBS 卷(然后当我尝试将卷附加到新实例时死了)。但是,有时即使等待一秒钟,我也会收到 IncorrectState 错误。我认为这意味着创建快照(即使是相同的 EBS 卷)所需的时间会有所不同,并且一秒钟足以解决部分但不是全部可能的延迟时间。

我可以将硬编码延迟增加到一定比预期时间更长的时间,但是这种方法有很多错误(在我将使用它的大部分时间它都不必要地等待,它仍然不能保证是足够长的时间,它不会很好地转化为第二步的解决方案,将 EBS 卷安装到实例上)。

我真的希望能够定期检查 AWS,检查快照的状态是否发生了变化,然后在发生变化后继续。我做错了什么,我应该如何修复我的代码以允许我的程序动态确定快照何时已完全创建?

编辑:根据建议,我尝试使用 getProgress() 而不是 getState()。我修改后的代码如下所示:

String snapProgress = snap.getProgress();

System.out.println("snapProgress is " + snapProgress);
// Wait for the snapshot to be created
while (!snapProgress.equals("100%"))
{
    Thread.sleep(1000);
    System.out.print(".");
    snapProgress = snapRes.getSnapshot().getProgress();
}
System.out.println("Done.");

我得到与使用getState() 时相同的输出。我认为我的问题是我的代码引用的快照对象没有正确更新。有没有比简单地重复调用其方法更好的方法来刷新/更新该对象?我怀疑我在 API 处理请求的方式上遇到了某种问题。

【问题讨论】:

    标签: java amazon-ec2


    【解决方案1】:

    解决了。我认为问题在于 Snapshot.getState() 调用实际上并没有对 AWS 进行新调用,而是不断返回对象在创建时的状态(始终处于挂起状态)。

    我使用describeSnapshots() 方法解决了这个问题:

    String snapState = snap.getState();
    System.out.println("snapState is " + snapState);
    
    System.out.print("Waiting for snapshot to be created");
    // Wait for the snapshot to be created
    while (snapState.equals("pending"))
    {
        Thread.sleep(500);
        System.out.print(".");
        DescribeSnapshotsResult describeSnapRes 
            = ec2.describeSnapshots(new DescribeSnapshotsRequest().withSnapshotIds(snap.getSnapshotId()));
    snapState = describeSnapRes.getSnapshots().get(0).getState();
     }
     System.out.println("\nDone.");
    

    这每次都会正确调用 AWS,而且它有效。

    【讨论】:

    • 谢谢 .. 我也需要做同样的事情!我希望这会对我有所帮助,尽管我的代码是用 Python 编写的 :)
    • 很高兴我能帮上忙!祝你的项目好运!
    【解决方案2】:

    尝试使用 getProgress() 方法而不是 getstate() 。如果您将其设为空白,则您的 EBS 快照尚未准备好。它以字符串百分比格式提供输出(快照准备就绪时为 100%)。希望它可以解决问题。让我知道它是否有效。

    【讨论】:

    • 不,这不起作用(见编辑)。不过,感谢您的建议。
    猜你喜欢
    • 2020-07-10
    • 1970-01-01
    • 2020-02-02
    • 1970-01-01
    • 2020-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-17
    相关资源
    最近更新 更多