我有多个 EBS 支持的 EC2 实例正在运行,我希望能够为其中一个 EBS 卷拍摄快照,从该快照创建一个新的 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() 的可能值是“pending、completed 或 error”,因此我决定使用 AWS 检查快照是否仍处于“pending”状态。我写了下面的代码,但是没有用:
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 循环时(在 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 处理请求的方式上遇到了某种问题。
最佳答案
解决了。我认为问题是 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 进行正确的调用,并且它有效。
关于java - 在 AWS Java API 中,我如何知道我的 EBS 快照何时创建?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12065059/