//===----------------------------------------------------------------------===// // Copyright © 2025-2026 Apple Inc. and the Containerization project authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //===----------------------------------------------------------------------===// #if os(macOS) import ContainerizationError import ContainerizationOCI import Foundation import Logging import NIOCore /// A virtualization.framework backed `VirtualMachineManager` implementation. public struct VZVirtualMachineManager: VirtualMachineManager { private let kernel: Kernel private let initialFilesystem: Mount private let rosetta: Bool private let nestedVirtualization: Bool private let group: EventLoopGroup? private let logger: Logger? public init( kernel: Kernel, initialFilesystem: Mount, rosetta: Bool = false, nestedVirtualization: Bool = false, group: EventLoopGroup? = nil, logger: Logger? = nil ) { self.kernel = kernel self.initialFilesystem = initialFilesystem self.rosetta = rosetta self.nestedVirtualization = nestedVirtualization self.group = group self.logger = logger } public func create(config: some VMCreationConfig) throws -> any VirtualMachineInstance { let vmConfig = config.configuration // Use nested virtualization if requested in config or set as default in manager let useNestedVirtualization = vmConfig.nestedVirtualization || self.nestedVirtualization // Clamp to system RAM as Virtualization.framework bounds us to this. let memoryInBytes = min(vmConfig.memoryInBytes, ProcessInfo.processInfo.physicalMemory) // Clamp to system CPU count as Virtualization.framework bounds us to this. let cpus = min(vmConfig.cpus, ProcessInfo.processInfo.activeProcessorCount) return try VZVirtualMachineInstance( group: self.group, logger: self.logger, with: { instanceConfig in instanceConfig.cpus = cpus instanceConfig.memoryInBytes = memoryInBytes instanceConfig.kernel = self.kernel instanceConfig.initialFilesystem = self.initialFilesystem if let bootLog = vmConfig.bootLog { instanceConfig.bootLog = bootLog } instanceConfig.interfaces = vmConfig.interfaces instanceConfig.rosetta = self.rosetta instanceConfig.nestedVirtualization = useNestedVirtualization instanceConfig.mountsByID = vmConfig.mountsByID instanceConfig.extensions = vmConfig.extensions }) } } #endif