Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions Sources/Containerization/LinuxContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ public final class LinuxContainer: Container, Sendable {
/// Run the container with a minimal init process that handles signal
/// forwarding and zombie reaping.
public var useInit: Bool = false
/// Enable virtio-gpu device.
public var graphicsDevice: Bool = false
/// Enable graphical output (scanout) for the virtio-gpu device.
public var graphicsDisplay: Bool = false

public init() {}

Expand All @@ -94,7 +98,9 @@ public final class LinuxContainer: Container, Sendable {
virtualization: Bool = false,
bootLog: BootLog? = nil,
ociRuntimePath: String? = nil,
useInit: Bool = false
useInit: Bool = false,
graphicsDevice: Bool = false,
graphicsDisplay: Bool = false
) {
self.process = process
self.cpus = cpus
Expand All @@ -110,6 +116,8 @@ public final class LinuxContainer: Container, Sendable {
self.bootLog = bootLog
self.ociRuntimePath = ociRuntimePath
self.useInit = useInit
self.graphicsDevice = graphicsDevice
self.graphicsDisplay = graphicsDisplay
}
}

Expand Down Expand Up @@ -548,7 +556,9 @@ extension LinuxContainer {
interfaces: self.interfaces,
mountsByID: [self.id: containerMounts],
bootLog: self.config.bootLog,
nestedVirtualization: self.config.virtualization
nestedVirtualization: self.config.virtualization,
graphicsDevice: self.config.graphicsDevice,
graphicsDisplay: self.config.graphicsDisplay
)
let creationConfig = StandardVMConfig(configuration: vmConfig)
let vm = try await self.vmm.create(config: creationConfig)
Expand Down
10 changes: 9 additions & 1 deletion Sources/Containerization/VMConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,20 +80,28 @@ public struct VMConfiguration: Sendable {
/// Enable nested virtualization support. If the VirtualMachineManager
/// does not support this feature, it MUST return an .unsupported ContainerizationError.
public var nestedVirtualization: Bool
/// Enable virtio-gpu device.
public var graphicsDevice: Bool
/// Enable graphical output (scanout) for the virtio-gpu device.
public var graphicsDisplay: Bool

public init(
cpus: Int = 4,
memoryInBytes: UInt64 = 1024 * 1024 * 1024,
interfaces: [any Interface] = [],
mountsByID: [String: [Mount]] = [:],
bootLog: BootLog? = nil,
nestedVirtualization: Bool = false
nestedVirtualization: Bool = false,
graphicsDevice: Bool = false,
graphicsDisplay: Bool = false
) {
self.cpus = cpus
self.memoryInBytes = memoryInBytes
self.interfaces = interfaces
self.mountsByID = mountsByID
self.bootLog = bootLog
self.nestedVirtualization = nestedVirtualization
self.graphicsDevice = graphicsDevice
self.graphicsDisplay = graphicsDisplay
}
}
16 changes: 16 additions & 0 deletions Sources/Containerization/VZVirtualMachineInstance.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ struct VZVirtualMachineInstance: Sendable {
public var initialFilesystem: Mount?
/// Destination for the virtual machine's boot logs.
public var bootLog: BootLog?
/// Enable virtio-gpu device.
public var graphicsDevice: Bool
/// Enable graphical output (scanout) for the virtio-gpu device.
public var graphicsDisplay: Bool

init() {
self.cpus = 4
Expand All @@ -65,6 +69,8 @@ struct VZVirtualMachineInstance: Sendable {
self.nestedVirtualization = false
self.mountsByID = [:]
self.interfaces = []
self.graphicsDevice = false
self.graphicsDisplay = false
}
}

Expand Down Expand Up @@ -392,6 +398,16 @@ extension VZVirtualMachineInstance.Configuration {
}
}

if self.graphicsDevice || self.graphicsDisplay {
let device = VZVirtioGraphicsDeviceConfiguration()
if self.graphicsDisplay {
device.scanouts = [
VZVirtioGraphicsScanoutConfiguration(widthInPixels: 1920, heightInPixels: 1080)
]
}
config.graphicsDevices = [device]
}

let platform = VZGenericPlatformConfiguration()
// We shouldn't silently succeed if the user asked for virt and their hardware does
// not support it.
Expand Down
2 changes: 2 additions & 0 deletions Sources/Containerization/VZVirtualMachineManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ public struct VZVirtualMachineManager: VirtualMachineManager {
instanceConfig.interfaces = vmConfig.interfaces
instanceConfig.rosetta = self.rosetta
instanceConfig.nestedVirtualization = useNestedVirtualization
instanceConfig.graphicsDevice = vmConfig.graphicsDevice
instanceConfig.graphicsDisplay = vmConfig.graphicsDisplay

instanceConfig.mountsByID = vmConfig.mountsByID
})
Expand Down
8 changes: 8 additions & 0 deletions Sources/cctl/RunCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ extension Application {
@Flag(name: .long, help: "Run with an init process for signal forwarding and zombie reaping")
var `init`: Bool = false

@Flag(name: .customLong("graphics-acceleration"), help: "Enable virtio-gpu acceleration")
var graphicsAcceleration: Bool = false

@Flag(name: .customLong("graphics-output"), help: "Enable graphical output (display)")
var graphicsOutput: Bool = false

@Option(
name: [.customLong("kernel"), .customShort("k")], help: "Kernel binary path", completion: .file(),
transform: { str in
Expand Down Expand Up @@ -157,6 +163,8 @@ extension Application {
}

config.useInit = self.`init`
config.graphicsDevice = self.graphicsAcceleration
config.graphicsDisplay = self.graphicsOutput
}

defer {
Expand Down