Skip to content

Commit b6fb544

Browse files
committed
Use unique VMIDs in integ tests
Many of our integ tests use an integer as the VMID. Some of the test suites run in parallel which risks either creating the same ID multiple times or one test tearing down another test's resources. This change makes each test's VMIDs unique Signed-off-by: Kern Walster <[email protected]>
1 parent 3fae0bd commit b6fb544

File tree

5 files changed

+98
-36
lines changed

5 files changed

+98
-36
lines changed

internal/integtest/vmid.go

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"). You may
4+
// not use this file except in compliance with the License. A copy of the
5+
// License is located at
6+
//
7+
// http://aws.amazon.com/apache2.0/
8+
//
9+
// or in the "license" file accompanying this file. This file is distributed
10+
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
// express or implied. See the License for the specific language governing
12+
// permissions and limitations under the License.
13+
14+
package integtest
15+
16+
import (
17+
"crypto/rand"
18+
"encoding/hex"
19+
"fmt"
20+
)
21+
22+
// VMIDGen generates namespaced VMIDs that are unique across different VMIDGens.
23+
// We have many tests which use a numeric ID as the VMID which could conflict with
24+
// concurrently running test. VMIDGen guarantees uniqueness across different tests.
25+
type VMIDGen struct {
26+
prefix string
27+
}
28+
29+
// NewVMIDGen creates a new VMIDGen
30+
func NewVMIDGen() (*VMIDGen, error) {
31+
b := make([]byte, 16)
32+
_, err := rand.Read(b)
33+
if err != nil {
34+
return nil, err
35+
}
36+
return &VMIDGen{hex.EncodeToString(b)}, nil
37+
}
38+
39+
// VMID creates a namespaced VMID given an integer seed.
40+
// A VMIDGen will generate the same VMID multiple times given the same seed,
41+
// but two different VMIDGens will generate different ids given the same seed.
42+
func (gen *VMIDGen) VMID(seed int) string {
43+
return fmt.Sprintf("%s-%d", gen.prefix, seed)
44+
}

runtime/cni_integ_test.go

