Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added a few of APIs for mac guest #93

Merged
merged 3 commits into from
Oct 30, 2022
Merged
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
38 changes: 37 additions & 1 deletion example/macOS/installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,26 @@ package main
import (
"context"
"fmt"
"os"
"time"

"github.com/Code-Hex/vz/v2"
)

func installMacOS(ctx context.Context) error {
if err := CreateVMBundle(); err != nil {
return fmt.Errorf("failed to VM.bundle in home directory: %w", err)
}

restoreImagePath := GetRestoreImagePath()
if _, err := os.Stat(restoreImagePath); err != nil {
if !os.IsNotExist(err) {
return err
}
if err := downloadRestoreImage(ctx, restoreImagePath); err != nil {
return fmt.Errorf("failed to download restore image: %w", err)
}
}
restoreImage, err := vz.LoadMacOSRestoreImageFromPath(restoreImagePath)
if err != nil {
return fmt.Errorf("failed to load restore image: %w", err)
Expand Down Expand Up @@ -46,7 +59,7 @@ func installMacOS(ctx context.Context) error {
fmt.Println("install has been completed")
return
case <-ticker.C:
fmt.Printf("install: %d\r", int(installer.FractionCompleted()*100))
fmt.Printf("install: %.3f%%\r", installer.FractionCompleted()*100)
}
}
}()
Expand Down Expand Up @@ -95,3 +108,26 @@ func createMacInstallerPlatformConfiguration(macOSConfiguration *vz.MacOSConfigu
vz.WithMachineIdentifier(machineIdentifier),
)
}

func downloadRestoreImage(ctx context.Context, destPath string) error {
progress, err := vz.FetchLatestSupportedMacOSRestoreImage(ctx, destPath)
if err != nil {
return err
}

fmt.Printf("download restore image in %q\n", destPath)
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
fmt.Println("download has been cancelled")
return ctx.Err()
case <-progress.Finished():
fmt.Println("download has been completed")
return progress.Err()
case <-ticker.C:
fmt.Printf("download: %.3f%%\r", progress.FractionCompleted()*100)
}
}
}
16 changes: 8 additions & 8 deletions example/macOS/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,6 @@ func createNetworkDeviceConfiguration() (*vz.VirtioNetworkDeviceConfiguration, e
return vz.NewVirtioNetworkDeviceConfiguration(natAttachment)
}

func createPointingDeviceConfiguration() (*vz.USBScreenCoordinatePointingDeviceConfiguration, error) {
return vz.NewUSBScreenCoordinatePointingDeviceConfiguration()
}

func createKeyboardConfiguration() (*vz.USBKeyboardConfiguration, error) {
return vz.NewUSBKeyboardConfiguration()
}
Expand Down Expand Up @@ -262,13 +258,17 @@ func setupVMConfiguration(platformConfig vz.PlatformConfiguration) (*vz.VirtualM
networkDeviceConfig,
})

pointingDeviceConfig, err := createPointingDeviceConfiguration()
usbScreenPointingDevice, err := vz.NewUSBScreenCoordinatePointingDeviceConfiguration()
if err != nil {
return nil, fmt.Errorf("failed to create pointing device configuration: %w", err)
}
config.SetPointingDevicesVirtualMachineConfiguration([]vz.PointingDeviceConfiguration{
pointingDeviceConfig,
})
pointingDevices := []vz.PointingDeviceConfiguration{usbScreenPointingDevice}

trackpad, err := vz.NewMacTrackpadConfiguration()
if err == nil {
pointingDevices = append(pointingDevices, trackpad)
}
config.SetPointingDevicesVirtualMachineConfiguration(pointingDevices)

