Skip to content

Commit 6db5f91

Browse files
authored
Merge pull request #466 from xibz/stopvm-err
Fix leak of VMs
2 parents 80bc1ef + 9488f68 commit 6db5f91

File tree

4 files changed

+63
-27
lines changed

4 files changed

+63
-27
lines changed

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ ROOTFS_SLOW_REBOOT_INSTALLPATH=$(FIRECRACKER_CONTAINERD_RUNTIME_DIR)/rootfs-slow
196196
$(ROOTFS_SLOW_REBOOT_INSTALLPATH): tools/image-builder/rootfs-slow-reboot.img $(FIRECRACKER_CONTAINERD_RUNTIME_DIR)
197197
install -D -o root -g root -m400 $< $@
198198

199+
ROOTFS_NO_AGENT_INSTALLPATH=$(FIRECRACKER_CONTAINERD_RUNTIME_DIR)/rootfs-no-agent.img
200+
$(ROOTFS_NO_AGENT_INSTALLPATH): tools/image-builder/rootfs-no-agent.img $(FIRECRACKER_CONTAINERD_RUNTIME_DIR)
201+
install -D -o root -g root -m400 $< $@
202+
199203
.PHONY: default-vmlinux
200204
default-vmlinux: $(DEFAULT_VMLINUX_NAME)
201205

@@ -209,7 +213,7 @@ install-default-rootfs: $(DEFAULT_ROOTFS_INSTALLPATH)
209213
install-default-runc-jailer-config: $(DEFAULT_RUNC_JAILER_CONFIG_INSTALLPATH)
210214

211215
.PHONY: install-test-rootfs
212-
install-test-rootfs: $(ROOTFS_SLOW_BOOT_INSTALLPATH) $(ROOTFS_SLOW_REBOOT_INSTALLPATH)
216+
install-test-rootfs: $(ROOTFS_SLOW_BOOT_INSTALLPATH) $(ROOTFS_SLOW_REBOOT_INSTALLPATH) $(ROOTFS_NO_AGENT_INSTALLPATH)
213217

214218
##########################
215219
# CNI Network

