VZVirtualMachineInstance: Adjust silent success behavior of nested virt (#88)

Fixes #85

The virtualization bool on LinuxContainer mostly just forwards to
VZVirtualMachineInstance which today would silently take your boolean
and do nothing if the underlying platform doesn't have support for it.
This is (to me) arguably worse than erroring, as it gives the client a
false security that the setting is on, and they should have virt
capabilities in the container/guest now.

This change makes it so that we throw a ContainerizationError for this
case, with a code of .unsupported so it's checkable by a user if they
want more information on the "why".
This commit is contained in:
Danny Canter
2025-06-11 11:39:39 -04:00
committed by GitHub
parent bc1032e218
commit 7320f8360e
3 changed files with 39 additions and 10 deletions
@@ -294,16 +294,18 @@ extension VZVirtualMachineInstance.Configuration {
try mount.configure(config: &config)
}
#if arch(arm64)
let platform = VZGenericPlatformConfiguration()
if VZGenericPlatformConfiguration.isNestedVirtualizationSupported {
platform.isNestedVirtualizationEnabled = self.nestedVirtualization
// We shouldn't silently succeed if the user asked for virt and their hardware does
// not support it.
if !VZGenericPlatformConfiguration.isNestedVirtualizationSupported && self.nestedVirtualization {
throw ContainerizationError(
.unsupported,
message: "nested virtualization is not supported on the platform"
)
}
platform.isNestedVirtualizationEnabled = self.nestedVirtualization
config.platform = platform
#endif
try config.validate()
return config
}
+20 -2
View File
@@ -37,6 +37,14 @@ enum IntegrationError: Swift.Error {
case noOutput
}
struct SkipTest: Swift.Error, CustomStringConvertible {
let reason: String
var description: String {
reason
}
}
@main
struct IntegrationSuite: AsyncParsableCommand {
static let appRoot: URL = {
@@ -209,6 +217,7 @@ struct IntegrationSuite: AsyncParsableCommand {
]
var passed = 0
var skipped = 0
for (name, test) in tests {
do {
log.info("test \(name) started...")
@@ -218,15 +227,24 @@ struct IntegrationSuite: AsyncParsableCommand {
let lasted = CFAbsoluteTimeGetCurrent() - started
log.info("✅ test \(name) complete in \(lasted)s.")
passed += 1
} catch let err as SkipTest {
log.info("⏭️ skipped test: \(err)")
skipped += 1
} catch {
log.error("❌ test \(name) failed: \(error)")
}
}
let ended = CFAbsoluteTimeGetCurrent() - suiteStarted
log.info("\nintegration suite completed in \(ended)s with \(passed)/\(tests.count) passed!")
var finishingText = "\n\nIntegration suite completed in \(ended)s with \(passed)/\(tests.count) passed"
if skipped > 0 {
finishingText += " and \(skipped)/\(tests.count) skipped"
}
finishingText += "!"
if passed < tests.count {
log.info("\(finishingText)")
if passed + skipped < tests.count {
log.error("")
throw ExitCode(1)
}
+11 -2
View File
@@ -17,6 +17,7 @@
import ArgumentParser
import Containerization
import ContainerizationError
import ContainerizationOCI
import Foundation
import Logging
@@ -69,8 +70,16 @@ extension IntegrationSuite {
container.virtualization = true
try await container.create()
try await container.start()
do {
try await container.create()
try await container.start()
} catch {
if let err = error as? ContainerizationError {
if err.code == .unsupported {
throw SkipTest(reason: err.message)
}
}
}
let status = try await container.wait()
try await container.stop()