keyboardDeviceConfig, err := createKeyboardConfiguration()
if err != nil {
Expand Down
49 changes: 49 additions & 0 deletions pointing_device_arm64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//go:build darwin && arm64
// +build darwin,arm64

package vz

/*
#cgo darwin CFLAGS: -x objective-c -fno-objc-arc
#cgo darwin LDFLAGS: -lobjc -framework Foundation -framework Virtualization
# include "virtualization_13_arm64.h"
*/
import "C"
import "runtime"

// MacTrackpadConfiguration is a struct that defines the configuration
// for a Mac trackpad.
//
// This device is only recognized by virtual machines running macOS 13.0 and later.
// In order to support both macOS 13.0 and earlier guests, VirtualMachineConfiguration.pointingDevices
// can be set to an array containing both a MacTrackpadConfiguration and
// a USBScreenCoordinatePointingDeviceConfiguration object. macOS 13.0 and later guests will use
// the multi-touch trackpad device, while earlier versions of macOS will use the USB pointing device.
//
// see: https://developer.apple.com/documentation/virtualization/vzmactrackpadconfiguration?language=objc
type MacTrackpadConfiguration struct {
pointer

*basePointingDeviceConfiguration
}

var _ PointingDeviceConfiguration = (*MacTrackpadConfiguration)(nil)

// NewMacTrackpadConfiguration creates a new MacTrackpadConfiguration.
//
// This is only supported on macOS 13 and newer, ErrUnsupportedOSVersion will
// be returned on older versions.
func NewMacTrackpadConfiguration() (*MacTrackpadConfiguration, error) {
if macosMajorVersionLessThan(13) {
return nil, ErrUnsupportedOSVersion
}
config := &MacTrackpadConfiguration{
pointer: pointer{
ptr: C.newVZMacTrackpadConfiguration(),
},
}
runtime.SetFinalizer(config, func(self *MacTrackpadConfiguration) {
self.Release()
})
return config, nil
}
13 changes: 13 additions & 0 deletions shared_directory.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,16 @@ func NewMultipleDirectoryShare(shares map[string]*SharedDirectory) (*MultipleDir
})
return config, nil
}

// MacOSGuestAutomountTag returns the macOS automount tag.
//
// A device configured with this tag will be automatically mounted in a macOS guest.
// This is only supported on macOS 13 and newer, ErrUnsupportedOSVersion will
// be returned on older versions.
func MacOSGuestAutomountTag() (string, error) {
if macosMajorVersionLessThan(13) {
return "", ErrUnsupportedOSVersion
}
cstring := (*char)(C.getMacOSGuestAutomountTag())
return cstring.String(), nil
}
4 changes: 3 additions & 1 deletion virtualization_13.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,6 @@ void *newVZSpiceAgentPortAttachment();
void setSharesClipboardVZSpiceAgentPortAttachment(void *attachment, bool sharesClipboard);
const char *getSpiceAgentPortName();

void startWithOptionsCompletionHandler(void *machine, void *queue, void *options, void *completionHandler);
void startWithOptionsCompletionHandler(void *machine, void *queue, void *options, void *completionHandler);

const char *getMacOSGuestAutomountTag();
14 changes: 14 additions & 0 deletions virtualization_13.m
Original file line number Diff line number Diff line change
Expand Up @@ -438,4 +438,18 @@ void startWithOptionsCompletionHandler(void *machine, void *queue, void *options
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}

/*!
@abstract The macOS automount tag.
@discussion A device configured with this tag will be automatically mounted in a macOS guest.
*/
const char *getMacOSGuestAutomountTag()
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
return [[VZVirtioFileSystemDeviceConfiguration macOSGuestAutomountTag] UTF8String];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
2 changes: 2 additions & 0 deletions virtualization_13_arm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ int availabilityVZLinuxRosettaDirectoryShare();

void *newVZMacOSVirtualMachineStartOptions(bool startUpFromMacOSRecovery);

void *newVZMacTrackpadConfiguration();

#endif
19 changes: 19 additions & 0 deletions virtualization_13_arm64.m
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,22 @@ int availabilityVZLinuxRosettaDirectoryShare()
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}

/*!
@abstract Configuration for a Mac trackpad.
@discussion
This device can be used by VZVirtualMachineView to send pointer events and multi-touch trackpad gestures to the virtual machine.
Note: this device is only recognized by virtual machines running macOS 13.0 and later. In order to support both macOS 13.0 and earlier
guests, VZVirtualMachineConfiguration.pointingDevices can be set to an array containing both a VZMacTrackpadConfiguration and
a VZUSBScreenCoordinatePointingDeviceConfiguration object. macOS 13.0 and later guests will use the multi-touch trackpad device,
while earlier versions of macOS will use the USB pointing device.
*/
void *newVZMacTrackpadConfiguration()
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
return [[VZMacTrackpadConfiguration alloc] init];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
3 changes: 0 additions & 3 deletions virtualization_arm64.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,6 @@ func NewMacAuxiliaryStorage(storagePath string, opts ...NewMacAuxiliaryStorageOp
if macosMajorVersionLessThan(12) {
return nil, ErrUnsupportedOSVersion
}
if _, err := os.Stat(storagePath); err != nil {
return nil, err
}

storage := &MacAuxiliaryStorage{storagePath: storagePath}
for _, opt := range opts {
Expand Down