Skip to content

Commit c6b3e5a

Browse files
jdtsillasdtsillasbblommers
authored
EBS: Some fixes to snapshot uploading (#6520)
* Two fixes to support Citrix AWS hypervisor plugin: ebs responses for putting a block and completing a snapshot should be 201 and 202 respectively rather than 200; If the body cannot be utf-8 decoded, try base64.Z * Update responses.py * Update responses.py * Update responses.py * Add EBS snapshot unit test * EBS: put_snapshot_block() should support raw bytes --------- Co-authored-by: Demetrios Tsillas <[email protected]> Co-authored-by: Bert Blommers <[email protected]>
1 parent 6831c42 commit c6b3e5a

File tree

6 files changed

+89
-6
lines changed

6 files changed

+89
-6
lines changed

.github/workflows/tests_sdk_dotnet.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ jobs:
2828
restore-keys: |
2929
${{ runner.os }}-nuget
3030
- name: Install dependencies
31-
run: cd other_langs/tests_dotnet && dotnet restore ExampleTestProject/
31+
run: cd other_langs/tests_dotnet && dotnet restore ExampleTestProject/ && dotnet restore ebs
3232
- name: Run tests
3333
run: |
3434
mkdir ~/.aws && touch ~/.aws/credentials && echo -e "[default]\naws_access_key_id = test\naws_secret_access_key = test" > ~/.aws/credentials
35-
cd other_langs/tests_dotnet && dotnet test ExampleTestProject/
35+
cd other_langs/tests_dotnet && dotnet test ExampleTestProject/ && dotnet restore ebs

moto/ebs/responses.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def snapshots(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE:
2424
return self.start_snapshot()
2525

2626
def snapshot_block(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE: # type: ignore[return]
27-
self.setup_class(request, full_url, headers)
27+
self.setup_class(request, full_url, headers, use_raw_body=True)
2828
if request.method == "PUT":
2929
return self.put_snapshot_block(full_url, headers)
3030
if request.method == "GET":
@@ -59,7 +59,7 @@ def complete_snapshot(
5959
self.setup_class(request, full_url, headers)
6060
snapshot_id = full_url.split("/")[-1]
6161
status = self.ebs_backend.complete_snapshot(snapshot_id=snapshot_id)
62-
return 200, {}, json.dumps(status)
62+
return 202, {}, json.dumps(status)
6363

6464
def put_snapshot_block(self, full_url: str, headers: Any) -> TYPE_RESPONSE:
6565
"""
@@ -82,7 +82,7 @@ def put_snapshot_block(self, full_url: str, headers: Any) -> TYPE_RESPONSE:
8282
data_length=data_length,
8383
)
8484
return (
85-
200,
85+
201,
8686
{
8787
"x-amz-Checksum": checksum,
8888
"x-amz-Checksum-Algorithm": checksum_algorithm,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net7.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
8+
<IsPackable>true</IsPackable>
9+
<PackAsTool>true</PackAsTool>
10+
11+
<UserSecretsId>45a910a7-aba2-43ee-ad3c-ccad57f044d9</UserSecretsId>
12+
</PropertyGroup>
13+
14+
<ItemGroup>
15+
<PackageReference Include="AWSSDK.EBS" Version="3.7.100.153" />
16+
<PackageReference Include="FluentAssertions" Version="6.8.0" />
17+
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
18+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
19+
<PackageReference Include="xunit" Version="2.4.1" />
20+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
21+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
22+
<PrivateAssets>all</PrivateAssets>
23+
</PackageReference>
24+
</ItemGroup>
25+
26+
</Project>
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using FluentAssertions;
2+
3+
// To interact with Amazon EBS
4+
using Amazon.EBS;
5+
using Amazon.EBS.Model;
6+
7+
using System.Security.Cryptography;
8+
9+
10+
public class EbsSnashotTest
11+
{
12+
[Fact]
13+
public async Task TestSnapshotCreation()
14+
{
15+
16+
AmazonEBSConfig config = new AmazonEBSConfig()
17+
{
18+
ServiceURL = "http://localhost:5000",
19+
};
20+
21+
AmazonEBSClient ebsClient = new AmazonEBSClient(config);
22+
23+
// https://docs.aws.amazon.com/ebs/latest/APIReference/API_StartSnapshot.html
24+
var startSnapshotRequest = new StartSnapshotRequest { VolumeSize = 1 };
25+
var startSnapshotResponse = await ebsClient.StartSnapshotAsync(startSnapshotRequest);
26+
startSnapshotResponse.Status.Should().Be("pending");
27+
28+
// https://docs.aws.amazon.com/ebs/latest/APIReference/API_PutSnapshotBlock.html
29+
var blockData = new byte[] { 0x01, 0x02, 0x03, 0x04 };
30+
Stream blockDataStream = new MemoryStream(blockData);
31+
SHA256Managed sha256hasher = new SHA256Managed();
32+
byte[] sha256Hash = sha256hasher.ComputeHash(blockDataStream);
33+
var sha256checksum = Convert.ToBase64String(sha256Hash);
34+
var putSnapshotBlockRequest = new PutSnapshotBlockRequest
35+
{
36+
BlockIndex = 0,
37+
Checksum = sha256checksum,
38+
ChecksumAlgorithm = "SHA256",
39+
DataLength = blockData.Length,
40+
SnapshotId = startSnapshotResponse.SnapshotId,
41+
BlockData = blockDataStream
42+
};
43+
var putSnapshotBlockResponse = await ebsClient.PutSnapshotBlockAsync(putSnapshotBlockRequest);
44+
putSnapshotBlockResponse.Checksum.Should().Be(sha256checksum);
45+
putSnapshotBlockResponse.ChecksumAlgorithm.Should().Be("SHA256");
46+
47+
https://docs.aws.amazon.com/ebs/latest/APIReference/API_CompleteSnapshot.html
48+
var completeSnapshotRequest = new CompleteSnapshotRequest
49+
{
50+
ChangedBlocksCount = 1,
51+
SnapshotId = startSnapshotResponse.SnapshotId
52+
};
53+
var completeSnapshotResponse = await ebsClient.CompleteSnapshotAsync(completeSnapshotRequest);
54+
completeSnapshotResponse.Status.Should().Be("completed");
55+
}
56+
}
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
global using Xunit;

tests/test_ebs/test_ebs.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def test_complete_snapshot():
5151

5252
@mock_ebs
5353
def test_put_snapshot_block():
54-
data = b"data for this specific block"
54+
data = b"data for this specific block\xbf"
5555
checksum = hashlib.sha256(data).hexdigest()
5656
client = boto3.client("ebs", region_name="eu-west-1")
5757
snapshot_id = client.start_snapshot(VolumeSize=720)["SnapshotId"]

0 commit comments

Comments
 (0)