Skip to content

Commit 58e638f

Browse files
committed
implemented blockDeviceIdentifier
1 parent 910967e commit 58e638f

File tree

5 files changed

+168
-0
lines changed

5 files changed

+168
-0
lines changed

osversion_test.go

+19
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,25 @@ func TestAvailableVersion(t *testing.T) {
161161
}
162162
}
163163
})
164+
165+
t.Run("macOS 12.3", func(t *testing.T) {
166+
majorMinorVersion = 12
167+
cases := map[string]func() error{
168+
"BlockDeviceIdentifier": func() error {
169+
_, err := (*VirtioBlockDeviceConfiguration)(nil).BlockDeviceIdentifier()
170+
return err
171+
},
172+
"SetBlockDeviceIdentifier": func() error {
173+
return (*VirtioBlockDeviceConfiguration)(nil).SetBlockDeviceIdentifier("")
174+
},
175+
}
176+
for name, fn := range cases {
177+
err := fn()
178+
if !errors.Is(err, ErrUnsupportedOSVersion) {
179+
t.Fatalf("unexpected error %v in %s", err, name)
180+
}
181+
}
182+
})
164183
}
165184

166185
func Test_fetchMajorMinorVersion(t *testing.T) {

storage.go

+45
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package vz
44
#cgo darwin CFLAGS: -x objective-c -fno-objc-arc
55
#cgo darwin LDFLAGS: -lobjc -framework Foundation -framework Virtualization
66
# include "virtualization.h"
7+
# include "virtualization_12_3.h"
78
# include "virtualization_13.h"
89
*/
910
import "C"
@@ -104,6 +105,8 @@ type VirtioBlockDeviceConfiguration struct {
104105
*pointer
105106

106107
*baseStorageDeviceConfiguration
108+
109+
blockDeviceIdentifier string
107110
}
108111

109112
// NewVirtioBlockDeviceConfiguration initialize a VZVirtioBlockDeviceConfiguration with a device attachment.
@@ -130,6 +133,48 @@ func NewVirtioBlockDeviceConfiguration(attachment StorageDeviceAttachment) (*Vir
130133
return config, nil
131134
}
132135

136+
// BlockDeviceIdentifier returns the device identifier is a string identifying the Virtio block device.
137+
// Empty string by default.
138+
//
139+
// The identifier can be retrieved in the guest via a VIRTIO_BLK_T_GET_ID request.
140+
//
141+
// This is only supported on macOS 12.3 and newer, error will be returned on older versions.
142+
//
143+
// see: https://developer.apple.com/documentation/virtualization/vzvirtioblockdeviceconfiguration/3917717-blockdeviceidentifier
144+
func (v *VirtioBlockDeviceConfiguration) BlockDeviceIdentifier() (string, error) {
145+
if err := macOSAvailable(12.3); err != nil {
146+
return "", err
147+
}
148+
return v.blockDeviceIdentifier, nil
149+
}
150+
151+
// SetBlockDeviceIdentifier sets the device identifier is a string identifying the Virtio block device.
152+
//
153+
// The device identifier must be at most 20 bytes in length and ASCII-encodable.
154+
//
155+
// This is only supported on macOS 12.3 and newer, error will be returned on older versions.
156+
//
157+
// see: https://developer.apple.com/documentation/virtualization/vzvirtioblockdeviceconfiguration/3917717-blockdeviceidentifier
158+
func (v *VirtioBlockDeviceConfiguration) SetBlockDeviceIdentifier(identifier string) error {
159+
if err := macOSAvailable(12.3); err != nil {
160+
return err
161+
}
162+
idChar := charWithGoString(identifier)
163+
defer idChar.Free()
164+
165+
nserrPtr := newNSErrorAsNil()
166+
C.setBlockDeviceIdentifierVZVirtioBlockDeviceConfiguration(
167+
objc.Ptr(v),
168+
idChar.CString(),
169+
&nserrPtr,
170+
)
171+
if err := newNSError(nserrPtr); err != nil {
172+
return err
173+
}
174+
v.blockDeviceIdentifier = identifier
175+
return nil
176+
}
177+
133178
// USBMassStorageDeviceConfiguration is a configuration of a USB Mass Storage storage device.
134179
//
135180
// This device configuration creates a storage device that conforms to the USB Mass Storage specification.

storage_test.go

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package vz_test
2+
3+
import (
4+
"path/filepath"
5+
"strings"
6+
"testing"
7+
8+
"github.com/Code-Hex/vz/v2"
9+
)
10+
11+
func TestBlockDeviceIdentifier(t *testing.T) {
12+
if vz.Available(12.3) {
13+
t.Skip("VirtioBlockDeviceConfiguration.SetBlockDeviceIdentifier is supported from macOS 12.3")
14+
}
15+
dir := t.TempDir()
16+
path := filepath.Join(dir, "disk.img")
17+
if err := vz.CreateDiskImage(path, 512); err != nil {
18+
t.Fatal(err)
19+
}
20+
21+
attachment, err := vz.NewDiskImageStorageDeviceAttachment(path, false)
22+
if err != nil {
23+
t.Fatal(err)
24+
}
25+
config, err := vz.NewVirtioBlockDeviceConfiguration(attachment)
26+
if err != nil {
27+
t.Fatal(err)
28+
}
29+
got1, err := config.BlockDeviceIdentifier()
30+
if err != nil {
31+
t.Fatal(err)
32+
}
33+
if got1 != "" {
34+
t.Fatalf("want empty by default: %q", got1)
35+
}
36+
37+
invalidID := strings.Repeat("h", 25)
38+
if err := config.SetBlockDeviceIdentifier(invalidID); err == nil {
39+
t.Fatal("want error")
40+
} else {
41+
nserr, ok := err.(*vz.NSError)
42+
if !ok {
43+
t.Fatalf("unexpected error: %v", err)
44+
}
45+
if nserr.Domain != "VZErrorDomain" {
46+
t.Errorf("unexpected NSError domain: %v", nserr)
47+
}
48+
if nserr.Code != int(vz.ErrorInvalidVirtualMachineConfiguration) {
49+
t.Errorf("unexpected NSError code: %v", nserr)
50+
}
51+
}
52+
53+
want := "hello"
54+
if err := config.SetBlockDeviceIdentifier(want); err != nil {
55+
t.Fatal(err)
56+
}
57+
got2, err := config.BlockDeviceIdentifier()
58+
if err != nil {
59+
t.Fatal(err)
60+
}
61+
if got2 != want {
62+
t.Fatalf("want %q but got %q", want, got2)
63+
}
64+
}

virtualization_12_3.h

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// virtualization_12_3.h
3+
//
4+
// Created by codehex.
5+
//
6+
7+
#pragma once
8+
9+
#import "virtualization_helper.h"
10+
#import <Virtualization/Virtualization.h>
11+
12+
// FIXME(codehex): this is dirty hack to avoid clang-format error like below
13+
// "Configuration file(s) do(es) not support C++: /github.com/Code-Hex/vz/.clang-format"
14+
#define NSURLComponents NSURLComponents
15+
16+
void setBlockDeviceIdentifierVZVirtioBlockDeviceConfiguration(void *blockDeviceConfig, const char *identifier, void **error);

virtualization_12_3.m

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// virtualization_12_3.m
3+
//
4+
// Created by codehex.
5+
//
6+
7+
#import "virtualization_12_3.h"
8+
9+
void setBlockDeviceIdentifierVZVirtioBlockDeviceConfiguration(void *blockDeviceConfig, const char *identifier, void **error)
10+
{
11+
if (@available(macOS 12.3, *)) {
12+
NSString *identifierNSString = [NSString stringWithUTF8String:identifier];
13+
BOOL valid = [VZVirtioBlockDeviceConfiguration
14+
validateBlockDeviceIdentifier:identifierNSString
15+
error:(NSError *_Nullable *_Nullable)error];
16+
if (!valid) {
17+
return;
18+
}
19+
[(VZVirtioBlockDeviceConfiguration *)blockDeviceConfig setBlockDeviceIdentifier:identifierNSString];
20+
return;
21+
}
22+
23+
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
24+
}

0 commit comments

Comments
 (0)