java - 在 AWS Java API 中,我如何知道我的 EBS 快照何时创建?

标签 java amazon-ec2

我有多个 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/

相关文章:

java - JMockit MockUp 类和 Mockito/mock 等价物

django - 错误: "The security token included in the request is invalid" when using Boto python

linux - 在 amazon linux 上安装 zmq 时出现问题(无法找到 uuid)

java - AWS EC2 Tomcat Java Webapp - 我如何管理 bot http session

java - 反序列化包含任意名称和数据类型的 JSON 元素

java - 在java中,在lambda函数内部使用时,三元运算符是否被视为单行表达式?

java - 生成特定的随机字符串数组

java - 如何从命令行使用 Eclipse 嵌入式 Maven 安装?

amazon-web-services - 如何限制特定IAM角色对S3存储桶的访问?

linux - 尝试在 AWS EC2 的 Ubuntu 18.04 上安装 PHP 时出错