Allow setting log level for vminitd (#772)

The `--log-level` option when running the agent sub-command for vminitd
was being silently ignored cause of the way the agent is being run. As a
workaround we need to read `/proc/self/cmdline` to get the right args
This commit is contained in:
Aditya Ramani authored and GitHub committed 2026-06-16 18:04:31 -07:00
1 parent 7e2ae5a170
commit d55cc188ce
6 files changed
+133 -48

No files matched your search

+6
View File
@@ -15,6 +15,7 @@
//===----------------------------------------------------------------------===//
import Foundation
import Logging
/// An object representing a Linux kernel used to boot a virtual machine.
/// In addition to a path to the kernel itself, this type stores relevant
@@ -37,6 +38,11 @@ public struct Kernel: Sendable, Codable {
self.kernelArgs.append("panic=\(level)")
}
// Sets the log level for the Agent
mutating public func setAgentLogLevel(level: Logger.Level) {
self.initArgs.append(contentsOf: ["--log-level", level.description])
}
/// Additional kernel arguments.
public var kernelArgs: [String]
/// Additional arguments passed to the Initial Process / Agent.
@@ -17,6 +17,7 @@
//
import Foundation
import Logging
import Testing
@testable import Containerization
@@ -55,4 +56,38 @@ final class KernelTests {
#expect(commandLine.kernelArgs == ["console=hvc0", "debug", "panic=10"])
}
@Test func setAgentLogLevelAppendsFlagAndValue() {
var commandLine = Kernel.CommandLine(initArgs: [])
commandLine.setAgentLogLevel(level: .debug)
#expect(commandLine.initArgs == ["--log-level", "debug"])
}
@Test(arguments: [
(Logger.Level.trace, "trace"),
(.debug, "debug"),
(.info, "info"),
(.notice, "notice"),
(.warning, "warning"),
(.error, "error"),
(.critical, "critical"),
])
func setAgentLogLevelForEachLevel(level: Logger.Level, expected: String) {
var commandLine = Kernel.CommandLine(initArgs: [])
commandLine.setAgentLogLevel(level: level)
#expect(commandLine.initArgs == ["--log-level", expected])
}
@Test func setAgentLogLevelPreservesExistingInitArgs() {
var commandLine = Kernel.CommandLine(initArgs: ["--verbose"])
commandLine.setAgentLogLevel(level: .info)
#expect(commandLine.initArgs == ["--verbose", "--log-level", "info"])
}
@Test func setAgentLogLevelDoesNotAffectKernelArgs() {
var commandLine = Kernel.CommandLine(debug: true, panic: 0, initArgs: [])
let kernelArgsBefore = commandLine.kernelArgs
commandLine.setAgentLogLevel(level: .warning)
#expect(commandLine.kernelArgs == kernelArgsBefore)
}
}
+72 -45
View File
@@ -1,13 +1,13 @@
{
"originHash" : "5de11e9b526f881c570e7b65cb339765f3aa79e8646a0c1289d36f224f9f8ca0",
"originHash" : "f9b523ded39c0fa3565fd16d3b4097384449d541048751be7efee4a43af79fd4",
"pins" : [
{
"identity" : "async-http-client",
"kind" : "remoteSourceControl",
"location" : "https://github.com/swift-server/async-http-client.git",
"state" : {
"revision" : "b2faff932b956df50668241d14f1b42f7bae12b4",
"version" : "1.30.0"
"revision" : "7744c2a035c68ec14726c709f031835e3e30bde1",
"version" : "1.34.0"
}
},
{
@@ -15,17 +15,35 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/containerization.git",
"state" : {
"revision" : "636eef0eff00e451de6d5d426e6a6785b90b44e2",
"version" : "0.26.5"
"revision" : "9275f365dd555c8f072e7d250d809f5eb7bdd746",
"version" : "0.33.4"
}
},
{
"identity" : "grpc-swift",
"identity" : "grpc-swift-2",
"kind" : "remoteSourceControl",
"location" : "https://github.com/grpc/grpc-swift.git",
"location" : "https://github.com/grpc/grpc-swift-2.git",
"state" : {
"revision" : "f857994e146f5146d702e9c31ac6f3c27d55d18a",
"version" : "1.27.0"
"revision" : "21fe69ab7ce0e87ac089534733c52f037e74a3eb",
"version" : "2.4.1"
}
},
{
"identity" : "grpc-swift-nio-transport",
"kind" : "remoteSourceControl",
"location" : "https://github.com/grpc/grpc-swift-nio-transport.git",
"state" : {
"revision" : "e7d463749f9037b047dcd6da4e633718ddc432b8",
"version" : "2.8.0"
}
},
{
"identity" : "grpc-swift-protobuf",
"kind" : "remoteSourceControl",
"location" : "https://github.com/grpc/grpc-swift-protobuf.git",
"state" : {
"revision" : "b05885fa9bdd88f1eab2e7162f1ee81340b0da33",
"version" : "2.4.0"
}
},
{
@@ -42,8 +60,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-argument-parser.git",
"state" : {
"revision" : "cdd0ef3755280949551dc26dee5de9ddeda89f54",
"version" : "1.6.2"
"revision" : "6a52f3251125d74daf04fcbd5e6f08a75d074382",
"version" : "1.8.2"
}
},
{
@@ -51,8 +69,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-asn1.git",
"state" : {
"revision" : "40d25bbb2fc5b557a9aa8512210bded327c0f60d",
"version" : "1.5.0"
"revision" : "a9a5efd40eaf558a2bcd48d64b1d1646be686008",
"version" : "1.7.1"
}
},
{
@@ -60,8 +78,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-async-algorithms.git",
"state" : {
"revision" : "042e1c4d9d19748c9c228f8d4ebc97bb1e339b0b",
"version" : "1.0.4"
"revision" : "d0b4a06d0f173a2f3be27d3ea21b3c3aa18db440",
"version" : "1.1.4"
}
},
{
@@ -78,8 +96,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-certificates.git",
"state" : {
"revision" : "c399f90e7bbe8874f6cbfda1d5f9023d1f5ce122",
"version" : "1.15.1"
"revision" : "bde8ca32a096825dfce37467137c903418c1893d",
"version" : "1.19.1"
}
},
{
@@ -87,8 +105,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-collections.git",
"state" : {
"revision" : "7b847a3b7008b2dc2f47ca3110d8c782fb2e5c7e",
"version" : "1.3.0"
"revision" : "a0cb0954ecb21e4e31b0070e6ed5674e8556685a",
"version" : "1.6.0"
}
},
{
"identity" : "swift-configuration",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-configuration.git",
"state" : {
"revision" : "be76c4ad929eb6c4bcaf3351799f2adf9e6848a9",
"version" : "1.2.0"
}
},
{
@@ -105,8 +132,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-distributed-tracing.git",
"state" : {
"revision" : "baa932c1336f7894145cbaafcd34ce2dd0b77c97",
"version" : "1.3.1"
"revision" : "dc4030184203ffafbb2ec614352487235d747fe0",
"version" : "1.4.1"
}
},
{
@@ -114,8 +141,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-http-structured-headers.git",
"state" : {
"revision" : "76d7627bd88b47bf5a0f8497dd244885960dde0b",
"version" : "1.6.0"
"revision" : "933538faa42c432d385f02e07df0ace7c5ecfc47",
"version" : "1.7.0"
}
},
{
@@ -123,8 +150,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-http-types.git",
"state" : {
"revision" : "45eb0224913ea070ec4fba17291b9e7ecf4749ca",
"version" : "1.5.1"
"revision" : "db774a277f60063a32d854f2980299caf06da041",
"version" : "1.6.0"
}
},
{
@@ -132,8 +159,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-log.git",
"state" : {
"revision" : "ce592ae52f982c847a4efc0dd881cc9eb32d29f2",
"version" : "1.6.4"
"revision" : "92448c359f00ebe36ae97d3bd9086f13c7692b5a",
"version" : "1.13.2"
}
},
{
@@ -141,8 +168,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio.git",
"state" : {
"revision" : "56724a2b6d8e2aed1b2c5f23865b9ea5c43f9977",
"version" : "2.89.0"
"revision" : "77b84ac2cd2ac9e4ac67d19f045fd5b434f56967",
"version" : "2.101.0"
}
},
{
@@ -150,8 +177,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio-extras.git",
"state" : {
"revision" : "7ee281d816fa8e5f3967a2c294035a318ea551c7",
"version" : "1.31.0"
"revision" : "d2eeec0339074034f11a040a74aa2a341a2c4506",
"version" : "1.34.1"
}
},
{
@@ -159,8 +186,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio-http2.git",
"state" : {
"revision" : "c2ba4cfbb83f307c66f5a6df6bb43e3c88dfbf80",
"version" : "1.39.0"
"revision" : "61d1b44f6e4e118792be1cff88ee2bc0267c6f9a",
"version" : "1.44.0"
}
},
{
@@ -168,8 +195,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio-ssl.git",
"state" : {
"revision" : "173cc69a058623525a58ae6710e2f5727c663793",
"version" : "2.36.0"
"revision" : "407d82d5b6cc00e1c3fb83a81b1539b70c788c5e",
"version" : "2.37.1"
}
},
{
@@ -177,8 +204,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio-transport-services.git",
"state" : {
"revision" : "df6c28355051c72c884574a6c858bc54f7311ff9",
"version" : "1.25.2"
"revision" : "67787bb645a5e67d2edcdfbe48a216cc549222d5",
"version" : "1.28.0"
}
},
{
@@ -195,8 +222,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-protobuf.git",
"state" : {
"revision" : "c169a5744230951031770e27e475ff6eefe51f9d",
"version" : "1.33.3"
"revision" : "f6506eaa86ed2e01cb0ae14a75035b7fdbf0918f",
"version" : "1.38.0"
}
},
{
@@ -204,8 +231,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-service-context.git",
"state" : {
"revision" : "1983448fefc717a2bc2ebde5490fe99873c5b8a6",
"version" : "1.2.1"
"revision" : "d0997351b0c7779017f88e7a93bc30a1878d7f29",
"version" : "1.3.0"
}
},
{
@@ -213,8 +240,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/swift-server/swift-service-lifecycle.git",
"state" : {
"revision" : "1de37290c0ab3c5a96028e0f02911b672fd42348",
"version" : "2.9.1"
"revision" : "9829955b385e5bb88128b73f1b8389e9b9c3191a",
"version" : "2.11.0"
}
},
{
@@ -222,8 +249,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-system.git",
"state" : {
"revision" : "395a77f0aa927f0ff73941d7ac35f2b46d47c9db",
"version" : "1.6.3"
"revision" : "7502b711c92a17741fa625d722b0ccbd595d8ed1",
"version" : "1.7.2"
}
},
{
+1 -1
View File
@@ -17,7 +17,7 @@
import PackageDescription
let scVersion = "0.26.5"
let scVersion = "0.33.4"
let package = Package(
name: "ctr-example",
+5 -1
View File
@@ -23,10 +23,14 @@ import Synchronization
public struct LogLevelOption: ParsableArguments {
@Option(name: .long, help: "Set the log level (trace, debug, info, notice, warning, error, critical)")
var logLevel: String = "info"
public var logLevel: String = "info"
public init() {}
public init(logLevel: String) {
self.logLevel = logLevel
}
public func resolvedLogLevel() -> Logger.Level {
switch logLevel.lowercased() {
case "trace":
+14 -1
View File
@@ -51,7 +51,9 @@ struct Application: AsyncParsableCommand {
// so we do this synchronously before any async code runs.
try mountProc()
var command = try parseAsRoot()
// When running as PID 1 with a Musl-static build, Swift's runtime
// captures argc/argv as empty. Recover argv from /proc/self/cmdline.
var command = try parseAsRoot(Self.procSelfArgv())
if let asyncCommand = command as? AsyncParsableCommand {
nonisolated(unsafe) var unsafeCommand = asyncCommand
try await unsafeCommand.run()
@@ -85,6 +87,17 @@ struct Application: AsyncParsableCommand {
try mnt.mount(createWithPerms: 0o755)
}
// /proc/self/cmdline holds argv as NUL-separated bytes. Read it after
// mountProc(). Returns argv minus argv[0], suitable for parseAsRoot(_:).
private static func procSelfArgv() -> [String] {
guard let data = try? Data(contentsOf: URL(fileURLWithPath: "/proc/self/cmdline")) else {
return []
}
let parts = data.split(separator: 0, omittingEmptySubsequences: true)
.map { String(decoding: $0, as: UTF8.self) }
return Array(parts.dropFirst())
}
private static func isProcMounted() -> Bool {
guard let data = try? String(contentsOfFile: "/proc/mounts", encoding: .utf8) else {
return false