从AWS Java API,如何判断何时创建了EBS快照?

时间:2012-08-22 00:58:35

标签: java amazon-ec2

我有多个运行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卷。根据{{​​3}},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 Console中,我可以看到快照已经创建(它现在有一个绿色圆圈标记为“已完成”),但不知怎的,我的程序还没有收到消息。

当我用简单的等待一秒钟替换while循环(在第一个代码片段中的Thread.sleep(1000)之后插入行Snapshot snap = snapRes.getSnapshot();)时,程序通常会创建一个新的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处理请求的方式有关。

2 个答案:

答案 0 :(得分:5)

解决了它。我认为问题在于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,并且可以正常工作。

答案 1 :(得分:0)

尝试使用getProgress()方法而不是getstate()。如果您将其留空,那么您的EBS快照尚未就绪。它以字符串百分比格式提供输出(快照准备就绪时为100%)。希望它应该成功。如果有效,请告诉我。