Skip to content

Commit

Permalink
Merge pull request #117 from balajiv113/disk
Browse files Browse the repository at this point in the history
  • Loading branch information
Code-Hex committed Dec 23, 2022
2 parents 23eeede + a275b82 commit 957dfd2
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 1 deletion.
2 changes: 1 addition & 1 deletion example/gui-linux/main.go
Expand Up @@ -114,7 +114,7 @@ func createMainDiskImage(diskPath string) error {
}

func createBlockDeviceConfiguration(diskPath string) (*vz.VirtioBlockDeviceConfiguration, error) {
attachment, err := vz.NewDiskImageStorageDeviceAttachment(diskPath, false)
attachment, err := vz.NewDiskImageStorageDeviceAttachmentWithCacheAndSync(diskPath, false, vz.DiskImageCachingModeAutomatic, vz.DiskImageSynchronizationModeFsync)
if err != nil {
return nil, fmt.Errorf("failed to create a new disk image storage device attachment: %w", err)
}
Expand Down
4 changes: 4 additions & 0 deletions osversion_test.go
Expand Up @@ -155,6 +155,10 @@ func TestAvailableVersion(t *testing.T) {
"(*VirtualMachine).StartGraphicApplication": func() error {
return (*VirtualMachine)(nil).StartGraphicApplication(0, 0)
},
"NewDiskImageStorageDeviceAttachmentWithCacheAndSync": func() error {
_, err := NewDiskImageStorageDeviceAttachmentWithCacheAndSync("test", false, DiskImageCachingModeAutomatic, DiskImageSynchronizationModeFsync)
return err
},
}
for name, fn := range cases {
t.Run(name, func(t *testing.T) {
Expand Down
65 changes: 65 additions & 0 deletions storage.go
Expand Up @@ -4,6 +4,7 @@ package vz
#cgo darwin CFLAGS: -mmacosx-version-min=11 -x objective-c -fno-objc-arc
#cgo darwin LDFLAGS: -lobjc -framework Foundation -framework Virtualization
# include "virtualization_11.h"
# include "virtualization_12.h"
# include "virtualization_12_3.h"
# include "virtualization_13.h"
*/
Expand Down Expand Up @@ -41,6 +42,28 @@ type DiskImageStorageDeviceAttachment struct {
*baseStorageDeviceAttachment
}

// DiskImageCachingMode describes the disk image caching mode.
//
// see: https://developer.apple.com/documentation/virtualization/vzdiskimagecachingmode?language=objc
type DiskImageCachingMode int

const (
DiskImageCachingModeAutomatic DiskImageCachingMode = iota
DiskImageCachingModeUncached
DiskImageCachingModeCached
)

// DiskImageSynchronizationMode describes the disk image synchronization mode.
//
// see: https://developer.apple.com/documentation/virtualization/vzdiskimagesynchronizationmode?language=objc
type DiskImageSynchronizationMode int

const (
DiskImageSynchronizationModeFull DiskImageSynchronizationMode = 1 + iota
DiskImageSynchronizationModeFsync
DiskImageSynchronizationModeNone
)

// NewDiskImageStorageDeviceAttachment initialize the attachment from a local file path.
// Returns error is not nil, assigned with the error if the initialization failed.
//
Expand Down Expand Up @@ -79,6 +102,48 @@ func NewDiskImageStorageDeviceAttachment(diskPath string, readOnly bool) (*DiskI
return attachment, nil
}

// NewDiskImageStorageDeviceAttachmentWithCacheAndSync initialize the attachment from a local file path.
// Returns error is not nil, assigned with the error if the initialization failed.
//
// - diskPath is local file URL to the disk image in RAW format.
// - readOnly if YES, the device attachment is read-only, otherwise the device can write data to the disk image.
// - cachingMode is one of the available DiskImageCachingMode options.
// - syncMode is to define how the disk image synchronizes with the underlying storage when the guest operating system flushes data, described by one of the available DiskImageSynchronizationMode modes.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewDiskImageStorageDeviceAttachmentWithCacheAndSync(diskPath string, readOnly bool, cachingMode DiskImageCachingMode, syncMode DiskImageSynchronizationMode) (*DiskImageStorageDeviceAttachment, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
if _, err := os.Stat(diskPath); err != nil {
return nil, err
}

nserrPtr := newNSErrorAsNil()

diskPathChar := charWithGoString(diskPath)
defer diskPathChar.Free()
attachment := &DiskImageStorageDeviceAttachment{
pointer: objc.NewPointer(
C.newVZDiskImageStorageDeviceAttachmentWithCacheAndSyncMode(
diskPathChar.CString(),
C.bool(readOnly),
C.int(cachingMode),
C.int(syncMode),
&nserrPtr,
),
),
}
if err := newNSError(nserrPtr); err != nil {
return nil, err
}
objc.SetFinalizer(attachment, func(self *DiskImageStorageDeviceAttachment) {
objc.Release(self)
})
return attachment, nil
}

// StorageDeviceConfiguration for a storage device configuration.
type StorageDeviceConfiguration interface {
objc.NSObject
Expand Down
36 changes: 36 additions & 0 deletions storage_test.go
Expand Up @@ -62,3 +62,39 @@ func TestBlockDeviceIdentifier(t *testing.T) {
t.Fatalf("want %q but got %q", want, got2)
}
}

func TestBlockDeviceWithCacheAndSyncMode(t *testing.T) {
if vz.Available(12) {
t.Skip("vz.NewDiskImageStorageDeviceAttachmentWithCacheAndSync is supported from macOS 12")
}

container := newVirtualizationMachine(t,
func(vmc *vz.VirtualMachineConfiguration) error {
dir := t.TempDir()
path := filepath.Join(dir, "disk.img")
if err := vz.CreateDiskImage(path, 512); err != nil {
t.Fatal(err)
}

attachment, err := vz.NewDiskImageStorageDeviceAttachmentWithCacheAndSync(path, false, vz.DiskImageCachingModeAutomatic, vz.DiskImageSynchronizationModeFsync)
if err != nil {
t.Fatal(err)
}
config, err := vz.NewVirtioBlockDeviceConfiguration(attachment)
if err != nil {
t.Fatal(err)
}
vmc.SetStorageDevicesVirtualMachineConfiguration([]vz.StorageDeviceConfiguration{
config,
})
return nil
},
)
defer container.Close()

vm := container.VirtualMachine

if got := vm.State(); vz.VirtualMachineStateRunning != got {
t.Fatalf("want state %v but got %v", vz.VirtualMachineStateRunning, got)
}
}
1 change: 1 addition & 0 deletions virtualization_12.h
Expand Up @@ -21,6 +21,7 @@ void *newVZVirtioSoundDeviceHostInputStreamConfiguration(); // use in Go
void *newVZVirtioSoundDeviceOutputStreamConfiguration();
void *newVZVirtioSoundDeviceHostOutputStreamConfiguration(); // use in Go

void *newVZDiskImageStorageDeviceAttachmentWithCacheAndSyncMode(const char *diskPath, bool readOnly, int cacheMode, int syncMode, void **error);
void *newVZUSBScreenCoordinatePointingDeviceConfiguration();
void *newVZUSBKeyboardConfiguration();
void *newVZVirtioSoundDeviceConfiguration();
Expand Down
25 changes: 25 additions & 0 deletions virtualization_12.m
Expand Up @@ -210,6 +210,31 @@ void setStreamsVZVirtioSoundDeviceConfiguration(void *audioDeviceConfiguration,
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}

/*!
@abstract Initialize the attachment from a local file url.
@param diskPath Local file path to the disk image in RAW format.
@param readOnly If YES, the device attachment is read-only, otherwise the device can write data to the disk image.
@param cacheMode The caching mode from one of the available VZDiskImageCachingMode options.
@param syncMode How the disk image synchronizes with the underlying storage when the guest operating system flushes data, described by one of the available VZDiskImageSynchronizationMode modes.
@param error If not nil, assigned with the error if the initialization failed.
@return A VZDiskImageStorageDeviceAttachment on success. Nil otherwise and the error parameter is populated if set.
*/
void *newVZDiskImageStorageDeviceAttachmentWithCacheAndSyncMode(const char *diskPath, bool readOnly, int cacheMode, int syncMode, void **error)
{
if (@available(macOS 12, *)) {
NSString *diskPathNSString = [NSString stringWithUTF8String:diskPath];
NSURL *diskURL = [NSURL fileURLWithPath:diskPathNSString];
return [[VZDiskImageStorageDeviceAttachment alloc]
initWithURL:diskURL
readOnly:(BOOL)readOnly
cachingMode:(VZDiskImageCachingMode)cacheMode
synchronizationMode: (VZDiskImageSynchronizationMode)syncMode
error:(NSError *_Nullable *_Nullable)error];
}

RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}

/*!
@abstract Initialize the VZSharedDirectory from the directory path and read only option.
@param dirPath
Expand Down

0 comments on commit 957dfd2

Please sign in to comment.