runtime/service.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -465,9 +465,7 @@ func (s *service) CreateVM(requestCtx context.Context, request *proto.CreateVMRe
465465
// If we failed to create the VM, we have no point in existing anymore, so shutdown
466466
if err != nil {
467467
s.shimCancel()
468-
469468
s.logger.WithError(err).Error("failed to create VM")
470-
471469
if errors.Cause(err) == context.DeadlineExceeded {
472470
return nil, status.Errorf(codes.DeadlineExceeded, "VM %q didn't start within %s: %s", request.VMID, timeout, err)
473471
}
@@ -481,7 +479,6 @@ func (s *service) CreateVM(requestCtx context.Context, request *proto.CreateVMRe
481479
}
482480

483481
go s.monitorVMExit()
484-
485482
// let all the other methods know that the VM is ready for tasks
486483
close(s.vmReady)
487484

@@ -528,6 +525,15 @@ func (s *service) createVM(requestCtx context.Context, request *proto.CreateVMRe
528525
return errors.Wrap(err, "failed to create jailer")
529526
}
530527

528+
defer func() {
529+
// in the event of an error, we should stop the VM
530+
if err != nil {
531+
if e := s.jailer.Stop(true); e != nil {
532+
s.logger.WithError(e).Debug("failed to stop firecracker")
533+
}
534+
}
535+
}()
536+
531537
s.machineConfig, err = s.buildVMConfiguration(request)
532538
if err != nil {
533539
return errors.Wrapf(err, "failed to build VM configuration")

runtime/service_integ_test.go

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1909,7 +1909,6 @@ func requireNonEmptyFifo(t testing.TB, path string) {
19091909

19101910
func TestCreateVM_Isolated(t *testing.T) {
19111911
prepareIntegTest(t)
1912-
19131912
client, err := containerd.New(containerdSockPath, containerd.WithDefaultRuntime(firecrackerRuntime))
19141913
require.NoError(t, err, "unable to create client to containerd service at %s, is containerd running?", containerdSockPath)
19151914
defer client.Close()
@@ -1921,17 +1920,38 @@ func TestCreateVM_Isolated(t *testing.T) {
19211920

19221921
fcClient := fccontrol.NewFirecrackerClient(pluginClient.Client())
19231922

1924-
subtests := []struct {
1923+
type subtest struct {
19251924
name string
19261925
request proto.CreateVMRequest
19271926
validate func(*testing.T, error)
1928-
}{
1927+
stopVM bool
1928+
}
1929+
1930+
subtests := []subtest{
19291931
{
19301932
name: "Happy Case",
19311933
request: proto.CreateVMRequest{},
19321934
validate: func(t *testing.T, err error) {
19331935
require.NoError(t, err)
19341936
},
1937+
stopVM: true,
1938+
},
1939+
{
1940+
name: "Error Case",
1941+
request: proto.CreateVMRequest{
1942+
TimeoutSeconds: 5,
1943+
RootDrive: &proto.FirecrackerRootDrive{
1944+
HostPath: "/var/lib/firecracker-containerd/runtime/rootfs-no-agent.img",
1945+
},
1946+
},
1947+
validate: func(t *testing.T, err error) {
1948+
require.NotNil(t, err, "expected an error but did not receive any")
1949+
time.Sleep(5 * time.Second)
1950+
firecrackerProcesses, err := findProcess(ctx, findFirecracker)
1951+
require.NoError(t, err, "failed waiting for expected firecracker process %q to come up", firecrackerProcessName)
1952+
require.Len(t, firecrackerProcesses, 0, "expected only no firecracker processes to exist")
1953+
},
1954+
stopVM: false,
19351955
},
19361956
{
19371957
name: "Slow Root FS",
@@ -1945,6 +1965,7 @@ func TestCreateVM_Isolated(t *testing.T) {
19451965
assert.Equal(t, codes.DeadlineExceeded, status.Code(err))
19461966
assert.Contains(t, err.Error(), "didn't start within 20s")
19471967
},
1968+
stopVM: true,
19481969
},
19491970
{
19501971
name: "Slow Root FS and Longer Timeout",
@@ -1957,10 +1978,11 @@ func TestCreateVM_Isolated(t *testing.T) {
19571978
validate: func(t *testing.T, err error) {
19581979
require.NoError(t, err)
19591980
},
1981+
stopVM: true,
19601982
},
19611983
}
19621984

1963-
runTest := func(t *testing.T, request proto.CreateVMRequest, validate func(t *testing.T, err error)) {
1985+
runTest := func(t *testing.T, request proto.CreateVMRequest, s subtest) {
19641986
vmID := testNameToVMID(t.Name())
19651987

19661988
tempDir, err := ioutil.TempDir("", vmID)
@@ -1981,34 +2003,31 @@ func TestCreateVM_Isolated(t *testing.T) {
19812003
requireNonEmptyFifo(t, metricsFile)
19822004

19832005
// Some test cases are expected to have an error, some are not.
1984-
validate(t, createVMErr)
1985-
1986-
// No VM to stop.
1987-
if createVMErr != nil {
1988-
return
1989-
}
2006+
s.validate(t, createVMErr)
19902007

1991-
// Ensure the response fields are populated correctly
1992-
assert.Equal(t, request.VMID, resp.VMID)
2008+
if createVMErr == nil && s.stopVM {
2009+
// Ensure the response fields are populated correctly
2010+
assert.Equal(t, request.VMID, resp.VMID)
19932011

1994-
_, err = fcClient.StopVM(ctx, &proto.StopVMRequest{VMID: request.VMID})
1995-
require.Equal(t, status.Code(err), codes.OK)
2012+
_, err = fcClient.StopVM(ctx, &proto.StopVMRequest{VMID: request.VMID})
2013+
require.Equal(t, status.Code(err), codes.OK)
2014+
}
19962015
}
19972016

1998-
for _, subtest := range subtests {
1999-
request := subtest.request
2000-
validate := subtest.validate
2001-
t.Run(subtest.name, func(t *testing.T) {
2002-
runTest(t, request, validate)
2017+
for _, _s := range subtests {
2018+
s := _s
2019+
request := s.request
2020+
t.Run(s.name, func(t *testing.T) {
2021+
runTest(t, request, s)
20032022
})
20042023

2005-
requestWithJailer := subtest.request
2024+
requestWithJailer := s.request
20062025
requestWithJailer.JailerConfig = &proto.JailerConfig{
20072026
UID: 30000,
20082027
GID: 30000,
20092028
}
2010-
t.Run(subtest.name+"/Jailer", func(t *testing.T) {
2011-
runTest(t, requestWithJailer, validate)
2029+
t.Run(s.name+"/Jailer", func(t *testing.T) {
2030+
runTest(t, requestWithJailer, s)
20122031
})
20132032
}
20142033
}

tools/image-builder/Makefile

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ fi
3737
touch --reference=debootstrap_stamp --no-create "$(WORKDIR)"
3838
endef
3939

40-
all: rootfs.img rootfs-slow-boot.img rootfs-slow-reboot.img
40+
all: rootfs.img rootfs-slow-boot.img rootfs-slow-reboot.img rootfs-no-agent.img
4141

4242
$(WORKDIR):
4343
mkdir $(WORKDIR)
@@ -81,6 +81,13 @@ rootfs-slow-reboot.img: files_common_stamp files_debootstrap_stamp files_ephemer
8181
echo 'ExecStop=/bin/sleep 60' >> tmp/$@/etc/systemd/system/firecracker-agent.service
8282
mksquashfs tmp/$@ $@ -noappend
8383

84+
rootfs-no-agent.img: files_common_stamp files_debootstrap_stamp files_ephemeral_stamp
85+
rm -fr tmp/$@
86+
cp -a "$(WORKDIR)" tmp/$@
87+
rm tmp/$@/etc/systemd/system/firecracker-agent.service
88+
rm tmp/$@/usr/local/bin/agent
89+
mksquashfs tmp/$@ $@ -noappend
90+
8491
builder: builder_stamp
8592

8693
builder_stamp:

0 commit comments

Comments
 (0)