+10-8
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,14 @@ func TestCNISupport_Isolated(t *testing.T) {
5353
image, err := alpineImage(ctx, client, defaultSnapshotterName)
5454
require.NoError(t, err, "failed to get alpine image")
5555

56+
gen, err := integtest.NewVMIDGen()
57+
require.NoError(t, err, "failed to create a VMIDGen")
58+
5659
numVMs := 5
5760
var vmIDs []string
5861
webpages := make(map[string]string)
5962
for i := 0; i < numVMs; i++ {
60-
vmID := fmt.Sprintf("vm-%d", i)
63+
vmID := gen.VMID(i)
6164
vmIDs = append(vmIDs, vmID)
6265
webpages[vmID] = fmt.Sprintf("Hello, my virtual machine %s\n", vmID)
6366
}
@@ -247,9 +250,8 @@ func TestCNIPlugin_Performance(t *testing.T) {
247250
runCommand(ctx, t, "ip", "addr", "add", ipCidr, "dev", testDevName)
248251
runCommand(ctx, t, "ip", "link", "set", "dev", testDevName, "up")
249252

250-
vmID := func(vmIndex int) string {
251-
return fmt.Sprintf("vm-%d", vmIndex)
252-
}
253+
gen, err := integtest.NewVMIDGen()
254+
require.NoError(t, err, "Failed to create a VMIDGen")
253255

254256
var vmGroup sync.WaitGroup
255257
containers := make(chan containerd.Container, numVMs)
@@ -272,7 +274,7 @@ func TestCNIPlugin_Performance(t *testing.T) {
272274
}()
273275

274276
_, err = fcClient.CreateVM(ctx, &proto.CreateVMRequest{
275-
VMID: vmID(vmIndex),
277+
VMID: gen.VMID(vmIndex),
276278
MachineCfg: &proto.FirecrackerMachineConfiguration{
277279
MemSizeMib: uint32(vmMemSizeMB),
278280
},
@@ -285,8 +287,8 @@ func TestCNIPlugin_Performance(t *testing.T) {
285287
})
286288
require.NoError(t, err, "failed to create vm")
287289

288-
containerName := fmt.Sprintf("%s-container", vmID(vmIndex))
289-
snapshotName := fmt.Sprintf("%s-snapshot", vmID(vmIndex))
290+
containerName := fmt.Sprintf("%s-container", gen.VMID(vmIndex))
291+
snapshotName := fmt.Sprintf("%s-snapshot", gen.VMID(vmIndex))
290292

291293
newContainer, err := client.NewContainer(ctx,
292294
containerName,
@@ -300,7 +302,7 @@ func TestCNIPlugin_Performance(t *testing.T) {
300302
"--interval", "60",
301303
"--client", ipAddr,
302304
),
303-
firecrackeroci.WithVMID(vmID(vmIndex)),
305+
firecrackeroci.WithVMID(gen.VMID(vmIndex)),
304306
firecrackeroci.WithVMNetwork,
305307
),
306308
)

runtime/service_integ_test.go

+24-13
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,9 @@ func testMultipleVMs(ctx context.Context, t *testing.T, count int) {
355355
stopped int64
356356
)
357357

358+
gen, err := integtest.NewVMIDGen()
359+
require.NoError(t, err, "Failed to create a VMIDGen")
360+
358361
// This test spawns separate VMs in parallel and ensures containers are spawned within each expected VM. It asserts each
359362
// container ends up in the right VM by assigning each VM a network device with a unique mac address and having each container
360363
// print the mac address it sees inside its VM.
@@ -371,7 +374,7 @@ func testMultipleVMs(ctx context.Context, t *testing.T, count int) {
371374

372375
rootfsPath := cfg.RootDrive
373376

374-
vmIDStr := strconv.Itoa(vmID)
377+
vmIDStr := gen.VMID(vmID)
375378
req := &proto.CreateVMRequest{
376379
KernelArgs: kernelArgs,
377380
VMID: vmIDStr,
@@ -426,6 +429,7 @@ func testMultipleVMs(ctx context.Context, t *testing.T, count int) {
426429
return testMultipleExecs(
427430
containerCtx,
428431
vmID,
432+
gen,
429433
containerID,
430434
client, image,
431435
jailerConfig,
@@ -435,21 +439,21 @@ func testMultipleVMs(ctx context.Context, t *testing.T, count int) {
435439
}
436440

437441
// verify duplicate CreateVM call fails with right error
438-
_, err = fcClient.CreateVM(ctx, &proto.CreateVMRequest{VMID: strconv.Itoa(vmID)})
442+
_, err = fcClient.CreateVM(ctx, &proto.CreateVMRequest{VMID: vmIDStr})
439443
if err == nil {
440444
return fmt.Errorf("creating the same VM must return an error")
441445
}
442446

443447
// verify GetVMInfo returns expected data
444-
vmInfoResp, err := fcClient.GetVMInfo(ctx, &proto.GetVMInfoRequest{VMID: strconv.Itoa(vmID)})
448+
vmInfoResp, err := fcClient.GetVMInfo(ctx, &proto.GetVMInfoRequest{VMID: vmIDStr})
445449
if err != nil {
446450
return err
447451
}
448-
if vmInfoResp.VMID != strconv.Itoa(vmID) {
449-
return fmt.Errorf("%q must be %q", vmInfoResp.VMID, strconv.Itoa(vmID))
452+
if vmInfoResp.VMID != vmIDStr {
453+
return fmt.Errorf("%q must be %q", vmInfoResp.VMID, vmIDStr)
450454
}
451455

452-
nspVMid := defaultNamespace + "#" + strconv.Itoa(vmID)
456+
nspVMid := defaultNamespace + "#" + vmIDStr
453457
cfg, err := config.LoadConfig("")
454458
if err != nil {
455459
return err
@@ -465,7 +469,7 @@ func testMultipleVMs(ctx context.Context, t *testing.T, count int) {
465469
// just verify that updating the metadata doesn't return an error, a separate test case is needed
466470
// to very the MMDS update propagates to the container correctly
467471
_, err = fcClient.SetVMMetadata(ctx, &proto.SetVMMetadataRequest{
468-
VMID: strconv.Itoa(vmID),
472+
VMID: vmIDStr,
469473
Metadata: "{}",
470474
})
471475
if err != nil {
@@ -477,7 +481,7 @@ func testMultipleVMs(ctx context.Context, t *testing.T, count int) {
477481
return fmt.Errorf("unexpected error from the containers in VM %d: %w", vmID, err)
478482
}
479483

480-
_, err = fcClient.StopVM(ctx, &proto.StopVMRequest{VMID: strconv.Itoa(vmID), TimeoutSeconds: 5})
484+
_, err = fcClient.StopVM(ctx, &proto.StopVMRequest{VMID: vmIDStr, TimeoutSeconds: 5})
481485
atomic.AddInt64(&stopped, 1)
482486
return err
483487
}
@@ -515,13 +519,14 @@ loop:
515519
func testMultipleExecs(
516520
ctx context.Context,
517521
vmID int,
522+
gen *integtest.VMIDGen,
518523
containerID int,
519524
client *containerd.Client,
520525
image containerd.Image,
521526
jailerConfig *proto.JailerConfig,
522527
cgroupPath string,
523528
) error {
524-
vmIDStr := strconv.Itoa(vmID)
529+
vmIDStr := gen.VMID(vmID)
525530
testTimeout := 600 * time.Second
526531

527532
containerName := fmt.Sprintf("container-%d-%d", vmID, containerID)
@@ -826,6 +831,9 @@ func TestStubBlockDevices_Isolated(t *testing.T) {
826831

827832
const vmID = 0
828833

834+
gen, err := integtest.NewVMIDGen()
835+
require.NoError(t, err, "failed to create VMIDGen")
836+
829837
ctx := namespaces.WithNamespace(context.Background(), "default")
830838

831839
client, err := containerd.New(integtest.ContainerdSockPath, containerd.WithDefaultRuntime(firecrackerRuntime))
@@ -846,7 +854,7 @@ func TestStubBlockDevices_Isolated(t *testing.T) {
846854
require.NoError(t, err, "failed to create fccontrol client")
847855

848856
_, err = fcClient.CreateVM(ctx, &proto.CreateVMRequest{
849-
VMID: strconv.Itoa(vmID),
857+
VMID: gen.VMID(vmID),
850858
NetworkInterfaces: []*proto.FirecrackerNetworkInterface{
851859
{
852860
AllowMMDS: true,
@@ -865,7 +873,7 @@ func TestStubBlockDevices_Isolated(t *testing.T) {
865873
containerd.WithSnapshotter(defaultSnapshotterName),
866874
containerd.WithNewSnapshot(snapshotName, image),
867875
containerd.WithNewSpec(
868-
firecrackeroci.WithVMID(strconv.Itoa(vmID)),
876+
firecrackeroci.WithVMID(gen.VMID(vmID)),
869877
oci.WithProcessArgs("/bin/sh", "/var/firecracker-containerd-test/scripts/lsblk.sh"),
870878

871879
oci.WithMounts([]specs.Mount{
@@ -1447,6 +1455,9 @@ func TestMemoryBalloon_Isolated(t *testing.T) {
14471455
}
14481456
t.Logf("TestMemoryBalloon_Isolated: will run %d vm's", numberOfVms)
14491457

1458+
gen, err := integtest.NewVMIDGen()
1459+
require.NoError(t, err, "Failed to create a VMIDGen")
1460+
14501461
var vmGroup sync.WaitGroup
14511462
for i := 0; i < numberOfVms; i++ {
14521463
vmGroup.Add(1)
@@ -1462,7 +1473,7 @@ func TestMemoryBalloon_Isolated(t *testing.T) {
14621473
require.NoError(t, err, "failed to create fccontrol client")
14631474

14641475
_, err = fcClient.CreateVM(ctx, &proto.CreateVMRequest{
1465-
VMID: strconv.Itoa(vmID),
1476+
VMID: gen.VMID(vmID),
14661477
MachineCfg: &proto.FirecrackerMachineConfiguration{
14671478
MemSizeMib: 512,
14681479
},
@@ -1484,7 +1495,7 @@ func TestMemoryBalloon_Isolated(t *testing.T) {
14841495
require.NoError(t, err, "failed to create vm")
14851496

14861497
// Test UpdateBalloon correctly updates amount of memory for the balloon device
1487-
vmIDStr := strconv.Itoa(vmID)
1498+
vmIDStr := gen.VMID(vmID)
14881499
newAmountMib := int64(50)
14891500
_, err = fcClient.UpdateBalloon(ctx, &proto.UpdateBalloonRequest{
14901501
VMID: vmIDStr,

snapshotter/metrics_integ_test.go

+12-9
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"fmt"
2020
"io"
2121
"net/http"
22-
"strconv"
2322
"testing"
2423

2524
"github.com/containerd/containerd"
@@ -43,15 +42,17 @@ const (
4342
func TestSnapshotterMetrics_Isolated(t *testing.T) {
4443
integtest.Prepare(t)
4544

46-
vmID := 0
45+
gen, err := integtest.NewVMIDGen()
46+
require.NoError(t, err, "Failed to create a VMIDGen")
47+
vmID := gen.VMID(0)
4748

48-
ctx := namespaces.WithNamespace(context.Background(), strconv.Itoa(vmID))
49+
ctx := namespaces.WithNamespace(context.Background(), vmID)
4950

5051
fcClient, err := integtest.NewFCControlClient(integtest.ContainerdSockPath)
51-
defer fcClient.StopVM(ctx, &proto.StopVMRequest{VMID: strconv.Itoa(vmID)})
52+
defer fcClient.StopVM(ctx, &proto.StopVMRequest{VMID: vmID})
5253
require.NoError(t, err, "Failed to create fccontrol client")
5354

54-
require.NoError(t, pullImageWithRemoteSnapshotterInVM(ctx, strconv.Itoa(vmID), fcClient))
55+
require.NoError(t, pullImageWithRemoteSnapshotterInVM(ctx, vmID, fcClient))
5556
verifyMetricsResponse(t, 1)
5657
}
5758

@@ -63,15 +64,17 @@ func TestSnapshotterMetricsMultipleVMs_Isolated(t *testing.T) {
6364
require.NoError(t, err, "Failed to create fccontrol client")
6465

6566
group, ctx := errgroup.WithContext(context.Background())
67+
gen, err := integtest.NewVMIDGen()
68+
require.NoError(t, err, "Failed to create a VMIDGen")
6669

6770
for vmID := 0; vmID < numberOfVms; vmID++ {
68-
id := vmID
69-
ctxNamespace := namespaces.WithNamespace(ctx, strconv.Itoa(id))
70-
defer fcClient.StopVM(ctxNamespace, &proto.StopVMRequest{VMID: strconv.Itoa(id)})
71+
id := gen.VMID(vmID)
72+
ctxNamespace := namespaces.WithNamespace(ctx, id)
73+
defer fcClient.StopVM(ctxNamespace, &proto.StopVMRequest{VMID: id})
7174

7275
group.Go(
7376
func() error {
74-
return pullImageWithRemoteSnapshotterInVM(ctxNamespace, strconv.Itoa(id), fcClient)
77+
return pullImageWithRemoteSnapshotterInVM(ctxNamespace, id, fcClient)
7578
},
7679
)
7780

snapshotter/service_integ_test.go

+8-6
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ package main
1616
import (
1717
"context"
1818
"fmt"
19-
"strconv"
2019
"testing"
2120

2221
"github.com/containerd/containerd"
@@ -51,25 +50,28 @@ const (
5150
func TestLaunchContainerWithRemoteSnapshotter_Isolated(t *testing.T) {
5251
integtest.Prepare(t, integtest.WithDefaultNetwork())
5352

54-
vmID := 0
55-
err := launchContainerWithRemoteSnapshotterInVM(context.Background(), strconv.Itoa(vmID))
53+
gen, err := integtest.NewVMIDGen()
54+
require.NoError(t, err, "Failed to create a VMIDGen")
55+
err = launchContainerWithRemoteSnapshotterInVM(context.Background(), gen.VMID(0))
5656
require.NoError(t, err)
5757
}
5858

5959
func TestLaunchMultipleContainersWithRemoteSnapshotter_Isolated(t *testing.T) {
6060
integtest.Prepare(t, integtest.WithDefaultNetwork())
61+
gen, err := integtest.NewVMIDGen()
62+
require.NoError(t, err, "Failed to create a VMIDGen")
6163

6264
eg, ctx := errgroup.WithContext(context.Background())
6365

6466
numberOfVms := integtest.NumberOfVms
6567
for vmID := 0; vmID < numberOfVms; vmID++ {
6668
ctx := ctx
67-
id := vmID
69+
id := gen.VMID(vmID)
6870
eg.Go(func() error {
69-
return launchContainerWithRemoteSnapshotterInVM(ctx, strconv.Itoa(id))
71+
return launchContainerWithRemoteSnapshotterInVM(ctx, id)
7072
})
7173
}
72-
err := eg.Wait()
74+
err = eg.Wait()
7375
require.NoError(t, err)
7476
}
7577

0 commit comments

Comments
 (0)