From eb1b8741b5ff18b7b42bc19b0d2e9114fc487038 Mon Sep 17 00:00:00 2001 From: Danny Canter Date: Mon, 27 Oct 2025 17:33:49 -0700 Subject: [PATCH] LinuxContainer/Pod: Remove pause/resume (#366) --- Sources/Containerization/LinuxContainer.swift | 18 ---- Sources/Containerization/LinuxPod.swift | 16 ---- .../VZVirtualMachineInstance.swift | 3 + Sources/Integration/ContainerTests.swift | 88 ------------------- Sources/Integration/PodTests.swift | 27 ------ Sources/Integration/Suite.swift | 4 - 6 files changed, 3 insertions(+), 153 deletions(-) diff --git a/Sources/Containerization/LinuxContainer.swift b/Sources/Containerization/LinuxContainer.swift index bc477f6e..2e1e92b2 100644 --- a/Sources/Containerization/LinuxContainer.swift +++ b/Sources/Containerization/LinuxContainer.swift @@ -519,24 +519,6 @@ extension LinuxContainer { } } - /// Pause the container. - public func pause() async throws { - try await self.state.withLock { state in - let startedState = try state.startedState("pause") - try await startedState.vm.pause() - state = .paused(.init(startedState)) - } - } - - /// Resume the container. - public func resume() async throws { - try await self.state.withLock { state in - let pausedState = try state.pausedState("resume") - try await pausedState.vm.resume() - state = .started(.init(pausedState)) - } - } - /// Send a signal to the container. public func kill(_ signal: Int32) async throws { try await self.state.withLock { diff --git a/Sources/Containerization/LinuxPod.swift b/Sources/Containerization/LinuxPod.swift index 8ea42a04..1fddc682 100644 --- a/Sources/Containerization/LinuxPod.swift +++ b/Sources/Containerization/LinuxPod.swift @@ -532,22 +532,6 @@ extension LinuxPod { } } - /// Pause the pod's VM. - public func pause() async throws { - try await self.state.withLock { state in - let createdState = try state.phase.createdState("pause") - try await createdState.vm.pause() - } - } - - /// Resume the pod's VM. - public func resume() async throws { - try await self.state.withLock { state in - let createdState = try state.phase.createdState("resume") - try await createdState.vm.resume() - } - } - /// Send a signal to a container. public func killContainer(_ containerID: String, signal: Int32) async throws { try await self.state.withLock { state in diff --git a/Sources/Containerization/VZVirtualMachineInstance.swift b/Sources/Containerization/VZVirtualMachineInstance.swift index e98a244e..8b2850eb 100644 --- a/Sources/Containerization/VZVirtualMachineInstance.swift +++ b/Sources/Containerization/VZVirtualMachineInstance.swift @@ -154,6 +154,9 @@ extension VZVirtualMachineInstance: VirtualMachineInstance { } } + // NOTE: Investigate what is the "right" way to handle already vended vsock + // connections for pause and resume. + func pause() async throws { try await lock.withLock { _ in await self.timeSyncer.pause() diff --git a/Sources/Integration/ContainerTests.swift b/Sources/Integration/ContainerTests.swift index 4d42f6a4..2514e6b9 100644 --- a/Sources/Integration/ContainerTests.swift +++ b/Sources/Integration/ContainerTests.swift @@ -558,94 +558,6 @@ extension IntegrationSuite { } } - func testPauseResume() async throws { - let id = "test-pause-resume" - - let bs = try await bootstrap(id) - let container = try LinuxContainer(id, rootfs: bs.rootfs, vmm: bs.vmm) { config in - config.process.arguments = ["sleep", "infinity"] - config.bootlog = bs.bootlog - } - - try await container.create() - try await container.start() - - // Very simple test of can we perform actions on the container after pause/resume. - try await container.pause() - try await Task.sleep(for: .milliseconds(500)) - try await container.resume() - - try await container.kill(SIGKILL) - try await container.wait() - try await container.stop() - } - - func testPauseResumeWait() async throws { - let id = "test-pause-resume-wait" - - let bs = try await bootstrap(id) - let container = try LinuxContainer(id, rootfs: bs.rootfs, vmm: bs.vmm) { config in - config.process.arguments = ["sleep", "2"] - config.bootlog = bs.bootlog - } - - try await container.create() - try await container.start() - - let t = Task { - try await container.wait(timeoutInSeconds: 5) - } - - try await Task.sleep(for: .milliseconds(25)) - - try await container.pause() - try await Task.sleep(for: .milliseconds(500)) - try await container.resume() - - let status = try await t.value - - guard status.exitCode == 0 else { - throw IntegrationError.assert(msg: "process status \(status) != 0") - } - - try await container.stop() - } - - func testPauseResumeIO() async throws { - let id = "test-pause-resume-io" - - let bs = try await bootstrap(id) - let buffer = BufferWriter() - let container = try LinuxContainer(id, rootfs: bs.rootfs, vmm: bs.vmm) { config in - config.process.arguments = ["ping", "-c", "5", "localhost"] - config.process.stdout = buffer - config.bootlog = bs.bootlog - } - - try await container.create() - try await container.start() - - try await container.pause() - try await Task.sleep(for: .seconds(2)) - try await container.resume() - - try await container.wait() - - guard let str = String(data: buffer.data, encoding: .utf8) else { - throw IntegrationError.assert(msg: "failed to convert stdout to utf8") - } - - // Should be 10 lines long. 5 of "filler" and 5 of actual - // output, however one of the lines is a blank newline. - let expectedLines = 9 - let lines = str.split(separator: "\n") - guard lines.count == expectedLines else { - throw IntegrationError.assert(msg: "expected \(expectedLines), got \(lines.count)") - } - - try await container.stop() - } - func testNestedVirtualizationEnabled() async throws { let id = "test-nested-virt" diff --git a/Sources/Integration/PodTests.swift b/Sources/Integration/PodTests.swift index f979dc95..aa452d1b 100644 --- a/Sources/Integration/PodTests.swift +++ b/Sources/Integration/PodTests.swift @@ -243,33 +243,6 @@ extension IntegrationSuite { } } - func testPodPauseResume() async throws { - let id = "test-pod-pause-resume" - - let bs = try await bootstrap(id) - let pod = try LinuxPod(id, vmm: bs.vmm) { config in - config.cpus = 4 - config.memoryInBytes = 1024.mib() - config.bootlog = bs.bootlog - } - - try await pod.addContainer("container1", rootfs: bs.rootfs) { config in - config.process.arguments = ["/bin/sleep", "infinity"] - } - - try await pod.create() - try await pod.startContainer("container1") - - // Test pause/resume - try await pod.pause() - try await Task.sleep(for: .milliseconds(500)) - try await pod.resume() - - try await pod.killContainer("container1", signal: SIGKILL) - try await pod.waitContainer("container1") - try await pod.stop() - } - func testPodStopContainerIdempotency() async throws { let id = "test-pod-stop-container-idempotency" diff --git a/Sources/Integration/Suite.swift b/Sources/Integration/Suite.swift index e916350a..b0b71106 100644 --- a/Sources/Integration/Suite.swift +++ b/Sources/Integration/Suite.swift @@ -282,9 +282,6 @@ struct IntegrationSuite: AsyncParsableCommand { Test("container hostname", testHostname), Test("container hosts", testHostsFile), Test("container mount", testMounts), - Test("container pause and resume", testPauseResume), - Test("container pause, resume and wait", testPauseResumeWait), - Test("container pause, resume and verify io", testPauseResumeIO), Test("nested virt", testNestedVirtualizationEnabled), Test("container manager", testContainerManagerCreate), Test("container reuse", testContainerReuse), @@ -300,7 +297,6 @@ struct IntegrationSuite: AsyncParsableCommand { Test("pod concurrent containers", testPodConcurrentContainers), Test("pod exec in container", testPodExecInContainer), Test("pod container hostname", testPodContainerHostname), - Test("pod pause resume", testPodPauseResume), Test("pod stop container idempotency", testPodStopContainerIdempotency), Test("pod list containers", testPodListContainers), Test("pod container statistics", testPodContainerStatistics),