Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2026 System Services

WWDC26 · 20 min · System Services

Expand the capabilities of your Virtualization app

Bring powerful new capabilities in macOS 27 to your Virtualization app. Discover how to automate the setup of macOS guests through user account setup on first boot. We’ll explore advanced workflows that involve passthrough of USB accessories to virtual machines, as well as custom network topologies and port forwarding. You’ll also learn about recent improvements that can enrich the experience of running your app’s virtual machines.

Watch at developer.apple.com ↗

Transcript all transcripts

Chapters

Code shown on screen · 8 snippets

Provision a macOS guest swift · at 1:57 ↗
import Virtualization

let provisioningOptions = VZMacGuestProvisioningOptions()
provisioningOptions.fullName = fullName
provisioningOptions.username = username
provisioningOptions.password = password
provisioningOptions.logsInAutomatically = true
provisioningOptions.enablesRemoteLogin = true

let startOptions = VZMacOSVirtualMachineStartOptions()
try startOptions.setGuestProvisioning(provisioningOptions)

try await virtualMachine.start(options: startOptions)
Register an Accessory Access listener swift · at 7:12 ↗
import AccessoryAccess

let criteria: [AAUSBAccessoryMatchingCriteria] = []
let accessories = try await AAUSBAccessoryManager.shared.registerListener(self, matchingCriteria: criteria)

for accessory in accessories {
    // Handle previously attached accessories.
}
Respond to USB accessory connection swift · at 7:39 ↗
import AccessoryAccess
import Virtualization

class AccessoryListener: NSObject, AAUSBAccessoryListener {
    func usbAccessoryDidConnect(_ usbAccessory: AAUSBAccessory) {
        virtualMachine.queue.async {
            do {
                let configuration = VZUSBPassthroughDeviceConfiguration(device: usbAccessory)
                let device = try VZUSBPassthroughDevice(configuration: configuration)
                self.virtualMachine.usbControllers.first?.attach(device: device) { error in
                    // Handle error if necessary...
                }
            } catch {
                // Handle error...
            }
        }
    }
}
Create a custom vmnet network swift · at 10:04 ↗
import Virtualization
import vmnet

var status: vmnet_return_t = .VMNET_FAILURE
guard let networkConfiguration =
    vmnet_network_configuration_create(.VMNET_SHARED_MODE, &status) else { ... }

guard let network =
    vmnet_network_create(networkConfiguration, &status) else { ... }

let attachment = VZVmnetNetworkDeviceAttachment(network: network)

let networkDeviceConfiguration = VZVirtioNetworkDeviceConfiguration()
networkDeviceConfiguration.attachment = attachment

virtualMachineConfiguration.networkDevices = [networkDeviceConfiguration]

let virtualMachine = VZVirtualMachine(configuration: virtualMachineConfiguration)
Use DiskImageKit with Virtualization swift · at 14:54 ↗
import DiskImageKit
import Virtualization

let baseImage = try DiskImage(opening: .open(url: baseLayerURL, mode: .readOnly))
let cacheImage = try baseImage.appending(.asifLayer(url: cacheLayerURL, type: .cache))
let overlayImage = try DiskImage(opening: .open(url: overlayLayerURL))
let stackedImage = try cacheImage.appending(overlayImage)

let storageDeviceAttachment = try VZDiskImageStorageDeviceAttachment(diskImage: stackedImage)

let storageDeviceConfiguration =
    VZVirtioBlockDeviceConfiguration(attachment: storageDeviceAttachment)

virtualMachineConfiguration.storageDevices = [storageDeviceConfiguration]

let virtualMachine = VZVirtualMachine(configuration: virtualMachineConfiguration)
Configure a custom Virtio device swift · at 17:41 ↗
import Virtualization

let deviceConfiguration = VZCustomVirtioDeviceConfiguration()

// Virtio entropy device.
deviceConfiguration.deviceID = 4
// PCI class for crypto devices.
deviceConfiguration.pciClassID = 0x10
// PCI subclass for network and computing encryption controllers.
deviceConfiguration.pciSubclassID = 0x00
// An entropy device uses a single Virtio queue.
deviceConfiguration.virtioQueueCount = 1

deviceConfiguration.provider =
    VZCustomVirtioDeviceDelegateProvider(deviceQueue: deviceQueue, delegate: provider)

virtualMachineConfiguration.customVirtioDevices = [deviceConfiguration]

let virtualMachine = VZVirtualMachine(configuration: virtualMachineConfiguration)
Attach a delegate to a VZCustomVirtioDevice swift · at 18:20 ↗
import Virtualization

class DeviceConfigurationDelegate: NSObject, VZCustomVirtioDeviceConfigurationDelegate {
    func customVirtioConfiguration(_ deviceConfiguration: VZCustomVirtioDeviceConfiguration,
                                   didCreateDevice device: VZCustomVirtioDevice) {
        device.delegate = deviceDelegate
        self.device = device
    }
}
Process Virtio queue elements swift · at 18:42 ↗
import Virtualization

class DeviceDelegate: NSObject, VZCustomVirtioDeviceDelegate {
    func customVirtioDevice(_ device: VZCustomVirtioDevice,
                            didReceiveNotificationFor queue: VZVirtioQueue) {
        while let element = queue.nextElement() {
            // Process element...
            element.returnToQueue()
        }
    }
}

Resources