2012-08-22 71 views
3

我有多個EBS支持的EC2實例正在運行,我希望能夠在其中一個EBS卷的後面拍攝快照,從該快照創建一個新的EBS卷,然後將該新的EBS卷掛載到另一個上額外的驅動。我知道如何通過AWS Web控制檯執行此操作,但我希望通過使用AWS Java API來自動執行此過程。從AWS Java API中,如何知道我的EBS快照何時創建?

如果我簡單地調用下面的命令一個接一個:

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 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處理請求的方式而遇到某種問題。

回答

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的每一次正確的呼叫,和它的作品。

+0

謝謝..我需要做同樣的事情!我希望這會幫助我,儘管我的代碼是在Python中:) –

+0

很高興我能幫上忙!祝你的項目好運! –

0

而不是getstate(),請嘗試使用getProgress()方法。如果你把它弄空白,那麼你的EBS快照還沒有準備好。它以字符串百分比格式給出輸出(當快照準備就緒時爲100%)。希望它能做到這一點。讓我知道它是否有效。

+0

不,不起作用(請參閱編輯)。還是)感謝你的建議。 –